]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/arm/arm.md
Allow the static chain to be set from C
[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.
21cc9773 130(define_attr "arch" "any,a,t,32,t1,t2,v6,nov6,neon_for_64bits,avoid_neon_for_64bits,iwmmxt,iwmmxt2,armv6_or_vfpv3"
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"))
21cc9773 177 (const_string "yes")
178
179 (and (eq_attr "arch" "armv6_or_vfpv3")
180 (match_test "arm_arch6 || TARGET_VFP3"))
181 (const_string "yes")
182 ]
6b8f7c28 183
d5d4dc8d 184 (const_string "no")))
185
aa06c51c 186(define_attr "opt" "any,speed,size"
187 (const_string "any"))
188
189(define_attr "opt_enabled" "no,yes"
190 (cond [(eq_attr "opt" "any")
191 (const_string "yes")
192
193 (and (eq_attr "opt" "speed")
194 (match_test "optimize_function_for_speed_p (cfun)"))
195 (const_string "yes")
196
197 (and (eq_attr "opt" "size")
198 (match_test "optimize_function_for_size_p (cfun)"))
199 (const_string "yes")]
200 (const_string "no")))
201
861033d5 202(define_attr "use_literal_pool" "no,yes"
203 (cond [(and (eq_attr "type" "f_loads,f_loadd")
204 (match_test "CONSTANT_P (operands[1])"))
205 (const_string "yes")]
206 (const_string "no")))
207
d5d4dc8d 208; Enable all alternatives that are both arch_enabled and insn_enabled.
951a3f72 209; FIXME:: opt_enabled has been temporarily removed till the time we have
210; an attribute that allows the use of such alternatives.
211; This depends on caching of speed_p, size_p on a per
212; alternative basis. The problem is that the enabled attribute
213; cannot depend on any state that is not cached or is not constant
214; for a compilation unit. We probably need a generic "hot/cold"
215; alternative which if implemented can help with this. We disable this
216; until such a time as this is implemented and / or the improvements or
217; regressions with removing this attribute are double checked.
218; See ashldi3_neon and <shift>di3_neon in neon.md.
219
93b431d9 220 (define_attr "enabled" "no,yes"
0abea32c 221 (cond [(and (eq_attr "predicable_short_it" "no")
c7a58118 222 (and (eq_attr "predicated" "yes")
223 (match_test "arm_restrict_it")))
224 (const_string "no")
225
226 (and (eq_attr "enabled_for_depr_it" "no")
227 (match_test "arm_restrict_it"))
228 (const_string "no")
229
861033d5 230 (and (eq_attr "use_literal_pool" "yes")
231 (match_test "arm_disable_literal_pool"))
232 (const_string "no")
233
aa06c51c 234 (eq_attr "arch_enabled" "no")
aa06c51c 235 (const_string "no")]
236 (const_string "yes")))
d5d4dc8d 237
56d27660 238; POOL_RANGE is how far away from a constant pool entry that this insn
239; can be placed. If the distance is zero, then this insn will never
240; reference the pool.
42e1de19 241; Note that for Thumb constant pools the PC value is rounded down to the
242; nearest multiple of four. Therefore, THUMB2_POOL_RANGE (and POOL_RANGE for
243; Thumb insns) should be set to <max_range> - 2.
cffb2a26 244; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
8848d797 245; before its address. It is set to <max_range> - (8 + <data_size>).
cde1623a 246(define_attr "arm_pool_range" "" (const_int 0))
247(define_attr "thumb2_pool_range" "" (const_int 0))
248(define_attr "arm_neg_pool_range" "" (const_int 0))
249(define_attr "thumb2_neg_pool_range" "" (const_int 0))
250
251(define_attr "pool_range" ""
252 (cond [(eq_attr "is_thumb" "yes") (attr "thumb2_pool_range")]
253 (attr "arm_pool_range")))
254(define_attr "neg_pool_range" ""
255 (cond [(eq_attr "is_thumb" "yes") (attr "thumb2_neg_pool_range")]
256 (attr "arm_neg_pool_range")))
56d27660 257
215b30b3 258; An assembler sequence may clobber the condition codes without us knowing.
4d7a8451 259; If such an insn references the pool, then we have no way of knowing how,
260; so use the most conservative value for pool_range.
9c08d1fa 261(define_asm_attributes
4d7a8451 262 [(set_attr "conds" "clob")
263 (set_attr "length" "4")
264 (set_attr "pool_range" "250")])
9c08d1fa 265
9888ad6d 266; Load scheduling, set from the arm_ld_sched variable
4c834714 267; initialized by arm_option_override()
9888ad6d 268(define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
849170fd 269
f7fbdd4a 270; condition codes: this one is used by final_prescan_insn to speed up
271; conditionalizing instructions. It saves having to scan the rtl to see if
272; it uses or alters the condition codes.
215b30b3 273;
f7fbdd4a 274; USE means that the condition codes are used by the insn in the process of
215b30b3 275; outputting code, this means (at present) that we can't use the insn in
276; inlined branches
277;
f7fbdd4a 278; SET means that the purpose of the insn is to set the condition codes in a
215b30b3 279; well defined manner.
280;
f7fbdd4a 281; CLOB means that the condition codes are altered in an undefined manner, if
215b30b3 282; they are altered at all
283;
ad6d3e2a 284; UNCONDITIONAL means the instruction can not be conditionally executed and
285; that the instruction does not use or alter the condition codes.
c52acdd2 286;
ad6d3e2a 287; NOCOND means that the instruction does not use or alter the condition
288; codes but can be converted into a conditionally exectuted instruction.
f7fbdd4a 289
b0694be0 290(define_attr "conds" "use,set,clob,unconditional,nocond"
747b7458 291 (if_then_else
292 (ior (eq_attr "is_thumb1" "yes")
293 (eq_attr "type" "call"))
c1a66faf 294 (const_string "clob")
32093010 295 (if_then_else (eq_attr "is_neon_type" "no")
52432540 296 (const_string "nocond")
297 (const_string "unconditional"))))
f7fbdd4a 298
215b30b3 299; Predicable means that the insn can be conditionally executed based on
300; an automatically added predicate (additional patterns are generated by
301; gen...). We default to 'no' because no Thumb patterns match this rule
302; and not all ARM patterns do.
0d66636f 303(define_attr "predicable" "no,yes" (const_string "no"))
304
129a2fe4 305; Only model the write buffer for ARM6 and ARM7. Earlier processors don't
306; have one. Later ones, such as StrongARM, have write-back caches, so don't
8d232dc7 307; suffer blockages enough to warrant modelling this (and it can adversely
129a2fe4 308; affect the schedule).
74a71f7d 309(define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_tune_wbuf")))
129a2fe4 310
215b30b3 311; WRITE_CONFLICT implies that a read following an unrelated write is likely
312; to stall the processor. Used with model_wbuf above.
9c08d1fa 313(define_attr "write_conflict" "no,yes"
314 (if_then_else (eq_attr "type"
96854199 315 "block,call,load1")
9c08d1fa 316 (const_string "yes")
317 (const_string "no")))
318
215b30b3 319; Classify the insns into those that take one cycle and those that take more
320; than one on the main cpu execution unit.
f7fbdd4a 321(define_attr "core_cycles" "single,multi"
322 (if_then_else (eq_attr "type"
112eda6f 323 "adc_imm, adc_reg, adcs_imm, adcs_reg, adr, alu_ext, alu_imm, alu_sreg,\
324 alu_shift_imm, alu_shift_reg, alu_dsp_reg, alus_ext, alus_imm, alus_sreg,\
d82e788e 325 alus_shift_imm, alus_shift_reg, bfm, csel, rev, logic_imm, logic_reg,\
326 logic_shift_imm, logic_shift_reg, logics_imm, logics_reg,\
327 logics_shift_imm, logics_shift_reg, extend, shift_imm, float, fcsel,\
7cb6c048 328 wmmx_wor, wmmx_wxor, wmmx_wand, wmmx_wandn, wmmx_wmov, wmmx_tmcrr,\
329 wmmx_tmrrc, wmmx_wldr, wmmx_wstr, wmmx_tmcr, wmmx_tmrc, wmmx_wadd,\
330 wmmx_wsub, wmmx_wmul, wmmx_wmac, wmmx_wavg2, wmmx_tinsr, wmmx_textrm,\
331 wmmx_wshufh, wmmx_wcmpeq, wmmx_wcmpgt, wmmx_wmax, wmmx_wmin, wmmx_wpack,\
332 wmmx_wunpckih, wmmx_wunpckil, wmmx_wunpckeh, wmmx_wunpckel, wmmx_wror,\
333 wmmx_wsra, wmmx_wsrl, wmmx_wsll, wmmx_wmadd, wmmx_tmia, wmmx_tmiaph,\
334 wmmx_tmiaxy, wmmx_tbcst, wmmx_tmovmsk, wmmx_wacc, wmmx_waligni,\
335 wmmx_walignr, wmmx_tandc, wmmx_textrc, wmmx_torc, wmmx_torvsc, wmmx_wsad,\
336 wmmx_wabs, wmmx_wabsdiff, wmmx_waddsubhx, wmmx_wsubaddhx, wmmx_wavg4,\
337 wmmx_wmulw, wmmx_wqmulm, wmmx_wqmulwm, wmmx_waddbhus, wmmx_wqmiaxy,\
338 wmmx_wmiaxy, wmmx_wmiawxy, wmmx_wmerge")
f7fbdd4a 339 (const_string "single")
340 (const_string "multi")))
341
cffb2a26 342;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
215b30b3 343;; distant label. Only applicable to Thumb code.
cffb2a26 344(define_attr "far_jump" "yes,no" (const_string "no"))
345
d51f92df 346
25f905c2 347;; The number of machine instructions this pattern expands to.
348;; Used for Thumb-2 conditional execution.
349(define_attr "ce_count" "" (const_int 1))
350
4182b724 351;;---------------------------------------------------------------------------
352;; Unspecs
353
354(include "unspecs.md")
355
d51f92df 356;;---------------------------------------------------------------------------
fd781bb2 357;; Mode iterators
d51f92df 358
3de0dec6 359(include "iterators.md")
03770691 360
d51f92df 361;;---------------------------------------------------------------------------
362;; Predicates
363
9c9db025 364(include "predicates.md")
234f6557 365(include "constraints.md")
9c9db025 366
a2cd141b 367;;---------------------------------------------------------------------------
368;; Pipeline descriptions
215b30b3 369
e3879fd0 370(define_attr "tune_cortexr4" "yes,no"
371 (const (if_then_else
7d3cda8c 372 (eq_attr "tune" "cortexr4,cortexr4f,cortexr5")
e3879fd0 373 (const_string "yes")
374 (const_string "no"))))
375
a2cd141b 376;; True if the generic scheduling description should be used.
377
378(define_attr "generic_sched" "yes,no"
2546d93a 379 (const (if_then_else
e18862f3 380 (ior (eq_attr "tune" "fa526,fa626,fa606te,fa626te,fmp626,fa726te,\
381 arm926ejs,arm1020e,arm1026ejs,arm1136js,\
382 arm1136jfs,cortexa5,cortexa7,cortexa8,\
383 cortexa9,cortexa12,cortexa15,cortexa53,\
384 cortexm4,cortexm7,marvell_pj4")
2546d93a 385 (eq_attr "tune_cortexr4" "yes"))
4d5cb40d 386 (const_string "no")
387 (const_string "yes"))))
388
c0e1af52 389(define_attr "generic_vfp" "yes,no"
390 (const (if_then_else
391 (and (eq_attr "fpu" "vfp")
e18862f3 392 (eq_attr "tune" "!arm1020e,arm1022e,cortexa5,cortexa7,\
393 cortexa8,cortexa9,cortexa53,cortexm4,\
394 cortexm7,marvell_pj4")
e3879fd0 395 (eq_attr "tune_cortexr4" "no"))
c0e1af52 396 (const_string "yes")
397 (const_string "no"))))
398
6b8f7c28 399(include "marvell-f-iwmmxt.md")
a2cd141b 400(include "arm-generic.md")
401(include "arm926ejs.md")
c0e1af52 402(include "arm1020e.md")
a2cd141b 403(include "arm1026ejs.md")
404(include "arm1136jfs.md")
0e266d06 405(include "fa526.md")
406(include "fa606te.md")
407(include "fa626te.md")
408(include "fmp626.md")
409(include "fa726te.md")
3f1e069f 410(include "cortex-a5.md")
d6b7f019 411(include "cortex-a7.md")
bcaec148 412(include "cortex-a8.md")
036068af 413(include "cortex-a9.md")
65f2f758 414(include "cortex-a15.md")
da10bc87 415(include "cortex-a53.md")
934a1e72 416(include "cortex-r4.md")
e3879fd0 417(include "cortex-r4f.md")
e18862f3 418(include "cortex-m7.md")
2546d93a 419(include "cortex-m4.md")
420(include "cortex-m4-fpu.md")
55e3ada8 421(include "vfp11.md")
ea7d210b 422(include "marvell-pj4.md")
3586df96 423
9c08d1fa 424\f
215b30b3 425;;---------------------------------------------------------------------------
e1159bbe 426;; Insn patterns
427;;
a0f94409 428;; Addition insns.
215b30b3 429
9c08d1fa 430;; Note: For DImode insns, there is normally no reason why operands should
431;; not be in the same register, what we don't want is for something being
432;; written to partially overlap something that is an input.
433
cffb2a26 434(define_expand "adddi3"
435 [(parallel
215b30b3 436 [(set (match_operand:DI 0 "s_register_operand" "")
cffb2a26 437 (plus:DI (match_operand:DI 1 "s_register_operand" "")
10e5ccd5 438 (match_operand:DI 2 "arm_adddi_operand" "")))
bd5b4116 439 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 440 "TARGET_EITHER"
441 "
25f905c2 442 if (TARGET_THUMB1)
cffb2a26 443 {
0438d37f 444 if (!REG_P (operands[1]))
bc5a93af 445 operands[1] = force_reg (DImode, operands[1]);
0438d37f 446 if (!REG_P (operands[2]))
bc5a93af 447 operands[2] = force_reg (DImode, operands[2]);
cffb2a26 448 }
449 "
450)
451
a0f94409 452(define_insn_and_split "*arm_adddi3"
10e5ccd5 453 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r,&r,&r")
454 (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0, r, 0, r")
455 (match_operand:DI 2 "arm_adddi_operand" "r, 0, r, Dd, Dd")))
bd5b4116 456 (clobber (reg:CC CC_REGNUM))]
b805622c 457 "TARGET_32BIT && !TARGET_NEON"
33782ec7 458 "#"
94829feb 459 "TARGET_32BIT && reload_completed
460 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))"
a0f94409 461 [(parallel [(set (reg:CC_C CC_REGNUM)
462 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
463 (match_dup 1)))
464 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 465 (set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (match_dup 5))
466 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
a0f94409 467 "
468 {
469 operands[3] = gen_highpart (SImode, operands[0]);
470 operands[0] = gen_lowpart (SImode, operands[0]);
471 operands[4] = gen_highpart (SImode, operands[1]);
472 operands[1] = gen_lowpart (SImode, operands[1]);
10e5ccd5 473 operands[5] = gen_highpart_mode (SImode, DImode, operands[2]);
a0f94409 474 operands[2] = gen_lowpart (SImode, operands[2]);
475 }"
cffb2a26 476 [(set_attr "conds" "clob")
1b7da4ac 477 (set_attr "length" "8")
478 (set_attr "type" "multiple")]
cffb2a26 479)
9c08d1fa 480
a0f94409 481(define_insn_and_split "*adddi_sesidi_di"
9c08d1fa 482 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
483 (plus:DI (sign_extend:DI
97499065 484 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 485 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 486 (clobber (reg:CC CC_REGNUM))]
b805622c 487 "TARGET_32BIT"
33782ec7 488 "#"
25f905c2 489 "TARGET_32BIT && reload_completed"
a0f94409 490 [(parallel [(set (reg:CC_C CC_REGNUM)
491 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
492 (match_dup 1)))
493 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 494 (set (match_dup 3) (plus:SI (plus:SI (ashiftrt:SI (match_dup 2)
a0f94409 495 (const_int 31))
080c0b9a 496 (match_dup 4))
497 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
a0f94409 498 "
499 {
500 operands[3] = gen_highpart (SImode, operands[0]);
501 operands[0] = gen_lowpart (SImode, operands[0]);
502 operands[4] = gen_highpart (SImode, operands[1]);
503 operands[1] = gen_lowpart (SImode, operands[1]);
504 operands[2] = gen_lowpart (SImode, operands[2]);
505 }"
215b30b3 506 [(set_attr "conds" "clob")
1b7da4ac 507 (set_attr "length" "8")
508 (set_attr "type" "multiple")]
215b30b3 509)
9c08d1fa 510
a0f94409 511(define_insn_and_split "*adddi_zesidi_di"
9c08d1fa 512 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
513 (plus:DI (zero_extend:DI
97499065 514 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 515 (match_operand:DI 1 "s_register_operand" "0,r")))
a0f94409 516 (clobber (reg:CC CC_REGNUM))]
b805622c 517 "TARGET_32BIT"
33782ec7 518 "#"
25f905c2 519 "TARGET_32BIT && reload_completed"
a0f94409 520 [(parallel [(set (reg:CC_C CC_REGNUM)
521 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
522 (match_dup 1)))
523 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 524 (set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (const_int 0))
525 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
a0f94409 526 "
527 {
528 operands[3] = gen_highpart (SImode, operands[0]);
529 operands[0] = gen_lowpart (SImode, operands[0]);
530 operands[4] = gen_highpart (SImode, operands[1]);
531 operands[1] = gen_lowpart (SImode, operands[1]);
532 operands[2] = gen_lowpart (SImode, operands[2]);
533 }"
cffb2a26 534 [(set_attr "conds" "clob")
1b7da4ac 535 (set_attr "length" "8")
536 (set_attr "type" "multiple")]
cffb2a26 537)
b11cae9e 538
87b22bf7 539(define_expand "addsi3"
cffb2a26 540 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 541 (plus:SI (match_operand:SI 1 "s_register_operand" "")
542 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 543 "TARGET_EITHER"
87b22bf7 544 "
0438d37f 545 if (TARGET_32BIT && CONST_INT_P (operands[2]))
87b22bf7 546 {
96f57e36 547 arm_split_constant (PLUS, SImode, NULL_RTX,
548 INTVAL (operands[2]), operands[0], operands[1],
e1ba4a27 549 optimize && can_create_pseudo_p ());
87b22bf7 550 DONE;
551 }
cffb2a26 552 "
553)
87b22bf7 554
5bd751ff 555; If there is a scratch available, this will be faster than synthesizing the
a0f94409 556; addition.
557(define_peephole2
558 [(match_scratch:SI 3 "r")
372575c7 559 (set (match_operand:SI 0 "arm_general_register_operand" "")
560 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
cffb2a26 561 (match_operand:SI 2 "const_int_operand" "")))]
25f905c2 562 "TARGET_32BIT &&
a0f94409 563 !(const_ok_for_arm (INTVAL (operands[2]))
564 || const_ok_for_arm (-INTVAL (operands[2])))
565 && const_ok_for_arm (~INTVAL (operands[2]))"
566 [(set (match_dup 3) (match_dup 2))
567 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
568 ""
569)
87b22bf7 570
2f02c19f 571;; The r/r/k alternative is required when reloading the address
572;; (plus (reg rN) (reg sp)) into (reg rN). In this case reload will
573;; put the duplicated register first, and not try the commutative version.
a0f94409 574(define_insn_and_split "*arm_addsi3"
7c36fe71 575 [(set (match_operand:SI 0 "s_register_operand" "=rk,l,l ,l ,r ,k ,r,r ,k ,r ,k,k,r ,k ,r")
576 (plus:SI (match_operand:SI 1 "s_register_operand" "%0 ,l,0 ,l ,rk,k ,r,rk,k ,rk,k,r,rk,k ,rk")
577 (match_operand:SI 2 "reg_or_int_operand" "rk ,l,Py,Pd,rI,rI,k,Pj,Pj,L ,L,L,PJ,PJ,?n")))]
25f905c2 578 "TARGET_32BIT"
5565501b 579 "@
c24d855d 580 add%?\\t%0, %0, %2
5565501b 581 add%?\\t%0, %1, %2
a0b3420a 582 add%?\\t%0, %1, %2
7c36fe71 583 add%?\\t%0, %1, %2
584 add%?\\t%0, %1, %2
aaa37ad6 585 add%?\\t%0, %1, %2
2f02c19f 586 add%?\\t%0, %2, %1
d5cbae34 587 addw%?\\t%0, %1, %2
588 addw%?\\t%0, %1, %2
aaa37ad6 589 sub%?\\t%0, %1, #%n2
87b22bf7 590 sub%?\\t%0, %1, #%n2
d7757711 591 sub%?\\t%0, %1, #%n2
d5cbae34 592 subw%?\\t%0, %1, #%n2
593 subw%?\\t%0, %1, #%n2
87b22bf7 594 #"
a3ffc315 595 "TARGET_32BIT
0438d37f 596 && CONST_INT_P (operands[2])
d5cbae34 597 && !const_ok_for_op (INTVAL (operands[2]), PLUS)
a3ffc315 598 && (reload_completed || !arm_eliminable_register (operands[1]))"
a0f94409 599 [(clobber (const_int 0))]
600 "
96f57e36 601 arm_split_constant (PLUS, SImode, curr_insn,
602 INTVAL (operands[2]), operands[0],
a0f94409 603 operands[1], 0);
604 DONE;
605 "
7c36fe71 606 [(set_attr "length" "2,4,4,4,4,4,4,4,4,4,4,4,4,4,16")
d5cbae34 607 (set_attr "predicable" "yes")
7c36fe71 608 (set_attr "predicable_short_it" "yes,yes,yes,yes,no,no,no,no,no,no,no,no,no,no,no")
609 (set_attr "arch" "t2,t2,t2,t2,*,*,*,t2,t2,*,*,a,t2,t2,*")
65f68e55 610 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
d82e788e 611 (const_string "alu_imm")
112eda6f 612 (const_string "alu_sreg")))
65f68e55 613 ]
cffb2a26 614)
615
90c2bcf0 616(define_insn "addsi3_compare0"
bd5b4116 617 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 618 (compare:CC_NOOV
65f68e55 619 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r,r")
620 (match_operand:SI 2 "arm_add_operand" "I,L,r"))
5565501b 621 (const_int 0)))
65f68e55 622 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9c08d1fa 623 (plus:SI (match_dup 1) (match_dup 2)))]
ec792a7b 624 "TARGET_ARM"
5565501b 625 "@
25f905c2 626 add%.\\t%0, %1, %2
65f68e55 627 sub%.\\t%0, %1, #%n2
628 add%.\\t%0, %1, %2"
629 [(set_attr "conds" "set")
112eda6f 630 (set_attr "type" "alus_imm,alus_imm,alus_sreg")]
cffb2a26 631)
9c08d1fa 632
aea4c774 633(define_insn "*addsi3_compare0_scratch"
bd5b4116 634 [(set (reg:CC_NOOV CC_REGNUM)
aea4c774 635 (compare:CC_NOOV
65f68e55 636 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r, r")
637 (match_operand:SI 1 "arm_add_operand" "I,L, r"))
aea4c774 638 (const_int 0)))]
ec792a7b 639 "TARGET_ARM"
cffb2a26 640 "@
641 cmn%?\\t%0, %1
65f68e55 642 cmp%?\\t%0, #%n1
643 cmn%?\\t%0, %1"
596e5e8f 644 [(set_attr "conds" "set")
65f68e55 645 (set_attr "predicable" "yes")
112eda6f 646 (set_attr "type" "alus_imm,alus_imm,alus_sreg")]
0d66636f 647)
cffb2a26 648
aed179ae 649(define_insn "*compare_negsi_si"
650 [(set (reg:CC_Z CC_REGNUM)
651 (compare:CC_Z
7c36fe71 652 (neg:SI (match_operand:SI 0 "s_register_operand" "l,r"))
653 (match_operand:SI 1 "s_register_operand" "l,r")))]
25f905c2 654 "TARGET_32BIT"
aed179ae 655 "cmn%?\\t%1, %0"
596e5e8f 656 [(set_attr "conds" "set")
7c36fe71 657 (set_attr "predicable" "yes")
658 (set_attr "arch" "t2,*")
659 (set_attr "length" "2,4")
1b7da4ac 660 (set_attr "predicable_short_it" "yes,no")
112eda6f 661 (set_attr "type" "alus_sreg")]
0d66636f 662)
aea4c774 663
203c488f 664;; This is the canonicalization of addsi3_compare0_for_combiner when the
665;; addend is a constant.
190efb17 666(define_insn "cmpsi2_addneg"
203c488f 667 [(set (reg:CC CC_REGNUM)
668 (compare:CC
669 (match_operand:SI 1 "s_register_operand" "r,r")
2a977b78 670 (match_operand:SI 2 "arm_addimm_operand" "L,I")))
203c488f 671 (set (match_operand:SI 0 "s_register_operand" "=r,r")
672 (plus:SI (match_dup 1)
2a977b78 673 (match_operand:SI 3 "arm_addimm_operand" "I,L")))]
25f905c2 674 "TARGET_32BIT && INTVAL (operands[2]) == -INTVAL (operands[3])"
203c488f 675 "@
2a977b78 676 add%.\\t%0, %1, %3
677 sub%.\\t%0, %1, #%n3"
1b7da4ac 678 [(set_attr "conds" "set")
112eda6f 679 (set_attr "type" "alus_sreg")]
203c488f 680)
681
682;; Convert the sequence
683;; sub rd, rn, #1
684;; cmn rd, #1 (equivalent to cmp rd, #-1)
685;; bne dest
686;; into
687;; subs rd, rn, #1
688;; bcs dest ((unsigned)rn >= 1)
689;; similarly for the beq variant using bcc.
690;; This is a common looping idiom (while (n--))
691(define_peephole2
372575c7 692 [(set (match_operand:SI 0 "arm_general_register_operand" "")
693 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
203c488f 694 (const_int -1)))
695 (set (match_operand 2 "cc_register" "")
696 (compare (match_dup 0) (const_int -1)))
697 (set (pc)
698 (if_then_else (match_operator 3 "equality_operator"
699 [(match_dup 2) (const_int 0)])
700 (match_operand 4 "" "")
701 (match_operand 5 "" "")))]
25f905c2 702 "TARGET_32BIT && peep2_reg_dead_p (3, operands[2])"
203c488f 703 [(parallel[
704 (set (match_dup 2)
705 (compare:CC
706 (match_dup 1) (const_int 1)))
707 (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
708 (set (pc)
709 (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
710 (match_dup 4)
711 (match_dup 5)))]
712 "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
713 operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
714 ? GEU : LTU),
715 VOIDmode,
716 operands[2], const0_rtx);"
717)
718
ebcc79bc 719;; The next four insns work because they compare the result with one of
720;; the operands, and we know that the use of the condition code is
721;; either GEU or LTU, so we can use the carry flag from the addition
722;; instead of doing the compare a second time.
723(define_insn "*addsi3_compare_op1"
bd5b4116 724 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 725 (compare:CC_C
65f68e55 726 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
727 (match_operand:SI 2 "arm_add_operand" "I,L,r"))
ebcc79bc 728 (match_dup 1)))
65f68e55 729 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
ebcc79bc 730 (plus:SI (match_dup 1) (match_dup 2)))]
25f905c2 731 "TARGET_32BIT"
ebcc79bc 732 "@
25f905c2 733 add%.\\t%0, %1, %2
65f68e55 734 sub%.\\t%0, %1, #%n2
735 add%.\\t%0, %1, %2"
736 [(set_attr "conds" "set")
112eda6f 737 (set_attr "type" "alus_imm,alus_imm,alus_sreg")]
0d66636f 738)
ebcc79bc 739
740(define_insn "*addsi3_compare_op2"
bd5b4116 741 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 742 (compare:CC_C
65f68e55 743 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
744 (match_operand:SI 2 "arm_add_operand" "I,L,r"))
ebcc79bc 745 (match_dup 2)))
65f68e55 746 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9c08d1fa 747 (plus:SI (match_dup 1) (match_dup 2)))]
25f905c2 748 "TARGET_32BIT"
5565501b 749 "@
65f68e55 750 add%.\\t%0, %1, %2
25f905c2 751 add%.\\t%0, %1, %2
752 sub%.\\t%0, %1, #%n2"
65f68e55 753 [(set_attr "conds" "set")
112eda6f 754 (set_attr "type" "alus_imm,alus_imm,alus_sreg")]
0d66636f 755)
9c08d1fa 756
ebcc79bc 757(define_insn "*compare_addsi2_op0"
bd5b4116 758 [(set (reg:CC_C CC_REGNUM)
7c36fe71 759 (compare:CC_C
760 (plus:SI (match_operand:SI 0 "s_register_operand" "l,l,r,r,r")
761 (match_operand:SI 1 "arm_add_operand" "Pv,l,I,L,r"))
762 (match_dup 0)))]
25f905c2 763 "TARGET_32BIT"
ebcc79bc 764 "@
7c36fe71 765 cmp%?\\t%0, #%n1
766 cmn%?\\t%0, %1
ebcc79bc 767 cmn%?\\t%0, %1
65f68e55 768 cmp%?\\t%0, #%n1
769 cmn%?\\t%0, %1"
596e5e8f 770 [(set_attr "conds" "set")
65f68e55 771 (set_attr "predicable" "yes")
7c36fe71 772 (set_attr "arch" "t2,t2,*,*,*")
773 (set_attr "predicable_short_it" "yes,yes,no,no,no")
774 (set_attr "length" "2,2,4,4,4")
112eda6f 775 (set_attr "type" "alus_imm,alus_sreg,alus_imm,alus_imm,alus_sreg")]
0d66636f 776)
ebcc79bc 777
778(define_insn "*compare_addsi2_op1"
bd5b4116 779 [(set (reg:CC_C CC_REGNUM)
7c36fe71 780 (compare:CC_C
781 (plus:SI (match_operand:SI 0 "s_register_operand" "l,l,r,r,r")
782 (match_operand:SI 1 "arm_add_operand" "Pv,l,I,L,r"))
783 (match_dup 1)))]
25f905c2 784 "TARGET_32BIT"
ebcc79bc 785 "@
7c36fe71 786 cmp%?\\t%0, #%n1
787 cmn%?\\t%0, %1
ebcc79bc 788 cmn%?\\t%0, %1
65f68e55 789 cmp%?\\t%0, #%n1
790 cmn%?\\t%0, %1"
596e5e8f 791 [(set_attr "conds" "set")
65f68e55 792 (set_attr "predicable" "yes")
7c36fe71 793 (set_attr "arch" "t2,t2,*,*,*")
794 (set_attr "predicable_short_it" "yes,yes,no,no,no")
795 (set_attr "length" "2,2,4,4,4")
112eda6f 796 (set_attr "type" "alus_imm,alus_sreg,alus_imm,alus_imm,alus_sreg")]
7c36fe71 797 )
ebcc79bc 798
080c0b9a 799(define_insn "*addsi3_carryin_<optab>"
7c36fe71 800 [(set (match_operand:SI 0 "s_register_operand" "=l,r,r")
801 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%l,r,r")
802 (match_operand:SI 2 "arm_not_operand" "0,rI,K"))
803 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))]
25f905c2 804 "TARGET_32BIT"
10e5ccd5 805 "@
a0b3420a 806 adc%?\\t%0, %1, %2
10e5ccd5 807 adc%?\\t%0, %1, %2
808 sbc%?\\t%0, %1, #%B2"
a7de272d 809 [(set_attr "conds" "use")
7c36fe71 810 (set_attr "predicable" "yes")
811 (set_attr "arch" "t2,*,*")
812 (set_attr "length" "4")
1b7da4ac 813 (set_attr "predicable_short_it" "yes,no,no")
814 (set_attr "type" "adc_reg,adc_reg,adc_imm")]
cffb2a26 815)
ebcc79bc 816
080c0b9a 817(define_insn "*addsi3_carryin_alt2_<optab>"
7c36fe71 818 [(set (match_operand:SI 0 "s_register_operand" "=l,r,r")
819 (plus:SI (plus:SI (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))
820 (match_operand:SI 1 "s_register_operand" "%l,r,r"))
821 (match_operand:SI 2 "arm_rhs_operand" "l,rI,K")))]
25f905c2 822 "TARGET_32BIT"
10e5ccd5 823 "@
a0b3420a 824 adc%?\\t%0, %1, %2
10e5ccd5 825 adc%?\\t%0, %1, %2
826 sbc%?\\t%0, %1, #%B2"
a7de272d 827 [(set_attr "conds" "use")
7c36fe71 828 (set_attr "predicable" "yes")
829 (set_attr "arch" "t2,*,*")
830 (set_attr "length" "4")
1b7da4ac 831 (set_attr "predicable_short_it" "yes,no,no")
832 (set_attr "type" "adc_reg,adc_reg,adc_imm")]
0d66636f 833)
ebcc79bc 834
080c0b9a 835(define_insn "*addsi3_carryin_shift_<optab>"
ebcc79bc 836 [(set (match_operand:SI 0 "s_register_operand" "=r")
080c0b9a 837 (plus:SI (plus:SI
838 (match_operator:SI 2 "shift_operator"
839 [(match_operand:SI 3 "s_register_operand" "r")
840 (match_operand:SI 4 "reg_or_int_operand" "rM")])
841 (match_operand:SI 1 "s_register_operand" "r"))
842 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))]
25f905c2 843 "TARGET_32BIT"
080c0b9a 844 "adc%?\\t%0, %1, %3%S2"
845 [(set_attr "conds" "use")
a7de272d 846 (set_attr "predicable" "yes")
7c36fe71 847 (set_attr "predicable_short_it" "no")
080c0b9a 848 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
d82e788e 849 (const_string "alu_shift_imm")
850 (const_string "alu_shift_reg")))]
cffb2a26 851)
ebcc79bc 852
922b6913 853(define_insn "*addsi3_carryin_clobercc_<optab>"
854 [(set (match_operand:SI 0 "s_register_operand" "=r")
855 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%r")
856 (match_operand:SI 2 "arm_rhs_operand" "rI"))
857 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))
858 (clobber (reg:CC CC_REGNUM))]
859 "TARGET_32BIT"
860 "adc%.\\t%0, %1, %2"
1b7da4ac 861 [(set_attr "conds" "set")
862 (set_attr "type" "adcs_reg")]
922b6913 863)
864
9154bd82 865(define_insn "*subsi3_carryin"
866 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
867 (minus:SI (minus:SI (match_operand:SI 1 "reg_or_int_operand" "r,I")
868 (match_operand:SI 2 "s_register_operand" "r,r"))
869 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
870 "TARGET_32BIT"
871 "@
872 sbc%?\\t%0, %1, %2
873 rsc%?\\t%0, %2, %1"
874 [(set_attr "conds" "use")
875 (set_attr "arch" "*,a")
7c36fe71 876 (set_attr "predicable" "yes")
1b7da4ac 877 (set_attr "predicable_short_it" "no")
878 (set_attr "type" "adc_reg,adc_imm")]
9154bd82 879)
880
881(define_insn "*subsi3_carryin_const"
882 [(set (match_operand:SI 0 "s_register_operand" "=r")
883 (minus:SI (plus:SI (match_operand:SI 1 "reg_or_int_operand" "r")
884 (match_operand:SI 2 "arm_not_operand" "K"))
885 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
886 "TARGET_32BIT"
887 "sbc\\t%0, %1, #%B2"
1b7da4ac 888 [(set_attr "conds" "use")
889 (set_attr "type" "adc_imm")]
9154bd82 890)
891
892(define_insn "*subsi3_carryin_compare"
893 [(set (reg:CC CC_REGNUM)
894 (compare:CC (match_operand:SI 1 "s_register_operand" "r")
895 (match_operand:SI 2 "s_register_operand" "r")))
896 (set (match_operand:SI 0 "s_register_operand" "=r")
897 (minus:SI (minus:SI (match_dup 1)
898 (match_dup 2))
899 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
900 "TARGET_32BIT"
901 "sbcs\\t%0, %1, %2"
1b7da4ac 902 [(set_attr "conds" "set")
903 (set_attr "type" "adcs_reg")]
9154bd82 904)
905
906(define_insn "*subsi3_carryin_compare_const"
907 [(set (reg:CC CC_REGNUM)
908 (compare:CC (match_operand:SI 1 "reg_or_int_operand" "r")
909 (match_operand:SI 2 "arm_not_operand" "K")))
910 (set (match_operand:SI 0 "s_register_operand" "=r")
911 (minus:SI (plus:SI (match_dup 1)
912 (match_dup 2))
913 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
914 "TARGET_32BIT"
915 "sbcs\\t%0, %1, #%B2"
1b7da4ac 916 [(set_attr "conds" "set")
917 (set_attr "type" "adcs_imm")]
9154bd82 918)
919
920(define_insn "*subsi3_carryin_shift"
921 [(set (match_operand:SI 0 "s_register_operand" "=r")
922 (minus:SI (minus:SI
923 (match_operand:SI 1 "s_register_operand" "r")
924 (match_operator:SI 2 "shift_operator"
925 [(match_operand:SI 3 "s_register_operand" "r")
926 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
927 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
928 "TARGET_32BIT"
929 "sbc%?\\t%0, %1, %3%S2"
930 [(set_attr "conds" "use")
931 (set_attr "predicable" "yes")
932 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
d82e788e 933 (const_string "alu_shift_imm")
934 (const_string "alu_shift_reg")))]
9154bd82 935)
936
937(define_insn "*rsbsi3_carryin_shift"
938 [(set (match_operand:SI 0 "s_register_operand" "=r")
939 (minus:SI (minus:SI
940 (match_operator:SI 2 "shift_operator"
941 [(match_operand:SI 3 "s_register_operand" "r")
942 (match_operand:SI 4 "reg_or_int_operand" "rM")])
943 (match_operand:SI 1 "s_register_operand" "r"))
944 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
945 "TARGET_ARM"
946 "rsc%?\\t%0, %1, %3%S2"
947 [(set_attr "conds" "use")
948 (set_attr "predicable" "yes")
949 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
d82e788e 950 (const_string "alu_shift_imm")
951 (const_string "alu_shift_reg")))]
9154bd82 952)
953
d795fb69 954; transform ((x << y) - 1) to ~(~(x-1) << y) Where X is a constant.
955(define_split
956 [(set (match_operand:SI 0 "s_register_operand" "")
957 (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
958 (match_operand:SI 2 "s_register_operand" ""))
959 (const_int -1)))
960 (clobber (match_operand:SI 3 "s_register_operand" ""))]
25f905c2 961 "TARGET_32BIT"
d795fb69 962 [(set (match_dup 3) (match_dup 1))
963 (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
964 "
965 operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
966")
967
604f3a0a 968(define_expand "addsf3"
969 [(set (match_operand:SF 0 "s_register_operand" "")
970 (plus:SF (match_operand:SF 1 "s_register_operand" "")
d86c91f6 971 (match_operand:SF 2 "s_register_operand" "")))]
25f905c2 972 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 973 "
604f3a0a 974")
975
604f3a0a 976(define_expand "adddf3"
977 [(set (match_operand:DF 0 "s_register_operand" "")
978 (plus:DF (match_operand:DF 1 "s_register_operand" "")
d86c91f6 979 (match_operand:DF 2 "s_register_operand" "")))]
a50d7267 980 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 981 "
604f3a0a 982")
983
cffb2a26 984(define_expand "subdi3"
985 [(parallel
986 [(set (match_operand:DI 0 "s_register_operand" "")
987 (minus:DI (match_operand:DI 1 "s_register_operand" "")
988 (match_operand:DI 2 "s_register_operand" "")))
bd5b4116 989 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 990 "TARGET_EITHER"
991 "
25f905c2 992 if (TARGET_THUMB1)
cffb2a26 993 {
0438d37f 994 if (!REG_P (operands[1]))
5aa8c5f0 995 operands[1] = force_reg (DImode, operands[1]);
0438d37f 996 if (!REG_P (operands[2]))
5aa8c5f0 997 operands[2] = force_reg (DImode, operands[2]);
cffb2a26 998 }
999 "
1000)
1001
2f9b23e3 1002(define_insn_and_split "*arm_subdi3"
cffb2a26 1003 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
9c08d1fa 1004 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
1005 (match_operand:DI 2 "s_register_operand" "r,0,0")))
bd5b4116 1006 (clobber (reg:CC CC_REGNUM))]
94829feb 1007 "TARGET_32BIT && !TARGET_NEON"
2f9b23e3 1008 "#" ; "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
1009 "&& reload_completed"
1010 [(parallel [(set (reg:CC CC_REGNUM)
1011 (compare:CC (match_dup 1) (match_dup 2)))
1012 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1013 (set (match_dup 3) (minus:SI (minus:SI (match_dup 4) (match_dup 5))
1014 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1015 {
1016 operands[3] = gen_highpart (SImode, operands[0]);
1017 operands[0] = gen_lowpart (SImode, operands[0]);
1018 operands[4] = gen_highpart (SImode, operands[1]);
1019 operands[1] = gen_lowpart (SImode, operands[1]);
1020 operands[5] = gen_highpart (SImode, operands[2]);
1021 operands[2] = gen_lowpart (SImode, operands[2]);
1022 }
cffb2a26 1023 [(set_attr "conds" "clob")
1b7da4ac 1024 (set_attr "length" "8")
1025 (set_attr "type" "multiple")]
cffb2a26 1026)
1027
2f9b23e3 1028(define_insn_and_split "*subdi_di_zesidi"
cffb2a26 1029 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 1030 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r")
9c08d1fa 1031 (zero_extend:DI
cffb2a26 1032 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 1033 (clobber (reg:CC CC_REGNUM))]
25f905c2 1034 "TARGET_32BIT"
2f9b23e3 1035 "#" ; "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
1036 "&& reload_completed"
1037 [(parallel [(set (reg:CC CC_REGNUM)
1038 (compare:CC (match_dup 1) (match_dup 2)))
1039 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1040 (set (match_dup 3) (minus:SI (plus:SI (match_dup 4) (match_dup 5))
1041 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1042 {
1043 operands[3] = gen_highpart (SImode, operands[0]);
1044 operands[0] = gen_lowpart (SImode, operands[0]);
1045 operands[4] = gen_highpart (SImode, operands[1]);
1046 operands[1] = gen_lowpart (SImode, operands[1]);
1047 operands[5] = GEN_INT (~0);
1048 }
cffb2a26 1049 [(set_attr "conds" "clob")
1b7da4ac 1050 (set_attr "length" "8")
1051 (set_attr "type" "multiple")]
cffb2a26 1052)
9c08d1fa 1053
2f9b23e3 1054(define_insn_and_split "*subdi_di_sesidi"
cffb2a26 1055 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 1056 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r")
9c08d1fa 1057 (sign_extend:DI
cffb2a26 1058 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 1059 (clobber (reg:CC CC_REGNUM))]
25f905c2 1060 "TARGET_32BIT"
2f9b23e3 1061 "#" ; "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
1062 "&& reload_completed"
1063 [(parallel [(set (reg:CC CC_REGNUM)
1064 (compare:CC (match_dup 1) (match_dup 2)))
1065 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1066 (set (match_dup 3) (minus:SI (minus:SI (match_dup 4)
1067 (ashiftrt:SI (match_dup 2)
1068 (const_int 31)))
1069 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1070 {
1071 operands[3] = gen_highpart (SImode, operands[0]);
1072 operands[0] = gen_lowpart (SImode, operands[0]);
1073 operands[4] = gen_highpart (SImode, operands[1]);
1074 operands[1] = gen_lowpart (SImode, operands[1]);
1075 }
cffb2a26 1076 [(set_attr "conds" "clob")
1b7da4ac 1077 (set_attr "length" "8")
1078 (set_attr "type" "multiple")]
cffb2a26 1079)
9c08d1fa 1080
2f9b23e3 1081(define_insn_and_split "*subdi_zesidi_di"
cffb2a26 1082 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1083 (minus:DI (zero_extend:DI
cffb2a26 1084 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 1085 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 1086 (clobber (reg:CC CC_REGNUM))]
cffb2a26 1087 "TARGET_ARM"
2f9b23e3 1088 "#" ; "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
1089 ; is equivalent to:
1090 ; "subs\\t%Q0, %2, %Q1\;rsc\\t%R0, %R1, #0"
1091 "&& reload_completed"
1092 [(parallel [(set (reg:CC CC_REGNUM)
1093 (compare:CC (match_dup 2) (match_dup 1)))
1094 (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))])
1095 (set (match_dup 3) (minus:SI (minus:SI (const_int 0) (match_dup 4))
1096 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1097 {
1098 operands[3] = gen_highpart (SImode, operands[0]);
1099 operands[0] = gen_lowpart (SImode, operands[0]);
1100 operands[4] = gen_highpart (SImode, operands[1]);
1101 operands[1] = gen_lowpart (SImode, operands[1]);
1102 }
cffb2a26 1103 [(set_attr "conds" "clob")
1b7da4ac 1104 (set_attr "length" "8")
1105 (set_attr "type" "multiple")]
cffb2a26 1106)
9c08d1fa 1107
2f9b23e3 1108(define_insn_and_split "*subdi_sesidi_di"
cffb2a26 1109 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1110 (minus:DI (sign_extend:DI
cffb2a26 1111 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 1112 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 1113 (clobber (reg:CC CC_REGNUM))]
cffb2a26 1114 "TARGET_ARM"
2f9b23e3 1115 "#" ; "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
1116 ; is equivalent to:
1117 ; "subs\\t%Q0, %2, %Q1\;rsc\\t%R0, %R1, %2, asr #31"
1118 "&& reload_completed"
1119 [(parallel [(set (reg:CC CC_REGNUM)
1120 (compare:CC (match_dup 2) (match_dup 1)))
1121 (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))])
1122 (set (match_dup 3) (minus:SI (minus:SI
1123 (ashiftrt:SI (match_dup 2)
1124 (const_int 31))
1125 (match_dup 4))
1126 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1127 {
1128 operands[3] = gen_highpart (SImode, operands[0]);
1129 operands[0] = gen_lowpart (SImode, operands[0]);
1130 operands[4] = gen_highpart (SImode, operands[1]);
1131 operands[1] = gen_lowpart (SImode, operands[1]);
1132 }
cffb2a26 1133 [(set_attr "conds" "clob")
1b7da4ac 1134 (set_attr "length" "8")
1135 (set_attr "type" "multiple")]
cffb2a26 1136)
9c08d1fa 1137
2f9b23e3 1138(define_insn_and_split "*subdi_zesidi_zesidi"
cffb2a26 1139 [(set (match_operand:DI 0 "s_register_operand" "=r")
9c08d1fa 1140 (minus:DI (zero_extend:DI
cffb2a26 1141 (match_operand:SI 1 "s_register_operand" "r"))
9c08d1fa 1142 (zero_extend:DI
cffb2a26 1143 (match_operand:SI 2 "s_register_operand" "r"))))
bd5b4116 1144 (clobber (reg:CC CC_REGNUM))]
25f905c2 1145 "TARGET_32BIT"
2f9b23e3 1146 "#" ; "subs\\t%Q0, %1, %2\;sbc\\t%R0, %1, %1"
1147 "&& reload_completed"
1148 [(parallel [(set (reg:CC CC_REGNUM)
1149 (compare:CC (match_dup 1) (match_dup 2)))
1150 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1151 (set (match_dup 3) (minus:SI (minus:SI (match_dup 1) (match_dup 1))
1152 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1153 {
1154 operands[3] = gen_highpart (SImode, operands[0]);
1155 operands[0] = gen_lowpart (SImode, operands[0]);
1156 }
cffb2a26 1157 [(set_attr "conds" "clob")
1b7da4ac 1158 (set_attr "length" "8")
1159 (set_attr "type" "multiple")]
cffb2a26 1160)
b11cae9e 1161
87b22bf7 1162(define_expand "subsi3"
cffb2a26 1163 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 1164 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
1165 (match_operand:SI 2 "s_register_operand" "")))]
cffb2a26 1166 "TARGET_EITHER"
87b22bf7 1167 "
0438d37f 1168 if (CONST_INT_P (operands[1]))
87b22bf7 1169 {
25f905c2 1170 if (TARGET_32BIT)
cffb2a26 1171 {
96f57e36 1172 arm_split_constant (MINUS, SImode, NULL_RTX,
1173 INTVAL (operands[1]), operands[0],
e1ba4a27 1174 operands[2], optimize && can_create_pseudo_p ());
cffb2a26 1175 DONE;
1176 }
25f905c2 1177 else /* TARGET_THUMB1 */
cffb2a26 1178 operands[1] = force_reg (SImode, operands[1]);
87b22bf7 1179 }
cffb2a26 1180 "
1181)
87b22bf7 1182
25f905c2 1183; ??? Check Thumb-2 split length
a0f94409 1184(define_insn_and_split "*arm_subsi3_insn"
7c36fe71 1185 [(set (match_operand:SI 0 "s_register_operand" "=l,l ,l ,l ,r ,r,r,rk,r")
1186 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "l ,0 ,l ,Pz,rI,r,r,k ,?n")
1187 (match_operand:SI 2 "reg_or_int_operand" "l ,Py,Pd,l ,r ,I,r,r ,r")))]
25f905c2 1188 "TARGET_32BIT"
e2348bcb 1189 "@
7c36fe71 1190 sub%?\\t%0, %1, %2
1191 sub%?\\t%0, %2
1192 sub%?\\t%0, %1, %2
1193 rsb%?\\t%0, %2, %1
87b22bf7 1194 rsb%?\\t%0, %2, %1
aaa37ad6 1195 sub%?\\t%0, %1, %2
080c0b9a 1196 sub%?\\t%0, %1, %2
65f68e55 1197 sub%?\\t%0, %1, %2
87b22bf7 1198 #"
0438d37f 1199 "&& (CONST_INT_P (operands[1])
91a5e339 1200 && !const_ok_for_arm (INTVAL (operands[1])))"
87b22bf7 1201 [(clobber (const_int 0))]
1202 "
96f57e36 1203 arm_split_constant (MINUS, SImode, curr_insn,
1204 INTVAL (operands[1]), operands[0], operands[2], 0);
87b22bf7 1205 DONE;
cffb2a26 1206 "
7c36fe71 1207 [(set_attr "length" "4,4,4,4,4,4,4,4,16")
1208 (set_attr "arch" "t2,t2,t2,t2,*,*,*,*,*")
65f68e55 1209 (set_attr "predicable" "yes")
7c36fe71 1210 (set_attr "predicable_short_it" "yes,yes,yes,yes,no,no,no,no,no")
112eda6f 1211 (set_attr "type" "alu_sreg,alu_sreg,alu_sreg,alu_sreg,alu_imm,alu_imm,alu_sreg,alu_sreg,multiple")]
a0f94409 1212)
1213
1214(define_peephole2
1215 [(match_scratch:SI 3 "r")
372575c7 1216 (set (match_operand:SI 0 "arm_general_register_operand" "")
a0f94409 1217 (minus:SI (match_operand:SI 1 "const_int_operand" "")
372575c7 1218 (match_operand:SI 2 "arm_general_register_operand" "")))]
25f905c2 1219 "TARGET_32BIT
a0f94409 1220 && !const_ok_for_arm (INTVAL (operands[1]))
1221 && const_ok_for_arm (~INTVAL (operands[1]))"
1222 [(set (match_dup 3) (match_dup 1))
1223 (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1224 ""
cffb2a26 1225)
b11cae9e 1226
f7fbdd4a 1227(define_insn "*subsi3_compare0"
bd5b4116 1228 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1229 (compare:CC_NOOV
65f68e55 1230 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,r,I")
1231 (match_operand:SI 2 "arm_rhs_operand" "I,r,r"))
215b30b3 1232 (const_int 0)))
65f68e55 1233 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9c08d1fa 1234 (minus:SI (match_dup 1) (match_dup 2)))]
25f905c2 1235 "TARGET_32BIT"
e2348bcb 1236 "@
65f68e55 1237 sub%.\\t%0, %1, %2
25f905c2 1238 sub%.\\t%0, %1, %2
1239 rsb%.\\t%0, %2, %1"
65f68e55 1240 [(set_attr "conds" "set")
112eda6f 1241 (set_attr "type" "alus_imm,alus_sreg,alus_sreg")]
cffb2a26 1242)
9c08d1fa 1243
190efb17 1244(define_insn "subsi3_compare"
080c0b9a 1245 [(set (reg:CC CC_REGNUM)
65f68e55 1246 (compare:CC (match_operand:SI 1 "arm_rhs_operand" "r,r,I")
1247 (match_operand:SI 2 "arm_rhs_operand" "I,r,r")))
1248 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2df9477b 1249 (minus:SI (match_dup 1) (match_dup 2)))]
1250 "TARGET_32BIT"
1251 "@
65f68e55 1252 sub%.\\t%0, %1, %2
2df9477b 1253 sub%.\\t%0, %1, %2
1254 rsb%.\\t%0, %2, %1"
65f68e55 1255 [(set_attr "conds" "set")
112eda6f 1256 (set_attr "type" "alus_imm,alus_sreg,alus_sreg")]
2df9477b 1257)
1258
604f3a0a 1259(define_expand "subsf3"
1260 [(set (match_operand:SF 0 "s_register_operand" "")
d86c91f6 1261 (minus:SF (match_operand:SF 1 "s_register_operand" "")
1262 (match_operand:SF 2 "s_register_operand" "")))]
25f905c2 1263 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1264 "
604f3a0a 1265")
1266
604f3a0a 1267(define_expand "subdf3"
1268 [(set (match_operand:DF 0 "s_register_operand" "")
d86c91f6 1269 (minus:DF (match_operand:DF 1 "s_register_operand" "")
1270 (match_operand:DF 2 "s_register_operand" "")))]
a50d7267 1271 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 1272 "
604f3a0a 1273")
1274
b11cae9e 1275\f
1276;; Multiplication insns
1277
4422d91f 1278(define_expand "mulhi3"
1279 [(set (match_operand:HI 0 "s_register_operand" "")
1280 (mult:HI (match_operand:HI 1 "s_register_operand" "")
1281 (match_operand:HI 2 "s_register_operand" "")))]
1282 "TARGET_DSP_MULTIPLY"
1283 "
1284 {
1285 rtx result = gen_reg_rtx (SImode);
1286 emit_insn (gen_mulhisi3 (result, operands[1], operands[2]));
1287 emit_move_insn (operands[0], gen_lowpart (HImode, result));
1288 DONE;
1289 }"
1290)
1291
cffb2a26 1292(define_expand "mulsi3"
1293 [(set (match_operand:SI 0 "s_register_operand" "")
1294 (mult:SI (match_operand:SI 2 "s_register_operand" "")
1295 (match_operand:SI 1 "s_register_operand" "")))]
1296 "TARGET_EITHER"
1297 ""
1298)
1299
9c08d1fa 1300;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
cffb2a26 1301(define_insn "*arm_mulsi3"
1302 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1303 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1304 (match_operand:SI 1 "s_register_operand" "%0,r")))]
58d7d654 1305 "TARGET_32BIT && !arm_arch6"
f7fbdd4a 1306 "mul%?\\t%0, %2, %1"
9da0ec36 1307 [(set_attr "type" "mul")
0d66636f 1308 (set_attr "predicable" "yes")]
cffb2a26 1309)
1310
58d7d654 1311(define_insn "*arm_mulsi3_v6"
d952d547 1312 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
1313 (mult:SI (match_operand:SI 1 "s_register_operand" "0,l,r")
1314 (match_operand:SI 2 "s_register_operand" "l,0,r")))]
58d7d654 1315 "TARGET_32BIT && arm_arch6"
1316 "mul%?\\t%0, %1, %2"
9da0ec36 1317 [(set_attr "type" "mul")
d952d547 1318 (set_attr "predicable" "yes")
1319 (set_attr "arch" "t2,t2,*")
1320 (set_attr "length" "4")
1321 (set_attr "predicable_short_it" "yes,yes,no")]
58d7d654 1322)
1323
f7fbdd4a 1324(define_insn "*mulsi3_compare0"
bd5b4116 1325 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1326 (compare:CC_NOOV (mult:SI
1327 (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1328 (match_operand:SI 1 "s_register_operand" "%0,r"))
9c08d1fa 1329 (const_int 0)))
1330 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1331 (mult:SI (match_dup 2) (match_dup 1)))]
58d7d654 1332 "TARGET_ARM && !arm_arch6"
1333 "mul%.\\t%0, %2, %1"
1334 [(set_attr "conds" "set")
9da0ec36 1335 (set_attr "type" "muls")]
58d7d654 1336)
1337
1338(define_insn "*mulsi3_compare0_v6"
1339 [(set (reg:CC_NOOV CC_REGNUM)
1340 (compare:CC_NOOV (mult:SI
1341 (match_operand:SI 2 "s_register_operand" "r")
1342 (match_operand:SI 1 "s_register_operand" "r"))
1343 (const_int 0)))
1344 (set (match_operand:SI 0 "s_register_operand" "=r")
1345 (mult:SI (match_dup 2) (match_dup 1)))]
1346 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1347 "mul%.\\t%0, %2, %1"
cffb2a26 1348 [(set_attr "conds" "set")
9da0ec36 1349 (set_attr "type" "muls")]
cffb2a26 1350)
9c08d1fa 1351
f7fbdd4a 1352(define_insn "*mulsi_compare0_scratch"
bd5b4116 1353 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1354 (compare:CC_NOOV (mult:SI
1355 (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1356 (match_operand:SI 1 "s_register_operand" "%0,r"))
9c08d1fa 1357 (const_int 0)))
1358 (clobber (match_scratch:SI 0 "=&r,&r"))]
58d7d654 1359 "TARGET_ARM && !arm_arch6"
1360 "mul%.\\t%0, %2, %1"
1361 [(set_attr "conds" "set")
9da0ec36 1362 (set_attr "type" "muls")]
58d7d654 1363)
1364
1365(define_insn "*mulsi_compare0_scratch_v6"
1366 [(set (reg:CC_NOOV CC_REGNUM)
1367 (compare:CC_NOOV (mult:SI
1368 (match_operand:SI 2 "s_register_operand" "r")
1369 (match_operand:SI 1 "s_register_operand" "r"))
1370 (const_int 0)))
1371 (clobber (match_scratch:SI 0 "=r"))]
1372 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1373 "mul%.\\t%0, %2, %1"
cffb2a26 1374 [(set_attr "conds" "set")
9da0ec36 1375 (set_attr "type" "muls")]
cffb2a26 1376)
9c08d1fa 1377
b11cae9e 1378;; Unnamed templates to match MLA instruction.
1379
f7fbdd4a 1380(define_insn "*mulsi3addsi"
9c08d1fa 1381 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
c8f69309 1382 (plus:SI
9c08d1fa 1383 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1384 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1385 (match_operand:SI 3 "s_register_operand" "r,r,0,0")))]
58d7d654 1386 "TARGET_32BIT && !arm_arch6"
1387 "mla%?\\t%0, %2, %1, %3"
9da0ec36 1388 [(set_attr "type" "mla")
58d7d654 1389 (set_attr "predicable" "yes")]
1390)
1391
1392(define_insn "*mulsi3addsi_v6"
1393 [(set (match_operand:SI 0 "s_register_operand" "=r")
1394 (plus:SI
1395 (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1396 (match_operand:SI 1 "s_register_operand" "r"))
1397 (match_operand:SI 3 "s_register_operand" "r")))]
1398 "TARGET_32BIT && arm_arch6"
f7fbdd4a 1399 "mla%?\\t%0, %2, %1, %3"
9da0ec36 1400 [(set_attr "type" "mla")
d952d547 1401 (set_attr "predicable" "yes")
1402 (set_attr "predicable_short_it" "no")]
0d66636f 1403)
b11cae9e 1404
f7fbdd4a 1405(define_insn "*mulsi3addsi_compare0"
bd5b4116 1406 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1407 (compare:CC_NOOV
1408 (plus:SI (mult:SI
1409 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1410 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1411 (match_operand:SI 3 "s_register_operand" "r,r,0,0"))
215b30b3 1412 (const_int 0)))
9c08d1fa 1413 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1414 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1415 (match_dup 3)))]
58d7d654 1416 "TARGET_ARM && arm_arch6"
1417 "mla%.\\t%0, %2, %1, %3"
1418 [(set_attr "conds" "set")
9da0ec36 1419 (set_attr "type" "mlas")]
58d7d654 1420)
1421
1422(define_insn "*mulsi3addsi_compare0_v6"
1423 [(set (reg:CC_NOOV CC_REGNUM)
1424 (compare:CC_NOOV
1425 (plus:SI (mult:SI
1426 (match_operand:SI 2 "s_register_operand" "r")
1427 (match_operand:SI 1 "s_register_operand" "r"))
1428 (match_operand:SI 3 "s_register_operand" "r"))
1429 (const_int 0)))
1430 (set (match_operand:SI 0 "s_register_operand" "=r")
1431 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1432 (match_dup 3)))]
1433 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1434 "mla%.\\t%0, %2, %1, %3"
0d66636f 1435 [(set_attr "conds" "set")
9da0ec36 1436 (set_attr "type" "mlas")]
0d66636f 1437)
9c08d1fa 1438
f7fbdd4a 1439(define_insn "*mulsi3addsi_compare0_scratch"
bd5b4116 1440 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1441 (compare:CC_NOOV
1442 (plus:SI (mult:SI
1443 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1444 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
215b30b3 1445 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1446 (const_int 0)))
9c08d1fa 1447 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
58d7d654 1448 "TARGET_ARM && !arm_arch6"
1449 "mla%.\\t%0, %2, %1, %3"
1450 [(set_attr "conds" "set")
9da0ec36 1451 (set_attr "type" "mlas")]
58d7d654 1452)
1453
1454(define_insn "*mulsi3addsi_compare0_scratch_v6"
1455 [(set (reg:CC_NOOV CC_REGNUM)
1456 (compare:CC_NOOV
1457 (plus:SI (mult:SI
1458 (match_operand:SI 2 "s_register_operand" "r")
1459 (match_operand:SI 1 "s_register_operand" "r"))
1460 (match_operand:SI 3 "s_register_operand" "r"))
1461 (const_int 0)))
1462 (clobber (match_scratch:SI 0 "=r"))]
1463 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1464 "mla%.\\t%0, %2, %1, %3"
cffb2a26 1465 [(set_attr "conds" "set")
9da0ec36 1466 (set_attr "type" "mlas")]
cffb2a26 1467)
f7fbdd4a 1468
89545238 1469(define_insn "*mulsi3subsi"
1470 [(set (match_operand:SI 0 "s_register_operand" "=r")
1471 (minus:SI
1472 (match_operand:SI 3 "s_register_operand" "r")
1473 (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1474 (match_operand:SI 1 "s_register_operand" "r"))))]
1475 "TARGET_32BIT && arm_arch_thumb2"
1476 "mls%?\\t%0, %2, %1, %3"
9da0ec36 1477 [(set_attr "type" "mla")
d952d547 1478 (set_attr "predicable" "yes")
1479 (set_attr "predicable_short_it" "no")]
89545238 1480)
1481
5cdca009 1482(define_expand "maddsidi4"
1483 [(set (match_operand:DI 0 "s_register_operand" "")
1484 (plus:DI
1485 (mult:DI
1486 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1487 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1488 (match_operand:DI 3 "s_register_operand" "")))]
1489 "TARGET_32BIT && arm_arch3m"
1490 "")
82b85d08 1491
1492(define_insn "*mulsidi3adddi"
fe8dbf85 1493 [(set (match_operand:DI 0 "s_register_operand" "=&r")
82b85d08 1494 (plus:DI
215b30b3 1495 (mult:DI
fe8dbf85 1496 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1497 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1498 (match_operand:DI 1 "s_register_operand" "0")))]
58d7d654 1499 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1500 "smlal%?\\t%Q0, %R0, %3, %2"
9da0ec36 1501 [(set_attr "type" "smlal")
58d7d654 1502 (set_attr "predicable" "yes")]
1503)
1504
1505(define_insn "*mulsidi3adddi_v6"
1506 [(set (match_operand:DI 0 "s_register_operand" "=r")
1507 (plus:DI
1508 (mult:DI
1509 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1510 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1511 (match_operand:DI 1 "s_register_operand" "0")))]
1512 "TARGET_32BIT && arm_arch6"
fe8dbf85 1513 "smlal%?\\t%Q0, %R0, %3, %2"
9da0ec36 1514 [(set_attr "type" "smlal")
d952d547 1515 (set_attr "predicable" "yes")
1516 (set_attr "predicable_short_it" "no")]
0d66636f 1517)
82b85d08 1518
957788b0 1519;; 32x32->64 widening multiply.
1520;; As with mulsi3, the only difference between the v3-5 and v6+
1521;; versions of these patterns is the requirement that the output not
1522;; overlap the inputs, but that still means we have to have a named
1523;; expander and two different starred insns.
1524
1525(define_expand "mulsidi3"
1526 [(set (match_operand:DI 0 "s_register_operand" "")
1527 (mult:DI
1528 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1529 (sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1530 "TARGET_32BIT && arm_arch3m"
1531 ""
1532)
1533
1534(define_insn "*mulsidi3_nov6"
f7fbdd4a 1535 [(set (match_operand:DI 0 "s_register_operand" "=&r")
215b30b3 1536 (mult:DI
1537 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1538 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
58d7d654 1539 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1540 "smull%?\\t%Q0, %R0, %1, %2"
9da0ec36 1541 [(set_attr "type" "smull")
58d7d654 1542 (set_attr "predicable" "yes")]
1543)
1544
957788b0 1545(define_insn "*mulsidi3_v6"
58d7d654 1546 [(set (match_operand:DI 0 "s_register_operand" "=r")
1547 (mult:DI
1548 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1549 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1550 "TARGET_32BIT && arm_arch6"
97499065 1551 "smull%?\\t%Q0, %R0, %1, %2"
9da0ec36 1552 [(set_attr "type" "smull")
d952d547 1553 (set_attr "predicable" "yes")
1554 (set_attr "predicable_short_it" "no")]
0d66636f 1555)
f7fbdd4a 1556
957788b0 1557(define_expand "umulsidi3"
1558 [(set (match_operand:DI 0 "s_register_operand" "")
1559 (mult:DI
1560 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1561 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1562 "TARGET_32BIT && arm_arch3m"
1563 ""
1564)
1565
1566(define_insn "*umulsidi3_nov6"
f7fbdd4a 1567 [(set (match_operand:DI 0 "s_register_operand" "=&r")
215b30b3 1568 (mult:DI
1569 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1570 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
58d7d654 1571 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1572 "umull%?\\t%Q0, %R0, %1, %2"
9da0ec36 1573 [(set_attr "type" "umull")
58d7d654 1574 (set_attr "predicable" "yes")]
1575)
1576
957788b0 1577(define_insn "*umulsidi3_v6"
58d7d654 1578 [(set (match_operand:DI 0 "s_register_operand" "=r")
1579 (mult:DI
1580 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1581 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1582 "TARGET_32BIT && arm_arch6"
97499065 1583 "umull%?\\t%Q0, %R0, %1, %2"
9da0ec36 1584 [(set_attr "type" "umull")
d952d547 1585 (set_attr "predicable" "yes")
1586 (set_attr "predicable_short_it" "no")]
0d66636f 1587)
b11cae9e 1588
5cdca009 1589(define_expand "umaddsidi4"
1590 [(set (match_operand:DI 0 "s_register_operand" "")
1591 (plus:DI
1592 (mult:DI
1593 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1594 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1595 (match_operand:DI 3 "s_register_operand" "")))]
1596 "TARGET_32BIT && arm_arch3m"
1597 "")
82b85d08 1598
1599(define_insn "*umulsidi3adddi"
8ead09f9 1600 [(set (match_operand:DI 0 "s_register_operand" "=&r")
82b85d08 1601 (plus:DI
215b30b3 1602 (mult:DI
fe8dbf85 1603 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1604 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1605 (match_operand:DI 1 "s_register_operand" "0")))]
58d7d654 1606 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1607 "umlal%?\\t%Q0, %R0, %3, %2"
9da0ec36 1608 [(set_attr "type" "umlal")
58d7d654 1609 (set_attr "predicable" "yes")]
1610)
1611
1612(define_insn "*umulsidi3adddi_v6"
1613 [(set (match_operand:DI 0 "s_register_operand" "=r")
1614 (plus:DI
1615 (mult:DI
1616 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1617 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1618 (match_operand:DI 1 "s_register_operand" "0")))]
1619 "TARGET_32BIT && arm_arch6"
fe8dbf85 1620 "umlal%?\\t%Q0, %R0, %3, %2"
9da0ec36 1621 [(set_attr "type" "umlal")
d952d547 1622 (set_attr "predicable" "yes")
1623 (set_attr "predicable_short_it" "no")]
0d66636f 1624)
82b85d08 1625
957788b0 1626(define_expand "smulsi3_highpart"
1627 [(parallel
1628 [(set (match_operand:SI 0 "s_register_operand" "")
1629 (truncate:SI
1630 (lshiftrt:DI
1631 (mult:DI
1632 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1633 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1634 (const_int 32))))
1635 (clobber (match_scratch:SI 3 ""))])]
1636 "TARGET_32BIT && arm_arch3m"
1637 ""
1638)
1639
1640(define_insn "*smulsi3_highpart_nov6"
f082f1c4 1641 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1642 (truncate:SI
1643 (lshiftrt:DI
215b30b3 1644 (mult:DI
e5fea38e 1645 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
215b30b3 1646 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
f082f1c4 1647 (const_int 32))))
1648 (clobber (match_scratch:SI 3 "=&r,&r"))]
58d7d654 1649 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1650 "smull%?\\t%3, %0, %2, %1"
9da0ec36 1651 [(set_attr "type" "smull")
58d7d654 1652 (set_attr "predicable" "yes")]
1653)
1654
957788b0 1655(define_insn "*smulsi3_highpart_v6"
58d7d654 1656 [(set (match_operand:SI 0 "s_register_operand" "=r")
1657 (truncate:SI
1658 (lshiftrt:DI
1659 (mult:DI
1660 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1661 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1662 (const_int 32))))
1663 (clobber (match_scratch:SI 3 "=r"))]
1664 "TARGET_32BIT && arm_arch6"
f082f1c4 1665 "smull%?\\t%3, %0, %2, %1"
9da0ec36 1666 [(set_attr "type" "smull")
d952d547 1667 (set_attr "predicable" "yes")
1668 (set_attr "predicable_short_it" "no")]
cffb2a26 1669)
f082f1c4 1670
957788b0 1671(define_expand "umulsi3_highpart"
1672 [(parallel
1673 [(set (match_operand:SI 0 "s_register_operand" "")
1674 (truncate:SI
1675 (lshiftrt:DI
1676 (mult:DI
1677 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1678 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1679 (const_int 32))))
1680 (clobber (match_scratch:SI 3 ""))])]
1681 "TARGET_32BIT && arm_arch3m"
1682 ""
1683)
1684
1685(define_insn "*umulsi3_highpart_nov6"
f082f1c4 1686 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1687 (truncate:SI
1688 (lshiftrt:DI
215b30b3 1689 (mult:DI
e5fea38e 1690 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
215b30b3 1691 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
f082f1c4 1692 (const_int 32))))
1693 (clobber (match_scratch:SI 3 "=&r,&r"))]
58d7d654 1694 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1695 "umull%?\\t%3, %0, %2, %1"
9da0ec36 1696 [(set_attr "type" "umull")
58d7d654 1697 (set_attr "predicable" "yes")]
1698)
1699
957788b0 1700(define_insn "*umulsi3_highpart_v6"
58d7d654 1701 [(set (match_operand:SI 0 "s_register_operand" "=r")
1702 (truncate:SI
1703 (lshiftrt:DI
1704 (mult:DI
1705 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1706 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1707 (const_int 32))))
1708 (clobber (match_scratch:SI 3 "=r"))]
1709 "TARGET_32BIT && arm_arch6"
f082f1c4 1710 "umull%?\\t%3, %0, %2, %1"
9da0ec36 1711 [(set_attr "type" "umull")
d952d547 1712 (set_attr "predicable" "yes")
1713 (set_attr "predicable_short_it" "no")]
cffb2a26 1714)
f082f1c4 1715
331beb1a 1716(define_insn "mulhisi3"
1717 [(set (match_operand:SI 0 "s_register_operand" "=r")
1718 (mult:SI (sign_extend:SI
1719 (match_operand:HI 1 "s_register_operand" "%r"))
1720 (sign_extend:SI
1721 (match_operand:HI 2 "s_register_operand" "r"))))]
25f905c2 1722 "TARGET_DSP_MULTIPLY"
61a2d04c 1723 "smulbb%?\\t%0, %1, %2"
9da0ec36 1724 [(set_attr "type" "smulxy")
fec538d9 1725 (set_attr "predicable" "yes")]
1726)
1727
1728(define_insn "*mulhisi3tb"
1729 [(set (match_operand:SI 0 "s_register_operand" "=r")
1730 (mult:SI (ashiftrt:SI
1731 (match_operand:SI 1 "s_register_operand" "r")
1732 (const_int 16))
1733 (sign_extend:SI
1734 (match_operand:HI 2 "s_register_operand" "r"))))]
25f905c2 1735 "TARGET_DSP_MULTIPLY"
fec538d9 1736 "smultb%?\\t%0, %1, %2"
9da0ec36 1737 [(set_attr "type" "smulxy")
d952d547 1738 (set_attr "predicable" "yes")
1739 (set_attr "predicable_short_it" "no")]
fec538d9 1740)
1741
1742(define_insn "*mulhisi3bt"
1743 [(set (match_operand:SI 0 "s_register_operand" "=r")
1744 (mult:SI (sign_extend:SI
1745 (match_operand:HI 1 "s_register_operand" "r"))
1746 (ashiftrt:SI
1747 (match_operand:SI 2 "s_register_operand" "r")
1748 (const_int 16))))]
25f905c2 1749 "TARGET_DSP_MULTIPLY"
fec538d9 1750 "smulbt%?\\t%0, %1, %2"
9da0ec36 1751 [(set_attr "type" "smulxy")
d952d547 1752 (set_attr "predicable" "yes")
1753 (set_attr "predicable_short_it" "no")]
fec538d9 1754)
1755
1756(define_insn "*mulhisi3tt"
1757 [(set (match_operand:SI 0 "s_register_operand" "=r")
1758 (mult:SI (ashiftrt:SI
1759 (match_operand:SI 1 "s_register_operand" "r")
1760 (const_int 16))
1761 (ashiftrt:SI
1762 (match_operand:SI 2 "s_register_operand" "r")
1763 (const_int 16))))]
25f905c2 1764 "TARGET_DSP_MULTIPLY"
fec538d9 1765 "smultt%?\\t%0, %1, %2"
9da0ec36 1766 [(set_attr "type" "smulxy")
d952d547 1767 (set_attr "predicable" "yes")
1768 (set_attr "predicable_short_it" "no")]
331beb1a 1769)
1770
5cdca009 1771(define_insn "maddhisi4"
331beb1a 1772 [(set (match_operand:SI 0 "s_register_operand" "=r")
cfa6c608 1773 (plus:SI (mult:SI (sign_extend:SI
1774 (match_operand:HI 1 "s_register_operand" "r"))
331beb1a 1775 (sign_extend:SI
cfa6c608 1776 (match_operand:HI 2 "s_register_operand" "r")))
1777 (match_operand:SI 3 "s_register_operand" "r")))]
25f905c2 1778 "TARGET_DSP_MULTIPLY"
5cdca009 1779 "smlabb%?\\t%0, %1, %2, %3"
9da0ec36 1780 [(set_attr "type" "smlaxy")
d952d547 1781 (set_attr "predicable" "yes")
1782 (set_attr "predicable_short_it" "no")]
331beb1a 1783)
1784
9a92f368 1785;; Note: there is no maddhisi4ibt because this one is canonical form
1786(define_insn "*maddhisi4tb"
1787 [(set (match_operand:SI 0 "s_register_operand" "=r")
1788 (plus:SI (mult:SI (ashiftrt:SI
1789 (match_operand:SI 1 "s_register_operand" "r")
1790 (const_int 16))
1791 (sign_extend:SI
1792 (match_operand:HI 2 "s_register_operand" "r")))
1793 (match_operand:SI 3 "s_register_operand" "r")))]
1794 "TARGET_DSP_MULTIPLY"
1795 "smlatb%?\\t%0, %1, %2, %3"
9da0ec36 1796 [(set_attr "type" "smlaxy")
d952d547 1797 (set_attr "predicable" "yes")
1798 (set_attr "predicable_short_it" "no")]
9a92f368 1799)
1800
1801(define_insn "*maddhisi4tt"
1802 [(set (match_operand:SI 0 "s_register_operand" "=r")
1803 (plus:SI (mult:SI (ashiftrt:SI
1804 (match_operand:SI 1 "s_register_operand" "r")
1805 (const_int 16))
1806 (ashiftrt:SI
1807 (match_operand:SI 2 "s_register_operand" "r")
1808 (const_int 16)))
1809 (match_operand:SI 3 "s_register_operand" "r")))]
1810 "TARGET_DSP_MULTIPLY"
1811 "smlatt%?\\t%0, %1, %2, %3"
9da0ec36 1812 [(set_attr "type" "smlaxy")
d952d547 1813 (set_attr "predicable" "yes")
1814 (set_attr "predicable_short_it" "no")]
9a92f368 1815)
1816
aff5fb4d 1817(define_insn "maddhidi4"
331beb1a 1818 [(set (match_operand:DI 0 "s_register_operand" "=r")
1819 (plus:DI
331beb1a 1820 (mult:DI (sign_extend:DI
d952d547 1821 (match_operand:HI 1 "s_register_operand" "r"))
331beb1a 1822 (sign_extend:DI
cfa6c608 1823 (match_operand:HI 2 "s_register_operand" "r")))
1824 (match_operand:DI 3 "s_register_operand" "0")))]
25f905c2 1825 "TARGET_DSP_MULTIPLY"
5cdca009 1826 "smlalbb%?\\t%Q0, %R0, %1, %2"
9da0ec36 1827 [(set_attr "type" "smlalxy")
d952d547 1828 (set_attr "predicable" "yes")
1829 (set_attr "predicable_short_it" "no")])
331beb1a 1830
9a92f368 1831;; Note: there is no maddhidi4ibt because this one is canonical form
1832(define_insn "*maddhidi4tb"
1833 [(set (match_operand:DI 0 "s_register_operand" "=r")
1834 (plus:DI
1835 (mult:DI (sign_extend:DI
1836 (ashiftrt:SI
1837 (match_operand:SI 1 "s_register_operand" "r")
1838 (const_int 16)))
1839 (sign_extend:DI
1840 (match_operand:HI 2 "s_register_operand" "r")))
1841 (match_operand:DI 3 "s_register_operand" "0")))]
1842 "TARGET_DSP_MULTIPLY"
1843 "smlaltb%?\\t%Q0, %R0, %1, %2"
9da0ec36 1844 [(set_attr "type" "smlalxy")
d952d547 1845 (set_attr "predicable" "yes")
1846 (set_attr "predicable_short_it" "no")])
9a92f368 1847
1848(define_insn "*maddhidi4tt"
1849 [(set (match_operand:DI 0 "s_register_operand" "=r")
1850 (plus:DI
1851 (mult:DI (sign_extend:DI
1852 (ashiftrt:SI
1853 (match_operand:SI 1 "s_register_operand" "r")
1854 (const_int 16)))
1855 (sign_extend:DI
1856 (ashiftrt:SI
1857 (match_operand:SI 2 "s_register_operand" "r")
1858 (const_int 16))))
1859 (match_operand:DI 3 "s_register_operand" "0")))]
1860 "TARGET_DSP_MULTIPLY"
1861 "smlaltt%?\\t%Q0, %R0, %1, %2"
9da0ec36 1862 [(set_attr "type" "smlalxy")
d952d547 1863 (set_attr "predicable" "yes")
1864 (set_attr "predicable_short_it" "no")])
9a92f368 1865
604f3a0a 1866(define_expand "mulsf3"
1867 [(set (match_operand:SF 0 "s_register_operand" "")
1868 (mult:SF (match_operand:SF 1 "s_register_operand" "")
d86c91f6 1869 (match_operand:SF 2 "s_register_operand" "")))]
25f905c2 1870 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1871 "
604f3a0a 1872")
1873
604f3a0a 1874(define_expand "muldf3"
1875 [(set (match_operand:DF 0 "s_register_operand" "")
1876 (mult:DF (match_operand:DF 1 "s_register_operand" "")
d86c91f6 1877 (match_operand:DF 2 "s_register_operand" "")))]
a50d7267 1878 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 1879 "
604f3a0a 1880")
b11cae9e 1881\f
1882;; Division insns
1883
7db9af5d 1884(define_expand "divsf3"
1885 [(set (match_operand:SF 0 "s_register_operand" "")
d86c91f6 1886 (div:SF (match_operand:SF 1 "s_register_operand" "")
1887 (match_operand:SF 2 "s_register_operand" "")))]
994606f8 1888 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
7db9af5d 1889 "")
9c08d1fa 1890
7db9af5d 1891(define_expand "divdf3"
1892 [(set (match_operand:DF 0 "s_register_operand" "")
d86c91f6 1893 (div:DF (match_operand:DF 1 "s_register_operand" "")
1894 (match_operand:DF 2 "s_register_operand" "")))]
994606f8 1895 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
7db9af5d 1896 "")
b11cae9e 1897\f
1898;; Boolean and,ior,xor insns
1899
f6ebffac 1900;; Split up double word logical operations
1901
1902;; Split up simple DImode logical operations. Simply perform the logical
1903;; operation on the upper and lower halves of the registers.
1904(define_split
1905 [(set (match_operand:DI 0 "s_register_operand" "")
1906 (match_operator:DI 6 "logical_binary_operator"
1907 [(match_operand:DI 1 "s_register_operand" "")
1908 (match_operand:DI 2 "s_register_operand" "")]))]
25f905c2 1909 "TARGET_32BIT && reload_completed
e2669ea7 1910 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))
25f905c2 1911 && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
f6ebffac 1912 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1913 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1914 "
215b30b3 1915 {
1916 operands[3] = gen_highpart (SImode, operands[0]);
1917 operands[0] = gen_lowpart (SImode, operands[0]);
1918 operands[4] = gen_highpart (SImode, operands[1]);
1919 operands[1] = gen_lowpart (SImode, operands[1]);
1920 operands[5] = gen_highpart (SImode, operands[2]);
1921 operands[2] = gen_lowpart (SImode, operands[2]);
1922 }"
1923)
f6ebffac 1924
f6ebffac 1925(define_split
1926 [(set (match_operand:DI 0 "s_register_operand" "")
1927 (match_operator:DI 6 "logical_binary_operator"
1928 [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1929 (match_operand:DI 1 "s_register_operand" "")]))]
25f905c2 1930 "TARGET_32BIT && reload_completed"
f6ebffac 1931 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1932 (set (match_dup 3) (match_op_dup:SI 6
1933 [(ashiftrt:SI (match_dup 2) (const_int 31))
1934 (match_dup 4)]))]
1935 "
215b30b3 1936 {
1937 operands[3] = gen_highpart (SImode, operands[0]);
1938 operands[0] = gen_lowpart (SImode, operands[0]);
1939 operands[4] = gen_highpart (SImode, operands[1]);
1940 operands[1] = gen_lowpart (SImode, operands[1]);
1941 operands[5] = gen_highpart (SImode, operands[2]);
1942 operands[2] = gen_lowpart (SImode, operands[2]);
1943 }"
1944)
f6ebffac 1945
f6ebffac 1946;; The zero extend of operand 2 means we can just copy the high part of
1947;; operand1 into operand0.
1948(define_split
1949 [(set (match_operand:DI 0 "s_register_operand" "")
1950 (ior:DI
1951 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1952 (match_operand:DI 1 "s_register_operand" "")))]
25f905c2 1953 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
f6ebffac 1954 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1955 (set (match_dup 3) (match_dup 4))]
1956 "
215b30b3 1957 {
1958 operands[4] = gen_highpart (SImode, operands[1]);
1959 operands[3] = gen_highpart (SImode, operands[0]);
1960 operands[0] = gen_lowpart (SImode, operands[0]);
1961 operands[1] = gen_lowpart (SImode, operands[1]);
1962 }"
1963)
f6ebffac 1964
1965;; The zero extend of operand 2 means we can just copy the high part of
1966;; operand1 into operand0.
1967(define_split
1968 [(set (match_operand:DI 0 "s_register_operand" "")
1969 (xor:DI
1970 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1971 (match_operand:DI 1 "s_register_operand" "")))]
25f905c2 1972 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
f6ebffac 1973 [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1974 (set (match_dup 3) (match_dup 4))]
1975 "
215b30b3 1976 {
1977 operands[4] = gen_highpart (SImode, operands[1]);
1978 operands[3] = gen_highpart (SImode, operands[0]);
1979 operands[0] = gen_lowpart (SImode, operands[0]);
1980 operands[1] = gen_lowpart (SImode, operands[1]);
1981 }"
1982)
f6ebffac 1983
e2669ea7 1984(define_expand "anddi3"
1985 [(set (match_operand:DI 0 "s_register_operand" "")
1986 (and:DI (match_operand:DI 1 "s_register_operand" "")
1987 (match_operand:DI 2 "neon_inv_logic_op2" "")))]
1988 "TARGET_32BIT"
1989 ""
1990)
1991
f6bbdcf6 1992(define_insn_and_split "*anddi3_insn"
0a314dcd 1993 [(set (match_operand:DI 0 "s_register_operand" "=w,w ,&r,&r,&r,&r,?w,?w")
1994 (and:DI (match_operand:DI 1 "s_register_operand" "%w,0 ,0 ,r ,0 ,r ,w ,0")
1995 (match_operand:DI 2 "arm_anddi_operand_neon" "w ,DL,r ,r ,De,De,w ,DL")))]
f6bbdcf6 1996 "TARGET_32BIT && !TARGET_IWMMXT"
1997{
1998 switch (which_alternative)
1999 {
0a314dcd 2000 case 0: /* fall through */
2001 case 6: return "vand\t%P0, %P1, %P2";
2002 case 1: /* fall through */
2003 case 7: return neon_output_logic_immediate ("vand", &operands[2],
2004 DImode, 1, VALID_NEON_QREG_MODE (DImode));
f6bbdcf6 2005 case 2:
0a314dcd 2006 case 3:
2007 case 4:
f6bbdcf6 2008 case 5: /* fall through */
0a314dcd 2009 return "#";
f6bbdcf6 2010 default: gcc_unreachable ();
2011 }
2012}
0a314dcd 2013 "TARGET_32BIT && !TARGET_IWMMXT && reload_completed
2014 && !(IS_VFP_REGNUM (REGNO (operands[0])))"
f6bbdcf6 2015 [(set (match_dup 3) (match_dup 4))
2016 (set (match_dup 5) (match_dup 6))]
2017 "
2018 {
2019 operands[3] = gen_lowpart (SImode, operands[0]);
2020 operands[5] = gen_highpart (SImode, operands[0]);
2021
2022 operands[4] = simplify_gen_binary (AND, SImode,
2023 gen_lowpart (SImode, operands[1]),
2024 gen_lowpart (SImode, operands[2]));
2025 operands[6] = simplify_gen_binary (AND, SImode,
2026 gen_highpart (SImode, operands[1]),
2027 gen_highpart_mode (SImode, DImode, operands[2]));
2028
2029 }"
32093010 2030 [(set_attr "type" "neon_logic,neon_logic,multiple,multiple,\
2031 multiple,multiple,neon_logic,neon_logic")
0a314dcd 2032 (set_attr "arch" "neon_for_64bits,neon_for_64bits,*,*,*,*,
f6bbdcf6 2033 avoid_neon_for_64bits,avoid_neon_for_64bits")
0a314dcd 2034 (set_attr "length" "*,*,8,8,8,8,*,*")
2035 ]
215b30b3 2036)
b11cae9e 2037
a0f94409 2038(define_insn_and_split "*anddi_zesidi_di"
9c08d1fa 2039 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2040 (and:DI (zero_extend:DI
2041 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 2042 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2043 "TARGET_32BIT"
f6ebffac 2044 "#"
25f905c2 2045 "TARGET_32BIT && reload_completed"
a0f94409 2046 ; The zero extend of operand 2 clears the high word of the output
2047 ; operand.
2048 [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
2049 (set (match_dup 3) (const_int 0))]
2050 "
2051 {
2052 operands[3] = gen_highpart (SImode, operands[0]);
2053 operands[0] = gen_lowpart (SImode, operands[0]);
2054 operands[1] = gen_lowpart (SImode, operands[1]);
2055 }"
1b7da4ac 2056 [(set_attr "length" "8")
2057 (set_attr "type" "multiple")]
215b30b3 2058)
b11cae9e 2059
f7fbdd4a 2060(define_insn "*anddi_sesdi_di"
cffb2a26 2061 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 2062 (and:DI (sign_extend:DI
2063 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 2064 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2065 "TARGET_32BIT"
f6ebffac 2066 "#"
1b7da4ac 2067 [(set_attr "length" "8")
2068 (set_attr "type" "multiple")]
cffb2a26 2069)
b11cae9e 2070
87b22bf7 2071(define_expand "andsi3"
cffb2a26 2072 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2073 (and:SI (match_operand:SI 1 "s_register_operand" "")
2074 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 2075 "TARGET_EITHER"
87b22bf7 2076 "
25f905c2 2077 if (TARGET_32BIT)
87b22bf7 2078 {
0438d37f 2079 if (CONST_INT_P (operands[2]))
cffb2a26 2080 {
47b5b27b 2081 if (INTVAL (operands[2]) == 255 && arm_arch6)
2082 {
2083 operands[1] = convert_to_mode (QImode, operands[1], 1);
2084 emit_insn (gen_thumb2_zero_extendqisi2_v6 (operands[0],
2085 operands[1]));
2086 }
2087 else
2088 arm_split_constant (AND, SImode, NULL_RTX,
2089 INTVAL (operands[2]), operands[0],
2090 operands[1],
2091 optimize && can_create_pseudo_p ());
615caa51 2092
cffb2a26 2093 DONE;
2094 }
87b22bf7 2095 }
25f905c2 2096 else /* TARGET_THUMB1 */
cffb2a26 2097 {
0438d37f 2098 if (!CONST_INT_P (operands[2]))
923ffadb 2099 {
2100 rtx tmp = force_reg (SImode, operands[2]);
2101 if (rtx_equal_p (operands[0], operands[1]))
2102 operands[2] = tmp;
2103 else
2104 {
2105 operands[2] = operands[1];
2106 operands[1] = tmp;
2107 }
2108 }
cffb2a26 2109 else
2110 {
2111 int i;
2112
215b30b3 2113 if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
cffb2a26 2114 {
215b30b3 2115 operands[2] = force_reg (SImode,
2116 GEN_INT (~INTVAL (operands[2])));
cffb2a26 2117
747b7458 2118 emit_insn (gen_thumb1_bicsi3 (operands[0], operands[2], operands[1]));
cffb2a26 2119
2120 DONE;
2121 }
87b22bf7 2122
cffb2a26 2123 for (i = 9; i <= 31; i++)
2124 {
2125 if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
2126 {
2127 emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
2128 const0_rtx));
2129 DONE;
2130 }
215b30b3 2131 else if ((((HOST_WIDE_INT) 1) << i) - 1
2132 == ~INTVAL (operands[2]))
cffb2a26 2133 {
2134 rtx shift = GEN_INT (i);
2135 rtx reg = gen_reg_rtx (SImode);
2136
2137 emit_insn (gen_lshrsi3 (reg, operands[1], shift));
2138 emit_insn (gen_ashlsi3 (operands[0], reg, shift));
2139
2140 DONE;
2141 }
2142 }
2143
2144 operands[2] = force_reg (SImode, operands[2]);
2145 }
215b30b3 2146 }
2147 "
cffb2a26 2148)
2149
25f905c2 2150; ??? Check split length for Thumb-2
a0f94409 2151(define_insn_and_split "*arm_andsi3_insn"
29e234a3 2152 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r,r,r")
2153 (and:SI (match_operand:SI 1 "s_register_operand" "%r,0,r,r,r")
2154 (match_operand:SI 2 "reg_or_int_operand" "I,l,K,r,?n")))]
25f905c2 2155 "TARGET_32BIT"
5565501b 2156 "@
29e234a3 2157 and%?\\t%0, %1, %2
5565501b 2158 and%?\\t%0, %1, %2
87b22bf7 2159 bic%?\\t%0, %1, #%B2
65f68e55 2160 and%?\\t%0, %1, %2
87b22bf7 2161 #"
25f905c2 2162 "TARGET_32BIT
0438d37f 2163 && CONST_INT_P (operands[2])
a0f94409 2164 && !(const_ok_for_arm (INTVAL (operands[2]))
2165 || const_ok_for_arm (~INTVAL (operands[2])))"
2166 [(clobber (const_int 0))]
2167 "
96f57e36 2168 arm_split_constant (AND, SImode, curr_insn,
2169 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 2170 DONE;
2171 "
29e234a3 2172 [(set_attr "length" "4,4,4,4,16")
65f68e55 2173 (set_attr "predicable" "yes")
29e234a3 2174 (set_attr "predicable_short_it" "no,yes,no,no,no")
d82e788e 2175 (set_attr "type" "logic_imm,logic_imm,logic_reg,logic_reg,logic_imm")]
cffb2a26 2176)
2177
f7fbdd4a 2178(define_insn "*andsi3_compare0"
bd5b4116 2179 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 2180 (compare:CC_NOOV
65f68e55 2181 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
2182 (match_operand:SI 2 "arm_not_operand" "I,K,r"))
5565501b 2183 (const_int 0)))
65f68e55 2184 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9c08d1fa 2185 (and:SI (match_dup 1) (match_dup 2)))]
25f905c2 2186 "TARGET_32BIT"
5565501b 2187 "@
25f905c2 2188 and%.\\t%0, %1, %2
65f68e55 2189 bic%.\\t%0, %1, #%B2
2190 and%.\\t%0, %1, %2"
2191 [(set_attr "conds" "set")
d82e788e 2192 (set_attr "type" "logics_imm,logics_imm,logics_reg")]
cffb2a26 2193)
9c08d1fa 2194
f7fbdd4a 2195(define_insn "*andsi3_compare0_scratch"
bd5b4116 2196 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 2197 (compare:CC_NOOV
65f68e55 2198 (and:SI (match_operand:SI 0 "s_register_operand" "r,r,r")
2199 (match_operand:SI 1 "arm_not_operand" "I,K,r"))
5565501b 2200 (const_int 0)))
65f68e55 2201 (clobber (match_scratch:SI 2 "=X,r,X"))]
25f905c2 2202 "TARGET_32BIT"
5565501b 2203 "@
2204 tst%?\\t%0, %1
65f68e55 2205 bic%.\\t%2, %0, #%B1
2206 tst%?\\t%0, %1"
2207 [(set_attr "conds" "set")
d82e788e 2208 (set_attr "type" "logics_imm,logics_imm,logics_reg")]
0d66636f 2209)
9c08d1fa 2210
f7fbdd4a 2211(define_insn "*zeroextractsi_compare0_scratch"
bd5b4116 2212 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2213 (compare:CC_NOOV (zero_extract:SI
2214 (match_operand:SI 0 "s_register_operand" "r")
d952d547 2215 (match_operand 1 "const_int_operand" "n")
206ee9a2 2216 (match_operand 2 "const_int_operand" "n"))
9c08d1fa 2217 (const_int 0)))]
25f905c2 2218 "TARGET_32BIT
cffb2a26 2219 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
2220 && INTVAL (operands[1]) > 0
2221 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
2222 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
9c08d1fa 2223 "*
5c49a439 2224 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
2225 << INTVAL (operands[2]));
40dbec34 2226 output_asm_insn (\"tst%?\\t%0, %1\", operands);
e2348bcb 2227 return \"\";
0d66636f 2228 "
596e5e8f 2229 [(set_attr "conds" "set")
65f68e55 2230 (set_attr "predicable" "yes")
d952d547 2231 (set_attr "predicable_short_it" "no")
d82e788e 2232 (set_attr "type" "logics_imm")]
0d66636f 2233)
9c08d1fa 2234
f4462328 2235(define_insn_and_split "*ne_zeroextractsi"
c4034607 2236 [(set (match_operand:SI 0 "s_register_operand" "=r")
2237 (ne:SI (zero_extract:SI
2238 (match_operand:SI 1 "s_register_operand" "r")
2239 (match_operand:SI 2 "const_int_operand" "n")
2240 (match_operand:SI 3 "const_int_operand" "n"))
3b8c7f7a 2241 (const_int 0)))
2242 (clobber (reg:CC CC_REGNUM))]
25f905c2 2243 "TARGET_32BIT
cffb2a26 2244 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2245 && INTVAL (operands[2]) > 0
2246 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2247 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
f4462328 2248 "#"
25f905c2 2249 "TARGET_32BIT
f4462328 2250 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2251 && INTVAL (operands[2]) > 0
2252 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2253 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
2254 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2255 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2256 (const_int 0)))
2257 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2258 (set (match_dup 0)
2259 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2260 (match_dup 0) (const_int 1)))]
2261 "
2262 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
2263 << INTVAL (operands[3]));
2264 "
2265 [(set_attr "conds" "clob")
25f905c2 2266 (set (attr "length")
2267 (if_then_else (eq_attr "is_thumb" "yes")
2268 (const_int 12)
1b7da4ac 2269 (const_int 8)))
2270 (set_attr "type" "multiple")]
f4462328 2271)
2272
2273(define_insn_and_split "*ne_zeroextractsi_shifted"
2274 [(set (match_operand:SI 0 "s_register_operand" "=r")
2275 (ne:SI (zero_extract:SI
2276 (match_operand:SI 1 "s_register_operand" "r")
2277 (match_operand:SI 2 "const_int_operand" "n")
2278 (const_int 0))
2279 (const_int 0)))
2280 (clobber (reg:CC CC_REGNUM))]
2281 "TARGET_ARM"
2282 "#"
2283 "TARGET_ARM"
2284 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2285 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2286 (const_int 0)))
2287 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2288 (set (match_dup 0)
2289 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2290 (match_dup 0) (const_int 1)))]
2291 "
2292 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
2293 "
2294 [(set_attr "conds" "clob")
1b7da4ac 2295 (set_attr "length" "8")
2296 (set_attr "type" "multiple")]
f4462328 2297)
2298
2299(define_insn_and_split "*ite_ne_zeroextractsi"
2300 [(set (match_operand:SI 0 "s_register_operand" "=r")
2301 (if_then_else:SI (ne (zero_extract:SI
2302 (match_operand:SI 1 "s_register_operand" "r")
2303 (match_operand:SI 2 "const_int_operand" "n")
2304 (match_operand:SI 3 "const_int_operand" "n"))
2305 (const_int 0))
2306 (match_operand:SI 4 "arm_not_operand" "rIK")
2307 (const_int 0)))
2308 (clobber (reg:CC CC_REGNUM))]
2309 "TARGET_ARM
2310 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2311 && INTVAL (operands[2]) > 0
2312 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 2313 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2314 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 2315 "#"
2316 "TARGET_ARM
2317 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2318 && INTVAL (operands[2]) > 0
2319 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 2320 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2321 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 2322 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2323 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2324 (const_int 0)))
2325 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2326 (set (match_dup 0)
2327 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2328 (match_dup 0) (match_dup 4)))]
2329 "
c4034607 2330 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
f4462328 2331 << INTVAL (operands[3]));
2332 "
2333 [(set_attr "conds" "clob")
1b7da4ac 2334 (set_attr "length" "8")
2335 (set_attr "type" "multiple")]
f4462328 2336)
2337
2338(define_insn_and_split "*ite_ne_zeroextractsi_shifted"
2339 [(set (match_operand:SI 0 "s_register_operand" "=r")
2340 (if_then_else:SI (ne (zero_extract:SI
2341 (match_operand:SI 1 "s_register_operand" "r")
2342 (match_operand:SI 2 "const_int_operand" "n")
2343 (const_int 0))
2344 (const_int 0))
2345 (match_operand:SI 3 "arm_not_operand" "rIK")
2346 (const_int 0)))
2347 (clobber (reg:CC CC_REGNUM))]
f8d7bf2f 2348 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 2349 "#"
f8d7bf2f 2350 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 2351 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2352 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2353 (const_int 0)))
2354 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2355 (set (match_dup 0)
2356 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2357 (match_dup 0) (match_dup 3)))]
2358 "
2359 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
0d66636f 2360 "
2361 [(set_attr "conds" "clob")
1b7da4ac 2362 (set_attr "length" "8")
2363 (set_attr "type" "multiple")]
215b30b3 2364)
9c08d1fa 2365
25f905c2 2366;; ??? Use Thumb-2 has bitfield insert/extract instructions.
d7863cfe 2367(define_split
2368 [(set (match_operand:SI 0 "s_register_operand" "")
2369 (match_operator:SI 1 "shiftable_operator"
2370 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2371 (match_operand:SI 3 "const_int_operand" "")
2372 (match_operand:SI 4 "const_int_operand" ""))
2373 (match_operand:SI 5 "s_register_operand" "")]))
2374 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2375 "TARGET_ARM"
2376 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2377 (set (match_dup 0)
2378 (match_op_dup 1
2379 [(lshiftrt:SI (match_dup 6) (match_dup 4))
2380 (match_dup 5)]))]
2381 "{
2382 HOST_WIDE_INT temp = INTVAL (operands[3]);
2383
2384 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2385 operands[4] = GEN_INT (32 - temp);
2386 }"
2387)
2388
d7863cfe 2389(define_split
2390 [(set (match_operand:SI 0 "s_register_operand" "")
2391 (match_operator:SI 1 "shiftable_operator"
2392 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2393 (match_operand:SI 3 "const_int_operand" "")
2394 (match_operand:SI 4 "const_int_operand" ""))
2395 (match_operand:SI 5 "s_register_operand" "")]))
2396 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2397 "TARGET_ARM"
2398 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2399 (set (match_dup 0)
2400 (match_op_dup 1
2401 [(ashiftrt:SI (match_dup 6) (match_dup 4))
2402 (match_dup 5)]))]
2403 "{
2404 HOST_WIDE_INT temp = INTVAL (operands[3]);
2405
2406 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2407 operands[4] = GEN_INT (32 - temp);
2408 }"
2409)
2410
a42059fd 2411;;; ??? This pattern is bogus. If operand3 has bits outside the range
2412;;; represented by the bitfield, then this will produce incorrect results.
2413;;; Somewhere, the value needs to be truncated. On targets like the m68k,
ceb2fe0f 2414;;; which have a real bit-field insert instruction, the truncation happens
2415;;; in the bit-field insert instruction itself. Since arm does not have a
2416;;; bit-field insert instruction, we would have to emit code here to truncate
a42059fd 2417;;; the value before we insert. This loses some of the advantage of having
2418;;; this insv pattern, so this pattern needs to be reevalutated.
2419
8a18b90c 2420(define_expand "insv"
eb04cafb 2421 [(set (zero_extract (match_operand 0 "nonimmediate_operand" "")
2422 (match_operand 1 "general_operand" "")
2423 (match_operand 2 "general_operand" ""))
2424 (match_operand 3 "reg_or_int_operand" ""))]
8b054d5a 2425 "TARGET_ARM || arm_arch_thumb2"
8a18b90c 2426 "
215b30b3 2427 {
2428 int start_bit = INTVAL (operands[2]);
2429 int width = INTVAL (operands[1]);
2430 HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
2431 rtx target, subtarget;
2432
8b054d5a 2433 if (arm_arch_thumb2)
2434 {
eb04cafb 2435 if (unaligned_access && MEM_P (operands[0])
2436 && s_register_operand (operands[3], GET_MODE (operands[3]))
2437 && (width == 16 || width == 32) && (start_bit % BITS_PER_UNIT) == 0)
8b054d5a 2438 {
eb04cafb 2439 rtx base_addr;
2440
2441 if (BYTES_BIG_ENDIAN)
2442 start_bit = GET_MODE_BITSIZE (GET_MODE (operands[3])) - width
2443 - start_bit;
8b054d5a 2444
eb04cafb 2445 if (width == 32)
8b054d5a 2446 {
eb04cafb 2447 base_addr = adjust_address (operands[0], SImode,
2448 start_bit / BITS_PER_UNIT);
2449 emit_insn (gen_unaligned_storesi (base_addr, operands[3]));
8b054d5a 2450 }
eb04cafb 2451 else
2452 {
2453 rtx tmp = gen_reg_rtx (HImode);
8b054d5a 2454
eb04cafb 2455 base_addr = adjust_address (operands[0], HImode,
2456 start_bit / BITS_PER_UNIT);
2457 emit_move_insn (tmp, gen_lowpart (HImode, operands[3]));
2458 emit_insn (gen_unaligned_storehi (base_addr, tmp));
2459 }
2460 DONE;
8b054d5a 2461 }
eb04cafb 2462 else if (s_register_operand (operands[0], GET_MODE (operands[0])))
8b054d5a 2463 {
eb04cafb 2464 bool use_bfi = TRUE;
8b054d5a 2465
0438d37f 2466 if (CONST_INT_P (operands[3]))
eb04cafb 2467 {
2468 HOST_WIDE_INT val = INTVAL (operands[3]) & mask;
2469
2470 if (val == 0)
2471 {
2472 emit_insn (gen_insv_zero (operands[0], operands[1],
2473 operands[2]));
2474 DONE;
2475 }
2476
2477 /* See if the set can be done with a single orr instruction. */
2478 if (val == mask && const_ok_for_arm (val << start_bit))
2479 use_bfi = FALSE;
2480 }
2481
2482 if (use_bfi)
2483 {
0438d37f 2484 if (!REG_P (operands[3]))
eb04cafb 2485 operands[3] = force_reg (SImode, operands[3]);
2486
2487 emit_insn (gen_insv_t2 (operands[0], operands[1], operands[2],
2488 operands[3]));
2489 DONE;
2490 }
8b054d5a 2491 }
eb04cafb 2492 else
2493 FAIL;
8b054d5a 2494 }
2495
eb04cafb 2496 if (!s_register_operand (operands[0], GET_MODE (operands[0])))
2497 FAIL;
2498
3f8fde42 2499 target = copy_rtx (operands[0]);
215b30b3 2500 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
2501 subreg as the final target. */
2502 if (GET_CODE (target) == SUBREG)
2503 {
2504 subtarget = gen_reg_rtx (SImode);
2505 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
2506 < GET_MODE_SIZE (SImode))
2507 target = SUBREG_REG (target);
2508 }
2509 else
2510 subtarget = target;
8a18b90c 2511
0438d37f 2512 if (CONST_INT_P (operands[3]))
215b30b3 2513 {
2514 /* Since we are inserting a known constant, we may be able to
2515 reduce the number of bits that we have to clear so that
2516 the mask becomes simple. */
2517 /* ??? This code does not check to see if the new mask is actually
2518 simpler. It may not be. */
2519 rtx op1 = gen_reg_rtx (SImode);
2520 /* ??? Truncate operand3 to fit in the bitfield. See comment before
2521 start of this pattern. */
2522 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
2523 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
2524
c5b3a71b 2525 emit_insn (gen_andsi3 (op1, operands[0],
2526 gen_int_mode (~mask2, SImode)));
215b30b3 2527 emit_insn (gen_iorsi3 (subtarget, op1,
4292ca6b 2528 gen_int_mode (op3_value << start_bit, SImode)));
215b30b3 2529 }
2530 else if (start_bit == 0
2531 && !(const_ok_for_arm (mask)
2532 || const_ok_for_arm (~mask)))
2533 {
2534 /* A Trick, since we are setting the bottom bits in the word,
2535 we can shift operand[3] up, operand[0] down, OR them together
2536 and rotate the result back again. This takes 3 insns, and
5910bb95 2537 the third might be mergeable into another op. */
215b30b3 2538 /* The shift up copes with the possibility that operand[3] is
2539 wider than the bitfield. */
2540 rtx op0 = gen_reg_rtx (SImode);
2541 rtx op1 = gen_reg_rtx (SImode);
2542
2543 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2544 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
2545 emit_insn (gen_iorsi3 (op1, op1, op0));
2546 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
2547 }
2548 else if ((width + start_bit == 32)
2549 && !(const_ok_for_arm (mask)
2550 || const_ok_for_arm (~mask)))
2551 {
2552 /* Similar trick, but slightly less efficient. */
8a18b90c 2553
215b30b3 2554 rtx op0 = gen_reg_rtx (SImode);
2555 rtx op1 = gen_reg_rtx (SImode);
8a18b90c 2556
215b30b3 2557 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2558 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
2559 emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
2560 emit_insn (gen_iorsi3 (subtarget, op1, op0));
2561 }
2562 else
2563 {
c5b3a71b 2564 rtx op0 = gen_int_mode (mask, SImode);
215b30b3 2565 rtx op1 = gen_reg_rtx (SImode);
2566 rtx op2 = gen_reg_rtx (SImode);
8a18b90c 2567
215b30b3 2568 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
2569 {
2570 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 2571
215b30b3 2572 emit_insn (gen_movsi (tmp, op0));
2573 op0 = tmp;
2574 }
8a18b90c 2575
215b30b3 2576 /* Mask out any bits in operand[3] that are not needed. */
2577 emit_insn (gen_andsi3 (op1, operands[3], op0));
8a18b90c 2578
0438d37f 2579 if (CONST_INT_P (op0)
215b30b3 2580 && (const_ok_for_arm (mask << start_bit)
2581 || const_ok_for_arm (~(mask << start_bit))))
2582 {
c5b3a71b 2583 op0 = gen_int_mode (~(mask << start_bit), SImode);
215b30b3 2584 emit_insn (gen_andsi3 (op2, operands[0], op0));
2585 }
2586 else
2587 {
0438d37f 2588 if (CONST_INT_P (op0))
215b30b3 2589 {
2590 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 2591
215b30b3 2592 emit_insn (gen_movsi (tmp, op0));
2593 op0 = tmp;
2594 }
2595
2596 if (start_bit != 0)
2597 emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
a42059fd 2598
215b30b3 2599 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
2600 }
8a18b90c 2601
215b30b3 2602 if (start_bit != 0)
2603 emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
8a18b90c 2604
215b30b3 2605 emit_insn (gen_iorsi3 (subtarget, op1, op2));
2606 }
f082f1c4 2607
215b30b3 2608 if (subtarget != target)
2609 {
2610 /* If TARGET is still a SUBREG, then it must be wider than a word,
2611 so we must be careful only to set the subword we were asked to. */
2612 if (GET_CODE (target) == SUBREG)
2613 emit_move_insn (target, subtarget);
2614 else
2615 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
2616 }
8a18b90c 2617
215b30b3 2618 DONE;
2619 }"
2620)
8a18b90c 2621
8b054d5a 2622(define_insn "insv_zero"
2623 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
809003b3 2624 (match_operand:SI 1 "const_int_M_operand" "M")
2625 (match_operand:SI 2 "const_int_M_operand" "M"))
8b054d5a 2626 (const_int 0))]
2627 "arm_arch_thumb2"
2628 "bfc%?\t%0, %2, %1"
2629 [(set_attr "length" "4")
d952d547 2630 (set_attr "predicable" "yes")
d82e788e 2631 (set_attr "predicable_short_it" "no")
2632 (set_attr "type" "bfm")]
8b054d5a 2633)
2634
2635(define_insn "insv_t2"
2636 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
809003b3 2637 (match_operand:SI 1 "const_int_M_operand" "M")
2638 (match_operand:SI 2 "const_int_M_operand" "M"))
8b054d5a 2639 (match_operand:SI 3 "s_register_operand" "r"))]
2640 "arm_arch_thumb2"
2641 "bfi%?\t%0, %3, %2, %1"
2642 [(set_attr "length" "4")
d952d547 2643 (set_attr "predicable" "yes")
d82e788e 2644 (set_attr "predicable_short_it" "no")
2645 (set_attr "type" "bfm")]
8b054d5a 2646)
2647
215b30b3 2648; constants for op 2 will never be given to these patterns.
a0f94409 2649(define_insn_and_split "*anddi_notdi_di"
9c08d1fa 2650 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 2651 (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "0,r"))
2652 (match_operand:DI 2 "s_register_operand" "r,0")))]
25f905c2 2653 "TARGET_32BIT"
f6ebffac 2654 "#"
e2669ea7 2655 "TARGET_32BIT && reload_completed
2656 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))
2657 && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
a0f94409 2658 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2659 (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2660 "
2661 {
2662 operands[3] = gen_highpart (SImode, operands[0]);
2663 operands[0] = gen_lowpart (SImode, operands[0]);
2664 operands[4] = gen_highpart (SImode, operands[1]);
2665 operands[1] = gen_lowpart (SImode, operands[1]);
2666 operands[5] = gen_highpart (SImode, operands[2]);
2667 operands[2] = gen_lowpart (SImode, operands[2]);
2668 }"
0d66636f 2669 [(set_attr "length" "8")
1b7da4ac 2670 (set_attr "predicable" "yes")
2671 (set_attr "type" "multiple")]
0d66636f 2672)
d952d547 2673
a0f94409 2674(define_insn_and_split "*anddi_notzesidi_di"
9c08d1fa 2675 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2676 (and:DI (not:DI (zero_extend:DI
2677 (match_operand:SI 2 "s_register_operand" "r,r")))
e2348bcb 2678 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 2679 "TARGET_32BIT"
e2348bcb 2680 "@
97499065 2681 bic%?\\t%Q0, %Q1, %2
f6ebffac 2682 #"
a0f94409 2683 ; (not (zero_extend ...)) allows us to just copy the high word from
2684 ; operand1 to operand0.
25f905c2 2685 "TARGET_32BIT
a0f94409 2686 && reload_completed
2687 && operands[0] != operands[1]"
5a097f7d 2688 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
a0f94409 2689 (set (match_dup 3) (match_dup 4))]
2690 "
2691 {
2692 operands[3] = gen_highpart (SImode, operands[0]);
2693 operands[0] = gen_lowpart (SImode, operands[0]);
2694 operands[4] = gen_highpart (SImode, operands[1]);
2695 operands[1] = gen_lowpart (SImode, operands[1]);
2696 }"
0d66636f 2697 [(set_attr "length" "4,8")
d952d547 2698 (set_attr "predicable" "yes")
1b7da4ac 2699 (set_attr "predicable_short_it" "no")
2700 (set_attr "type" "multiple")]
0d66636f 2701)
d952d547 2702
d8cd5fa0 2703(define_insn_and_split "*anddi_notdi_zesidi"
2704 [(set (match_operand:DI 0 "s_register_operand" "=r")
2705 (and:DI (not:DI (match_operand:DI 2 "s_register_operand" "r"))
2706 (zero_extend:DI
2707 (match_operand:SI 1 "s_register_operand" "r"))))]
2708 "TARGET_32BIT"
2709 "#"
2710 "TARGET_32BIT && reload_completed"
2711 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2712 (set (match_dup 3) (const_int 0))]
2713 "
2714 {
2715 operands[3] = gen_highpart (SImode, operands[0]);
2716 operands[0] = gen_lowpart (SImode, operands[0]);
2717 operands[2] = gen_lowpart (SImode, operands[2]);
2718 }"
2719 [(set_attr "length" "8")
2720 (set_attr "predicable" "yes")
2721 (set_attr "predicable_short_it" "no")
2722 (set_attr "type" "multiple")]
2723)
2724
a0f94409 2725(define_insn_and_split "*anddi_notsesidi_di"
9c08d1fa 2726 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2727 (and:DI (not:DI (sign_extend:DI
2728 (match_operand:SI 2 "s_register_operand" "r,r")))
5a097f7d 2729 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2730 "TARGET_32BIT"
f6ebffac 2731 "#"
25f905c2 2732 "TARGET_32BIT && reload_completed"
5a097f7d 2733 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
a0f94409 2734 (set (match_dup 3) (and:SI (not:SI
2735 (ashiftrt:SI (match_dup 2) (const_int 31)))
2736 (match_dup 4)))]
2737 "
2738 {
2739 operands[3] = gen_highpart (SImode, operands[0]);
2740 operands[0] = gen_lowpart (SImode, operands[0]);
2741 operands[4] = gen_highpart (SImode, operands[1]);
2742 operands[1] = gen_lowpart (SImode, operands[1]);
2743 }"
0d66636f 2744 [(set_attr "length" "8")
d952d547 2745 (set_attr "predicable" "yes")
1b7da4ac 2746 (set_attr "predicable_short_it" "no")
2747 (set_attr "type" "multiple")]
0d66636f 2748)
d952d547 2749
8a18b90c 2750(define_insn "andsi_notsi_si"
9c08d1fa 2751 [(set (match_operand:SI 0 "s_register_operand" "=r")
2752 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2753 (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 2754 "TARGET_32BIT"
0d66636f 2755 "bic%?\\t%0, %1, %2"
d952d547 2756 [(set_attr "predicable" "yes")
1b7da4ac 2757 (set_attr "predicable_short_it" "no")
2758 (set_attr "type" "logic_reg")]
0d66636f 2759)
b11cae9e 2760
8a18b90c 2761(define_insn "andsi_not_shiftsi_si"
a2cd141b 2762 [(set (match_operand:SI 0 "s_register_operand" "=r")
2763 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2764 [(match_operand:SI 2 "s_register_operand" "r")
2765 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2766 (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 2767 "TARGET_ARM"
6c4c2133 2768 "bic%?\\t%0, %1, %2%S4"
344495ea 2769 [(set_attr "predicable" "yes")
331beb1a 2770 (set_attr "shift" "2")
a2cd141b 2771 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
d82e788e 2772 (const_string "logic_shift_imm")
2773 (const_string "logic_shift_reg")))]
6c4c2133 2774)
8a18b90c 2775
f7fbdd4a 2776(define_insn "*andsi_notsi_si_compare0"
bd5b4116 2777 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 2778 (compare:CC_NOOV
2779 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2780 (match_operand:SI 1 "s_register_operand" "r"))
2781 (const_int 0)))
9c08d1fa 2782 (set (match_operand:SI 0 "s_register_operand" "=r")
2783 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
25f905c2 2784 "TARGET_32BIT"
2785 "bic%.\\t%0, %1, %2"
d82e788e 2786 [(set_attr "conds" "set")
2787 (set_attr "type" "logics_shift_reg")]
0d66636f 2788)
9c08d1fa 2789
f7fbdd4a 2790(define_insn "*andsi_notsi_si_compare0_scratch"
bd5b4116 2791 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 2792 (compare:CC_NOOV
2793 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2794 (match_operand:SI 1 "s_register_operand" "r"))
2795 (const_int 0)))
9c08d1fa 2796 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 2797 "TARGET_32BIT"
2798 "bic%.\\t%0, %1, %2"
d82e788e 2799 [(set_attr "conds" "set")
2800 (set_attr "type" "logics_shift_reg")]
0d66636f 2801)
9c08d1fa 2802
e2669ea7 2803(define_expand "iordi3"
2804 [(set (match_operand:DI 0 "s_register_operand" "")
2805 (ior:DI (match_operand:DI 1 "s_register_operand" "")
2806 (match_operand:DI 2 "neon_logic_op2" "")))]
2807 "TARGET_32BIT"
2808 ""
2809)
2810
74d6113f 2811(define_insn_and_split "*iordi3_insn"
2812 [(set (match_operand:DI 0 "s_register_operand" "=w,w ,&r,&r,&r,&r,?w,?w")
2813 (ior:DI (match_operand:DI 1 "s_register_operand" "%w,0 ,0 ,r ,0 ,r ,w ,0")
e0fe6977 2814 (match_operand:DI 2 "arm_iordi_operand_neon" "w ,Dl,r ,r ,Df,Df,w ,Dl")))]
74d6113f 2815 "TARGET_32BIT && !TARGET_IWMMXT"
2816 {
2817 switch (which_alternative)
2818 {
2819 case 0: /* fall through */
2820 case 6: return "vorr\t%P0, %P1, %P2";
2821 case 1: /* fall through */
2822 case 7: return neon_output_logic_immediate ("vorr", &operands[2],
2823 DImode, 0, VALID_NEON_QREG_MODE (DImode));
2824 case 2:
2825 case 3:
2826 case 4:
2827 case 5:
2828 return "#";
2829 default: gcc_unreachable ();
2830 }
2831 }
2832 "TARGET_32BIT && !TARGET_IWMMXT && reload_completed
2833 && !(IS_VFP_REGNUM (REGNO (operands[0])))"
2834 [(set (match_dup 3) (match_dup 4))
2835 (set (match_dup 5) (match_dup 6))]
2836 "
2837 {
2838 operands[3] = gen_lowpart (SImode, operands[0]);
2839 operands[5] = gen_highpart (SImode, operands[0]);
2840
2841 operands[4] = simplify_gen_binary (IOR, SImode,
2842 gen_lowpart (SImode, operands[1]),
2843 gen_lowpart (SImode, operands[2]));
2844 operands[6] = simplify_gen_binary (IOR, SImode,
2845 gen_highpart (SImode, operands[1]),
2846 gen_highpart_mode (SImode, DImode, operands[2]));
2847
2848 }"
32093010 2849 [(set_attr "type" "neon_logic,neon_logic,multiple,multiple,multiple,\
2850 multiple,neon_logic,neon_logic")
e0fe6977 2851 (set_attr "length" "*,*,8,8,8,8,*,*")
74d6113f 2852 (set_attr "arch" "neon_for_64bits,neon_for_64bits,*,*,*,*,avoid_neon_for_64bits,avoid_neon_for_64bits")]
cffb2a26 2853)
9c08d1fa 2854
f7fbdd4a 2855(define_insn "*iordi_zesidi_di"
9c08d1fa 2856 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2857 (ior:DI (zero_extend:DI
2858 (match_operand:SI 2 "s_register_operand" "r,r"))
e2348bcb 2859 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 2860 "TARGET_32BIT"
e2348bcb 2861 "@
97499065 2862 orr%?\\t%Q0, %Q1, %2
f6ebffac 2863 #"
0d66636f 2864 [(set_attr "length" "4,8")
d952d547 2865 (set_attr "predicable" "yes")
1b7da4ac 2866 (set_attr "predicable_short_it" "no")
2867 (set_attr "type" "logic_reg,multiple")]
cffb2a26 2868)
9c08d1fa 2869
f7fbdd4a 2870(define_insn "*iordi_sesidi_di"
9c08d1fa 2871 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2872 (ior:DI (sign_extend:DI
2873 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 2874 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2875 "TARGET_32BIT"
f6ebffac 2876 "#"
0d66636f 2877 [(set_attr "length" "8")
1b7da4ac 2878 (set_attr "predicable" "yes")
2879 (set_attr "type" "multiple")]
cffb2a26 2880)
9c08d1fa 2881
87b22bf7 2882(define_expand "iorsi3"
cffb2a26 2883 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2884 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2885 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 2886 "TARGET_EITHER"
87b22bf7 2887 "
0438d37f 2888 if (CONST_INT_P (operands[2]))
87b22bf7 2889 {
25f905c2 2890 if (TARGET_32BIT)
cffb2a26 2891 {
96f57e36 2892 arm_split_constant (IOR, SImode, NULL_RTX,
2893 INTVAL (operands[2]), operands[0], operands[1],
e1ba4a27 2894 optimize && can_create_pseudo_p ());
cffb2a26 2895 DONE;
2896 }
25f905c2 2897 else /* TARGET_THUMB1 */
923ffadb 2898 {
2899 rtx tmp = force_reg (SImode, operands[2]);
2900 if (rtx_equal_p (operands[0], operands[1]))
2901 operands[2] = tmp;
2902 else
2903 {
2904 operands[2] = operands[1];
2905 operands[1] = tmp;
2906 }
2907 }
87b22bf7 2908 }
cffb2a26 2909 "
2910)
87b22bf7 2911
d5d4dc8d 2912(define_insn_and_split "*iorsi3_insn"
29e234a3 2913 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r,r,r")
2914 (ior:SI (match_operand:SI 1 "s_register_operand" "%r,0,r,r,r")
2915 (match_operand:SI 2 "reg_or_int_operand" "I,l,K,r,?n")))]
d5d4dc8d 2916 "TARGET_32BIT"
87b22bf7 2917 "@
29e234a3 2918 orr%?\\t%0, %1, %2
87b22bf7 2919 orr%?\\t%0, %1, %2
d5d4dc8d 2920 orn%?\\t%0, %1, #%B2
65f68e55 2921 orr%?\\t%0, %1, %2
87b22bf7 2922 #"
d5d4dc8d 2923 "TARGET_32BIT
0438d37f 2924 && CONST_INT_P (operands[2])
d5d4dc8d 2925 && !(const_ok_for_arm (INTVAL (operands[2]))
2926 || (TARGET_THUMB2 && const_ok_for_arm (~INTVAL (operands[2]))))"
a0f94409 2927 [(clobber (const_int 0))]
d5d4dc8d 2928{
29e234a3 2929 arm_split_constant (IOR, SImode, curr_insn,
96f57e36 2930 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 2931 DONE;
d5d4dc8d 2932}
29e234a3 2933 [(set_attr "length" "4,4,4,4,16")
2934 (set_attr "arch" "32,t2,t2,32,32")
65f68e55 2935 (set_attr "predicable" "yes")
29e234a3 2936 (set_attr "predicable_short_it" "no,yes,no,no,no")
d82e788e 2937 (set_attr "type" "logic_imm,logic_reg,logic_imm,logic_reg,logic_reg")]
65f68e55 2938)
cffb2a26 2939
a0f94409 2940(define_peephole2
2941 [(match_scratch:SI 3 "r")
372575c7 2942 (set (match_operand:SI 0 "arm_general_register_operand" "")
2943 (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
87b22bf7 2944 (match_operand:SI 2 "const_int_operand" "")))]
90560cad 2945 "TARGET_ARM
a0f94409 2946 && !const_ok_for_arm (INTVAL (operands[2]))
2947 && const_ok_for_arm (~INTVAL (operands[2]))"
2948 [(set (match_dup 3) (match_dup 2))
2949 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2950 ""
215b30b3 2951)
a0f94409 2952
f7fbdd4a 2953(define_insn "*iorsi3_compare0"
bd5b4116 2954 [(set (reg:CC_NOOV CC_REGNUM)
65f68e55 2955 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r,r")
2956 (match_operand:SI 2 "arm_rhs_operand" "I,r"))
9c08d1fa 2957 (const_int 0)))
65f68e55 2958 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 2959 (ior:SI (match_dup 1) (match_dup 2)))]
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")]
cffb2a26 2964)
9c08d1fa 2965
f7fbdd4a 2966(define_insn "*iorsi3_compare0_scratch"
bd5b4116 2967 [(set (reg:CC_NOOV CC_REGNUM)
65f68e55 2968 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r,r")
2969 (match_operand:SI 2 "arm_rhs_operand" "I,r"))
9c08d1fa 2970 (const_int 0)))
65f68e55 2971 (clobber (match_scratch:SI 0 "=r,r"))]
25f905c2 2972 "TARGET_32BIT"
2973 "orr%.\\t%0, %1, %2"
65f68e55 2974 [(set_attr "conds" "set")
d82e788e 2975 (set_attr "type" "logics_imm,logics_reg")]
0d66636f 2976)
9c08d1fa 2977
e2669ea7 2978(define_expand "xordi3"
2979 [(set (match_operand:DI 0 "s_register_operand" "")
2980 (xor:DI (match_operand:DI 1 "s_register_operand" "")
8ee7dc6f 2981 (match_operand:DI 2 "arm_xordi_operand" "")))]
e2669ea7 2982 "TARGET_32BIT"
2983 ""
2984)
2985
8ee7dc6f 2986(define_insn_and_split "*xordi3_insn"
2987 [(set (match_operand:DI 0 "s_register_operand" "=w,&r,&r,&r,&r,?w")
205c3b0a 2988 (xor:DI (match_operand:DI 1 "s_register_operand" "%w ,0,r ,0 ,r ,w")
8ee7dc6f 2989 (match_operand:DI 2 "arm_xordi_operand" "w ,r ,r ,Dg,Dg,w")))]
2990 "TARGET_32BIT && !TARGET_IWMMXT"
2991{
2992 switch (which_alternative)
2993 {
2994 case 1:
2995 case 2:
2996 case 3:
2997 case 4: /* fall through */
2998 return "#";
2999 case 0: /* fall through */
3000 case 5: return "veor\t%P0, %P1, %P2";
3001 default: gcc_unreachable ();
3002 }
3003}
3004 "TARGET_32BIT && !TARGET_IWMMXT && reload_completed
3005 && !(IS_VFP_REGNUM (REGNO (operands[0])))"
3006 [(set (match_dup 3) (match_dup 4))
3007 (set (match_dup 5) (match_dup 6))]
3008 "
3009 {
3010 operands[3] = gen_lowpart (SImode, operands[0]);
3011 operands[5] = gen_highpart (SImode, operands[0]);
3012
3013 operands[4] = simplify_gen_binary (XOR, SImode,
3014 gen_lowpart (SImode, operands[1]),
3015 gen_lowpart (SImode, operands[2]));
3016 operands[6] = simplify_gen_binary (XOR, SImode,
3017 gen_highpart (SImode, operands[1]),
3018 gen_highpart_mode (SImode, DImode, operands[2]));
3019
3020 }"
3021 [(set_attr "length" "*,8,8,8,8,*")
32093010 3022 (set_attr "type" "neon_logic,multiple,multiple,multiple,multiple,neon_logic")
8ee7dc6f 3023 (set_attr "arch" "neon_for_64bits,*,*,*,*,avoid_neon_for_64bits")]
cffb2a26 3024)
9c08d1fa 3025
f7fbdd4a 3026(define_insn "*xordi_zesidi_di"
9c08d1fa 3027 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3028 (xor:DI (zero_extend:DI
3029 (match_operand:SI 2 "s_register_operand" "r,r"))
e2348bcb 3030 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 3031 "TARGET_32BIT"
e2348bcb 3032 "@
97499065 3033 eor%?\\t%Q0, %Q1, %2
f6ebffac 3034 #"
0d66636f 3035 [(set_attr "length" "4,8")
d952d547 3036 (set_attr "predicable" "yes")
1b7da4ac 3037 (set_attr "predicable_short_it" "no")
3038 (set_attr "type" "logic_reg")]
cffb2a26 3039)
9c08d1fa 3040
f7fbdd4a 3041(define_insn "*xordi_sesidi_di"
9c08d1fa 3042 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3043 (xor:DI (sign_extend:DI
3044 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 3045 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 3046 "TARGET_32BIT"
f6ebffac 3047 "#"
0d66636f 3048 [(set_attr "length" "8")
1b7da4ac 3049 (set_attr "predicable" "yes")
3050 (set_attr "type" "multiple")]
cffb2a26 3051)
9c08d1fa 3052
cffb2a26 3053(define_expand "xorsi3"
3054 [(set (match_operand:SI 0 "s_register_operand" "")
3055 (xor:SI (match_operand:SI 1 "s_register_operand" "")
923ffadb 3056 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 3057 "TARGET_EITHER"
0438d37f 3058 "if (CONST_INT_P (operands[2]))
923ffadb 3059 {
3060 if (TARGET_32BIT)
3061 {
3062 arm_split_constant (XOR, SImode, NULL_RTX,
3063 INTVAL (operands[2]), operands[0], operands[1],
3064 optimize && can_create_pseudo_p ());
3065 DONE;
3066 }
3067 else /* TARGET_THUMB1 */
3068 {
3069 rtx tmp = force_reg (SImode, operands[2]);
3070 if (rtx_equal_p (operands[0], operands[1]))
3071 operands[2] = tmp;
3072 else
3073 {
3074 operands[2] = operands[1];
3075 operands[1] = tmp;
3076 }
3077 }
3078 }"
cffb2a26 3079)
3080
5dcb35d9 3081(define_insn_and_split "*arm_xorsi3"
29e234a3 3082 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r,r")
3083 (xor:SI (match_operand:SI 1 "s_register_operand" "%r,0,r,r")
3084 (match_operand:SI 2 "reg_or_int_operand" "I,l,r,?n")))]
25f905c2 3085 "TARGET_32BIT"
5dcb35d9 3086 "@
29e234a3 3087 eor%?\\t%0, %1, %2
65f68e55 3088 eor%?\\t%0, %1, %2
5dcb35d9 3089 eor%?\\t%0, %1, %2
3090 #"
3091 "TARGET_32BIT
0438d37f 3092 && CONST_INT_P (operands[2])
5dcb35d9 3093 && !const_ok_for_arm (INTVAL (operands[2]))"
3094 [(clobber (const_int 0))]
3095{
3096 arm_split_constant (XOR, SImode, curr_insn,
3097 INTVAL (operands[2]), operands[0], operands[1], 0);
3098 DONE;
3099}
29e234a3 3100 [(set_attr "length" "4,4,4,16")
65f68e55 3101 (set_attr "predicable" "yes")
29e234a3 3102 (set_attr "predicable_short_it" "no,yes,no,no")
1b7da4ac 3103 (set_attr "type" "logic_imm,logic_reg,logic_reg,multiple")]
cffb2a26 3104)
3105
f7fbdd4a 3106(define_insn "*xorsi3_compare0"
bd5b4116 3107 [(set (reg:CC_NOOV CC_REGNUM)
65f68e55 3108 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r,r")
3109 (match_operand:SI 2 "arm_rhs_operand" "I,r"))
9c08d1fa 3110 (const_int 0)))
65f68e55 3111 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 3112 (xor:SI (match_dup 1) (match_dup 2)))]
25f905c2 3113 "TARGET_32BIT"
3114 "eor%.\\t%0, %1, %2"
65f68e55 3115 [(set_attr "conds" "set")
d82e788e 3116 (set_attr "type" "logics_imm,logics_reg")]
0d66636f 3117)
9c08d1fa 3118
f7fbdd4a 3119(define_insn "*xorsi3_compare0_scratch"
bd5b4116 3120 [(set (reg:CC_NOOV CC_REGNUM)
65f68e55 3121 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r,r")
3122 (match_operand:SI 1 "arm_rhs_operand" "I,r"))
9c08d1fa 3123 (const_int 0)))]
25f905c2 3124 "TARGET_32BIT"
40dbec34 3125 "teq%?\\t%0, %1"
65f68e55 3126 [(set_attr "conds" "set")
d82e788e 3127 (set_attr "type" "logics_imm,logics_reg")]
cffb2a26 3128)
9c08d1fa 3129
215b30b3 3130; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
3131; (NOT D) we can sometimes merge the final NOT into one of the following
3132; insns.
9c08d1fa 3133
3134(define_split
a058e94a 3135 [(set (match_operand:SI 0 "s_register_operand" "")
3136 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
3137 (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
3138 (match_operand:SI 3 "arm_rhs_operand" "")))
3139 (clobber (match_operand:SI 4 "s_register_operand" ""))]
25f905c2 3140 "TARGET_32BIT"
9c08d1fa 3141 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
3142 (not:SI (match_dup 3))))
3143 (set (match_dup 0) (not:SI (match_dup 4)))]
3144 ""
3145)
3146
ba6a3b2f 3147(define_insn_and_split "*andsi_iorsi3_notsi"
9c08d1fa 3148 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
e5fea38e 3149 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "%0,r,r")
9c08d1fa 3150 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
3151 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
25f905c2 3152 "TARGET_32BIT"
ba6a3b2f 3153 "#" ; "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
3154 "&& reload_completed"
3155 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
3156 (set (match_dup 0) (and:SI (not:SI (match_dup 3)) (match_dup 0)))]
3157 ""
0d66636f 3158 [(set_attr "length" "8")
25f905c2 3159 (set_attr "ce_count" "2")
d952d547 3160 (set_attr "predicable" "yes")
1b7da4ac 3161 (set_attr "predicable_short_it" "no")
3162 (set_attr "type" "multiple")]
cffb2a26 3163)
9c08d1fa 3164
25f905c2 3165; ??? Are these four splitters still beneficial when the Thumb-2 bitfield
3166; insns are available?
d7863cfe 3167(define_split
3168 [(set (match_operand:SI 0 "s_register_operand" "")
3169 (match_operator:SI 1 "logical_binary_operator"
3170 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
3171 (match_operand:SI 3 "const_int_operand" "")
3172 (match_operand:SI 4 "const_int_operand" ""))
3173 (match_operator:SI 9 "logical_binary_operator"
3174 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3175 (match_operand:SI 6 "const_int_operand" ""))
3176 (match_operand:SI 7 "s_register_operand" "")])]))
3177 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3178 "TARGET_32BIT
d7863cfe 3179 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3180 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3181 [(set (match_dup 8)
3182 (match_op_dup 1
3183 [(ashift:SI (match_dup 2) (match_dup 4))
3184 (match_dup 5)]))
3185 (set (match_dup 0)
3186 (match_op_dup 1
3187 [(lshiftrt:SI (match_dup 8) (match_dup 6))
3188 (match_dup 7)]))]
3189 "
3190 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3191")
3192
3193(define_split
3194 [(set (match_operand:SI 0 "s_register_operand" "")
3195 (match_operator:SI 1 "logical_binary_operator"
3196 [(match_operator:SI 9 "logical_binary_operator"
3197 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3198 (match_operand:SI 6 "const_int_operand" ""))
3199 (match_operand:SI 7 "s_register_operand" "")])
3200 (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
3201 (match_operand:SI 3 "const_int_operand" "")
3202 (match_operand:SI 4 "const_int_operand" ""))]))
3203 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3204 "TARGET_32BIT
d7863cfe 3205 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3206 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3207 [(set (match_dup 8)
3208 (match_op_dup 1
3209 [(ashift:SI (match_dup 2) (match_dup 4))
3210 (match_dup 5)]))
3211 (set (match_dup 0)
3212 (match_op_dup 1
3213 [(lshiftrt:SI (match_dup 8) (match_dup 6))
3214 (match_dup 7)]))]
3215 "
3216 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3217")
3218
3219(define_split
3220 [(set (match_operand:SI 0 "s_register_operand" "")
3221 (match_operator:SI 1 "logical_binary_operator"
3222 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
3223 (match_operand:SI 3 "const_int_operand" "")
3224 (match_operand:SI 4 "const_int_operand" ""))
3225 (match_operator:SI 9 "logical_binary_operator"
3226 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3227 (match_operand:SI 6 "const_int_operand" ""))
3228 (match_operand:SI 7 "s_register_operand" "")])]))
3229 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3230 "TARGET_32BIT
d7863cfe 3231 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3232 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3233 [(set (match_dup 8)
3234 (match_op_dup 1
3235 [(ashift:SI (match_dup 2) (match_dup 4))
3236 (match_dup 5)]))
3237 (set (match_dup 0)
3238 (match_op_dup 1
3239 [(ashiftrt:SI (match_dup 8) (match_dup 6))
3240 (match_dup 7)]))]
3241 "
3242 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3243")
3244
3245(define_split
3246 [(set (match_operand:SI 0 "s_register_operand" "")
3247 (match_operator:SI 1 "logical_binary_operator"
3248 [(match_operator:SI 9 "logical_binary_operator"
3249 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3250 (match_operand:SI 6 "const_int_operand" ""))
3251 (match_operand:SI 7 "s_register_operand" "")])
3252 (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
3253 (match_operand:SI 3 "const_int_operand" "")
3254 (match_operand:SI 4 "const_int_operand" ""))]))
3255 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3256 "TARGET_32BIT
d7863cfe 3257 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3258 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3259 [(set (match_dup 8)
3260 (match_op_dup 1
3261 [(ashift:SI (match_dup 2) (match_dup 4))
3262 (match_dup 5)]))
3263 (set (match_dup 0)
3264 (match_op_dup 1
3265 [(ashiftrt:SI (match_dup 8) (match_dup 6))
3266 (match_dup 7)]))]
3267 "
3268 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3269")
9c08d1fa 3270\f
3271
3272;; Minimum and maximum insns
3273
8b9dc177 3274(define_expand "smaxsi3"
3275 [(parallel [
3276 (set (match_operand:SI 0 "s_register_operand" "")
3277 (smax:SI (match_operand:SI 1 "s_register_operand" "")
3278 (match_operand:SI 2 "arm_rhs_operand" "")))
3279 (clobber (reg:CC CC_REGNUM))])]
25f905c2 3280 "TARGET_32BIT"
8b9dc177 3281 "
8774928b 3282 if (operands[2] == const0_rtx || operands[2] == constm1_rtx)
8b9dc177 3283 {
3284 /* No need for a clobber of the condition code register here. */
3285 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3286 gen_rtx_SMAX (SImode, operands[1],
3287 operands[2])));
3288 DONE;
3289 }
3290")
3291
3292(define_insn "*smax_0"
3293 [(set (match_operand:SI 0 "s_register_operand" "=r")
3294 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3295 (const_int 0)))]
25f905c2 3296 "TARGET_32BIT"
8b9dc177 3297 "bic%?\\t%0, %1, %1, asr #31"
d952d547 3298 [(set_attr "predicable" "yes")
1b7da4ac 3299 (set_attr "predicable_short_it" "no")
3300 (set_attr "type" "logic_shift_reg")]
8b9dc177 3301)
3302
8774928b 3303(define_insn "*smax_m1"
3304 [(set (match_operand:SI 0 "s_register_operand" "=r")
3305 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3306 (const_int -1)))]
25f905c2 3307 "TARGET_32BIT"
8774928b 3308 "orr%?\\t%0, %1, %1, asr #31"
d952d547 3309 [(set_attr "predicable" "yes")
1b7da4ac 3310 (set_attr "predicable_short_it" "no")
3311 (set_attr "type" "logic_shift_reg")]
8774928b 3312)
3313
3dc953f2 3314(define_insn_and_split "*arm_smax_insn"
8b9dc177 3315 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3316 (smax:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3317 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
bd5b4116 3318 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3319 "TARGET_ARM"
3dc953f2 3320 "#"
3321 ; cmp\\t%1, %2\;movlt\\t%0, %2
3322 ; cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
3323 "TARGET_ARM"
3324 [(set (reg:CC CC_REGNUM)
3325 (compare:CC (match_dup 1) (match_dup 2)))
3326 (set (match_dup 0)
3327 (if_then_else:SI (ge:SI (reg:CC CC_REGNUM) (const_int 0))
3328 (match_dup 1)
3329 (match_dup 2)))]
3330 ""
cffb2a26 3331 [(set_attr "conds" "clob")
1b7da4ac 3332 (set_attr "length" "8,12")
3333 (set_attr "type" "multiple")]
cffb2a26 3334)
9c08d1fa 3335
8b9dc177 3336(define_expand "sminsi3"
3337 [(parallel [
3338 (set (match_operand:SI 0 "s_register_operand" "")
3339 (smin:SI (match_operand:SI 1 "s_register_operand" "")
3340 (match_operand:SI 2 "arm_rhs_operand" "")))
3341 (clobber (reg:CC CC_REGNUM))])]
25f905c2 3342 "TARGET_32BIT"
8b9dc177 3343 "
3344 if (operands[2] == const0_rtx)
3345 {
3346 /* No need for a clobber of the condition code register here. */
3347 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3348 gen_rtx_SMIN (SImode, operands[1],
3349 operands[2])));
3350 DONE;
3351 }
3352")
3353
3354(define_insn "*smin_0"
3355 [(set (match_operand:SI 0 "s_register_operand" "=r")
3356 (smin:SI (match_operand:SI 1 "s_register_operand" "r")
3357 (const_int 0)))]
25f905c2 3358 "TARGET_32BIT"
8b9dc177 3359 "and%?\\t%0, %1, %1, asr #31"
d952d547 3360 [(set_attr "predicable" "yes")
1b7da4ac 3361 (set_attr "predicable_short_it" "no")
3362 (set_attr "type" "logic_shift_reg")]
8b9dc177 3363)
3364
3dc953f2 3365(define_insn_and_split "*arm_smin_insn"
8b9dc177 3366 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3367 (smin:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3368 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
bd5b4116 3369 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3370 "TARGET_ARM"
3dc953f2 3371 "#"
3372 ; cmp\\t%1, %2\;movge\\t%0, %2
3373 ; cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
3374 "TARGET_ARM"
3375 [(set (reg:CC CC_REGNUM)
3376 (compare:CC (match_dup 1) (match_dup 2)))
3377 (set (match_dup 0)
3378 (if_then_else:SI (lt:SI (reg:CC CC_REGNUM) (const_int 0))
3379 (match_dup 1)
3380 (match_dup 2)))]
3381 ""
0d66636f 3382 [(set_attr "conds" "clob")
1b7da4ac 3383 (set_attr "length" "8,12")
3384 (set_attr "type" "multiple,multiple")]
0d66636f 3385)
9c08d1fa 3386
25f905c2 3387(define_expand "umaxsi3"
3388 [(parallel [
3389 (set (match_operand:SI 0 "s_register_operand" "")
3390 (umax:SI (match_operand:SI 1 "s_register_operand" "")
3391 (match_operand:SI 2 "arm_rhs_operand" "")))
3392 (clobber (reg:CC CC_REGNUM))])]
3393 "TARGET_32BIT"
3394 ""
3395)
3396
3dc953f2 3397(define_insn_and_split "*arm_umaxsi3"
9c08d1fa 3398 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3399 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3400 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 3401 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3402 "TARGET_ARM"
3dc953f2 3403 "#"
3404 ; cmp\\t%1, %2\;movcc\\t%0, %2
3405 ; cmp\\t%1, %2\;movcs\\t%0, %1
3406 ; cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
3407 "TARGET_ARM"
3408 [(set (reg:CC CC_REGNUM)
3409 (compare:CC (match_dup 1) (match_dup 2)))
3410 (set (match_dup 0)
3411 (if_then_else:SI (geu:SI (reg:CC CC_REGNUM) (const_int 0))
3412 (match_dup 1)
3413 (match_dup 2)))]
3414 ""
0d66636f 3415 [(set_attr "conds" "clob")
1b7da4ac 3416 (set_attr "length" "8,8,12")
3417 (set_attr "type" "store1")]
0d66636f 3418)
9c08d1fa 3419
25f905c2 3420(define_expand "uminsi3"
3421 [(parallel [
3422 (set (match_operand:SI 0 "s_register_operand" "")
3423 (umin:SI (match_operand:SI 1 "s_register_operand" "")
3424 (match_operand:SI 2 "arm_rhs_operand" "")))
3425 (clobber (reg:CC CC_REGNUM))])]
3426 "TARGET_32BIT"
3427 ""
3428)
3429
3dc953f2 3430(define_insn_and_split "*arm_uminsi3"
9c08d1fa 3431 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3432 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3433 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 3434 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3435 "TARGET_ARM"
3dc953f2 3436 "#"
3437 ; cmp\\t%1, %2\;movcs\\t%0, %2
3438 ; cmp\\t%1, %2\;movcc\\t%0, %1
3439 ; cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
3440 "TARGET_ARM"
3441 [(set (reg:CC CC_REGNUM)
3442 (compare:CC (match_dup 1) (match_dup 2)))
3443 (set (match_dup 0)
3444 (if_then_else:SI (ltu:SI (reg:CC CC_REGNUM) (const_int 0))
3445 (match_dup 1)
3446 (match_dup 2)))]
3447 ""
0d66636f 3448 [(set_attr "conds" "clob")
1b7da4ac 3449 (set_attr "length" "8,8,12")
3450 (set_attr "type" "store1")]
0d66636f 3451)
9c08d1fa 3452
8a18b90c 3453(define_insn "*store_minmaxsi"
9c08d1fa 3454 [(set (match_operand:SI 0 "memory_operand" "=m")
3455 (match_operator:SI 3 "minmax_operator"
3456 [(match_operand:SI 1 "s_register_operand" "r")
3457 (match_operand:SI 2 "s_register_operand" "r")]))
bd5b4116 3458 (clobber (reg:CC CC_REGNUM))]
b207d152 3459 "TARGET_32BIT && optimize_function_for_size_p (cfun) && !arm_restrict_it"
9c08d1fa 3460 "*
dc55b8a9 3461 operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
3462 operands[1], operands[2]);
e2348bcb 3463 output_asm_insn (\"cmp\\t%1, %2\", operands);
25f905c2 3464 if (TARGET_THUMB2)
3465 output_asm_insn (\"ite\t%d3\", operands);
e2348bcb 3466 output_asm_insn (\"str%d3\\t%1, %0\", operands);
3467 output_asm_insn (\"str%D3\\t%2, %0\", operands);
3468 return \"\";
0d66636f 3469 "
3470 [(set_attr "conds" "clob")
25f905c2 3471 (set (attr "length")
3472 (if_then_else (eq_attr "is_thumb" "yes")
3473 (const_int 14)
3474 (const_int 12)))
0d66636f 3475 (set_attr "type" "store1")]
3476)
9c08d1fa 3477
8a18b90c 3478; Reject the frame pointer in operand[1], since reloading this after
3479; it has been eliminated can cause carnage.
f7fbdd4a 3480(define_insn "*minmax_arithsi"
9c08d1fa 3481 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3482 (match_operator:SI 4 "shiftable_operator"
3483 [(match_operator:SI 5 "minmax_operator"
3484 [(match_operand:SI 2 "s_register_operand" "r,r")
3485 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
3486 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 3487 (clobber (reg:CC CC_REGNUM))]
7c36fe71 3488 "TARGET_32BIT && !arm_eliminable_register (operands[1]) && !arm_restrict_it"
9c08d1fa 3489 "*
0d66636f 3490 {
3491 enum rtx_code code = GET_CODE (operands[4]);
25f905c2 3492 bool need_else;
3493
3494 if (which_alternative != 0 || operands[3] != const0_rtx
ca0fc5a2 3495 || (code != PLUS && code != IOR && code != XOR))
25f905c2 3496 need_else = true;
3497 else
3498 need_else = false;
0d66636f 3499
dc55b8a9 3500 operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
3501 operands[2], operands[3]);
0d66636f 3502 output_asm_insn (\"cmp\\t%2, %3\", operands);
25f905c2 3503 if (TARGET_THUMB2)
3504 {
3505 if (need_else)
3506 output_asm_insn (\"ite\\t%d5\", operands);
3507 else
3508 output_asm_insn (\"it\\t%d5\", operands);
3509 }
0d66636f 3510 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
25f905c2 3511 if (need_else)
0d66636f 3512 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
3513 return \"\";
215b30b3 3514 }"
0d66636f 3515 [(set_attr "conds" "clob")
25f905c2 3516 (set (attr "length")
3517 (if_then_else (eq_attr "is_thumb" "yes")
3518 (const_int 14)
1b7da4ac 3519 (const_int 12)))
3520 (set_attr "type" "multiple")]
0d66636f 3521)
9c08d1fa 3522
4164bca1 3523; Reject the frame pointer in operand[1], since reloading this after
3524; it has been eliminated can cause carnage.
3525(define_insn_and_split "*minmax_arithsi_non_canon"
7c36fe71 3526 [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts")
4164bca1 3527 (minus:SI
7c36fe71 3528 (match_operand:SI 1 "s_register_operand" "0,?Ts")
4164bca1 3529 (match_operator:SI 4 "minmax_operator"
7c36fe71 3530 [(match_operand:SI 2 "s_register_operand" "Ts,Ts")
3531 (match_operand:SI 3 "arm_rhs_operand" "TsI,TsI")])))
4164bca1 3532 (clobber (reg:CC CC_REGNUM))]
7c36fe71 3533 "TARGET_32BIT && !arm_eliminable_register (operands[1])
3534 && !(arm_restrict_it && CONST_INT_P (operands[3]))"
4164bca1 3535 "#"
3536 "TARGET_32BIT && !arm_eliminable_register (operands[1]) && reload_completed"
3537 [(set (reg:CC CC_REGNUM)
3538 (compare:CC (match_dup 2) (match_dup 3)))
3539
3540 (cond_exec (match_op_dup 4 [(reg:CC CC_REGNUM) (const_int 0)])
3541 (set (match_dup 0)
3542 (minus:SI (match_dup 1)
3543 (match_dup 2))))
3544 (cond_exec (match_op_dup 5 [(reg:CC CC_REGNUM) (const_int 0)])
3545 (set (match_dup 0)
36ee0cde 3546 (match_dup 6)))]
4164bca1 3547 {
3754d046 3548 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
4164bca1 3549 operands[2], operands[3]);
3550 enum rtx_code rc = minmax_code (operands[4]);
3551 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode,
3552 operands[2], operands[3]);
3553
3554 if (mode == CCFPmode || mode == CCFPEmode)
3555 rc = reverse_condition_maybe_unordered (rc);
3556 else
3557 rc = reverse_condition (rc);
3558 operands[5] = gen_rtx_fmt_ee (rc, SImode, operands[2], operands[3]);
36ee0cde 3559 if (CONST_INT_P (operands[3]))
3560 operands[6] = plus_constant (SImode, operands[1], -INTVAL (operands[3]));
3561 else
3562 operands[6] = gen_rtx_MINUS (SImode, operands[1], operands[3]);
4164bca1 3563 }
3564 [(set_attr "conds" "clob")
3565 (set (attr "length")
3566 (if_then_else (eq_attr "is_thumb" "yes")
3567 (const_int 14)
1b7da4ac 3568 (const_int 12)))
3569 (set_attr "type" "multiple")]
4164bca1 3570)
3571
b49e3742 3572(define_code_iterator SAT [smin smax])
3573(define_code_iterator SATrev [smin smax])
3574(define_code_attr SATlo [(smin "1") (smax "2")])
3575(define_code_attr SAThi [(smin "2") (smax "1")])
3576
3577(define_insn "*satsi_<SAT:code>"
3578 [(set (match_operand:SI 0 "s_register_operand" "=r")
3579 (SAT:SI (SATrev:SI (match_operand:SI 3 "s_register_operand" "r")
3580 (match_operand:SI 1 "const_int_operand" "i"))
3581 (match_operand:SI 2 "const_int_operand" "i")))]
3582 "TARGET_32BIT && arm_arch6 && <SAT:CODE> != <SATrev:CODE>
3583 && arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>], NULL, NULL)"
3584{
3585 int mask;
3586 bool signed_sat;
3587 if (!arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>],
3588 &mask, &signed_sat))
3589 gcc_unreachable ();
3590
3591 operands[1] = GEN_INT (mask);
3592 if (signed_sat)
3593 return "ssat%?\t%0, %1, %3";
3594 else
3595 return "usat%?\t%0, %1, %3";
3596}
7c36fe71 3597 [(set_attr "predicable" "yes")
1b7da4ac 3598 (set_attr "predicable_short_it" "no")
3599 (set_attr "type" "alus_imm")]
bebe9bbb 3600)
b49e3742 3601
3602(define_insn "*satsi_<SAT:code>_shift"
3603 [(set (match_operand:SI 0 "s_register_operand" "=r")
3604 (SAT:SI (SATrev:SI (match_operator:SI 3 "sat_shift_operator"
3605 [(match_operand:SI 4 "s_register_operand" "r")
3606 (match_operand:SI 5 "const_int_operand" "i")])
3607 (match_operand:SI 1 "const_int_operand" "i"))
3608 (match_operand:SI 2 "const_int_operand" "i")))]
3609 "TARGET_32BIT && arm_arch6 && <SAT:CODE> != <SATrev:CODE>
3610 && arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>], NULL, NULL)"
3611{
3612 int mask;
3613 bool signed_sat;
3614 if (!arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>],
3615 &mask, &signed_sat))
3616 gcc_unreachable ();
3617
3618 operands[1] = GEN_INT (mask);
3619 if (signed_sat)
3620 return "ssat%?\t%0, %1, %4%S3";
3621 else
3622 return "usat%?\t%0, %1, %4%S3";
3623}
3624 [(set_attr "predicable" "yes")
7c36fe71 3625 (set_attr "predicable_short_it" "no")
b49e3742 3626 (set_attr "shift" "3")
d82e788e 3627 (set_attr "type" "logic_shift_reg")])
b11cae9e 3628\f
3629;; Shift and rotation insns
3630
a2cd141b 3631(define_expand "ashldi3"
3632 [(set (match_operand:DI 0 "s_register_operand" "")
3633 (ashift:DI (match_operand:DI 1 "s_register_operand" "")
aa06c51c 3634 (match_operand:SI 2 "general_operand" "")))]
25f905c2 3635 "TARGET_32BIT"
a2cd141b 3636 "
aa06c51c 3637 if (TARGET_NEON)
3638 {
3639 /* Delay the decision whether to use NEON or core-regs until
3640 register allocation. */
3641 emit_insn (gen_ashldi3_neon (operands[0], operands[1], operands[2]));
3642 DONE;
3643 }
3644 else
3645 {
3646 /* Only the NEON case can handle in-memory shift counts. */
3647 if (!reg_or_int_operand (operands[2], SImode))
3648 operands[2] = force_reg (SImode, operands[2]);
3649 }
3650
b805622c 3651 if (!CONST_INT_P (operands[2]) && TARGET_REALLY_IWMMXT)
ffcc986d 3652 ; /* No special preparation statements; expand pattern as above. */
3653 else
a2cd141b 3654 {
ffcc986d 3655 rtx scratch1, scratch2;
3656
3657 if (CONST_INT_P (operands[2])
3658 && (HOST_WIDE_INT) INTVAL (operands[2]) == 1)
a2cd141b 3659 {
3660 emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
3661 DONE;
3662 }
ffcc986d 3663
3664 /* Ideally we should use iwmmxt here if we could know that operands[1]
3665 ends up already living in an iwmmxt register. Otherwise it's
3666 cheaper to have the alternate code being generated than moving
3667 values to iwmmxt regs and back. */
3668
3669 /* If we're optimizing for size, we prefer the libgcc calls. */
3670 if (optimize_function_for_size_p (cfun))
3671 FAIL;
3672
3673 /* Expand operation using core-registers.
3674 'FAIL' would achieve the same thing, but this is a bit smarter. */
3675 scratch1 = gen_reg_rtx (SImode);
3676 scratch2 = gen_reg_rtx (SImode);
3677 arm_emit_coreregs_64bit_shift (ASHIFT, operands[0], operands[1],
3678 operands[2], scratch1, scratch2);
3679 DONE;
a2cd141b 3680 }
a2cd141b 3681 "
3682)
3683
2837e3fb 3684(define_insn "arm_ashldi3_1bit"
50ad1bf9 3685 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 3686 (ashift:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 3687 (const_int 1)))
3688 (clobber (reg:CC CC_REGNUM))]
25f905c2 3689 "TARGET_32BIT"
2837e3fb 3690 "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
a2cd141b 3691 [(set_attr "conds" "clob")
1b7da4ac 3692 (set_attr "length" "8")
3693 (set_attr "type" "multiple")]
a2cd141b 3694)
3695
87b22bf7 3696(define_expand "ashlsi3"
cffb2a26 3697 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3698 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
3699 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3700 "TARGET_EITHER"
87b22bf7 3701 "
0438d37f 3702 if (CONST_INT_P (operands[2])
87b22bf7 3703 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3704 {
3705 emit_insn (gen_movsi (operands[0], const0_rtx));
3706 DONE;
3707 }
cffb2a26 3708 "
3709)
3710
a2cd141b 3711(define_expand "ashrdi3"
3712 [(set (match_operand:DI 0 "s_register_operand" "")
3713 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
3714 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3715 "TARGET_32BIT"
a2cd141b 3716 "
aa06c51c 3717 if (TARGET_NEON)
3718 {
3719 /* Delay the decision whether to use NEON or core-regs until
3720 register allocation. */
3721 emit_insn (gen_ashrdi3_neon (operands[0], operands[1], operands[2]));
3722 DONE;
3723 }
3724
b805622c 3725 if (!CONST_INT_P (operands[2]) && TARGET_REALLY_IWMMXT)
ffcc986d 3726 ; /* No special preparation statements; expand pattern as above. */
3727 else
a2cd141b 3728 {
ffcc986d 3729 rtx scratch1, scratch2;
3730
3731 if (CONST_INT_P (operands[2])
3732 && (HOST_WIDE_INT) INTVAL (operands[2]) == 1)
a2cd141b 3733 {
3734 emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
3735 DONE;
3736 }
ffcc986d 3737
3738 /* Ideally we should use iwmmxt here if we could know that operands[1]
3739 ends up already living in an iwmmxt register. Otherwise it's
3740 cheaper to have the alternate code being generated than moving
3741 values to iwmmxt regs and back. */
3742
3743 /* If we're optimizing for size, we prefer the libgcc calls. */
3744 if (optimize_function_for_size_p (cfun))
3745 FAIL;
3746
3747 /* Expand operation using core-registers.
3748 'FAIL' would achieve the same thing, but this is a bit smarter. */
3749 scratch1 = gen_reg_rtx (SImode);
3750 scratch2 = gen_reg_rtx (SImode);
3751 arm_emit_coreregs_64bit_shift (ASHIFTRT, operands[0], operands[1],
3752 operands[2], scratch1, scratch2);
3753 DONE;
a2cd141b 3754 }
a2cd141b 3755 "
3756)
3757
2837e3fb 3758(define_insn "arm_ashrdi3_1bit"
50ad1bf9 3759 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 3760 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 3761 (const_int 1)))
3762 (clobber (reg:CC CC_REGNUM))]
25f905c2 3763 "TARGET_32BIT"
2837e3fb 3764 "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
a2cd141b 3765 [(set_attr "conds" "clob")
1b7da4ac 3766 (set_attr "length" "8")
3767 (set_attr "type" "multiple")]
a2cd141b 3768)
3769
87b22bf7 3770(define_expand "ashrsi3"
cffb2a26 3771 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3772 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
3773 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3774 "TARGET_EITHER"
87b22bf7 3775 "
0438d37f 3776 if (CONST_INT_P (operands[2])
87b22bf7 3777 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3778 operands[2] = GEN_INT (31);
cffb2a26 3779 "
3780)
3781
a2cd141b 3782(define_expand "lshrdi3"
3783 [(set (match_operand:DI 0 "s_register_operand" "")
3784 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
3785 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3786 "TARGET_32BIT"
a2cd141b 3787 "
aa06c51c 3788 if (TARGET_NEON)
3789 {
3790 /* Delay the decision whether to use NEON or core-regs until
3791 register allocation. */
3792 emit_insn (gen_lshrdi3_neon (operands[0], operands[1], operands[2]));
3793 DONE;
3794 }
3795
b805622c 3796 if (!CONST_INT_P (operands[2]) && TARGET_REALLY_IWMMXT)
ffcc986d 3797 ; /* No special preparation statements; expand pattern as above. */
3798 else
a2cd141b 3799 {
ffcc986d 3800 rtx scratch1, scratch2;
3801
3802 if (CONST_INT_P (operands[2])
3803 && (HOST_WIDE_INT) INTVAL (operands[2]) == 1)
a2cd141b 3804 {
3805 emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
3806 DONE;
3807 }
ffcc986d 3808
3809 /* Ideally we should use iwmmxt here if we could know that operands[1]
3810 ends up already living in an iwmmxt register. Otherwise it's
3811 cheaper to have the alternate code being generated than moving
3812 values to iwmmxt regs and back. */
3813
3814 /* If we're optimizing for size, we prefer the libgcc calls. */
3815 if (optimize_function_for_size_p (cfun))
3816 FAIL;
3817
3818 /* Expand operation using core-registers.
3819 'FAIL' would achieve the same thing, but this is a bit smarter. */
3820 scratch1 = gen_reg_rtx (SImode);
3821 scratch2 = gen_reg_rtx (SImode);
3822 arm_emit_coreregs_64bit_shift (LSHIFTRT, operands[0], operands[1],
3823 operands[2], scratch1, scratch2);
3824 DONE;
a2cd141b 3825 }
a2cd141b 3826 "
3827)
3828
2837e3fb 3829(define_insn "arm_lshrdi3_1bit"
50ad1bf9 3830 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 3831 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 3832 (const_int 1)))
3833 (clobber (reg:CC CC_REGNUM))]
25f905c2 3834 "TARGET_32BIT"
2837e3fb 3835 "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
a2cd141b 3836 [(set_attr "conds" "clob")
1b7da4ac 3837 (set_attr "length" "8")
3838 (set_attr "type" "multiple")]
a2cd141b 3839)
3840
87b22bf7 3841(define_expand "lshrsi3"
cffb2a26 3842 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3843 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
3844 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3845 "TARGET_EITHER"
87b22bf7 3846 "
0438d37f 3847 if (CONST_INT_P (operands[2])
87b22bf7 3848 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3849 {
3850 emit_insn (gen_movsi (operands[0], const0_rtx));
3851 DONE;
3852 }
cffb2a26 3853 "
3854)
3855
87b22bf7 3856(define_expand "rotlsi3"
cffb2a26 3857 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3858 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
3859 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3860 "TARGET_32BIT"
87b22bf7 3861 "
0438d37f 3862 if (CONST_INT_P (operands[2]))
87b22bf7 3863 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
3864 else
b11cae9e 3865 {
87b22bf7 3866 rtx reg = gen_reg_rtx (SImode);
3867 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
3868 operands[2] = reg;
b11cae9e 3869 }
cffb2a26 3870 "
3871)
9c08d1fa 3872
87b22bf7 3873(define_expand "rotrsi3"
cffb2a26 3874 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3875 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
3876 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3877 "TARGET_EITHER"
87b22bf7 3878 "
25f905c2 3879 if (TARGET_32BIT)
cffb2a26 3880 {
0438d37f 3881 if (CONST_INT_P (operands[2])
cffb2a26 3882 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3883 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
3884 }
25f905c2 3885 else /* TARGET_THUMB1 */
cffb2a26 3886 {
0438d37f 3887 if (CONST_INT_P (operands [2]))
cffb2a26 3888 operands [2] = force_reg (SImode, operands[2]);
3889 }
3890 "
3891)
87b22bf7 3892
cffb2a26 3893(define_insn "*arm_shiftsi3"
88c29385 3894 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r,r")
cffb2a26 3895 (match_operator:SI 3 "shift_operator"
88c29385 3896 [(match_operand:SI 1 "s_register_operand" "0,l,r,r")
3897 (match_operand:SI 2 "reg_or_int_operand" "l,M,M,r")]))]
25f905c2 3898 "TARGET_32BIT"
3899 "* return arm_output_shift(operands, 0);"
344495ea 3900 [(set_attr "predicable" "yes")
88c29385 3901 (set_attr "arch" "t2,t2,*,*")
3902 (set_attr "predicable_short_it" "yes,yes,no,no")
7c36fe71 3903 (set_attr "length" "4")
331beb1a 3904 (set_attr "shift" "1")
88c29385 3905 (set_attr "type" "alu_shift_reg,alu_shift_imm,alu_shift_imm,alu_shift_reg")]
6c4c2133 3906)
87b22bf7 3907
f7fbdd4a 3908(define_insn "*shiftsi3_compare0"
bd5b4116 3909 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 3910 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
6b6abc9c 3911 [(match_operand:SI 1 "s_register_operand" "r,r")
3912 (match_operand:SI 2 "arm_rhs_operand" "M,r")])
9c08d1fa 3913 (const_int 0)))
6b6abc9c 3914 (set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 3915 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
25f905c2 3916 "TARGET_32BIT"
3917 "* return arm_output_shift(operands, 1);"
344495ea 3918 [(set_attr "conds" "set")
331beb1a 3919 (set_attr "shift" "1")
d82e788e 3920 (set_attr "type" "alus_shift_imm,alus_shift_reg")]
0d66636f 3921)
9c08d1fa 3922
f7fbdd4a 3923(define_insn "*shiftsi3_compare0_scratch"
bd5b4116 3924 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 3925 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
6b6abc9c 3926 [(match_operand:SI 1 "s_register_operand" "r,r")
3927 (match_operand:SI 2 "arm_rhs_operand" "M,r")])
9c08d1fa 3928 (const_int 0)))
6b6abc9c 3929 (clobber (match_scratch:SI 0 "=r,r"))]
25f905c2 3930 "TARGET_32BIT"
3931 "* return arm_output_shift(operands, 1);"
344495ea 3932 [(set_attr "conds" "set")
6b6abc9c 3933 (set_attr "shift" "1")
d82e788e 3934 (set_attr "type" "shift_imm,shift_reg")]
0d66636f 3935)
9c08d1fa 3936
d5d4dc8d 3937(define_insn "*not_shiftsi"
3938 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 3939 (not:SI (match_operator:SI 3 "shift_operator"
d5d4dc8d 3940 [(match_operand:SI 1 "s_register_operand" "r,r")
3941 (match_operand:SI 2 "shift_amount_operand" "M,rM")])))]
3942 "TARGET_32BIT"
6c4c2133 3943 "mvn%?\\t%0, %1%S3"
344495ea 3944 [(set_attr "predicable" "yes")
d952d547 3945 (set_attr "predicable_short_it" "no")
331beb1a 3946 (set_attr "shift" "1")
d5d4dc8d 3947 (set_attr "arch" "32,a")
1aed5204 3948 (set_attr "type" "mvn_shift,mvn_shift_reg")])
9c08d1fa 3949
d5d4dc8d 3950(define_insn "*not_shiftsi_compare0"
bd5b4116 3951 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 3952 (compare:CC_NOOV
3953 (not:SI (match_operator:SI 3 "shift_operator"
3954 [(match_operand:SI 1 "s_register_operand" "r,r")
3955 (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
3956 (const_int 0)))
3957 (set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 3958 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
d5d4dc8d 3959 "TARGET_32BIT"
25f905c2 3960 "mvn%.\\t%0, %1%S3"
344495ea 3961 [(set_attr "conds" "set")
331beb1a 3962 (set_attr "shift" "1")
d5d4dc8d 3963 (set_attr "arch" "32,a")
1aed5204 3964 (set_attr "type" "mvn_shift,mvn_shift_reg")])
9c08d1fa 3965
d5d4dc8d 3966(define_insn "*not_shiftsi_compare0_scratch"
bd5b4116 3967 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 3968 (compare:CC_NOOV
3969 (not:SI (match_operator:SI 3 "shift_operator"
3970 [(match_operand:SI 1 "s_register_operand" "r,r")
3971 (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
3972 (const_int 0)))
3973 (clobber (match_scratch:SI 0 "=r,r"))]
3974 "TARGET_32BIT"
25f905c2 3975 "mvn%.\\t%0, %1%S3"
344495ea 3976 [(set_attr "conds" "set")
331beb1a 3977 (set_attr "shift" "1")
d5d4dc8d 3978 (set_attr "arch" "32,a")
1aed5204 3979 (set_attr "type" "mvn_shift,mvn_shift_reg")])
9c08d1fa 3980
cffb2a26 3981;; We don't really have extzv, but defining this using shifts helps
3982;; to reduce register pressure later on.
3983
3984(define_expand "extzv"
eb04cafb 3985 [(set (match_operand 0 "s_register_operand" "")
3986 (zero_extract (match_operand 1 "nonimmediate_operand" "")
3987 (match_operand 2 "const_int_operand" "")
3988 (match_operand 3 "const_int_operand" "")))]
8b054d5a 3989 "TARGET_THUMB1 || arm_arch_thumb2"
cffb2a26 3990 "
3991 {
3992 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
3993 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
3994
8b054d5a 3995 if (arm_arch_thumb2)
3996 {
eb04cafb 3997 HOST_WIDE_INT width = INTVAL (operands[2]);
3998 HOST_WIDE_INT bitpos = INTVAL (operands[3]);
3999
4000 if (unaligned_access && MEM_P (operands[1])
4001 && (width == 16 || width == 32) && (bitpos % BITS_PER_UNIT) == 0)
4002 {
4003 rtx base_addr;
4004
4005 if (BYTES_BIG_ENDIAN)
4006 bitpos = GET_MODE_BITSIZE (GET_MODE (operands[0])) - width
4007 - bitpos;
4008
4009 if (width == 32)
4010 {
4011 base_addr = adjust_address (operands[1], SImode,
4012 bitpos / BITS_PER_UNIT);
4013 emit_insn (gen_unaligned_loadsi (operands[0], base_addr));
4014 }
4015 else
4016 {
4017 rtx dest = operands[0];
4018 rtx tmp = gen_reg_rtx (SImode);
4019
4020 /* We may get a paradoxical subreg here. Strip it off. */
4021 if (GET_CODE (dest) == SUBREG
4022 && GET_MODE (dest) == SImode
4023 && GET_MODE (SUBREG_REG (dest)) == HImode)
4024 dest = SUBREG_REG (dest);
4025
4026 if (GET_MODE_BITSIZE (GET_MODE (dest)) != width)
4027 FAIL;
4028
4029 base_addr = adjust_address (operands[1], HImode,
4030 bitpos / BITS_PER_UNIT);
4031 emit_insn (gen_unaligned_loadhiu (tmp, base_addr));
4032 emit_move_insn (gen_lowpart (SImode, dest), tmp);
4033 }
4034 DONE;
4035 }
4036 else if (s_register_operand (operands[1], GET_MODE (operands[1])))
4037 {
4038 emit_insn (gen_extzv_t2 (operands[0], operands[1], operands[2],
4039 operands[3]));
4040 DONE;
4041 }
4042 else
4043 FAIL;
8b054d5a 4044 }
eb04cafb 4045
4046 if (!s_register_operand (operands[1], GET_MODE (operands[1])))
4047 FAIL;
8b054d5a 4048
cffb2a26 4049 operands[3] = GEN_INT (rshift);
4050
4051 if (lshift == 0)
4052 {
4053 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
4054 DONE;
4055 }
4056
eb04cafb 4057 emit_insn (gen_extzv_t1 (operands[0], operands[1], GEN_INT (lshift),
4058 operands[3], gen_reg_rtx (SImode)));
4059 DONE;
215b30b3 4060 }"
cffb2a26 4061)
4062
eb04cafb 4063;; Helper for extzv, for the Thumb-1 register-shifts case.
4064
4065(define_expand "extzv_t1"
4066 [(set (match_operand:SI 4 "s_register_operand" "")
4067 (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "")
4068 (match_operand:SI 2 "const_int_operand" "")))
4069 (set (match_operand:SI 0 "s_register_operand" "")
4070 (lshiftrt:SI (match_dup 4)
4071 (match_operand:SI 3 "const_int_operand" "")))]
4072 "TARGET_THUMB1"
4073 "")
4074
4075(define_expand "extv"
4076 [(set (match_operand 0 "s_register_operand" "")
4077 (sign_extract (match_operand 1 "nonimmediate_operand" "")
4078 (match_operand 2 "const_int_operand" "")
4079 (match_operand 3 "const_int_operand" "")))]
4080 "arm_arch_thumb2"
4081{
4082 HOST_WIDE_INT width = INTVAL (operands[2]);
4083 HOST_WIDE_INT bitpos = INTVAL (operands[3]);
4084
4085 if (unaligned_access && MEM_P (operands[1]) && (width == 16 || width == 32)
4086 && (bitpos % BITS_PER_UNIT) == 0)
4087 {
4088 rtx base_addr;
4089
4090 if (BYTES_BIG_ENDIAN)
4091 bitpos = GET_MODE_BITSIZE (GET_MODE (operands[0])) - width - bitpos;
4092
4093 if (width == 32)
4094 {
4095 base_addr = adjust_address (operands[1], SImode,
4096 bitpos / BITS_PER_UNIT);
4097 emit_insn (gen_unaligned_loadsi (operands[0], base_addr));
4098 }
4099 else
4100 {
4101 rtx dest = operands[0];
4102 rtx tmp = gen_reg_rtx (SImode);
4103
4104 /* We may get a paradoxical subreg here. Strip it off. */
4105 if (GET_CODE (dest) == SUBREG
4106 && GET_MODE (dest) == SImode
4107 && GET_MODE (SUBREG_REG (dest)) == HImode)
4108 dest = SUBREG_REG (dest);
4109
4110 if (GET_MODE_BITSIZE (GET_MODE (dest)) != width)
4111 FAIL;
4112
4113 base_addr = adjust_address (operands[1], HImode,
4114 bitpos / BITS_PER_UNIT);
4115 emit_insn (gen_unaligned_loadhis (tmp, base_addr));
4116 emit_move_insn (gen_lowpart (SImode, dest), tmp);
4117 }
4118
4119 DONE;
4120 }
4121 else if (!s_register_operand (operands[1], GET_MODE (operands[1])))
4122 FAIL;
4123 else if (GET_MODE (operands[0]) == SImode
4124 && GET_MODE (operands[1]) == SImode)
4125 {
4126 emit_insn (gen_extv_regsi (operands[0], operands[1], operands[2],
4127 operands[3]));
4128 DONE;
4129 }
4130
4131 FAIL;
4132})
4133
4134; Helper to expand register forms of extv with the proper modes.
4135
4136(define_expand "extv_regsi"
4137 [(set (match_operand:SI 0 "s_register_operand" "")
4138 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
4139 (match_operand 2 "const_int_operand" "")
4140 (match_operand 3 "const_int_operand" "")))]
4141 ""
4142{
4143})
4144
4145; ARMv6+ unaligned load/store instructions (used for packed structure accesses).
4146
4147(define_insn "unaligned_loadsi"
4148 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4149 (unspec:SI [(match_operand:SI 1 "memory_operand" "Uw,m")]
4150 UNSPEC_UNALIGNED_LOAD))]
4151 "unaligned_access && TARGET_32BIT"
4152 "ldr%?\t%0, %1\t@ unaligned"
4153 [(set_attr "arch" "t2,any")
4154 (set_attr "length" "2,4")
4155 (set_attr "predicable" "yes")
d952d547 4156 (set_attr "predicable_short_it" "yes,no")
eb04cafb 4157 (set_attr "type" "load1")])
4158
4159(define_insn "unaligned_loadhis"
4160 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4161 (sign_extend:SI
e3f4ccee 4162 (unspec:HI [(match_operand:HI 1 "memory_operand" "Uw,Uh")]
eb04cafb 4163 UNSPEC_UNALIGNED_LOAD)))]
4164 "unaligned_access && TARGET_32BIT"
4165 "ldr%(sh%)\t%0, %1\t@ unaligned"
4166 [(set_attr "arch" "t2,any")
4167 (set_attr "length" "2,4")
4168 (set_attr "predicable" "yes")
d952d547 4169 (set_attr "predicable_short_it" "yes,no")
eb04cafb 4170 (set_attr "type" "load_byte")])
4171
4172(define_insn "unaligned_loadhiu"
4173 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4174 (zero_extend:SI
4175 (unspec:HI [(match_operand:HI 1 "memory_operand" "Uw,m")]
4176 UNSPEC_UNALIGNED_LOAD)))]
4177 "unaligned_access && TARGET_32BIT"
4178 "ldr%(h%)\t%0, %1\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" "load_byte")])
4184
4185(define_insn "unaligned_storesi"
4186 [(set (match_operand:SI 0 "memory_operand" "=Uw,m")
4187 (unspec:SI [(match_operand:SI 1 "s_register_operand" "l,r")]
4188 UNSPEC_UNALIGNED_STORE))]
4189 "unaligned_access && TARGET_32BIT"
4190 "str%?\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
4197(define_insn "unaligned_storehi"
4198 [(set (match_operand:HI 0 "memory_operand" "=Uw,m")
4199 (unspec:HI [(match_operand:HI 1 "s_register_operand" "l,r")]
4200 UNSPEC_UNALIGNED_STORE))]
4201 "unaligned_access && TARGET_32BIT"
4202 "str%(h%)\t%1, %0\t@ unaligned"
4203 [(set_attr "arch" "t2,any")
4204 (set_attr "length" "2,4")
4205 (set_attr "predicable" "yes")
d952d547 4206 (set_attr "predicable_short_it" "yes,no")
eb04cafb 4207 (set_attr "type" "store1")])
4208
ae51a965 4209;; Unaligned double-word load and store.
4210;; Split after reload into two unaligned single-word accesses.
4211;; It prevents lower_subreg from splitting some other aligned
4212;; double-word accesses too early. Used for internal memcpy.
4213
4214(define_insn_and_split "unaligned_loaddi"
4215 [(set (match_operand:DI 0 "s_register_operand" "=l,r")
4216 (unspec:DI [(match_operand:DI 1 "memory_operand" "o,o")]
4217 UNSPEC_UNALIGNED_LOAD))]
4218 "unaligned_access && TARGET_32BIT"
4219 "#"
4220 "&& reload_completed"
4221 [(set (match_dup 0) (unspec:SI [(match_dup 1)] UNSPEC_UNALIGNED_LOAD))
4222 (set (match_dup 2) (unspec:SI [(match_dup 3)] UNSPEC_UNALIGNED_LOAD))]
4223 {
4224 operands[2] = gen_highpart (SImode, operands[0]);
4225 operands[0] = gen_lowpart (SImode, operands[0]);
4226 operands[3] = gen_highpart (SImode, operands[1]);
4227 operands[1] = gen_lowpart (SImode, operands[1]);
4228
4229 /* If the first destination register overlaps with the base address,
4230 swap the order in which the loads are emitted. */
4231 if (reg_overlap_mentioned_p (operands[0], operands[1]))
4232 {
f145bcba 4233 std::swap (operands[1], operands[3]);
4234 std::swap (operands[0], operands[2]);
ae51a965 4235 }
4236 }
4237 [(set_attr "arch" "t2,any")
4238 (set_attr "length" "4,8")
4239 (set_attr "predicable" "yes")
4240 (set_attr "type" "load2")])
4241
4242(define_insn_and_split "unaligned_storedi"
4243 [(set (match_operand:DI 0 "memory_operand" "=o,o")
4244 (unspec:DI [(match_operand:DI 1 "s_register_operand" "l,r")]
4245 UNSPEC_UNALIGNED_STORE))]
4246 "unaligned_access && TARGET_32BIT"
4247 "#"
4248 "&& reload_completed"
4249 [(set (match_dup 0) (unspec:SI [(match_dup 1)] UNSPEC_UNALIGNED_STORE))
4250 (set (match_dup 2) (unspec:SI [(match_dup 3)] UNSPEC_UNALIGNED_STORE))]
4251 {
4252 operands[2] = gen_highpart (SImode, operands[0]);
4253 operands[0] = gen_lowpart (SImode, operands[0]);
4254 operands[3] = gen_highpart (SImode, operands[1]);
4255 operands[1] = gen_lowpart (SImode, operands[1]);
4256 }
4257 [(set_attr "arch" "t2,any")
4258 (set_attr "length" "4,8")
4259 (set_attr "predicable" "yes")
4260 (set_attr "type" "store2")])
4261
4262
eb04cafb 4263(define_insn "*extv_reg"
8b054d5a 4264 [(set (match_operand:SI 0 "s_register_operand" "=r")
4265 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
809003b3 4266 (match_operand:SI 2 "const_int_M_operand" "M")
4267 (match_operand:SI 3 "const_int_M_operand" "M")))]
8b054d5a 4268 "arm_arch_thumb2"
4269 "sbfx%?\t%0, %1, %3, %2"
4270 [(set_attr "length" "4")
d952d547 4271 (set_attr "predicable" "yes")
d82e788e 4272 (set_attr "predicable_short_it" "no")
4273 (set_attr "type" "bfm")]
8b054d5a 4274)
4275
4276(define_insn "extzv_t2"
4277 [(set (match_operand:SI 0 "s_register_operand" "=r")
4278 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "r")
809003b3 4279 (match_operand:SI 2 "const_int_M_operand" "M")
4280 (match_operand:SI 3 "const_int_M_operand" "M")))]
8b054d5a 4281 "arm_arch_thumb2"
4282 "ubfx%?\t%0, %1, %3, %2"
4283 [(set_attr "length" "4")
d952d547 4284 (set_attr "predicable" "yes")
d82e788e 4285 (set_attr "predicable_short_it" "no")
4286 (set_attr "type" "bfm")]
8b054d5a 4287)
4288
7d3cda8c 4289
4290;; Division instructions
4291(define_insn "divsi3"
4292 [(set (match_operand:SI 0 "s_register_operand" "=r")
4293 (div:SI (match_operand:SI 1 "s_register_operand" "r")
4294 (match_operand:SI 2 "s_register_operand" "r")))]
4295 "TARGET_IDIV"
4296 "sdiv%?\t%0, %1, %2"
4297 [(set_attr "predicable" "yes")
d952d547 4298 (set_attr "predicable_short_it" "no")
9da0ec36 4299 (set_attr "type" "sdiv")]
7d3cda8c 4300)
4301
4302(define_insn "udivsi3"
4303 [(set (match_operand:SI 0 "s_register_operand" "=r")
4304 (udiv:SI (match_operand:SI 1 "s_register_operand" "r")
4305 (match_operand:SI 2 "s_register_operand" "r")))]
4306 "TARGET_IDIV"
4307 "udiv%?\t%0, %1, %2"
4308 [(set_attr "predicable" "yes")
d952d547 4309 (set_attr "predicable_short_it" "no")
9da0ec36 4310 (set_attr "type" "udiv")]
7d3cda8c 4311)
4312
b11cae9e 4313\f
4314;; Unary arithmetic insns
4315
cffb2a26 4316(define_expand "negdi2"
4317 [(parallel
8135a42b 4318 [(set (match_operand:DI 0 "s_register_operand" "")
4319 (neg:DI (match_operand:DI 1 "s_register_operand" "")))
bd5b4116 4320 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 4321 "TARGET_EITHER"
774d2fbb 4322 {
4323 if (TARGET_NEON)
4324 {
4325 emit_insn (gen_negdi2_neon (operands[0], operands[1]));
4326 DONE;
4327 }
4328 }
cffb2a26 4329)
4330
4331;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
e5fea38e 4332;; The first alternative allows the common case of a *full* overlap.
ba6a3b2f 4333(define_insn_and_split "*arm_negdi2"
458a8706 4334 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 4335 (neg:DI (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 4336 (clobber (reg:CC CC_REGNUM))]
cffb2a26 4337 "TARGET_ARM"
ba6a3b2f 4338 "#" ; "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
4339 "&& reload_completed"
4340 [(parallel [(set (reg:CC CC_REGNUM)
4341 (compare:CC (const_int 0) (match_dup 1)))
4342 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 1)))])
4343 (set (match_dup 2) (minus:SI (minus:SI (const_int 0) (match_dup 3))
4344 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
4345 {
4346 operands[2] = gen_highpart (SImode, operands[0]);
4347 operands[0] = gen_lowpart (SImode, operands[0]);
4348 operands[3] = gen_highpart (SImode, operands[1]);
4349 operands[1] = gen_lowpart (SImode, operands[1]);
4350 }
cffb2a26 4351 [(set_attr "conds" "clob")
1b7da4ac 4352 (set_attr "length" "8")
4353 (set_attr "type" "multiple")]
cffb2a26 4354)
b11cae9e 4355
cffb2a26 4356(define_expand "negsi2"
4357 [(set (match_operand:SI 0 "s_register_operand" "")
4358 (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
4359 "TARGET_EITHER"
b11cae9e 4360 ""
cffb2a26 4361)
4362
4363(define_insn "*arm_negsi2"
d952d547 4364 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4365 (neg:SI (match_operand:SI 1 "s_register_operand" "l,r")))]
25f905c2 4366 "TARGET_32BIT"
cffb2a26 4367 "rsb%?\\t%0, %1, #0"
d952d547 4368 [(set_attr "predicable" "yes")
4369 (set_attr "predicable_short_it" "yes,no")
4370 (set_attr "arch" "t2,*")
1b7da4ac 4371 (set_attr "length" "4")
112eda6f 4372 (set_attr "type" "alu_sreg")]
cffb2a26 4373)
4374
604f3a0a 4375(define_expand "negsf2"
4376 [(set (match_operand:SF 0 "s_register_operand" "")
4377 (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
994606f8 4378 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
604f3a0a 4379 ""
4380)
4381
4382(define_expand "negdf2"
4383 [(set (match_operand:DF 0 "s_register_operand" "")
4384 (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
994606f8 4385 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
604f3a0a 4386 "")
4387
7eaf2be0 4388(define_insn_and_split "*zextendsidi_negsi"
4389 [(set (match_operand:DI 0 "s_register_operand" "=r")
4390 (zero_extend:DI (neg:SI (match_operand:SI 1 "s_register_operand" "r"))))]
4391 "TARGET_32BIT"
4392 "#"
4393 ""
4394 [(set (match_dup 2)
4395 (neg:SI (match_dup 1)))
4396 (set (match_dup 3)
4397 (const_int 0))]
4398 {
4399 operands[2] = gen_lowpart (SImode, operands[0]);
4400 operands[3] = gen_highpart (SImode, operands[0]);
4401 }
4402 [(set_attr "length" "8")
4403 (set_attr "type" "multiple")]
4404)
4405
83e2b922 4406;; Negate an extended 32-bit value.
4407(define_insn_and_split "*negdi_extendsidi"
61fa8ff2 4408 [(set (match_operand:DI 0 "s_register_operand" "=l,r")
4409 (neg:DI (sign_extend:DI
4410 (match_operand:SI 1 "s_register_operand" "l,r"))))
83e2b922 4411 (clobber (reg:CC CC_REGNUM))]
4412 "TARGET_32BIT"
61fa8ff2 4413 "#"
83e2b922 4414 "&& reload_completed"
4415 [(const_int 0)]
4416 {
61fa8ff2 4417 rtx low = gen_lowpart (SImode, operands[0]);
4418 rtx high = gen_highpart (SImode, operands[0]);
4419
4420 if (reg_overlap_mentioned_p (low, operands[1]))
4421 {
4422 /* Input overlaps the low word of the output. Use:
4423 asr Rhi, Rin, #31
4424 rsbs Rlo, Rin, #0
4425 rsc Rhi, Rhi, #0 (thumb2: sbc Rhi, Rhi, Rhi, lsl #1). */
4426 rtx cc_reg = gen_rtx_REG (CC_Cmode, CC_REGNUM);
4427
4428 emit_insn (gen_rtx_SET (VOIDmode, high,
4429 gen_rtx_ASHIFTRT (SImode, operands[1],
4430 GEN_INT (31))));
4431
4432 emit_insn (gen_subsi3_compare (low, const0_rtx, operands[1]));
4433 if (TARGET_ARM)
4434 emit_insn (gen_rtx_SET (VOIDmode, high,
4435 gen_rtx_MINUS (SImode,
4436 gen_rtx_MINUS (SImode,
4437 const0_rtx,
4438 high),
4439 gen_rtx_LTU (SImode,
4440 cc_reg,
4441 const0_rtx))));
4442 else
4443 {
4444 rtx two_x = gen_rtx_ASHIFT (SImode, high, GEN_INT (1));
4445 emit_insn (gen_rtx_SET (VOIDmode, high,
4446 gen_rtx_MINUS (SImode,
4447 gen_rtx_MINUS (SImode,
4448 high,
4449 two_x),
4450 gen_rtx_LTU (SImode,
4451 cc_reg,
4452 const0_rtx))));
4453 }
4454 }
4455 else
4456 {
4457 /* No overlap, or overlap on high word. Use:
4458 rsb Rlo, Rin, #0
4459 bic Rhi, Rlo, Rin
4460 asr Rhi, Rhi, #31
4461 Flags not needed for this sequence. */
4462 emit_insn (gen_rtx_SET (VOIDmode, low,
4463 gen_rtx_NEG (SImode, operands[1])));
4464 emit_insn (gen_rtx_SET (VOIDmode, high,
4465 gen_rtx_AND (SImode,
4466 gen_rtx_NOT (SImode, operands[1]),
4467 low)));
4468 emit_insn (gen_rtx_SET (VOIDmode, high,
4469 gen_rtx_ASHIFTRT (SImode, high,
4470 GEN_INT (31))));
4471 }
4472 DONE;
83e2b922 4473 }
61fa8ff2 4474 [(set_attr "length" "12")
4475 (set_attr "arch" "t2,*")
1b7da4ac 4476 (set_attr "type" "multiple")]
83e2b922 4477)
4478
4479(define_insn_and_split "*negdi_zero_extendsidi"
4480 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
4481 (neg:DI (zero_extend:DI (match_operand:SI 1 "s_register_operand" "0,r"))))
4482 (clobber (reg:CC CC_REGNUM))]
4483 "TARGET_32BIT"
4484 "#" ; "rsbs\\t%Q0, %1, #0\;sbc\\t%R0,%R0,%R0"
4485 ;; Don't care what register is input to sbc,
4486 ;; since we just just need to propagate the carry.
4487 "&& reload_completed"
4488 [(parallel [(set (reg:CC CC_REGNUM)
4489 (compare:CC (const_int 0) (match_dup 1)))
4490 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 1)))])
4491 (set (match_dup 2) (minus:SI (minus:SI (match_dup 2) (match_dup 2))
4492 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
4493 {
4494 operands[2] = gen_highpart (SImode, operands[0]);
4495 operands[0] = gen_lowpart (SImode, operands[0]);
4496 }
4497 [(set_attr "conds" "clob")
1b7da4ac 4498 (set_attr "length" "8")
4499 (set_attr "type" "multiple")] ;; length in thumb is 4
83e2b922 4500)
4501
9c08d1fa 4502;; abssi2 doesn't really clobber the condition codes if a different register
4503;; is being set. To keep things simple, assume during rtl manipulations that
4504;; it does, but tell the final scan operator the truth. Similarly for
4505;; (neg (abs...))
4506
604f3a0a 4507(define_expand "abssi2"
4508 [(parallel
4509 [(set (match_operand:SI 0 "s_register_operand" "")
4510 (abs:SI (match_operand:SI 1 "s_register_operand" "")))
ba156559 4511 (clobber (match_dup 2))])]
4512 "TARGET_EITHER"
4513 "
25f905c2 4514 if (TARGET_THUMB1)
ba156559 4515 operands[2] = gen_rtx_SCRATCH (SImode);
4516 else
4517 operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
4518")
604f3a0a 4519
ba6a3b2f 4520(define_insn_and_split "*arm_abssi2"
ba156559 4521 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
9c08d1fa 4522 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
bd5b4116 4523 (clobber (reg:CC CC_REGNUM))]
cffb2a26 4524 "TARGET_ARM"
ba6a3b2f 4525 "#"
4526 "&& reload_completed"
4527 [(const_int 0)]
4528 {
4529 /* if (which_alternative == 0) */
4530 if (REGNO(operands[0]) == REGNO(operands[1]))
4531 {
4532 /* Emit the pattern:
4533 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
4534 [(set (reg:CC CC_REGNUM)
4535 (compare:CC (match_dup 0) (const_int 0)))
4536 (cond_exec (lt:CC (reg:CC CC_REGNUM) (const_int 0))
4537 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 1))))]
4538 */
4539 emit_insn (gen_rtx_SET (VOIDmode,
4540 gen_rtx_REG (CCmode, CC_REGNUM),
4541 gen_rtx_COMPARE (CCmode, operands[0], const0_rtx)));
4542 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
4543 (gen_rtx_LT (SImode,
4544 gen_rtx_REG (CCmode, CC_REGNUM),
4545 const0_rtx)),
4546 (gen_rtx_SET (VOIDmode,
4547 operands[0],
4548 (gen_rtx_MINUS (SImode,
4549 const0_rtx,
4550 operands[1]))))));
4551 DONE;
4552 }
4553 else
4554 {
4555 /* Emit the pattern:
4556 alt1: eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31
4557 [(set (match_dup 0)
4558 (xor:SI (match_dup 1)
4559 (ashiftrt:SI (match_dup 1) (const_int 31))))
4560 (set (match_dup 0)
4561 (minus:SI (match_dup 0)
4562 (ashiftrt:SI (match_dup 1) (const_int 31))))]
4563 */
4564 emit_insn (gen_rtx_SET (VOIDmode,
4565 operands[0],
4566 gen_rtx_XOR (SImode,
4567 gen_rtx_ASHIFTRT (SImode,
4568 operands[1],
4569 GEN_INT (31)),
4570 operands[1])));
4571 emit_insn (gen_rtx_SET (VOIDmode,
4572 operands[0],
4573 gen_rtx_MINUS (SImode,
4574 operands[0],
4575 gen_rtx_ASHIFTRT (SImode,
4576 operands[1],
4577 GEN_INT (31)))));
4578 DONE;
4579 }
4580 }
cffb2a26 4581 [(set_attr "conds" "clob,*")
331beb1a 4582 (set_attr "shift" "1")
2ad08b65 4583 (set_attr "predicable" "no, yes")
1b7da4ac 4584 (set_attr "length" "8")
4585 (set_attr "type" "multiple")]
cffb2a26 4586)
9c08d1fa 4587
ba6a3b2f 4588(define_insn_and_split "*arm_neg_abssi2"
9c08d1fa 4589 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
4590 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
bd5b4116 4591 (clobber (reg:CC CC_REGNUM))]
cffb2a26 4592 "TARGET_ARM"
ba6a3b2f 4593 "#"
4594 "&& reload_completed"
4595 [(const_int 0)]
4596 {
4597 /* if (which_alternative == 0) */
4598 if (REGNO (operands[0]) == REGNO (operands[1]))
4599 {
4600 /* Emit the pattern:
4601 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
4602 */
4603 emit_insn (gen_rtx_SET (VOIDmode,
4604 gen_rtx_REG (CCmode, CC_REGNUM),
4605 gen_rtx_COMPARE (CCmode, operands[0], const0_rtx)));
4606 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
4607 gen_rtx_GT (SImode,
4608 gen_rtx_REG (CCmode, CC_REGNUM),
4609 const0_rtx),
4610 gen_rtx_SET (VOIDmode,
4611 operands[0],
4612 (gen_rtx_MINUS (SImode,
4613 const0_rtx,
4614 operands[1])))));
4615 }
4616 else
4617 {
4618 /* Emit the pattern:
4619 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31
4620 */
4621 emit_insn (gen_rtx_SET (VOIDmode,
4622 operands[0],
4623 gen_rtx_XOR (SImode,
4624 gen_rtx_ASHIFTRT (SImode,
4625 operands[1],
4626 GEN_INT (31)),
4627 operands[1])));
4628 emit_insn (gen_rtx_SET (VOIDmode,
4629 operands[0],
4630 gen_rtx_MINUS (SImode,
4631 gen_rtx_ASHIFTRT (SImode,
4632 operands[1],
4633 GEN_INT (31)),
4634 operands[0])));
4635 }
4636 DONE;
4637 }
cffb2a26 4638 [(set_attr "conds" "clob,*")
331beb1a 4639 (set_attr "shift" "1")
2ad08b65 4640 (set_attr "predicable" "no, yes")
1b7da4ac 4641 (set_attr "length" "8")
4642 (set_attr "type" "multiple")]
cffb2a26 4643)
b11cae9e 4644
604f3a0a 4645(define_expand "abssf2"
4646 [(set (match_operand:SF 0 "s_register_operand" "")
4647 (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
25f905c2 4648 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 4649 "")
4650
604f3a0a 4651(define_expand "absdf2"
4652 [(set (match_operand:DF 0 "s_register_operand" "")
4653 (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 4654 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 4655 "")
4656
7db9af5d 4657(define_expand "sqrtsf2"
4658 [(set (match_operand:SF 0 "s_register_operand" "")
4659 (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
994606f8 4660 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
7db9af5d 4661 "")
9c08d1fa 4662
7db9af5d 4663(define_expand "sqrtdf2"
4664 [(set (match_operand:DF 0 "s_register_operand" "")
4665 (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
994606f8 4666 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
7db9af5d 4667 "")
9c08d1fa 4668
a0f94409 4669(define_insn_and_split "one_cmpldi2"
10efb95f 4670 [(set (match_operand:DI 0 "s_register_operand" "=w,&r,&r,?w")
4671 (not:DI (match_operand:DI 1 "s_register_operand" " w, 0, r, w")))]
25f905c2 4672 "TARGET_32BIT"
10efb95f 4673 "@
4674 vmvn\t%P0, %P1
4675 #
4676 #
4677 vmvn\t%P0, %P1"
4678 "TARGET_32BIT && reload_completed
4679 && arm_general_register_operand (operands[0], DImode)"
a0f94409 4680 [(set (match_dup 0) (not:SI (match_dup 1)))
4681 (set (match_dup 2) (not:SI (match_dup 3)))]
4682 "
4683 {
4684 operands[2] = gen_highpart (SImode, operands[0]);
4685 operands[0] = gen_lowpart (SImode, operands[0]);
4686 operands[3] = gen_highpart (SImode, operands[1]);
4687 operands[1] = gen_lowpart (SImode, operands[1]);
4688 }"
10efb95f 4689 [(set_attr "length" "*,8,8,*")
4690 (set_attr "predicable" "no,yes,yes,no")
32093010 4691 (set_attr "type" "neon_move,multiple,multiple,neon_move")
b6779ddc 4692 (set_attr "arch" "neon_for_64bits,*,*,avoid_neon_for_64bits")]
cffb2a26 4693)
b11cae9e 4694
cffb2a26 4695(define_expand "one_cmplsi2"
4696 [(set (match_operand:SI 0 "s_register_operand" "")
4697 (not:SI (match_operand:SI 1 "s_register_operand" "")))]
4698 "TARGET_EITHER"
b11cae9e 4699 ""
cffb2a26 4700)
4701
4702(define_insn "*arm_one_cmplsi2"
d952d547 4703 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4704 (not:SI (match_operand:SI 1 "s_register_operand" "l,r")))]
25f905c2 4705 "TARGET_32BIT"
cffb2a26 4706 "mvn%?\\t%0, %1"
d2a518d1 4707 [(set_attr "predicable" "yes")
d952d547 4708 (set_attr "predicable_short_it" "yes,no")
4709 (set_attr "arch" "t2,*")
4710 (set_attr "length" "4")
1aed5204 4711 (set_attr "type" "mvn_reg")]
cffb2a26 4712)
4713
f7fbdd4a 4714(define_insn "*notsi_compare0"
bd5b4116 4715 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 4716 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
4717 (const_int 0)))
4718 (set (match_operand:SI 0 "s_register_operand" "=r")
4719 (not:SI (match_dup 1)))]
25f905c2 4720 "TARGET_32BIT"
4721 "mvn%.\\t%0, %1"
d2a518d1 4722 [(set_attr "conds" "set")
1aed5204 4723 (set_attr "type" "mvn_reg")]
cffb2a26 4724)
9c08d1fa 4725
f7fbdd4a 4726(define_insn "*notsi_compare0_scratch"
bd5b4116 4727 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 4728 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
4729 (const_int 0)))
4730 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 4731 "TARGET_32BIT"
4732 "mvn%.\\t%0, %1"
d2a518d1 4733 [(set_attr "conds" "set")
1aed5204 4734 (set_attr "type" "mvn_reg")]
cffb2a26 4735)
b11cae9e 4736\f
4737;; Fixed <--> Floating conversion insns
4738
9b8516be 4739(define_expand "floatsihf2"
4740 [(set (match_operand:HF 0 "general_operand" "")
4741 (float:HF (match_operand:SI 1 "general_operand" "")))]
4742 "TARGET_EITHER"
4743 "
4744 {
4745 rtx op1 = gen_reg_rtx (SFmode);
4746 expand_float (op1, operands[1], 0);
4747 op1 = convert_to_mode (HFmode, op1, 0);
4748 emit_move_insn (operands[0], op1);
4749 DONE;
4750 }"
4751)
4752
4753(define_expand "floatdihf2"
4754 [(set (match_operand:HF 0 "general_operand" "")
4755 (float:HF (match_operand:DI 1 "general_operand" "")))]
4756 "TARGET_EITHER"
4757 "
4758 {
4759 rtx op1 = gen_reg_rtx (SFmode);
4760 expand_float (op1, operands[1], 0);
4761 op1 = convert_to_mode (HFmode, op1, 0);
4762 emit_move_insn (operands[0], op1);
4763 DONE;
4764 }"
4765)
4766
604f3a0a 4767(define_expand "floatsisf2"
4768 [(set (match_operand:SF 0 "s_register_operand" "")
4769 (float:SF (match_operand:SI 1 "s_register_operand" "")))]
25f905c2 4770 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 4771 "
604f3a0a 4772")
4773
604f3a0a 4774(define_expand "floatsidf2"
4775 [(set (match_operand:DF 0 "s_register_operand" "")
4776 (float:DF (match_operand:SI 1 "s_register_operand" "")))]
a50d7267 4777 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 4778 "
604f3a0a 4779")
4780
9b8516be 4781(define_expand "fix_trunchfsi2"
4782 [(set (match_operand:SI 0 "general_operand" "")
4783 (fix:SI (fix:HF (match_operand:HF 1 "general_operand" ""))))]
4784 "TARGET_EITHER"
4785 "
4786 {
4787 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
4788 expand_fix (operands[0], op1, 0);
4789 DONE;
4790 }"
4791)
4792
4793(define_expand "fix_trunchfdi2"
4794 [(set (match_operand:DI 0 "general_operand" "")
4795 (fix:DI (fix:HF (match_operand:HF 1 "general_operand" ""))))]
4796 "TARGET_EITHER"
4797 "
4798 {
4799 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
4800 expand_fix (operands[0], op1, 0);
4801 DONE;
4802 }"
4803)
4804
604f3a0a 4805(define_expand "fix_truncsfsi2"
4806 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 4807 (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" ""))))]
25f905c2 4808 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 4809 "
604f3a0a 4810")
4811
604f3a0a 4812(define_expand "fix_truncdfsi2"
4813 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 4814 (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" ""))))]
a50d7267 4815 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 4816 "
604f3a0a 4817")
4818
f544c6d2 4819;; Truncation insns
b11cae9e 4820
604f3a0a 4821(define_expand "truncdfsf2"
4822 [(set (match_operand:SF 0 "s_register_operand" "")
4823 (float_truncate:SF
4824 (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 4825 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 4826 ""
4827)
9b8516be 4828
4829/* DFmode -> HFmode conversions have to go through SFmode. */
4830(define_expand "truncdfhf2"
4831 [(set (match_operand:HF 0 "general_operand" "")
4832 (float_truncate:HF
4833 (match_operand:DF 1 "general_operand" "")))]
4834 "TARGET_EITHER"
4835 "
4836 {
4837 rtx op1;
4838 op1 = convert_to_mode (SFmode, operands[1], 0);
4839 op1 = convert_to_mode (HFmode, op1, 0);
4840 emit_move_insn (operands[0], op1);
4841 DONE;
4842 }"
4843)
b11cae9e 4844\f
9c08d1fa 4845;; Zero and sign extension instructions.
b11cae9e 4846
848e66ac 4847(define_insn "zero_extend<mode>di2"
6aa689e8 4848 [(set (match_operand:DI 0 "s_register_operand" "=w,r,?r,w")
6d97728e 4849 (zero_extend:DI (match_operand:QHSI 1 "<qhs_zextenddi_op>"
4850 "<qhs_zextenddi_cstr>")))]
848e66ac 4851 "TARGET_32BIT <qhs_zextenddi_cond>"
4852 "#"
6aa689e8 4853 [(set_attr "length" "8,4,8,8")
b6779ddc 4854 (set_attr "arch" "neon_for_64bits,*,*,avoid_neon_for_64bits")
848e66ac 4855 (set_attr "ce_count" "2")
efbb5e19 4856 (set_attr "predicable" "yes")
4857 (set_attr "type" "multiple,mov_reg,multiple,multiple")]
25f905c2 4858)
4859
848e66ac 4860(define_insn "extend<mode>di2"
6aa689e8 4861 [(set (match_operand:DI 0 "s_register_operand" "=w,r,?r,?r,w")
63d204a8 4862 (sign_extend:DI (match_operand:QHSI 1 "<qhs_extenddi_op>"
4863 "<qhs_extenddi_cstr>")))]
848e66ac 4864 "TARGET_32BIT <qhs_sextenddi_cond>"
4865 "#"
6aa689e8 4866 [(set_attr "length" "8,4,8,8,8")
848e66ac 4867 (set_attr "ce_count" "2")
4868 (set_attr "shift" "1")
8012d2c2 4869 (set_attr "predicable" "yes")
1b7da4ac 4870 (set_attr "arch" "neon_for_64bits,*,a,t,avoid_neon_for_64bits")
4871 (set_attr "type" "multiple,mov_reg,multiple,multiple,multiple")]
0d66636f 4872)
9c08d1fa 4873
848e66ac 4874;; Splits for all extensions to DImode
4875(define_split
4876 [(set (match_operand:DI 0 "s_register_operand" "")
4877 (zero_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
6aa689e8 4878 "TARGET_32BIT && reload_completed && !IS_VFP_REGNUM (REGNO (operands[0]))"
848e66ac 4879 [(set (match_dup 0) (match_dup 1))]
4880{
848e66ac 4881 rtx lo_part = gen_lowpart (SImode, operands[0]);
3754d046 4882 machine_mode src_mode = GET_MODE (operands[1]);
848e66ac 4883
4884 if (REG_P (operands[0])
4885 && !reg_overlap_mentioned_p (operands[0], operands[1]))
4886 emit_clobber (operands[0]);
4887 if (!REG_P (lo_part) || src_mode != SImode
4888 || !rtx_equal_p (lo_part, operands[1]))
4889 {
4890 if (src_mode == SImode)
4891 emit_move_insn (lo_part, operands[1]);
4892 else
4893 emit_insn (gen_rtx_SET (VOIDmode, lo_part,
4894 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
4895 operands[1] = lo_part;
4896 }
4897 operands[0] = gen_highpart (SImode, operands[0]);
4898 operands[1] = const0_rtx;
4899})
9c08d1fa 4900
848e66ac 4901(define_split
25f905c2 4902 [(set (match_operand:DI 0 "s_register_operand" "")
848e66ac 4903 (sign_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
6aa689e8 4904 "TARGET_32BIT && reload_completed && !IS_VFP_REGNUM (REGNO (operands[0]))"
848e66ac 4905 [(set (match_dup 0) (ashiftrt:SI (match_dup 1) (const_int 31)))]
4906{
4907 rtx lo_part = gen_lowpart (SImode, operands[0]);
3754d046 4908 machine_mode src_mode = GET_MODE (operands[1]);
25f905c2 4909
848e66ac 4910 if (REG_P (operands[0])
4911 && !reg_overlap_mentioned_p (operands[0], operands[1]))
4912 emit_clobber (operands[0]);
4913
4914 if (!REG_P (lo_part) || src_mode != SImode
4915 || !rtx_equal_p (lo_part, operands[1]))
4916 {
4917 if (src_mode == SImode)
4918 emit_move_insn (lo_part, operands[1]);
4919 else
4920 emit_insn (gen_rtx_SET (VOIDmode, lo_part,
4921 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
4922 operands[1] = lo_part;
4923 }
4924 operands[0] = gen_highpart (SImode, operands[0]);
4925})
9c08d1fa 4926
4927(define_expand "zero_extendhisi2"
ef51b8e1 4928 [(set (match_operand:SI 0 "s_register_operand" "")
4929 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
cffb2a26 4930 "TARGET_EITHER"
ef51b8e1 4931{
4932 if (TARGET_ARM && !arm_arch4 && MEM_P (operands[1]))
f7fbdd4a 4933 {
ef51b8e1 4934 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
4935 DONE;
25f7a26e 4936 }
ef51b8e1 4937 if (!arm_arch6 && !MEM_P (operands[1]))
4938 {
4939 rtx t = gen_lowpart (SImode, operands[1]);
4940 rtx tmp = gen_reg_rtx (SImode);
4941 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
4942 emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (16)));
4943 DONE;
4944 }
4945})
9c08d1fa 4946
ef51b8e1 4947(define_split
b146458f 4948 [(set (match_operand:SI 0 "s_register_operand" "")
4949 (zero_extend:SI (match_operand:HI 1 "s_register_operand" "")))]
ef51b8e1 4950 "!TARGET_THUMB2 && !arm_arch6"
4951 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4952 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 16)))]
4953{
4954 operands[2] = gen_lowpart (SImode, operands[1]);
4955})
4956
cffb2a26 4957(define_insn "*arm_zero_extendhisi2"
ef51b8e1 4958 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4959 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 4960 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 4961 "@
4962 #
4963 ldr%(h%)\\t%0, %1"
d82e788e 4964 [(set_attr "type" "alu_shift_reg,load_byte")
848e66ac 4965 (set_attr "predicable" "yes")]
cffb2a26 4966)
f7fbdd4a 4967
a2cd141b 4968(define_insn "*arm_zero_extendhisi2_v6"
4969 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
e3f4ccee 4970 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,Uh")))]
a2cd141b 4971 "TARGET_ARM && arm_arch6"
4972 "@
4973 uxth%?\\t%0, %1
25f905c2 4974 ldr%(h%)\\t%0, %1"
65f68e55 4975 [(set_attr "predicable" "yes")
6b6abc9c 4976 (set_attr "type" "extend,load_byte")]
a2cd141b 4977)
4978
4979(define_insn "*arm_zero_extendhisi2addsi"
4980 [(set (match_operand:SI 0 "s_register_operand" "=r")
4981 (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
4982 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4983 "TARGET_INT_SIMD"
a2cd141b 4984 "uxtah%?\\t%0, %2, %1"
d82e788e 4985 [(set_attr "type" "alu_shift_reg")
d952d547 4986 (set_attr "predicable" "yes")
4987 (set_attr "predicable_short_it" "no")]
a2cd141b 4988)
4989
87b22bf7 4990(define_expand "zero_extendqisi2"
cffb2a26 4991 [(set (match_operand:SI 0 "s_register_operand" "")
4992 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
4993 "TARGET_EITHER"
ef51b8e1 4994{
0438d37f 4995 if (TARGET_ARM && !arm_arch6 && !MEM_P (operands[1]))
87b22bf7 4996 {
ef51b8e1 4997 emit_insn (gen_andsi3 (operands[0],
4998 gen_lowpart (SImode, operands[1]),
4999 GEN_INT (255)));
5000 DONE;
5001 }
5002 if (!arm_arch6 && !MEM_P (operands[1]))
5003 {
5004 rtx t = gen_lowpart (SImode, operands[1]);
5005 rtx tmp = gen_reg_rtx (SImode);
5006 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
5007 emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (24)));
5008 DONE;
5009 }
5010})
cffb2a26 5011
ef51b8e1 5012(define_split
b146458f 5013 [(set (match_operand:SI 0 "s_register_operand" "")
5014 (zero_extend:SI (match_operand:QI 1 "s_register_operand" "")))]
ef51b8e1 5015 "!arm_arch6"
5016 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
5017 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 24)))]
5018{
5019 operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
5020 if (TARGET_ARM)
5021 {
5022 emit_insn (gen_andsi3 (operands[0], operands[2], GEN_INT (255)));
87b22bf7 5023 DONE;
5024 }
ef51b8e1 5025})
9c08d1fa 5026
cffb2a26 5027(define_insn "*arm_zero_extendqisi2"
ef51b8e1 5028 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5029 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 5030 "TARGET_ARM && !arm_arch6"
ef51b8e1 5031 "@
5032 #
5033 ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
5034 [(set_attr "length" "8,4")
d82e788e 5035 (set_attr "type" "alu_shift_reg,load_byte")
848e66ac 5036 (set_attr "predicable" "yes")]
cffb2a26 5037)
87b22bf7 5038
a2cd141b 5039(define_insn "*arm_zero_extendqisi2_v6"
5040 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
e3f4ccee 5041 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,Uh")))]
a2cd141b 5042 "TARGET_ARM && arm_arch6"
5043 "@
25f905c2 5044 uxtb%(%)\\t%0, %1
5045 ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
6b6abc9c 5046 [(set_attr "type" "extend,load_byte")
848e66ac 5047 (set_attr "predicable" "yes")]
a2cd141b 5048)
5049
5050(define_insn "*arm_zero_extendqisi2addsi"
5051 [(set (match_operand:SI 0 "s_register_operand" "=r")
5052 (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
5053 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 5054 "TARGET_INT_SIMD"
a2cd141b 5055 "uxtab%?\\t%0, %2, %1"
5056 [(set_attr "predicable" "yes")
d952d547 5057 (set_attr "predicable_short_it" "no")
d82e788e 5058 (set_attr "type" "alu_shift_reg")]
a2cd141b 5059)
5060
87b22bf7 5061(define_split
5062 [(set (match_operand:SI 0 "s_register_operand" "")
5063 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
5064 (clobber (match_operand:SI 2 "s_register_operand" ""))]
0438d37f 5065 "TARGET_32BIT && (!MEM_P (operands[1])) && ! BYTES_BIG_ENDIAN"
87b22bf7 5066 [(set (match_dup 2) (match_dup 1))
5067 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
cffb2a26 5068 ""
5069)
9c08d1fa 5070
8a4d25d6 5071(define_split
5072 [(set (match_operand:SI 0 "s_register_operand" "")
5073 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 3)))
5074 (clobber (match_operand:SI 2 "s_register_operand" ""))]
0438d37f 5075 "TARGET_32BIT && (!MEM_P (operands[1])) && BYTES_BIG_ENDIAN"
8a4d25d6 5076 [(set (match_dup 2) (match_dup 1))
5077 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
5078 ""
5079)
5080
1c274529 5081
5082(define_split
5083 [(set (match_operand:SI 0 "s_register_operand" "")
5084 (ior_xor:SI (and:SI (ashift:SI
5085 (match_operand:SI 1 "s_register_operand" "")
5086 (match_operand:SI 2 "const_int_operand" ""))
5087 (match_operand:SI 3 "const_int_operand" ""))
5088 (zero_extend:SI
5089 (match_operator 5 "subreg_lowpart_operator"
5090 [(match_operand:SI 4 "s_register_operand" "")]))))]
5091 "TARGET_32BIT
63787642 5092 && ((unsigned HOST_WIDE_INT) INTVAL (operands[3])
1c274529 5093 == (GET_MODE_MASK (GET_MODE (operands[5]))
5094 & (GET_MODE_MASK (GET_MODE (operands[5]))
5095 << (INTVAL (operands[2])))))"
5096 [(set (match_dup 0) (ior_xor:SI (ashift:SI (match_dup 1) (match_dup 2))
5097 (match_dup 4)))
5098 (set (match_dup 0) (zero_extend:SI (match_dup 5)))]
5099 "operands[5] = gen_lowpart (GET_MODE (operands[5]), operands[0]);"
5100)
5101
f7fbdd4a 5102(define_insn "*compareqi_eq0"
bd5b4116 5103 [(set (reg:CC_Z CC_REGNUM)
206ee9a2 5104 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
87b22bf7 5105 (const_int 0)))]
25f905c2 5106 "TARGET_32BIT"
596e5e8f 5107 "tst%?\\t%0, #255"
5108 [(set_attr "conds" "set")
d952d547 5109 (set_attr "predicable" "yes")
1b7da4ac 5110 (set_attr "predicable_short_it" "no")
5111 (set_attr "type" "logic_imm")]
cffb2a26 5112)
b11cae9e 5113
b11cae9e 5114(define_expand "extendhisi2"
ef51b8e1 5115 [(set (match_operand:SI 0 "s_register_operand" "")
5116 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
cffb2a26 5117 "TARGET_EITHER"
ef51b8e1 5118{
5119 if (TARGET_THUMB1)
5120 {
5121 emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1]));
5122 DONE;
5123 }
5124 if (MEM_P (operands[1]) && TARGET_ARM && !arm_arch4)
5125 {
5126 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
5127 DONE;
5128 }
ed29c566 5129
ef51b8e1 5130 if (!arm_arch6 && !MEM_P (operands[1]))
5131 {
5132 rtx t = gen_lowpart (SImode, operands[1]);
5133 rtx tmp = gen_reg_rtx (SImode);
5134 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
5135 emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (16)));
5136 DONE;
5137 }
5138})
cffb2a26 5139
ef51b8e1 5140(define_split
5141 [(parallel
5142 [(set (match_operand:SI 0 "register_operand" "")
5143 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))
5144 (clobber (match_scratch:SI 2 ""))])]
5145 "!arm_arch6"
5146 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
5147 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
5148{
5149 operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
5150})
25f7a26e 5151
25f905c2 5152;; This pattern will only be used when ldsh is not available
25f7a26e 5153(define_expand "extendhisi2_mem"
eab14235 5154 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 5155 (set (match_dup 3)
eab14235 5156 (zero_extend:SI (match_dup 7)))
25f7a26e 5157 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
5158 (set (match_operand:SI 0 "" "")
5159 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
cffb2a26 5160 "TARGET_ARM"
25f7a26e 5161 "
215b30b3 5162 {
5163 rtx mem1, mem2;
5164 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
5165
788fcce0 5166 mem1 = change_address (operands[1], QImode, addr);
29c05e22 5167 mem2 = change_address (operands[1], QImode,
5168 plus_constant (Pmode, addr, 1));
215b30b3 5169 operands[0] = gen_lowpart (SImode, operands[0]);
5170 operands[1] = mem1;
5171 operands[2] = gen_reg_rtx (SImode);
5172 operands[3] = gen_reg_rtx (SImode);
5173 operands[6] = gen_reg_rtx (SImode);
5174 operands[7] = mem2;
25f7a26e 5175
215b30b3 5176 if (BYTES_BIG_ENDIAN)
5177 {
5178 operands[4] = operands[2];
5179 operands[5] = operands[3];
5180 }
5181 else
5182 {
5183 operands[4] = operands[3];
5184 operands[5] = operands[2];
5185 }
5186 }"
5187)
b11cae9e 5188
ef51b8e1 5189(define_split
5190 [(set (match_operand:SI 0 "register_operand" "")
5191 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
5192 "!arm_arch6"
5193 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
5194 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
5195{
5196 operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
5197})
5198
a2cd141b 5199(define_insn "*arm_extendhisi2"
ef51b8e1 5200 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
e3f4ccee 5201 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,Uh")))]
a2cd141b 5202 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 5203 "@
5204 #
5205 ldr%(sh%)\\t%0, %1"
5206 [(set_attr "length" "8,4")
d82e788e 5207 (set_attr "type" "alu_shift_reg,load_byte")
e3f4ccee 5208 (set_attr "predicable" "yes")]
cffb2a26 5209)
f7fbdd4a 5210
25f905c2 5211;; ??? Check Thumb-2 pool range
a2cd141b 5212(define_insn "*arm_extendhisi2_v6"
5213 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
e3f4ccee 5214 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,Uh")))]
25f905c2 5215 "TARGET_32BIT && arm_arch6"
a2cd141b 5216 "@
5217 sxth%?\\t%0, %1
25f905c2 5218 ldr%(sh%)\\t%0, %1"
6b6abc9c 5219 [(set_attr "type" "extend,load_byte")
a2cd141b 5220 (set_attr "predicable" "yes")
e3f4ccee 5221 (set_attr "predicable_short_it" "no")]
a2cd141b 5222)
5223
5224(define_insn "*arm_extendhisi2addsi"
5225 [(set (match_operand:SI 0 "s_register_operand" "=r")
5226 (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
5227 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 5228 "TARGET_INT_SIMD"
a2cd141b 5229 "sxtah%?\\t%0, %2, %1"
1b7da4ac 5230 [(set_attr "type" "alu_shift_reg")]
a2cd141b 5231)
5232
c8f69309 5233(define_expand "extendqihi2"
5234 [(set (match_dup 2)
bed7d9a5 5235 (ashift:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")
c8f69309 5236 (const_int 24)))
9c08d1fa 5237 (set (match_operand:HI 0 "s_register_operand" "")
c8f69309 5238 (ashiftrt:SI (match_dup 2)
5239 (const_int 24)))]
cffb2a26 5240 "TARGET_ARM"
c8f69309 5241 "
215b30b3 5242 {
0438d37f 5243 if (arm_arch4 && MEM_P (operands[1]))
215b30b3 5244 {
5245 emit_insn (gen_rtx_SET (VOIDmode,
5246 operands[0],
5247 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
5248 DONE;
5249 }
5250 if (!s_register_operand (operands[1], QImode))
5251 operands[1] = copy_to_mode_reg (QImode, operands[1]);
5252 operands[0] = gen_lowpart (SImode, operands[0]);
5253 operands[1] = gen_lowpart (SImode, operands[1]);
5254 operands[2] = gen_reg_rtx (SImode);
5255 }"
5256)
f7fbdd4a 5257
25f905c2 5258(define_insn "*arm_extendqihi_insn"
b4e8a300 5259 [(set (match_operand:HI 0 "s_register_operand" "=r")
bed7d9a5 5260 (sign_extend:HI (match_operand:QI 1 "arm_extendqisi_mem_op" "Uq")))]
cffb2a26 5261 "TARGET_ARM && arm_arch4"
25f905c2 5262 "ldr%(sb%)\\t%0, %1"
a2cd141b 5263 [(set_attr "type" "load_byte")
e3f4ccee 5264 (set_attr "predicable" "yes")]
cffb2a26 5265)
3fc2009e 5266
b11cae9e 5267(define_expand "extendqisi2"
ef51b8e1 5268 [(set (match_operand:SI 0 "s_register_operand" "")
5269 (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")))]
cffb2a26 5270 "TARGET_EITHER"
ef51b8e1 5271{
5272 if (!arm_arch4 && MEM_P (operands[1]))
5273 operands[1] = copy_to_mode_reg (QImode, operands[1]);
a2cd141b 5274
ef51b8e1 5275 if (!arm_arch6 && !MEM_P (operands[1]))
5276 {
5277 rtx t = gen_lowpart (SImode, operands[1]);
5278 rtx tmp = gen_reg_rtx (SImode);
5279 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
5280 emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (24)));
5281 DONE;
5282 }
5283})
a2cd141b 5284
ef51b8e1 5285(define_split
5286 [(set (match_operand:SI 0 "register_operand" "")
5287 (sign_extend:SI (match_operand:QI 1 "register_operand" "")))]
5288 "!arm_arch6"
5289 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
5290 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))]
5291{
5292 operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
5293})
f7fbdd4a 5294
a2cd141b 5295(define_insn "*arm_extendqisi"
ef51b8e1 5296 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5297 (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
a2cd141b 5298 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 5299 "@
5300 #
5301 ldr%(sb%)\\t%0, %1"
5302 [(set_attr "length" "8,4")
d82e788e 5303 (set_attr "type" "alu_shift_reg,load_byte")
e3f4ccee 5304 (set_attr "predicable" "yes")]
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")
e3f4ccee 5316 (set_attr "predicable" "yes")]
a2cd141b 5317)
5318
5319(define_insn "*arm_extendqisi2addsi"
5320 [(set (match_operand:SI 0 "s_register_operand" "=r")
5321 (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
5322 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 5323 "TARGET_INT_SIMD"
a2cd141b 5324 "sxtab%?\\t%0, %2, %1"
d82e788e 5325 [(set_attr "type" "alu_shift_reg")
d952d547 5326 (set_attr "predicable" "yes")
5327 (set_attr "predicable_short_it" "no")]
a2cd141b 5328)
5329
caedf871 5330(define_expand "extendsfdf2"
5331 [(set (match_operand:DF 0 "s_register_operand" "")
5332 (float_extend:DF (match_operand:SF 1 "s_register_operand" "")))]
a50d7267 5333 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
caedf871 5334 ""
5335)
9b8516be 5336
5337/* HFmode -> DFmode conversions have to go through SFmode. */
5338(define_expand "extendhfdf2"
5339 [(set (match_operand:DF 0 "general_operand" "")
5340 (float_extend:DF (match_operand:HF 1 "general_operand" "")))]
5341 "TARGET_EITHER"
5342 "
5343 {
5344 rtx op1;
5345 op1 = convert_to_mode (SFmode, operands[1], 0);
5346 op1 = convert_to_mode (DFmode, op1, 0);
5347 emit_insn (gen_movdf (operands[0], op1));
5348 DONE;
5349 }"
5350)
b11cae9e 5351\f
5352;; Move insns (including loads and stores)
5353
5354;; XXX Just some ideas about movti.
9c08d1fa 5355;; I don't think these are a good idea on the arm, there just aren't enough
5356;; registers
b11cae9e 5357;;(define_expand "loadti"
9c08d1fa 5358;; [(set (match_operand:TI 0 "s_register_operand" "")
b11cae9e 5359;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
5360;; "" "")
5361
5362;;(define_expand "storeti"
5363;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
9c08d1fa 5364;; (match_operand:TI 1 "s_register_operand" ""))]
b11cae9e 5365;; "" "")
5366
5367;;(define_expand "movti"
5368;; [(set (match_operand:TI 0 "general_operand" "")
5369;; (match_operand:TI 1 "general_operand" ""))]
5370;; ""
5371;; "
5372;;{
5373;; rtx insn;
5374;;
0438d37f 5375;; if (MEM_P (operands[0]) && MEM_P (operands[1]))
b11cae9e 5376;; operands[1] = copy_to_reg (operands[1]);
0438d37f 5377;; if (MEM_P (operands[0]))
b11cae9e 5378;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
0438d37f 5379;; else if (MEM_P (operands[1]))
b11cae9e 5380;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
5381;; else
5382;; FAIL;
5383;;
5384;; emit_insn (insn);
5385;; DONE;
5386;;}")
5387
a2f10574 5388;; Recognize garbage generated above.
b11cae9e 5389
5390;;(define_insn ""
5391;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
5392;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
5393;; ""
5394;; "*
5395;; {
5396;; register mem = (which_alternative < 3);
0d66636f 5397;; register const char *template;
b11cae9e 5398;;
5399;; operands[mem] = XEXP (operands[mem], 0);
5400;; switch (which_alternative)
5401;; {
5402;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
5403;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
5404;; case 2: template = \"ldmia\\t%1, %M0\"; break;
5405;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
5406;; case 4: template = \"stmia\\t%0!, %M1\"; break;
5407;; case 5: template = \"stmia\\t%0, %M1\"; break;
5408;; }
e2348bcb 5409;; output_asm_insn (template, operands);
5410;; return \"\";
b11cae9e 5411;; }")
5412
cffb2a26 5413(define_expand "movdi"
5414 [(set (match_operand:DI 0 "general_operand" "")
5415 (match_operand:DI 1 "general_operand" ""))]
5416 "TARGET_EITHER"
5417 "
e1ba4a27 5418 if (can_create_pseudo_p ())
cffb2a26 5419 {
0438d37f 5420 if (!REG_P (operands[0]))
b2778788 5421 operands[1] = force_reg (DImode, operands[1]);
cffb2a26 5422 }
5423 "
5424)
b11cae9e 5425
cffb2a26 5426(define_insn "*arm_movdi"
353cf59a 5427 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, q, m")
5428 (match_operand:DI 1 "di_operand" "rDa,Db,Dc,mi,q"))]
cde1623a 5429 "TARGET_32BIT
b805622c 5430 && !(TARGET_HARD_FLOAT && TARGET_VFP)
b2778788 5431 && !TARGET_IWMMXT
5432 && ( register_operand (operands[0], DImode)
5433 || register_operand (operands[1], DImode))"
b11cae9e 5434 "*
d51f92df 5435 switch (which_alternative)
5436 {
5437 case 0:
5438 case 1:
5439 case 2:
5440 return \"#\";
5441 default:
26ff80c0 5442 return output_move_double (operands, true, NULL);
d51f92df 5443 }
cffb2a26 5444 "
359a6e9f 5445 [(set_attr "length" "8,12,16,8,8")
1b7da4ac 5446 (set_attr "type" "multiple,multiple,multiple,load2,store2")
cde1623a 5447 (set_attr "arm_pool_range" "*,*,*,1020,*")
8848d797 5448 (set_attr "arm_neg_pool_range" "*,*,*,1004,*")
42e1de19 5449 (set_attr "thumb2_pool_range" "*,*,*,4094,*")
cde1623a 5450 (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
cffb2a26 5451)
5452
d51f92df 5453(define_split
5454 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
e6dd3afa 5455 (match_operand:ANY64 1 "immediate_operand" ""))]
25f905c2 5456 "TARGET_32BIT
d51f92df 5457 && reload_completed
5458 && (arm_const_double_inline_cost (operands[1])
861033d5 5459 <= arm_max_const_double_inline_cost ())"
d51f92df 5460 [(const_int 0)]
5461 "
5462 arm_split_constant (SET, SImode, curr_insn,
5463 INTVAL (gen_lowpart (SImode, operands[1])),
5464 gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
5465 arm_split_constant (SET, SImode, curr_insn,
5466 INTVAL (gen_highpart_mode (SImode,
5467 GET_MODE (operands[0]),
5468 operands[1])),
5469 gen_highpart (SImode, operands[0]), NULL_RTX, 0);
5470 DONE;
5471 "
5472)
5473
e5ba9289 5474; If optimizing for size, or if we have load delay slots, then
5475; we want to split the constant into two separate operations.
5476; In both cases this may split a trivial part into a single data op
5477; leaving a single complex constant to load. We can also get longer
5478; offsets in a LDR which means we get better chances of sharing the pool
5479; entries. Finally, we can normally do a better job of scheduling
5480; LDR instructions than we can with LDM.
5481; This pattern will only match if the one above did not.
5482(define_split
5483 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
5484 (match_operand:ANY64 1 "const_double_operand" ""))]
5485 "TARGET_ARM && reload_completed
5486 && arm_const_double_by_parts (operands[1])"
5487 [(set (match_dup 0) (match_dup 1))
5488 (set (match_dup 2) (match_dup 3))]
5489 "
5490 operands[2] = gen_highpart (SImode, operands[0]);
5491 operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
5492 operands[1]);
5493 operands[0] = gen_lowpart (SImode, operands[0]);
5494 operands[1] = gen_lowpart (SImode, operands[1]);
5495 "
5496)
5497
d51f92df 5498(define_split
5499 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
5500 (match_operand:ANY64 1 "arm_general_register_operand" ""))]
5501 "TARGET_EITHER && reload_completed"
5502 [(set (match_dup 0) (match_dup 1))
5503 (set (match_dup 2) (match_dup 3))]
5504 "
5505 operands[2] = gen_highpart (SImode, operands[0]);
5506 operands[3] = gen_highpart (SImode, operands[1]);
5507 operands[0] = gen_lowpart (SImode, operands[0]);
5508 operands[1] = gen_lowpart (SImode, operands[1]);
5509
5510 /* Handle a partial overlap. */
5511 if (rtx_equal_p (operands[0], operands[3]))
5512 {
5513 rtx tmp0 = operands[0];
5514 rtx tmp1 = operands[1];
5515
5516 operands[0] = operands[2];
5517 operands[1] = operands[3];
5518 operands[2] = tmp0;
5519 operands[3] = tmp1;
5520 }
5521 "
5522)
5523
a8a3b539 5524;; We can't actually do base+index doubleword loads if the index and
5525;; destination overlap. Split here so that we at least have chance to
5526;; schedule.
5527(define_split
5528 [(set (match_operand:DI 0 "s_register_operand" "")
5529 (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
5530 (match_operand:SI 2 "s_register_operand" ""))))]
5531 "TARGET_LDRD
5532 && reg_overlap_mentioned_p (operands[0], operands[1])
5533 && reg_overlap_mentioned_p (operands[0], operands[2])"
5534 [(set (match_dup 4)
5535 (plus:SI (match_dup 1)
5536 (match_dup 2)))
5537 (set (match_dup 0)
5538 (mem:DI (match_dup 4)))]
5539 "
5540 operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
5541 "
5542)
5543
9c08d1fa 5544(define_expand "movsi"
5545 [(set (match_operand:SI 0 "general_operand" "")
5546 (match_operand:SI 1 "general_operand" ""))]
cffb2a26 5547 "TARGET_EITHER"
9c08d1fa 5548 "
befb0bac 5549 {
e348ff3e 5550 rtx base, offset, tmp;
5551
25f905c2 5552 if (TARGET_32BIT)
9c08d1fa 5553 {
674a8f0b 5554 /* Everything except mem = const or mem = mem can be done easily. */
0438d37f 5555 if (MEM_P (operands[0]))
cffb2a26 5556 operands[1] = force_reg (SImode, operands[1]);
a2cd141b 5557 if (arm_general_register_operand (operands[0], SImode)
0438d37f 5558 && CONST_INT_P (operands[1])
cffb2a26 5559 && !(const_ok_for_arm (INTVAL (operands[1]))
5560 || const_ok_for_arm (~INTVAL (operands[1]))))
5561 {
96f57e36 5562 arm_split_constant (SET, SImode, NULL_RTX,
5563 INTVAL (operands[1]), operands[0], NULL_RTX,
e1ba4a27 5564 optimize && can_create_pseudo_p ());
cffb2a26 5565 DONE;
5566 }
5567 }
25f905c2 5568 else /* TARGET_THUMB1... */
cffb2a26 5569 {
e1ba4a27 5570 if (can_create_pseudo_p ())
cffb2a26 5571 {
0438d37f 5572 if (!REG_P (operands[0]))
cffb2a26 5573 operands[1] = force_reg (SImode, operands[1]);
5574 }
9c08d1fa 5575 }
f655717d 5576
e348ff3e 5577 if (ARM_OFFSETS_MUST_BE_WITHIN_SECTIONS_P)
5578 {
5579 split_const (operands[1], &base, &offset);
5580 if (GET_CODE (base) == SYMBOL_REF
5581 && !offset_within_block_p (base, INTVAL (offset)))
5582 {
b308ddcf 5583 tmp = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
e348ff3e 5584 emit_move_insn (tmp, base);
5585 emit_insn (gen_addsi3 (operands[0], tmp, offset));
5586 DONE;
5587 }
5588 }
5589
f655717d 5590 /* Recognize the case where operand[1] is a reference to thread-local
5591 data and load its address to a register. */
5592 if (arm_tls_referenced_p (operands[1]))
5593 {
5594 rtx tmp = operands[1];
5595 rtx addend = NULL;
5596
5597 if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
5598 {
5599 addend = XEXP (XEXP (tmp, 0), 1);
5600 tmp = XEXP (XEXP (tmp, 0), 0);
5601 }
5602
5603 gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
5604 gcc_assert (SYMBOL_REF_TLS_MODEL (tmp) != 0);
5605
e1ba4a27 5606 tmp = legitimize_tls_address (tmp,
5607 !can_create_pseudo_p () ? operands[0] : 0);
f655717d 5608 if (addend)
5609 {
5610 tmp = gen_rtx_PLUS (SImode, tmp, addend);
5611 tmp = force_operand (tmp, operands[0]);
5612 }
5613 operands[1] = tmp;
5614 }
5615 else if (flag_pic
5616 && (CONSTANT_P (operands[1])
5617 || symbol_mentioned_p (operands[1])
5618 || label_mentioned_p (operands[1])))
5619 operands[1] = legitimize_pic_address (operands[1], SImode,
e1ba4a27 5620 (!can_create_pseudo_p ()
5621 ? operands[0]
5622 : 0));
befb0bac 5623 }
215b30b3 5624 "
5625)
9c08d1fa 5626
d0e6a121 5627;; The ARM LO_SUM and HIGH are backwards - HIGH sets the low bits, and
5628;; LO_SUM adds in the high bits. Fortunately these are opaque operations
5629;; so this does not matter.
5630(define_insn "*arm_movt"
5631 [(set (match_operand:SI 0 "nonimmediate_operand" "=r")
5632 (lo_sum:SI (match_operand:SI 1 "nonimmediate_operand" "0")
5633 (match_operand:SI 2 "general_operand" "i")))]
c9b2ce40 5634 "arm_arch_thumb2"
d0e6a121 5635 "movt%?\t%0, #:upper16:%c2"
5636 [(set_attr "predicable" "yes")
d952d547 5637 (set_attr "predicable_short_it" "no")
1b7da4ac 5638 (set_attr "length" "4")
5639 (set_attr "type" "mov_imm")]
d0e6a121 5640)
5641
cffb2a26 5642(define_insn "*arm_movsi_insn"
aaa37ad6 5643 [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,rk,m")
110eae03 5644 (match_operand:SI 1 "general_operand" "rk, I,K,j,mi,rk"))]
755eb2b4 5645 "TARGET_ARM && ! TARGET_IWMMXT
a2cd141b 5646 && !(TARGET_HARD_FLOAT && TARGET_VFP)
cffb2a26 5647 && ( register_operand (operands[0], SImode)
5648 || register_operand (operands[1], SImode))"
f7fbdd4a 5649 "@
aaa37ad6 5650 mov%?\\t%0, %1
f7fbdd4a 5651 mov%?\\t%0, %1
5652 mvn%?\\t%0, #%B1
25f905c2 5653 movw%?\\t%0, %1
f7fbdd4a 5654 ldr%?\\t%0, %1
5655 str%?\\t%1, %0"
1aed5204 5656 [(set_attr "type" "mov_reg,mov_imm,mvn_imm,mov_imm,load1,store1")
0d66636f 5657 (set_attr "predicable" "yes")
aaa37ad6 5658 (set_attr "pool_range" "*,*,*,*,4096,*")
5659 (set_attr "neg_pool_range" "*,*,*,*,4084,*")]
cffb2a26 5660)
87b22bf7 5661
5662(define_split
a2cd141b 5663 [(set (match_operand:SI 0 "arm_general_register_operand" "")
87b22bf7 5664 (match_operand:SI 1 "const_int_operand" ""))]
25f905c2 5665 "TARGET_32BIT
215b30b3 5666 && (!(const_ok_for_arm (INTVAL (operands[1]))
5667 || const_ok_for_arm (~INTVAL (operands[1]))))"
87b22bf7 5668 [(clobber (const_int 0))]
5669 "
96f57e36 5670 arm_split_constant (SET, SImode, NULL_RTX,
5671 INTVAL (operands[1]), operands[0], NULL_RTX, 0);
87b22bf7 5672 DONE;
215b30b3 5673 "
5674)
9c08d1fa 5675
861033d5 5676;; A normal way to do (symbol + offset) requires three instructions at least
5677;; (depends on how big the offset is) as below:
5678;; movw r0, #:lower16:g
5679;; movw r0, #:upper16:g
5680;; adds r0, #4
5681;;
5682;; A better way would be:
5683;; movw r0, #:lower16:g+4
5684;; movw r0, #:upper16:g+4
5685;;
5686;; The limitation of this way is that the length of offset should be a 16-bit
5687;; signed value, because current assembler only supports REL type relocation for
5688;; such case. If the more powerful RELA type is supported in future, we should
5689;; update this pattern to go with better way.
5690(define_split
5691 [(set (match_operand:SI 0 "arm_general_register_operand" "")
5692 (const:SI (plus:SI (match_operand:SI 1 "general_operand" "")
5693 (match_operand:SI 2 "const_int_operand" ""))))]
5694 "TARGET_THUMB2
5695 && arm_disable_literal_pool
5696 && reload_completed
5697 && GET_CODE (operands[1]) == SYMBOL_REF"
5698 [(clobber (const_int 0))]
5699 "
5700 int offset = INTVAL (operands[2]);
5701
5702 if (offset < -0x8000 || offset > 0x7fff)
5703 {
5704 arm_emit_movpair (operands[0], operands[1]);
5705 emit_insn (gen_rtx_SET (SImode, operands[0],
5706 gen_rtx_PLUS (SImode, operands[0], operands[2])));
5707 }
5708 else
5709 {
5710 rtx op = gen_rtx_CONST (SImode,
5711 gen_rtx_PLUS (SImode, operands[1], operands[2]));
5712 arm_emit_movpair (operands[0], op);
5713 }
5714 "
5715)
5716
b8d5d078 5717;; Split symbol_refs at the later stage (after cprop), instead of generating
5718;; movt/movw pair directly at expand. Otherwise corresponding high_sum
5719;; and lo_sum would be merged back into memory load at cprop. However,
5720;; if the default is to prefer movt/movw rather than a load from the constant
5721;; pool, the performance is better.
5722(define_split
5723 [(set (match_operand:SI 0 "arm_general_register_operand" "")
5724 (match_operand:SI 1 "general_operand" ""))]
5725 "TARGET_32BIT
5726 && TARGET_USE_MOVT && GET_CODE (operands[1]) == SYMBOL_REF
5727 && !flag_pic && !target_word_relocations
5728 && !arm_tls_referenced_p (operands[1])"
5729 [(clobber (const_int 0))]
5730{
5731 arm_emit_movpair (operands[0], operands[1]);
5732 DONE;
5733})
5734
bc360af8 5735;; When generating pic, we need to load the symbol offset into a register.
5736;; So that the optimizer does not confuse this with a normal symbol load
5737;; we use an unspec. The offset will be loaded from a constant pool entry,
5738;; since that is the only type of relocation we can use.
cffb2a26 5739
bc360af8 5740;; Wrap calculation of the whole PIC address in a single pattern for the
5741;; benefit of optimizers, particularly, PRE and HOIST. Calculation of
5742;; a PIC address involves two loads from memory, so we want to CSE it
5743;; as often as possible.
5744;; This pattern will be split into one of the pic_load_addr_* patterns
5745;; and a move after GCSE optimizations.
5746;;
5747;; Note: Update arm.c: legitimize_pic_address() when changing this pattern.
5748(define_expand "calculate_pic_address"
94f8caca 5749 [(set (match_operand:SI 0 "register_operand" "")
5750 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "")
5751 (unspec:SI [(match_operand:SI 2 "" "")]
5752 UNSPEC_PIC_SYM))))]
5753 "flag_pic"
5754)
5755
5756;; Split calculate_pic_address into pic_load_addr_* and a move.
5757(define_split
5758 [(set (match_operand:SI 0 "register_operand" "")
5759 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "")
5760 (unspec:SI [(match_operand:SI 2 "" "")]
5761 UNSPEC_PIC_SYM))))]
5762 "flag_pic"
5763 [(set (match_dup 3) (unspec:SI [(match_dup 2)] UNSPEC_PIC_SYM))
5764 (set (match_dup 0) (mem:SI (plus:SI (match_dup 1) (match_dup 3))))]
5765 "operands[3] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];"
5766)
5767
350ccca5 5768;; operand1 is the memory address to go into
5769;; pic_load_addr_32bit.
5770;; operand2 is the PIC label to be emitted
5771;; from pic_add_dot_plus_eight.
5772;; We do this to allow hoisting of the entire insn.
5773(define_insn_and_split "pic_load_addr_unified"
5774 [(set (match_operand:SI 0 "s_register_operand" "=r,r,l")
5775 (unspec:SI [(match_operand:SI 1 "" "mX,mX,mX")
5776 (match_operand:SI 2 "" "")]
5777 UNSPEC_PIC_UNIFIED))]
5778 "flag_pic"
5779 "#"
5780 "&& reload_completed"
5781 [(set (match_dup 0) (unspec:SI [(match_dup 1)] UNSPEC_PIC_SYM))
5782 (set (match_dup 0) (unspec:SI [(match_dup 0) (match_dup 3)
5783 (match_dup 2)] UNSPEC_PIC_BASE))]
5784 "operands[3] = TARGET_THUMB ? GEN_INT (4) : GEN_INT (8);"
5785 [(set_attr "type" "load1,load1,load1")
42e1de19 5786 (set_attr "pool_range" "4096,4094,1022")
350ccca5 5787 (set_attr "neg_pool_range" "4084,0,0")
5788 (set_attr "arch" "a,t2,t1")
5789 (set_attr "length" "8,6,4")]
5790)
5791
67336bcf 5792;; The rather odd constraints on the following are to force reload to leave
5793;; the insn alone, and to force the minipool generation pass to then move
5794;; the GOT symbol to memory.
849170fd 5795
b3cd5f55 5796(define_insn "pic_load_addr_32bit"
849170fd 5797 [(set (match_operand:SI 0 "s_register_operand" "=r")
e1159bbe 5798 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
b3cd5f55 5799 "TARGET_32BIT && flag_pic"
67336bcf 5800 "ldr%?\\t%0, %1"
a2cd141b 5801 [(set_attr "type" "load1")
42e1de19 5802 (set (attr "pool_range")
5803 (if_then_else (eq_attr "is_thumb" "no")
5804 (const_int 4096)
5805 (const_int 4094)))
b3cd5f55 5806 (set (attr "neg_pool_range")
5807 (if_then_else (eq_attr "is_thumb" "no")
5808 (const_int 4084)
5809 (const_int 0)))]
8c4d8060 5810)
5811
25f905c2 5812(define_insn "pic_load_addr_thumb1"
8c4d8060 5813 [(set (match_operand:SI 0 "s_register_operand" "=l")
e1159bbe 5814 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
25f905c2 5815 "TARGET_THUMB1 && flag_pic"
8c4d8060 5816 "ldr\\t%0, %1"
a2cd141b 5817 [(set_attr "type" "load1")
42e1de19 5818 (set (attr "pool_range") (const_int 1018))]
cffb2a26 5819)
849170fd 5820
cffb2a26 5821(define_insn "pic_add_dot_plus_four"
15d5d060 5822 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5823 (unspec:SI [(match_operand:SI 1 "register_operand" "0")
5824 (const_int 4)
beef0fb5 5825 (match_operand 2 "" "")]
5826 UNSPEC_PIC_BASE))]
b3cd5f55 5827 "TARGET_THUMB"
cffb2a26 5828 "*
6cdcb15c 5829 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5830 INTVAL (operands[2]));
cffb2a26 5831 return \"add\\t%0, %|pc\";
5832 "
1b7da4ac 5833 [(set_attr "length" "2")
112eda6f 5834 (set_attr "type" "alu_sreg")]
cffb2a26 5835)
849170fd 5836
5837(define_insn "pic_add_dot_plus_eight"
15d5d060 5838 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5839 (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5840 (const_int 8)
beef0fb5 5841 (match_operand 2 "" "")]
5842 UNSPEC_PIC_BASE))]
f655717d 5843 "TARGET_ARM"
c4034607 5844 "*
6cdcb15c 5845 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5846 INTVAL (operands[2]));
15d5d060 5847 return \"add%?\\t%0, %|pc, %1\";
cffb2a26 5848 "
1b7da4ac 5849 [(set_attr "predicable" "yes")
112eda6f 5850 (set_attr "type" "alu_sreg")]
cffb2a26 5851)
849170fd 5852
f655717d 5853(define_insn "tls_load_dot_plus_eight"
cc071db6 5854 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5855 (mem:SI (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5856 (const_int 8)
beef0fb5 5857 (match_operand 2 "" "")]
5858 UNSPEC_PIC_BASE)))]
f655717d 5859 "TARGET_ARM"
5860 "*
6cdcb15c 5861 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5862 INTVAL (operands[2]));
f655717d 5863 return \"ldr%?\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_eight\";
5864 "
1b7da4ac 5865 [(set_attr "predicable" "yes")
5866 (set_attr "type" "load1")]
f655717d 5867)
5868
5869;; PIC references to local variables can generate pic_add_dot_plus_eight
5870;; followed by a load. These sequences can be crunched down to
5871;; tls_load_dot_plus_eight by a peephole.
5872
5873(define_peephole2
c0c1fba5 5874 [(set (match_operand:SI 0 "register_operand" "")
5875 (unspec:SI [(match_operand:SI 3 "register_operand" "")
5876 (const_int 8)
5877 (match_operand 1 "" "")]
5878 UNSPEC_PIC_BASE))
2d05dfad 5879 (set (match_operand:SI 2 "arm_general_register_operand" "")
5880 (mem:SI (match_dup 0)))]
f655717d 5881 "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
c0c1fba5 5882 [(set (match_dup 2)
5883 (mem:SI (unspec:SI [(match_dup 3)
5884 (const_int 8)
5885 (match_dup 1)]
5886 UNSPEC_PIC_BASE)))]
f655717d 5887 ""
5888)
5889
bac7fc85 5890(define_insn "pic_offset_arm"
5891 [(set (match_operand:SI 0 "register_operand" "=r")
5892 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
5893 (unspec:SI [(match_operand:SI 2 "" "X")]
5894 UNSPEC_PIC_OFFSET))))]
5895 "TARGET_VXWORKS_RTP && TARGET_ARM && flag_pic"
5896 "ldr%?\\t%0, [%1,%2]"
5897 [(set_attr "type" "load1")]
5898)
5899
95373f08 5900(define_expand "builtin_setjmp_receiver"
5901 [(label_ref (match_operand 0 "" ""))]
5902 "flag_pic"
5903 "
5904{
b935b306 5905 /* r3 is clobbered by set/longjmp, so we can use it as a scratch
5906 register. */
2cb7d577 5907 if (arm_pic_register != INVALID_REGNUM)
5908 arm_load_pic_register (1UL << 3);
95373f08 5909 DONE;
5910}")
5911
9c08d1fa 5912;; If copying one reg to another we can set the condition codes according to
5913;; its value. Such a move is common after a return from subroutine and the
5914;; result is being tested against zero.
5915
f7fbdd4a 5916(define_insn "*movsi_compare0"
bd5b4116 5917 [(set (reg:CC CC_REGNUM)
cffb2a26 5918 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
5919 (const_int 0)))
5920 (set (match_operand:SI 0 "s_register_operand" "=r,r")
5921 (match_dup 1))]
25f905c2 5922 "TARGET_32BIT"
e2348bcb 5923 "@
40dbec34 5924 cmp%?\\t%0, #0
25f905c2 5925 sub%.\\t%0, %1, #0"
65f68e55 5926 [(set_attr "conds" "set")
d82e788e 5927 (set_attr "type" "alus_imm,alus_imm")]
cffb2a26 5928)
b11cae9e 5929
b11cae9e 5930;; Subroutine to store a half word from a register into memory.
5931;; Operand 0 is the source register (HImode)
c8f69309 5932;; Operand 1 is the destination address in a register (SImode)
b11cae9e 5933
9c08d1fa 5934;; In both this routine and the next, we must be careful not to spill
01cc3b75 5935;; a memory address of reg+large_const into a separate PLUS insn, since this
9c08d1fa 5936;; can generate unrecognizable rtl.
5937
b11cae9e 5938(define_expand "storehi"
c8f69309 5939 [;; store the low byte
f082f1c4 5940 (set (match_operand 1 "" "") (match_dup 3))
b11cae9e 5941 ;; extract the high byte
c8f69309 5942 (set (match_dup 2)
5943 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
b11cae9e 5944 ;; store the high byte
787f8210 5945 (set (match_dup 4) (match_dup 5))]
cffb2a26 5946 "TARGET_ARM"
b11cae9e 5947 "
215b30b3 5948 {
537ffcfc 5949 rtx op1 = operands[1];
5950 rtx addr = XEXP (op1, 0);
215b30b3 5951 enum rtx_code code = GET_CODE (addr);
5952
0438d37f 5953 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
215b30b3 5954 || code == MINUS)
537ffcfc 5955 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
215b30b3 5956
537ffcfc 5957 operands[4] = adjust_address (op1, QImode, 1);
e513d163 5958 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 5959 operands[3] = gen_lowpart (QImode, operands[0]);
5960 operands[0] = gen_lowpart (SImode, operands[0]);
787f8210 5961 operands[2] = gen_reg_rtx (SImode);
5962 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 5963 }"
5964)
b11cae9e 5965
c7597b5d 5966(define_expand "storehi_bigend"
f082f1c4 5967 [(set (match_dup 4) (match_dup 3))
c7597b5d 5968 (set (match_dup 2)
5969 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
787f8210 5970 (set (match_operand 1 "" "") (match_dup 5))]
cffb2a26 5971 "TARGET_ARM"
b11cae9e 5972 "
215b30b3 5973 {
537ffcfc 5974 rtx op1 = operands[1];
5975 rtx addr = XEXP (op1, 0);
215b30b3 5976 enum rtx_code code = GET_CODE (addr);
5977
0438d37f 5978 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
215b30b3 5979 || code == MINUS)
537ffcfc 5980 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
215b30b3 5981
537ffcfc 5982 operands[4] = adjust_address (op1, QImode, 1);
e513d163 5983 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 5984 operands[3] = gen_lowpart (QImode, operands[0]);
5985 operands[0] = gen_lowpart (SImode, operands[0]);
5986 operands[2] = gen_reg_rtx (SImode);
787f8210 5987 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 5988 }"
5989)
c7597b5d 5990
5991;; Subroutine to store a half word integer constant into memory.
5992(define_expand "storeinthi"
f082f1c4 5993 [(set (match_operand 0 "" "")
787f8210 5994 (match_operand 1 "" ""))
9e8503e6 5995 (set (match_dup 3) (match_dup 2))]
cffb2a26 5996 "TARGET_ARM"
c7597b5d 5997 "
215b30b3 5998 {
5999 HOST_WIDE_INT value = INTVAL (operands[1]);
6000 rtx addr = XEXP (operands[0], 0);
537ffcfc 6001 rtx op0 = operands[0];
215b30b3 6002 enum rtx_code code = GET_CODE (addr);
c7597b5d 6003
0438d37f 6004 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
215b30b3 6005 || code == MINUS)
537ffcfc 6006 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
c7597b5d 6007
215b30b3 6008 operands[1] = gen_reg_rtx (SImode);
6009 if (BYTES_BIG_ENDIAN)
6010 {
6011 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
6012 if ((value & 255) == ((value >> 8) & 255))
6013 operands[2] = operands[1];
6014 else
6015 {
6016 operands[2] = gen_reg_rtx (SImode);
6017 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
6018 }
6019 }
6020 else
6021 {
6022 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
6023 if ((value & 255) == ((value >> 8) & 255))
6024 operands[2] = operands[1];
6025 else
6026 {
6027 operands[2] = gen_reg_rtx (SImode);
6028 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
6029 }
6030 }
c7597b5d 6031
537ffcfc 6032 operands[3] = adjust_address (op0, QImode, 1);
e513d163 6033 operands[0] = adjust_address (operands[0], QImode, 0);
9e8503e6 6034 operands[2] = gen_lowpart (QImode, operands[2]);
787f8210 6035 operands[1] = gen_lowpart (QImode, operands[1]);
215b30b3 6036 }"
6037)
b11cae9e 6038
f7fbdd4a 6039(define_expand "storehi_single_op"
6040 [(set (match_operand:HI 0 "memory_operand" "")
6041 (match_operand:HI 1 "general_operand" ""))]
25f905c2 6042 "TARGET_32BIT && arm_arch4"
f7fbdd4a 6043 "
215b30b3 6044 if (!s_register_operand (operands[1], HImode))
f7fbdd4a 6045 operands[1] = copy_to_mode_reg (HImode, operands[1]);
215b30b3 6046 "
6047)
f7fbdd4a 6048
b11cae9e 6049(define_expand "movhi"
6050 [(set (match_operand:HI 0 "general_operand" "")
c8f69309 6051 (match_operand:HI 1 "general_operand" ""))]
cffb2a26 6052 "TARGET_EITHER"
b11cae9e 6053 "
cffb2a26 6054 if (TARGET_ARM)
b11cae9e 6055 {
e1ba4a27 6056 if (can_create_pseudo_p ())
cffb2a26 6057 {
0438d37f 6058 if (MEM_P (operands[0]))
b11cae9e 6059 {
cffb2a26 6060 if (arm_arch4)
6061 {
6062 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
6063 DONE;
6064 }
0438d37f 6065 if (CONST_INT_P (operands[1]))
cffb2a26 6066 emit_insn (gen_storeinthi (operands[0], operands[1]));
c7597b5d 6067 else
cffb2a26 6068 {
0438d37f 6069 if (MEM_P (operands[1]))
cffb2a26 6070 operands[1] = force_reg (HImode, operands[1]);
6071 if (BYTES_BIG_ENDIAN)
6072 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
6073 else
6074 emit_insn (gen_storehi (operands[1], operands[0]));
6075 }
6076 DONE;
b11cae9e 6077 }
cffb2a26 6078 /* Sign extend a constant, and keep it in an SImode reg. */
0438d37f 6079 else if (CONST_INT_P (operands[1]))
9c08d1fa 6080 {
cffb2a26 6081 rtx reg = gen_reg_rtx (SImode);
6082 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
6083
6084 /* If the constant is already valid, leave it alone. */
215b30b3 6085 if (!const_ok_for_arm (val))
cffb2a26 6086 {
6087 /* If setting all the top bits will make the constant
6088 loadable in a single instruction, then set them.
6089 Otherwise, sign extend the number. */
6090
215b30b3 6091 if (const_ok_for_arm (~(val | ~0xffff)))
cffb2a26 6092 val |= ~0xffff;
6093 else if (val & 0x8000)
6094 val |= ~0xffff;
6095 }
6096
6097 emit_insn (gen_movsi (reg, GEN_INT (val)));
9e8503e6 6098 operands[1] = gen_lowpart (HImode, reg);
9c08d1fa 6099 }
e1ba4a27 6100 else if (arm_arch4 && optimize && can_create_pseudo_p ()
0438d37f 6101 && MEM_P (operands[1]))
0045890a 6102 {
6103 rtx reg = gen_reg_rtx (SImode);
6104
6105 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
6106 operands[1] = gen_lowpart (HImode, reg);
6107 }
215b30b3 6108 else if (!arm_arch4)
f7fbdd4a 6109 {
0438d37f 6110 if (MEM_P (operands[1]))
cffb2a26 6111 {
c1a66faf 6112 rtx base;
6113 rtx offset = const0_rtx;
6114 rtx reg = gen_reg_rtx (SImode);
6115
0438d37f 6116 if ((REG_P (base = XEXP (operands[1], 0))
c1a66faf 6117 || (GET_CODE (base) == PLUS
0438d37f 6118 && (CONST_INT_P (offset = XEXP (base, 1)))
c1a66faf 6119 && ((INTVAL(offset) & 1) != 1)
0438d37f 6120 && REG_P (base = XEXP (base, 0))))
c1a66faf 6121 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
206ee9a2 6122 {
8deb3959 6123 rtx new_rtx;
c1a66faf 6124
8deb3959 6125 new_rtx = widen_memory_access (operands[1], SImode,
6126 ((INTVAL (offset) & ~3)
6127 - INTVAL (offset)));
6128 emit_insn (gen_movsi (reg, new_rtx));
c1a66faf 6129 if (((INTVAL (offset) & 2) != 0)
6130 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
6131 {
6132 rtx reg2 = gen_reg_rtx (SImode);
6133
6134 emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
6135 reg = reg2;
6136 }
206ee9a2 6137 }
c1a66faf 6138 else
6139 emit_insn (gen_movhi_bytes (reg, operands[1]));
6140
6141 operands[1] = gen_lowpart (HImode, reg);
cffb2a26 6142 }
6143 }
6144 }
674a8f0b 6145 /* Handle loading a large integer during reload. */
0438d37f 6146 else if (CONST_INT_P (operands[1])
215b30b3 6147 && !const_ok_for_arm (INTVAL (operands[1]))
6148 && !const_ok_for_arm (~INTVAL (operands[1])))
cffb2a26 6149 {
6150 /* Writing a constant to memory needs a scratch, which should
6151 be handled with SECONDARY_RELOADs. */
0438d37f 6152 gcc_assert (REG_P (operands[0]));
cffb2a26 6153
6154 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
6155 emit_insn (gen_movsi (operands[0], operands[1]));
6156 DONE;
6157 }
6158 }
25f905c2 6159 else if (TARGET_THUMB2)
6160 {
6161 /* Thumb-2 can do everything except mem=mem and mem=const easily. */
e1ba4a27 6162 if (can_create_pseudo_p ())
25f905c2 6163 {
0438d37f 6164 if (!REG_P (operands[0]))
25f905c2 6165 operands[1] = force_reg (HImode, operands[1]);
6166 /* Zero extend a constant, and keep it in an SImode reg. */
0438d37f 6167 else if (CONST_INT_P (operands[1]))
25f905c2 6168 {
6169 rtx reg = gen_reg_rtx (SImode);
6170 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
6171
6172 emit_insn (gen_movsi (reg, GEN_INT (val)));
6173 operands[1] = gen_lowpart (HImode, reg);
6174 }
6175 }
6176 }
6177 else /* TARGET_THUMB1 */
cffb2a26 6178 {
e1ba4a27 6179 if (can_create_pseudo_p ())
cffb2a26 6180 {
0438d37f 6181 if (CONST_INT_P (operands[1]))
6cffc037 6182 {
6183 rtx reg = gen_reg_rtx (SImode);
6184
6185 emit_insn (gen_movsi (reg, operands[1]));
6186 operands[1] = gen_lowpart (HImode, reg);
6187 }
cffb2a26 6188
6189 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 6190 happen if we are passed a SP (never OK for HImode/QImode) or
bc409cb4 6191 virtual register (also rejected as illegitimate for HImode/QImode)
6192 relative address. */
cffb2a26 6193 /* ??? This should perhaps be fixed elsewhere, for instance, in
6194 fixup_stack_1, by checking for other kinds of invalid addresses,
6195 e.g. a bare reference to a virtual register. This may confuse the
6196 alpha though, which must handle this case differently. */
0438d37f 6197 if (MEM_P (operands[0])
215b30b3 6198 && !memory_address_p (GET_MODE (operands[0]),
6199 XEXP (operands[0], 0)))
537ffcfc 6200 operands[0]
6201 = replace_equiv_address (operands[0],
6202 copy_to_reg (XEXP (operands[0], 0)));
cffb2a26 6203
0438d37f 6204 if (MEM_P (operands[1])
215b30b3 6205 && !memory_address_p (GET_MODE (operands[1]),
6206 XEXP (operands[1], 0)))
537ffcfc 6207 operands[1]
6208 = replace_equiv_address (operands[1],
6209 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 6210
0438d37f 6211 if (MEM_P (operands[1]) && optimize > 0)
6cffc037 6212 {
6213 rtx reg = gen_reg_rtx (SImode);
6214
6215 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
6216 operands[1] = gen_lowpart (HImode, reg);
6217 }
6218
0438d37f 6219 if (MEM_P (operands[0]))
6cffc037 6220 operands[1] = force_reg (HImode, operands[1]);
cffb2a26 6221 }
0438d37f 6222 else if (CONST_INT_P (operands[1])
234f6557 6223 && !satisfies_constraint_I (operands[1]))
cffb2a26 6224 {
6cffc037 6225 /* Handle loading a large integer during reload. */
6226
cffb2a26 6227 /* Writing a constant to memory needs a scratch, which should
6228 be handled with SECONDARY_RELOADs. */
0438d37f 6229 gcc_assert (REG_P (operands[0]));
cffb2a26 6230
1a83b3ff 6231 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
cffb2a26 6232 emit_insn (gen_movsi (operands[0], operands[1]));
6233 DONE;
6234 }
b11cae9e 6235 }
cffb2a26 6236 "
6237)
6238
25f7a26e 6239(define_expand "movhi_bytes"
eab14235 6240 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 6241 (set (match_dup 3)
eab14235 6242 (zero_extend:SI (match_dup 6)))
25f7a26e 6243 (set (match_operand:SI 0 "" "")
6244 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
cffb2a26 6245 "TARGET_ARM"
25f7a26e 6246 "
215b30b3 6247 {
6248 rtx mem1, mem2;
6249 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
6250
788fcce0 6251 mem1 = change_address (operands[1], QImode, addr);
29c05e22 6252 mem2 = change_address (operands[1], QImode,
6253 plus_constant (Pmode, addr, 1));
215b30b3 6254 operands[0] = gen_lowpart (SImode, operands[0]);
6255 operands[1] = mem1;
6256 operands[2] = gen_reg_rtx (SImode);
6257 operands[3] = gen_reg_rtx (SImode);
6258 operands[6] = mem2;
25f7a26e 6259
215b30b3 6260 if (BYTES_BIG_ENDIAN)
6261 {
6262 operands[4] = operands[2];
6263 operands[5] = operands[3];
6264 }
6265 else
6266 {
6267 operands[4] = operands[3];
6268 operands[5] = operands[2];
6269 }
6270 }"
6271)
25f7a26e 6272
c7597b5d 6273(define_expand "movhi_bigend"
6274 [(set (match_dup 2)
6275 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
6276 (const_int 16)))
6277 (set (match_dup 3)
6278 (ashiftrt:SI (match_dup 2) (const_int 16)))
6279 (set (match_operand:HI 0 "s_register_operand" "")
787f8210 6280 (match_dup 4))]
cffb2a26 6281 "TARGET_ARM"
c7597b5d 6282 "
6283 operands[2] = gen_reg_rtx (SImode);
6284 operands[3] = gen_reg_rtx (SImode);
787f8210 6285 operands[4] = gen_lowpart (HImode, operands[3]);
215b30b3 6286 "
6287)
b11cae9e 6288
a2f10574 6289;; Pattern to recognize insn generated default case above
f7fbdd4a 6290(define_insn "*movhi_insn_arch4"
cde1623a 6291 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
5fd254ed 6292 (match_operand:HI 1 "general_operand" "rIk,K,r,mi"))]
cffb2a26 6293 "TARGET_ARM
6294 && arm_arch4
85e02ccb 6295 && (register_operand (operands[0], HImode)
6296 || register_operand (operands[1], HImode))"
f7fbdd4a 6297 "@
6298 mov%?\\t%0, %1\\t%@ movhi
6299 mvn%?\\t%0, #%B1\\t%@ movhi
25f905c2 6300 str%(h%)\\t%1, %0\\t%@ movhi
6301 ldr%(h%)\\t%0, %1\\t%@ movhi"
65f68e55 6302 [(set_attr "predicable" "yes")
cffb2a26 6303 (set_attr "pool_range" "*,*,*,256")
65f68e55 6304 (set_attr "neg_pool_range" "*,*,*,244")
6305 (set_attr_alternative "type"
6306 [(if_then_else (match_operand 1 "const_int_operand" "")
1aed5204 6307 (const_string "mov_imm" )
6308 (const_string "mov_reg"))
6309 (const_string "mvn_imm")
65f68e55 6310 (const_string "store1")
6311 (const_string "load1")])]
cffb2a26 6312)
f7fbdd4a 6313
f7fbdd4a 6314(define_insn "*movhi_bytes"
65f68e55 6315 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
5fd254ed 6316 (match_operand:HI 1 "arm_rhs_operand" "I,rk,K"))]
c1a66faf 6317 "TARGET_ARM"
25f7a26e 6318 "@
65f68e55 6319 mov%?\\t%0, %1\\t%@ movhi
25f7a26e 6320 mov%?\\t%0, %1\\t%@ movhi
0d66636f 6321 mvn%?\\t%0, #%B1\\t%@ movhi"
d2a518d1 6322 [(set_attr "predicable" "yes")
1aed5204 6323 (set_attr "type" "mov_imm,mov_reg,mvn_imm")]
0d66636f 6324)
cffb2a26 6325
bc5c7e08 6326;; We use a DImode scratch because we may occasionally need an additional
6327;; temporary if the address isn't offsettable -- push_reload doesn't seem
6328;; to take any notice of the "o" constraints on reload_memory_operand operand.
d3373b54 6329(define_expand "reload_outhi"
cffb2a26 6330 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
215b30b3 6331 (match_operand:HI 1 "s_register_operand" "r")
6332 (match_operand:DI 2 "s_register_operand" "=&l")])]
cffb2a26 6333 "TARGET_EITHER"
6334 "if (TARGET_ARM)
6335 arm_reload_out_hi (operands);
6336 else
6337 thumb_reload_out_hi (operands);
d3373b54 6338 DONE;
cffb2a26 6339 "
6340)
d3373b54 6341
25f7a26e 6342(define_expand "reload_inhi"
6343 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
cffb2a26 6344 (match_operand:HI 1 "arm_reload_memory_operand" "o")
bc5c7e08 6345 (match_operand:DI 2 "s_register_operand" "=&r")])]
c1a66faf 6346 "TARGET_EITHER"
25f7a26e 6347 "
cffb2a26 6348 if (TARGET_ARM)
6349 arm_reload_in_hi (operands);
6350 else
6351 thumb_reload_out_hi (operands);
25f7a26e 6352 DONE;
6353")
6354
9c08d1fa 6355(define_expand "movqi"
6356 [(set (match_operand:QI 0 "general_operand" "")
6357 (match_operand:QI 1 "general_operand" ""))]
cffb2a26 6358 "TARGET_EITHER"
9c08d1fa 6359 "
6cffc037 6360 /* Everything except mem = const or mem = mem can be done easily */
0045890a 6361
e1ba4a27 6362 if (can_create_pseudo_p ())
cffb2a26 6363 {
0438d37f 6364 if (CONST_INT_P (operands[1]))
6cffc037 6365 {
6366 rtx reg = gen_reg_rtx (SImode);
6367
03770691 6368 /* For thumb we want an unsigned immediate, then we are more likely
6369 to be able to use a movs insn. */
6370 if (TARGET_THUMB)
6371 operands[1] = GEN_INT (INTVAL (operands[1]) & 255);
6372
6cffc037 6373 emit_insn (gen_movsi (reg, operands[1]));
6374 operands[1] = gen_lowpart (QImode, reg);
6375 }
cffb2a26 6376
6cffc037 6377 if (TARGET_THUMB)
6378 {
cffb2a26 6379 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 6380 happen if we are passed a SP (never OK for HImode/QImode) or
bc409cb4 6381 virtual register (also rejected as illegitimate for HImode/QImode)
6382 relative address. */
cffb2a26 6383 /* ??? This should perhaps be fixed elsewhere, for instance, in
6384 fixup_stack_1, by checking for other kinds of invalid addresses,
6385 e.g. a bare reference to a virtual register. This may confuse the
6386 alpha though, which must handle this case differently. */
0438d37f 6387 if (MEM_P (operands[0])
215b30b3 6388 && !memory_address_p (GET_MODE (operands[0]),
cffb2a26 6389 XEXP (operands[0], 0)))
537ffcfc 6390 operands[0]
6391 = replace_equiv_address (operands[0],
6392 copy_to_reg (XEXP (operands[0], 0)));
0438d37f 6393 if (MEM_P (operands[1])
215b30b3 6394 && !memory_address_p (GET_MODE (operands[1]),
cffb2a26 6395 XEXP (operands[1], 0)))
537ffcfc 6396 operands[1]
6397 = replace_equiv_address (operands[1],
6398 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 6399 }
6400
0438d37f 6401 if (MEM_P (operands[1]) && optimize > 0)
6cffc037 6402 {
6403 rtx reg = gen_reg_rtx (SImode);
6404
6405 emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
6406 operands[1] = gen_lowpart (QImode, reg);
6407 }
6408
0438d37f 6409 if (MEM_P (operands[0]))
6cffc037 6410 operands[1] = force_reg (QImode, operands[1]);
6411 }
6412 else if (TARGET_THUMB
0438d37f 6413 && CONST_INT_P (operands[1])
234f6557 6414 && !satisfies_constraint_I (operands[1]))
6cffc037 6415 {
674a8f0b 6416 /* Handle loading a large integer during reload. */
cffb2a26 6417
6cffc037 6418 /* Writing a constant to memory needs a scratch, which should
6419 be handled with SECONDARY_RELOADs. */
0438d37f 6420 gcc_assert (REG_P (operands[0]));
6cffc037 6421
6422 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
6423 emit_insn (gen_movsi (operands[0], operands[1]));
6424 DONE;
cffb2a26 6425 }
6426 "
6427)
b11cae9e 6428
cffb2a26 6429(define_insn "*arm_movqi_insn"
fd711051 6430 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,l,r,l,Uu,r,m")
490f62ca 6431 (match_operand:QI 1 "general_operand" "rk,rk,I,Py,K,Uu,l,Uh,r"))]
25f905c2 6432 "TARGET_32BIT
cffb2a26 6433 && ( register_operand (operands[0], QImode)
6434 || register_operand (operands[1], QImode))"
5565501b 6435 "@
fd711051 6436 mov%?\\t%0, %1
6437 mov%?\\t%0, %1
65f68e55 6438 mov%?\\t%0, %1
5565501b 6439 mov%?\\t%0, %1
6440 mvn%?\\t%0, #%B1
25f905c2 6441 ldr%(b%)\\t%0, %1
a54e3e7b 6442 str%(b%)\\t%1, %0
6443 ldr%(b%)\\t%0, %1
25f905c2 6444 str%(b%)\\t%1, %0"
1aed5204 6445 [(set_attr "type" "mov_reg,mov_reg,mov_imm,mov_imm,mvn_imm,load1,store1,load1,store1")
a54e3e7b 6446 (set_attr "predicable" "yes")
fd711051 6447 (set_attr "predicable_short_it" "yes,yes,yes,no,no,no,no,no,no")
6448 (set_attr "arch" "t2,any,any,t2,any,t2,t2,any,any")
6449 (set_attr "length" "2,4,4,2,4,2,2,4,4")]
cffb2a26 6450)
6451
9b8516be 6452;; HFmode moves
6453(define_expand "movhf"
6454 [(set (match_operand:HF 0 "general_operand" "")
6455 (match_operand:HF 1 "general_operand" ""))]
6456 "TARGET_EITHER"
6457 "
6458 if (TARGET_32BIT)
6459 {
0438d37f 6460 if (MEM_P (operands[0]))
9b8516be 6461 operands[1] = force_reg (HFmode, operands[1]);
6462 }
6463 else /* TARGET_THUMB1 */
6464 {
6465 if (can_create_pseudo_p ())
6466 {
0438d37f 6467 if (!REG_P (operands[0]))
9b8516be 6468 operands[1] = force_reg (HFmode, operands[1]);
6469 }
6470 }
6471 "
6472)
6473
6474(define_insn "*arm32_movhf"
6475 [(set (match_operand:HF 0 "nonimmediate_operand" "=r,m,r,r")
6476 (match_operand:HF 1 "general_operand" " m,r,r,F"))]
7c36fe71 6477 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_FP16) && !arm_restrict_it
9b8516be 6478 && ( s_register_operand (operands[0], HFmode)
6479 || s_register_operand (operands[1], HFmode))"
6480 "*
6481 switch (which_alternative)
6482 {
6483 case 0: /* ARM register from memory */
6484 return \"ldr%(h%)\\t%0, %1\\t%@ __fp16\";
6485 case 1: /* memory from ARM register */
6486 return \"str%(h%)\\t%1, %0\\t%@ __fp16\";
6487 case 2: /* ARM register from ARM register */
6488 return \"mov%?\\t%0, %1\\t%@ __fp16\";
6489 case 3: /* ARM register from constant */
6490 {
6491 REAL_VALUE_TYPE r;
6492 long bits;
6493 rtx ops[4];
6494
6495 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
6496 bits = real_to_target (NULL, &r, HFmode);
6497 ops[0] = operands[0];
6498 ops[1] = GEN_INT (bits);
6499 ops[2] = GEN_INT (bits & 0xff00);
6500 ops[3] = GEN_INT (bits & 0x00ff);
6501
6502 if (arm_arch_thumb2)
6503 output_asm_insn (\"movw%?\\t%0, %1\", ops);
6504 else
6505 output_asm_insn (\"mov%?\\t%0, %2\;orr%?\\t%0, %0, %3\", ops);
6506 return \"\";
6507 }
6508 default:
6509 gcc_unreachable ();
6510 }
6511 "
6512 [(set_attr "conds" "unconditional")
ad4fc3c0 6513 (set_attr "type" "load1,store1,mov_reg,multiple")
9b8516be 6514 (set_attr "length" "4,4,4,8")
d2a518d1 6515 (set_attr "predicable" "yes")]
9b8516be 6516)
6517
87b22bf7 6518(define_expand "movsf"
6519 [(set (match_operand:SF 0 "general_operand" "")
6520 (match_operand:SF 1 "general_operand" ""))]
cffb2a26 6521 "TARGET_EITHER"
87b22bf7 6522 "
25f905c2 6523 if (TARGET_32BIT)
cffb2a26 6524 {
0438d37f 6525 if (MEM_P (operands[0]))
cffb2a26 6526 operands[1] = force_reg (SFmode, operands[1]);
6527 }
25f905c2 6528 else /* TARGET_THUMB1 */
cffb2a26 6529 {
e1ba4a27 6530 if (can_create_pseudo_p ())
cffb2a26 6531 {
0438d37f 6532 if (!REG_P (operands[0]))
cffb2a26 6533 operands[1] = force_reg (SFmode, operands[1]);
6534 }
6535 }
6536 "
6537)
6538
03d440a6 6539;; Transform a floating-point move of a constant into a core register into
6540;; an SImode operation.
cffb2a26 6541(define_split
03d440a6 6542 [(set (match_operand:SF 0 "arm_general_register_operand" "")
cffb2a26 6543 (match_operand:SF 1 "immediate_operand" ""))]
339034d0 6544 "TARGET_EITHER
cffb2a26 6545 && reload_completed
0438d37f 6546 && CONST_DOUBLE_P (operands[1])"
cffb2a26 6547 [(set (match_dup 2) (match_dup 3))]
6548 "
6549 operands[2] = gen_lowpart (SImode, operands[0]);
6550 operands[3] = gen_lowpart (SImode, operands[1]);
6551 if (operands[2] == 0 || operands[3] == 0)
6552 FAIL;
215b30b3 6553 "
6554)
87b22bf7 6555
cffb2a26 6556(define_insn "*arm_movsf_soft_insn"
6557 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
6558 (match_operand:SF 1 "general_operand" "r,mE,r"))]
cde1623a 6559 "TARGET_32BIT
cffb2a26 6560 && TARGET_SOFT_FLOAT
0438d37f 6561 && (!MEM_P (operands[0])
215b30b3 6562 || register_operand (operands[1], SFmode))"
9a1112d7 6563 "@
6564 mov%?\\t%0, %1
6565 ldr%?\\t%0, %1\\t%@ float
6566 str%?\\t%1, %0\\t%@ float"
cde1623a 6567 [(set_attr "predicable" "yes")
7c36fe71 6568 (set_attr "predicable_short_it" "no")
1aed5204 6569 (set_attr "type" "mov_reg,load1,store1")
42e1de19 6570 (set_attr "arm_pool_range" "*,4096,*")
6571 (set_attr "thumb2_pool_range" "*,4094,*")
cde1623a 6572 (set_attr "arm_neg_pool_range" "*,4084,*")
6573 (set_attr "thumb2_neg_pool_range" "*,0,*")]
cffb2a26 6574)
6575
9c08d1fa 6576(define_expand "movdf"
87b22bf7 6577 [(set (match_operand:DF 0 "general_operand" "")
6578 (match_operand:DF 1 "general_operand" ""))]
cffb2a26 6579 "TARGET_EITHER"
9c08d1fa 6580 "
25f905c2 6581 if (TARGET_32BIT)
cffb2a26 6582 {
0438d37f 6583 if (MEM_P (operands[0]))
cffb2a26 6584 operands[1] = force_reg (DFmode, operands[1]);
6585 }
6586 else /* TARGET_THUMB */
6587 {
e1ba4a27 6588 if (can_create_pseudo_p ())
cffb2a26 6589 {
0438d37f 6590 if (!REG_P (operands[0]))
cffb2a26 6591 operands[1] = force_reg (DFmode, operands[1]);
6592 }
6593 }
6594 "
6595)
b11cae9e 6596
9c08d1fa 6597;; Reloading a df mode value stored in integer regs to memory can require a
6598;; scratch reg.
6599(define_expand "reload_outdf"
cffb2a26 6600 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
87b22bf7 6601 (match_operand:DF 1 "s_register_operand" "r")
6602 (match_operand:SI 2 "s_register_operand" "=&r")]
06adefdc 6603 "TARGET_THUMB2"
87b22bf7 6604 "
215b30b3 6605 {
6606 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
f7fbdd4a 6607
215b30b3 6608 if (code == REG)
6609 operands[2] = XEXP (operands[0], 0);
6610 else if (code == POST_INC || code == PRE_DEC)
6611 {
6612 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
6613 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
6614 emit_insn (gen_movdi (operands[0], operands[1]));
6615 DONE;
6616 }
6617 else if (code == PRE_INC)
6618 {
6619 rtx reg = XEXP (XEXP (operands[0], 0), 0);
f7fbdd4a 6620
215b30b3 6621 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
6622 operands[2] = reg;
6623 }
6624 else if (code == POST_DEC)
6625 operands[2] = XEXP (XEXP (operands[0], 0), 0);
6626 else
6627 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
6628 XEXP (XEXP (operands[0], 0), 1)));
f7fbdd4a 6629
788fcce0 6630 emit_insn (gen_rtx_SET (VOIDmode,
6631 replace_equiv_address (operands[0], operands[2]),
215b30b3 6632 operands[1]));
f7fbdd4a 6633
215b30b3 6634 if (code == POST_DEC)
6635 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
6636
6637 DONE;
6638 }"
6639)
9c08d1fa 6640
9a1112d7 6641(define_insn "*movdf_soft_insn"
353cf59a 6642 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,q,m")
6643 (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,q"))]
cde1623a 6644 "TARGET_32BIT && TARGET_SOFT_FLOAT
b2778788 6645 && ( register_operand (operands[0], DFmode)
6646 || register_operand (operands[1], DFmode))"
d51f92df 6647 "*
6648 switch (which_alternative)
6649 {
6650 case 0:
6651 case 1:
6652 case 2:
6653 return \"#\";
6654 default:
26ff80c0 6655 return output_move_double (operands, true, NULL);
d51f92df 6656 }
6657 "
359a6e9f 6658 [(set_attr "length" "8,12,16,8,8")
1b7da4ac 6659 (set_attr "type" "multiple,multiple,multiple,load2,store2")
42e1de19 6660 (set_attr "arm_pool_range" "*,*,*,1020,*")
6661 (set_attr "thumb2_pool_range" "*,*,*,1018,*")
8848d797 6662 (set_attr "arm_neg_pool_range" "*,*,*,1004,*")
cde1623a 6663 (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
cffb2a26 6664)
b11cae9e 6665\f
b11cae9e 6666
9c08d1fa 6667;; load- and store-multiple insns
6668;; The arm can load/store any set of registers, provided that they are in
320ea44d 6669;; ascending order, but these expanders assume a contiguous set.
b11cae9e 6670
9c08d1fa 6671(define_expand "load_multiple"
6672 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6673 (match_operand:SI 1 "" ""))
6674 (use (match_operand:SI 2 "" ""))])]
25f905c2 6675 "TARGET_32BIT"
9580c25f 6676{
6677 HOST_WIDE_INT offset = 0;
6678
bd5b4116 6679 /* Support only fixed point registers. */
0438d37f 6680 if (!CONST_INT_P (operands[2])
9c08d1fa 6681 || INTVAL (operands[2]) > 14
6682 || INTVAL (operands[2]) < 2
0438d37f 6683 || !MEM_P (operands[1])
6684 || !REG_P (operands[0])
bd5b4116 6685 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
6686 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 6687 FAIL;
6688
6689 operands[3]
320ea44d 6690 = arm_gen_load_multiple (arm_regs_in_sequence + REGNO (operands[0]),
6691 INTVAL (operands[2]),
f082f1c4 6692 force_reg (SImode, XEXP (operands[1], 0)),
320ea44d 6693 FALSE, operands[1], &offset);
9580c25f 6694})
b11cae9e 6695
9c08d1fa 6696(define_expand "store_multiple"
6697 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6698 (match_operand:SI 1 "" ""))
6699 (use (match_operand:SI 2 "" ""))])]
25f905c2 6700 "TARGET_32BIT"
9580c25f 6701{
6702 HOST_WIDE_INT offset = 0;
6703
674a8f0b 6704 /* Support only fixed point registers. */
0438d37f 6705 if (!CONST_INT_P (operands[2])
9c08d1fa 6706 || INTVAL (operands[2]) > 14
6707 || INTVAL (operands[2]) < 2
0438d37f 6708 || !REG_P (operands[1])
6709 || !MEM_P (operands[0])
bd5b4116 6710 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
6711 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 6712 FAIL;
6713
6714 operands[3]
320ea44d 6715 = arm_gen_store_multiple (arm_regs_in_sequence + REGNO (operands[1]),
6716 INTVAL (operands[2]),
f082f1c4 6717 force_reg (SImode, XEXP (operands[0], 0)),
320ea44d 6718 FALSE, operands[0], &offset);
9580c25f 6719})
b11cae9e 6720
9c08d1fa 6721
e34ebfca 6722(define_expand "setmemsi"
6723 [(match_operand:BLK 0 "general_operand" "")
6724 (match_operand:SI 1 "const_int_operand" "")
6725 (match_operand:SI 2 "const_int_operand" "")
6726 (match_operand:SI 3 "const_int_operand" "")]
6727 "TARGET_32BIT"
6728{
6729 if (arm_gen_setmem (operands))
6730 DONE;
6731
6732 FAIL;
6733})
6734
6735
9c08d1fa 6736;; Move a block of memory if it is word aligned and MORE than 2 words long.
6737;; We could let this apply for blocks of less than this, but it clobbers so
6738;; many registers that there is then probably a better way.
6739
008c057d 6740(define_expand "movmemqi"
34191dd1 6741 [(match_operand:BLK 0 "general_operand" "")
6742 (match_operand:BLK 1 "general_operand" "")
6743 (match_operand:SI 2 "const_int_operand" "")
6744 (match_operand:SI 3 "const_int_operand" "")]
ae51a965 6745 ""
9c08d1fa 6746 "
25f905c2 6747 if (TARGET_32BIT)
cffb2a26 6748 {
ae51a965 6749 if (TARGET_LDRD && current_tune->prefer_ldrd_strd
6750 && !optimize_function_for_size_p (cfun))
6751 {
6752 if (gen_movmem_ldrd_strd (operands))
6753 DONE;
6754 FAIL;
6755 }
6756
008c057d 6757 if (arm_gen_movmemqi (operands))
cffb2a26 6758 DONE;
6759 FAIL;
6760 }
25f905c2 6761 else /* TARGET_THUMB1 */
cffb2a26 6762 {
6763 if ( INTVAL (operands[3]) != 4
6764 || INTVAL (operands[2]) > 48)
6765 FAIL;
6766
008c057d 6767 thumb_expand_movmemqi (operands);
cffb2a26 6768 DONE;
6769 }
6770 "
6771)
9c08d1fa 6772\f
b11cae9e 6773
341940e8 6774;; Compare & branch insns
8d232dc7 6775;; The range calculations are based as follows:
341940e8 6776;; For forward branches, the address calculation returns the address of
6777;; the next instruction. This is 2 beyond the branch instruction.
6778;; For backward branches, the address calculation returns the address of
6779;; the first instruction in this pattern (cmp). This is 2 before the branch
6780;; instruction for the shortest sequence, and 4 before the branch instruction
6781;; if we have to jump around an unconditional branch.
6782;; To the basic branch range the PC offset must be added (this is +4).
6783;; So for forward branches we have
6784;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
6785;; And for backward branches we have
6786;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
6787;;
6788;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
6789;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
cffb2a26 6790
aeac46d4 6791(define_expand "cbranchsi4"
6792 [(set (pc) (if_then_else
aa06947a 6793 (match_operator 0 "expandable_comparison_operator"
aeac46d4 6794 [(match_operand:SI 1 "s_register_operand" "")
6795 (match_operand:SI 2 "nonmemory_operand" "")])
6796 (label_ref (match_operand 3 "" ""))
6797 (pc)))]
f9aa4160 6798 "TARGET_EITHER"
aeac46d4 6799 "
74f4459c 6800 if (!TARGET_THUMB1)
6801 {
f9aa4160 6802 if (!arm_validize_comparison (&operands[0], &operands[1], &operands[2]))
6803 FAIL;
74f4459c 6804 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6805 operands[3]));
6806 DONE;
6807 }
25f905c2 6808 if (thumb1_cmpneg_operand (operands[2], SImode))
aeac46d4 6809 {
6810 emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
6811 operands[3], operands[0]));
6812 DONE;
6813 }
25f905c2 6814 if (!thumb1_cmp_operand (operands[2], SImode))
aeac46d4 6815 operands[2] = force_reg (SImode, operands[2]);
6816 ")
6817
74f4459c 6818(define_expand "cbranchsf4"
6819 [(set (pc) (if_then_else
aa06947a 6820 (match_operator 0 "expandable_comparison_operator"
74f4459c 6821 [(match_operand:SF 1 "s_register_operand" "")
6822 (match_operand:SF 2 "arm_float_compare_operand" "")])
6823 (label_ref (match_operand 3 "" ""))
6824 (pc)))]
6825 "TARGET_32BIT && TARGET_HARD_FLOAT"
6826 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6827 operands[3])); DONE;"
6828)
6829
6830(define_expand "cbranchdf4"
6831 [(set (pc) (if_then_else
aa06947a 6832 (match_operator 0 "expandable_comparison_operator"
74f4459c 6833 [(match_operand:DF 1 "s_register_operand" "")
6834 (match_operand:DF 2 "arm_float_compare_operand" "")])
6835 (label_ref (match_operand 3 "" ""))
6836 (pc)))]
a50d7267 6837 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
74f4459c 6838 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6839 operands[3])); DONE;"
6840)
6841
74f4459c 6842(define_expand "cbranchdi4"
6843 [(set (pc) (if_then_else
aa06947a 6844 (match_operator 0 "expandable_comparison_operator"
b8eae306 6845 [(match_operand:DI 1 "s_register_operand" "")
a8045a4f 6846 (match_operand:DI 2 "cmpdi_operand" "")])
74f4459c 6847 (label_ref (match_operand 3 "" ""))
6848 (pc)))]
a8045a4f 6849 "TARGET_32BIT"
6850 "{
0438d37f 6851 if (!arm_validize_comparison (&operands[0], &operands[1], &operands[2]))
f9aa4160 6852 FAIL;
6853 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
a8045a4f 6854 operands[3]));
6855 DONE;
6856 }"
74f4459c 6857)
6858
9c08d1fa 6859;; Comparison and test insns
6860
cffb2a26 6861(define_insn "*arm_cmpsi_insn"
bd5b4116 6862 [(set (reg:CC CC_REGNUM)
f9f234ec 6863 (compare:CC (match_operand:SI 0 "s_register_operand" "l,r,r,r,r")
6864 (match_operand:SI 1 "arm_add_operand" "Py,r,r,I,L")))]
25f905c2 6865 "TARGET_32BIT"
5565501b 6866 "@
a6864a24 6867 cmp%?\\t%0, %1
6868 cmp%?\\t%0, %1
aea4c774 6869 cmp%?\\t%0, %1
f9f234ec 6870 cmp%?\\t%0, %1
aea4c774 6871 cmn%?\\t%0, #%n1"
a6864a24 6872 [(set_attr "conds" "set")
f9f234ec 6873 (set_attr "arch" "t2,t2,any,any,any")
6874 (set_attr "length" "2,2,4,4,4")
65f68e55 6875 (set_attr "predicable" "yes")
f9f234ec 6876 (set_attr "predicable_short_it" "yes,yes,yes,no,no")
112eda6f 6877 (set_attr "type" "alus_imm,alus_sreg,alus_sreg,alus_imm,alus_imm")]
cffb2a26 6878)
b11cae9e 6879
d5d4dc8d 6880(define_insn "*cmpsi_shiftsi"
bd5b4116 6881 [(set (reg:CC CC_REGNUM)
d82e788e 6882 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r,r")
cffb2a26 6883 (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")])))]
d5d4dc8d 6886 "TARGET_32BIT"
f9f234ec 6887 "cmp\\t%0, %1%S3"
344495ea 6888 [(set_attr "conds" "set")
331beb1a 6889 (set_attr "shift" "1")
d82e788e 6890 (set_attr "arch" "32,a,a")
6891 (set_attr "type" "alus_shift_imm,alu_shift_reg,alus_shift_imm")])
b11cae9e 6892
d5d4dc8d 6893(define_insn "*cmpsi_shiftsi_swp"
bd5b4116 6894 [(set (reg:CC_SWP CC_REGNUM)
aea4c774 6895 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
d82e788e 6896 [(match_operand:SI 1 "s_register_operand" "r,r,r")
6897 (match_operand:SI 2 "shift_amount_operand" "M,r,M")])
6898 (match_operand:SI 0 "s_register_operand" "r,r,r")))]
d5d4dc8d 6899 "TARGET_32BIT"
aea4c774 6900 "cmp%?\\t%0, %1%S3"
344495ea 6901 [(set_attr "conds" "set")
331beb1a 6902 (set_attr "shift" "1")
d82e788e 6903 (set_attr "arch" "32,a,a")
6904 (set_attr "type" "alus_shift_imm,alu_shift_reg,alus_shift_imm")])
b11cae9e 6905
25f905c2 6906(define_insn "*arm_cmpsi_negshiftsi_si"
aed179ae 6907 [(set (reg:CC_Z CC_REGNUM)
6908 (compare:CC_Z
6909 (neg:SI (match_operator:SI 1 "shift_operator"
6910 [(match_operand:SI 2 "s_register_operand" "r")
6911 (match_operand:SI 3 "reg_or_int_operand" "rM")]))
6912 (match_operand:SI 0 "s_register_operand" "r")))]
cffb2a26 6913 "TARGET_ARM"
aed179ae 6914 "cmn%?\\t%0, %2%S1"
344495ea 6915 [(set_attr "conds" "set")
aed179ae 6916 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
d82e788e 6917 (const_string "alus_shift_imm")
6918 (const_string "alus_shift_reg")))
596e5e8f 6919 (set_attr "predicable" "yes")]
0d66636f 6920)
b11cae9e 6921
a8045a4f 6922;; DImode comparisons. The generic code generates branches that
6923;; if-conversion can not reduce to a conditional compare, so we do
6924;; that directly.
6925
ba6a3b2f 6926(define_insn_and_split "*arm_cmpdi_insn"
a8045a4f 6927 [(set (reg:CC_NCV CC_REGNUM)
6928 (compare:CC_NCV (match_operand:DI 0 "s_register_operand" "r")
6929 (match_operand:DI 1 "arm_di_operand" "rDi")))
6930 (clobber (match_scratch:SI 2 "=r"))]
b805622c 6931 "TARGET_32BIT"
ba6a3b2f 6932 "#" ; "cmp\\t%Q0, %Q1\;sbcs\\t%2, %R0, %R1"
6933 "&& reload_completed"
6934 [(set (reg:CC CC_REGNUM)
6935 (compare:CC (match_dup 0) (match_dup 1)))
6936 (parallel [(set (reg:CC CC_REGNUM)
6937 (compare:CC (match_dup 3) (match_dup 4)))
6938 (set (match_dup 2)
6939 (minus:SI (match_dup 5)
6940 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))])]
6941 {
6942 operands[3] = gen_highpart (SImode, operands[0]);
6943 operands[0] = gen_lowpart (SImode, operands[0]);
6944 if (CONST_INT_P (operands[1]))
6945 {
6946 operands[4] = GEN_INT (~INTVAL (gen_highpart_mode (SImode,
6947 DImode,
6948 operands[1])));
6949 operands[5] = gen_rtx_PLUS (SImode, operands[3], operands[4]);
6950 }
6951 else
6952 {
6953 operands[4] = gen_highpart (SImode, operands[1]);
6954 operands[5] = gen_rtx_MINUS (SImode, operands[3], operands[4]);
6955 }
6956 operands[1] = gen_lowpart (SImode, operands[1]);
6957 operands[2] = gen_lowpart (SImode, operands[2]);
6958 }
a8045a4f 6959 [(set_attr "conds" "set")
1b7da4ac 6960 (set_attr "length" "8")
6961 (set_attr "type" "multiple")]
a8045a4f 6962)
6963
ba6a3b2f 6964(define_insn_and_split "*arm_cmpdi_unsigned"
a8045a4f 6965 [(set (reg:CC_CZ CC_REGNUM)
1a86364b 6966 (compare:CC_CZ (match_operand:DI 0 "s_register_operand" "l,r,r,r")
6967 (match_operand:DI 1 "arm_di_operand" "Py,r,Di,rDi")))]
7c36fe71 6968
48a98053 6969 "TARGET_32BIT"
ba6a3b2f 6970 "#" ; "cmp\\t%R0, %R1\;it eq\;cmpeq\\t%Q0, %Q1"
6971 "&& reload_completed"
6972 [(set (reg:CC CC_REGNUM)
6973 (compare:CC (match_dup 2) (match_dup 3)))
6974 (cond_exec (eq:SI (reg:CC CC_REGNUM) (const_int 0))
6975 (set (reg:CC CC_REGNUM)
6976 (compare:CC (match_dup 0) (match_dup 1))))]
6977 {
6978 operands[2] = gen_highpart (SImode, operands[0]);
6979 operands[0] = gen_lowpart (SImode, operands[0]);
6980 if (CONST_INT_P (operands[1]))
6981 operands[3] = gen_highpart_mode (SImode, DImode, operands[1]);
6982 else
6983 operands[3] = gen_highpart (SImode, operands[1]);
6984 operands[1] = gen_lowpart (SImode, operands[1]);
6985 }
a8045a4f 6986 [(set_attr "conds" "set")
1a86364b 6987 (set_attr "enabled_for_depr_it" "yes,yes,no,*")
6988 (set_attr "arch" "t2,t2,t2,a")
6989 (set_attr "length" "6,6,10,8")
1b7da4ac 6990 (set_attr "type" "multiple")]
a8045a4f 6991)
6992
6993(define_insn "*arm_cmpdi_zero"
6994 [(set (reg:CC_Z CC_REGNUM)
6995 (compare:CC_Z (match_operand:DI 0 "s_register_operand" "r")
6996 (const_int 0)))
6997 (clobber (match_scratch:SI 1 "=r"))]
6998 "TARGET_32BIT"
6999 "orr%.\\t%1, %Q0, %R0"
1b7da4ac 7000 [(set_attr "conds" "set")
7001 (set_attr "type" "logics_reg")]
a8045a4f 7002)
7003
9c08d1fa 7004; This insn allows redundant compares to be removed by cse, nothing should
7005; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
7006; is deleted later on. The match_dup will match the mode here, so that
7007; mode changes of the condition codes aren't lost by this even though we don't
7008; specify what they are.
7009
8a18b90c 7010(define_insn "*deleted_compare"
9c08d1fa 7011 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
25f905c2 7012 "TARGET_32BIT"
40dbec34 7013 "\\t%@ deleted compare"
cffb2a26 7014 [(set_attr "conds" "set")
1b7da4ac 7015 (set_attr "length" "0")
7016 (set_attr "type" "no_insn")]
cffb2a26 7017)
9c08d1fa 7018
7019\f
7020;; Conditional branch insns
7021
74f4459c 7022(define_expand "cbranch_cc"
9c08d1fa 7023 [(set (pc)
74f4459c 7024 (if_then_else (match_operator 0 "" [(match_operand 1 "" "")
7025 (match_operand 2 "" "")])
7026 (label_ref (match_operand 3 "" ""))
9c08d1fa 7027 (pc)))]
25f905c2 7028 "TARGET_32BIT"
74f4459c 7029 "operands[1] = arm_gen_compare_reg (GET_CODE (operands[0]),
e1b93706 7030 operands[1], operands[2], NULL_RTX);
74f4459c 7031 operands[2] = const0_rtx;"
8fa3ba89 7032)
7033
7034;;
7035;; Patterns to match conditional branch insns.
7036;;
7037
ffcc986d 7038(define_insn "arm_cond_branch"
9c08d1fa 7039 [(set (pc)
8fa3ba89 7040 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 7041 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 7042 (label_ref (match_operand 0 "" ""))
7043 (pc)))]
25f905c2 7044 "TARGET_32BIT"
d75350ce 7045 "*
9c08d1fa 7046 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 7047 {
7048 arm_ccfsm_state += 2;
7049 return \"\";
7050 }
e2348bcb 7051 return \"b%d1\\t%l0\";
cffb2a26 7052 "
a2cd141b 7053 [(set_attr "conds" "use")
a6864a24 7054 (set_attr "type" "branch")
7055 (set (attr "length")
7056 (if_then_else
0bf497f5 7057 (and (match_test "TARGET_THUMB2")
a6864a24 7058 (and (ge (minus (match_dup 0) (pc)) (const_int -250))
7059 (le (minus (match_dup 0) (pc)) (const_int 256))))
7060 (const_int 2)
7061 (const_int 4)))]
cffb2a26 7062)
d75350ce 7063
cffb2a26 7064(define_insn "*arm_cond_branch_reversed"
9c08d1fa 7065 [(set (pc)
8fa3ba89 7066 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 7067 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 7068 (pc)
7069 (label_ref (match_operand 0 "" ""))))]
25f905c2 7070 "TARGET_32BIT"
d75350ce 7071 "*
9c08d1fa 7072 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 7073 {
7074 arm_ccfsm_state += 2;
7075 return \"\";
7076 }
e2348bcb 7077 return \"b%D1\\t%l0\";
cffb2a26 7078 "
a2cd141b 7079 [(set_attr "conds" "use")
a6864a24 7080 (set_attr "type" "branch")
7081 (set (attr "length")
7082 (if_then_else
0bf497f5 7083 (and (match_test "TARGET_THUMB2")
a6864a24 7084 (and (ge (minus (match_dup 0) (pc)) (const_int -250))
7085 (le (minus (match_dup 0) (pc)) (const_int 256))))
7086 (const_int 2)
7087 (const_int 4)))]
cffb2a26 7088)
7089
b11cae9e 7090\f
9c08d1fa 7091
7092; scc insns
7093
74f4459c 7094(define_expand "cstore_cc"
7db9af5d 7095 [(set (match_operand:SI 0 "s_register_operand" "")
74f4459c 7096 (match_operator:SI 1 "" [(match_operand 2 "" "")
7097 (match_operand 3 "" "")]))]
25f905c2 7098 "TARGET_32BIT"
74f4459c 7099 "operands[2] = arm_gen_compare_reg (GET_CODE (operands[1]),
e1b93706 7100 operands[2], operands[3], NULL_RTX);
74f4459c 7101 operands[3] = const0_rtx;"
8fa3ba89 7102)
7103
a3b84066 7104(define_insn_and_split "*mov_scc"
9c08d1fa 7105 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7106 (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7107 [(match_operand 2 "cc_register" "") (const_int 0)]))]
cffb2a26 7108 "TARGET_ARM"
a3b84066 7109 "#" ; "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
7110 "TARGET_ARM"
7111 [(set (match_dup 0)
7112 (if_then_else:SI (match_dup 1)
7113 (const_int 1)
7114 (const_int 0)))]
7115 ""
cffb2a26 7116 [(set_attr "conds" "use")
1b7da4ac 7117 (set_attr "length" "8")
7118 (set_attr "type" "multiple")]
cffb2a26 7119)
9c08d1fa 7120
a3b84066 7121(define_insn_and_split "*mov_negscc"
9c08d1fa 7122 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7123 (neg:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7124 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 7125 "TARGET_ARM"
a3b84066 7126 "#" ; "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
7127 "TARGET_ARM"
7128 [(set (match_dup 0)
7129 (if_then_else:SI (match_dup 1)
7130 (match_dup 3)
7131 (const_int 0)))]
7132 {
7133 operands[3] = GEN_INT (~0);
7134 }
cffb2a26 7135 [(set_attr "conds" "use")
1b7da4ac 7136 (set_attr "length" "8")
7137 (set_attr "type" "multiple")]
cffb2a26 7138)
9c08d1fa 7139
a3b84066 7140(define_insn_and_split "*mov_notscc"
9c08d1fa 7141 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7142 (not:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7143 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 7144 "TARGET_ARM"
a3b84066 7145 "#" ; "mvn%D1\\t%0, #0\;mvn%d1\\t%0, #1"
7146 "TARGET_ARM"
7147 [(set (match_dup 0)
7148 (if_then_else:SI (match_dup 1)
7149 (match_dup 3)
7150 (match_dup 4)))]
7151 {
7152 operands[3] = GEN_INT (~1);
7153 operands[4] = GEN_INT (~0);
7154 }
cffb2a26 7155 [(set_attr "conds" "use")
1b7da4ac 7156 (set_attr "length" "8")
7157 (set_attr "type" "multiple")]
cffb2a26 7158)
9c08d1fa 7159
595d88b5 7160(define_expand "cstoresi4"
7161 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 7162 (match_operator:SI 1 "expandable_comparison_operator"
595d88b5 7163 [(match_operand:SI 2 "s_register_operand" "")
7164 (match_operand:SI 3 "reg_or_int_operand" "")]))]
74f4459c 7165 "TARGET_32BIT || TARGET_THUMB1"
595d88b5 7166 "{
7167 rtx op3, scratch, scratch2;
7168
74f4459c 7169 if (!TARGET_THUMB1)
7170 {
7171 if (!arm_add_operand (operands[3], SImode))
7172 operands[3] = force_reg (SImode, operands[3]);
7173 emit_insn (gen_cstore_cc (operands[0], operands[1],
7174 operands[2], operands[3]));
7175 DONE;
7176 }
7177
595d88b5 7178 if (operands[3] == const0_rtx)
7179 {
7180 switch (GET_CODE (operands[1]))
7181 {
7182 case EQ:
25f905c2 7183 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], operands[2]));
595d88b5 7184 break;
7185
7186 case NE:
25f905c2 7187 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], operands[2]));
595d88b5 7188 break;
7189
7190 case LE:
7191 scratch = expand_binop (SImode, add_optab, operands[2], constm1_rtx,
7192 NULL_RTX, 0, OPTAB_WIDEN);
7193 scratch = expand_binop (SImode, ior_optab, operands[2], scratch,
7194 NULL_RTX, 0, OPTAB_WIDEN);
7195 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7196 operands[0], 1, OPTAB_WIDEN);
7197 break;
7198
7199 case GE:
7200 scratch = expand_unop (SImode, one_cmpl_optab, operands[2],
7201 NULL_RTX, 1);
7202 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7203 NULL_RTX, 1, OPTAB_WIDEN);
7204 break;
7205
7206 case GT:
7207 scratch = expand_binop (SImode, ashr_optab, operands[2],
7208 GEN_INT (31), NULL_RTX, 0, OPTAB_WIDEN);
7209 scratch = expand_binop (SImode, sub_optab, scratch, operands[2],
7210 NULL_RTX, 0, OPTAB_WIDEN);
7211 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31), operands[0],
7212 0, OPTAB_WIDEN);
7213 break;
7214
7215 /* LT is handled by generic code. No need for unsigned with 0. */
7216 default:
7217 FAIL;
7218 }
7219 DONE;
7220 }
7221
7222 switch (GET_CODE (operands[1]))
7223 {
7224 case EQ:
7225 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7226 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7227 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], scratch));
595d88b5 7228 break;
7229
7230 case NE:
7231 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7232 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7233 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], scratch));
595d88b5 7234 break;
7235
7236 case LE:
7237 op3 = force_reg (SImode, operands[3]);
7238
7239 scratch = expand_binop (SImode, lshr_optab, operands[2], GEN_INT (31),
7240 NULL_RTX, 1, OPTAB_WIDEN);
7241 scratch2 = expand_binop (SImode, ashr_optab, op3, GEN_INT (31),
7242 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7243 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
595d88b5 7244 op3, operands[2]));
7245 break;
7246
7247 case GE:
7248 op3 = operands[3];
25f905c2 7249 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7250 op3 = force_reg (SImode, op3);
7251 scratch = expand_binop (SImode, ashr_optab, operands[2], GEN_INT (31),
7252 NULL_RTX, 0, OPTAB_WIDEN);
7253 scratch2 = expand_binop (SImode, lshr_optab, op3, GEN_INT (31),
7254 NULL_RTX, 1, OPTAB_WIDEN);
25f905c2 7255 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
595d88b5 7256 operands[2], op3));
7257 break;
7258
7259 case LEU:
7260 op3 = force_reg (SImode, operands[3]);
7261 scratch = force_reg (SImode, const0_rtx);
25f905c2 7262 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
595d88b5 7263 op3, operands[2]));
7264 break;
7265
7266 case GEU:
7267 op3 = operands[3];
25f905c2 7268 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7269 op3 = force_reg (SImode, op3);
7270 scratch = force_reg (SImode, const0_rtx);
25f905c2 7271 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
595d88b5 7272 operands[2], op3));
7273 break;
7274
7275 case LTU:
7276 op3 = operands[3];
25f905c2 7277 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7278 op3 = force_reg (SImode, op3);
7279 scratch = gen_reg_rtx (SImode);
408b7ae5 7280 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], operands[2], op3));
595d88b5 7281 break;
7282
7283 case GTU:
7284 op3 = force_reg (SImode, operands[3]);
7285 scratch = gen_reg_rtx (SImode);
408b7ae5 7286 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], op3, operands[2]));
595d88b5 7287 break;
7288
7289 /* No good sequences for GT, LT. */
7290 default:
7291 FAIL;
7292 }
7293 DONE;
7294}")
7295
74f4459c 7296(define_expand "cstoresf4"
7297 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 7298 (match_operator:SI 1 "expandable_comparison_operator"
74f4459c 7299 [(match_operand:SF 2 "s_register_operand" "")
7300 (match_operand:SF 3 "arm_float_compare_operand" "")]))]
7301 "TARGET_32BIT && TARGET_HARD_FLOAT"
7302 "emit_insn (gen_cstore_cc (operands[0], operands[1],
7303 operands[2], operands[3])); DONE;"
7304)
7305
7306(define_expand "cstoredf4"
7307 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 7308 (match_operator:SI 1 "expandable_comparison_operator"
74f4459c 7309 [(match_operand:DF 2 "s_register_operand" "")
7310 (match_operand:DF 3 "arm_float_compare_operand" "")]))]
d63ed457 7311 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
74f4459c 7312 "emit_insn (gen_cstore_cc (operands[0], operands[1],
7313 operands[2], operands[3])); DONE;"
7314)
7315
74f4459c 7316(define_expand "cstoredi4"
7317 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 7318 (match_operator:SI 1 "expandable_comparison_operator"
b8eae306 7319 [(match_operand:DI 2 "s_register_operand" "")
a8045a4f 7320 (match_operand:DI 3 "cmpdi_operand" "")]))]
7321 "TARGET_32BIT"
7322 "{
f9aa4160 7323 if (!arm_validize_comparison (&operands[1],
7324 &operands[2],
7325 &operands[3]))
7326 FAIL;
7327 emit_insn (gen_cstore_cc (operands[0], operands[1], operands[2],
a8045a4f 7328 operands[3]));
7329 DONE;
7330 }"
74f4459c 7331)
7332
9c08d1fa 7333\f
39b5e676 7334;; Conditional move insns
7335
7336(define_expand "movsicc"
8a18b90c 7337 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 7338 (if_then_else:SI (match_operand 1 "expandable_comparison_operator" "")
aea4c774 7339 (match_operand:SI 2 "arm_not_operand" "")
8a18b90c 7340 (match_operand:SI 3 "arm_not_operand" "")))]
25f905c2 7341 "TARGET_32BIT"
39b5e676 7342 "
215b30b3 7343 {
f9aa4160 7344 enum rtx_code code;
278b301d 7345 rtx ccreg;
7346
f9aa4160 7347 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
7348 &XEXP (operands[1], 1)))
278b301d 7349 FAIL;
f9aa4160 7350
7351 code = GET_CODE (operands[1]);
74f4459c 7352 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
e1b93706 7353 XEXP (operands[1], 1), NULL_RTX);
29bb088d 7354 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7355 }"
7356)
39b5e676 7357
7358(define_expand "movsfcc"
8a18b90c 7359 [(set (match_operand:SF 0 "s_register_operand" "")
4df97ffc 7360 (if_then_else:SF (match_operand 1 "arm_cond_move_operator" "")
8a18b90c 7361 (match_operand:SF 2 "s_register_operand" "")
d86c91f6 7362 (match_operand:SF 3 "s_register_operand" "")))]
19f6bf8d 7363 "TARGET_32BIT && TARGET_HARD_FLOAT"
39b5e676 7364 "
215b30b3 7365 {
7366 enum rtx_code code = GET_CODE (operands[1]);
7367 rtx ccreg;
f082f1c4 7368
f9aa4160 7369 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
7370 &XEXP (operands[1], 1)))
7371 FAIL;
39b5e676 7372
f9aa4160 7373 code = GET_CODE (operands[1]);
74f4459c 7374 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
e1b93706 7375 XEXP (operands[1], 1), NULL_RTX);
29bb088d 7376 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7377 }"
7378)
39b5e676 7379
7380(define_expand "movdfcc"
8a18b90c 7381 [(set (match_operand:DF 0 "s_register_operand" "")
4df97ffc 7382 (if_then_else:DF (match_operand 1 "arm_cond_move_operator" "")
8a18b90c 7383 (match_operand:DF 2 "s_register_operand" "")
d86c91f6 7384 (match_operand:DF 3 "s_register_operand" "")))]
994606f8 7385 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
39b5e676 7386 "
215b30b3 7387 {
7388 enum rtx_code code = GET_CODE (operands[1]);
278b301d 7389 rtx ccreg;
39b5e676 7390
f9aa4160 7391 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
7392 &XEXP (operands[1], 1)))
7393 FAIL;
7394 code = GET_CODE (operands[1]);
74f4459c 7395 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
e1b93706 7396 XEXP (operands[1], 1), NULL_RTX);
29bb088d 7397 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7398 }"
7399)
39b5e676 7400
91cb50d2 7401(define_insn "*cmov<mode>"
7402 [(set (match_operand:SDF 0 "s_register_operand" "=<F_constraint>")
7403 (if_then_else:SDF (match_operator 1 "arm_vsel_comparison_operator"
7404 [(match_operand 2 "cc_register" "") (const_int 0)])
7405 (match_operand:SDF 3 "s_register_operand"
7406 "<F_constraint>")
7407 (match_operand:SDF 4 "s_register_operand"
7408 "<F_constraint>")))]
7409 "TARGET_HARD_FLOAT && TARGET_FPU_ARMV8 <vfp_double_cond>"
7410 "*
7411 {
7412 enum arm_cond_code code = maybe_get_arm_condition_code (operands[1]);
7413 switch (code)
7414 {
7415 case ARM_GE:
7416 case ARM_GT:
7417 case ARM_EQ:
7418 case ARM_VS:
7419 return \"vsel%d1.<V_if_elem>\\t%<V_reg>0, %<V_reg>3, %<V_reg>4\";
7420 case ARM_LT:
7421 case ARM_LE:
7422 case ARM_NE:
7423 case ARM_VC:
7424 return \"vsel%D1.<V_if_elem>\\t%<V_reg>0, %<V_reg>4, %<V_reg>3\";
7425 default:
7426 gcc_unreachable ();
7427 }
7428 return \"\";
7429 }"
7430 [(set_attr "conds" "use")
6664d308 7431 (set_attr "type" "fcsel")]
91cb50d2 7432)
7433
190efb17 7434(define_insn_and_split "*movsicc_insn"
f082f1c4 7435 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
8a18b90c 7436 (if_then_else:SI
8fa3ba89 7437 (match_operator 3 "arm_comparison_operator"
8a18b90c 7438 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 7439 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
7440 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
cffb2a26 7441 "TARGET_ARM"
39b5e676 7442 "@
8a18b90c 7443 mov%D3\\t%0, %2
7444 mvn%D3\\t%0, #%B2
f082f1c4 7445 mov%d3\\t%0, %1
7446 mvn%d3\\t%0, #%B1
190efb17 7447 #
7448 #
7449 #
7450 #"
7451 ; alt4: mov%d3\\t%0, %1\;mov%D3\\t%0, %2
7452 ; alt5: mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
7453 ; alt6: mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
7454 ; alt7: mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
7455 "&& reload_completed"
7456 [(const_int 0)]
7457 {
7458 enum rtx_code rev_code;
3754d046 7459 machine_mode mode;
190efb17 7460 rtx rev_cond;
7461
7462 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
7463 operands[3],
7464 gen_rtx_SET (VOIDmode,
7465 operands[0],
7466 operands[1])));
7467
7468 rev_code = GET_CODE (operands[3]);
7469 mode = GET_MODE (operands[4]);
7470 if (mode == CCFPmode || mode == CCFPEmode)
7471 rev_code = reverse_condition_maybe_unordered (rev_code);
7472 else
7473 rev_code = reverse_condition (rev_code);
7474
7475 rev_cond = gen_rtx_fmt_ee (rev_code,
7476 VOIDmode,
7477 operands[4],
7478 const0_rtx);
7479 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
7480 rev_cond,
7481 gen_rtx_SET (VOIDmode,
7482 operands[0],
7483 operands[2])));
7484 DONE;
7485 }
f082f1c4 7486 [(set_attr "length" "4,4,4,4,8,8,8,8")
d2a518d1 7487 (set_attr "conds" "use")
65f68e55 7488 (set_attr_alternative "type"
7489 [(if_then_else (match_operand 2 "const_int_operand" "")
1aed5204 7490 (const_string "mov_imm")
7491 (const_string "mov_reg"))
7492 (const_string "mvn_imm")
65f68e55 7493 (if_then_else (match_operand 1 "const_int_operand" "")
1aed5204 7494 (const_string "mov_imm")
7495 (const_string "mov_reg"))
7496 (const_string "mvn_imm")
7497 (const_string "mov_reg")
7498 (const_string "mov_reg")
7499 (const_string "mov_reg")
7500 (const_string "mov_reg")])]
215b30b3 7501)
39b5e676 7502
39b5e676 7503(define_insn "*movsfcc_soft_insn"
f082f1c4 7504 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
8fa3ba89 7505 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
8a18b90c 7506 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 7507 (match_operand:SF 1 "s_register_operand" "0,r")
7508 (match_operand:SF 2 "s_register_operand" "r,0")))]
cffb2a26 7509 "TARGET_ARM && TARGET_SOFT_FLOAT"
f082f1c4 7510 "@
7511 mov%D3\\t%0, %2
7512 mov%d3\\t%0, %1"
d2a518d1 7513 [(set_attr "conds" "use")
1aed5204 7514 (set_attr "type" "mov_reg")]
8fa3ba89 7515)
39b5e676 7516
39b5e676 7517\f
9c08d1fa 7518;; Jump and linkage insns
7519
cffb2a26 7520(define_expand "jump"
9c08d1fa 7521 [(set (pc)
7522 (label_ref (match_operand 0 "" "")))]
cffb2a26 7523 "TARGET_EITHER"
9c08d1fa 7524 ""
cffb2a26 7525)
7526
7527(define_insn "*arm_jump"
7528 [(set (pc)
7529 (label_ref (match_operand 0 "" "")))]
25f905c2 7530 "TARGET_32BIT"
9c08d1fa 7531 "*
0d66636f 7532 {
7533 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7534 {
7535 arm_ccfsm_state += 2;
7536 return \"\";
7537 }
7538 return \"b%?\\t%l0\";
7539 }
7540 "
a6864a24 7541 [(set_attr "predicable" "yes")
7542 (set (attr "length")
7543 (if_then_else
0bf497f5 7544 (and (match_test "TARGET_THUMB2")
a6864a24 7545 (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
7546 (le (minus (match_dup 0) (pc)) (const_int 2048))))
7547 (const_int 2)
1b7da4ac 7548 (const_int 4)))
7549 (set_attr "type" "branch")]
0d66636f 7550)
9c08d1fa 7551
d3373b54 7552(define_expand "call"
7553 [(parallel [(call (match_operand 0 "memory_operand" "")
7554 (match_operand 1 "general_operand" ""))
cffb2a26 7555 (use (match_operand 2 "" ""))
bd5b4116 7556 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 7557 "TARGET_EITHER"
6c4c2133 7558 "
7559 {
bac7fc85 7560 rtx callee, pat;
bbe777ea 7561
bbe777ea 7562 /* In an untyped call, we can get NULL for operand 2. */
7563 if (operands[2] == NULL_RTX)
7564 operands[2] = const0_rtx;
7565
de55252a 7566 /* Decide if we should generate indirect calls by loading the
85c36fd1 7567 32-bit address of the callee into a register before performing the
de55252a 7568 branch and link. */
7569 callee = XEXP (operands[0], 0);
7570 if (GET_CODE (callee) == SYMBOL_REF
7571 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
7572 : !REG_P (callee))
bbe777ea 7573 XEXP (operands[0], 0) = force_reg (Pmode, callee);
bac7fc85 7574
7575 pat = gen_call_internal (operands[0], operands[1], operands[2]);
ca373797 7576 arm_emit_call_insn (pat, XEXP (operands[0], 0), false);
bac7fc85 7577 DONE;
6c4c2133 7578 }"
7579)
d3373b54 7580
bac7fc85 7581(define_expand "call_internal"
7582 [(parallel [(call (match_operand 0 "memory_operand" "")
7583 (match_operand 1 "general_operand" ""))
7584 (use (match_operand 2 "" ""))
7585 (clobber (reg:SI LR_REGNUM))])])
7586
f1039640 7587(define_insn "*call_reg_armv5"
d3373b54 7588 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
cffb2a26 7589 (match_operand 1 "" ""))
7590 (use (match_operand 2 "" ""))
bd5b4116 7591 (clobber (reg:SI LR_REGNUM))]
33ae7c4b 7592 "TARGET_ARM && arm_arch5 && !SIBLING_CALL_P (insn)"
f1039640 7593 "blx%?\\t%0"
7594 [(set_attr "type" "call")]
7595)
7596
7597(define_insn "*call_reg_arm"
7598 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7599 (match_operand 1 "" ""))
7600 (use (match_operand 2 "" ""))
7601 (clobber (reg:SI LR_REGNUM))]
33ae7c4b 7602 "TARGET_ARM && !arm_arch5 && !SIBLING_CALL_P (insn)"
9c08d1fa 7603 "*
5565501b 7604 return output_call (operands);
cffb2a26 7605 "
7606 ;; length is worst case, normally it is only two
7607 [(set_attr "length" "12")
7608 (set_attr "type" "call")]
7609)
9c08d1fa 7610
89504fc1 7611
7612;; Note: not used for armv5+ because the sequence used (ldr pc, ...) is not
7613;; considered a function call by the branch predictor of some cores (PR40887).
7614;; Falls back to blx rN (*call_reg_armv5).
7615
f7fbdd4a 7616(define_insn "*call_mem"
a3c63a9d 7617 [(call (mem:SI (match_operand:SI 0 "call_memory_operand" "m"))
cffb2a26 7618 (match_operand 1 "" ""))
7619 (use (match_operand 2 "" ""))
bd5b4116 7620 (clobber (reg:SI LR_REGNUM))]
33ae7c4b 7621 "TARGET_ARM && !arm_arch5 && !SIBLING_CALL_P (insn)"
9c08d1fa 7622 "*
5565501b 7623 return output_call_mem (operands);
cffb2a26 7624 "
7625 [(set_attr "length" "12")
7626 (set_attr "type" "call")]
7627)
7628
d3373b54 7629(define_expand "call_value"
e0698af7 7630 [(parallel [(set (match_operand 0 "" "")
7631 (call (match_operand 1 "memory_operand" "")
7632 (match_operand 2 "general_operand" "")))
cffb2a26 7633 (use (match_operand 3 "" ""))
bd5b4116 7634 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 7635 "TARGET_EITHER"
6c4c2133 7636 "
7637 {
bac7fc85 7638 rtx pat, callee;
bbe777ea 7639
7640 /* In an untyped call, we can get NULL for operand 2. */
7641 if (operands[3] == 0)
7642 operands[3] = const0_rtx;
7643
de55252a 7644 /* Decide if we should generate indirect calls by loading the
7645 32-bit address of the callee into a register before performing the
7646 branch and link. */
7647 callee = XEXP (operands[1], 0);
7648 if (GET_CODE (callee) == SYMBOL_REF
7649 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
7650 : !REG_P (callee))
78fe751b 7651 XEXP (operands[1], 0) = force_reg (Pmode, callee);
bac7fc85 7652
7653 pat = gen_call_value_internal (operands[0], operands[1],
7654 operands[2], operands[3]);
ca373797 7655 arm_emit_call_insn (pat, XEXP (operands[1], 0), false);
bac7fc85 7656 DONE;
6c4c2133 7657 }"
7658)
d3373b54 7659
bac7fc85 7660(define_expand "call_value_internal"
7661 [(parallel [(set (match_operand 0 "" "")
7662 (call (match_operand 1 "memory_operand" "")
7663 (match_operand 2 "general_operand" "")))
7664 (use (match_operand 3 "" ""))
7665 (clobber (reg:SI LR_REGNUM))])])
7666
f1039640 7667(define_insn "*call_value_reg_armv5"
27ed6835 7668 [(set (match_operand 0 "" "")
755eb2b4 7669 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
cffb2a26 7670 (match_operand 2 "" "")))
bbe777ea 7671 (use (match_operand 3 "" ""))
bd5b4116 7672 (clobber (reg:SI LR_REGNUM))]
33ae7c4b 7673 "TARGET_ARM && arm_arch5 && !SIBLING_CALL_P (insn)"
f1039640 7674 "blx%?\\t%1"
7675 [(set_attr "type" "call")]
7676)
7677
7678(define_insn "*call_value_reg_arm"
7679 [(set (match_operand 0 "" "")
7680 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7681 (match_operand 2 "" "")))
7682 (use (match_operand 3 "" ""))
7683 (clobber (reg:SI LR_REGNUM))]
33ae7c4b 7684 "TARGET_ARM && !arm_arch5 && !SIBLING_CALL_P (insn)"
9c08d1fa 7685 "*
215b30b3 7686 return output_call (&operands[1]);
cffb2a26 7687 "
7688 [(set_attr "length" "12")
7689 (set_attr "type" "call")]
7690)
9c08d1fa 7691
89504fc1 7692;; Note: see *call_mem
7693
f7fbdd4a 7694(define_insn "*call_value_mem"
27ed6835 7695 [(set (match_operand 0 "" "")
a3c63a9d 7696 (call (mem:SI (match_operand:SI 1 "call_memory_operand" "m"))
cffb2a26 7697 (match_operand 2 "" "")))
bbe777ea 7698 (use (match_operand 3 "" ""))
bd5b4116 7699 (clobber (reg:SI LR_REGNUM))]
33ae7c4b 7700 "TARGET_ARM && !arm_arch5 && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
7701 && !SIBLING_CALL_P (insn)"
9c08d1fa 7702 "*
215b30b3 7703 return output_call_mem (&operands[1]);
cffb2a26 7704 "
7705 [(set_attr "length" "12")
7706 (set_attr "type" "call")]
7707)
9c08d1fa 7708
7709;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
7710;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
7711
f7fbdd4a 7712(define_insn "*call_symbol"
27ed6835 7713 [(call (mem:SI (match_operand:SI 0 "" ""))
cffb2a26 7714 (match_operand 1 "" ""))
bbe777ea 7715 (use (match_operand 2 "" ""))
bd5b4116 7716 (clobber (reg:SI LR_REGNUM))]
d68c2c10 7717 "TARGET_32BIT
33ae7c4b 7718 && !SIBLING_CALL_P (insn)
cffb2a26 7719 && (GET_CODE (operands[0]) == SYMBOL_REF)
de55252a 7720 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
6ebaa29d 7721 "*
7722 {
55c1e470 7723 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
6ebaa29d 7724 }"
cffb2a26 7725 [(set_attr "type" "call")]
7726)
9c08d1fa 7727
f7fbdd4a 7728(define_insn "*call_value_symbol"
ccd90aaa 7729 [(set (match_operand 0 "" "")
27ed6835 7730 (call (mem:SI (match_operand:SI 1 "" ""))
dd6d7504 7731 (match_operand:SI 2 "" "")))
bbe777ea 7732 (use (match_operand 3 "" ""))
bd5b4116 7733 (clobber (reg:SI LR_REGNUM))]
d68c2c10 7734 "TARGET_32BIT
33ae7c4b 7735 && !SIBLING_CALL_P (insn)
cffb2a26 7736 && (GET_CODE (operands[1]) == SYMBOL_REF)
de55252a 7737 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
6ebaa29d 7738 "*
7739 {
55c1e470 7740 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
6ebaa29d 7741 }"
cffb2a26 7742 [(set_attr "type" "call")]
7743)
7744
ca373797 7745(define_expand "sibcall_internal"
7746 [(parallel [(call (match_operand 0 "memory_operand" "")
7747 (match_operand 1 "general_operand" ""))
7748 (return)
7749 (use (match_operand 2 "" ""))])])
7750
1c494086 7751;; We may also be able to do sibcalls for Thumb, but it's much harder...
7752(define_expand "sibcall"
7753 [(parallel [(call (match_operand 0 "memory_operand" "")
7754 (match_operand 1 "general_operand" ""))
2ba80634 7755 (return)
7756 (use (match_operand 2 "" ""))])]
d68c2c10 7757 "TARGET_32BIT"
1c494086 7758 "
7759 {
ca373797 7760 rtx pat;
7761
3112c3f7 7762 if ((!REG_P (XEXP (operands[0], 0))
7763 && GET_CODE (XEXP (operands[0], 0)) != SYMBOL_REF)
7764 || (GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
7765 && arm_is_long_call_p (SYMBOL_REF_DECL (XEXP (operands[0], 0)))))
33ae7c4b 7766 XEXP (operands[0], 0) = force_reg (SImode, XEXP (operands[0], 0));
7767
1c494086 7768 if (operands[2] == NULL_RTX)
7769 operands[2] = const0_rtx;
ca373797 7770
7771 pat = gen_sibcall_internal (operands[0], operands[1], operands[2]);
7772 arm_emit_call_insn (pat, operands[0], true);
7773 DONE;
1c494086 7774 }"
7775)
7776
ca373797 7777(define_expand "sibcall_value_internal"
7778 [(parallel [(set (match_operand 0 "" "")
7779 (call (match_operand 1 "memory_operand" "")
7780 (match_operand 2 "general_operand" "")))
7781 (return)
7782 (use (match_operand 3 "" ""))])])
7783
1c494086 7784(define_expand "sibcall_value"
ccd90aaa 7785 [(parallel [(set (match_operand 0 "" "")
1c494086 7786 (call (match_operand 1 "memory_operand" "")
7787 (match_operand 2 "general_operand" "")))
2ba80634 7788 (return)
7789 (use (match_operand 3 "" ""))])]
d68c2c10 7790 "TARGET_32BIT"
1c494086 7791 "
7792 {
ca373797 7793 rtx pat;
7794
3112c3f7 7795 if ((!REG_P (XEXP (operands[1], 0))
7796 && GET_CODE (XEXP (operands[1], 0)) != SYMBOL_REF)
7797 || (GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
7798 && arm_is_long_call_p (SYMBOL_REF_DECL (XEXP (operands[1], 0)))))
33ae7c4b 7799 XEXP (operands[1], 0) = force_reg (SImode, XEXP (operands[1], 0));
7800
1c494086 7801 if (operands[3] == NULL_RTX)
7802 operands[3] = const0_rtx;
ca373797 7803
7804 pat = gen_sibcall_value_internal (operands[0], operands[1],
7805 operands[2], operands[3]);
7806 arm_emit_call_insn (pat, operands[1], true);
7807 DONE;
1c494086 7808 }"
7809)
7810
7811(define_insn "*sibcall_insn"
84ce8e5c 7812 [(call (mem:SI (match_operand:SI 0 "call_insn_operand" "Cs, US"))
1c494086 7813 (match_operand 1 "" ""))
2ba80634 7814 (return)
7815 (use (match_operand 2 "" ""))]
33ae7c4b 7816 "TARGET_32BIT && SIBLING_CALL_P (insn)"
1c494086 7817 "*
33ae7c4b 7818 if (which_alternative == 1)
7819 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
7820 else
7821 {
7822 if (arm_arch5 || arm_arch4t)
947d113e 7823 return \"bx%?\\t%0\\t%@ indirect register sibling call\";
33ae7c4b 7824 else
7825 return \"mov%?\\t%|pc, %0\\t%@ indirect register sibling call\";
7826 }
1c494086 7827 "
7828 [(set_attr "type" "call")]
7829)
7830
7831(define_insn "*sibcall_value_insn"
84ce8e5c 7832 [(set (match_operand 0 "" "")
7833 (call (mem:SI (match_operand:SI 1 "call_insn_operand" "Cs,US"))
1c494086 7834 (match_operand 2 "" "")))
2ba80634 7835 (return)
7836 (use (match_operand 3 "" ""))]
33ae7c4b 7837 "TARGET_32BIT && SIBLING_CALL_P (insn)"
1c494086 7838 "*
33ae7c4b 7839 if (which_alternative == 1)
7840 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
7841 else
7842 {
7843 if (arm_arch5 || arm_arch4t)
84ce8e5c 7844 return \"bx%?\\t%1\";
33ae7c4b 7845 else
7846 return \"mov%?\\t%|pc, %1\\t@ indirect sibling call \";
7847 }
1c494086 7848 "
7849 [(set_attr "type" "call")]
7850)
7851
0686440e 7852(define_expand "<return_str>return"
7853 [(returns)]
8cba51a5 7854 "(TARGET_ARM || (TARGET_THUMB2
7855 && ARM_FUNC_TYPE (arm_current_func_type ()) == ARM_FT_NORMAL
7856 && !IS_STACKALIGN (arm_current_func_type ())))
0686440e 7857 <return_cond_false>"
8cba51a5 7858 "
7859 {
7860 if (TARGET_THUMB2)
7861 {
0686440e 7862 thumb2_expand_return (<return_simple_p>);
8cba51a5 7863 DONE;
7864 }
7865 }
7866 "
7867)
d68c2c10 7868
9c08d1fa 7869;; Often the return insn will be the same as loading from memory, so set attr
d68c2c10 7870(define_insn "*arm_return"
9c08d1fa 7871 [(return)]
cffb2a26 7872 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
9c08d1fa 7873 "*
9c08d1fa 7874 {
cffb2a26 7875 if (arm_ccfsm_state == 2)
7876 {
7877 arm_ccfsm_state += 2;
7878 return \"\";
7879 }
e2549f81 7880 return output_return_instruction (const_true_rtx, true, false, false);
cffb2a26 7881 }"
a2cd141b 7882 [(set_attr "type" "load1")
755eb2b4 7883 (set_attr "length" "12")
0d66636f 7884 (set_attr "predicable" "yes")]
cffb2a26 7885)
9c08d1fa 7886
0686440e 7887(define_insn "*cond_<return_str>return"
9c08d1fa 7888 [(set (pc)
8fa3ba89 7889 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 7890 [(match_operand 1 "cc_register" "") (const_int 0)])
0686440e 7891 (returns)
9c08d1fa 7892 (pc)))]
0686440e 7893 "TARGET_ARM <return_cond_true>"
9c08d1fa 7894 "*
8fa3ba89 7895 {
7896 if (arm_ccfsm_state == 2)
7897 {
7898 arm_ccfsm_state += 2;
7899 return \"\";
7900 }
0686440e 7901 return output_return_instruction (operands[0], true, false,
7902 <return_simple_p>);
8fa3ba89 7903 }"
7904 [(set_attr "conds" "use")
755eb2b4 7905 (set_attr "length" "12")
a2cd141b 7906 (set_attr "type" "load1")]
8fa3ba89 7907)
9c08d1fa 7908
0686440e 7909(define_insn "*cond_<return_str>return_inverted"
9c08d1fa 7910 [(set (pc)
8fa3ba89 7911 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 7912 [(match_operand 1 "cc_register" "") (const_int 0)])
9c08d1fa 7913 (pc)
0686440e 7914 (returns)))]
7915 "TARGET_ARM <return_cond_true>"
9c08d1fa 7916 "*
8fa3ba89 7917 {
7918 if (arm_ccfsm_state == 2)
7919 {
7920 arm_ccfsm_state += 2;
7921 return \"\";
7922 }
0686440e 7923 return output_return_instruction (operands[0], true, true,
7924 <return_simple_p>);
8fa3ba89 7925 }"
7926 [(set_attr "conds" "use")
37a1317b 7927 (set_attr "length" "12")
a2cd141b 7928 (set_attr "type" "load1")]
8fa3ba89 7929)
9c08d1fa 7930
e2549f81 7931(define_insn "*arm_simple_return"
7932 [(simple_return)]
7933 "TARGET_ARM"
7934 "*
7935 {
7936 if (arm_ccfsm_state == 2)
7937 {
7938 arm_ccfsm_state += 2;
7939 return \"\";
7940 }
7941 return output_return_instruction (const_true_rtx, true, false, true);
7942 }"
7943 [(set_attr "type" "branch")
7944 (set_attr "length" "4")
7945 (set_attr "predicable" "yes")]
7946)
7947
68121397 7948;; Generate a sequence of instructions to determine if the processor is
7949;; in 26-bit or 32-bit mode, and return the appropriate return address
7950;; mask.
7951
7952(define_expand "return_addr_mask"
7953 [(set (match_dup 1)
7954 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7955 (const_int 0)))
7956 (set (match_operand:SI 0 "s_register_operand" "")
7957 (if_then_else:SI (eq (match_dup 1) (const_int 0))
7958 (const_int -1)
7959 (const_int 67108860)))] ; 0x03fffffc
7960 "TARGET_ARM"
7961 "
62eddbd4 7962 operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
68121397 7963 ")
7964
7965(define_insn "*check_arch2"
7966 [(set (match_operand:CC_NOOV 0 "cc_register" "")
7967 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7968 (const_int 0)))]
7969 "TARGET_ARM"
7970 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
7971 [(set_attr "length" "8")
1b7da4ac 7972 (set_attr "conds" "set")
7973 (set_attr "type" "multiple")]
68121397 7974)
7975
9c08d1fa 7976;; Call subroutine returning any type.
7977
7978(define_expand "untyped_call"
7979 [(parallel [(call (match_operand 0 "" "")
7980 (const_int 0))
7981 (match_operand 1 "" "")
7982 (match_operand 2 "" "")])]
ccd90aaa 7983 "TARGET_EITHER"
9c08d1fa 7984 "
215b30b3 7985 {
7986 int i;
ccd90aaa 7987 rtx par = gen_rtx_PARALLEL (VOIDmode,
7988 rtvec_alloc (XVECLEN (operands[2], 0)));
7989 rtx addr = gen_reg_rtx (Pmode);
7990 rtx mem;
7991 int size = 0;
9c08d1fa 7992
ccd90aaa 7993 emit_move_insn (addr, XEXP (operands[1], 0));
7994 mem = change_address (operands[1], BLKmode, addr);
9c08d1fa 7995
215b30b3 7996 for (i = 0; i < XVECLEN (operands[2], 0); i++)
7997 {
ccd90aaa 7998 rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
9c08d1fa 7999
ccd90aaa 8000 /* Default code only uses r0 as a return value, but we could
8001 be using anything up to 4 registers. */
8002 if (REGNO (src) == R0_REGNUM)
8003 src = gen_rtx_REG (TImode, R0_REGNUM);
8004
8005 XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
8006 GEN_INT (size));
8007 size += GET_MODE_SIZE (GET_MODE (src));
8008 }
8009
8010 emit_call_insn (GEN_CALL_VALUE (par, operands[0], const0_rtx, NULL,
8011 const0_rtx));
8012
8013 size = 0;
8014
8015 for (i = 0; i < XVECLEN (par, 0); i++)
8016 {
8017 HOST_WIDE_INT offset = 0;
8018 rtx reg = XEXP (XVECEXP (par, 0, i), 0);
8019
8020 if (size != 0)
29c05e22 8021 emit_move_insn (addr, plus_constant (Pmode, addr, size));
ccd90aaa 8022
8023 mem = change_address (mem, GET_MODE (reg), NULL);
8024 if (REGNO (reg) == R0_REGNUM)
8025 {
8026 /* On thumb we have to use a write-back instruction. */
320ea44d 8027 emit_insn (arm_gen_store_multiple (arm_regs_in_sequence, 4, addr,
8028 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
ccd90aaa 8029 size = TARGET_ARM ? 16 : 0;
8030 }
8031 else
8032 {
8033 emit_move_insn (mem, reg);
8034 size = GET_MODE_SIZE (GET_MODE (reg));
8035 }
215b30b3 8036 }
9c08d1fa 8037
215b30b3 8038 /* The optimizer does not know that the call sets the function value
8039 registers we stored in the result block. We avoid problems by
8040 claiming that all hard registers are used and clobbered at this
8041 point. */
8042 emit_insn (gen_blockage ());
8043
8044 DONE;
8045 }"
8046)
9c08d1fa 8047
ccd90aaa 8048(define_expand "untyped_return"
8049 [(match_operand:BLK 0 "memory_operand" "")
8050 (match_operand 1 "" "")]
8051 "TARGET_EITHER"
8052 "
8053 {
8054 int i;
8055 rtx addr = gen_reg_rtx (Pmode);
8056 rtx mem;
8057 int size = 0;
8058
8059 emit_move_insn (addr, XEXP (operands[0], 0));
8060 mem = change_address (operands[0], BLKmode, addr);
8061
8062 for (i = 0; i < XVECLEN (operands[1], 0); i++)
8063 {
8064 HOST_WIDE_INT offset = 0;
8065 rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
8066
8067 if (size != 0)
29c05e22 8068 emit_move_insn (addr, plus_constant (Pmode, addr, size));
ccd90aaa 8069
8070 mem = change_address (mem, GET_MODE (reg), NULL);
8071 if (REGNO (reg) == R0_REGNUM)
8072 {
8073 /* On thumb we have to use a write-back instruction. */
320ea44d 8074 emit_insn (arm_gen_load_multiple (arm_regs_in_sequence, 4, addr,
8075 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
ccd90aaa 8076 size = TARGET_ARM ? 16 : 0;
8077 }
8078 else
8079 {
8080 emit_move_insn (reg, mem);
8081 size = GET_MODE_SIZE (GET_MODE (reg));
8082 }
8083 }
8084
8085 /* Emit USE insns before the return. */
8086 for (i = 0; i < XVECLEN (operands[1], 0); i++)
18b42941 8087 emit_use (SET_DEST (XVECEXP (operands[1], 0, i)));
ccd90aaa 8088
8089 /* Construct the return. */
8090 expand_naked_return ();
8091
8092 DONE;
8093 }"
8094)
8095
9c08d1fa 8096;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
8097;; all of memory. This blocks insns from being moved across this point.
8098
8099(define_insn "blockage"
e1159bbe 8100 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
cffb2a26 8101 "TARGET_EITHER"
9c08d1fa 8102 ""
cffb2a26 8103 [(set_attr "length" "0")
8104 (set_attr "type" "block")]
8105)
9c08d1fa 8106
f7fbdd4a 8107(define_expand "casesi"
8108 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
aea4c774 8109 (match_operand:SI 1 "const_int_operand" "") ; lower bound
8110 (match_operand:SI 2 "const_int_operand" "") ; total range
f7fbdd4a 8111 (match_operand:SI 3 "" "") ; table label
8112 (match_operand:SI 4 "" "")] ; Out of range label
e6ac8414 8113 "TARGET_32BIT || optimize_size || flag_pic"
f7fbdd4a 8114 "
215b30b3 8115 {
e6ac8414 8116 enum insn_code code;
215b30b3 8117 if (operands[1] != const0_rtx)
8118 {
e6ac8414 8119 rtx reg = gen_reg_rtx (SImode);
f7fbdd4a 8120
215b30b3 8121 emit_insn (gen_addsi3 (reg, operands[0],
d022fa24 8122 gen_int_mode (-INTVAL (operands[1]),
8123 SImode)));
215b30b3 8124 operands[0] = reg;
8125 }
9c08d1fa 8126
25f905c2 8127 if (TARGET_ARM)
e6ac8414 8128 code = CODE_FOR_arm_casesi_internal;
3db2019b 8129 else if (TARGET_THUMB1)
e6ac8414 8130 code = CODE_FOR_thumb1_casesi_internal_pic;
25f905c2 8131 else if (flag_pic)
e6ac8414 8132 code = CODE_FOR_thumb2_casesi_internal_pic;
25f905c2 8133 else
e6ac8414 8134 code = CODE_FOR_thumb2_casesi_internal;
8135
8136 if (!insn_data[(int) code].operand[1].predicate(operands[2], SImode))
8137 operands[2] = force_reg (SImode, operands[2]);
8138
8139 emit_jump_insn (GEN_FCN ((int) code) (operands[0], operands[2],
8140 operands[3], operands[4]));
215b30b3 8141 DONE;
8142 }"
8143)
f7fbdd4a 8144
f082f1c4 8145;; The USE in this pattern is needed to tell flow analysis that this is
8146;; a CASESI insn. It has no other purpose.
25f905c2 8147(define_insn "arm_casesi_internal"
f082f1c4 8148 [(parallel [(set (pc)
8149 (if_then_else
8150 (leu (match_operand:SI 0 "s_register_operand" "r")
8151 (match_operand:SI 1 "arm_rhs_operand" "rI"))
8152 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
8153 (label_ref (match_operand 2 "" ""))))
8154 (label_ref (match_operand 3 "" ""))))
bd5b4116 8155 (clobber (reg:CC CC_REGNUM))
f082f1c4 8156 (use (label_ref (match_dup 2)))])]
cffb2a26 8157 "TARGET_ARM"
f7fbdd4a 8158 "*
0d66636f 8159 if (flag_pic)
8160 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
8161 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
8162 "
8163 [(set_attr "conds" "clob")
1b7da4ac 8164 (set_attr "length" "12")
8165 (set_attr "type" "multiple")]
0d66636f 8166)
9c08d1fa 8167
cffb2a26 8168(define_expand "indirect_jump"
9c08d1fa 8169 [(set (pc)
cffb2a26 8170 (match_operand:SI 0 "s_register_operand" ""))]
8171 "TARGET_EITHER"
25f905c2 8172 "
8173 /* Thumb-2 doesn't have mov pc, reg. Explicitly set the low bit of the
8174 address and use bx. */
8175 if (TARGET_THUMB2)
8176 {
8177 rtx tmp;
8178 tmp = gen_reg_rtx (SImode);
8179 emit_insn (gen_iorsi3 (tmp, operands[0], GEN_INT(1)));
8180 operands[0] = tmp;
8181 }
8182 "
cffb2a26 8183)
8184
f1039640 8185;; NB Never uses BX.
cffb2a26 8186(define_insn "*arm_indirect_jump"
8187 [(set (pc)
8188 (match_operand:SI 0 "s_register_operand" "r"))]
8189 "TARGET_ARM"
8190 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
1b7da4ac 8191 [(set_attr "predicable" "yes")
8192 (set_attr "type" "branch")]
cffb2a26 8193)
9c08d1fa 8194
f7fbdd4a 8195(define_insn "*load_indirect_jump"
9c08d1fa 8196 [(set (pc)
8197 (match_operand:SI 0 "memory_operand" "m"))]
cffb2a26 8198 "TARGET_ARM"
8199 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
a2cd141b 8200 [(set_attr "type" "load1")
61a2d04c 8201 (set_attr "pool_range" "4096")
8202 (set_attr "neg_pool_range" "4084")
0d66636f 8203 (set_attr "predicable" "yes")]
cffb2a26 8204)
8205
9c08d1fa 8206\f
8207;; Misc insns
8208
8209(define_insn "nop"
8210 [(const_int 0)]
cffb2a26 8211 "TARGET_EITHER"
8212 "*
25f905c2 8213 if (TARGET_UNIFIED_ASM)
8214 return \"nop\";
cffb2a26 8215 if (TARGET_ARM)
8216 return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
8217 return \"mov\\tr8, r8\";
8218 "
8219 [(set (attr "length")
8220 (if_then_else (eq_attr "is_thumb" "yes")
8221 (const_int 2)
1b7da4ac 8222 (const_int 4)))
8223 (set_attr "type" "mov_reg")]
cffb2a26 8224)
8225
ad9d4399 8226(define_insn "trap"
8227 [(trap_if (const_int 1) (const_int 0))]
8228 ""
8229 "*
8230 if (TARGET_ARM)
8231 return \".inst\\t0xe7f000f0\";
8232 else
8233 return \".inst\\t0xdeff\";
8234 "
8235 [(set (attr "length")
8236 (if_then_else (eq_attr "is_thumb" "yes")
8237 (const_int 2)
8238 (const_int 4)))
8239 (set_attr "type" "trap")
8240 (set_attr "conds" "unconditional")]
8241)
8242
9c08d1fa 8243\f
8244;; Patterns to allow combination of arithmetic, cond code and shifts
8245
0abea32c 8246(define_insn "*<arith_shift_insn>_multsi"
8247 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8248 (shiftable_ops:SI
8249 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
8250 (match_operand:SI 3 "power_of_two_operand" ""))
8251 (match_operand:SI 1 "s_register_operand" "rk,<t2_binop0>")))]
d5d4dc8d 8252 "TARGET_32BIT"
0abea32c 8253 "<arith_shift_insn>%?\\t%0, %1, %2, lsl %b3"
8254 [(set_attr "predicable" "yes")
8255 (set_attr "predicable_short_it" "no")
8256 (set_attr "shift" "4")
8257 (set_attr "arch" "a,t2")
8258 (set_attr "type" "alu_shift_imm")])
8259
8260(define_insn "*<arith_shift_insn>_shiftsi"
8261 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8262 (shiftable_ops:SI
8263 (match_operator:SI 2 "shift_nomul_operator"
8264 [(match_operand:SI 3 "s_register_operand" "r,r,r")
8265 (match_operand:SI 4 "shift_amount_operand" "M,M,r")])
8266 (match_operand:SI 1 "s_register_operand" "rk,<t2_binop0>,rk")))]
a021b821 8267 "TARGET_32BIT && GET_CODE (operands[2]) != MULT"
0abea32c 8268 "<arith_shift_insn>%?\\t%0, %1, %3%S2"
344495ea 8269 [(set_attr "predicable" "yes")
74ef923b 8270 (set_attr "predicable_short_it" "no")
331beb1a 8271 (set_attr "shift" "4")
0abea32c 8272 (set_attr "arch" "a,t2,a")
8273 (set_attr "type" "alu_shift_imm,alu_shift_imm,alu_shift_reg")])
9c08d1fa 8274
d7863cfe 8275(define_split
8276 [(set (match_operand:SI 0 "s_register_operand" "")
8277 (match_operator:SI 1 "shiftable_operator"
8278 [(match_operator:SI 2 "shiftable_operator"
8279 [(match_operator:SI 3 "shift_operator"
8280 [(match_operand:SI 4 "s_register_operand" "")
8281 (match_operand:SI 5 "reg_or_int_operand" "")])
8282 (match_operand:SI 6 "s_register_operand" "")])
8283 (match_operand:SI 7 "arm_rhs_operand" "")]))
8284 (clobber (match_operand:SI 8 "s_register_operand" ""))]
d5d4dc8d 8285 "TARGET_32BIT"
d7863cfe 8286 [(set (match_dup 8)
8287 (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8288 (match_dup 6)]))
8289 (set (match_dup 0)
8290 (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
8291 "")
8292
f7fbdd4a 8293(define_insn "*arith_shiftsi_compare0"
bd5b4116 8294 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 8295 (compare:CC_NOOV
8296 (match_operator:SI 1 "shiftable_operator"
8297 [(match_operator:SI 3 "shift_operator"
8298 [(match_operand:SI 4 "s_register_operand" "r,r")
8299 (match_operand:SI 5 "shift_amount_operand" "M,r")])
8300 (match_operand:SI 2 "s_register_operand" "r,r")])
8301 (const_int 0)))
8302 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 8303 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8304 (match_dup 2)]))]
d5d4dc8d 8305 "TARGET_32BIT"
25f905c2 8306 "%i1%.\\t%0, %2, %4%S3"
344495ea 8307 [(set_attr "conds" "set")
331beb1a 8308 (set_attr "shift" "4")
d5d4dc8d 8309 (set_attr "arch" "32,a")
d82e788e 8310 (set_attr "type" "alus_shift_imm,alus_shift_reg")])
9c08d1fa 8311
f7fbdd4a 8312(define_insn "*arith_shiftsi_compare0_scratch"
bd5b4116 8313 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 8314 (compare:CC_NOOV
8315 (match_operator:SI 1 "shiftable_operator"
8316 [(match_operator:SI 3 "shift_operator"
8317 [(match_operand:SI 4 "s_register_operand" "r,r")
8318 (match_operand:SI 5 "shift_amount_operand" "M,r")])
8319 (match_operand:SI 2 "s_register_operand" "r,r")])
8320 (const_int 0)))
8321 (clobber (match_scratch:SI 0 "=r,r"))]
8322 "TARGET_32BIT"
25f905c2 8323 "%i1%.\\t%0, %2, %4%S3"
344495ea 8324 [(set_attr "conds" "set")
331beb1a 8325 (set_attr "shift" "4")
d5d4dc8d 8326 (set_attr "arch" "32,a")
d82e788e 8327 (set_attr "type" "alus_shift_imm,alus_shift_reg")])
9c08d1fa 8328
f7fbdd4a 8329(define_insn "*sub_shiftsi"
d5d4dc8d 8330 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8331 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
9c08d1fa 8332 (match_operator:SI 2 "shift_operator"
d5d4dc8d 8333 [(match_operand:SI 3 "s_register_operand" "r,r")
8334 (match_operand:SI 4 "shift_amount_operand" "M,r")])))]
8335 "TARGET_32BIT"
6c4c2133 8336 "sub%?\\t%0, %1, %3%S2"
344495ea 8337 [(set_attr "predicable" "yes")
331beb1a 8338 (set_attr "shift" "3")
d5d4dc8d 8339 (set_attr "arch" "32,a")
d82e788e 8340 (set_attr "type" "alus_shift_imm,alus_shift_reg")])
9c08d1fa 8341
f7fbdd4a 8342(define_insn "*sub_shiftsi_compare0"
bd5b4116 8343 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 8344 (compare:CC_NOOV
d82e788e 8345 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
40dbec34 8346 (match_operator:SI 2 "shift_operator"
d82e788e 8347 [(match_operand:SI 3 "s_register_operand" "r,r,r")
8348 (match_operand:SI 4 "shift_amount_operand" "M,r,M")]))
40dbec34 8349 (const_int 0)))
d82e788e 8350 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
d5d4dc8d 8351 (minus:SI (match_dup 1)
8352 (match_op_dup 2 [(match_dup 3) (match_dup 4)])))]
8353 "TARGET_32BIT"
25f905c2 8354 "sub%.\\t%0, %1, %3%S2"
344495ea 8355 [(set_attr "conds" "set")
a2cd141b 8356 (set_attr "shift" "3")
d82e788e 8357 (set_attr "arch" "32,a,a")
8358 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
9c08d1fa 8359
f7fbdd4a 8360(define_insn "*sub_shiftsi_compare0_scratch"
bd5b4116 8361 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 8362 (compare:CC_NOOV
d82e788e 8363 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
40dbec34 8364 (match_operator:SI 2 "shift_operator"
d82e788e 8365 [(match_operand:SI 3 "s_register_operand" "r,r,r")
8366 (match_operand:SI 4 "shift_amount_operand" "M,r,M")]))
40dbec34 8367 (const_int 0)))
d82e788e 8368 (clobber (match_scratch:SI 0 "=r,r,r"))]
d5d4dc8d 8369 "TARGET_32BIT"
25f905c2 8370 "sub%.\\t%0, %1, %3%S2"
344495ea 8371 [(set_attr "conds" "set")
a2cd141b 8372 (set_attr "shift" "3")
d82e788e 8373 (set_attr "arch" "32,a,a")
8374 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
9c08d1fa 8375\f
8376
190efb17 8377(define_insn_and_split "*and_scc"
9c08d1fa 8378 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 8379 (and:SI (match_operator:SI 1 "arm_comparison_operator"
190efb17 8380 [(match_operand 2 "cc_register" "") (const_int 0)])
8381 (match_operand:SI 3 "s_register_operand" "r")))]
cffb2a26 8382 "TARGET_ARM"
190efb17 8383 "#" ; "mov%D1\\t%0, #0\;and%d1\\t%0, %3, #1"
8384 "&& reload_completed"
8385 [(cond_exec (match_dup 5) (set (match_dup 0) (const_int 0)))
8386 (cond_exec (match_dup 4) (set (match_dup 0)
8387 (and:SI (match_dup 3) (const_int 1))))]
8388 {
3754d046 8389 machine_mode mode = GET_MODE (operands[2]);
190efb17 8390 enum rtx_code rc = GET_CODE (operands[1]);
8391
8392 /* Note that operands[4] is the same as operands[1],
8393 but with VOIDmode as the result. */
8394 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
8395 if (mode == CCFPmode || mode == CCFPEmode)
8396 rc = reverse_condition_maybe_unordered (rc);
8397 else
8398 rc = reverse_condition (rc);
8399 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
8400 }
8fa3ba89 8401 [(set_attr "conds" "use")
1b7da4ac 8402 (set_attr "type" "multiple")
8fa3ba89 8403 (set_attr "length" "8")]
8404)
9c08d1fa 8405
190efb17 8406(define_insn_and_split "*ior_scc"
9c08d1fa 8407 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
190efb17 8408 (ior:SI (match_operator:SI 1 "arm_comparison_operator"
8409 [(match_operand 2 "cc_register" "") (const_int 0)])
8410 (match_operand:SI 3 "s_register_operand" "0,?r")))]
cffb2a26 8411 "TARGET_ARM"
e2348bcb 8412 "@
190efb17 8413 orr%d1\\t%0, %3, #1
8414 #"
8415 "&& reload_completed
8416 && REGNO (operands [0]) != REGNO (operands[3])"
8417 ;; && which_alternative == 1
8418 ; mov%D1\\t%0, %3\;orr%d1\\t%0, %3, #1
8419 [(cond_exec (match_dup 5) (set (match_dup 0) (match_dup 3)))
8420 (cond_exec (match_dup 4) (set (match_dup 0)
8421 (ior:SI (match_dup 3) (const_int 1))))]
8422 {
3754d046 8423 machine_mode mode = GET_MODE (operands[2]);
190efb17 8424 enum rtx_code rc = GET_CODE (operands[1]);
8425
8426 /* Note that operands[4] is the same as operands[1],
8427 but with VOIDmode as the result. */
8428 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
8429 if (mode == CCFPmode || mode == CCFPEmode)
8430 rc = reverse_condition_maybe_unordered (rc);
8431 else
8432 rc = reverse_condition (rc);
8433 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
8434 }
8fa3ba89 8435 [(set_attr "conds" "use")
1b7da4ac 8436 (set_attr "length" "4,8")
8437 (set_attr "type" "logic_imm,multiple")]
8fa3ba89 8438)
9c08d1fa 8439
2df9477b 8440; A series of splitters for the compare_scc pattern below. Note that
8441; order is important.
8442(define_split
8443 [(set (match_operand:SI 0 "s_register_operand" "")
8444 (lt:SI (match_operand:SI 1 "s_register_operand" "")
8445 (const_int 0)))
8446 (clobber (reg:CC CC_REGNUM))]
8447 "TARGET_32BIT && reload_completed"
8448 [(set (match_dup 0) (lshiftrt:SI (match_dup 1) (const_int 31)))])
8449
8450(define_split
8451 [(set (match_operand:SI 0 "s_register_operand" "")
8452 (ge:SI (match_operand:SI 1 "s_register_operand" "")
8453 (const_int 0)))
8454 (clobber (reg:CC CC_REGNUM))]
8455 "TARGET_32BIT && reload_completed"
8456 [(set (match_dup 0) (not:SI (match_dup 1)))
8457 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 31)))])
8458
98562479 8459(define_split
8460 [(set (match_operand:SI 0 "s_register_operand" "")
8461 (eq:SI (match_operand:SI 1 "s_register_operand" "")
8462 (const_int 0)))
8463 (clobber (reg:CC CC_REGNUM))]
8464 "arm_arch5 && TARGET_32BIT"
8465 [(set (match_dup 0) (clz:SI (match_dup 1)))
8466 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 5)))]
8467)
8468
2df9477b 8469(define_split
8470 [(set (match_operand:SI 0 "s_register_operand" "")
8471 (eq:SI (match_operand:SI 1 "s_register_operand" "")
8472 (const_int 0)))
8473 (clobber (reg:CC CC_REGNUM))]
8474 "TARGET_32BIT && reload_completed"
8475 [(parallel
080c0b9a 8476 [(set (reg:CC CC_REGNUM)
8477 (compare:CC (const_int 1) (match_dup 1)))
2df9477b 8478 (set (match_dup 0)
8479 (minus:SI (const_int 1) (match_dup 1)))])
080c0b9a 8480 (cond_exec (ltu:CC (reg:CC CC_REGNUM) (const_int 0))
2df9477b 8481 (set (match_dup 0) (const_int 0)))])
8482
8483(define_split
8484 [(set (match_operand:SI 0 "s_register_operand" "")
8485 (ne:SI (match_operand:SI 1 "s_register_operand" "")
8486 (match_operand:SI 2 "const_int_operand" "")))
8487 (clobber (reg:CC CC_REGNUM))]
8488 "TARGET_32BIT && reload_completed"
8489 [(parallel
8490 [(set (reg:CC CC_REGNUM)
8491 (compare:CC (match_dup 1) (match_dup 2)))
8492 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))])
8493 (cond_exec (ne:CC (reg:CC CC_REGNUM) (const_int 0))
8494 (set (match_dup 0) (const_int 1)))]
8495{
8496 operands[3] = GEN_INT (-INTVAL (operands[2]));
8497})
8498
8499(define_split
8500 [(set (match_operand:SI 0 "s_register_operand" "")
8501 (ne:SI (match_operand:SI 1 "s_register_operand" "")
8502 (match_operand:SI 2 "arm_add_operand" "")))
8503 (clobber (reg:CC CC_REGNUM))]
8504 "TARGET_32BIT && reload_completed"
8505 [(parallel
8506 [(set (reg:CC_NOOV CC_REGNUM)
8507 (compare:CC_NOOV (minus:SI (match_dup 1) (match_dup 2))
8508 (const_int 0)))
8509 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
8510 (cond_exec (ne:CC_NOOV (reg:CC_NOOV CC_REGNUM) (const_int 0))
8511 (set (match_dup 0) (const_int 1)))])
8512
8513(define_insn_and_split "*compare_scc"
fd711051 8514 [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts")
8fa3ba89 8515 (match_operator:SI 1 "arm_comparison_operator"
5565501b 8516 [(match_operand:SI 2 "s_register_operand" "r,r")
8517 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
bd5b4116 8518 (clobber (reg:CC CC_REGNUM))]
2df9477b 8519 "TARGET_32BIT"
8520 "#"
8521 "&& reload_completed"
8522 [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 3)))
8523 (cond_exec (match_dup 4) (set (match_dup 0) (const_int 0)))
8524 (cond_exec (match_dup 5) (set (match_dup 0) (const_int 1)))]
8525{
8526 rtx tmp1;
3754d046 8527 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
2df9477b 8528 operands[2], operands[3]);
8529 enum rtx_code rc = GET_CODE (operands[1]);
e2348bcb 8530
2df9477b 8531 tmp1 = gen_rtx_REG (mode, CC_REGNUM);
080c0b9a 8532
2df9477b 8533 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
8534 if (mode == CCFPmode || mode == CCFPEmode)
8535 rc = reverse_condition_maybe_unordered (rc);
8536 else
8537 rc = reverse_condition (rc);
8538 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
1b7da4ac 8539}
8540 [(set_attr "type" "multiple")]
8541)
9c08d1fa 8542
080c0b9a 8543;; Attempt to improve the sequence generated by the compare_scc splitters
8544;; not to use conditional execution.
98562479 8545
8546;; Rd = (eq (reg1) (const_int0)) // ARMv5
8547;; clz Rd, reg1
8548;; lsr Rd, Rd, #5
080c0b9a 8549(define_peephole2
8550 [(set (reg:CC CC_REGNUM)
8551 (compare:CC (match_operand:SI 1 "register_operand" "")
98562479 8552 (const_int 0)))
8553 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
8554 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
8555 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
8556 (set (match_dup 0) (const_int 1)))]
8557 "arm_arch5 && TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)"
8558 [(set (match_dup 0) (clz:SI (match_dup 1)))
8559 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 5)))]
8560)
8561
8562;; Rd = (eq (reg1) (const_int0)) // !ARMv5
8563;; negs Rd, reg1
8564;; adc Rd, Rd, reg1
8565(define_peephole2
8566 [(set (reg:CC CC_REGNUM)
8567 (compare:CC (match_operand:SI 1 "register_operand" "")
8568 (const_int 0)))
080c0b9a 8569 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
8570 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
8571 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
8572 (set (match_dup 0) (const_int 1)))
98562479 8573 (match_scratch:SI 2 "r")]
8574 "TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)"
922b6913 8575 [(parallel
8576 [(set (reg:CC CC_REGNUM)
98562479 8577 (compare:CC (const_int 0) (match_dup 1)))
8578 (set (match_dup 2) (minus:SI (const_int 0) (match_dup 1)))])
8579 (set (match_dup 0)
8580 (plus:SI (plus:SI (match_dup 1) (match_dup 2))
8581 (geu:SI (reg:CC CC_REGNUM) (const_int 0))))]
8582)
8583
31991287 8584;; Rd = (eq (reg1) (reg2/imm)) // ARMv5 and optimising for speed.
98562479 8585;; sub Rd, Reg1, reg2
8586;; clz Rd, Rd
8587;; lsr Rd, Rd, #5
8588(define_peephole2
8589 [(set (reg:CC CC_REGNUM)
8590 (compare:CC (match_operand:SI 1 "register_operand" "")
8591 (match_operand:SI 2 "arm_rhs_operand" "")))
8592 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
8593 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
8594 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
8595 (set (match_dup 0) (const_int 1)))]
31991287 8596 "arm_arch5 && TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)
8597 && !(TARGET_THUMB2 && optimize_insn_for_size_p ())"
98562479 8598 [(set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))
8599 (set (match_dup 0) (clz:SI (match_dup 0)))
8600 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 5)))]
8601)
8602
8603
31991287 8604;; Rd = (eq (reg1) (reg2)) // ! ARMv5 or optimising for size.
98562479 8605;; sub T1, Reg1, reg2
8606;; negs Rd, T1
8607;; adc Rd, Rd, T1
8608(define_peephole2
8609 [(set (reg:CC CC_REGNUM)
8610 (compare:CC (match_operand:SI 1 "register_operand" "")
8611 (match_operand:SI 2 "arm_rhs_operand" "")))
8612 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
8613 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
8614 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
8615 (set (match_dup 0) (const_int 1)))
8616 (match_scratch:SI 3 "r")]
8617 "TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)"
31991287 8618 [(set (match_dup 3) (match_dup 4))
080c0b9a 8619 (parallel
8620 [(set (reg:CC CC_REGNUM)
8621 (compare:CC (const_int 0) (match_dup 3)))
8622 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 3)))])
98562479 8623 (set (match_dup 0)
8624 (plus:SI (plus:SI (match_dup 0) (match_dup 3))
8625 (geu:SI (reg:CC CC_REGNUM) (const_int 0))))]
31991287 8626 "
8627 if (CONST_INT_P (operands[2]))
8628 operands[4] = plus_constant (SImode, operands[1], -INTVAL (operands[2]));
8629 else
8630 operands[4] = gen_rtx_MINUS (SImode, operands[1], operands[2]);
8631 ")
080c0b9a 8632
f7fbdd4a 8633(define_insn "*cond_move"
9c08d1fa 8634 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
aea4c774 8635 (if_then_else:SI (match_operator 3 "equality_operator"
8fa3ba89 8636 [(match_operator 4 "arm_comparison_operator"
8a18b90c 8637 [(match_operand 5 "cc_register" "") (const_int 0)])
aea4c774 8638 (const_int 0)])
8639 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8640 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
cffb2a26 8641 "TARGET_ARM"
9c08d1fa 8642 "*
8fa3ba89 8643 if (GET_CODE (operands[3]) == NE)
8644 {
8645 if (which_alternative != 1)
8646 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
8647 if (which_alternative != 0)
8648 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
8649 return \"\";
8650 }
8651 if (which_alternative != 0)
8652 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8653 if (which_alternative != 1)
8654 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
8655 return \"\";
8656 "
8657 [(set_attr "conds" "use")
1b7da4ac 8658 (set_attr "type" "mov_reg,mov_reg,multiple")
8fa3ba89 8659 (set_attr "length" "4,4,8")]
8660)
9c08d1fa 8661
f7fbdd4a 8662(define_insn "*cond_arith"
9c08d1fa 8663 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8664 (match_operator:SI 5 "shiftable_operator"
8fa3ba89 8665 [(match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 8666 [(match_operand:SI 2 "s_register_operand" "r,r")
8667 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8668 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 8669 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8670 "TARGET_ARM"
9c08d1fa 8671 "*
8fa3ba89 8672 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
8673 return \"%i5\\t%0, %1, %2, lsr #31\";
40dbec34 8674
8fa3ba89 8675 output_asm_insn (\"cmp\\t%2, %3\", operands);
8676 if (GET_CODE (operands[5]) == AND)
8677 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
8678 else if (GET_CODE (operands[5]) == MINUS)
8679 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
8680 else if (which_alternative != 0)
8681 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8682 return \"%i5%d4\\t%0, %1, #1\";
8683 "
8684 [(set_attr "conds" "clob")
1b7da4ac 8685 (set_attr "length" "12")
8686 (set_attr "type" "multiple")]
8fa3ba89 8687)
9c08d1fa 8688
f7fbdd4a 8689(define_insn "*cond_sub"
9c08d1fa 8690 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8691 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8fa3ba89 8692 (match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 8693 [(match_operand:SI 2 "s_register_operand" "r,r")
8694 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 8695 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8696 "TARGET_ARM"
9c08d1fa 8697 "*
8fa3ba89 8698 output_asm_insn (\"cmp\\t%2, %3\", operands);
8699 if (which_alternative != 0)
8700 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8701 return \"sub%d4\\t%0, %1, #1\";
8702 "
8703 [(set_attr "conds" "clob")
1b7da4ac 8704 (set_attr "length" "8,12")
8705 (set_attr "type" "multiple")]
8fa3ba89 8706)
9c08d1fa 8707
aea4c774 8708(define_insn "*cmp_ite0"
cffb2a26 8709 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 8710 (compare
8711 (if_then_else:SI
8fa3ba89 8712 (match_operator 4 "arm_comparison_operator"
2ff91fec 8713 [(match_operand:SI 0 "s_register_operand"
8714 "l,l,l,r,r,r,r,r,r")
8715 (match_operand:SI 1 "arm_add_operand"
8716 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
8fa3ba89 8717 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 8718 [(match_operand:SI 2 "s_register_operand"
8719 "l,r,r,l,l,r,r,r,r")
8720 (match_operand:SI 3 "arm_add_operand"
8721 "lPy,rI,L,lPy,lPy,rI,rI,L,L")])
aea4c774 8722 (const_int 0))
8723 (const_int 0)))]
2ff91fec 8724 "TARGET_32BIT"
9c08d1fa 8725 "*
aea4c774 8726 {
2ff91fec 8727 static const char * const cmp1[NUM_OF_COND_CMP][2] =
8728 {
8729 {\"cmp%d5\\t%0, %1\",
8730 \"cmp%d4\\t%2, %3\"},
8731 {\"cmn%d5\\t%0, #%n1\",
8732 \"cmp%d4\\t%2, %3\"},
8733 {\"cmp%d5\\t%0, %1\",
8734 \"cmn%d4\\t%2, #%n3\"},
8735 {\"cmn%d5\\t%0, #%n1\",
8736 \"cmn%d4\\t%2, #%n3\"}
8737 };
8738 static const char * const cmp2[NUM_OF_COND_CMP][2] =
8739 {
8740 {\"cmp\\t%2, %3\",
8741 \"cmp\\t%0, %1\"},
8742 {\"cmp\\t%2, %3\",
8743 \"cmn\\t%0, #%n1\"},
8744 {\"cmn\\t%2, #%n3\",
8745 \"cmp\\t%0, %1\"},
8746 {\"cmn\\t%2, #%n3\",
8747 \"cmn\\t%0, #%n1\"}
8748 };
8749 static const char * const ite[2] =
8fa3ba89 8750 {
2ff91fec 8751 \"it\\t%d5\",
8752 \"it\\t%d4\"
8fa3ba89 8753 };
2ff91fec 8754 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
8755 CMP_CMP, CMN_CMP, CMP_CMP,
8756 CMN_CMP, CMP_CMN, CMN_CMN};
8fa3ba89 8757 int swap =
8758 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8759
2ff91fec 8760 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
8761 if (TARGET_THUMB2) {
8762 output_asm_insn (ite[swap], operands);
8763 }
8764 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
8765 return \"\";
8fa3ba89 8766 }"
8767 [(set_attr "conds" "set")
2ff91fec 8768 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
1b7da4ac 8769 (set_attr "type" "multiple")
2ff91fec 8770 (set_attr_alternative "length"
8771 [(const_int 6)
8772 (const_int 8)
8773 (const_int 8)
8774 (const_int 8)
8775 (const_int 8)
8776 (if_then_else (eq_attr "is_thumb" "no")
8777 (const_int 8)
8778 (const_int 10))
8779 (if_then_else (eq_attr "is_thumb" "no")
8780 (const_int 8)
8781 (const_int 10))
8782 (if_then_else (eq_attr "is_thumb" "no")
8783 (const_int 8)
8784 (const_int 10))
8785 (if_then_else (eq_attr "is_thumb" "no")
8786 (const_int 8)
8787 (const_int 10))])]
8fa3ba89 8788)
9c08d1fa 8789
aea4c774 8790(define_insn "*cmp_ite1"
cffb2a26 8791 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 8792 (compare
8793 (if_then_else:SI
8fa3ba89 8794 (match_operator 4 "arm_comparison_operator"
2ff91fec 8795 [(match_operand:SI 0 "s_register_operand"
8796 "l,l,l,r,r,r,r,r,r")
8797 (match_operand:SI 1 "arm_add_operand"
8798 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
8fa3ba89 8799 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 8800 [(match_operand:SI 2 "s_register_operand"
8801 "l,r,r,l,l,r,r,r,r")
8802 (match_operand:SI 3 "arm_add_operand"
8803 "lPy,rI,L,lPy,lPy,rI,rI,L,L")])
aea4c774 8804 (const_int 1))
8805 (const_int 0)))]
2ff91fec 8806 "TARGET_32BIT"
9c08d1fa 8807 "*
9c08d1fa 8808 {
2ff91fec 8809 static const char * const cmp1[NUM_OF_COND_CMP][2] =
8810 {
8811 {\"cmp\\t%0, %1\",
8812 \"cmp\\t%2, %3\"},
8813 {\"cmn\\t%0, #%n1\",
8814 \"cmp\\t%2, %3\"},
8815 {\"cmp\\t%0, %1\",
8816 \"cmn\\t%2, #%n3\"},
8817 {\"cmn\\t%0, #%n1\",
8818 \"cmn\\t%2, #%n3\"}
8819 };
8820 static const char * const cmp2[NUM_OF_COND_CMP][2] =
215b30b3 8821 {
2ff91fec 8822 {\"cmp%d4\\t%2, %3\",
8823 \"cmp%D5\\t%0, %1\"},
8824 {\"cmp%d4\\t%2, %3\",
8825 \"cmn%D5\\t%0, #%n1\"},
8826 {\"cmn%d4\\t%2, #%n3\",
8827 \"cmp%D5\\t%0, %1\"},
8828 {\"cmn%d4\\t%2, #%n3\",
8829 \"cmn%D5\\t%0, #%n1\"}
215b30b3 8830 };
2ff91fec 8831 static const char * const ite[2] =
8832 {
8833 \"it\\t%d4\",
8834 \"it\\t%D5\"
8835 };
8836 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
8837 CMP_CMP, CMN_CMP, CMP_CMP,
8838 CMN_CMP, CMP_CMN, CMN_CMN};
215b30b3 8839 int swap =
8840 comparison_dominates_p (GET_CODE (operands[5]),
8841 reverse_condition (GET_CODE (operands[4])));
8842
2ff91fec 8843 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
8844 if (TARGET_THUMB2) {
8845 output_asm_insn (ite[swap], operands);
8846 }
8847 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
8848 return \"\";
215b30b3 8849 }"
8fa3ba89 8850 [(set_attr "conds" "set")
2ff91fec 8851 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
8852 (set_attr_alternative "length"
8853 [(const_int 6)
8854 (const_int 8)
8855 (const_int 8)
8856 (const_int 8)
8857 (const_int 8)
8858 (if_then_else (eq_attr "is_thumb" "no")
8859 (const_int 8)
8860 (const_int 10))
8861 (if_then_else (eq_attr "is_thumb" "no")
8862 (const_int 8)
8863 (const_int 10))
8864 (if_then_else (eq_attr "is_thumb" "no")
8865 (const_int 8)
8866 (const_int 10))
8867 (if_then_else (eq_attr "is_thumb" "no")
8868 (const_int 8)
1b7da4ac 8869 (const_int 10))])
8870 (set_attr "type" "multiple")]
8fa3ba89 8871)
9c08d1fa 8872
f6c53574 8873(define_insn "*cmp_and"
8874 [(set (match_operand 6 "dominant_cc_register" "")
8875 (compare
8876 (and:SI
8877 (match_operator 4 "arm_comparison_operator"
2ff91fec 8878 [(match_operand:SI 0 "s_register_operand"
8879 "l,l,l,r,r,r,r,r,r")
8880 (match_operand:SI 1 "arm_add_operand"
8881 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
f6c53574 8882 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 8883 [(match_operand:SI 2 "s_register_operand"
8884 "l,r,r,l,l,r,r,r,r")
8885 (match_operand:SI 3 "arm_add_operand"
8886 "lPy,rI,L,lPy,lPy,rI,rI,L,L")]))
f6c53574 8887 (const_int 0)))]
2ff91fec 8888 "TARGET_32BIT"
f6c53574 8889 "*
8890 {
2ff91fec 8891 static const char *const cmp1[NUM_OF_COND_CMP][2] =
f6c53574 8892 {
2ff91fec 8893 {\"cmp%d5\\t%0, %1\",
8894 \"cmp%d4\\t%2, %3\"},
8895 {\"cmn%d5\\t%0, #%n1\",
8896 \"cmp%d4\\t%2, %3\"},
8897 {\"cmp%d5\\t%0, %1\",
8898 \"cmn%d4\\t%2, #%n3\"},
8899 {\"cmn%d5\\t%0, #%n1\",
8900 \"cmn%d4\\t%2, #%n3\"}
f6c53574 8901 };
2ff91fec 8902 static const char *const cmp2[NUM_OF_COND_CMP][2] =
8903 {
8904 {\"cmp\\t%2, %3\",
8905 \"cmp\\t%0, %1\"},
8906 {\"cmp\\t%2, %3\",
8907 \"cmn\\t%0, #%n1\"},
8908 {\"cmn\\t%2, #%n3\",
8909 \"cmp\\t%0, %1\"},
8910 {\"cmn\\t%2, #%n3\",
8911 \"cmn\\t%0, #%n1\"}
8912 };
8913 static const char *const ite[2] =
8914 {
8915 \"it\\t%d5\",
8916 \"it\\t%d4\"
8917 };
8918 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
8919 CMP_CMP, CMN_CMP, CMP_CMP,
8920 CMN_CMP, CMP_CMN, CMN_CMN};
f6c53574 8921 int swap =
8922 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8923
2ff91fec 8924 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
8925 if (TARGET_THUMB2) {
8926 output_asm_insn (ite[swap], operands);
8927 }
8928 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
8929 return \"\";
f6c53574 8930 }"
8931 [(set_attr "conds" "set")
8932 (set_attr "predicable" "no")
2ff91fec 8933 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
8934 (set_attr_alternative "length"
8935 [(const_int 6)
8936 (const_int 8)
8937 (const_int 8)
8938 (const_int 8)
8939 (const_int 8)
8940 (if_then_else (eq_attr "is_thumb" "no")
8941 (const_int 8)
8942 (const_int 10))
8943 (if_then_else (eq_attr "is_thumb" "no")
8944 (const_int 8)
8945 (const_int 10))
8946 (if_then_else (eq_attr "is_thumb" "no")
8947 (const_int 8)
8948 (const_int 10))
8949 (if_then_else (eq_attr "is_thumb" "no")
8950 (const_int 8)
1b7da4ac 8951 (const_int 10))])
8952 (set_attr "type" "multiple")]
f6c53574 8953)
8954
8955(define_insn "*cmp_ior"
8956 [(set (match_operand 6 "dominant_cc_register" "")
8957 (compare
8958 (ior:SI
8959 (match_operator 4 "arm_comparison_operator"
2ff91fec 8960 [(match_operand:SI 0 "s_register_operand"
8961 "l,l,l,r,r,r,r,r,r")
8962 (match_operand:SI 1 "arm_add_operand"
8963 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
f6c53574 8964 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 8965 [(match_operand:SI 2 "s_register_operand"
8966 "l,r,r,l,l,r,r,r,r")
8967 (match_operand:SI 3 "arm_add_operand"
8968 "lPy,rI,L,lPy,lPy,rI,rI,L,L")]))
f6c53574 8969 (const_int 0)))]
2ff91fec 8970 "TARGET_32BIT"
f6c53574 8971 "*
f6c53574 8972 {
2ff91fec 8973 static const char *const cmp1[NUM_OF_COND_CMP][2] =
8974 {
8975 {\"cmp\\t%0, %1\",
8976 \"cmp\\t%2, %3\"},
8977 {\"cmn\\t%0, #%n1\",
8978 \"cmp\\t%2, %3\"},
8979 {\"cmp\\t%0, %1\",
8980 \"cmn\\t%2, #%n3\"},
8981 {\"cmn\\t%0, #%n1\",
8982 \"cmn\\t%2, #%n3\"}
8983 };
8984 static const char *const cmp2[NUM_OF_COND_CMP][2] =
8985 {
8986 {\"cmp%D4\\t%2, %3\",
8987 \"cmp%D5\\t%0, %1\"},
8988 {\"cmp%D4\\t%2, %3\",
8989 \"cmn%D5\\t%0, #%n1\"},
8990 {\"cmn%D4\\t%2, #%n3\",
8991 \"cmp%D5\\t%0, %1\"},
8992 {\"cmn%D4\\t%2, #%n3\",
8993 \"cmn%D5\\t%0, #%n1\"}
8994 };
8995 static const char *const ite[2] =
8996 {
8997 \"it\\t%D4\",
8998 \"it\\t%D5\"
8999 };
9000 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
9001 CMP_CMP, CMN_CMP, CMP_CMP,
9002 CMN_CMP, CMP_CMN, CMN_CMN};
9003 int swap =
9004 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9005
9006 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9007 if (TARGET_THUMB2) {
9008 output_asm_insn (ite[swap], operands);
9009 }
9010 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9011 return \"\";
9012 }
9013 "
f6c53574 9014 [(set_attr "conds" "set")
2ff91fec 9015 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
9016 (set_attr_alternative "length"
9017 [(const_int 6)
9018 (const_int 8)
9019 (const_int 8)
9020 (const_int 8)
9021 (const_int 8)
9022 (if_then_else (eq_attr "is_thumb" "no")
9023 (const_int 8)
9024 (const_int 10))
9025 (if_then_else (eq_attr "is_thumb" "no")
9026 (const_int 8)
9027 (const_int 10))
9028 (if_then_else (eq_attr "is_thumb" "no")
9029 (const_int 8)
9030 (const_int 10))
9031 (if_then_else (eq_attr "is_thumb" "no")
9032 (const_int 8)
1b7da4ac 9033 (const_int 10))])
9034 (set_attr "type" "multiple")]
f6c53574 9035)
9036
3c5afce6 9037(define_insn_and_split "*ior_scc_scc"
fd711051 9038 [(set (match_operand:SI 0 "s_register_operand" "=Ts")
3c5afce6 9039 (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9040 [(match_operand:SI 1 "s_register_operand" "r")
9041 (match_operand:SI 2 "arm_add_operand" "rIL")])
9042 (match_operator:SI 6 "arm_comparison_operator"
9043 [(match_operand:SI 4 "s_register_operand" "r")
9044 (match_operand:SI 5 "arm_add_operand" "rIL")])))
9045 (clobber (reg:CC CC_REGNUM))]
2ff91fec 9046 "TARGET_32BIT
3c5afce6 9047 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
9048 != CCmode)"
9049 "#"
2ff91fec 9050 "TARGET_32BIT && reload_completed"
3c5afce6 9051 [(set (match_dup 7)
9052 (compare
9053 (ior:SI
9054 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9055 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9056 (const_int 0)))
9057 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9058 "operands[7]
9059 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9060 DOM_CC_X_OR_Y),
601f584c 9061 CC_REGNUM);"
9062 [(set_attr "conds" "clob")
1b7da4ac 9063 (set_attr "length" "16")
9064 (set_attr "type" "multiple")]
9065)
601f584c 9066
9067; If the above pattern is followed by a CMP insn, then the compare is
9068; redundant, since we can rework the conditional instruction that follows.
9069(define_insn_and_split "*ior_scc_scc_cmp"
9070 [(set (match_operand 0 "dominant_cc_register" "")
9071 (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9072 [(match_operand:SI 1 "s_register_operand" "r")
9073 (match_operand:SI 2 "arm_add_operand" "rIL")])
9074 (match_operator:SI 6 "arm_comparison_operator"
9075 [(match_operand:SI 4 "s_register_operand" "r")
9076 (match_operand:SI 5 "arm_add_operand" "rIL")]))
9077 (const_int 0)))
fd711051 9078 (set (match_operand:SI 7 "s_register_operand" "=Ts")
601f584c 9079 (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9080 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
2ff91fec 9081 "TARGET_32BIT"
601f584c 9082 "#"
2ff91fec 9083 "TARGET_32BIT && reload_completed"
601f584c 9084 [(set (match_dup 0)
9085 (compare
9086 (ior:SI
9087 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9088 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9089 (const_int 0)))
9090 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9091 ""
9092 [(set_attr "conds" "set")
1b7da4ac 9093 (set_attr "length" "16")
9094 (set_attr "type" "multiple")]
9095)
3c5afce6 9096
9097(define_insn_and_split "*and_scc_scc"
fd711051 9098 [(set (match_operand:SI 0 "s_register_operand" "=Ts")
3c5afce6 9099 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9100 [(match_operand:SI 1 "s_register_operand" "r")
9101 (match_operand:SI 2 "arm_add_operand" "rIL")])
9102 (match_operator:SI 6 "arm_comparison_operator"
9103 [(match_operand:SI 4 "s_register_operand" "r")
9104 (match_operand:SI 5 "arm_add_operand" "rIL")])))
9105 (clobber (reg:CC CC_REGNUM))]
2ff91fec 9106 "TARGET_32BIT
3c5afce6 9107 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9108 != CCmode)"
9109 "#"
2ff91fec 9110 "TARGET_32BIT && reload_completed
601f584c 9111 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9112 != CCmode)"
3c5afce6 9113 [(set (match_dup 7)
9114 (compare
9115 (and:SI
9116 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9117 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9118 (const_int 0)))
9119 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9120 "operands[7]
9121 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9122 DOM_CC_X_AND_Y),
601f584c 9123 CC_REGNUM);"
9124 [(set_attr "conds" "clob")
1b7da4ac 9125 (set_attr "length" "16")
9126 (set_attr "type" "multiple")]
9127)
601f584c 9128
9129; If the above pattern is followed by a CMP insn, then the compare is
9130; redundant, since we can rework the conditional instruction that follows.
9131(define_insn_and_split "*and_scc_scc_cmp"
9132 [(set (match_operand 0 "dominant_cc_register" "")
9133 (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
9134 [(match_operand:SI 1 "s_register_operand" "r")
9135 (match_operand:SI 2 "arm_add_operand" "rIL")])
9136 (match_operator:SI 6 "arm_comparison_operator"
9137 [(match_operand:SI 4 "s_register_operand" "r")
9138 (match_operand:SI 5 "arm_add_operand" "rIL")]))
9139 (const_int 0)))
fd711051 9140 (set (match_operand:SI 7 "s_register_operand" "=Ts")
601f584c 9141 (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9142 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
2ff91fec 9143 "TARGET_32BIT"
601f584c 9144 "#"
2ff91fec 9145 "TARGET_32BIT && reload_completed"
601f584c 9146 [(set (match_dup 0)
9147 (compare
9148 (and:SI
9149 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9150 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9151 (const_int 0)))
9152 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9153 ""
9154 [(set_attr "conds" "set")
1b7da4ac 9155 (set_attr "length" "16")
9156 (set_attr "type" "multiple")]
9157)
601f584c 9158
9159;; If there is no dominance in the comparison, then we can still save an
9160;; instruction in the AND case, since we can know that the second compare
9161;; need only zero the value if false (if true, then the value is already
9162;; correct).
9163(define_insn_and_split "*and_scc_scc_nodom"
fd711051 9164 [(set (match_operand:SI 0 "s_register_operand" "=&Ts,&Ts,&Ts")
601f584c 9165 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9166 [(match_operand:SI 1 "s_register_operand" "r,r,0")
9167 (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
9168 (match_operator:SI 6 "arm_comparison_operator"
9169 [(match_operand:SI 4 "s_register_operand" "r,r,r")
9170 (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
9171 (clobber (reg:CC CC_REGNUM))]
2ff91fec 9172 "TARGET_32BIT
601f584c 9173 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9174 == CCmode)"
9175 "#"
2ff91fec 9176 "TARGET_32BIT && reload_completed"
601f584c 9177 [(parallel [(set (match_dup 0)
9178 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
9179 (clobber (reg:CC CC_REGNUM))])
9180 (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
9181 (set (match_dup 0)
9182 (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
9183 (match_dup 0)
9184 (const_int 0)))]
9185 "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
9186 operands[4], operands[5]),
9187 CC_REGNUM);
9188 operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
9189 operands[5]);"
9190 [(set_attr "conds" "clob")
1b7da4ac 9191 (set_attr "length" "20")
9192 (set_attr "type" "multiple")]
9193)
3c5afce6 9194
3a0bdee0 9195(define_split
9196 [(set (reg:CC_NOOV CC_REGNUM)
9197 (compare:CC_NOOV (ior:SI
9198 (and:SI (match_operand:SI 0 "s_register_operand" "")
9199 (const_int 1))
b0694be0 9200 (match_operator:SI 1 "arm_comparison_operator"
3a0bdee0 9201 [(match_operand:SI 2 "s_register_operand" "")
9202 (match_operand:SI 3 "arm_add_operand" "")]))
9203 (const_int 0)))
9204 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9205 "TARGET_ARM"
9206 [(set (match_dup 4)
9207 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9208 (match_dup 0)))
9209 (set (reg:CC_NOOV CC_REGNUM)
9210 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9211 (const_int 0)))]
9212 "")
9213
9214(define_split
9215 [(set (reg:CC_NOOV CC_REGNUM)
9216 (compare:CC_NOOV (ior:SI
b0694be0 9217 (match_operator:SI 1 "arm_comparison_operator"
3a0bdee0 9218 [(match_operand:SI 2 "s_register_operand" "")
9219 (match_operand:SI 3 "arm_add_operand" "")])
9220 (and:SI (match_operand:SI 0 "s_register_operand" "")
9221 (const_int 1)))
9222 (const_int 0)))
9223 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9224 "TARGET_ARM"
9225 [(set (match_dup 4)
9226 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9227 (match_dup 0)))
9228 (set (reg:CC_NOOV CC_REGNUM)
9229 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9230 (const_int 0)))]
9231 "")
25f905c2 9232;; ??? The conditional patterns above need checking for Thumb-2 usefulness
3a0bdee0 9233
190efb17 9234(define_insn_and_split "*negscc"
9c08d1fa 9235 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9236 (neg:SI (match_operator 3 "arm_comparison_operator"
9c08d1fa 9237 [(match_operand:SI 1 "s_register_operand" "r")
9238 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
bd5b4116 9239 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9240 "TARGET_ARM"
190efb17 9241 "#"
9242 "&& reload_completed"
9243 [(const_int 0)]
9244 {
9245 rtx cc_reg = gen_rtx_REG (CCmode, CC_REGNUM);
e2348bcb 9246
190efb17 9247 if (GET_CODE (operands[3]) == LT && operands[2] == const0_rtx)
9248 {
9249 /* Emit mov\\t%0, %1, asr #31 */
9250 emit_insn (gen_rtx_SET (VOIDmode,
9251 operands[0],
9252 gen_rtx_ASHIFTRT (SImode,
9253 operands[1],
9254 GEN_INT (31))));
9255 DONE;
9256 }
9257 else if (GET_CODE (operands[3]) == NE)
9258 {
9259 /* Emit subs\\t%0, %1, %2\;mvnne\\t%0, #0 */
9260 if (CONST_INT_P (operands[2]))
9261 emit_insn (gen_cmpsi2_addneg (operands[0], operands[1], operands[2],
9262 GEN_INT (- INTVAL (operands[2]))));
9263 else
9264 emit_insn (gen_subsi3_compare (operands[0], operands[1], operands[2]));
9265
9266 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
9267 gen_rtx_NE (SImode,
9268 cc_reg,
9269 const0_rtx),
9270 gen_rtx_SET (SImode,
9271 operands[0],
9272 GEN_INT (~0))));
9273 DONE;
9274 }
9275 else
9276 {
9277 /* Emit: cmp\\t%1, %2\;mov%D3\\t%0, #0\;mvn%d3\\t%0, #0 */
9278 emit_insn (gen_rtx_SET (VOIDmode,
9279 cc_reg,
9280 gen_rtx_COMPARE (CCmode, operands[1], operands[2])));
9281 enum rtx_code rc = GET_CODE (operands[3]);
9282
9283 rc = reverse_condition (rc);
9284 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
9285 gen_rtx_fmt_ee (rc,
9286 VOIDmode,
9287 cc_reg,
9288 const0_rtx),
9289 gen_rtx_SET (VOIDmode, operands[0], const0_rtx)));
9290 rc = GET_CODE (operands[3]);
9291 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
9292 gen_rtx_fmt_ee (rc,
9293 VOIDmode,
9294 cc_reg,
9295 const0_rtx),
9296 gen_rtx_SET (VOIDmode,
9297 operands[0],
9298 GEN_INT (~0))));
9299 DONE;
9300 }
9301 FAIL;
9302 }
8fa3ba89 9303 [(set_attr "conds" "clob")
1b7da4ac 9304 (set_attr "length" "12")
9305 (set_attr "type" "multiple")]
8fa3ba89 9306)
9c08d1fa 9307
90404b57 9308(define_insn_and_split "movcond_addsi"
9309 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r")
9310 (if_then_else:SI
9311 (match_operator 5 "comparison_operator"
9312 [(plus:SI (match_operand:SI 3 "s_register_operand" "r,r,r")
9313 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL"))
9314 (const_int 0)])
9315 (match_operand:SI 1 "arm_rhs_operand" "rI,rPy,r")
9316 (match_operand:SI 2 "arm_rhs_operand" "rI,rPy,r")))
9317 (clobber (reg:CC CC_REGNUM))]
9318 "TARGET_32BIT"
9319 "#"
9320 "&& reload_completed"
9321 [(set (reg:CC_NOOV CC_REGNUM)
9322 (compare:CC_NOOV
9323 (plus:SI (match_dup 3)
9324 (match_dup 4))
9325 (const_int 0)))
9326 (set (match_dup 0) (match_dup 1))
9327 (cond_exec (match_dup 6)
9328 (set (match_dup 0) (match_dup 2)))]
9329 "
9330 {
3754d046 9331 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[5]),
90404b57 9332 operands[3], operands[4]);
9333 enum rtx_code rc = GET_CODE (operands[5]);
90404b57 9334 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9335 gcc_assert (!(mode == CCFPmode || mode == CCFPEmode));
4d01ce2f 9336 if (REGNO (operands[2]) != REGNO (operands[0]))
9337 rc = reverse_condition (rc);
f145bcba 9338 else
9339 std::swap (operands[1], operands[2]);
90404b57 9340
9341 operands[6] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9342 }
9343 "
9344 [(set_attr "conds" "clob")
1b7da4ac 9345 (set_attr "enabled_for_depr_it" "no,yes,yes")
9346 (set_attr "type" "multiple")]
90404b57 9347)
9348
9c08d1fa 9349(define_insn "movcond"
9350 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 9351 (if_then_else:SI
8fa3ba89 9352 (match_operator 5 "arm_comparison_operator"
5565501b 9353 [(match_operand:SI 3 "s_register_operand" "r,r,r")
9354 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
9355 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9356 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 9357 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9358 "TARGET_ARM"
9c08d1fa 9359 "*
9360 if (GET_CODE (operands[5]) == LT
9361 && (operands[4] == const0_rtx))
9362 {
0438d37f 9363 if (which_alternative != 1 && REG_P (operands[1]))
9c08d1fa 9364 {
9c08d1fa 9365 if (operands[2] == const0_rtx)
e2348bcb 9366 return \"and\\t%0, %1, %3, asr #31\";
9367 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
9c08d1fa 9368 }
0438d37f 9369 else if (which_alternative != 0 && REG_P (operands[2]))
9c08d1fa 9370 {
9c08d1fa 9371 if (operands[1] == const0_rtx)
e2348bcb 9372 return \"bic\\t%0, %2, %3, asr #31\";
9373 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
9c08d1fa 9374 }
9375 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 9376 are constants. */
9c08d1fa 9377 }
e2348bcb 9378
9c08d1fa 9379 if (GET_CODE (operands[5]) == GE
9380 && (operands[4] == const0_rtx))
9381 {
0438d37f 9382 if (which_alternative != 1 && REG_P (operands[1]))
9c08d1fa 9383 {
9c08d1fa 9384 if (operands[2] == const0_rtx)
e2348bcb 9385 return \"bic\\t%0, %1, %3, asr #31\";
9386 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
9c08d1fa 9387 }
0438d37f 9388 else if (which_alternative != 0 && REG_P (operands[2]))
9c08d1fa 9389 {
9c08d1fa 9390 if (operands[1] == const0_rtx)
e2348bcb 9391 return \"and\\t%0, %2, %3, asr #31\";
9392 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
9c08d1fa 9393 }
9394 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 9395 are constants. */
9c08d1fa 9396 }
0438d37f 9397 if (CONST_INT_P (operands[4])
9c08d1fa 9398 && !const_ok_for_arm (INTVAL (operands[4])))
e2348bcb 9399 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
9c08d1fa 9400 else
e2348bcb 9401 output_asm_insn (\"cmp\\t%3, %4\", operands);
9c08d1fa 9402 if (which_alternative != 0)
e2348bcb 9403 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
9c08d1fa 9404 if (which_alternative != 1)
e2348bcb 9405 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
9c08d1fa 9406 return \"\";
215b30b3 9407 "
8fa3ba89 9408 [(set_attr "conds" "clob")
1b7da4ac 9409 (set_attr "length" "8,8,12")
9410 (set_attr "type" "multiple")]
8fa3ba89 9411)
9c08d1fa 9412
25f905c2 9413;; ??? The patterns below need checking for Thumb-2 usefulness.
9414
8a18b90c 9415(define_insn "*ifcompare_plus_move"
9416 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9417 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 9418 [(match_operand:SI 4 "s_register_operand" "r,r")
9419 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9420 (plus:SI
9421 (match_operand:SI 2 "s_register_operand" "r,r")
9422 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
129a2fe4 9423 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 9424 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9425 "TARGET_ARM"
8a18b90c 9426 "#"
8fa3ba89 9427 [(set_attr "conds" "clob")
1b7da4ac 9428 (set_attr "length" "8,12")
9429 (set_attr "type" "multiple")]
8fa3ba89 9430)
8a18b90c 9431
9432(define_insn "*if_plus_move"
129a2fe4 9433 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 9434 (if_then_else:SI
8fa3ba89 9435 (match_operator 4 "arm_comparison_operator"
8a18b90c 9436 [(match_operand 5 "cc_register" "") (const_int 0)])
9437 (plus:SI
129a2fe4 9438 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9439 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
9440 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
cffb2a26 9441 "TARGET_ARM"
8a18b90c 9442 "@
9443 add%d4\\t%0, %2, %3
9444 sub%d4\\t%0, %2, #%n3
9445 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
129a2fe4 9446 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8fa3ba89 9447 [(set_attr "conds" "use")
9448 (set_attr "length" "4,4,8,8")
65f68e55 9449 (set_attr_alternative "type"
9450 [(if_then_else (match_operand 3 "const_int_operand" "")
d82e788e 9451 (const_string "alu_imm" )
112eda6f 9452 (const_string "alu_sreg"))
d82e788e 9453 (const_string "alu_imm")
112eda6f 9454 (const_string "alu_sreg")
9455 (const_string "alu_sreg")])]
8fa3ba89 9456)
8a18b90c 9457
9458(define_insn "*ifcompare_move_plus"
5565501b 9459 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9460 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 9461 [(match_operand:SI 4 "s_register_operand" "r,r")
9462 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 9463 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 9464 (plus:SI
9465 (match_operand:SI 2 "s_register_operand" "r,r")
9466 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
bd5b4116 9467 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9468 "TARGET_ARM"
8a18b90c 9469 "#"
8fa3ba89 9470 [(set_attr "conds" "clob")
1b7da4ac 9471 (set_attr "length" "8,12")
9472 (set_attr "type" "multiple")]
8fa3ba89 9473)
8a18b90c 9474
9475(define_insn "*if_move_plus"
129a2fe4 9476 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 9477 (if_then_else:SI
8fa3ba89 9478 (match_operator 4 "arm_comparison_operator"
8a18b90c 9479 [(match_operand 5 "cc_register" "") (const_int 0)])
129a2fe4 9480 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8a18b90c 9481 (plus:SI
129a2fe4 9482 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9483 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
cffb2a26 9484 "TARGET_ARM"
8a18b90c 9485 "@
9486 add%D4\\t%0, %2, %3
9487 sub%D4\\t%0, %2, #%n3
9488 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
129a2fe4 9489 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8fa3ba89 9490 [(set_attr "conds" "use")
9491 (set_attr "length" "4,4,8,8")
112eda6f 9492 (set_attr "type" "alu_sreg,alu_imm,multiple,multiple")]
8fa3ba89 9493)
8a18b90c 9494
9495(define_insn "*ifcompare_arith_arith"
9496 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9497 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8a18b90c 9498 [(match_operand:SI 5 "s_register_operand" "r")
9499 (match_operand:SI 6 "arm_add_operand" "rIL")])
9c08d1fa 9500 (match_operator:SI 8 "shiftable_operator"
8a18b90c 9501 [(match_operand:SI 1 "s_register_operand" "r")
9502 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9c08d1fa 9503 (match_operator:SI 7 "shiftable_operator"
8a18b90c 9504 [(match_operand:SI 3 "s_register_operand" "r")
9505 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
bd5b4116 9506 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9507 "TARGET_ARM"
8a18b90c 9508 "#"
8fa3ba89 9509 [(set_attr "conds" "clob")
1b7da4ac 9510 (set_attr "length" "12")
9511 (set_attr "type" "multiple")]
8fa3ba89 9512)
9c08d1fa 9513
8a18b90c 9514(define_insn "*if_arith_arith"
9515 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9516 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8a18b90c 9517 [(match_operand 8 "cc_register" "") (const_int 0)])
9518 (match_operator:SI 6 "shiftable_operator"
9519 [(match_operand:SI 1 "s_register_operand" "r")
9520 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9521 (match_operator:SI 7 "shiftable_operator"
9522 [(match_operand:SI 3 "s_register_operand" "r")
9523 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
cffb2a26 9524 "TARGET_ARM"
8a18b90c 9525 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8fa3ba89 9526 [(set_attr "conds" "use")
1b7da4ac 9527 (set_attr "length" "8")
9528 (set_attr "type" "multiple")]
8fa3ba89 9529)
8a18b90c 9530
f7fbdd4a 9531(define_insn "*ifcompare_arith_move"
9c08d1fa 9532 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9533 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 9534 [(match_operand:SI 2 "s_register_operand" "r,r")
5565501b 9535 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
9c08d1fa 9536 (match_operator:SI 7 "shiftable_operator"
9537 [(match_operand:SI 4 "s_register_operand" "r,r")
9538 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
129a2fe4 9539 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 9540 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9541 "TARGET_ARM"
9c08d1fa 9542 "*
9c08d1fa 9543 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 9544 the conditional operator is LT or GE and we are comparing against zero and
674a8f0b 9545 everything is in registers then we can do this in two instructions. */
9c08d1fa 9546 if (operands[3] == const0_rtx
9547 && GET_CODE (operands[7]) != AND
0438d37f 9548 && REG_P (operands[5])
9549 && REG_P (operands[1])
9c08d1fa 9550 && REGNO (operands[1]) == REGNO (operands[4])
9551 && REGNO (operands[4]) != REGNO (operands[0]))
9552 {
9553 if (GET_CODE (operands[6]) == LT)
40dbec34 9554 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 9555 else if (GET_CODE (operands[6]) == GE)
40dbec34 9556 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 9557 }
0438d37f 9558 if (CONST_INT_P (operands[3])
9c08d1fa 9559 && !const_ok_for_arm (INTVAL (operands[3])))
e2348bcb 9560 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
9c08d1fa 9561 else
e2348bcb 9562 output_asm_insn (\"cmp\\t%2, %3\", operands);
40dbec34 9563 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
9c08d1fa 9564 if (which_alternative != 0)
129a2fe4 9565 return \"mov%D6\\t%0, %1\";
9c08d1fa 9566 return \"\";
215b30b3 9567 "
8fa3ba89 9568 [(set_attr "conds" "clob")
1b7da4ac 9569 (set_attr "length" "8,12")
9570 (set_attr "type" "multiple")]
8fa3ba89 9571)
9c08d1fa 9572
8a18b90c 9573(define_insn "*if_arith_move"
129a2fe4 9574 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9575 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8a18b90c 9576 [(match_operand 6 "cc_register" "") (const_int 0)])
9577 (match_operator:SI 5 "shiftable_operator"
129a2fe4 9578 [(match_operand:SI 2 "s_register_operand" "r,r")
9579 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
9580 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
cffb2a26 9581 "TARGET_ARM"
8a18b90c 9582 "@
9583 %I5%d4\\t%0, %2, %3
129a2fe4 9584 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8fa3ba89 9585 [(set_attr "conds" "use")
9586 (set_attr "length" "4,8")
1b7da4ac 9587 (set_attr "type" "alu_shift_reg,multiple")]
8fa3ba89 9588)
8a18b90c 9589
f7fbdd4a 9590(define_insn "*ifcompare_move_arith"
9c08d1fa 9591 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9592 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 9593 [(match_operand:SI 4 "s_register_operand" "r,r")
5565501b 9594 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 9595 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9c08d1fa 9596 (match_operator:SI 7 "shiftable_operator"
9597 [(match_operand:SI 2 "s_register_operand" "r,r")
9598 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 9599 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9600 "TARGET_ARM"
9c08d1fa 9601 "*
9c08d1fa 9602 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 9603 the conditional operator is LT or GE and we are comparing against zero and
9c08d1fa 9604 everything is in registers then we can do this in two instructions */
9605 if (operands[5] == const0_rtx
9606 && GET_CODE (operands[7]) != AND
0438d37f 9607 && REG_P (operands[3])
9608 && REG_P (operands[1])
9c08d1fa 9609 && REGNO (operands[1]) == REGNO (operands[2])
9610 && REGNO (operands[2]) != REGNO (operands[0]))
9611 {
9612 if (GET_CODE (operands[6]) == GE)
40dbec34 9613 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 9614 else if (GET_CODE (operands[6]) == LT)
40dbec34 9615 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 9616 }
40dbec34 9617
0438d37f 9618 if (CONST_INT_P (operands[5])
9c08d1fa 9619 && !const_ok_for_arm (INTVAL (operands[5])))
e2348bcb 9620 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
9c08d1fa 9621 else
e2348bcb 9622 output_asm_insn (\"cmp\\t%4, %5\", operands);
40dbec34 9623
9c08d1fa 9624 if (which_alternative != 0)
129a2fe4 9625 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
40dbec34 9626 return \"%I7%D6\\t%0, %2, %3\";
215b30b3 9627 "
8fa3ba89 9628 [(set_attr "conds" "clob")
1b7da4ac 9629 (set_attr "length" "8,12")
9630 (set_attr "type" "multiple")]
8fa3ba89 9631)
9c08d1fa 9632
8a18b90c 9633(define_insn "*if_move_arith"
129a2fe4 9634 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9635 (if_then_else:SI
8fa3ba89 9636 (match_operator 4 "arm_comparison_operator"
8a18b90c 9637 [(match_operand 6 "cc_register" "") (const_int 0)])
129a2fe4 9638 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 9639 (match_operator:SI 5 "shiftable_operator"
129a2fe4 9640 [(match_operand:SI 2 "s_register_operand" "r,r")
9641 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
cffb2a26 9642 "TARGET_ARM"
8a18b90c 9643 "@
9644 %I5%D4\\t%0, %2, %3
129a2fe4 9645 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
8fa3ba89 9646 [(set_attr "conds" "use")
9647 (set_attr "length" "4,8")
1b7da4ac 9648 (set_attr "type" "alu_shift_reg,multiple")]
8fa3ba89 9649)
8a18b90c 9650
9651(define_insn "*ifcompare_move_not"
9c08d1fa 9652 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9653 (if_then_else:SI
8fa3ba89 9654 (match_operator 5 "arm_comparison_operator"
8a18b90c 9655 [(match_operand:SI 3 "s_register_operand" "r,r")
9656 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9657 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9658 (not:SI
9659 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 9660 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9661 "TARGET_ARM"
8a18b90c 9662 "#"
8fa3ba89 9663 [(set_attr "conds" "clob")
1b7da4ac 9664 (set_attr "length" "8,12")
9665 (set_attr "type" "multiple")]
8fa3ba89 9666)
9c08d1fa 9667
8a18b90c 9668(define_insn "*if_move_not"
9669 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9670 (if_then_else:SI
8fa3ba89 9671 (match_operator 4 "arm_comparison_operator"
8a18b90c 9672 [(match_operand 3 "cc_register" "") (const_int 0)])
9673 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9674 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
cffb2a26 9675 "TARGET_ARM"
8a18b90c 9676 "@
9677 mvn%D4\\t%0, %2
9678 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
9679 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
8fa3ba89 9680 [(set_attr "conds" "use")
1aed5204 9681 (set_attr "type" "mvn_reg")
1b7da4ac 9682 (set_attr "length" "4,8,8")
9683 (set_attr "type" "mvn_reg,multiple,multiple")]
8fa3ba89 9684)
8a18b90c 9685
9686(define_insn "*ifcompare_not_move"
9c08d1fa 9687 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9688 (if_then_else:SI
8fa3ba89 9689 (match_operator 5 "arm_comparison_operator"
8a18b90c 9690 [(match_operand:SI 3 "s_register_operand" "r,r")
9691 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9692 (not:SI
9693 (match_operand:SI 2 "s_register_operand" "r,r"))
9694 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 9695 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9696 "TARGET_ARM"
8a18b90c 9697 "#"
8fa3ba89 9698 [(set_attr "conds" "clob")
1b7da4ac 9699 (set_attr "length" "8,12")
9700 (set_attr "type" "multiple")]
8fa3ba89 9701)
9c08d1fa 9702
8a18b90c 9703(define_insn "*if_not_move"
9704 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9705 (if_then_else:SI
8fa3ba89 9706 (match_operator 4 "arm_comparison_operator"
8a18b90c 9707 [(match_operand 3 "cc_register" "") (const_int 0)])
9708 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9709 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 9710 "TARGET_ARM"
8a18b90c 9711 "@
9712 mvn%d4\\t%0, %2
9713 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
9714 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
8fa3ba89 9715 [(set_attr "conds" "use")
1b7da4ac 9716 (set_attr "type" "mvn_reg,multiple,multiple")
8fa3ba89 9717 (set_attr "length" "4,8,8")]
9718)
8a18b90c 9719
9720(define_insn "*ifcompare_shift_move"
9c08d1fa 9721 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9722 (if_then_else:SI
8fa3ba89 9723 (match_operator 6 "arm_comparison_operator"
8a18b90c 9724 [(match_operand:SI 4 "s_register_operand" "r,r")
9725 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9726 (match_operator:SI 7 "shift_operator"
9727 [(match_operand:SI 2 "s_register_operand" "r,r")
9728 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
9729 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 9730 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9731 "TARGET_ARM"
9c08d1fa 9732 "#"
8fa3ba89 9733 [(set_attr "conds" "clob")
1b7da4ac 9734 (set_attr "length" "8,12")
9735 (set_attr "type" "multiple")]
8fa3ba89 9736)
9c08d1fa 9737
8a18b90c 9738(define_insn "*if_shift_move"
9739 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9740 (if_then_else:SI
8fa3ba89 9741 (match_operator 5 "arm_comparison_operator"
8a18b90c 9742 [(match_operand 6 "cc_register" "") (const_int 0)])
9743 (match_operator:SI 4 "shift_operator"
9744 [(match_operand:SI 2 "s_register_operand" "r,r,r")
9745 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
9746 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 9747 "TARGET_ARM"
5565501b 9748 "@
8a18b90c 9749 mov%d5\\t%0, %2%S4
9750 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
9751 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
8fa3ba89 9752 [(set_attr "conds" "use")
331beb1a 9753 (set_attr "shift" "2")
a2cd141b 9754 (set_attr "length" "4,8,8")
1b7da4ac 9755 (set_attr "type" "mov_shift_reg,multiple,multiple")]
8fa3ba89 9756)
5565501b 9757
8a18b90c 9758(define_insn "*ifcompare_move_shift"
9759 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 9760 (if_then_else:SI
8fa3ba89 9761 (match_operator 6 "arm_comparison_operator"
8a18b90c 9762 [(match_operand:SI 4 "s_register_operand" "r,r")
9763 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9764 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
5565501b 9765 (match_operator:SI 7 "shift_operator"
8a18b90c 9766 [(match_operand:SI 2 "s_register_operand" "r,r")
9767 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
bd5b4116 9768 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9769 "TARGET_ARM"
8a18b90c 9770 "#"
8fa3ba89 9771 [(set_attr "conds" "clob")
1b7da4ac 9772 (set_attr "length" "8,12")
9773 (set_attr "type" "multiple")]
8fa3ba89 9774)
5565501b 9775
8a18b90c 9776(define_insn "*if_move_shift"
9777 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 9778 (if_then_else:SI
8fa3ba89 9779 (match_operator 5 "arm_comparison_operator"
8a18b90c 9780 [(match_operand 6 "cc_register" "") (const_int 0)])
9781 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9782 (match_operator:SI 4 "shift_operator"
9783 [(match_operand:SI 2 "s_register_operand" "r,r,r")
9784 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
cffb2a26 9785 "TARGET_ARM"
5565501b 9786 "@
8a18b90c 9787 mov%D5\\t%0, %2%S4
9788 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
9789 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
8fa3ba89 9790 [(set_attr "conds" "use")
331beb1a 9791 (set_attr "shift" "2")
a2cd141b 9792 (set_attr "length" "4,8,8")
1b7da4ac 9793 (set_attr "type" "mov_shift_reg,multiple,multiple")]
8fa3ba89 9794)
9c08d1fa 9795
f7fbdd4a 9796(define_insn "*ifcompare_shift_shift"
8a18b90c 9797 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 9798 (if_then_else:SI
8fa3ba89 9799 (match_operator 7 "arm_comparison_operator"
8a18b90c 9800 [(match_operand:SI 5 "s_register_operand" "r")
9801 (match_operand:SI 6 "arm_add_operand" "rIL")])
5565501b 9802 (match_operator:SI 8 "shift_operator"
8a18b90c 9803 [(match_operand:SI 1 "s_register_operand" "r")
9804 (match_operand:SI 2 "arm_rhs_operand" "rM")])
5565501b 9805 (match_operator:SI 9 "shift_operator"
8a18b90c 9806 [(match_operand:SI 3 "s_register_operand" "r")
9807 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
bd5b4116 9808 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9809 "TARGET_ARM"
8a18b90c 9810 "#"
8fa3ba89 9811 [(set_attr "conds" "clob")
1b7da4ac 9812 (set_attr "length" "12")
9813 (set_attr "type" "multiple")]
8fa3ba89 9814)
9c08d1fa 9815
8a18b90c 9816(define_insn "*if_shift_shift"
9817 [(set (match_operand:SI 0 "s_register_operand" "=r")
9818 (if_then_else:SI
8fa3ba89 9819 (match_operator 5 "arm_comparison_operator"
8a18b90c 9820 [(match_operand 8 "cc_register" "") (const_int 0)])
9821 (match_operator:SI 6 "shift_operator"
9822 [(match_operand:SI 1 "s_register_operand" "r")
9823 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9824 (match_operator:SI 7 "shift_operator"
9825 [(match_operand:SI 3 "s_register_operand" "r")
9826 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
cffb2a26 9827 "TARGET_ARM"
8a18b90c 9828 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
8fa3ba89 9829 [(set_attr "conds" "use")
331beb1a 9830 (set_attr "shift" "1")
a2cd141b 9831 (set_attr "length" "8")
9832 (set (attr "type") (if_then_else
9833 (and (match_operand 2 "const_int_operand" "")
9834 (match_operand 4 "const_int_operand" ""))
1aed5204 9835 (const_string "mov_shift")
9836 (const_string "mov_shift_reg")))]
8fa3ba89 9837)
8a18b90c 9838
f7fbdd4a 9839(define_insn "*ifcompare_not_arith"
8a18b90c 9840 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 9841 (if_then_else:SI
8fa3ba89 9842 (match_operator 6 "arm_comparison_operator"
8a18b90c 9843 [(match_operand:SI 4 "s_register_operand" "r")
9844 (match_operand:SI 5 "arm_add_operand" "rIL")])
9845 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5565501b 9846 (match_operator:SI 7 "shiftable_operator"
8a18b90c 9847 [(match_operand:SI 2 "s_register_operand" "r")
9848 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
bd5b4116 9849 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9850 "TARGET_ARM"
8a18b90c 9851 "#"
8fa3ba89 9852 [(set_attr "conds" "clob")
1b7da4ac 9853 (set_attr "length" "12")
9854 (set_attr "type" "multiple")]
8fa3ba89 9855)
9c08d1fa 9856
8a18b90c 9857(define_insn "*if_not_arith"
9858 [(set (match_operand:SI 0 "s_register_operand" "=r")
9859 (if_then_else:SI
8fa3ba89 9860 (match_operator 5 "arm_comparison_operator"
8a18b90c 9861 [(match_operand 4 "cc_register" "") (const_int 0)])
9862 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9863 (match_operator:SI 6 "shiftable_operator"
9864 [(match_operand:SI 2 "s_register_operand" "r")
9865 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
cffb2a26 9866 "TARGET_ARM"
8a18b90c 9867 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
8fa3ba89 9868 [(set_attr "conds" "use")
1aed5204 9869 (set_attr "type" "mvn_reg")
8fa3ba89 9870 (set_attr "length" "8")]
9871)
8a18b90c 9872
9873(define_insn "*ifcompare_arith_not"
9874 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 9875 (if_then_else:SI
8fa3ba89 9876 (match_operator 6 "arm_comparison_operator"
8a18b90c 9877 [(match_operand:SI 4 "s_register_operand" "r")
9878 (match_operand:SI 5 "arm_add_operand" "rIL")])
5565501b 9879 (match_operator:SI 7 "shiftable_operator"
8a18b90c 9880 [(match_operand:SI 2 "s_register_operand" "r")
9881 (match_operand:SI 3 "arm_rhs_operand" "rI")])
9882 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
bd5b4116 9883 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9884 "TARGET_ARM"
8a18b90c 9885 "#"
8fa3ba89 9886 [(set_attr "conds" "clob")
1b7da4ac 9887 (set_attr "length" "12")
9888 (set_attr "type" "multiple")]
8fa3ba89 9889)
9c08d1fa 9890
8a18b90c 9891(define_insn "*if_arith_not"
9892 [(set (match_operand:SI 0 "s_register_operand" "=r")
9893 (if_then_else:SI
8fa3ba89 9894 (match_operator 5 "arm_comparison_operator"
8a18b90c 9895 [(match_operand 4 "cc_register" "") (const_int 0)])
9896 (match_operator:SI 6 "shiftable_operator"
9897 [(match_operand:SI 2 "s_register_operand" "r")
9898 (match_operand:SI 3 "arm_rhs_operand" "rI")])
9899 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
cffb2a26 9900 "TARGET_ARM"
8a18b90c 9901 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
8fa3ba89 9902 [(set_attr "conds" "use")
1b7da4ac 9903 (set_attr "type" "multiple")
8fa3ba89 9904 (set_attr "length" "8")]
9905)
8a18b90c 9906
f7fbdd4a 9907(define_insn "*ifcompare_neg_move"
8a18b90c 9908 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 9909 (if_then_else:SI
8fa3ba89 9910 (match_operator 5 "arm_comparison_operator"
8a18b90c 9911 [(match_operand:SI 3 "s_register_operand" "r,r")
9912 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9913 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
9914 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 9915 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9916 "TARGET_ARM"
8a18b90c 9917 "#"
8fa3ba89 9918 [(set_attr "conds" "clob")
1b7da4ac 9919 (set_attr "length" "8,12")
9920 (set_attr "type" "multiple")]
8fa3ba89 9921)
8a18b90c 9922
9923(define_insn "*if_neg_move"
9924 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9925 (if_then_else:SI
8fa3ba89 9926 (match_operator 4 "arm_comparison_operator"
8a18b90c 9927 [(match_operand 3 "cc_register" "") (const_int 0)])
9928 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9929 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 9930 "TARGET_ARM"
8a18b90c 9931 "@
9932 rsb%d4\\t%0, %2, #0
9933 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
9934 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
8fa3ba89 9935 [(set_attr "conds" "use")
1b7da4ac 9936 (set_attr "length" "4,8,8")
9937 (set_attr "type" "logic_shift_imm,multiple,multiple")]
8fa3ba89 9938)
9c08d1fa 9939
f7fbdd4a 9940(define_insn "*ifcompare_move_neg"
8a18b90c 9941 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 9942 (if_then_else:SI
8fa3ba89 9943 (match_operator 5 "arm_comparison_operator"
8a18b90c 9944 [(match_operand:SI 3 "s_register_operand" "r,r")
9945 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9946 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9947 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 9948 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9949 "TARGET_ARM"
8a18b90c 9950 "#"
8fa3ba89 9951 [(set_attr "conds" "clob")
1b7da4ac 9952 (set_attr "length" "8,12")
9953 (set_attr "type" "multiple")]
8fa3ba89 9954)
8a18b90c 9955
9956(define_insn "*if_move_neg"
9957 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9958 (if_then_else:SI
8fa3ba89 9959 (match_operator 4 "arm_comparison_operator"
8a18b90c 9960 [(match_operand 3 "cc_register" "") (const_int 0)])
9961 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9962 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
cffb2a26 9963 "TARGET_ARM"
8a18b90c 9964 "@
9965 rsb%D4\\t%0, %2, #0
9966 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
9967 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
0d66636f 9968 [(set_attr "conds" "use")
1b7da4ac 9969 (set_attr "length" "4,8,8")
9970 (set_attr "type" "logic_shift_imm,multiple,multiple")]
0d66636f 9971)
9c08d1fa 9972
f7fbdd4a 9973(define_insn "*arith_adjacentmem"
9c08d1fa 9974 [(set (match_operand:SI 0 "s_register_operand" "=r")
9975 (match_operator:SI 1 "shiftable_operator"
9976 [(match_operand:SI 2 "memory_operand" "m")
9977 (match_operand:SI 3 "memory_operand" "m")]))
9978 (clobber (match_scratch:SI 4 "=r"))]
cffb2a26 9979 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9c08d1fa 9980 "*
215b30b3 9981 {
9982 rtx ldm[3];
9983 rtx arith[4];
94dee231 9984 rtx base_reg;
9985 HOST_WIDE_INT val1 = 0, val2 = 0;
9c08d1fa 9986
215b30b3 9987 if (REGNO (operands[0]) > REGNO (operands[4]))
9988 {
9989 ldm[1] = operands[4];
9990 ldm[2] = operands[0];
9991 }
9992 else
9993 {
9994 ldm[1] = operands[0];
9995 ldm[2] = operands[4];
9996 }
94dee231 9997
9998 base_reg = XEXP (operands[2], 0);
9999
10000 if (!REG_P (base_reg))
10001 {
10002 val1 = INTVAL (XEXP (base_reg, 1));
10003 base_reg = XEXP (base_reg, 0);
10004 }
10005
10006 if (!REG_P (XEXP (operands[3], 0)))
215b30b3 10007 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
94dee231 10008
215b30b3 10009 arith[0] = operands[0];
10010 arith[3] = operands[1];
94dee231 10011
215b30b3 10012 if (val1 < val2)
10013 {
10014 arith[1] = ldm[1];
10015 arith[2] = ldm[2];
10016 }
10017 else
10018 {
10019 arith[1] = ldm[2];
10020 arith[2] = ldm[1];
10021 }
94dee231 10022
10023 ldm[0] = base_reg;
10024 if (val1 !=0 && val2 != 0)
215b30b3 10025 {
cdb1295a 10026 rtx ops[3];
10027
94dee231 10028 if (val1 == 4 || val2 == 4)
10029 /* Other val must be 8, since we know they are adjacent and neither
10030 is zero. */
25f905c2 10031 output_asm_insn (\"ldm%(ib%)\\t%0, {%1, %2}\", ldm);
cdb1295a 10032 else if (const_ok_for_arm (val1) || const_ok_for_arm (-val1))
94dee231 10033 {
94dee231 10034 ldm[0] = ops[0] = operands[4];
10035 ops[1] = base_reg;
10036 ops[2] = GEN_INT (val1);
10037 output_add_immediate (ops);
10038 if (val1 < val2)
25f905c2 10039 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
94dee231 10040 else
25f905c2 10041 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
94dee231 10042 }
cdb1295a 10043 else
10044 {
10045 /* Offset is out of range for a single add, so use two ldr. */
10046 ops[0] = ldm[1];
10047 ops[1] = base_reg;
10048 ops[2] = GEN_INT (val1);
10049 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10050 ops[0] = ldm[2];
10051 ops[2] = GEN_INT (val2);
10052 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10053 }
215b30b3 10054 }
94dee231 10055 else if (val1 != 0)
215b30b3 10056 {
215b30b3 10057 if (val1 < val2)
25f905c2 10058 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
215b30b3 10059 else
25f905c2 10060 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
215b30b3 10061 }
10062 else
10063 {
215b30b3 10064 if (val1 < val2)
25f905c2 10065 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
215b30b3 10066 else
25f905c2 10067 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
215b30b3 10068 }
10069 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
10070 return \"\";
10071 }"
10072 [(set_attr "length" "12")
10073 (set_attr "predicable" "yes")
a2cd141b 10074 (set_attr "type" "load1")]
215b30b3 10075)
9c08d1fa 10076
9c08d1fa 10077; This pattern is never tried by combine, so do it as a peephole
10078
a0f94409 10079(define_peephole2
372575c7 10080 [(set (match_operand:SI 0 "arm_general_register_operand" "")
10081 (match_operand:SI 1 "arm_general_register_operand" ""))
bd5b4116 10082 (set (reg:CC CC_REGNUM)
aea4c774 10083 (compare:CC (match_dup 1) (const_int 0)))]
372575c7 10084 "TARGET_ARM"
a0f94409 10085 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
10086 (set (match_dup 0) (match_dup 1))])]
10087 ""
0d66636f 10088)
9c08d1fa 10089
9c08d1fa 10090(define_split
10091 [(set (match_operand:SI 0 "s_register_operand" "")
10092 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
10093 (const_int 0))
8fa3ba89 10094 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9c08d1fa 10095 [(match_operand:SI 3 "s_register_operand" "")
10096 (match_operand:SI 4 "arm_rhs_operand" "")]))))
10097 (clobber (match_operand:SI 5 "s_register_operand" ""))]
cffb2a26 10098 "TARGET_ARM"
9c08d1fa 10099 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
10100 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
10101 (match_dup 5)))]
215b30b3 10102 ""
10103)
9c08d1fa 10104
aea4c774 10105;; This split can be used because CC_Z mode implies that the following
10106;; branch will be an equality, or an unsigned inequality, so the sign
10107;; extension is not needed.
9c08d1fa 10108
aea4c774 10109(define_split
bd5b4116 10110 [(set (reg:CC_Z CC_REGNUM)
aea4c774 10111 (compare:CC_Z
10112 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9c08d1fa 10113 (const_int 24))
aea4c774 10114 (match_operand 1 "const_int_operand" "")))
10115 (clobber (match_scratch:SI 2 ""))]
cffb2a26 10116 "TARGET_ARM
10117 && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
10118 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
aea4c774 10119 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
bd5b4116 10120 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
aea4c774 10121 "
9c08d1fa 10122 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
215b30b3 10123 "
10124)
25f905c2 10125;; ??? Check the patterns above for Thumb-2 usefulness
9c08d1fa 10126
87b22bf7 10127(define_expand "prologue"
10128 [(clobber (const_int 0))]
cffb2a26 10129 "TARGET_EITHER"
25f905c2 10130 "if (TARGET_32BIT)
cffb2a26 10131 arm_expand_prologue ();
10132 else
25f905c2 10133 thumb1_expand_prologue ();
87b22bf7 10134 DONE;
cffb2a26 10135 "
10136)
87b22bf7 10137
56d27660 10138(define_expand "epilogue"
4c44712e 10139 [(clobber (const_int 0))]
cffb2a26 10140 "TARGET_EITHER"
56d27660 10141 "
18d50ae6 10142 if (crtl->calls_eh_return)
fb94f18b 10143 emit_insn (gen_force_register_use (gen_rtx_REG (Pmode, 2)));
25f905c2 10144 if (TARGET_THUMB1)
c3635784 10145 {
10146 thumb1_expand_epilogue ();
10147 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
10148 gen_rtvec (1, ret_rtx), VUNSPEC_EPILOGUE));
10149 }
10150 else if (HAVE_return)
10151 {
10152 /* HAVE_return is testing for USE_RETURN_INSN (FALSE). Hence,
10153 no need for explicit testing again. */
10154 emit_jump_insn (gen_return ());
10155 }
10156 else if (TARGET_32BIT)
10157 {
10158 arm_expand_epilogue (true);
10159 }
cffb2a26 10160 DONE;
10161 "
10162)
56d27660 10163
ef5651d0 10164;; Note - although unspec_volatile's USE all hard registers,
10165;; USEs are ignored after relaod has completed. Thus we need
10166;; to add an unspec of the link register to ensure that flow
10167;; does not think that it is unused by the sibcall branch that
10168;; will replace the standard function epilogue.
c3635784 10169(define_expand "sibcall_epilogue"
fb94f18b 10170 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_REGISTER_USE)
c3635784 10171 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
10172 "TARGET_32BIT"
10173 "
10174 arm_expand_epilogue (false);
10175 DONE;
10176 "
1c494086 10177)
10178
cffb2a26 10179(define_expand "eh_epilogue"
7db9af5d 10180 [(use (match_operand:SI 0 "register_operand" ""))
10181 (use (match_operand:SI 1 "register_operand" ""))
10182 (use (match_operand:SI 2 "register_operand" ""))]
cffb2a26 10183 "TARGET_EITHER"
10184 "
215b30b3 10185 {
10186 cfun->machine->eh_epilogue_sp_ofs = operands[1];
0438d37f 10187 if (!REG_P (operands[2]) || REGNO (operands[2]) != 2)
215b30b3 10188 {
10189 rtx ra = gen_rtx_REG (Pmode, 2);
10190
10191 emit_move_insn (ra, operands[2]);
10192 operands[2] = ra;
10193 }
5cf3595a 10194 /* This is a hack -- we may have crystalized the function type too
10195 early. */
10196 cfun->machine->func_type = 0;
215b30b3 10197 }"
10198)
56d27660 10199
9c08d1fa 10200;; This split is only used during output to reduce the number of patterns
10201;; that need assembler instructions adding to them. We allowed the setting
10202;; of the conditions to be implicit during rtl generation so that
10203;; the conditional compare patterns would work. However this conflicts to
8a18b90c 10204;; some extent with the conditional data operations, so we have to split them
9c08d1fa 10205;; up again here.
10206
25f905c2 10207;; ??? Need to audit these splitters for Thumb-2. Why isn't normal
10208;; conditional execution sufficient?
10209
9c08d1fa 10210(define_split
10211 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 10212 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10213 [(match_operand 2 "" "") (match_operand 3 "" "")])
10214 (match_dup 0)
10215 (match_operand 4 "" "")))
bd5b4116 10216 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10217 "TARGET_ARM && reload_completed"
8fa3ba89 10218 [(set (match_dup 5) (match_dup 6))
10219 (cond_exec (match_dup 7)
10220 (set (match_dup 0) (match_dup 4)))]
10221 "
10222 {
3754d046 10223 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8fa3ba89 10224 operands[2], operands[3]);
10225 enum rtx_code rc = GET_CODE (operands[1]);
10226
bd5b4116 10227 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10228 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10229 if (mode == CCFPmode || mode == CCFPEmode)
10230 rc = reverse_condition_maybe_unordered (rc);
10231 else
10232 rc = reverse_condition (rc);
10233
10234 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
10235 }"
10236)
10237
10238(define_split
10239 [(set (match_operand:SI 0 "s_register_operand" "")
10240 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10241 [(match_operand 2 "" "") (match_operand 3 "" "")])
10242 (match_operand 4 "" "")
10243 (match_dup 0)))
bd5b4116 10244 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10245 "TARGET_ARM && reload_completed"
8fa3ba89 10246 [(set (match_dup 5) (match_dup 6))
10247 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
10248 (set (match_dup 0) (match_dup 4)))]
10249 "
10250 {
3754d046 10251 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8fa3ba89 10252 operands[2], operands[3]);
10253
bd5b4116 10254 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10255 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10256 }"
10257)
10258
10259(define_split
10260 [(set (match_operand:SI 0 "s_register_operand" "")
10261 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9c08d1fa 10262 [(match_operand 2 "" "") (match_operand 3 "" "")])
10263 (match_operand 4 "" "")
10264 (match_operand 5 "" "")))
bd5b4116 10265 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10266 "TARGET_ARM && reload_completed"
8fa3ba89 10267 [(set (match_dup 6) (match_dup 7))
10268 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10269 (set (match_dup 0) (match_dup 4)))
10270 (cond_exec (match_dup 8)
10271 (set (match_dup 0) (match_dup 5)))]
10272 "
10273 {
3754d046 10274 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8fa3ba89 10275 operands[2], operands[3]);
10276 enum rtx_code rc = GET_CODE (operands[1]);
10277
bd5b4116 10278 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10279 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10280 if (mode == CCFPmode || mode == CCFPEmode)
10281 rc = reverse_condition_maybe_unordered (rc);
10282 else
10283 rc = reverse_condition (rc);
10284
10285 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10286 }"
10287)
10288
cffb2a26 10289(define_split
10290 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 10291 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
cffb2a26 10292 [(match_operand:SI 2 "s_register_operand" "")
10293 (match_operand:SI 3 "arm_add_operand" "")])
10294 (match_operand:SI 4 "arm_rhs_operand" "")
10295 (not:SI
10296 (match_operand:SI 5 "s_register_operand" ""))))
bd5b4116 10297 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10298 "TARGET_ARM && reload_completed"
cffb2a26 10299 [(set (match_dup 6) (match_dup 7))
f6c53574 10300 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10301 (set (match_dup 0) (match_dup 4)))
10302 (cond_exec (match_dup 8)
10303 (set (match_dup 0) (not:SI (match_dup 5))))]
cffb2a26 10304 "
215b30b3 10305 {
3754d046 10306 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
215b30b3 10307 operands[2], operands[3]);
f6c53574 10308 enum rtx_code rc = GET_CODE (operands[1]);
cffb2a26 10309
bd5b4116 10310 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
1a83b3ff 10311 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
f6c53574 10312 if (mode == CCFPmode || mode == CCFPEmode)
10313 rc = reverse_condition_maybe_unordered (rc);
10314 else
10315 rc = reverse_condition (rc);
10316
10317 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
215b30b3 10318 }"
10319)
cffb2a26 10320
10321(define_insn "*cond_move_not"
10322 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10323 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
cffb2a26 10324 [(match_operand 3 "cc_register" "") (const_int 0)])
10325 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10326 (not:SI
10327 (match_operand:SI 2 "s_register_operand" "r,r"))))]
10328 "TARGET_ARM"
10329 "@
10330 mvn%D4\\t%0, %2
10331 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
0d66636f 10332 [(set_attr "conds" "use")
1b7da4ac 10333 (set_attr "type" "mvn_reg,multiple")
0d66636f 10334 (set_attr "length" "4,8")]
10335)
cffb2a26 10336
9c08d1fa 10337;; The next two patterns occur when an AND operation is followed by a
10338;; scc insn sequence
10339
f7fbdd4a 10340(define_insn "*sign_extract_onebit"
9c08d1fa 10341 [(set (match_operand:SI 0 "s_register_operand" "=r")
10342 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10343 (const_int 1)
ed750274 10344 (match_operand:SI 2 "const_int_operand" "n")))
10345 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10346 "TARGET_ARM"
9c08d1fa 10347 "*
0d66636f 10348 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10349 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
10350 return \"mvnne\\t%0, #0\";
10351 "
10352 [(set_attr "conds" "clob")
1b7da4ac 10353 (set_attr "length" "8")
10354 (set_attr "type" "multiple")]
0d66636f 10355)
9c08d1fa 10356
f7fbdd4a 10357(define_insn "*not_signextract_onebit"
9c08d1fa 10358 [(set (match_operand:SI 0 "s_register_operand" "=r")
10359 (not:SI
10360 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10361 (const_int 1)
ed750274 10362 (match_operand:SI 2 "const_int_operand" "n"))))
10363 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10364 "TARGET_ARM"
9c08d1fa 10365 "*
0d66636f 10366 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10367 output_asm_insn (\"tst\\t%1, %2\", operands);
10368 output_asm_insn (\"mvneq\\t%0, #0\", operands);
10369 return \"movne\\t%0, #0\";
10370 "
10371 [(set_attr "conds" "clob")
1b7da4ac 10372 (set_attr "length" "12")
10373 (set_attr "type" "multiple")]
0d66636f 10374)
25f905c2 10375;; ??? The above patterns need auditing for Thumb-2
87b22bf7 10376
0d66636f 10377;; Push multiple registers to the stack. Registers are in parallel (use ...)
10378;; expressions. For simplicity, the first register is also in the unspec
10379;; part.
08508cbf 10380;; To avoid the usage of GNU extension, the length attribute is computed
10381;; in a C function arm_attr_length_push_multi.
f7fbdd4a 10382(define_insn "*push_multi"
87b22bf7 10383 [(match_parallel 2 "multi_register_push"
7571d3f7 10384 [(set (match_operand:BLK 0 "push_mult_memory_operand" "")
3cc80a30 10385 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "")]
e1159bbe 10386 UNSPEC_PUSH_MULT))])]
7571d3f7 10387 ""
87b22bf7 10388 "*
215b30b3 10389 {
10390 int num_saves = XVECLEN (operands[2], 0);
ed593f11 10391
215b30b3 10392 /* For the StrongARM at least it is faster to
25f905c2 10393 use STR to store only a single register.
542d5028 10394 In Thumb mode always use push, and the assembler will pick
10395 something appropriate. */
25f905c2 10396 if (num_saves == 1 && TARGET_ARM)
61309563 10397 output_asm_insn (\"str%?\\t%1, [%m0, #-4]!\", operands);
215b30b3 10398 else
10399 {
10400 int i;
10401 char pattern[100];
ed593f11 10402
25f905c2 10403 if (TARGET_ARM)
61309563 10404 strcpy (pattern, \"stm%(fd%)\\t%m0!, {%1\");
10405 else if (TARGET_THUMB2)
10406 strcpy (pattern, \"push%?\\t{%1\");
25f905c2 10407 else
10408 strcpy (pattern, \"push\\t{%1\");
215b30b3 10409
6079f055 10410 for (i = 1; i < num_saves; i++)
215b30b3 10411 {
10412 strcat (pattern, \", %|\");
10413 strcat (pattern,
10414 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
10415 }
10416
10417 strcat (pattern, \"}\");
10418 output_asm_insn (pattern, operands);
10419 }
10420
10421 return \"\";
10422 }"
a6864a24 10423 [(set_attr "type" "store4")
10424 (set (attr "length")
08508cbf 10425 (symbol_ref "arm_attr_length_push_multi (operands[2], operands[1])"))]
215b30b3 10426)
f7fbdd4a 10427
4c58c898 10428(define_insn "stack_tie"
10429 [(set (mem:BLK (scratch))
aaa37ad6 10430 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "rk")
10431 (match_operand:SI 1 "s_register_operand" "rk")]
4c58c898 10432 UNSPEC_PRLG_STK))]
10433 ""
10434 ""
1b7da4ac 10435 [(set_attr "length" "0")
10436 (set_attr "type" "block")]
4c58c898 10437)
10438
426be8c5 10439;; Pop (as used in epilogue RTL)
10440;;
10441(define_insn "*load_multiple_with_writeback"
10442 [(match_parallel 0 "load_multiple_operation"
10443 [(set (match_operand:SI 1 "s_register_operand" "+rk")
10444 (plus:SI (match_dup 1)
809003b3 10445 (match_operand:SI 2 "const_int_I_operand" "I")))
426be8c5 10446 (set (match_operand:SI 3 "s_register_operand" "=rk")
10447 (mem:SI (match_dup 1)))
10448 ])]
10449 "TARGET_32BIT && (reload_in_progress || reload_completed)"
10450 "*
10451 {
10452 arm_output_multireg_pop (operands, /*return_pc=*/false,
10453 /*cond=*/const_true_rtx,
10454 /*reverse=*/false,
10455 /*update=*/true);
10456 return \"\";
10457 }
10458 "
10459 [(set_attr "type" "load4")
10460 (set_attr "predicable" "yes")]
10461)
10462
10463;; Pop with return (as used in epilogue RTL)
10464;;
10465;; This instruction is generated when the registers are popped at the end of
10466;; epilogue. Here, instead of popping the value into LR and then generating
10467;; jump to LR, value is popped into PC directly. Hence, the pattern is combined
10468;; with (return).
10469(define_insn "*pop_multiple_with_writeback_and_return"
10470 [(match_parallel 0 "pop_multiple_return"
10471 [(return)
10472 (set (match_operand:SI 1 "s_register_operand" "+rk")
10473 (plus:SI (match_dup 1)
809003b3 10474 (match_operand:SI 2 "const_int_I_operand" "I")))
426be8c5 10475 (set (match_operand:SI 3 "s_register_operand" "=rk")
10476 (mem:SI (match_dup 1)))
10477 ])]
10478 "TARGET_32BIT && (reload_in_progress || reload_completed)"
10479 "*
10480 {
10481 arm_output_multireg_pop (operands, /*return_pc=*/true,
10482 /*cond=*/const_true_rtx,
10483 /*reverse=*/false,
10484 /*update=*/true);
10485 return \"\";
10486 }
10487 "
10488 [(set_attr "type" "load4")
10489 (set_attr "predicable" "yes")]
10490)
10491
10492(define_insn "*pop_multiple_with_return"
10493 [(match_parallel 0 "pop_multiple_return"
10494 [(return)
10495 (set (match_operand:SI 2 "s_register_operand" "=rk")
10496 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
10497 ])]
10498 "TARGET_32BIT && (reload_in_progress || reload_completed)"
10499 "*
10500 {
10501 arm_output_multireg_pop (operands, /*return_pc=*/true,
10502 /*cond=*/const_true_rtx,
10503 /*reverse=*/false,
10504 /*update=*/false);
10505 return \"\";
10506 }
10507 "
10508 [(set_attr "type" "load4")
10509 (set_attr "predicable" "yes")]
10510)
10511
10512;; Load into PC and return
10513(define_insn "*ldr_with_return"
10514 [(return)
10515 (set (reg:SI PC_REGNUM)
10516 (mem:SI (post_inc:SI (match_operand:SI 0 "s_register_operand" "+rk"))))]
10517 "TARGET_32BIT && (reload_in_progress || reload_completed)"
10518 "ldr%?\t%|pc, [%0], #4"
10519 [(set_attr "type" "load1")
10520 (set_attr "predicable" "yes")]
10521)
1a0b0f12 10522;; Pop for floating point registers (as used in epilogue RTL)
10523(define_insn "*vfp_pop_multiple_with_writeback"
10524 [(match_parallel 0 "pop_multiple_fp"
10525 [(set (match_operand:SI 1 "s_register_operand" "+rk")
10526 (plus:SI (match_dup 1)
809003b3 10527 (match_operand:SI 2 "const_int_I_operand" "I")))
2f2163a4 10528 (set (match_operand:DF 3 "vfp_hard_register_operand" "")
1a0b0f12 10529 (mem:DF (match_dup 1)))])]
10530 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
10531 "*
10532 {
10533 int num_regs = XVECLEN (operands[0], 0);
10534 char pattern[100];
10535 rtx op_list[2];
b34d8dac 10536 strcpy (pattern, \"vldm\\t\");
1a0b0f12 10537 strcat (pattern, reg_names[REGNO (SET_DEST (XVECEXP (operands[0], 0, 0)))]);
10538 strcat (pattern, \"!, {\");
10539 op_list[0] = XEXP (XVECEXP (operands[0], 0, 1), 0);
10540 strcat (pattern, \"%P0\");
10541 if ((num_regs - 1) > 1)
10542 {
10543 strcat (pattern, \"-%P1\");
10544 op_list [1] = XEXP (XVECEXP (operands[0], 0, num_regs - 1), 0);
10545 }
10546
10547 strcat (pattern, \"}\");
10548 output_asm_insn (pattern, op_list);
10549 return \"\";
10550 }
10551 "
10552 [(set_attr "type" "load4")
10553 (set_attr "conds" "unconditional")
10554 (set_attr "predicable" "no")]
10555)
10556
f7fbdd4a 10557;; Special patterns for dealing with the constant pool
10558
cffb2a26 10559(define_insn "align_4"
e1159bbe 10560 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
cffb2a26 10561 "TARGET_EITHER"
f7fbdd4a 10562 "*
cffb2a26 10563 assemble_align (32);
f7fbdd4a 10564 return \"\";
cffb2a26 10565 "
1b7da4ac 10566 [(set_attr "type" "no_insn")]
cffb2a26 10567)
f7fbdd4a 10568
755eb2b4 10569(define_insn "align_8"
10570 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
f9273c43 10571 "TARGET_EITHER"
755eb2b4 10572 "*
10573 assemble_align (64);
10574 return \"\";
10575 "
1b7da4ac 10576 [(set_attr "type" "no_insn")]
755eb2b4 10577)
10578
cffb2a26 10579(define_insn "consttable_end"
e1159bbe 10580 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
cffb2a26 10581 "TARGET_EITHER"
f7fbdd4a 10582 "*
cffb2a26 10583 making_const_table = FALSE;
f7fbdd4a 10584 return \"\";
cffb2a26 10585 "
1b7da4ac 10586 [(set_attr "type" "no_insn")]
cffb2a26 10587)
f7fbdd4a 10588
cffb2a26 10589(define_insn "consttable_4"
e1159bbe 10590 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
cffb2a26 10591 "TARGET_EITHER"
10592 "*
10593 {
9b8516be 10594 rtx x = operands[0];
cffb2a26 10595 making_const_table = TRUE;
9b8516be 10596 switch (GET_MODE_CLASS (GET_MODE (x)))
cffb2a26 10597 {
10598 case MODE_FLOAT:
9b8516be 10599 if (GET_MODE (x) == HFmode)
10600 arm_emit_fp16_const (x);
10601 else
10602 {
10603 REAL_VALUE_TYPE r;
10604 REAL_VALUE_FROM_CONST_DOUBLE (r, x);
10605 assemble_real (r, GET_MODE (x), BITS_PER_WORD);
10606 }
10607 break;
cffb2a26 10608 default:
7b04c5d5 10609 /* XXX: Sometimes gcc does something really dumb and ends up with
10610 a HIGH in a constant pool entry, usually because it's trying to
10611 load into a VFP register. We know this will always be used in
10612 combination with a LO_SUM which ignores the high bits, so just
10613 strip off the HIGH. */
10614 if (GET_CODE (x) == HIGH)
10615 x = XEXP (x, 0);
9b8516be 10616 assemble_integer (x, 4, BITS_PER_WORD, 1);
10617 mark_symbol_refs_as_used (x);
cffb2a26 10618 break;
10619 }
10620 return \"\";
10621 }"
1b7da4ac 10622 [(set_attr "length" "4")
10623 (set_attr "type" "no_insn")]
cffb2a26 10624)
10625
10626(define_insn "consttable_8"
e1159bbe 10627 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
cffb2a26 10628 "TARGET_EITHER"
10629 "*
10630 {
10631 making_const_table = TRUE;
10632 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10633 {
10634 case MODE_FLOAT:
10635 {
badfe841 10636 REAL_VALUE_TYPE r;
10637 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10638 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
cffb2a26 10639 break;
10640 }
10641 default:
09d688ff 10642 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
cffb2a26 10643 break;
10644 }
10645 return \"\";
10646 }"
1b7da4ac 10647 [(set_attr "length" "8")
10648 (set_attr "type" "no_insn")]
cffb2a26 10649)
10650
d98a3884 10651(define_insn "consttable_16"
10652 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_16)]
10653 "TARGET_EITHER"
10654 "*
10655 {
10656 making_const_table = TRUE;
10657 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10658 {
10659 case MODE_FLOAT:
10660 {
10661 REAL_VALUE_TYPE r;
10662 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10663 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10664 break;
10665 }
10666 default:
10667 assemble_integer (operands[0], 16, BITS_PER_WORD, 1);
10668 break;
10669 }
10670 return \"\";
10671 }"
1b7da4ac 10672 [(set_attr "length" "16")
10673 (set_attr "type" "no_insn")]
d98a3884 10674)
10675
331beb1a 10676;; V5 Instructions,
10677
8f4be2be 10678(define_insn "clzsi2"
10679 [(set (match_operand:SI 0 "s_register_operand" "=r")
10680 (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 10681 "TARGET_32BIT && arm_arch5"
ee7cbe0e 10682 "clz%?\\t%0, %1"
bcaec148 10683 [(set_attr "predicable" "yes")
4a510717 10684 (set_attr "predicable_short_it" "no")
bebe9bbb 10685 (set_attr "type" "clz")])
331beb1a 10686
099ad98b 10687(define_insn "rbitsi2"
10688 [(set (match_operand:SI 0 "s_register_operand" "=r")
10689 (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")] UNSPEC_RBIT))]
10690 "TARGET_32BIT && arm_arch_thumb2"
10691 "rbit%?\\t%0, %1"
10692 [(set_attr "predicable" "yes")
4a510717 10693 (set_attr "predicable_short_it" "no")
bebe9bbb 10694 (set_attr "type" "clz")])
099ad98b 10695
10696(define_expand "ctzsi2"
10697 [(set (match_operand:SI 0 "s_register_operand" "")
10698 (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
10699 "TARGET_32BIT && arm_arch_thumb2"
10700 "
30191172 10701 {
10702 rtx tmp = gen_reg_rtx (SImode);
10703 emit_insn (gen_rbitsi2 (tmp, operands[1]));
10704 emit_insn (gen_clzsi2 (operands[0], tmp));
10705 }
099ad98b 10706 DONE;
10707 "
10708)
10709
e1159bbe 10710;; V5E instructions.
331beb1a 10711
10712(define_insn "prefetch"
f4e79814 10713 [(prefetch (match_operand:SI 0 "address_operand" "p")
10714 (match_operand:SI 1 "" "")
10715 (match_operand:SI 2 "" ""))]
25f905c2 10716 "TARGET_32BIT && arm_arch5e"
1b7da4ac 10717 "pld\\t%a0"
10718 [(set_attr "type" "load1")]
10719)
331beb1a 10720
0d66636f 10721;; General predication pattern
10722
10723(define_cond_exec
10724 [(match_operator 0 "arm_comparison_operator"
10725 [(match_operand 1 "cc_register" "")
10726 (const_int 0)])]
25f905c2 10727 "TARGET_32BIT"
0d66636f 10728 ""
c7a58118 10729[(set_attr "predicated" "yes")]
0d66636f 10730)
10731
fb94f18b 10732(define_insn "force_register_use"
10733 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_REGISTER_USE)]
063a05c7 10734 ""
fb94f18b 10735 "%@ %0 needed"
1b7da4ac 10736 [(set_attr "length" "0")
10737 (set_attr "type" "no_insn")]
063a05c7 10738)
7db9af5d 10739
4c44712e 10740
10741;; Patterns for exception handling
10742
10743(define_expand "eh_return"
10744 [(use (match_operand 0 "general_operand" ""))]
10745 "TARGET_EITHER"
10746 "
10747 {
25f905c2 10748 if (TARGET_32BIT)
4c44712e 10749 emit_insn (gen_arm_eh_return (operands[0]));
10750 else
10751 emit_insn (gen_thumb_eh_return (operands[0]));
10752 DONE;
10753 }"
10754)
10755
10756;; We can't expand this before we know where the link register is stored.
10757(define_insn_and_split "arm_eh_return"
10758 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
10759 VUNSPEC_EH_RETURN)
10760 (clobber (match_scratch:SI 1 "=&r"))]
10761 "TARGET_ARM"
10762 "#"
10763 "&& reload_completed"
10764 [(const_int 0)]
10765 "
10766 {
10767 arm_set_return_address (operands[0], operands[1]);
10768 DONE;
10769 }"
10770)
10771
f655717d 10772\f
10773;; TLS support
10774
10775(define_insn "load_tp_hard"
10776 [(set (match_operand:SI 0 "register_operand" "=r")
10777 (unspec:SI [(const_int 0)] UNSPEC_TLS))]
10778 "TARGET_HARD_TP"
10779 "mrc%?\\tp15, 0, %0, c13, c0, 3\\t@ load_tp_hard"
1b7da4ac 10780 [(set_attr "predicable" "yes")
4b5d7374 10781 (set_attr "type" "mrs")]
f655717d 10782)
10783
10784;; Doesn't clobber R1-R3. Must use r0 for the first operand.
10785(define_insn "load_tp_soft"
10786 [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
10787 (clobber (reg:SI LR_REGNUM))
10788 (clobber (reg:SI IP_REGNUM))
10789 (clobber (reg:CC CC_REGNUM))]
10790 "TARGET_SOFT_TP"
10791 "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
1b7da4ac 10792 [(set_attr "conds" "clob")
10793 (set_attr "type" "branch")]
f655717d 10794)
10795
f41e4452 10796;; tls descriptor call
10797(define_insn "tlscall"
10798 [(set (reg:SI R0_REGNUM)
10799 (unspec:SI [(reg:SI R0_REGNUM)
10800 (match_operand:SI 0 "" "X")
10801 (match_operand 1 "" "")] UNSPEC_TLS))
10802 (clobber (reg:SI R1_REGNUM))
10803 (clobber (reg:SI LR_REGNUM))
10804 (clobber (reg:SI CC_REGNUM))]
10805 "TARGET_GNU2_TLS"
10806 {
10807 targetm.asm_out.internal_label (asm_out_file, "LPIC",
10808 INTVAL (operands[1]));
10809 return "bl\\t%c0(tlscall)";
10810 }
10811 [(set_attr "conds" "clob")
1b7da4ac 10812 (set_attr "length" "4")
10813 (set_attr "type" "branch")]
f41e4452 10814)
10815
1fe0edab 10816;; For thread pointer builtin
10817(define_expand "get_thread_pointersi"
10818 [(match_operand:SI 0 "s_register_operand" "=r")]
10819 ""
10820 "
10821 {
10822 arm_load_tp (operands[0]);
10823 DONE;
10824 }")
10825
f41e4452 10826;;
10827
aabe09ac 10828;; We only care about the lower 16 bits of the constant
10829;; being inserted into the upper 16 bits of the register.
eca5c984 10830(define_insn "*arm_movtas_ze"
10831 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
10832 (const_int 16)
10833 (const_int 16))
10834 (match_operand:SI 1 "const_int_operand" ""))]
181ab277 10835 "arm_arch_thumb2"
aabe09ac 10836 "movt%?\t%0, %L1"
eca5c984 10837 [(set_attr "predicable" "yes")
7c36fe71 10838 (set_attr "predicable_short_it" "no")
1b7da4ac 10839 (set_attr "length" "4")
10840 (set_attr "type" "mov_imm")]
eca5c984 10841)
10842
c0fc3696 10843(define_insn "*arm_rev"
a486b499 10844 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
10845 (bswap:SI (match_operand:SI 1 "s_register_operand" "l,l,r")))]
10846 "arm_arch6"
10847 "@
10848 rev\t%0, %1
10849 rev%?\t%0, %1
10850 rev%?\t%0, %1"
10851 [(set_attr "arch" "t1,t2,32")
1b7da4ac 10852 (set_attr "length" "2,2,4")
4a510717 10853 (set_attr "predicable" "no,yes,yes")
10854 (set_attr "predicable_short_it" "no")
1b7da4ac 10855 (set_attr "type" "rev")]
ff82f757 10856)
10857
10858(define_expand "arm_legacy_rev"
10859 [(set (match_operand:SI 2 "s_register_operand" "")
10860 (xor:SI (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
10861 (const_int 16))
10862 (match_dup 1)))
10863 (set (match_dup 2)
10864 (lshiftrt:SI (match_dup 2)
10865 (const_int 8)))
10866 (set (match_operand:SI 3 "s_register_operand" "")
10867 (rotatert:SI (match_dup 1)
10868 (const_int 8)))
10869 (set (match_dup 2)
10870 (and:SI (match_dup 2)
10871 (const_int -65281)))
10872 (set (match_operand:SI 0 "s_register_operand" "")
10873 (xor:SI (match_dup 3)
10874 (match_dup 2)))]
10875 "TARGET_32BIT"
10876 ""
10877)
10878
10879;; Reuse temporaries to keep register pressure down.
10880(define_expand "thumb_legacy_rev"
10881 [(set (match_operand:SI 2 "s_register_operand" "")
10882 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
10883 (const_int 24)))
10884 (set (match_operand:SI 3 "s_register_operand" "")
10885 (lshiftrt:SI (match_dup 1)
10886 (const_int 24)))
10887 (set (match_dup 3)
10888 (ior:SI (match_dup 3)
10889 (match_dup 2)))
10890 (set (match_operand:SI 4 "s_register_operand" "")
10891 (const_int 16))
10892 (set (match_operand:SI 5 "s_register_operand" "")
10893 (rotatert:SI (match_dup 1)
10894 (match_dup 4)))
10895 (set (match_dup 2)
10896 (ashift:SI (match_dup 5)
10897 (const_int 24)))
10898 (set (match_dup 5)
10899 (lshiftrt:SI (match_dup 5)
10900 (const_int 24)))
10901 (set (match_dup 5)
10902 (ior:SI (match_dup 5)
10903 (match_dup 2)))
10904 (set (match_dup 5)
10905 (rotatert:SI (match_dup 5)
10906 (match_dup 4)))
10907 (set (match_operand:SI 0 "s_register_operand" "")
10908 (ior:SI (match_dup 5)
10909 (match_dup 3)))]
10910 "TARGET_THUMB"
10911 ""
10912)
10913
10914(define_expand "bswapsi2"
10915 [(set (match_operand:SI 0 "s_register_operand" "=r")
10916 (bswap:SI (match_operand:SI 1 "s_register_operand" "r")))]
8d1af482 10917"TARGET_EITHER && (arm_arch6 || !optimize_size)"
ff82f757 10918"
8d1af482 10919 if (!arm_arch6)
10920 {
10921 rtx op2 = gen_reg_rtx (SImode);
10922 rtx op3 = gen_reg_rtx (SImode);
ff82f757 10923
8d1af482 10924 if (TARGET_THUMB)
10925 {
10926 rtx op4 = gen_reg_rtx (SImode);
10927 rtx op5 = gen_reg_rtx (SImode);
ff82f757 10928
8d1af482 10929 emit_insn (gen_thumb_legacy_rev (operands[0], operands[1],
10930 op2, op3, op4, op5));
10931 }
10932 else
10933 {
10934 emit_insn (gen_arm_legacy_rev (operands[0], operands[1],
10935 op2, op3));
10936 }
ff82f757 10937
8d1af482 10938 DONE;
10939 }
ff82f757 10940 "
10941)
10942
a486b499 10943;; bswap16 patterns: use revsh and rev16 instructions for the signed
10944;; and unsigned variants, respectively. For rev16, expose
10945;; byte-swapping in the lower 16 bits only.
10946(define_insn "*arm_revsh"
10947 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
10948 (sign_extend:SI (bswap:HI (match_operand:HI 1 "s_register_operand" "l,l,r"))))]
10949 "arm_arch6"
10950 "@
10951 revsh\t%0, %1
10952 revsh%?\t%0, %1
10953 revsh%?\t%0, %1"
10954 [(set_attr "arch" "t1,t2,32")
1b7da4ac 10955 (set_attr "length" "2,2,4")
10956 (set_attr "type" "rev")]
a486b499 10957)
10958
10959(define_insn "*arm_rev16"
10960 [(set (match_operand:HI 0 "s_register_operand" "=l,l,r")
10961 (bswap:HI (match_operand:HI 1 "s_register_operand" "l,l,r")))]
10962 "arm_arch6"
10963 "@
10964 rev16\t%0, %1
10965 rev16%?\t%0, %1
10966 rev16%?\t%0, %1"
10967 [(set_attr "arch" "t1,t2,32")
1b7da4ac 10968 (set_attr "length" "2,2,4")
10969 (set_attr "type" "rev")]
09f69e55 10970)
10971
10972;; There are no canonicalisation rules for the position of the lshiftrt, ashift
10973;; operations within an IOR/AND RTX, therefore we have two patterns matching
10974;; each valid permutation.
10975
10976(define_insn "arm_rev16si2"
10977 [(set (match_operand:SI 0 "register_operand" "=l,l,r")
10978 (ior:SI (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "l,l,r")
10979 (const_int 8))
10980 (match_operand:SI 3 "const_int_operand" "n,n,n"))
10981 (and:SI (lshiftrt:SI (match_dup 1)
10982 (const_int 8))
10983 (match_operand:SI 2 "const_int_operand" "n,n,n"))))]
10984 "arm_arch6
10985 && aarch_rev16_shleft_mask_imm_p (operands[3], SImode)
10986 && aarch_rev16_shright_mask_imm_p (operands[2], SImode)"
10987 "rev16\\t%0, %1"
10988 [(set_attr "arch" "t1,t2,32")
10989 (set_attr "length" "2,2,4")
10990 (set_attr "type" "rev")]
10991)
10992
10993(define_insn "arm_rev16si2_alt"
10994 [(set (match_operand:SI 0 "register_operand" "=l,l,r")
10995 (ior:SI (and:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,l,r")
10996 (const_int 8))
10997 (match_operand:SI 2 "const_int_operand" "n,n,n"))
10998 (and:SI (ashift:SI (match_dup 1)
10999 (const_int 8))
11000 (match_operand:SI 3 "const_int_operand" "n,n,n"))))]
11001 "arm_arch6
11002 && aarch_rev16_shleft_mask_imm_p (operands[3], SImode)
11003 && aarch_rev16_shright_mask_imm_p (operands[2], SImode)"
11004 "rev16\\t%0, %1"
11005 [(set_attr "arch" "t1,t2,32")
11006 (set_attr "length" "2,2,4")
11007 (set_attr "type" "rev")]
a486b499 11008)
11009
11010(define_expand "bswaphi2"
11011 [(set (match_operand:HI 0 "s_register_operand" "=r")
11012 (bswap:HI (match_operand:HI 1 "s_register_operand" "r")))]
11013"arm_arch6"
11014""
11015)
11016
1653cf17 11017;; Patterns for LDRD/STRD in Thumb2 mode
11018
11019(define_insn "*thumb2_ldrd"
11020 [(set (match_operand:SI 0 "s_register_operand" "=r")
11021 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
11022 (match_operand:SI 2 "ldrd_strd_offset_operand" "Do"))))
11023 (set (match_operand:SI 3 "s_register_operand" "=r")
11024 (mem:SI (plus:SI (match_dup 1)
11025 (match_operand:SI 4 "const_int_operand" ""))))]
11026 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11027 && current_tune->prefer_ldrd_strd
11028 && ((INTVAL (operands[2]) + 4) == INTVAL (operands[4]))
11029 && (operands_ok_ldrd_strd (operands[0], operands[3],
11030 operands[1], INTVAL (operands[2]),
11031 false, true))"
11032 "ldrd%?\t%0, %3, [%1, %2]"
11033 [(set_attr "type" "load2")
d952d547 11034 (set_attr "predicable" "yes")
11035 (set_attr "predicable_short_it" "no")])
1653cf17 11036
11037(define_insn "*thumb2_ldrd_base"
11038 [(set (match_operand:SI 0 "s_register_operand" "=r")
11039 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
11040 (set (match_operand:SI 2 "s_register_operand" "=r")
11041 (mem:SI (plus:SI (match_dup 1)
11042 (const_int 4))))]
11043 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11044 && current_tune->prefer_ldrd_strd
11045 && (operands_ok_ldrd_strd (operands[0], operands[2],
11046 operands[1], 0, false, true))"
11047 "ldrd%?\t%0, %2, [%1]"
11048 [(set_attr "type" "load2")
d952d547 11049 (set_attr "predicable" "yes")
11050 (set_attr "predicable_short_it" "no")])
1653cf17 11051
11052(define_insn "*thumb2_ldrd_base_neg"
11053 [(set (match_operand:SI 0 "s_register_operand" "=r")
11054 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
11055 (const_int -4))))
11056 (set (match_operand:SI 2 "s_register_operand" "=r")
11057 (mem:SI (match_dup 1)))]
11058 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11059 && current_tune->prefer_ldrd_strd
11060 && (operands_ok_ldrd_strd (operands[0], operands[2],
11061 operands[1], -4, false, true))"
11062 "ldrd%?\t%0, %2, [%1, #-4]"
11063 [(set_attr "type" "load2")
d952d547 11064 (set_attr "predicable" "yes")
11065 (set_attr "predicable_short_it" "no")])
1653cf17 11066
11067(define_insn "*thumb2_strd"
11068 [(set (mem:SI (plus:SI (match_operand:SI 0 "s_register_operand" "rk")
11069 (match_operand:SI 1 "ldrd_strd_offset_operand" "Do")))
11070 (match_operand:SI 2 "s_register_operand" "r"))
11071 (set (mem:SI (plus:SI (match_dup 0)
11072 (match_operand:SI 3 "const_int_operand" "")))
11073 (match_operand:SI 4 "s_register_operand" "r"))]
11074 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11075 && current_tune->prefer_ldrd_strd
11076 && ((INTVAL (operands[1]) + 4) == INTVAL (operands[3]))
11077 && (operands_ok_ldrd_strd (operands[2], operands[4],
11078 operands[0], INTVAL (operands[1]),
11079 false, false))"
11080 "strd%?\t%2, %4, [%0, %1]"
11081 [(set_attr "type" "store2")
d952d547 11082 (set_attr "predicable" "yes")
11083 (set_attr "predicable_short_it" "no")])
1653cf17 11084
11085(define_insn "*thumb2_strd_base"
11086 [(set (mem:SI (match_operand:SI 0 "s_register_operand" "rk"))
11087 (match_operand:SI 1 "s_register_operand" "r"))
11088 (set (mem:SI (plus:SI (match_dup 0)
11089 (const_int 4)))
11090 (match_operand:SI 2 "s_register_operand" "r"))]
11091 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11092 && current_tune->prefer_ldrd_strd
11093 && (operands_ok_ldrd_strd (operands[1], operands[2],
11094 operands[0], 0, false, false))"
11095 "strd%?\t%1, %2, [%0]"
11096 [(set_attr "type" "store2")
d952d547 11097 (set_attr "predicable" "yes")
11098 (set_attr "predicable_short_it" "no")])
1653cf17 11099
11100(define_insn "*thumb2_strd_base_neg"
11101 [(set (mem:SI (plus:SI (match_operand:SI 0 "s_register_operand" "rk")
11102 (const_int -4)))
11103 (match_operand:SI 1 "s_register_operand" "r"))
11104 (set (mem:SI (match_dup 0))
11105 (match_operand:SI 2 "s_register_operand" "r"))]
11106 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11107 && current_tune->prefer_ldrd_strd
11108 && (operands_ok_ldrd_strd (operands[1], operands[2],
11109 operands[0], -4, false, false))"
11110 "strd%?\t%1, %2, [%0, #-4]"
11111 [(set_attr "type" "store2")
d952d547 11112 (set_attr "predicable" "yes")
11113 (set_attr "predicable_short_it" "no")])
1653cf17 11114
2a0c73f2 11115;; ARMv8 CRC32 instructions.
11116(define_insn "<crc_variant>"
11117 [(set (match_operand:SI 0 "s_register_operand" "=r")
11118 (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")
11119 (match_operand:<crc_mode> 2 "s_register_operand" "r")]
11120 CRC))]
11121 "TARGET_CRC32"
11122 "<crc_variant>\\t%0, %1, %2"
11123 [(set_attr "type" "crc")
11124 (set_attr "conds" "unconditional")]
11125)
1653cf17 11126
353cf59a 11127;; Load the load/store double peephole optimizations.
11128(include "ldrdstrd.md")
11129
320ea44d 11130;; Load the load/store multiple patterns
11131(include "ldmstm.md")
426be8c5 11132
11133;; Patterns in ldmstm.md don't cover more than 4 registers. This pattern covers
11134;; large lists without explicit writeback generated for APCS_FRAME epilogue.
11135(define_insn "*load_multiple"
11136 [(match_parallel 0 "load_multiple_operation"
11137 [(set (match_operand:SI 2 "s_register_operand" "=rk")
11138 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
11139 ])]
11140 "TARGET_32BIT"
11141 "*
11142 {
11143 arm_output_multireg_pop (operands, /*return_pc=*/false,
11144 /*cond=*/const_true_rtx,
11145 /*reverse=*/false,
11146 /*update=*/false);
11147 return \"\";
11148 }
11149 "
11150 [(set_attr "predicable" "yes")]
11151)
11152
d98a3884 11153;; Vector bits common to IWMMXT and Neon
11154(include "vec-common.md")
755eb2b4 11155;; Load the Intel Wireless Multimedia Extension patterns
11156(include "iwmmxt.md")
a2cd141b 11157;; Load the VFP co-processor patterns
11158(include "vfp.md")
bc360af8 11159;; Thumb-1 patterns
11160(include "thumb1.md")
25f905c2 11161;; Thumb-2 patterns
11162(include "thumb2.md")
d98a3884 11163;; Neon patterns
11164(include "neon.md")
e84fdf6e 11165;; Crypto patterns
11166(include "crypto.md")
06df6b17 11167;; Synchronization Primitives
11168(include "sync.md")
bbbe4599 11169;; Fixed-point patterns
11170(include "arm-fixed.md")