]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/arm/arm.md
* gcov-io.c (gcov_read_words): Don't call memmove if excess is 0.
[thirdparty/gcc.git] / gcc / config / arm / arm.md
CommitLineData
129a2fe4 1;;- Machine description for ARM for GNU compiler
3aea1f79 2;; Copyright (C) 1991-2014 Free Software Foundation, Inc.
b11cae9e 3;; Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
f082f1c4 4;; and Martin Simmons (@harleqn.co.uk).
129a2fe4 5;; More major hacks by Richard Earnshaw (rearnsha@arm.com).
b11cae9e 6
acf6ed70 7;; This file is part of GCC.
b11cae9e 8
acf6ed70 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
038d1e19 11;; by the Free Software Foundation; either version 3, or (at your
acf6ed70 12;; option) any later version.
b11cae9e 13
acf6ed70 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.
b11cae9e 18
19;; You should have received a copy of the GNU General Public License
038d1e19 20;; along with GCC; see the file COPYING3. If not see
21;; <http://www.gnu.org/licenses/>.
b11cae9e 22
23;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
24
cb860649 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
9c08d1fa 44\f
e1159bbe 45;;---------------------------------------------------------------------------
46;; Constants
47
bffbb863 48;; Register numbers -- All machine registers should be defined here
e1159bbe 49(define_constants
bffbb863 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
e1159bbe 59 ]
60)
3c5afce6 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)
2ff91fec 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)
e1159bbe 77
b11cae9e 78\f
e1159bbe 79;;---------------------------------------------------------------------------
9c08d1fa 80;; Attributes
81
a651f34d 82;; Processor type. This is created automatically from arm-cores.def.
83(include "arm-tune.md")
84
861033d5 85;; Instruction classification types
86(include "types.md")
87
215b30b3 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.
1c494086 91(define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
cffb2a26 92
ef51b8e1 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
747b7458 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
c7a58118 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
331beb1a 108;; Operand number of an input operand that is shifted. Zero if the
109;; given instruction does not shift one of its input operands.
331beb1a 110(define_attr "shift" "" (const_int 0))
111
3d91c5d6 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).
bffbb863 115(define_attr "fpu" "none,vfp"
c7f506fd 116 (const (symbol_ref "arm_fpu_attr")))
3d91c5d6 117
c7a58118 118(define_attr "predicated" "yes,no" (const_string "no"))
119
094e994f 120; LENGTH of an instruction (in bytes)
06df6b17 121(define_attr "length" ""
e1b93706 122 (const_int 4))
9c08d1fa 123
d5d4dc8d 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.
b6779ddc 130(define_attr "arch" "any,a,t,32,t1,t2,v6,nov6,neon_for_64bits,avoid_neon_for_64bits,iwmmxt,iwmmxt2"
d5d4dc8d 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")
0bf497f5 138 (match_test "TARGET_ARM"))
d5d4dc8d 139 (const_string "yes")
140
141 (and (eq_attr "arch" "t")
0bf497f5 142 (match_test "TARGET_THUMB"))
d5d4dc8d 143 (const_string "yes")
144
145 (and (eq_attr "arch" "t1")
0bf497f5 146 (match_test "TARGET_THUMB1"))
d5d4dc8d 147 (const_string "yes")
148
149 (and (eq_attr "arch" "t2")
0bf497f5 150 (match_test "TARGET_THUMB2"))
d5d4dc8d 151 (const_string "yes")
152
153 (and (eq_attr "arch" "32")
0bf497f5 154 (match_test "TARGET_32BIT"))
d5d4dc8d 155 (const_string "yes")
156
157 (and (eq_attr "arch" "v6")
0bf497f5 158 (match_test "TARGET_32BIT && arm_arch6"))
d5d4dc8d 159 (const_string "yes")
160
161 (and (eq_attr "arch" "nov6")
0bf497f5 162 (match_test "TARGET_32BIT && !arm_arch6"))
a651f34d 163 (const_string "yes")
164
b6779ddc 165 (and (eq_attr "arch" "avoid_neon_for_64bits")
166 (match_test "TARGET_NEON")
167 (not (match_test "TARGET_PREFER_NEON_64BITS")))
a651f34d 168 (const_string "yes")
169
b6779ddc 170 (and (eq_attr "arch" "neon_for_64bits")
171 (match_test "TARGET_NEON")
172 (match_test "TARGET_PREFER_NEON_64BITS"))
6b8f7c28 173 (const_string "yes")
174
175 (and (eq_attr "arch" "iwmmxt2")
176 (match_test "TARGET_REALLY_IWMMXT2"))
d5d4dc8d 177 (const_string "yes")]
6b8f7c28 178
d5d4dc8d 179 (const_string "no")))
180
aa06c51c 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
861033d5 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
d5d4dc8d 203; Enable all alternatives that are both arch_enabled and insn_enabled.
951a3f72 204; FIXME:: opt_enabled has been temporarily removed till the time we have
205; an attribute that allows the use of such alternatives.
206; This depends on caching of speed_p, size_p on a per
207; alternative basis. The problem is that the enabled attribute
208; cannot depend on any state that is not cached or is not constant
209; for a compilation unit. We probably need a generic "hot/cold"
210; alternative which if implemented can help with this. We disable this
211; until such a time as this is implemented and / or the improvements or
212; regressions with removing this attribute are double checked.
213; See ashldi3_neon and <shift>di3_neon in neon.md.
214
93b431d9 215 (define_attr "enabled" "no,yes"
0abea32c 216 (cond [(and (eq_attr "predicable_short_it" "no")
c7a58118 217 (and (eq_attr "predicated" "yes")
218 (match_test "arm_restrict_it")))
219 (const_string "no")
220
221 (and (eq_attr "enabled_for_depr_it" "no")
222 (match_test "arm_restrict_it"))
223 (const_string "no")
224
861033d5 225 (and (eq_attr "use_literal_pool" "yes")
226 (match_test "arm_disable_literal_pool"))
227 (const_string "no")
228
aa06c51c 229 (eq_attr "arch_enabled" "no")
aa06c51c 230 (const_string "no")]
231 (const_string "yes")))
d5d4dc8d 232
56d27660 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.
42e1de19 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.
cffb2a26 239; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
8848d797 240; before its address. It is set to <max_range> - (8 + <data_size>).
cde1623a 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")))
56d27660 252
215b30b3 253; An assembler sequence may clobber the condition codes without us knowing.
4d7a8451 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.
9c08d1fa 256(define_asm_attributes
4d7a8451 257 [(set_attr "conds" "clob")
258 (set_attr "length" "4")
259 (set_attr "pool_range" "250")])
9c08d1fa 260
9888ad6d 261; Load scheduling, set from the arm_ld_sched variable
4c834714 262; initialized by arm_option_override()
9888ad6d 263(define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
849170fd 264
f7fbdd4a 265; condition codes: this one is used by final_prescan_insn to speed up
266; conditionalizing instructions. It saves having to scan the rtl to see if
267; it uses or alters the condition codes.
215b30b3 268;
f7fbdd4a 269; USE means that the condition codes are used by the insn in the process of
215b30b3 270; outputting code, this means (at present) that we can't use the insn in
271; inlined branches
272;
f7fbdd4a 273; SET means that the purpose of the insn is to set the condition codes in a
215b30b3 274; well defined manner.
275;
f7fbdd4a 276; CLOB means that the condition codes are altered in an undefined manner, if
215b30b3 277; they are altered at all
278;
ad6d3e2a 279; UNCONDITIONAL means the instruction can not be conditionally executed and
280; that the instruction does not use or alter the condition codes.
c52acdd2 281;
ad6d3e2a 282; NOCOND means that the instruction does not use or alter the condition
283; codes but can be converted into a conditionally exectuted instruction.
f7fbdd4a 284
b0694be0 285(define_attr "conds" "use,set,clob,unconditional,nocond"
747b7458 286 (if_then_else
287 (ior (eq_attr "is_thumb1" "yes")
288 (eq_attr "type" "call"))
c1a66faf 289 (const_string "clob")
32093010 290 (if_then_else (eq_attr "is_neon_type" "no")
52432540 291 (const_string "nocond")
292 (const_string "unconditional"))))
f7fbdd4a 293
215b30b3 294; Predicable means that the insn can be conditionally executed based on
295; an automatically added predicate (additional patterns are generated by
296; gen...). We default to 'no' because no Thumb patterns match this rule
297; and not all ARM patterns do.
0d66636f 298(define_attr "predicable" "no,yes" (const_string "no"))
299
129a2fe4 300; Only model the write buffer for ARM6 and ARM7. Earlier processors don't
301; have one. Later ones, such as StrongARM, have write-back caches, so don't
8d232dc7 302; suffer blockages enough to warrant modelling this (and it can adversely
129a2fe4 303; affect the schedule).
74a71f7d 304(define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_tune_wbuf")))
129a2fe4 305
215b30b3 306; WRITE_CONFLICT implies that a read following an unrelated write is likely
307; to stall the processor. Used with model_wbuf above.
9c08d1fa 308(define_attr "write_conflict" "no,yes"
309 (if_then_else (eq_attr "type"
96854199 310 "block,call,load1")
9c08d1fa 311 (const_string "yes")
312 (const_string "no")))
313
215b30b3 314; Classify the insns into those that take one cycle and those that take more
315; than one on the main cpu execution unit.
f7fbdd4a 316(define_attr "core_cycles" "single,multi"
317 (if_then_else (eq_attr "type"
d82e788e 318 "adc_imm, adc_reg, adcs_imm, adcs_reg, adr, alu_ext, alu_imm, alu_reg,\
319 alu_shift_imm, alu_shift_reg, alus_ext, alus_imm, alus_reg,\
320 alus_shift_imm, alus_shift_reg, bfm, csel, rev, logic_imm, logic_reg,\
321 logic_shift_imm, logic_shift_reg, logics_imm, logics_reg,\
322 logics_shift_imm, logics_shift_reg, extend, shift_imm, float, fcsel,\
7cb6c048 323 wmmx_wor, wmmx_wxor, wmmx_wand, wmmx_wandn, wmmx_wmov, wmmx_tmcrr,\
324 wmmx_tmrrc, wmmx_wldr, wmmx_wstr, wmmx_tmcr, wmmx_tmrc, wmmx_wadd,\
325 wmmx_wsub, wmmx_wmul, wmmx_wmac, wmmx_wavg2, wmmx_tinsr, wmmx_textrm,\
326 wmmx_wshufh, wmmx_wcmpeq, wmmx_wcmpgt, wmmx_wmax, wmmx_wmin, wmmx_wpack,\
327 wmmx_wunpckih, wmmx_wunpckil, wmmx_wunpckeh, wmmx_wunpckel, wmmx_wror,\
328 wmmx_wsra, wmmx_wsrl, wmmx_wsll, wmmx_wmadd, wmmx_tmia, wmmx_tmiaph,\
329 wmmx_tmiaxy, wmmx_tbcst, wmmx_tmovmsk, wmmx_wacc, wmmx_waligni,\
330 wmmx_walignr, wmmx_tandc, wmmx_textrc, wmmx_torc, wmmx_torvsc, wmmx_wsad,\
331 wmmx_wabs, wmmx_wabsdiff, wmmx_waddsubhx, wmmx_wsubaddhx, wmmx_wavg4,\
332 wmmx_wmulw, wmmx_wqmulm, wmmx_wqmulwm, wmmx_waddbhus, wmmx_wqmiaxy,\
333 wmmx_wmiaxy, wmmx_wmiawxy, wmmx_wmerge")
f7fbdd4a 334 (const_string "single")
335 (const_string "multi")))
336
cffb2a26 337;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
215b30b3 338;; distant label. Only applicable to Thumb code.
cffb2a26 339(define_attr "far_jump" "yes,no" (const_string "no"))
340
d51f92df 341
25f905c2 342;; The number of machine instructions this pattern expands to.
343;; Used for Thumb-2 conditional execution.
344(define_attr "ce_count" "" (const_int 1))
345
4182b724 346;;---------------------------------------------------------------------------
347;; Unspecs
348
349(include "unspecs.md")
350
d51f92df 351;;---------------------------------------------------------------------------
fd781bb2 352;; Mode iterators
d51f92df 353
3de0dec6 354(include "iterators.md")
03770691 355
d51f92df 356;;---------------------------------------------------------------------------
357;; Predicates
358
9c9db025 359(include "predicates.md")
234f6557 360(include "constraints.md")
9c9db025 361
a2cd141b 362;;---------------------------------------------------------------------------
363;; Pipeline descriptions
215b30b3 364
e3879fd0 365(define_attr "tune_cortexr4" "yes,no"
366 (const (if_then_else
7d3cda8c 367 (eq_attr "tune" "cortexr4,cortexr4f,cortexr5")
e3879fd0 368 (const_string "yes")
369 (const_string "no"))))
370
a2cd141b 371;; True if the generic scheduling description should be used.
372
373(define_attr "generic_sched" "yes,no"
2546d93a 374 (const (if_then_else
25b10f06 375 (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")
2546d93a 376 (eq_attr "tune_cortexr4" "yes"))
4d5cb40d 377 (const_string "no")
378 (const_string "yes"))))
379
c0e1af52 380(define_attr "generic_vfp" "yes,no"
381 (const (if_then_else
382 (and (eq_attr "fpu" "vfp")
43e4f6e8 383 (eq_attr "tune" "!arm1020e,arm1022e,cortexa5,cortexa7,cortexa8,cortexa9,cortexa53,cortexm4,marvell_pj4")
e3879fd0 384 (eq_attr "tune_cortexr4" "no"))
c0e1af52 385 (const_string "yes")
386 (const_string "no"))))
387
6b8f7c28 388(include "marvell-f-iwmmxt.md")
a2cd141b 389(include "arm-generic.md")
390(include "arm926ejs.md")
c0e1af52 391(include "arm1020e.md")
a2cd141b 392(include "arm1026ejs.md")
393(include "arm1136jfs.md")
0e266d06 394(include "fa526.md")
395(include "fa606te.md")
396(include "fa626te.md")
397(include "fmp626.md")
398(include "fa726te.md")
3f1e069f 399(include "cortex-a5.md")
d6b7f019 400(include "cortex-a7.md")
bcaec148 401(include "cortex-a8.md")
036068af 402(include "cortex-a9.md")
65f2f758 403(include "cortex-a15.md")
da10bc87 404(include "cortex-a53.md")
934a1e72 405(include "cortex-r4.md")
e3879fd0 406(include "cortex-r4f.md")
2546d93a 407(include "cortex-m4.md")
408(include "cortex-m4-fpu.md")
55e3ada8 409(include "vfp11.md")
ea7d210b 410(include "marvell-pj4.md")
3586df96 411
9c08d1fa 412\f
215b30b3 413;;---------------------------------------------------------------------------
e1159bbe 414;; Insn patterns
415;;
a0f94409 416;; Addition insns.
215b30b3 417
9c08d1fa 418;; Note: For DImode insns, there is normally no reason why operands should
419;; not be in the same register, what we don't want is for something being
420;; written to partially overlap something that is an input.
421
cffb2a26 422(define_expand "adddi3"
423 [(parallel
215b30b3 424 [(set (match_operand:DI 0 "s_register_operand" "")
cffb2a26 425 (plus:DI (match_operand:DI 1 "s_register_operand" "")
10e5ccd5 426 (match_operand:DI 2 "arm_adddi_operand" "")))
bd5b4116 427 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 428 "TARGET_EITHER"
429 "
25f905c2 430 if (TARGET_THUMB1)
cffb2a26 431 {
0438d37f 432 if (!REG_P (operands[1]))
bc5a93af 433 operands[1] = force_reg (DImode, operands[1]);
0438d37f 434 if (!REG_P (operands[2]))
bc5a93af 435 operands[2] = force_reg (DImode, operands[2]);
cffb2a26 436 }
437 "
438)
439
a0f94409 440(define_insn_and_split "*arm_adddi3"
10e5ccd5 441 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r,&r,&r")
442 (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0, r, 0, r")
443 (match_operand:DI 2 "arm_adddi_operand" "r, 0, r, Dd, Dd")))
bd5b4116 444 (clobber (reg:CC CC_REGNUM))]
b805622c 445 "TARGET_32BIT && !TARGET_NEON"
33782ec7 446 "#"
94829feb 447 "TARGET_32BIT && reload_completed
448 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))"
a0f94409 449 [(parallel [(set (reg:CC_C CC_REGNUM)
450 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
451 (match_dup 1)))
452 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 453 (set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (match_dup 5))
454 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
a0f94409 455 "
456 {
457 operands[3] = gen_highpart (SImode, operands[0]);
458 operands[0] = gen_lowpart (SImode, operands[0]);
459 operands[4] = gen_highpart (SImode, operands[1]);
460 operands[1] = gen_lowpart (SImode, operands[1]);
10e5ccd5 461 operands[5] = gen_highpart_mode (SImode, DImode, operands[2]);
a0f94409 462 operands[2] = gen_lowpart (SImode, operands[2]);
463 }"
cffb2a26 464 [(set_attr "conds" "clob")
1b7da4ac 465 (set_attr "length" "8")
466 (set_attr "type" "multiple")]
cffb2a26 467)
9c08d1fa 468
a0f94409 469(define_insn_and_split "*adddi_sesidi_di"
9c08d1fa 470 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
471 (plus:DI (sign_extend:DI
97499065 472 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 473 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 474 (clobber (reg:CC CC_REGNUM))]
b805622c 475 "TARGET_32BIT"
33782ec7 476 "#"
25f905c2 477 "TARGET_32BIT && reload_completed"
a0f94409 478 [(parallel [(set (reg:CC_C CC_REGNUM)
479 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
480 (match_dup 1)))
481 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 482 (set (match_dup 3) (plus:SI (plus:SI (ashiftrt:SI (match_dup 2)
a0f94409 483 (const_int 31))
080c0b9a 484 (match_dup 4))
485 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
a0f94409 486 "
487 {
488 operands[3] = gen_highpart (SImode, operands[0]);
489 operands[0] = gen_lowpart (SImode, operands[0]);
490 operands[4] = gen_highpart (SImode, operands[1]);
491 operands[1] = gen_lowpart (SImode, operands[1]);
492 operands[2] = gen_lowpart (SImode, operands[2]);
493 }"
215b30b3 494 [(set_attr "conds" "clob")
1b7da4ac 495 (set_attr "length" "8")
496 (set_attr "type" "multiple")]
215b30b3 497)
9c08d1fa 498
a0f94409 499(define_insn_and_split "*adddi_zesidi_di"
9c08d1fa 500 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
501 (plus:DI (zero_extend:DI
97499065 502 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 503 (match_operand:DI 1 "s_register_operand" "0,r")))
a0f94409 504 (clobber (reg:CC CC_REGNUM))]
b805622c 505 "TARGET_32BIT"
33782ec7 506 "#"
25f905c2 507 "TARGET_32BIT && reload_completed"
a0f94409 508 [(parallel [(set (reg:CC_C CC_REGNUM)
509 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
510 (match_dup 1)))
511 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 512 (set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (const_int 0))
513 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
a0f94409 514 "
515 {
516 operands[3] = gen_highpart (SImode, operands[0]);
517 operands[0] = gen_lowpart (SImode, operands[0]);
518 operands[4] = gen_highpart (SImode, operands[1]);
519 operands[1] = gen_lowpart (SImode, operands[1]);
520 operands[2] = gen_lowpart (SImode, operands[2]);
521 }"
cffb2a26 522 [(set_attr "conds" "clob")
1b7da4ac 523 (set_attr "length" "8")
524 (set_attr "type" "multiple")]
cffb2a26 525)
b11cae9e 526
87b22bf7 527(define_expand "addsi3"
cffb2a26 528 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 529 (plus:SI (match_operand:SI 1 "s_register_operand" "")
530 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 531 "TARGET_EITHER"
87b22bf7 532 "
0438d37f 533 if (TARGET_32BIT && CONST_INT_P (operands[2]))
87b22bf7 534 {
96f57e36 535 arm_split_constant (PLUS, SImode, NULL_RTX,
536 INTVAL (operands[2]), operands[0], operands[1],
e1ba4a27 537 optimize && can_create_pseudo_p ());
87b22bf7 538 DONE;
539 }
cffb2a26 540 "
541)
87b22bf7 542
5bd751ff 543; If there is a scratch available, this will be faster than synthesizing the
a0f94409 544; addition.
545(define_peephole2
546 [(match_scratch:SI 3 "r")
372575c7 547 (set (match_operand:SI 0 "arm_general_register_operand" "")
548 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
cffb2a26 549 (match_operand:SI 2 "const_int_operand" "")))]
25f905c2 550 "TARGET_32BIT &&
a0f94409 551 !(const_ok_for_arm (INTVAL (operands[2]))
552 || const_ok_for_arm (-INTVAL (operands[2])))
553 && const_ok_for_arm (~INTVAL (operands[2]))"
554 [(set (match_dup 3) (match_dup 2))
555 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
556 ""
557)
87b22bf7 558
2f02c19f 559;; The r/r/k alternative is required when reloading the address
560;; (plus (reg rN) (reg sp)) into (reg rN). In this case reload will
561;; put the duplicated register first, and not try the commutative version.
a0f94409 562(define_insn_and_split "*arm_addsi3"
7c36fe71 563 [(set (match_operand:SI 0 "s_register_operand" "=rk,l,l ,l ,r ,k ,r,r ,k ,r ,k,k,r ,k ,r")
564 (plus:SI (match_operand:SI 1 "s_register_operand" "%0 ,l,0 ,l ,rk,k ,r,rk,k ,rk,k,r,rk,k ,rk")
565 (match_operand:SI 2 "reg_or_int_operand" "rk ,l,Py,Pd,rI,rI,k,Pj,Pj,L ,L,L,PJ,PJ,?n")))]
25f905c2 566 "TARGET_32BIT"
5565501b 567 "@
c24d855d 568 add%?\\t%0, %0, %2
5565501b 569 add%?\\t%0, %1, %2
a0b3420a 570 add%?\\t%0, %1, %2
7c36fe71 571 add%?\\t%0, %1, %2
572 add%?\\t%0, %1, %2
aaa37ad6 573 add%?\\t%0, %1, %2
2f02c19f 574 add%?\\t%0, %2, %1
d5cbae34 575 addw%?\\t%0, %1, %2
576 addw%?\\t%0, %1, %2
aaa37ad6 577 sub%?\\t%0, %1, #%n2
87b22bf7 578 sub%?\\t%0, %1, #%n2
d7757711 579 sub%?\\t%0, %1, #%n2
d5cbae34 580 subw%?\\t%0, %1, #%n2
581 subw%?\\t%0, %1, #%n2
87b22bf7 582 #"
a3ffc315 583 "TARGET_32BIT
0438d37f 584 && CONST_INT_P (operands[2])
d5cbae34 585 && !const_ok_for_op (INTVAL (operands[2]), PLUS)
a3ffc315 586 && (reload_completed || !arm_eliminable_register (operands[1]))"
a0f94409 587 [(clobber (const_int 0))]
588 "
96f57e36 589 arm_split_constant (PLUS, SImode, curr_insn,
590 INTVAL (operands[2]), operands[0],
a0f94409 591 operands[1], 0);
592 DONE;
593 "
7c36fe71 594 [(set_attr "length" "2,4,4,4,4,4,4,4,4,4,4,4,4,4,16")
d5cbae34 595 (set_attr "predicable" "yes")
7c36fe71 596 (set_attr "predicable_short_it" "yes,yes,yes,yes,no,no,no,no,no,no,no,no,no,no,no")
597 (set_attr "arch" "t2,t2,t2,t2,*,*,*,t2,t2,*,*,a,t2,t2,*")
65f68e55 598 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
d82e788e 599 (const_string "alu_imm")
600 (const_string "alu_reg")))
65f68e55 601 ]
cffb2a26 602)
603
90c2bcf0 604(define_insn "addsi3_compare0"
bd5b4116 605 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 606 (compare:CC_NOOV
65f68e55 607 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r,r")
608 (match_operand:SI 2 "arm_add_operand" "I,L,r"))
5565501b 609 (const_int 0)))
65f68e55 610 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9c08d1fa 611 (plus:SI (match_dup 1) (match_dup 2)))]
ec792a7b 612 "TARGET_ARM"
5565501b 613 "@
25f905c2 614 add%.\\t%0, %1, %2
65f68e55 615 sub%.\\t%0, %1, #%n2
616 add%.\\t%0, %1, %2"
617 [(set_attr "conds" "set")
1b7da4ac 618 (set_attr "type" "alus_imm,alus_imm,alus_reg")]
cffb2a26 619)
9c08d1fa 620
aea4c774 621(define_insn "*addsi3_compare0_scratch"
bd5b4116 622 [(set (reg:CC_NOOV CC_REGNUM)
aea4c774 623 (compare:CC_NOOV
65f68e55 624 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r, r")
625 (match_operand:SI 1 "arm_add_operand" "I,L, r"))
aea4c774 626 (const_int 0)))]
ec792a7b 627 "TARGET_ARM"
cffb2a26 628 "@
629 cmn%?\\t%0, %1
65f68e55 630 cmp%?\\t%0, #%n1
631 cmn%?\\t%0, %1"
596e5e8f 632 [(set_attr "conds" "set")
65f68e55 633 (set_attr "predicable" "yes")
1b7da4ac 634 (set_attr "type" "alus_imm,alus_imm,alus_reg")]
0d66636f 635)
cffb2a26 636
aed179ae 637(define_insn "*compare_negsi_si"
638 [(set (reg:CC_Z CC_REGNUM)
639 (compare:CC_Z
7c36fe71 640 (neg:SI (match_operand:SI 0 "s_register_operand" "l,r"))
641 (match_operand:SI 1 "s_register_operand" "l,r")))]
25f905c2 642 "TARGET_32BIT"
aed179ae 643 "cmn%?\\t%1, %0"
596e5e8f 644 [(set_attr "conds" "set")
7c36fe71 645 (set_attr "predicable" "yes")
646 (set_attr "arch" "t2,*")
647 (set_attr "length" "2,4")
1b7da4ac 648 (set_attr "predicable_short_it" "yes,no")
649 (set_attr "type" "alus_reg")]
0d66636f 650)
aea4c774 651
203c488f 652;; This is the canonicalization of addsi3_compare0_for_combiner when the
653;; addend is a constant.
190efb17 654(define_insn "cmpsi2_addneg"
203c488f 655 [(set (reg:CC CC_REGNUM)
656 (compare:CC
657 (match_operand:SI 1 "s_register_operand" "r,r")
2a977b78 658 (match_operand:SI 2 "arm_addimm_operand" "L,I")))
203c488f 659 (set (match_operand:SI 0 "s_register_operand" "=r,r")
660 (plus:SI (match_dup 1)
2a977b78 661 (match_operand:SI 3 "arm_addimm_operand" "I,L")))]
25f905c2 662 "TARGET_32BIT && INTVAL (operands[2]) == -INTVAL (operands[3])"
203c488f 663 "@
2a977b78 664 add%.\\t%0, %1, %3
665 sub%.\\t%0, %1, #%n3"
1b7da4ac 666 [(set_attr "conds" "set")
667 (set_attr "type" "alus_reg")]
203c488f 668)
669
670;; Convert the sequence
671;; sub rd, rn, #1
672;; cmn rd, #1 (equivalent to cmp rd, #-1)
673;; bne dest
674;; into
675;; subs rd, rn, #1
676;; bcs dest ((unsigned)rn >= 1)
677;; similarly for the beq variant using bcc.
678;; This is a common looping idiom (while (n--))
679(define_peephole2
372575c7 680 [(set (match_operand:SI 0 "arm_general_register_operand" "")
681 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
203c488f 682 (const_int -1)))
683 (set (match_operand 2 "cc_register" "")
684 (compare (match_dup 0) (const_int -1)))
685 (set (pc)
686 (if_then_else (match_operator 3 "equality_operator"
687 [(match_dup 2) (const_int 0)])
688 (match_operand 4 "" "")
689 (match_operand 5 "" "")))]
25f905c2 690 "TARGET_32BIT && peep2_reg_dead_p (3, operands[2])"
203c488f 691 [(parallel[
692 (set (match_dup 2)
693 (compare:CC
694 (match_dup 1) (const_int 1)))
695 (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
696 (set (pc)
697 (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
698 (match_dup 4)
699 (match_dup 5)))]
700 "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
701 operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
702 ? GEU : LTU),
703 VOIDmode,
704 operands[2], const0_rtx);"
705)
706
ebcc79bc 707;; The next four insns work because they compare the result with one of
708;; the operands, and we know that the use of the condition code is
709;; either GEU or LTU, so we can use the carry flag from the addition
710;; instead of doing the compare a second time.
711(define_insn "*addsi3_compare_op1"
bd5b4116 712 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 713 (compare:CC_C
65f68e55 714 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
715 (match_operand:SI 2 "arm_add_operand" "I,L,r"))
ebcc79bc 716 (match_dup 1)))
65f68e55 717 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
ebcc79bc 718 (plus:SI (match_dup 1) (match_dup 2)))]
25f905c2 719 "TARGET_32BIT"
ebcc79bc 720 "@
25f905c2 721 add%.\\t%0, %1, %2
65f68e55 722 sub%.\\t%0, %1, #%n2
723 add%.\\t%0, %1, %2"
724 [(set_attr "conds" "set")
d82e788e 725 (set_attr "type" "alus_imm,alus_imm,alus_reg")]
0d66636f 726)
ebcc79bc 727
728(define_insn "*addsi3_compare_op2"
bd5b4116 729 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 730 (compare:CC_C
65f68e55 731 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
732 (match_operand:SI 2 "arm_add_operand" "I,L,r"))
ebcc79bc 733 (match_dup 2)))
65f68e55 734 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9c08d1fa 735 (plus:SI (match_dup 1) (match_dup 2)))]
25f905c2 736 "TARGET_32BIT"
5565501b 737 "@
65f68e55 738 add%.\\t%0, %1, %2
25f905c2 739 add%.\\t%0, %1, %2
740 sub%.\\t%0, %1, #%n2"
65f68e55 741 [(set_attr "conds" "set")
d82e788e 742 (set_attr "type" "alus_imm,alus_imm,alus_reg")]
0d66636f 743)
9c08d1fa 744
ebcc79bc 745(define_insn "*compare_addsi2_op0"
bd5b4116 746 [(set (reg:CC_C CC_REGNUM)
7c36fe71 747 (compare:CC_C
748 (plus:SI (match_operand:SI 0 "s_register_operand" "l,l,r,r,r")
749 (match_operand:SI 1 "arm_add_operand" "Pv,l,I,L,r"))
750 (match_dup 0)))]
25f905c2 751 "TARGET_32BIT"
ebcc79bc 752 "@
7c36fe71 753 cmp%?\\t%0, #%n1
754 cmn%?\\t%0, %1
ebcc79bc 755 cmn%?\\t%0, %1
65f68e55 756 cmp%?\\t%0, #%n1
757 cmn%?\\t%0, %1"
596e5e8f 758 [(set_attr "conds" "set")
65f68e55 759 (set_attr "predicable" "yes")
7c36fe71 760 (set_attr "arch" "t2,t2,*,*,*")
761 (set_attr "predicable_short_it" "yes,yes,no,no,no")
762 (set_attr "length" "2,2,4,4,4")
d82e788e 763 (set_attr "type" "alus_imm,alus_reg,alus_imm,alus_imm,alus_reg")]
0d66636f 764)
ebcc79bc 765
766(define_insn "*compare_addsi2_op1"
bd5b4116 767 [(set (reg:CC_C CC_REGNUM)
7c36fe71 768 (compare:CC_C
769 (plus:SI (match_operand:SI 0 "s_register_operand" "l,l,r,r,r")
770 (match_operand:SI 1 "arm_add_operand" "Pv,l,I,L,r"))
771 (match_dup 1)))]
25f905c2 772 "TARGET_32BIT"
ebcc79bc 773 "@
7c36fe71 774 cmp%?\\t%0, #%n1
775 cmn%?\\t%0, %1
ebcc79bc 776 cmn%?\\t%0, %1
65f68e55 777 cmp%?\\t%0, #%n1
778 cmn%?\\t%0, %1"
596e5e8f 779 [(set_attr "conds" "set")
65f68e55 780 (set_attr "predicable" "yes")
7c36fe71 781 (set_attr "arch" "t2,t2,*,*,*")
782 (set_attr "predicable_short_it" "yes,yes,no,no,no")
783 (set_attr "length" "2,2,4,4,4")
d82e788e 784 (set_attr "type" "alus_imm,alus_reg,alus_imm,alus_imm,alus_reg")]
7c36fe71 785 )
ebcc79bc 786
080c0b9a 787(define_insn "*addsi3_carryin_<optab>"
7c36fe71 788 [(set (match_operand:SI 0 "s_register_operand" "=l,r,r")
789 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%l,r,r")
790 (match_operand:SI 2 "arm_not_operand" "0,rI,K"))
791 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))]
25f905c2 792 "TARGET_32BIT"
10e5ccd5 793 "@
a0b3420a 794 adc%?\\t%0, %1, %2
10e5ccd5 795 adc%?\\t%0, %1, %2
796 sbc%?\\t%0, %1, #%B2"
a7de272d 797 [(set_attr "conds" "use")
7c36fe71 798 (set_attr "predicable" "yes")
799 (set_attr "arch" "t2,*,*")
800 (set_attr "length" "4")
1b7da4ac 801 (set_attr "predicable_short_it" "yes,no,no")
802 (set_attr "type" "adc_reg,adc_reg,adc_imm")]
cffb2a26 803)
ebcc79bc 804
080c0b9a 805(define_insn "*addsi3_carryin_alt2_<optab>"
7c36fe71 806 [(set (match_operand:SI 0 "s_register_operand" "=l,r,r")
807 (plus:SI (plus:SI (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))
808 (match_operand:SI 1 "s_register_operand" "%l,r,r"))
809 (match_operand:SI 2 "arm_rhs_operand" "l,rI,K")))]
25f905c2 810 "TARGET_32BIT"
10e5ccd5 811 "@
a0b3420a 812 adc%?\\t%0, %1, %2
10e5ccd5 813 adc%?\\t%0, %1, %2
814 sbc%?\\t%0, %1, #%B2"
a7de272d 815 [(set_attr "conds" "use")
7c36fe71 816 (set_attr "predicable" "yes")
817 (set_attr "arch" "t2,*,*")
818 (set_attr "length" "4")
1b7da4ac 819 (set_attr "predicable_short_it" "yes,no,no")
820 (set_attr "type" "adc_reg,adc_reg,adc_imm")]
0d66636f 821)
ebcc79bc 822
080c0b9a 823(define_insn "*addsi3_carryin_shift_<optab>"
ebcc79bc 824 [(set (match_operand:SI 0 "s_register_operand" "=r")
080c0b9a 825 (plus:SI (plus:SI
826 (match_operator:SI 2 "shift_operator"
827 [(match_operand:SI 3 "s_register_operand" "r")
828 (match_operand:SI 4 "reg_or_int_operand" "rM")])
829 (match_operand:SI 1 "s_register_operand" "r"))
830 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))]
25f905c2 831 "TARGET_32BIT"
080c0b9a 832 "adc%?\\t%0, %1, %3%S2"
833 [(set_attr "conds" "use")
a7de272d 834 (set_attr "predicable" "yes")
7c36fe71 835 (set_attr "predicable_short_it" "no")
080c0b9a 836 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
d82e788e 837 (const_string "alu_shift_imm")
838 (const_string "alu_shift_reg")))]
cffb2a26 839)
ebcc79bc 840
922b6913 841(define_insn "*addsi3_carryin_clobercc_<optab>"
842 [(set (match_operand:SI 0 "s_register_operand" "=r")
843 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%r")
844 (match_operand:SI 2 "arm_rhs_operand" "rI"))
845 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))
846 (clobber (reg:CC CC_REGNUM))]
847 "TARGET_32BIT"
848 "adc%.\\t%0, %1, %2"
1b7da4ac 849 [(set_attr "conds" "set")
850 (set_attr "type" "adcs_reg")]
922b6913 851)
852
9154bd82 853(define_insn "*subsi3_carryin"
854 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
855 (minus:SI (minus:SI (match_operand:SI 1 "reg_or_int_operand" "r,I")
856 (match_operand:SI 2 "s_register_operand" "r,r"))
857 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
858 "TARGET_32BIT"
859 "@
860 sbc%?\\t%0, %1, %2
861 rsc%?\\t%0, %2, %1"
862 [(set_attr "conds" "use")
863 (set_attr "arch" "*,a")
7c36fe71 864 (set_attr "predicable" "yes")
1b7da4ac 865 (set_attr "predicable_short_it" "no")
866 (set_attr "type" "adc_reg,adc_imm")]
9154bd82 867)
868
869(define_insn "*subsi3_carryin_const"
870 [(set (match_operand:SI 0 "s_register_operand" "=r")
871 (minus:SI (plus:SI (match_operand:SI 1 "reg_or_int_operand" "r")
872 (match_operand:SI 2 "arm_not_operand" "K"))
873 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
874 "TARGET_32BIT"
875 "sbc\\t%0, %1, #%B2"
1b7da4ac 876 [(set_attr "conds" "use")
877 (set_attr "type" "adc_imm")]
9154bd82 878)
879
880(define_insn "*subsi3_carryin_compare"
881 [(set (reg:CC CC_REGNUM)
882 (compare:CC (match_operand:SI 1 "s_register_operand" "r")
883 (match_operand:SI 2 "s_register_operand" "r")))
884 (set (match_operand:SI 0 "s_register_operand" "=r")
885 (minus:SI (minus:SI (match_dup 1)
886 (match_dup 2))
887 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
888 "TARGET_32BIT"
889 "sbcs\\t%0, %1, %2"
1b7da4ac 890 [(set_attr "conds" "set")
891 (set_attr "type" "adcs_reg")]
9154bd82 892)
893
894(define_insn "*subsi3_carryin_compare_const"
895 [(set (reg:CC CC_REGNUM)
896 (compare:CC (match_operand:SI 1 "reg_or_int_operand" "r")
897 (match_operand:SI 2 "arm_not_operand" "K")))
898 (set (match_operand:SI 0 "s_register_operand" "=r")
899 (minus:SI (plus:SI (match_dup 1)
900 (match_dup 2))
901 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
902 "TARGET_32BIT"
903 "sbcs\\t%0, %1, #%B2"
1b7da4ac 904 [(set_attr "conds" "set")
905 (set_attr "type" "adcs_imm")]
9154bd82 906)
907
908(define_insn "*subsi3_carryin_shift"
909 [(set (match_operand:SI 0 "s_register_operand" "=r")
910 (minus:SI (minus:SI
911 (match_operand:SI 1 "s_register_operand" "r")
912 (match_operator:SI 2 "shift_operator"
913 [(match_operand:SI 3 "s_register_operand" "r")
914 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
915 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
916 "TARGET_32BIT"
917 "sbc%?\\t%0, %1, %3%S2"
918 [(set_attr "conds" "use")
919 (set_attr "predicable" "yes")
920 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
d82e788e 921 (const_string "alu_shift_imm")
922 (const_string "alu_shift_reg")))]
9154bd82 923)
924
925(define_insn "*rsbsi3_carryin_shift"
926 [(set (match_operand:SI 0 "s_register_operand" "=r")
927 (minus:SI (minus:SI
928 (match_operator:SI 2 "shift_operator"
929 [(match_operand:SI 3 "s_register_operand" "r")
930 (match_operand:SI 4 "reg_or_int_operand" "rM")])
931 (match_operand:SI 1 "s_register_operand" "r"))
932 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
933 "TARGET_ARM"
934 "rsc%?\\t%0, %1, %3%S2"
935 [(set_attr "conds" "use")
936 (set_attr "predicable" "yes")
937 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
d82e788e 938 (const_string "alu_shift_imm")
939 (const_string "alu_shift_reg")))]
9154bd82 940)
941
d795fb69 942; transform ((x << y) - 1) to ~(~(x-1) << y) Where X is a constant.
943(define_split
944 [(set (match_operand:SI 0 "s_register_operand" "")
945 (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
946 (match_operand:SI 2 "s_register_operand" ""))
947 (const_int -1)))
948 (clobber (match_operand:SI 3 "s_register_operand" ""))]
25f905c2 949 "TARGET_32BIT"
d795fb69 950 [(set (match_dup 3) (match_dup 1))
951 (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
952 "
953 operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
954")
955
604f3a0a 956(define_expand "addsf3"
957 [(set (match_operand:SF 0 "s_register_operand" "")
958 (plus:SF (match_operand:SF 1 "s_register_operand" "")
d86c91f6 959 (match_operand:SF 2 "s_register_operand" "")))]
25f905c2 960 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 961 "
604f3a0a 962")
963
604f3a0a 964(define_expand "adddf3"
965 [(set (match_operand:DF 0 "s_register_operand" "")
966 (plus:DF (match_operand:DF 1 "s_register_operand" "")
d86c91f6 967 (match_operand:DF 2 "s_register_operand" "")))]
a50d7267 968 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 969 "
604f3a0a 970")
971
cffb2a26 972(define_expand "subdi3"
973 [(parallel
974 [(set (match_operand:DI 0 "s_register_operand" "")
975 (minus:DI (match_operand:DI 1 "s_register_operand" "")
976 (match_operand:DI 2 "s_register_operand" "")))
bd5b4116 977 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 978 "TARGET_EITHER"
979 "
25f905c2 980 if (TARGET_THUMB1)
cffb2a26 981 {
0438d37f 982 if (!REG_P (operands[1]))
5aa8c5f0 983 operands[1] = force_reg (DImode, operands[1]);
0438d37f 984 if (!REG_P (operands[2]))
5aa8c5f0 985 operands[2] = force_reg (DImode, operands[2]);
cffb2a26 986 }
987 "
988)
989
2f9b23e3 990(define_insn_and_split "*arm_subdi3"
cffb2a26 991 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
9c08d1fa 992 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
993 (match_operand:DI 2 "s_register_operand" "r,0,0")))
bd5b4116 994 (clobber (reg:CC CC_REGNUM))]
94829feb 995 "TARGET_32BIT && !TARGET_NEON"
2f9b23e3 996 "#" ; "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
997 "&& reload_completed"
998 [(parallel [(set (reg:CC CC_REGNUM)
999 (compare:CC (match_dup 1) (match_dup 2)))
1000 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1001 (set (match_dup 3) (minus:SI (minus:SI (match_dup 4) (match_dup 5))
1002 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1003 {
1004 operands[3] = gen_highpart (SImode, operands[0]);
1005 operands[0] = gen_lowpart (SImode, operands[0]);
1006 operands[4] = gen_highpart (SImode, operands[1]);
1007 operands[1] = gen_lowpart (SImode, operands[1]);
1008 operands[5] = gen_highpart (SImode, operands[2]);
1009 operands[2] = gen_lowpart (SImode, operands[2]);
1010 }
cffb2a26 1011 [(set_attr "conds" "clob")
1b7da4ac 1012 (set_attr "length" "8")
1013 (set_attr "type" "multiple")]
cffb2a26 1014)
1015
2f9b23e3 1016(define_insn_and_split "*subdi_di_zesidi"
cffb2a26 1017 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 1018 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r")
9c08d1fa 1019 (zero_extend:DI
cffb2a26 1020 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 1021 (clobber (reg:CC CC_REGNUM))]
25f905c2 1022 "TARGET_32BIT"
2f9b23e3 1023 "#" ; "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
1024 "&& reload_completed"
1025 [(parallel [(set (reg:CC CC_REGNUM)
1026 (compare:CC (match_dup 1) (match_dup 2)))
1027 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1028 (set (match_dup 3) (minus:SI (plus:SI (match_dup 4) (match_dup 5))
1029 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1030 {
1031 operands[3] = gen_highpart (SImode, operands[0]);
1032 operands[0] = gen_lowpart (SImode, operands[0]);
1033 operands[4] = gen_highpart (SImode, operands[1]);
1034 operands[1] = gen_lowpart (SImode, operands[1]);
1035 operands[5] = GEN_INT (~0);
1036 }
cffb2a26 1037 [(set_attr "conds" "clob")
1b7da4ac 1038 (set_attr "length" "8")
1039 (set_attr "type" "multiple")]
cffb2a26 1040)
9c08d1fa 1041
2f9b23e3 1042(define_insn_and_split "*subdi_di_sesidi"
cffb2a26 1043 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 1044 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r")
9c08d1fa 1045 (sign_extend:DI
cffb2a26 1046 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 1047 (clobber (reg:CC CC_REGNUM))]
25f905c2 1048 "TARGET_32BIT"
2f9b23e3 1049 "#" ; "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
1050 "&& reload_completed"
1051 [(parallel [(set (reg:CC CC_REGNUM)
1052 (compare:CC (match_dup 1) (match_dup 2)))
1053 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1054 (set (match_dup 3) (minus:SI (minus:SI (match_dup 4)
1055 (ashiftrt:SI (match_dup 2)
1056 (const_int 31)))
1057 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1058 {
1059 operands[3] = gen_highpart (SImode, operands[0]);
1060 operands[0] = gen_lowpart (SImode, operands[0]);
1061 operands[4] = gen_highpart (SImode, operands[1]);
1062 operands[1] = gen_lowpart (SImode, operands[1]);
1063 }
cffb2a26 1064 [(set_attr "conds" "clob")
1b7da4ac 1065 (set_attr "length" "8")
1066 (set_attr "type" "multiple")]
cffb2a26 1067)
9c08d1fa 1068
2f9b23e3 1069(define_insn_and_split "*subdi_zesidi_di"
cffb2a26 1070 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1071 (minus:DI (zero_extend:DI
cffb2a26 1072 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 1073 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 1074 (clobber (reg:CC CC_REGNUM))]
cffb2a26 1075 "TARGET_ARM"
2f9b23e3 1076 "#" ; "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
1077 ; is equivalent to:
1078 ; "subs\\t%Q0, %2, %Q1\;rsc\\t%R0, %R1, #0"
1079 "&& reload_completed"
1080 [(parallel [(set (reg:CC CC_REGNUM)
1081 (compare:CC (match_dup 2) (match_dup 1)))
1082 (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))])
1083 (set (match_dup 3) (minus:SI (minus:SI (const_int 0) (match_dup 4))
1084 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1085 {
1086 operands[3] = gen_highpart (SImode, operands[0]);
1087 operands[0] = gen_lowpart (SImode, operands[0]);
1088 operands[4] = gen_highpart (SImode, operands[1]);
1089 operands[1] = gen_lowpart (SImode, operands[1]);
1090 }
cffb2a26 1091 [(set_attr "conds" "clob")
1b7da4ac 1092 (set_attr "length" "8")
1093 (set_attr "type" "multiple")]
cffb2a26 1094)
9c08d1fa 1095
2f9b23e3 1096(define_insn_and_split "*subdi_sesidi_di"
cffb2a26 1097 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1098 (minus:DI (sign_extend:DI
cffb2a26 1099 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 1100 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 1101 (clobber (reg:CC CC_REGNUM))]
cffb2a26 1102 "TARGET_ARM"
2f9b23e3 1103 "#" ; "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
1104 ; is equivalent to:
1105 ; "subs\\t%Q0, %2, %Q1\;rsc\\t%R0, %R1, %2, asr #31"
1106 "&& reload_completed"
1107 [(parallel [(set (reg:CC CC_REGNUM)
1108 (compare:CC (match_dup 2) (match_dup 1)))
1109 (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))])
1110 (set (match_dup 3) (minus:SI (minus:SI
1111 (ashiftrt:SI (match_dup 2)
1112 (const_int 31))
1113 (match_dup 4))
1114 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1115 {
1116 operands[3] = gen_highpart (SImode, operands[0]);
1117 operands[0] = gen_lowpart (SImode, operands[0]);
1118 operands[4] = gen_highpart (SImode, operands[1]);
1119 operands[1] = gen_lowpart (SImode, operands[1]);
1120 }
cffb2a26 1121 [(set_attr "conds" "clob")
1b7da4ac 1122 (set_attr "length" "8")
1123 (set_attr "type" "multiple")]
cffb2a26 1124)
9c08d1fa 1125
2f9b23e3 1126(define_insn_and_split "*subdi_zesidi_zesidi"
cffb2a26 1127 [(set (match_operand:DI 0 "s_register_operand" "=r")
9c08d1fa 1128 (minus:DI (zero_extend:DI
cffb2a26 1129 (match_operand:SI 1 "s_register_operand" "r"))
9c08d1fa 1130 (zero_extend:DI
cffb2a26 1131 (match_operand:SI 2 "s_register_operand" "r"))))
bd5b4116 1132 (clobber (reg:CC CC_REGNUM))]
25f905c2 1133 "TARGET_32BIT"
2f9b23e3 1134 "#" ; "subs\\t%Q0, %1, %2\;sbc\\t%R0, %1, %1"
1135 "&& reload_completed"
1136 [(parallel [(set (reg:CC CC_REGNUM)
1137 (compare:CC (match_dup 1) (match_dup 2)))
1138 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1139 (set (match_dup 3) (minus:SI (minus:SI (match_dup 1) (match_dup 1))
1140 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1141 {
1142 operands[3] = gen_highpart (SImode, operands[0]);
1143 operands[0] = gen_lowpart (SImode, operands[0]);
1144 }
cffb2a26 1145 [(set_attr "conds" "clob")
1b7da4ac 1146 (set_attr "length" "8")
1147 (set_attr "type" "multiple")]
cffb2a26 1148)
b11cae9e 1149
87b22bf7 1150(define_expand "subsi3"
cffb2a26 1151 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 1152 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
1153 (match_operand:SI 2 "s_register_operand" "")))]
cffb2a26 1154 "TARGET_EITHER"
87b22bf7 1155 "
0438d37f 1156 if (CONST_INT_P (operands[1]))
87b22bf7 1157 {
25f905c2 1158 if (TARGET_32BIT)
cffb2a26 1159 {
96f57e36 1160 arm_split_constant (MINUS, SImode, NULL_RTX,
1161 INTVAL (operands[1]), operands[0],
e1ba4a27 1162 operands[2], optimize && can_create_pseudo_p ());
cffb2a26 1163 DONE;
1164 }
25f905c2 1165 else /* TARGET_THUMB1 */
cffb2a26 1166 operands[1] = force_reg (SImode, operands[1]);
87b22bf7 1167 }
cffb2a26 1168 "
1169)
87b22bf7 1170
25f905c2 1171; ??? Check Thumb-2 split length
a0f94409 1172(define_insn_and_split "*arm_subsi3_insn"
7c36fe71 1173 [(set (match_operand:SI 0 "s_register_operand" "=l,l ,l ,l ,r ,r,r,rk,r")
1174 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "l ,0 ,l ,Pz,rI,r,r,k ,?n")
1175 (match_operand:SI 2 "reg_or_int_operand" "l ,Py,Pd,l ,r ,I,r,r ,r")))]
25f905c2 1176 "TARGET_32BIT"
e2348bcb 1177 "@
7c36fe71 1178 sub%?\\t%0, %1, %2
1179 sub%?\\t%0, %2
1180 sub%?\\t%0, %1, %2
1181 rsb%?\\t%0, %2, %1
87b22bf7 1182 rsb%?\\t%0, %2, %1
aaa37ad6 1183 sub%?\\t%0, %1, %2
080c0b9a 1184 sub%?\\t%0, %1, %2
65f68e55 1185 sub%?\\t%0, %1, %2
87b22bf7 1186 #"
0438d37f 1187 "&& (CONST_INT_P (operands[1])
91a5e339 1188 && !const_ok_for_arm (INTVAL (operands[1])))"
87b22bf7 1189 [(clobber (const_int 0))]
1190 "
96f57e36 1191 arm_split_constant (MINUS, SImode, curr_insn,
1192 INTVAL (operands[1]), operands[0], operands[2], 0);
87b22bf7 1193 DONE;
cffb2a26 1194 "
7c36fe71 1195 [(set_attr "length" "4,4,4,4,4,4,4,4,16")
1196 (set_attr "arch" "t2,t2,t2,t2,*,*,*,*,*")
65f68e55 1197 (set_attr "predicable" "yes")
7c36fe71 1198 (set_attr "predicable_short_it" "yes,yes,yes,yes,no,no,no,no,no")
1b7da4ac 1199 (set_attr "type" "alu_reg,alu_reg,alu_reg,alu_reg,alu_imm,alu_imm,alu_reg,alu_reg,multiple")]
a0f94409 1200)
1201
1202(define_peephole2
1203 [(match_scratch:SI 3 "r")
372575c7 1204 (set (match_operand:SI 0 "arm_general_register_operand" "")
a0f94409 1205 (minus:SI (match_operand:SI 1 "const_int_operand" "")
372575c7 1206 (match_operand:SI 2 "arm_general_register_operand" "")))]
25f905c2 1207 "TARGET_32BIT
a0f94409 1208 && !const_ok_for_arm (INTVAL (operands[1]))
1209 && const_ok_for_arm (~INTVAL (operands[1]))"
1210 [(set (match_dup 3) (match_dup 1))
1211 (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1212 ""
cffb2a26 1213)
b11cae9e 1214
f7fbdd4a 1215(define_insn "*subsi3_compare0"
bd5b4116 1216 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1217 (compare:CC_NOOV
65f68e55 1218 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,r,I")
1219 (match_operand:SI 2 "arm_rhs_operand" "I,r,r"))
215b30b3 1220 (const_int 0)))
65f68e55 1221 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9c08d1fa 1222 (minus:SI (match_dup 1) (match_dup 2)))]
25f905c2 1223 "TARGET_32BIT"
e2348bcb 1224 "@
65f68e55 1225 sub%.\\t%0, %1, %2
25f905c2 1226 sub%.\\t%0, %1, %2
1227 rsb%.\\t%0, %2, %1"
65f68e55 1228 [(set_attr "conds" "set")
d82e788e 1229 (set_attr "type" "alus_imm,alus_reg,alus_reg")]
cffb2a26 1230)
9c08d1fa 1231
190efb17 1232(define_insn "subsi3_compare"
080c0b9a 1233 [(set (reg:CC CC_REGNUM)
65f68e55 1234 (compare:CC (match_operand:SI 1 "arm_rhs_operand" "r,r,I")
1235 (match_operand:SI 2 "arm_rhs_operand" "I,r,r")))
1236 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2df9477b 1237 (minus:SI (match_dup 1) (match_dup 2)))]
1238 "TARGET_32BIT"
1239 "@
65f68e55 1240 sub%.\\t%0, %1, %2
2df9477b 1241 sub%.\\t%0, %1, %2
1242 rsb%.\\t%0, %2, %1"
65f68e55 1243 [(set_attr "conds" "set")
d82e788e 1244 (set_attr "type" "alus_imm,alus_reg,alus_reg")]
2df9477b 1245)
1246
604f3a0a 1247(define_expand "subsf3"
1248 [(set (match_operand:SF 0 "s_register_operand" "")
d86c91f6 1249 (minus:SF (match_operand:SF 1 "s_register_operand" "")
1250 (match_operand:SF 2 "s_register_operand" "")))]
25f905c2 1251 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1252 "
604f3a0a 1253")
1254
604f3a0a 1255(define_expand "subdf3"
1256 [(set (match_operand:DF 0 "s_register_operand" "")
d86c91f6 1257 (minus:DF (match_operand:DF 1 "s_register_operand" "")
1258 (match_operand:DF 2 "s_register_operand" "")))]
a50d7267 1259 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 1260 "
604f3a0a 1261")
1262
b11cae9e 1263\f
1264;; Multiplication insns
1265
4422d91f 1266(define_expand "mulhi3"
1267 [(set (match_operand:HI 0 "s_register_operand" "")
1268 (mult:HI (match_operand:HI 1 "s_register_operand" "")
1269 (match_operand:HI 2 "s_register_operand" "")))]
1270 "TARGET_DSP_MULTIPLY"
1271 "
1272 {
1273 rtx result = gen_reg_rtx (SImode);
1274 emit_insn (gen_mulhisi3 (result, operands[1], operands[2]));
1275 emit_move_insn (operands[0], gen_lowpart (HImode, result));
1276 DONE;
1277 }"
1278)
1279
cffb2a26 1280(define_expand "mulsi3"
1281 [(set (match_operand:SI 0 "s_register_operand" "")
1282 (mult:SI (match_operand:SI 2 "s_register_operand" "")
1283 (match_operand:SI 1 "s_register_operand" "")))]
1284 "TARGET_EITHER"
1285 ""
1286)
1287
9c08d1fa 1288;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
cffb2a26 1289(define_insn "*arm_mulsi3"
1290 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1291 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1292 (match_operand:SI 1 "s_register_operand" "%0,r")))]
58d7d654 1293 "TARGET_32BIT && !arm_arch6"
f7fbdd4a 1294 "mul%?\\t%0, %2, %1"
9da0ec36 1295 [(set_attr "type" "mul")
0d66636f 1296 (set_attr "predicable" "yes")]
cffb2a26 1297)
1298
58d7d654 1299(define_insn "*arm_mulsi3_v6"
d952d547 1300 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
1301 (mult:SI (match_operand:SI 1 "s_register_operand" "0,l,r")
1302 (match_operand:SI 2 "s_register_operand" "l,0,r")))]
58d7d654 1303 "TARGET_32BIT && arm_arch6"
1304 "mul%?\\t%0, %1, %2"
9da0ec36 1305 [(set_attr "type" "mul")
d952d547 1306 (set_attr "predicable" "yes")
1307 (set_attr "arch" "t2,t2,*")
1308 (set_attr "length" "4")
1309 (set_attr "predicable_short_it" "yes,yes,no")]
58d7d654 1310)
1311
f7fbdd4a 1312(define_insn "*mulsi3_compare0"
bd5b4116 1313 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1314 (compare:CC_NOOV (mult:SI
1315 (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1316 (match_operand:SI 1 "s_register_operand" "%0,r"))
9c08d1fa 1317 (const_int 0)))
1318 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1319 (mult:SI (match_dup 2) (match_dup 1)))]
58d7d654 1320 "TARGET_ARM && !arm_arch6"
1321 "mul%.\\t%0, %2, %1"
1322 [(set_attr "conds" "set")
9da0ec36 1323 (set_attr "type" "muls")]
58d7d654 1324)
1325
1326(define_insn "*mulsi3_compare0_v6"
1327 [(set (reg:CC_NOOV CC_REGNUM)
1328 (compare:CC_NOOV (mult:SI
1329 (match_operand:SI 2 "s_register_operand" "r")
1330 (match_operand:SI 1 "s_register_operand" "r"))
1331 (const_int 0)))
1332 (set (match_operand:SI 0 "s_register_operand" "=r")
1333 (mult:SI (match_dup 2) (match_dup 1)))]
1334 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1335 "mul%.\\t%0, %2, %1"
cffb2a26 1336 [(set_attr "conds" "set")
9da0ec36 1337 (set_attr "type" "muls")]
cffb2a26 1338)
9c08d1fa 1339
f7fbdd4a 1340(define_insn "*mulsi_compare0_scratch"
bd5b4116 1341 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1342 (compare:CC_NOOV (mult:SI
1343 (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1344 (match_operand:SI 1 "s_register_operand" "%0,r"))
9c08d1fa 1345 (const_int 0)))
1346 (clobber (match_scratch:SI 0 "=&r,&r"))]
58d7d654 1347 "TARGET_ARM && !arm_arch6"
1348 "mul%.\\t%0, %2, %1"
1349 [(set_attr "conds" "set")
9da0ec36 1350 (set_attr "type" "muls")]
58d7d654 1351)
1352
1353(define_insn "*mulsi_compare0_scratch_v6"
1354 [(set (reg:CC_NOOV CC_REGNUM)
1355 (compare:CC_NOOV (mult:SI
1356 (match_operand:SI 2 "s_register_operand" "r")
1357 (match_operand:SI 1 "s_register_operand" "r"))
1358 (const_int 0)))
1359 (clobber (match_scratch:SI 0 "=r"))]
1360 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1361 "mul%.\\t%0, %2, %1"
cffb2a26 1362 [(set_attr "conds" "set")
9da0ec36 1363 (set_attr "type" "muls")]
cffb2a26 1364)
9c08d1fa 1365
b11cae9e 1366;; Unnamed templates to match MLA instruction.
1367
f7fbdd4a 1368(define_insn "*mulsi3addsi"
9c08d1fa 1369 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
c8f69309 1370 (plus:SI
9c08d1fa 1371 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1372 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1373 (match_operand:SI 3 "s_register_operand" "r,r,0,0")))]
58d7d654 1374 "TARGET_32BIT && !arm_arch6"
1375 "mla%?\\t%0, %2, %1, %3"
9da0ec36 1376 [(set_attr "type" "mla")
58d7d654 1377 (set_attr "predicable" "yes")]
1378)
1379
1380(define_insn "*mulsi3addsi_v6"
1381 [(set (match_operand:SI 0 "s_register_operand" "=r")
1382 (plus:SI
1383 (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1384 (match_operand:SI 1 "s_register_operand" "r"))
1385 (match_operand:SI 3 "s_register_operand" "r")))]
1386 "TARGET_32BIT && arm_arch6"
f7fbdd4a 1387 "mla%?\\t%0, %2, %1, %3"
9da0ec36 1388 [(set_attr "type" "mla")
d952d547 1389 (set_attr "predicable" "yes")
1390 (set_attr "predicable_short_it" "no")]
0d66636f 1391)
b11cae9e 1392
f7fbdd4a 1393(define_insn "*mulsi3addsi_compare0"
bd5b4116 1394 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1395 (compare:CC_NOOV
1396 (plus:SI (mult:SI
1397 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1398 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1399 (match_operand:SI 3 "s_register_operand" "r,r,0,0"))
215b30b3 1400 (const_int 0)))
9c08d1fa 1401 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1402 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1403 (match_dup 3)))]
58d7d654 1404 "TARGET_ARM && arm_arch6"
1405 "mla%.\\t%0, %2, %1, %3"
1406 [(set_attr "conds" "set")
9da0ec36 1407 (set_attr "type" "mlas")]
58d7d654 1408)
1409
1410(define_insn "*mulsi3addsi_compare0_v6"
1411 [(set (reg:CC_NOOV CC_REGNUM)
1412 (compare:CC_NOOV
1413 (plus:SI (mult:SI
1414 (match_operand:SI 2 "s_register_operand" "r")
1415 (match_operand:SI 1 "s_register_operand" "r"))
1416 (match_operand:SI 3 "s_register_operand" "r"))
1417 (const_int 0)))
1418 (set (match_operand:SI 0 "s_register_operand" "=r")
1419 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1420 (match_dup 3)))]
1421 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1422 "mla%.\\t%0, %2, %1, %3"
0d66636f 1423 [(set_attr "conds" "set")
9da0ec36 1424 (set_attr "type" "mlas")]
0d66636f 1425)
9c08d1fa 1426
f7fbdd4a 1427(define_insn "*mulsi3addsi_compare0_scratch"
bd5b4116 1428 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1429 (compare:CC_NOOV
1430 (plus:SI (mult:SI
1431 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1432 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
215b30b3 1433 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1434 (const_int 0)))
9c08d1fa 1435 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
58d7d654 1436 "TARGET_ARM && !arm_arch6"
1437 "mla%.\\t%0, %2, %1, %3"
1438 [(set_attr "conds" "set")
9da0ec36 1439 (set_attr "type" "mlas")]
58d7d654 1440)
1441
1442(define_insn "*mulsi3addsi_compare0_scratch_v6"
1443 [(set (reg:CC_NOOV CC_REGNUM)
1444 (compare:CC_NOOV
1445 (plus:SI (mult:SI
1446 (match_operand:SI 2 "s_register_operand" "r")
1447 (match_operand:SI 1 "s_register_operand" "r"))
1448 (match_operand:SI 3 "s_register_operand" "r"))
1449 (const_int 0)))
1450 (clobber (match_scratch:SI 0 "=r"))]
1451 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1452 "mla%.\\t%0, %2, %1, %3"
cffb2a26 1453 [(set_attr "conds" "set")
9da0ec36 1454 (set_attr "type" "mlas")]
cffb2a26 1455)
f7fbdd4a 1456
89545238 1457(define_insn "*mulsi3subsi"
1458 [(set (match_operand:SI 0 "s_register_operand" "=r")
1459 (minus:SI
1460 (match_operand:SI 3 "s_register_operand" "r")
1461 (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1462 (match_operand:SI 1 "s_register_operand" "r"))))]
1463 "TARGET_32BIT && arm_arch_thumb2"
1464 "mls%?\\t%0, %2, %1, %3"
9da0ec36 1465 [(set_attr "type" "mla")
d952d547 1466 (set_attr "predicable" "yes")
1467 (set_attr "predicable_short_it" "no")]
89545238 1468)
1469
5cdca009 1470(define_expand "maddsidi4"
1471 [(set (match_operand:DI 0 "s_register_operand" "")
1472 (plus:DI
1473 (mult:DI
1474 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1475 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1476 (match_operand:DI 3 "s_register_operand" "")))]
1477 "TARGET_32BIT && arm_arch3m"
1478 "")
82b85d08 1479
1480(define_insn "*mulsidi3adddi"
fe8dbf85 1481 [(set (match_operand:DI 0 "s_register_operand" "=&r")
82b85d08 1482 (plus:DI
215b30b3 1483 (mult:DI
fe8dbf85 1484 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1485 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1486 (match_operand:DI 1 "s_register_operand" "0")))]
58d7d654 1487 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1488 "smlal%?\\t%Q0, %R0, %3, %2"
9da0ec36 1489 [(set_attr "type" "smlal")
58d7d654 1490 (set_attr "predicable" "yes")]
1491)
1492
1493(define_insn "*mulsidi3adddi_v6"
1494 [(set (match_operand:DI 0 "s_register_operand" "=r")
1495 (plus:DI
1496 (mult:DI
1497 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1498 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1499 (match_operand:DI 1 "s_register_operand" "0")))]
1500 "TARGET_32BIT && arm_arch6"
fe8dbf85 1501 "smlal%?\\t%Q0, %R0, %3, %2"
9da0ec36 1502 [(set_attr "type" "smlal")
d952d547 1503 (set_attr "predicable" "yes")
1504 (set_attr "predicable_short_it" "no")]
0d66636f 1505)
82b85d08 1506
957788b0 1507;; 32x32->64 widening multiply.
1508;; As with mulsi3, the only difference between the v3-5 and v6+
1509;; versions of these patterns is the requirement that the output not
1510;; overlap the inputs, but that still means we have to have a named
1511;; expander and two different starred insns.
1512
1513(define_expand "mulsidi3"
1514 [(set (match_operand:DI 0 "s_register_operand" "")
1515 (mult:DI
1516 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1517 (sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1518 "TARGET_32BIT && arm_arch3m"
1519 ""
1520)
1521
1522(define_insn "*mulsidi3_nov6"
f7fbdd4a 1523 [(set (match_operand:DI 0 "s_register_operand" "=&r")
215b30b3 1524 (mult:DI
1525 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1526 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
58d7d654 1527 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1528 "smull%?\\t%Q0, %R0, %1, %2"
9da0ec36 1529 [(set_attr "type" "smull")
58d7d654 1530 (set_attr "predicable" "yes")]
1531)
1532
957788b0 1533(define_insn "*mulsidi3_v6"
58d7d654 1534 [(set (match_operand:DI 0 "s_register_operand" "=r")
1535 (mult:DI
1536 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1537 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1538 "TARGET_32BIT && arm_arch6"
97499065 1539 "smull%?\\t%Q0, %R0, %1, %2"
9da0ec36 1540 [(set_attr "type" "smull")
d952d547 1541 (set_attr "predicable" "yes")
1542 (set_attr "predicable_short_it" "no")]
0d66636f 1543)
f7fbdd4a 1544
957788b0 1545(define_expand "umulsidi3"
1546 [(set (match_operand:DI 0 "s_register_operand" "")
1547 (mult:DI
1548 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1549 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1550 "TARGET_32BIT && arm_arch3m"
1551 ""
1552)
1553
1554(define_insn "*umulsidi3_nov6"
f7fbdd4a 1555 [(set (match_operand:DI 0 "s_register_operand" "=&r")
215b30b3 1556 (mult:DI
1557 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1558 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
58d7d654 1559 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1560 "umull%?\\t%Q0, %R0, %1, %2"
9da0ec36 1561 [(set_attr "type" "umull")
58d7d654 1562 (set_attr "predicable" "yes")]
1563)
1564
957788b0 1565(define_insn "*umulsidi3_v6"
58d7d654 1566 [(set (match_operand:DI 0 "s_register_operand" "=r")
1567 (mult:DI
1568 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1569 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1570 "TARGET_32BIT && arm_arch6"
97499065 1571 "umull%?\\t%Q0, %R0, %1, %2"
9da0ec36 1572 [(set_attr "type" "umull")
d952d547 1573 (set_attr "predicable" "yes")
1574 (set_attr "predicable_short_it" "no")]
0d66636f 1575)
b11cae9e 1576
5cdca009 1577(define_expand "umaddsidi4"
1578 [(set (match_operand:DI 0 "s_register_operand" "")
1579 (plus:DI
1580 (mult:DI
1581 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1582 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1583 (match_operand:DI 3 "s_register_operand" "")))]
1584 "TARGET_32BIT && arm_arch3m"
1585 "")
82b85d08 1586
1587(define_insn "*umulsidi3adddi"
8ead09f9 1588 [(set (match_operand:DI 0 "s_register_operand" "=&r")
82b85d08 1589 (plus:DI
215b30b3 1590 (mult:DI
fe8dbf85 1591 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1592 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1593 (match_operand:DI 1 "s_register_operand" "0")))]
58d7d654 1594 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1595 "umlal%?\\t%Q0, %R0, %3, %2"
9da0ec36 1596 [(set_attr "type" "umlal")
58d7d654 1597 (set_attr "predicable" "yes")]
1598)
1599
1600(define_insn "*umulsidi3adddi_v6"
1601 [(set (match_operand:DI 0 "s_register_operand" "=r")
1602 (plus:DI
1603 (mult:DI
1604 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1605 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1606 (match_operand:DI 1 "s_register_operand" "0")))]
1607 "TARGET_32BIT && arm_arch6"
fe8dbf85 1608 "umlal%?\\t%Q0, %R0, %3, %2"
9da0ec36 1609 [(set_attr "type" "umlal")
d952d547 1610 (set_attr "predicable" "yes")
1611 (set_attr "predicable_short_it" "no")]
0d66636f 1612)
82b85d08 1613
957788b0 1614(define_expand "smulsi3_highpart"
1615 [(parallel
1616 [(set (match_operand:SI 0 "s_register_operand" "")
1617 (truncate:SI
1618 (lshiftrt:DI
1619 (mult:DI
1620 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1621 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1622 (const_int 32))))
1623 (clobber (match_scratch:SI 3 ""))])]
1624 "TARGET_32BIT && arm_arch3m"
1625 ""
1626)
1627
1628(define_insn "*smulsi3_highpart_nov6"
f082f1c4 1629 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1630 (truncate:SI
1631 (lshiftrt:DI
215b30b3 1632 (mult:DI
e5fea38e 1633 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
215b30b3 1634 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
f082f1c4 1635 (const_int 32))))
1636 (clobber (match_scratch:SI 3 "=&r,&r"))]
58d7d654 1637 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1638 "smull%?\\t%3, %0, %2, %1"
9da0ec36 1639 [(set_attr "type" "smull")
58d7d654 1640 (set_attr "predicable" "yes")]
1641)
1642
957788b0 1643(define_insn "*smulsi3_highpart_v6"
58d7d654 1644 [(set (match_operand:SI 0 "s_register_operand" "=r")
1645 (truncate:SI
1646 (lshiftrt:DI
1647 (mult:DI
1648 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1649 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1650 (const_int 32))))
1651 (clobber (match_scratch:SI 3 "=r"))]
1652 "TARGET_32BIT && arm_arch6"
f082f1c4 1653 "smull%?\\t%3, %0, %2, %1"
9da0ec36 1654 [(set_attr "type" "smull")
d952d547 1655 (set_attr "predicable" "yes")
1656 (set_attr "predicable_short_it" "no")]
cffb2a26 1657)
f082f1c4 1658
957788b0 1659(define_expand "umulsi3_highpart"
1660 [(parallel
1661 [(set (match_operand:SI 0 "s_register_operand" "")
1662 (truncate:SI
1663 (lshiftrt:DI
1664 (mult:DI
1665 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1666 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1667 (const_int 32))))
1668 (clobber (match_scratch:SI 3 ""))])]
1669 "TARGET_32BIT && arm_arch3m"
1670 ""
1671)
1672
1673(define_insn "*umulsi3_highpart_nov6"
f082f1c4 1674 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1675 (truncate:SI
1676 (lshiftrt:DI
215b30b3 1677 (mult:DI
e5fea38e 1678 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
215b30b3 1679 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
f082f1c4 1680 (const_int 32))))
1681 (clobber (match_scratch:SI 3 "=&r,&r"))]
58d7d654 1682 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1683 "umull%?\\t%3, %0, %2, %1"
9da0ec36 1684 [(set_attr "type" "umull")
58d7d654 1685 (set_attr "predicable" "yes")]
1686)
1687
957788b0 1688(define_insn "*umulsi3_highpart_v6"
58d7d654 1689 [(set (match_operand:SI 0 "s_register_operand" "=r")
1690 (truncate:SI
1691 (lshiftrt:DI
1692 (mult:DI
1693 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1694 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1695 (const_int 32))))
1696 (clobber (match_scratch:SI 3 "=r"))]
1697 "TARGET_32BIT && arm_arch6"
f082f1c4 1698 "umull%?\\t%3, %0, %2, %1"
9da0ec36 1699 [(set_attr "type" "umull")
d952d547 1700 (set_attr "predicable" "yes")
1701 (set_attr "predicable_short_it" "no")]
cffb2a26 1702)
f082f1c4 1703
331beb1a 1704(define_insn "mulhisi3"
1705 [(set (match_operand:SI 0 "s_register_operand" "=r")
1706 (mult:SI (sign_extend:SI
1707 (match_operand:HI 1 "s_register_operand" "%r"))
1708 (sign_extend:SI
1709 (match_operand:HI 2 "s_register_operand" "r"))))]
25f905c2 1710 "TARGET_DSP_MULTIPLY"
61a2d04c 1711 "smulbb%?\\t%0, %1, %2"
9da0ec36 1712 [(set_attr "type" "smulxy")
fec538d9 1713 (set_attr "predicable" "yes")]
1714)
1715
1716(define_insn "*mulhisi3tb"
1717 [(set (match_operand:SI 0 "s_register_operand" "=r")
1718 (mult:SI (ashiftrt:SI
1719 (match_operand:SI 1 "s_register_operand" "r")
1720 (const_int 16))
1721 (sign_extend:SI
1722 (match_operand:HI 2 "s_register_operand" "r"))))]
25f905c2 1723 "TARGET_DSP_MULTIPLY"
fec538d9 1724 "smultb%?\\t%0, %1, %2"
9da0ec36 1725 [(set_attr "type" "smulxy")
d952d547 1726 (set_attr "predicable" "yes")
1727 (set_attr "predicable_short_it" "no")]
fec538d9 1728)
1729
1730(define_insn "*mulhisi3bt"
1731 [(set (match_operand:SI 0 "s_register_operand" "=r")
1732 (mult:SI (sign_extend:SI
1733 (match_operand:HI 1 "s_register_operand" "r"))
1734 (ashiftrt:SI
1735 (match_operand:SI 2 "s_register_operand" "r")
1736 (const_int 16))))]
25f905c2 1737 "TARGET_DSP_MULTIPLY"
fec538d9 1738 "smulbt%?\\t%0, %1, %2"
9da0ec36 1739 [(set_attr "type" "smulxy")
d952d547 1740 (set_attr "predicable" "yes")
1741 (set_attr "predicable_short_it" "no")]
fec538d9 1742)
1743
1744(define_insn "*mulhisi3tt"
1745 [(set (match_operand:SI 0 "s_register_operand" "=r")
1746 (mult:SI (ashiftrt:SI
1747 (match_operand:SI 1 "s_register_operand" "r")
1748 (const_int 16))
1749 (ashiftrt:SI
1750 (match_operand:SI 2 "s_register_operand" "r")
1751 (const_int 16))))]
25f905c2 1752 "TARGET_DSP_MULTIPLY"
fec538d9 1753 "smultt%?\\t%0, %1, %2"
9da0ec36 1754 [(set_attr "type" "smulxy")
d952d547 1755 (set_attr "predicable" "yes")
1756 (set_attr "predicable_short_it" "no")]
331beb1a 1757)
1758
5cdca009 1759(define_insn "maddhisi4"
331beb1a 1760 [(set (match_operand:SI 0 "s_register_operand" "=r")
cfa6c608 1761 (plus:SI (mult:SI (sign_extend:SI
1762 (match_operand:HI 1 "s_register_operand" "r"))
331beb1a 1763 (sign_extend:SI
cfa6c608 1764 (match_operand:HI 2 "s_register_operand" "r")))
1765 (match_operand:SI 3 "s_register_operand" "r")))]
25f905c2 1766 "TARGET_DSP_MULTIPLY"
5cdca009 1767 "smlabb%?\\t%0, %1, %2, %3"
9da0ec36 1768 [(set_attr "type" "smlaxy")
d952d547 1769 (set_attr "predicable" "yes")
1770 (set_attr "predicable_short_it" "no")]
331beb1a 1771)
1772
9a92f368 1773;; Note: there is no maddhisi4ibt because this one is canonical form
1774(define_insn "*maddhisi4tb"
1775 [(set (match_operand:SI 0 "s_register_operand" "=r")
1776 (plus:SI (mult:SI (ashiftrt:SI
1777 (match_operand:SI 1 "s_register_operand" "r")
1778 (const_int 16))
1779 (sign_extend:SI
1780 (match_operand:HI 2 "s_register_operand" "r")))
1781 (match_operand:SI 3 "s_register_operand" "r")))]
1782 "TARGET_DSP_MULTIPLY"
1783 "smlatb%?\\t%0, %1, %2, %3"
9da0ec36 1784 [(set_attr "type" "smlaxy")
d952d547 1785 (set_attr "predicable" "yes")
1786 (set_attr "predicable_short_it" "no")]
9a92f368 1787)
1788
1789(define_insn "*maddhisi4tt"
1790 [(set (match_operand:SI 0 "s_register_operand" "=r")
1791 (plus:SI (mult:SI (ashiftrt:SI
1792 (match_operand:SI 1 "s_register_operand" "r")
1793 (const_int 16))
1794 (ashiftrt:SI
1795 (match_operand:SI 2 "s_register_operand" "r")
1796 (const_int 16)))
1797 (match_operand:SI 3 "s_register_operand" "r")))]
1798 "TARGET_DSP_MULTIPLY"
1799 "smlatt%?\\t%0, %1, %2, %3"
9da0ec36 1800 [(set_attr "type" "smlaxy")
d952d547 1801 (set_attr "predicable" "yes")
1802 (set_attr "predicable_short_it" "no")]
9a92f368 1803)
1804
aff5fb4d 1805(define_insn "maddhidi4"
331beb1a 1806 [(set (match_operand:DI 0 "s_register_operand" "=r")
1807 (plus:DI
331beb1a 1808 (mult:DI (sign_extend:DI
d952d547 1809 (match_operand:HI 1 "s_register_operand" "r"))
331beb1a 1810 (sign_extend:DI
cfa6c608 1811 (match_operand:HI 2 "s_register_operand" "r")))
1812 (match_operand:DI 3 "s_register_operand" "0")))]
25f905c2 1813 "TARGET_DSP_MULTIPLY"
5cdca009 1814 "smlalbb%?\\t%Q0, %R0, %1, %2"
9da0ec36 1815 [(set_attr "type" "smlalxy")
d952d547 1816 (set_attr "predicable" "yes")
1817 (set_attr "predicable_short_it" "no")])
331beb1a 1818
9a92f368 1819;; Note: there is no maddhidi4ibt because this one is canonical form
1820(define_insn "*maddhidi4tb"
1821 [(set (match_operand:DI 0 "s_register_operand" "=r")
1822 (plus:DI
1823 (mult:DI (sign_extend:DI
1824 (ashiftrt:SI
1825 (match_operand:SI 1 "s_register_operand" "r")
1826 (const_int 16)))
1827 (sign_extend:DI
1828 (match_operand:HI 2 "s_register_operand" "r")))
1829 (match_operand:DI 3 "s_register_operand" "0")))]
1830 "TARGET_DSP_MULTIPLY"
1831 "smlaltb%?\\t%Q0, %R0, %1, %2"
9da0ec36 1832 [(set_attr "type" "smlalxy")
d952d547 1833 (set_attr "predicable" "yes")
1834 (set_attr "predicable_short_it" "no")])
9a92f368 1835
1836(define_insn "*maddhidi4tt"
1837 [(set (match_operand:DI 0 "s_register_operand" "=r")
1838 (plus:DI
1839 (mult:DI (sign_extend:DI
1840 (ashiftrt:SI
1841 (match_operand:SI 1 "s_register_operand" "r")
1842 (const_int 16)))
1843 (sign_extend:DI
1844 (ashiftrt:SI
1845 (match_operand:SI 2 "s_register_operand" "r")
1846 (const_int 16))))
1847 (match_operand:DI 3 "s_register_operand" "0")))]
1848 "TARGET_DSP_MULTIPLY"
1849 "smlaltt%?\\t%Q0, %R0, %1, %2"
9da0ec36 1850 [(set_attr "type" "smlalxy")
d952d547 1851 (set_attr "predicable" "yes")
1852 (set_attr "predicable_short_it" "no")])
9a92f368 1853
604f3a0a 1854(define_expand "mulsf3"
1855 [(set (match_operand:SF 0 "s_register_operand" "")
1856 (mult:SF (match_operand:SF 1 "s_register_operand" "")
d86c91f6 1857 (match_operand:SF 2 "s_register_operand" "")))]
25f905c2 1858 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1859 "
604f3a0a 1860")
1861
604f3a0a 1862(define_expand "muldf3"
1863 [(set (match_operand:DF 0 "s_register_operand" "")
1864 (mult:DF (match_operand:DF 1 "s_register_operand" "")
d86c91f6 1865 (match_operand:DF 2 "s_register_operand" "")))]
a50d7267 1866 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 1867 "
604f3a0a 1868")
b11cae9e 1869\f
1870;; Division insns
1871
7db9af5d 1872(define_expand "divsf3"
1873 [(set (match_operand:SF 0 "s_register_operand" "")
d86c91f6 1874 (div:SF (match_operand:SF 1 "s_register_operand" "")
1875 (match_operand:SF 2 "s_register_operand" "")))]
994606f8 1876 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
7db9af5d 1877 "")
9c08d1fa 1878
7db9af5d 1879(define_expand "divdf3"
1880 [(set (match_operand:DF 0 "s_register_operand" "")
d86c91f6 1881 (div:DF (match_operand:DF 1 "s_register_operand" "")
1882 (match_operand:DF 2 "s_register_operand" "")))]
994606f8 1883 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
7db9af5d 1884 "")
b11cae9e 1885\f
1886;; Boolean and,ior,xor insns
1887
f6ebffac 1888;; Split up double word logical operations
1889
1890;; Split up simple DImode logical operations. Simply perform the logical
1891;; operation on the upper and lower halves of the registers.
1892(define_split
1893 [(set (match_operand:DI 0 "s_register_operand" "")
1894 (match_operator:DI 6 "logical_binary_operator"
1895 [(match_operand:DI 1 "s_register_operand" "")
1896 (match_operand:DI 2 "s_register_operand" "")]))]
25f905c2 1897 "TARGET_32BIT && reload_completed
e2669ea7 1898 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))
25f905c2 1899 && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
f6ebffac 1900 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1901 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1902 "
215b30b3 1903 {
1904 operands[3] = gen_highpart (SImode, operands[0]);
1905 operands[0] = gen_lowpart (SImode, operands[0]);
1906 operands[4] = gen_highpart (SImode, operands[1]);
1907 operands[1] = gen_lowpart (SImode, operands[1]);
1908 operands[5] = gen_highpart (SImode, operands[2]);
1909 operands[2] = gen_lowpart (SImode, operands[2]);
1910 }"
1911)
f6ebffac 1912
f6ebffac 1913(define_split
1914 [(set (match_operand:DI 0 "s_register_operand" "")
1915 (match_operator:DI 6 "logical_binary_operator"
1916 [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1917 (match_operand:DI 1 "s_register_operand" "")]))]
25f905c2 1918 "TARGET_32BIT && reload_completed"
f6ebffac 1919 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1920 (set (match_dup 3) (match_op_dup:SI 6
1921 [(ashiftrt:SI (match_dup 2) (const_int 31))
1922 (match_dup 4)]))]
1923 "
215b30b3 1924 {
1925 operands[3] = gen_highpart (SImode, operands[0]);
1926 operands[0] = gen_lowpart (SImode, operands[0]);
1927 operands[4] = gen_highpart (SImode, operands[1]);
1928 operands[1] = gen_lowpart (SImode, operands[1]);
1929 operands[5] = gen_highpart (SImode, operands[2]);
1930 operands[2] = gen_lowpart (SImode, operands[2]);
1931 }"
1932)
f6ebffac 1933
f6ebffac 1934;; The zero extend of operand 2 means we can just copy the high part of
1935;; operand1 into operand0.
1936(define_split
1937 [(set (match_operand:DI 0 "s_register_operand" "")
1938 (ior:DI
1939 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1940 (match_operand:DI 1 "s_register_operand" "")))]
25f905c2 1941 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
f6ebffac 1942 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1943 (set (match_dup 3) (match_dup 4))]
1944 "
215b30b3 1945 {
1946 operands[4] = gen_highpart (SImode, operands[1]);
1947 operands[3] = gen_highpart (SImode, operands[0]);
1948 operands[0] = gen_lowpart (SImode, operands[0]);
1949 operands[1] = gen_lowpart (SImode, operands[1]);
1950 }"
1951)
f6ebffac 1952
1953;; The zero extend of operand 2 means we can just copy the high part of
1954;; operand1 into operand0.
1955(define_split
1956 [(set (match_operand:DI 0 "s_register_operand" "")
1957 (xor:DI
1958 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1959 (match_operand:DI 1 "s_register_operand" "")))]
25f905c2 1960 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
f6ebffac 1961 [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1962 (set (match_dup 3) (match_dup 4))]
1963 "
215b30b3 1964 {
1965 operands[4] = gen_highpart (SImode, operands[1]);
1966 operands[3] = gen_highpart (SImode, operands[0]);
1967 operands[0] = gen_lowpart (SImode, operands[0]);
1968 operands[1] = gen_lowpart (SImode, operands[1]);
1969 }"
1970)
f6ebffac 1971
e2669ea7 1972(define_expand "anddi3"
1973 [(set (match_operand:DI 0 "s_register_operand" "")
1974 (and:DI (match_operand:DI 1 "s_register_operand" "")
1975 (match_operand:DI 2 "neon_inv_logic_op2" "")))]
1976 "TARGET_32BIT"
1977 ""
1978)
1979
f6bbdcf6 1980(define_insn_and_split "*anddi3_insn"
0a314dcd 1981 [(set (match_operand:DI 0 "s_register_operand" "=w,w ,&r,&r,&r,&r,?w,?w")
1982 (and:DI (match_operand:DI 1 "s_register_operand" "%w,0 ,0 ,r ,0 ,r ,w ,0")
1983 (match_operand:DI 2 "arm_anddi_operand_neon" "w ,DL,r ,r ,De,De,w ,DL")))]
f6bbdcf6 1984 "TARGET_32BIT && !TARGET_IWMMXT"
1985{
1986 switch (which_alternative)
1987 {
0a314dcd 1988 case 0: /* fall through */
1989 case 6: return "vand\t%P0, %P1, %P2";
1990 case 1: /* fall through */
1991 case 7: return neon_output_logic_immediate ("vand", &operands[2],
1992 DImode, 1, VALID_NEON_QREG_MODE (DImode));
f6bbdcf6 1993 case 2:
0a314dcd 1994 case 3:
1995 case 4:
f6bbdcf6 1996 case 5: /* fall through */
0a314dcd 1997 return "#";
f6bbdcf6 1998 default: gcc_unreachable ();
1999 }
2000}
0a314dcd 2001 "TARGET_32BIT && !TARGET_IWMMXT && reload_completed
2002 && !(IS_VFP_REGNUM (REGNO (operands[0])))"
f6bbdcf6 2003 [(set (match_dup 3) (match_dup 4))
2004 (set (match_dup 5) (match_dup 6))]
2005 "
2006 {
2007 operands[3] = gen_lowpart (SImode, operands[0]);
2008 operands[5] = gen_highpart (SImode, operands[0]);
2009
2010 operands[4] = simplify_gen_binary (AND, SImode,
2011 gen_lowpart (SImode, operands[1]),
2012 gen_lowpart (SImode, operands[2]));
2013 operands[6] = simplify_gen_binary (AND, SImode,
2014 gen_highpart (SImode, operands[1]),
2015 gen_highpart_mode (SImode, DImode, operands[2]));
2016
2017 }"
32093010 2018 [(set_attr "type" "neon_logic,neon_logic,multiple,multiple,\
2019 multiple,multiple,neon_logic,neon_logic")
0a314dcd 2020 (set_attr "arch" "neon_for_64bits,neon_for_64bits,*,*,*,*,
f6bbdcf6 2021 avoid_neon_for_64bits,avoid_neon_for_64bits")
0a314dcd 2022 (set_attr "length" "*,*,8,8,8,8,*,*")
2023 ]
215b30b3 2024)
b11cae9e 2025
a0f94409 2026(define_insn_and_split "*anddi_zesidi_di"
9c08d1fa 2027 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2028 (and:DI (zero_extend:DI
2029 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 2030 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2031 "TARGET_32BIT"
f6ebffac 2032 "#"
25f905c2 2033 "TARGET_32BIT && reload_completed"
a0f94409 2034 ; The zero extend of operand 2 clears the high word of the output
2035 ; operand.
2036 [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
2037 (set (match_dup 3) (const_int 0))]
2038 "
2039 {
2040 operands[3] = gen_highpart (SImode, operands[0]);
2041 operands[0] = gen_lowpart (SImode, operands[0]);
2042 operands[1] = gen_lowpart (SImode, operands[1]);
2043 }"
1b7da4ac 2044 [(set_attr "length" "8")
2045 (set_attr "type" "multiple")]
215b30b3 2046)
b11cae9e 2047
f7fbdd4a 2048(define_insn "*anddi_sesdi_di"
cffb2a26 2049 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 2050 (and:DI (sign_extend:DI
2051 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 2052 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2053 "TARGET_32BIT"
f6ebffac 2054 "#"
1b7da4ac 2055 [(set_attr "length" "8")
2056 (set_attr "type" "multiple")]
cffb2a26 2057)
b11cae9e 2058
87b22bf7 2059(define_expand "andsi3"
cffb2a26 2060 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2061 (and:SI (match_operand:SI 1 "s_register_operand" "")
2062 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 2063 "TARGET_EITHER"
87b22bf7 2064 "
25f905c2 2065 if (TARGET_32BIT)
87b22bf7 2066 {
0438d37f 2067 if (CONST_INT_P (operands[2]))
cffb2a26 2068 {
47b5b27b 2069 if (INTVAL (operands[2]) == 255 && arm_arch6)
2070 {
2071 operands[1] = convert_to_mode (QImode, operands[1], 1);
2072 emit_insn (gen_thumb2_zero_extendqisi2_v6 (operands[0],
2073 operands[1]));
2074 }
2075 else
2076 arm_split_constant (AND, SImode, NULL_RTX,
2077 INTVAL (operands[2]), operands[0],
2078 operands[1],
2079 optimize && can_create_pseudo_p ());
615caa51 2080
cffb2a26 2081 DONE;
2082 }
87b22bf7 2083 }
25f905c2 2084 else /* TARGET_THUMB1 */
cffb2a26 2085 {
0438d37f 2086 if (!CONST_INT_P (operands[2]))
923ffadb 2087 {
2088 rtx tmp = force_reg (SImode, operands[2]);
2089 if (rtx_equal_p (operands[0], operands[1]))
2090 operands[2] = tmp;
2091 else
2092 {
2093 operands[2] = operands[1];
2094 operands[1] = tmp;
2095 }
2096 }
cffb2a26 2097 else
2098 {
2099 int i;
2100
215b30b3 2101 if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
cffb2a26 2102 {
215b30b3 2103 operands[2] = force_reg (SImode,
2104 GEN_INT (~INTVAL (operands[2])));
cffb2a26 2105
747b7458 2106 emit_insn (gen_thumb1_bicsi3 (operands[0], operands[2], operands[1]));
cffb2a26 2107
2108 DONE;
2109 }
87b22bf7 2110
cffb2a26 2111 for (i = 9; i <= 31; i++)
2112 {
2113 if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
2114 {
2115 emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
2116 const0_rtx));
2117 DONE;
2118 }
215b30b3 2119 else if ((((HOST_WIDE_INT) 1) << i) - 1
2120 == ~INTVAL (operands[2]))
cffb2a26 2121 {
2122 rtx shift = GEN_INT (i);
2123 rtx reg = gen_reg_rtx (SImode);
2124
2125 emit_insn (gen_lshrsi3 (reg, operands[1], shift));
2126 emit_insn (gen_ashlsi3 (operands[0], reg, shift));
2127
2128 DONE;
2129 }
2130 }
2131
2132 operands[2] = force_reg (SImode, operands[2]);
2133 }
215b30b3 2134 }
2135 "
cffb2a26 2136)
2137
25f905c2 2138; ??? Check split length for Thumb-2
a0f94409 2139(define_insn_and_split "*arm_andsi3_insn"
29e234a3 2140 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r,r,r")
2141 (and:SI (match_operand:SI 1 "s_register_operand" "%r,0,r,r,r")
2142 (match_operand:SI 2 "reg_or_int_operand" "I,l,K,r,?n")))]
25f905c2 2143 "TARGET_32BIT"
5565501b 2144 "@
29e234a3 2145 and%?\\t%0, %1, %2
5565501b 2146 and%?\\t%0, %1, %2
87b22bf7 2147 bic%?\\t%0, %1, #%B2
65f68e55 2148 and%?\\t%0, %1, %2
87b22bf7 2149 #"
25f905c2 2150 "TARGET_32BIT
0438d37f 2151 && CONST_INT_P (operands[2])
a0f94409 2152 && !(const_ok_for_arm (INTVAL (operands[2]))
2153 || const_ok_for_arm (~INTVAL (operands[2])))"
2154 [(clobber (const_int 0))]
2155 "
96f57e36 2156 arm_split_constant (AND, SImode, curr_insn,
2157 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 2158 DONE;
2159 "
29e234a3 2160 [(set_attr "length" "4,4,4,4,16")
65f68e55 2161 (set_attr "predicable" "yes")
29e234a3 2162 (set_attr "predicable_short_it" "no,yes,no,no,no")
d82e788e 2163 (set_attr "type" "logic_imm,logic_imm,logic_reg,logic_reg,logic_imm")]
cffb2a26 2164)
2165
f7fbdd4a 2166(define_insn "*andsi3_compare0"
bd5b4116 2167 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 2168 (compare:CC_NOOV
65f68e55 2169 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
2170 (match_operand:SI 2 "arm_not_operand" "I,K,r"))
5565501b 2171 (const_int 0)))
65f68e55 2172 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9c08d1fa 2173 (and:SI (match_dup 1) (match_dup 2)))]
25f905c2 2174 "TARGET_32BIT"
5565501b 2175 "@
25f905c2 2176 and%.\\t%0, %1, %2
65f68e55 2177 bic%.\\t%0, %1, #%B2
2178 and%.\\t%0, %1, %2"
2179 [(set_attr "conds" "set")
d82e788e 2180 (set_attr "type" "logics_imm,logics_imm,logics_reg")]
cffb2a26 2181)
9c08d1fa 2182
f7fbdd4a 2183(define_insn "*andsi3_compare0_scratch"
bd5b4116 2184 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 2185 (compare:CC_NOOV
65f68e55 2186 (and:SI (match_operand:SI 0 "s_register_operand" "r,r,r")
2187 (match_operand:SI 1 "arm_not_operand" "I,K,r"))
5565501b 2188 (const_int 0)))
65f68e55 2189 (clobber (match_scratch:SI 2 "=X,r,X"))]
25f905c2 2190 "TARGET_32BIT"
5565501b 2191 "@
2192 tst%?\\t%0, %1
65f68e55 2193 bic%.\\t%2, %0, #%B1
2194 tst%?\\t%0, %1"
2195 [(set_attr "conds" "set")
d82e788e 2196 (set_attr "type" "logics_imm,logics_imm,logics_reg")]
0d66636f 2197)
9c08d1fa 2198
f7fbdd4a 2199(define_insn "*zeroextractsi_compare0_scratch"
bd5b4116 2200 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2201 (compare:CC_NOOV (zero_extract:SI
2202 (match_operand:SI 0 "s_register_operand" "r")
d952d547 2203 (match_operand 1 "const_int_operand" "n")
206ee9a2 2204 (match_operand 2 "const_int_operand" "n"))
9c08d1fa 2205 (const_int 0)))]
25f905c2 2206 "TARGET_32BIT
cffb2a26 2207 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
2208 && INTVAL (operands[1]) > 0
2209 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
2210 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
9c08d1fa 2211 "*
5c49a439 2212 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
2213 << INTVAL (operands[2]));
40dbec34 2214 output_asm_insn (\"tst%?\\t%0, %1\", operands);
e2348bcb 2215 return \"\";
0d66636f 2216 "
596e5e8f 2217 [(set_attr "conds" "set")
65f68e55 2218 (set_attr "predicable" "yes")
d952d547 2219 (set_attr "predicable_short_it" "no")
d82e788e 2220 (set_attr "type" "logics_imm")]
0d66636f 2221)
9c08d1fa 2222
f4462328 2223(define_insn_and_split "*ne_zeroextractsi"
c4034607 2224 [(set (match_operand:SI 0 "s_register_operand" "=r")
2225 (ne:SI (zero_extract:SI
2226 (match_operand:SI 1 "s_register_operand" "r")
2227 (match_operand:SI 2 "const_int_operand" "n")
2228 (match_operand:SI 3 "const_int_operand" "n"))
3b8c7f7a 2229 (const_int 0)))
2230 (clobber (reg:CC CC_REGNUM))]
25f905c2 2231 "TARGET_32BIT
cffb2a26 2232 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2233 && INTVAL (operands[2]) > 0
2234 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2235 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
f4462328 2236 "#"
25f905c2 2237 "TARGET_32BIT
f4462328 2238 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2239 && INTVAL (operands[2]) > 0
2240 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2241 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
2242 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2243 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2244 (const_int 0)))
2245 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2246 (set (match_dup 0)
2247 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2248 (match_dup 0) (const_int 1)))]
2249 "
2250 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
2251 << INTVAL (operands[3]));
2252 "
2253 [(set_attr "conds" "clob")
25f905c2 2254 (set (attr "length")
2255 (if_then_else (eq_attr "is_thumb" "yes")
2256 (const_int 12)
1b7da4ac 2257 (const_int 8)))
2258 (set_attr "type" "multiple")]
f4462328 2259)
2260
2261(define_insn_and_split "*ne_zeroextractsi_shifted"
2262 [(set (match_operand:SI 0 "s_register_operand" "=r")
2263 (ne:SI (zero_extract:SI
2264 (match_operand:SI 1 "s_register_operand" "r")
2265 (match_operand:SI 2 "const_int_operand" "n")
2266 (const_int 0))
2267 (const_int 0)))
2268 (clobber (reg:CC CC_REGNUM))]
2269 "TARGET_ARM"
2270 "#"
2271 "TARGET_ARM"
2272 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2273 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2274 (const_int 0)))
2275 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2276 (set (match_dup 0)
2277 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2278 (match_dup 0) (const_int 1)))]
2279 "
2280 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
2281 "
2282 [(set_attr "conds" "clob")
1b7da4ac 2283 (set_attr "length" "8")
2284 (set_attr "type" "multiple")]
f4462328 2285)
2286
2287(define_insn_and_split "*ite_ne_zeroextractsi"
2288 [(set (match_operand:SI 0 "s_register_operand" "=r")
2289 (if_then_else:SI (ne (zero_extract:SI
2290 (match_operand:SI 1 "s_register_operand" "r")
2291 (match_operand:SI 2 "const_int_operand" "n")
2292 (match_operand:SI 3 "const_int_operand" "n"))
2293 (const_int 0))
2294 (match_operand:SI 4 "arm_not_operand" "rIK")
2295 (const_int 0)))
2296 (clobber (reg:CC CC_REGNUM))]
2297 "TARGET_ARM
2298 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2299 && INTVAL (operands[2]) > 0
2300 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 2301 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2302 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 2303 "#"
2304 "TARGET_ARM
2305 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2306 && INTVAL (operands[2]) > 0
2307 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 2308 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2309 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 2310 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2311 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2312 (const_int 0)))
2313 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2314 (set (match_dup 0)
2315 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2316 (match_dup 0) (match_dup 4)))]
2317 "
c4034607 2318 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
f4462328 2319 << INTVAL (operands[3]));
2320 "
2321 [(set_attr "conds" "clob")
1b7da4ac 2322 (set_attr "length" "8")
2323 (set_attr "type" "multiple")]
f4462328 2324)
2325
2326(define_insn_and_split "*ite_ne_zeroextractsi_shifted"
2327 [(set (match_operand:SI 0 "s_register_operand" "=r")
2328 (if_then_else:SI (ne (zero_extract:SI
2329 (match_operand:SI 1 "s_register_operand" "r")
2330 (match_operand:SI 2 "const_int_operand" "n")
2331 (const_int 0))
2332 (const_int 0))
2333 (match_operand:SI 3 "arm_not_operand" "rIK")
2334 (const_int 0)))
2335 (clobber (reg:CC CC_REGNUM))]
f8d7bf2f 2336 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 2337 "#"
f8d7bf2f 2338 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 2339 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2340 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2341 (const_int 0)))
2342 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2343 (set (match_dup 0)
2344 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2345 (match_dup 0) (match_dup 3)))]
2346 "
2347 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
0d66636f 2348 "
2349 [(set_attr "conds" "clob")
1b7da4ac 2350 (set_attr "length" "8")
2351 (set_attr "type" "multiple")]
215b30b3 2352)
9c08d1fa 2353
25f905c2 2354;; ??? Use Thumb-2 has bitfield insert/extract instructions.
d7863cfe 2355(define_split
2356 [(set (match_operand:SI 0 "s_register_operand" "")
2357 (match_operator:SI 1 "shiftable_operator"
2358 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2359 (match_operand:SI 3 "const_int_operand" "")
2360 (match_operand:SI 4 "const_int_operand" ""))
2361 (match_operand:SI 5 "s_register_operand" "")]))
2362 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2363 "TARGET_ARM"
2364 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2365 (set (match_dup 0)
2366 (match_op_dup 1
2367 [(lshiftrt:SI (match_dup 6) (match_dup 4))
2368 (match_dup 5)]))]
2369 "{
2370 HOST_WIDE_INT temp = INTVAL (operands[3]);
2371
2372 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2373 operands[4] = GEN_INT (32 - temp);
2374 }"
2375)
2376
d7863cfe 2377(define_split
2378 [(set (match_operand:SI 0 "s_register_operand" "")
2379 (match_operator:SI 1 "shiftable_operator"
2380 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2381 (match_operand:SI 3 "const_int_operand" "")
2382 (match_operand:SI 4 "const_int_operand" ""))
2383 (match_operand:SI 5 "s_register_operand" "")]))
2384 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2385 "TARGET_ARM"
2386 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2387 (set (match_dup 0)
2388 (match_op_dup 1
2389 [(ashiftrt:SI (match_dup 6) (match_dup 4))
2390 (match_dup 5)]))]
2391 "{
2392 HOST_WIDE_INT temp = INTVAL (operands[3]);
2393
2394 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2395 operands[4] = GEN_INT (32 - temp);
2396 }"
2397)
2398
a42059fd 2399;;; ??? This pattern is bogus. If operand3 has bits outside the range
2400;;; represented by the bitfield, then this will produce incorrect results.
2401;;; Somewhere, the value needs to be truncated. On targets like the m68k,
ceb2fe0f 2402;;; which have a real bit-field insert instruction, the truncation happens
2403;;; in the bit-field insert instruction itself. Since arm does not have a
2404;;; bit-field insert instruction, we would have to emit code here to truncate
a42059fd 2405;;; the value before we insert. This loses some of the advantage of having
2406;;; this insv pattern, so this pattern needs to be reevalutated.
2407
8a18b90c 2408(define_expand "insv"
eb04cafb 2409 [(set (zero_extract (match_operand 0 "nonimmediate_operand" "")
2410 (match_operand 1 "general_operand" "")
2411 (match_operand 2 "general_operand" ""))
2412 (match_operand 3 "reg_or_int_operand" ""))]
8b054d5a 2413 "TARGET_ARM || arm_arch_thumb2"
8a18b90c 2414 "
215b30b3 2415 {
2416 int start_bit = INTVAL (operands[2]);
2417 int width = INTVAL (operands[1]);
2418 HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
2419 rtx target, subtarget;
2420
8b054d5a 2421 if (arm_arch_thumb2)
2422 {
eb04cafb 2423 if (unaligned_access && MEM_P (operands[0])
2424 && s_register_operand (operands[3], GET_MODE (operands[3]))
2425 && (width == 16 || width == 32) && (start_bit % BITS_PER_UNIT) == 0)
8b054d5a 2426 {
eb04cafb 2427 rtx base_addr;
2428
2429 if (BYTES_BIG_ENDIAN)
2430 start_bit = GET_MODE_BITSIZE (GET_MODE (operands[3])) - width
2431 - start_bit;
8b054d5a 2432
eb04cafb 2433 if (width == 32)
8b054d5a 2434 {
eb04cafb 2435 base_addr = adjust_address (operands[0], SImode,
2436 start_bit / BITS_PER_UNIT);
2437 emit_insn (gen_unaligned_storesi (base_addr, operands[3]));
8b054d5a 2438 }
eb04cafb 2439 else
2440 {
2441 rtx tmp = gen_reg_rtx (HImode);
8b054d5a 2442
eb04cafb 2443 base_addr = adjust_address (operands[0], HImode,
2444 start_bit / BITS_PER_UNIT);
2445 emit_move_insn (tmp, gen_lowpart (HImode, operands[3]));
2446 emit_insn (gen_unaligned_storehi (base_addr, tmp));
2447 }
2448 DONE;
8b054d5a 2449 }
eb04cafb 2450 else if (s_register_operand (operands[0], GET_MODE (operands[0])))
8b054d5a 2451 {
eb04cafb 2452 bool use_bfi = TRUE;
8b054d5a 2453
0438d37f 2454 if (CONST_INT_P (operands[3]))
eb04cafb 2455 {
2456 HOST_WIDE_INT val = INTVAL (operands[3]) & mask;
2457
2458 if (val == 0)
2459 {
2460 emit_insn (gen_insv_zero (operands[0], operands[1],
2461 operands[2]));
2462 DONE;
2463 }
2464
2465 /* See if the set can be done with a single orr instruction. */
2466 if (val == mask && const_ok_for_arm (val << start_bit))
2467 use_bfi = FALSE;
2468 }
2469
2470 if (use_bfi)
2471 {
0438d37f 2472 if (!REG_P (operands[3]))
eb04cafb 2473 operands[3] = force_reg (SImode, operands[3]);
2474
2475 emit_insn (gen_insv_t2 (operands[0], operands[1], operands[2],
2476 operands[3]));
2477 DONE;
2478 }
8b054d5a 2479 }
eb04cafb 2480 else
2481 FAIL;
8b054d5a 2482 }
2483
eb04cafb 2484 if (!s_register_operand (operands[0], GET_MODE (operands[0])))
2485 FAIL;
2486
3f8fde42 2487 target = copy_rtx (operands[0]);
215b30b3 2488 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
2489 subreg as the final target. */
2490 if (GET_CODE (target) == SUBREG)
2491 {
2492 subtarget = gen_reg_rtx (SImode);
2493 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
2494 < GET_MODE_SIZE (SImode))
2495 target = SUBREG_REG (target);
2496 }
2497 else
2498 subtarget = target;
8a18b90c 2499
0438d37f 2500 if (CONST_INT_P (operands[3]))
215b30b3 2501 {
2502 /* Since we are inserting a known constant, we may be able to
2503 reduce the number of bits that we have to clear so that
2504 the mask becomes simple. */
2505 /* ??? This code does not check to see if the new mask is actually
2506 simpler. It may not be. */
2507 rtx op1 = gen_reg_rtx (SImode);
2508 /* ??? Truncate operand3 to fit in the bitfield. See comment before
2509 start of this pattern. */
2510 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
2511 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
2512
c5b3a71b 2513 emit_insn (gen_andsi3 (op1, operands[0],
2514 gen_int_mode (~mask2, SImode)));
215b30b3 2515 emit_insn (gen_iorsi3 (subtarget, op1,
4292ca6b 2516 gen_int_mode (op3_value << start_bit, SImode)));
215b30b3 2517 }
2518 else if (start_bit == 0
2519 && !(const_ok_for_arm (mask)
2520 || const_ok_for_arm (~mask)))
2521 {
2522 /* A Trick, since we are setting the bottom bits in the word,
2523 we can shift operand[3] up, operand[0] down, OR them together
2524 and rotate the result back again. This takes 3 insns, and
5910bb95 2525 the third might be mergeable into another op. */
215b30b3 2526 /* The shift up copes with the possibility that operand[3] is
2527 wider than the bitfield. */
2528 rtx op0 = gen_reg_rtx (SImode);
2529 rtx op1 = gen_reg_rtx (SImode);
2530
2531 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2532 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
2533 emit_insn (gen_iorsi3 (op1, op1, op0));
2534 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
2535 }
2536 else if ((width + start_bit == 32)
2537 && !(const_ok_for_arm (mask)
2538 || const_ok_for_arm (~mask)))
2539 {
2540 /* Similar trick, but slightly less efficient. */
8a18b90c 2541
215b30b3 2542 rtx op0 = gen_reg_rtx (SImode);
2543 rtx op1 = gen_reg_rtx (SImode);
8a18b90c 2544
215b30b3 2545 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2546 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
2547 emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
2548 emit_insn (gen_iorsi3 (subtarget, op1, op0));
2549 }
2550 else
2551 {
c5b3a71b 2552 rtx op0 = gen_int_mode (mask, SImode);
215b30b3 2553 rtx op1 = gen_reg_rtx (SImode);
2554 rtx op2 = gen_reg_rtx (SImode);
8a18b90c 2555
215b30b3 2556 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
2557 {
2558 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 2559
215b30b3 2560 emit_insn (gen_movsi (tmp, op0));
2561 op0 = tmp;
2562 }
8a18b90c 2563
215b30b3 2564 /* Mask out any bits in operand[3] that are not needed. */
2565 emit_insn (gen_andsi3 (op1, operands[3], op0));
8a18b90c 2566
0438d37f 2567 if (CONST_INT_P (op0)
215b30b3 2568 && (const_ok_for_arm (mask << start_bit)
2569 || const_ok_for_arm (~(mask << start_bit))))
2570 {
c5b3a71b 2571 op0 = gen_int_mode (~(mask << start_bit), SImode);
215b30b3 2572 emit_insn (gen_andsi3 (op2, operands[0], op0));
2573 }
2574 else
2575 {
0438d37f 2576 if (CONST_INT_P (op0))
215b30b3 2577 {
2578 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 2579
215b30b3 2580 emit_insn (gen_movsi (tmp, op0));
2581 op0 = tmp;
2582 }
2583
2584 if (start_bit != 0)
2585 emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
a42059fd 2586
215b30b3 2587 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
2588 }
8a18b90c 2589
215b30b3 2590 if (start_bit != 0)
2591 emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
8a18b90c 2592
215b30b3 2593 emit_insn (gen_iorsi3 (subtarget, op1, op2));
2594 }
f082f1c4 2595
215b30b3 2596 if (subtarget != target)
2597 {
2598 /* If TARGET is still a SUBREG, then it must be wider than a word,
2599 so we must be careful only to set the subword we were asked to. */
2600 if (GET_CODE (target) == SUBREG)
2601 emit_move_insn (target, subtarget);
2602 else
2603 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
2604 }
8a18b90c 2605
215b30b3 2606 DONE;
2607 }"
2608)
8a18b90c 2609
8b054d5a 2610(define_insn "insv_zero"
2611 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
809003b3 2612 (match_operand:SI 1 "const_int_M_operand" "M")
2613 (match_operand:SI 2 "const_int_M_operand" "M"))
8b054d5a 2614 (const_int 0))]
2615 "arm_arch_thumb2"
2616 "bfc%?\t%0, %2, %1"
2617 [(set_attr "length" "4")
d952d547 2618 (set_attr "predicable" "yes")
d82e788e 2619 (set_attr "predicable_short_it" "no")
2620 (set_attr "type" "bfm")]
8b054d5a 2621)
2622
2623(define_insn "insv_t2"
2624 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
809003b3 2625 (match_operand:SI 1 "const_int_M_operand" "M")
2626 (match_operand:SI 2 "const_int_M_operand" "M"))
8b054d5a 2627 (match_operand:SI 3 "s_register_operand" "r"))]
2628 "arm_arch_thumb2"
2629 "bfi%?\t%0, %3, %2, %1"
2630 [(set_attr "length" "4")
d952d547 2631 (set_attr "predicable" "yes")
d82e788e 2632 (set_attr "predicable_short_it" "no")
2633 (set_attr "type" "bfm")]
8b054d5a 2634)
2635
215b30b3 2636; constants for op 2 will never be given to these patterns.
a0f94409 2637(define_insn_and_split "*anddi_notdi_di"
9c08d1fa 2638 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 2639 (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "0,r"))
2640 (match_operand:DI 2 "s_register_operand" "r,0")))]
25f905c2 2641 "TARGET_32BIT"
f6ebffac 2642 "#"
e2669ea7 2643 "TARGET_32BIT && reload_completed
2644 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))
2645 && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
a0f94409 2646 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2647 (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2648 "
2649 {
2650 operands[3] = gen_highpart (SImode, operands[0]);
2651 operands[0] = gen_lowpart (SImode, operands[0]);
2652 operands[4] = gen_highpart (SImode, operands[1]);
2653 operands[1] = gen_lowpart (SImode, operands[1]);
2654 operands[5] = gen_highpart (SImode, operands[2]);
2655 operands[2] = gen_lowpart (SImode, operands[2]);
2656 }"
0d66636f 2657 [(set_attr "length" "8")
1b7da4ac 2658 (set_attr "predicable" "yes")
2659 (set_attr "type" "multiple")]
0d66636f 2660)
d952d547 2661
a0f94409 2662(define_insn_and_split "*anddi_notzesidi_di"
9c08d1fa 2663 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2664 (and:DI (not:DI (zero_extend:DI
2665 (match_operand:SI 2 "s_register_operand" "r,r")))
e2348bcb 2666 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 2667 "TARGET_32BIT"
e2348bcb 2668 "@
97499065 2669 bic%?\\t%Q0, %Q1, %2
f6ebffac 2670 #"
a0f94409 2671 ; (not (zero_extend ...)) allows us to just copy the high word from
2672 ; operand1 to operand0.
25f905c2 2673 "TARGET_32BIT
a0f94409 2674 && reload_completed
2675 && operands[0] != operands[1]"
5a097f7d 2676 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
a0f94409 2677 (set (match_dup 3) (match_dup 4))]
2678 "
2679 {
2680 operands[3] = gen_highpart (SImode, operands[0]);
2681 operands[0] = gen_lowpart (SImode, operands[0]);
2682 operands[4] = gen_highpart (SImode, operands[1]);
2683 operands[1] = gen_lowpart (SImode, operands[1]);
2684 }"
0d66636f 2685 [(set_attr "length" "4,8")
d952d547 2686 (set_attr "predicable" "yes")
1b7da4ac 2687 (set_attr "predicable_short_it" "no")
2688 (set_attr "type" "multiple")]
0d66636f 2689)
d952d547 2690
d8cd5fa0 2691(define_insn_and_split "*anddi_notdi_zesidi"
2692 [(set (match_operand:DI 0 "s_register_operand" "=r")
2693 (and:DI (not:DI (match_operand:DI 2 "s_register_operand" "r"))
2694 (zero_extend:DI
2695 (match_operand:SI 1 "s_register_operand" "r"))))]
2696 "TARGET_32BIT"
2697 "#"
2698 "TARGET_32BIT && reload_completed"
2699 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2700 (set (match_dup 3) (const_int 0))]
2701 "
2702 {
2703 operands[3] = gen_highpart (SImode, operands[0]);
2704 operands[0] = gen_lowpart (SImode, operands[0]);
2705 operands[2] = gen_lowpart (SImode, operands[2]);
2706 }"
2707 [(set_attr "length" "8")
2708 (set_attr "predicable" "yes")
2709 (set_attr "predicable_short_it" "no")
2710 (set_attr "type" "multiple")]
2711)
2712
a0f94409 2713(define_insn_and_split "*anddi_notsesidi_di"
9c08d1fa 2714 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2715 (and:DI (not:DI (sign_extend:DI
2716 (match_operand:SI 2 "s_register_operand" "r,r")))
5a097f7d 2717 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2718 "TARGET_32BIT"
f6ebffac 2719 "#"
25f905c2 2720 "TARGET_32BIT && reload_completed"
5a097f7d 2721 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
a0f94409 2722 (set (match_dup 3) (and:SI (not:SI
2723 (ashiftrt:SI (match_dup 2) (const_int 31)))
2724 (match_dup 4)))]
2725 "
2726 {
2727 operands[3] = gen_highpart (SImode, operands[0]);
2728 operands[0] = gen_lowpart (SImode, operands[0]);
2729 operands[4] = gen_highpart (SImode, operands[1]);
2730 operands[1] = gen_lowpart (SImode, operands[1]);
2731 }"
0d66636f 2732 [(set_attr "length" "8")
d952d547 2733 (set_attr "predicable" "yes")
1b7da4ac 2734 (set_attr "predicable_short_it" "no")
2735 (set_attr "type" "multiple")]
0d66636f 2736)
d952d547 2737
8a18b90c 2738(define_insn "andsi_notsi_si"
9c08d1fa 2739 [(set (match_operand:SI 0 "s_register_operand" "=r")
2740 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2741 (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 2742 "TARGET_32BIT"
0d66636f 2743 "bic%?\\t%0, %1, %2"
d952d547 2744 [(set_attr "predicable" "yes")
1b7da4ac 2745 (set_attr "predicable_short_it" "no")
2746 (set_attr "type" "logic_reg")]
0d66636f 2747)
b11cae9e 2748
8a18b90c 2749(define_insn "andsi_not_shiftsi_si"
a2cd141b 2750 [(set (match_operand:SI 0 "s_register_operand" "=r")
2751 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2752 [(match_operand:SI 2 "s_register_operand" "r")
2753 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2754 (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 2755 "TARGET_ARM"
6c4c2133 2756 "bic%?\\t%0, %1, %2%S4"
344495ea 2757 [(set_attr "predicable" "yes")
331beb1a 2758 (set_attr "shift" "2")
a2cd141b 2759 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
d82e788e 2760 (const_string "logic_shift_imm")
2761 (const_string "logic_shift_reg")))]
6c4c2133 2762)
8a18b90c 2763
f7fbdd4a 2764(define_insn "*andsi_notsi_si_compare0"
bd5b4116 2765 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 2766 (compare:CC_NOOV
2767 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2768 (match_operand:SI 1 "s_register_operand" "r"))
2769 (const_int 0)))
9c08d1fa 2770 (set (match_operand:SI 0 "s_register_operand" "=r")
2771 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
25f905c2 2772 "TARGET_32BIT"
2773 "bic%.\\t%0, %1, %2"
d82e788e 2774 [(set_attr "conds" "set")
2775 (set_attr "type" "logics_shift_reg")]
0d66636f 2776)
9c08d1fa 2777
f7fbdd4a 2778(define_insn "*andsi_notsi_si_compare0_scratch"
bd5b4116 2779 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 2780 (compare:CC_NOOV
2781 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2782 (match_operand:SI 1 "s_register_operand" "r"))
2783 (const_int 0)))
9c08d1fa 2784 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 2785 "TARGET_32BIT"
2786 "bic%.\\t%0, %1, %2"
d82e788e 2787 [(set_attr "conds" "set")
2788 (set_attr "type" "logics_shift_reg")]
0d66636f 2789)
9c08d1fa 2790
e2669ea7 2791(define_expand "iordi3"
2792 [(set (match_operand:DI 0 "s_register_operand" "")
2793 (ior:DI (match_operand:DI 1 "s_register_operand" "")
2794 (match_operand:DI 2 "neon_logic_op2" "")))]
2795 "TARGET_32BIT"
2796 ""
2797)
2798
74d6113f 2799(define_insn_and_split "*iordi3_insn"
2800 [(set (match_operand:DI 0 "s_register_operand" "=w,w ,&r,&r,&r,&r,?w,?w")
2801 (ior:DI (match_operand:DI 1 "s_register_operand" "%w,0 ,0 ,r ,0 ,r ,w ,0")
e0fe6977 2802 (match_operand:DI 2 "arm_iordi_operand_neon" "w ,Dl,r ,r ,Df,Df,w ,Dl")))]
74d6113f 2803 "TARGET_32BIT && !TARGET_IWMMXT"
2804 {
2805 switch (which_alternative)
2806 {
2807 case 0: /* fall through */
2808 case 6: return "vorr\t%P0, %P1, %P2";
2809 case 1: /* fall through */
2810 case 7: return neon_output_logic_immediate ("vorr", &operands[2],
2811 DImode, 0, VALID_NEON_QREG_MODE (DImode));
2812 case 2:
2813 case 3:
2814 case 4:
2815 case 5:
2816 return "#";
2817 default: gcc_unreachable ();
2818 }
2819 }
2820 "TARGET_32BIT && !TARGET_IWMMXT && reload_completed
2821 && !(IS_VFP_REGNUM (REGNO (operands[0])))"
2822 [(set (match_dup 3) (match_dup 4))
2823 (set (match_dup 5) (match_dup 6))]
2824 "
2825 {
2826 operands[3] = gen_lowpart (SImode, operands[0]);
2827 operands[5] = gen_highpart (SImode, operands[0]);
2828
2829 operands[4] = simplify_gen_binary (IOR, SImode,
2830 gen_lowpart (SImode, operands[1]),
2831 gen_lowpart (SImode, operands[2]));
2832 operands[6] = simplify_gen_binary (IOR, SImode,
2833 gen_highpart (SImode, operands[1]),
2834 gen_highpart_mode (SImode, DImode, operands[2]));
2835
2836 }"
32093010 2837 [(set_attr "type" "neon_logic,neon_logic,multiple,multiple,multiple,\
2838 multiple,neon_logic,neon_logic")
e0fe6977 2839 (set_attr "length" "*,*,8,8,8,8,*,*")
74d6113f 2840 (set_attr "arch" "neon_for_64bits,neon_for_64bits,*,*,*,*,avoid_neon_for_64bits,avoid_neon_for_64bits")]
cffb2a26 2841)
9c08d1fa 2842
f7fbdd4a 2843(define_insn "*iordi_zesidi_di"
9c08d1fa 2844 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2845 (ior:DI (zero_extend:DI
2846 (match_operand:SI 2 "s_register_operand" "r,r"))
e2348bcb 2847 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 2848 "TARGET_32BIT"
e2348bcb 2849 "@
97499065 2850 orr%?\\t%Q0, %Q1, %2
f6ebffac 2851 #"
0d66636f 2852 [(set_attr "length" "4,8")
d952d547 2853 (set_attr "predicable" "yes")
1b7da4ac 2854 (set_attr "predicable_short_it" "no")
2855 (set_attr "type" "logic_reg,multiple")]
cffb2a26 2856)
9c08d1fa 2857
f7fbdd4a 2858(define_insn "*iordi_sesidi_di"
9c08d1fa 2859 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2860 (ior:DI (sign_extend:DI
2861 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 2862 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2863 "TARGET_32BIT"
f6ebffac 2864 "#"
0d66636f 2865 [(set_attr "length" "8")
1b7da4ac 2866 (set_attr "predicable" "yes")
2867 (set_attr "type" "multiple")]
cffb2a26 2868)
9c08d1fa 2869
87b22bf7 2870(define_expand "iorsi3"
cffb2a26 2871 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2872 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2873 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 2874 "TARGET_EITHER"
87b22bf7 2875 "
0438d37f 2876 if (CONST_INT_P (operands[2]))
87b22bf7 2877 {
25f905c2 2878 if (TARGET_32BIT)
cffb2a26 2879 {
96f57e36 2880 arm_split_constant (IOR, SImode, NULL_RTX,
2881 INTVAL (operands[2]), operands[0], operands[1],
e1ba4a27 2882 optimize && can_create_pseudo_p ());
cffb2a26 2883 DONE;
2884 }
25f905c2 2885 else /* TARGET_THUMB1 */
923ffadb 2886 {
2887 rtx tmp = force_reg (SImode, operands[2]);
2888 if (rtx_equal_p (operands[0], operands[1]))
2889 operands[2] = tmp;
2890 else
2891 {
2892 operands[2] = operands[1];
2893 operands[1] = tmp;
2894 }
2895 }
87b22bf7 2896 }
cffb2a26 2897 "
2898)
87b22bf7 2899
d5d4dc8d 2900(define_insn_and_split "*iorsi3_insn"
29e234a3 2901 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r,r,r")
2902 (ior:SI (match_operand:SI 1 "s_register_operand" "%r,0,r,r,r")
2903 (match_operand:SI 2 "reg_or_int_operand" "I,l,K,r,?n")))]
d5d4dc8d 2904 "TARGET_32BIT"
87b22bf7 2905 "@
29e234a3 2906 orr%?\\t%0, %1, %2
87b22bf7 2907 orr%?\\t%0, %1, %2
d5d4dc8d 2908 orn%?\\t%0, %1, #%B2
65f68e55 2909 orr%?\\t%0, %1, %2
87b22bf7 2910 #"
d5d4dc8d 2911 "TARGET_32BIT
0438d37f 2912 && CONST_INT_P (operands[2])
d5d4dc8d 2913 && !(const_ok_for_arm (INTVAL (operands[2]))
2914 || (TARGET_THUMB2 && const_ok_for_arm (~INTVAL (operands[2]))))"
a0f94409 2915 [(clobber (const_int 0))]
d5d4dc8d 2916{
29e234a3 2917 arm_split_constant (IOR, SImode, curr_insn,
96f57e36 2918 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 2919 DONE;
d5d4dc8d 2920}
29e234a3 2921 [(set_attr "length" "4,4,4,4,16")
2922 (set_attr "arch" "32,t2,t2,32,32")
65f68e55 2923 (set_attr "predicable" "yes")
29e234a3 2924 (set_attr "predicable_short_it" "no,yes,no,no,no")
d82e788e 2925 (set_attr "type" "logic_imm,logic_reg,logic_imm,logic_reg,logic_reg")]
65f68e55 2926)
cffb2a26 2927
a0f94409 2928(define_peephole2
2929 [(match_scratch:SI 3 "r")
372575c7 2930 (set (match_operand:SI 0 "arm_general_register_operand" "")
2931 (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
87b22bf7 2932 (match_operand:SI 2 "const_int_operand" "")))]
90560cad 2933 "TARGET_ARM
a0f94409 2934 && !const_ok_for_arm (INTVAL (operands[2]))
2935 && const_ok_for_arm (~INTVAL (operands[2]))"
2936 [(set (match_dup 3) (match_dup 2))
2937 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2938 ""
215b30b3 2939)
a0f94409 2940
f7fbdd4a 2941(define_insn "*iorsi3_compare0"
bd5b4116 2942 [(set (reg:CC_NOOV CC_REGNUM)
65f68e55 2943 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r,r")
2944 (match_operand:SI 2 "arm_rhs_operand" "I,r"))
9c08d1fa 2945 (const_int 0)))
65f68e55 2946 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 2947 (ior:SI (match_dup 1) (match_dup 2)))]
25f905c2 2948 "TARGET_32BIT"
2949 "orr%.\\t%0, %1, %2"
65f68e55 2950 [(set_attr "conds" "set")
d82e788e 2951 (set_attr "type" "logics_imm,logics_reg")]
cffb2a26 2952)
9c08d1fa 2953
f7fbdd4a 2954(define_insn "*iorsi3_compare0_scratch"
bd5b4116 2955 [(set (reg:CC_NOOV CC_REGNUM)
65f68e55 2956 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r,r")
2957 (match_operand:SI 2 "arm_rhs_operand" "I,r"))
9c08d1fa 2958 (const_int 0)))
65f68e55 2959 (clobber (match_scratch:SI 0 "=r,r"))]
25f905c2 2960 "TARGET_32BIT"
2961 "orr%.\\t%0, %1, %2"
65f68e55 2962 [(set_attr "conds" "set")
d82e788e 2963 (set_attr "type" "logics_imm,logics_reg")]
0d66636f 2964)
9c08d1fa 2965
e2669ea7 2966(define_expand "xordi3"
2967 [(set (match_operand:DI 0 "s_register_operand" "")
2968 (xor:DI (match_operand:DI 1 "s_register_operand" "")
8ee7dc6f 2969 (match_operand:DI 2 "arm_xordi_operand" "")))]
e2669ea7 2970 "TARGET_32BIT"
2971 ""
2972)
2973
8ee7dc6f 2974(define_insn_and_split "*xordi3_insn"
2975 [(set (match_operand:DI 0 "s_register_operand" "=w,&r,&r,&r,&r,?w")
205c3b0a 2976 (xor:DI (match_operand:DI 1 "s_register_operand" "%w ,0,r ,0 ,r ,w")
8ee7dc6f 2977 (match_operand:DI 2 "arm_xordi_operand" "w ,r ,r ,Dg,Dg,w")))]
2978 "TARGET_32BIT && !TARGET_IWMMXT"
2979{
2980 switch (which_alternative)
2981 {
2982 case 1:
2983 case 2:
2984 case 3:
2985 case 4: /* fall through */
2986 return "#";
2987 case 0: /* fall through */
2988 case 5: return "veor\t%P0, %P1, %P2";
2989 default: gcc_unreachable ();
2990 }
2991}
2992 "TARGET_32BIT && !TARGET_IWMMXT && reload_completed
2993 && !(IS_VFP_REGNUM (REGNO (operands[0])))"
2994 [(set (match_dup 3) (match_dup 4))
2995 (set (match_dup 5) (match_dup 6))]
2996 "
2997 {
2998 operands[3] = gen_lowpart (SImode, operands[0]);
2999 operands[5] = gen_highpart (SImode, operands[0]);
3000
3001 operands[4] = simplify_gen_binary (XOR, SImode,
3002 gen_lowpart (SImode, operands[1]),
3003 gen_lowpart (SImode, operands[2]));
3004 operands[6] = simplify_gen_binary (XOR, SImode,
3005 gen_highpart (SImode, operands[1]),
3006 gen_highpart_mode (SImode, DImode, operands[2]));
3007
3008 }"
3009 [(set_attr "length" "*,8,8,8,8,*")
32093010 3010 (set_attr "type" "neon_logic,multiple,multiple,multiple,multiple,neon_logic")
8ee7dc6f 3011 (set_attr "arch" "neon_for_64bits,*,*,*,*,avoid_neon_for_64bits")]
cffb2a26 3012)
9c08d1fa 3013
f7fbdd4a 3014(define_insn "*xordi_zesidi_di"
9c08d1fa 3015 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3016 (xor:DI (zero_extend:DI
3017 (match_operand:SI 2 "s_register_operand" "r,r"))
e2348bcb 3018 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 3019 "TARGET_32BIT"
e2348bcb 3020 "@
97499065 3021 eor%?\\t%Q0, %Q1, %2
f6ebffac 3022 #"
0d66636f 3023 [(set_attr "length" "4,8")
d952d547 3024 (set_attr "predicable" "yes")
1b7da4ac 3025 (set_attr "predicable_short_it" "no")
3026 (set_attr "type" "logic_reg")]
cffb2a26 3027)
9c08d1fa 3028
f7fbdd4a 3029(define_insn "*xordi_sesidi_di"
9c08d1fa 3030 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3031 (xor:DI (sign_extend:DI
3032 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 3033 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 3034 "TARGET_32BIT"
f6ebffac 3035 "#"
0d66636f 3036 [(set_attr "length" "8")
1b7da4ac 3037 (set_attr "predicable" "yes")
3038 (set_attr "type" "multiple")]
cffb2a26 3039)
9c08d1fa 3040
cffb2a26 3041(define_expand "xorsi3"
3042 [(set (match_operand:SI 0 "s_register_operand" "")
3043 (xor:SI (match_operand:SI 1 "s_register_operand" "")
923ffadb 3044 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 3045 "TARGET_EITHER"
0438d37f 3046 "if (CONST_INT_P (operands[2]))
923ffadb 3047 {
3048 if (TARGET_32BIT)
3049 {
3050 arm_split_constant (XOR, SImode, NULL_RTX,
3051 INTVAL (operands[2]), operands[0], operands[1],
3052 optimize && can_create_pseudo_p ());
3053 DONE;
3054 }
3055 else /* TARGET_THUMB1 */
3056 {
3057 rtx tmp = force_reg (SImode, operands[2]);
3058 if (rtx_equal_p (operands[0], operands[1]))
3059 operands[2] = tmp;
3060 else
3061 {
3062 operands[2] = operands[1];
3063 operands[1] = tmp;
3064 }
3065 }
3066 }"
cffb2a26 3067)
3068
5dcb35d9 3069(define_insn_and_split "*arm_xorsi3"
29e234a3 3070 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r,r")
3071 (xor:SI (match_operand:SI 1 "s_register_operand" "%r,0,r,r")
3072 (match_operand:SI 2 "reg_or_int_operand" "I,l,r,?n")))]
25f905c2 3073 "TARGET_32BIT"
5dcb35d9 3074 "@
29e234a3 3075 eor%?\\t%0, %1, %2
65f68e55 3076 eor%?\\t%0, %1, %2
5dcb35d9 3077 eor%?\\t%0, %1, %2
3078 #"
3079 "TARGET_32BIT
0438d37f 3080 && CONST_INT_P (operands[2])
5dcb35d9 3081 && !const_ok_for_arm (INTVAL (operands[2]))"
3082 [(clobber (const_int 0))]
3083{
3084 arm_split_constant (XOR, SImode, curr_insn,
3085 INTVAL (operands[2]), operands[0], operands[1], 0);
3086 DONE;
3087}
29e234a3 3088 [(set_attr "length" "4,4,4,16")
65f68e55 3089 (set_attr "predicable" "yes")
29e234a3 3090 (set_attr "predicable_short_it" "no,yes,no,no")
1b7da4ac 3091 (set_attr "type" "logic_imm,logic_reg,logic_reg,multiple")]
cffb2a26 3092)
3093
f7fbdd4a 3094(define_insn "*xorsi3_compare0"
bd5b4116 3095 [(set (reg:CC_NOOV CC_REGNUM)
65f68e55 3096 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r,r")
3097 (match_operand:SI 2 "arm_rhs_operand" "I,r"))
9c08d1fa 3098 (const_int 0)))
65f68e55 3099 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 3100 (xor:SI (match_dup 1) (match_dup 2)))]
25f905c2 3101 "TARGET_32BIT"
3102 "eor%.\\t%0, %1, %2"
65f68e55 3103 [(set_attr "conds" "set")
d82e788e 3104 (set_attr "type" "logics_imm,logics_reg")]
0d66636f 3105)
9c08d1fa 3106
f7fbdd4a 3107(define_insn "*xorsi3_compare0_scratch"
bd5b4116 3108 [(set (reg:CC_NOOV CC_REGNUM)
65f68e55 3109 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r,r")
3110 (match_operand:SI 1 "arm_rhs_operand" "I,r"))
9c08d1fa 3111 (const_int 0)))]
25f905c2 3112 "TARGET_32BIT"
40dbec34 3113 "teq%?\\t%0, %1"
65f68e55 3114 [(set_attr "conds" "set")
d82e788e 3115 (set_attr "type" "logics_imm,logics_reg")]
cffb2a26 3116)
9c08d1fa 3117
215b30b3 3118; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
3119; (NOT D) we can sometimes merge the final NOT into one of the following
3120; insns.
9c08d1fa 3121
3122(define_split
a058e94a 3123 [(set (match_operand:SI 0 "s_register_operand" "")
3124 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
3125 (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
3126 (match_operand:SI 3 "arm_rhs_operand" "")))
3127 (clobber (match_operand:SI 4 "s_register_operand" ""))]
25f905c2 3128 "TARGET_32BIT"
9c08d1fa 3129 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
3130 (not:SI (match_dup 3))))
3131 (set (match_dup 0) (not:SI (match_dup 4)))]
3132 ""
3133)
3134
ba6a3b2f 3135(define_insn_and_split "*andsi_iorsi3_notsi"
9c08d1fa 3136 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
e5fea38e 3137 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "%0,r,r")
9c08d1fa 3138 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
3139 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
25f905c2 3140 "TARGET_32BIT"
ba6a3b2f 3141 "#" ; "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
3142 "&& reload_completed"
3143 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
3144 (set (match_dup 0) (and:SI (not:SI (match_dup 3)) (match_dup 0)))]
3145 ""
0d66636f 3146 [(set_attr "length" "8")
25f905c2 3147 (set_attr "ce_count" "2")
d952d547 3148 (set_attr "predicable" "yes")
1b7da4ac 3149 (set_attr "predicable_short_it" "no")
3150 (set_attr "type" "multiple")]
cffb2a26 3151)
9c08d1fa 3152
25f905c2 3153; ??? Are these four splitters still beneficial when the Thumb-2 bitfield
3154; insns are available?
d7863cfe 3155(define_split
3156 [(set (match_operand:SI 0 "s_register_operand" "")
3157 (match_operator:SI 1 "logical_binary_operator"
3158 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
3159 (match_operand:SI 3 "const_int_operand" "")
3160 (match_operand:SI 4 "const_int_operand" ""))
3161 (match_operator:SI 9 "logical_binary_operator"
3162 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3163 (match_operand:SI 6 "const_int_operand" ""))
3164 (match_operand:SI 7 "s_register_operand" "")])]))
3165 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3166 "TARGET_32BIT
d7863cfe 3167 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3168 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3169 [(set (match_dup 8)
3170 (match_op_dup 1
3171 [(ashift:SI (match_dup 2) (match_dup 4))
3172 (match_dup 5)]))
3173 (set (match_dup 0)
3174 (match_op_dup 1
3175 [(lshiftrt:SI (match_dup 8) (match_dup 6))
3176 (match_dup 7)]))]
3177 "
3178 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3179")
3180
3181(define_split
3182 [(set (match_operand:SI 0 "s_register_operand" "")
3183 (match_operator:SI 1 "logical_binary_operator"
3184 [(match_operator:SI 9 "logical_binary_operator"
3185 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3186 (match_operand:SI 6 "const_int_operand" ""))
3187 (match_operand:SI 7 "s_register_operand" "")])
3188 (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
3189 (match_operand:SI 3 "const_int_operand" "")
3190 (match_operand:SI 4 "const_int_operand" ""))]))
3191 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3192 "TARGET_32BIT
d7863cfe 3193 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3194 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3195 [(set (match_dup 8)
3196 (match_op_dup 1
3197 [(ashift:SI (match_dup 2) (match_dup 4))
3198 (match_dup 5)]))
3199 (set (match_dup 0)
3200 (match_op_dup 1
3201 [(lshiftrt:SI (match_dup 8) (match_dup 6))
3202 (match_dup 7)]))]
3203 "
3204 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3205")
3206
3207(define_split
3208 [(set (match_operand:SI 0 "s_register_operand" "")
3209 (match_operator:SI 1 "logical_binary_operator"
3210 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
3211 (match_operand:SI 3 "const_int_operand" "")
3212 (match_operand:SI 4 "const_int_operand" ""))
3213 (match_operator:SI 9 "logical_binary_operator"
3214 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3215 (match_operand:SI 6 "const_int_operand" ""))
3216 (match_operand:SI 7 "s_register_operand" "")])]))
3217 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3218 "TARGET_32BIT
d7863cfe 3219 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3220 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3221 [(set (match_dup 8)
3222 (match_op_dup 1
3223 [(ashift:SI (match_dup 2) (match_dup 4))
3224 (match_dup 5)]))
3225 (set (match_dup 0)
3226 (match_op_dup 1
3227 [(ashiftrt:SI (match_dup 8) (match_dup 6))
3228 (match_dup 7)]))]
3229 "
3230 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3231")
3232
3233(define_split
3234 [(set (match_operand:SI 0 "s_register_operand" "")
3235 (match_operator:SI 1 "logical_binary_operator"
3236 [(match_operator:SI 9 "logical_binary_operator"
3237 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3238 (match_operand:SI 6 "const_int_operand" ""))
3239 (match_operand:SI 7 "s_register_operand" "")])
3240 (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
3241 (match_operand:SI 3 "const_int_operand" "")
3242 (match_operand:SI 4 "const_int_operand" ""))]))
3243 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3244 "TARGET_32BIT
d7863cfe 3245 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3246 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3247 [(set (match_dup 8)
3248 (match_op_dup 1
3249 [(ashift:SI (match_dup 2) (match_dup 4))
3250 (match_dup 5)]))
3251 (set (match_dup 0)
3252 (match_op_dup 1
3253 [(ashiftrt:SI (match_dup 8) (match_dup 6))
3254 (match_dup 7)]))]
3255 "
3256 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3257")
9c08d1fa 3258\f
3259
3260;; Minimum and maximum insns
3261
8b9dc177 3262(define_expand "smaxsi3"
3263 [(parallel [
3264 (set (match_operand:SI 0 "s_register_operand" "")
3265 (smax:SI (match_operand:SI 1 "s_register_operand" "")
3266 (match_operand:SI 2 "arm_rhs_operand" "")))
3267 (clobber (reg:CC CC_REGNUM))])]
25f905c2 3268 "TARGET_32BIT"
8b9dc177 3269 "
8774928b 3270 if (operands[2] == const0_rtx || operands[2] == constm1_rtx)
8b9dc177 3271 {
3272 /* No need for a clobber of the condition code register here. */
3273 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3274 gen_rtx_SMAX (SImode, operands[1],
3275 operands[2])));
3276 DONE;
3277 }
3278")
3279
3280(define_insn "*smax_0"
3281 [(set (match_operand:SI 0 "s_register_operand" "=r")
3282 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3283 (const_int 0)))]
25f905c2 3284 "TARGET_32BIT"
8b9dc177 3285 "bic%?\\t%0, %1, %1, asr #31"
d952d547 3286 [(set_attr "predicable" "yes")
1b7da4ac 3287 (set_attr "predicable_short_it" "no")
3288 (set_attr "type" "logic_shift_reg")]
8b9dc177 3289)
3290
8774928b 3291(define_insn "*smax_m1"
3292 [(set (match_operand:SI 0 "s_register_operand" "=r")
3293 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3294 (const_int -1)))]
25f905c2 3295 "TARGET_32BIT"
8774928b 3296 "orr%?\\t%0, %1, %1, asr #31"
d952d547 3297 [(set_attr "predicable" "yes")
1b7da4ac 3298 (set_attr "predicable_short_it" "no")
3299 (set_attr "type" "logic_shift_reg")]
8774928b 3300)
3301
3dc953f2 3302(define_insn_and_split "*arm_smax_insn"
8b9dc177 3303 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3304 (smax:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3305 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
bd5b4116 3306 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3307 "TARGET_ARM"
3dc953f2 3308 "#"
3309 ; cmp\\t%1, %2\;movlt\\t%0, %2
3310 ; cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
3311 "TARGET_ARM"
3312 [(set (reg:CC CC_REGNUM)
3313 (compare:CC (match_dup 1) (match_dup 2)))
3314 (set (match_dup 0)
3315 (if_then_else:SI (ge:SI (reg:CC CC_REGNUM) (const_int 0))
3316 (match_dup 1)
3317 (match_dup 2)))]
3318 ""
cffb2a26 3319 [(set_attr "conds" "clob")
1b7da4ac 3320 (set_attr "length" "8,12")
3321 (set_attr "type" "multiple")]
cffb2a26 3322)
9c08d1fa 3323
8b9dc177 3324(define_expand "sminsi3"
3325 [(parallel [
3326 (set (match_operand:SI 0 "s_register_operand" "")
3327 (smin:SI (match_operand:SI 1 "s_register_operand" "")
3328 (match_operand:SI 2 "arm_rhs_operand" "")))
3329 (clobber (reg:CC CC_REGNUM))])]
25f905c2 3330 "TARGET_32BIT"
8b9dc177 3331 "
3332 if (operands[2] == const0_rtx)
3333 {
3334 /* No need for a clobber of the condition code register here. */
3335 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3336 gen_rtx_SMIN (SImode, operands[1],
3337 operands[2])));
3338 DONE;
3339 }
3340")
3341
3342(define_insn "*smin_0"
3343 [(set (match_operand:SI 0 "s_register_operand" "=r")
3344 (smin:SI (match_operand:SI 1 "s_register_operand" "r")
3345 (const_int 0)))]
25f905c2 3346 "TARGET_32BIT"
8b9dc177 3347 "and%?\\t%0, %1, %1, asr #31"
d952d547 3348 [(set_attr "predicable" "yes")
1b7da4ac 3349 (set_attr "predicable_short_it" "no")
3350 (set_attr "type" "logic_shift_reg")]
8b9dc177 3351)
3352
3dc953f2 3353(define_insn_and_split "*arm_smin_insn"
8b9dc177 3354 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3355 (smin:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3356 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
bd5b4116 3357 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3358 "TARGET_ARM"
3dc953f2 3359 "#"
3360 ; cmp\\t%1, %2\;movge\\t%0, %2
3361 ; cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
3362 "TARGET_ARM"
3363 [(set (reg:CC CC_REGNUM)
3364 (compare:CC (match_dup 1) (match_dup 2)))
3365 (set (match_dup 0)
3366 (if_then_else:SI (lt:SI (reg:CC CC_REGNUM) (const_int 0))
3367 (match_dup 1)
3368 (match_dup 2)))]
3369 ""
0d66636f 3370 [(set_attr "conds" "clob")
1b7da4ac 3371 (set_attr "length" "8,12")
3372 (set_attr "type" "multiple,multiple")]
0d66636f 3373)
9c08d1fa 3374
25f905c2 3375(define_expand "umaxsi3"
3376 [(parallel [
3377 (set (match_operand:SI 0 "s_register_operand" "")
3378 (umax:SI (match_operand:SI 1 "s_register_operand" "")
3379 (match_operand:SI 2 "arm_rhs_operand" "")))
3380 (clobber (reg:CC CC_REGNUM))])]
3381 "TARGET_32BIT"
3382 ""
3383)
3384
3dc953f2 3385(define_insn_and_split "*arm_umaxsi3"
9c08d1fa 3386 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3387 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3388 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 3389 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3390 "TARGET_ARM"
3dc953f2 3391 "#"
3392 ; cmp\\t%1, %2\;movcc\\t%0, %2
3393 ; cmp\\t%1, %2\;movcs\\t%0, %1
3394 ; cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
3395 "TARGET_ARM"
3396 [(set (reg:CC CC_REGNUM)
3397 (compare:CC (match_dup 1) (match_dup 2)))
3398 (set (match_dup 0)
3399 (if_then_else:SI (geu:SI (reg:CC CC_REGNUM) (const_int 0))
3400 (match_dup 1)
3401 (match_dup 2)))]
3402 ""
0d66636f 3403 [(set_attr "conds" "clob")
1b7da4ac 3404 (set_attr "length" "8,8,12")
3405 (set_attr "type" "store1")]
0d66636f 3406)
9c08d1fa 3407
25f905c2 3408(define_expand "uminsi3"
3409 [(parallel [
3410 (set (match_operand:SI 0 "s_register_operand" "")
3411 (umin:SI (match_operand:SI 1 "s_register_operand" "")
3412 (match_operand:SI 2 "arm_rhs_operand" "")))
3413 (clobber (reg:CC CC_REGNUM))])]
3414 "TARGET_32BIT"
3415 ""
3416)
3417
3dc953f2 3418(define_insn_and_split "*arm_uminsi3"
9c08d1fa 3419 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3420 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3421 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 3422 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3423 "TARGET_ARM"
3dc953f2 3424 "#"
3425 ; cmp\\t%1, %2\;movcs\\t%0, %2
3426 ; cmp\\t%1, %2\;movcc\\t%0, %1
3427 ; cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
3428 "TARGET_ARM"
3429 [(set (reg:CC CC_REGNUM)
3430 (compare:CC (match_dup 1) (match_dup 2)))
3431 (set (match_dup 0)
3432 (if_then_else:SI (ltu:SI (reg:CC CC_REGNUM) (const_int 0))
3433 (match_dup 1)
3434 (match_dup 2)))]
3435 ""
0d66636f 3436 [(set_attr "conds" "clob")
1b7da4ac 3437 (set_attr "length" "8,8,12")
3438 (set_attr "type" "store1")]
0d66636f 3439)
9c08d1fa 3440
8a18b90c 3441(define_insn "*store_minmaxsi"
9c08d1fa 3442 [(set (match_operand:SI 0 "memory_operand" "=m")
3443 (match_operator:SI 3 "minmax_operator"
3444 [(match_operand:SI 1 "s_register_operand" "r")
3445 (match_operand:SI 2 "s_register_operand" "r")]))
bd5b4116 3446 (clobber (reg:CC CC_REGNUM))]
5ce0ce9b 3447 "TARGET_32BIT && optimize_function_for_size_p (cfun)"
9c08d1fa 3448 "*
dc55b8a9 3449 operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
3450 operands[1], operands[2]);
e2348bcb 3451 output_asm_insn (\"cmp\\t%1, %2\", operands);
25f905c2 3452 if (TARGET_THUMB2)
3453 output_asm_insn (\"ite\t%d3\", operands);
e2348bcb 3454 output_asm_insn (\"str%d3\\t%1, %0\", operands);
3455 output_asm_insn (\"str%D3\\t%2, %0\", operands);
3456 return \"\";
0d66636f 3457 "
3458 [(set_attr "conds" "clob")
25f905c2 3459 (set (attr "length")
3460 (if_then_else (eq_attr "is_thumb" "yes")
3461 (const_int 14)
3462 (const_int 12)))
0d66636f 3463 (set_attr "type" "store1")]
3464)
9c08d1fa 3465
8a18b90c 3466; Reject the frame pointer in operand[1], since reloading this after
3467; it has been eliminated can cause carnage.
f7fbdd4a 3468(define_insn "*minmax_arithsi"
9c08d1fa 3469 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3470 (match_operator:SI 4 "shiftable_operator"
3471 [(match_operator:SI 5 "minmax_operator"
3472 [(match_operand:SI 2 "s_register_operand" "r,r")
3473 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
3474 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 3475 (clobber (reg:CC CC_REGNUM))]
7c36fe71 3476 "TARGET_32BIT && !arm_eliminable_register (operands[1]) && !arm_restrict_it"
9c08d1fa 3477 "*
0d66636f 3478 {
3479 enum rtx_code code = GET_CODE (operands[4]);
25f905c2 3480 bool need_else;
3481
3482 if (which_alternative != 0 || operands[3] != const0_rtx
ca0fc5a2 3483 || (code != PLUS && code != IOR && code != XOR))
25f905c2 3484 need_else = true;
3485 else
3486 need_else = false;
0d66636f 3487
dc55b8a9 3488 operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
3489 operands[2], operands[3]);
0d66636f 3490 output_asm_insn (\"cmp\\t%2, %3\", operands);
25f905c2 3491 if (TARGET_THUMB2)
3492 {
3493 if (need_else)
3494 output_asm_insn (\"ite\\t%d5\", operands);
3495 else
3496 output_asm_insn (\"it\\t%d5\", operands);
3497 }
0d66636f 3498 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
25f905c2 3499 if (need_else)
0d66636f 3500 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
3501 return \"\";
215b30b3 3502 }"
0d66636f 3503 [(set_attr "conds" "clob")
25f905c2 3504 (set (attr "length")
3505 (if_then_else (eq_attr "is_thumb" "yes")
3506 (const_int 14)
1b7da4ac 3507 (const_int 12)))
3508 (set_attr "type" "multiple")]
0d66636f 3509)
9c08d1fa 3510
4164bca1 3511; Reject the frame pointer in operand[1], since reloading this after
3512; it has been eliminated can cause carnage.
3513(define_insn_and_split "*minmax_arithsi_non_canon"
7c36fe71 3514 [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts")
4164bca1 3515 (minus:SI
7c36fe71 3516 (match_operand:SI 1 "s_register_operand" "0,?Ts")
4164bca1 3517 (match_operator:SI 4 "minmax_operator"
7c36fe71 3518 [(match_operand:SI 2 "s_register_operand" "Ts,Ts")
3519 (match_operand:SI 3 "arm_rhs_operand" "TsI,TsI")])))
4164bca1 3520 (clobber (reg:CC CC_REGNUM))]
7c36fe71 3521 "TARGET_32BIT && !arm_eliminable_register (operands[1])
3522 && !(arm_restrict_it && CONST_INT_P (operands[3]))"
4164bca1 3523 "#"
3524 "TARGET_32BIT && !arm_eliminable_register (operands[1]) && reload_completed"
3525 [(set (reg:CC CC_REGNUM)
3526 (compare:CC (match_dup 2) (match_dup 3)))
3527
3528 (cond_exec (match_op_dup 4 [(reg:CC CC_REGNUM) (const_int 0)])
3529 (set (match_dup 0)
3530 (minus:SI (match_dup 1)
3531 (match_dup 2))))
3532 (cond_exec (match_op_dup 5 [(reg:CC CC_REGNUM) (const_int 0)])
3533 (set (match_dup 0)
36ee0cde 3534 (match_dup 6)))]
4164bca1 3535 {
3536 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
3537 operands[2], operands[3]);
3538 enum rtx_code rc = minmax_code (operands[4]);
3539 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode,
3540 operands[2], operands[3]);
3541
3542 if (mode == CCFPmode || mode == CCFPEmode)
3543 rc = reverse_condition_maybe_unordered (rc);
3544 else
3545 rc = reverse_condition (rc);
3546 operands[5] = gen_rtx_fmt_ee (rc, SImode, operands[2], operands[3]);
36ee0cde 3547 if (CONST_INT_P (operands[3]))
3548 operands[6] = plus_constant (SImode, operands[1], -INTVAL (operands[3]));
3549 else
3550 operands[6] = gen_rtx_MINUS (SImode, operands[1], operands[3]);
4164bca1 3551 }
3552 [(set_attr "conds" "clob")
3553 (set (attr "length")
3554 (if_then_else (eq_attr "is_thumb" "yes")
3555 (const_int 14)
1b7da4ac 3556 (const_int 12)))
3557 (set_attr "type" "multiple")]
4164bca1 3558)
3559
b49e3742 3560(define_code_iterator SAT [smin smax])
3561(define_code_iterator SATrev [smin smax])
3562(define_code_attr SATlo [(smin "1") (smax "2")])
3563(define_code_attr SAThi [(smin "2") (smax "1")])
3564
3565(define_insn "*satsi_<SAT:code>"
3566 [(set (match_operand:SI 0 "s_register_operand" "=r")
3567 (SAT:SI (SATrev:SI (match_operand:SI 3 "s_register_operand" "r")
3568 (match_operand:SI 1 "const_int_operand" "i"))
3569 (match_operand:SI 2 "const_int_operand" "i")))]
3570 "TARGET_32BIT && arm_arch6 && <SAT:CODE> != <SATrev:CODE>
3571 && arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>], NULL, NULL)"
3572{
3573 int mask;
3574 bool signed_sat;
3575 if (!arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>],
3576 &mask, &signed_sat))
3577 gcc_unreachable ();
3578
3579 operands[1] = GEN_INT (mask);
3580 if (signed_sat)
3581 return "ssat%?\t%0, %1, %3";
3582 else
3583 return "usat%?\t%0, %1, %3";
3584}
7c36fe71 3585 [(set_attr "predicable" "yes")
1b7da4ac 3586 (set_attr "predicable_short_it" "no")
3587 (set_attr "type" "alus_imm")]
bebe9bbb 3588)
b49e3742 3589
3590(define_insn "*satsi_<SAT:code>_shift"
3591 [(set (match_operand:SI 0 "s_register_operand" "=r")
3592 (SAT:SI (SATrev:SI (match_operator:SI 3 "sat_shift_operator"
3593 [(match_operand:SI 4 "s_register_operand" "r")
3594 (match_operand:SI 5 "const_int_operand" "i")])
3595 (match_operand:SI 1 "const_int_operand" "i"))
3596 (match_operand:SI 2 "const_int_operand" "i")))]
3597 "TARGET_32BIT && arm_arch6 && <SAT:CODE> != <SATrev:CODE>
3598 && arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>], NULL, NULL)"
3599{
3600 int mask;
3601 bool signed_sat;
3602 if (!arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>],
3603 &mask, &signed_sat))
3604 gcc_unreachable ();
3605
3606 operands[1] = GEN_INT (mask);
3607 if (signed_sat)
3608 return "ssat%?\t%0, %1, %4%S3";
3609 else
3610 return "usat%?\t%0, %1, %4%S3";
3611}
3612 [(set_attr "predicable" "yes")
7c36fe71 3613 (set_attr "predicable_short_it" "no")
b49e3742 3614 (set_attr "shift" "3")
d82e788e 3615 (set_attr "type" "logic_shift_reg")])
b11cae9e 3616\f
3617;; Shift and rotation insns
3618
a2cd141b 3619(define_expand "ashldi3"
3620 [(set (match_operand:DI 0 "s_register_operand" "")
3621 (ashift:DI (match_operand:DI 1 "s_register_operand" "")
aa06c51c 3622 (match_operand:SI 2 "general_operand" "")))]
25f905c2 3623 "TARGET_32BIT"
a2cd141b 3624 "
aa06c51c 3625 if (TARGET_NEON)
3626 {
3627 /* Delay the decision whether to use NEON or core-regs until
3628 register allocation. */
3629 emit_insn (gen_ashldi3_neon (operands[0], operands[1], operands[2]));
3630 DONE;
3631 }
3632 else
3633 {
3634 /* Only the NEON case can handle in-memory shift counts. */
3635 if (!reg_or_int_operand (operands[2], SImode))
3636 operands[2] = force_reg (SImode, operands[2]);
3637 }
3638
b805622c 3639 if (!CONST_INT_P (operands[2]) && TARGET_REALLY_IWMMXT)
ffcc986d 3640 ; /* No special preparation statements; expand pattern as above. */
3641 else
a2cd141b 3642 {
ffcc986d 3643 rtx scratch1, scratch2;
3644
3645 if (CONST_INT_P (operands[2])
3646 && (HOST_WIDE_INT) INTVAL (operands[2]) == 1)
a2cd141b 3647 {
3648 emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
3649 DONE;
3650 }
ffcc986d 3651
3652 /* Ideally we should use iwmmxt here if we could know that operands[1]
3653 ends up already living in an iwmmxt register. Otherwise it's
3654 cheaper to have the alternate code being generated than moving
3655 values to iwmmxt regs and back. */
3656
3657 /* If we're optimizing for size, we prefer the libgcc calls. */
3658 if (optimize_function_for_size_p (cfun))
3659 FAIL;
3660
3661 /* Expand operation using core-registers.
3662 'FAIL' would achieve the same thing, but this is a bit smarter. */
3663 scratch1 = gen_reg_rtx (SImode);
3664 scratch2 = gen_reg_rtx (SImode);
3665 arm_emit_coreregs_64bit_shift (ASHIFT, operands[0], operands[1],
3666 operands[2], scratch1, scratch2);
3667 DONE;
a2cd141b 3668 }
a2cd141b 3669 "
3670)
3671
2837e3fb 3672(define_insn "arm_ashldi3_1bit"
50ad1bf9 3673 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 3674 (ashift:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 3675 (const_int 1)))
3676 (clobber (reg:CC CC_REGNUM))]
25f905c2 3677 "TARGET_32BIT"
2837e3fb 3678 "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
a2cd141b 3679 [(set_attr "conds" "clob")
1b7da4ac 3680 (set_attr "length" "8")
3681 (set_attr "type" "multiple")]
a2cd141b 3682)
3683
87b22bf7 3684(define_expand "ashlsi3"
cffb2a26 3685 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3686 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
3687 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3688 "TARGET_EITHER"
87b22bf7 3689 "
0438d37f 3690 if (CONST_INT_P (operands[2])
87b22bf7 3691 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3692 {
3693 emit_insn (gen_movsi (operands[0], const0_rtx));
3694 DONE;
3695 }
cffb2a26 3696 "
3697)
3698
a2cd141b 3699(define_expand "ashrdi3"
3700 [(set (match_operand:DI 0 "s_register_operand" "")
3701 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
3702 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3703 "TARGET_32BIT"
a2cd141b 3704 "
aa06c51c 3705 if (TARGET_NEON)
3706 {
3707 /* Delay the decision whether to use NEON or core-regs until
3708 register allocation. */
3709 emit_insn (gen_ashrdi3_neon (operands[0], operands[1], operands[2]));
3710 DONE;
3711 }
3712
b805622c 3713 if (!CONST_INT_P (operands[2]) && TARGET_REALLY_IWMMXT)
ffcc986d 3714 ; /* No special preparation statements; expand pattern as above. */
3715 else
a2cd141b 3716 {
ffcc986d 3717 rtx scratch1, scratch2;
3718
3719 if (CONST_INT_P (operands[2])
3720 && (HOST_WIDE_INT) INTVAL (operands[2]) == 1)
a2cd141b 3721 {
3722 emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
3723 DONE;
3724 }
ffcc986d 3725
3726 /* Ideally we should use iwmmxt here if we could know that operands[1]
3727 ends up already living in an iwmmxt register. Otherwise it's
3728 cheaper to have the alternate code being generated than moving
3729 values to iwmmxt regs and back. */
3730
3731 /* If we're optimizing for size, we prefer the libgcc calls. */
3732 if (optimize_function_for_size_p (cfun))
3733 FAIL;
3734
3735 /* Expand operation using core-registers.
3736 'FAIL' would achieve the same thing, but this is a bit smarter. */
3737 scratch1 = gen_reg_rtx (SImode);
3738 scratch2 = gen_reg_rtx (SImode);
3739 arm_emit_coreregs_64bit_shift (ASHIFTRT, operands[0], operands[1],
3740 operands[2], scratch1, scratch2);
3741 DONE;
a2cd141b 3742 }
a2cd141b 3743 "
3744)
3745
2837e3fb 3746(define_insn "arm_ashrdi3_1bit"
50ad1bf9 3747 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 3748 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 3749 (const_int 1)))
3750 (clobber (reg:CC CC_REGNUM))]
25f905c2 3751 "TARGET_32BIT"
2837e3fb 3752 "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
a2cd141b 3753 [(set_attr "conds" "clob")
1b7da4ac 3754 (set_attr "length" "8")
3755 (set_attr "type" "multiple")]
a2cd141b 3756)
3757
87b22bf7 3758(define_expand "ashrsi3"
cffb2a26 3759 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3760 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
3761 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3762 "TARGET_EITHER"
87b22bf7 3763 "
0438d37f 3764 if (CONST_INT_P (operands[2])
87b22bf7 3765 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3766 operands[2] = GEN_INT (31);
cffb2a26 3767 "
3768)
3769
a2cd141b 3770(define_expand "lshrdi3"
3771 [(set (match_operand:DI 0 "s_register_operand" "")
3772 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
3773 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3774 "TARGET_32BIT"
a2cd141b 3775 "
aa06c51c 3776 if (TARGET_NEON)
3777 {
3778 /* Delay the decision whether to use NEON or core-regs until
3779 register allocation. */
3780 emit_insn (gen_lshrdi3_neon (operands[0], operands[1], operands[2]));
3781 DONE;
3782 }
3783
b805622c 3784 if (!CONST_INT_P (operands[2]) && TARGET_REALLY_IWMMXT)
ffcc986d 3785 ; /* No special preparation statements; expand pattern as above. */
3786 else
a2cd141b 3787 {
ffcc986d 3788 rtx scratch1, scratch2;
3789
3790 if (CONST_INT_P (operands[2])
3791 && (HOST_WIDE_INT) INTVAL (operands[2]) == 1)
a2cd141b 3792 {
3793 emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
3794 DONE;
3795 }
ffcc986d 3796
3797 /* Ideally we should use iwmmxt here if we could know that operands[1]
3798 ends up already living in an iwmmxt register. Otherwise it's
3799 cheaper to have the alternate code being generated than moving
3800 values to iwmmxt regs and back. */
3801
3802 /* If we're optimizing for size, we prefer the libgcc calls. */
3803 if (optimize_function_for_size_p (cfun))
3804 FAIL;
3805
3806 /* Expand operation using core-registers.
3807 'FAIL' would achieve the same thing, but this is a bit smarter. */
3808 scratch1 = gen_reg_rtx (SImode);
3809 scratch2 = gen_reg_rtx (SImode);
3810 arm_emit_coreregs_64bit_shift (LSHIFTRT, operands[0], operands[1],
3811 operands[2], scratch1, scratch2);
3812 DONE;
a2cd141b 3813 }
a2cd141b 3814 "
3815)
3816
2837e3fb 3817(define_insn "arm_lshrdi3_1bit"
50ad1bf9 3818 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 3819 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 3820 (const_int 1)))
3821 (clobber (reg:CC CC_REGNUM))]
25f905c2 3822 "TARGET_32BIT"
2837e3fb 3823 "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
a2cd141b 3824 [(set_attr "conds" "clob")
1b7da4ac 3825 (set_attr "length" "8")
3826 (set_attr "type" "multiple")]
a2cd141b 3827)
3828
87b22bf7 3829(define_expand "lshrsi3"
cffb2a26 3830 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3831 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
3832 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3833 "TARGET_EITHER"
87b22bf7 3834 "
0438d37f 3835 if (CONST_INT_P (operands[2])
87b22bf7 3836 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3837 {
3838 emit_insn (gen_movsi (operands[0], const0_rtx));
3839 DONE;
3840 }
cffb2a26 3841 "
3842)
3843
87b22bf7 3844(define_expand "rotlsi3"
cffb2a26 3845 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3846 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
3847 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3848 "TARGET_32BIT"
87b22bf7 3849 "
0438d37f 3850 if (CONST_INT_P (operands[2]))
87b22bf7 3851 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
3852 else
b11cae9e 3853 {
87b22bf7 3854 rtx reg = gen_reg_rtx (SImode);
3855 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
3856 operands[2] = reg;
b11cae9e 3857 }
cffb2a26 3858 "
3859)
9c08d1fa 3860
87b22bf7 3861(define_expand "rotrsi3"
cffb2a26 3862 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3863 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
3864 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3865 "TARGET_EITHER"
87b22bf7 3866 "
25f905c2 3867 if (TARGET_32BIT)
cffb2a26 3868 {
0438d37f 3869 if (CONST_INT_P (operands[2])
cffb2a26 3870 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3871 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
3872 }
25f905c2 3873 else /* TARGET_THUMB1 */
cffb2a26 3874 {
0438d37f 3875 if (CONST_INT_P (operands [2]))
cffb2a26 3876 operands [2] = force_reg (SImode, operands[2]);
3877 }
3878 "
3879)
87b22bf7 3880
cffb2a26 3881(define_insn "*arm_shiftsi3"
88c29385 3882 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r,r")
cffb2a26 3883 (match_operator:SI 3 "shift_operator"
88c29385 3884 [(match_operand:SI 1 "s_register_operand" "0,l,r,r")
3885 (match_operand:SI 2 "reg_or_int_operand" "l,M,M,r")]))]
25f905c2 3886 "TARGET_32BIT"
3887 "* return arm_output_shift(operands, 0);"
344495ea 3888 [(set_attr "predicable" "yes")
88c29385 3889 (set_attr "arch" "t2,t2,*,*")
3890 (set_attr "predicable_short_it" "yes,yes,no,no")
7c36fe71 3891 (set_attr "length" "4")
331beb1a 3892 (set_attr "shift" "1")
88c29385 3893 (set_attr "type" "alu_shift_reg,alu_shift_imm,alu_shift_imm,alu_shift_reg")]
6c4c2133 3894)
87b22bf7 3895
f7fbdd4a 3896(define_insn "*shiftsi3_compare0"
bd5b4116 3897 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 3898 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
6b6abc9c 3899 [(match_operand:SI 1 "s_register_operand" "r,r")
3900 (match_operand:SI 2 "arm_rhs_operand" "M,r")])
9c08d1fa 3901 (const_int 0)))
6b6abc9c 3902 (set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 3903 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
25f905c2 3904 "TARGET_32BIT"
3905 "* return arm_output_shift(operands, 1);"
344495ea 3906 [(set_attr "conds" "set")
331beb1a 3907 (set_attr "shift" "1")
d82e788e 3908 (set_attr "type" "alus_shift_imm,alus_shift_reg")]
0d66636f 3909)
9c08d1fa 3910
f7fbdd4a 3911(define_insn "*shiftsi3_compare0_scratch"
bd5b4116 3912 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 3913 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
6b6abc9c 3914 [(match_operand:SI 1 "s_register_operand" "r,r")
3915 (match_operand:SI 2 "arm_rhs_operand" "M,r")])
9c08d1fa 3916 (const_int 0)))
6b6abc9c 3917 (clobber (match_scratch:SI 0 "=r,r"))]
25f905c2 3918 "TARGET_32BIT"
3919 "* return arm_output_shift(operands, 1);"
344495ea 3920 [(set_attr "conds" "set")
6b6abc9c 3921 (set_attr "shift" "1")
d82e788e 3922 (set_attr "type" "shift_imm,shift_reg")]
0d66636f 3923)
9c08d1fa 3924
d5d4dc8d 3925(define_insn "*not_shiftsi"
3926 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 3927 (not:SI (match_operator:SI 3 "shift_operator"
d5d4dc8d 3928 [(match_operand:SI 1 "s_register_operand" "r,r")
3929 (match_operand:SI 2 "shift_amount_operand" "M,rM")])))]
3930 "TARGET_32BIT"
6c4c2133 3931 "mvn%?\\t%0, %1%S3"
344495ea 3932 [(set_attr "predicable" "yes")
d952d547 3933 (set_attr "predicable_short_it" "no")
331beb1a 3934 (set_attr "shift" "1")
d5d4dc8d 3935 (set_attr "arch" "32,a")
1aed5204 3936 (set_attr "type" "mvn_shift,mvn_shift_reg")])
9c08d1fa 3937
d5d4dc8d 3938(define_insn "*not_shiftsi_compare0"
bd5b4116 3939 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 3940 (compare:CC_NOOV
3941 (not:SI (match_operator:SI 3 "shift_operator"
3942 [(match_operand:SI 1 "s_register_operand" "r,r")
3943 (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
3944 (const_int 0)))
3945 (set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 3946 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
d5d4dc8d 3947 "TARGET_32BIT"
25f905c2 3948 "mvn%.\\t%0, %1%S3"
344495ea 3949 [(set_attr "conds" "set")
331beb1a 3950 (set_attr "shift" "1")
d5d4dc8d 3951 (set_attr "arch" "32,a")
1aed5204 3952 (set_attr "type" "mvn_shift,mvn_shift_reg")])
9c08d1fa 3953
d5d4dc8d 3954(define_insn "*not_shiftsi_compare0_scratch"
bd5b4116 3955 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 3956 (compare:CC_NOOV
3957 (not:SI (match_operator:SI 3 "shift_operator"
3958 [(match_operand:SI 1 "s_register_operand" "r,r")
3959 (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
3960 (const_int 0)))
3961 (clobber (match_scratch:SI 0 "=r,r"))]
3962 "TARGET_32BIT"
25f905c2 3963 "mvn%.\\t%0, %1%S3"
344495ea 3964 [(set_attr "conds" "set")
331beb1a 3965 (set_attr "shift" "1")
d5d4dc8d 3966 (set_attr "arch" "32,a")
1aed5204 3967 (set_attr "type" "mvn_shift,mvn_shift_reg")])
9c08d1fa 3968
cffb2a26 3969;; We don't really have extzv, but defining this using shifts helps
3970;; to reduce register pressure later on.
3971
3972(define_expand "extzv"
eb04cafb 3973 [(set (match_operand 0 "s_register_operand" "")
3974 (zero_extract (match_operand 1 "nonimmediate_operand" "")
3975 (match_operand 2 "const_int_operand" "")
3976 (match_operand 3 "const_int_operand" "")))]
8b054d5a 3977 "TARGET_THUMB1 || arm_arch_thumb2"
cffb2a26 3978 "
3979 {
3980 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
3981 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
3982
8b054d5a 3983 if (arm_arch_thumb2)
3984 {
eb04cafb 3985 HOST_WIDE_INT width = INTVAL (operands[2]);
3986 HOST_WIDE_INT bitpos = INTVAL (operands[3]);
3987
3988 if (unaligned_access && MEM_P (operands[1])
3989 && (width == 16 || width == 32) && (bitpos % BITS_PER_UNIT) == 0)
3990 {
3991 rtx base_addr;
3992
3993 if (BYTES_BIG_ENDIAN)
3994 bitpos = GET_MODE_BITSIZE (GET_MODE (operands[0])) - width
3995 - bitpos;
3996
3997 if (width == 32)
3998 {
3999 base_addr = adjust_address (operands[1], SImode,
4000 bitpos / BITS_PER_UNIT);
4001 emit_insn (gen_unaligned_loadsi (operands[0], base_addr));
4002 }
4003 else
4004 {
4005 rtx dest = operands[0];
4006 rtx tmp = gen_reg_rtx (SImode);
4007
4008 /* We may get a paradoxical subreg here. Strip it off. */
4009 if (GET_CODE (dest) == SUBREG
4010 && GET_MODE (dest) == SImode
4011 && GET_MODE (SUBREG_REG (dest)) == HImode)
4012 dest = SUBREG_REG (dest);
4013
4014 if (GET_MODE_BITSIZE (GET_MODE (dest)) != width)
4015 FAIL;
4016
4017 base_addr = adjust_address (operands[1], HImode,
4018 bitpos / BITS_PER_UNIT);
4019 emit_insn (gen_unaligned_loadhiu (tmp, base_addr));
4020 emit_move_insn (gen_lowpart (SImode, dest), tmp);
4021 }
4022 DONE;
4023 }
4024 else if (s_register_operand (operands[1], GET_MODE (operands[1])))
4025 {
4026 emit_insn (gen_extzv_t2 (operands[0], operands[1], operands[2],
4027 operands[3]));
4028 DONE;
4029 }
4030 else
4031 FAIL;
8b054d5a 4032 }
eb04cafb 4033
4034 if (!s_register_operand (operands[1], GET_MODE (operands[1])))
4035 FAIL;
8b054d5a 4036
cffb2a26 4037 operands[3] = GEN_INT (rshift);
4038
4039 if (lshift == 0)
4040 {
4041 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
4042 DONE;
4043 }
4044
eb04cafb 4045 emit_insn (gen_extzv_t1 (operands[0], operands[1], GEN_INT (lshift),
4046 operands[3], gen_reg_rtx (SImode)));
4047 DONE;
215b30b3 4048 }"
cffb2a26 4049)
4050
eb04cafb 4051;; Helper for extzv, for the Thumb-1 register-shifts case.
4052
4053(define_expand "extzv_t1"
4054 [(set (match_operand:SI 4 "s_register_operand" "")
4055 (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "")
4056 (match_operand:SI 2 "const_int_operand" "")))
4057 (set (match_operand:SI 0 "s_register_operand" "")
4058 (lshiftrt:SI (match_dup 4)
4059 (match_operand:SI 3 "const_int_operand" "")))]
4060 "TARGET_THUMB1"
4061 "")
4062
4063(define_expand "extv"
4064 [(set (match_operand 0 "s_register_operand" "")
4065 (sign_extract (match_operand 1 "nonimmediate_operand" "")
4066 (match_operand 2 "const_int_operand" "")
4067 (match_operand 3 "const_int_operand" "")))]
4068 "arm_arch_thumb2"
4069{
4070 HOST_WIDE_INT width = INTVAL (operands[2]);
4071 HOST_WIDE_INT bitpos = INTVAL (operands[3]);
4072
4073 if (unaligned_access && MEM_P (operands[1]) && (width == 16 || width == 32)
4074 && (bitpos % BITS_PER_UNIT) == 0)
4075 {
4076 rtx base_addr;
4077
4078 if (BYTES_BIG_ENDIAN)
4079 bitpos = GET_MODE_BITSIZE (GET_MODE (operands[0])) - width - bitpos;
4080
4081 if (width == 32)
4082 {
4083 base_addr = adjust_address (operands[1], SImode,
4084 bitpos / BITS_PER_UNIT);
4085 emit_insn (gen_unaligned_loadsi (operands[0], base_addr));
4086 }
4087 else
4088 {
4089 rtx dest = operands[0];
4090 rtx tmp = gen_reg_rtx (SImode);
4091
4092 /* We may get a paradoxical subreg here. Strip it off. */
4093 if (GET_CODE (dest) == SUBREG
4094 && GET_MODE (dest) == SImode
4095 && GET_MODE (SUBREG_REG (dest)) == HImode)
4096 dest = SUBREG_REG (dest);
4097
4098 if (GET_MODE_BITSIZE (GET_MODE (dest)) != width)
4099 FAIL;
4100
4101 base_addr = adjust_address (operands[1], HImode,
4102 bitpos / BITS_PER_UNIT);
4103 emit_insn (gen_unaligned_loadhis (tmp, base_addr));
4104 emit_move_insn (gen_lowpart (SImode, dest), tmp);
4105 }
4106
4107 DONE;
4108 }
4109 else if (!s_register_operand (operands[1], GET_MODE (operands[1])))
4110 FAIL;
4111 else if (GET_MODE (operands[0]) == SImode
4112 && GET_MODE (operands[1]) == SImode)
4113 {
4114 emit_insn (gen_extv_regsi (operands[0], operands[1], operands[2],
4115 operands[3]));
4116 DONE;
4117 }
4118
4119 FAIL;
4120})
4121
4122; Helper to expand register forms of extv with the proper modes.
4123
4124(define_expand "extv_regsi"
4125 [(set (match_operand:SI 0 "s_register_operand" "")
4126 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
4127 (match_operand 2 "const_int_operand" "")
4128 (match_operand 3 "const_int_operand" "")))]
4129 ""
4130{
4131})
4132
4133; ARMv6+ unaligned load/store instructions (used for packed structure accesses).
4134
4135(define_insn "unaligned_loadsi"
4136 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4137 (unspec:SI [(match_operand:SI 1 "memory_operand" "Uw,m")]
4138 UNSPEC_UNALIGNED_LOAD))]
4139 "unaligned_access && TARGET_32BIT"
4140 "ldr%?\t%0, %1\t@ unaligned"
4141 [(set_attr "arch" "t2,any")
4142 (set_attr "length" "2,4")
4143 (set_attr "predicable" "yes")
d952d547 4144 (set_attr "predicable_short_it" "yes,no")
eb04cafb 4145 (set_attr "type" "load1")])
4146
4147(define_insn "unaligned_loadhis"
4148 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4149 (sign_extend:SI
4150 (unspec:HI [(match_operand:HI 1 "memory_operand" "Uw,m")]
4151 UNSPEC_UNALIGNED_LOAD)))]
4152 "unaligned_access && TARGET_32BIT"
4153 "ldr%(sh%)\t%0, %1\t@ unaligned"
4154 [(set_attr "arch" "t2,any")
4155 (set_attr "length" "2,4")
4156 (set_attr "predicable" "yes")
d952d547 4157 (set_attr "predicable_short_it" "yes,no")
eb04cafb 4158 (set_attr "type" "load_byte")])
4159
4160(define_insn "unaligned_loadhiu"
4161 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4162 (zero_extend:SI
4163 (unspec:HI [(match_operand:HI 1 "memory_operand" "Uw,m")]
4164 UNSPEC_UNALIGNED_LOAD)))]
4165 "unaligned_access && TARGET_32BIT"
4166 "ldr%(h%)\t%0, %1\t@ unaligned"
4167 [(set_attr "arch" "t2,any")
4168 (set_attr "length" "2,4")
4169 (set_attr "predicable" "yes")
d952d547 4170 (set_attr "predicable_short_it" "yes,no")
eb04cafb 4171 (set_attr "type" "load_byte")])
4172
4173(define_insn "unaligned_storesi"
4174 [(set (match_operand:SI 0 "memory_operand" "=Uw,m")
4175 (unspec:SI [(match_operand:SI 1 "s_register_operand" "l,r")]
4176 UNSPEC_UNALIGNED_STORE))]
4177 "unaligned_access && TARGET_32BIT"
4178 "str%?\t%1, %0\t@ unaligned"
4179 [(set_attr "arch" "t2,any")
4180 (set_attr "length" "2,4")
4181 (set_attr "predicable" "yes")
d952d547 4182 (set_attr "predicable_short_it" "yes,no")
eb04cafb 4183 (set_attr "type" "store1")])
4184
4185(define_insn "unaligned_storehi"
4186 [(set (match_operand:HI 0 "memory_operand" "=Uw,m")
4187 (unspec:HI [(match_operand:HI 1 "s_register_operand" "l,r")]
4188 UNSPEC_UNALIGNED_STORE))]
4189 "unaligned_access && TARGET_32BIT"
4190 "str%(h%)\t%1, %0\t@ unaligned"
4191 [(set_attr "arch" "t2,any")
4192 (set_attr "length" "2,4")
4193 (set_attr "predicable" "yes")
d952d547 4194 (set_attr "predicable_short_it" "yes,no")
eb04cafb 4195 (set_attr "type" "store1")])
4196
ae51a965 4197;; Unaligned double-word load and store.
4198;; Split after reload into two unaligned single-word accesses.
4199;; It prevents lower_subreg from splitting some other aligned
4200;; double-word accesses too early. Used for internal memcpy.
4201
4202(define_insn_and_split "unaligned_loaddi"
4203 [(set (match_operand:DI 0 "s_register_operand" "=l,r")
4204 (unspec:DI [(match_operand:DI 1 "memory_operand" "o,o")]
4205 UNSPEC_UNALIGNED_LOAD))]
4206 "unaligned_access && TARGET_32BIT"
4207 "#"
4208 "&& reload_completed"
4209 [(set (match_dup 0) (unspec:SI [(match_dup 1)] UNSPEC_UNALIGNED_LOAD))
4210 (set (match_dup 2) (unspec:SI [(match_dup 3)] UNSPEC_UNALIGNED_LOAD))]
4211 {
4212 operands[2] = gen_highpart (SImode, operands[0]);
4213 operands[0] = gen_lowpart (SImode, operands[0]);
4214 operands[3] = gen_highpart (SImode, operands[1]);
4215 operands[1] = gen_lowpart (SImode, operands[1]);
4216
4217 /* If the first destination register overlaps with the base address,
4218 swap the order in which the loads are emitted. */
4219 if (reg_overlap_mentioned_p (operands[0], operands[1]))
4220 {
4221 rtx tmp = operands[1];
4222 operands[1] = operands[3];
4223 operands[3] = tmp;
4224 tmp = operands[0];
4225 operands[0] = operands[2];
4226 operands[2] = tmp;
4227 }
4228 }
4229 [(set_attr "arch" "t2,any")
4230 (set_attr "length" "4,8")
4231 (set_attr "predicable" "yes")
4232 (set_attr "type" "load2")])
4233
4234(define_insn_and_split "unaligned_storedi"
4235 [(set (match_operand:DI 0 "memory_operand" "=o,o")
4236 (unspec:DI [(match_operand:DI 1 "s_register_operand" "l,r")]
4237 UNSPEC_UNALIGNED_STORE))]
4238 "unaligned_access && TARGET_32BIT"
4239 "#"
4240 "&& reload_completed"
4241 [(set (match_dup 0) (unspec:SI [(match_dup 1)] UNSPEC_UNALIGNED_STORE))
4242 (set (match_dup 2) (unspec:SI [(match_dup 3)] UNSPEC_UNALIGNED_STORE))]
4243 {
4244 operands[2] = gen_highpart (SImode, operands[0]);
4245 operands[0] = gen_lowpart (SImode, operands[0]);
4246 operands[3] = gen_highpart (SImode, operands[1]);
4247 operands[1] = gen_lowpart (SImode, operands[1]);
4248 }
4249 [(set_attr "arch" "t2,any")
4250 (set_attr "length" "4,8")
4251 (set_attr "predicable" "yes")
4252 (set_attr "type" "store2")])
4253
4254
eb04cafb 4255(define_insn "*extv_reg"
8b054d5a 4256 [(set (match_operand:SI 0 "s_register_operand" "=r")
4257 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
809003b3 4258 (match_operand:SI 2 "const_int_M_operand" "M")
4259 (match_operand:SI 3 "const_int_M_operand" "M")))]
8b054d5a 4260 "arm_arch_thumb2"
4261 "sbfx%?\t%0, %1, %3, %2"
4262 [(set_attr "length" "4")
d952d547 4263 (set_attr "predicable" "yes")
d82e788e 4264 (set_attr "predicable_short_it" "no")
4265 (set_attr "type" "bfm")]
8b054d5a 4266)
4267
4268(define_insn "extzv_t2"
4269 [(set (match_operand:SI 0 "s_register_operand" "=r")
4270 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "r")
809003b3 4271 (match_operand:SI 2 "const_int_M_operand" "M")
4272 (match_operand:SI 3 "const_int_M_operand" "M")))]
8b054d5a 4273 "arm_arch_thumb2"
4274 "ubfx%?\t%0, %1, %3, %2"
4275 [(set_attr "length" "4")
d952d547 4276 (set_attr "predicable" "yes")
d82e788e 4277 (set_attr "predicable_short_it" "no")
4278 (set_attr "type" "bfm")]
8b054d5a 4279)
4280
7d3cda8c 4281
4282;; Division instructions
4283(define_insn "divsi3"
4284 [(set (match_operand:SI 0 "s_register_operand" "=r")
4285 (div:SI (match_operand:SI 1 "s_register_operand" "r")
4286 (match_operand:SI 2 "s_register_operand" "r")))]
4287 "TARGET_IDIV"
4288 "sdiv%?\t%0, %1, %2"
4289 [(set_attr "predicable" "yes")
d952d547 4290 (set_attr "predicable_short_it" "no")
9da0ec36 4291 (set_attr "type" "sdiv")]
7d3cda8c 4292)
4293
4294(define_insn "udivsi3"
4295 [(set (match_operand:SI 0 "s_register_operand" "=r")
4296 (udiv:SI (match_operand:SI 1 "s_register_operand" "r")
4297 (match_operand:SI 2 "s_register_operand" "r")))]
4298 "TARGET_IDIV"
4299 "udiv%?\t%0, %1, %2"
4300 [(set_attr "predicable" "yes")
d952d547 4301 (set_attr "predicable_short_it" "no")
9da0ec36 4302 (set_attr "type" "udiv")]
7d3cda8c 4303)
4304
b11cae9e 4305\f
4306;; Unary arithmetic insns
4307
cffb2a26 4308(define_expand "negdi2"
4309 [(parallel
8135a42b 4310 [(set (match_operand:DI 0 "s_register_operand" "")
4311 (neg:DI (match_operand:DI 1 "s_register_operand" "")))
bd5b4116 4312 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 4313 "TARGET_EITHER"
774d2fbb 4314 {
4315 if (TARGET_NEON)
4316 {
4317 emit_insn (gen_negdi2_neon (operands[0], operands[1]));
4318 DONE;
4319 }
4320 }
cffb2a26 4321)
4322
4323;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
e5fea38e 4324;; The first alternative allows the common case of a *full* overlap.
ba6a3b2f 4325(define_insn_and_split "*arm_negdi2"
458a8706 4326 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 4327 (neg:DI (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 4328 (clobber (reg:CC CC_REGNUM))]
cffb2a26 4329 "TARGET_ARM"
ba6a3b2f 4330 "#" ; "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
4331 "&& reload_completed"
4332 [(parallel [(set (reg:CC CC_REGNUM)
4333 (compare:CC (const_int 0) (match_dup 1)))
4334 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 1)))])
4335 (set (match_dup 2) (minus:SI (minus:SI (const_int 0) (match_dup 3))
4336 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
4337 {
4338 operands[2] = gen_highpart (SImode, operands[0]);
4339 operands[0] = gen_lowpart (SImode, operands[0]);
4340 operands[3] = gen_highpart (SImode, operands[1]);
4341 operands[1] = gen_lowpart (SImode, operands[1]);
4342 }
cffb2a26 4343 [(set_attr "conds" "clob")
1b7da4ac 4344 (set_attr "length" "8")
4345 (set_attr "type" "multiple")]
cffb2a26 4346)
b11cae9e 4347
cffb2a26 4348(define_expand "negsi2"
4349 [(set (match_operand:SI 0 "s_register_operand" "")
4350 (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
4351 "TARGET_EITHER"
b11cae9e 4352 ""
cffb2a26 4353)
4354
4355(define_insn "*arm_negsi2"
d952d547 4356 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4357 (neg:SI (match_operand:SI 1 "s_register_operand" "l,r")))]
25f905c2 4358 "TARGET_32BIT"
cffb2a26 4359 "rsb%?\\t%0, %1, #0"
d952d547 4360 [(set_attr "predicable" "yes")
4361 (set_attr "predicable_short_it" "yes,no")
4362 (set_attr "arch" "t2,*")
1b7da4ac 4363 (set_attr "length" "4")
4364 (set_attr "type" "alu_reg")]
cffb2a26 4365)
4366
604f3a0a 4367(define_expand "negsf2"
4368 [(set (match_operand:SF 0 "s_register_operand" "")
4369 (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
994606f8 4370 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
604f3a0a 4371 ""
4372)
4373
4374(define_expand "negdf2"
4375 [(set (match_operand:DF 0 "s_register_operand" "")
4376 (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
994606f8 4377 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
604f3a0a 4378 "")
4379
7eaf2be0 4380(define_insn_and_split "*zextendsidi_negsi"
4381 [(set (match_operand:DI 0 "s_register_operand" "=r")
4382 (zero_extend:DI (neg:SI (match_operand:SI 1 "s_register_operand" "r"))))]
4383 "TARGET_32BIT"
4384 "#"
4385 ""
4386 [(set (match_dup 2)
4387 (neg:SI (match_dup 1)))
4388 (set (match_dup 3)
4389 (const_int 0))]
4390 {
4391 operands[2] = gen_lowpart (SImode, operands[0]);
4392 operands[3] = gen_highpart (SImode, operands[0]);
4393 }
4394 [(set_attr "length" "8")
4395 (set_attr "type" "multiple")]
4396)
4397
83e2b922 4398;; Negate an extended 32-bit value.
4399(define_insn_and_split "*negdi_extendsidi"
61fa8ff2 4400 [(set (match_operand:DI 0 "s_register_operand" "=l,r")
4401 (neg:DI (sign_extend:DI
4402 (match_operand:SI 1 "s_register_operand" "l,r"))))
83e2b922 4403 (clobber (reg:CC CC_REGNUM))]
4404 "TARGET_32BIT"
61fa8ff2 4405 "#"
83e2b922 4406 "&& reload_completed"
4407 [(const_int 0)]
4408 {
61fa8ff2 4409 rtx low = gen_lowpart (SImode, operands[0]);
4410 rtx high = gen_highpart (SImode, operands[0]);
4411
4412 if (reg_overlap_mentioned_p (low, operands[1]))
4413 {
4414 /* Input overlaps the low word of the output. Use:
4415 asr Rhi, Rin, #31
4416 rsbs Rlo, Rin, #0
4417 rsc Rhi, Rhi, #0 (thumb2: sbc Rhi, Rhi, Rhi, lsl #1). */
4418 rtx cc_reg = gen_rtx_REG (CC_Cmode, CC_REGNUM);
4419
4420 emit_insn (gen_rtx_SET (VOIDmode, high,
4421 gen_rtx_ASHIFTRT (SImode, operands[1],
4422 GEN_INT (31))));
4423
4424 emit_insn (gen_subsi3_compare (low, const0_rtx, operands[1]));
4425 if (TARGET_ARM)
4426 emit_insn (gen_rtx_SET (VOIDmode, high,
4427 gen_rtx_MINUS (SImode,
4428 gen_rtx_MINUS (SImode,
4429 const0_rtx,
4430 high),
4431 gen_rtx_LTU (SImode,
4432 cc_reg,
4433 const0_rtx))));
4434 else
4435 {
4436 rtx two_x = gen_rtx_ASHIFT (SImode, high, GEN_INT (1));
4437 emit_insn (gen_rtx_SET (VOIDmode, high,
4438 gen_rtx_MINUS (SImode,
4439 gen_rtx_MINUS (SImode,
4440 high,
4441 two_x),
4442 gen_rtx_LTU (SImode,
4443 cc_reg,
4444 const0_rtx))));
4445 }
4446 }
4447 else
4448 {
4449 /* No overlap, or overlap on high word. Use:
4450 rsb Rlo, Rin, #0
4451 bic Rhi, Rlo, Rin
4452 asr Rhi, Rhi, #31
4453 Flags not needed for this sequence. */
4454 emit_insn (gen_rtx_SET (VOIDmode, low,
4455 gen_rtx_NEG (SImode, operands[1])));
4456 emit_insn (gen_rtx_SET (VOIDmode, high,
4457 gen_rtx_AND (SImode,
4458 gen_rtx_NOT (SImode, operands[1]),
4459 low)));
4460 emit_insn (gen_rtx_SET (VOIDmode, high,
4461 gen_rtx_ASHIFTRT (SImode, high,
4462 GEN_INT (31))));
4463 }
4464 DONE;
83e2b922 4465 }
61fa8ff2 4466 [(set_attr "length" "12")
4467 (set_attr "arch" "t2,*")
1b7da4ac 4468 (set_attr "type" "multiple")]
83e2b922 4469)
4470
4471(define_insn_and_split "*negdi_zero_extendsidi"
4472 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
4473 (neg:DI (zero_extend:DI (match_operand:SI 1 "s_register_operand" "0,r"))))
4474 (clobber (reg:CC CC_REGNUM))]
4475 "TARGET_32BIT"
4476 "#" ; "rsbs\\t%Q0, %1, #0\;sbc\\t%R0,%R0,%R0"
4477 ;; Don't care what register is input to sbc,
4478 ;; since we just just need to propagate the carry.
4479 "&& reload_completed"
4480 [(parallel [(set (reg:CC CC_REGNUM)
4481 (compare:CC (const_int 0) (match_dup 1)))
4482 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 1)))])
4483 (set (match_dup 2) (minus:SI (minus:SI (match_dup 2) (match_dup 2))
4484 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
4485 {
4486 operands[2] = gen_highpart (SImode, operands[0]);
4487 operands[0] = gen_lowpart (SImode, operands[0]);
4488 }
4489 [(set_attr "conds" "clob")
1b7da4ac 4490 (set_attr "length" "8")
4491 (set_attr "type" "multiple")] ;; length in thumb is 4
83e2b922 4492)
4493
9c08d1fa 4494;; abssi2 doesn't really clobber the condition codes if a different register
4495;; is being set. To keep things simple, assume during rtl manipulations that
4496;; it does, but tell the final scan operator the truth. Similarly for
4497;; (neg (abs...))
4498
604f3a0a 4499(define_expand "abssi2"
4500 [(parallel
4501 [(set (match_operand:SI 0 "s_register_operand" "")
4502 (abs:SI (match_operand:SI 1 "s_register_operand" "")))
ba156559 4503 (clobber (match_dup 2))])]
4504 "TARGET_EITHER"
4505 "
25f905c2 4506 if (TARGET_THUMB1)
ba156559 4507 operands[2] = gen_rtx_SCRATCH (SImode);
4508 else
4509 operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
4510")
604f3a0a 4511
ba6a3b2f 4512(define_insn_and_split "*arm_abssi2"
ba156559 4513 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
9c08d1fa 4514 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
bd5b4116 4515 (clobber (reg:CC CC_REGNUM))]
cffb2a26 4516 "TARGET_ARM"
ba6a3b2f 4517 "#"
4518 "&& reload_completed"
4519 [(const_int 0)]
4520 {
4521 /* if (which_alternative == 0) */
4522 if (REGNO(operands[0]) == REGNO(operands[1]))
4523 {
4524 /* Emit the pattern:
4525 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
4526 [(set (reg:CC CC_REGNUM)
4527 (compare:CC (match_dup 0) (const_int 0)))
4528 (cond_exec (lt:CC (reg:CC CC_REGNUM) (const_int 0))
4529 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 1))))]
4530 */
4531 emit_insn (gen_rtx_SET (VOIDmode,
4532 gen_rtx_REG (CCmode, CC_REGNUM),
4533 gen_rtx_COMPARE (CCmode, operands[0], const0_rtx)));
4534 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
4535 (gen_rtx_LT (SImode,
4536 gen_rtx_REG (CCmode, CC_REGNUM),
4537 const0_rtx)),
4538 (gen_rtx_SET (VOIDmode,
4539 operands[0],
4540 (gen_rtx_MINUS (SImode,
4541 const0_rtx,
4542 operands[1]))))));
4543 DONE;
4544 }
4545 else
4546 {
4547 /* Emit the pattern:
4548 alt1: eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31
4549 [(set (match_dup 0)
4550 (xor:SI (match_dup 1)
4551 (ashiftrt:SI (match_dup 1) (const_int 31))))
4552 (set (match_dup 0)
4553 (minus:SI (match_dup 0)
4554 (ashiftrt:SI (match_dup 1) (const_int 31))))]
4555 */
4556 emit_insn (gen_rtx_SET (VOIDmode,
4557 operands[0],
4558 gen_rtx_XOR (SImode,
4559 gen_rtx_ASHIFTRT (SImode,
4560 operands[1],
4561 GEN_INT (31)),
4562 operands[1])));
4563 emit_insn (gen_rtx_SET (VOIDmode,
4564 operands[0],
4565 gen_rtx_MINUS (SImode,
4566 operands[0],
4567 gen_rtx_ASHIFTRT (SImode,
4568 operands[1],
4569 GEN_INT (31)))));
4570 DONE;
4571 }
4572 }
cffb2a26 4573 [(set_attr "conds" "clob,*")
331beb1a 4574 (set_attr "shift" "1")
2ad08b65 4575 (set_attr "predicable" "no, yes")
1b7da4ac 4576 (set_attr "length" "8")
4577 (set_attr "type" "multiple")]
cffb2a26 4578)
9c08d1fa 4579
ba6a3b2f 4580(define_insn_and_split "*arm_neg_abssi2"
9c08d1fa 4581 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
4582 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
bd5b4116 4583 (clobber (reg:CC CC_REGNUM))]
cffb2a26 4584 "TARGET_ARM"
ba6a3b2f 4585 "#"
4586 "&& reload_completed"
4587 [(const_int 0)]
4588 {
4589 /* if (which_alternative == 0) */
4590 if (REGNO (operands[0]) == REGNO (operands[1]))
4591 {
4592 /* Emit the pattern:
4593 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
4594 */
4595 emit_insn (gen_rtx_SET (VOIDmode,
4596 gen_rtx_REG (CCmode, CC_REGNUM),
4597 gen_rtx_COMPARE (CCmode, operands[0], const0_rtx)));
4598 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
4599 gen_rtx_GT (SImode,
4600 gen_rtx_REG (CCmode, CC_REGNUM),
4601 const0_rtx),
4602 gen_rtx_SET (VOIDmode,
4603 operands[0],
4604 (gen_rtx_MINUS (SImode,
4605 const0_rtx,
4606 operands[1])))));
4607 }
4608 else
4609 {
4610 /* Emit the pattern:
4611 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31
4612 */
4613 emit_insn (gen_rtx_SET (VOIDmode,
4614 operands[0],
4615 gen_rtx_XOR (SImode,
4616 gen_rtx_ASHIFTRT (SImode,
4617 operands[1],
4618 GEN_INT (31)),
4619 operands[1])));
4620 emit_insn (gen_rtx_SET (VOIDmode,
4621 operands[0],
4622 gen_rtx_MINUS (SImode,
4623 gen_rtx_ASHIFTRT (SImode,
4624 operands[1],
4625 GEN_INT (31)),
4626 operands[0])));
4627 }
4628 DONE;
4629 }
cffb2a26 4630 [(set_attr "conds" "clob,*")
331beb1a 4631 (set_attr "shift" "1")
2ad08b65 4632 (set_attr "predicable" "no, yes")
1b7da4ac 4633 (set_attr "length" "8")
4634 (set_attr "type" "multiple")]
cffb2a26 4635)
b11cae9e 4636
604f3a0a 4637(define_expand "abssf2"
4638 [(set (match_operand:SF 0 "s_register_operand" "")
4639 (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
25f905c2 4640 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 4641 "")
4642
604f3a0a 4643(define_expand "absdf2"
4644 [(set (match_operand:DF 0 "s_register_operand" "")
4645 (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 4646 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 4647 "")
4648
7db9af5d 4649(define_expand "sqrtsf2"
4650 [(set (match_operand:SF 0 "s_register_operand" "")
4651 (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
994606f8 4652 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
7db9af5d 4653 "")
9c08d1fa 4654
7db9af5d 4655(define_expand "sqrtdf2"
4656 [(set (match_operand:DF 0 "s_register_operand" "")
4657 (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
994606f8 4658 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
7db9af5d 4659 "")
9c08d1fa 4660
a0f94409 4661(define_insn_and_split "one_cmpldi2"
10efb95f 4662 [(set (match_operand:DI 0 "s_register_operand" "=w,&r,&r,?w")
4663 (not:DI (match_operand:DI 1 "s_register_operand" " w, 0, r, w")))]
25f905c2 4664 "TARGET_32BIT"
10efb95f 4665 "@
4666 vmvn\t%P0, %P1
4667 #
4668 #
4669 vmvn\t%P0, %P1"
4670 "TARGET_32BIT && reload_completed
4671 && arm_general_register_operand (operands[0], DImode)"
a0f94409 4672 [(set (match_dup 0) (not:SI (match_dup 1)))
4673 (set (match_dup 2) (not:SI (match_dup 3)))]
4674 "
4675 {
4676 operands[2] = gen_highpart (SImode, operands[0]);
4677 operands[0] = gen_lowpart (SImode, operands[0]);
4678 operands[3] = gen_highpart (SImode, operands[1]);
4679 operands[1] = gen_lowpart (SImode, operands[1]);
4680 }"
10efb95f 4681 [(set_attr "length" "*,8,8,*")
4682 (set_attr "predicable" "no,yes,yes,no")
32093010 4683 (set_attr "type" "neon_move,multiple,multiple,neon_move")
b6779ddc 4684 (set_attr "arch" "neon_for_64bits,*,*,avoid_neon_for_64bits")]
cffb2a26 4685)
b11cae9e 4686
cffb2a26 4687(define_expand "one_cmplsi2"
4688 [(set (match_operand:SI 0 "s_register_operand" "")
4689 (not:SI (match_operand:SI 1 "s_register_operand" "")))]
4690 "TARGET_EITHER"
b11cae9e 4691 ""
cffb2a26 4692)
4693
4694(define_insn "*arm_one_cmplsi2"
d952d547 4695 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4696 (not:SI (match_operand:SI 1 "s_register_operand" "l,r")))]
25f905c2 4697 "TARGET_32BIT"
cffb2a26 4698 "mvn%?\\t%0, %1"
d2a518d1 4699 [(set_attr "predicable" "yes")
d952d547 4700 (set_attr "predicable_short_it" "yes,no")
4701 (set_attr "arch" "t2,*")
4702 (set_attr "length" "4")
1aed5204 4703 (set_attr "type" "mvn_reg")]
cffb2a26 4704)
4705
f7fbdd4a 4706(define_insn "*notsi_compare0"
bd5b4116 4707 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 4708 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
4709 (const_int 0)))
4710 (set (match_operand:SI 0 "s_register_operand" "=r")
4711 (not:SI (match_dup 1)))]
25f905c2 4712 "TARGET_32BIT"
4713 "mvn%.\\t%0, %1"
d2a518d1 4714 [(set_attr "conds" "set")
1aed5204 4715 (set_attr "type" "mvn_reg")]
cffb2a26 4716)
9c08d1fa 4717
f7fbdd4a 4718(define_insn "*notsi_compare0_scratch"
bd5b4116 4719 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 4720 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
4721 (const_int 0)))
4722 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 4723 "TARGET_32BIT"
4724 "mvn%.\\t%0, %1"
d2a518d1 4725 [(set_attr "conds" "set")
1aed5204 4726 (set_attr "type" "mvn_reg")]
cffb2a26 4727)
b11cae9e 4728\f
4729;; Fixed <--> Floating conversion insns
4730
9b8516be 4731(define_expand "floatsihf2"
4732 [(set (match_operand:HF 0 "general_operand" "")
4733 (float:HF (match_operand:SI 1 "general_operand" "")))]
4734 "TARGET_EITHER"
4735 "
4736 {
4737 rtx op1 = gen_reg_rtx (SFmode);
4738 expand_float (op1, operands[1], 0);
4739 op1 = convert_to_mode (HFmode, op1, 0);
4740 emit_move_insn (operands[0], op1);
4741 DONE;
4742 }"
4743)
4744
4745(define_expand "floatdihf2"
4746 [(set (match_operand:HF 0 "general_operand" "")
4747 (float:HF (match_operand:DI 1 "general_operand" "")))]
4748 "TARGET_EITHER"
4749 "
4750 {
4751 rtx op1 = gen_reg_rtx (SFmode);
4752 expand_float (op1, operands[1], 0);
4753 op1 = convert_to_mode (HFmode, op1, 0);
4754 emit_move_insn (operands[0], op1);
4755 DONE;
4756 }"
4757)
4758
604f3a0a 4759(define_expand "floatsisf2"
4760 [(set (match_operand:SF 0 "s_register_operand" "")
4761 (float:SF (match_operand:SI 1 "s_register_operand" "")))]
25f905c2 4762 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 4763 "
604f3a0a 4764")
4765
604f3a0a 4766(define_expand "floatsidf2"
4767 [(set (match_operand:DF 0 "s_register_operand" "")
4768 (float:DF (match_operand:SI 1 "s_register_operand" "")))]
a50d7267 4769 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 4770 "
604f3a0a 4771")
4772
9b8516be 4773(define_expand "fix_trunchfsi2"
4774 [(set (match_operand:SI 0 "general_operand" "")
4775 (fix:SI (fix:HF (match_operand:HF 1 "general_operand" ""))))]
4776 "TARGET_EITHER"
4777 "
4778 {
4779 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
4780 expand_fix (operands[0], op1, 0);
4781 DONE;
4782 }"
4783)
4784
4785(define_expand "fix_trunchfdi2"
4786 [(set (match_operand:DI 0 "general_operand" "")
4787 (fix:DI (fix:HF (match_operand:HF 1 "general_operand" ""))))]
4788 "TARGET_EITHER"
4789 "
4790 {
4791 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
4792 expand_fix (operands[0], op1, 0);
4793 DONE;
4794 }"
4795)
4796
604f3a0a 4797(define_expand "fix_truncsfsi2"
4798 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 4799 (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" ""))))]
25f905c2 4800 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 4801 "
604f3a0a 4802")
4803
604f3a0a 4804(define_expand "fix_truncdfsi2"
4805 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 4806 (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" ""))))]
a50d7267 4807 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 4808 "
604f3a0a 4809")
4810
f544c6d2 4811;; Truncation insns
b11cae9e 4812
604f3a0a 4813(define_expand "truncdfsf2"
4814 [(set (match_operand:SF 0 "s_register_operand" "")
4815 (float_truncate:SF
4816 (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 4817 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 4818 ""
4819)
9b8516be 4820
4821/* DFmode -> HFmode conversions have to go through SFmode. */
4822(define_expand "truncdfhf2"
4823 [(set (match_operand:HF 0 "general_operand" "")
4824 (float_truncate:HF
4825 (match_operand:DF 1 "general_operand" "")))]
4826 "TARGET_EITHER"
4827 "
4828 {
4829 rtx op1;
4830 op1 = convert_to_mode (SFmode, operands[1], 0);
4831 op1 = convert_to_mode (HFmode, op1, 0);
4832 emit_move_insn (operands[0], op1);
4833 DONE;
4834 }"
4835)
b11cae9e 4836\f
9c08d1fa 4837;; Zero and sign extension instructions.
b11cae9e 4838
848e66ac 4839(define_insn "zero_extend<mode>di2"
6aa689e8 4840 [(set (match_operand:DI 0 "s_register_operand" "=w,r,?r,w")
6d97728e 4841 (zero_extend:DI (match_operand:QHSI 1 "<qhs_zextenddi_op>"
4842 "<qhs_zextenddi_cstr>")))]
848e66ac 4843 "TARGET_32BIT <qhs_zextenddi_cond>"
4844 "#"
6aa689e8 4845 [(set_attr "length" "8,4,8,8")
b6779ddc 4846 (set_attr "arch" "neon_for_64bits,*,*,avoid_neon_for_64bits")
848e66ac 4847 (set_attr "ce_count" "2")
efbb5e19 4848 (set_attr "predicable" "yes")
4849 (set_attr "type" "multiple,mov_reg,multiple,multiple")]
25f905c2 4850)
4851
848e66ac 4852(define_insn "extend<mode>di2"
6aa689e8 4853 [(set (match_operand:DI 0 "s_register_operand" "=w,r,?r,?r,w")
63d204a8 4854 (sign_extend:DI (match_operand:QHSI 1 "<qhs_extenddi_op>"
4855 "<qhs_extenddi_cstr>")))]
848e66ac 4856 "TARGET_32BIT <qhs_sextenddi_cond>"
4857 "#"
6aa689e8 4858 [(set_attr "length" "8,4,8,8,8")
848e66ac 4859 (set_attr "ce_count" "2")
4860 (set_attr "shift" "1")
8012d2c2 4861 (set_attr "predicable" "yes")
1b7da4ac 4862 (set_attr "arch" "neon_for_64bits,*,a,t,avoid_neon_for_64bits")
4863 (set_attr "type" "multiple,mov_reg,multiple,multiple,multiple")]
0d66636f 4864)
9c08d1fa 4865
848e66ac 4866;; Splits for all extensions to DImode
4867(define_split
4868 [(set (match_operand:DI 0 "s_register_operand" "")
4869 (zero_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
6aa689e8 4870 "TARGET_32BIT && reload_completed && !IS_VFP_REGNUM (REGNO (operands[0]))"
848e66ac 4871 [(set (match_dup 0) (match_dup 1))]
4872{
848e66ac 4873 rtx lo_part = gen_lowpart (SImode, operands[0]);
4874 enum machine_mode src_mode = GET_MODE (operands[1]);
4875
4876 if (REG_P (operands[0])
4877 && !reg_overlap_mentioned_p (operands[0], operands[1]))
4878 emit_clobber (operands[0]);
4879 if (!REG_P (lo_part) || src_mode != SImode
4880 || !rtx_equal_p (lo_part, operands[1]))
4881 {
4882 if (src_mode == SImode)
4883 emit_move_insn (lo_part, operands[1]);
4884 else
4885 emit_insn (gen_rtx_SET (VOIDmode, lo_part,
4886 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
4887 operands[1] = lo_part;
4888 }
4889 operands[0] = gen_highpart (SImode, operands[0]);
4890 operands[1] = const0_rtx;
4891})
9c08d1fa 4892
848e66ac 4893(define_split
25f905c2 4894 [(set (match_operand:DI 0 "s_register_operand" "")
848e66ac 4895 (sign_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
6aa689e8 4896 "TARGET_32BIT && reload_completed && !IS_VFP_REGNUM (REGNO (operands[0]))"
848e66ac 4897 [(set (match_dup 0) (ashiftrt:SI (match_dup 1) (const_int 31)))]
4898{
4899 rtx lo_part = gen_lowpart (SImode, operands[0]);
4900 enum machine_mode src_mode = GET_MODE (operands[1]);
25f905c2 4901
848e66ac 4902 if (REG_P (operands[0])
4903 && !reg_overlap_mentioned_p (operands[0], operands[1]))
4904 emit_clobber (operands[0]);
4905
4906 if (!REG_P (lo_part) || src_mode != SImode
4907 || !rtx_equal_p (lo_part, operands[1]))
4908 {
4909 if (src_mode == SImode)
4910 emit_move_insn (lo_part, operands[1]);
4911 else
4912 emit_insn (gen_rtx_SET (VOIDmode, lo_part,
4913 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
4914 operands[1] = lo_part;
4915 }
4916 operands[0] = gen_highpart (SImode, operands[0]);
4917})
9c08d1fa 4918
4919(define_expand "zero_extendhisi2"
ef51b8e1 4920 [(set (match_operand:SI 0 "s_register_operand" "")
4921 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
cffb2a26 4922 "TARGET_EITHER"
ef51b8e1 4923{
4924 if (TARGET_ARM && !arm_arch4 && MEM_P (operands[1]))
f7fbdd4a 4925 {
ef51b8e1 4926 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
4927 DONE;
25f7a26e 4928 }
ef51b8e1 4929 if (!arm_arch6 && !MEM_P (operands[1]))
4930 {
4931 rtx t = gen_lowpart (SImode, operands[1]);
4932 rtx tmp = gen_reg_rtx (SImode);
4933 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
4934 emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (16)));
4935 DONE;
4936 }
4937})
9c08d1fa 4938
ef51b8e1 4939(define_split
b146458f 4940 [(set (match_operand:SI 0 "s_register_operand" "")
4941 (zero_extend:SI (match_operand:HI 1 "s_register_operand" "")))]
ef51b8e1 4942 "!TARGET_THUMB2 && !arm_arch6"
4943 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4944 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 16)))]
4945{
4946 operands[2] = gen_lowpart (SImode, operands[1]);
4947})
4948
cffb2a26 4949(define_insn "*arm_zero_extendhisi2"
ef51b8e1 4950 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4951 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 4952 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 4953 "@
4954 #
4955 ldr%(h%)\\t%0, %1"
d82e788e 4956 [(set_attr "type" "alu_shift_reg,load_byte")
848e66ac 4957 (set_attr "predicable" "yes")]
cffb2a26 4958)
f7fbdd4a 4959
a2cd141b 4960(define_insn "*arm_zero_extendhisi2_v6"
4961 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4962 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
4963 "TARGET_ARM && arm_arch6"
4964 "@
4965 uxth%?\\t%0, %1
25f905c2 4966 ldr%(h%)\\t%0, %1"
65f68e55 4967 [(set_attr "predicable" "yes")
6b6abc9c 4968 (set_attr "type" "extend,load_byte")]
a2cd141b 4969)
4970
4971(define_insn "*arm_zero_extendhisi2addsi"
4972 [(set (match_operand:SI 0 "s_register_operand" "=r")
4973 (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
4974 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4975 "TARGET_INT_SIMD"
a2cd141b 4976 "uxtah%?\\t%0, %2, %1"
d82e788e 4977 [(set_attr "type" "alu_shift_reg")
d952d547 4978 (set_attr "predicable" "yes")
4979 (set_attr "predicable_short_it" "no")]
a2cd141b 4980)
4981
87b22bf7 4982(define_expand "zero_extendqisi2"
cffb2a26 4983 [(set (match_operand:SI 0 "s_register_operand" "")
4984 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
4985 "TARGET_EITHER"
ef51b8e1 4986{
0438d37f 4987 if (TARGET_ARM && !arm_arch6 && !MEM_P (operands[1]))
87b22bf7 4988 {
ef51b8e1 4989 emit_insn (gen_andsi3 (operands[0],
4990 gen_lowpart (SImode, operands[1]),
4991 GEN_INT (255)));
4992 DONE;
4993 }
4994 if (!arm_arch6 && !MEM_P (operands[1]))
4995 {
4996 rtx t = gen_lowpart (SImode, operands[1]);
4997 rtx tmp = gen_reg_rtx (SImode);
4998 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
4999 emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (24)));
5000 DONE;
5001 }
5002})
cffb2a26 5003
ef51b8e1 5004(define_split
b146458f 5005 [(set (match_operand:SI 0 "s_register_operand" "")
5006 (zero_extend:SI (match_operand:QI 1 "s_register_operand" "")))]
ef51b8e1 5007 "!arm_arch6"
5008 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
5009 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 24)))]
5010{
5011 operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
5012 if (TARGET_ARM)
5013 {
5014 emit_insn (gen_andsi3 (operands[0], operands[2], GEN_INT (255)));
87b22bf7 5015 DONE;
5016 }
ef51b8e1 5017})
9c08d1fa 5018
cffb2a26 5019(define_insn "*arm_zero_extendqisi2"
ef51b8e1 5020 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5021 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 5022 "TARGET_ARM && !arm_arch6"
ef51b8e1 5023 "@
5024 #
5025 ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
5026 [(set_attr "length" "8,4")
d82e788e 5027 (set_attr "type" "alu_shift_reg,load_byte")
848e66ac 5028 (set_attr "predicable" "yes")]
cffb2a26 5029)
87b22bf7 5030
a2cd141b 5031(define_insn "*arm_zero_extendqisi2_v6"
5032 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5033 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
5034 "TARGET_ARM && arm_arch6"
5035 "@
25f905c2 5036 uxtb%(%)\\t%0, %1
5037 ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
6b6abc9c 5038 [(set_attr "type" "extend,load_byte")
848e66ac 5039 (set_attr "predicable" "yes")]
a2cd141b 5040)
5041
5042(define_insn "*arm_zero_extendqisi2addsi"
5043 [(set (match_operand:SI 0 "s_register_operand" "=r")
5044 (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
5045 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 5046 "TARGET_INT_SIMD"
a2cd141b 5047 "uxtab%?\\t%0, %2, %1"
5048 [(set_attr "predicable" "yes")
d952d547 5049 (set_attr "predicable_short_it" "no")
d82e788e 5050 (set_attr "type" "alu_shift_reg")]
a2cd141b 5051)
5052
87b22bf7 5053(define_split
5054 [(set (match_operand:SI 0 "s_register_operand" "")
5055 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
5056 (clobber (match_operand:SI 2 "s_register_operand" ""))]
0438d37f 5057 "TARGET_32BIT && (!MEM_P (operands[1])) && ! BYTES_BIG_ENDIAN"
87b22bf7 5058 [(set (match_dup 2) (match_dup 1))
5059 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
cffb2a26 5060 ""
5061)
9c08d1fa 5062
8a4d25d6 5063(define_split
5064 [(set (match_operand:SI 0 "s_register_operand" "")
5065 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 3)))
5066 (clobber (match_operand:SI 2 "s_register_operand" ""))]
0438d37f 5067 "TARGET_32BIT && (!MEM_P (operands[1])) && BYTES_BIG_ENDIAN"
8a4d25d6 5068 [(set (match_dup 2) (match_dup 1))
5069 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
5070 ""
5071)
5072
1c274529 5073
5074(define_split
5075 [(set (match_operand:SI 0 "s_register_operand" "")
5076 (ior_xor:SI (and:SI (ashift:SI
5077 (match_operand:SI 1 "s_register_operand" "")
5078 (match_operand:SI 2 "const_int_operand" ""))
5079 (match_operand:SI 3 "const_int_operand" ""))
5080 (zero_extend:SI
5081 (match_operator 5 "subreg_lowpart_operator"
5082 [(match_operand:SI 4 "s_register_operand" "")]))))]
5083 "TARGET_32BIT
63787642 5084 && ((unsigned HOST_WIDE_INT) INTVAL (operands[3])
1c274529 5085 == (GET_MODE_MASK (GET_MODE (operands[5]))
5086 & (GET_MODE_MASK (GET_MODE (operands[5]))
5087 << (INTVAL (operands[2])))))"
5088 [(set (match_dup 0) (ior_xor:SI (ashift:SI (match_dup 1) (match_dup 2))
5089 (match_dup 4)))
5090 (set (match_dup 0) (zero_extend:SI (match_dup 5)))]
5091 "operands[5] = gen_lowpart (GET_MODE (operands[5]), operands[0]);"
5092)
5093
f7fbdd4a 5094(define_insn "*compareqi_eq0"
bd5b4116 5095 [(set (reg:CC_Z CC_REGNUM)
206ee9a2 5096 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
87b22bf7 5097 (const_int 0)))]
25f905c2 5098 "TARGET_32BIT"
596e5e8f 5099 "tst%?\\t%0, #255"
5100 [(set_attr "conds" "set")
d952d547 5101 (set_attr "predicable" "yes")
1b7da4ac 5102 (set_attr "predicable_short_it" "no")
5103 (set_attr "type" "logic_imm")]
cffb2a26 5104)
b11cae9e 5105
b11cae9e 5106(define_expand "extendhisi2"
ef51b8e1 5107 [(set (match_operand:SI 0 "s_register_operand" "")
5108 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
cffb2a26 5109 "TARGET_EITHER"
ef51b8e1 5110{
5111 if (TARGET_THUMB1)
5112 {
5113 emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1]));
5114 DONE;
5115 }
5116 if (MEM_P (operands[1]) && TARGET_ARM && !arm_arch4)
5117 {
5118 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
5119 DONE;
5120 }
ed29c566 5121
ef51b8e1 5122 if (!arm_arch6 && !MEM_P (operands[1]))
5123 {
5124 rtx t = gen_lowpart (SImode, operands[1]);
5125 rtx tmp = gen_reg_rtx (SImode);
5126 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
5127 emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (16)));
5128 DONE;
5129 }
5130})
cffb2a26 5131
ef51b8e1 5132(define_split
5133 [(parallel
5134 [(set (match_operand:SI 0 "register_operand" "")
5135 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))
5136 (clobber (match_scratch:SI 2 ""))])]
5137 "!arm_arch6"
5138 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
5139 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
5140{
5141 operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
5142})
25f7a26e 5143
25f905c2 5144;; This pattern will only be used when ldsh is not available
25f7a26e 5145(define_expand "extendhisi2_mem"
eab14235 5146 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 5147 (set (match_dup 3)
eab14235 5148 (zero_extend:SI (match_dup 7)))
25f7a26e 5149 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
5150 (set (match_operand:SI 0 "" "")
5151 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
cffb2a26 5152 "TARGET_ARM"
25f7a26e 5153 "
215b30b3 5154 {
5155 rtx mem1, mem2;
5156 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
5157
788fcce0 5158 mem1 = change_address (operands[1], QImode, addr);
29c05e22 5159 mem2 = change_address (operands[1], QImode,
5160 plus_constant (Pmode, addr, 1));
215b30b3 5161 operands[0] = gen_lowpart (SImode, operands[0]);
5162 operands[1] = mem1;
5163 operands[2] = gen_reg_rtx (SImode);
5164 operands[3] = gen_reg_rtx (SImode);
5165 operands[6] = gen_reg_rtx (SImode);
5166 operands[7] = mem2;
25f7a26e 5167
215b30b3 5168 if (BYTES_BIG_ENDIAN)
5169 {
5170 operands[4] = operands[2];
5171 operands[5] = operands[3];
5172 }
5173 else
5174 {
5175 operands[4] = operands[3];
5176 operands[5] = operands[2];
5177 }
5178 }"
5179)
b11cae9e 5180
ef51b8e1 5181(define_split
5182 [(set (match_operand:SI 0 "register_operand" "")
5183 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
5184 "!arm_arch6"
5185 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
5186 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
5187{
5188 operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
5189})
5190
a2cd141b 5191(define_insn "*arm_extendhisi2"
ef51b8e1 5192 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5193 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 5194 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 5195 "@
5196 #
5197 ldr%(sh%)\\t%0, %1"
5198 [(set_attr "length" "8,4")
d82e788e 5199 (set_attr "type" "alu_shift_reg,load_byte")
0d66636f 5200 (set_attr "predicable" "yes")
ef51b8e1 5201 (set_attr "pool_range" "*,256")
5202 (set_attr "neg_pool_range" "*,244")]
cffb2a26 5203)
f7fbdd4a 5204
25f905c2 5205;; ??? Check Thumb-2 pool range
a2cd141b 5206(define_insn "*arm_extendhisi2_v6"
5207 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5208 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
25f905c2 5209 "TARGET_32BIT && arm_arch6"
a2cd141b 5210 "@
5211 sxth%?\\t%0, %1
25f905c2 5212 ldr%(sh%)\\t%0, %1"
6b6abc9c 5213 [(set_attr "type" "extend,load_byte")
a2cd141b 5214 (set_attr "predicable" "yes")
d952d547 5215 (set_attr "predicable_short_it" "no")
a2cd141b 5216 (set_attr "pool_range" "*,256")
5217 (set_attr "neg_pool_range" "*,244")]
5218)
5219
5220(define_insn "*arm_extendhisi2addsi"
5221 [(set (match_operand:SI 0 "s_register_operand" "=r")
5222 (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
5223 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 5224 "TARGET_INT_SIMD"
a2cd141b 5225 "sxtah%?\\t%0, %2, %1"
1b7da4ac 5226 [(set_attr "type" "alu_shift_reg")]
a2cd141b 5227)
5228
c8f69309 5229(define_expand "extendqihi2"
5230 [(set (match_dup 2)
bed7d9a5 5231 (ashift:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")
c8f69309 5232 (const_int 24)))
9c08d1fa 5233 (set (match_operand:HI 0 "s_register_operand" "")
c8f69309 5234 (ashiftrt:SI (match_dup 2)
5235 (const_int 24)))]
cffb2a26 5236 "TARGET_ARM"
c8f69309 5237 "
215b30b3 5238 {
0438d37f 5239 if (arm_arch4 && MEM_P (operands[1]))
215b30b3 5240 {
5241 emit_insn (gen_rtx_SET (VOIDmode,
5242 operands[0],
5243 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
5244 DONE;
5245 }
5246 if (!s_register_operand (operands[1], QImode))
5247 operands[1] = copy_to_mode_reg (QImode, operands[1]);
5248 operands[0] = gen_lowpart (SImode, operands[0]);
5249 operands[1] = gen_lowpart (SImode, operands[1]);
5250 operands[2] = gen_reg_rtx (SImode);
5251 }"
5252)
f7fbdd4a 5253
25f905c2 5254(define_insn "*arm_extendqihi_insn"
b4e8a300 5255 [(set (match_operand:HI 0 "s_register_operand" "=r")
bed7d9a5 5256 (sign_extend:HI (match_operand:QI 1 "arm_extendqisi_mem_op" "Uq")))]
cffb2a26 5257 "TARGET_ARM && arm_arch4"
25f905c2 5258 "ldr%(sb%)\\t%0, %1"
a2cd141b 5259 [(set_attr "type" "load_byte")
0d66636f 5260 (set_attr "predicable" "yes")
cffb2a26 5261 (set_attr "pool_range" "256")
5262 (set_attr "neg_pool_range" "244")]
5263)
3fc2009e 5264
b11cae9e 5265(define_expand "extendqisi2"
ef51b8e1 5266 [(set (match_operand:SI 0 "s_register_operand" "")
5267 (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")))]
cffb2a26 5268 "TARGET_EITHER"
ef51b8e1 5269{
5270 if (!arm_arch4 && MEM_P (operands[1]))
5271 operands[1] = copy_to_mode_reg (QImode, operands[1]);
a2cd141b 5272
ef51b8e1 5273 if (!arm_arch6 && !MEM_P (operands[1]))
5274 {
5275 rtx t = gen_lowpart (SImode, operands[1]);
5276 rtx tmp = gen_reg_rtx (SImode);
5277 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
5278 emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (24)));
5279 DONE;
5280 }
5281})
a2cd141b 5282
ef51b8e1 5283(define_split
5284 [(set (match_operand:SI 0 "register_operand" "")
5285 (sign_extend:SI (match_operand:QI 1 "register_operand" "")))]
5286 "!arm_arch6"
5287 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
5288 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))]
5289{
5290 operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
5291})
f7fbdd4a 5292
a2cd141b 5293(define_insn "*arm_extendqisi"
ef51b8e1 5294 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5295 (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
a2cd141b 5296 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 5297 "@
5298 #
5299 ldr%(sb%)\\t%0, %1"
5300 [(set_attr "length" "8,4")
d82e788e 5301 (set_attr "type" "alu_shift_reg,load_byte")
0d66636f 5302 (set_attr "predicable" "yes")
ef51b8e1 5303 (set_attr "pool_range" "*,256")
5304 (set_attr "neg_pool_range" "*,244")]
cffb2a26 5305)
3fc2009e 5306
a2cd141b 5307(define_insn "*arm_extendqisi_v6"
5308 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
bed7d9a5 5309 (sign_extend:SI
5310 (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
a2cd141b 5311 "TARGET_ARM && arm_arch6"
b4e8a300 5312 "@
5313 sxtb%?\\t%0, %1
25f905c2 5314 ldr%(sb%)\\t%0, %1"
6b6abc9c 5315 [(set_attr "type" "extend,load_byte")
a2cd141b 5316 (set_attr "predicable" "yes")
a2cd141b 5317 (set_attr "pool_range" "*,256")
5318 (set_attr "neg_pool_range" "*,244")]
5319)
5320
5321(define_insn "*arm_extendqisi2addsi"
5322 [(set (match_operand:SI 0 "s_register_operand" "=r")
5323 (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
5324 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 5325 "TARGET_INT_SIMD"
a2cd141b 5326 "sxtab%?\\t%0, %2, %1"
d82e788e 5327 [(set_attr "type" "alu_shift_reg")
d952d547 5328 (set_attr "predicable" "yes")
5329 (set_attr "predicable_short_it" "no")]
a2cd141b 5330)
5331
caedf871 5332(define_expand "extendsfdf2"
5333 [(set (match_operand:DF 0 "s_register_operand" "")
5334 (float_extend:DF (match_operand:SF 1 "s_register_operand" "")))]
a50d7267 5335 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
caedf871 5336 ""
5337)
9b8516be 5338
5339/* HFmode -> DFmode conversions have to go through SFmode. */
5340(define_expand "extendhfdf2"
5341 [(set (match_operand:DF 0 "general_operand" "")
5342 (float_extend:DF (match_operand:HF 1 "general_operand" "")))]
5343 "TARGET_EITHER"
5344 "
5345 {
5346 rtx op1;
5347 op1 = convert_to_mode (SFmode, operands[1], 0);
5348 op1 = convert_to_mode (DFmode, op1, 0);
5349 emit_insn (gen_movdf (operands[0], op1));
5350 DONE;
5351 }"
5352)
b11cae9e 5353\f
5354;; Move insns (including loads and stores)
5355
5356;; XXX Just some ideas about movti.
9c08d1fa 5357;; I don't think these are a good idea on the arm, there just aren't enough
5358;; registers
b11cae9e 5359;;(define_expand "loadti"
9c08d1fa 5360;; [(set (match_operand:TI 0 "s_register_operand" "")
b11cae9e 5361;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
5362;; "" "")
5363
5364;;(define_expand "storeti"
5365;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
9c08d1fa 5366;; (match_operand:TI 1 "s_register_operand" ""))]
b11cae9e 5367;; "" "")
5368
5369;;(define_expand "movti"
5370;; [(set (match_operand:TI 0 "general_operand" "")
5371;; (match_operand:TI 1 "general_operand" ""))]
5372;; ""
5373;; "
5374;;{
5375;; rtx insn;
5376;;
0438d37f 5377;; if (MEM_P (operands[0]) && MEM_P (operands[1]))
b11cae9e 5378;; operands[1] = copy_to_reg (operands[1]);
0438d37f 5379;; if (MEM_P (operands[0]))
b11cae9e 5380;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
0438d37f 5381;; else if (MEM_P (operands[1]))
b11cae9e 5382;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
5383;; else
5384;; FAIL;
5385;;
5386;; emit_insn (insn);
5387;; DONE;
5388;;}")
5389
a2f10574 5390;; Recognize garbage generated above.
b11cae9e 5391
5392;;(define_insn ""
5393;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
5394;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
5395;; ""
5396;; "*
5397;; {
5398;; register mem = (which_alternative < 3);
0d66636f 5399;; register const char *template;
b11cae9e 5400;;
5401;; operands[mem] = XEXP (operands[mem], 0);
5402;; switch (which_alternative)
5403;; {
5404;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
5405;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
5406;; case 2: template = \"ldmia\\t%1, %M0\"; break;
5407;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
5408;; case 4: template = \"stmia\\t%0!, %M1\"; break;
5409;; case 5: template = \"stmia\\t%0, %M1\"; break;
5410;; }
e2348bcb 5411;; output_asm_insn (template, operands);
5412;; return \"\";
b11cae9e 5413;; }")
5414
cffb2a26 5415(define_expand "movdi"
5416 [(set (match_operand:DI 0 "general_operand" "")
5417 (match_operand:DI 1 "general_operand" ""))]
5418 "TARGET_EITHER"
5419 "
e1ba4a27 5420 if (can_create_pseudo_p ())
cffb2a26 5421 {
0438d37f 5422 if (!REG_P (operands[0]))
b2778788 5423 operands[1] = force_reg (DImode, operands[1]);
cffb2a26 5424 }
5425 "
5426)
b11cae9e 5427
cffb2a26 5428(define_insn "*arm_movdi"
353cf59a 5429 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, q, m")
5430 (match_operand:DI 1 "di_operand" "rDa,Db,Dc,mi,q"))]
cde1623a 5431 "TARGET_32BIT
b805622c 5432 && !(TARGET_HARD_FLOAT && TARGET_VFP)
b2778788 5433 && !TARGET_IWMMXT
5434 && ( register_operand (operands[0], DImode)
5435 || register_operand (operands[1], DImode))"
b11cae9e 5436 "*
d51f92df 5437 switch (which_alternative)
5438 {
5439 case 0:
5440 case 1:
5441 case 2:
5442 return \"#\";
5443 default:
26ff80c0 5444 return output_move_double (operands, true, NULL);
d51f92df 5445 }
cffb2a26 5446 "
359a6e9f 5447 [(set_attr "length" "8,12,16,8,8")
1b7da4ac 5448 (set_attr "type" "multiple,multiple,multiple,load2,store2")
cde1623a 5449 (set_attr "arm_pool_range" "*,*,*,1020,*")
8848d797 5450 (set_attr "arm_neg_pool_range" "*,*,*,1004,*")
42e1de19 5451 (set_attr "thumb2_pool_range" "*,*,*,4094,*")
cde1623a 5452 (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
cffb2a26 5453)
5454
d51f92df 5455(define_split
5456 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
e6dd3afa 5457 (match_operand:ANY64 1 "immediate_operand" ""))]
25f905c2 5458 "TARGET_32BIT
d51f92df 5459 && reload_completed
5460 && (arm_const_double_inline_cost (operands[1])
861033d5 5461 <= arm_max_const_double_inline_cost ())"
d51f92df 5462 [(const_int 0)]
5463 "
5464 arm_split_constant (SET, SImode, curr_insn,
5465 INTVAL (gen_lowpart (SImode, operands[1])),
5466 gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
5467 arm_split_constant (SET, SImode, curr_insn,
5468 INTVAL (gen_highpart_mode (SImode,
5469 GET_MODE (operands[0]),
5470 operands[1])),
5471 gen_highpart (SImode, operands[0]), NULL_RTX, 0);
5472 DONE;
5473 "
5474)
5475
e5ba9289 5476; If optimizing for size, or if we have load delay slots, then
5477; we want to split the constant into two separate operations.
5478; In both cases this may split a trivial part into a single data op
5479; leaving a single complex constant to load. We can also get longer
5480; offsets in a LDR which means we get better chances of sharing the pool
5481; entries. Finally, we can normally do a better job of scheduling
5482; LDR instructions than we can with LDM.
5483; This pattern will only match if the one above did not.
5484(define_split
5485 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
5486 (match_operand:ANY64 1 "const_double_operand" ""))]
5487 "TARGET_ARM && reload_completed
5488 && arm_const_double_by_parts (operands[1])"
5489 [(set (match_dup 0) (match_dup 1))
5490 (set (match_dup 2) (match_dup 3))]
5491 "
5492 operands[2] = gen_highpart (SImode, operands[0]);
5493 operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
5494 operands[1]);
5495 operands[0] = gen_lowpart (SImode, operands[0]);
5496 operands[1] = gen_lowpart (SImode, operands[1]);
5497 "
5498)
5499
d51f92df 5500(define_split
5501 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
5502 (match_operand:ANY64 1 "arm_general_register_operand" ""))]
5503 "TARGET_EITHER && reload_completed"
5504 [(set (match_dup 0) (match_dup 1))
5505 (set (match_dup 2) (match_dup 3))]
5506 "
5507 operands[2] = gen_highpart (SImode, operands[0]);
5508 operands[3] = gen_highpart (SImode, operands[1]);
5509 operands[0] = gen_lowpart (SImode, operands[0]);
5510 operands[1] = gen_lowpart (SImode, operands[1]);
5511
5512 /* Handle a partial overlap. */
5513 if (rtx_equal_p (operands[0], operands[3]))
5514 {
5515 rtx tmp0 = operands[0];
5516 rtx tmp1 = operands[1];
5517
5518 operands[0] = operands[2];
5519 operands[1] = operands[3];
5520 operands[2] = tmp0;
5521 operands[3] = tmp1;
5522 }
5523 "
5524)
5525
a8a3b539 5526;; We can't actually do base+index doubleword loads if the index and
5527;; destination overlap. Split here so that we at least have chance to
5528;; schedule.
5529(define_split
5530 [(set (match_operand:DI 0 "s_register_operand" "")
5531 (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
5532 (match_operand:SI 2 "s_register_operand" ""))))]
5533 "TARGET_LDRD
5534 && reg_overlap_mentioned_p (operands[0], operands[1])
5535 && reg_overlap_mentioned_p (operands[0], operands[2])"
5536 [(set (match_dup 4)
5537 (plus:SI (match_dup 1)
5538 (match_dup 2)))
5539 (set (match_dup 0)
5540 (mem:DI (match_dup 4)))]
5541 "
5542 operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
5543 "
5544)
5545
9c08d1fa 5546(define_expand "movsi"
5547 [(set (match_operand:SI 0 "general_operand" "")
5548 (match_operand:SI 1 "general_operand" ""))]
cffb2a26 5549 "TARGET_EITHER"
9c08d1fa 5550 "
befb0bac 5551 {
e348ff3e 5552 rtx base, offset, tmp;
5553
25f905c2 5554 if (TARGET_32BIT)
9c08d1fa 5555 {
674a8f0b 5556 /* Everything except mem = const or mem = mem can be done easily. */
0438d37f 5557 if (MEM_P (operands[0]))
cffb2a26 5558 operands[1] = force_reg (SImode, operands[1]);
a2cd141b 5559 if (arm_general_register_operand (operands[0], SImode)
0438d37f 5560 && CONST_INT_P (operands[1])
cffb2a26 5561 && !(const_ok_for_arm (INTVAL (operands[1]))
5562 || const_ok_for_arm (~INTVAL (operands[1]))))
5563 {
96f57e36 5564 arm_split_constant (SET, SImode, NULL_RTX,
5565 INTVAL (operands[1]), operands[0], NULL_RTX,
e1ba4a27 5566 optimize && can_create_pseudo_p ());
cffb2a26 5567 DONE;
5568 }
5569 }
25f905c2 5570 else /* TARGET_THUMB1... */
cffb2a26 5571 {
e1ba4a27 5572 if (can_create_pseudo_p ())
cffb2a26 5573 {
0438d37f 5574 if (!REG_P (operands[0]))
cffb2a26 5575 operands[1] = force_reg (SImode, operands[1]);
5576 }
9c08d1fa 5577 }
f655717d 5578
e348ff3e 5579 if (ARM_OFFSETS_MUST_BE_WITHIN_SECTIONS_P)
5580 {
5581 split_const (operands[1], &base, &offset);
5582 if (GET_CODE (base) == SYMBOL_REF
5583 && !offset_within_block_p (base, INTVAL (offset)))
5584 {
b308ddcf 5585 tmp = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
e348ff3e 5586 emit_move_insn (tmp, base);
5587 emit_insn (gen_addsi3 (operands[0], tmp, offset));
5588 DONE;
5589 }
5590 }
5591
f655717d 5592 /* Recognize the case where operand[1] is a reference to thread-local
5593 data and load its address to a register. */
5594 if (arm_tls_referenced_p (operands[1]))
5595 {
5596 rtx tmp = operands[1];
5597 rtx addend = NULL;
5598
5599 if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
5600 {
5601 addend = XEXP (XEXP (tmp, 0), 1);
5602 tmp = XEXP (XEXP (tmp, 0), 0);
5603 }
5604
5605 gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
5606 gcc_assert (SYMBOL_REF_TLS_MODEL (tmp) != 0);
5607
e1ba4a27 5608 tmp = legitimize_tls_address (tmp,
5609 !can_create_pseudo_p () ? operands[0] : 0);
f655717d 5610 if (addend)
5611 {
5612 tmp = gen_rtx_PLUS (SImode, tmp, addend);
5613 tmp = force_operand (tmp, operands[0]);
5614 }
5615 operands[1] = tmp;
5616 }
5617 else if (flag_pic
5618 && (CONSTANT_P (operands[1])
5619 || symbol_mentioned_p (operands[1])
5620 || label_mentioned_p (operands[1])))
5621 operands[1] = legitimize_pic_address (operands[1], SImode,
e1ba4a27 5622 (!can_create_pseudo_p ()
5623 ? operands[0]
5624 : 0));
befb0bac 5625 }
215b30b3 5626 "
5627)
9c08d1fa 5628
d0e6a121 5629;; The ARM LO_SUM and HIGH are backwards - HIGH sets the low bits, and
5630;; LO_SUM adds in the high bits. Fortunately these are opaque operations
5631;; so this does not matter.
5632(define_insn "*arm_movt"
5633 [(set (match_operand:SI 0 "nonimmediate_operand" "=r")
5634 (lo_sum:SI (match_operand:SI 1 "nonimmediate_operand" "0")
5635 (match_operand:SI 2 "general_operand" "i")))]
c9b2ce40 5636 "arm_arch_thumb2"
d0e6a121 5637 "movt%?\t%0, #:upper16:%c2"
5638 [(set_attr "predicable" "yes")
d952d547 5639 (set_attr "predicable_short_it" "no")
1b7da4ac 5640 (set_attr "length" "4")
5641 (set_attr "type" "mov_imm")]
d0e6a121 5642)
5643
cffb2a26 5644(define_insn "*arm_movsi_insn"
aaa37ad6 5645 [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,rk,m")
110eae03 5646 (match_operand:SI 1 "general_operand" "rk, I,K,j,mi,rk"))]
755eb2b4 5647 "TARGET_ARM && ! TARGET_IWMMXT
a2cd141b 5648 && !(TARGET_HARD_FLOAT && TARGET_VFP)
cffb2a26 5649 && ( register_operand (operands[0], SImode)
5650 || register_operand (operands[1], SImode))"
f7fbdd4a 5651 "@
aaa37ad6 5652 mov%?\\t%0, %1
f7fbdd4a 5653 mov%?\\t%0, %1
5654 mvn%?\\t%0, #%B1
25f905c2 5655 movw%?\\t%0, %1
f7fbdd4a 5656 ldr%?\\t%0, %1
5657 str%?\\t%1, %0"
1aed5204 5658 [(set_attr "type" "mov_reg,mov_imm,mvn_imm,mov_imm,load1,store1")
0d66636f 5659 (set_attr "predicable" "yes")
aaa37ad6 5660 (set_attr "pool_range" "*,*,*,*,4096,*")
5661 (set_attr "neg_pool_range" "*,*,*,*,4084,*")]
cffb2a26 5662)
87b22bf7 5663
5664(define_split
a2cd141b 5665 [(set (match_operand:SI 0 "arm_general_register_operand" "")
87b22bf7 5666 (match_operand:SI 1 "const_int_operand" ""))]
25f905c2 5667 "TARGET_32BIT
215b30b3 5668 && (!(const_ok_for_arm (INTVAL (operands[1]))
5669 || const_ok_for_arm (~INTVAL (operands[1]))))"
87b22bf7 5670 [(clobber (const_int 0))]
5671 "
96f57e36 5672 arm_split_constant (SET, SImode, NULL_RTX,
5673 INTVAL (operands[1]), operands[0], NULL_RTX, 0);
87b22bf7 5674 DONE;
215b30b3 5675 "
5676)
9c08d1fa 5677
861033d5 5678;; A normal way to do (symbol + offset) requires three instructions at least
5679;; (depends on how big the offset is) as below:
5680;; movw r0, #:lower16:g
5681;; movw r0, #:upper16:g
5682;; adds r0, #4
5683;;
5684;; A better way would be:
5685;; movw r0, #:lower16:g+4
5686;; movw r0, #:upper16:g+4
5687;;
5688;; The limitation of this way is that the length of offset should be a 16-bit
5689;; signed value, because current assembler only supports REL type relocation for
5690;; such case. If the more powerful RELA type is supported in future, we should
5691;; update this pattern to go with better way.
5692(define_split
5693 [(set (match_operand:SI 0 "arm_general_register_operand" "")
5694 (const:SI (plus:SI (match_operand:SI 1 "general_operand" "")
5695 (match_operand:SI 2 "const_int_operand" ""))))]
5696 "TARGET_THUMB2
5697 && arm_disable_literal_pool
5698 && reload_completed
5699 && GET_CODE (operands[1]) == SYMBOL_REF"
5700 [(clobber (const_int 0))]
5701 "
5702 int offset = INTVAL (operands[2]);
5703
5704 if (offset < -0x8000 || offset > 0x7fff)
5705 {
5706 arm_emit_movpair (operands[0], operands[1]);
5707 emit_insn (gen_rtx_SET (SImode, operands[0],
5708 gen_rtx_PLUS (SImode, operands[0], operands[2])));
5709 }
5710 else
5711 {
5712 rtx op = gen_rtx_CONST (SImode,
5713 gen_rtx_PLUS (SImode, operands[1], operands[2]));
5714 arm_emit_movpair (operands[0], op);
5715 }
5716 "
5717)
5718
b8d5d078 5719;; Split symbol_refs at the later stage (after cprop), instead of generating
5720;; movt/movw pair directly at expand. Otherwise corresponding high_sum
5721;; and lo_sum would be merged back into memory load at cprop. However,
5722;; if the default is to prefer movt/movw rather than a load from the constant
5723;; pool, the performance is better.
5724(define_split
5725 [(set (match_operand:SI 0 "arm_general_register_operand" "")
5726 (match_operand:SI 1 "general_operand" ""))]
5727 "TARGET_32BIT
5728 && TARGET_USE_MOVT && GET_CODE (operands[1]) == SYMBOL_REF
5729 && !flag_pic && !target_word_relocations
5730 && !arm_tls_referenced_p (operands[1])"
5731 [(clobber (const_int 0))]
5732{
5733 arm_emit_movpair (operands[0], operands[1]);
5734 DONE;
5735})
5736
bc360af8 5737;; When generating pic, we need to load the symbol offset into a register.
5738;; So that the optimizer does not confuse this with a normal symbol load
5739;; we use an unspec. The offset will be loaded from a constant pool entry,
5740;; since that is the only type of relocation we can use.
cffb2a26 5741
bc360af8 5742;; Wrap calculation of the whole PIC address in a single pattern for the
5743;; benefit of optimizers, particularly, PRE and HOIST. Calculation of
5744;; a PIC address involves two loads from memory, so we want to CSE it
5745;; as often as possible.
5746;; This pattern will be split into one of the pic_load_addr_* patterns
5747;; and a move after GCSE optimizations.
5748;;
5749;; Note: Update arm.c: legitimize_pic_address() when changing this pattern.
5750(define_expand "calculate_pic_address"
94f8caca 5751 [(set (match_operand:SI 0 "register_operand" "")
5752 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "")
5753 (unspec:SI [(match_operand:SI 2 "" "")]
5754 UNSPEC_PIC_SYM))))]
5755 "flag_pic"
5756)
5757
5758;; Split calculate_pic_address into pic_load_addr_* and a move.
5759(define_split
5760 [(set (match_operand:SI 0 "register_operand" "")
5761 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "")
5762 (unspec:SI [(match_operand:SI 2 "" "")]
5763 UNSPEC_PIC_SYM))))]
5764 "flag_pic"
5765 [(set (match_dup 3) (unspec:SI [(match_dup 2)] UNSPEC_PIC_SYM))
5766 (set (match_dup 0) (mem:SI (plus:SI (match_dup 1) (match_dup 3))))]
5767 "operands[3] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];"
5768)
5769
350ccca5 5770;; operand1 is the memory address to go into
5771;; pic_load_addr_32bit.
5772;; operand2 is the PIC label to be emitted
5773;; from pic_add_dot_plus_eight.
5774;; We do this to allow hoisting of the entire insn.
5775(define_insn_and_split "pic_load_addr_unified"
5776 [(set (match_operand:SI 0 "s_register_operand" "=r,r,l")
5777 (unspec:SI [(match_operand:SI 1 "" "mX,mX,mX")
5778 (match_operand:SI 2 "" "")]
5779 UNSPEC_PIC_UNIFIED))]
5780 "flag_pic"
5781 "#"
5782 "&& reload_completed"
5783 [(set (match_dup 0) (unspec:SI [(match_dup 1)] UNSPEC_PIC_SYM))
5784 (set (match_dup 0) (unspec:SI [(match_dup 0) (match_dup 3)
5785 (match_dup 2)] UNSPEC_PIC_BASE))]
5786 "operands[3] = TARGET_THUMB ? GEN_INT (4) : GEN_INT (8);"
5787 [(set_attr "type" "load1,load1,load1")
42e1de19 5788 (set_attr "pool_range" "4096,4094,1022")
350ccca5 5789 (set_attr "neg_pool_range" "4084,0,0")
5790 (set_attr "arch" "a,t2,t1")
5791 (set_attr "length" "8,6,4")]
5792)
5793
67336bcf 5794;; The rather odd constraints on the following are to force reload to leave
5795;; the insn alone, and to force the minipool generation pass to then move
5796;; the GOT symbol to memory.
849170fd 5797
b3cd5f55 5798(define_insn "pic_load_addr_32bit"
849170fd 5799 [(set (match_operand:SI 0 "s_register_operand" "=r")
e1159bbe 5800 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
b3cd5f55 5801 "TARGET_32BIT && flag_pic"
67336bcf 5802 "ldr%?\\t%0, %1"
a2cd141b 5803 [(set_attr "type" "load1")
42e1de19 5804 (set (attr "pool_range")
5805 (if_then_else (eq_attr "is_thumb" "no")
5806 (const_int 4096)
5807 (const_int 4094)))
b3cd5f55 5808 (set (attr "neg_pool_range")
5809 (if_then_else (eq_attr "is_thumb" "no")
5810 (const_int 4084)
5811 (const_int 0)))]
8c4d8060 5812)
5813
25f905c2 5814(define_insn "pic_load_addr_thumb1"
8c4d8060 5815 [(set (match_operand:SI 0 "s_register_operand" "=l")
e1159bbe 5816 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
25f905c2 5817 "TARGET_THUMB1 && flag_pic"
8c4d8060 5818 "ldr\\t%0, %1"
a2cd141b 5819 [(set_attr "type" "load1")
42e1de19 5820 (set (attr "pool_range") (const_int 1018))]
cffb2a26 5821)
849170fd 5822
cffb2a26 5823(define_insn "pic_add_dot_plus_four"
15d5d060 5824 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5825 (unspec:SI [(match_operand:SI 1 "register_operand" "0")
5826 (const_int 4)
beef0fb5 5827 (match_operand 2 "" "")]
5828 UNSPEC_PIC_BASE))]
b3cd5f55 5829 "TARGET_THUMB"
cffb2a26 5830 "*
6cdcb15c 5831 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5832 INTVAL (operands[2]));
cffb2a26 5833 return \"add\\t%0, %|pc\";
5834 "
1b7da4ac 5835 [(set_attr "length" "2")
5836 (set_attr "type" "alu_reg")]
cffb2a26 5837)
849170fd 5838
5839(define_insn "pic_add_dot_plus_eight"
15d5d060 5840 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5841 (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5842 (const_int 8)
beef0fb5 5843 (match_operand 2 "" "")]
5844 UNSPEC_PIC_BASE))]
f655717d 5845 "TARGET_ARM"
c4034607 5846 "*
6cdcb15c 5847 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5848 INTVAL (operands[2]));
15d5d060 5849 return \"add%?\\t%0, %|pc, %1\";
cffb2a26 5850 "
1b7da4ac 5851 [(set_attr "predicable" "yes")
5852 (set_attr "type" "alu_reg")]
cffb2a26 5853)
849170fd 5854
f655717d 5855(define_insn "tls_load_dot_plus_eight"
cc071db6 5856 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5857 (mem:SI (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5858 (const_int 8)
beef0fb5 5859 (match_operand 2 "" "")]
5860 UNSPEC_PIC_BASE)))]
f655717d 5861 "TARGET_ARM"
5862 "*
6cdcb15c 5863 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5864 INTVAL (operands[2]));
f655717d 5865 return \"ldr%?\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_eight\";
5866 "
1b7da4ac 5867 [(set_attr "predicable" "yes")
5868 (set_attr "type" "load1")]
f655717d 5869)
5870
5871;; PIC references to local variables can generate pic_add_dot_plus_eight
5872;; followed by a load. These sequences can be crunched down to
5873;; tls_load_dot_plus_eight by a peephole.
5874
5875(define_peephole2
c0c1fba5 5876 [(set (match_operand:SI 0 "register_operand" "")
5877 (unspec:SI [(match_operand:SI 3 "register_operand" "")
5878 (const_int 8)
5879 (match_operand 1 "" "")]
5880 UNSPEC_PIC_BASE))
2d05dfad 5881 (set (match_operand:SI 2 "arm_general_register_operand" "")
5882 (mem:SI (match_dup 0)))]
f655717d 5883 "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
c0c1fba5 5884 [(set (match_dup 2)
5885 (mem:SI (unspec:SI [(match_dup 3)
5886 (const_int 8)
5887 (match_dup 1)]
5888 UNSPEC_PIC_BASE)))]
f655717d 5889 ""
5890)
5891
bac7fc85 5892(define_insn "pic_offset_arm"
5893 [(set (match_operand:SI 0 "register_operand" "=r")
5894 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
5895 (unspec:SI [(match_operand:SI 2 "" "X")]
5896 UNSPEC_PIC_OFFSET))))]
5897 "TARGET_VXWORKS_RTP && TARGET_ARM && flag_pic"
5898 "ldr%?\\t%0, [%1,%2]"
5899 [(set_attr "type" "load1")]
5900)
5901
95373f08 5902(define_expand "builtin_setjmp_receiver"
5903 [(label_ref (match_operand 0 "" ""))]
5904 "flag_pic"
5905 "
5906{
b935b306 5907 /* r3 is clobbered by set/longjmp, so we can use it as a scratch
5908 register. */
2cb7d577 5909 if (arm_pic_register != INVALID_REGNUM)
5910 arm_load_pic_register (1UL << 3);
95373f08 5911 DONE;
5912}")
5913
9c08d1fa 5914;; If copying one reg to another we can set the condition codes according to
5915;; its value. Such a move is common after a return from subroutine and the
5916;; result is being tested against zero.
5917
f7fbdd4a 5918(define_insn "*movsi_compare0"
bd5b4116 5919 [(set (reg:CC CC_REGNUM)
cffb2a26 5920 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
5921 (const_int 0)))
5922 (set (match_operand:SI 0 "s_register_operand" "=r,r")
5923 (match_dup 1))]
25f905c2 5924 "TARGET_32BIT"
e2348bcb 5925 "@
40dbec34 5926 cmp%?\\t%0, #0
25f905c2 5927 sub%.\\t%0, %1, #0"
65f68e55 5928 [(set_attr "conds" "set")
d82e788e 5929 (set_attr "type" "alus_imm,alus_imm")]
cffb2a26 5930)
b11cae9e 5931
b11cae9e 5932;; Subroutine to store a half word from a register into memory.
5933;; Operand 0 is the source register (HImode)
c8f69309 5934;; Operand 1 is the destination address in a register (SImode)
b11cae9e 5935
9c08d1fa 5936;; In both this routine and the next, we must be careful not to spill
01cc3b75 5937;; a memory address of reg+large_const into a separate PLUS insn, since this
9c08d1fa 5938;; can generate unrecognizable rtl.
5939
b11cae9e 5940(define_expand "storehi"
c8f69309 5941 [;; store the low byte
f082f1c4 5942 (set (match_operand 1 "" "") (match_dup 3))
b11cae9e 5943 ;; extract the high byte
c8f69309 5944 (set (match_dup 2)
5945 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
b11cae9e 5946 ;; store the high byte
787f8210 5947 (set (match_dup 4) (match_dup 5))]
cffb2a26 5948 "TARGET_ARM"
b11cae9e 5949 "
215b30b3 5950 {
537ffcfc 5951 rtx op1 = operands[1];
5952 rtx addr = XEXP (op1, 0);
215b30b3 5953 enum rtx_code code = GET_CODE (addr);
5954
0438d37f 5955 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
215b30b3 5956 || code == MINUS)
537ffcfc 5957 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
215b30b3 5958
537ffcfc 5959 operands[4] = adjust_address (op1, QImode, 1);
e513d163 5960 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 5961 operands[3] = gen_lowpart (QImode, operands[0]);
5962 operands[0] = gen_lowpart (SImode, operands[0]);
787f8210 5963 operands[2] = gen_reg_rtx (SImode);
5964 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 5965 }"
5966)
b11cae9e 5967
c7597b5d 5968(define_expand "storehi_bigend"
f082f1c4 5969 [(set (match_dup 4) (match_dup 3))
c7597b5d 5970 (set (match_dup 2)
5971 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
787f8210 5972 (set (match_operand 1 "" "") (match_dup 5))]
cffb2a26 5973 "TARGET_ARM"
b11cae9e 5974 "
215b30b3 5975 {
537ffcfc 5976 rtx op1 = operands[1];
5977 rtx addr = XEXP (op1, 0);
215b30b3 5978 enum rtx_code code = GET_CODE (addr);
5979
0438d37f 5980 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
215b30b3 5981 || code == MINUS)
537ffcfc 5982 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
215b30b3 5983
537ffcfc 5984 operands[4] = adjust_address (op1, QImode, 1);
e513d163 5985 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 5986 operands[3] = gen_lowpart (QImode, operands[0]);
5987 operands[0] = gen_lowpart (SImode, operands[0]);
5988 operands[2] = gen_reg_rtx (SImode);
787f8210 5989 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 5990 }"
5991)
c7597b5d 5992
5993;; Subroutine to store a half word integer constant into memory.
5994(define_expand "storeinthi"
f082f1c4 5995 [(set (match_operand 0 "" "")
787f8210 5996 (match_operand 1 "" ""))
9e8503e6 5997 (set (match_dup 3) (match_dup 2))]
cffb2a26 5998 "TARGET_ARM"
c7597b5d 5999 "
215b30b3 6000 {
6001 HOST_WIDE_INT value = INTVAL (operands[1]);
6002 rtx addr = XEXP (operands[0], 0);
537ffcfc 6003 rtx op0 = operands[0];
215b30b3 6004 enum rtx_code code = GET_CODE (addr);
c7597b5d 6005
0438d37f 6006 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
215b30b3 6007 || code == MINUS)
537ffcfc 6008 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
c7597b5d 6009
215b30b3 6010 operands[1] = gen_reg_rtx (SImode);
6011 if (BYTES_BIG_ENDIAN)
6012 {
6013 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
6014 if ((value & 255) == ((value >> 8) & 255))
6015 operands[2] = operands[1];
6016 else
6017 {
6018 operands[2] = gen_reg_rtx (SImode);
6019 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
6020 }
6021 }
6022 else
6023 {
6024 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
6025 if ((value & 255) == ((value >> 8) & 255))
6026 operands[2] = operands[1];
6027 else
6028 {
6029 operands[2] = gen_reg_rtx (SImode);
6030 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
6031 }
6032 }
c7597b5d 6033
537ffcfc 6034 operands[3] = adjust_address (op0, QImode, 1);
e513d163 6035 operands[0] = adjust_address (operands[0], QImode, 0);
9e8503e6 6036 operands[2] = gen_lowpart (QImode, operands[2]);
787f8210 6037 operands[1] = gen_lowpart (QImode, operands[1]);
215b30b3 6038 }"
6039)
b11cae9e 6040
f7fbdd4a 6041(define_expand "storehi_single_op"
6042 [(set (match_operand:HI 0 "memory_operand" "")
6043 (match_operand:HI 1 "general_operand" ""))]
25f905c2 6044 "TARGET_32BIT && arm_arch4"
f7fbdd4a 6045 "
215b30b3 6046 if (!s_register_operand (operands[1], HImode))
f7fbdd4a 6047 operands[1] = copy_to_mode_reg (HImode, operands[1]);
215b30b3 6048 "
6049)
f7fbdd4a 6050
b11cae9e 6051(define_expand "movhi"
6052 [(set (match_operand:HI 0 "general_operand" "")
c8f69309 6053 (match_operand:HI 1 "general_operand" ""))]
cffb2a26 6054 "TARGET_EITHER"
b11cae9e 6055 "
cffb2a26 6056 if (TARGET_ARM)
b11cae9e 6057 {
e1ba4a27 6058 if (can_create_pseudo_p ())
cffb2a26 6059 {
0438d37f 6060 if (MEM_P (operands[0]))
b11cae9e 6061 {
cffb2a26 6062 if (arm_arch4)
6063 {
6064 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
6065 DONE;
6066 }
0438d37f 6067 if (CONST_INT_P (operands[1]))
cffb2a26 6068 emit_insn (gen_storeinthi (operands[0], operands[1]));
c7597b5d 6069 else
cffb2a26 6070 {
0438d37f 6071 if (MEM_P (operands[1]))
cffb2a26 6072 operands[1] = force_reg (HImode, operands[1]);
6073 if (BYTES_BIG_ENDIAN)
6074 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
6075 else
6076 emit_insn (gen_storehi (operands[1], operands[0]));
6077 }
6078 DONE;
b11cae9e 6079 }
cffb2a26 6080 /* Sign extend a constant, and keep it in an SImode reg. */
0438d37f 6081 else if (CONST_INT_P (operands[1]))
9c08d1fa 6082 {
cffb2a26 6083 rtx reg = gen_reg_rtx (SImode);
6084 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
6085
6086 /* If the constant is already valid, leave it alone. */
215b30b3 6087 if (!const_ok_for_arm (val))
cffb2a26 6088 {
6089 /* If setting all the top bits will make the constant
6090 loadable in a single instruction, then set them.
6091 Otherwise, sign extend the number. */
6092
215b30b3 6093 if (const_ok_for_arm (~(val | ~0xffff)))
cffb2a26 6094 val |= ~0xffff;
6095 else if (val & 0x8000)
6096 val |= ~0xffff;
6097 }
6098
6099 emit_insn (gen_movsi (reg, GEN_INT (val)));
9e8503e6 6100 operands[1] = gen_lowpart (HImode, reg);
9c08d1fa 6101 }
e1ba4a27 6102 else if (arm_arch4 && optimize && can_create_pseudo_p ()
0438d37f 6103 && MEM_P (operands[1]))
0045890a 6104 {
6105 rtx reg = gen_reg_rtx (SImode);
6106
6107 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
6108 operands[1] = gen_lowpart (HImode, reg);
6109 }
215b30b3 6110 else if (!arm_arch4)
f7fbdd4a 6111 {
0438d37f 6112 if (MEM_P (operands[1]))
cffb2a26 6113 {
c1a66faf 6114 rtx base;
6115 rtx offset = const0_rtx;
6116 rtx reg = gen_reg_rtx (SImode);
6117
0438d37f 6118 if ((REG_P (base = XEXP (operands[1], 0))
c1a66faf 6119 || (GET_CODE (base) == PLUS
0438d37f 6120 && (CONST_INT_P (offset = XEXP (base, 1)))
c1a66faf 6121 && ((INTVAL(offset) & 1) != 1)
0438d37f 6122 && REG_P (base = XEXP (base, 0))))
c1a66faf 6123 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
206ee9a2 6124 {
8deb3959 6125 rtx new_rtx;
c1a66faf 6126
8deb3959 6127 new_rtx = widen_memory_access (operands[1], SImode,
6128 ((INTVAL (offset) & ~3)
6129 - INTVAL (offset)));
6130 emit_insn (gen_movsi (reg, new_rtx));
c1a66faf 6131 if (((INTVAL (offset) & 2) != 0)
6132 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
6133 {
6134 rtx reg2 = gen_reg_rtx (SImode);
6135
6136 emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
6137 reg = reg2;
6138 }
206ee9a2 6139 }
c1a66faf 6140 else
6141 emit_insn (gen_movhi_bytes (reg, operands[1]));
6142
6143 operands[1] = gen_lowpart (HImode, reg);
cffb2a26 6144 }
6145 }
6146 }
674a8f0b 6147 /* Handle loading a large integer during reload. */
0438d37f 6148 else if (CONST_INT_P (operands[1])
215b30b3 6149 && !const_ok_for_arm (INTVAL (operands[1]))
6150 && !const_ok_for_arm (~INTVAL (operands[1])))
cffb2a26 6151 {
6152 /* Writing a constant to memory needs a scratch, which should
6153 be handled with SECONDARY_RELOADs. */
0438d37f 6154 gcc_assert (REG_P (operands[0]));
cffb2a26 6155
6156 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
6157 emit_insn (gen_movsi (operands[0], operands[1]));
6158 DONE;
6159 }
6160 }
25f905c2 6161 else if (TARGET_THUMB2)
6162 {
6163 /* Thumb-2 can do everything except mem=mem and mem=const easily. */
e1ba4a27 6164 if (can_create_pseudo_p ())
25f905c2 6165 {
0438d37f 6166 if (!REG_P (operands[0]))
25f905c2 6167 operands[1] = force_reg (HImode, operands[1]);
6168 /* Zero extend a constant, and keep it in an SImode reg. */
0438d37f 6169 else if (CONST_INT_P (operands[1]))
25f905c2 6170 {
6171 rtx reg = gen_reg_rtx (SImode);
6172 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
6173
6174 emit_insn (gen_movsi (reg, GEN_INT (val)));
6175 operands[1] = gen_lowpart (HImode, reg);
6176 }
6177 }
6178 }
6179 else /* TARGET_THUMB1 */
cffb2a26 6180 {
e1ba4a27 6181 if (can_create_pseudo_p ())
cffb2a26 6182 {
0438d37f 6183 if (CONST_INT_P (operands[1]))
6cffc037 6184 {
6185 rtx reg = gen_reg_rtx (SImode);
6186
6187 emit_insn (gen_movsi (reg, operands[1]));
6188 operands[1] = gen_lowpart (HImode, reg);
6189 }
cffb2a26 6190
6191 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 6192 happen if we are passed a SP (never OK for HImode/QImode) or
bc409cb4 6193 virtual register (also rejected as illegitimate for HImode/QImode)
6194 relative address. */
cffb2a26 6195 /* ??? This should perhaps be fixed elsewhere, for instance, in
6196 fixup_stack_1, by checking for other kinds of invalid addresses,
6197 e.g. a bare reference to a virtual register. This may confuse the
6198 alpha though, which must handle this case differently. */
0438d37f 6199 if (MEM_P (operands[0])
215b30b3 6200 && !memory_address_p (GET_MODE (operands[0]),
6201 XEXP (operands[0], 0)))
537ffcfc 6202 operands[0]
6203 = replace_equiv_address (operands[0],
6204 copy_to_reg (XEXP (operands[0], 0)));
cffb2a26 6205
0438d37f 6206 if (MEM_P (operands[1])
215b30b3 6207 && !memory_address_p (GET_MODE (operands[1]),
6208 XEXP (operands[1], 0)))
537ffcfc 6209 operands[1]
6210 = replace_equiv_address (operands[1],
6211 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 6212
0438d37f 6213 if (MEM_P (operands[1]) && optimize > 0)
6cffc037 6214 {
6215 rtx reg = gen_reg_rtx (SImode);
6216
6217 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
6218 operands[1] = gen_lowpart (HImode, reg);
6219 }
6220
0438d37f 6221 if (MEM_P (operands[0]))
6cffc037 6222 operands[1] = force_reg (HImode, operands[1]);
cffb2a26 6223 }
0438d37f 6224 else if (CONST_INT_P (operands[1])
234f6557 6225 && !satisfies_constraint_I (operands[1]))
cffb2a26 6226 {
6cffc037 6227 /* Handle loading a large integer during reload. */
6228
cffb2a26 6229 /* Writing a constant to memory needs a scratch, which should
6230 be handled with SECONDARY_RELOADs. */
0438d37f 6231 gcc_assert (REG_P (operands[0]));
cffb2a26 6232
1a83b3ff 6233 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
cffb2a26 6234 emit_insn (gen_movsi (operands[0], operands[1]));
6235 DONE;
6236 }
b11cae9e 6237 }
cffb2a26 6238 "
6239)
6240
25f7a26e 6241(define_expand "movhi_bytes"
eab14235 6242 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 6243 (set (match_dup 3)
eab14235 6244 (zero_extend:SI (match_dup 6)))
25f7a26e 6245 (set (match_operand:SI 0 "" "")
6246 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
cffb2a26 6247 "TARGET_ARM"
25f7a26e 6248 "
215b30b3 6249 {
6250 rtx mem1, mem2;
6251 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
6252
788fcce0 6253 mem1 = change_address (operands[1], QImode, addr);
29c05e22 6254 mem2 = change_address (operands[1], QImode,
6255 plus_constant (Pmode, addr, 1));
215b30b3 6256 operands[0] = gen_lowpart (SImode, operands[0]);
6257 operands[1] = mem1;
6258 operands[2] = gen_reg_rtx (SImode);
6259 operands[3] = gen_reg_rtx (SImode);
6260 operands[6] = mem2;
25f7a26e 6261
215b30b3 6262 if (BYTES_BIG_ENDIAN)
6263 {
6264 operands[4] = operands[2];
6265 operands[5] = operands[3];
6266 }
6267 else
6268 {
6269 operands[4] = operands[3];
6270 operands[5] = operands[2];
6271 }
6272 }"
6273)
25f7a26e 6274
c7597b5d 6275(define_expand "movhi_bigend"
6276 [(set (match_dup 2)
6277 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
6278 (const_int 16)))
6279 (set (match_dup 3)
6280 (ashiftrt:SI (match_dup 2) (const_int 16)))
6281 (set (match_operand:HI 0 "s_register_operand" "")
787f8210 6282 (match_dup 4))]
cffb2a26 6283 "TARGET_ARM"
c7597b5d 6284 "
6285 operands[2] = gen_reg_rtx (SImode);
6286 operands[3] = gen_reg_rtx (SImode);
787f8210 6287 operands[4] = gen_lowpart (HImode, operands[3]);
215b30b3 6288 "
6289)
b11cae9e 6290
a2f10574 6291;; Pattern to recognize insn generated default case above
f7fbdd4a 6292(define_insn "*movhi_insn_arch4"
cde1623a 6293 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
85e02ccb 6294 (match_operand:HI 1 "general_operand" "rI,K,r,mi"))]
cffb2a26 6295 "TARGET_ARM
6296 && arm_arch4
85e02ccb 6297 && (register_operand (operands[0], HImode)
6298 || register_operand (operands[1], HImode))"
f7fbdd4a 6299 "@
6300 mov%?\\t%0, %1\\t%@ movhi
6301 mvn%?\\t%0, #%B1\\t%@ movhi
25f905c2 6302 str%(h%)\\t%1, %0\\t%@ movhi
6303 ldr%(h%)\\t%0, %1\\t%@ movhi"
65f68e55 6304 [(set_attr "predicable" "yes")
cffb2a26 6305 (set_attr "pool_range" "*,*,*,256")
65f68e55 6306 (set_attr "neg_pool_range" "*,*,*,244")
6307 (set_attr_alternative "type"
6308 [(if_then_else (match_operand 1 "const_int_operand" "")
1aed5204 6309 (const_string "mov_imm" )
6310 (const_string "mov_reg"))
6311 (const_string "mvn_imm")
65f68e55 6312 (const_string "store1")
6313 (const_string "load1")])]
cffb2a26 6314)
f7fbdd4a 6315
f7fbdd4a 6316(define_insn "*movhi_bytes"
65f68e55 6317 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
6318 (match_operand:HI 1 "arm_rhs_operand" "I,r,K"))]
c1a66faf 6319 "TARGET_ARM"
25f7a26e 6320 "@
65f68e55 6321 mov%?\\t%0, %1\\t%@ movhi
25f7a26e 6322 mov%?\\t%0, %1\\t%@ movhi
0d66636f 6323 mvn%?\\t%0, #%B1\\t%@ movhi"
d2a518d1 6324 [(set_attr "predicable" "yes")
1aed5204 6325 (set_attr "type" "mov_imm,mov_reg,mvn_imm")]
0d66636f 6326)
cffb2a26 6327
bc5c7e08 6328;; We use a DImode scratch because we may occasionally need an additional
6329;; temporary if the address isn't offsettable -- push_reload doesn't seem
6330;; to take any notice of the "o" constraints on reload_memory_operand operand.
d3373b54 6331(define_expand "reload_outhi"
cffb2a26 6332 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
215b30b3 6333 (match_operand:HI 1 "s_register_operand" "r")
6334 (match_operand:DI 2 "s_register_operand" "=&l")])]
cffb2a26 6335 "TARGET_EITHER"
6336 "if (TARGET_ARM)
6337 arm_reload_out_hi (operands);
6338 else
6339 thumb_reload_out_hi (operands);
d3373b54 6340 DONE;
cffb2a26 6341 "
6342)
d3373b54 6343
25f7a26e 6344(define_expand "reload_inhi"
6345 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
cffb2a26 6346 (match_operand:HI 1 "arm_reload_memory_operand" "o")
bc5c7e08 6347 (match_operand:DI 2 "s_register_operand" "=&r")])]
c1a66faf 6348 "TARGET_EITHER"
25f7a26e 6349 "
cffb2a26 6350 if (TARGET_ARM)
6351 arm_reload_in_hi (operands);
6352 else
6353 thumb_reload_out_hi (operands);
25f7a26e 6354 DONE;
6355")
6356
9c08d1fa 6357(define_expand "movqi"
6358 [(set (match_operand:QI 0 "general_operand" "")
6359 (match_operand:QI 1 "general_operand" ""))]
cffb2a26 6360 "TARGET_EITHER"
9c08d1fa 6361 "
6cffc037 6362 /* Everything except mem = const or mem = mem can be done easily */
0045890a 6363
e1ba4a27 6364 if (can_create_pseudo_p ())
cffb2a26 6365 {
0438d37f 6366 if (CONST_INT_P (operands[1]))
6cffc037 6367 {
6368 rtx reg = gen_reg_rtx (SImode);
6369
03770691 6370 /* For thumb we want an unsigned immediate, then we are more likely
6371 to be able to use a movs insn. */
6372 if (TARGET_THUMB)
6373 operands[1] = GEN_INT (INTVAL (operands[1]) & 255);
6374
6cffc037 6375 emit_insn (gen_movsi (reg, operands[1]));
6376 operands[1] = gen_lowpart (QImode, reg);
6377 }
cffb2a26 6378
6cffc037 6379 if (TARGET_THUMB)
6380 {
cffb2a26 6381 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 6382 happen if we are passed a SP (never OK for HImode/QImode) or
bc409cb4 6383 virtual register (also rejected as illegitimate for HImode/QImode)
6384 relative address. */
cffb2a26 6385 /* ??? This should perhaps be fixed elsewhere, for instance, in
6386 fixup_stack_1, by checking for other kinds of invalid addresses,
6387 e.g. a bare reference to a virtual register. This may confuse the
6388 alpha though, which must handle this case differently. */
0438d37f 6389 if (MEM_P (operands[0])
215b30b3 6390 && !memory_address_p (GET_MODE (operands[0]),
cffb2a26 6391 XEXP (operands[0], 0)))
537ffcfc 6392 operands[0]
6393 = replace_equiv_address (operands[0],
6394 copy_to_reg (XEXP (operands[0], 0)));
0438d37f 6395 if (MEM_P (operands[1])
215b30b3 6396 && !memory_address_p (GET_MODE (operands[1]),
cffb2a26 6397 XEXP (operands[1], 0)))
537ffcfc 6398 operands[1]
6399 = replace_equiv_address (operands[1],
6400 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 6401 }
6402
0438d37f 6403 if (MEM_P (operands[1]) && optimize > 0)
6cffc037 6404 {
6405 rtx reg = gen_reg_rtx (SImode);
6406
6407 emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
6408 operands[1] = gen_lowpart (QImode, reg);
6409 }
6410
0438d37f 6411 if (MEM_P (operands[0]))
6cffc037 6412 operands[1] = force_reg (QImode, operands[1]);
6413 }
6414 else if (TARGET_THUMB
0438d37f 6415 && CONST_INT_P (operands[1])
234f6557 6416 && !satisfies_constraint_I (operands[1]))
6cffc037 6417 {
674a8f0b 6418 /* Handle loading a large integer during reload. */
cffb2a26 6419
6cffc037 6420 /* Writing a constant to memory needs a scratch, which should
6421 be handled with SECONDARY_RELOADs. */
0438d37f 6422 gcc_assert (REG_P (operands[0]));
6cffc037 6423
6424 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
6425 emit_insn (gen_movsi (operands[0], operands[1]));
6426 DONE;
cffb2a26 6427 }
6428 "
6429)
b11cae9e 6430
cffb2a26 6431(define_insn "*arm_movqi_insn"
fd711051 6432 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,l,r,l,Uu,r,m")
6433 (match_operand:QI 1 "general_operand" "r,r,I,Py,K,Uu,l,m,r"))]
25f905c2 6434 "TARGET_32BIT
cffb2a26 6435 && ( register_operand (operands[0], QImode)
6436 || register_operand (operands[1], QImode))"
5565501b 6437 "@
fd711051 6438 mov%?\\t%0, %1
6439 mov%?\\t%0, %1
65f68e55 6440 mov%?\\t%0, %1
5565501b 6441 mov%?\\t%0, %1
6442 mvn%?\\t%0, #%B1
25f905c2 6443 ldr%(b%)\\t%0, %1
a54e3e7b 6444 str%(b%)\\t%1, %0
6445 ldr%(b%)\\t%0, %1
25f905c2 6446 str%(b%)\\t%1, %0"
1aed5204 6447 [(set_attr "type" "mov_reg,mov_reg,mov_imm,mov_imm,mvn_imm,load1,store1,load1,store1")
a54e3e7b 6448 (set_attr "predicable" "yes")
fd711051 6449 (set_attr "predicable_short_it" "yes,yes,yes,no,no,no,no,no,no")
6450 (set_attr "arch" "t2,any,any,t2,any,t2,t2,any,any")
6451 (set_attr "length" "2,4,4,2,4,2,2,4,4")]
cffb2a26 6452)
6453
9b8516be 6454;; HFmode moves
6455(define_expand "movhf"
6456 [(set (match_operand:HF 0 "general_operand" "")
6457 (match_operand:HF 1 "general_operand" ""))]
6458 "TARGET_EITHER"
6459 "
6460 if (TARGET_32BIT)
6461 {
0438d37f 6462 if (MEM_P (operands[0]))
9b8516be 6463 operands[1] = force_reg (HFmode, operands[1]);
6464 }
6465 else /* TARGET_THUMB1 */
6466 {
6467 if (can_create_pseudo_p ())
6468 {
0438d37f 6469 if (!REG_P (operands[0]))
9b8516be 6470 operands[1] = force_reg (HFmode, operands[1]);
6471 }
6472 }
6473 "
6474)
6475
6476(define_insn "*arm32_movhf"
6477 [(set (match_operand:HF 0 "nonimmediate_operand" "=r,m,r,r")
6478 (match_operand:HF 1 "general_operand" " m,r,r,F"))]
7c36fe71 6479 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_FP16) && !arm_restrict_it
9b8516be 6480 && ( s_register_operand (operands[0], HFmode)
6481 || s_register_operand (operands[1], HFmode))"
6482 "*
6483 switch (which_alternative)
6484 {
6485 case 0: /* ARM register from memory */
6486 return \"ldr%(h%)\\t%0, %1\\t%@ __fp16\";
6487 case 1: /* memory from ARM register */
6488 return \"str%(h%)\\t%1, %0\\t%@ __fp16\";
6489 case 2: /* ARM register from ARM register */
6490 return \"mov%?\\t%0, %1\\t%@ __fp16\";
6491 case 3: /* ARM register from constant */
6492 {
6493 REAL_VALUE_TYPE r;
6494 long bits;
6495 rtx ops[4];
6496
6497 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
6498 bits = real_to_target (NULL, &r, HFmode);
6499 ops[0] = operands[0];
6500 ops[1] = GEN_INT (bits);
6501 ops[2] = GEN_INT (bits & 0xff00);
6502 ops[3] = GEN_INT (bits & 0x00ff);
6503
6504 if (arm_arch_thumb2)
6505 output_asm_insn (\"movw%?\\t%0, %1\", ops);
6506 else
6507 output_asm_insn (\"mov%?\\t%0, %2\;orr%?\\t%0, %0, %3\", ops);
6508 return \"\";
6509 }
6510 default:
6511 gcc_unreachable ();
6512 }
6513 "
6514 [(set_attr "conds" "unconditional")
ad4fc3c0 6515 (set_attr "type" "load1,store1,mov_reg,multiple")
9b8516be 6516 (set_attr "length" "4,4,4,8")
d2a518d1 6517 (set_attr "predicable" "yes")]
9b8516be 6518)
6519
87b22bf7 6520(define_expand "movsf"
6521 [(set (match_operand:SF 0 "general_operand" "")
6522 (match_operand:SF 1 "general_operand" ""))]
cffb2a26 6523 "TARGET_EITHER"
87b22bf7 6524 "
25f905c2 6525 if (TARGET_32BIT)
cffb2a26 6526 {
0438d37f 6527 if (MEM_P (operands[0]))
cffb2a26 6528 operands[1] = force_reg (SFmode, operands[1]);
6529 }
25f905c2 6530 else /* TARGET_THUMB1 */
cffb2a26 6531 {
e1ba4a27 6532 if (can_create_pseudo_p ())
cffb2a26 6533 {
0438d37f 6534 if (!REG_P (operands[0]))
cffb2a26 6535 operands[1] = force_reg (SFmode, operands[1]);
6536 }
6537 }
6538 "
6539)
6540
03d440a6 6541;; Transform a floating-point move of a constant into a core register into
6542;; an SImode operation.
cffb2a26 6543(define_split
03d440a6 6544 [(set (match_operand:SF 0 "arm_general_register_operand" "")
cffb2a26 6545 (match_operand:SF 1 "immediate_operand" ""))]
339034d0 6546 "TARGET_EITHER
cffb2a26 6547 && reload_completed
0438d37f 6548 && CONST_DOUBLE_P (operands[1])"
cffb2a26 6549 [(set (match_dup 2) (match_dup 3))]
6550 "
6551 operands[2] = gen_lowpart (SImode, operands[0]);
6552 operands[3] = gen_lowpart (SImode, operands[1]);
6553 if (operands[2] == 0 || operands[3] == 0)
6554 FAIL;
215b30b3 6555 "
6556)
87b22bf7 6557
cffb2a26 6558(define_insn "*arm_movsf_soft_insn"
6559 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
6560 (match_operand:SF 1 "general_operand" "r,mE,r"))]
cde1623a 6561 "TARGET_32BIT
cffb2a26 6562 && TARGET_SOFT_FLOAT
0438d37f 6563 && (!MEM_P (operands[0])
215b30b3 6564 || register_operand (operands[1], SFmode))"
9a1112d7 6565 "@
6566 mov%?\\t%0, %1
6567 ldr%?\\t%0, %1\\t%@ float
6568 str%?\\t%1, %0\\t%@ float"
cde1623a 6569 [(set_attr "predicable" "yes")
7c36fe71 6570 (set_attr "predicable_short_it" "no")
1aed5204 6571 (set_attr "type" "mov_reg,load1,store1")
42e1de19 6572 (set_attr "arm_pool_range" "*,4096,*")
6573 (set_attr "thumb2_pool_range" "*,4094,*")
cde1623a 6574 (set_attr "arm_neg_pool_range" "*,4084,*")
6575 (set_attr "thumb2_neg_pool_range" "*,0,*")]
cffb2a26 6576)
6577
9c08d1fa 6578(define_expand "movdf"
87b22bf7 6579 [(set (match_operand:DF 0 "general_operand" "")
6580 (match_operand:DF 1 "general_operand" ""))]
cffb2a26 6581 "TARGET_EITHER"
9c08d1fa 6582 "
25f905c2 6583 if (TARGET_32BIT)
cffb2a26 6584 {
0438d37f 6585 if (MEM_P (operands[0]))
cffb2a26 6586 operands[1] = force_reg (DFmode, operands[1]);
6587 }
6588 else /* TARGET_THUMB */
6589 {
e1ba4a27 6590 if (can_create_pseudo_p ())
cffb2a26 6591 {
0438d37f 6592 if (!REG_P (operands[0]))
cffb2a26 6593 operands[1] = force_reg (DFmode, operands[1]);
6594 }
6595 }
6596 "
6597)
b11cae9e 6598
9c08d1fa 6599;; Reloading a df mode value stored in integer regs to memory can require a
6600;; scratch reg.
6601(define_expand "reload_outdf"
cffb2a26 6602 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
87b22bf7 6603 (match_operand:DF 1 "s_register_operand" "r")
6604 (match_operand:SI 2 "s_register_operand" "=&r")]
06adefdc 6605 "TARGET_THUMB2"
87b22bf7 6606 "
215b30b3 6607 {
6608 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
f7fbdd4a 6609
215b30b3 6610 if (code == REG)
6611 operands[2] = XEXP (operands[0], 0);
6612 else if (code == POST_INC || code == PRE_DEC)
6613 {
6614 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
6615 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
6616 emit_insn (gen_movdi (operands[0], operands[1]));
6617 DONE;
6618 }
6619 else if (code == PRE_INC)
6620 {
6621 rtx reg = XEXP (XEXP (operands[0], 0), 0);
f7fbdd4a 6622
215b30b3 6623 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
6624 operands[2] = reg;
6625 }
6626 else if (code == POST_DEC)
6627 operands[2] = XEXP (XEXP (operands[0], 0), 0);
6628 else
6629 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
6630 XEXP (XEXP (operands[0], 0), 1)));
f7fbdd4a 6631
788fcce0 6632 emit_insn (gen_rtx_SET (VOIDmode,
6633 replace_equiv_address (operands[0], operands[2]),
215b30b3 6634 operands[1]));
f7fbdd4a 6635
215b30b3 6636 if (code == POST_DEC)
6637 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
6638
6639 DONE;
6640 }"
6641)
9c08d1fa 6642
9a1112d7 6643(define_insn "*movdf_soft_insn"
353cf59a 6644 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,q,m")
6645 (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,q"))]
cde1623a 6646 "TARGET_32BIT && TARGET_SOFT_FLOAT
b2778788 6647 && ( register_operand (operands[0], DFmode)
6648 || register_operand (operands[1], DFmode))"
d51f92df 6649 "*
6650 switch (which_alternative)
6651 {
6652 case 0:
6653 case 1:
6654 case 2:
6655 return \"#\";
6656 default:
26ff80c0 6657 return output_move_double (operands, true, NULL);
d51f92df 6658 }
6659 "
359a6e9f 6660 [(set_attr "length" "8,12,16,8,8")
1b7da4ac 6661 (set_attr "type" "multiple,multiple,multiple,load2,store2")
42e1de19 6662 (set_attr "arm_pool_range" "*,*,*,1020,*")
6663 (set_attr "thumb2_pool_range" "*,*,*,1018,*")
8848d797 6664 (set_attr "arm_neg_pool_range" "*,*,*,1004,*")
cde1623a 6665 (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
cffb2a26 6666)
b11cae9e 6667\f
b11cae9e 6668
9c08d1fa 6669;; load- and store-multiple insns
6670;; The arm can load/store any set of registers, provided that they are in
320ea44d 6671;; ascending order, but these expanders assume a contiguous set.
b11cae9e 6672
9c08d1fa 6673(define_expand "load_multiple"
6674 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6675 (match_operand:SI 1 "" ""))
6676 (use (match_operand:SI 2 "" ""))])]
25f905c2 6677 "TARGET_32BIT"
9580c25f 6678{
6679 HOST_WIDE_INT offset = 0;
6680
bd5b4116 6681 /* Support only fixed point registers. */
0438d37f 6682 if (!CONST_INT_P (operands[2])
9c08d1fa 6683 || INTVAL (operands[2]) > 14
6684 || INTVAL (operands[2]) < 2
0438d37f 6685 || !MEM_P (operands[1])
6686 || !REG_P (operands[0])
bd5b4116 6687 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
6688 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 6689 FAIL;
6690
6691 operands[3]
320ea44d 6692 = arm_gen_load_multiple (arm_regs_in_sequence + REGNO (operands[0]),
6693 INTVAL (operands[2]),
f082f1c4 6694 force_reg (SImode, XEXP (operands[1], 0)),
320ea44d 6695 FALSE, operands[1], &offset);
9580c25f 6696})
b11cae9e 6697
9c08d1fa 6698(define_expand "store_multiple"
6699 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6700 (match_operand:SI 1 "" ""))
6701 (use (match_operand:SI 2 "" ""))])]
25f905c2 6702 "TARGET_32BIT"
9580c25f 6703{
6704 HOST_WIDE_INT offset = 0;
6705
674a8f0b 6706 /* Support only fixed point registers. */
0438d37f 6707 if (!CONST_INT_P (operands[2])
9c08d1fa 6708 || INTVAL (operands[2]) > 14
6709 || INTVAL (operands[2]) < 2
0438d37f 6710 || !REG_P (operands[1])
6711 || !MEM_P (operands[0])
bd5b4116 6712 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
6713 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 6714 FAIL;
6715
6716 operands[3]
320ea44d 6717 = arm_gen_store_multiple (arm_regs_in_sequence + REGNO (operands[1]),
6718 INTVAL (operands[2]),
f082f1c4 6719 force_reg (SImode, XEXP (operands[0], 0)),
320ea44d 6720 FALSE, operands[0], &offset);
9580c25f 6721})
b11cae9e 6722
9c08d1fa 6723
6724;; Move a block of memory if it is word aligned and MORE than 2 words long.
6725;; We could let this apply for blocks of less than this, but it clobbers so
6726;; many registers that there is then probably a better way.
6727
008c057d 6728(define_expand "movmemqi"
34191dd1 6729 [(match_operand:BLK 0 "general_operand" "")
6730 (match_operand:BLK 1 "general_operand" "")
6731 (match_operand:SI 2 "const_int_operand" "")
6732 (match_operand:SI 3 "const_int_operand" "")]
ae51a965 6733 ""
9c08d1fa 6734 "
25f905c2 6735 if (TARGET_32BIT)
cffb2a26 6736 {
ae51a965 6737 if (TARGET_LDRD && current_tune->prefer_ldrd_strd
6738 && !optimize_function_for_size_p (cfun))
6739 {
6740 if (gen_movmem_ldrd_strd (operands))
6741 DONE;
6742 FAIL;
6743 }
6744
008c057d 6745 if (arm_gen_movmemqi (operands))
cffb2a26 6746 DONE;
6747 FAIL;
6748 }
25f905c2 6749 else /* TARGET_THUMB1 */
cffb2a26 6750 {
6751 if ( INTVAL (operands[3]) != 4
6752 || INTVAL (operands[2]) > 48)
6753 FAIL;
6754
008c057d 6755 thumb_expand_movmemqi (operands);
cffb2a26 6756 DONE;
6757 }
6758 "
6759)
9c08d1fa 6760\f
b11cae9e 6761
341940e8 6762;; Compare & branch insns
8d232dc7 6763;; The range calculations are based as follows:
341940e8 6764;; For forward branches, the address calculation returns the address of
6765;; the next instruction. This is 2 beyond the branch instruction.
6766;; For backward branches, the address calculation returns the address of
6767;; the first instruction in this pattern (cmp). This is 2 before the branch
6768;; instruction for the shortest sequence, and 4 before the branch instruction
6769;; if we have to jump around an unconditional branch.
6770;; To the basic branch range the PC offset must be added (this is +4).
6771;; So for forward branches we have
6772;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
6773;; And for backward branches we have
6774;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
6775;;
6776;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
6777;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
cffb2a26 6778
aeac46d4 6779(define_expand "cbranchsi4"
6780 [(set (pc) (if_then_else
aa06947a 6781 (match_operator 0 "expandable_comparison_operator"
aeac46d4 6782 [(match_operand:SI 1 "s_register_operand" "")
6783 (match_operand:SI 2 "nonmemory_operand" "")])
6784 (label_ref (match_operand 3 "" ""))
6785 (pc)))]
f9aa4160 6786 "TARGET_EITHER"
aeac46d4 6787 "
74f4459c 6788 if (!TARGET_THUMB1)
6789 {
f9aa4160 6790 if (!arm_validize_comparison (&operands[0], &operands[1], &operands[2]))
6791 FAIL;
74f4459c 6792 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6793 operands[3]));
6794 DONE;
6795 }
25f905c2 6796 if (thumb1_cmpneg_operand (operands[2], SImode))
aeac46d4 6797 {
6798 emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
6799 operands[3], operands[0]));
6800 DONE;
6801 }
25f905c2 6802 if (!thumb1_cmp_operand (operands[2], SImode))
aeac46d4 6803 operands[2] = force_reg (SImode, operands[2]);
6804 ")
6805
74f4459c 6806(define_expand "cbranchsf4"
6807 [(set (pc) (if_then_else
aa06947a 6808 (match_operator 0 "expandable_comparison_operator"
74f4459c 6809 [(match_operand:SF 1 "s_register_operand" "")
6810 (match_operand:SF 2 "arm_float_compare_operand" "")])
6811 (label_ref (match_operand 3 "" ""))
6812 (pc)))]
6813 "TARGET_32BIT && TARGET_HARD_FLOAT"
6814 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6815 operands[3])); DONE;"
6816)
6817
6818(define_expand "cbranchdf4"
6819 [(set (pc) (if_then_else
aa06947a 6820 (match_operator 0 "expandable_comparison_operator"
74f4459c 6821 [(match_operand:DF 1 "s_register_operand" "")
6822 (match_operand:DF 2 "arm_float_compare_operand" "")])
6823 (label_ref (match_operand 3 "" ""))
6824 (pc)))]
a50d7267 6825 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
74f4459c 6826 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6827 operands[3])); DONE;"
6828)
6829
74f4459c 6830(define_expand "cbranchdi4"
6831 [(set (pc) (if_then_else
aa06947a 6832 (match_operator 0 "expandable_comparison_operator"
b8eae306 6833 [(match_operand:DI 1 "s_register_operand" "")
a8045a4f 6834 (match_operand:DI 2 "cmpdi_operand" "")])
74f4459c 6835 (label_ref (match_operand 3 "" ""))
6836 (pc)))]
a8045a4f 6837 "TARGET_32BIT"
6838 "{
0438d37f 6839 if (!arm_validize_comparison (&operands[0], &operands[1], &operands[2]))
f9aa4160 6840 FAIL;
6841 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
a8045a4f 6842 operands[3]));
6843 DONE;
6844 }"
74f4459c 6845)
6846
9c08d1fa 6847;; Comparison and test insns
6848
cffb2a26 6849(define_insn "*arm_cmpsi_insn"
bd5b4116 6850 [(set (reg:CC CC_REGNUM)
f9f234ec 6851 (compare:CC (match_operand:SI 0 "s_register_operand" "l,r,r,r,r")
6852 (match_operand:SI 1 "arm_add_operand" "Py,r,r,I,L")))]
25f905c2 6853 "TARGET_32BIT"
5565501b 6854 "@
a6864a24 6855 cmp%?\\t%0, %1
6856 cmp%?\\t%0, %1
aea4c774 6857 cmp%?\\t%0, %1
f9f234ec 6858 cmp%?\\t%0, %1
aea4c774 6859 cmn%?\\t%0, #%n1"
a6864a24 6860 [(set_attr "conds" "set")
f9f234ec 6861 (set_attr "arch" "t2,t2,any,any,any")
6862 (set_attr "length" "2,2,4,4,4")
65f68e55 6863 (set_attr "predicable" "yes")
f9f234ec 6864 (set_attr "predicable_short_it" "yes,yes,yes,no,no")
6865 (set_attr "type" "alus_imm,alus_reg,alus_reg,alus_imm,alus_imm")]
cffb2a26 6866)
b11cae9e 6867
d5d4dc8d 6868(define_insn "*cmpsi_shiftsi"
bd5b4116 6869 [(set (reg:CC CC_REGNUM)
d82e788e 6870 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r,r")
cffb2a26 6871 (match_operator:SI 3 "shift_operator"
d82e788e 6872 [(match_operand:SI 1 "s_register_operand" "r,r,r")
6873 (match_operand:SI 2 "shift_amount_operand" "M,r,M")])))]
d5d4dc8d 6874 "TARGET_32BIT"
f9f234ec 6875 "cmp\\t%0, %1%S3"
344495ea 6876 [(set_attr "conds" "set")
331beb1a 6877 (set_attr "shift" "1")
d82e788e 6878 (set_attr "arch" "32,a,a")
6879 (set_attr "type" "alus_shift_imm,alu_shift_reg,alus_shift_imm")])
b11cae9e 6880
d5d4dc8d 6881(define_insn "*cmpsi_shiftsi_swp"
bd5b4116 6882 [(set (reg:CC_SWP CC_REGNUM)
aea4c774 6883 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
d82e788e 6884 [(match_operand:SI 1 "s_register_operand" "r,r,r")
6885 (match_operand:SI 2 "shift_amount_operand" "M,r,M")])
6886 (match_operand:SI 0 "s_register_operand" "r,r,r")))]
d5d4dc8d 6887 "TARGET_32BIT"
aea4c774 6888 "cmp%?\\t%0, %1%S3"
344495ea 6889 [(set_attr "conds" "set")
331beb1a 6890 (set_attr "shift" "1")
d82e788e 6891 (set_attr "arch" "32,a,a")
6892 (set_attr "type" "alus_shift_imm,alu_shift_reg,alus_shift_imm")])
b11cae9e 6893
25f905c2 6894(define_insn "*arm_cmpsi_negshiftsi_si"
aed179ae 6895 [(set (reg:CC_Z CC_REGNUM)
6896 (compare:CC_Z
6897 (neg:SI (match_operator:SI 1 "shift_operator"
6898 [(match_operand:SI 2 "s_register_operand" "r")
6899 (match_operand:SI 3 "reg_or_int_operand" "rM")]))
6900 (match_operand:SI 0 "s_register_operand" "r")))]
cffb2a26 6901 "TARGET_ARM"
aed179ae 6902 "cmn%?\\t%0, %2%S1"
344495ea 6903 [(set_attr "conds" "set")
aed179ae 6904 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
d82e788e 6905 (const_string "alus_shift_imm")
6906 (const_string "alus_shift_reg")))
596e5e8f 6907 (set_attr "predicable" "yes")]
0d66636f 6908)
b11cae9e 6909
a8045a4f 6910;; DImode comparisons. The generic code generates branches that
6911;; if-conversion can not reduce to a conditional compare, so we do
6912;; that directly.
6913
ba6a3b2f 6914(define_insn_and_split "*arm_cmpdi_insn"
a8045a4f 6915 [(set (reg:CC_NCV CC_REGNUM)
6916 (compare:CC_NCV (match_operand:DI 0 "s_register_operand" "r")
6917 (match_operand:DI 1 "arm_di_operand" "rDi")))
6918 (clobber (match_scratch:SI 2 "=r"))]
b805622c 6919 "TARGET_32BIT"
ba6a3b2f 6920 "#" ; "cmp\\t%Q0, %Q1\;sbcs\\t%2, %R0, %R1"
6921 "&& reload_completed"
6922 [(set (reg:CC CC_REGNUM)
6923 (compare:CC (match_dup 0) (match_dup 1)))
6924 (parallel [(set (reg:CC CC_REGNUM)
6925 (compare:CC (match_dup 3) (match_dup 4)))
6926 (set (match_dup 2)
6927 (minus:SI (match_dup 5)
6928 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))])]
6929 {
6930 operands[3] = gen_highpart (SImode, operands[0]);
6931 operands[0] = gen_lowpart (SImode, operands[0]);
6932 if (CONST_INT_P (operands[1]))
6933 {
6934 operands[4] = GEN_INT (~INTVAL (gen_highpart_mode (SImode,
6935 DImode,
6936 operands[1])));
6937 operands[5] = gen_rtx_PLUS (SImode, operands[3], operands[4]);
6938 }
6939 else
6940 {
6941 operands[4] = gen_highpart (SImode, operands[1]);
6942 operands[5] = gen_rtx_MINUS (SImode, operands[3], operands[4]);
6943 }
6944 operands[1] = gen_lowpart (SImode, operands[1]);
6945 operands[2] = gen_lowpart (SImode, operands[2]);
6946 }
a8045a4f 6947 [(set_attr "conds" "set")
1b7da4ac 6948 (set_attr "length" "8")
6949 (set_attr "type" "multiple")]
a8045a4f 6950)
6951
ba6a3b2f 6952(define_insn_and_split "*arm_cmpdi_unsigned"
a8045a4f 6953 [(set (reg:CC_CZ CC_REGNUM)
1a86364b 6954 (compare:CC_CZ (match_operand:DI 0 "s_register_operand" "l,r,r,r")
6955 (match_operand:DI 1 "arm_di_operand" "Py,r,Di,rDi")))]
7c36fe71 6956
48a98053 6957 "TARGET_32BIT"
ba6a3b2f 6958 "#" ; "cmp\\t%R0, %R1\;it eq\;cmpeq\\t%Q0, %Q1"
6959 "&& reload_completed"
6960 [(set (reg:CC CC_REGNUM)
6961 (compare:CC (match_dup 2) (match_dup 3)))
6962 (cond_exec (eq:SI (reg:CC CC_REGNUM) (const_int 0))
6963 (set (reg:CC CC_REGNUM)
6964 (compare:CC (match_dup 0) (match_dup 1))))]
6965 {
6966 operands[2] = gen_highpart (SImode, operands[0]);
6967 operands[0] = gen_lowpart (SImode, operands[0]);
6968 if (CONST_INT_P (operands[1]))
6969 operands[3] = gen_highpart_mode (SImode, DImode, operands[1]);
6970 else
6971 operands[3] = gen_highpart (SImode, operands[1]);
6972 operands[1] = gen_lowpart (SImode, operands[1]);
6973 }
a8045a4f 6974 [(set_attr "conds" "set")
1a86364b 6975 (set_attr "enabled_for_depr_it" "yes,yes,no,*")
6976 (set_attr "arch" "t2,t2,t2,a")
6977 (set_attr "length" "6,6,10,8")
1b7da4ac 6978 (set_attr "type" "multiple")]
a8045a4f 6979)
6980
6981(define_insn "*arm_cmpdi_zero"
6982 [(set (reg:CC_Z CC_REGNUM)
6983 (compare:CC_Z (match_operand:DI 0 "s_register_operand" "r")
6984 (const_int 0)))
6985 (clobber (match_scratch:SI 1 "=r"))]
6986 "TARGET_32BIT"
6987 "orr%.\\t%1, %Q0, %R0"
1b7da4ac 6988 [(set_attr "conds" "set")
6989 (set_attr "type" "logics_reg")]
a8045a4f 6990)
6991
9c08d1fa 6992; This insn allows redundant compares to be removed by cse, nothing should
6993; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
6994; is deleted later on. The match_dup will match the mode here, so that
6995; mode changes of the condition codes aren't lost by this even though we don't
6996; specify what they are.
6997
8a18b90c 6998(define_insn "*deleted_compare"
9c08d1fa 6999 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
25f905c2 7000 "TARGET_32BIT"
40dbec34 7001 "\\t%@ deleted compare"
cffb2a26 7002 [(set_attr "conds" "set")
1b7da4ac 7003 (set_attr "length" "0")
7004 (set_attr "type" "no_insn")]
cffb2a26 7005)
9c08d1fa 7006
7007\f
7008;; Conditional branch insns
7009
74f4459c 7010(define_expand "cbranch_cc"
9c08d1fa 7011 [(set (pc)
74f4459c 7012 (if_then_else (match_operator 0 "" [(match_operand 1 "" "")
7013 (match_operand 2 "" "")])
7014 (label_ref (match_operand 3 "" ""))
9c08d1fa 7015 (pc)))]
25f905c2 7016 "TARGET_32BIT"
74f4459c 7017 "operands[1] = arm_gen_compare_reg (GET_CODE (operands[0]),
e1b93706 7018 operands[1], operands[2], NULL_RTX);
74f4459c 7019 operands[2] = const0_rtx;"
8fa3ba89 7020)
7021
7022;;
7023;; Patterns to match conditional branch insns.
7024;;
7025
ffcc986d 7026(define_insn "arm_cond_branch"
9c08d1fa 7027 [(set (pc)
8fa3ba89 7028 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 7029 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 7030 (label_ref (match_operand 0 "" ""))
7031 (pc)))]
25f905c2 7032 "TARGET_32BIT"
d75350ce 7033 "*
9c08d1fa 7034 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 7035 {
7036 arm_ccfsm_state += 2;
7037 return \"\";
7038 }
e2348bcb 7039 return \"b%d1\\t%l0\";
cffb2a26 7040 "
a2cd141b 7041 [(set_attr "conds" "use")
a6864a24 7042 (set_attr "type" "branch")
7043 (set (attr "length")
7044 (if_then_else
0bf497f5 7045 (and (match_test "TARGET_THUMB2")
a6864a24 7046 (and (ge (minus (match_dup 0) (pc)) (const_int -250))
7047 (le (minus (match_dup 0) (pc)) (const_int 256))))
7048 (const_int 2)
7049 (const_int 4)))]
cffb2a26 7050)
d75350ce 7051
cffb2a26 7052(define_insn "*arm_cond_branch_reversed"
9c08d1fa 7053 [(set (pc)
8fa3ba89 7054 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 7055 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 7056 (pc)
7057 (label_ref (match_operand 0 "" ""))))]
25f905c2 7058 "TARGET_32BIT"
d75350ce 7059 "*
9c08d1fa 7060 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 7061 {
7062 arm_ccfsm_state += 2;
7063 return \"\";
7064 }
e2348bcb 7065 return \"b%D1\\t%l0\";
cffb2a26 7066 "
a2cd141b 7067 [(set_attr "conds" "use")
a6864a24 7068 (set_attr "type" "branch")
7069 (set (attr "length")
7070 (if_then_else
0bf497f5 7071 (and (match_test "TARGET_THUMB2")
a6864a24 7072 (and (ge (minus (match_dup 0) (pc)) (const_int -250))
7073 (le (minus (match_dup 0) (pc)) (const_int 256))))
7074 (const_int 2)
7075 (const_int 4)))]
cffb2a26 7076)
7077
b11cae9e 7078\f
9c08d1fa 7079
7080; scc insns
7081
74f4459c 7082(define_expand "cstore_cc"
7db9af5d 7083 [(set (match_operand:SI 0 "s_register_operand" "")
74f4459c 7084 (match_operator:SI 1 "" [(match_operand 2 "" "")
7085 (match_operand 3 "" "")]))]
25f905c2 7086 "TARGET_32BIT"
74f4459c 7087 "operands[2] = arm_gen_compare_reg (GET_CODE (operands[1]),
e1b93706 7088 operands[2], operands[3], NULL_RTX);
74f4459c 7089 operands[3] = const0_rtx;"
8fa3ba89 7090)
7091
a3b84066 7092(define_insn_and_split "*mov_scc"
9c08d1fa 7093 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7094 (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7095 [(match_operand 2 "cc_register" "") (const_int 0)]))]
cffb2a26 7096 "TARGET_ARM"
a3b84066 7097 "#" ; "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
7098 "TARGET_ARM"
7099 [(set (match_dup 0)
7100 (if_then_else:SI (match_dup 1)
7101 (const_int 1)
7102 (const_int 0)))]
7103 ""
cffb2a26 7104 [(set_attr "conds" "use")
1b7da4ac 7105 (set_attr "length" "8")
7106 (set_attr "type" "multiple")]
cffb2a26 7107)
9c08d1fa 7108
a3b84066 7109(define_insn_and_split "*mov_negscc"
9c08d1fa 7110 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7111 (neg:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7112 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 7113 "TARGET_ARM"
a3b84066 7114 "#" ; "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
7115 "TARGET_ARM"
7116 [(set (match_dup 0)
7117 (if_then_else:SI (match_dup 1)
7118 (match_dup 3)
7119 (const_int 0)))]
7120 {
7121 operands[3] = GEN_INT (~0);
7122 }
cffb2a26 7123 [(set_attr "conds" "use")
1b7da4ac 7124 (set_attr "length" "8")
7125 (set_attr "type" "multiple")]
cffb2a26 7126)
9c08d1fa 7127
a3b84066 7128(define_insn_and_split "*mov_notscc"
9c08d1fa 7129 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7130 (not:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7131 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 7132 "TARGET_ARM"
a3b84066 7133 "#" ; "mvn%D1\\t%0, #0\;mvn%d1\\t%0, #1"
7134 "TARGET_ARM"
7135 [(set (match_dup 0)
7136 (if_then_else:SI (match_dup 1)
7137 (match_dup 3)
7138 (match_dup 4)))]
7139 {
7140 operands[3] = GEN_INT (~1);
7141 operands[4] = GEN_INT (~0);
7142 }
cffb2a26 7143 [(set_attr "conds" "use")
1b7da4ac 7144 (set_attr "length" "8")
7145 (set_attr "type" "multiple")]
cffb2a26 7146)
9c08d1fa 7147
595d88b5 7148(define_expand "cstoresi4"
7149 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 7150 (match_operator:SI 1 "expandable_comparison_operator"
595d88b5 7151 [(match_operand:SI 2 "s_register_operand" "")
7152 (match_operand:SI 3 "reg_or_int_operand" "")]))]
74f4459c 7153 "TARGET_32BIT || TARGET_THUMB1"
595d88b5 7154 "{
7155 rtx op3, scratch, scratch2;
7156
74f4459c 7157 if (!TARGET_THUMB1)
7158 {
7159 if (!arm_add_operand (operands[3], SImode))
7160 operands[3] = force_reg (SImode, operands[3]);
7161 emit_insn (gen_cstore_cc (operands[0], operands[1],
7162 operands[2], operands[3]));
7163 DONE;
7164 }
7165
595d88b5 7166 if (operands[3] == const0_rtx)
7167 {
7168 switch (GET_CODE (operands[1]))
7169 {
7170 case EQ:
25f905c2 7171 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], operands[2]));
595d88b5 7172 break;
7173
7174 case NE:
25f905c2 7175 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], operands[2]));
595d88b5 7176 break;
7177
7178 case LE:
7179 scratch = expand_binop (SImode, add_optab, operands[2], constm1_rtx,
7180 NULL_RTX, 0, OPTAB_WIDEN);
7181 scratch = expand_binop (SImode, ior_optab, operands[2], scratch,
7182 NULL_RTX, 0, OPTAB_WIDEN);
7183 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7184 operands[0], 1, OPTAB_WIDEN);
7185 break;
7186
7187 case GE:
7188 scratch = expand_unop (SImode, one_cmpl_optab, operands[2],
7189 NULL_RTX, 1);
7190 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7191 NULL_RTX, 1, OPTAB_WIDEN);
7192 break;
7193
7194 case GT:
7195 scratch = expand_binop (SImode, ashr_optab, operands[2],
7196 GEN_INT (31), NULL_RTX, 0, OPTAB_WIDEN);
7197 scratch = expand_binop (SImode, sub_optab, scratch, operands[2],
7198 NULL_RTX, 0, OPTAB_WIDEN);
7199 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31), operands[0],
7200 0, OPTAB_WIDEN);
7201 break;
7202
7203 /* LT is handled by generic code. No need for unsigned with 0. */
7204 default:
7205 FAIL;
7206 }
7207 DONE;
7208 }
7209
7210 switch (GET_CODE (operands[1]))
7211 {
7212 case EQ:
7213 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7214 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7215 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], scratch));
595d88b5 7216 break;
7217
7218 case NE:
7219 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7220 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7221 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], scratch));
595d88b5 7222 break;
7223
7224 case LE:
7225 op3 = force_reg (SImode, operands[3]);
7226
7227 scratch = expand_binop (SImode, lshr_optab, operands[2], GEN_INT (31),
7228 NULL_RTX, 1, OPTAB_WIDEN);
7229 scratch2 = expand_binop (SImode, ashr_optab, op3, GEN_INT (31),
7230 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7231 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
595d88b5 7232 op3, operands[2]));
7233 break;
7234
7235 case GE:
7236 op3 = operands[3];
25f905c2 7237 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7238 op3 = force_reg (SImode, op3);
7239 scratch = expand_binop (SImode, ashr_optab, operands[2], GEN_INT (31),
7240 NULL_RTX, 0, OPTAB_WIDEN);
7241 scratch2 = expand_binop (SImode, lshr_optab, op3, GEN_INT (31),
7242 NULL_RTX, 1, OPTAB_WIDEN);
25f905c2 7243 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
595d88b5 7244 operands[2], op3));
7245 break;
7246
7247 case LEU:
7248 op3 = force_reg (SImode, operands[3]);
7249 scratch = force_reg (SImode, const0_rtx);
25f905c2 7250 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
595d88b5 7251 op3, operands[2]));
7252 break;
7253
7254 case GEU:
7255 op3 = operands[3];
25f905c2 7256 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7257 op3 = force_reg (SImode, op3);
7258 scratch = force_reg (SImode, const0_rtx);
25f905c2 7259 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
595d88b5 7260 operands[2], op3));
7261 break;
7262
7263 case LTU:
7264 op3 = operands[3];
25f905c2 7265 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7266 op3 = force_reg (SImode, op3);
7267 scratch = gen_reg_rtx (SImode);
408b7ae5 7268 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], operands[2], op3));
595d88b5 7269 break;
7270
7271 case GTU:
7272 op3 = force_reg (SImode, operands[3]);
7273 scratch = gen_reg_rtx (SImode);
408b7ae5 7274 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], op3, operands[2]));
595d88b5 7275 break;
7276
7277 /* No good sequences for GT, LT. */
7278 default:
7279 FAIL;
7280 }
7281 DONE;
7282}")
7283
74f4459c 7284(define_expand "cstoresf4"
7285 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 7286 (match_operator:SI 1 "expandable_comparison_operator"
74f4459c 7287 [(match_operand:SF 2 "s_register_operand" "")
7288 (match_operand:SF 3 "arm_float_compare_operand" "")]))]
7289 "TARGET_32BIT && TARGET_HARD_FLOAT"
7290 "emit_insn (gen_cstore_cc (operands[0], operands[1],
7291 operands[2], operands[3])); DONE;"
7292)
7293
7294(define_expand "cstoredf4"
7295 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 7296 (match_operator:SI 1 "expandable_comparison_operator"
74f4459c 7297 [(match_operand:DF 2 "s_register_operand" "")
7298 (match_operand:DF 3 "arm_float_compare_operand" "")]))]
d63ed457 7299 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
74f4459c 7300 "emit_insn (gen_cstore_cc (operands[0], operands[1],
7301 operands[2], operands[3])); DONE;"
7302)
7303
74f4459c 7304(define_expand "cstoredi4"
7305 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 7306 (match_operator:SI 1 "expandable_comparison_operator"
b8eae306 7307 [(match_operand:DI 2 "s_register_operand" "")
a8045a4f 7308 (match_operand:DI 3 "cmpdi_operand" "")]))]
7309 "TARGET_32BIT"
7310 "{
f9aa4160 7311 if (!arm_validize_comparison (&operands[1],
7312 &operands[2],
7313 &operands[3]))
7314 FAIL;
7315 emit_insn (gen_cstore_cc (operands[0], operands[1], operands[2],
a8045a4f 7316 operands[3]));
7317 DONE;
7318 }"
74f4459c 7319)
7320
9c08d1fa 7321\f
39b5e676 7322;; Conditional move insns
7323
7324(define_expand "movsicc"
8a18b90c 7325 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 7326 (if_then_else:SI (match_operand 1 "expandable_comparison_operator" "")
aea4c774 7327 (match_operand:SI 2 "arm_not_operand" "")
8a18b90c 7328 (match_operand:SI 3 "arm_not_operand" "")))]
25f905c2 7329 "TARGET_32BIT"
39b5e676 7330 "
215b30b3 7331 {
f9aa4160 7332 enum rtx_code code;
278b301d 7333 rtx ccreg;
7334
f9aa4160 7335 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
7336 &XEXP (operands[1], 1)))
278b301d 7337 FAIL;
f9aa4160 7338
7339 code = GET_CODE (operands[1]);
74f4459c 7340 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
e1b93706 7341 XEXP (operands[1], 1), NULL_RTX);
29bb088d 7342 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7343 }"
7344)
39b5e676 7345
7346(define_expand "movsfcc"
8a18b90c 7347 [(set (match_operand:SF 0 "s_register_operand" "")
4df97ffc 7348 (if_then_else:SF (match_operand 1 "arm_cond_move_operator" "")
8a18b90c 7349 (match_operand:SF 2 "s_register_operand" "")
d86c91f6 7350 (match_operand:SF 3 "s_register_operand" "")))]
19f6bf8d 7351 "TARGET_32BIT && TARGET_HARD_FLOAT"
39b5e676 7352 "
215b30b3 7353 {
7354 enum rtx_code code = GET_CODE (operands[1]);
7355 rtx ccreg;
f082f1c4 7356
f9aa4160 7357 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
7358 &XEXP (operands[1], 1)))
7359 FAIL;
39b5e676 7360
f9aa4160 7361 code = GET_CODE (operands[1]);
74f4459c 7362 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
e1b93706 7363 XEXP (operands[1], 1), NULL_RTX);
29bb088d 7364 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7365 }"
7366)
39b5e676 7367
7368(define_expand "movdfcc"
8a18b90c 7369 [(set (match_operand:DF 0 "s_register_operand" "")
4df97ffc 7370 (if_then_else:DF (match_operand 1 "arm_cond_move_operator" "")
8a18b90c 7371 (match_operand:DF 2 "s_register_operand" "")
d86c91f6 7372 (match_operand:DF 3 "s_register_operand" "")))]
994606f8 7373 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
39b5e676 7374 "
215b30b3 7375 {
7376 enum rtx_code code = GET_CODE (operands[1]);
278b301d 7377 rtx ccreg;
39b5e676 7378
f9aa4160 7379 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
7380 &XEXP (operands[1], 1)))
7381 FAIL;
7382 code = GET_CODE (operands[1]);
74f4459c 7383 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
e1b93706 7384 XEXP (operands[1], 1), NULL_RTX);
29bb088d 7385 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7386 }"
7387)
39b5e676 7388
91cb50d2 7389(define_insn "*cmov<mode>"
7390 [(set (match_operand:SDF 0 "s_register_operand" "=<F_constraint>")
7391 (if_then_else:SDF (match_operator 1 "arm_vsel_comparison_operator"
7392 [(match_operand 2 "cc_register" "") (const_int 0)])
7393 (match_operand:SDF 3 "s_register_operand"
7394 "<F_constraint>")
7395 (match_operand:SDF 4 "s_register_operand"
7396 "<F_constraint>")))]
7397 "TARGET_HARD_FLOAT && TARGET_FPU_ARMV8 <vfp_double_cond>"
7398 "*
7399 {
7400 enum arm_cond_code code = maybe_get_arm_condition_code (operands[1]);
7401 switch (code)
7402 {
7403 case ARM_GE:
7404 case ARM_GT:
7405 case ARM_EQ:
7406 case ARM_VS:
7407 return \"vsel%d1.<V_if_elem>\\t%<V_reg>0, %<V_reg>3, %<V_reg>4\";
7408 case ARM_LT:
7409 case ARM_LE:
7410 case ARM_NE:
7411 case ARM_VC:
7412 return \"vsel%D1.<V_if_elem>\\t%<V_reg>0, %<V_reg>4, %<V_reg>3\";
7413 default:
7414 gcc_unreachable ();
7415 }
7416 return \"\";
7417 }"
7418 [(set_attr "conds" "use")
7419 (set_attr "type" "f_sel<vfp_type>")]
7420)
7421
190efb17 7422(define_insn_and_split "*movsicc_insn"
f082f1c4 7423 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
8a18b90c 7424 (if_then_else:SI
8fa3ba89 7425 (match_operator 3 "arm_comparison_operator"
8a18b90c 7426 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 7427 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
7428 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
cffb2a26 7429 "TARGET_ARM"
39b5e676 7430 "@
8a18b90c 7431 mov%D3\\t%0, %2
7432 mvn%D3\\t%0, #%B2
f082f1c4 7433 mov%d3\\t%0, %1
7434 mvn%d3\\t%0, #%B1
190efb17 7435 #
7436 #
7437 #
7438 #"
7439 ; alt4: mov%d3\\t%0, %1\;mov%D3\\t%0, %2
7440 ; alt5: mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
7441 ; alt6: mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
7442 ; alt7: mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
7443 "&& reload_completed"
7444 [(const_int 0)]
7445 {
7446 enum rtx_code rev_code;
7447 enum machine_mode mode;
7448 rtx rev_cond;
7449
7450 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
7451 operands[3],
7452 gen_rtx_SET (VOIDmode,
7453 operands[0],
7454 operands[1])));
7455
7456 rev_code = GET_CODE (operands[3]);
7457 mode = GET_MODE (operands[4]);
7458 if (mode == CCFPmode || mode == CCFPEmode)
7459 rev_code = reverse_condition_maybe_unordered (rev_code);
7460 else
7461 rev_code = reverse_condition (rev_code);
7462
7463 rev_cond = gen_rtx_fmt_ee (rev_code,
7464 VOIDmode,
7465 operands[4],
7466 const0_rtx);
7467 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
7468 rev_cond,
7469 gen_rtx_SET (VOIDmode,
7470 operands[0],
7471 operands[2])));
7472 DONE;
7473 }
f082f1c4 7474 [(set_attr "length" "4,4,4,4,8,8,8,8")
d2a518d1 7475 (set_attr "conds" "use")
65f68e55 7476 (set_attr_alternative "type"
7477 [(if_then_else (match_operand 2 "const_int_operand" "")
1aed5204 7478 (const_string "mov_imm")
7479 (const_string "mov_reg"))
7480 (const_string "mvn_imm")
65f68e55 7481 (if_then_else (match_operand 1 "const_int_operand" "")
1aed5204 7482 (const_string "mov_imm")
7483 (const_string "mov_reg"))
7484 (const_string "mvn_imm")
7485 (const_string "mov_reg")
7486 (const_string "mov_reg")
7487 (const_string "mov_reg")
7488 (const_string "mov_reg")])]
215b30b3 7489)
39b5e676 7490
39b5e676 7491(define_insn "*movsfcc_soft_insn"
f082f1c4 7492 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
8fa3ba89 7493 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
8a18b90c 7494 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 7495 (match_operand:SF 1 "s_register_operand" "0,r")
7496 (match_operand:SF 2 "s_register_operand" "r,0")))]
cffb2a26 7497 "TARGET_ARM && TARGET_SOFT_FLOAT"
f082f1c4 7498 "@
7499 mov%D3\\t%0, %2
7500 mov%d3\\t%0, %1"
d2a518d1 7501 [(set_attr "conds" "use")
1aed5204 7502 (set_attr "type" "mov_reg")]
8fa3ba89 7503)
39b5e676 7504
39b5e676 7505\f
9c08d1fa 7506;; Jump and linkage insns
7507
cffb2a26 7508(define_expand "jump"
9c08d1fa 7509 [(set (pc)
7510 (label_ref (match_operand 0 "" "")))]
cffb2a26 7511 "TARGET_EITHER"
9c08d1fa 7512 ""
cffb2a26 7513)
7514
7515(define_insn "*arm_jump"
7516 [(set (pc)
7517 (label_ref (match_operand 0 "" "")))]
25f905c2 7518 "TARGET_32BIT"
9c08d1fa 7519 "*
0d66636f 7520 {
7521 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7522 {
7523 arm_ccfsm_state += 2;
7524 return \"\";
7525 }
7526 return \"b%?\\t%l0\";
7527 }
7528 "
a6864a24 7529 [(set_attr "predicable" "yes")
7530 (set (attr "length")
7531 (if_then_else
0bf497f5 7532 (and (match_test "TARGET_THUMB2")
a6864a24 7533 (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
7534 (le (minus (match_dup 0) (pc)) (const_int 2048))))
7535 (const_int 2)
1b7da4ac 7536 (const_int 4)))
7537 (set_attr "type" "branch")]
0d66636f 7538)
9c08d1fa 7539
d3373b54 7540(define_expand "call"
7541 [(parallel [(call (match_operand 0 "memory_operand" "")
7542 (match_operand 1 "general_operand" ""))
cffb2a26 7543 (use (match_operand 2 "" ""))
bd5b4116 7544 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 7545 "TARGET_EITHER"
6c4c2133 7546 "
7547 {
bac7fc85 7548 rtx callee, pat;
bbe777ea 7549
bbe777ea 7550 /* In an untyped call, we can get NULL for operand 2. */
7551 if (operands[2] == NULL_RTX)
7552 operands[2] = const0_rtx;
7553
de55252a 7554 /* Decide if we should generate indirect calls by loading the
85c36fd1 7555 32-bit address of the callee into a register before performing the
de55252a 7556 branch and link. */
7557 callee = XEXP (operands[0], 0);
7558 if (GET_CODE (callee) == SYMBOL_REF
7559 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
7560 : !REG_P (callee))
bbe777ea 7561 XEXP (operands[0], 0) = force_reg (Pmode, callee);
bac7fc85 7562
7563 pat = gen_call_internal (operands[0], operands[1], operands[2]);
ca373797 7564 arm_emit_call_insn (pat, XEXP (operands[0], 0), false);
bac7fc85 7565 DONE;
6c4c2133 7566 }"
7567)
d3373b54 7568
bac7fc85 7569(define_expand "call_internal"
7570 [(parallel [(call (match_operand 0 "memory_operand" "")
7571 (match_operand 1 "general_operand" ""))
7572 (use (match_operand 2 "" ""))
7573 (clobber (reg:SI LR_REGNUM))])])
7574
f1039640 7575(define_insn "*call_reg_armv5"
d3373b54 7576 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
cffb2a26 7577 (match_operand 1 "" ""))
7578 (use (match_operand 2 "" ""))
bd5b4116 7579 (clobber (reg:SI LR_REGNUM))]
33ae7c4b 7580 "TARGET_ARM && arm_arch5 && !SIBLING_CALL_P (insn)"
f1039640 7581 "blx%?\\t%0"
7582 [(set_attr "type" "call")]
7583)
7584
7585(define_insn "*call_reg_arm"
7586 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7587 (match_operand 1 "" ""))
7588 (use (match_operand 2 "" ""))
7589 (clobber (reg:SI LR_REGNUM))]
33ae7c4b 7590 "TARGET_ARM && !arm_arch5 && !SIBLING_CALL_P (insn)"
9c08d1fa 7591 "*
5565501b 7592 return output_call (operands);
cffb2a26 7593 "
7594 ;; length is worst case, normally it is only two
7595 [(set_attr "length" "12")
7596 (set_attr "type" "call")]
7597)
9c08d1fa 7598
89504fc1 7599
7600;; Note: not used for armv5+ because the sequence used (ldr pc, ...) is not
7601;; considered a function call by the branch predictor of some cores (PR40887).
7602;; Falls back to blx rN (*call_reg_armv5).
7603
f7fbdd4a 7604(define_insn "*call_mem"
a3c63a9d 7605 [(call (mem:SI (match_operand:SI 0 "call_memory_operand" "m"))
cffb2a26 7606 (match_operand 1 "" ""))
7607 (use (match_operand 2 "" ""))
bd5b4116 7608 (clobber (reg:SI LR_REGNUM))]
33ae7c4b 7609 "TARGET_ARM && !arm_arch5 && !SIBLING_CALL_P (insn)"
9c08d1fa 7610 "*
5565501b 7611 return output_call_mem (operands);
cffb2a26 7612 "
7613 [(set_attr "length" "12")
7614 (set_attr "type" "call")]
7615)
7616
d3373b54 7617(define_expand "call_value"
e0698af7 7618 [(parallel [(set (match_operand 0 "" "")
7619 (call (match_operand 1 "memory_operand" "")
7620 (match_operand 2 "general_operand" "")))
cffb2a26 7621 (use (match_operand 3 "" ""))
bd5b4116 7622 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 7623 "TARGET_EITHER"
6c4c2133 7624 "
7625 {
bac7fc85 7626 rtx pat, callee;
bbe777ea 7627
7628 /* In an untyped call, we can get NULL for operand 2. */
7629 if (operands[3] == 0)
7630 operands[3] = const0_rtx;
7631
de55252a 7632 /* Decide if we should generate indirect calls by loading the
7633 32-bit address of the callee into a register before performing the
7634 branch and link. */
7635 callee = XEXP (operands[1], 0);
7636 if (GET_CODE (callee) == SYMBOL_REF
7637 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
7638 : !REG_P (callee))
78fe751b 7639 XEXP (operands[1], 0) = force_reg (Pmode, callee);
bac7fc85 7640
7641 pat = gen_call_value_internal (operands[0], operands[1],
7642 operands[2], operands[3]);
ca373797 7643 arm_emit_call_insn (pat, XEXP (operands[1], 0), false);
bac7fc85 7644 DONE;
6c4c2133 7645 }"
7646)
d3373b54 7647
bac7fc85 7648(define_expand "call_value_internal"
7649 [(parallel [(set (match_operand 0 "" "")
7650 (call (match_operand 1 "memory_operand" "")
7651 (match_operand 2 "general_operand" "")))
7652 (use (match_operand 3 "" ""))
7653 (clobber (reg:SI LR_REGNUM))])])
7654
f1039640 7655(define_insn "*call_value_reg_armv5"
27ed6835 7656 [(set (match_operand 0 "" "")
755eb2b4 7657 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
cffb2a26 7658 (match_operand 2 "" "")))
bbe777ea 7659 (use (match_operand 3 "" ""))
bd5b4116 7660 (clobber (reg:SI LR_REGNUM))]
33ae7c4b 7661 "TARGET_ARM && arm_arch5 && !SIBLING_CALL_P (insn)"
f1039640 7662 "blx%?\\t%1"
7663 [(set_attr "type" "call")]
7664)
7665
7666(define_insn "*call_value_reg_arm"
7667 [(set (match_operand 0 "" "")
7668 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7669 (match_operand 2 "" "")))
7670 (use (match_operand 3 "" ""))
7671 (clobber (reg:SI LR_REGNUM))]
33ae7c4b 7672 "TARGET_ARM && !arm_arch5 && !SIBLING_CALL_P (insn)"
9c08d1fa 7673 "*
215b30b3 7674 return output_call (&operands[1]);
cffb2a26 7675 "
7676 [(set_attr "length" "12")
7677 (set_attr "type" "call")]
7678)
9c08d1fa 7679
89504fc1 7680;; Note: see *call_mem
7681
f7fbdd4a 7682(define_insn "*call_value_mem"
27ed6835 7683 [(set (match_operand 0 "" "")
a3c63a9d 7684 (call (mem:SI (match_operand:SI 1 "call_memory_operand" "m"))
cffb2a26 7685 (match_operand 2 "" "")))
bbe777ea 7686 (use (match_operand 3 "" ""))
bd5b4116 7687 (clobber (reg:SI LR_REGNUM))]
33ae7c4b 7688 "TARGET_ARM && !arm_arch5 && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
7689 && !SIBLING_CALL_P (insn)"
9c08d1fa 7690 "*
215b30b3 7691 return output_call_mem (&operands[1]);
cffb2a26 7692 "
7693 [(set_attr "length" "12")
7694 (set_attr "type" "call")]
7695)
9c08d1fa 7696
7697;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
7698;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
7699
f7fbdd4a 7700(define_insn "*call_symbol"
27ed6835 7701 [(call (mem:SI (match_operand:SI 0 "" ""))
cffb2a26 7702 (match_operand 1 "" ""))
bbe777ea 7703 (use (match_operand 2 "" ""))
bd5b4116 7704 (clobber (reg:SI LR_REGNUM))]
d68c2c10 7705 "TARGET_32BIT
33ae7c4b 7706 && !SIBLING_CALL_P (insn)
cffb2a26 7707 && (GET_CODE (operands[0]) == SYMBOL_REF)
de55252a 7708 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
6ebaa29d 7709 "*
7710 {
55c1e470 7711 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
6ebaa29d 7712 }"
cffb2a26 7713 [(set_attr "type" "call")]
7714)
9c08d1fa 7715
f7fbdd4a 7716(define_insn "*call_value_symbol"
ccd90aaa 7717 [(set (match_operand 0 "" "")
27ed6835 7718 (call (mem:SI (match_operand:SI 1 "" ""))
dd6d7504 7719 (match_operand:SI 2 "" "")))
bbe777ea 7720 (use (match_operand 3 "" ""))
bd5b4116 7721 (clobber (reg:SI LR_REGNUM))]
d68c2c10 7722 "TARGET_32BIT
33ae7c4b 7723 && !SIBLING_CALL_P (insn)
cffb2a26 7724 && (GET_CODE (operands[1]) == SYMBOL_REF)
de55252a 7725 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
6ebaa29d 7726 "*
7727 {
55c1e470 7728 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
6ebaa29d 7729 }"
cffb2a26 7730 [(set_attr "type" "call")]
7731)
7732
ca373797 7733(define_expand "sibcall_internal"
7734 [(parallel [(call (match_operand 0 "memory_operand" "")
7735 (match_operand 1 "general_operand" ""))
7736 (return)
7737 (use (match_operand 2 "" ""))])])
7738
1c494086 7739;; We may also be able to do sibcalls for Thumb, but it's much harder...
7740(define_expand "sibcall"
7741 [(parallel [(call (match_operand 0 "memory_operand" "")
7742 (match_operand 1 "general_operand" ""))
2ba80634 7743 (return)
7744 (use (match_operand 2 "" ""))])]
d68c2c10 7745 "TARGET_32BIT"
1c494086 7746 "
7747 {
ca373797 7748 rtx pat;
7749
3112c3f7 7750 if ((!REG_P (XEXP (operands[0], 0))
7751 && GET_CODE (XEXP (operands[0], 0)) != SYMBOL_REF)
7752 || (GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
7753 && arm_is_long_call_p (SYMBOL_REF_DECL (XEXP (operands[0], 0)))))
33ae7c4b 7754 XEXP (operands[0], 0) = force_reg (SImode, XEXP (operands[0], 0));
7755
1c494086 7756 if (operands[2] == NULL_RTX)
7757 operands[2] = const0_rtx;
ca373797 7758
7759 pat = gen_sibcall_internal (operands[0], operands[1], operands[2]);
7760 arm_emit_call_insn (pat, operands[0], true);
7761 DONE;
1c494086 7762 }"
7763)
7764
ca373797 7765(define_expand "sibcall_value_internal"
7766 [(parallel [(set (match_operand 0 "" "")
7767 (call (match_operand 1 "memory_operand" "")
7768 (match_operand 2 "general_operand" "")))
7769 (return)
7770 (use (match_operand 3 "" ""))])])
7771
1c494086 7772(define_expand "sibcall_value"
ccd90aaa 7773 [(parallel [(set (match_operand 0 "" "")
1c494086 7774 (call (match_operand 1 "memory_operand" "")
7775 (match_operand 2 "general_operand" "")))
2ba80634 7776 (return)
7777 (use (match_operand 3 "" ""))])]
d68c2c10 7778 "TARGET_32BIT"
1c494086 7779 "
7780 {
ca373797 7781 rtx pat;
7782
3112c3f7 7783 if ((!REG_P (XEXP (operands[1], 0))
7784 && GET_CODE (XEXP (operands[1], 0)) != SYMBOL_REF)
7785 || (GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
7786 && arm_is_long_call_p (SYMBOL_REF_DECL (XEXP (operands[1], 0)))))
33ae7c4b 7787 XEXP (operands[1], 0) = force_reg (SImode, XEXP (operands[1], 0));
7788
1c494086 7789 if (operands[3] == NULL_RTX)
7790 operands[3] = const0_rtx;
ca373797 7791
7792 pat = gen_sibcall_value_internal (operands[0], operands[1],
7793 operands[2], operands[3]);
7794 arm_emit_call_insn (pat, operands[1], true);
7795 DONE;
1c494086 7796 }"
7797)
7798
7799(define_insn "*sibcall_insn"
84ce8e5c 7800 [(call (mem:SI (match_operand:SI 0 "call_insn_operand" "Cs, US"))
1c494086 7801 (match_operand 1 "" ""))
2ba80634 7802 (return)
7803 (use (match_operand 2 "" ""))]
33ae7c4b 7804 "TARGET_32BIT && SIBLING_CALL_P (insn)"
1c494086 7805 "*
33ae7c4b 7806 if (which_alternative == 1)
7807 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
7808 else
7809 {
7810 if (arm_arch5 || arm_arch4t)
947d113e 7811 return \"bx%?\\t%0\\t%@ indirect register sibling call\";
33ae7c4b 7812 else
7813 return \"mov%?\\t%|pc, %0\\t%@ indirect register sibling call\";
7814 }
1c494086 7815 "
7816 [(set_attr "type" "call")]
7817)
7818
7819(define_insn "*sibcall_value_insn"
84ce8e5c 7820 [(set (match_operand 0 "" "")
7821 (call (mem:SI (match_operand:SI 1 "call_insn_operand" "Cs,US"))
1c494086 7822 (match_operand 2 "" "")))
2ba80634 7823 (return)
7824 (use (match_operand 3 "" ""))]
33ae7c4b 7825 "TARGET_32BIT && SIBLING_CALL_P (insn)"
1c494086 7826 "*
33ae7c4b 7827 if (which_alternative == 1)
7828 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
7829 else
7830 {
7831 if (arm_arch5 || arm_arch4t)
84ce8e5c 7832 return \"bx%?\\t%1\";
33ae7c4b 7833 else
7834 return \"mov%?\\t%|pc, %1\\t@ indirect sibling call \";
7835 }
1c494086 7836 "
7837 [(set_attr "type" "call")]
7838)
7839
0686440e 7840(define_expand "<return_str>return"
7841 [(returns)]
8cba51a5 7842 "(TARGET_ARM || (TARGET_THUMB2
7843 && ARM_FUNC_TYPE (arm_current_func_type ()) == ARM_FT_NORMAL
7844 && !IS_STACKALIGN (arm_current_func_type ())))
0686440e 7845 <return_cond_false>"
8cba51a5 7846 "
7847 {
7848 if (TARGET_THUMB2)
7849 {
0686440e 7850 thumb2_expand_return (<return_simple_p>);
8cba51a5 7851 DONE;
7852 }
7853 }
7854 "
7855)
d68c2c10 7856
9c08d1fa 7857;; Often the return insn will be the same as loading from memory, so set attr
d68c2c10 7858(define_insn "*arm_return"
9c08d1fa 7859 [(return)]
cffb2a26 7860 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
9c08d1fa 7861 "*
9c08d1fa 7862 {
cffb2a26 7863 if (arm_ccfsm_state == 2)
7864 {
7865 arm_ccfsm_state += 2;
7866 return \"\";
7867 }
e2549f81 7868 return output_return_instruction (const_true_rtx, true, false, false);
cffb2a26 7869 }"
a2cd141b 7870 [(set_attr "type" "load1")
755eb2b4 7871 (set_attr "length" "12")
0d66636f 7872 (set_attr "predicable" "yes")]
cffb2a26 7873)
9c08d1fa 7874
0686440e 7875(define_insn "*cond_<return_str>return"
9c08d1fa 7876 [(set (pc)
8fa3ba89 7877 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 7878 [(match_operand 1 "cc_register" "") (const_int 0)])
0686440e 7879 (returns)
9c08d1fa 7880 (pc)))]
0686440e 7881 "TARGET_ARM <return_cond_true>"
9c08d1fa 7882 "*
8fa3ba89 7883 {
7884 if (arm_ccfsm_state == 2)
7885 {
7886 arm_ccfsm_state += 2;
7887 return \"\";
7888 }
0686440e 7889 return output_return_instruction (operands[0], true, false,
7890 <return_simple_p>);
8fa3ba89 7891 }"
7892 [(set_attr "conds" "use")
755eb2b4 7893 (set_attr "length" "12")
a2cd141b 7894 (set_attr "type" "load1")]
8fa3ba89 7895)
9c08d1fa 7896
0686440e 7897(define_insn "*cond_<return_str>return_inverted"
9c08d1fa 7898 [(set (pc)
8fa3ba89 7899 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 7900 [(match_operand 1 "cc_register" "") (const_int 0)])
9c08d1fa 7901 (pc)
0686440e 7902 (returns)))]
7903 "TARGET_ARM <return_cond_true>"
9c08d1fa 7904 "*
8fa3ba89 7905 {
7906 if (arm_ccfsm_state == 2)
7907 {
7908 arm_ccfsm_state += 2;
7909 return \"\";
7910 }
0686440e 7911 return output_return_instruction (operands[0], true, true,
7912 <return_simple_p>);
8fa3ba89 7913 }"
7914 [(set_attr "conds" "use")
37a1317b 7915 (set_attr "length" "12")
a2cd141b 7916 (set_attr "type" "load1")]
8fa3ba89 7917)
9c08d1fa 7918
e2549f81 7919(define_insn "*arm_simple_return"
7920 [(simple_return)]
7921 "TARGET_ARM"
7922 "*
7923 {
7924 if (arm_ccfsm_state == 2)
7925 {
7926 arm_ccfsm_state += 2;
7927 return \"\";
7928 }
7929 return output_return_instruction (const_true_rtx, true, false, true);
7930 }"
7931 [(set_attr "type" "branch")
7932 (set_attr "length" "4")
7933 (set_attr "predicable" "yes")]
7934)
7935
68121397 7936;; Generate a sequence of instructions to determine if the processor is
7937;; in 26-bit or 32-bit mode, and return the appropriate return address
7938;; mask.
7939
7940(define_expand "return_addr_mask"
7941 [(set (match_dup 1)
7942 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7943 (const_int 0)))
7944 (set (match_operand:SI 0 "s_register_operand" "")
7945 (if_then_else:SI (eq (match_dup 1) (const_int 0))
7946 (const_int -1)
7947 (const_int 67108860)))] ; 0x03fffffc
7948 "TARGET_ARM"
7949 "
62eddbd4 7950 operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
68121397 7951 ")
7952
7953(define_insn "*check_arch2"
7954 [(set (match_operand:CC_NOOV 0 "cc_register" "")
7955 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7956 (const_int 0)))]
7957 "TARGET_ARM"
7958 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
7959 [(set_attr "length" "8")
1b7da4ac 7960 (set_attr "conds" "set")
7961 (set_attr "type" "multiple")]
68121397 7962)
7963
9c08d1fa 7964;; Call subroutine returning any type.
7965
7966(define_expand "untyped_call"
7967 [(parallel [(call (match_operand 0 "" "")
7968 (const_int 0))
7969 (match_operand 1 "" "")
7970 (match_operand 2 "" "")])]
ccd90aaa 7971 "TARGET_EITHER"
9c08d1fa 7972 "
215b30b3 7973 {
7974 int i;
ccd90aaa 7975 rtx par = gen_rtx_PARALLEL (VOIDmode,
7976 rtvec_alloc (XVECLEN (operands[2], 0)));
7977 rtx addr = gen_reg_rtx (Pmode);
7978 rtx mem;
7979 int size = 0;
9c08d1fa 7980
ccd90aaa 7981 emit_move_insn (addr, XEXP (operands[1], 0));
7982 mem = change_address (operands[1], BLKmode, addr);
9c08d1fa 7983
215b30b3 7984 for (i = 0; i < XVECLEN (operands[2], 0); i++)
7985 {
ccd90aaa 7986 rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
9c08d1fa 7987
ccd90aaa 7988 /* Default code only uses r0 as a return value, but we could
7989 be using anything up to 4 registers. */
7990 if (REGNO (src) == R0_REGNUM)
7991 src = gen_rtx_REG (TImode, R0_REGNUM);
7992
7993 XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
7994 GEN_INT (size));
7995 size += GET_MODE_SIZE (GET_MODE (src));
7996 }
7997
7998 emit_call_insn (GEN_CALL_VALUE (par, operands[0], const0_rtx, NULL,
7999 const0_rtx));
8000
8001 size = 0;
8002
8003 for (i = 0; i < XVECLEN (par, 0); i++)
8004 {
8005 HOST_WIDE_INT offset = 0;
8006 rtx reg = XEXP (XVECEXP (par, 0, i), 0);
8007
8008 if (size != 0)
29c05e22 8009 emit_move_insn (addr, plus_constant (Pmode, addr, size));
ccd90aaa 8010
8011 mem = change_address (mem, GET_MODE (reg), NULL);
8012 if (REGNO (reg) == R0_REGNUM)
8013 {
8014 /* On thumb we have to use a write-back instruction. */
320ea44d 8015 emit_insn (arm_gen_store_multiple (arm_regs_in_sequence, 4, addr,
8016 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
ccd90aaa 8017 size = TARGET_ARM ? 16 : 0;
8018 }
8019 else
8020 {
8021 emit_move_insn (mem, reg);
8022 size = GET_MODE_SIZE (GET_MODE (reg));
8023 }
215b30b3 8024 }
9c08d1fa 8025
215b30b3 8026 /* The optimizer does not know that the call sets the function value
8027 registers we stored in the result block. We avoid problems by
8028 claiming that all hard registers are used and clobbered at this
8029 point. */
8030 emit_insn (gen_blockage ());
8031
8032 DONE;
8033 }"
8034)
9c08d1fa 8035
ccd90aaa 8036(define_expand "untyped_return"
8037 [(match_operand:BLK 0 "memory_operand" "")
8038 (match_operand 1 "" "")]
8039 "TARGET_EITHER"
8040 "
8041 {
8042 int i;
8043 rtx addr = gen_reg_rtx (Pmode);
8044 rtx mem;
8045 int size = 0;
8046
8047 emit_move_insn (addr, XEXP (operands[0], 0));
8048 mem = change_address (operands[0], BLKmode, addr);
8049
8050 for (i = 0; i < XVECLEN (operands[1], 0); i++)
8051 {
8052 HOST_WIDE_INT offset = 0;
8053 rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
8054
8055 if (size != 0)
29c05e22 8056 emit_move_insn (addr, plus_constant (Pmode, addr, size));
ccd90aaa 8057
8058 mem = change_address (mem, GET_MODE (reg), NULL);
8059 if (REGNO (reg) == R0_REGNUM)
8060 {
8061 /* On thumb we have to use a write-back instruction. */
320ea44d 8062 emit_insn (arm_gen_load_multiple (arm_regs_in_sequence, 4, addr,
8063 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
ccd90aaa 8064 size = TARGET_ARM ? 16 : 0;
8065 }
8066 else
8067 {
8068 emit_move_insn (reg, mem);
8069 size = GET_MODE_SIZE (GET_MODE (reg));
8070 }
8071 }
8072
8073 /* Emit USE insns before the return. */
8074 for (i = 0; i < XVECLEN (operands[1], 0); i++)
18b42941 8075 emit_use (SET_DEST (XVECEXP (operands[1], 0, i)));
ccd90aaa 8076
8077 /* Construct the return. */
8078 expand_naked_return ();
8079
8080 DONE;
8081 }"
8082)
8083
9c08d1fa 8084;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
8085;; all of memory. This blocks insns from being moved across this point.
8086
8087(define_insn "blockage"
e1159bbe 8088 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
cffb2a26 8089 "TARGET_EITHER"
9c08d1fa 8090 ""
cffb2a26 8091 [(set_attr "length" "0")
8092 (set_attr "type" "block")]
8093)
9c08d1fa 8094
f7fbdd4a 8095(define_expand "casesi"
8096 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
aea4c774 8097 (match_operand:SI 1 "const_int_operand" "") ; lower bound
8098 (match_operand:SI 2 "const_int_operand" "") ; total range
f7fbdd4a 8099 (match_operand:SI 3 "" "") ; table label
8100 (match_operand:SI 4 "" "")] ; Out of range label
e6ac8414 8101 "TARGET_32BIT || optimize_size || flag_pic"
f7fbdd4a 8102 "
215b30b3 8103 {
e6ac8414 8104 enum insn_code code;
215b30b3 8105 if (operands[1] != const0_rtx)
8106 {
e6ac8414 8107 rtx reg = gen_reg_rtx (SImode);
f7fbdd4a 8108
215b30b3 8109 emit_insn (gen_addsi3 (reg, operands[0],
d022fa24 8110 gen_int_mode (-INTVAL (operands[1]),
8111 SImode)));
215b30b3 8112 operands[0] = reg;
8113 }
9c08d1fa 8114
25f905c2 8115 if (TARGET_ARM)
e6ac8414 8116 code = CODE_FOR_arm_casesi_internal;
3db2019b 8117 else if (TARGET_THUMB1)
e6ac8414 8118 code = CODE_FOR_thumb1_casesi_internal_pic;
25f905c2 8119 else if (flag_pic)
e6ac8414 8120 code = CODE_FOR_thumb2_casesi_internal_pic;
25f905c2 8121 else
e6ac8414 8122 code = CODE_FOR_thumb2_casesi_internal;
8123
8124 if (!insn_data[(int) code].operand[1].predicate(operands[2], SImode))
8125 operands[2] = force_reg (SImode, operands[2]);
8126
8127 emit_jump_insn (GEN_FCN ((int) code) (operands[0], operands[2],
8128 operands[3], operands[4]));
215b30b3 8129 DONE;
8130 }"
8131)
f7fbdd4a 8132
f082f1c4 8133;; The USE in this pattern is needed to tell flow analysis that this is
8134;; a CASESI insn. It has no other purpose.
25f905c2 8135(define_insn "arm_casesi_internal"
f082f1c4 8136 [(parallel [(set (pc)
8137 (if_then_else
8138 (leu (match_operand:SI 0 "s_register_operand" "r")
8139 (match_operand:SI 1 "arm_rhs_operand" "rI"))
8140 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
8141 (label_ref (match_operand 2 "" ""))))
8142 (label_ref (match_operand 3 "" ""))))
bd5b4116 8143 (clobber (reg:CC CC_REGNUM))
f082f1c4 8144 (use (label_ref (match_dup 2)))])]
cffb2a26 8145 "TARGET_ARM"
f7fbdd4a 8146 "*
0d66636f 8147 if (flag_pic)
8148 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
8149 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
8150 "
8151 [(set_attr "conds" "clob")
1b7da4ac 8152 (set_attr "length" "12")
8153 (set_attr "type" "multiple")]
0d66636f 8154)
9c08d1fa 8155
cffb2a26 8156(define_expand "indirect_jump"
9c08d1fa 8157 [(set (pc)
cffb2a26 8158 (match_operand:SI 0 "s_register_operand" ""))]
8159 "TARGET_EITHER"
25f905c2 8160 "
8161 /* Thumb-2 doesn't have mov pc, reg. Explicitly set the low bit of the
8162 address and use bx. */
8163 if (TARGET_THUMB2)
8164 {
8165 rtx tmp;
8166 tmp = gen_reg_rtx (SImode);
8167 emit_insn (gen_iorsi3 (tmp, operands[0], GEN_INT(1)));
8168 operands[0] = tmp;
8169 }
8170 "
cffb2a26 8171)
8172
f1039640 8173;; NB Never uses BX.
cffb2a26 8174(define_insn "*arm_indirect_jump"
8175 [(set (pc)
8176 (match_operand:SI 0 "s_register_operand" "r"))]
8177 "TARGET_ARM"
8178 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
1b7da4ac 8179 [(set_attr "predicable" "yes")
8180 (set_attr "type" "branch")]
cffb2a26 8181)
9c08d1fa 8182
f7fbdd4a 8183(define_insn "*load_indirect_jump"
9c08d1fa 8184 [(set (pc)
8185 (match_operand:SI 0 "memory_operand" "m"))]
cffb2a26 8186 "TARGET_ARM"
8187 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
a2cd141b 8188 [(set_attr "type" "load1")
61a2d04c 8189 (set_attr "pool_range" "4096")
8190 (set_attr "neg_pool_range" "4084")
0d66636f 8191 (set_attr "predicable" "yes")]
cffb2a26 8192)
8193
9c08d1fa 8194\f
8195;; Misc insns
8196
8197(define_insn "nop"
8198 [(const_int 0)]
cffb2a26 8199 "TARGET_EITHER"
8200 "*
25f905c2 8201 if (TARGET_UNIFIED_ASM)
8202 return \"nop\";
cffb2a26 8203 if (TARGET_ARM)
8204 return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
8205 return \"mov\\tr8, r8\";
8206 "
8207 [(set (attr "length")
8208 (if_then_else (eq_attr "is_thumb" "yes")
8209 (const_int 2)
1b7da4ac 8210 (const_int 4)))
8211 (set_attr "type" "mov_reg")]
cffb2a26 8212)
8213
ad9d4399 8214(define_insn "trap"
8215 [(trap_if (const_int 1) (const_int 0))]
8216 ""
8217 "*
8218 if (TARGET_ARM)
8219 return \".inst\\t0xe7f000f0\";
8220 else
8221 return \".inst\\t0xdeff\";
8222 "
8223 [(set (attr "length")
8224 (if_then_else (eq_attr "is_thumb" "yes")
8225 (const_int 2)
8226 (const_int 4)))
8227 (set_attr "type" "trap")
8228 (set_attr "conds" "unconditional")]
8229)
8230
9c08d1fa 8231\f
8232;; Patterns to allow combination of arithmetic, cond code and shifts
8233
0abea32c 8234(define_insn "*<arith_shift_insn>_multsi"
8235 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8236 (shiftable_ops:SI
8237 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
8238 (match_operand:SI 3 "power_of_two_operand" ""))
8239 (match_operand:SI 1 "s_register_operand" "rk,<t2_binop0>")))]
d5d4dc8d 8240 "TARGET_32BIT"
0abea32c 8241 "<arith_shift_insn>%?\\t%0, %1, %2, lsl %b3"
8242 [(set_attr "predicable" "yes")
8243 (set_attr "predicable_short_it" "no")
8244 (set_attr "shift" "4")
8245 (set_attr "arch" "a,t2")
8246 (set_attr "type" "alu_shift_imm")])
8247
8248(define_insn "*<arith_shift_insn>_shiftsi"
8249 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8250 (shiftable_ops:SI
8251 (match_operator:SI 2 "shift_nomul_operator"
8252 [(match_operand:SI 3 "s_register_operand" "r,r,r")
8253 (match_operand:SI 4 "shift_amount_operand" "M,M,r")])
8254 (match_operand:SI 1 "s_register_operand" "rk,<t2_binop0>,rk")))]
8255 "TARGET_32BIT && GET_CODE (operands[3]) != MULT"
8256 "<arith_shift_insn>%?\\t%0, %1, %3%S2"
344495ea 8257 [(set_attr "predicable" "yes")
74ef923b 8258 (set_attr "predicable_short_it" "no")
331beb1a 8259 (set_attr "shift" "4")
0abea32c 8260 (set_attr "arch" "a,t2,a")
8261 (set_attr "type" "alu_shift_imm,alu_shift_imm,alu_shift_reg")])
9c08d1fa 8262
d7863cfe 8263(define_split
8264 [(set (match_operand:SI 0 "s_register_operand" "")
8265 (match_operator:SI 1 "shiftable_operator"
8266 [(match_operator:SI 2 "shiftable_operator"
8267 [(match_operator:SI 3 "shift_operator"
8268 [(match_operand:SI 4 "s_register_operand" "")
8269 (match_operand:SI 5 "reg_or_int_operand" "")])
8270 (match_operand:SI 6 "s_register_operand" "")])
8271 (match_operand:SI 7 "arm_rhs_operand" "")]))
8272 (clobber (match_operand:SI 8 "s_register_operand" ""))]
d5d4dc8d 8273 "TARGET_32BIT"
d7863cfe 8274 [(set (match_dup 8)
8275 (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8276 (match_dup 6)]))
8277 (set (match_dup 0)
8278 (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
8279 "")
8280
f7fbdd4a 8281(define_insn "*arith_shiftsi_compare0"
bd5b4116 8282 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 8283 (compare:CC_NOOV
8284 (match_operator:SI 1 "shiftable_operator"
8285 [(match_operator:SI 3 "shift_operator"
8286 [(match_operand:SI 4 "s_register_operand" "r,r")
8287 (match_operand:SI 5 "shift_amount_operand" "M,r")])
8288 (match_operand:SI 2 "s_register_operand" "r,r")])
8289 (const_int 0)))
8290 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 8291 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8292 (match_dup 2)]))]
d5d4dc8d 8293 "TARGET_32BIT"
25f905c2 8294 "%i1%.\\t%0, %2, %4%S3"
344495ea 8295 [(set_attr "conds" "set")
331beb1a 8296 (set_attr "shift" "4")
d5d4dc8d 8297 (set_attr "arch" "32,a")
d82e788e 8298 (set_attr "type" "alus_shift_imm,alus_shift_reg")])
9c08d1fa 8299
f7fbdd4a 8300(define_insn "*arith_shiftsi_compare0_scratch"
bd5b4116 8301 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 8302 (compare:CC_NOOV
8303 (match_operator:SI 1 "shiftable_operator"
8304 [(match_operator:SI 3 "shift_operator"
8305 [(match_operand:SI 4 "s_register_operand" "r,r")
8306 (match_operand:SI 5 "shift_amount_operand" "M,r")])
8307 (match_operand:SI 2 "s_register_operand" "r,r")])
8308 (const_int 0)))
8309 (clobber (match_scratch:SI 0 "=r,r"))]
8310 "TARGET_32BIT"
25f905c2 8311 "%i1%.\\t%0, %2, %4%S3"
344495ea 8312 [(set_attr "conds" "set")
331beb1a 8313 (set_attr "shift" "4")
d5d4dc8d 8314 (set_attr "arch" "32,a")
d82e788e 8315 (set_attr "type" "alus_shift_imm,alus_shift_reg")])
9c08d1fa 8316
f7fbdd4a 8317(define_insn "*sub_shiftsi"
d5d4dc8d 8318 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8319 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
9c08d1fa 8320 (match_operator:SI 2 "shift_operator"
d5d4dc8d 8321 [(match_operand:SI 3 "s_register_operand" "r,r")
8322 (match_operand:SI 4 "shift_amount_operand" "M,r")])))]
8323 "TARGET_32BIT"
6c4c2133 8324 "sub%?\\t%0, %1, %3%S2"
344495ea 8325 [(set_attr "predicable" "yes")
331beb1a 8326 (set_attr "shift" "3")
d5d4dc8d 8327 (set_attr "arch" "32,a")
d82e788e 8328 (set_attr "type" "alus_shift_imm,alus_shift_reg")])
9c08d1fa 8329
f7fbdd4a 8330(define_insn "*sub_shiftsi_compare0"
bd5b4116 8331 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 8332 (compare:CC_NOOV
d82e788e 8333 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
40dbec34 8334 (match_operator:SI 2 "shift_operator"
d82e788e 8335 [(match_operand:SI 3 "s_register_operand" "r,r,r")
8336 (match_operand:SI 4 "shift_amount_operand" "M,r,M")]))
40dbec34 8337 (const_int 0)))
d82e788e 8338 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
d5d4dc8d 8339 (minus:SI (match_dup 1)
8340 (match_op_dup 2 [(match_dup 3) (match_dup 4)])))]
8341 "TARGET_32BIT"
25f905c2 8342 "sub%.\\t%0, %1, %3%S2"
344495ea 8343 [(set_attr "conds" "set")
a2cd141b 8344 (set_attr "shift" "3")
d82e788e 8345 (set_attr "arch" "32,a,a")
8346 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
9c08d1fa 8347
f7fbdd4a 8348(define_insn "*sub_shiftsi_compare0_scratch"
bd5b4116 8349 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 8350 (compare:CC_NOOV
d82e788e 8351 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
40dbec34 8352 (match_operator:SI 2 "shift_operator"
d82e788e 8353 [(match_operand:SI 3 "s_register_operand" "r,r,r")
8354 (match_operand:SI 4 "shift_amount_operand" "M,r,M")]))
40dbec34 8355 (const_int 0)))
d82e788e 8356 (clobber (match_scratch:SI 0 "=r,r,r"))]
d5d4dc8d 8357 "TARGET_32BIT"
25f905c2 8358 "sub%.\\t%0, %1, %3%S2"
344495ea 8359 [(set_attr "conds" "set")
a2cd141b 8360 (set_attr "shift" "3")
d82e788e 8361 (set_attr "arch" "32,a,a")
8362 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
9c08d1fa 8363\f
8364
190efb17 8365(define_insn_and_split "*and_scc"
9c08d1fa 8366 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 8367 (and:SI (match_operator:SI 1 "arm_comparison_operator"
190efb17 8368 [(match_operand 2 "cc_register" "") (const_int 0)])
8369 (match_operand:SI 3 "s_register_operand" "r")))]
cffb2a26 8370 "TARGET_ARM"
190efb17 8371 "#" ; "mov%D1\\t%0, #0\;and%d1\\t%0, %3, #1"
8372 "&& reload_completed"
8373 [(cond_exec (match_dup 5) (set (match_dup 0) (const_int 0)))
8374 (cond_exec (match_dup 4) (set (match_dup 0)
8375 (and:SI (match_dup 3) (const_int 1))))]
8376 {
8377 enum machine_mode mode = GET_MODE (operands[2]);
8378 enum rtx_code rc = GET_CODE (operands[1]);
8379
8380 /* Note that operands[4] is the same as operands[1],
8381 but with VOIDmode as the result. */
8382 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
8383 if (mode == CCFPmode || mode == CCFPEmode)
8384 rc = reverse_condition_maybe_unordered (rc);
8385 else
8386 rc = reverse_condition (rc);
8387 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
8388 }
8fa3ba89 8389 [(set_attr "conds" "use")
1b7da4ac 8390 (set_attr "type" "multiple")
8fa3ba89 8391 (set_attr "length" "8")]
8392)
9c08d1fa 8393
190efb17 8394(define_insn_and_split "*ior_scc"
9c08d1fa 8395 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
190efb17 8396 (ior:SI (match_operator:SI 1 "arm_comparison_operator"
8397 [(match_operand 2 "cc_register" "") (const_int 0)])
8398 (match_operand:SI 3 "s_register_operand" "0,?r")))]
cffb2a26 8399 "TARGET_ARM"
e2348bcb 8400 "@
190efb17 8401 orr%d1\\t%0, %3, #1
8402 #"
8403 "&& reload_completed
8404 && REGNO (operands [0]) != REGNO (operands[3])"
8405 ;; && which_alternative == 1
8406 ; mov%D1\\t%0, %3\;orr%d1\\t%0, %3, #1
8407 [(cond_exec (match_dup 5) (set (match_dup 0) (match_dup 3)))
8408 (cond_exec (match_dup 4) (set (match_dup 0)
8409 (ior:SI (match_dup 3) (const_int 1))))]
8410 {
8411 enum machine_mode mode = GET_MODE (operands[2]);
8412 enum rtx_code rc = GET_CODE (operands[1]);
8413
8414 /* Note that operands[4] is the same as operands[1],
8415 but with VOIDmode as the result. */
8416 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
8417 if (mode == CCFPmode || mode == CCFPEmode)
8418 rc = reverse_condition_maybe_unordered (rc);
8419 else
8420 rc = reverse_condition (rc);
8421 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
8422 }
8fa3ba89 8423 [(set_attr "conds" "use")
1b7da4ac 8424 (set_attr "length" "4,8")
8425 (set_attr "type" "logic_imm,multiple")]
8fa3ba89 8426)
9c08d1fa 8427
2df9477b 8428; A series of splitters for the compare_scc pattern below. Note that
8429; order is important.
8430(define_split
8431 [(set (match_operand:SI 0 "s_register_operand" "")
8432 (lt:SI (match_operand:SI 1 "s_register_operand" "")
8433 (const_int 0)))
8434 (clobber (reg:CC CC_REGNUM))]
8435 "TARGET_32BIT && reload_completed"
8436 [(set (match_dup 0) (lshiftrt:SI (match_dup 1) (const_int 31)))])
8437
8438(define_split
8439 [(set (match_operand:SI 0 "s_register_operand" "")
8440 (ge:SI (match_operand:SI 1 "s_register_operand" "")
8441 (const_int 0)))
8442 (clobber (reg:CC CC_REGNUM))]
8443 "TARGET_32BIT && reload_completed"
8444 [(set (match_dup 0) (not:SI (match_dup 1)))
8445 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 31)))])
8446
98562479 8447(define_split
8448 [(set (match_operand:SI 0 "s_register_operand" "")
8449 (eq:SI (match_operand:SI 1 "s_register_operand" "")
8450 (const_int 0)))
8451 (clobber (reg:CC CC_REGNUM))]
8452 "arm_arch5 && TARGET_32BIT"
8453 [(set (match_dup 0) (clz:SI (match_dup 1)))
8454 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 5)))]
8455)
8456
2df9477b 8457(define_split
8458 [(set (match_operand:SI 0 "s_register_operand" "")
8459 (eq:SI (match_operand:SI 1 "s_register_operand" "")
8460 (const_int 0)))
8461 (clobber (reg:CC CC_REGNUM))]
8462 "TARGET_32BIT && reload_completed"
8463 [(parallel
080c0b9a 8464 [(set (reg:CC CC_REGNUM)
8465 (compare:CC (const_int 1) (match_dup 1)))
2df9477b 8466 (set (match_dup 0)
8467 (minus:SI (const_int 1) (match_dup 1)))])
080c0b9a 8468 (cond_exec (ltu:CC (reg:CC CC_REGNUM) (const_int 0))
2df9477b 8469 (set (match_dup 0) (const_int 0)))])
8470
8471(define_split
8472 [(set (match_operand:SI 0 "s_register_operand" "")
8473 (ne:SI (match_operand:SI 1 "s_register_operand" "")
8474 (match_operand:SI 2 "const_int_operand" "")))
8475 (clobber (reg:CC CC_REGNUM))]
8476 "TARGET_32BIT && reload_completed"
8477 [(parallel
8478 [(set (reg:CC CC_REGNUM)
8479 (compare:CC (match_dup 1) (match_dup 2)))
8480 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))])
8481 (cond_exec (ne:CC (reg:CC CC_REGNUM) (const_int 0))
8482 (set (match_dup 0) (const_int 1)))]
8483{
8484 operands[3] = GEN_INT (-INTVAL (operands[2]));
8485})
8486
8487(define_split
8488 [(set (match_operand:SI 0 "s_register_operand" "")
8489 (ne:SI (match_operand:SI 1 "s_register_operand" "")
8490 (match_operand:SI 2 "arm_add_operand" "")))
8491 (clobber (reg:CC CC_REGNUM))]
8492 "TARGET_32BIT && reload_completed"
8493 [(parallel
8494 [(set (reg:CC_NOOV CC_REGNUM)
8495 (compare:CC_NOOV (minus:SI (match_dup 1) (match_dup 2))
8496 (const_int 0)))
8497 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
8498 (cond_exec (ne:CC_NOOV (reg:CC_NOOV CC_REGNUM) (const_int 0))
8499 (set (match_dup 0) (const_int 1)))])
8500
8501(define_insn_and_split "*compare_scc"
fd711051 8502 [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts")
8fa3ba89 8503 (match_operator:SI 1 "arm_comparison_operator"
5565501b 8504 [(match_operand:SI 2 "s_register_operand" "r,r")
8505 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
bd5b4116 8506 (clobber (reg:CC CC_REGNUM))]
2df9477b 8507 "TARGET_32BIT"
8508 "#"
8509 "&& reload_completed"
8510 [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 3)))
8511 (cond_exec (match_dup 4) (set (match_dup 0) (const_int 0)))
8512 (cond_exec (match_dup 5) (set (match_dup 0) (const_int 1)))]
8513{
8514 rtx tmp1;
8515 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8516 operands[2], operands[3]);
8517 enum rtx_code rc = GET_CODE (operands[1]);
e2348bcb 8518
2df9477b 8519 tmp1 = gen_rtx_REG (mode, CC_REGNUM);
080c0b9a 8520
2df9477b 8521 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
8522 if (mode == CCFPmode || mode == CCFPEmode)
8523 rc = reverse_condition_maybe_unordered (rc);
8524 else
8525 rc = reverse_condition (rc);
8526 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
1b7da4ac 8527}
8528 [(set_attr "type" "multiple")]
8529)
9c08d1fa 8530
080c0b9a 8531;; Attempt to improve the sequence generated by the compare_scc splitters
8532;; not to use conditional execution.
98562479 8533
8534;; Rd = (eq (reg1) (const_int0)) // ARMv5
8535;; clz Rd, reg1
8536;; lsr Rd, Rd, #5
080c0b9a 8537(define_peephole2
8538 [(set (reg:CC CC_REGNUM)
8539 (compare:CC (match_operand:SI 1 "register_operand" "")
98562479 8540 (const_int 0)))
8541 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
8542 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
8543 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
8544 (set (match_dup 0) (const_int 1)))]
8545 "arm_arch5 && TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)"
8546 [(set (match_dup 0) (clz:SI (match_dup 1)))
8547 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 5)))]
8548)
8549
8550;; Rd = (eq (reg1) (const_int0)) // !ARMv5
8551;; negs Rd, reg1
8552;; adc Rd, Rd, reg1
8553(define_peephole2
8554 [(set (reg:CC CC_REGNUM)
8555 (compare:CC (match_operand:SI 1 "register_operand" "")
8556 (const_int 0)))
080c0b9a 8557 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
8558 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
8559 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
8560 (set (match_dup 0) (const_int 1)))
98562479 8561 (match_scratch:SI 2 "r")]
8562 "TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)"
922b6913 8563 [(parallel
8564 [(set (reg:CC CC_REGNUM)
98562479 8565 (compare:CC (const_int 0) (match_dup 1)))
8566 (set (match_dup 2) (minus:SI (const_int 0) (match_dup 1)))])
8567 (set (match_dup 0)
8568 (plus:SI (plus:SI (match_dup 1) (match_dup 2))
8569 (geu:SI (reg:CC CC_REGNUM) (const_int 0))))]
8570)
8571
31991287 8572;; Rd = (eq (reg1) (reg2/imm)) // ARMv5 and optimising for speed.
98562479 8573;; sub Rd, Reg1, reg2
8574;; clz Rd, Rd
8575;; lsr Rd, Rd, #5
8576(define_peephole2
8577 [(set (reg:CC CC_REGNUM)
8578 (compare:CC (match_operand:SI 1 "register_operand" "")
8579 (match_operand:SI 2 "arm_rhs_operand" "")))
8580 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
8581 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
8582 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
8583 (set (match_dup 0) (const_int 1)))]
31991287 8584 "arm_arch5 && TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)
8585 && !(TARGET_THUMB2 && optimize_insn_for_size_p ())"
98562479 8586 [(set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))
8587 (set (match_dup 0) (clz:SI (match_dup 0)))
8588 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 5)))]
8589)
8590
8591
31991287 8592;; Rd = (eq (reg1) (reg2)) // ! ARMv5 or optimising for size.
98562479 8593;; sub T1, Reg1, reg2
8594;; negs Rd, T1
8595;; adc Rd, Rd, T1
8596(define_peephole2
8597 [(set (reg:CC CC_REGNUM)
8598 (compare:CC (match_operand:SI 1 "register_operand" "")
8599 (match_operand:SI 2 "arm_rhs_operand" "")))
8600 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
8601 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
8602 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
8603 (set (match_dup 0) (const_int 1)))
8604 (match_scratch:SI 3 "r")]
8605 "TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)"
31991287 8606 [(set (match_dup 3) (match_dup 4))
080c0b9a 8607 (parallel
8608 [(set (reg:CC CC_REGNUM)
8609 (compare:CC (const_int 0) (match_dup 3)))
8610 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 3)))])
98562479 8611 (set (match_dup 0)
8612 (plus:SI (plus:SI (match_dup 0) (match_dup 3))
8613 (geu:SI (reg:CC CC_REGNUM) (const_int 0))))]
31991287 8614 "
8615 if (CONST_INT_P (operands[2]))
8616 operands[4] = plus_constant (SImode, operands[1], -INTVAL (operands[2]));
8617 else
8618 operands[4] = gen_rtx_MINUS (SImode, operands[1], operands[2]);
8619 ")
080c0b9a 8620
f7fbdd4a 8621(define_insn "*cond_move"
9c08d1fa 8622 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
aea4c774 8623 (if_then_else:SI (match_operator 3 "equality_operator"
8fa3ba89 8624 [(match_operator 4 "arm_comparison_operator"
8a18b90c 8625 [(match_operand 5 "cc_register" "") (const_int 0)])
aea4c774 8626 (const_int 0)])
8627 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8628 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
cffb2a26 8629 "TARGET_ARM"
9c08d1fa 8630 "*
8fa3ba89 8631 if (GET_CODE (operands[3]) == NE)
8632 {
8633 if (which_alternative != 1)
8634 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
8635 if (which_alternative != 0)
8636 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
8637 return \"\";
8638 }
8639 if (which_alternative != 0)
8640 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8641 if (which_alternative != 1)
8642 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
8643 return \"\";
8644 "
8645 [(set_attr "conds" "use")
1b7da4ac 8646 (set_attr "type" "mov_reg,mov_reg,multiple")
8fa3ba89 8647 (set_attr "length" "4,4,8")]
8648)
9c08d1fa 8649
f7fbdd4a 8650(define_insn "*cond_arith"
9c08d1fa 8651 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8652 (match_operator:SI 5 "shiftable_operator"
8fa3ba89 8653 [(match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 8654 [(match_operand:SI 2 "s_register_operand" "r,r")
8655 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8656 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 8657 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8658 "TARGET_ARM"
9c08d1fa 8659 "*
8fa3ba89 8660 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
8661 return \"%i5\\t%0, %1, %2, lsr #31\";
40dbec34 8662
8fa3ba89 8663 output_asm_insn (\"cmp\\t%2, %3\", operands);
8664 if (GET_CODE (operands[5]) == AND)
8665 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
8666 else if (GET_CODE (operands[5]) == MINUS)
8667 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
8668 else if (which_alternative != 0)
8669 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8670 return \"%i5%d4\\t%0, %1, #1\";
8671 "
8672 [(set_attr "conds" "clob")
1b7da4ac 8673 (set_attr "length" "12")
8674 (set_attr "type" "multiple")]
8fa3ba89 8675)
9c08d1fa 8676
f7fbdd4a 8677(define_insn "*cond_sub"
9c08d1fa 8678 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8679 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8fa3ba89 8680 (match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 8681 [(match_operand:SI 2 "s_register_operand" "r,r")
8682 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 8683 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8684 "TARGET_ARM"
9c08d1fa 8685 "*
8fa3ba89 8686 output_asm_insn (\"cmp\\t%2, %3\", operands);
8687 if (which_alternative != 0)
8688 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8689 return \"sub%d4\\t%0, %1, #1\";
8690 "
8691 [(set_attr "conds" "clob")
1b7da4ac 8692 (set_attr "length" "8,12")
8693 (set_attr "type" "multiple")]
8fa3ba89 8694)
9c08d1fa 8695
aea4c774 8696(define_insn "*cmp_ite0"
cffb2a26 8697 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 8698 (compare
8699 (if_then_else:SI
8fa3ba89 8700 (match_operator 4 "arm_comparison_operator"
2ff91fec 8701 [(match_operand:SI 0 "s_register_operand"
8702 "l,l,l,r,r,r,r,r,r")
8703 (match_operand:SI 1 "arm_add_operand"
8704 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
8fa3ba89 8705 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 8706 [(match_operand:SI 2 "s_register_operand"
8707 "l,r,r,l,l,r,r,r,r")
8708 (match_operand:SI 3 "arm_add_operand"
8709 "lPy,rI,L,lPy,lPy,rI,rI,L,L")])
aea4c774 8710 (const_int 0))
8711 (const_int 0)))]
2ff91fec 8712 "TARGET_32BIT"
9c08d1fa 8713 "*
aea4c774 8714 {
2ff91fec 8715 static const char * const cmp1[NUM_OF_COND_CMP][2] =
8716 {
8717 {\"cmp%d5\\t%0, %1\",
8718 \"cmp%d4\\t%2, %3\"},
8719 {\"cmn%d5\\t%0, #%n1\",
8720 \"cmp%d4\\t%2, %3\"},
8721 {\"cmp%d5\\t%0, %1\",
8722 \"cmn%d4\\t%2, #%n3\"},
8723 {\"cmn%d5\\t%0, #%n1\",
8724 \"cmn%d4\\t%2, #%n3\"}
8725 };
8726 static const char * const cmp2[NUM_OF_COND_CMP][2] =
8727 {
8728 {\"cmp\\t%2, %3\",
8729 \"cmp\\t%0, %1\"},
8730 {\"cmp\\t%2, %3\",
8731 \"cmn\\t%0, #%n1\"},
8732 {\"cmn\\t%2, #%n3\",
8733 \"cmp\\t%0, %1\"},
8734 {\"cmn\\t%2, #%n3\",
8735 \"cmn\\t%0, #%n1\"}
8736 };
8737 static const char * const ite[2] =
8fa3ba89 8738 {
2ff91fec 8739 \"it\\t%d5\",
8740 \"it\\t%d4\"
8fa3ba89 8741 };
2ff91fec 8742 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
8743 CMP_CMP, CMN_CMP, CMP_CMP,
8744 CMN_CMP, CMP_CMN, CMN_CMN};
8fa3ba89 8745 int swap =
8746 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8747
2ff91fec 8748 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
8749 if (TARGET_THUMB2) {
8750 output_asm_insn (ite[swap], operands);
8751 }
8752 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
8753 return \"\";
8fa3ba89 8754 }"
8755 [(set_attr "conds" "set")
2ff91fec 8756 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
1b7da4ac 8757 (set_attr "type" "multiple")
2ff91fec 8758 (set_attr_alternative "length"
8759 [(const_int 6)
8760 (const_int 8)
8761 (const_int 8)
8762 (const_int 8)
8763 (const_int 8)
8764 (if_then_else (eq_attr "is_thumb" "no")
8765 (const_int 8)
8766 (const_int 10))
8767 (if_then_else (eq_attr "is_thumb" "no")
8768 (const_int 8)
8769 (const_int 10))
8770 (if_then_else (eq_attr "is_thumb" "no")
8771 (const_int 8)
8772 (const_int 10))
8773 (if_then_else (eq_attr "is_thumb" "no")
8774 (const_int 8)
8775 (const_int 10))])]
8fa3ba89 8776)
9c08d1fa 8777
aea4c774 8778(define_insn "*cmp_ite1"
cffb2a26 8779 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 8780 (compare
8781 (if_then_else:SI
8fa3ba89 8782 (match_operator 4 "arm_comparison_operator"
2ff91fec 8783 [(match_operand:SI 0 "s_register_operand"
8784 "l,l,l,r,r,r,r,r,r")
8785 (match_operand:SI 1 "arm_add_operand"
8786 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
8fa3ba89 8787 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 8788 [(match_operand:SI 2 "s_register_operand"
8789 "l,r,r,l,l,r,r,r,r")
8790 (match_operand:SI 3 "arm_add_operand"
8791 "lPy,rI,L,lPy,lPy,rI,rI,L,L")])
aea4c774 8792 (const_int 1))
8793 (const_int 0)))]
2ff91fec 8794 "TARGET_32BIT"
9c08d1fa 8795 "*
9c08d1fa 8796 {
2ff91fec 8797 static const char * const cmp1[NUM_OF_COND_CMP][2] =
8798 {
8799 {\"cmp\\t%0, %1\",
8800 \"cmp\\t%2, %3\"},
8801 {\"cmn\\t%0, #%n1\",
8802 \"cmp\\t%2, %3\"},
8803 {\"cmp\\t%0, %1\",
8804 \"cmn\\t%2, #%n3\"},
8805 {\"cmn\\t%0, #%n1\",
8806 \"cmn\\t%2, #%n3\"}
8807 };
8808 static const char * const cmp2[NUM_OF_COND_CMP][2] =
215b30b3 8809 {
2ff91fec 8810 {\"cmp%d4\\t%2, %3\",
8811 \"cmp%D5\\t%0, %1\"},
8812 {\"cmp%d4\\t%2, %3\",
8813 \"cmn%D5\\t%0, #%n1\"},
8814 {\"cmn%d4\\t%2, #%n3\",
8815 \"cmp%D5\\t%0, %1\"},
8816 {\"cmn%d4\\t%2, #%n3\",
8817 \"cmn%D5\\t%0, #%n1\"}
215b30b3 8818 };
2ff91fec 8819 static const char * const ite[2] =
8820 {
8821 \"it\\t%d4\",
8822 \"it\\t%D5\"
8823 };
8824 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
8825 CMP_CMP, CMN_CMP, CMP_CMP,
8826 CMN_CMP, CMP_CMN, CMN_CMN};
215b30b3 8827 int swap =
8828 comparison_dominates_p (GET_CODE (operands[5]),
8829 reverse_condition (GET_CODE (operands[4])));
8830
2ff91fec 8831 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
8832 if (TARGET_THUMB2) {
8833 output_asm_insn (ite[swap], operands);
8834 }
8835 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
8836 return \"\";
215b30b3 8837 }"
8fa3ba89 8838 [(set_attr "conds" "set")
2ff91fec 8839 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
8840 (set_attr_alternative "length"
8841 [(const_int 6)
8842 (const_int 8)
8843 (const_int 8)
8844 (const_int 8)
8845 (const_int 8)
8846 (if_then_else (eq_attr "is_thumb" "no")
8847 (const_int 8)
8848 (const_int 10))
8849 (if_then_else (eq_attr "is_thumb" "no")
8850 (const_int 8)
8851 (const_int 10))
8852 (if_then_else (eq_attr "is_thumb" "no")
8853 (const_int 8)
8854 (const_int 10))
8855 (if_then_else (eq_attr "is_thumb" "no")
8856 (const_int 8)
1b7da4ac 8857 (const_int 10))])
8858 (set_attr "type" "multiple")]
8fa3ba89 8859)
9c08d1fa 8860
f6c53574 8861(define_insn "*cmp_and"
8862 [(set (match_operand 6 "dominant_cc_register" "")
8863 (compare
8864 (and:SI
8865 (match_operator 4 "arm_comparison_operator"
2ff91fec 8866 [(match_operand:SI 0 "s_register_operand"
8867 "l,l,l,r,r,r,r,r,r")
8868 (match_operand:SI 1 "arm_add_operand"
8869 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
f6c53574 8870 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 8871 [(match_operand:SI 2 "s_register_operand"
8872 "l,r,r,l,l,r,r,r,r")
8873 (match_operand:SI 3 "arm_add_operand"
8874 "lPy,rI,L,lPy,lPy,rI,rI,L,L")]))
f6c53574 8875 (const_int 0)))]
2ff91fec 8876 "TARGET_32BIT"
f6c53574 8877 "*
8878 {
2ff91fec 8879 static const char *const cmp1[NUM_OF_COND_CMP][2] =
f6c53574 8880 {
2ff91fec 8881 {\"cmp%d5\\t%0, %1\",
8882 \"cmp%d4\\t%2, %3\"},
8883 {\"cmn%d5\\t%0, #%n1\",
8884 \"cmp%d4\\t%2, %3\"},
8885 {\"cmp%d5\\t%0, %1\",
8886 \"cmn%d4\\t%2, #%n3\"},
8887 {\"cmn%d5\\t%0, #%n1\",
8888 \"cmn%d4\\t%2, #%n3\"}
f6c53574 8889 };
2ff91fec 8890 static const char *const cmp2[NUM_OF_COND_CMP][2] =
8891 {
8892 {\"cmp\\t%2, %3\",
8893 \"cmp\\t%0, %1\"},
8894 {\"cmp\\t%2, %3\",
8895 \"cmn\\t%0, #%n1\"},
8896 {\"cmn\\t%2, #%n3\",
8897 \"cmp\\t%0, %1\"},
8898 {\"cmn\\t%2, #%n3\",
8899 \"cmn\\t%0, #%n1\"}
8900 };
8901 static const char *const ite[2] =
8902 {
8903 \"it\\t%d5\",
8904 \"it\\t%d4\"
8905 };
8906 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
8907 CMP_CMP, CMN_CMP, CMP_CMP,
8908 CMN_CMP, CMP_CMN, CMN_CMN};
f6c53574 8909 int swap =
8910 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8911
2ff91fec 8912 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
8913 if (TARGET_THUMB2) {
8914 output_asm_insn (ite[swap], operands);
8915 }
8916 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
8917 return \"\";
f6c53574 8918 }"
8919 [(set_attr "conds" "set")
8920 (set_attr "predicable" "no")
2ff91fec 8921 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
8922 (set_attr_alternative "length"
8923 [(const_int 6)
8924 (const_int 8)
8925 (const_int 8)
8926 (const_int 8)
8927 (const_int 8)
8928 (if_then_else (eq_attr "is_thumb" "no")
8929 (const_int 8)
8930 (const_int 10))
8931 (if_then_else (eq_attr "is_thumb" "no")
8932 (const_int 8)
8933 (const_int 10))
8934 (if_then_else (eq_attr "is_thumb" "no")
8935 (const_int 8)
8936 (const_int 10))
8937 (if_then_else (eq_attr "is_thumb" "no")
8938 (const_int 8)
1b7da4ac 8939 (const_int 10))])
8940 (set_attr "type" "multiple")]
f6c53574 8941)
8942
8943(define_insn "*cmp_ior"
8944 [(set (match_operand 6 "dominant_cc_register" "")
8945 (compare
8946 (ior:SI
8947 (match_operator 4 "arm_comparison_operator"
2ff91fec 8948 [(match_operand:SI 0 "s_register_operand"
8949 "l,l,l,r,r,r,r,r,r")
8950 (match_operand:SI 1 "arm_add_operand"
8951 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
f6c53574 8952 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 8953 [(match_operand:SI 2 "s_register_operand"
8954 "l,r,r,l,l,r,r,r,r")
8955 (match_operand:SI 3 "arm_add_operand"
8956 "lPy,rI,L,lPy,lPy,rI,rI,L,L")]))
f6c53574 8957 (const_int 0)))]
2ff91fec 8958 "TARGET_32BIT"
f6c53574 8959 "*
f6c53574 8960 {
2ff91fec 8961 static const char *const cmp1[NUM_OF_COND_CMP][2] =
8962 {
8963 {\"cmp\\t%0, %1\",
8964 \"cmp\\t%2, %3\"},
8965 {\"cmn\\t%0, #%n1\",
8966 \"cmp\\t%2, %3\"},
8967 {\"cmp\\t%0, %1\",
8968 \"cmn\\t%2, #%n3\"},
8969 {\"cmn\\t%0, #%n1\",
8970 \"cmn\\t%2, #%n3\"}
8971 };
8972 static const char *const cmp2[NUM_OF_COND_CMP][2] =
8973 {
8974 {\"cmp%D4\\t%2, %3\",
8975 \"cmp%D5\\t%0, %1\"},
8976 {\"cmp%D4\\t%2, %3\",
8977 \"cmn%D5\\t%0, #%n1\"},
8978 {\"cmn%D4\\t%2, #%n3\",
8979 \"cmp%D5\\t%0, %1\"},
8980 {\"cmn%D4\\t%2, #%n3\",
8981 \"cmn%D5\\t%0, #%n1\"}
8982 };
8983 static const char *const ite[2] =
8984 {
8985 \"it\\t%D4\",
8986 \"it\\t%D5\"
8987 };
8988 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
8989 CMP_CMP, CMN_CMP, CMP_CMP,
8990 CMN_CMP, CMP_CMN, CMN_CMN};
8991 int swap =
8992 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8993
8994 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
8995 if (TARGET_THUMB2) {
8996 output_asm_insn (ite[swap], operands);
8997 }
8998 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
8999 return \"\";
9000 }
9001 "
f6c53574 9002 [(set_attr "conds" "set")
2ff91fec 9003 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
9004 (set_attr_alternative "length"
9005 [(const_int 6)
9006 (const_int 8)
9007 (const_int 8)
9008 (const_int 8)
9009 (const_int 8)
9010 (if_then_else (eq_attr "is_thumb" "no")
9011 (const_int 8)
9012 (const_int 10))
9013 (if_then_else (eq_attr "is_thumb" "no")
9014 (const_int 8)
9015 (const_int 10))
9016 (if_then_else (eq_attr "is_thumb" "no")
9017 (const_int 8)
9018 (const_int 10))
9019 (if_then_else (eq_attr "is_thumb" "no")
9020 (const_int 8)
1b7da4ac 9021 (const_int 10))])
9022 (set_attr "type" "multiple")]
f6c53574 9023)
9024
3c5afce6 9025(define_insn_and_split "*ior_scc_scc"
fd711051 9026 [(set (match_operand:SI 0 "s_register_operand" "=Ts")
3c5afce6 9027 (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9028 [(match_operand:SI 1 "s_register_operand" "r")
9029 (match_operand:SI 2 "arm_add_operand" "rIL")])
9030 (match_operator:SI 6 "arm_comparison_operator"
9031 [(match_operand:SI 4 "s_register_operand" "r")
9032 (match_operand:SI 5 "arm_add_operand" "rIL")])))
9033 (clobber (reg:CC CC_REGNUM))]
2ff91fec 9034 "TARGET_32BIT
3c5afce6 9035 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
9036 != CCmode)"
9037 "#"
2ff91fec 9038 "TARGET_32BIT && reload_completed"
3c5afce6 9039 [(set (match_dup 7)
9040 (compare
9041 (ior:SI
9042 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9043 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9044 (const_int 0)))
9045 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9046 "operands[7]
9047 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9048 DOM_CC_X_OR_Y),
601f584c 9049 CC_REGNUM);"
9050 [(set_attr "conds" "clob")
1b7da4ac 9051 (set_attr "length" "16")
9052 (set_attr "type" "multiple")]
9053)
601f584c 9054
9055; If the above pattern is followed by a CMP insn, then the compare is
9056; redundant, since we can rework the conditional instruction that follows.
9057(define_insn_and_split "*ior_scc_scc_cmp"
9058 [(set (match_operand 0 "dominant_cc_register" "")
9059 (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9060 [(match_operand:SI 1 "s_register_operand" "r")
9061 (match_operand:SI 2 "arm_add_operand" "rIL")])
9062 (match_operator:SI 6 "arm_comparison_operator"
9063 [(match_operand:SI 4 "s_register_operand" "r")
9064 (match_operand:SI 5 "arm_add_operand" "rIL")]))
9065 (const_int 0)))
fd711051 9066 (set (match_operand:SI 7 "s_register_operand" "=Ts")
601f584c 9067 (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9068 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
2ff91fec 9069 "TARGET_32BIT"
601f584c 9070 "#"
2ff91fec 9071 "TARGET_32BIT && reload_completed"
601f584c 9072 [(set (match_dup 0)
9073 (compare
9074 (ior:SI
9075 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9076 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9077 (const_int 0)))
9078 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9079 ""
9080 [(set_attr "conds" "set")
1b7da4ac 9081 (set_attr "length" "16")
9082 (set_attr "type" "multiple")]
9083)
3c5afce6 9084
9085(define_insn_and_split "*and_scc_scc"
fd711051 9086 [(set (match_operand:SI 0 "s_register_operand" "=Ts")
3c5afce6 9087 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9088 [(match_operand:SI 1 "s_register_operand" "r")
9089 (match_operand:SI 2 "arm_add_operand" "rIL")])
9090 (match_operator:SI 6 "arm_comparison_operator"
9091 [(match_operand:SI 4 "s_register_operand" "r")
9092 (match_operand:SI 5 "arm_add_operand" "rIL")])))
9093 (clobber (reg:CC CC_REGNUM))]
2ff91fec 9094 "TARGET_32BIT
3c5afce6 9095 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9096 != CCmode)"
9097 "#"
2ff91fec 9098 "TARGET_32BIT && reload_completed
601f584c 9099 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9100 != CCmode)"
3c5afce6 9101 [(set (match_dup 7)
9102 (compare
9103 (and:SI
9104 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9105 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9106 (const_int 0)))
9107 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9108 "operands[7]
9109 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9110 DOM_CC_X_AND_Y),
601f584c 9111 CC_REGNUM);"
9112 [(set_attr "conds" "clob")
1b7da4ac 9113 (set_attr "length" "16")
9114 (set_attr "type" "multiple")]
9115)
601f584c 9116
9117; If the above pattern is followed by a CMP insn, then the compare is
9118; redundant, since we can rework the conditional instruction that follows.
9119(define_insn_and_split "*and_scc_scc_cmp"
9120 [(set (match_operand 0 "dominant_cc_register" "")
9121 (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
9122 [(match_operand:SI 1 "s_register_operand" "r")
9123 (match_operand:SI 2 "arm_add_operand" "rIL")])
9124 (match_operator:SI 6 "arm_comparison_operator"
9125 [(match_operand:SI 4 "s_register_operand" "r")
9126 (match_operand:SI 5 "arm_add_operand" "rIL")]))
9127 (const_int 0)))
fd711051 9128 (set (match_operand:SI 7 "s_register_operand" "=Ts")
601f584c 9129 (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9130 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
2ff91fec 9131 "TARGET_32BIT"
601f584c 9132 "#"
2ff91fec 9133 "TARGET_32BIT && reload_completed"
601f584c 9134 [(set (match_dup 0)
9135 (compare
9136 (and:SI
9137 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9138 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9139 (const_int 0)))
9140 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9141 ""
9142 [(set_attr "conds" "set")
1b7da4ac 9143 (set_attr "length" "16")
9144 (set_attr "type" "multiple")]
9145)
601f584c 9146
9147;; If there is no dominance in the comparison, then we can still save an
9148;; instruction in the AND case, since we can know that the second compare
9149;; need only zero the value if false (if true, then the value is already
9150;; correct).
9151(define_insn_and_split "*and_scc_scc_nodom"
fd711051 9152 [(set (match_operand:SI 0 "s_register_operand" "=&Ts,&Ts,&Ts")
601f584c 9153 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9154 [(match_operand:SI 1 "s_register_operand" "r,r,0")
9155 (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
9156 (match_operator:SI 6 "arm_comparison_operator"
9157 [(match_operand:SI 4 "s_register_operand" "r,r,r")
9158 (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
9159 (clobber (reg:CC CC_REGNUM))]
2ff91fec 9160 "TARGET_32BIT
601f584c 9161 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9162 == CCmode)"
9163 "#"
2ff91fec 9164 "TARGET_32BIT && reload_completed"
601f584c 9165 [(parallel [(set (match_dup 0)
9166 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
9167 (clobber (reg:CC CC_REGNUM))])
9168 (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
9169 (set (match_dup 0)
9170 (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
9171 (match_dup 0)
9172 (const_int 0)))]
9173 "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
9174 operands[4], operands[5]),
9175 CC_REGNUM);
9176 operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
9177 operands[5]);"
9178 [(set_attr "conds" "clob")
1b7da4ac 9179 (set_attr "length" "20")
9180 (set_attr "type" "multiple")]
9181)
3c5afce6 9182
3a0bdee0 9183(define_split
9184 [(set (reg:CC_NOOV CC_REGNUM)
9185 (compare:CC_NOOV (ior:SI
9186 (and:SI (match_operand:SI 0 "s_register_operand" "")
9187 (const_int 1))
b0694be0 9188 (match_operator:SI 1 "arm_comparison_operator"
3a0bdee0 9189 [(match_operand:SI 2 "s_register_operand" "")
9190 (match_operand:SI 3 "arm_add_operand" "")]))
9191 (const_int 0)))
9192 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9193 "TARGET_ARM"
9194 [(set (match_dup 4)
9195 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9196 (match_dup 0)))
9197 (set (reg:CC_NOOV CC_REGNUM)
9198 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9199 (const_int 0)))]
9200 "")
9201
9202(define_split
9203 [(set (reg:CC_NOOV CC_REGNUM)
9204 (compare:CC_NOOV (ior:SI
b0694be0 9205 (match_operator:SI 1 "arm_comparison_operator"
3a0bdee0 9206 [(match_operand:SI 2 "s_register_operand" "")
9207 (match_operand:SI 3 "arm_add_operand" "")])
9208 (and:SI (match_operand:SI 0 "s_register_operand" "")
9209 (const_int 1)))
9210 (const_int 0)))
9211 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9212 "TARGET_ARM"
9213 [(set (match_dup 4)
9214 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9215 (match_dup 0)))
9216 (set (reg:CC_NOOV CC_REGNUM)
9217 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9218 (const_int 0)))]
9219 "")
25f905c2 9220;; ??? The conditional patterns above need checking for Thumb-2 usefulness
3a0bdee0 9221
190efb17 9222(define_insn_and_split "*negscc"
9c08d1fa 9223 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9224 (neg:SI (match_operator 3 "arm_comparison_operator"
9c08d1fa 9225 [(match_operand:SI 1 "s_register_operand" "r")
9226 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
bd5b4116 9227 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9228 "TARGET_ARM"
190efb17 9229 "#"
9230 "&& reload_completed"
9231 [(const_int 0)]
9232 {
9233 rtx cc_reg = gen_rtx_REG (CCmode, CC_REGNUM);
e2348bcb 9234
190efb17 9235 if (GET_CODE (operands[3]) == LT && operands[2] == const0_rtx)
9236 {
9237 /* Emit mov\\t%0, %1, asr #31 */
9238 emit_insn (gen_rtx_SET (VOIDmode,
9239 operands[0],
9240 gen_rtx_ASHIFTRT (SImode,
9241 operands[1],
9242 GEN_INT (31))));
9243 DONE;
9244 }
9245 else if (GET_CODE (operands[3]) == NE)
9246 {
9247 /* Emit subs\\t%0, %1, %2\;mvnne\\t%0, #0 */
9248 if (CONST_INT_P (operands[2]))
9249 emit_insn (gen_cmpsi2_addneg (operands[0], operands[1], operands[2],
9250 GEN_INT (- INTVAL (operands[2]))));
9251 else
9252 emit_insn (gen_subsi3_compare (operands[0], operands[1], operands[2]));
9253
9254 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
9255 gen_rtx_NE (SImode,
9256 cc_reg,
9257 const0_rtx),
9258 gen_rtx_SET (SImode,
9259 operands[0],
9260 GEN_INT (~0))));
9261 DONE;
9262 }
9263 else
9264 {
9265 /* Emit: cmp\\t%1, %2\;mov%D3\\t%0, #0\;mvn%d3\\t%0, #0 */
9266 emit_insn (gen_rtx_SET (VOIDmode,
9267 cc_reg,
9268 gen_rtx_COMPARE (CCmode, operands[1], operands[2])));
9269 enum rtx_code rc = GET_CODE (operands[3]);
9270
9271 rc = reverse_condition (rc);
9272 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
9273 gen_rtx_fmt_ee (rc,
9274 VOIDmode,
9275 cc_reg,
9276 const0_rtx),
9277 gen_rtx_SET (VOIDmode, operands[0], const0_rtx)));
9278 rc = GET_CODE (operands[3]);
9279 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
9280 gen_rtx_fmt_ee (rc,
9281 VOIDmode,
9282 cc_reg,
9283 const0_rtx),
9284 gen_rtx_SET (VOIDmode,
9285 operands[0],
9286 GEN_INT (~0))));
9287 DONE;
9288 }
9289 FAIL;
9290 }
8fa3ba89 9291 [(set_attr "conds" "clob")
1b7da4ac 9292 (set_attr "length" "12")
9293 (set_attr "type" "multiple")]
8fa3ba89 9294)
9c08d1fa 9295
90404b57 9296(define_insn_and_split "movcond_addsi"
9297 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r")
9298 (if_then_else:SI
9299 (match_operator 5 "comparison_operator"
9300 [(plus:SI (match_operand:SI 3 "s_register_operand" "r,r,r")
9301 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL"))
9302 (const_int 0)])
9303 (match_operand:SI 1 "arm_rhs_operand" "rI,rPy,r")
9304 (match_operand:SI 2 "arm_rhs_operand" "rI,rPy,r")))
9305 (clobber (reg:CC CC_REGNUM))]
9306 "TARGET_32BIT"
9307 "#"
9308 "&& reload_completed"
9309 [(set (reg:CC_NOOV CC_REGNUM)
9310 (compare:CC_NOOV
9311 (plus:SI (match_dup 3)
9312 (match_dup 4))
9313 (const_int 0)))
9314 (set (match_dup 0) (match_dup 1))
9315 (cond_exec (match_dup 6)
9316 (set (match_dup 0) (match_dup 2)))]
9317 "
9318 {
9319 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[5]),
9320 operands[3], operands[4]);
9321 enum rtx_code rc = GET_CODE (operands[5]);
9322
9323 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9324 gcc_assert (!(mode == CCFPmode || mode == CCFPEmode));
9325 rc = reverse_condition (rc);
9326
9327 operands[6] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9328 }
9329 "
9330 [(set_attr "conds" "clob")
1b7da4ac 9331 (set_attr "enabled_for_depr_it" "no,yes,yes")
9332 (set_attr "type" "multiple")]
90404b57 9333)
9334
9c08d1fa 9335(define_insn "movcond"
9336 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 9337 (if_then_else:SI
8fa3ba89 9338 (match_operator 5 "arm_comparison_operator"
5565501b 9339 [(match_operand:SI 3 "s_register_operand" "r,r,r")
9340 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
9341 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9342 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 9343 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9344 "TARGET_ARM"
9c08d1fa 9345 "*
9346 if (GET_CODE (operands[5]) == LT
9347 && (operands[4] == const0_rtx))
9348 {
0438d37f 9349 if (which_alternative != 1 && REG_P (operands[1]))
9c08d1fa 9350 {
9c08d1fa 9351 if (operands[2] == const0_rtx)
e2348bcb 9352 return \"and\\t%0, %1, %3, asr #31\";
9353 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
9c08d1fa 9354 }
0438d37f 9355 else if (which_alternative != 0 && REG_P (operands[2]))
9c08d1fa 9356 {
9c08d1fa 9357 if (operands[1] == const0_rtx)
e2348bcb 9358 return \"bic\\t%0, %2, %3, asr #31\";
9359 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
9c08d1fa 9360 }
9361 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 9362 are constants. */
9c08d1fa 9363 }
e2348bcb 9364
9c08d1fa 9365 if (GET_CODE (operands[5]) == GE
9366 && (operands[4] == const0_rtx))
9367 {
0438d37f 9368 if (which_alternative != 1 && REG_P (operands[1]))
9c08d1fa 9369 {
9c08d1fa 9370 if (operands[2] == const0_rtx)
e2348bcb 9371 return \"bic\\t%0, %1, %3, asr #31\";
9372 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
9c08d1fa 9373 }
0438d37f 9374 else if (which_alternative != 0 && REG_P (operands[2]))
9c08d1fa 9375 {
9c08d1fa 9376 if (operands[1] == const0_rtx)
e2348bcb 9377 return \"and\\t%0, %2, %3, asr #31\";
9378 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
9c08d1fa 9379 }
9380 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 9381 are constants. */
9c08d1fa 9382 }
0438d37f 9383 if (CONST_INT_P (operands[4])
9c08d1fa 9384 && !const_ok_for_arm (INTVAL (operands[4])))
e2348bcb 9385 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
9c08d1fa 9386 else
e2348bcb 9387 output_asm_insn (\"cmp\\t%3, %4\", operands);
9c08d1fa 9388 if (which_alternative != 0)
e2348bcb 9389 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
9c08d1fa 9390 if (which_alternative != 1)
e2348bcb 9391 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
9c08d1fa 9392 return \"\";
215b30b3 9393 "
8fa3ba89 9394 [(set_attr "conds" "clob")
1b7da4ac 9395 (set_attr "length" "8,8,12")
9396 (set_attr "type" "multiple")]
8fa3ba89 9397)
9c08d1fa 9398
25f905c2 9399;; ??? The patterns below need checking for Thumb-2 usefulness.
9400
8a18b90c 9401(define_insn "*ifcompare_plus_move"
9402 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9403 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 9404 [(match_operand:SI 4 "s_register_operand" "r,r")
9405 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9406 (plus:SI
9407 (match_operand:SI 2 "s_register_operand" "r,r")
9408 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
129a2fe4 9409 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 9410 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9411 "TARGET_ARM"
8a18b90c 9412 "#"
8fa3ba89 9413 [(set_attr "conds" "clob")
1b7da4ac 9414 (set_attr "length" "8,12")
9415 (set_attr "type" "multiple")]
8fa3ba89 9416)
8a18b90c 9417
9418(define_insn "*if_plus_move"
129a2fe4 9419 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 9420 (if_then_else:SI
8fa3ba89 9421 (match_operator 4 "arm_comparison_operator"
8a18b90c 9422 [(match_operand 5 "cc_register" "") (const_int 0)])
9423 (plus:SI
129a2fe4 9424 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9425 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
9426 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
cffb2a26 9427 "TARGET_ARM"
8a18b90c 9428 "@
9429 add%d4\\t%0, %2, %3
9430 sub%d4\\t%0, %2, #%n3
9431 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
129a2fe4 9432 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8fa3ba89 9433 [(set_attr "conds" "use")
9434 (set_attr "length" "4,4,8,8")
65f68e55 9435 (set_attr_alternative "type"
9436 [(if_then_else (match_operand 3 "const_int_operand" "")
d82e788e 9437 (const_string "alu_imm" )
1b7da4ac 9438 (const_string "alu_reg"))
d82e788e 9439 (const_string "alu_imm")
1b7da4ac 9440 (const_string "alu_reg")
9441 (const_string "alu_reg")])]
8fa3ba89 9442)
8a18b90c 9443
9444(define_insn "*ifcompare_move_plus"
5565501b 9445 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9446 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 9447 [(match_operand:SI 4 "s_register_operand" "r,r")
9448 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 9449 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 9450 (plus:SI
9451 (match_operand:SI 2 "s_register_operand" "r,r")
9452 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
bd5b4116 9453 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9454 "TARGET_ARM"
8a18b90c 9455 "#"
8fa3ba89 9456 [(set_attr "conds" "clob")
1b7da4ac 9457 (set_attr "length" "8,12")
9458 (set_attr "type" "multiple")]
8fa3ba89 9459)
8a18b90c 9460
9461(define_insn "*if_move_plus"
129a2fe4 9462 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 9463 (if_then_else:SI
8fa3ba89 9464 (match_operator 4 "arm_comparison_operator"
8a18b90c 9465 [(match_operand 5 "cc_register" "") (const_int 0)])
129a2fe4 9466 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8a18b90c 9467 (plus:SI
129a2fe4 9468 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9469 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
cffb2a26 9470 "TARGET_ARM"
8a18b90c 9471 "@
9472 add%D4\\t%0, %2, %3
9473 sub%D4\\t%0, %2, #%n3
9474 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
129a2fe4 9475 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8fa3ba89 9476 [(set_attr "conds" "use")
9477 (set_attr "length" "4,4,8,8")
1b7da4ac 9478 (set_attr "type" "alu_reg,alu_imm,multiple,multiple")]
8fa3ba89 9479)
8a18b90c 9480
9481(define_insn "*ifcompare_arith_arith"
9482 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9483 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8a18b90c 9484 [(match_operand:SI 5 "s_register_operand" "r")
9485 (match_operand:SI 6 "arm_add_operand" "rIL")])
9c08d1fa 9486 (match_operator:SI 8 "shiftable_operator"
8a18b90c 9487 [(match_operand:SI 1 "s_register_operand" "r")
9488 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9c08d1fa 9489 (match_operator:SI 7 "shiftable_operator"
8a18b90c 9490 [(match_operand:SI 3 "s_register_operand" "r")
9491 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
bd5b4116 9492 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9493 "TARGET_ARM"
8a18b90c 9494 "#"
8fa3ba89 9495 [(set_attr "conds" "clob")
1b7da4ac 9496 (set_attr "length" "12")
9497 (set_attr "type" "multiple")]
8fa3ba89 9498)
9c08d1fa 9499
8a18b90c 9500(define_insn "*if_arith_arith"
9501 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9502 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8a18b90c 9503 [(match_operand 8 "cc_register" "") (const_int 0)])
9504 (match_operator:SI 6 "shiftable_operator"
9505 [(match_operand:SI 1 "s_register_operand" "r")
9506 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9507 (match_operator:SI 7 "shiftable_operator"
9508 [(match_operand:SI 3 "s_register_operand" "r")
9509 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
cffb2a26 9510 "TARGET_ARM"
8a18b90c 9511 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8fa3ba89 9512 [(set_attr "conds" "use")
1b7da4ac 9513 (set_attr "length" "8")
9514 (set_attr "type" "multiple")]
8fa3ba89 9515)
8a18b90c 9516
f7fbdd4a 9517(define_insn "*ifcompare_arith_move"
9c08d1fa 9518 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9519 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 9520 [(match_operand:SI 2 "s_register_operand" "r,r")
5565501b 9521 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
9c08d1fa 9522 (match_operator:SI 7 "shiftable_operator"
9523 [(match_operand:SI 4 "s_register_operand" "r,r")
9524 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
129a2fe4 9525 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 9526 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9527 "TARGET_ARM"
9c08d1fa 9528 "*
9c08d1fa 9529 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 9530 the conditional operator is LT or GE and we are comparing against zero and
674a8f0b 9531 everything is in registers then we can do this in two instructions. */
9c08d1fa 9532 if (operands[3] == const0_rtx
9533 && GET_CODE (operands[7]) != AND
0438d37f 9534 && REG_P (operands[5])
9535 && REG_P (operands[1])
9c08d1fa 9536 && REGNO (operands[1]) == REGNO (operands[4])
9537 && REGNO (operands[4]) != REGNO (operands[0]))
9538 {
9539 if (GET_CODE (operands[6]) == LT)
40dbec34 9540 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 9541 else if (GET_CODE (operands[6]) == GE)
40dbec34 9542 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 9543 }
0438d37f 9544 if (CONST_INT_P (operands[3])
9c08d1fa 9545 && !const_ok_for_arm (INTVAL (operands[3])))
e2348bcb 9546 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
9c08d1fa 9547 else
e2348bcb 9548 output_asm_insn (\"cmp\\t%2, %3\", operands);
40dbec34 9549 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
9c08d1fa 9550 if (which_alternative != 0)
129a2fe4 9551 return \"mov%D6\\t%0, %1\";
9c08d1fa 9552 return \"\";
215b30b3 9553 "
8fa3ba89 9554 [(set_attr "conds" "clob")
1b7da4ac 9555 (set_attr "length" "8,12")
9556 (set_attr "type" "multiple")]
8fa3ba89 9557)
9c08d1fa 9558
8a18b90c 9559(define_insn "*if_arith_move"
129a2fe4 9560 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9561 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8a18b90c 9562 [(match_operand 6 "cc_register" "") (const_int 0)])
9563 (match_operator:SI 5 "shiftable_operator"
129a2fe4 9564 [(match_operand:SI 2 "s_register_operand" "r,r")
9565 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
9566 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
cffb2a26 9567 "TARGET_ARM"
8a18b90c 9568 "@
9569 %I5%d4\\t%0, %2, %3
129a2fe4 9570 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8fa3ba89 9571 [(set_attr "conds" "use")
9572 (set_attr "length" "4,8")
1b7da4ac 9573 (set_attr "type" "alu_shift_reg,multiple")]
8fa3ba89 9574)
8a18b90c 9575
f7fbdd4a 9576(define_insn "*ifcompare_move_arith"
9c08d1fa 9577 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9578 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 9579 [(match_operand:SI 4 "s_register_operand" "r,r")
5565501b 9580 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 9581 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9c08d1fa 9582 (match_operator:SI 7 "shiftable_operator"
9583 [(match_operand:SI 2 "s_register_operand" "r,r")
9584 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 9585 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9586 "TARGET_ARM"
9c08d1fa 9587 "*
9c08d1fa 9588 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 9589 the conditional operator is LT or GE and we are comparing against zero and
9c08d1fa 9590 everything is in registers then we can do this in two instructions */
9591 if (operands[5] == const0_rtx
9592 && GET_CODE (operands[7]) != AND
0438d37f 9593 && REG_P (operands[3])
9594 && REG_P (operands[1])
9c08d1fa 9595 && REGNO (operands[1]) == REGNO (operands[2])
9596 && REGNO (operands[2]) != REGNO (operands[0]))
9597 {
9598 if (GET_CODE (operands[6]) == GE)
40dbec34 9599 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 9600 else if (GET_CODE (operands[6]) == LT)
40dbec34 9601 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 9602 }
40dbec34 9603
0438d37f 9604 if (CONST_INT_P (operands[5])
9c08d1fa 9605 && !const_ok_for_arm (INTVAL (operands[5])))
e2348bcb 9606 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
9c08d1fa 9607 else
e2348bcb 9608 output_asm_insn (\"cmp\\t%4, %5\", operands);
40dbec34 9609
9c08d1fa 9610 if (which_alternative != 0)
129a2fe4 9611 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
40dbec34 9612 return \"%I7%D6\\t%0, %2, %3\";
215b30b3 9613 "
8fa3ba89 9614 [(set_attr "conds" "clob")
1b7da4ac 9615 (set_attr "length" "8,12")
9616 (set_attr "type" "multiple")]
8fa3ba89 9617)
9c08d1fa 9618
8a18b90c 9619(define_insn "*if_move_arith"
129a2fe4 9620 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9621 (if_then_else:SI
8fa3ba89 9622 (match_operator 4 "arm_comparison_operator"
8a18b90c 9623 [(match_operand 6 "cc_register" "") (const_int 0)])
129a2fe4 9624 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 9625 (match_operator:SI 5 "shiftable_operator"
129a2fe4 9626 [(match_operand:SI 2 "s_register_operand" "r,r")
9627 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
cffb2a26 9628 "TARGET_ARM"
8a18b90c 9629 "@
9630 %I5%D4\\t%0, %2, %3
129a2fe4 9631 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
8fa3ba89 9632 [(set_attr "conds" "use")
9633 (set_attr "length" "4,8")
1b7da4ac 9634 (set_attr "type" "alu_shift_reg,multiple")]
8fa3ba89 9635)
8a18b90c 9636
9637(define_insn "*ifcompare_move_not"
9c08d1fa 9638 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9639 (if_then_else:SI
8fa3ba89 9640 (match_operator 5 "arm_comparison_operator"
8a18b90c 9641 [(match_operand:SI 3 "s_register_operand" "r,r")
9642 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9643 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9644 (not:SI
9645 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 9646 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9647 "TARGET_ARM"
8a18b90c 9648 "#"
8fa3ba89 9649 [(set_attr "conds" "clob")
1b7da4ac 9650 (set_attr "length" "8,12")
9651 (set_attr "type" "multiple")]
8fa3ba89 9652)
9c08d1fa 9653
8a18b90c 9654(define_insn "*if_move_not"
9655 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9656 (if_then_else:SI
8fa3ba89 9657 (match_operator 4 "arm_comparison_operator"
8a18b90c 9658 [(match_operand 3 "cc_register" "") (const_int 0)])
9659 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9660 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
cffb2a26 9661 "TARGET_ARM"
8a18b90c 9662 "@
9663 mvn%D4\\t%0, %2
9664 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
9665 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
8fa3ba89 9666 [(set_attr "conds" "use")
1aed5204 9667 (set_attr "type" "mvn_reg")
1b7da4ac 9668 (set_attr "length" "4,8,8")
9669 (set_attr "type" "mvn_reg,multiple,multiple")]
8fa3ba89 9670)
8a18b90c 9671
9672(define_insn "*ifcompare_not_move"
9c08d1fa 9673 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9674 (if_then_else:SI
8fa3ba89 9675 (match_operator 5 "arm_comparison_operator"
8a18b90c 9676 [(match_operand:SI 3 "s_register_operand" "r,r")
9677 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9678 (not:SI
9679 (match_operand:SI 2 "s_register_operand" "r,r"))
9680 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 9681 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9682 "TARGET_ARM"
8a18b90c 9683 "#"
8fa3ba89 9684 [(set_attr "conds" "clob")
1b7da4ac 9685 (set_attr "length" "8,12")
9686 (set_attr "type" "multiple")]
8fa3ba89 9687)
9c08d1fa 9688
8a18b90c 9689(define_insn "*if_not_move"
9690 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9691 (if_then_else:SI
8fa3ba89 9692 (match_operator 4 "arm_comparison_operator"
8a18b90c 9693 [(match_operand 3 "cc_register" "") (const_int 0)])
9694 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9695 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 9696 "TARGET_ARM"
8a18b90c 9697 "@
9698 mvn%d4\\t%0, %2
9699 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
9700 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
8fa3ba89 9701 [(set_attr "conds" "use")
1b7da4ac 9702 (set_attr "type" "mvn_reg,multiple,multiple")
8fa3ba89 9703 (set_attr "length" "4,8,8")]
9704)
8a18b90c 9705
9706(define_insn "*ifcompare_shift_move"
9c08d1fa 9707 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9708 (if_then_else:SI
8fa3ba89 9709 (match_operator 6 "arm_comparison_operator"
8a18b90c 9710 [(match_operand:SI 4 "s_register_operand" "r,r")
9711 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9712 (match_operator:SI 7 "shift_operator"
9713 [(match_operand:SI 2 "s_register_operand" "r,r")
9714 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
9715 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 9716 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9717 "TARGET_ARM"
9c08d1fa 9718 "#"
8fa3ba89 9719 [(set_attr "conds" "clob")
1b7da4ac 9720 (set_attr "length" "8,12")
9721 (set_attr "type" "multiple")]
8fa3ba89 9722)
9c08d1fa 9723
8a18b90c 9724(define_insn "*if_shift_move"
9725 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9726 (if_then_else:SI
8fa3ba89 9727 (match_operator 5 "arm_comparison_operator"
8a18b90c 9728 [(match_operand 6 "cc_register" "") (const_int 0)])
9729 (match_operator:SI 4 "shift_operator"
9730 [(match_operand:SI 2 "s_register_operand" "r,r,r")
9731 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
9732 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 9733 "TARGET_ARM"
5565501b 9734 "@
8a18b90c 9735 mov%d5\\t%0, %2%S4
9736 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
9737 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
8fa3ba89 9738 [(set_attr "conds" "use")
331beb1a 9739 (set_attr "shift" "2")
a2cd141b 9740 (set_attr "length" "4,8,8")
1b7da4ac 9741 (set_attr "type" "mov_shift_reg,multiple,multiple")]
8fa3ba89 9742)
5565501b 9743
8a18b90c 9744(define_insn "*ifcompare_move_shift"
9745 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 9746 (if_then_else:SI
8fa3ba89 9747 (match_operator 6 "arm_comparison_operator"
8a18b90c 9748 [(match_operand:SI 4 "s_register_operand" "r,r")
9749 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9750 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
5565501b 9751 (match_operator:SI 7 "shift_operator"
8a18b90c 9752 [(match_operand:SI 2 "s_register_operand" "r,r")
9753 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
bd5b4116 9754 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9755 "TARGET_ARM"
8a18b90c 9756 "#"
8fa3ba89 9757 [(set_attr "conds" "clob")
1b7da4ac 9758 (set_attr "length" "8,12")
9759 (set_attr "type" "multiple")]
8fa3ba89 9760)
5565501b 9761
8a18b90c 9762(define_insn "*if_move_shift"
9763 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 9764 (if_then_else:SI
8fa3ba89 9765 (match_operator 5 "arm_comparison_operator"
8a18b90c 9766 [(match_operand 6 "cc_register" "") (const_int 0)])
9767 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9768 (match_operator:SI 4 "shift_operator"
9769 [(match_operand:SI 2 "s_register_operand" "r,r,r")
9770 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
cffb2a26 9771 "TARGET_ARM"
5565501b 9772 "@
8a18b90c 9773 mov%D5\\t%0, %2%S4
9774 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
9775 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
8fa3ba89 9776 [(set_attr "conds" "use")
331beb1a 9777 (set_attr "shift" "2")
a2cd141b 9778 (set_attr "length" "4,8,8")
1b7da4ac 9779 (set_attr "type" "mov_shift_reg,multiple,multiple")]
8fa3ba89 9780)
9c08d1fa 9781
f7fbdd4a 9782(define_insn "*ifcompare_shift_shift"
8a18b90c 9783 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 9784 (if_then_else:SI
8fa3ba89 9785 (match_operator 7 "arm_comparison_operator"
8a18b90c 9786 [(match_operand:SI 5 "s_register_operand" "r")
9787 (match_operand:SI 6 "arm_add_operand" "rIL")])
5565501b 9788 (match_operator:SI 8 "shift_operator"
8a18b90c 9789 [(match_operand:SI 1 "s_register_operand" "r")
9790 (match_operand:SI 2 "arm_rhs_operand" "rM")])
5565501b 9791 (match_operator:SI 9 "shift_operator"
8a18b90c 9792 [(match_operand:SI 3 "s_register_operand" "r")
9793 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
bd5b4116 9794 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9795 "TARGET_ARM"
8a18b90c 9796 "#"
8fa3ba89 9797 [(set_attr "conds" "clob")
1b7da4ac 9798 (set_attr "length" "12")
9799 (set_attr "type" "multiple")]
8fa3ba89 9800)
9c08d1fa 9801
8a18b90c 9802(define_insn "*if_shift_shift"
9803 [(set (match_operand:SI 0 "s_register_operand" "=r")
9804 (if_then_else:SI
8fa3ba89 9805 (match_operator 5 "arm_comparison_operator"
8a18b90c 9806 [(match_operand 8 "cc_register" "") (const_int 0)])
9807 (match_operator:SI 6 "shift_operator"
9808 [(match_operand:SI 1 "s_register_operand" "r")
9809 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9810 (match_operator:SI 7 "shift_operator"
9811 [(match_operand:SI 3 "s_register_operand" "r")
9812 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
cffb2a26 9813 "TARGET_ARM"
8a18b90c 9814 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
8fa3ba89 9815 [(set_attr "conds" "use")
331beb1a 9816 (set_attr "shift" "1")
a2cd141b 9817 (set_attr "length" "8")
9818 (set (attr "type") (if_then_else
9819 (and (match_operand 2 "const_int_operand" "")
9820 (match_operand 4 "const_int_operand" ""))
1aed5204 9821 (const_string "mov_shift")
9822 (const_string "mov_shift_reg")))]
8fa3ba89 9823)
8a18b90c 9824
f7fbdd4a 9825(define_insn "*ifcompare_not_arith"
8a18b90c 9826 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 9827 (if_then_else:SI
8fa3ba89 9828 (match_operator 6 "arm_comparison_operator"
8a18b90c 9829 [(match_operand:SI 4 "s_register_operand" "r")
9830 (match_operand:SI 5 "arm_add_operand" "rIL")])
9831 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5565501b 9832 (match_operator:SI 7 "shiftable_operator"
8a18b90c 9833 [(match_operand:SI 2 "s_register_operand" "r")
9834 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
bd5b4116 9835 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9836 "TARGET_ARM"
8a18b90c 9837 "#"
8fa3ba89 9838 [(set_attr "conds" "clob")
1b7da4ac 9839 (set_attr "length" "12")
9840 (set_attr "type" "multiple")]
8fa3ba89 9841)
9c08d1fa 9842
8a18b90c 9843(define_insn "*if_not_arith"
9844 [(set (match_operand:SI 0 "s_register_operand" "=r")
9845 (if_then_else:SI
8fa3ba89 9846 (match_operator 5 "arm_comparison_operator"
8a18b90c 9847 [(match_operand 4 "cc_register" "") (const_int 0)])
9848 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9849 (match_operator:SI 6 "shiftable_operator"
9850 [(match_operand:SI 2 "s_register_operand" "r")
9851 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
cffb2a26 9852 "TARGET_ARM"
8a18b90c 9853 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
8fa3ba89 9854 [(set_attr "conds" "use")
1aed5204 9855 (set_attr "type" "mvn_reg")
8fa3ba89 9856 (set_attr "length" "8")]
9857)
8a18b90c 9858
9859(define_insn "*ifcompare_arith_not"
9860 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 9861 (if_then_else:SI
8fa3ba89 9862 (match_operator 6 "arm_comparison_operator"
8a18b90c 9863 [(match_operand:SI 4 "s_register_operand" "r")
9864 (match_operand:SI 5 "arm_add_operand" "rIL")])
5565501b 9865 (match_operator:SI 7 "shiftable_operator"
8a18b90c 9866 [(match_operand:SI 2 "s_register_operand" "r")
9867 (match_operand:SI 3 "arm_rhs_operand" "rI")])
9868 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
bd5b4116 9869 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9870 "TARGET_ARM"
8a18b90c 9871 "#"
8fa3ba89 9872 [(set_attr "conds" "clob")
1b7da4ac 9873 (set_attr "length" "12")
9874 (set_attr "type" "multiple")]
8fa3ba89 9875)
9c08d1fa 9876
8a18b90c 9877(define_insn "*if_arith_not"
9878 [(set (match_operand:SI 0 "s_register_operand" "=r")
9879 (if_then_else:SI
8fa3ba89 9880 (match_operator 5 "arm_comparison_operator"
8a18b90c 9881 [(match_operand 4 "cc_register" "") (const_int 0)])
9882 (match_operator:SI 6 "shiftable_operator"
9883 [(match_operand:SI 2 "s_register_operand" "r")
9884 (match_operand:SI 3 "arm_rhs_operand" "rI")])
9885 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
cffb2a26 9886 "TARGET_ARM"
8a18b90c 9887 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
8fa3ba89 9888 [(set_attr "conds" "use")
1b7da4ac 9889 (set_attr "type" "multiple")
8fa3ba89 9890 (set_attr "length" "8")]
9891)
8a18b90c 9892
f7fbdd4a 9893(define_insn "*ifcompare_neg_move"
8a18b90c 9894 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 9895 (if_then_else:SI
8fa3ba89 9896 (match_operator 5 "arm_comparison_operator"
8a18b90c 9897 [(match_operand:SI 3 "s_register_operand" "r,r")
9898 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9899 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
9900 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 9901 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9902 "TARGET_ARM"
8a18b90c 9903 "#"
8fa3ba89 9904 [(set_attr "conds" "clob")
1b7da4ac 9905 (set_attr "length" "8,12")
9906 (set_attr "type" "multiple")]
8fa3ba89 9907)
8a18b90c 9908
9909(define_insn "*if_neg_move"
9910 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9911 (if_then_else:SI
8fa3ba89 9912 (match_operator 4 "arm_comparison_operator"
8a18b90c 9913 [(match_operand 3 "cc_register" "") (const_int 0)])
9914 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9915 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 9916 "TARGET_ARM"
8a18b90c 9917 "@
9918 rsb%d4\\t%0, %2, #0
9919 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
9920 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
8fa3ba89 9921 [(set_attr "conds" "use")
1b7da4ac 9922 (set_attr "length" "4,8,8")
9923 (set_attr "type" "logic_shift_imm,multiple,multiple")]
8fa3ba89 9924)
9c08d1fa 9925
f7fbdd4a 9926(define_insn "*ifcompare_move_neg"
8a18b90c 9927 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 9928 (if_then_else:SI
8fa3ba89 9929 (match_operator 5 "arm_comparison_operator"
8a18b90c 9930 [(match_operand:SI 3 "s_register_operand" "r,r")
9931 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9932 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9933 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 9934 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9935 "TARGET_ARM"
8a18b90c 9936 "#"
8fa3ba89 9937 [(set_attr "conds" "clob")
1b7da4ac 9938 (set_attr "length" "8,12")
9939 (set_attr "type" "multiple")]
8fa3ba89 9940)
8a18b90c 9941
9942(define_insn "*if_move_neg"
9943 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9944 (if_then_else:SI
8fa3ba89 9945 (match_operator 4 "arm_comparison_operator"
8a18b90c 9946 [(match_operand 3 "cc_register" "") (const_int 0)])
9947 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9948 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
cffb2a26 9949 "TARGET_ARM"
8a18b90c 9950 "@
9951 rsb%D4\\t%0, %2, #0
9952 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
9953 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
0d66636f 9954 [(set_attr "conds" "use")
1b7da4ac 9955 (set_attr "length" "4,8,8")
9956 (set_attr "type" "logic_shift_imm,multiple,multiple")]
0d66636f 9957)
9c08d1fa 9958
f7fbdd4a 9959(define_insn "*arith_adjacentmem"
9c08d1fa 9960 [(set (match_operand:SI 0 "s_register_operand" "=r")
9961 (match_operator:SI 1 "shiftable_operator"
9962 [(match_operand:SI 2 "memory_operand" "m")
9963 (match_operand:SI 3 "memory_operand" "m")]))
9964 (clobber (match_scratch:SI 4 "=r"))]
cffb2a26 9965 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9c08d1fa 9966 "*
215b30b3 9967 {
9968 rtx ldm[3];
9969 rtx arith[4];
94dee231 9970 rtx base_reg;
9971 HOST_WIDE_INT val1 = 0, val2 = 0;
9c08d1fa 9972
215b30b3 9973 if (REGNO (operands[0]) > REGNO (operands[4]))
9974 {
9975 ldm[1] = operands[4];
9976 ldm[2] = operands[0];
9977 }
9978 else
9979 {
9980 ldm[1] = operands[0];
9981 ldm[2] = operands[4];
9982 }
94dee231 9983
9984 base_reg = XEXP (operands[2], 0);
9985
9986 if (!REG_P (base_reg))
9987 {
9988 val1 = INTVAL (XEXP (base_reg, 1));
9989 base_reg = XEXP (base_reg, 0);
9990 }
9991
9992 if (!REG_P (XEXP (operands[3], 0)))
215b30b3 9993 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
94dee231 9994
215b30b3 9995 arith[0] = operands[0];
9996 arith[3] = operands[1];
94dee231 9997
215b30b3 9998 if (val1 < val2)
9999 {
10000 arith[1] = ldm[1];
10001 arith[2] = ldm[2];
10002 }
10003 else
10004 {
10005 arith[1] = ldm[2];
10006 arith[2] = ldm[1];
10007 }
94dee231 10008
10009 ldm[0] = base_reg;
10010 if (val1 !=0 && val2 != 0)
215b30b3 10011 {
cdb1295a 10012 rtx ops[3];
10013
94dee231 10014 if (val1 == 4 || val2 == 4)
10015 /* Other val must be 8, since we know they are adjacent and neither
10016 is zero. */
25f905c2 10017 output_asm_insn (\"ldm%(ib%)\\t%0, {%1, %2}\", ldm);
cdb1295a 10018 else if (const_ok_for_arm (val1) || const_ok_for_arm (-val1))
94dee231 10019 {
94dee231 10020 ldm[0] = ops[0] = operands[4];
10021 ops[1] = base_reg;
10022 ops[2] = GEN_INT (val1);
10023 output_add_immediate (ops);
10024 if (val1 < val2)
25f905c2 10025 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
94dee231 10026 else
25f905c2 10027 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
94dee231 10028 }
cdb1295a 10029 else
10030 {
10031 /* Offset is out of range for a single add, so use two ldr. */
10032 ops[0] = ldm[1];
10033 ops[1] = base_reg;
10034 ops[2] = GEN_INT (val1);
10035 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10036 ops[0] = ldm[2];
10037 ops[2] = GEN_INT (val2);
10038 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10039 }
215b30b3 10040 }
94dee231 10041 else if (val1 != 0)
215b30b3 10042 {
215b30b3 10043 if (val1 < val2)
25f905c2 10044 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
215b30b3 10045 else
25f905c2 10046 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
215b30b3 10047 }
10048 else
10049 {
215b30b3 10050 if (val1 < val2)
25f905c2 10051 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
215b30b3 10052 else
25f905c2 10053 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
215b30b3 10054 }
10055 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
10056 return \"\";
10057 }"
10058 [(set_attr "length" "12")
10059 (set_attr "predicable" "yes")
a2cd141b 10060 (set_attr "type" "load1")]
215b30b3 10061)
9c08d1fa 10062
9c08d1fa 10063; This pattern is never tried by combine, so do it as a peephole
10064
a0f94409 10065(define_peephole2
372575c7 10066 [(set (match_operand:SI 0 "arm_general_register_operand" "")
10067 (match_operand:SI 1 "arm_general_register_operand" ""))
bd5b4116 10068 (set (reg:CC CC_REGNUM)
aea4c774 10069 (compare:CC (match_dup 1) (const_int 0)))]
372575c7 10070 "TARGET_ARM"
a0f94409 10071 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
10072 (set (match_dup 0) (match_dup 1))])]
10073 ""
0d66636f 10074)
9c08d1fa 10075
9c08d1fa 10076(define_split
10077 [(set (match_operand:SI 0 "s_register_operand" "")
10078 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
10079 (const_int 0))
8fa3ba89 10080 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9c08d1fa 10081 [(match_operand:SI 3 "s_register_operand" "")
10082 (match_operand:SI 4 "arm_rhs_operand" "")]))))
10083 (clobber (match_operand:SI 5 "s_register_operand" ""))]
cffb2a26 10084 "TARGET_ARM"
9c08d1fa 10085 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
10086 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
10087 (match_dup 5)))]
215b30b3 10088 ""
10089)
9c08d1fa 10090
aea4c774 10091;; This split can be used because CC_Z mode implies that the following
10092;; branch will be an equality, or an unsigned inequality, so the sign
10093;; extension is not needed.
9c08d1fa 10094
aea4c774 10095(define_split
bd5b4116 10096 [(set (reg:CC_Z CC_REGNUM)
aea4c774 10097 (compare:CC_Z
10098 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9c08d1fa 10099 (const_int 24))
aea4c774 10100 (match_operand 1 "const_int_operand" "")))
10101 (clobber (match_scratch:SI 2 ""))]
cffb2a26 10102 "TARGET_ARM
10103 && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
10104 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
aea4c774 10105 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
bd5b4116 10106 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
aea4c774 10107 "
9c08d1fa 10108 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
215b30b3 10109 "
10110)
25f905c2 10111;; ??? Check the patterns above for Thumb-2 usefulness
9c08d1fa 10112
87b22bf7 10113(define_expand "prologue"
10114 [(clobber (const_int 0))]
cffb2a26 10115 "TARGET_EITHER"
25f905c2 10116 "if (TARGET_32BIT)
cffb2a26 10117 arm_expand_prologue ();
10118 else
25f905c2 10119 thumb1_expand_prologue ();
87b22bf7 10120 DONE;
cffb2a26 10121 "
10122)
87b22bf7 10123
56d27660 10124(define_expand "epilogue"
4c44712e 10125 [(clobber (const_int 0))]
cffb2a26 10126 "TARGET_EITHER"
56d27660 10127 "
18d50ae6 10128 if (crtl->calls_eh_return)
fb94f18b 10129 emit_insn (gen_force_register_use (gen_rtx_REG (Pmode, 2)));
25f905c2 10130 if (TARGET_THUMB1)
c3635784 10131 {
10132 thumb1_expand_epilogue ();
10133 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
10134 gen_rtvec (1, ret_rtx), VUNSPEC_EPILOGUE));
10135 }
10136 else if (HAVE_return)
10137 {
10138 /* HAVE_return is testing for USE_RETURN_INSN (FALSE). Hence,
10139 no need for explicit testing again. */
10140 emit_jump_insn (gen_return ());
10141 }
10142 else if (TARGET_32BIT)
10143 {
10144 arm_expand_epilogue (true);
10145 }
cffb2a26 10146 DONE;
10147 "
10148)
56d27660 10149
ef5651d0 10150;; Note - although unspec_volatile's USE all hard registers,
10151;; USEs are ignored after relaod has completed. Thus we need
10152;; to add an unspec of the link register to ensure that flow
10153;; does not think that it is unused by the sibcall branch that
10154;; will replace the standard function epilogue.
c3635784 10155(define_expand "sibcall_epilogue"
fb94f18b 10156 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_REGISTER_USE)
c3635784 10157 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
10158 "TARGET_32BIT"
10159 "
10160 arm_expand_epilogue (false);
10161 DONE;
10162 "
1c494086 10163)
10164
cffb2a26 10165(define_expand "eh_epilogue"
7db9af5d 10166 [(use (match_operand:SI 0 "register_operand" ""))
10167 (use (match_operand:SI 1 "register_operand" ""))
10168 (use (match_operand:SI 2 "register_operand" ""))]
cffb2a26 10169 "TARGET_EITHER"
10170 "
215b30b3 10171 {
10172 cfun->machine->eh_epilogue_sp_ofs = operands[1];
0438d37f 10173 if (!REG_P (operands[2]) || REGNO (operands[2]) != 2)
215b30b3 10174 {
10175 rtx ra = gen_rtx_REG (Pmode, 2);
10176
10177 emit_move_insn (ra, operands[2]);
10178 operands[2] = ra;
10179 }
5cf3595a 10180 /* This is a hack -- we may have crystalized the function type too
10181 early. */
10182 cfun->machine->func_type = 0;
215b30b3 10183 }"
10184)
56d27660 10185
9c08d1fa 10186;; This split is only used during output to reduce the number of patterns
10187;; that need assembler instructions adding to them. We allowed the setting
10188;; of the conditions to be implicit during rtl generation so that
10189;; the conditional compare patterns would work. However this conflicts to
8a18b90c 10190;; some extent with the conditional data operations, so we have to split them
9c08d1fa 10191;; up again here.
10192
25f905c2 10193;; ??? Need to audit these splitters for Thumb-2. Why isn't normal
10194;; conditional execution sufficient?
10195
9c08d1fa 10196(define_split
10197 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 10198 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10199 [(match_operand 2 "" "") (match_operand 3 "" "")])
10200 (match_dup 0)
10201 (match_operand 4 "" "")))
bd5b4116 10202 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10203 "TARGET_ARM && reload_completed"
8fa3ba89 10204 [(set (match_dup 5) (match_dup 6))
10205 (cond_exec (match_dup 7)
10206 (set (match_dup 0) (match_dup 4)))]
10207 "
10208 {
10209 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10210 operands[2], operands[3]);
10211 enum rtx_code rc = GET_CODE (operands[1]);
10212
bd5b4116 10213 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10214 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10215 if (mode == CCFPmode || mode == CCFPEmode)
10216 rc = reverse_condition_maybe_unordered (rc);
10217 else
10218 rc = reverse_condition (rc);
10219
10220 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
10221 }"
10222)
10223
10224(define_split
10225 [(set (match_operand:SI 0 "s_register_operand" "")
10226 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10227 [(match_operand 2 "" "") (match_operand 3 "" "")])
10228 (match_operand 4 "" "")
10229 (match_dup 0)))
bd5b4116 10230 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10231 "TARGET_ARM && reload_completed"
8fa3ba89 10232 [(set (match_dup 5) (match_dup 6))
10233 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
10234 (set (match_dup 0) (match_dup 4)))]
10235 "
10236 {
10237 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10238 operands[2], operands[3]);
10239
bd5b4116 10240 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10241 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10242 }"
10243)
10244
10245(define_split
10246 [(set (match_operand:SI 0 "s_register_operand" "")
10247 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9c08d1fa 10248 [(match_operand 2 "" "") (match_operand 3 "" "")])
10249 (match_operand 4 "" "")
10250 (match_operand 5 "" "")))
bd5b4116 10251 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10252 "TARGET_ARM && reload_completed"
8fa3ba89 10253 [(set (match_dup 6) (match_dup 7))
10254 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10255 (set (match_dup 0) (match_dup 4)))
10256 (cond_exec (match_dup 8)
10257 (set (match_dup 0) (match_dup 5)))]
10258 "
10259 {
10260 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10261 operands[2], operands[3]);
10262 enum rtx_code rc = GET_CODE (operands[1]);
10263
bd5b4116 10264 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10265 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10266 if (mode == CCFPmode || mode == CCFPEmode)
10267 rc = reverse_condition_maybe_unordered (rc);
10268 else
10269 rc = reverse_condition (rc);
10270
10271 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10272 }"
10273)
10274
cffb2a26 10275(define_split
10276 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 10277 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
cffb2a26 10278 [(match_operand:SI 2 "s_register_operand" "")
10279 (match_operand:SI 3 "arm_add_operand" "")])
10280 (match_operand:SI 4 "arm_rhs_operand" "")
10281 (not:SI
10282 (match_operand:SI 5 "s_register_operand" ""))))
bd5b4116 10283 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10284 "TARGET_ARM && reload_completed"
cffb2a26 10285 [(set (match_dup 6) (match_dup 7))
f6c53574 10286 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10287 (set (match_dup 0) (match_dup 4)))
10288 (cond_exec (match_dup 8)
10289 (set (match_dup 0) (not:SI (match_dup 5))))]
cffb2a26 10290 "
215b30b3 10291 {
10292 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10293 operands[2], operands[3]);
f6c53574 10294 enum rtx_code rc = GET_CODE (operands[1]);
cffb2a26 10295
bd5b4116 10296 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
1a83b3ff 10297 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
f6c53574 10298 if (mode == CCFPmode || mode == CCFPEmode)
10299 rc = reverse_condition_maybe_unordered (rc);
10300 else
10301 rc = reverse_condition (rc);
10302
10303 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
215b30b3 10304 }"
10305)
cffb2a26 10306
10307(define_insn "*cond_move_not"
10308 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10309 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
cffb2a26 10310 [(match_operand 3 "cc_register" "") (const_int 0)])
10311 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10312 (not:SI
10313 (match_operand:SI 2 "s_register_operand" "r,r"))))]
10314 "TARGET_ARM"
10315 "@
10316 mvn%D4\\t%0, %2
10317 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
0d66636f 10318 [(set_attr "conds" "use")
1b7da4ac 10319 (set_attr "type" "mvn_reg,multiple")
0d66636f 10320 (set_attr "length" "4,8")]
10321)
cffb2a26 10322
9c08d1fa 10323;; The next two patterns occur when an AND operation is followed by a
10324;; scc insn sequence
10325
f7fbdd4a 10326(define_insn "*sign_extract_onebit"
9c08d1fa 10327 [(set (match_operand:SI 0 "s_register_operand" "=r")
10328 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10329 (const_int 1)
ed750274 10330 (match_operand:SI 2 "const_int_operand" "n")))
10331 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10332 "TARGET_ARM"
9c08d1fa 10333 "*
0d66636f 10334 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10335 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
10336 return \"mvnne\\t%0, #0\";
10337 "
10338 [(set_attr "conds" "clob")
1b7da4ac 10339 (set_attr "length" "8")
10340 (set_attr "type" "multiple")]
0d66636f 10341)
9c08d1fa 10342
f7fbdd4a 10343(define_insn "*not_signextract_onebit"
9c08d1fa 10344 [(set (match_operand:SI 0 "s_register_operand" "=r")
10345 (not:SI
10346 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10347 (const_int 1)
ed750274 10348 (match_operand:SI 2 "const_int_operand" "n"))))
10349 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10350 "TARGET_ARM"
9c08d1fa 10351 "*
0d66636f 10352 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10353 output_asm_insn (\"tst\\t%1, %2\", operands);
10354 output_asm_insn (\"mvneq\\t%0, #0\", operands);
10355 return \"movne\\t%0, #0\";
10356 "
10357 [(set_attr "conds" "clob")
1b7da4ac 10358 (set_attr "length" "12")
10359 (set_attr "type" "multiple")]
0d66636f 10360)
25f905c2 10361;; ??? The above patterns need auditing for Thumb-2
87b22bf7 10362
0d66636f 10363;; Push multiple registers to the stack. Registers are in parallel (use ...)
10364;; expressions. For simplicity, the first register is also in the unspec
10365;; part.
08508cbf 10366;; To avoid the usage of GNU extension, the length attribute is computed
10367;; in a C function arm_attr_length_push_multi.
f7fbdd4a 10368(define_insn "*push_multi"
87b22bf7 10369 [(match_parallel 2 "multi_register_push"
7571d3f7 10370 [(set (match_operand:BLK 0 "push_mult_memory_operand" "")
3cc80a30 10371 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "")]
e1159bbe 10372 UNSPEC_PUSH_MULT))])]
7571d3f7 10373 ""
87b22bf7 10374 "*
215b30b3 10375 {
10376 int num_saves = XVECLEN (operands[2], 0);
ed593f11 10377
215b30b3 10378 /* For the StrongARM at least it is faster to
25f905c2 10379 use STR to store only a single register.
542d5028 10380 In Thumb mode always use push, and the assembler will pick
10381 something appropriate. */
25f905c2 10382 if (num_saves == 1 && TARGET_ARM)
61309563 10383 output_asm_insn (\"str%?\\t%1, [%m0, #-4]!\", operands);
215b30b3 10384 else
10385 {
10386 int i;
10387 char pattern[100];
ed593f11 10388
25f905c2 10389 if (TARGET_ARM)
61309563 10390 strcpy (pattern, \"stm%(fd%)\\t%m0!, {%1\");
10391 else if (TARGET_THUMB2)
10392 strcpy (pattern, \"push%?\\t{%1\");
25f905c2 10393 else
10394 strcpy (pattern, \"push\\t{%1\");
215b30b3 10395
6079f055 10396 for (i = 1; i < num_saves; i++)
215b30b3 10397 {
10398 strcat (pattern, \", %|\");
10399 strcat (pattern,
10400 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
10401 }
10402
10403 strcat (pattern, \"}\");
10404 output_asm_insn (pattern, operands);
10405 }
10406
10407 return \"\";
10408 }"
a6864a24 10409 [(set_attr "type" "store4")
10410 (set (attr "length")
08508cbf 10411 (symbol_ref "arm_attr_length_push_multi (operands[2], operands[1])"))]
215b30b3 10412)
f7fbdd4a 10413
4c58c898 10414(define_insn "stack_tie"
10415 [(set (mem:BLK (scratch))
aaa37ad6 10416 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "rk")
10417 (match_operand:SI 1 "s_register_operand" "rk")]
4c58c898 10418 UNSPEC_PRLG_STK))]
10419 ""
10420 ""
1b7da4ac 10421 [(set_attr "length" "0")
10422 (set_attr "type" "block")]
4c58c898 10423)
10424
426be8c5 10425;; Pop (as used in epilogue RTL)
10426;;
10427(define_insn "*load_multiple_with_writeback"
10428 [(match_parallel 0 "load_multiple_operation"
10429 [(set (match_operand:SI 1 "s_register_operand" "+rk")
10430 (plus:SI (match_dup 1)
809003b3 10431 (match_operand:SI 2 "const_int_I_operand" "I")))
426be8c5 10432 (set (match_operand:SI 3 "s_register_operand" "=rk")
10433 (mem:SI (match_dup 1)))
10434 ])]
10435 "TARGET_32BIT && (reload_in_progress || reload_completed)"
10436 "*
10437 {
10438 arm_output_multireg_pop (operands, /*return_pc=*/false,
10439 /*cond=*/const_true_rtx,
10440 /*reverse=*/false,
10441 /*update=*/true);
10442 return \"\";
10443 }
10444 "
10445 [(set_attr "type" "load4")
10446 (set_attr "predicable" "yes")]
10447)
10448
10449;; Pop with return (as used in epilogue RTL)
10450;;
10451;; This instruction is generated when the registers are popped at the end of
10452;; epilogue. Here, instead of popping the value into LR and then generating
10453;; jump to LR, value is popped into PC directly. Hence, the pattern is combined
10454;; with (return).
10455(define_insn "*pop_multiple_with_writeback_and_return"
10456 [(match_parallel 0 "pop_multiple_return"
10457 [(return)
10458 (set (match_operand:SI 1 "s_register_operand" "+rk")
10459 (plus:SI (match_dup 1)
809003b3 10460 (match_operand:SI 2 "const_int_I_operand" "I")))
426be8c5 10461 (set (match_operand:SI 3 "s_register_operand" "=rk")
10462 (mem:SI (match_dup 1)))
10463 ])]
10464 "TARGET_32BIT && (reload_in_progress || reload_completed)"
10465 "*
10466 {
10467 arm_output_multireg_pop (operands, /*return_pc=*/true,
10468 /*cond=*/const_true_rtx,
10469 /*reverse=*/false,
10470 /*update=*/true);
10471 return \"\";
10472 }
10473 "
10474 [(set_attr "type" "load4")
10475 (set_attr "predicable" "yes")]
10476)
10477
10478(define_insn "*pop_multiple_with_return"
10479 [(match_parallel 0 "pop_multiple_return"
10480 [(return)
10481 (set (match_operand:SI 2 "s_register_operand" "=rk")
10482 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
10483 ])]
10484 "TARGET_32BIT && (reload_in_progress || reload_completed)"
10485 "*
10486 {
10487 arm_output_multireg_pop (operands, /*return_pc=*/true,
10488 /*cond=*/const_true_rtx,
10489 /*reverse=*/false,
10490 /*update=*/false);
10491 return \"\";
10492 }
10493 "
10494 [(set_attr "type" "load4")
10495 (set_attr "predicable" "yes")]
10496)
10497
10498;; Load into PC and return
10499(define_insn "*ldr_with_return"
10500 [(return)
10501 (set (reg:SI PC_REGNUM)
10502 (mem:SI (post_inc:SI (match_operand:SI 0 "s_register_operand" "+rk"))))]
10503 "TARGET_32BIT && (reload_in_progress || reload_completed)"
10504 "ldr%?\t%|pc, [%0], #4"
10505 [(set_attr "type" "load1")
10506 (set_attr "predicable" "yes")]
10507)
1a0b0f12 10508;; Pop for floating point registers (as used in epilogue RTL)
10509(define_insn "*vfp_pop_multiple_with_writeback"
10510 [(match_parallel 0 "pop_multiple_fp"
10511 [(set (match_operand:SI 1 "s_register_operand" "+rk")
10512 (plus:SI (match_dup 1)
809003b3 10513 (match_operand:SI 2 "const_int_I_operand" "I")))
2f2163a4 10514 (set (match_operand:DF 3 "vfp_hard_register_operand" "")
1a0b0f12 10515 (mem:DF (match_dup 1)))])]
10516 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
10517 "*
10518 {
10519 int num_regs = XVECLEN (operands[0], 0);
10520 char pattern[100];
10521 rtx op_list[2];
10522 strcpy (pattern, \"fldmfdd\\t\");
10523 strcat (pattern, reg_names[REGNO (SET_DEST (XVECEXP (operands[0], 0, 0)))]);
10524 strcat (pattern, \"!, {\");
10525 op_list[0] = XEXP (XVECEXP (operands[0], 0, 1), 0);
10526 strcat (pattern, \"%P0\");
10527 if ((num_regs - 1) > 1)
10528 {
10529 strcat (pattern, \"-%P1\");
10530 op_list [1] = XEXP (XVECEXP (operands[0], 0, num_regs - 1), 0);
10531 }
10532
10533 strcat (pattern, \"}\");
10534 output_asm_insn (pattern, op_list);
10535 return \"\";
10536 }
10537 "
10538 [(set_attr "type" "load4")
10539 (set_attr "conds" "unconditional")
10540 (set_attr "predicable" "no")]
10541)
10542
f7fbdd4a 10543;; Special patterns for dealing with the constant pool
10544
cffb2a26 10545(define_insn "align_4"
e1159bbe 10546 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
cffb2a26 10547 "TARGET_EITHER"
f7fbdd4a 10548 "*
cffb2a26 10549 assemble_align (32);
f7fbdd4a 10550 return \"\";
cffb2a26 10551 "
1b7da4ac 10552 [(set_attr "type" "no_insn")]
cffb2a26 10553)
f7fbdd4a 10554
755eb2b4 10555(define_insn "align_8"
10556 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
f9273c43 10557 "TARGET_EITHER"
755eb2b4 10558 "*
10559 assemble_align (64);
10560 return \"\";
10561 "
1b7da4ac 10562 [(set_attr "type" "no_insn")]
755eb2b4 10563)
10564
cffb2a26 10565(define_insn "consttable_end"
e1159bbe 10566 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
cffb2a26 10567 "TARGET_EITHER"
f7fbdd4a 10568 "*
cffb2a26 10569 making_const_table = FALSE;
f7fbdd4a 10570 return \"\";
cffb2a26 10571 "
1b7da4ac 10572 [(set_attr "type" "no_insn")]
cffb2a26 10573)
f7fbdd4a 10574
cffb2a26 10575(define_insn "consttable_4"
e1159bbe 10576 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
cffb2a26 10577 "TARGET_EITHER"
10578 "*
10579 {
9b8516be 10580 rtx x = operands[0];
cffb2a26 10581 making_const_table = TRUE;
9b8516be 10582 switch (GET_MODE_CLASS (GET_MODE (x)))
cffb2a26 10583 {
10584 case MODE_FLOAT:
9b8516be 10585 if (GET_MODE (x) == HFmode)
10586 arm_emit_fp16_const (x);
10587 else
10588 {
10589 REAL_VALUE_TYPE r;
10590 REAL_VALUE_FROM_CONST_DOUBLE (r, x);
10591 assemble_real (r, GET_MODE (x), BITS_PER_WORD);
10592 }
10593 break;
cffb2a26 10594 default:
7b04c5d5 10595 /* XXX: Sometimes gcc does something really dumb and ends up with
10596 a HIGH in a constant pool entry, usually because it's trying to
10597 load into a VFP register. We know this will always be used in
10598 combination with a LO_SUM which ignores the high bits, so just
10599 strip off the HIGH. */
10600 if (GET_CODE (x) == HIGH)
10601 x = XEXP (x, 0);
9b8516be 10602 assemble_integer (x, 4, BITS_PER_WORD, 1);
10603 mark_symbol_refs_as_used (x);
cffb2a26 10604 break;
10605 }
10606 return \"\";
10607 }"
1b7da4ac 10608 [(set_attr "length" "4")
10609 (set_attr "type" "no_insn")]
cffb2a26 10610)
10611
10612(define_insn "consttable_8"
e1159bbe 10613 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
cffb2a26 10614 "TARGET_EITHER"
10615 "*
10616 {
10617 making_const_table = TRUE;
10618 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10619 {
10620 case MODE_FLOAT:
10621 {
badfe841 10622 REAL_VALUE_TYPE r;
10623 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10624 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
cffb2a26 10625 break;
10626 }
10627 default:
09d688ff 10628 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
cffb2a26 10629 break;
10630 }
10631 return \"\";
10632 }"
1b7da4ac 10633 [(set_attr "length" "8")
10634 (set_attr "type" "no_insn")]
cffb2a26 10635)
10636
d98a3884 10637(define_insn "consttable_16"
10638 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_16)]
10639 "TARGET_EITHER"
10640 "*
10641 {
10642 making_const_table = TRUE;
10643 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10644 {
10645 case MODE_FLOAT:
10646 {
10647 REAL_VALUE_TYPE r;
10648 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10649 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10650 break;
10651 }
10652 default:
10653 assemble_integer (operands[0], 16, BITS_PER_WORD, 1);
10654 break;
10655 }
10656 return \"\";
10657 }"
1b7da4ac 10658 [(set_attr "length" "16")
10659 (set_attr "type" "no_insn")]
d98a3884 10660)
10661
331beb1a 10662;; V5 Instructions,
10663
8f4be2be 10664(define_insn "clzsi2"
10665 [(set (match_operand:SI 0 "s_register_operand" "=r")
10666 (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 10667 "TARGET_32BIT && arm_arch5"
ee7cbe0e 10668 "clz%?\\t%0, %1"
bcaec148 10669 [(set_attr "predicable" "yes")
bebe9bbb 10670 (set_attr "type" "clz")])
331beb1a 10671
099ad98b 10672(define_insn "rbitsi2"
10673 [(set (match_operand:SI 0 "s_register_operand" "=r")
10674 (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")] UNSPEC_RBIT))]
10675 "TARGET_32BIT && arm_arch_thumb2"
10676 "rbit%?\\t%0, %1"
10677 [(set_attr "predicable" "yes")
bebe9bbb 10678 (set_attr "type" "clz")])
099ad98b 10679
10680(define_expand "ctzsi2"
10681 [(set (match_operand:SI 0 "s_register_operand" "")
10682 (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
10683 "TARGET_32BIT && arm_arch_thumb2"
10684 "
30191172 10685 {
10686 rtx tmp = gen_reg_rtx (SImode);
10687 emit_insn (gen_rbitsi2 (tmp, operands[1]));
10688 emit_insn (gen_clzsi2 (operands[0], tmp));
10689 }
099ad98b 10690 DONE;
10691 "
10692)
10693
e1159bbe 10694;; V5E instructions.
331beb1a 10695
10696(define_insn "prefetch"
f4e79814 10697 [(prefetch (match_operand:SI 0 "address_operand" "p")
10698 (match_operand:SI 1 "" "")
10699 (match_operand:SI 2 "" ""))]
25f905c2 10700 "TARGET_32BIT && arm_arch5e"
1b7da4ac 10701 "pld\\t%a0"
10702 [(set_attr "type" "load1")]
10703)
331beb1a 10704
0d66636f 10705;; General predication pattern
10706
10707(define_cond_exec
10708 [(match_operator 0 "arm_comparison_operator"
10709 [(match_operand 1 "cc_register" "")
10710 (const_int 0)])]
25f905c2 10711 "TARGET_32BIT"
0d66636f 10712 ""
c7a58118 10713[(set_attr "predicated" "yes")]
0d66636f 10714)
10715
fb94f18b 10716(define_insn "force_register_use"
10717 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_REGISTER_USE)]
063a05c7 10718 ""
fb94f18b 10719 "%@ %0 needed"
1b7da4ac 10720 [(set_attr "length" "0")
10721 (set_attr "type" "no_insn")]
063a05c7 10722)
7db9af5d 10723
4c44712e 10724
10725;; Patterns for exception handling
10726
10727(define_expand "eh_return"
10728 [(use (match_operand 0 "general_operand" ""))]
10729 "TARGET_EITHER"
10730 "
10731 {
25f905c2 10732 if (TARGET_32BIT)
4c44712e 10733 emit_insn (gen_arm_eh_return (operands[0]));
10734 else
10735 emit_insn (gen_thumb_eh_return (operands[0]));
10736 DONE;
10737 }"
10738)
10739
10740;; We can't expand this before we know where the link register is stored.
10741(define_insn_and_split "arm_eh_return"
10742 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
10743 VUNSPEC_EH_RETURN)
10744 (clobber (match_scratch:SI 1 "=&r"))]
10745 "TARGET_ARM"
10746 "#"
10747 "&& reload_completed"
10748 [(const_int 0)]
10749 "
10750 {
10751 arm_set_return_address (operands[0], operands[1]);
10752 DONE;
10753 }"
10754)
10755
f655717d 10756\f
10757;; TLS support
10758
10759(define_insn "load_tp_hard"
10760 [(set (match_operand:SI 0 "register_operand" "=r")
10761 (unspec:SI [(const_int 0)] UNSPEC_TLS))]
10762 "TARGET_HARD_TP"
10763 "mrc%?\\tp15, 0, %0, c13, c0, 3\\t@ load_tp_hard"
1b7da4ac 10764 [(set_attr "predicable" "yes")
4b5d7374 10765 (set_attr "type" "mrs")]
f655717d 10766)
10767
10768;; Doesn't clobber R1-R3. Must use r0 for the first operand.
10769(define_insn "load_tp_soft"
10770 [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
10771 (clobber (reg:SI LR_REGNUM))
10772 (clobber (reg:SI IP_REGNUM))
10773 (clobber (reg:CC CC_REGNUM))]
10774 "TARGET_SOFT_TP"
10775 "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
1b7da4ac 10776 [(set_attr "conds" "clob")
10777 (set_attr "type" "branch")]
f655717d 10778)
10779
f41e4452 10780;; tls descriptor call
10781(define_insn "tlscall"
10782 [(set (reg:SI R0_REGNUM)
10783 (unspec:SI [(reg:SI R0_REGNUM)
10784 (match_operand:SI 0 "" "X")
10785 (match_operand 1 "" "")] UNSPEC_TLS))
10786 (clobber (reg:SI R1_REGNUM))
10787 (clobber (reg:SI LR_REGNUM))
10788 (clobber (reg:SI CC_REGNUM))]
10789 "TARGET_GNU2_TLS"
10790 {
10791 targetm.asm_out.internal_label (asm_out_file, "LPIC",
10792 INTVAL (operands[1]));
10793 return "bl\\t%c0(tlscall)";
10794 }
10795 [(set_attr "conds" "clob")
1b7da4ac 10796 (set_attr "length" "4")
10797 (set_attr "type" "branch")]
f41e4452 10798)
10799
1fe0edab 10800;; For thread pointer builtin
10801(define_expand "get_thread_pointersi"
10802 [(match_operand:SI 0 "s_register_operand" "=r")]
10803 ""
10804 "
10805 {
10806 arm_load_tp (operands[0]);
10807 DONE;
10808 }")
10809
f41e4452 10810;;
10811
aabe09ac 10812;; We only care about the lower 16 bits of the constant
10813;; being inserted into the upper 16 bits of the register.
eca5c984 10814(define_insn "*arm_movtas_ze"
10815 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
10816 (const_int 16)
10817 (const_int 16))
10818 (match_operand:SI 1 "const_int_operand" ""))]
181ab277 10819 "arm_arch_thumb2"
aabe09ac 10820 "movt%?\t%0, %L1"
eca5c984 10821 [(set_attr "predicable" "yes")
7c36fe71 10822 (set_attr "predicable_short_it" "no")
1b7da4ac 10823 (set_attr "length" "4")
10824 (set_attr "type" "mov_imm")]
eca5c984 10825)
10826
c0fc3696 10827(define_insn "*arm_rev"
a486b499 10828 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
10829 (bswap:SI (match_operand:SI 1 "s_register_operand" "l,l,r")))]
10830 "arm_arch6"
10831 "@
10832 rev\t%0, %1
10833 rev%?\t%0, %1
10834 rev%?\t%0, %1"
10835 [(set_attr "arch" "t1,t2,32")
1b7da4ac 10836 (set_attr "length" "2,2,4")
10837 (set_attr "type" "rev")]
ff82f757 10838)
10839
10840(define_expand "arm_legacy_rev"
10841 [(set (match_operand:SI 2 "s_register_operand" "")
10842 (xor:SI (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
10843 (const_int 16))
10844 (match_dup 1)))
10845 (set (match_dup 2)
10846 (lshiftrt:SI (match_dup 2)
10847 (const_int 8)))
10848 (set (match_operand:SI 3 "s_register_operand" "")
10849 (rotatert:SI (match_dup 1)
10850 (const_int 8)))
10851 (set (match_dup 2)
10852 (and:SI (match_dup 2)
10853 (const_int -65281)))
10854 (set (match_operand:SI 0 "s_register_operand" "")
10855 (xor:SI (match_dup 3)
10856 (match_dup 2)))]
10857 "TARGET_32BIT"
10858 ""
10859)
10860
10861;; Reuse temporaries to keep register pressure down.
10862(define_expand "thumb_legacy_rev"
10863 [(set (match_operand:SI 2 "s_register_operand" "")
10864 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
10865 (const_int 24)))
10866 (set (match_operand:SI 3 "s_register_operand" "")
10867 (lshiftrt:SI (match_dup 1)
10868 (const_int 24)))
10869 (set (match_dup 3)
10870 (ior:SI (match_dup 3)
10871 (match_dup 2)))
10872 (set (match_operand:SI 4 "s_register_operand" "")
10873 (const_int 16))
10874 (set (match_operand:SI 5 "s_register_operand" "")
10875 (rotatert:SI (match_dup 1)
10876 (match_dup 4)))
10877 (set (match_dup 2)
10878 (ashift:SI (match_dup 5)
10879 (const_int 24)))
10880 (set (match_dup 5)
10881 (lshiftrt:SI (match_dup 5)
10882 (const_int 24)))
10883 (set (match_dup 5)
10884 (ior:SI (match_dup 5)
10885 (match_dup 2)))
10886 (set (match_dup 5)
10887 (rotatert:SI (match_dup 5)
10888 (match_dup 4)))
10889 (set (match_operand:SI 0 "s_register_operand" "")
10890 (ior:SI (match_dup 5)
10891 (match_dup 3)))]
10892 "TARGET_THUMB"
10893 ""
10894)
10895
10896(define_expand "bswapsi2"
10897 [(set (match_operand:SI 0 "s_register_operand" "=r")
10898 (bswap:SI (match_operand:SI 1 "s_register_operand" "r")))]
8d1af482 10899"TARGET_EITHER && (arm_arch6 || !optimize_size)"
ff82f757 10900"
8d1af482 10901 if (!arm_arch6)
10902 {
10903 rtx op2 = gen_reg_rtx (SImode);
10904 rtx op3 = gen_reg_rtx (SImode);
ff82f757 10905
8d1af482 10906 if (TARGET_THUMB)
10907 {
10908 rtx op4 = gen_reg_rtx (SImode);
10909 rtx op5 = gen_reg_rtx (SImode);
ff82f757 10910
8d1af482 10911 emit_insn (gen_thumb_legacy_rev (operands[0], operands[1],
10912 op2, op3, op4, op5));
10913 }
10914 else
10915 {
10916 emit_insn (gen_arm_legacy_rev (operands[0], operands[1],
10917 op2, op3));
10918 }
ff82f757 10919
8d1af482 10920 DONE;
10921 }
ff82f757 10922 "
10923)
10924
a486b499 10925;; bswap16 patterns: use revsh and rev16 instructions for the signed
10926;; and unsigned variants, respectively. For rev16, expose
10927;; byte-swapping in the lower 16 bits only.
10928(define_insn "*arm_revsh"
10929 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
10930 (sign_extend:SI (bswap:HI (match_operand:HI 1 "s_register_operand" "l,l,r"))))]
10931 "arm_arch6"
10932 "@
10933 revsh\t%0, %1
10934 revsh%?\t%0, %1
10935 revsh%?\t%0, %1"
10936 [(set_attr "arch" "t1,t2,32")
1b7da4ac 10937 (set_attr "length" "2,2,4")
10938 (set_attr "type" "rev")]
a486b499 10939)
10940
10941(define_insn "*arm_rev16"
10942 [(set (match_operand:HI 0 "s_register_operand" "=l,l,r")
10943 (bswap:HI (match_operand:HI 1 "s_register_operand" "l,l,r")))]
10944 "arm_arch6"
10945 "@
10946 rev16\t%0, %1
10947 rev16%?\t%0, %1
10948 rev16%?\t%0, %1"
10949 [(set_attr "arch" "t1,t2,32")
1b7da4ac 10950 (set_attr "length" "2,2,4")
10951 (set_attr "type" "rev")]
09f69e55 10952)
10953
10954;; There are no canonicalisation rules for the position of the lshiftrt, ashift
10955;; operations within an IOR/AND RTX, therefore we have two patterns matching
10956;; each valid permutation.
10957
10958(define_insn "arm_rev16si2"
10959 [(set (match_operand:SI 0 "register_operand" "=l,l,r")
10960 (ior:SI (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "l,l,r")
10961 (const_int 8))
10962 (match_operand:SI 3 "const_int_operand" "n,n,n"))
10963 (and:SI (lshiftrt:SI (match_dup 1)
10964 (const_int 8))
10965 (match_operand:SI 2 "const_int_operand" "n,n,n"))))]
10966 "arm_arch6
10967 && aarch_rev16_shleft_mask_imm_p (operands[3], SImode)
10968 && aarch_rev16_shright_mask_imm_p (operands[2], SImode)"
10969 "rev16\\t%0, %1"
10970 [(set_attr "arch" "t1,t2,32")
10971 (set_attr "length" "2,2,4")
10972 (set_attr "type" "rev")]
10973)
10974
10975(define_insn "arm_rev16si2_alt"
10976 [(set (match_operand:SI 0 "register_operand" "=l,l,r")
10977 (ior:SI (and:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,l,r")
10978 (const_int 8))
10979 (match_operand:SI 2 "const_int_operand" "n,n,n"))
10980 (and:SI (ashift:SI (match_dup 1)
10981 (const_int 8))
10982 (match_operand:SI 3 "const_int_operand" "n,n,n"))))]
10983 "arm_arch6
10984 && aarch_rev16_shleft_mask_imm_p (operands[3], SImode)
10985 && aarch_rev16_shright_mask_imm_p (operands[2], SImode)"
10986 "rev16\\t%0, %1"
10987 [(set_attr "arch" "t1,t2,32")
10988 (set_attr "length" "2,2,4")
10989 (set_attr "type" "rev")]
a486b499 10990)
10991
10992(define_expand "bswaphi2"
10993 [(set (match_operand:HI 0 "s_register_operand" "=r")
10994 (bswap:HI (match_operand:HI 1 "s_register_operand" "r")))]
10995"arm_arch6"
10996""
10997)
10998
1653cf17 10999;; Patterns for LDRD/STRD in Thumb2 mode
11000
11001(define_insn "*thumb2_ldrd"
11002 [(set (match_operand:SI 0 "s_register_operand" "=r")
11003 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
11004 (match_operand:SI 2 "ldrd_strd_offset_operand" "Do"))))
11005 (set (match_operand:SI 3 "s_register_operand" "=r")
11006 (mem:SI (plus:SI (match_dup 1)
11007 (match_operand:SI 4 "const_int_operand" ""))))]
11008 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11009 && current_tune->prefer_ldrd_strd
11010 && ((INTVAL (operands[2]) + 4) == INTVAL (operands[4]))
11011 && (operands_ok_ldrd_strd (operands[0], operands[3],
11012 operands[1], INTVAL (operands[2]),
11013 false, true))"
11014 "ldrd%?\t%0, %3, [%1, %2]"
11015 [(set_attr "type" "load2")
d952d547 11016 (set_attr "predicable" "yes")
11017 (set_attr "predicable_short_it" "no")])
1653cf17 11018
11019(define_insn "*thumb2_ldrd_base"
11020 [(set (match_operand:SI 0 "s_register_operand" "=r")
11021 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
11022 (set (match_operand:SI 2 "s_register_operand" "=r")
11023 (mem:SI (plus:SI (match_dup 1)
11024 (const_int 4))))]
11025 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11026 && current_tune->prefer_ldrd_strd
11027 && (operands_ok_ldrd_strd (operands[0], operands[2],
11028 operands[1], 0, false, true))"
11029 "ldrd%?\t%0, %2, [%1]"
11030 [(set_attr "type" "load2")
d952d547 11031 (set_attr "predicable" "yes")
11032 (set_attr "predicable_short_it" "no")])
1653cf17 11033
11034(define_insn "*thumb2_ldrd_base_neg"
11035 [(set (match_operand:SI 0 "s_register_operand" "=r")
11036 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
11037 (const_int -4))))
11038 (set (match_operand:SI 2 "s_register_operand" "=r")
11039 (mem:SI (match_dup 1)))]
11040 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11041 && current_tune->prefer_ldrd_strd
11042 && (operands_ok_ldrd_strd (operands[0], operands[2],
11043 operands[1], -4, false, true))"
11044 "ldrd%?\t%0, %2, [%1, #-4]"
11045 [(set_attr "type" "load2")
d952d547 11046 (set_attr "predicable" "yes")
11047 (set_attr "predicable_short_it" "no")])
1653cf17 11048
11049(define_insn "*thumb2_strd"
11050 [(set (mem:SI (plus:SI (match_operand:SI 0 "s_register_operand" "rk")
11051 (match_operand:SI 1 "ldrd_strd_offset_operand" "Do")))
11052 (match_operand:SI 2 "s_register_operand" "r"))
11053 (set (mem:SI (plus:SI (match_dup 0)
11054 (match_operand:SI 3 "const_int_operand" "")))
11055 (match_operand:SI 4 "s_register_operand" "r"))]
11056 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11057 && current_tune->prefer_ldrd_strd
11058 && ((INTVAL (operands[1]) + 4) == INTVAL (operands[3]))
11059 && (operands_ok_ldrd_strd (operands[2], operands[4],
11060 operands[0], INTVAL (operands[1]),
11061 false, false))"
11062 "strd%?\t%2, %4, [%0, %1]"
11063 [(set_attr "type" "store2")
d952d547 11064 (set_attr "predicable" "yes")
11065 (set_attr "predicable_short_it" "no")])
1653cf17 11066
11067(define_insn "*thumb2_strd_base"
11068 [(set (mem:SI (match_operand:SI 0 "s_register_operand" "rk"))
11069 (match_operand:SI 1 "s_register_operand" "r"))
11070 (set (mem:SI (plus:SI (match_dup 0)
11071 (const_int 4)))
11072 (match_operand:SI 2 "s_register_operand" "r"))]
11073 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11074 && current_tune->prefer_ldrd_strd
11075 && (operands_ok_ldrd_strd (operands[1], operands[2],
11076 operands[0], 0, false, false))"
11077 "strd%?\t%1, %2, [%0]"
11078 [(set_attr "type" "store2")
d952d547 11079 (set_attr "predicable" "yes")
11080 (set_attr "predicable_short_it" "no")])
1653cf17 11081
11082(define_insn "*thumb2_strd_base_neg"
11083 [(set (mem:SI (plus:SI (match_operand:SI 0 "s_register_operand" "rk")
11084 (const_int -4)))
11085 (match_operand:SI 1 "s_register_operand" "r"))
11086 (set (mem:SI (match_dup 0))
11087 (match_operand:SI 2 "s_register_operand" "r"))]
11088 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11089 && current_tune->prefer_ldrd_strd
11090 && (operands_ok_ldrd_strd (operands[1], operands[2],
11091 operands[0], -4, false, false))"
11092 "strd%?\t%1, %2, [%0, #-4]"
11093 [(set_attr "type" "store2")
d952d547 11094 (set_attr "predicable" "yes")
11095 (set_attr "predicable_short_it" "no")])
1653cf17 11096
2a0c73f2 11097;; ARMv8 CRC32 instructions.
11098(define_insn "<crc_variant>"
11099 [(set (match_operand:SI 0 "s_register_operand" "=r")
11100 (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")
11101 (match_operand:<crc_mode> 2 "s_register_operand" "r")]
11102 CRC))]
11103 "TARGET_CRC32"
11104 "<crc_variant>\\t%0, %1, %2"
11105 [(set_attr "type" "crc")
11106 (set_attr "conds" "unconditional")]
11107)
1653cf17 11108
353cf59a 11109;; Load the load/store double peephole optimizations.
11110(include "ldrdstrd.md")
11111
320ea44d 11112;; Load the load/store multiple patterns
11113(include "ldmstm.md")
426be8c5 11114
11115;; Patterns in ldmstm.md don't cover more than 4 registers. This pattern covers
11116;; large lists without explicit writeback generated for APCS_FRAME epilogue.
11117(define_insn "*load_multiple"
11118 [(match_parallel 0 "load_multiple_operation"
11119 [(set (match_operand:SI 2 "s_register_operand" "=rk")
11120 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
11121 ])]
11122 "TARGET_32BIT"
11123 "*
11124 {
11125 arm_output_multireg_pop (operands, /*return_pc=*/false,
11126 /*cond=*/const_true_rtx,
11127 /*reverse=*/false,
11128 /*update=*/false);
11129 return \"\";
11130 }
11131 "
11132 [(set_attr "predicable" "yes")]
11133)
11134
d98a3884 11135;; Vector bits common to IWMMXT and Neon
11136(include "vec-common.md")
755eb2b4 11137;; Load the Intel Wireless Multimedia Extension patterns
11138(include "iwmmxt.md")
a2cd141b 11139;; Load the VFP co-processor patterns
11140(include "vfp.md")
bc360af8 11141;; Thumb-1 patterns
11142(include "thumb1.md")
25f905c2 11143;; Thumb-2 patterns
11144(include "thumb2.md")
d98a3884 11145;; Neon patterns
11146(include "neon.md")
e84fdf6e 11147;; Crypto patterns
11148(include "crypto.md")
06df6b17 11149;; Synchronization Primitives
11150(include "sync.md")
bbbe4599 11151;; Fixed-point patterns
11152(include "arm-fixed.md")