]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/arm/arm.md
gcc/
[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
e4585731 128; arm_arch6. "v6t2" for Thumb-2 with arm_arch6. This attribute is
129; used to compute attribute "enabled", use type "any" to enable an
130; alternative in all cases.
131(define_attr "arch" "any,a,t,32,t1,t2,v6,nov6,v6t2,neon_for_64bits,avoid_neon_for_64bits,iwmmxt,iwmmxt2,armv6_or_vfpv3"
d5d4dc8d 132 (const_string "any"))
133
134(define_attr "arch_enabled" "no,yes"
135 (cond [(eq_attr "arch" "any")
136 (const_string "yes")
137
138 (and (eq_attr "arch" "a")
0bf497f5 139 (match_test "TARGET_ARM"))
d5d4dc8d 140 (const_string "yes")
141
142 (and (eq_attr "arch" "t")
0bf497f5 143 (match_test "TARGET_THUMB"))
d5d4dc8d 144 (const_string "yes")
145
146 (and (eq_attr "arch" "t1")
0bf497f5 147 (match_test "TARGET_THUMB1"))
d5d4dc8d 148 (const_string "yes")
149
150 (and (eq_attr "arch" "t2")
0bf497f5 151 (match_test "TARGET_THUMB2"))
d5d4dc8d 152 (const_string "yes")
153
154 (and (eq_attr "arch" "32")
0bf497f5 155 (match_test "TARGET_32BIT"))
d5d4dc8d 156 (const_string "yes")
157
158 (and (eq_attr "arch" "v6")
0bf497f5 159 (match_test "TARGET_32BIT && arm_arch6"))
d5d4dc8d 160 (const_string "yes")
161
162 (and (eq_attr "arch" "nov6")
0bf497f5 163 (match_test "TARGET_32BIT && !arm_arch6"))
a651f34d 164 (const_string "yes")
165
e4585731 166 (and (eq_attr "arch" "v6t2")
167 (match_test "TARGET_32BIT && arm_arch6 && arm_arch_thumb2"))
168 (const_string "yes")
169
b6779ddc 170 (and (eq_attr "arch" "avoid_neon_for_64bits")
171 (match_test "TARGET_NEON")
172 (not (match_test "TARGET_PREFER_NEON_64BITS")))
a651f34d 173 (const_string "yes")
174
b6779ddc 175 (and (eq_attr "arch" "neon_for_64bits")
176 (match_test "TARGET_NEON")
177 (match_test "TARGET_PREFER_NEON_64BITS"))
6b8f7c28 178 (const_string "yes")
179
180 (and (eq_attr "arch" "iwmmxt2")
181 (match_test "TARGET_REALLY_IWMMXT2"))
21cc9773 182 (const_string "yes")
183
184 (and (eq_attr "arch" "armv6_or_vfpv3")
185 (match_test "arm_arch6 || TARGET_VFP3"))
186 (const_string "yes")
187 ]
6b8f7c28 188
d5d4dc8d 189 (const_string "no")))
190
aa06c51c 191(define_attr "opt" "any,speed,size"
192 (const_string "any"))
193
194(define_attr "opt_enabled" "no,yes"
195 (cond [(eq_attr "opt" "any")
196 (const_string "yes")
197
198 (and (eq_attr "opt" "speed")
199 (match_test "optimize_function_for_speed_p (cfun)"))
200 (const_string "yes")
201
202 (and (eq_attr "opt" "size")
203 (match_test "optimize_function_for_size_p (cfun)"))
204 (const_string "yes")]
205 (const_string "no")))
206
861033d5 207(define_attr "use_literal_pool" "no,yes"
208 (cond [(and (eq_attr "type" "f_loads,f_loadd")
209 (match_test "CONSTANT_P (operands[1])"))
210 (const_string "yes")]
211 (const_string "no")))
212
d5d4dc8d 213; Enable all alternatives that are both arch_enabled and insn_enabled.
951a3f72 214; FIXME:: opt_enabled has been temporarily removed till the time we have
215; an attribute that allows the use of such alternatives.
216; This depends on caching of speed_p, size_p on a per
217; alternative basis. The problem is that the enabled attribute
218; cannot depend on any state that is not cached or is not constant
219; for a compilation unit. We probably need a generic "hot/cold"
220; alternative which if implemented can help with this. We disable this
221; until such a time as this is implemented and / or the improvements or
222; regressions with removing this attribute are double checked.
223; See ashldi3_neon and <shift>di3_neon in neon.md.
224
93b431d9 225 (define_attr "enabled" "no,yes"
0abea32c 226 (cond [(and (eq_attr "predicable_short_it" "no")
c7a58118 227 (and (eq_attr "predicated" "yes")
228 (match_test "arm_restrict_it")))
229 (const_string "no")
230
231 (and (eq_attr "enabled_for_depr_it" "no")
232 (match_test "arm_restrict_it"))
233 (const_string "no")
234
861033d5 235 (and (eq_attr "use_literal_pool" "yes")
236 (match_test "arm_disable_literal_pool"))
237 (const_string "no")
238
aa06c51c 239 (eq_attr "arch_enabled" "no")
aa06c51c 240 (const_string "no")]
241 (const_string "yes")))
d5d4dc8d 242
56d27660 243; POOL_RANGE is how far away from a constant pool entry that this insn
244; can be placed. If the distance is zero, then this insn will never
245; reference the pool.
42e1de19 246; Note that for Thumb constant pools the PC value is rounded down to the
247; nearest multiple of four. Therefore, THUMB2_POOL_RANGE (and POOL_RANGE for
248; Thumb insns) should be set to <max_range> - 2.
cffb2a26 249; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
8848d797 250; before its address. It is set to <max_range> - (8 + <data_size>).
cde1623a 251(define_attr "arm_pool_range" "" (const_int 0))
252(define_attr "thumb2_pool_range" "" (const_int 0))
253(define_attr "arm_neg_pool_range" "" (const_int 0))
254(define_attr "thumb2_neg_pool_range" "" (const_int 0))
255
256(define_attr "pool_range" ""
257 (cond [(eq_attr "is_thumb" "yes") (attr "thumb2_pool_range")]
258 (attr "arm_pool_range")))
259(define_attr "neg_pool_range" ""
260 (cond [(eq_attr "is_thumb" "yes") (attr "thumb2_neg_pool_range")]
261 (attr "arm_neg_pool_range")))
56d27660 262
215b30b3 263; An assembler sequence may clobber the condition codes without us knowing.
4d7a8451 264; If such an insn references the pool, then we have no way of knowing how,
265; so use the most conservative value for pool_range.
9c08d1fa 266(define_asm_attributes
4d7a8451 267 [(set_attr "conds" "clob")
268 (set_attr "length" "4")
269 (set_attr "pool_range" "250")])
9c08d1fa 270
9888ad6d 271; Load scheduling, set from the arm_ld_sched variable
4c834714 272; initialized by arm_option_override()
9888ad6d 273(define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
849170fd 274
f7fbdd4a 275; condition codes: this one is used by final_prescan_insn to speed up
276; conditionalizing instructions. It saves having to scan the rtl to see if
277; it uses or alters the condition codes.
215b30b3 278;
f7fbdd4a 279; USE means that the condition codes are used by the insn in the process of
215b30b3 280; outputting code, this means (at present) that we can't use the insn in
281; inlined branches
282;
f7fbdd4a 283; SET means that the purpose of the insn is to set the condition codes in a
215b30b3 284; well defined manner.
285;
f7fbdd4a 286; CLOB means that the condition codes are altered in an undefined manner, if
215b30b3 287; they are altered at all
288;
ad6d3e2a 289; UNCONDITIONAL means the instruction can not be conditionally executed and
290; that the instruction does not use or alter the condition codes.
c52acdd2 291;
ad6d3e2a 292; NOCOND means that the instruction does not use or alter the condition
293; codes but can be converted into a conditionally exectuted instruction.
f7fbdd4a 294
b0694be0 295(define_attr "conds" "use,set,clob,unconditional,nocond"
747b7458 296 (if_then_else
297 (ior (eq_attr "is_thumb1" "yes")
298 (eq_attr "type" "call"))
c1a66faf 299 (const_string "clob")
32093010 300 (if_then_else (eq_attr "is_neon_type" "no")
52432540 301 (const_string "nocond")
302 (const_string "unconditional"))))
f7fbdd4a 303
215b30b3 304; Predicable means that the insn can be conditionally executed based on
305; an automatically added predicate (additional patterns are generated by
306; gen...). We default to 'no' because no Thumb patterns match this rule
307; and not all ARM patterns do.
0d66636f 308(define_attr "predicable" "no,yes" (const_string "no"))
309
129a2fe4 310; Only model the write buffer for ARM6 and ARM7. Earlier processors don't
311; have one. Later ones, such as StrongARM, have write-back caches, so don't
8d232dc7 312; suffer blockages enough to warrant modelling this (and it can adversely
129a2fe4 313; affect the schedule).
74a71f7d 314(define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_tune_wbuf")))
129a2fe4 315
215b30b3 316; WRITE_CONFLICT implies that a read following an unrelated write is likely
317; to stall the processor. Used with model_wbuf above.
9c08d1fa 318(define_attr "write_conflict" "no,yes"
319 (if_then_else (eq_attr "type"
96854199 320 "block,call,load1")
9c08d1fa 321 (const_string "yes")
322 (const_string "no")))
323
215b30b3 324; Classify the insns into those that take one cycle and those that take more
325; than one on the main cpu execution unit.
f7fbdd4a 326(define_attr "core_cycles" "single,multi"
327 (if_then_else (eq_attr "type"
112eda6f 328 "adc_imm, adc_reg, adcs_imm, adcs_reg, adr, alu_ext, alu_imm, alu_sreg,\
329 alu_shift_imm, alu_shift_reg, alu_dsp_reg, alus_ext, alus_imm, alus_sreg,\
d82e788e 330 alus_shift_imm, alus_shift_reg, bfm, csel, rev, logic_imm, logic_reg,\
331 logic_shift_imm, logic_shift_reg, logics_imm, logics_reg,\
332 logics_shift_imm, logics_shift_reg, extend, shift_imm, float, fcsel,\
7cb6c048 333 wmmx_wor, wmmx_wxor, wmmx_wand, wmmx_wandn, wmmx_wmov, wmmx_tmcrr,\
334 wmmx_tmrrc, wmmx_wldr, wmmx_wstr, wmmx_tmcr, wmmx_tmrc, wmmx_wadd,\
335 wmmx_wsub, wmmx_wmul, wmmx_wmac, wmmx_wavg2, wmmx_tinsr, wmmx_textrm,\
336 wmmx_wshufh, wmmx_wcmpeq, wmmx_wcmpgt, wmmx_wmax, wmmx_wmin, wmmx_wpack,\
337 wmmx_wunpckih, wmmx_wunpckil, wmmx_wunpckeh, wmmx_wunpckel, wmmx_wror,\
338 wmmx_wsra, wmmx_wsrl, wmmx_wsll, wmmx_wmadd, wmmx_tmia, wmmx_tmiaph,\
339 wmmx_tmiaxy, wmmx_tbcst, wmmx_tmovmsk, wmmx_wacc, wmmx_waligni,\
340 wmmx_walignr, wmmx_tandc, wmmx_textrc, wmmx_torc, wmmx_torvsc, wmmx_wsad,\
341 wmmx_wabs, wmmx_wabsdiff, wmmx_waddsubhx, wmmx_wsubaddhx, wmmx_wavg4,\
342 wmmx_wmulw, wmmx_wqmulm, wmmx_wqmulwm, wmmx_waddbhus, wmmx_wqmiaxy,\
343 wmmx_wmiaxy, wmmx_wmiawxy, wmmx_wmerge")
f7fbdd4a 344 (const_string "single")
345 (const_string "multi")))
346
cffb2a26 347;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
215b30b3 348;; distant label. Only applicable to Thumb code.
cffb2a26 349(define_attr "far_jump" "yes,no" (const_string "no"))
350
d51f92df 351
25f905c2 352;; The number of machine instructions this pattern expands to.
353;; Used for Thumb-2 conditional execution.
354(define_attr "ce_count" "" (const_int 1))
355
4182b724 356;;---------------------------------------------------------------------------
357;; Unspecs
358
359(include "unspecs.md")
360
d51f92df 361;;---------------------------------------------------------------------------
fd781bb2 362;; Mode iterators
d51f92df 363
3de0dec6 364(include "iterators.md")
03770691 365
d51f92df 366;;---------------------------------------------------------------------------
367;; Predicates
368
9c9db025 369(include "predicates.md")
234f6557 370(include "constraints.md")
9c9db025 371
a2cd141b 372;;---------------------------------------------------------------------------
373;; Pipeline descriptions
215b30b3 374
e3879fd0 375(define_attr "tune_cortexr4" "yes,no"
376 (const (if_then_else
7d3cda8c 377 (eq_attr "tune" "cortexr4,cortexr4f,cortexr5")
e3879fd0 378 (const_string "yes")
379 (const_string "no"))))
380
a2cd141b 381;; True if the generic scheduling description should be used.
382
383(define_attr "generic_sched" "yes,no"
2546d93a 384 (const (if_then_else
e18862f3 385 (ior (eq_attr "tune" "fa526,fa626,fa606te,fa626te,fmp626,fa726te,\
386 arm926ejs,arm1020e,arm1026ejs,arm1136js,\
387 arm1136jfs,cortexa5,cortexa7,cortexa8,\
42e7b263 388 cortexa9,cortexa12,cortexa15,cortexa17,\
389 cortexa53,cortexm4,cortexm7,marvell_pj4")
2546d93a 390 (eq_attr "tune_cortexr4" "yes"))
4d5cb40d 391 (const_string "no")
392 (const_string "yes"))))
393
c0e1af52 394(define_attr "generic_vfp" "yes,no"
395 (const (if_then_else
396 (and (eq_attr "fpu" "vfp")
e18862f3 397 (eq_attr "tune" "!arm1020e,arm1022e,cortexa5,cortexa7,\
398 cortexa8,cortexa9,cortexa53,cortexm4,\
399 cortexm7,marvell_pj4")
e3879fd0 400 (eq_attr "tune_cortexr4" "no"))
c0e1af52 401 (const_string "yes")
402 (const_string "no"))))
403
6b8f7c28 404(include "marvell-f-iwmmxt.md")
a2cd141b 405(include "arm-generic.md")
406(include "arm926ejs.md")
c0e1af52 407(include "arm1020e.md")
a2cd141b 408(include "arm1026ejs.md")
409(include "arm1136jfs.md")
0e266d06 410(include "fa526.md")
411(include "fa606te.md")
412(include "fa626te.md")
413(include "fmp626.md")
414(include "fa726te.md")
3f1e069f 415(include "cortex-a5.md")
d6b7f019 416(include "cortex-a7.md")
bcaec148 417(include "cortex-a8.md")
036068af 418(include "cortex-a9.md")
65f2f758 419(include "cortex-a15.md")
42e7b263 420(include "cortex-a17.md")
da10bc87 421(include "cortex-a53.md")
934a1e72 422(include "cortex-r4.md")
e3879fd0 423(include "cortex-r4f.md")
e18862f3 424(include "cortex-m7.md")
2546d93a 425(include "cortex-m4.md")
426(include "cortex-m4-fpu.md")
55e3ada8 427(include "vfp11.md")
ea7d210b 428(include "marvell-pj4.md")
3586df96 429
9c08d1fa 430\f
215b30b3 431;;---------------------------------------------------------------------------
e1159bbe 432;; Insn patterns
433;;
a0f94409 434;; Addition insns.
215b30b3 435
9c08d1fa 436;; Note: For DImode insns, there is normally no reason why operands should
437;; not be in the same register, what we don't want is for something being
438;; written to partially overlap something that is an input.
439
cffb2a26 440(define_expand "adddi3"
441 [(parallel
215b30b3 442 [(set (match_operand:DI 0 "s_register_operand" "")
cffb2a26 443 (plus:DI (match_operand:DI 1 "s_register_operand" "")
10e5ccd5 444 (match_operand:DI 2 "arm_adddi_operand" "")))
bd5b4116 445 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 446 "TARGET_EITHER"
447 "
25f905c2 448 if (TARGET_THUMB1)
cffb2a26 449 {
0438d37f 450 if (!REG_P (operands[1]))
bc5a93af 451 operands[1] = force_reg (DImode, operands[1]);
0438d37f 452 if (!REG_P (operands[2]))
bc5a93af 453 operands[2] = force_reg (DImode, operands[2]);
cffb2a26 454 }
455 "
456)
457
a0f94409 458(define_insn_and_split "*arm_adddi3"
10e5ccd5 459 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r,&r,&r")
460 (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0, r, 0, r")
461 (match_operand:DI 2 "arm_adddi_operand" "r, 0, r, Dd, Dd")))
bd5b4116 462 (clobber (reg:CC CC_REGNUM))]
b805622c 463 "TARGET_32BIT && !TARGET_NEON"
33782ec7 464 "#"
94829feb 465 "TARGET_32BIT && reload_completed
466 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))"
a0f94409 467 [(parallel [(set (reg:CC_C CC_REGNUM)
468 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
469 (match_dup 1)))
470 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 471 (set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (match_dup 5))
472 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
a0f94409 473 "
474 {
475 operands[3] = gen_highpart (SImode, operands[0]);
476 operands[0] = gen_lowpart (SImode, operands[0]);
477 operands[4] = gen_highpart (SImode, operands[1]);
478 operands[1] = gen_lowpart (SImode, operands[1]);
10e5ccd5 479 operands[5] = gen_highpart_mode (SImode, DImode, operands[2]);
a0f94409 480 operands[2] = gen_lowpart (SImode, operands[2]);
481 }"
cffb2a26 482 [(set_attr "conds" "clob")
1b7da4ac 483 (set_attr "length" "8")
484 (set_attr "type" "multiple")]
cffb2a26 485)
9c08d1fa 486
a0f94409 487(define_insn_and_split "*adddi_sesidi_di"
9c08d1fa 488 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
489 (plus:DI (sign_extend:DI
97499065 490 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 491 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 492 (clobber (reg:CC CC_REGNUM))]
b805622c 493 "TARGET_32BIT"
33782ec7 494 "#"
25f905c2 495 "TARGET_32BIT && reload_completed"
a0f94409 496 [(parallel [(set (reg:CC_C CC_REGNUM)
497 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
498 (match_dup 1)))
499 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 500 (set (match_dup 3) (plus:SI (plus:SI (ashiftrt:SI (match_dup 2)
a0f94409 501 (const_int 31))
080c0b9a 502 (match_dup 4))
503 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
a0f94409 504 "
505 {
506 operands[3] = gen_highpart (SImode, operands[0]);
507 operands[0] = gen_lowpart (SImode, operands[0]);
508 operands[4] = gen_highpart (SImode, operands[1]);
509 operands[1] = gen_lowpart (SImode, operands[1]);
510 operands[2] = gen_lowpart (SImode, operands[2]);
511 }"
215b30b3 512 [(set_attr "conds" "clob")
1b7da4ac 513 (set_attr "length" "8")
514 (set_attr "type" "multiple")]
215b30b3 515)
9c08d1fa 516
a0f94409 517(define_insn_and_split "*adddi_zesidi_di"
9c08d1fa 518 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
519 (plus:DI (zero_extend:DI
97499065 520 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 521 (match_operand:DI 1 "s_register_operand" "0,r")))
a0f94409 522 (clobber (reg:CC CC_REGNUM))]
b805622c 523 "TARGET_32BIT"
33782ec7 524 "#"
25f905c2 525 "TARGET_32BIT && reload_completed"
a0f94409 526 [(parallel [(set (reg:CC_C CC_REGNUM)
527 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
528 (match_dup 1)))
529 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 530 (set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (const_int 0))
531 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
a0f94409 532 "
533 {
534 operands[3] = gen_highpart (SImode, operands[0]);
535 operands[0] = gen_lowpart (SImode, operands[0]);
536 operands[4] = gen_highpart (SImode, operands[1]);
537 operands[1] = gen_lowpart (SImode, operands[1]);
538 operands[2] = gen_lowpart (SImode, operands[2]);
539 }"
cffb2a26 540 [(set_attr "conds" "clob")
1b7da4ac 541 (set_attr "length" "8")
542 (set_attr "type" "multiple")]
cffb2a26 543)
b11cae9e 544
87b22bf7 545(define_expand "addsi3"
cffb2a26 546 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 547 (plus:SI (match_operand:SI 1 "s_register_operand" "")
548 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 549 "TARGET_EITHER"
87b22bf7 550 "
0438d37f 551 if (TARGET_32BIT && CONST_INT_P (operands[2]))
87b22bf7 552 {
96f57e36 553 arm_split_constant (PLUS, SImode, NULL_RTX,
554 INTVAL (operands[2]), operands[0], operands[1],
e1ba4a27 555 optimize && can_create_pseudo_p ());
87b22bf7 556 DONE;
557 }
cffb2a26 558 "
559)
87b22bf7 560
5bd751ff 561; If there is a scratch available, this will be faster than synthesizing the
a0f94409 562; addition.
563(define_peephole2
564 [(match_scratch:SI 3 "r")
372575c7 565 (set (match_operand:SI 0 "arm_general_register_operand" "")
566 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
cffb2a26 567 (match_operand:SI 2 "const_int_operand" "")))]
25f905c2 568 "TARGET_32BIT &&
a0f94409 569 !(const_ok_for_arm (INTVAL (operands[2]))
570 || const_ok_for_arm (-INTVAL (operands[2])))
571 && const_ok_for_arm (~INTVAL (operands[2]))"
572 [(set (match_dup 3) (match_dup 2))
573 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
574 ""
575)
87b22bf7 576
2f02c19f 577;; The r/r/k alternative is required when reloading the address
578;; (plus (reg rN) (reg sp)) into (reg rN). In this case reload will
579;; put the duplicated register first, and not try the commutative version.
a0f94409 580(define_insn_and_split "*arm_addsi3"
7c36fe71 581 [(set (match_operand:SI 0 "s_register_operand" "=rk,l,l ,l ,r ,k ,r,r ,k ,r ,k,k,r ,k ,r")
582 (plus:SI (match_operand:SI 1 "s_register_operand" "%0 ,l,0 ,l ,rk,k ,r,rk,k ,rk,k,r,rk,k ,rk")
583 (match_operand:SI 2 "reg_or_int_operand" "rk ,l,Py,Pd,rI,rI,k,Pj,Pj,L ,L,L,PJ,PJ,?n")))]
25f905c2 584 "TARGET_32BIT"
5565501b 585 "@
c24d855d 586 add%?\\t%0, %0, %2
5565501b 587 add%?\\t%0, %1, %2
a0b3420a 588 add%?\\t%0, %1, %2
7c36fe71 589 add%?\\t%0, %1, %2
590 add%?\\t%0, %1, %2
aaa37ad6 591 add%?\\t%0, %1, %2
2f02c19f 592 add%?\\t%0, %2, %1
d5cbae34 593 addw%?\\t%0, %1, %2
594 addw%?\\t%0, %1, %2
aaa37ad6 595 sub%?\\t%0, %1, #%n2
87b22bf7 596 sub%?\\t%0, %1, #%n2
d7757711 597 sub%?\\t%0, %1, #%n2
d5cbae34 598 subw%?\\t%0, %1, #%n2
599 subw%?\\t%0, %1, #%n2
87b22bf7 600 #"
a3ffc315 601 "TARGET_32BIT
0438d37f 602 && CONST_INT_P (operands[2])
d5cbae34 603 && !const_ok_for_op (INTVAL (operands[2]), PLUS)
a3ffc315 604 && (reload_completed || !arm_eliminable_register (operands[1]))"
a0f94409 605 [(clobber (const_int 0))]
606 "
96f57e36 607 arm_split_constant (PLUS, SImode, curr_insn,
608 INTVAL (operands[2]), operands[0],
a0f94409 609 operands[1], 0);
610 DONE;
611 "
7c36fe71 612 [(set_attr "length" "2,4,4,4,4,4,4,4,4,4,4,4,4,4,16")
d5cbae34 613 (set_attr "predicable" "yes")
7c36fe71 614 (set_attr "predicable_short_it" "yes,yes,yes,yes,no,no,no,no,no,no,no,no,no,no,no")
615 (set_attr "arch" "t2,t2,t2,t2,*,*,*,t2,t2,*,*,a,t2,t2,*")
65f68e55 616 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
d82e788e 617 (const_string "alu_imm")
112eda6f 618 (const_string "alu_sreg")))
65f68e55 619 ]
cffb2a26 620)
621
90c2bcf0 622(define_insn "addsi3_compare0"
bd5b4116 623 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 624 (compare:CC_NOOV
65f68e55 625 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r,r")
626 (match_operand:SI 2 "arm_add_operand" "I,L,r"))
5565501b 627 (const_int 0)))
65f68e55 628 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9c08d1fa 629 (plus:SI (match_dup 1) (match_dup 2)))]
ec792a7b 630 "TARGET_ARM"
5565501b 631 "@
25f905c2 632 add%.\\t%0, %1, %2
65f68e55 633 sub%.\\t%0, %1, #%n2
634 add%.\\t%0, %1, %2"
635 [(set_attr "conds" "set")
112eda6f 636 (set_attr "type" "alus_imm,alus_imm,alus_sreg")]
cffb2a26 637)
9c08d1fa 638
aea4c774 639(define_insn "*addsi3_compare0_scratch"
bd5b4116 640 [(set (reg:CC_NOOV CC_REGNUM)
aea4c774 641 (compare:CC_NOOV
65f68e55 642 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r, r")
643 (match_operand:SI 1 "arm_add_operand" "I,L, r"))
aea4c774 644 (const_int 0)))]
ec792a7b 645 "TARGET_ARM"
cffb2a26 646 "@
647 cmn%?\\t%0, %1
65f68e55 648 cmp%?\\t%0, #%n1
649 cmn%?\\t%0, %1"
596e5e8f 650 [(set_attr "conds" "set")
65f68e55 651 (set_attr "predicable" "yes")
112eda6f 652 (set_attr "type" "alus_imm,alus_imm,alus_sreg")]
0d66636f 653)
cffb2a26 654
aed179ae 655(define_insn "*compare_negsi_si"
656 [(set (reg:CC_Z CC_REGNUM)
657 (compare:CC_Z
7c36fe71 658 (neg:SI (match_operand:SI 0 "s_register_operand" "l,r"))
659 (match_operand:SI 1 "s_register_operand" "l,r")))]
25f905c2 660 "TARGET_32BIT"
aed179ae 661 "cmn%?\\t%1, %0"
596e5e8f 662 [(set_attr "conds" "set")
7c36fe71 663 (set_attr "predicable" "yes")
664 (set_attr "arch" "t2,*")
665 (set_attr "length" "2,4")
1b7da4ac 666 (set_attr "predicable_short_it" "yes,no")
112eda6f 667 (set_attr "type" "alus_sreg")]
0d66636f 668)
aea4c774 669
203c488f 670;; This is the canonicalization of addsi3_compare0_for_combiner when the
671;; addend is a constant.
190efb17 672(define_insn "cmpsi2_addneg"
203c488f 673 [(set (reg:CC CC_REGNUM)
674 (compare:CC
675 (match_operand:SI 1 "s_register_operand" "r,r")
2a977b78 676 (match_operand:SI 2 "arm_addimm_operand" "L,I")))
203c488f 677 (set (match_operand:SI 0 "s_register_operand" "=r,r")
678 (plus:SI (match_dup 1)
2a977b78 679 (match_operand:SI 3 "arm_addimm_operand" "I,L")))]
25f905c2 680 "TARGET_32BIT && INTVAL (operands[2]) == -INTVAL (operands[3])"
203c488f 681 "@
2a977b78 682 add%.\\t%0, %1, %3
683 sub%.\\t%0, %1, #%n3"
1b7da4ac 684 [(set_attr "conds" "set")
112eda6f 685 (set_attr "type" "alus_sreg")]
203c488f 686)
687
688;; Convert the sequence
689;; sub rd, rn, #1
690;; cmn rd, #1 (equivalent to cmp rd, #-1)
691;; bne dest
692;; into
693;; subs rd, rn, #1
694;; bcs dest ((unsigned)rn >= 1)
695;; similarly for the beq variant using bcc.
696;; This is a common looping idiom (while (n--))
697(define_peephole2
372575c7 698 [(set (match_operand:SI 0 "arm_general_register_operand" "")
699 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
203c488f 700 (const_int -1)))
701 (set (match_operand 2 "cc_register" "")
702 (compare (match_dup 0) (const_int -1)))
703 (set (pc)
704 (if_then_else (match_operator 3 "equality_operator"
705 [(match_dup 2) (const_int 0)])
706 (match_operand 4 "" "")
707 (match_operand 5 "" "")))]
25f905c2 708 "TARGET_32BIT && peep2_reg_dead_p (3, operands[2])"
203c488f 709 [(parallel[
710 (set (match_dup 2)
711 (compare:CC
712 (match_dup 1) (const_int 1)))
713 (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
714 (set (pc)
715 (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
716 (match_dup 4)
717 (match_dup 5)))]
718 "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
719 operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
720 ? GEU : LTU),
721 VOIDmode,
722 operands[2], const0_rtx);"
723)
724
ebcc79bc 725;; The next four insns work because they compare the result with one of
726;; the operands, and we know that the use of the condition code is
727;; either GEU or LTU, so we can use the carry flag from the addition
728;; instead of doing the compare a second time.
729(define_insn "*addsi3_compare_op1"
bd5b4116 730 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 731 (compare:CC_C
65f68e55 732 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
733 (match_operand:SI 2 "arm_add_operand" "I,L,r"))
ebcc79bc 734 (match_dup 1)))
65f68e55 735 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
ebcc79bc 736 (plus:SI (match_dup 1) (match_dup 2)))]
25f905c2 737 "TARGET_32BIT"
ebcc79bc 738 "@
25f905c2 739 add%.\\t%0, %1, %2
65f68e55 740 sub%.\\t%0, %1, #%n2
741 add%.\\t%0, %1, %2"
742 [(set_attr "conds" "set")
112eda6f 743 (set_attr "type" "alus_imm,alus_imm,alus_sreg")]
0d66636f 744)
ebcc79bc 745
746(define_insn "*addsi3_compare_op2"
bd5b4116 747 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 748 (compare:CC_C
65f68e55 749 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
750 (match_operand:SI 2 "arm_add_operand" "I,L,r"))
ebcc79bc 751 (match_dup 2)))
65f68e55 752 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9c08d1fa 753 (plus:SI (match_dup 1) (match_dup 2)))]
25f905c2 754 "TARGET_32BIT"
5565501b 755 "@
65f68e55 756 add%.\\t%0, %1, %2
25f905c2 757 add%.\\t%0, %1, %2
758 sub%.\\t%0, %1, #%n2"
65f68e55 759 [(set_attr "conds" "set")
112eda6f 760 (set_attr "type" "alus_imm,alus_imm,alus_sreg")]
0d66636f 761)
9c08d1fa 762
ebcc79bc 763(define_insn "*compare_addsi2_op0"
bd5b4116 764 [(set (reg:CC_C CC_REGNUM)
7c36fe71 765 (compare:CC_C
766 (plus:SI (match_operand:SI 0 "s_register_operand" "l,l,r,r,r")
767 (match_operand:SI 1 "arm_add_operand" "Pv,l,I,L,r"))
768 (match_dup 0)))]
25f905c2 769 "TARGET_32BIT"
ebcc79bc 770 "@
7c36fe71 771 cmp%?\\t%0, #%n1
772 cmn%?\\t%0, %1
ebcc79bc 773 cmn%?\\t%0, %1
65f68e55 774 cmp%?\\t%0, #%n1
775 cmn%?\\t%0, %1"
596e5e8f 776 [(set_attr "conds" "set")
65f68e55 777 (set_attr "predicable" "yes")
7c36fe71 778 (set_attr "arch" "t2,t2,*,*,*")
779 (set_attr "predicable_short_it" "yes,yes,no,no,no")
780 (set_attr "length" "2,2,4,4,4")
112eda6f 781 (set_attr "type" "alus_imm,alus_sreg,alus_imm,alus_imm,alus_sreg")]
0d66636f 782)
ebcc79bc 783
784(define_insn "*compare_addsi2_op1"
bd5b4116 785 [(set (reg:CC_C CC_REGNUM)
7c36fe71 786 (compare:CC_C
787 (plus:SI (match_operand:SI 0 "s_register_operand" "l,l,r,r,r")
788 (match_operand:SI 1 "arm_add_operand" "Pv,l,I,L,r"))
789 (match_dup 1)))]
25f905c2 790 "TARGET_32BIT"
ebcc79bc 791 "@
7c36fe71 792 cmp%?\\t%0, #%n1
793 cmn%?\\t%0, %1
ebcc79bc 794 cmn%?\\t%0, %1
65f68e55 795 cmp%?\\t%0, #%n1
796 cmn%?\\t%0, %1"
596e5e8f 797 [(set_attr "conds" "set")
65f68e55 798 (set_attr "predicable" "yes")
7c36fe71 799 (set_attr "arch" "t2,t2,*,*,*")
800 (set_attr "predicable_short_it" "yes,yes,no,no,no")
801 (set_attr "length" "2,2,4,4,4")
112eda6f 802 (set_attr "type" "alus_imm,alus_sreg,alus_imm,alus_imm,alus_sreg")]
7c36fe71 803 )
ebcc79bc 804
080c0b9a 805(define_insn "*addsi3_carryin_<optab>"
7c36fe71 806 [(set (match_operand:SI 0 "s_register_operand" "=l,r,r")
807 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%l,r,r")
808 (match_operand:SI 2 "arm_not_operand" "0,rI,K"))
809 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))]
25f905c2 810 "TARGET_32BIT"
10e5ccd5 811 "@
a0b3420a 812 adc%?\\t%0, %1, %2
10e5ccd5 813 adc%?\\t%0, %1, %2
814 sbc%?\\t%0, %1, #%B2"
a7de272d 815 [(set_attr "conds" "use")
7c36fe71 816 (set_attr "predicable" "yes")
817 (set_attr "arch" "t2,*,*")
818 (set_attr "length" "4")
1b7da4ac 819 (set_attr "predicable_short_it" "yes,no,no")
820 (set_attr "type" "adc_reg,adc_reg,adc_imm")]
cffb2a26 821)
ebcc79bc 822
080c0b9a 823(define_insn "*addsi3_carryin_alt2_<optab>"
7c36fe71 824 [(set (match_operand:SI 0 "s_register_operand" "=l,r,r")
825 (plus:SI (plus:SI (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))
826 (match_operand:SI 1 "s_register_operand" "%l,r,r"))
827 (match_operand:SI 2 "arm_rhs_operand" "l,rI,K")))]
25f905c2 828 "TARGET_32BIT"
10e5ccd5 829 "@
a0b3420a 830 adc%?\\t%0, %1, %2
10e5ccd5 831 adc%?\\t%0, %1, %2
832 sbc%?\\t%0, %1, #%B2"
a7de272d 833 [(set_attr "conds" "use")
7c36fe71 834 (set_attr "predicable" "yes")
835 (set_attr "arch" "t2,*,*")
836 (set_attr "length" "4")
1b7da4ac 837 (set_attr "predicable_short_it" "yes,no,no")
838 (set_attr "type" "adc_reg,adc_reg,adc_imm")]
0d66636f 839)
ebcc79bc 840
080c0b9a 841(define_insn "*addsi3_carryin_shift_<optab>"
ebcc79bc 842 [(set (match_operand:SI 0 "s_register_operand" "=r")
080c0b9a 843 (plus:SI (plus:SI
844 (match_operator:SI 2 "shift_operator"
845 [(match_operand:SI 3 "s_register_operand" "r")
846 (match_operand:SI 4 "reg_or_int_operand" "rM")])
847 (match_operand:SI 1 "s_register_operand" "r"))
848 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))]
25f905c2 849 "TARGET_32BIT"
080c0b9a 850 "adc%?\\t%0, %1, %3%S2"
851 [(set_attr "conds" "use")
a7de272d 852 (set_attr "predicable" "yes")
7c36fe71 853 (set_attr "predicable_short_it" "no")
080c0b9a 854 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
d82e788e 855 (const_string "alu_shift_imm")
856 (const_string "alu_shift_reg")))]
cffb2a26 857)
ebcc79bc 858
922b6913 859(define_insn "*addsi3_carryin_clobercc_<optab>"
860 [(set (match_operand:SI 0 "s_register_operand" "=r")
861 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%r")
862 (match_operand:SI 2 "arm_rhs_operand" "rI"))
863 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))
864 (clobber (reg:CC CC_REGNUM))]
865 "TARGET_32BIT"
866 "adc%.\\t%0, %1, %2"
1b7da4ac 867 [(set_attr "conds" "set")
868 (set_attr "type" "adcs_reg")]
922b6913 869)
870
9154bd82 871(define_insn "*subsi3_carryin"
872 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
873 (minus:SI (minus:SI (match_operand:SI 1 "reg_or_int_operand" "r,I")
874 (match_operand:SI 2 "s_register_operand" "r,r"))
875 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
876 "TARGET_32BIT"
877 "@
878 sbc%?\\t%0, %1, %2
879 rsc%?\\t%0, %2, %1"
880 [(set_attr "conds" "use")
881 (set_attr "arch" "*,a")
7c36fe71 882 (set_attr "predicable" "yes")
1b7da4ac 883 (set_attr "predicable_short_it" "no")
884 (set_attr "type" "adc_reg,adc_imm")]
9154bd82 885)
886
887(define_insn "*subsi3_carryin_const"
888 [(set (match_operand:SI 0 "s_register_operand" "=r")
889 (minus:SI (plus:SI (match_operand:SI 1 "reg_or_int_operand" "r")
890 (match_operand:SI 2 "arm_not_operand" "K"))
891 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
892 "TARGET_32BIT"
893 "sbc\\t%0, %1, #%B2"
1b7da4ac 894 [(set_attr "conds" "use")
895 (set_attr "type" "adc_imm")]
9154bd82 896)
897
898(define_insn "*subsi3_carryin_compare"
899 [(set (reg:CC CC_REGNUM)
900 (compare:CC (match_operand:SI 1 "s_register_operand" "r")
901 (match_operand:SI 2 "s_register_operand" "r")))
902 (set (match_operand:SI 0 "s_register_operand" "=r")
903 (minus:SI (minus:SI (match_dup 1)
904 (match_dup 2))
905 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
906 "TARGET_32BIT"
907 "sbcs\\t%0, %1, %2"
1b7da4ac 908 [(set_attr "conds" "set")
909 (set_attr "type" "adcs_reg")]
9154bd82 910)
911
912(define_insn "*subsi3_carryin_compare_const"
913 [(set (reg:CC CC_REGNUM)
914 (compare:CC (match_operand:SI 1 "reg_or_int_operand" "r")
915 (match_operand:SI 2 "arm_not_operand" "K")))
916 (set (match_operand:SI 0 "s_register_operand" "=r")
917 (minus:SI (plus:SI (match_dup 1)
918 (match_dup 2))
919 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
920 "TARGET_32BIT"
921 "sbcs\\t%0, %1, #%B2"
1b7da4ac 922 [(set_attr "conds" "set")
923 (set_attr "type" "adcs_imm")]
9154bd82 924)
925
926(define_insn "*subsi3_carryin_shift"
927 [(set (match_operand:SI 0 "s_register_operand" "=r")
928 (minus:SI (minus:SI
929 (match_operand:SI 1 "s_register_operand" "r")
930 (match_operator:SI 2 "shift_operator"
931 [(match_operand:SI 3 "s_register_operand" "r")
932 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
933 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
934 "TARGET_32BIT"
935 "sbc%?\\t%0, %1, %3%S2"
936 [(set_attr "conds" "use")
937 (set_attr "predicable" "yes")
938 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
d82e788e 939 (const_string "alu_shift_imm")
940 (const_string "alu_shift_reg")))]
9154bd82 941)
942
943(define_insn "*rsbsi3_carryin_shift"
944 [(set (match_operand:SI 0 "s_register_operand" "=r")
945 (minus:SI (minus:SI
946 (match_operator:SI 2 "shift_operator"
947 [(match_operand:SI 3 "s_register_operand" "r")
948 (match_operand:SI 4 "reg_or_int_operand" "rM")])
949 (match_operand:SI 1 "s_register_operand" "r"))
950 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
951 "TARGET_ARM"
952 "rsc%?\\t%0, %1, %3%S2"
953 [(set_attr "conds" "use")
954 (set_attr "predicable" "yes")
955 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
d82e788e 956 (const_string "alu_shift_imm")
957 (const_string "alu_shift_reg")))]
9154bd82 958)
959
d795fb69 960; transform ((x << y) - 1) to ~(~(x-1) << y) Where X is a constant.
961(define_split
962 [(set (match_operand:SI 0 "s_register_operand" "")
963 (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
964 (match_operand:SI 2 "s_register_operand" ""))
965 (const_int -1)))
966 (clobber (match_operand:SI 3 "s_register_operand" ""))]
25f905c2 967 "TARGET_32BIT"
d795fb69 968 [(set (match_dup 3) (match_dup 1))
969 (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
970 "
971 operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
972")
973
604f3a0a 974(define_expand "addsf3"
975 [(set (match_operand:SF 0 "s_register_operand" "")
976 (plus:SF (match_operand:SF 1 "s_register_operand" "")
d86c91f6 977 (match_operand:SF 2 "s_register_operand" "")))]
25f905c2 978 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 979 "
604f3a0a 980")
981
604f3a0a 982(define_expand "adddf3"
983 [(set (match_operand:DF 0 "s_register_operand" "")
984 (plus:DF (match_operand:DF 1 "s_register_operand" "")
d86c91f6 985 (match_operand:DF 2 "s_register_operand" "")))]
a50d7267 986 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 987 "
604f3a0a 988")
989
cffb2a26 990(define_expand "subdi3"
991 [(parallel
992 [(set (match_operand:DI 0 "s_register_operand" "")
993 (minus:DI (match_operand:DI 1 "s_register_operand" "")
994 (match_operand:DI 2 "s_register_operand" "")))
bd5b4116 995 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 996 "TARGET_EITHER"
997 "
25f905c2 998 if (TARGET_THUMB1)
cffb2a26 999 {
0438d37f 1000 if (!REG_P (operands[1]))
5aa8c5f0 1001 operands[1] = force_reg (DImode, operands[1]);
0438d37f 1002 if (!REG_P (operands[2]))
5aa8c5f0 1003 operands[2] = force_reg (DImode, operands[2]);
cffb2a26 1004 }
1005 "
1006)
1007
2f9b23e3 1008(define_insn_and_split "*arm_subdi3"
cffb2a26 1009 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
9c08d1fa 1010 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
1011 (match_operand:DI 2 "s_register_operand" "r,0,0")))
bd5b4116 1012 (clobber (reg:CC CC_REGNUM))]
94829feb 1013 "TARGET_32BIT && !TARGET_NEON"
2f9b23e3 1014 "#" ; "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
1015 "&& reload_completed"
1016 [(parallel [(set (reg:CC CC_REGNUM)
1017 (compare:CC (match_dup 1) (match_dup 2)))
1018 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1019 (set (match_dup 3) (minus:SI (minus:SI (match_dup 4) (match_dup 5))
1020 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1021 {
1022 operands[3] = gen_highpart (SImode, operands[0]);
1023 operands[0] = gen_lowpart (SImode, operands[0]);
1024 operands[4] = gen_highpart (SImode, operands[1]);
1025 operands[1] = gen_lowpart (SImode, operands[1]);
1026 operands[5] = gen_highpart (SImode, operands[2]);
1027 operands[2] = gen_lowpart (SImode, operands[2]);
1028 }
cffb2a26 1029 [(set_attr "conds" "clob")
1b7da4ac 1030 (set_attr "length" "8")
1031 (set_attr "type" "multiple")]
cffb2a26 1032)
1033
2f9b23e3 1034(define_insn_and_split "*subdi_di_zesidi"
cffb2a26 1035 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 1036 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r")
9c08d1fa 1037 (zero_extend:DI
cffb2a26 1038 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 1039 (clobber (reg:CC CC_REGNUM))]
25f905c2 1040 "TARGET_32BIT"
2f9b23e3 1041 "#" ; "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
1042 "&& reload_completed"
1043 [(parallel [(set (reg:CC CC_REGNUM)
1044 (compare:CC (match_dup 1) (match_dup 2)))
1045 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1046 (set (match_dup 3) (minus:SI (plus:SI (match_dup 4) (match_dup 5))
1047 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1048 {
1049 operands[3] = gen_highpart (SImode, operands[0]);
1050 operands[0] = gen_lowpart (SImode, operands[0]);
1051 operands[4] = gen_highpart (SImode, operands[1]);
1052 operands[1] = gen_lowpart (SImode, operands[1]);
1053 operands[5] = GEN_INT (~0);
1054 }
cffb2a26 1055 [(set_attr "conds" "clob")
1b7da4ac 1056 (set_attr "length" "8")
1057 (set_attr "type" "multiple")]
cffb2a26 1058)
9c08d1fa 1059
2f9b23e3 1060(define_insn_and_split "*subdi_di_sesidi"
cffb2a26 1061 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 1062 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r")
9c08d1fa 1063 (sign_extend:DI
cffb2a26 1064 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 1065 (clobber (reg:CC CC_REGNUM))]
25f905c2 1066 "TARGET_32BIT"
2f9b23e3 1067 "#" ; "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
1068 "&& reload_completed"
1069 [(parallel [(set (reg:CC CC_REGNUM)
1070 (compare:CC (match_dup 1) (match_dup 2)))
1071 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1072 (set (match_dup 3) (minus:SI (minus:SI (match_dup 4)
1073 (ashiftrt:SI (match_dup 2)
1074 (const_int 31)))
1075 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1076 {
1077 operands[3] = gen_highpart (SImode, operands[0]);
1078 operands[0] = gen_lowpart (SImode, operands[0]);
1079 operands[4] = gen_highpart (SImode, operands[1]);
1080 operands[1] = gen_lowpart (SImode, operands[1]);
1081 }
cffb2a26 1082 [(set_attr "conds" "clob")
1b7da4ac 1083 (set_attr "length" "8")
1084 (set_attr "type" "multiple")]
cffb2a26 1085)
9c08d1fa 1086
2f9b23e3 1087(define_insn_and_split "*subdi_zesidi_di"
cffb2a26 1088 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1089 (minus:DI (zero_extend:DI
cffb2a26 1090 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 1091 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 1092 (clobber (reg:CC CC_REGNUM))]
cffb2a26 1093 "TARGET_ARM"
2f9b23e3 1094 "#" ; "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
1095 ; is equivalent to:
1096 ; "subs\\t%Q0, %2, %Q1\;rsc\\t%R0, %R1, #0"
1097 "&& reload_completed"
1098 [(parallel [(set (reg:CC CC_REGNUM)
1099 (compare:CC (match_dup 2) (match_dup 1)))
1100 (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))])
1101 (set (match_dup 3) (minus:SI (minus:SI (const_int 0) (match_dup 4))
1102 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1103 {
1104 operands[3] = gen_highpart (SImode, operands[0]);
1105 operands[0] = gen_lowpart (SImode, operands[0]);
1106 operands[4] = gen_highpart (SImode, operands[1]);
1107 operands[1] = gen_lowpart (SImode, operands[1]);
1108 }
cffb2a26 1109 [(set_attr "conds" "clob")
1b7da4ac 1110 (set_attr "length" "8")
1111 (set_attr "type" "multiple")]
cffb2a26 1112)
9c08d1fa 1113
2f9b23e3 1114(define_insn_and_split "*subdi_sesidi_di"
cffb2a26 1115 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1116 (minus:DI (sign_extend:DI
cffb2a26 1117 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 1118 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 1119 (clobber (reg:CC CC_REGNUM))]
cffb2a26 1120 "TARGET_ARM"
2f9b23e3 1121 "#" ; "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
1122 ; is equivalent to:
1123 ; "subs\\t%Q0, %2, %Q1\;rsc\\t%R0, %R1, %2, asr #31"
1124 "&& reload_completed"
1125 [(parallel [(set (reg:CC CC_REGNUM)
1126 (compare:CC (match_dup 2) (match_dup 1)))
1127 (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))])
1128 (set (match_dup 3) (minus:SI (minus:SI
1129 (ashiftrt:SI (match_dup 2)
1130 (const_int 31))
1131 (match_dup 4))
1132 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1133 {
1134 operands[3] = gen_highpart (SImode, operands[0]);
1135 operands[0] = gen_lowpart (SImode, operands[0]);
1136 operands[4] = gen_highpart (SImode, operands[1]);
1137 operands[1] = gen_lowpart (SImode, operands[1]);
1138 }
cffb2a26 1139 [(set_attr "conds" "clob")
1b7da4ac 1140 (set_attr "length" "8")
1141 (set_attr "type" "multiple")]
cffb2a26 1142)
9c08d1fa 1143
2f9b23e3 1144(define_insn_and_split "*subdi_zesidi_zesidi"
cffb2a26 1145 [(set (match_operand:DI 0 "s_register_operand" "=r")
9c08d1fa 1146 (minus:DI (zero_extend:DI
cffb2a26 1147 (match_operand:SI 1 "s_register_operand" "r"))
9c08d1fa 1148 (zero_extend:DI
cffb2a26 1149 (match_operand:SI 2 "s_register_operand" "r"))))
bd5b4116 1150 (clobber (reg:CC CC_REGNUM))]
25f905c2 1151 "TARGET_32BIT"
2f9b23e3 1152 "#" ; "subs\\t%Q0, %1, %2\;sbc\\t%R0, %1, %1"
1153 "&& reload_completed"
1154 [(parallel [(set (reg:CC CC_REGNUM)
1155 (compare:CC (match_dup 1) (match_dup 2)))
1156 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1157 (set (match_dup 3) (minus:SI (minus:SI (match_dup 1) (match_dup 1))
1158 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1159 {
1160 operands[3] = gen_highpart (SImode, operands[0]);
1161 operands[0] = gen_lowpart (SImode, operands[0]);
1162 }
cffb2a26 1163 [(set_attr "conds" "clob")
1b7da4ac 1164 (set_attr "length" "8")
1165 (set_attr "type" "multiple")]
cffb2a26 1166)
b11cae9e 1167
87b22bf7 1168(define_expand "subsi3"
cffb2a26 1169 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 1170 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
1171 (match_operand:SI 2 "s_register_operand" "")))]
cffb2a26 1172 "TARGET_EITHER"
87b22bf7 1173 "
0438d37f 1174 if (CONST_INT_P (operands[1]))
87b22bf7 1175 {
25f905c2 1176 if (TARGET_32BIT)
cffb2a26 1177 {
96f57e36 1178 arm_split_constant (MINUS, SImode, NULL_RTX,
1179 INTVAL (operands[1]), operands[0],
e1ba4a27 1180 operands[2], optimize && can_create_pseudo_p ());
cffb2a26 1181 DONE;
1182 }
25f905c2 1183 else /* TARGET_THUMB1 */
cffb2a26 1184 operands[1] = force_reg (SImode, operands[1]);
87b22bf7 1185 }
cffb2a26 1186 "
1187)
87b22bf7 1188
25f905c2 1189; ??? Check Thumb-2 split length
a0f94409 1190(define_insn_and_split "*arm_subsi3_insn"
7c36fe71 1191 [(set (match_operand:SI 0 "s_register_operand" "=l,l ,l ,l ,r ,r,r,rk,r")
1192 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "l ,0 ,l ,Pz,rI,r,r,k ,?n")
1193 (match_operand:SI 2 "reg_or_int_operand" "l ,Py,Pd,l ,r ,I,r,r ,r")))]
25f905c2 1194 "TARGET_32BIT"
e2348bcb 1195 "@
7c36fe71 1196 sub%?\\t%0, %1, %2
1197 sub%?\\t%0, %2
1198 sub%?\\t%0, %1, %2
1199 rsb%?\\t%0, %2, %1
87b22bf7 1200 rsb%?\\t%0, %2, %1
aaa37ad6 1201 sub%?\\t%0, %1, %2
080c0b9a 1202 sub%?\\t%0, %1, %2
65f68e55 1203 sub%?\\t%0, %1, %2
87b22bf7 1204 #"
0438d37f 1205 "&& (CONST_INT_P (operands[1])
91a5e339 1206 && !const_ok_for_arm (INTVAL (operands[1])))"
87b22bf7 1207 [(clobber (const_int 0))]
1208 "
96f57e36 1209 arm_split_constant (MINUS, SImode, curr_insn,
1210 INTVAL (operands[1]), operands[0], operands[2], 0);
87b22bf7 1211 DONE;
cffb2a26 1212 "
7c36fe71 1213 [(set_attr "length" "4,4,4,4,4,4,4,4,16")
1214 (set_attr "arch" "t2,t2,t2,t2,*,*,*,*,*")
65f68e55 1215 (set_attr "predicable" "yes")
7c36fe71 1216 (set_attr "predicable_short_it" "yes,yes,yes,yes,no,no,no,no,no")
112eda6f 1217 (set_attr "type" "alu_sreg,alu_sreg,alu_sreg,alu_sreg,alu_imm,alu_imm,alu_sreg,alu_sreg,multiple")]
a0f94409 1218)
1219
1220(define_peephole2
1221 [(match_scratch:SI 3 "r")
372575c7 1222 (set (match_operand:SI 0 "arm_general_register_operand" "")
a0f94409 1223 (minus:SI (match_operand:SI 1 "const_int_operand" "")
372575c7 1224 (match_operand:SI 2 "arm_general_register_operand" "")))]
25f905c2 1225 "TARGET_32BIT
a0f94409 1226 && !const_ok_for_arm (INTVAL (operands[1]))
1227 && const_ok_for_arm (~INTVAL (operands[1]))"
1228 [(set (match_dup 3) (match_dup 1))
1229 (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1230 ""
cffb2a26 1231)
b11cae9e 1232
f7fbdd4a 1233(define_insn "*subsi3_compare0"
bd5b4116 1234 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1235 (compare:CC_NOOV
65f68e55 1236 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,r,I")
1237 (match_operand:SI 2 "arm_rhs_operand" "I,r,r"))
215b30b3 1238 (const_int 0)))
65f68e55 1239 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9c08d1fa 1240 (minus:SI (match_dup 1) (match_dup 2)))]
25f905c2 1241 "TARGET_32BIT"
e2348bcb 1242 "@
65f68e55 1243 sub%.\\t%0, %1, %2
25f905c2 1244 sub%.\\t%0, %1, %2
1245 rsb%.\\t%0, %2, %1"
65f68e55 1246 [(set_attr "conds" "set")
112eda6f 1247 (set_attr "type" "alus_imm,alus_sreg,alus_sreg")]
cffb2a26 1248)
9c08d1fa 1249
190efb17 1250(define_insn "subsi3_compare"
080c0b9a 1251 [(set (reg:CC CC_REGNUM)
65f68e55 1252 (compare:CC (match_operand:SI 1 "arm_rhs_operand" "r,r,I")
1253 (match_operand:SI 2 "arm_rhs_operand" "I,r,r")))
1254 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2df9477b 1255 (minus:SI (match_dup 1) (match_dup 2)))]
1256 "TARGET_32BIT"
1257 "@
65f68e55 1258 sub%.\\t%0, %1, %2
2df9477b 1259 sub%.\\t%0, %1, %2
1260 rsb%.\\t%0, %2, %1"
65f68e55 1261 [(set_attr "conds" "set")
112eda6f 1262 (set_attr "type" "alus_imm,alus_sreg,alus_sreg")]
2df9477b 1263)
1264
604f3a0a 1265(define_expand "subsf3"
1266 [(set (match_operand:SF 0 "s_register_operand" "")
d86c91f6 1267 (minus:SF (match_operand:SF 1 "s_register_operand" "")
1268 (match_operand:SF 2 "s_register_operand" "")))]
25f905c2 1269 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1270 "
604f3a0a 1271")
1272
604f3a0a 1273(define_expand "subdf3"
1274 [(set (match_operand:DF 0 "s_register_operand" "")
d86c91f6 1275 (minus:DF (match_operand:DF 1 "s_register_operand" "")
1276 (match_operand:DF 2 "s_register_operand" "")))]
a50d7267 1277 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 1278 "
604f3a0a 1279")
1280
b11cae9e 1281\f
1282;; Multiplication insns
1283
4422d91f 1284(define_expand "mulhi3"
1285 [(set (match_operand:HI 0 "s_register_operand" "")
1286 (mult:HI (match_operand:HI 1 "s_register_operand" "")
1287 (match_operand:HI 2 "s_register_operand" "")))]
1288 "TARGET_DSP_MULTIPLY"
1289 "
1290 {
1291 rtx result = gen_reg_rtx (SImode);
1292 emit_insn (gen_mulhisi3 (result, operands[1], operands[2]));
1293 emit_move_insn (operands[0], gen_lowpart (HImode, result));
1294 DONE;
1295 }"
1296)
1297
cffb2a26 1298(define_expand "mulsi3"
1299 [(set (match_operand:SI 0 "s_register_operand" "")
1300 (mult:SI (match_operand:SI 2 "s_register_operand" "")
1301 (match_operand:SI 1 "s_register_operand" "")))]
1302 "TARGET_EITHER"
1303 ""
1304)
1305
9c08d1fa 1306;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
cffb2a26 1307(define_insn "*arm_mulsi3"
1308 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1309 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1310 (match_operand:SI 1 "s_register_operand" "%0,r")))]
58d7d654 1311 "TARGET_32BIT && !arm_arch6"
f7fbdd4a 1312 "mul%?\\t%0, %2, %1"
9da0ec36 1313 [(set_attr "type" "mul")
0d66636f 1314 (set_attr "predicable" "yes")]
cffb2a26 1315)
1316
58d7d654 1317(define_insn "*arm_mulsi3_v6"
d952d547 1318 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
1319 (mult:SI (match_operand:SI 1 "s_register_operand" "0,l,r")
1320 (match_operand:SI 2 "s_register_operand" "l,0,r")))]
58d7d654 1321 "TARGET_32BIT && arm_arch6"
1322 "mul%?\\t%0, %1, %2"
9da0ec36 1323 [(set_attr "type" "mul")
d952d547 1324 (set_attr "predicable" "yes")
1325 (set_attr "arch" "t2,t2,*")
1326 (set_attr "length" "4")
1327 (set_attr "predicable_short_it" "yes,yes,no")]
58d7d654 1328)
1329
f7fbdd4a 1330(define_insn "*mulsi3_compare0"
bd5b4116 1331 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1332 (compare:CC_NOOV (mult:SI
1333 (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1334 (match_operand:SI 1 "s_register_operand" "%0,r"))
9c08d1fa 1335 (const_int 0)))
1336 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1337 (mult:SI (match_dup 2) (match_dup 1)))]
58d7d654 1338 "TARGET_ARM && !arm_arch6"
1339 "mul%.\\t%0, %2, %1"
1340 [(set_attr "conds" "set")
9da0ec36 1341 (set_attr "type" "muls")]
58d7d654 1342)
1343
1344(define_insn "*mulsi3_compare0_v6"
1345 [(set (reg:CC_NOOV CC_REGNUM)
1346 (compare:CC_NOOV (mult:SI
1347 (match_operand:SI 2 "s_register_operand" "r")
1348 (match_operand:SI 1 "s_register_operand" "r"))
1349 (const_int 0)))
1350 (set (match_operand:SI 0 "s_register_operand" "=r")
1351 (mult:SI (match_dup 2) (match_dup 1)))]
1352 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1353 "mul%.\\t%0, %2, %1"
cffb2a26 1354 [(set_attr "conds" "set")
9da0ec36 1355 (set_attr "type" "muls")]
cffb2a26 1356)
9c08d1fa 1357
f7fbdd4a 1358(define_insn "*mulsi_compare0_scratch"
bd5b4116 1359 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1360 (compare:CC_NOOV (mult:SI
1361 (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1362 (match_operand:SI 1 "s_register_operand" "%0,r"))
9c08d1fa 1363 (const_int 0)))
1364 (clobber (match_scratch:SI 0 "=&r,&r"))]
58d7d654 1365 "TARGET_ARM && !arm_arch6"
1366 "mul%.\\t%0, %2, %1"
1367 [(set_attr "conds" "set")
9da0ec36 1368 (set_attr "type" "muls")]
58d7d654 1369)
1370
1371(define_insn "*mulsi_compare0_scratch_v6"
1372 [(set (reg:CC_NOOV CC_REGNUM)
1373 (compare:CC_NOOV (mult:SI
1374 (match_operand:SI 2 "s_register_operand" "r")
1375 (match_operand:SI 1 "s_register_operand" "r"))
1376 (const_int 0)))
1377 (clobber (match_scratch:SI 0 "=r"))]
1378 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1379 "mul%.\\t%0, %2, %1"
cffb2a26 1380 [(set_attr "conds" "set")
9da0ec36 1381 (set_attr "type" "muls")]
cffb2a26 1382)
9c08d1fa 1383
b11cae9e 1384;; Unnamed templates to match MLA instruction.
1385
f7fbdd4a 1386(define_insn "*mulsi3addsi"
9c08d1fa 1387 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
c8f69309 1388 (plus:SI
9c08d1fa 1389 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1390 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1391 (match_operand:SI 3 "s_register_operand" "r,r,0,0")))]
58d7d654 1392 "TARGET_32BIT && !arm_arch6"
1393 "mla%?\\t%0, %2, %1, %3"
9da0ec36 1394 [(set_attr "type" "mla")
58d7d654 1395 (set_attr "predicable" "yes")]
1396)
1397
1398(define_insn "*mulsi3addsi_v6"
1399 [(set (match_operand:SI 0 "s_register_operand" "=r")
1400 (plus:SI
1401 (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1402 (match_operand:SI 1 "s_register_operand" "r"))
1403 (match_operand:SI 3 "s_register_operand" "r")))]
1404 "TARGET_32BIT && arm_arch6"
f7fbdd4a 1405 "mla%?\\t%0, %2, %1, %3"
9da0ec36 1406 [(set_attr "type" "mla")
d952d547 1407 (set_attr "predicable" "yes")
1408 (set_attr "predicable_short_it" "no")]
0d66636f 1409)
b11cae9e 1410
f7fbdd4a 1411(define_insn "*mulsi3addsi_compare0"
bd5b4116 1412 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1413 (compare:CC_NOOV
1414 (plus:SI (mult:SI
1415 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1416 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1417 (match_operand:SI 3 "s_register_operand" "r,r,0,0"))
215b30b3 1418 (const_int 0)))
9c08d1fa 1419 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1420 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1421 (match_dup 3)))]
58d7d654 1422 "TARGET_ARM && arm_arch6"
1423 "mla%.\\t%0, %2, %1, %3"
1424 [(set_attr "conds" "set")
9da0ec36 1425 (set_attr "type" "mlas")]
58d7d654 1426)
1427
1428(define_insn "*mulsi3addsi_compare0_v6"
1429 [(set (reg:CC_NOOV CC_REGNUM)
1430 (compare:CC_NOOV
1431 (plus:SI (mult:SI
1432 (match_operand:SI 2 "s_register_operand" "r")
1433 (match_operand:SI 1 "s_register_operand" "r"))
1434 (match_operand:SI 3 "s_register_operand" "r"))
1435 (const_int 0)))
1436 (set (match_operand:SI 0 "s_register_operand" "=r")
1437 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1438 (match_dup 3)))]
1439 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1440 "mla%.\\t%0, %2, %1, %3"
0d66636f 1441 [(set_attr "conds" "set")
9da0ec36 1442 (set_attr "type" "mlas")]
0d66636f 1443)
9c08d1fa 1444
f7fbdd4a 1445(define_insn "*mulsi3addsi_compare0_scratch"
bd5b4116 1446 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1447 (compare:CC_NOOV
1448 (plus:SI (mult:SI
1449 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1450 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
215b30b3 1451 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1452 (const_int 0)))
9c08d1fa 1453 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
58d7d654 1454 "TARGET_ARM && !arm_arch6"
1455 "mla%.\\t%0, %2, %1, %3"
1456 [(set_attr "conds" "set")
9da0ec36 1457 (set_attr "type" "mlas")]
58d7d654 1458)
1459
1460(define_insn "*mulsi3addsi_compare0_scratch_v6"
1461 [(set (reg:CC_NOOV CC_REGNUM)
1462 (compare:CC_NOOV
1463 (plus:SI (mult:SI
1464 (match_operand:SI 2 "s_register_operand" "r")
1465 (match_operand:SI 1 "s_register_operand" "r"))
1466 (match_operand:SI 3 "s_register_operand" "r"))
1467 (const_int 0)))
1468 (clobber (match_scratch:SI 0 "=r"))]
1469 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1470 "mla%.\\t%0, %2, %1, %3"
cffb2a26 1471 [(set_attr "conds" "set")
9da0ec36 1472 (set_attr "type" "mlas")]
cffb2a26 1473)
f7fbdd4a 1474
89545238 1475(define_insn "*mulsi3subsi"
1476 [(set (match_operand:SI 0 "s_register_operand" "=r")
1477 (minus:SI
1478 (match_operand:SI 3 "s_register_operand" "r")
1479 (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1480 (match_operand:SI 1 "s_register_operand" "r"))))]
1481 "TARGET_32BIT && arm_arch_thumb2"
1482 "mls%?\\t%0, %2, %1, %3"
9da0ec36 1483 [(set_attr "type" "mla")
d952d547 1484 (set_attr "predicable" "yes")
1485 (set_attr "predicable_short_it" "no")]
89545238 1486)
1487
5cdca009 1488(define_expand "maddsidi4"
1489 [(set (match_operand:DI 0 "s_register_operand" "")
1490 (plus:DI
1491 (mult:DI
1492 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1493 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1494 (match_operand:DI 3 "s_register_operand" "")))]
1495 "TARGET_32BIT && arm_arch3m"
1496 "")
82b85d08 1497
1498(define_insn "*mulsidi3adddi"
fe8dbf85 1499 [(set (match_operand:DI 0 "s_register_operand" "=&r")
82b85d08 1500 (plus:DI
215b30b3 1501 (mult:DI
fe8dbf85 1502 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1503 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1504 (match_operand:DI 1 "s_register_operand" "0")))]
58d7d654 1505 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1506 "smlal%?\\t%Q0, %R0, %3, %2"
9da0ec36 1507 [(set_attr "type" "smlal")
58d7d654 1508 (set_attr "predicable" "yes")]
1509)
1510
1511(define_insn "*mulsidi3adddi_v6"
1512 [(set (match_operand:DI 0 "s_register_operand" "=r")
1513 (plus:DI
1514 (mult:DI
1515 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1516 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1517 (match_operand:DI 1 "s_register_operand" "0")))]
1518 "TARGET_32BIT && arm_arch6"
fe8dbf85 1519 "smlal%?\\t%Q0, %R0, %3, %2"
9da0ec36 1520 [(set_attr "type" "smlal")
d952d547 1521 (set_attr "predicable" "yes")
1522 (set_attr "predicable_short_it" "no")]
0d66636f 1523)
82b85d08 1524
957788b0 1525;; 32x32->64 widening multiply.
1526;; As with mulsi3, the only difference between the v3-5 and v6+
1527;; versions of these patterns is the requirement that the output not
1528;; overlap the inputs, but that still means we have to have a named
1529;; expander and two different starred insns.
1530
1531(define_expand "mulsidi3"
1532 [(set (match_operand:DI 0 "s_register_operand" "")
1533 (mult:DI
1534 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1535 (sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1536 "TARGET_32BIT && arm_arch3m"
1537 ""
1538)
1539
1540(define_insn "*mulsidi3_nov6"
f7fbdd4a 1541 [(set (match_operand:DI 0 "s_register_operand" "=&r")
215b30b3 1542 (mult:DI
1543 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1544 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
58d7d654 1545 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1546 "smull%?\\t%Q0, %R0, %1, %2"
9da0ec36 1547 [(set_attr "type" "smull")
58d7d654 1548 (set_attr "predicable" "yes")]
1549)
1550
957788b0 1551(define_insn "*mulsidi3_v6"
58d7d654 1552 [(set (match_operand:DI 0 "s_register_operand" "=r")
1553 (mult:DI
1554 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1555 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1556 "TARGET_32BIT && arm_arch6"
97499065 1557 "smull%?\\t%Q0, %R0, %1, %2"
9da0ec36 1558 [(set_attr "type" "smull")
d952d547 1559 (set_attr "predicable" "yes")
1560 (set_attr "predicable_short_it" "no")]
0d66636f 1561)
f7fbdd4a 1562
957788b0 1563(define_expand "umulsidi3"
1564 [(set (match_operand:DI 0 "s_register_operand" "")
1565 (mult:DI
1566 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1567 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1568 "TARGET_32BIT && arm_arch3m"
1569 ""
1570)
1571
1572(define_insn "*umulsidi3_nov6"
f7fbdd4a 1573 [(set (match_operand:DI 0 "s_register_operand" "=&r")
215b30b3 1574 (mult:DI
1575 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1576 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
58d7d654 1577 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1578 "umull%?\\t%Q0, %R0, %1, %2"
9da0ec36 1579 [(set_attr "type" "umull")
58d7d654 1580 (set_attr "predicable" "yes")]
1581)
1582
957788b0 1583(define_insn "*umulsidi3_v6"
58d7d654 1584 [(set (match_operand:DI 0 "s_register_operand" "=r")
1585 (mult:DI
1586 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1587 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1588 "TARGET_32BIT && arm_arch6"
97499065 1589 "umull%?\\t%Q0, %R0, %1, %2"
9da0ec36 1590 [(set_attr "type" "umull")
d952d547 1591 (set_attr "predicable" "yes")
1592 (set_attr "predicable_short_it" "no")]
0d66636f 1593)
b11cae9e 1594
5cdca009 1595(define_expand "umaddsidi4"
1596 [(set (match_operand:DI 0 "s_register_operand" "")
1597 (plus:DI
1598 (mult:DI
1599 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1600 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1601 (match_operand:DI 3 "s_register_operand" "")))]
1602 "TARGET_32BIT && arm_arch3m"
1603 "")
82b85d08 1604
1605(define_insn "*umulsidi3adddi"
8ead09f9 1606 [(set (match_operand:DI 0 "s_register_operand" "=&r")
82b85d08 1607 (plus:DI
215b30b3 1608 (mult:DI
fe8dbf85 1609 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1610 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1611 (match_operand:DI 1 "s_register_operand" "0")))]
58d7d654 1612 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1613 "umlal%?\\t%Q0, %R0, %3, %2"
9da0ec36 1614 [(set_attr "type" "umlal")
58d7d654 1615 (set_attr "predicable" "yes")]
1616)
1617
1618(define_insn "*umulsidi3adddi_v6"
1619 [(set (match_operand:DI 0 "s_register_operand" "=r")
1620 (plus:DI
1621 (mult:DI
1622 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1623 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1624 (match_operand:DI 1 "s_register_operand" "0")))]
1625 "TARGET_32BIT && arm_arch6"
fe8dbf85 1626 "umlal%?\\t%Q0, %R0, %3, %2"
9da0ec36 1627 [(set_attr "type" "umlal")
d952d547 1628 (set_attr "predicable" "yes")
1629 (set_attr "predicable_short_it" "no")]
0d66636f 1630)
82b85d08 1631
957788b0 1632(define_expand "smulsi3_highpart"
1633 [(parallel
1634 [(set (match_operand:SI 0 "s_register_operand" "")
1635 (truncate:SI
1636 (lshiftrt:DI
1637 (mult:DI
1638 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1639 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1640 (const_int 32))))
1641 (clobber (match_scratch:SI 3 ""))])]
1642 "TARGET_32BIT && arm_arch3m"
1643 ""
1644)
1645
1646(define_insn "*smulsi3_highpart_nov6"
f082f1c4 1647 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1648 (truncate:SI
1649 (lshiftrt:DI
215b30b3 1650 (mult:DI
e5fea38e 1651 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
215b30b3 1652 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
f082f1c4 1653 (const_int 32))))
1654 (clobber (match_scratch:SI 3 "=&r,&r"))]
58d7d654 1655 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1656 "smull%?\\t%3, %0, %2, %1"
9da0ec36 1657 [(set_attr "type" "smull")
58d7d654 1658 (set_attr "predicable" "yes")]
1659)
1660
957788b0 1661(define_insn "*smulsi3_highpart_v6"
58d7d654 1662 [(set (match_operand:SI 0 "s_register_operand" "=r")
1663 (truncate:SI
1664 (lshiftrt:DI
1665 (mult:DI
1666 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1667 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1668 (const_int 32))))
1669 (clobber (match_scratch:SI 3 "=r"))]
1670 "TARGET_32BIT && arm_arch6"
f082f1c4 1671 "smull%?\\t%3, %0, %2, %1"
9da0ec36 1672 [(set_attr "type" "smull")
d952d547 1673 (set_attr "predicable" "yes")
1674 (set_attr "predicable_short_it" "no")]
cffb2a26 1675)
f082f1c4 1676
957788b0 1677(define_expand "umulsi3_highpart"
1678 [(parallel
1679 [(set (match_operand:SI 0 "s_register_operand" "")
1680 (truncate:SI
1681 (lshiftrt:DI
1682 (mult:DI
1683 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1684 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1685 (const_int 32))))
1686 (clobber (match_scratch:SI 3 ""))])]
1687 "TARGET_32BIT && arm_arch3m"
1688 ""
1689)
1690
1691(define_insn "*umulsi3_highpart_nov6"
f082f1c4 1692 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1693 (truncate:SI
1694 (lshiftrt:DI
215b30b3 1695 (mult:DI
e5fea38e 1696 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
215b30b3 1697 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
f082f1c4 1698 (const_int 32))))
1699 (clobber (match_scratch:SI 3 "=&r,&r"))]
58d7d654 1700 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1701 "umull%?\\t%3, %0, %2, %1"
9da0ec36 1702 [(set_attr "type" "umull")
58d7d654 1703 (set_attr "predicable" "yes")]
1704)
1705
957788b0 1706(define_insn "*umulsi3_highpart_v6"
58d7d654 1707 [(set (match_operand:SI 0 "s_register_operand" "=r")
1708 (truncate:SI
1709 (lshiftrt:DI
1710 (mult:DI
1711 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1712 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1713 (const_int 32))))
1714 (clobber (match_scratch:SI 3 "=r"))]
1715 "TARGET_32BIT && arm_arch6"
f082f1c4 1716 "umull%?\\t%3, %0, %2, %1"
9da0ec36 1717 [(set_attr "type" "umull")
d952d547 1718 (set_attr "predicable" "yes")
1719 (set_attr "predicable_short_it" "no")]
cffb2a26 1720)
f082f1c4 1721
331beb1a 1722(define_insn "mulhisi3"
1723 [(set (match_operand:SI 0 "s_register_operand" "=r")
1724 (mult:SI (sign_extend:SI
1725 (match_operand:HI 1 "s_register_operand" "%r"))
1726 (sign_extend:SI
1727 (match_operand:HI 2 "s_register_operand" "r"))))]
25f905c2 1728 "TARGET_DSP_MULTIPLY"
61a2d04c 1729 "smulbb%?\\t%0, %1, %2"
9da0ec36 1730 [(set_attr "type" "smulxy")
fec538d9 1731 (set_attr "predicable" "yes")]
1732)
1733
1734(define_insn "*mulhisi3tb"
1735 [(set (match_operand:SI 0 "s_register_operand" "=r")
1736 (mult:SI (ashiftrt:SI
1737 (match_operand:SI 1 "s_register_operand" "r")
1738 (const_int 16))
1739 (sign_extend:SI
1740 (match_operand:HI 2 "s_register_operand" "r"))))]
25f905c2 1741 "TARGET_DSP_MULTIPLY"
fec538d9 1742 "smultb%?\\t%0, %1, %2"
9da0ec36 1743 [(set_attr "type" "smulxy")
d952d547 1744 (set_attr "predicable" "yes")
1745 (set_attr "predicable_short_it" "no")]
fec538d9 1746)
1747
1748(define_insn "*mulhisi3bt"
1749 [(set (match_operand:SI 0 "s_register_operand" "=r")
1750 (mult:SI (sign_extend:SI
1751 (match_operand:HI 1 "s_register_operand" "r"))
1752 (ashiftrt:SI
1753 (match_operand:SI 2 "s_register_operand" "r")
1754 (const_int 16))))]
25f905c2 1755 "TARGET_DSP_MULTIPLY"
fec538d9 1756 "smulbt%?\\t%0, %1, %2"
9da0ec36 1757 [(set_attr "type" "smulxy")
d952d547 1758 (set_attr "predicable" "yes")
1759 (set_attr "predicable_short_it" "no")]
fec538d9 1760)
1761
1762(define_insn "*mulhisi3tt"
1763 [(set (match_operand:SI 0 "s_register_operand" "=r")
1764 (mult:SI (ashiftrt:SI
1765 (match_operand:SI 1 "s_register_operand" "r")
1766 (const_int 16))
1767 (ashiftrt:SI
1768 (match_operand:SI 2 "s_register_operand" "r")
1769 (const_int 16))))]
25f905c2 1770 "TARGET_DSP_MULTIPLY"
fec538d9 1771 "smultt%?\\t%0, %1, %2"
9da0ec36 1772 [(set_attr "type" "smulxy")
d952d547 1773 (set_attr "predicable" "yes")
1774 (set_attr "predicable_short_it" "no")]
331beb1a 1775)
1776
5cdca009 1777(define_insn "maddhisi4"
331beb1a 1778 [(set (match_operand:SI 0 "s_register_operand" "=r")
cfa6c608 1779 (plus:SI (mult:SI (sign_extend:SI
1780 (match_operand:HI 1 "s_register_operand" "r"))
331beb1a 1781 (sign_extend:SI
cfa6c608 1782 (match_operand:HI 2 "s_register_operand" "r")))
1783 (match_operand:SI 3 "s_register_operand" "r")))]
25f905c2 1784 "TARGET_DSP_MULTIPLY"
5cdca009 1785 "smlabb%?\\t%0, %1, %2, %3"
9da0ec36 1786 [(set_attr "type" "smlaxy")
d952d547 1787 (set_attr "predicable" "yes")
1788 (set_attr "predicable_short_it" "no")]
331beb1a 1789)
1790
9a92f368 1791;; Note: there is no maddhisi4ibt because this one is canonical form
1792(define_insn "*maddhisi4tb"
1793 [(set (match_operand:SI 0 "s_register_operand" "=r")
1794 (plus:SI (mult:SI (ashiftrt:SI
1795 (match_operand:SI 1 "s_register_operand" "r")
1796 (const_int 16))
1797 (sign_extend:SI
1798 (match_operand:HI 2 "s_register_operand" "r")))
1799 (match_operand:SI 3 "s_register_operand" "r")))]
1800 "TARGET_DSP_MULTIPLY"
1801 "smlatb%?\\t%0, %1, %2, %3"
9da0ec36 1802 [(set_attr "type" "smlaxy")
d952d547 1803 (set_attr "predicable" "yes")
1804 (set_attr "predicable_short_it" "no")]
9a92f368 1805)
1806
1807(define_insn "*maddhisi4tt"
1808 [(set (match_operand:SI 0 "s_register_operand" "=r")
1809 (plus:SI (mult:SI (ashiftrt:SI
1810 (match_operand:SI 1 "s_register_operand" "r")
1811 (const_int 16))
1812 (ashiftrt:SI
1813 (match_operand:SI 2 "s_register_operand" "r")
1814 (const_int 16)))
1815 (match_operand:SI 3 "s_register_operand" "r")))]
1816 "TARGET_DSP_MULTIPLY"
1817 "smlatt%?\\t%0, %1, %2, %3"
9da0ec36 1818 [(set_attr "type" "smlaxy")
d952d547 1819 (set_attr "predicable" "yes")
1820 (set_attr "predicable_short_it" "no")]
9a92f368 1821)
1822
aff5fb4d 1823(define_insn "maddhidi4"
331beb1a 1824 [(set (match_operand:DI 0 "s_register_operand" "=r")
1825 (plus:DI
331beb1a 1826 (mult:DI (sign_extend:DI
d952d547 1827 (match_operand:HI 1 "s_register_operand" "r"))
331beb1a 1828 (sign_extend:DI
cfa6c608 1829 (match_operand:HI 2 "s_register_operand" "r")))
1830 (match_operand:DI 3 "s_register_operand" "0")))]
25f905c2 1831 "TARGET_DSP_MULTIPLY"
5cdca009 1832 "smlalbb%?\\t%Q0, %R0, %1, %2"
9da0ec36 1833 [(set_attr "type" "smlalxy")
d952d547 1834 (set_attr "predicable" "yes")
1835 (set_attr "predicable_short_it" "no")])
331beb1a 1836
9a92f368 1837;; Note: there is no maddhidi4ibt because this one is canonical form
1838(define_insn "*maddhidi4tb"
1839 [(set (match_operand:DI 0 "s_register_operand" "=r")
1840 (plus:DI
1841 (mult:DI (sign_extend:DI
1842 (ashiftrt:SI
1843 (match_operand:SI 1 "s_register_operand" "r")
1844 (const_int 16)))
1845 (sign_extend:DI
1846 (match_operand:HI 2 "s_register_operand" "r")))
1847 (match_operand:DI 3 "s_register_operand" "0")))]
1848 "TARGET_DSP_MULTIPLY"
1849 "smlaltb%?\\t%Q0, %R0, %1, %2"
9da0ec36 1850 [(set_attr "type" "smlalxy")
d952d547 1851 (set_attr "predicable" "yes")
1852 (set_attr "predicable_short_it" "no")])
9a92f368 1853
1854(define_insn "*maddhidi4tt"
1855 [(set (match_operand:DI 0 "s_register_operand" "=r")
1856 (plus:DI
1857 (mult:DI (sign_extend:DI
1858 (ashiftrt:SI
1859 (match_operand:SI 1 "s_register_operand" "r")
1860 (const_int 16)))
1861 (sign_extend:DI
1862 (ashiftrt:SI
1863 (match_operand:SI 2 "s_register_operand" "r")
1864 (const_int 16))))
1865 (match_operand:DI 3 "s_register_operand" "0")))]
1866 "TARGET_DSP_MULTIPLY"
1867 "smlaltt%?\\t%Q0, %R0, %1, %2"
9da0ec36 1868 [(set_attr "type" "smlalxy")
d952d547 1869 (set_attr "predicable" "yes")
1870 (set_attr "predicable_short_it" "no")])
9a92f368 1871
604f3a0a 1872(define_expand "mulsf3"
1873 [(set (match_operand:SF 0 "s_register_operand" "")
1874 (mult:SF (match_operand:SF 1 "s_register_operand" "")
d86c91f6 1875 (match_operand:SF 2 "s_register_operand" "")))]
25f905c2 1876 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1877 "
604f3a0a 1878")
1879
604f3a0a 1880(define_expand "muldf3"
1881 [(set (match_operand:DF 0 "s_register_operand" "")
1882 (mult:DF (match_operand:DF 1 "s_register_operand" "")
d86c91f6 1883 (match_operand:DF 2 "s_register_operand" "")))]
a50d7267 1884 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 1885 "
604f3a0a 1886")
b11cae9e 1887\f
1888;; Division insns
1889
7db9af5d 1890(define_expand "divsf3"
1891 [(set (match_operand:SF 0 "s_register_operand" "")
d86c91f6 1892 (div:SF (match_operand:SF 1 "s_register_operand" "")
1893 (match_operand:SF 2 "s_register_operand" "")))]
994606f8 1894 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
7db9af5d 1895 "")
9c08d1fa 1896
7db9af5d 1897(define_expand "divdf3"
1898 [(set (match_operand:DF 0 "s_register_operand" "")
d86c91f6 1899 (div:DF (match_operand:DF 1 "s_register_operand" "")
1900 (match_operand:DF 2 "s_register_operand" "")))]
994606f8 1901 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
7db9af5d 1902 "")
b11cae9e 1903\f
1904;; Boolean and,ior,xor insns
1905
f6ebffac 1906;; Split up double word logical operations
1907
1908;; Split up simple DImode logical operations. Simply perform the logical
1909;; operation on the upper and lower halves of the registers.
1910(define_split
1911 [(set (match_operand:DI 0 "s_register_operand" "")
1912 (match_operator:DI 6 "logical_binary_operator"
1913 [(match_operand:DI 1 "s_register_operand" "")
1914 (match_operand:DI 2 "s_register_operand" "")]))]
25f905c2 1915 "TARGET_32BIT && reload_completed
e2669ea7 1916 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))
25f905c2 1917 && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
f6ebffac 1918 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1919 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1920 "
215b30b3 1921 {
1922 operands[3] = gen_highpart (SImode, operands[0]);
1923 operands[0] = gen_lowpart (SImode, operands[0]);
1924 operands[4] = gen_highpart (SImode, operands[1]);
1925 operands[1] = gen_lowpart (SImode, operands[1]);
1926 operands[5] = gen_highpart (SImode, operands[2]);
1927 operands[2] = gen_lowpart (SImode, operands[2]);
1928 }"
1929)
f6ebffac 1930
f6ebffac 1931(define_split
1932 [(set (match_operand:DI 0 "s_register_operand" "")
1933 (match_operator:DI 6 "logical_binary_operator"
1934 [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1935 (match_operand:DI 1 "s_register_operand" "")]))]
25f905c2 1936 "TARGET_32BIT && reload_completed"
f6ebffac 1937 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1938 (set (match_dup 3) (match_op_dup:SI 6
1939 [(ashiftrt:SI (match_dup 2) (const_int 31))
1940 (match_dup 4)]))]
1941 "
215b30b3 1942 {
1943 operands[3] = gen_highpart (SImode, operands[0]);
1944 operands[0] = gen_lowpart (SImode, operands[0]);
1945 operands[4] = gen_highpart (SImode, operands[1]);
1946 operands[1] = gen_lowpart (SImode, operands[1]);
1947 operands[5] = gen_highpart (SImode, operands[2]);
1948 operands[2] = gen_lowpart (SImode, operands[2]);
1949 }"
1950)
f6ebffac 1951
f6ebffac 1952;; The zero extend of operand 2 means we can just copy the high part of
1953;; operand1 into operand0.
1954(define_split
1955 [(set (match_operand:DI 0 "s_register_operand" "")
1956 (ior:DI
1957 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1958 (match_operand:DI 1 "s_register_operand" "")))]
25f905c2 1959 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
f6ebffac 1960 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1961 (set (match_dup 3) (match_dup 4))]
1962 "
215b30b3 1963 {
1964 operands[4] = gen_highpart (SImode, operands[1]);
1965 operands[3] = gen_highpart (SImode, operands[0]);
1966 operands[0] = gen_lowpart (SImode, operands[0]);
1967 operands[1] = gen_lowpart (SImode, operands[1]);
1968 }"
1969)
f6ebffac 1970
1971;; The zero extend of operand 2 means we can just copy the high part of
1972;; operand1 into operand0.
1973(define_split
1974 [(set (match_operand:DI 0 "s_register_operand" "")
1975 (xor:DI
1976 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1977 (match_operand:DI 1 "s_register_operand" "")))]
25f905c2 1978 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
f6ebffac 1979 [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1980 (set (match_dup 3) (match_dup 4))]
1981 "
215b30b3 1982 {
1983 operands[4] = gen_highpart (SImode, operands[1]);
1984 operands[3] = gen_highpart (SImode, operands[0]);
1985 operands[0] = gen_lowpart (SImode, operands[0]);
1986 operands[1] = gen_lowpart (SImode, operands[1]);
1987 }"
1988)
f6ebffac 1989
e2669ea7 1990(define_expand "anddi3"
1991 [(set (match_operand:DI 0 "s_register_operand" "")
1992 (and:DI (match_operand:DI 1 "s_register_operand" "")
1993 (match_operand:DI 2 "neon_inv_logic_op2" "")))]
1994 "TARGET_32BIT"
1995 ""
1996)
1997
f6bbdcf6 1998(define_insn_and_split "*anddi3_insn"
0a314dcd 1999 [(set (match_operand:DI 0 "s_register_operand" "=w,w ,&r,&r,&r,&r,?w,?w")
2000 (and:DI (match_operand:DI 1 "s_register_operand" "%w,0 ,0 ,r ,0 ,r ,w ,0")
2001 (match_operand:DI 2 "arm_anddi_operand_neon" "w ,DL,r ,r ,De,De,w ,DL")))]
f6bbdcf6 2002 "TARGET_32BIT && !TARGET_IWMMXT"
2003{
2004 switch (which_alternative)
2005 {
0a314dcd 2006 case 0: /* fall through */
2007 case 6: return "vand\t%P0, %P1, %P2";
2008 case 1: /* fall through */
2009 case 7: return neon_output_logic_immediate ("vand", &operands[2],
2010 DImode, 1, VALID_NEON_QREG_MODE (DImode));
f6bbdcf6 2011 case 2:
0a314dcd 2012 case 3:
2013 case 4:
f6bbdcf6 2014 case 5: /* fall through */
0a314dcd 2015 return "#";
f6bbdcf6 2016 default: gcc_unreachable ();
2017 }
2018}
0a314dcd 2019 "TARGET_32BIT && !TARGET_IWMMXT && reload_completed
2020 && !(IS_VFP_REGNUM (REGNO (operands[0])))"
f6bbdcf6 2021 [(set (match_dup 3) (match_dup 4))
2022 (set (match_dup 5) (match_dup 6))]
2023 "
2024 {
2025 operands[3] = gen_lowpart (SImode, operands[0]);
2026 operands[5] = gen_highpart (SImode, operands[0]);
2027
2028 operands[4] = simplify_gen_binary (AND, SImode,
2029 gen_lowpart (SImode, operands[1]),
2030 gen_lowpart (SImode, operands[2]));
2031 operands[6] = simplify_gen_binary (AND, SImode,
2032 gen_highpart (SImode, operands[1]),
2033 gen_highpart_mode (SImode, DImode, operands[2]));
2034
2035 }"
32093010 2036 [(set_attr "type" "neon_logic,neon_logic,multiple,multiple,\
2037 multiple,multiple,neon_logic,neon_logic")
0a314dcd 2038 (set_attr "arch" "neon_for_64bits,neon_for_64bits,*,*,*,*,
f6bbdcf6 2039 avoid_neon_for_64bits,avoid_neon_for_64bits")
0a314dcd 2040 (set_attr "length" "*,*,8,8,8,8,*,*")
2041 ]
215b30b3 2042)
b11cae9e 2043
a0f94409 2044(define_insn_and_split "*anddi_zesidi_di"
9c08d1fa 2045 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2046 (and:DI (zero_extend:DI
2047 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 2048 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2049 "TARGET_32BIT"
f6ebffac 2050 "#"
25f905c2 2051 "TARGET_32BIT && reload_completed"
a0f94409 2052 ; The zero extend of operand 2 clears the high word of the output
2053 ; operand.
2054 [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
2055 (set (match_dup 3) (const_int 0))]
2056 "
2057 {
2058 operands[3] = gen_highpart (SImode, operands[0]);
2059 operands[0] = gen_lowpart (SImode, operands[0]);
2060 operands[1] = gen_lowpart (SImode, operands[1]);
2061 }"
1b7da4ac 2062 [(set_attr "length" "8")
2063 (set_attr "type" "multiple")]
215b30b3 2064)
b11cae9e 2065
f7fbdd4a 2066(define_insn "*anddi_sesdi_di"
cffb2a26 2067 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 2068 (and:DI (sign_extend:DI
2069 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 2070 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2071 "TARGET_32BIT"
f6ebffac 2072 "#"
1b7da4ac 2073 [(set_attr "length" "8")
2074 (set_attr "type" "multiple")]
cffb2a26 2075)
b11cae9e 2076
87b22bf7 2077(define_expand "andsi3"
cffb2a26 2078 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2079 (and:SI (match_operand:SI 1 "s_register_operand" "")
2080 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 2081 "TARGET_EITHER"
87b22bf7 2082 "
25f905c2 2083 if (TARGET_32BIT)
87b22bf7 2084 {
0438d37f 2085 if (CONST_INT_P (operands[2]))
cffb2a26 2086 {
47b5b27b 2087 if (INTVAL (operands[2]) == 255 && arm_arch6)
2088 {
2089 operands[1] = convert_to_mode (QImode, operands[1], 1);
2090 emit_insn (gen_thumb2_zero_extendqisi2_v6 (operands[0],
2091 operands[1]));
2092 }
2093 else
2094 arm_split_constant (AND, SImode, NULL_RTX,
2095 INTVAL (operands[2]), operands[0],
2096 operands[1],
2097 optimize && can_create_pseudo_p ());
615caa51 2098
cffb2a26 2099 DONE;
2100 }
87b22bf7 2101 }
25f905c2 2102 else /* TARGET_THUMB1 */
cffb2a26 2103 {
0438d37f 2104 if (!CONST_INT_P (operands[2]))
923ffadb 2105 {
2106 rtx tmp = force_reg (SImode, operands[2]);
2107 if (rtx_equal_p (operands[0], operands[1]))
2108 operands[2] = tmp;
2109 else
2110 {
2111 operands[2] = operands[1];
2112 operands[1] = tmp;
2113 }
2114 }
cffb2a26 2115 else
2116 {
2117 int i;
2118
215b30b3 2119 if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
cffb2a26 2120 {
215b30b3 2121 operands[2] = force_reg (SImode,
2122 GEN_INT (~INTVAL (operands[2])));
cffb2a26 2123
747b7458 2124 emit_insn (gen_thumb1_bicsi3 (operands[0], operands[2], operands[1]));
cffb2a26 2125
2126 DONE;
2127 }
87b22bf7 2128
cffb2a26 2129 for (i = 9; i <= 31; i++)
2130 {
2131 if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
2132 {
2133 emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
2134 const0_rtx));
2135 DONE;
2136 }
215b30b3 2137 else if ((((HOST_WIDE_INT) 1) << i) - 1
2138 == ~INTVAL (operands[2]))
cffb2a26 2139 {
2140 rtx shift = GEN_INT (i);
2141 rtx reg = gen_reg_rtx (SImode);
2142
2143 emit_insn (gen_lshrsi3 (reg, operands[1], shift));
2144 emit_insn (gen_ashlsi3 (operands[0], reg, shift));
2145
2146 DONE;
2147 }
2148 }
2149
2150 operands[2] = force_reg (SImode, operands[2]);
2151 }
215b30b3 2152 }
2153 "
cffb2a26 2154)
2155
25f905c2 2156; ??? Check split length for Thumb-2
a0f94409 2157(define_insn_and_split "*arm_andsi3_insn"
29e234a3 2158 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r,r,r")
2159 (and:SI (match_operand:SI 1 "s_register_operand" "%r,0,r,r,r")
2160 (match_operand:SI 2 "reg_or_int_operand" "I,l,K,r,?n")))]
25f905c2 2161 "TARGET_32BIT"
5565501b 2162 "@
29e234a3 2163 and%?\\t%0, %1, %2
5565501b 2164 and%?\\t%0, %1, %2
87b22bf7 2165 bic%?\\t%0, %1, #%B2
65f68e55 2166 and%?\\t%0, %1, %2
87b22bf7 2167 #"
25f905c2 2168 "TARGET_32BIT
0438d37f 2169 && CONST_INT_P (operands[2])
a0f94409 2170 && !(const_ok_for_arm (INTVAL (operands[2]))
2171 || const_ok_for_arm (~INTVAL (operands[2])))"
2172 [(clobber (const_int 0))]
2173 "
96f57e36 2174 arm_split_constant (AND, SImode, curr_insn,
2175 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 2176 DONE;
2177 "
29e234a3 2178 [(set_attr "length" "4,4,4,4,16")
65f68e55 2179 (set_attr "predicable" "yes")
29e234a3 2180 (set_attr "predicable_short_it" "no,yes,no,no,no")
d82e788e 2181 (set_attr "type" "logic_imm,logic_imm,logic_reg,logic_reg,logic_imm")]
cffb2a26 2182)
2183
f7fbdd4a 2184(define_insn "*andsi3_compare0"
bd5b4116 2185 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 2186 (compare:CC_NOOV
65f68e55 2187 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
2188 (match_operand:SI 2 "arm_not_operand" "I,K,r"))
5565501b 2189 (const_int 0)))
65f68e55 2190 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9c08d1fa 2191 (and:SI (match_dup 1) (match_dup 2)))]
25f905c2 2192 "TARGET_32BIT"
5565501b 2193 "@
25f905c2 2194 and%.\\t%0, %1, %2
65f68e55 2195 bic%.\\t%0, %1, #%B2
2196 and%.\\t%0, %1, %2"
2197 [(set_attr "conds" "set")
d82e788e 2198 (set_attr "type" "logics_imm,logics_imm,logics_reg")]
cffb2a26 2199)
9c08d1fa 2200
f7fbdd4a 2201(define_insn "*andsi3_compare0_scratch"
bd5b4116 2202 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 2203 (compare:CC_NOOV
65f68e55 2204 (and:SI (match_operand:SI 0 "s_register_operand" "r,r,r")
2205 (match_operand:SI 1 "arm_not_operand" "I,K,r"))
5565501b 2206 (const_int 0)))
65f68e55 2207 (clobber (match_scratch:SI 2 "=X,r,X"))]
25f905c2 2208 "TARGET_32BIT"
5565501b 2209 "@
2210 tst%?\\t%0, %1
65f68e55 2211 bic%.\\t%2, %0, #%B1
2212 tst%?\\t%0, %1"
2213 [(set_attr "conds" "set")
d82e788e 2214 (set_attr "type" "logics_imm,logics_imm,logics_reg")]
0d66636f 2215)
9c08d1fa 2216
f7fbdd4a 2217(define_insn "*zeroextractsi_compare0_scratch"
bd5b4116 2218 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2219 (compare:CC_NOOV (zero_extract:SI
2220 (match_operand:SI 0 "s_register_operand" "r")
d952d547 2221 (match_operand 1 "const_int_operand" "n")
206ee9a2 2222 (match_operand 2 "const_int_operand" "n"))
9c08d1fa 2223 (const_int 0)))]
25f905c2 2224 "TARGET_32BIT
cffb2a26 2225 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
2226 && INTVAL (operands[1]) > 0
2227 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
2228 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
9c08d1fa 2229 "*
5c49a439 2230 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
2231 << INTVAL (operands[2]));
40dbec34 2232 output_asm_insn (\"tst%?\\t%0, %1\", operands);
e2348bcb 2233 return \"\";
0d66636f 2234 "
596e5e8f 2235 [(set_attr "conds" "set")
65f68e55 2236 (set_attr "predicable" "yes")
d952d547 2237 (set_attr "predicable_short_it" "no")
d82e788e 2238 (set_attr "type" "logics_imm")]
0d66636f 2239)
9c08d1fa 2240
f4462328 2241(define_insn_and_split "*ne_zeroextractsi"
c4034607 2242 [(set (match_operand:SI 0 "s_register_operand" "=r")
2243 (ne:SI (zero_extract:SI
2244 (match_operand:SI 1 "s_register_operand" "r")
2245 (match_operand:SI 2 "const_int_operand" "n")
2246 (match_operand:SI 3 "const_int_operand" "n"))
3b8c7f7a 2247 (const_int 0)))
2248 (clobber (reg:CC CC_REGNUM))]
25f905c2 2249 "TARGET_32BIT
cffb2a26 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)"
f4462328 2254 "#"
25f905c2 2255 "TARGET_32BIT
f4462328 2256 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2257 && INTVAL (operands[2]) > 0
2258 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2259 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
2260 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2261 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2262 (const_int 0)))
2263 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2264 (set (match_dup 0)
2265 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2266 (match_dup 0) (const_int 1)))]
2267 "
2268 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
2269 << INTVAL (operands[3]));
2270 "
2271 [(set_attr "conds" "clob")
25f905c2 2272 (set (attr "length")
2273 (if_then_else (eq_attr "is_thumb" "yes")
2274 (const_int 12)
1b7da4ac 2275 (const_int 8)))
2276 (set_attr "type" "multiple")]
f4462328 2277)
2278
2279(define_insn_and_split "*ne_zeroextractsi_shifted"
2280 [(set (match_operand:SI 0 "s_register_operand" "=r")
2281 (ne:SI (zero_extract:SI
2282 (match_operand:SI 1 "s_register_operand" "r")
2283 (match_operand:SI 2 "const_int_operand" "n")
2284 (const_int 0))
2285 (const_int 0)))
2286 (clobber (reg:CC CC_REGNUM))]
2287 "TARGET_ARM"
2288 "#"
2289 "TARGET_ARM"
2290 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2291 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2292 (const_int 0)))
2293 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2294 (set (match_dup 0)
2295 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2296 (match_dup 0) (const_int 1)))]
2297 "
2298 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
2299 "
2300 [(set_attr "conds" "clob")
1b7da4ac 2301 (set_attr "length" "8")
2302 (set_attr "type" "multiple")]
f4462328 2303)
2304
2305(define_insn_and_split "*ite_ne_zeroextractsi"
2306 [(set (match_operand:SI 0 "s_register_operand" "=r")
2307 (if_then_else:SI (ne (zero_extract:SI
2308 (match_operand:SI 1 "s_register_operand" "r")
2309 (match_operand:SI 2 "const_int_operand" "n")
2310 (match_operand:SI 3 "const_int_operand" "n"))
2311 (const_int 0))
2312 (match_operand:SI 4 "arm_not_operand" "rIK")
2313 (const_int 0)))
2314 (clobber (reg:CC CC_REGNUM))]
2315 "TARGET_ARM
2316 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2317 && INTVAL (operands[2]) > 0
2318 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 2319 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2320 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 2321 "#"
2322 "TARGET_ARM
2323 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2324 && INTVAL (operands[2]) > 0
2325 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 2326 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2327 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 2328 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2329 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2330 (const_int 0)))
2331 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2332 (set (match_dup 0)
2333 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2334 (match_dup 0) (match_dup 4)))]
2335 "
c4034607 2336 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
f4462328 2337 << INTVAL (operands[3]));
2338 "
2339 [(set_attr "conds" "clob")
1b7da4ac 2340 (set_attr "length" "8")
2341 (set_attr "type" "multiple")]
f4462328 2342)
2343
2344(define_insn_and_split "*ite_ne_zeroextractsi_shifted"
2345 [(set (match_operand:SI 0 "s_register_operand" "=r")
2346 (if_then_else:SI (ne (zero_extract:SI
2347 (match_operand:SI 1 "s_register_operand" "r")
2348 (match_operand:SI 2 "const_int_operand" "n")
2349 (const_int 0))
2350 (const_int 0))
2351 (match_operand:SI 3 "arm_not_operand" "rIK")
2352 (const_int 0)))
2353 (clobber (reg:CC CC_REGNUM))]
f8d7bf2f 2354 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 2355 "#"
f8d7bf2f 2356 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 2357 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2358 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2359 (const_int 0)))
2360 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2361 (set (match_dup 0)
2362 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2363 (match_dup 0) (match_dup 3)))]
2364 "
2365 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
0d66636f 2366 "
2367 [(set_attr "conds" "clob")
1b7da4ac 2368 (set_attr "length" "8")
2369 (set_attr "type" "multiple")]
215b30b3 2370)
9c08d1fa 2371
25f905c2 2372;; ??? Use Thumb-2 has bitfield insert/extract instructions.
d7863cfe 2373(define_split
2374 [(set (match_operand:SI 0 "s_register_operand" "")
2375 (match_operator:SI 1 "shiftable_operator"
2376 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2377 (match_operand:SI 3 "const_int_operand" "")
2378 (match_operand:SI 4 "const_int_operand" ""))
2379 (match_operand:SI 5 "s_register_operand" "")]))
2380 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2381 "TARGET_ARM"
2382 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2383 (set (match_dup 0)
2384 (match_op_dup 1
2385 [(lshiftrt:SI (match_dup 6) (match_dup 4))
2386 (match_dup 5)]))]
2387 "{
2388 HOST_WIDE_INT temp = INTVAL (operands[3]);
2389
2390 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2391 operands[4] = GEN_INT (32 - temp);
2392 }"
2393)
2394
d7863cfe 2395(define_split
2396 [(set (match_operand:SI 0 "s_register_operand" "")
2397 (match_operator:SI 1 "shiftable_operator"
2398 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2399 (match_operand:SI 3 "const_int_operand" "")
2400 (match_operand:SI 4 "const_int_operand" ""))
2401 (match_operand:SI 5 "s_register_operand" "")]))
2402 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2403 "TARGET_ARM"
2404 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2405 (set (match_dup 0)
2406 (match_op_dup 1
2407 [(ashiftrt:SI (match_dup 6) (match_dup 4))
2408 (match_dup 5)]))]
2409 "{
2410 HOST_WIDE_INT temp = INTVAL (operands[3]);
2411
2412 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2413 operands[4] = GEN_INT (32 - temp);
2414 }"
2415)
2416
a42059fd 2417;;; ??? This pattern is bogus. If operand3 has bits outside the range
2418;;; represented by the bitfield, then this will produce incorrect results.
2419;;; Somewhere, the value needs to be truncated. On targets like the m68k,
ceb2fe0f 2420;;; which have a real bit-field insert instruction, the truncation happens
2421;;; in the bit-field insert instruction itself. Since arm does not have a
2422;;; bit-field insert instruction, we would have to emit code here to truncate
a42059fd 2423;;; the value before we insert. This loses some of the advantage of having
2424;;; this insv pattern, so this pattern needs to be reevalutated.
2425
8a18b90c 2426(define_expand "insv"
eb04cafb 2427 [(set (zero_extract (match_operand 0 "nonimmediate_operand" "")
2428 (match_operand 1 "general_operand" "")
2429 (match_operand 2 "general_operand" ""))
2430 (match_operand 3 "reg_or_int_operand" ""))]
8b054d5a 2431 "TARGET_ARM || arm_arch_thumb2"
8a18b90c 2432 "
215b30b3 2433 {
2434 int start_bit = INTVAL (operands[2]);
2435 int width = INTVAL (operands[1]);
2436 HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
2437 rtx target, subtarget;
2438
8b054d5a 2439 if (arm_arch_thumb2)
2440 {
eb04cafb 2441 if (unaligned_access && MEM_P (operands[0])
2442 && s_register_operand (operands[3], GET_MODE (operands[3]))
2443 && (width == 16 || width == 32) && (start_bit % BITS_PER_UNIT) == 0)
8b054d5a 2444 {
eb04cafb 2445 rtx base_addr;
2446
2447 if (BYTES_BIG_ENDIAN)
2448 start_bit = GET_MODE_BITSIZE (GET_MODE (operands[3])) - width
2449 - start_bit;
8b054d5a 2450
eb04cafb 2451 if (width == 32)
8b054d5a 2452 {
eb04cafb 2453 base_addr = adjust_address (operands[0], SImode,
2454 start_bit / BITS_PER_UNIT);
2455 emit_insn (gen_unaligned_storesi (base_addr, operands[3]));
8b054d5a 2456 }
eb04cafb 2457 else
2458 {
2459 rtx tmp = gen_reg_rtx (HImode);
8b054d5a 2460
eb04cafb 2461 base_addr = adjust_address (operands[0], HImode,
2462 start_bit / BITS_PER_UNIT);
2463 emit_move_insn (tmp, gen_lowpart (HImode, operands[3]));
2464 emit_insn (gen_unaligned_storehi (base_addr, tmp));
2465 }
2466 DONE;
8b054d5a 2467 }
eb04cafb 2468 else if (s_register_operand (operands[0], GET_MODE (operands[0])))
8b054d5a 2469 {
eb04cafb 2470 bool use_bfi = TRUE;
8b054d5a 2471
0438d37f 2472 if (CONST_INT_P (operands[3]))
eb04cafb 2473 {
2474 HOST_WIDE_INT val = INTVAL (operands[3]) & mask;
2475
2476 if (val == 0)
2477 {
2478 emit_insn (gen_insv_zero (operands[0], operands[1],
2479 operands[2]));
2480 DONE;
2481 }
2482
2483 /* See if the set can be done with a single orr instruction. */
2484 if (val == mask && const_ok_for_arm (val << start_bit))
2485 use_bfi = FALSE;
2486 }
2487
2488 if (use_bfi)
2489 {
0438d37f 2490 if (!REG_P (operands[3]))
eb04cafb 2491 operands[3] = force_reg (SImode, operands[3]);
2492
2493 emit_insn (gen_insv_t2 (operands[0], operands[1], operands[2],
2494 operands[3]));
2495 DONE;
2496 }
8b054d5a 2497 }
eb04cafb 2498 else
2499 FAIL;
8b054d5a 2500 }
2501
eb04cafb 2502 if (!s_register_operand (operands[0], GET_MODE (operands[0])))
2503 FAIL;
2504
3f8fde42 2505 target = copy_rtx (operands[0]);
215b30b3 2506 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
2507 subreg as the final target. */
2508 if (GET_CODE (target) == SUBREG)
2509 {
2510 subtarget = gen_reg_rtx (SImode);
2511 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
2512 < GET_MODE_SIZE (SImode))
2513 target = SUBREG_REG (target);
2514 }
2515 else
2516 subtarget = target;
8a18b90c 2517
0438d37f 2518 if (CONST_INT_P (operands[3]))
215b30b3 2519 {
2520 /* Since we are inserting a known constant, we may be able to
2521 reduce the number of bits that we have to clear so that
2522 the mask becomes simple. */
2523 /* ??? This code does not check to see if the new mask is actually
2524 simpler. It may not be. */
2525 rtx op1 = gen_reg_rtx (SImode);
2526 /* ??? Truncate operand3 to fit in the bitfield. See comment before
2527 start of this pattern. */
2528 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
2529 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
2530
c5b3a71b 2531 emit_insn (gen_andsi3 (op1, operands[0],
2532 gen_int_mode (~mask2, SImode)));
215b30b3 2533 emit_insn (gen_iorsi3 (subtarget, op1,
4292ca6b 2534 gen_int_mode (op3_value << start_bit, SImode)));
215b30b3 2535 }
2536 else if (start_bit == 0
2537 && !(const_ok_for_arm (mask)
2538 || const_ok_for_arm (~mask)))
2539 {
2540 /* A Trick, since we are setting the bottom bits in the word,
2541 we can shift operand[3] up, operand[0] down, OR them together
2542 and rotate the result back again. This takes 3 insns, and
5910bb95 2543 the third might be mergeable into another op. */
215b30b3 2544 /* The shift up copes with the possibility that operand[3] is
2545 wider than the bitfield. */
2546 rtx op0 = gen_reg_rtx (SImode);
2547 rtx op1 = gen_reg_rtx (SImode);
2548
2549 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2550 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
2551 emit_insn (gen_iorsi3 (op1, op1, op0));
2552 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
2553 }
2554 else if ((width + start_bit == 32)
2555 && !(const_ok_for_arm (mask)
2556 || const_ok_for_arm (~mask)))
2557 {
2558 /* Similar trick, but slightly less efficient. */
8a18b90c 2559
215b30b3 2560 rtx op0 = gen_reg_rtx (SImode);
2561 rtx op1 = gen_reg_rtx (SImode);
8a18b90c 2562
215b30b3 2563 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2564 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
2565 emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
2566 emit_insn (gen_iorsi3 (subtarget, op1, op0));
2567 }
2568 else
2569 {
c5b3a71b 2570 rtx op0 = gen_int_mode (mask, SImode);
215b30b3 2571 rtx op1 = gen_reg_rtx (SImode);
2572 rtx op2 = gen_reg_rtx (SImode);
8a18b90c 2573
215b30b3 2574 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
2575 {
2576 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 2577
215b30b3 2578 emit_insn (gen_movsi (tmp, op0));
2579 op0 = tmp;
2580 }
8a18b90c 2581
215b30b3 2582 /* Mask out any bits in operand[3] that are not needed. */
2583 emit_insn (gen_andsi3 (op1, operands[3], op0));
8a18b90c 2584
0438d37f 2585 if (CONST_INT_P (op0)
215b30b3 2586 && (const_ok_for_arm (mask << start_bit)
2587 || const_ok_for_arm (~(mask << start_bit))))
2588 {
c5b3a71b 2589 op0 = gen_int_mode (~(mask << start_bit), SImode);
215b30b3 2590 emit_insn (gen_andsi3 (op2, operands[0], op0));
2591 }
2592 else
2593 {
0438d37f 2594 if (CONST_INT_P (op0))
215b30b3 2595 {
2596 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 2597
215b30b3 2598 emit_insn (gen_movsi (tmp, op0));
2599 op0 = tmp;
2600 }
2601
2602 if (start_bit != 0)
2603 emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
a42059fd 2604
215b30b3 2605 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
2606 }
8a18b90c 2607
215b30b3 2608 if (start_bit != 0)
2609 emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
8a18b90c 2610
215b30b3 2611 emit_insn (gen_iorsi3 (subtarget, op1, op2));
2612 }
f082f1c4 2613
215b30b3 2614 if (subtarget != target)
2615 {
2616 /* If TARGET is still a SUBREG, then it must be wider than a word,
2617 so we must be careful only to set the subword we were asked to. */
2618 if (GET_CODE (target) == SUBREG)
2619 emit_move_insn (target, subtarget);
2620 else
2621 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
2622 }
8a18b90c 2623
215b30b3 2624 DONE;
2625 }"
2626)
8a18b90c 2627
8b054d5a 2628(define_insn "insv_zero"
2629 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
809003b3 2630 (match_operand:SI 1 "const_int_M_operand" "M")
2631 (match_operand:SI 2 "const_int_M_operand" "M"))
8b054d5a 2632 (const_int 0))]
2633 "arm_arch_thumb2"
2634 "bfc%?\t%0, %2, %1"
2635 [(set_attr "length" "4")
d952d547 2636 (set_attr "predicable" "yes")
d82e788e 2637 (set_attr "predicable_short_it" "no")
2638 (set_attr "type" "bfm")]
8b054d5a 2639)
2640
2641(define_insn "insv_t2"
2642 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
809003b3 2643 (match_operand:SI 1 "const_int_M_operand" "M")
2644 (match_operand:SI 2 "const_int_M_operand" "M"))
8b054d5a 2645 (match_operand:SI 3 "s_register_operand" "r"))]
2646 "arm_arch_thumb2"
2647 "bfi%?\t%0, %3, %2, %1"
2648 [(set_attr "length" "4")
d952d547 2649 (set_attr "predicable" "yes")
d82e788e 2650 (set_attr "predicable_short_it" "no")
2651 (set_attr "type" "bfm")]
8b054d5a 2652)
2653
215b30b3 2654; constants for op 2 will never be given to these patterns.
a0f94409 2655(define_insn_and_split "*anddi_notdi_di"
9c08d1fa 2656 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 2657 (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "0,r"))
2658 (match_operand:DI 2 "s_register_operand" "r,0")))]
25f905c2 2659 "TARGET_32BIT"
f6ebffac 2660 "#"
e2669ea7 2661 "TARGET_32BIT && reload_completed
2662 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))
2663 && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
a0f94409 2664 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2665 (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2666 "
2667 {
2668 operands[3] = gen_highpart (SImode, operands[0]);
2669 operands[0] = gen_lowpart (SImode, operands[0]);
2670 operands[4] = gen_highpart (SImode, operands[1]);
2671 operands[1] = gen_lowpart (SImode, operands[1]);
2672 operands[5] = gen_highpart (SImode, operands[2]);
2673 operands[2] = gen_lowpart (SImode, operands[2]);
2674 }"
0d66636f 2675 [(set_attr "length" "8")
1b7da4ac 2676 (set_attr "predicable" "yes")
2677 (set_attr "type" "multiple")]
0d66636f 2678)
d952d547 2679
a0f94409 2680(define_insn_and_split "*anddi_notzesidi_di"
9c08d1fa 2681 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2682 (and:DI (not:DI (zero_extend:DI
2683 (match_operand:SI 2 "s_register_operand" "r,r")))
e2348bcb 2684 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 2685 "TARGET_32BIT"
e2348bcb 2686 "@
97499065 2687 bic%?\\t%Q0, %Q1, %2
f6ebffac 2688 #"
a0f94409 2689 ; (not (zero_extend ...)) allows us to just copy the high word from
2690 ; operand1 to operand0.
25f905c2 2691 "TARGET_32BIT
a0f94409 2692 && reload_completed
2693 && operands[0] != operands[1]"
5a097f7d 2694 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
a0f94409 2695 (set (match_dup 3) (match_dup 4))]
2696 "
2697 {
2698 operands[3] = gen_highpart (SImode, operands[0]);
2699 operands[0] = gen_lowpart (SImode, operands[0]);
2700 operands[4] = gen_highpart (SImode, operands[1]);
2701 operands[1] = gen_lowpart (SImode, operands[1]);
2702 }"
0d66636f 2703 [(set_attr "length" "4,8")
d952d547 2704 (set_attr "predicable" "yes")
1b7da4ac 2705 (set_attr "predicable_short_it" "no")
2706 (set_attr "type" "multiple")]
0d66636f 2707)
d952d547 2708
d8cd5fa0 2709(define_insn_and_split "*anddi_notdi_zesidi"
2710 [(set (match_operand:DI 0 "s_register_operand" "=r")
2711 (and:DI (not:DI (match_operand:DI 2 "s_register_operand" "r"))
2712 (zero_extend:DI
2713 (match_operand:SI 1 "s_register_operand" "r"))))]
2714 "TARGET_32BIT"
2715 "#"
2716 "TARGET_32BIT && reload_completed"
2717 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2718 (set (match_dup 3) (const_int 0))]
2719 "
2720 {
2721 operands[3] = gen_highpart (SImode, operands[0]);
2722 operands[0] = gen_lowpart (SImode, operands[0]);
2723 operands[2] = gen_lowpart (SImode, operands[2]);
2724 }"
2725 [(set_attr "length" "8")
2726 (set_attr "predicable" "yes")
2727 (set_attr "predicable_short_it" "no")
2728 (set_attr "type" "multiple")]
2729)
2730
a0f94409 2731(define_insn_and_split "*anddi_notsesidi_di"
9c08d1fa 2732 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2733 (and:DI (not:DI (sign_extend:DI
2734 (match_operand:SI 2 "s_register_operand" "r,r")))
5a097f7d 2735 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2736 "TARGET_32BIT"
f6ebffac 2737 "#"
25f905c2 2738 "TARGET_32BIT && reload_completed"
5a097f7d 2739 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
a0f94409 2740 (set (match_dup 3) (and:SI (not:SI
2741 (ashiftrt:SI (match_dup 2) (const_int 31)))
2742 (match_dup 4)))]
2743 "
2744 {
2745 operands[3] = gen_highpart (SImode, operands[0]);
2746 operands[0] = gen_lowpart (SImode, operands[0]);
2747 operands[4] = gen_highpart (SImode, operands[1]);
2748 operands[1] = gen_lowpart (SImode, operands[1]);
2749 }"
0d66636f 2750 [(set_attr "length" "8")
d952d547 2751 (set_attr "predicable" "yes")
1b7da4ac 2752 (set_attr "predicable_short_it" "no")
2753 (set_attr "type" "multiple")]
0d66636f 2754)
d952d547 2755
8a18b90c 2756(define_insn "andsi_notsi_si"
9c08d1fa 2757 [(set (match_operand:SI 0 "s_register_operand" "=r")
2758 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2759 (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 2760 "TARGET_32BIT"
0d66636f 2761 "bic%?\\t%0, %1, %2"
d952d547 2762 [(set_attr "predicable" "yes")
1b7da4ac 2763 (set_attr "predicable_short_it" "no")
2764 (set_attr "type" "logic_reg")]
0d66636f 2765)
b11cae9e 2766
8a18b90c 2767(define_insn "andsi_not_shiftsi_si"
a2cd141b 2768 [(set (match_operand:SI 0 "s_register_operand" "=r")
2769 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2770 [(match_operand:SI 2 "s_register_operand" "r")
2771 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2772 (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 2773 "TARGET_ARM"
6c4c2133 2774 "bic%?\\t%0, %1, %2%S4"
344495ea 2775 [(set_attr "predicable" "yes")
331beb1a 2776 (set_attr "shift" "2")
a2cd141b 2777 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
d82e788e 2778 (const_string "logic_shift_imm")
2779 (const_string "logic_shift_reg")))]
6c4c2133 2780)
8a18b90c 2781
f7fbdd4a 2782(define_insn "*andsi_notsi_si_compare0"
bd5b4116 2783 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 2784 (compare:CC_NOOV
2785 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2786 (match_operand:SI 1 "s_register_operand" "r"))
2787 (const_int 0)))
9c08d1fa 2788 (set (match_operand:SI 0 "s_register_operand" "=r")
2789 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
25f905c2 2790 "TARGET_32BIT"
2791 "bic%.\\t%0, %1, %2"
d82e788e 2792 [(set_attr "conds" "set")
2793 (set_attr "type" "logics_shift_reg")]
0d66636f 2794)
9c08d1fa 2795
f7fbdd4a 2796(define_insn "*andsi_notsi_si_compare0_scratch"
bd5b4116 2797 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 2798 (compare:CC_NOOV
2799 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2800 (match_operand:SI 1 "s_register_operand" "r"))
2801 (const_int 0)))
9c08d1fa 2802 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 2803 "TARGET_32BIT"
2804 "bic%.\\t%0, %1, %2"
d82e788e 2805 [(set_attr "conds" "set")
2806 (set_attr "type" "logics_shift_reg")]
0d66636f 2807)
9c08d1fa 2808
e2669ea7 2809(define_expand "iordi3"
2810 [(set (match_operand:DI 0 "s_register_operand" "")
2811 (ior:DI (match_operand:DI 1 "s_register_operand" "")
2812 (match_operand:DI 2 "neon_logic_op2" "")))]
2813 "TARGET_32BIT"
2814 ""
2815)
2816
74d6113f 2817(define_insn_and_split "*iordi3_insn"
2818 [(set (match_operand:DI 0 "s_register_operand" "=w,w ,&r,&r,&r,&r,?w,?w")
2819 (ior:DI (match_operand:DI 1 "s_register_operand" "%w,0 ,0 ,r ,0 ,r ,w ,0")
e0fe6977 2820 (match_operand:DI 2 "arm_iordi_operand_neon" "w ,Dl,r ,r ,Df,Df,w ,Dl")))]
74d6113f 2821 "TARGET_32BIT && !TARGET_IWMMXT"
2822 {
2823 switch (which_alternative)
2824 {
2825 case 0: /* fall through */
2826 case 6: return "vorr\t%P0, %P1, %P2";
2827 case 1: /* fall through */
2828 case 7: return neon_output_logic_immediate ("vorr", &operands[2],
2829 DImode, 0, VALID_NEON_QREG_MODE (DImode));
2830 case 2:
2831 case 3:
2832 case 4:
2833 case 5:
2834 return "#";
2835 default: gcc_unreachable ();
2836 }
2837 }
2838 "TARGET_32BIT && !TARGET_IWMMXT && reload_completed
2839 && !(IS_VFP_REGNUM (REGNO (operands[0])))"
2840 [(set (match_dup 3) (match_dup 4))
2841 (set (match_dup 5) (match_dup 6))]
2842 "
2843 {
2844 operands[3] = gen_lowpart (SImode, operands[0]);
2845 operands[5] = gen_highpart (SImode, operands[0]);
2846
2847 operands[4] = simplify_gen_binary (IOR, SImode,
2848 gen_lowpart (SImode, operands[1]),
2849 gen_lowpart (SImode, operands[2]));
2850 operands[6] = simplify_gen_binary (IOR, SImode,
2851 gen_highpart (SImode, operands[1]),
2852 gen_highpart_mode (SImode, DImode, operands[2]));
2853
2854 }"
32093010 2855 [(set_attr "type" "neon_logic,neon_logic,multiple,multiple,multiple,\
2856 multiple,neon_logic,neon_logic")
e0fe6977 2857 (set_attr "length" "*,*,8,8,8,8,*,*")
74d6113f 2858 (set_attr "arch" "neon_for_64bits,neon_for_64bits,*,*,*,*,avoid_neon_for_64bits,avoid_neon_for_64bits")]
cffb2a26 2859)
9c08d1fa 2860
f7fbdd4a 2861(define_insn "*iordi_zesidi_di"
9c08d1fa 2862 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2863 (ior:DI (zero_extend:DI
2864 (match_operand:SI 2 "s_register_operand" "r,r"))
e2348bcb 2865 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 2866 "TARGET_32BIT"
e2348bcb 2867 "@
97499065 2868 orr%?\\t%Q0, %Q1, %2
f6ebffac 2869 #"
0d66636f 2870 [(set_attr "length" "4,8")
d952d547 2871 (set_attr "predicable" "yes")
1b7da4ac 2872 (set_attr "predicable_short_it" "no")
2873 (set_attr "type" "logic_reg,multiple")]
cffb2a26 2874)
9c08d1fa 2875
f7fbdd4a 2876(define_insn "*iordi_sesidi_di"
9c08d1fa 2877 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2878 (ior:DI (sign_extend:DI
2879 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 2880 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2881 "TARGET_32BIT"
f6ebffac 2882 "#"
0d66636f 2883 [(set_attr "length" "8")
1b7da4ac 2884 (set_attr "predicable" "yes")
2885 (set_attr "type" "multiple")]
cffb2a26 2886)
9c08d1fa 2887
87b22bf7 2888(define_expand "iorsi3"
cffb2a26 2889 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2890 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2891 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 2892 "TARGET_EITHER"
87b22bf7 2893 "
0438d37f 2894 if (CONST_INT_P (operands[2]))
87b22bf7 2895 {
25f905c2 2896 if (TARGET_32BIT)
cffb2a26 2897 {
96f57e36 2898 arm_split_constant (IOR, SImode, NULL_RTX,
2899 INTVAL (operands[2]), operands[0], operands[1],
e1ba4a27 2900 optimize && can_create_pseudo_p ());
cffb2a26 2901 DONE;
2902 }
25f905c2 2903 else /* TARGET_THUMB1 */
923ffadb 2904 {
2905 rtx tmp = force_reg (SImode, operands[2]);
2906 if (rtx_equal_p (operands[0], operands[1]))
2907 operands[2] = tmp;
2908 else
2909 {
2910 operands[2] = operands[1];
2911 operands[1] = tmp;
2912 }
2913 }
87b22bf7 2914 }
cffb2a26 2915 "
2916)
87b22bf7 2917
d5d4dc8d 2918(define_insn_and_split "*iorsi3_insn"
29e234a3 2919 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r,r,r")
2920 (ior:SI (match_operand:SI 1 "s_register_operand" "%r,0,r,r,r")
2921 (match_operand:SI 2 "reg_or_int_operand" "I,l,K,r,?n")))]
d5d4dc8d 2922 "TARGET_32BIT"
87b22bf7 2923 "@
29e234a3 2924 orr%?\\t%0, %1, %2
87b22bf7 2925 orr%?\\t%0, %1, %2
d5d4dc8d 2926 orn%?\\t%0, %1, #%B2
65f68e55 2927 orr%?\\t%0, %1, %2
87b22bf7 2928 #"
d5d4dc8d 2929 "TARGET_32BIT
0438d37f 2930 && CONST_INT_P (operands[2])
d5d4dc8d 2931 && !(const_ok_for_arm (INTVAL (operands[2]))
2932 || (TARGET_THUMB2 && const_ok_for_arm (~INTVAL (operands[2]))))"
a0f94409 2933 [(clobber (const_int 0))]
d5d4dc8d 2934{
29e234a3 2935 arm_split_constant (IOR, SImode, curr_insn,
96f57e36 2936 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 2937 DONE;
d5d4dc8d 2938}
29e234a3 2939 [(set_attr "length" "4,4,4,4,16")
2940 (set_attr "arch" "32,t2,t2,32,32")
65f68e55 2941 (set_attr "predicable" "yes")
29e234a3 2942 (set_attr "predicable_short_it" "no,yes,no,no,no")
d82e788e 2943 (set_attr "type" "logic_imm,logic_reg,logic_imm,logic_reg,logic_reg")]
65f68e55 2944)
cffb2a26 2945
a0f94409 2946(define_peephole2
2947 [(match_scratch:SI 3 "r")
372575c7 2948 (set (match_operand:SI 0 "arm_general_register_operand" "")
2949 (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
87b22bf7 2950 (match_operand:SI 2 "const_int_operand" "")))]
90560cad 2951 "TARGET_ARM
a0f94409 2952 && !const_ok_for_arm (INTVAL (operands[2]))
2953 && const_ok_for_arm (~INTVAL (operands[2]))"
2954 [(set (match_dup 3) (match_dup 2))
2955 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2956 ""
215b30b3 2957)
a0f94409 2958
f7fbdd4a 2959(define_insn "*iorsi3_compare0"
bd5b4116 2960 [(set (reg:CC_NOOV CC_REGNUM)
65f68e55 2961 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r,r")
2962 (match_operand:SI 2 "arm_rhs_operand" "I,r"))
9c08d1fa 2963 (const_int 0)))
65f68e55 2964 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 2965 (ior:SI (match_dup 1) (match_dup 2)))]
25f905c2 2966 "TARGET_32BIT"
2967 "orr%.\\t%0, %1, %2"
65f68e55 2968 [(set_attr "conds" "set")
d82e788e 2969 (set_attr "type" "logics_imm,logics_reg")]
cffb2a26 2970)
9c08d1fa 2971
f7fbdd4a 2972(define_insn "*iorsi3_compare0_scratch"
bd5b4116 2973 [(set (reg:CC_NOOV CC_REGNUM)
65f68e55 2974 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r,r")
2975 (match_operand:SI 2 "arm_rhs_operand" "I,r"))
9c08d1fa 2976 (const_int 0)))
65f68e55 2977 (clobber (match_scratch:SI 0 "=r,r"))]
25f905c2 2978 "TARGET_32BIT"
2979 "orr%.\\t%0, %1, %2"
65f68e55 2980 [(set_attr "conds" "set")
d82e788e 2981 (set_attr "type" "logics_imm,logics_reg")]
0d66636f 2982)
9c08d1fa 2983
e2669ea7 2984(define_expand "xordi3"
2985 [(set (match_operand:DI 0 "s_register_operand" "")
2986 (xor:DI (match_operand:DI 1 "s_register_operand" "")
8ee7dc6f 2987 (match_operand:DI 2 "arm_xordi_operand" "")))]
e2669ea7 2988 "TARGET_32BIT"
2989 ""
2990)
2991
8ee7dc6f 2992(define_insn_and_split "*xordi3_insn"
2993 [(set (match_operand:DI 0 "s_register_operand" "=w,&r,&r,&r,&r,?w")
205c3b0a 2994 (xor:DI (match_operand:DI 1 "s_register_operand" "%w ,0,r ,0 ,r ,w")
8ee7dc6f 2995 (match_operand:DI 2 "arm_xordi_operand" "w ,r ,r ,Dg,Dg,w")))]
2996 "TARGET_32BIT && !TARGET_IWMMXT"
2997{
2998 switch (which_alternative)
2999 {
3000 case 1:
3001 case 2:
3002 case 3:
3003 case 4: /* fall through */
3004 return "#";
3005 case 0: /* fall through */
3006 case 5: return "veor\t%P0, %P1, %P2";
3007 default: gcc_unreachable ();
3008 }
3009}
3010 "TARGET_32BIT && !TARGET_IWMMXT && reload_completed
3011 && !(IS_VFP_REGNUM (REGNO (operands[0])))"
3012 [(set (match_dup 3) (match_dup 4))
3013 (set (match_dup 5) (match_dup 6))]
3014 "
3015 {
3016 operands[3] = gen_lowpart (SImode, operands[0]);
3017 operands[5] = gen_highpart (SImode, operands[0]);
3018
3019 operands[4] = simplify_gen_binary (XOR, SImode,
3020 gen_lowpart (SImode, operands[1]),
3021 gen_lowpart (SImode, operands[2]));
3022 operands[6] = simplify_gen_binary (XOR, SImode,
3023 gen_highpart (SImode, operands[1]),
3024 gen_highpart_mode (SImode, DImode, operands[2]));
3025
3026 }"
3027 [(set_attr "length" "*,8,8,8,8,*")
32093010 3028 (set_attr "type" "neon_logic,multiple,multiple,multiple,multiple,neon_logic")
8ee7dc6f 3029 (set_attr "arch" "neon_for_64bits,*,*,*,*,avoid_neon_for_64bits")]
cffb2a26 3030)
9c08d1fa 3031
f7fbdd4a 3032(define_insn "*xordi_zesidi_di"
9c08d1fa 3033 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3034 (xor:DI (zero_extend:DI
3035 (match_operand:SI 2 "s_register_operand" "r,r"))
e2348bcb 3036 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 3037 "TARGET_32BIT"
e2348bcb 3038 "@
97499065 3039 eor%?\\t%Q0, %Q1, %2
f6ebffac 3040 #"
0d66636f 3041 [(set_attr "length" "4,8")
d952d547 3042 (set_attr "predicable" "yes")
1b7da4ac 3043 (set_attr "predicable_short_it" "no")
3044 (set_attr "type" "logic_reg")]
cffb2a26 3045)
9c08d1fa 3046
f7fbdd4a 3047(define_insn "*xordi_sesidi_di"
9c08d1fa 3048 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3049 (xor:DI (sign_extend:DI
3050 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 3051 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 3052 "TARGET_32BIT"
f6ebffac 3053 "#"
0d66636f 3054 [(set_attr "length" "8")
1b7da4ac 3055 (set_attr "predicable" "yes")
3056 (set_attr "type" "multiple")]
cffb2a26 3057)
9c08d1fa 3058
cffb2a26 3059(define_expand "xorsi3"
3060 [(set (match_operand:SI 0 "s_register_operand" "")
3061 (xor:SI (match_operand:SI 1 "s_register_operand" "")
923ffadb 3062 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 3063 "TARGET_EITHER"
0438d37f 3064 "if (CONST_INT_P (operands[2]))
923ffadb 3065 {
3066 if (TARGET_32BIT)
3067 {
3068 arm_split_constant (XOR, SImode, NULL_RTX,
3069 INTVAL (operands[2]), operands[0], operands[1],
3070 optimize && can_create_pseudo_p ());
3071 DONE;
3072 }
3073 else /* TARGET_THUMB1 */
3074 {
3075 rtx tmp = force_reg (SImode, operands[2]);
3076 if (rtx_equal_p (operands[0], operands[1]))
3077 operands[2] = tmp;
3078 else
3079 {
3080 operands[2] = operands[1];
3081 operands[1] = tmp;
3082 }
3083 }
3084 }"
cffb2a26 3085)
3086
5dcb35d9 3087(define_insn_and_split "*arm_xorsi3"
29e234a3 3088 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r,r")
3089 (xor:SI (match_operand:SI 1 "s_register_operand" "%r,0,r,r")
3090 (match_operand:SI 2 "reg_or_int_operand" "I,l,r,?n")))]
25f905c2 3091 "TARGET_32BIT"
5dcb35d9 3092 "@
29e234a3 3093 eor%?\\t%0, %1, %2
65f68e55 3094 eor%?\\t%0, %1, %2
5dcb35d9 3095 eor%?\\t%0, %1, %2
3096 #"
3097 "TARGET_32BIT
0438d37f 3098 && CONST_INT_P (operands[2])
5dcb35d9 3099 && !const_ok_for_arm (INTVAL (operands[2]))"
3100 [(clobber (const_int 0))]
3101{
3102 arm_split_constant (XOR, SImode, curr_insn,
3103 INTVAL (operands[2]), operands[0], operands[1], 0);
3104 DONE;
3105}
29e234a3 3106 [(set_attr "length" "4,4,4,16")
65f68e55 3107 (set_attr "predicable" "yes")
29e234a3 3108 (set_attr "predicable_short_it" "no,yes,no,no")
1b7da4ac 3109 (set_attr "type" "logic_imm,logic_reg,logic_reg,multiple")]
cffb2a26 3110)
3111
f7fbdd4a 3112(define_insn "*xorsi3_compare0"
bd5b4116 3113 [(set (reg:CC_NOOV CC_REGNUM)
65f68e55 3114 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r,r")
3115 (match_operand:SI 2 "arm_rhs_operand" "I,r"))
9c08d1fa 3116 (const_int 0)))
65f68e55 3117 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 3118 (xor:SI (match_dup 1) (match_dup 2)))]
25f905c2 3119 "TARGET_32BIT"
3120 "eor%.\\t%0, %1, %2"
65f68e55 3121 [(set_attr "conds" "set")
d82e788e 3122 (set_attr "type" "logics_imm,logics_reg")]
0d66636f 3123)
9c08d1fa 3124
f7fbdd4a 3125(define_insn "*xorsi3_compare0_scratch"
bd5b4116 3126 [(set (reg:CC_NOOV CC_REGNUM)
65f68e55 3127 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r,r")
3128 (match_operand:SI 1 "arm_rhs_operand" "I,r"))
9c08d1fa 3129 (const_int 0)))]
25f905c2 3130 "TARGET_32BIT"
40dbec34 3131 "teq%?\\t%0, %1"
65f68e55 3132 [(set_attr "conds" "set")
d82e788e 3133 (set_attr "type" "logics_imm,logics_reg")]
cffb2a26 3134)
9c08d1fa 3135
215b30b3 3136; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
3137; (NOT D) we can sometimes merge the final NOT into one of the following
3138; insns.
9c08d1fa 3139
3140(define_split
a058e94a 3141 [(set (match_operand:SI 0 "s_register_operand" "")
3142 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
3143 (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
3144 (match_operand:SI 3 "arm_rhs_operand" "")))
3145 (clobber (match_operand:SI 4 "s_register_operand" ""))]
25f905c2 3146 "TARGET_32BIT"
9c08d1fa 3147 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
3148 (not:SI (match_dup 3))))
3149 (set (match_dup 0) (not:SI (match_dup 4)))]
3150 ""
3151)
3152
ba6a3b2f 3153(define_insn_and_split "*andsi_iorsi3_notsi"
9c08d1fa 3154 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
e5fea38e 3155 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "%0,r,r")
9c08d1fa 3156 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
3157 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
25f905c2 3158 "TARGET_32BIT"
ba6a3b2f 3159 "#" ; "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
3160 "&& reload_completed"
3161 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
3162 (set (match_dup 0) (and:SI (not:SI (match_dup 3)) (match_dup 0)))]
3163 ""
0d66636f 3164 [(set_attr "length" "8")
25f905c2 3165 (set_attr "ce_count" "2")
d952d547 3166 (set_attr "predicable" "yes")
1b7da4ac 3167 (set_attr "predicable_short_it" "no")
3168 (set_attr "type" "multiple")]
cffb2a26 3169)
9c08d1fa 3170
25f905c2 3171; ??? Are these four splitters still beneficial when the Thumb-2 bitfield
3172; insns are available?
d7863cfe 3173(define_split
3174 [(set (match_operand:SI 0 "s_register_operand" "")
3175 (match_operator:SI 1 "logical_binary_operator"
3176 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
3177 (match_operand:SI 3 "const_int_operand" "")
3178 (match_operand:SI 4 "const_int_operand" ""))
3179 (match_operator:SI 9 "logical_binary_operator"
3180 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3181 (match_operand:SI 6 "const_int_operand" ""))
3182 (match_operand:SI 7 "s_register_operand" "")])]))
3183 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3184 "TARGET_32BIT
d7863cfe 3185 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3186 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3187 [(set (match_dup 8)
3188 (match_op_dup 1
3189 [(ashift:SI (match_dup 2) (match_dup 4))
3190 (match_dup 5)]))
3191 (set (match_dup 0)
3192 (match_op_dup 1
3193 [(lshiftrt:SI (match_dup 8) (match_dup 6))
3194 (match_dup 7)]))]
3195 "
3196 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3197")
3198
3199(define_split
3200 [(set (match_operand:SI 0 "s_register_operand" "")
3201 (match_operator:SI 1 "logical_binary_operator"
3202 [(match_operator:SI 9 "logical_binary_operator"
3203 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3204 (match_operand:SI 6 "const_int_operand" ""))
3205 (match_operand:SI 7 "s_register_operand" "")])
3206 (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
3207 (match_operand:SI 3 "const_int_operand" "")
3208 (match_operand:SI 4 "const_int_operand" ""))]))
3209 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3210 "TARGET_32BIT
d7863cfe 3211 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3212 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3213 [(set (match_dup 8)
3214 (match_op_dup 1
3215 [(ashift:SI (match_dup 2) (match_dup 4))
3216 (match_dup 5)]))
3217 (set (match_dup 0)
3218 (match_op_dup 1
3219 [(lshiftrt:SI (match_dup 8) (match_dup 6))
3220 (match_dup 7)]))]
3221 "
3222 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3223")
3224
3225(define_split
3226 [(set (match_operand:SI 0 "s_register_operand" "")
3227 (match_operator:SI 1 "logical_binary_operator"
3228 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
3229 (match_operand:SI 3 "const_int_operand" "")
3230 (match_operand:SI 4 "const_int_operand" ""))
3231 (match_operator:SI 9 "logical_binary_operator"
3232 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3233 (match_operand:SI 6 "const_int_operand" ""))
3234 (match_operand:SI 7 "s_register_operand" "")])]))
3235 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3236 "TARGET_32BIT
d7863cfe 3237 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3238 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3239 [(set (match_dup 8)
3240 (match_op_dup 1
3241 [(ashift:SI (match_dup 2) (match_dup 4))
3242 (match_dup 5)]))
3243 (set (match_dup 0)
3244 (match_op_dup 1
3245 [(ashiftrt:SI (match_dup 8) (match_dup 6))
3246 (match_dup 7)]))]
3247 "
3248 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3249")
3250
3251(define_split
3252 [(set (match_operand:SI 0 "s_register_operand" "")
3253 (match_operator:SI 1 "logical_binary_operator"
3254 [(match_operator:SI 9 "logical_binary_operator"
3255 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3256 (match_operand:SI 6 "const_int_operand" ""))
3257 (match_operand:SI 7 "s_register_operand" "")])
3258 (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
3259 (match_operand:SI 3 "const_int_operand" "")
3260 (match_operand:SI 4 "const_int_operand" ""))]))
3261 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3262 "TARGET_32BIT
d7863cfe 3263 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3264 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3265 [(set (match_dup 8)
3266 (match_op_dup 1
3267 [(ashift:SI (match_dup 2) (match_dup 4))
3268 (match_dup 5)]))
3269 (set (match_dup 0)
3270 (match_op_dup 1
3271 [(ashiftrt:SI (match_dup 8) (match_dup 6))
3272 (match_dup 7)]))]
3273 "
3274 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3275")
9c08d1fa 3276\f
3277
3278;; Minimum and maximum insns
3279
8b9dc177 3280(define_expand "smaxsi3"
3281 [(parallel [
3282 (set (match_operand:SI 0 "s_register_operand" "")
3283 (smax:SI (match_operand:SI 1 "s_register_operand" "")
3284 (match_operand:SI 2 "arm_rhs_operand" "")))
3285 (clobber (reg:CC CC_REGNUM))])]
25f905c2 3286 "TARGET_32BIT"
8b9dc177 3287 "
8774928b 3288 if (operands[2] == const0_rtx || operands[2] == constm1_rtx)
8b9dc177 3289 {
3290 /* No need for a clobber of the condition code register here. */
3291 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3292 gen_rtx_SMAX (SImode, operands[1],
3293 operands[2])));
3294 DONE;
3295 }
3296")
3297
3298(define_insn "*smax_0"
3299 [(set (match_operand:SI 0 "s_register_operand" "=r")
3300 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3301 (const_int 0)))]
25f905c2 3302 "TARGET_32BIT"
8b9dc177 3303 "bic%?\\t%0, %1, %1, asr #31"
d952d547 3304 [(set_attr "predicable" "yes")
1b7da4ac 3305 (set_attr "predicable_short_it" "no")
3306 (set_attr "type" "logic_shift_reg")]
8b9dc177 3307)
3308
8774928b 3309(define_insn "*smax_m1"
3310 [(set (match_operand:SI 0 "s_register_operand" "=r")
3311 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3312 (const_int -1)))]
25f905c2 3313 "TARGET_32BIT"
8774928b 3314 "orr%?\\t%0, %1, %1, asr #31"
d952d547 3315 [(set_attr "predicable" "yes")
1b7da4ac 3316 (set_attr "predicable_short_it" "no")
3317 (set_attr "type" "logic_shift_reg")]
8774928b 3318)
3319
3dc953f2 3320(define_insn_and_split "*arm_smax_insn"
8b9dc177 3321 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3322 (smax:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3323 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
bd5b4116 3324 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3325 "TARGET_ARM"
3dc953f2 3326 "#"
3327 ; cmp\\t%1, %2\;movlt\\t%0, %2
3328 ; cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
3329 "TARGET_ARM"
3330 [(set (reg:CC CC_REGNUM)
3331 (compare:CC (match_dup 1) (match_dup 2)))
3332 (set (match_dup 0)
3333 (if_then_else:SI (ge:SI (reg:CC CC_REGNUM) (const_int 0))
3334 (match_dup 1)
3335 (match_dup 2)))]
3336 ""
cffb2a26 3337 [(set_attr "conds" "clob")
1b7da4ac 3338 (set_attr "length" "8,12")
3339 (set_attr "type" "multiple")]
cffb2a26 3340)
9c08d1fa 3341
8b9dc177 3342(define_expand "sminsi3"
3343 [(parallel [
3344 (set (match_operand:SI 0 "s_register_operand" "")
3345 (smin:SI (match_operand:SI 1 "s_register_operand" "")
3346 (match_operand:SI 2 "arm_rhs_operand" "")))
3347 (clobber (reg:CC CC_REGNUM))])]
25f905c2 3348 "TARGET_32BIT"
8b9dc177 3349 "
3350 if (operands[2] == const0_rtx)
3351 {
3352 /* No need for a clobber of the condition code register here. */
3353 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3354 gen_rtx_SMIN (SImode, operands[1],
3355 operands[2])));
3356 DONE;
3357 }
3358")
3359
3360(define_insn "*smin_0"
3361 [(set (match_operand:SI 0 "s_register_operand" "=r")
3362 (smin:SI (match_operand:SI 1 "s_register_operand" "r")
3363 (const_int 0)))]
25f905c2 3364 "TARGET_32BIT"
8b9dc177 3365 "and%?\\t%0, %1, %1, asr #31"
d952d547 3366 [(set_attr "predicable" "yes")
1b7da4ac 3367 (set_attr "predicable_short_it" "no")
3368 (set_attr "type" "logic_shift_reg")]
8b9dc177 3369)
3370
3dc953f2 3371(define_insn_and_split "*arm_smin_insn"
8b9dc177 3372 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3373 (smin:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3374 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
bd5b4116 3375 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3376 "TARGET_ARM"
3dc953f2 3377 "#"
3378 ; cmp\\t%1, %2\;movge\\t%0, %2
3379 ; cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
3380 "TARGET_ARM"
3381 [(set (reg:CC CC_REGNUM)
3382 (compare:CC (match_dup 1) (match_dup 2)))
3383 (set (match_dup 0)
3384 (if_then_else:SI (lt:SI (reg:CC CC_REGNUM) (const_int 0))
3385 (match_dup 1)
3386 (match_dup 2)))]
3387 ""
0d66636f 3388 [(set_attr "conds" "clob")
1b7da4ac 3389 (set_attr "length" "8,12")
3390 (set_attr "type" "multiple,multiple")]
0d66636f 3391)
9c08d1fa 3392
25f905c2 3393(define_expand "umaxsi3"
3394 [(parallel [
3395 (set (match_operand:SI 0 "s_register_operand" "")
3396 (umax:SI (match_operand:SI 1 "s_register_operand" "")
3397 (match_operand:SI 2 "arm_rhs_operand" "")))
3398 (clobber (reg:CC CC_REGNUM))])]
3399 "TARGET_32BIT"
3400 ""
3401)
3402
3dc953f2 3403(define_insn_and_split "*arm_umaxsi3"
9c08d1fa 3404 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3405 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3406 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 3407 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3408 "TARGET_ARM"
3dc953f2 3409 "#"
3410 ; cmp\\t%1, %2\;movcc\\t%0, %2
3411 ; cmp\\t%1, %2\;movcs\\t%0, %1
3412 ; cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
3413 "TARGET_ARM"
3414 [(set (reg:CC CC_REGNUM)
3415 (compare:CC (match_dup 1) (match_dup 2)))
3416 (set (match_dup 0)
3417 (if_then_else:SI (geu:SI (reg:CC CC_REGNUM) (const_int 0))
3418 (match_dup 1)
3419 (match_dup 2)))]
3420 ""
0d66636f 3421 [(set_attr "conds" "clob")
1b7da4ac 3422 (set_attr "length" "8,8,12")
3423 (set_attr "type" "store1")]
0d66636f 3424)
9c08d1fa 3425
25f905c2 3426(define_expand "uminsi3"
3427 [(parallel [
3428 (set (match_operand:SI 0 "s_register_operand" "")
3429 (umin:SI (match_operand:SI 1 "s_register_operand" "")
3430 (match_operand:SI 2 "arm_rhs_operand" "")))
3431 (clobber (reg:CC CC_REGNUM))])]
3432 "TARGET_32BIT"
3433 ""
3434)
3435
3dc953f2 3436(define_insn_and_split "*arm_uminsi3"
9c08d1fa 3437 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3438 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3439 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 3440 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3441 "TARGET_ARM"
3dc953f2 3442 "#"
3443 ; cmp\\t%1, %2\;movcs\\t%0, %2
3444 ; cmp\\t%1, %2\;movcc\\t%0, %1
3445 ; cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
3446 "TARGET_ARM"
3447 [(set (reg:CC CC_REGNUM)
3448 (compare:CC (match_dup 1) (match_dup 2)))
3449 (set (match_dup 0)
3450 (if_then_else:SI (ltu:SI (reg:CC CC_REGNUM) (const_int 0))
3451 (match_dup 1)
3452 (match_dup 2)))]
3453 ""
0d66636f 3454 [(set_attr "conds" "clob")
1b7da4ac 3455 (set_attr "length" "8,8,12")
3456 (set_attr "type" "store1")]
0d66636f 3457)
9c08d1fa 3458
8a18b90c 3459(define_insn "*store_minmaxsi"
9c08d1fa 3460 [(set (match_operand:SI 0 "memory_operand" "=m")
3461 (match_operator:SI 3 "minmax_operator"
3462 [(match_operand:SI 1 "s_register_operand" "r")
3463 (match_operand:SI 2 "s_register_operand" "r")]))
bd5b4116 3464 (clobber (reg:CC CC_REGNUM))]
b207d152 3465 "TARGET_32BIT && optimize_function_for_size_p (cfun) && !arm_restrict_it"
9c08d1fa 3466 "*
dc55b8a9 3467 operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
3468 operands[1], operands[2]);
e2348bcb 3469 output_asm_insn (\"cmp\\t%1, %2\", operands);
25f905c2 3470 if (TARGET_THUMB2)
3471 output_asm_insn (\"ite\t%d3\", operands);
e2348bcb 3472 output_asm_insn (\"str%d3\\t%1, %0\", operands);
3473 output_asm_insn (\"str%D3\\t%2, %0\", operands);
3474 return \"\";
0d66636f 3475 "
3476 [(set_attr "conds" "clob")
25f905c2 3477 (set (attr "length")
3478 (if_then_else (eq_attr "is_thumb" "yes")
3479 (const_int 14)
3480 (const_int 12)))
0d66636f 3481 (set_attr "type" "store1")]
3482)
9c08d1fa 3483
8a18b90c 3484; Reject the frame pointer in operand[1], since reloading this after
3485; it has been eliminated can cause carnage.
f7fbdd4a 3486(define_insn "*minmax_arithsi"
9c08d1fa 3487 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3488 (match_operator:SI 4 "shiftable_operator"
3489 [(match_operator:SI 5 "minmax_operator"
3490 [(match_operand:SI 2 "s_register_operand" "r,r")
3491 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
3492 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 3493 (clobber (reg:CC CC_REGNUM))]
7c36fe71 3494 "TARGET_32BIT && !arm_eliminable_register (operands[1]) && !arm_restrict_it"
9c08d1fa 3495 "*
0d66636f 3496 {
3497 enum rtx_code code = GET_CODE (operands[4]);
25f905c2 3498 bool need_else;
3499
3500 if (which_alternative != 0 || operands[3] != const0_rtx
ca0fc5a2 3501 || (code != PLUS && code != IOR && code != XOR))
25f905c2 3502 need_else = true;
3503 else
3504 need_else = false;
0d66636f 3505
dc55b8a9 3506 operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
3507 operands[2], operands[3]);
0d66636f 3508 output_asm_insn (\"cmp\\t%2, %3\", operands);
25f905c2 3509 if (TARGET_THUMB2)
3510 {
3511 if (need_else)
3512 output_asm_insn (\"ite\\t%d5\", operands);
3513 else
3514 output_asm_insn (\"it\\t%d5\", operands);
3515 }
0d66636f 3516 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
25f905c2 3517 if (need_else)
0d66636f 3518 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
3519 return \"\";
215b30b3 3520 }"
0d66636f 3521 [(set_attr "conds" "clob")
25f905c2 3522 (set (attr "length")
3523 (if_then_else (eq_attr "is_thumb" "yes")
3524 (const_int 14)
1b7da4ac 3525 (const_int 12)))
3526 (set_attr "type" "multiple")]
0d66636f 3527)
9c08d1fa 3528
4164bca1 3529; Reject the frame pointer in operand[1], since reloading this after
3530; it has been eliminated can cause carnage.
3531(define_insn_and_split "*minmax_arithsi_non_canon"
7c36fe71 3532 [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts")
4164bca1 3533 (minus:SI
7c36fe71 3534 (match_operand:SI 1 "s_register_operand" "0,?Ts")
4164bca1 3535 (match_operator:SI 4 "minmax_operator"
7c36fe71 3536 [(match_operand:SI 2 "s_register_operand" "Ts,Ts")
3537 (match_operand:SI 3 "arm_rhs_operand" "TsI,TsI")])))
4164bca1 3538 (clobber (reg:CC CC_REGNUM))]
7c36fe71 3539 "TARGET_32BIT && !arm_eliminable_register (operands[1])
3540 && !(arm_restrict_it && CONST_INT_P (operands[3]))"
4164bca1 3541 "#"
3542 "TARGET_32BIT && !arm_eliminable_register (operands[1]) && reload_completed"
3543 [(set (reg:CC CC_REGNUM)
3544 (compare:CC (match_dup 2) (match_dup 3)))
3545
3546 (cond_exec (match_op_dup 4 [(reg:CC CC_REGNUM) (const_int 0)])
3547 (set (match_dup 0)
3548 (minus:SI (match_dup 1)
3549 (match_dup 2))))
3550 (cond_exec (match_op_dup 5 [(reg:CC CC_REGNUM) (const_int 0)])
3551 (set (match_dup 0)
36ee0cde 3552 (match_dup 6)))]
4164bca1 3553 {
3754d046 3554 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
4164bca1 3555 operands[2], operands[3]);
3556 enum rtx_code rc = minmax_code (operands[4]);
3557 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode,
3558 operands[2], operands[3]);
3559
3560 if (mode == CCFPmode || mode == CCFPEmode)
3561 rc = reverse_condition_maybe_unordered (rc);
3562 else
3563 rc = reverse_condition (rc);
3564 operands[5] = gen_rtx_fmt_ee (rc, SImode, operands[2], operands[3]);
36ee0cde 3565 if (CONST_INT_P (operands[3]))
3566 operands[6] = plus_constant (SImode, operands[1], -INTVAL (operands[3]));
3567 else
3568 operands[6] = gen_rtx_MINUS (SImode, operands[1], operands[3]);
4164bca1 3569 }
3570 [(set_attr "conds" "clob")
3571 (set (attr "length")
3572 (if_then_else (eq_attr "is_thumb" "yes")
3573 (const_int 14)
1b7da4ac 3574 (const_int 12)))
3575 (set_attr "type" "multiple")]
4164bca1 3576)
3577
b49e3742 3578(define_code_iterator SAT [smin smax])
3579(define_code_iterator SATrev [smin smax])
3580(define_code_attr SATlo [(smin "1") (smax "2")])
3581(define_code_attr SAThi [(smin "2") (smax "1")])
3582
3583(define_insn "*satsi_<SAT:code>"
3584 [(set (match_operand:SI 0 "s_register_operand" "=r")
3585 (SAT:SI (SATrev:SI (match_operand:SI 3 "s_register_operand" "r")
3586 (match_operand:SI 1 "const_int_operand" "i"))
3587 (match_operand:SI 2 "const_int_operand" "i")))]
3588 "TARGET_32BIT && arm_arch6 && <SAT:CODE> != <SATrev:CODE>
3589 && arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>], NULL, NULL)"
3590{
3591 int mask;
3592 bool signed_sat;
3593 if (!arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>],
3594 &mask, &signed_sat))
3595 gcc_unreachable ();
3596
3597 operands[1] = GEN_INT (mask);
3598 if (signed_sat)
3599 return "ssat%?\t%0, %1, %3";
3600 else
3601 return "usat%?\t%0, %1, %3";
3602}
7c36fe71 3603 [(set_attr "predicable" "yes")
1b7da4ac 3604 (set_attr "predicable_short_it" "no")
3605 (set_attr "type" "alus_imm")]
bebe9bbb 3606)
b49e3742 3607
3608(define_insn "*satsi_<SAT:code>_shift"
3609 [(set (match_operand:SI 0 "s_register_operand" "=r")
3610 (SAT:SI (SATrev:SI (match_operator:SI 3 "sat_shift_operator"
3611 [(match_operand:SI 4 "s_register_operand" "r")
3612 (match_operand:SI 5 "const_int_operand" "i")])
3613 (match_operand:SI 1 "const_int_operand" "i"))
3614 (match_operand:SI 2 "const_int_operand" "i")))]
3615 "TARGET_32BIT && arm_arch6 && <SAT:CODE> != <SATrev:CODE>
3616 && arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>], NULL, NULL)"
3617{
3618 int mask;
3619 bool signed_sat;
3620 if (!arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>],
3621 &mask, &signed_sat))
3622 gcc_unreachable ();
3623
3624 operands[1] = GEN_INT (mask);
3625 if (signed_sat)
3626 return "ssat%?\t%0, %1, %4%S3";
3627 else
3628 return "usat%?\t%0, %1, %4%S3";
3629}
3630 [(set_attr "predicable" "yes")
7c36fe71 3631 (set_attr "predicable_short_it" "no")
b49e3742 3632 (set_attr "shift" "3")
d82e788e 3633 (set_attr "type" "logic_shift_reg")])
b11cae9e 3634\f
3635;; Shift and rotation insns
3636
a2cd141b 3637(define_expand "ashldi3"
3638 [(set (match_operand:DI 0 "s_register_operand" "")
3639 (ashift:DI (match_operand:DI 1 "s_register_operand" "")
aa06c51c 3640 (match_operand:SI 2 "general_operand" "")))]
25f905c2 3641 "TARGET_32BIT"
a2cd141b 3642 "
aa06c51c 3643 if (TARGET_NEON)
3644 {
3645 /* Delay the decision whether to use NEON or core-regs until
3646 register allocation. */
3647 emit_insn (gen_ashldi3_neon (operands[0], operands[1], operands[2]));
3648 DONE;
3649 }
3650 else
3651 {
3652 /* Only the NEON case can handle in-memory shift counts. */
3653 if (!reg_or_int_operand (operands[2], SImode))
3654 operands[2] = force_reg (SImode, operands[2]);
3655 }
3656
b805622c 3657 if (!CONST_INT_P (operands[2]) && TARGET_REALLY_IWMMXT)
ffcc986d 3658 ; /* No special preparation statements; expand pattern as above. */
3659 else
a2cd141b 3660 {
ffcc986d 3661 rtx scratch1, scratch2;
3662
3663 if (CONST_INT_P (operands[2])
3664 && (HOST_WIDE_INT) INTVAL (operands[2]) == 1)
a2cd141b 3665 {
3666 emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
3667 DONE;
3668 }
ffcc986d 3669
3670 /* Ideally we should use iwmmxt here if we could know that operands[1]
3671 ends up already living in an iwmmxt register. Otherwise it's
3672 cheaper to have the alternate code being generated than moving
3673 values to iwmmxt regs and back. */
3674
3675 /* If we're optimizing for size, we prefer the libgcc calls. */
3676 if (optimize_function_for_size_p (cfun))
3677 FAIL;
3678
3679 /* Expand operation using core-registers.
3680 'FAIL' would achieve the same thing, but this is a bit smarter. */
3681 scratch1 = gen_reg_rtx (SImode);
3682 scratch2 = gen_reg_rtx (SImode);
3683 arm_emit_coreregs_64bit_shift (ASHIFT, operands[0], operands[1],
3684 operands[2], scratch1, scratch2);
3685 DONE;
a2cd141b 3686 }
a2cd141b 3687 "
3688)
3689
2837e3fb 3690(define_insn "arm_ashldi3_1bit"
50ad1bf9 3691 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 3692 (ashift:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 3693 (const_int 1)))
3694 (clobber (reg:CC CC_REGNUM))]
25f905c2 3695 "TARGET_32BIT"
2837e3fb 3696 "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
a2cd141b 3697 [(set_attr "conds" "clob")
1b7da4ac 3698 (set_attr "length" "8")
3699 (set_attr "type" "multiple")]
a2cd141b 3700)
3701
87b22bf7 3702(define_expand "ashlsi3"
cffb2a26 3703 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3704 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
3705 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3706 "TARGET_EITHER"
87b22bf7 3707 "
0438d37f 3708 if (CONST_INT_P (operands[2])
87b22bf7 3709 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3710 {
3711 emit_insn (gen_movsi (operands[0], const0_rtx));
3712 DONE;
3713 }
cffb2a26 3714 "
3715)
3716
a2cd141b 3717(define_expand "ashrdi3"
3718 [(set (match_operand:DI 0 "s_register_operand" "")
3719 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
3720 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3721 "TARGET_32BIT"
a2cd141b 3722 "
aa06c51c 3723 if (TARGET_NEON)
3724 {
3725 /* Delay the decision whether to use NEON or core-regs until
3726 register allocation. */
3727 emit_insn (gen_ashrdi3_neon (operands[0], operands[1], operands[2]));
3728 DONE;
3729 }
3730
b805622c 3731 if (!CONST_INT_P (operands[2]) && TARGET_REALLY_IWMMXT)
ffcc986d 3732 ; /* No special preparation statements; expand pattern as above. */
3733 else
a2cd141b 3734 {
ffcc986d 3735 rtx scratch1, scratch2;
3736
3737 if (CONST_INT_P (operands[2])
3738 && (HOST_WIDE_INT) INTVAL (operands[2]) == 1)
a2cd141b 3739 {
3740 emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
3741 DONE;
3742 }
ffcc986d 3743
3744 /* Ideally we should use iwmmxt here if we could know that operands[1]
3745 ends up already living in an iwmmxt register. Otherwise it's
3746 cheaper to have the alternate code being generated than moving
3747 values to iwmmxt regs and back. */
3748
3749 /* If we're optimizing for size, we prefer the libgcc calls. */
3750 if (optimize_function_for_size_p (cfun))
3751 FAIL;
3752
3753 /* Expand operation using core-registers.
3754 'FAIL' would achieve the same thing, but this is a bit smarter. */
3755 scratch1 = gen_reg_rtx (SImode);
3756 scratch2 = gen_reg_rtx (SImode);
3757 arm_emit_coreregs_64bit_shift (ASHIFTRT, operands[0], operands[1],
3758 operands[2], scratch1, scratch2);
3759 DONE;
a2cd141b 3760 }
a2cd141b 3761 "
3762)
3763
2837e3fb 3764(define_insn "arm_ashrdi3_1bit"
50ad1bf9 3765 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 3766 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 3767 (const_int 1)))
3768 (clobber (reg:CC CC_REGNUM))]
25f905c2 3769 "TARGET_32BIT"
2837e3fb 3770 "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
a2cd141b 3771 [(set_attr "conds" "clob")
1b7da4ac 3772 (set_attr "length" "8")
3773 (set_attr "type" "multiple")]
a2cd141b 3774)
3775
87b22bf7 3776(define_expand "ashrsi3"
cffb2a26 3777 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3778 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
3779 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3780 "TARGET_EITHER"
87b22bf7 3781 "
0438d37f 3782 if (CONST_INT_P (operands[2])
87b22bf7 3783 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3784 operands[2] = GEN_INT (31);
cffb2a26 3785 "
3786)
3787
a2cd141b 3788(define_expand "lshrdi3"
3789 [(set (match_operand:DI 0 "s_register_operand" "")
3790 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
3791 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3792 "TARGET_32BIT"
a2cd141b 3793 "
aa06c51c 3794 if (TARGET_NEON)
3795 {
3796 /* Delay the decision whether to use NEON or core-regs until
3797 register allocation. */
3798 emit_insn (gen_lshrdi3_neon (operands[0], operands[1], operands[2]));
3799 DONE;
3800 }
3801
b805622c 3802 if (!CONST_INT_P (operands[2]) && TARGET_REALLY_IWMMXT)
ffcc986d 3803 ; /* No special preparation statements; expand pattern as above. */
3804 else
a2cd141b 3805 {
ffcc986d 3806 rtx scratch1, scratch2;
3807
3808 if (CONST_INT_P (operands[2])
3809 && (HOST_WIDE_INT) INTVAL (operands[2]) == 1)
a2cd141b 3810 {
3811 emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
3812 DONE;
3813 }
ffcc986d 3814
3815 /* Ideally we should use iwmmxt here if we could know that operands[1]
3816 ends up already living in an iwmmxt register. Otherwise it's
3817 cheaper to have the alternate code being generated than moving
3818 values to iwmmxt regs and back. */
3819
3820 /* If we're optimizing for size, we prefer the libgcc calls. */
3821 if (optimize_function_for_size_p (cfun))
3822 FAIL;
3823
3824 /* Expand operation using core-registers.
3825 'FAIL' would achieve the same thing, but this is a bit smarter. */
3826 scratch1 = gen_reg_rtx (SImode);
3827 scratch2 = gen_reg_rtx (SImode);
3828 arm_emit_coreregs_64bit_shift (LSHIFTRT, operands[0], operands[1],
3829 operands[2], scratch1, scratch2);
3830 DONE;
a2cd141b 3831 }
a2cd141b 3832 "
3833)
3834
2837e3fb 3835(define_insn "arm_lshrdi3_1bit"
50ad1bf9 3836 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 3837 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 3838 (const_int 1)))
3839 (clobber (reg:CC CC_REGNUM))]
25f905c2 3840 "TARGET_32BIT"
2837e3fb 3841 "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
a2cd141b 3842 [(set_attr "conds" "clob")
1b7da4ac 3843 (set_attr "length" "8")
3844 (set_attr "type" "multiple")]
a2cd141b 3845)
3846
87b22bf7 3847(define_expand "lshrsi3"
cffb2a26 3848 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3849 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
3850 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3851 "TARGET_EITHER"
87b22bf7 3852 "
0438d37f 3853 if (CONST_INT_P (operands[2])
87b22bf7 3854 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3855 {
3856 emit_insn (gen_movsi (operands[0], const0_rtx));
3857 DONE;
3858 }
cffb2a26 3859 "
3860)
3861
87b22bf7 3862(define_expand "rotlsi3"
cffb2a26 3863 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3864 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
3865 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3866 "TARGET_32BIT"
87b22bf7 3867 "
0438d37f 3868 if (CONST_INT_P (operands[2]))
87b22bf7 3869 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
3870 else
b11cae9e 3871 {
87b22bf7 3872 rtx reg = gen_reg_rtx (SImode);
3873 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
3874 operands[2] = reg;
b11cae9e 3875 }
cffb2a26 3876 "
3877)
9c08d1fa 3878
87b22bf7 3879(define_expand "rotrsi3"
cffb2a26 3880 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3881 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
3882 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3883 "TARGET_EITHER"
87b22bf7 3884 "
25f905c2 3885 if (TARGET_32BIT)
cffb2a26 3886 {
0438d37f 3887 if (CONST_INT_P (operands[2])
cffb2a26 3888 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3889 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
3890 }
25f905c2 3891 else /* TARGET_THUMB1 */
cffb2a26 3892 {
0438d37f 3893 if (CONST_INT_P (operands [2]))
cffb2a26 3894 operands [2] = force_reg (SImode, operands[2]);
3895 }
3896 "
3897)
87b22bf7 3898
cffb2a26 3899(define_insn "*arm_shiftsi3"
88c29385 3900 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r,r")
cffb2a26 3901 (match_operator:SI 3 "shift_operator"
88c29385 3902 [(match_operand:SI 1 "s_register_operand" "0,l,r,r")
3903 (match_operand:SI 2 "reg_or_int_operand" "l,M,M,r")]))]
25f905c2 3904 "TARGET_32BIT"
3905 "* return arm_output_shift(operands, 0);"
344495ea 3906 [(set_attr "predicable" "yes")
88c29385 3907 (set_attr "arch" "t2,t2,*,*")
3908 (set_attr "predicable_short_it" "yes,yes,no,no")
7c36fe71 3909 (set_attr "length" "4")
331beb1a 3910 (set_attr "shift" "1")
88c29385 3911 (set_attr "type" "alu_shift_reg,alu_shift_imm,alu_shift_imm,alu_shift_reg")]
6c4c2133 3912)
87b22bf7 3913
f7fbdd4a 3914(define_insn "*shiftsi3_compare0"
bd5b4116 3915 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 3916 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
6b6abc9c 3917 [(match_operand:SI 1 "s_register_operand" "r,r")
3918 (match_operand:SI 2 "arm_rhs_operand" "M,r")])
9c08d1fa 3919 (const_int 0)))
6b6abc9c 3920 (set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 3921 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
25f905c2 3922 "TARGET_32BIT"
3923 "* return arm_output_shift(operands, 1);"
344495ea 3924 [(set_attr "conds" "set")
331beb1a 3925 (set_attr "shift" "1")
d82e788e 3926 (set_attr "type" "alus_shift_imm,alus_shift_reg")]
0d66636f 3927)
9c08d1fa 3928
f7fbdd4a 3929(define_insn "*shiftsi3_compare0_scratch"
bd5b4116 3930 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 3931 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
6b6abc9c 3932 [(match_operand:SI 1 "s_register_operand" "r,r")
3933 (match_operand:SI 2 "arm_rhs_operand" "M,r")])
9c08d1fa 3934 (const_int 0)))
6b6abc9c 3935 (clobber (match_scratch:SI 0 "=r,r"))]
25f905c2 3936 "TARGET_32BIT"
3937 "* return arm_output_shift(operands, 1);"
344495ea 3938 [(set_attr "conds" "set")
6b6abc9c 3939 (set_attr "shift" "1")
d82e788e 3940 (set_attr "type" "shift_imm,shift_reg")]
0d66636f 3941)
9c08d1fa 3942
d5d4dc8d 3943(define_insn "*not_shiftsi"
3944 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 3945 (not:SI (match_operator:SI 3 "shift_operator"
d5d4dc8d 3946 [(match_operand:SI 1 "s_register_operand" "r,r")
3947 (match_operand:SI 2 "shift_amount_operand" "M,rM")])))]
3948 "TARGET_32BIT"
6c4c2133 3949 "mvn%?\\t%0, %1%S3"
344495ea 3950 [(set_attr "predicable" "yes")
d952d547 3951 (set_attr "predicable_short_it" "no")
331beb1a 3952 (set_attr "shift" "1")
d5d4dc8d 3953 (set_attr "arch" "32,a")
1aed5204 3954 (set_attr "type" "mvn_shift,mvn_shift_reg")])
9c08d1fa 3955
d5d4dc8d 3956(define_insn "*not_shiftsi_compare0"
bd5b4116 3957 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 3958 (compare:CC_NOOV
3959 (not:SI (match_operator:SI 3 "shift_operator"
3960 [(match_operand:SI 1 "s_register_operand" "r,r")
3961 (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
3962 (const_int 0)))
3963 (set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 3964 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
d5d4dc8d 3965 "TARGET_32BIT"
25f905c2 3966 "mvn%.\\t%0, %1%S3"
344495ea 3967 [(set_attr "conds" "set")
331beb1a 3968 (set_attr "shift" "1")
d5d4dc8d 3969 (set_attr "arch" "32,a")
1aed5204 3970 (set_attr "type" "mvn_shift,mvn_shift_reg")])
9c08d1fa 3971
d5d4dc8d 3972(define_insn "*not_shiftsi_compare0_scratch"
bd5b4116 3973 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 3974 (compare:CC_NOOV
3975 (not:SI (match_operator:SI 3 "shift_operator"
3976 [(match_operand:SI 1 "s_register_operand" "r,r")
3977 (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
3978 (const_int 0)))
3979 (clobber (match_scratch:SI 0 "=r,r"))]
3980 "TARGET_32BIT"
25f905c2 3981 "mvn%.\\t%0, %1%S3"
344495ea 3982 [(set_attr "conds" "set")
331beb1a 3983 (set_attr "shift" "1")
d5d4dc8d 3984 (set_attr "arch" "32,a")
1aed5204 3985 (set_attr "type" "mvn_shift,mvn_shift_reg")])
9c08d1fa 3986
cffb2a26 3987;; We don't really have extzv, but defining this using shifts helps
3988;; to reduce register pressure later on.
3989
3990(define_expand "extzv"
eb04cafb 3991 [(set (match_operand 0 "s_register_operand" "")
3992 (zero_extract (match_operand 1 "nonimmediate_operand" "")
3993 (match_operand 2 "const_int_operand" "")
3994 (match_operand 3 "const_int_operand" "")))]
8b054d5a 3995 "TARGET_THUMB1 || arm_arch_thumb2"
cffb2a26 3996 "
3997 {
3998 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
3999 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
4000
8b054d5a 4001 if (arm_arch_thumb2)
4002 {
eb04cafb 4003 HOST_WIDE_INT width = INTVAL (operands[2]);
4004 HOST_WIDE_INT bitpos = INTVAL (operands[3]);
4005
4006 if (unaligned_access && MEM_P (operands[1])
4007 && (width == 16 || width == 32) && (bitpos % BITS_PER_UNIT) == 0)
4008 {
4009 rtx base_addr;
4010
4011 if (BYTES_BIG_ENDIAN)
4012 bitpos = GET_MODE_BITSIZE (GET_MODE (operands[0])) - width
4013 - bitpos;
4014
4015 if (width == 32)
4016 {
4017 base_addr = adjust_address (operands[1], SImode,
4018 bitpos / BITS_PER_UNIT);
4019 emit_insn (gen_unaligned_loadsi (operands[0], base_addr));
4020 }
4021 else
4022 {
4023 rtx dest = operands[0];
4024 rtx tmp = gen_reg_rtx (SImode);
4025
4026 /* We may get a paradoxical subreg here. Strip it off. */
4027 if (GET_CODE (dest) == SUBREG
4028 && GET_MODE (dest) == SImode
4029 && GET_MODE (SUBREG_REG (dest)) == HImode)
4030 dest = SUBREG_REG (dest);
4031
4032 if (GET_MODE_BITSIZE (GET_MODE (dest)) != width)
4033 FAIL;
4034
4035 base_addr = adjust_address (operands[1], HImode,
4036 bitpos / BITS_PER_UNIT);
4037 emit_insn (gen_unaligned_loadhiu (tmp, base_addr));
4038 emit_move_insn (gen_lowpart (SImode, dest), tmp);
4039 }
4040 DONE;
4041 }
4042 else if (s_register_operand (operands[1], GET_MODE (operands[1])))
4043 {
4044 emit_insn (gen_extzv_t2 (operands[0], operands[1], operands[2],
4045 operands[3]));
4046 DONE;
4047 }
4048 else
4049 FAIL;
8b054d5a 4050 }
eb04cafb 4051
4052 if (!s_register_operand (operands[1], GET_MODE (operands[1])))
4053 FAIL;
8b054d5a 4054
cffb2a26 4055 operands[3] = GEN_INT (rshift);
4056
4057 if (lshift == 0)
4058 {
4059 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
4060 DONE;
4061 }
4062
eb04cafb 4063 emit_insn (gen_extzv_t1 (operands[0], operands[1], GEN_INT (lshift),
4064 operands[3], gen_reg_rtx (SImode)));
4065 DONE;
215b30b3 4066 }"
cffb2a26 4067)
4068
eb04cafb 4069;; Helper for extzv, for the Thumb-1 register-shifts case.
4070
4071(define_expand "extzv_t1"
4072 [(set (match_operand:SI 4 "s_register_operand" "")
4073 (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "")
4074 (match_operand:SI 2 "const_int_operand" "")))
4075 (set (match_operand:SI 0 "s_register_operand" "")
4076 (lshiftrt:SI (match_dup 4)
4077 (match_operand:SI 3 "const_int_operand" "")))]
4078 "TARGET_THUMB1"
4079 "")
4080
4081(define_expand "extv"
4082 [(set (match_operand 0 "s_register_operand" "")
4083 (sign_extract (match_operand 1 "nonimmediate_operand" "")
4084 (match_operand 2 "const_int_operand" "")
4085 (match_operand 3 "const_int_operand" "")))]
4086 "arm_arch_thumb2"
4087{
4088 HOST_WIDE_INT width = INTVAL (operands[2]);
4089 HOST_WIDE_INT bitpos = INTVAL (operands[3]);
4090
4091 if (unaligned_access && MEM_P (operands[1]) && (width == 16 || width == 32)
4092 && (bitpos % BITS_PER_UNIT) == 0)
4093 {
4094 rtx base_addr;
4095
4096 if (BYTES_BIG_ENDIAN)
4097 bitpos = GET_MODE_BITSIZE (GET_MODE (operands[0])) - width - bitpos;
4098
4099 if (width == 32)
4100 {
4101 base_addr = adjust_address (operands[1], SImode,
4102 bitpos / BITS_PER_UNIT);
4103 emit_insn (gen_unaligned_loadsi (operands[0], base_addr));
4104 }
4105 else
4106 {
4107 rtx dest = operands[0];
4108 rtx tmp = gen_reg_rtx (SImode);
4109
4110 /* We may get a paradoxical subreg here. Strip it off. */
4111 if (GET_CODE (dest) == SUBREG
4112 && GET_MODE (dest) == SImode
4113 && GET_MODE (SUBREG_REG (dest)) == HImode)
4114 dest = SUBREG_REG (dest);
4115
4116 if (GET_MODE_BITSIZE (GET_MODE (dest)) != width)
4117 FAIL;
4118
4119 base_addr = adjust_address (operands[1], HImode,
4120 bitpos / BITS_PER_UNIT);
4121 emit_insn (gen_unaligned_loadhis (tmp, base_addr));
4122 emit_move_insn (gen_lowpart (SImode, dest), tmp);
4123 }
4124
4125 DONE;
4126 }
4127 else if (!s_register_operand (operands[1], GET_MODE (operands[1])))
4128 FAIL;
4129 else if (GET_MODE (operands[0]) == SImode
4130 && GET_MODE (operands[1]) == SImode)
4131 {
4132 emit_insn (gen_extv_regsi (operands[0], operands[1], operands[2],
4133 operands[3]));
4134 DONE;
4135 }
4136
4137 FAIL;
4138})
4139
4140; Helper to expand register forms of extv with the proper modes.
4141
4142(define_expand "extv_regsi"
4143 [(set (match_operand:SI 0 "s_register_operand" "")
4144 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
4145 (match_operand 2 "const_int_operand" "")
4146 (match_operand 3 "const_int_operand" "")))]
4147 ""
4148{
4149})
4150
4151; ARMv6+ unaligned load/store instructions (used for packed structure accesses).
4152
4153(define_insn "unaligned_loadsi"
4154 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4155 (unspec:SI [(match_operand:SI 1 "memory_operand" "Uw,m")]
4156 UNSPEC_UNALIGNED_LOAD))]
4157 "unaligned_access && TARGET_32BIT"
4158 "ldr%?\t%0, %1\t@ unaligned"
4159 [(set_attr "arch" "t2,any")
4160 (set_attr "length" "2,4")
4161 (set_attr "predicable" "yes")
d952d547 4162 (set_attr "predicable_short_it" "yes,no")
eb04cafb 4163 (set_attr "type" "load1")])
4164
4165(define_insn "unaligned_loadhis"
4166 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4167 (sign_extend:SI
e3f4ccee 4168 (unspec:HI [(match_operand:HI 1 "memory_operand" "Uw,Uh")]
eb04cafb 4169 UNSPEC_UNALIGNED_LOAD)))]
4170 "unaligned_access && TARGET_32BIT"
4171 "ldr%(sh%)\t%0, %1\t@ unaligned"
4172 [(set_attr "arch" "t2,any")
4173 (set_attr "length" "2,4")
4174 (set_attr "predicable" "yes")
d952d547 4175 (set_attr "predicable_short_it" "yes,no")
eb04cafb 4176 (set_attr "type" "load_byte")])
4177
4178(define_insn "unaligned_loadhiu"
4179 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4180 (zero_extend:SI
4181 (unspec:HI [(match_operand:HI 1 "memory_operand" "Uw,m")]
4182 UNSPEC_UNALIGNED_LOAD)))]
4183 "unaligned_access && TARGET_32BIT"
4184 "ldr%(h%)\t%0, %1\t@ unaligned"
4185 [(set_attr "arch" "t2,any")
4186 (set_attr "length" "2,4")
4187 (set_attr "predicable" "yes")
d952d547 4188 (set_attr "predicable_short_it" "yes,no")
eb04cafb 4189 (set_attr "type" "load_byte")])
4190
4191(define_insn "unaligned_storesi"
4192 [(set (match_operand:SI 0 "memory_operand" "=Uw,m")
4193 (unspec:SI [(match_operand:SI 1 "s_register_operand" "l,r")]
4194 UNSPEC_UNALIGNED_STORE))]
4195 "unaligned_access && TARGET_32BIT"
4196 "str%?\t%1, %0\t@ unaligned"
4197 [(set_attr "arch" "t2,any")
4198 (set_attr "length" "2,4")
4199 (set_attr "predicable" "yes")
d952d547 4200 (set_attr "predicable_short_it" "yes,no")
eb04cafb 4201 (set_attr "type" "store1")])
4202
4203(define_insn "unaligned_storehi"
4204 [(set (match_operand:HI 0 "memory_operand" "=Uw,m")
4205 (unspec:HI [(match_operand:HI 1 "s_register_operand" "l,r")]
4206 UNSPEC_UNALIGNED_STORE))]
4207 "unaligned_access && TARGET_32BIT"
4208 "str%(h%)\t%1, %0\t@ unaligned"
4209 [(set_attr "arch" "t2,any")
4210 (set_attr "length" "2,4")
4211 (set_attr "predicable" "yes")
d952d547 4212 (set_attr "predicable_short_it" "yes,no")
eb04cafb 4213 (set_attr "type" "store1")])
4214
ae51a965 4215;; Unaligned double-word load and store.
4216;; Split after reload into two unaligned single-word accesses.
4217;; It prevents lower_subreg from splitting some other aligned
4218;; double-word accesses too early. Used for internal memcpy.
4219
4220(define_insn_and_split "unaligned_loaddi"
4221 [(set (match_operand:DI 0 "s_register_operand" "=l,r")
4222 (unspec:DI [(match_operand:DI 1 "memory_operand" "o,o")]
4223 UNSPEC_UNALIGNED_LOAD))]
4224 "unaligned_access && TARGET_32BIT"
4225 "#"
4226 "&& reload_completed"
4227 [(set (match_dup 0) (unspec:SI [(match_dup 1)] UNSPEC_UNALIGNED_LOAD))
4228 (set (match_dup 2) (unspec:SI [(match_dup 3)] UNSPEC_UNALIGNED_LOAD))]
4229 {
4230 operands[2] = gen_highpart (SImode, operands[0]);
4231 operands[0] = gen_lowpart (SImode, operands[0]);
4232 operands[3] = gen_highpart (SImode, operands[1]);
4233 operands[1] = gen_lowpart (SImode, operands[1]);
4234
4235 /* If the first destination register overlaps with the base address,
4236 swap the order in which the loads are emitted. */
4237 if (reg_overlap_mentioned_p (operands[0], operands[1]))
4238 {
f145bcba 4239 std::swap (operands[1], operands[3]);
4240 std::swap (operands[0], operands[2]);
ae51a965 4241 }
4242 }
4243 [(set_attr "arch" "t2,any")
4244 (set_attr "length" "4,8")
4245 (set_attr "predicable" "yes")
4246 (set_attr "type" "load2")])
4247
4248(define_insn_and_split "unaligned_storedi"
4249 [(set (match_operand:DI 0 "memory_operand" "=o,o")
4250 (unspec:DI [(match_operand:DI 1 "s_register_operand" "l,r")]
4251 UNSPEC_UNALIGNED_STORE))]
4252 "unaligned_access && TARGET_32BIT"
4253 "#"
4254 "&& reload_completed"
4255 [(set (match_dup 0) (unspec:SI [(match_dup 1)] UNSPEC_UNALIGNED_STORE))
4256 (set (match_dup 2) (unspec:SI [(match_dup 3)] UNSPEC_UNALIGNED_STORE))]
4257 {
4258 operands[2] = gen_highpart (SImode, operands[0]);
4259 operands[0] = gen_lowpart (SImode, operands[0]);
4260 operands[3] = gen_highpart (SImode, operands[1]);
4261 operands[1] = gen_lowpart (SImode, operands[1]);
4262 }
4263 [(set_attr "arch" "t2,any")
4264 (set_attr "length" "4,8")
4265 (set_attr "predicable" "yes")
4266 (set_attr "type" "store2")])
4267
4268
eb04cafb 4269(define_insn "*extv_reg"
8b054d5a 4270 [(set (match_operand:SI 0 "s_register_operand" "=r")
4271 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
809003b3 4272 (match_operand:SI 2 "const_int_M_operand" "M")
4273 (match_operand:SI 3 "const_int_M_operand" "M")))]
8b054d5a 4274 "arm_arch_thumb2"
4275 "sbfx%?\t%0, %1, %3, %2"
4276 [(set_attr "length" "4")
d952d547 4277 (set_attr "predicable" "yes")
d82e788e 4278 (set_attr "predicable_short_it" "no")
4279 (set_attr "type" "bfm")]
8b054d5a 4280)
4281
4282(define_insn "extzv_t2"
4283 [(set (match_operand:SI 0 "s_register_operand" "=r")
4284 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "r")
809003b3 4285 (match_operand:SI 2 "const_int_M_operand" "M")
4286 (match_operand:SI 3 "const_int_M_operand" "M")))]
8b054d5a 4287 "arm_arch_thumb2"
4288 "ubfx%?\t%0, %1, %3, %2"
4289 [(set_attr "length" "4")
d952d547 4290 (set_attr "predicable" "yes")
d82e788e 4291 (set_attr "predicable_short_it" "no")
4292 (set_attr "type" "bfm")]
8b054d5a 4293)
4294
7d3cda8c 4295
4296;; Division instructions
4297(define_insn "divsi3"
4298 [(set (match_operand:SI 0 "s_register_operand" "=r")
4299 (div:SI (match_operand:SI 1 "s_register_operand" "r")
4300 (match_operand:SI 2 "s_register_operand" "r")))]
4301 "TARGET_IDIV"
4302 "sdiv%?\t%0, %1, %2"
4303 [(set_attr "predicable" "yes")
d952d547 4304 (set_attr "predicable_short_it" "no")
9da0ec36 4305 (set_attr "type" "sdiv")]
7d3cda8c 4306)
4307
4308(define_insn "udivsi3"
4309 [(set (match_operand:SI 0 "s_register_operand" "=r")
4310 (udiv:SI (match_operand:SI 1 "s_register_operand" "r")
4311 (match_operand:SI 2 "s_register_operand" "r")))]
4312 "TARGET_IDIV"
4313 "udiv%?\t%0, %1, %2"
4314 [(set_attr "predicable" "yes")
d952d547 4315 (set_attr "predicable_short_it" "no")
9da0ec36 4316 (set_attr "type" "udiv")]
7d3cda8c 4317)
4318
b11cae9e 4319\f
4320;; Unary arithmetic insns
4321
cffb2a26 4322(define_expand "negdi2"
4323 [(parallel
8135a42b 4324 [(set (match_operand:DI 0 "s_register_operand" "")
4325 (neg:DI (match_operand:DI 1 "s_register_operand" "")))
bd5b4116 4326 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 4327 "TARGET_EITHER"
774d2fbb 4328 {
4329 if (TARGET_NEON)
4330 {
4331 emit_insn (gen_negdi2_neon (operands[0], operands[1]));
4332 DONE;
4333 }
4334 }
cffb2a26 4335)
4336
4337;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
e5fea38e 4338;; The first alternative allows the common case of a *full* overlap.
ba6a3b2f 4339(define_insn_and_split "*arm_negdi2"
458a8706 4340 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 4341 (neg:DI (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 4342 (clobber (reg:CC CC_REGNUM))]
cffb2a26 4343 "TARGET_ARM"
ba6a3b2f 4344 "#" ; "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
4345 "&& reload_completed"
4346 [(parallel [(set (reg:CC CC_REGNUM)
4347 (compare:CC (const_int 0) (match_dup 1)))
4348 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 1)))])
4349 (set (match_dup 2) (minus:SI (minus:SI (const_int 0) (match_dup 3))
4350 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
4351 {
4352 operands[2] = gen_highpart (SImode, operands[0]);
4353 operands[0] = gen_lowpart (SImode, operands[0]);
4354 operands[3] = gen_highpart (SImode, operands[1]);
4355 operands[1] = gen_lowpart (SImode, operands[1]);
4356 }
cffb2a26 4357 [(set_attr "conds" "clob")
1b7da4ac 4358 (set_attr "length" "8")
4359 (set_attr "type" "multiple")]
cffb2a26 4360)
b11cae9e 4361
cffb2a26 4362(define_expand "negsi2"
4363 [(set (match_operand:SI 0 "s_register_operand" "")
4364 (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
4365 "TARGET_EITHER"
b11cae9e 4366 ""
cffb2a26 4367)
4368
4369(define_insn "*arm_negsi2"
d952d547 4370 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4371 (neg:SI (match_operand:SI 1 "s_register_operand" "l,r")))]
25f905c2 4372 "TARGET_32BIT"
cffb2a26 4373 "rsb%?\\t%0, %1, #0"
d952d547 4374 [(set_attr "predicable" "yes")
4375 (set_attr "predicable_short_it" "yes,no")
4376 (set_attr "arch" "t2,*")
1b7da4ac 4377 (set_attr "length" "4")
112eda6f 4378 (set_attr "type" "alu_sreg")]
cffb2a26 4379)
4380
604f3a0a 4381(define_expand "negsf2"
4382 [(set (match_operand:SF 0 "s_register_operand" "")
4383 (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
994606f8 4384 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
604f3a0a 4385 ""
4386)
4387
4388(define_expand "negdf2"
4389 [(set (match_operand:DF 0 "s_register_operand" "")
4390 (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
994606f8 4391 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
604f3a0a 4392 "")
4393
7eaf2be0 4394(define_insn_and_split "*zextendsidi_negsi"
4395 [(set (match_operand:DI 0 "s_register_operand" "=r")
4396 (zero_extend:DI (neg:SI (match_operand:SI 1 "s_register_operand" "r"))))]
4397 "TARGET_32BIT"
4398 "#"
4399 ""
4400 [(set (match_dup 2)
4401 (neg:SI (match_dup 1)))
4402 (set (match_dup 3)
4403 (const_int 0))]
4404 {
4405 operands[2] = gen_lowpart (SImode, operands[0]);
4406 operands[3] = gen_highpart (SImode, operands[0]);
4407 }
4408 [(set_attr "length" "8")
4409 (set_attr "type" "multiple")]
4410)
4411
83e2b922 4412;; Negate an extended 32-bit value.
4413(define_insn_and_split "*negdi_extendsidi"
61fa8ff2 4414 [(set (match_operand:DI 0 "s_register_operand" "=l,r")
4415 (neg:DI (sign_extend:DI
4416 (match_operand:SI 1 "s_register_operand" "l,r"))))
83e2b922 4417 (clobber (reg:CC CC_REGNUM))]
4418 "TARGET_32BIT"
61fa8ff2 4419 "#"
83e2b922 4420 "&& reload_completed"
4421 [(const_int 0)]
4422 {
61fa8ff2 4423 rtx low = gen_lowpart (SImode, operands[0]);
4424 rtx high = gen_highpart (SImode, operands[0]);
4425
4426 if (reg_overlap_mentioned_p (low, operands[1]))
4427 {
4428 /* Input overlaps the low word of the output. Use:
4429 asr Rhi, Rin, #31
4430 rsbs Rlo, Rin, #0
4431 rsc Rhi, Rhi, #0 (thumb2: sbc Rhi, Rhi, Rhi, lsl #1). */
4432 rtx cc_reg = gen_rtx_REG (CC_Cmode, CC_REGNUM);
4433
4434 emit_insn (gen_rtx_SET (VOIDmode, high,
4435 gen_rtx_ASHIFTRT (SImode, operands[1],
4436 GEN_INT (31))));
4437
4438 emit_insn (gen_subsi3_compare (low, const0_rtx, operands[1]));
4439 if (TARGET_ARM)
4440 emit_insn (gen_rtx_SET (VOIDmode, high,
4441 gen_rtx_MINUS (SImode,
4442 gen_rtx_MINUS (SImode,
4443 const0_rtx,
4444 high),
4445 gen_rtx_LTU (SImode,
4446 cc_reg,
4447 const0_rtx))));
4448 else
4449 {
4450 rtx two_x = gen_rtx_ASHIFT (SImode, high, GEN_INT (1));
4451 emit_insn (gen_rtx_SET (VOIDmode, high,
4452 gen_rtx_MINUS (SImode,
4453 gen_rtx_MINUS (SImode,
4454 high,
4455 two_x),
4456 gen_rtx_LTU (SImode,
4457 cc_reg,
4458 const0_rtx))));
4459 }
4460 }
4461 else
4462 {
4463 /* No overlap, or overlap on high word. Use:
4464 rsb Rlo, Rin, #0
4465 bic Rhi, Rlo, Rin
4466 asr Rhi, Rhi, #31
4467 Flags not needed for this sequence. */
4468 emit_insn (gen_rtx_SET (VOIDmode, low,
4469 gen_rtx_NEG (SImode, operands[1])));
4470 emit_insn (gen_rtx_SET (VOIDmode, high,
4471 gen_rtx_AND (SImode,
4472 gen_rtx_NOT (SImode, operands[1]),
4473 low)));
4474 emit_insn (gen_rtx_SET (VOIDmode, high,
4475 gen_rtx_ASHIFTRT (SImode, high,
4476 GEN_INT (31))));
4477 }
4478 DONE;
83e2b922 4479 }
61fa8ff2 4480 [(set_attr "length" "12")
4481 (set_attr "arch" "t2,*")
1b7da4ac 4482 (set_attr "type" "multiple")]
83e2b922 4483)
4484
4485(define_insn_and_split "*negdi_zero_extendsidi"
4486 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
4487 (neg:DI (zero_extend:DI (match_operand:SI 1 "s_register_operand" "0,r"))))
4488 (clobber (reg:CC CC_REGNUM))]
4489 "TARGET_32BIT"
4490 "#" ; "rsbs\\t%Q0, %1, #0\;sbc\\t%R0,%R0,%R0"
4491 ;; Don't care what register is input to sbc,
4492 ;; since we just just need to propagate the carry.
4493 "&& reload_completed"
4494 [(parallel [(set (reg:CC CC_REGNUM)
4495 (compare:CC (const_int 0) (match_dup 1)))
4496 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 1)))])
4497 (set (match_dup 2) (minus:SI (minus:SI (match_dup 2) (match_dup 2))
4498 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
4499 {
4500 operands[2] = gen_highpart (SImode, operands[0]);
4501 operands[0] = gen_lowpart (SImode, operands[0]);
4502 }
4503 [(set_attr "conds" "clob")
1b7da4ac 4504 (set_attr "length" "8")
4505 (set_attr "type" "multiple")] ;; length in thumb is 4
83e2b922 4506)
4507
9c08d1fa 4508;; abssi2 doesn't really clobber the condition codes if a different register
4509;; is being set. To keep things simple, assume during rtl manipulations that
4510;; it does, but tell the final scan operator the truth. Similarly for
4511;; (neg (abs...))
4512
604f3a0a 4513(define_expand "abssi2"
4514 [(parallel
4515 [(set (match_operand:SI 0 "s_register_operand" "")
4516 (abs:SI (match_operand:SI 1 "s_register_operand" "")))
ba156559 4517 (clobber (match_dup 2))])]
4518 "TARGET_EITHER"
4519 "
25f905c2 4520 if (TARGET_THUMB1)
ba156559 4521 operands[2] = gen_rtx_SCRATCH (SImode);
4522 else
4523 operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
4524")
604f3a0a 4525
ba6a3b2f 4526(define_insn_and_split "*arm_abssi2"
ba156559 4527 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
9c08d1fa 4528 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
bd5b4116 4529 (clobber (reg:CC CC_REGNUM))]
cffb2a26 4530 "TARGET_ARM"
ba6a3b2f 4531 "#"
4532 "&& reload_completed"
4533 [(const_int 0)]
4534 {
4535 /* if (which_alternative == 0) */
4536 if (REGNO(operands[0]) == REGNO(operands[1]))
4537 {
4538 /* Emit the pattern:
4539 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
4540 [(set (reg:CC CC_REGNUM)
4541 (compare:CC (match_dup 0) (const_int 0)))
4542 (cond_exec (lt:CC (reg:CC CC_REGNUM) (const_int 0))
4543 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 1))))]
4544 */
4545 emit_insn (gen_rtx_SET (VOIDmode,
4546 gen_rtx_REG (CCmode, CC_REGNUM),
4547 gen_rtx_COMPARE (CCmode, operands[0], const0_rtx)));
4548 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
4549 (gen_rtx_LT (SImode,
4550 gen_rtx_REG (CCmode, CC_REGNUM),
4551 const0_rtx)),
4552 (gen_rtx_SET (VOIDmode,
4553 operands[0],
4554 (gen_rtx_MINUS (SImode,
4555 const0_rtx,
4556 operands[1]))))));
4557 DONE;
4558 }
4559 else
4560 {
4561 /* Emit the pattern:
4562 alt1: eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31
4563 [(set (match_dup 0)
4564 (xor:SI (match_dup 1)
4565 (ashiftrt:SI (match_dup 1) (const_int 31))))
4566 (set (match_dup 0)
4567 (minus:SI (match_dup 0)
4568 (ashiftrt:SI (match_dup 1) (const_int 31))))]
4569 */
4570 emit_insn (gen_rtx_SET (VOIDmode,
4571 operands[0],
4572 gen_rtx_XOR (SImode,
4573 gen_rtx_ASHIFTRT (SImode,
4574 operands[1],
4575 GEN_INT (31)),
4576 operands[1])));
4577 emit_insn (gen_rtx_SET (VOIDmode,
4578 operands[0],
4579 gen_rtx_MINUS (SImode,
4580 operands[0],
4581 gen_rtx_ASHIFTRT (SImode,
4582 operands[1],
4583 GEN_INT (31)))));
4584 DONE;
4585 }
4586 }
cffb2a26 4587 [(set_attr "conds" "clob,*")
331beb1a 4588 (set_attr "shift" "1")
2ad08b65 4589 (set_attr "predicable" "no, yes")
1b7da4ac 4590 (set_attr "length" "8")
4591 (set_attr "type" "multiple")]
cffb2a26 4592)
9c08d1fa 4593
ba6a3b2f 4594(define_insn_and_split "*arm_neg_abssi2"
9c08d1fa 4595 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
4596 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
bd5b4116 4597 (clobber (reg:CC CC_REGNUM))]
cffb2a26 4598 "TARGET_ARM"
ba6a3b2f 4599 "#"
4600 "&& reload_completed"
4601 [(const_int 0)]
4602 {
4603 /* if (which_alternative == 0) */
4604 if (REGNO (operands[0]) == REGNO (operands[1]))
4605 {
4606 /* Emit the pattern:
4607 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
4608 */
4609 emit_insn (gen_rtx_SET (VOIDmode,
4610 gen_rtx_REG (CCmode, CC_REGNUM),
4611 gen_rtx_COMPARE (CCmode, operands[0], const0_rtx)));
4612 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
4613 gen_rtx_GT (SImode,
4614 gen_rtx_REG (CCmode, CC_REGNUM),
4615 const0_rtx),
4616 gen_rtx_SET (VOIDmode,
4617 operands[0],
4618 (gen_rtx_MINUS (SImode,
4619 const0_rtx,
4620 operands[1])))));
4621 }
4622 else
4623 {
4624 /* Emit the pattern:
4625 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31
4626 */
4627 emit_insn (gen_rtx_SET (VOIDmode,
4628 operands[0],
4629 gen_rtx_XOR (SImode,
4630 gen_rtx_ASHIFTRT (SImode,
4631 operands[1],
4632 GEN_INT (31)),
4633 operands[1])));
4634 emit_insn (gen_rtx_SET (VOIDmode,
4635 operands[0],
4636 gen_rtx_MINUS (SImode,
4637 gen_rtx_ASHIFTRT (SImode,
4638 operands[1],
4639 GEN_INT (31)),
4640 operands[0])));
4641 }
4642 DONE;
4643 }
cffb2a26 4644 [(set_attr "conds" "clob,*")
331beb1a 4645 (set_attr "shift" "1")
2ad08b65 4646 (set_attr "predicable" "no, yes")
1b7da4ac 4647 (set_attr "length" "8")
4648 (set_attr "type" "multiple")]
cffb2a26 4649)
b11cae9e 4650
604f3a0a 4651(define_expand "abssf2"
4652 [(set (match_operand:SF 0 "s_register_operand" "")
4653 (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
25f905c2 4654 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 4655 "")
4656
604f3a0a 4657(define_expand "absdf2"
4658 [(set (match_operand:DF 0 "s_register_operand" "")
4659 (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 4660 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 4661 "")
4662
7db9af5d 4663(define_expand "sqrtsf2"
4664 [(set (match_operand:SF 0 "s_register_operand" "")
4665 (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
994606f8 4666 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
7db9af5d 4667 "")
9c08d1fa 4668
7db9af5d 4669(define_expand "sqrtdf2"
4670 [(set (match_operand:DF 0 "s_register_operand" "")
4671 (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
994606f8 4672 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
7db9af5d 4673 "")
9c08d1fa 4674
a0f94409 4675(define_insn_and_split "one_cmpldi2"
10efb95f 4676 [(set (match_operand:DI 0 "s_register_operand" "=w,&r,&r,?w")
4677 (not:DI (match_operand:DI 1 "s_register_operand" " w, 0, r, w")))]
25f905c2 4678 "TARGET_32BIT"
10efb95f 4679 "@
4680 vmvn\t%P0, %P1
4681 #
4682 #
4683 vmvn\t%P0, %P1"
4684 "TARGET_32BIT && reload_completed
4685 && arm_general_register_operand (operands[0], DImode)"
a0f94409 4686 [(set (match_dup 0) (not:SI (match_dup 1)))
4687 (set (match_dup 2) (not:SI (match_dup 3)))]
4688 "
4689 {
4690 operands[2] = gen_highpart (SImode, operands[0]);
4691 operands[0] = gen_lowpart (SImode, operands[0]);
4692 operands[3] = gen_highpart (SImode, operands[1]);
4693 operands[1] = gen_lowpart (SImode, operands[1]);
4694 }"
10efb95f 4695 [(set_attr "length" "*,8,8,*")
4696 (set_attr "predicable" "no,yes,yes,no")
32093010 4697 (set_attr "type" "neon_move,multiple,multiple,neon_move")
b6779ddc 4698 (set_attr "arch" "neon_for_64bits,*,*,avoid_neon_for_64bits")]
cffb2a26 4699)
b11cae9e 4700
cffb2a26 4701(define_expand "one_cmplsi2"
4702 [(set (match_operand:SI 0 "s_register_operand" "")
4703 (not:SI (match_operand:SI 1 "s_register_operand" "")))]
4704 "TARGET_EITHER"
b11cae9e 4705 ""
cffb2a26 4706)
4707
4708(define_insn "*arm_one_cmplsi2"
d952d547 4709 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4710 (not:SI (match_operand:SI 1 "s_register_operand" "l,r")))]
25f905c2 4711 "TARGET_32BIT"
cffb2a26 4712 "mvn%?\\t%0, %1"
d2a518d1 4713 [(set_attr "predicable" "yes")
d952d547 4714 (set_attr "predicable_short_it" "yes,no")
4715 (set_attr "arch" "t2,*")
4716 (set_attr "length" "4")
1aed5204 4717 (set_attr "type" "mvn_reg")]
cffb2a26 4718)
4719
f7fbdd4a 4720(define_insn "*notsi_compare0"
bd5b4116 4721 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 4722 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
4723 (const_int 0)))
4724 (set (match_operand:SI 0 "s_register_operand" "=r")
4725 (not:SI (match_dup 1)))]
25f905c2 4726 "TARGET_32BIT"
4727 "mvn%.\\t%0, %1"
d2a518d1 4728 [(set_attr "conds" "set")
1aed5204 4729 (set_attr "type" "mvn_reg")]
cffb2a26 4730)
9c08d1fa 4731
f7fbdd4a 4732(define_insn "*notsi_compare0_scratch"
bd5b4116 4733 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 4734 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
4735 (const_int 0)))
4736 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 4737 "TARGET_32BIT"
4738 "mvn%.\\t%0, %1"
d2a518d1 4739 [(set_attr "conds" "set")
1aed5204 4740 (set_attr "type" "mvn_reg")]
cffb2a26 4741)
b11cae9e 4742\f
4743;; Fixed <--> Floating conversion insns
4744
9b8516be 4745(define_expand "floatsihf2"
4746 [(set (match_operand:HF 0 "general_operand" "")
4747 (float:HF (match_operand:SI 1 "general_operand" "")))]
4748 "TARGET_EITHER"
4749 "
4750 {
4751 rtx op1 = gen_reg_rtx (SFmode);
4752 expand_float (op1, operands[1], 0);
4753 op1 = convert_to_mode (HFmode, op1, 0);
4754 emit_move_insn (operands[0], op1);
4755 DONE;
4756 }"
4757)
4758
4759(define_expand "floatdihf2"
4760 [(set (match_operand:HF 0 "general_operand" "")
4761 (float:HF (match_operand:DI 1 "general_operand" "")))]
4762 "TARGET_EITHER"
4763 "
4764 {
4765 rtx op1 = gen_reg_rtx (SFmode);
4766 expand_float (op1, operands[1], 0);
4767 op1 = convert_to_mode (HFmode, op1, 0);
4768 emit_move_insn (operands[0], op1);
4769 DONE;
4770 }"
4771)
4772
604f3a0a 4773(define_expand "floatsisf2"
4774 [(set (match_operand:SF 0 "s_register_operand" "")
4775 (float:SF (match_operand:SI 1 "s_register_operand" "")))]
25f905c2 4776 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 4777 "
604f3a0a 4778")
4779
604f3a0a 4780(define_expand "floatsidf2"
4781 [(set (match_operand:DF 0 "s_register_operand" "")
4782 (float:DF (match_operand:SI 1 "s_register_operand" "")))]
a50d7267 4783 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 4784 "
604f3a0a 4785")
4786
9b8516be 4787(define_expand "fix_trunchfsi2"
4788 [(set (match_operand:SI 0 "general_operand" "")
4789 (fix:SI (fix:HF (match_operand:HF 1 "general_operand" ""))))]
4790 "TARGET_EITHER"
4791 "
4792 {
4793 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
4794 expand_fix (operands[0], op1, 0);
4795 DONE;
4796 }"
4797)
4798
4799(define_expand "fix_trunchfdi2"
4800 [(set (match_operand:DI 0 "general_operand" "")
4801 (fix:DI (fix:HF (match_operand:HF 1 "general_operand" ""))))]
4802 "TARGET_EITHER"
4803 "
4804 {
4805 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
4806 expand_fix (operands[0], op1, 0);
4807 DONE;
4808 }"
4809)
4810
604f3a0a 4811(define_expand "fix_truncsfsi2"
4812 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 4813 (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" ""))))]
25f905c2 4814 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 4815 "
604f3a0a 4816")
4817
604f3a0a 4818(define_expand "fix_truncdfsi2"
4819 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 4820 (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" ""))))]
a50d7267 4821 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 4822 "
604f3a0a 4823")
4824
f544c6d2 4825;; Truncation insns
b11cae9e 4826
604f3a0a 4827(define_expand "truncdfsf2"
4828 [(set (match_operand:SF 0 "s_register_operand" "")
4829 (float_truncate:SF
4830 (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 4831 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 4832 ""
4833)
9b8516be 4834
4835/* DFmode -> HFmode conversions have to go through SFmode. */
4836(define_expand "truncdfhf2"
4837 [(set (match_operand:HF 0 "general_operand" "")
4838 (float_truncate:HF
4839 (match_operand:DF 1 "general_operand" "")))]
4840 "TARGET_EITHER"
4841 "
4842 {
4843 rtx op1;
4844 op1 = convert_to_mode (SFmode, operands[1], 0);
4845 op1 = convert_to_mode (HFmode, op1, 0);
4846 emit_move_insn (operands[0], op1);
4847 DONE;
4848 }"
4849)
b11cae9e 4850\f
9c08d1fa 4851;; Zero and sign extension instructions.
b11cae9e 4852
848e66ac 4853(define_insn "zero_extend<mode>di2"
6aa689e8 4854 [(set (match_operand:DI 0 "s_register_operand" "=w,r,?r,w")
6d97728e 4855 (zero_extend:DI (match_operand:QHSI 1 "<qhs_zextenddi_op>"
4856 "<qhs_zextenddi_cstr>")))]
848e66ac 4857 "TARGET_32BIT <qhs_zextenddi_cond>"
4858 "#"
6aa689e8 4859 [(set_attr "length" "8,4,8,8")
b6779ddc 4860 (set_attr "arch" "neon_for_64bits,*,*,avoid_neon_for_64bits")
848e66ac 4861 (set_attr "ce_count" "2")
efbb5e19 4862 (set_attr "predicable" "yes")
4863 (set_attr "type" "multiple,mov_reg,multiple,multiple")]
25f905c2 4864)
4865
848e66ac 4866(define_insn "extend<mode>di2"
6aa689e8 4867 [(set (match_operand:DI 0 "s_register_operand" "=w,r,?r,?r,w")
63d204a8 4868 (sign_extend:DI (match_operand:QHSI 1 "<qhs_extenddi_op>"
4869 "<qhs_extenddi_cstr>")))]
848e66ac 4870 "TARGET_32BIT <qhs_sextenddi_cond>"
4871 "#"
6aa689e8 4872 [(set_attr "length" "8,4,8,8,8")
848e66ac 4873 (set_attr "ce_count" "2")
4874 (set_attr "shift" "1")
8012d2c2 4875 (set_attr "predicable" "yes")
1b7da4ac 4876 (set_attr "arch" "neon_for_64bits,*,a,t,avoid_neon_for_64bits")
4877 (set_attr "type" "multiple,mov_reg,multiple,multiple,multiple")]
0d66636f 4878)
9c08d1fa 4879
848e66ac 4880;; Splits for all extensions to DImode
4881(define_split
4882 [(set (match_operand:DI 0 "s_register_operand" "")
4883 (zero_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
6aa689e8 4884 "TARGET_32BIT && reload_completed && !IS_VFP_REGNUM (REGNO (operands[0]))"
848e66ac 4885 [(set (match_dup 0) (match_dup 1))]
4886{
848e66ac 4887 rtx lo_part = gen_lowpart (SImode, operands[0]);
3754d046 4888 machine_mode src_mode = GET_MODE (operands[1]);
848e66ac 4889
4890 if (REG_P (operands[0])
4891 && !reg_overlap_mentioned_p (operands[0], operands[1]))
4892 emit_clobber (operands[0]);
4893 if (!REG_P (lo_part) || src_mode != SImode
4894 || !rtx_equal_p (lo_part, operands[1]))
4895 {
4896 if (src_mode == SImode)
4897 emit_move_insn (lo_part, operands[1]);
4898 else
4899 emit_insn (gen_rtx_SET (VOIDmode, lo_part,
4900 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
4901 operands[1] = lo_part;
4902 }
4903 operands[0] = gen_highpart (SImode, operands[0]);
4904 operands[1] = const0_rtx;
4905})
9c08d1fa 4906
848e66ac 4907(define_split
25f905c2 4908 [(set (match_operand:DI 0 "s_register_operand" "")
848e66ac 4909 (sign_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
6aa689e8 4910 "TARGET_32BIT && reload_completed && !IS_VFP_REGNUM (REGNO (operands[0]))"
848e66ac 4911 [(set (match_dup 0) (ashiftrt:SI (match_dup 1) (const_int 31)))]
4912{
4913 rtx lo_part = gen_lowpart (SImode, operands[0]);
3754d046 4914 machine_mode src_mode = GET_MODE (operands[1]);
25f905c2 4915
848e66ac 4916 if (REG_P (operands[0])
4917 && !reg_overlap_mentioned_p (operands[0], operands[1]))
4918 emit_clobber (operands[0]);
4919
4920 if (!REG_P (lo_part) || src_mode != SImode
4921 || !rtx_equal_p (lo_part, operands[1]))
4922 {
4923 if (src_mode == SImode)
4924 emit_move_insn (lo_part, operands[1]);
4925 else
4926 emit_insn (gen_rtx_SET (VOIDmode, lo_part,
4927 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
4928 operands[1] = lo_part;
4929 }
4930 operands[0] = gen_highpart (SImode, operands[0]);
4931})
9c08d1fa 4932
4933(define_expand "zero_extendhisi2"
ef51b8e1 4934 [(set (match_operand:SI 0 "s_register_operand" "")
4935 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
cffb2a26 4936 "TARGET_EITHER"
ef51b8e1 4937{
4938 if (TARGET_ARM && !arm_arch4 && MEM_P (operands[1]))
f7fbdd4a 4939 {
ef51b8e1 4940 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
4941 DONE;
25f7a26e 4942 }
ef51b8e1 4943 if (!arm_arch6 && !MEM_P (operands[1]))
4944 {
4945 rtx t = gen_lowpart (SImode, operands[1]);
4946 rtx tmp = gen_reg_rtx (SImode);
4947 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
4948 emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (16)));
4949 DONE;
4950 }
4951})
9c08d1fa 4952
ef51b8e1 4953(define_split
b146458f 4954 [(set (match_operand:SI 0 "s_register_operand" "")
4955 (zero_extend:SI (match_operand:HI 1 "s_register_operand" "")))]
ef51b8e1 4956 "!TARGET_THUMB2 && !arm_arch6"
4957 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4958 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 16)))]
4959{
4960 operands[2] = gen_lowpart (SImode, operands[1]);
4961})
4962
cffb2a26 4963(define_insn "*arm_zero_extendhisi2"
ef51b8e1 4964 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4965 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 4966 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 4967 "@
4968 #
4969 ldr%(h%)\\t%0, %1"
d82e788e 4970 [(set_attr "type" "alu_shift_reg,load_byte")
848e66ac 4971 (set_attr "predicable" "yes")]
cffb2a26 4972)
f7fbdd4a 4973
a2cd141b 4974(define_insn "*arm_zero_extendhisi2_v6"
4975 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
e3f4ccee 4976 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,Uh")))]
a2cd141b 4977 "TARGET_ARM && arm_arch6"
4978 "@
4979 uxth%?\\t%0, %1
25f905c2 4980 ldr%(h%)\\t%0, %1"
65f68e55 4981 [(set_attr "predicable" "yes")
6b6abc9c 4982 (set_attr "type" "extend,load_byte")]
a2cd141b 4983)
4984
4985(define_insn "*arm_zero_extendhisi2addsi"
4986 [(set (match_operand:SI 0 "s_register_operand" "=r")
4987 (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
4988 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4989 "TARGET_INT_SIMD"
a2cd141b 4990 "uxtah%?\\t%0, %2, %1"
d82e788e 4991 [(set_attr "type" "alu_shift_reg")
d952d547 4992 (set_attr "predicable" "yes")
4993 (set_attr "predicable_short_it" "no")]
a2cd141b 4994)
4995
87b22bf7 4996(define_expand "zero_extendqisi2"
cffb2a26 4997 [(set (match_operand:SI 0 "s_register_operand" "")
4998 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
4999 "TARGET_EITHER"
ef51b8e1 5000{
0438d37f 5001 if (TARGET_ARM && !arm_arch6 && !MEM_P (operands[1]))
87b22bf7 5002 {
ef51b8e1 5003 emit_insn (gen_andsi3 (operands[0],
5004 gen_lowpart (SImode, operands[1]),
5005 GEN_INT (255)));
5006 DONE;
5007 }
5008 if (!arm_arch6 && !MEM_P (operands[1]))
5009 {
5010 rtx t = gen_lowpart (SImode, operands[1]);
5011 rtx tmp = gen_reg_rtx (SImode);
5012 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
5013 emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (24)));
5014 DONE;
5015 }
5016})
cffb2a26 5017
ef51b8e1 5018(define_split
b146458f 5019 [(set (match_operand:SI 0 "s_register_operand" "")
5020 (zero_extend:SI (match_operand:QI 1 "s_register_operand" "")))]
ef51b8e1 5021 "!arm_arch6"
5022 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
5023 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 24)))]
5024{
5025 operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
5026 if (TARGET_ARM)
5027 {
5028 emit_insn (gen_andsi3 (operands[0], operands[2], GEN_INT (255)));
87b22bf7 5029 DONE;
5030 }
ef51b8e1 5031})
9c08d1fa 5032
cffb2a26 5033(define_insn "*arm_zero_extendqisi2"
ef51b8e1 5034 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5035 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 5036 "TARGET_ARM && !arm_arch6"
ef51b8e1 5037 "@
5038 #
5039 ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
5040 [(set_attr "length" "8,4")
d82e788e 5041 (set_attr "type" "alu_shift_reg,load_byte")
848e66ac 5042 (set_attr "predicable" "yes")]
cffb2a26 5043)
87b22bf7 5044
a2cd141b 5045(define_insn "*arm_zero_extendqisi2_v6"
5046 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
e3f4ccee 5047 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,Uh")))]
a2cd141b 5048 "TARGET_ARM && arm_arch6"
5049 "@
25f905c2 5050 uxtb%(%)\\t%0, %1
5051 ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
6b6abc9c 5052 [(set_attr "type" "extend,load_byte")
848e66ac 5053 (set_attr "predicable" "yes")]
a2cd141b 5054)
5055
5056(define_insn "*arm_zero_extendqisi2addsi"
5057 [(set (match_operand:SI 0 "s_register_operand" "=r")
5058 (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
5059 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 5060 "TARGET_INT_SIMD"
a2cd141b 5061 "uxtab%?\\t%0, %2, %1"
5062 [(set_attr "predicable" "yes")
d952d547 5063 (set_attr "predicable_short_it" "no")
d82e788e 5064 (set_attr "type" "alu_shift_reg")]
a2cd141b 5065)
5066
87b22bf7 5067(define_split
5068 [(set (match_operand:SI 0 "s_register_operand" "")
5069 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
5070 (clobber (match_operand:SI 2 "s_register_operand" ""))]
0438d37f 5071 "TARGET_32BIT && (!MEM_P (operands[1])) && ! BYTES_BIG_ENDIAN"
87b22bf7 5072 [(set (match_dup 2) (match_dup 1))
5073 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
cffb2a26 5074 ""
5075)
9c08d1fa 5076
8a4d25d6 5077(define_split
5078 [(set (match_operand:SI 0 "s_register_operand" "")
5079 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 3)))
5080 (clobber (match_operand:SI 2 "s_register_operand" ""))]
0438d37f 5081 "TARGET_32BIT && (!MEM_P (operands[1])) && BYTES_BIG_ENDIAN"
8a4d25d6 5082 [(set (match_dup 2) (match_dup 1))
5083 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
5084 ""
5085)
5086
1c274529 5087
5088(define_split
5089 [(set (match_operand:SI 0 "s_register_operand" "")
5090 (ior_xor:SI (and:SI (ashift:SI
5091 (match_operand:SI 1 "s_register_operand" "")
5092 (match_operand:SI 2 "const_int_operand" ""))
5093 (match_operand:SI 3 "const_int_operand" ""))
5094 (zero_extend:SI
5095 (match_operator 5 "subreg_lowpart_operator"
5096 [(match_operand:SI 4 "s_register_operand" "")]))))]
5097 "TARGET_32BIT
63787642 5098 && ((unsigned HOST_WIDE_INT) INTVAL (operands[3])
1c274529 5099 == (GET_MODE_MASK (GET_MODE (operands[5]))
5100 & (GET_MODE_MASK (GET_MODE (operands[5]))
5101 << (INTVAL (operands[2])))))"
5102 [(set (match_dup 0) (ior_xor:SI (ashift:SI (match_dup 1) (match_dup 2))
5103 (match_dup 4)))
5104 (set (match_dup 0) (zero_extend:SI (match_dup 5)))]
5105 "operands[5] = gen_lowpart (GET_MODE (operands[5]), operands[0]);"
5106)
5107
f7fbdd4a 5108(define_insn "*compareqi_eq0"
bd5b4116 5109 [(set (reg:CC_Z CC_REGNUM)
206ee9a2 5110 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
87b22bf7 5111 (const_int 0)))]
25f905c2 5112 "TARGET_32BIT"
596e5e8f 5113 "tst%?\\t%0, #255"
5114 [(set_attr "conds" "set")
d952d547 5115 (set_attr "predicable" "yes")
1b7da4ac 5116 (set_attr "predicable_short_it" "no")
5117 (set_attr "type" "logic_imm")]
cffb2a26 5118)
b11cae9e 5119
b11cae9e 5120(define_expand "extendhisi2"
ef51b8e1 5121 [(set (match_operand:SI 0 "s_register_operand" "")
5122 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
cffb2a26 5123 "TARGET_EITHER"
ef51b8e1 5124{
5125 if (TARGET_THUMB1)
5126 {
5127 emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1]));
5128 DONE;
5129 }
5130 if (MEM_P (operands[1]) && TARGET_ARM && !arm_arch4)
5131 {
5132 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
5133 DONE;
5134 }
ed29c566 5135
ef51b8e1 5136 if (!arm_arch6 && !MEM_P (operands[1]))
5137 {
5138 rtx t = gen_lowpart (SImode, operands[1]);
5139 rtx tmp = gen_reg_rtx (SImode);
5140 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
5141 emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (16)));
5142 DONE;
5143 }
5144})
cffb2a26 5145
ef51b8e1 5146(define_split
5147 [(parallel
5148 [(set (match_operand:SI 0 "register_operand" "")
5149 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))
5150 (clobber (match_scratch:SI 2 ""))])]
5151 "!arm_arch6"
5152 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
5153 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
5154{
5155 operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
5156})
25f7a26e 5157
25f905c2 5158;; This pattern will only be used when ldsh is not available
25f7a26e 5159(define_expand "extendhisi2_mem"
eab14235 5160 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 5161 (set (match_dup 3)
eab14235 5162 (zero_extend:SI (match_dup 7)))
25f7a26e 5163 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
5164 (set (match_operand:SI 0 "" "")
5165 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
cffb2a26 5166 "TARGET_ARM"
25f7a26e 5167 "
215b30b3 5168 {
5169 rtx mem1, mem2;
5170 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
5171
788fcce0 5172 mem1 = change_address (operands[1], QImode, addr);
29c05e22 5173 mem2 = change_address (operands[1], QImode,
5174 plus_constant (Pmode, addr, 1));
215b30b3 5175 operands[0] = gen_lowpart (SImode, operands[0]);
5176 operands[1] = mem1;
5177 operands[2] = gen_reg_rtx (SImode);
5178 operands[3] = gen_reg_rtx (SImode);
5179 operands[6] = gen_reg_rtx (SImode);
5180 operands[7] = mem2;
25f7a26e 5181
215b30b3 5182 if (BYTES_BIG_ENDIAN)
5183 {
5184 operands[4] = operands[2];
5185 operands[5] = operands[3];
5186 }
5187 else
5188 {
5189 operands[4] = operands[3];
5190 operands[5] = operands[2];
5191 }
5192 }"
5193)
b11cae9e 5194
ef51b8e1 5195(define_split
5196 [(set (match_operand:SI 0 "register_operand" "")
5197 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
5198 "!arm_arch6"
5199 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
5200 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
5201{
5202 operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
5203})
5204
a2cd141b 5205(define_insn "*arm_extendhisi2"
ef51b8e1 5206 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
e3f4ccee 5207 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,Uh")))]
a2cd141b 5208 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 5209 "@
5210 #
5211 ldr%(sh%)\\t%0, %1"
5212 [(set_attr "length" "8,4")
d82e788e 5213 (set_attr "type" "alu_shift_reg,load_byte")
e3f4ccee 5214 (set_attr "predicable" "yes")]
cffb2a26 5215)
f7fbdd4a 5216
25f905c2 5217;; ??? Check Thumb-2 pool range
a2cd141b 5218(define_insn "*arm_extendhisi2_v6"
5219 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
e3f4ccee 5220 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,Uh")))]
25f905c2 5221 "TARGET_32BIT && arm_arch6"
a2cd141b 5222 "@
5223 sxth%?\\t%0, %1
25f905c2 5224 ldr%(sh%)\\t%0, %1"
6b6abc9c 5225 [(set_attr "type" "extend,load_byte")
a2cd141b 5226 (set_attr "predicable" "yes")
e3f4ccee 5227 (set_attr "predicable_short_it" "no")]
a2cd141b 5228)
5229
5230(define_insn "*arm_extendhisi2addsi"
5231 [(set (match_operand:SI 0 "s_register_operand" "=r")
5232 (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
5233 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 5234 "TARGET_INT_SIMD"
a2cd141b 5235 "sxtah%?\\t%0, %2, %1"
1b7da4ac 5236 [(set_attr "type" "alu_shift_reg")]
a2cd141b 5237)
5238
c8f69309 5239(define_expand "extendqihi2"
5240 [(set (match_dup 2)
bed7d9a5 5241 (ashift:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")
c8f69309 5242 (const_int 24)))
9c08d1fa 5243 (set (match_operand:HI 0 "s_register_operand" "")
c8f69309 5244 (ashiftrt:SI (match_dup 2)
5245 (const_int 24)))]
cffb2a26 5246 "TARGET_ARM"
c8f69309 5247 "
215b30b3 5248 {
0438d37f 5249 if (arm_arch4 && MEM_P (operands[1]))
215b30b3 5250 {
5251 emit_insn (gen_rtx_SET (VOIDmode,
5252 operands[0],
5253 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
5254 DONE;
5255 }
5256 if (!s_register_operand (operands[1], QImode))
5257 operands[1] = copy_to_mode_reg (QImode, operands[1]);
5258 operands[0] = gen_lowpart (SImode, operands[0]);
5259 operands[1] = gen_lowpart (SImode, operands[1]);
5260 operands[2] = gen_reg_rtx (SImode);
5261 }"
5262)
f7fbdd4a 5263
25f905c2 5264(define_insn "*arm_extendqihi_insn"
b4e8a300 5265 [(set (match_operand:HI 0 "s_register_operand" "=r")
bed7d9a5 5266 (sign_extend:HI (match_operand:QI 1 "arm_extendqisi_mem_op" "Uq")))]
cffb2a26 5267 "TARGET_ARM && arm_arch4"
25f905c2 5268 "ldr%(sb%)\\t%0, %1"
a2cd141b 5269 [(set_attr "type" "load_byte")
e3f4ccee 5270 (set_attr "predicable" "yes")]
cffb2a26 5271)
3fc2009e 5272
b11cae9e 5273(define_expand "extendqisi2"
ef51b8e1 5274 [(set (match_operand:SI 0 "s_register_operand" "")
5275 (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")))]
cffb2a26 5276 "TARGET_EITHER"
ef51b8e1 5277{
5278 if (!arm_arch4 && MEM_P (operands[1]))
5279 operands[1] = copy_to_mode_reg (QImode, operands[1]);
a2cd141b 5280
ef51b8e1 5281 if (!arm_arch6 && !MEM_P (operands[1]))
5282 {
5283 rtx t = gen_lowpart (SImode, operands[1]);
5284 rtx tmp = gen_reg_rtx (SImode);
5285 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
5286 emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (24)));
5287 DONE;
5288 }
5289})
a2cd141b 5290
ef51b8e1 5291(define_split
5292 [(set (match_operand:SI 0 "register_operand" "")
5293 (sign_extend:SI (match_operand:QI 1 "register_operand" "")))]
5294 "!arm_arch6"
5295 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
5296 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))]
5297{
5298 operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
5299})
f7fbdd4a 5300
a2cd141b 5301(define_insn "*arm_extendqisi"
ef51b8e1 5302 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5303 (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
a2cd141b 5304 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 5305 "@
5306 #
5307 ldr%(sb%)\\t%0, %1"
5308 [(set_attr "length" "8,4")
d82e788e 5309 (set_attr "type" "alu_shift_reg,load_byte")
e3f4ccee 5310 (set_attr "predicable" "yes")]
cffb2a26 5311)
3fc2009e 5312
a2cd141b 5313(define_insn "*arm_extendqisi_v6"
5314 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
bed7d9a5 5315 (sign_extend:SI
5316 (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
a2cd141b 5317 "TARGET_ARM && arm_arch6"
b4e8a300 5318 "@
5319 sxtb%?\\t%0, %1
25f905c2 5320 ldr%(sb%)\\t%0, %1"
6b6abc9c 5321 [(set_attr "type" "extend,load_byte")
e3f4ccee 5322 (set_attr "predicable" "yes")]
a2cd141b 5323)
5324
5325(define_insn "*arm_extendqisi2addsi"
5326 [(set (match_operand:SI 0 "s_register_operand" "=r")
5327 (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
5328 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 5329 "TARGET_INT_SIMD"
a2cd141b 5330 "sxtab%?\\t%0, %2, %1"
d82e788e 5331 [(set_attr "type" "alu_shift_reg")
d952d547 5332 (set_attr "predicable" "yes")
5333 (set_attr "predicable_short_it" "no")]
a2cd141b 5334)
5335
caedf871 5336(define_expand "extendsfdf2"
5337 [(set (match_operand:DF 0 "s_register_operand" "")
5338 (float_extend:DF (match_operand:SF 1 "s_register_operand" "")))]
a50d7267 5339 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
caedf871 5340 ""
5341)
9b8516be 5342
5343/* HFmode -> DFmode conversions have to go through SFmode. */
5344(define_expand "extendhfdf2"
5345 [(set (match_operand:DF 0 "general_operand" "")
5346 (float_extend:DF (match_operand:HF 1 "general_operand" "")))]
5347 "TARGET_EITHER"
5348 "
5349 {
5350 rtx op1;
5351 op1 = convert_to_mode (SFmode, operands[1], 0);
5352 op1 = convert_to_mode (DFmode, op1, 0);
5353 emit_insn (gen_movdf (operands[0], op1));
5354 DONE;
5355 }"
5356)
b11cae9e 5357\f
5358;; Move insns (including loads and stores)
5359
5360;; XXX Just some ideas about movti.
9c08d1fa 5361;; I don't think these are a good idea on the arm, there just aren't enough
5362;; registers
b11cae9e 5363;;(define_expand "loadti"
9c08d1fa 5364;; [(set (match_operand:TI 0 "s_register_operand" "")
b11cae9e 5365;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
5366;; "" "")
5367
5368;;(define_expand "storeti"
5369;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
9c08d1fa 5370;; (match_operand:TI 1 "s_register_operand" ""))]
b11cae9e 5371;; "" "")
5372
5373;;(define_expand "movti"
5374;; [(set (match_operand:TI 0 "general_operand" "")
5375;; (match_operand:TI 1 "general_operand" ""))]
5376;; ""
5377;; "
5378;;{
5379;; rtx insn;
5380;;
0438d37f 5381;; if (MEM_P (operands[0]) && MEM_P (operands[1]))
b11cae9e 5382;; operands[1] = copy_to_reg (operands[1]);
0438d37f 5383;; if (MEM_P (operands[0]))
b11cae9e 5384;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
0438d37f 5385;; else if (MEM_P (operands[1]))
b11cae9e 5386;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
5387;; else
5388;; FAIL;
5389;;
5390;; emit_insn (insn);
5391;; DONE;
5392;;}")
5393
a2f10574 5394;; Recognize garbage generated above.
b11cae9e 5395
5396;;(define_insn ""
5397;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
5398;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
5399;; ""
5400;; "*
5401;; {
5402;; register mem = (which_alternative < 3);
0d66636f 5403;; register const char *template;
b11cae9e 5404;;
5405;; operands[mem] = XEXP (operands[mem], 0);
5406;; switch (which_alternative)
5407;; {
5408;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
5409;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
5410;; case 2: template = \"ldmia\\t%1, %M0\"; break;
5411;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
5412;; case 4: template = \"stmia\\t%0!, %M1\"; break;
5413;; case 5: template = \"stmia\\t%0, %M1\"; break;
5414;; }
e2348bcb 5415;; output_asm_insn (template, operands);
5416;; return \"\";
b11cae9e 5417;; }")
5418
cffb2a26 5419(define_expand "movdi"
5420 [(set (match_operand:DI 0 "general_operand" "")
5421 (match_operand:DI 1 "general_operand" ""))]
5422 "TARGET_EITHER"
5423 "
e1ba4a27 5424 if (can_create_pseudo_p ())
cffb2a26 5425 {
0438d37f 5426 if (!REG_P (operands[0]))
b2778788 5427 operands[1] = force_reg (DImode, operands[1]);
cffb2a26 5428 }
5429 "
5430)
b11cae9e 5431
cffb2a26 5432(define_insn "*arm_movdi"
353cf59a 5433 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, q, m")
5434 (match_operand:DI 1 "di_operand" "rDa,Db,Dc,mi,q"))]
cde1623a 5435 "TARGET_32BIT
b805622c 5436 && !(TARGET_HARD_FLOAT && TARGET_VFP)
b2778788 5437 && !TARGET_IWMMXT
5438 && ( register_operand (operands[0], DImode)
5439 || register_operand (operands[1], DImode))"
b11cae9e 5440 "*
d51f92df 5441 switch (which_alternative)
5442 {
5443 case 0:
5444 case 1:
5445 case 2:
5446 return \"#\";
5447 default:
26ff80c0 5448 return output_move_double (operands, true, NULL);
d51f92df 5449 }
cffb2a26 5450 "
359a6e9f 5451 [(set_attr "length" "8,12,16,8,8")
1b7da4ac 5452 (set_attr "type" "multiple,multiple,multiple,load2,store2")
cde1623a 5453 (set_attr "arm_pool_range" "*,*,*,1020,*")
8848d797 5454 (set_attr "arm_neg_pool_range" "*,*,*,1004,*")
42e1de19 5455 (set_attr "thumb2_pool_range" "*,*,*,4094,*")
cde1623a 5456 (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
cffb2a26 5457)
5458
d51f92df 5459(define_split
5460 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
e6dd3afa 5461 (match_operand:ANY64 1 "immediate_operand" ""))]
25f905c2 5462 "TARGET_32BIT
d51f92df 5463 && reload_completed
5464 && (arm_const_double_inline_cost (operands[1])
861033d5 5465 <= arm_max_const_double_inline_cost ())"
d51f92df 5466 [(const_int 0)]
5467 "
5468 arm_split_constant (SET, SImode, curr_insn,
5469 INTVAL (gen_lowpart (SImode, operands[1])),
5470 gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
5471 arm_split_constant (SET, SImode, curr_insn,
5472 INTVAL (gen_highpart_mode (SImode,
5473 GET_MODE (operands[0]),
5474 operands[1])),
5475 gen_highpart (SImode, operands[0]), NULL_RTX, 0);
5476 DONE;
5477 "
5478)
5479
e5ba9289 5480; If optimizing for size, or if we have load delay slots, then
5481; we want to split the constant into two separate operations.
5482; In both cases this may split a trivial part into a single data op
5483; leaving a single complex constant to load. We can also get longer
5484; offsets in a LDR which means we get better chances of sharing the pool
5485; entries. Finally, we can normally do a better job of scheduling
5486; LDR instructions than we can with LDM.
5487; This pattern will only match if the one above did not.
5488(define_split
5489 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
5490 (match_operand:ANY64 1 "const_double_operand" ""))]
5491 "TARGET_ARM && reload_completed
5492 && arm_const_double_by_parts (operands[1])"
5493 [(set (match_dup 0) (match_dup 1))
5494 (set (match_dup 2) (match_dup 3))]
5495 "
5496 operands[2] = gen_highpart (SImode, operands[0]);
5497 operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
5498 operands[1]);
5499 operands[0] = gen_lowpart (SImode, operands[0]);
5500 operands[1] = gen_lowpart (SImode, operands[1]);
5501 "
5502)
5503
d51f92df 5504(define_split
5505 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
5506 (match_operand:ANY64 1 "arm_general_register_operand" ""))]
5507 "TARGET_EITHER && reload_completed"
5508 [(set (match_dup 0) (match_dup 1))
5509 (set (match_dup 2) (match_dup 3))]
5510 "
5511 operands[2] = gen_highpart (SImode, operands[0]);
5512 operands[3] = gen_highpart (SImode, operands[1]);
5513 operands[0] = gen_lowpart (SImode, operands[0]);
5514 operands[1] = gen_lowpart (SImode, operands[1]);
5515
5516 /* Handle a partial overlap. */
5517 if (rtx_equal_p (operands[0], operands[3]))
5518 {
5519 rtx tmp0 = operands[0];
5520 rtx tmp1 = operands[1];
5521
5522 operands[0] = operands[2];
5523 operands[1] = operands[3];
5524 operands[2] = tmp0;
5525 operands[3] = tmp1;
5526 }
5527 "
5528)
5529
a8a3b539 5530;; We can't actually do base+index doubleword loads if the index and
5531;; destination overlap. Split here so that we at least have chance to
5532;; schedule.
5533(define_split
5534 [(set (match_operand:DI 0 "s_register_operand" "")
5535 (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
5536 (match_operand:SI 2 "s_register_operand" ""))))]
5537 "TARGET_LDRD
5538 && reg_overlap_mentioned_p (operands[0], operands[1])
5539 && reg_overlap_mentioned_p (operands[0], operands[2])"
5540 [(set (match_dup 4)
5541 (plus:SI (match_dup 1)
5542 (match_dup 2)))
5543 (set (match_dup 0)
5544 (mem:DI (match_dup 4)))]
5545 "
5546 operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
5547 "
5548)
5549
9c08d1fa 5550(define_expand "movsi"
5551 [(set (match_operand:SI 0 "general_operand" "")
5552 (match_operand:SI 1 "general_operand" ""))]
cffb2a26 5553 "TARGET_EITHER"
9c08d1fa 5554 "
befb0bac 5555 {
e348ff3e 5556 rtx base, offset, tmp;
5557
25f905c2 5558 if (TARGET_32BIT)
9c08d1fa 5559 {
674a8f0b 5560 /* Everything except mem = const or mem = mem can be done easily. */
0438d37f 5561 if (MEM_P (operands[0]))
cffb2a26 5562 operands[1] = force_reg (SImode, operands[1]);
a2cd141b 5563 if (arm_general_register_operand (operands[0], SImode)
0438d37f 5564 && CONST_INT_P (operands[1])
cffb2a26 5565 && !(const_ok_for_arm (INTVAL (operands[1]))
5566 || const_ok_for_arm (~INTVAL (operands[1]))))
5567 {
96f57e36 5568 arm_split_constant (SET, SImode, NULL_RTX,
5569 INTVAL (operands[1]), operands[0], NULL_RTX,
e1ba4a27 5570 optimize && can_create_pseudo_p ());
cffb2a26 5571 DONE;
5572 }
5573 }
25f905c2 5574 else /* TARGET_THUMB1... */
cffb2a26 5575 {
e1ba4a27 5576 if (can_create_pseudo_p ())
cffb2a26 5577 {
0438d37f 5578 if (!REG_P (operands[0]))
cffb2a26 5579 operands[1] = force_reg (SImode, operands[1]);
5580 }
9c08d1fa 5581 }
f655717d 5582
e348ff3e 5583 if (ARM_OFFSETS_MUST_BE_WITHIN_SECTIONS_P)
5584 {
5585 split_const (operands[1], &base, &offset);
5586 if (GET_CODE (base) == SYMBOL_REF
5587 && !offset_within_block_p (base, INTVAL (offset)))
5588 {
b308ddcf 5589 tmp = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
e348ff3e 5590 emit_move_insn (tmp, base);
5591 emit_insn (gen_addsi3 (operands[0], tmp, offset));
5592 DONE;
5593 }
5594 }
5595
f655717d 5596 /* Recognize the case where operand[1] is a reference to thread-local
5597 data and load its address to a register. */
5598 if (arm_tls_referenced_p (operands[1]))
5599 {
5600 rtx tmp = operands[1];
5601 rtx addend = NULL;
5602
5603 if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
5604 {
5605 addend = XEXP (XEXP (tmp, 0), 1);
5606 tmp = XEXP (XEXP (tmp, 0), 0);
5607 }
5608
5609 gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
5610 gcc_assert (SYMBOL_REF_TLS_MODEL (tmp) != 0);
5611
e1ba4a27 5612 tmp = legitimize_tls_address (tmp,
5613 !can_create_pseudo_p () ? operands[0] : 0);
f655717d 5614 if (addend)
5615 {
5616 tmp = gen_rtx_PLUS (SImode, tmp, addend);
5617 tmp = force_operand (tmp, operands[0]);
5618 }
5619 operands[1] = tmp;
5620 }
5621 else if (flag_pic
5622 && (CONSTANT_P (operands[1])
5623 || symbol_mentioned_p (operands[1])
5624 || label_mentioned_p (operands[1])))
5625 operands[1] = legitimize_pic_address (operands[1], SImode,
e1ba4a27 5626 (!can_create_pseudo_p ()
5627 ? operands[0]
5628 : 0));
befb0bac 5629 }
215b30b3 5630 "
5631)
9c08d1fa 5632
d0e6a121 5633;; The ARM LO_SUM and HIGH are backwards - HIGH sets the low bits, and
5634;; LO_SUM adds in the high bits. Fortunately these are opaque operations
5635;; so this does not matter.
5636(define_insn "*arm_movt"
5637 [(set (match_operand:SI 0 "nonimmediate_operand" "=r")
5638 (lo_sum:SI (match_operand:SI 1 "nonimmediate_operand" "0")
5639 (match_operand:SI 2 "general_operand" "i")))]
c9b2ce40 5640 "arm_arch_thumb2"
d0e6a121 5641 "movt%?\t%0, #:upper16:%c2"
5642 [(set_attr "predicable" "yes")
d952d547 5643 (set_attr "predicable_short_it" "no")
1b7da4ac 5644 (set_attr "length" "4")
5645 (set_attr "type" "mov_imm")]
d0e6a121 5646)
5647
cffb2a26 5648(define_insn "*arm_movsi_insn"
aaa37ad6 5649 [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,rk,m")
110eae03 5650 (match_operand:SI 1 "general_operand" "rk, I,K,j,mi,rk"))]
755eb2b4 5651 "TARGET_ARM && ! TARGET_IWMMXT
a2cd141b 5652 && !(TARGET_HARD_FLOAT && TARGET_VFP)
cffb2a26 5653 && ( register_operand (operands[0], SImode)
5654 || register_operand (operands[1], SImode))"
f7fbdd4a 5655 "@
aaa37ad6 5656 mov%?\\t%0, %1
f7fbdd4a 5657 mov%?\\t%0, %1
5658 mvn%?\\t%0, #%B1
25f905c2 5659 movw%?\\t%0, %1
f7fbdd4a 5660 ldr%?\\t%0, %1
5661 str%?\\t%1, %0"
1aed5204 5662 [(set_attr "type" "mov_reg,mov_imm,mvn_imm,mov_imm,load1,store1")
0d66636f 5663 (set_attr "predicable" "yes")
aaa37ad6 5664 (set_attr "pool_range" "*,*,*,*,4096,*")
5665 (set_attr "neg_pool_range" "*,*,*,*,4084,*")]
cffb2a26 5666)
87b22bf7 5667
5668(define_split
a2cd141b 5669 [(set (match_operand:SI 0 "arm_general_register_operand" "")
87b22bf7 5670 (match_operand:SI 1 "const_int_operand" ""))]
25f905c2 5671 "TARGET_32BIT
215b30b3 5672 && (!(const_ok_for_arm (INTVAL (operands[1]))
5673 || const_ok_for_arm (~INTVAL (operands[1]))))"
87b22bf7 5674 [(clobber (const_int 0))]
5675 "
96f57e36 5676 arm_split_constant (SET, SImode, NULL_RTX,
5677 INTVAL (operands[1]), operands[0], NULL_RTX, 0);
87b22bf7 5678 DONE;
215b30b3 5679 "
5680)
9c08d1fa 5681
861033d5 5682;; A normal way to do (symbol + offset) requires three instructions at least
5683;; (depends on how big the offset is) as below:
5684;; movw r0, #:lower16:g
5685;; movw r0, #:upper16:g
5686;; adds r0, #4
5687;;
5688;; A better way would be:
5689;; movw r0, #:lower16:g+4
5690;; movw r0, #:upper16:g+4
5691;;
5692;; The limitation of this way is that the length of offset should be a 16-bit
5693;; signed value, because current assembler only supports REL type relocation for
5694;; such case. If the more powerful RELA type is supported in future, we should
5695;; update this pattern to go with better way.
5696(define_split
5697 [(set (match_operand:SI 0 "arm_general_register_operand" "")
5698 (const:SI (plus:SI (match_operand:SI 1 "general_operand" "")
5699 (match_operand:SI 2 "const_int_operand" ""))))]
5700 "TARGET_THUMB2
5701 && arm_disable_literal_pool
5702 && reload_completed
5703 && GET_CODE (operands[1]) == SYMBOL_REF"
5704 [(clobber (const_int 0))]
5705 "
5706 int offset = INTVAL (operands[2]);
5707
5708 if (offset < -0x8000 || offset > 0x7fff)
5709 {
5710 arm_emit_movpair (operands[0], operands[1]);
5711 emit_insn (gen_rtx_SET (SImode, operands[0],
5712 gen_rtx_PLUS (SImode, operands[0], operands[2])));
5713 }
5714 else
5715 {
5716 rtx op = gen_rtx_CONST (SImode,
5717 gen_rtx_PLUS (SImode, operands[1], operands[2]));
5718 arm_emit_movpair (operands[0], op);
5719 }
5720 "
5721)
5722
b8d5d078 5723;; Split symbol_refs at the later stage (after cprop), instead of generating
5724;; movt/movw pair directly at expand. Otherwise corresponding high_sum
5725;; and lo_sum would be merged back into memory load at cprop. However,
5726;; if the default is to prefer movt/movw rather than a load from the constant
5727;; pool, the performance is better.
5728(define_split
5729 [(set (match_operand:SI 0 "arm_general_register_operand" "")
5730 (match_operand:SI 1 "general_operand" ""))]
5731 "TARGET_32BIT
5732 && TARGET_USE_MOVT && GET_CODE (operands[1]) == SYMBOL_REF
5733 && !flag_pic && !target_word_relocations
5734 && !arm_tls_referenced_p (operands[1])"
5735 [(clobber (const_int 0))]
5736{
5737 arm_emit_movpair (operands[0], operands[1]);
5738 DONE;
5739})
5740
bc360af8 5741;; When generating pic, we need to load the symbol offset into a register.
5742;; So that the optimizer does not confuse this with a normal symbol load
5743;; we use an unspec. The offset will be loaded from a constant pool entry,
5744;; since that is the only type of relocation we can use.
cffb2a26 5745
bc360af8 5746;; Wrap calculation of the whole PIC address in a single pattern for the
5747;; benefit of optimizers, particularly, PRE and HOIST. Calculation of
5748;; a PIC address involves two loads from memory, so we want to CSE it
5749;; as often as possible.
5750;; This pattern will be split into one of the pic_load_addr_* patterns
5751;; and a move after GCSE optimizations.
5752;;
5753;; Note: Update arm.c: legitimize_pic_address() when changing this pattern.
5754(define_expand "calculate_pic_address"
94f8caca 5755 [(set (match_operand:SI 0 "register_operand" "")
5756 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "")
5757 (unspec:SI [(match_operand:SI 2 "" "")]
5758 UNSPEC_PIC_SYM))))]
5759 "flag_pic"
5760)
5761
5762;; Split calculate_pic_address into pic_load_addr_* and a move.
5763(define_split
5764 [(set (match_operand:SI 0 "register_operand" "")
5765 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "")
5766 (unspec:SI [(match_operand:SI 2 "" "")]
5767 UNSPEC_PIC_SYM))))]
5768 "flag_pic"
5769 [(set (match_dup 3) (unspec:SI [(match_dup 2)] UNSPEC_PIC_SYM))
5770 (set (match_dup 0) (mem:SI (plus:SI (match_dup 1) (match_dup 3))))]
5771 "operands[3] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];"
5772)
5773
350ccca5 5774;; operand1 is the memory address to go into
5775;; pic_load_addr_32bit.
5776;; operand2 is the PIC label to be emitted
5777;; from pic_add_dot_plus_eight.
5778;; We do this to allow hoisting of the entire insn.
5779(define_insn_and_split "pic_load_addr_unified"
5780 [(set (match_operand:SI 0 "s_register_operand" "=r,r,l")
5781 (unspec:SI [(match_operand:SI 1 "" "mX,mX,mX")
5782 (match_operand:SI 2 "" "")]
5783 UNSPEC_PIC_UNIFIED))]
5784 "flag_pic"
5785 "#"
5786 "&& reload_completed"
5787 [(set (match_dup 0) (unspec:SI [(match_dup 1)] UNSPEC_PIC_SYM))
5788 (set (match_dup 0) (unspec:SI [(match_dup 0) (match_dup 3)
5789 (match_dup 2)] UNSPEC_PIC_BASE))]
5790 "operands[3] = TARGET_THUMB ? GEN_INT (4) : GEN_INT (8);"
5791 [(set_attr "type" "load1,load1,load1")
42e1de19 5792 (set_attr "pool_range" "4096,4094,1022")
350ccca5 5793 (set_attr "neg_pool_range" "4084,0,0")
5794 (set_attr "arch" "a,t2,t1")
5795 (set_attr "length" "8,6,4")]
5796)
5797
67336bcf 5798;; The rather odd constraints on the following are to force reload to leave
5799;; the insn alone, and to force the minipool generation pass to then move
5800;; the GOT symbol to memory.
849170fd 5801
b3cd5f55 5802(define_insn "pic_load_addr_32bit"
849170fd 5803 [(set (match_operand:SI 0 "s_register_operand" "=r")
e1159bbe 5804 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
b3cd5f55 5805 "TARGET_32BIT && flag_pic"
67336bcf 5806 "ldr%?\\t%0, %1"
a2cd141b 5807 [(set_attr "type" "load1")
42e1de19 5808 (set (attr "pool_range")
5809 (if_then_else (eq_attr "is_thumb" "no")
5810 (const_int 4096)
5811 (const_int 4094)))
b3cd5f55 5812 (set (attr "neg_pool_range")
5813 (if_then_else (eq_attr "is_thumb" "no")
5814 (const_int 4084)
5815 (const_int 0)))]
8c4d8060 5816)
5817
25f905c2 5818(define_insn "pic_load_addr_thumb1"
8c4d8060 5819 [(set (match_operand:SI 0 "s_register_operand" "=l")
e1159bbe 5820 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
25f905c2 5821 "TARGET_THUMB1 && flag_pic"
8c4d8060 5822 "ldr\\t%0, %1"
a2cd141b 5823 [(set_attr "type" "load1")
42e1de19 5824 (set (attr "pool_range") (const_int 1018))]
cffb2a26 5825)
849170fd 5826
cffb2a26 5827(define_insn "pic_add_dot_plus_four"
15d5d060 5828 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5829 (unspec:SI [(match_operand:SI 1 "register_operand" "0")
5830 (const_int 4)
beef0fb5 5831 (match_operand 2 "" "")]
5832 UNSPEC_PIC_BASE))]
b3cd5f55 5833 "TARGET_THUMB"
cffb2a26 5834 "*
6cdcb15c 5835 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5836 INTVAL (operands[2]));
cffb2a26 5837 return \"add\\t%0, %|pc\";
5838 "
1b7da4ac 5839 [(set_attr "length" "2")
112eda6f 5840 (set_attr "type" "alu_sreg")]
cffb2a26 5841)
849170fd 5842
5843(define_insn "pic_add_dot_plus_eight"
15d5d060 5844 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5845 (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5846 (const_int 8)
beef0fb5 5847 (match_operand 2 "" "")]
5848 UNSPEC_PIC_BASE))]
f655717d 5849 "TARGET_ARM"
c4034607 5850 "*
6cdcb15c 5851 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5852 INTVAL (operands[2]));
15d5d060 5853 return \"add%?\\t%0, %|pc, %1\";
cffb2a26 5854 "
1b7da4ac 5855 [(set_attr "predicable" "yes")
112eda6f 5856 (set_attr "type" "alu_sreg")]
cffb2a26 5857)
849170fd 5858
f655717d 5859(define_insn "tls_load_dot_plus_eight"
cc071db6 5860 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5861 (mem:SI (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5862 (const_int 8)
beef0fb5 5863 (match_operand 2 "" "")]
5864 UNSPEC_PIC_BASE)))]
f655717d 5865 "TARGET_ARM"
5866 "*
6cdcb15c 5867 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5868 INTVAL (operands[2]));
f655717d 5869 return \"ldr%?\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_eight\";
5870 "
1b7da4ac 5871 [(set_attr "predicable" "yes")
5872 (set_attr "type" "load1")]
f655717d 5873)
5874
5875;; PIC references to local variables can generate pic_add_dot_plus_eight
5876;; followed by a load. These sequences can be crunched down to
5877;; tls_load_dot_plus_eight by a peephole.
5878
5879(define_peephole2
c0c1fba5 5880 [(set (match_operand:SI 0 "register_operand" "")
5881 (unspec:SI [(match_operand:SI 3 "register_operand" "")
5882 (const_int 8)
5883 (match_operand 1 "" "")]
5884 UNSPEC_PIC_BASE))
2d05dfad 5885 (set (match_operand:SI 2 "arm_general_register_operand" "")
5886 (mem:SI (match_dup 0)))]
f655717d 5887 "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
c0c1fba5 5888 [(set (match_dup 2)
5889 (mem:SI (unspec:SI [(match_dup 3)
5890 (const_int 8)
5891 (match_dup 1)]
5892 UNSPEC_PIC_BASE)))]
f655717d 5893 ""
5894)
5895
bac7fc85 5896(define_insn "pic_offset_arm"
5897 [(set (match_operand:SI 0 "register_operand" "=r")
5898 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
5899 (unspec:SI [(match_operand:SI 2 "" "X")]
5900 UNSPEC_PIC_OFFSET))))]
5901 "TARGET_VXWORKS_RTP && TARGET_ARM && flag_pic"
5902 "ldr%?\\t%0, [%1,%2]"
5903 [(set_attr "type" "load1")]
5904)
5905
95373f08 5906(define_expand "builtin_setjmp_receiver"
5907 [(label_ref (match_operand 0 "" ""))]
5908 "flag_pic"
5909 "
5910{
b935b306 5911 /* r3 is clobbered by set/longjmp, so we can use it as a scratch
5912 register. */
2cb7d577 5913 if (arm_pic_register != INVALID_REGNUM)
5914 arm_load_pic_register (1UL << 3);
95373f08 5915 DONE;
5916}")
5917
9c08d1fa 5918;; If copying one reg to another we can set the condition codes according to
5919;; its value. Such a move is common after a return from subroutine and the
5920;; result is being tested against zero.
5921
f7fbdd4a 5922(define_insn "*movsi_compare0"
bd5b4116 5923 [(set (reg:CC CC_REGNUM)
cffb2a26 5924 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
5925 (const_int 0)))
5926 (set (match_operand:SI 0 "s_register_operand" "=r,r")
5927 (match_dup 1))]
25f905c2 5928 "TARGET_32BIT"
e2348bcb 5929 "@
40dbec34 5930 cmp%?\\t%0, #0
25f905c2 5931 sub%.\\t%0, %1, #0"
65f68e55 5932 [(set_attr "conds" "set")
d82e788e 5933 (set_attr "type" "alus_imm,alus_imm")]
cffb2a26 5934)
b11cae9e 5935
b11cae9e 5936;; Subroutine to store a half word from a register into memory.
5937;; Operand 0 is the source register (HImode)
c8f69309 5938;; Operand 1 is the destination address in a register (SImode)
b11cae9e 5939
9c08d1fa 5940;; In both this routine and the next, we must be careful not to spill
01cc3b75 5941;; a memory address of reg+large_const into a separate PLUS insn, since this
9c08d1fa 5942;; can generate unrecognizable rtl.
5943
b11cae9e 5944(define_expand "storehi"
c8f69309 5945 [;; store the low byte
f082f1c4 5946 (set (match_operand 1 "" "") (match_dup 3))
b11cae9e 5947 ;; extract the high byte
c8f69309 5948 (set (match_dup 2)
5949 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
b11cae9e 5950 ;; store the high byte
787f8210 5951 (set (match_dup 4) (match_dup 5))]
cffb2a26 5952 "TARGET_ARM"
b11cae9e 5953 "
215b30b3 5954 {
537ffcfc 5955 rtx op1 = operands[1];
5956 rtx addr = XEXP (op1, 0);
215b30b3 5957 enum rtx_code code = GET_CODE (addr);
5958
0438d37f 5959 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
215b30b3 5960 || code == MINUS)
537ffcfc 5961 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
215b30b3 5962
537ffcfc 5963 operands[4] = adjust_address (op1, QImode, 1);
e513d163 5964 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 5965 operands[3] = gen_lowpart (QImode, operands[0]);
5966 operands[0] = gen_lowpart (SImode, operands[0]);
787f8210 5967 operands[2] = gen_reg_rtx (SImode);
5968 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 5969 }"
5970)
b11cae9e 5971
c7597b5d 5972(define_expand "storehi_bigend"
f082f1c4 5973 [(set (match_dup 4) (match_dup 3))
c7597b5d 5974 (set (match_dup 2)
5975 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
787f8210 5976 (set (match_operand 1 "" "") (match_dup 5))]
cffb2a26 5977 "TARGET_ARM"
b11cae9e 5978 "
215b30b3 5979 {
537ffcfc 5980 rtx op1 = operands[1];
5981 rtx addr = XEXP (op1, 0);
215b30b3 5982 enum rtx_code code = GET_CODE (addr);
5983
0438d37f 5984 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
215b30b3 5985 || code == MINUS)
537ffcfc 5986 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
215b30b3 5987
537ffcfc 5988 operands[4] = adjust_address (op1, QImode, 1);
e513d163 5989 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 5990 operands[3] = gen_lowpart (QImode, operands[0]);
5991 operands[0] = gen_lowpart (SImode, operands[0]);
5992 operands[2] = gen_reg_rtx (SImode);
787f8210 5993 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 5994 }"
5995)
c7597b5d 5996
5997;; Subroutine to store a half word integer constant into memory.
5998(define_expand "storeinthi"
f082f1c4 5999 [(set (match_operand 0 "" "")
787f8210 6000 (match_operand 1 "" ""))
9e8503e6 6001 (set (match_dup 3) (match_dup 2))]
cffb2a26 6002 "TARGET_ARM"
c7597b5d 6003 "
215b30b3 6004 {
6005 HOST_WIDE_INT value = INTVAL (operands[1]);
6006 rtx addr = XEXP (operands[0], 0);
537ffcfc 6007 rtx op0 = operands[0];
215b30b3 6008 enum rtx_code code = GET_CODE (addr);
c7597b5d 6009
0438d37f 6010 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
215b30b3 6011 || code == MINUS)
537ffcfc 6012 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
c7597b5d 6013
215b30b3 6014 operands[1] = gen_reg_rtx (SImode);
6015 if (BYTES_BIG_ENDIAN)
6016 {
6017 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
6018 if ((value & 255) == ((value >> 8) & 255))
6019 operands[2] = operands[1];
6020 else
6021 {
6022 operands[2] = gen_reg_rtx (SImode);
6023 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
6024 }
6025 }
6026 else
6027 {
6028 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
6029 if ((value & 255) == ((value >> 8) & 255))
6030 operands[2] = operands[1];
6031 else
6032 {
6033 operands[2] = gen_reg_rtx (SImode);
6034 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
6035 }
6036 }
c7597b5d 6037
537ffcfc 6038 operands[3] = adjust_address (op0, QImode, 1);
e513d163 6039 operands[0] = adjust_address (operands[0], QImode, 0);
9e8503e6 6040 operands[2] = gen_lowpart (QImode, operands[2]);
787f8210 6041 operands[1] = gen_lowpart (QImode, operands[1]);
215b30b3 6042 }"
6043)
b11cae9e 6044
f7fbdd4a 6045(define_expand "storehi_single_op"
6046 [(set (match_operand:HI 0 "memory_operand" "")
6047 (match_operand:HI 1 "general_operand" ""))]
25f905c2 6048 "TARGET_32BIT && arm_arch4"
f7fbdd4a 6049 "
215b30b3 6050 if (!s_register_operand (operands[1], HImode))
f7fbdd4a 6051 operands[1] = copy_to_mode_reg (HImode, operands[1]);
215b30b3 6052 "
6053)
f7fbdd4a 6054
b11cae9e 6055(define_expand "movhi"
6056 [(set (match_operand:HI 0 "general_operand" "")
c8f69309 6057 (match_operand:HI 1 "general_operand" ""))]
cffb2a26 6058 "TARGET_EITHER"
b11cae9e 6059 "
cffb2a26 6060 if (TARGET_ARM)
b11cae9e 6061 {
e1ba4a27 6062 if (can_create_pseudo_p ())
cffb2a26 6063 {
0438d37f 6064 if (MEM_P (operands[0]))
b11cae9e 6065 {
cffb2a26 6066 if (arm_arch4)
6067 {
6068 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
6069 DONE;
6070 }
0438d37f 6071 if (CONST_INT_P (operands[1]))
cffb2a26 6072 emit_insn (gen_storeinthi (operands[0], operands[1]));
c7597b5d 6073 else
cffb2a26 6074 {
0438d37f 6075 if (MEM_P (operands[1]))
cffb2a26 6076 operands[1] = force_reg (HImode, operands[1]);
6077 if (BYTES_BIG_ENDIAN)
6078 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
6079 else
6080 emit_insn (gen_storehi (operands[1], operands[0]));
6081 }
6082 DONE;
b11cae9e 6083 }
cffb2a26 6084 /* Sign extend a constant, and keep it in an SImode reg. */
0438d37f 6085 else if (CONST_INT_P (operands[1]))
9c08d1fa 6086 {
cffb2a26 6087 rtx reg = gen_reg_rtx (SImode);
6088 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
6089
6090 /* If the constant is already valid, leave it alone. */
215b30b3 6091 if (!const_ok_for_arm (val))
cffb2a26 6092 {
6093 /* If setting all the top bits will make the constant
6094 loadable in a single instruction, then set them.
6095 Otherwise, sign extend the number. */
6096
215b30b3 6097 if (const_ok_for_arm (~(val | ~0xffff)))
cffb2a26 6098 val |= ~0xffff;
6099 else if (val & 0x8000)
6100 val |= ~0xffff;
6101 }
6102
6103 emit_insn (gen_movsi (reg, GEN_INT (val)));
9e8503e6 6104 operands[1] = gen_lowpart (HImode, reg);
9c08d1fa 6105 }
e1ba4a27 6106 else if (arm_arch4 && optimize && can_create_pseudo_p ()
0438d37f 6107 && MEM_P (operands[1]))
0045890a 6108 {
6109 rtx reg = gen_reg_rtx (SImode);
6110
6111 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
6112 operands[1] = gen_lowpart (HImode, reg);
6113 }
215b30b3 6114 else if (!arm_arch4)
f7fbdd4a 6115 {
0438d37f 6116 if (MEM_P (operands[1]))
cffb2a26 6117 {
c1a66faf 6118 rtx base;
6119 rtx offset = const0_rtx;
6120 rtx reg = gen_reg_rtx (SImode);
6121
0438d37f 6122 if ((REG_P (base = XEXP (operands[1], 0))
c1a66faf 6123 || (GET_CODE (base) == PLUS
0438d37f 6124 && (CONST_INT_P (offset = XEXP (base, 1)))
c1a66faf 6125 && ((INTVAL(offset) & 1) != 1)
0438d37f 6126 && REG_P (base = XEXP (base, 0))))
c1a66faf 6127 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
206ee9a2 6128 {
8deb3959 6129 rtx new_rtx;
c1a66faf 6130
8deb3959 6131 new_rtx = widen_memory_access (operands[1], SImode,
6132 ((INTVAL (offset) & ~3)
6133 - INTVAL (offset)));
6134 emit_insn (gen_movsi (reg, new_rtx));
c1a66faf 6135 if (((INTVAL (offset) & 2) != 0)
6136 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
6137 {
6138 rtx reg2 = gen_reg_rtx (SImode);
6139
6140 emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
6141 reg = reg2;
6142 }
206ee9a2 6143 }
c1a66faf 6144 else
6145 emit_insn (gen_movhi_bytes (reg, operands[1]));
6146
6147 operands[1] = gen_lowpart (HImode, reg);
cffb2a26 6148 }
6149 }
6150 }
674a8f0b 6151 /* Handle loading a large integer during reload. */
0438d37f 6152 else if (CONST_INT_P (operands[1])
215b30b3 6153 && !const_ok_for_arm (INTVAL (operands[1]))
6154 && !const_ok_for_arm (~INTVAL (operands[1])))
cffb2a26 6155 {
6156 /* Writing a constant to memory needs a scratch, which should
6157 be handled with SECONDARY_RELOADs. */
0438d37f 6158 gcc_assert (REG_P (operands[0]));
cffb2a26 6159
6160 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
6161 emit_insn (gen_movsi (operands[0], operands[1]));
6162 DONE;
6163 }
6164 }
25f905c2 6165 else if (TARGET_THUMB2)
6166 {
6167 /* Thumb-2 can do everything except mem=mem and mem=const easily. */
e1ba4a27 6168 if (can_create_pseudo_p ())
25f905c2 6169 {
0438d37f 6170 if (!REG_P (operands[0]))
25f905c2 6171 operands[1] = force_reg (HImode, operands[1]);
6172 /* Zero extend a constant, and keep it in an SImode reg. */
0438d37f 6173 else if (CONST_INT_P (operands[1]))
25f905c2 6174 {
6175 rtx reg = gen_reg_rtx (SImode);
6176 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
6177
6178 emit_insn (gen_movsi (reg, GEN_INT (val)));
6179 operands[1] = gen_lowpart (HImode, reg);
6180 }
6181 }
6182 }
6183 else /* TARGET_THUMB1 */
cffb2a26 6184 {
e1ba4a27 6185 if (can_create_pseudo_p ())
cffb2a26 6186 {
0438d37f 6187 if (CONST_INT_P (operands[1]))
6cffc037 6188 {
6189 rtx reg = gen_reg_rtx (SImode);
6190
6191 emit_insn (gen_movsi (reg, operands[1]));
6192 operands[1] = gen_lowpart (HImode, reg);
6193 }
cffb2a26 6194
6195 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 6196 happen if we are passed a SP (never OK for HImode/QImode) or
bc409cb4 6197 virtual register (also rejected as illegitimate for HImode/QImode)
6198 relative address. */
cffb2a26 6199 /* ??? This should perhaps be fixed elsewhere, for instance, in
6200 fixup_stack_1, by checking for other kinds of invalid addresses,
6201 e.g. a bare reference to a virtual register. This may confuse the
6202 alpha though, which must handle this case differently. */
0438d37f 6203 if (MEM_P (operands[0])
215b30b3 6204 && !memory_address_p (GET_MODE (operands[0]),
6205 XEXP (operands[0], 0)))
537ffcfc 6206 operands[0]
6207 = replace_equiv_address (operands[0],
6208 copy_to_reg (XEXP (operands[0], 0)));
cffb2a26 6209
0438d37f 6210 if (MEM_P (operands[1])
215b30b3 6211 && !memory_address_p (GET_MODE (operands[1]),
6212 XEXP (operands[1], 0)))
537ffcfc 6213 operands[1]
6214 = replace_equiv_address (operands[1],
6215 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 6216
0438d37f 6217 if (MEM_P (operands[1]) && optimize > 0)
6cffc037 6218 {
6219 rtx reg = gen_reg_rtx (SImode);
6220
6221 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
6222 operands[1] = gen_lowpart (HImode, reg);
6223 }
6224
0438d37f 6225 if (MEM_P (operands[0]))
6cffc037 6226 operands[1] = force_reg (HImode, operands[1]);
cffb2a26 6227 }
0438d37f 6228 else if (CONST_INT_P (operands[1])
234f6557 6229 && !satisfies_constraint_I (operands[1]))
cffb2a26 6230 {
6cffc037 6231 /* Handle loading a large integer during reload. */
6232
cffb2a26 6233 /* Writing a constant to memory needs a scratch, which should
6234 be handled with SECONDARY_RELOADs. */
0438d37f 6235 gcc_assert (REG_P (operands[0]));
cffb2a26 6236
1a83b3ff 6237 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
cffb2a26 6238 emit_insn (gen_movsi (operands[0], operands[1]));
6239 DONE;
6240 }
b11cae9e 6241 }
cffb2a26 6242 "
6243)
6244
25f7a26e 6245(define_expand "movhi_bytes"
eab14235 6246 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 6247 (set (match_dup 3)
eab14235 6248 (zero_extend:SI (match_dup 6)))
25f7a26e 6249 (set (match_operand:SI 0 "" "")
6250 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
cffb2a26 6251 "TARGET_ARM"
25f7a26e 6252 "
215b30b3 6253 {
6254 rtx mem1, mem2;
6255 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
6256
788fcce0 6257 mem1 = change_address (operands[1], QImode, addr);
29c05e22 6258 mem2 = change_address (operands[1], QImode,
6259 plus_constant (Pmode, addr, 1));
215b30b3 6260 operands[0] = gen_lowpart (SImode, operands[0]);
6261 operands[1] = mem1;
6262 operands[2] = gen_reg_rtx (SImode);
6263 operands[3] = gen_reg_rtx (SImode);
6264 operands[6] = mem2;
25f7a26e 6265
215b30b3 6266 if (BYTES_BIG_ENDIAN)
6267 {
6268 operands[4] = operands[2];
6269 operands[5] = operands[3];
6270 }
6271 else
6272 {
6273 operands[4] = operands[3];
6274 operands[5] = operands[2];
6275 }
6276 }"
6277)
25f7a26e 6278
c7597b5d 6279(define_expand "movhi_bigend"
6280 [(set (match_dup 2)
6281 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
6282 (const_int 16)))
6283 (set (match_dup 3)
6284 (ashiftrt:SI (match_dup 2) (const_int 16)))
6285 (set (match_operand:HI 0 "s_register_operand" "")
787f8210 6286 (match_dup 4))]
cffb2a26 6287 "TARGET_ARM"
c7597b5d 6288 "
6289 operands[2] = gen_reg_rtx (SImode);
6290 operands[3] = gen_reg_rtx (SImode);
787f8210 6291 operands[4] = gen_lowpart (HImode, operands[3]);
215b30b3 6292 "
6293)
b11cae9e 6294
a2f10574 6295;; Pattern to recognize insn generated default case above
f7fbdd4a 6296(define_insn "*movhi_insn_arch4"
e4585731 6297 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r,m,r")
6298 (match_operand:HI 1 "general_operand" "rIk,K,n,r,mi"))]
cffb2a26 6299 "TARGET_ARM
6300 && arm_arch4
85e02ccb 6301 && (register_operand (operands[0], HImode)
6302 || register_operand (operands[1], HImode))"
f7fbdd4a 6303 "@
6304 mov%?\\t%0, %1\\t%@ movhi
6305 mvn%?\\t%0, #%B1\\t%@ movhi
b1c1a101 6306 movw%?\\t%0, %L1\\t%@ movhi
25f905c2 6307 str%(h%)\\t%1, %0\\t%@ movhi
6308 ldr%(h%)\\t%0, %1\\t%@ movhi"
65f68e55 6309 [(set_attr "predicable" "yes")
e4585731 6310 (set_attr "pool_range" "*,*,*,*,256")
6311 (set_attr "neg_pool_range" "*,*,*,*,244")
6312 (set_attr "arch" "*,*,v6t2,*,*")
65f68e55 6313 (set_attr_alternative "type"
6314 [(if_then_else (match_operand 1 "const_int_operand" "")
1aed5204 6315 (const_string "mov_imm" )
6316 (const_string "mov_reg"))
6317 (const_string "mvn_imm")
e4585731 6318 (const_string "mov_imm")
65f68e55 6319 (const_string "store1")
6320 (const_string "load1")])]
cffb2a26 6321)
f7fbdd4a 6322
f7fbdd4a 6323(define_insn "*movhi_bytes"
65f68e55 6324 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
5fd254ed 6325 (match_operand:HI 1 "arm_rhs_operand" "I,rk,K"))]
c1a66faf 6326 "TARGET_ARM"
25f7a26e 6327 "@
65f68e55 6328 mov%?\\t%0, %1\\t%@ movhi
25f7a26e 6329 mov%?\\t%0, %1\\t%@ movhi
0d66636f 6330 mvn%?\\t%0, #%B1\\t%@ movhi"
d2a518d1 6331 [(set_attr "predicable" "yes")
1aed5204 6332 (set_attr "type" "mov_imm,mov_reg,mvn_imm")]
0d66636f 6333)
cffb2a26 6334
bc5c7e08 6335;; We use a DImode scratch because we may occasionally need an additional
6336;; temporary if the address isn't offsettable -- push_reload doesn't seem
6337;; to take any notice of the "o" constraints on reload_memory_operand operand.
d3373b54 6338(define_expand "reload_outhi"
cffb2a26 6339 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
215b30b3 6340 (match_operand:HI 1 "s_register_operand" "r")
6341 (match_operand:DI 2 "s_register_operand" "=&l")])]
cffb2a26 6342 "TARGET_EITHER"
6343 "if (TARGET_ARM)
6344 arm_reload_out_hi (operands);
6345 else
6346 thumb_reload_out_hi (operands);
d3373b54 6347 DONE;
cffb2a26 6348 "
6349)
d3373b54 6350
25f7a26e 6351(define_expand "reload_inhi"
6352 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
cffb2a26 6353 (match_operand:HI 1 "arm_reload_memory_operand" "o")
bc5c7e08 6354 (match_operand:DI 2 "s_register_operand" "=&r")])]
c1a66faf 6355 "TARGET_EITHER"
25f7a26e 6356 "
cffb2a26 6357 if (TARGET_ARM)
6358 arm_reload_in_hi (operands);
6359 else
6360 thumb_reload_out_hi (operands);
25f7a26e 6361 DONE;
6362")
6363
9c08d1fa 6364(define_expand "movqi"
6365 [(set (match_operand:QI 0 "general_operand" "")
6366 (match_operand:QI 1 "general_operand" ""))]
cffb2a26 6367 "TARGET_EITHER"
9c08d1fa 6368 "
6cffc037 6369 /* Everything except mem = const or mem = mem can be done easily */
0045890a 6370
e1ba4a27 6371 if (can_create_pseudo_p ())
cffb2a26 6372 {
0438d37f 6373 if (CONST_INT_P (operands[1]))
6cffc037 6374 {
6375 rtx reg = gen_reg_rtx (SImode);
6376
03770691 6377 /* For thumb we want an unsigned immediate, then we are more likely
6378 to be able to use a movs insn. */
6379 if (TARGET_THUMB)
6380 operands[1] = GEN_INT (INTVAL (operands[1]) & 255);
6381
6cffc037 6382 emit_insn (gen_movsi (reg, operands[1]));
6383 operands[1] = gen_lowpart (QImode, reg);
6384 }
cffb2a26 6385
6cffc037 6386 if (TARGET_THUMB)
6387 {
cffb2a26 6388 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 6389 happen if we are passed a SP (never OK for HImode/QImode) or
bc409cb4 6390 virtual register (also rejected as illegitimate for HImode/QImode)
6391 relative address. */
cffb2a26 6392 /* ??? This should perhaps be fixed elsewhere, for instance, in
6393 fixup_stack_1, by checking for other kinds of invalid addresses,
6394 e.g. a bare reference to a virtual register. This may confuse the
6395 alpha though, which must handle this case differently. */
0438d37f 6396 if (MEM_P (operands[0])
215b30b3 6397 && !memory_address_p (GET_MODE (operands[0]),
cffb2a26 6398 XEXP (operands[0], 0)))
537ffcfc 6399 operands[0]
6400 = replace_equiv_address (operands[0],
6401 copy_to_reg (XEXP (operands[0], 0)));
0438d37f 6402 if (MEM_P (operands[1])
215b30b3 6403 && !memory_address_p (GET_MODE (operands[1]),
cffb2a26 6404 XEXP (operands[1], 0)))
537ffcfc 6405 operands[1]
6406 = replace_equiv_address (operands[1],
6407 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 6408 }
6409
0438d37f 6410 if (MEM_P (operands[1]) && optimize > 0)
6cffc037 6411 {
6412 rtx reg = gen_reg_rtx (SImode);
6413
6414 emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
6415 operands[1] = gen_lowpart (QImode, reg);
6416 }
6417
0438d37f 6418 if (MEM_P (operands[0]))
6cffc037 6419 operands[1] = force_reg (QImode, operands[1]);
6420 }
6421 else if (TARGET_THUMB
0438d37f 6422 && CONST_INT_P (operands[1])
234f6557 6423 && !satisfies_constraint_I (operands[1]))
6cffc037 6424 {
674a8f0b 6425 /* Handle loading a large integer during reload. */
cffb2a26 6426
6cffc037 6427 /* Writing a constant to memory needs a scratch, which should
6428 be handled with SECONDARY_RELOADs. */
0438d37f 6429 gcc_assert (REG_P (operands[0]));
6cffc037 6430
6431 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
6432 emit_insn (gen_movsi (operands[0], operands[1]));
6433 DONE;
cffb2a26 6434 }
6435 "
6436)
b11cae9e 6437
cffb2a26 6438(define_insn "*arm_movqi_insn"
fd711051 6439 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,l,r,l,Uu,r,m")
490f62ca 6440 (match_operand:QI 1 "general_operand" "rk,rk,I,Py,K,Uu,l,Uh,r"))]
25f905c2 6441 "TARGET_32BIT
cffb2a26 6442 && ( register_operand (operands[0], QImode)
6443 || register_operand (operands[1], QImode))"
5565501b 6444 "@
fd711051 6445 mov%?\\t%0, %1
6446 mov%?\\t%0, %1
65f68e55 6447 mov%?\\t%0, %1
5565501b 6448 mov%?\\t%0, %1
6449 mvn%?\\t%0, #%B1
25f905c2 6450 ldr%(b%)\\t%0, %1
a54e3e7b 6451 str%(b%)\\t%1, %0
6452 ldr%(b%)\\t%0, %1
25f905c2 6453 str%(b%)\\t%1, %0"
1aed5204 6454 [(set_attr "type" "mov_reg,mov_reg,mov_imm,mov_imm,mvn_imm,load1,store1,load1,store1")
a54e3e7b 6455 (set_attr "predicable" "yes")
fd711051 6456 (set_attr "predicable_short_it" "yes,yes,yes,no,no,no,no,no,no")
6457 (set_attr "arch" "t2,any,any,t2,any,t2,t2,any,any")
6458 (set_attr "length" "2,4,4,2,4,2,2,4,4")]
cffb2a26 6459)
6460
9b8516be 6461;; HFmode moves
6462(define_expand "movhf"
6463 [(set (match_operand:HF 0 "general_operand" "")
6464 (match_operand:HF 1 "general_operand" ""))]
6465 "TARGET_EITHER"
6466 "
6467 if (TARGET_32BIT)
6468 {
0438d37f 6469 if (MEM_P (operands[0]))
9b8516be 6470 operands[1] = force_reg (HFmode, operands[1]);
6471 }
6472 else /* TARGET_THUMB1 */
6473 {
6474 if (can_create_pseudo_p ())
6475 {
0438d37f 6476 if (!REG_P (operands[0]))
9b8516be 6477 operands[1] = force_reg (HFmode, operands[1]);
6478 }
6479 }
6480 "
6481)
6482
6483(define_insn "*arm32_movhf"
6484 [(set (match_operand:HF 0 "nonimmediate_operand" "=r,m,r,r")
6485 (match_operand:HF 1 "general_operand" " m,r,r,F"))]
7c36fe71 6486 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_FP16) && !arm_restrict_it
9b8516be 6487 && ( s_register_operand (operands[0], HFmode)
6488 || s_register_operand (operands[1], HFmode))"
6489 "*
6490 switch (which_alternative)
6491 {
6492 case 0: /* ARM register from memory */
6493 return \"ldr%(h%)\\t%0, %1\\t%@ __fp16\";
6494 case 1: /* memory from ARM register */
6495 return \"str%(h%)\\t%1, %0\\t%@ __fp16\";
6496 case 2: /* ARM register from ARM register */
6497 return \"mov%?\\t%0, %1\\t%@ __fp16\";
6498 case 3: /* ARM register from constant */
6499 {
6500 REAL_VALUE_TYPE r;
6501 long bits;
6502 rtx ops[4];
6503
6504 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
6505 bits = real_to_target (NULL, &r, HFmode);
6506 ops[0] = operands[0];
6507 ops[1] = GEN_INT (bits);
6508 ops[2] = GEN_INT (bits & 0xff00);
6509 ops[3] = GEN_INT (bits & 0x00ff);
6510
6511 if (arm_arch_thumb2)
6512 output_asm_insn (\"movw%?\\t%0, %1\", ops);
6513 else
6514 output_asm_insn (\"mov%?\\t%0, %2\;orr%?\\t%0, %0, %3\", ops);
6515 return \"\";
6516 }
6517 default:
6518 gcc_unreachable ();
6519 }
6520 "
6521 [(set_attr "conds" "unconditional")
ad4fc3c0 6522 (set_attr "type" "load1,store1,mov_reg,multiple")
9b8516be 6523 (set_attr "length" "4,4,4,8")
d2a518d1 6524 (set_attr "predicable" "yes")]
9b8516be 6525)
6526
87b22bf7 6527(define_expand "movsf"
6528 [(set (match_operand:SF 0 "general_operand" "")
6529 (match_operand:SF 1 "general_operand" ""))]
cffb2a26 6530 "TARGET_EITHER"
87b22bf7 6531 "
25f905c2 6532 if (TARGET_32BIT)
cffb2a26 6533 {
0438d37f 6534 if (MEM_P (operands[0]))
cffb2a26 6535 operands[1] = force_reg (SFmode, operands[1]);
6536 }
25f905c2 6537 else /* TARGET_THUMB1 */
cffb2a26 6538 {
e1ba4a27 6539 if (can_create_pseudo_p ())
cffb2a26 6540 {
0438d37f 6541 if (!REG_P (operands[0]))
cffb2a26 6542 operands[1] = force_reg (SFmode, operands[1]);
6543 }
6544 }
6545 "
6546)
6547
03d440a6 6548;; Transform a floating-point move of a constant into a core register into
6549;; an SImode operation.
cffb2a26 6550(define_split
03d440a6 6551 [(set (match_operand:SF 0 "arm_general_register_operand" "")
cffb2a26 6552 (match_operand:SF 1 "immediate_operand" ""))]
339034d0 6553 "TARGET_EITHER
cffb2a26 6554 && reload_completed
0438d37f 6555 && CONST_DOUBLE_P (operands[1])"
cffb2a26 6556 [(set (match_dup 2) (match_dup 3))]
6557 "
6558 operands[2] = gen_lowpart (SImode, operands[0]);
6559 operands[3] = gen_lowpart (SImode, operands[1]);
6560 if (operands[2] == 0 || operands[3] == 0)
6561 FAIL;
215b30b3 6562 "
6563)
87b22bf7 6564
cffb2a26 6565(define_insn "*arm_movsf_soft_insn"
6566 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
6567 (match_operand:SF 1 "general_operand" "r,mE,r"))]
cde1623a 6568 "TARGET_32BIT
cffb2a26 6569 && TARGET_SOFT_FLOAT
0438d37f 6570 && (!MEM_P (operands[0])
215b30b3 6571 || register_operand (operands[1], SFmode))"
9a1112d7 6572 "@
6573 mov%?\\t%0, %1
6574 ldr%?\\t%0, %1\\t%@ float
6575 str%?\\t%1, %0\\t%@ float"
cde1623a 6576 [(set_attr "predicable" "yes")
7c36fe71 6577 (set_attr "predicable_short_it" "no")
1aed5204 6578 (set_attr "type" "mov_reg,load1,store1")
42e1de19 6579 (set_attr "arm_pool_range" "*,4096,*")
6580 (set_attr "thumb2_pool_range" "*,4094,*")
cde1623a 6581 (set_attr "arm_neg_pool_range" "*,4084,*")
6582 (set_attr "thumb2_neg_pool_range" "*,0,*")]
cffb2a26 6583)
6584
9c08d1fa 6585(define_expand "movdf"
87b22bf7 6586 [(set (match_operand:DF 0 "general_operand" "")
6587 (match_operand:DF 1 "general_operand" ""))]
cffb2a26 6588 "TARGET_EITHER"
9c08d1fa 6589 "
25f905c2 6590 if (TARGET_32BIT)
cffb2a26 6591 {
0438d37f 6592 if (MEM_P (operands[0]))
cffb2a26 6593 operands[1] = force_reg (DFmode, operands[1]);
6594 }
6595 else /* TARGET_THUMB */
6596 {
e1ba4a27 6597 if (can_create_pseudo_p ())
cffb2a26 6598 {
0438d37f 6599 if (!REG_P (operands[0]))
cffb2a26 6600 operands[1] = force_reg (DFmode, operands[1]);
6601 }
6602 }
6603 "
6604)
b11cae9e 6605
9c08d1fa 6606;; Reloading a df mode value stored in integer regs to memory can require a
6607;; scratch reg.
6608(define_expand "reload_outdf"
cffb2a26 6609 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
87b22bf7 6610 (match_operand:DF 1 "s_register_operand" "r")
6611 (match_operand:SI 2 "s_register_operand" "=&r")]
06adefdc 6612 "TARGET_THUMB2"
87b22bf7 6613 "
215b30b3 6614 {
6615 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
f7fbdd4a 6616
215b30b3 6617 if (code == REG)
6618 operands[2] = XEXP (operands[0], 0);
6619 else if (code == POST_INC || code == PRE_DEC)
6620 {
6621 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
6622 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
6623 emit_insn (gen_movdi (operands[0], operands[1]));
6624 DONE;
6625 }
6626 else if (code == PRE_INC)
6627 {
6628 rtx reg = XEXP (XEXP (operands[0], 0), 0);
f7fbdd4a 6629
215b30b3 6630 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
6631 operands[2] = reg;
6632 }
6633 else if (code == POST_DEC)
6634 operands[2] = XEXP (XEXP (operands[0], 0), 0);
6635 else
6636 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
6637 XEXP (XEXP (operands[0], 0), 1)));
f7fbdd4a 6638
788fcce0 6639 emit_insn (gen_rtx_SET (VOIDmode,
6640 replace_equiv_address (operands[0], operands[2]),
215b30b3 6641 operands[1]));
f7fbdd4a 6642
215b30b3 6643 if (code == POST_DEC)
6644 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
6645
6646 DONE;
6647 }"
6648)
9c08d1fa 6649
9a1112d7 6650(define_insn "*movdf_soft_insn"
353cf59a 6651 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,q,m")
6652 (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,q"))]
cde1623a 6653 "TARGET_32BIT && TARGET_SOFT_FLOAT
b2778788 6654 && ( register_operand (operands[0], DFmode)
6655 || register_operand (operands[1], DFmode))"
d51f92df 6656 "*
6657 switch (which_alternative)
6658 {
6659 case 0:
6660 case 1:
6661 case 2:
6662 return \"#\";
6663 default:
26ff80c0 6664 return output_move_double (operands, true, NULL);
d51f92df 6665 }
6666 "
359a6e9f 6667 [(set_attr "length" "8,12,16,8,8")
1b7da4ac 6668 (set_attr "type" "multiple,multiple,multiple,load2,store2")
42e1de19 6669 (set_attr "arm_pool_range" "*,*,*,1020,*")
6670 (set_attr "thumb2_pool_range" "*,*,*,1018,*")
8848d797 6671 (set_attr "arm_neg_pool_range" "*,*,*,1004,*")
cde1623a 6672 (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
cffb2a26 6673)
b11cae9e 6674\f
b11cae9e 6675
9c08d1fa 6676;; load- and store-multiple insns
6677;; The arm can load/store any set of registers, provided that they are in
320ea44d 6678;; ascending order, but these expanders assume a contiguous set.
b11cae9e 6679
9c08d1fa 6680(define_expand "load_multiple"
6681 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6682 (match_operand:SI 1 "" ""))
6683 (use (match_operand:SI 2 "" ""))])]
25f905c2 6684 "TARGET_32BIT"
9580c25f 6685{
6686 HOST_WIDE_INT offset = 0;
6687
bd5b4116 6688 /* Support only fixed point registers. */
0438d37f 6689 if (!CONST_INT_P (operands[2])
9c08d1fa 6690 || INTVAL (operands[2]) > 14
6691 || INTVAL (operands[2]) < 2
0438d37f 6692 || !MEM_P (operands[1])
6693 || !REG_P (operands[0])
bd5b4116 6694 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
6695 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 6696 FAIL;
6697
6698 operands[3]
320ea44d 6699 = arm_gen_load_multiple (arm_regs_in_sequence + REGNO (operands[0]),
6700 INTVAL (operands[2]),
f082f1c4 6701 force_reg (SImode, XEXP (operands[1], 0)),
320ea44d 6702 FALSE, operands[1], &offset);
9580c25f 6703})
b11cae9e 6704
9c08d1fa 6705(define_expand "store_multiple"
6706 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6707 (match_operand:SI 1 "" ""))
6708 (use (match_operand:SI 2 "" ""))])]
25f905c2 6709 "TARGET_32BIT"
9580c25f 6710{
6711 HOST_WIDE_INT offset = 0;
6712
674a8f0b 6713 /* Support only fixed point registers. */
0438d37f 6714 if (!CONST_INT_P (operands[2])
9c08d1fa 6715 || INTVAL (operands[2]) > 14
6716 || INTVAL (operands[2]) < 2
0438d37f 6717 || !REG_P (operands[1])
6718 || !MEM_P (operands[0])
bd5b4116 6719 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
6720 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 6721 FAIL;
6722
6723 operands[3]
320ea44d 6724 = arm_gen_store_multiple (arm_regs_in_sequence + REGNO (operands[1]),
6725 INTVAL (operands[2]),
f082f1c4 6726 force_reg (SImode, XEXP (operands[0], 0)),
320ea44d 6727 FALSE, operands[0], &offset);
9580c25f 6728})
b11cae9e 6729
9c08d1fa 6730
e34ebfca 6731(define_expand "setmemsi"
6732 [(match_operand:BLK 0 "general_operand" "")
6733 (match_operand:SI 1 "const_int_operand" "")
6734 (match_operand:SI 2 "const_int_operand" "")
6735 (match_operand:SI 3 "const_int_operand" "")]
6736 "TARGET_32BIT"
6737{
6738 if (arm_gen_setmem (operands))
6739 DONE;
6740
6741 FAIL;
6742})
6743
6744
9c08d1fa 6745;; Move a block of memory if it is word aligned and MORE than 2 words long.
6746;; We could let this apply for blocks of less than this, but it clobbers so
6747;; many registers that there is then probably a better way.
6748
008c057d 6749(define_expand "movmemqi"
34191dd1 6750 [(match_operand:BLK 0 "general_operand" "")
6751 (match_operand:BLK 1 "general_operand" "")
6752 (match_operand:SI 2 "const_int_operand" "")
6753 (match_operand:SI 3 "const_int_operand" "")]
ae51a965 6754 ""
9c08d1fa 6755 "
25f905c2 6756 if (TARGET_32BIT)
cffb2a26 6757 {
ae51a965 6758 if (TARGET_LDRD && current_tune->prefer_ldrd_strd
6759 && !optimize_function_for_size_p (cfun))
6760 {
6761 if (gen_movmem_ldrd_strd (operands))
6762 DONE;
6763 FAIL;
6764 }
6765
008c057d 6766 if (arm_gen_movmemqi (operands))
cffb2a26 6767 DONE;
6768 FAIL;
6769 }
25f905c2 6770 else /* TARGET_THUMB1 */
cffb2a26 6771 {
6772 if ( INTVAL (operands[3]) != 4
6773 || INTVAL (operands[2]) > 48)
6774 FAIL;
6775
008c057d 6776 thumb_expand_movmemqi (operands);
cffb2a26 6777 DONE;
6778 }
6779 "
6780)
9c08d1fa 6781\f
b11cae9e 6782
341940e8 6783;; Compare & branch insns
8d232dc7 6784;; The range calculations are based as follows:
341940e8 6785;; For forward branches, the address calculation returns the address of
6786;; the next instruction. This is 2 beyond the branch instruction.
6787;; For backward branches, the address calculation returns the address of
6788;; the first instruction in this pattern (cmp). This is 2 before the branch
6789;; instruction for the shortest sequence, and 4 before the branch instruction
6790;; if we have to jump around an unconditional branch.
6791;; To the basic branch range the PC offset must be added (this is +4).
6792;; So for forward branches we have
6793;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
6794;; And for backward branches we have
6795;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
6796;;
6797;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
6798;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
cffb2a26 6799
aeac46d4 6800(define_expand "cbranchsi4"
6801 [(set (pc) (if_then_else
aa06947a 6802 (match_operator 0 "expandable_comparison_operator"
aeac46d4 6803 [(match_operand:SI 1 "s_register_operand" "")
6804 (match_operand:SI 2 "nonmemory_operand" "")])
6805 (label_ref (match_operand 3 "" ""))
6806 (pc)))]
f9aa4160 6807 "TARGET_EITHER"
aeac46d4 6808 "
74f4459c 6809 if (!TARGET_THUMB1)
6810 {
f9aa4160 6811 if (!arm_validize_comparison (&operands[0], &operands[1], &operands[2]))
6812 FAIL;
74f4459c 6813 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6814 operands[3]));
6815 DONE;
6816 }
25f905c2 6817 if (thumb1_cmpneg_operand (operands[2], SImode))
aeac46d4 6818 {
6819 emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
6820 operands[3], operands[0]));
6821 DONE;
6822 }
25f905c2 6823 if (!thumb1_cmp_operand (operands[2], SImode))
aeac46d4 6824 operands[2] = force_reg (SImode, operands[2]);
6825 ")
6826
74f4459c 6827(define_expand "cbranchsf4"
6828 [(set (pc) (if_then_else
aa06947a 6829 (match_operator 0 "expandable_comparison_operator"
74f4459c 6830 [(match_operand:SF 1 "s_register_operand" "")
6831 (match_operand:SF 2 "arm_float_compare_operand" "")])
6832 (label_ref (match_operand 3 "" ""))
6833 (pc)))]
6834 "TARGET_32BIT && TARGET_HARD_FLOAT"
6835 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6836 operands[3])); DONE;"
6837)
6838
6839(define_expand "cbranchdf4"
6840 [(set (pc) (if_then_else
aa06947a 6841 (match_operator 0 "expandable_comparison_operator"
74f4459c 6842 [(match_operand:DF 1 "s_register_operand" "")
6843 (match_operand:DF 2 "arm_float_compare_operand" "")])
6844 (label_ref (match_operand 3 "" ""))
6845 (pc)))]
a50d7267 6846 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
74f4459c 6847 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6848 operands[3])); DONE;"
6849)
6850
74f4459c 6851(define_expand "cbranchdi4"
6852 [(set (pc) (if_then_else
aa06947a 6853 (match_operator 0 "expandable_comparison_operator"
b8eae306 6854 [(match_operand:DI 1 "s_register_operand" "")
a8045a4f 6855 (match_operand:DI 2 "cmpdi_operand" "")])
74f4459c 6856 (label_ref (match_operand 3 "" ""))
6857 (pc)))]
a8045a4f 6858 "TARGET_32BIT"
6859 "{
0438d37f 6860 if (!arm_validize_comparison (&operands[0], &operands[1], &operands[2]))
f9aa4160 6861 FAIL;
6862 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
a8045a4f 6863 operands[3]));
6864 DONE;
6865 }"
74f4459c 6866)
6867
9c08d1fa 6868;; Comparison and test insns
6869
cffb2a26 6870(define_insn "*arm_cmpsi_insn"
bd5b4116 6871 [(set (reg:CC CC_REGNUM)
f9f234ec 6872 (compare:CC (match_operand:SI 0 "s_register_operand" "l,r,r,r,r")
6873 (match_operand:SI 1 "arm_add_operand" "Py,r,r,I,L")))]
25f905c2 6874 "TARGET_32BIT"
5565501b 6875 "@
a6864a24 6876 cmp%?\\t%0, %1
6877 cmp%?\\t%0, %1
aea4c774 6878 cmp%?\\t%0, %1
f9f234ec 6879 cmp%?\\t%0, %1
aea4c774 6880 cmn%?\\t%0, #%n1"
a6864a24 6881 [(set_attr "conds" "set")
f9f234ec 6882 (set_attr "arch" "t2,t2,any,any,any")
6883 (set_attr "length" "2,2,4,4,4")
65f68e55 6884 (set_attr "predicable" "yes")
f9f234ec 6885 (set_attr "predicable_short_it" "yes,yes,yes,no,no")
112eda6f 6886 (set_attr "type" "alus_imm,alus_sreg,alus_sreg,alus_imm,alus_imm")]
cffb2a26 6887)
b11cae9e 6888
d5d4dc8d 6889(define_insn "*cmpsi_shiftsi"
bd5b4116 6890 [(set (reg:CC CC_REGNUM)
d82e788e 6891 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r,r")
cffb2a26 6892 (match_operator:SI 3 "shift_operator"
d82e788e 6893 [(match_operand:SI 1 "s_register_operand" "r,r,r")
6894 (match_operand:SI 2 "shift_amount_operand" "M,r,M")])))]
d5d4dc8d 6895 "TARGET_32BIT"
f9f234ec 6896 "cmp\\t%0, %1%S3"
344495ea 6897 [(set_attr "conds" "set")
331beb1a 6898 (set_attr "shift" "1")
d82e788e 6899 (set_attr "arch" "32,a,a")
6900 (set_attr "type" "alus_shift_imm,alu_shift_reg,alus_shift_imm")])
b11cae9e 6901
d5d4dc8d 6902(define_insn "*cmpsi_shiftsi_swp"
bd5b4116 6903 [(set (reg:CC_SWP CC_REGNUM)
aea4c774 6904 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
d82e788e 6905 [(match_operand:SI 1 "s_register_operand" "r,r,r")
6906 (match_operand:SI 2 "shift_amount_operand" "M,r,M")])
6907 (match_operand:SI 0 "s_register_operand" "r,r,r")))]
d5d4dc8d 6908 "TARGET_32BIT"
aea4c774 6909 "cmp%?\\t%0, %1%S3"
344495ea 6910 [(set_attr "conds" "set")
331beb1a 6911 (set_attr "shift" "1")
d82e788e 6912 (set_attr "arch" "32,a,a")
6913 (set_attr "type" "alus_shift_imm,alu_shift_reg,alus_shift_imm")])
b11cae9e 6914
25f905c2 6915(define_insn "*arm_cmpsi_negshiftsi_si"
aed179ae 6916 [(set (reg:CC_Z CC_REGNUM)
6917 (compare:CC_Z
6918 (neg:SI (match_operator:SI 1 "shift_operator"
6919 [(match_operand:SI 2 "s_register_operand" "r")
6920 (match_operand:SI 3 "reg_or_int_operand" "rM")]))
6921 (match_operand:SI 0 "s_register_operand" "r")))]
cffb2a26 6922 "TARGET_ARM"
aed179ae 6923 "cmn%?\\t%0, %2%S1"
344495ea 6924 [(set_attr "conds" "set")
aed179ae 6925 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
d82e788e 6926 (const_string "alus_shift_imm")
6927 (const_string "alus_shift_reg")))
596e5e8f 6928 (set_attr "predicable" "yes")]
0d66636f 6929)
b11cae9e 6930
a8045a4f 6931;; DImode comparisons. The generic code generates branches that
6932;; if-conversion can not reduce to a conditional compare, so we do
6933;; that directly.
6934
ba6a3b2f 6935(define_insn_and_split "*arm_cmpdi_insn"
a8045a4f 6936 [(set (reg:CC_NCV CC_REGNUM)
6937 (compare:CC_NCV (match_operand:DI 0 "s_register_operand" "r")
6938 (match_operand:DI 1 "arm_di_operand" "rDi")))
6939 (clobber (match_scratch:SI 2 "=r"))]
b805622c 6940 "TARGET_32BIT"
ba6a3b2f 6941 "#" ; "cmp\\t%Q0, %Q1\;sbcs\\t%2, %R0, %R1"
6942 "&& reload_completed"
6943 [(set (reg:CC CC_REGNUM)
6944 (compare:CC (match_dup 0) (match_dup 1)))
6945 (parallel [(set (reg:CC CC_REGNUM)
6946 (compare:CC (match_dup 3) (match_dup 4)))
6947 (set (match_dup 2)
6948 (minus:SI (match_dup 5)
6949 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))])]
6950 {
6951 operands[3] = gen_highpart (SImode, operands[0]);
6952 operands[0] = gen_lowpart (SImode, operands[0]);
6953 if (CONST_INT_P (operands[1]))
6954 {
6955 operands[4] = GEN_INT (~INTVAL (gen_highpart_mode (SImode,
6956 DImode,
6957 operands[1])));
6958 operands[5] = gen_rtx_PLUS (SImode, operands[3], operands[4]);
6959 }
6960 else
6961 {
6962 operands[4] = gen_highpart (SImode, operands[1]);
6963 operands[5] = gen_rtx_MINUS (SImode, operands[3], operands[4]);
6964 }
6965 operands[1] = gen_lowpart (SImode, operands[1]);
6966 operands[2] = gen_lowpart (SImode, operands[2]);
6967 }
a8045a4f 6968 [(set_attr "conds" "set")
1b7da4ac 6969 (set_attr "length" "8")
6970 (set_attr "type" "multiple")]
a8045a4f 6971)
6972
ba6a3b2f 6973(define_insn_and_split "*arm_cmpdi_unsigned"
a8045a4f 6974 [(set (reg:CC_CZ CC_REGNUM)
1a86364b 6975 (compare:CC_CZ (match_operand:DI 0 "s_register_operand" "l,r,r,r")
6976 (match_operand:DI 1 "arm_di_operand" "Py,r,Di,rDi")))]
7c36fe71 6977
48a98053 6978 "TARGET_32BIT"
ba6a3b2f 6979 "#" ; "cmp\\t%R0, %R1\;it eq\;cmpeq\\t%Q0, %Q1"
6980 "&& reload_completed"
6981 [(set (reg:CC CC_REGNUM)
6982 (compare:CC (match_dup 2) (match_dup 3)))
6983 (cond_exec (eq:SI (reg:CC CC_REGNUM) (const_int 0))
6984 (set (reg:CC CC_REGNUM)
6985 (compare:CC (match_dup 0) (match_dup 1))))]
6986 {
6987 operands[2] = gen_highpart (SImode, operands[0]);
6988 operands[0] = gen_lowpart (SImode, operands[0]);
6989 if (CONST_INT_P (operands[1]))
6990 operands[3] = gen_highpart_mode (SImode, DImode, operands[1]);
6991 else
6992 operands[3] = gen_highpart (SImode, operands[1]);
6993 operands[1] = gen_lowpart (SImode, operands[1]);
6994 }
a8045a4f 6995 [(set_attr "conds" "set")
1a86364b 6996 (set_attr "enabled_for_depr_it" "yes,yes,no,*")
6997 (set_attr "arch" "t2,t2,t2,a")
6998 (set_attr "length" "6,6,10,8")
1b7da4ac 6999 (set_attr "type" "multiple")]
a8045a4f 7000)
7001
7002(define_insn "*arm_cmpdi_zero"
7003 [(set (reg:CC_Z CC_REGNUM)
7004 (compare:CC_Z (match_operand:DI 0 "s_register_operand" "r")
7005 (const_int 0)))
7006 (clobber (match_scratch:SI 1 "=r"))]
7007 "TARGET_32BIT"
7008 "orr%.\\t%1, %Q0, %R0"
1b7da4ac 7009 [(set_attr "conds" "set")
7010 (set_attr "type" "logics_reg")]
a8045a4f 7011)
7012
9c08d1fa 7013; This insn allows redundant compares to be removed by cse, nothing should
7014; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
7015; is deleted later on. The match_dup will match the mode here, so that
7016; mode changes of the condition codes aren't lost by this even though we don't
7017; specify what they are.
7018
8a18b90c 7019(define_insn "*deleted_compare"
9c08d1fa 7020 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
25f905c2 7021 "TARGET_32BIT"
40dbec34 7022 "\\t%@ deleted compare"
cffb2a26 7023 [(set_attr "conds" "set")
1b7da4ac 7024 (set_attr "length" "0")
7025 (set_attr "type" "no_insn")]
cffb2a26 7026)
9c08d1fa 7027
7028\f
7029;; Conditional branch insns
7030
74f4459c 7031(define_expand "cbranch_cc"
9c08d1fa 7032 [(set (pc)
74f4459c 7033 (if_then_else (match_operator 0 "" [(match_operand 1 "" "")
7034 (match_operand 2 "" "")])
7035 (label_ref (match_operand 3 "" ""))
9c08d1fa 7036 (pc)))]
25f905c2 7037 "TARGET_32BIT"
74f4459c 7038 "operands[1] = arm_gen_compare_reg (GET_CODE (operands[0]),
e1b93706 7039 operands[1], operands[2], NULL_RTX);
74f4459c 7040 operands[2] = const0_rtx;"
8fa3ba89 7041)
7042
7043;;
7044;; Patterns to match conditional branch insns.
7045;;
7046
ffcc986d 7047(define_insn "arm_cond_branch"
9c08d1fa 7048 [(set (pc)
8fa3ba89 7049 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 7050 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 7051 (label_ref (match_operand 0 "" ""))
7052 (pc)))]
25f905c2 7053 "TARGET_32BIT"
d75350ce 7054 "*
9c08d1fa 7055 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 7056 {
7057 arm_ccfsm_state += 2;
7058 return \"\";
7059 }
e2348bcb 7060 return \"b%d1\\t%l0\";
cffb2a26 7061 "
a2cd141b 7062 [(set_attr "conds" "use")
a6864a24 7063 (set_attr "type" "branch")
7064 (set (attr "length")
7065 (if_then_else
0bf497f5 7066 (and (match_test "TARGET_THUMB2")
a6864a24 7067 (and (ge (minus (match_dup 0) (pc)) (const_int -250))
7068 (le (minus (match_dup 0) (pc)) (const_int 256))))
7069 (const_int 2)
7070 (const_int 4)))]
cffb2a26 7071)
d75350ce 7072
cffb2a26 7073(define_insn "*arm_cond_branch_reversed"
9c08d1fa 7074 [(set (pc)
8fa3ba89 7075 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 7076 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 7077 (pc)
7078 (label_ref (match_operand 0 "" ""))))]
25f905c2 7079 "TARGET_32BIT"
d75350ce 7080 "*
9c08d1fa 7081 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 7082 {
7083 arm_ccfsm_state += 2;
7084 return \"\";
7085 }
e2348bcb 7086 return \"b%D1\\t%l0\";
cffb2a26 7087 "
a2cd141b 7088 [(set_attr "conds" "use")
a6864a24 7089 (set_attr "type" "branch")
7090 (set (attr "length")
7091 (if_then_else
0bf497f5 7092 (and (match_test "TARGET_THUMB2")
a6864a24 7093 (and (ge (minus (match_dup 0) (pc)) (const_int -250))
7094 (le (minus (match_dup 0) (pc)) (const_int 256))))
7095 (const_int 2)
7096 (const_int 4)))]
cffb2a26 7097)
7098
b11cae9e 7099\f
9c08d1fa 7100
7101; scc insns
7102
74f4459c 7103(define_expand "cstore_cc"
7db9af5d 7104 [(set (match_operand:SI 0 "s_register_operand" "")
74f4459c 7105 (match_operator:SI 1 "" [(match_operand 2 "" "")
7106 (match_operand 3 "" "")]))]
25f905c2 7107 "TARGET_32BIT"
74f4459c 7108 "operands[2] = arm_gen_compare_reg (GET_CODE (operands[1]),
e1b93706 7109 operands[2], operands[3], NULL_RTX);
74f4459c 7110 operands[3] = const0_rtx;"
8fa3ba89 7111)
7112
a3b84066 7113(define_insn_and_split "*mov_scc"
9c08d1fa 7114 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7115 (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7116 [(match_operand 2 "cc_register" "") (const_int 0)]))]
cffb2a26 7117 "TARGET_ARM"
a3b84066 7118 "#" ; "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
7119 "TARGET_ARM"
7120 [(set (match_dup 0)
7121 (if_then_else:SI (match_dup 1)
7122 (const_int 1)
7123 (const_int 0)))]
7124 ""
cffb2a26 7125 [(set_attr "conds" "use")
1b7da4ac 7126 (set_attr "length" "8")
7127 (set_attr "type" "multiple")]
cffb2a26 7128)
9c08d1fa 7129
a3b84066 7130(define_insn_and_split "*mov_negscc"
9c08d1fa 7131 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7132 (neg:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7133 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 7134 "TARGET_ARM"
a3b84066 7135 "#" ; "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
7136 "TARGET_ARM"
7137 [(set (match_dup 0)
7138 (if_then_else:SI (match_dup 1)
7139 (match_dup 3)
7140 (const_int 0)))]
7141 {
7142 operands[3] = GEN_INT (~0);
7143 }
cffb2a26 7144 [(set_attr "conds" "use")
1b7da4ac 7145 (set_attr "length" "8")
7146 (set_attr "type" "multiple")]
cffb2a26 7147)
9c08d1fa 7148
a3b84066 7149(define_insn_and_split "*mov_notscc"
9c08d1fa 7150 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7151 (not:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7152 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 7153 "TARGET_ARM"
a3b84066 7154 "#" ; "mvn%D1\\t%0, #0\;mvn%d1\\t%0, #1"
7155 "TARGET_ARM"
7156 [(set (match_dup 0)
7157 (if_then_else:SI (match_dup 1)
7158 (match_dup 3)
7159 (match_dup 4)))]
7160 {
7161 operands[3] = GEN_INT (~1);
7162 operands[4] = GEN_INT (~0);
7163 }
cffb2a26 7164 [(set_attr "conds" "use")
1b7da4ac 7165 (set_attr "length" "8")
7166 (set_attr "type" "multiple")]
cffb2a26 7167)
9c08d1fa 7168
595d88b5 7169(define_expand "cstoresi4"
7170 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 7171 (match_operator:SI 1 "expandable_comparison_operator"
595d88b5 7172 [(match_operand:SI 2 "s_register_operand" "")
7173 (match_operand:SI 3 "reg_or_int_operand" "")]))]
74f4459c 7174 "TARGET_32BIT || TARGET_THUMB1"
595d88b5 7175 "{
7176 rtx op3, scratch, scratch2;
7177
74f4459c 7178 if (!TARGET_THUMB1)
7179 {
7180 if (!arm_add_operand (operands[3], SImode))
7181 operands[3] = force_reg (SImode, operands[3]);
7182 emit_insn (gen_cstore_cc (operands[0], operands[1],
7183 operands[2], operands[3]));
7184 DONE;
7185 }
7186
595d88b5 7187 if (operands[3] == const0_rtx)
7188 {
7189 switch (GET_CODE (operands[1]))
7190 {
7191 case EQ:
25f905c2 7192 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], operands[2]));
595d88b5 7193 break;
7194
7195 case NE:
25f905c2 7196 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], operands[2]));
595d88b5 7197 break;
7198
7199 case LE:
7200 scratch = expand_binop (SImode, add_optab, operands[2], constm1_rtx,
7201 NULL_RTX, 0, OPTAB_WIDEN);
7202 scratch = expand_binop (SImode, ior_optab, operands[2], scratch,
7203 NULL_RTX, 0, OPTAB_WIDEN);
7204 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7205 operands[0], 1, OPTAB_WIDEN);
7206 break;
7207
7208 case GE:
7209 scratch = expand_unop (SImode, one_cmpl_optab, operands[2],
7210 NULL_RTX, 1);
7211 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7212 NULL_RTX, 1, OPTAB_WIDEN);
7213 break;
7214
7215 case GT:
7216 scratch = expand_binop (SImode, ashr_optab, operands[2],
7217 GEN_INT (31), NULL_RTX, 0, OPTAB_WIDEN);
7218 scratch = expand_binop (SImode, sub_optab, scratch, operands[2],
7219 NULL_RTX, 0, OPTAB_WIDEN);
7220 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31), operands[0],
7221 0, OPTAB_WIDEN);
7222 break;
7223
7224 /* LT is handled by generic code. No need for unsigned with 0. */
7225 default:
7226 FAIL;
7227 }
7228 DONE;
7229 }
7230
7231 switch (GET_CODE (operands[1]))
7232 {
7233 case EQ:
7234 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7235 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7236 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], scratch));
595d88b5 7237 break;
7238
7239 case NE:
7240 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7241 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7242 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], scratch));
595d88b5 7243 break;
7244
7245 case LE:
7246 op3 = force_reg (SImode, operands[3]);
7247
7248 scratch = expand_binop (SImode, lshr_optab, operands[2], GEN_INT (31),
7249 NULL_RTX, 1, OPTAB_WIDEN);
7250 scratch2 = expand_binop (SImode, ashr_optab, op3, GEN_INT (31),
7251 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7252 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
595d88b5 7253 op3, operands[2]));
7254 break;
7255
7256 case GE:
7257 op3 = operands[3];
25f905c2 7258 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7259 op3 = force_reg (SImode, op3);
7260 scratch = expand_binop (SImode, ashr_optab, operands[2], GEN_INT (31),
7261 NULL_RTX, 0, OPTAB_WIDEN);
7262 scratch2 = expand_binop (SImode, lshr_optab, op3, GEN_INT (31),
7263 NULL_RTX, 1, OPTAB_WIDEN);
25f905c2 7264 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
595d88b5 7265 operands[2], op3));
7266 break;
7267
7268 case LEU:
7269 op3 = force_reg (SImode, operands[3]);
7270 scratch = force_reg (SImode, const0_rtx);
25f905c2 7271 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
595d88b5 7272 op3, operands[2]));
7273 break;
7274
7275 case GEU:
7276 op3 = operands[3];
25f905c2 7277 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7278 op3 = force_reg (SImode, op3);
7279 scratch = force_reg (SImode, const0_rtx);
25f905c2 7280 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
595d88b5 7281 operands[2], op3));
7282 break;
7283
7284 case LTU:
7285 op3 = operands[3];
25f905c2 7286 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7287 op3 = force_reg (SImode, op3);
7288 scratch = gen_reg_rtx (SImode);
408b7ae5 7289 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], operands[2], op3));
595d88b5 7290 break;
7291
7292 case GTU:
7293 op3 = force_reg (SImode, operands[3]);
7294 scratch = gen_reg_rtx (SImode);
408b7ae5 7295 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], op3, operands[2]));
595d88b5 7296 break;
7297
7298 /* No good sequences for GT, LT. */
7299 default:
7300 FAIL;
7301 }
7302 DONE;
7303}")
7304
74f4459c 7305(define_expand "cstoresf4"
7306 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 7307 (match_operator:SI 1 "expandable_comparison_operator"
74f4459c 7308 [(match_operand:SF 2 "s_register_operand" "")
7309 (match_operand:SF 3 "arm_float_compare_operand" "")]))]
7310 "TARGET_32BIT && TARGET_HARD_FLOAT"
7311 "emit_insn (gen_cstore_cc (operands[0], operands[1],
7312 operands[2], operands[3])); DONE;"
7313)
7314
7315(define_expand "cstoredf4"
7316 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 7317 (match_operator:SI 1 "expandable_comparison_operator"
74f4459c 7318 [(match_operand:DF 2 "s_register_operand" "")
7319 (match_operand:DF 3 "arm_float_compare_operand" "")]))]
d63ed457 7320 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
74f4459c 7321 "emit_insn (gen_cstore_cc (operands[0], operands[1],
7322 operands[2], operands[3])); DONE;"
7323)
7324
74f4459c 7325(define_expand "cstoredi4"
7326 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 7327 (match_operator:SI 1 "expandable_comparison_operator"
b8eae306 7328 [(match_operand:DI 2 "s_register_operand" "")
a8045a4f 7329 (match_operand:DI 3 "cmpdi_operand" "")]))]
7330 "TARGET_32BIT"
7331 "{
f9aa4160 7332 if (!arm_validize_comparison (&operands[1],
7333 &operands[2],
7334 &operands[3]))
7335 FAIL;
7336 emit_insn (gen_cstore_cc (operands[0], operands[1], operands[2],
a8045a4f 7337 operands[3]));
7338 DONE;
7339 }"
74f4459c 7340)
7341
9c08d1fa 7342\f
39b5e676 7343;; Conditional move insns
7344
7345(define_expand "movsicc"
8a18b90c 7346 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 7347 (if_then_else:SI (match_operand 1 "expandable_comparison_operator" "")
aea4c774 7348 (match_operand:SI 2 "arm_not_operand" "")
8a18b90c 7349 (match_operand:SI 3 "arm_not_operand" "")))]
25f905c2 7350 "TARGET_32BIT"
39b5e676 7351 "
215b30b3 7352 {
f9aa4160 7353 enum rtx_code code;
278b301d 7354 rtx ccreg;
7355
f9aa4160 7356 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
7357 &XEXP (operands[1], 1)))
278b301d 7358 FAIL;
f9aa4160 7359
7360 code = GET_CODE (operands[1]);
74f4459c 7361 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
e1b93706 7362 XEXP (operands[1], 1), NULL_RTX);
29bb088d 7363 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7364 }"
7365)
39b5e676 7366
7367(define_expand "movsfcc"
8a18b90c 7368 [(set (match_operand:SF 0 "s_register_operand" "")
4df97ffc 7369 (if_then_else:SF (match_operand 1 "arm_cond_move_operator" "")
8a18b90c 7370 (match_operand:SF 2 "s_register_operand" "")
d86c91f6 7371 (match_operand:SF 3 "s_register_operand" "")))]
19f6bf8d 7372 "TARGET_32BIT && TARGET_HARD_FLOAT"
39b5e676 7373 "
215b30b3 7374 {
7375 enum rtx_code code = GET_CODE (operands[1]);
7376 rtx ccreg;
f082f1c4 7377
f9aa4160 7378 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
7379 &XEXP (operands[1], 1)))
7380 FAIL;
39b5e676 7381
f9aa4160 7382 code = GET_CODE (operands[1]);
74f4459c 7383 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
e1b93706 7384 XEXP (operands[1], 1), NULL_RTX);
29bb088d 7385 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7386 }"
7387)
39b5e676 7388
7389(define_expand "movdfcc"
8a18b90c 7390 [(set (match_operand:DF 0 "s_register_operand" "")
4df97ffc 7391 (if_then_else:DF (match_operand 1 "arm_cond_move_operator" "")
8a18b90c 7392 (match_operand:DF 2 "s_register_operand" "")
d86c91f6 7393 (match_operand:DF 3 "s_register_operand" "")))]
994606f8 7394 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
39b5e676 7395 "
215b30b3 7396 {
7397 enum rtx_code code = GET_CODE (operands[1]);
278b301d 7398 rtx ccreg;
39b5e676 7399
f9aa4160 7400 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
7401 &XEXP (operands[1], 1)))
7402 FAIL;
7403 code = GET_CODE (operands[1]);
74f4459c 7404 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
e1b93706 7405 XEXP (operands[1], 1), NULL_RTX);
29bb088d 7406 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7407 }"
7408)
39b5e676 7409
91cb50d2 7410(define_insn "*cmov<mode>"
7411 [(set (match_operand:SDF 0 "s_register_operand" "=<F_constraint>")
7412 (if_then_else:SDF (match_operator 1 "arm_vsel_comparison_operator"
7413 [(match_operand 2 "cc_register" "") (const_int 0)])
7414 (match_operand:SDF 3 "s_register_operand"
7415 "<F_constraint>")
7416 (match_operand:SDF 4 "s_register_operand"
7417 "<F_constraint>")))]
7418 "TARGET_HARD_FLOAT && TARGET_FPU_ARMV8 <vfp_double_cond>"
7419 "*
7420 {
7421 enum arm_cond_code code = maybe_get_arm_condition_code (operands[1]);
7422 switch (code)
7423 {
7424 case ARM_GE:
7425 case ARM_GT:
7426 case ARM_EQ:
7427 case ARM_VS:
7428 return \"vsel%d1.<V_if_elem>\\t%<V_reg>0, %<V_reg>3, %<V_reg>4\";
7429 case ARM_LT:
7430 case ARM_LE:
7431 case ARM_NE:
7432 case ARM_VC:
7433 return \"vsel%D1.<V_if_elem>\\t%<V_reg>0, %<V_reg>4, %<V_reg>3\";
7434 default:
7435 gcc_unreachable ();
7436 }
7437 return \"\";
7438 }"
7439 [(set_attr "conds" "use")
6664d308 7440 (set_attr "type" "fcsel")]
91cb50d2 7441)
7442
190efb17 7443(define_insn_and_split "*movsicc_insn"
f082f1c4 7444 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
8a18b90c 7445 (if_then_else:SI
8fa3ba89 7446 (match_operator 3 "arm_comparison_operator"
8a18b90c 7447 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 7448 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
7449 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
cffb2a26 7450 "TARGET_ARM"
39b5e676 7451 "@
8a18b90c 7452 mov%D3\\t%0, %2
7453 mvn%D3\\t%0, #%B2
f082f1c4 7454 mov%d3\\t%0, %1
7455 mvn%d3\\t%0, #%B1
190efb17 7456 #
7457 #
7458 #
7459 #"
7460 ; alt4: mov%d3\\t%0, %1\;mov%D3\\t%0, %2
7461 ; alt5: mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
7462 ; alt6: mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
7463 ; alt7: mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
7464 "&& reload_completed"
7465 [(const_int 0)]
7466 {
7467 enum rtx_code rev_code;
3754d046 7468 machine_mode mode;
190efb17 7469 rtx rev_cond;
7470
7471 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
7472 operands[3],
7473 gen_rtx_SET (VOIDmode,
7474 operands[0],
7475 operands[1])));
7476
7477 rev_code = GET_CODE (operands[3]);
7478 mode = GET_MODE (operands[4]);
7479 if (mode == CCFPmode || mode == CCFPEmode)
7480 rev_code = reverse_condition_maybe_unordered (rev_code);
7481 else
7482 rev_code = reverse_condition (rev_code);
7483
7484 rev_cond = gen_rtx_fmt_ee (rev_code,
7485 VOIDmode,
7486 operands[4],
7487 const0_rtx);
7488 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
7489 rev_cond,
7490 gen_rtx_SET (VOIDmode,
7491 operands[0],
7492 operands[2])));
7493 DONE;
7494 }
f082f1c4 7495 [(set_attr "length" "4,4,4,4,8,8,8,8")
d2a518d1 7496 (set_attr "conds" "use")
65f68e55 7497 (set_attr_alternative "type"
7498 [(if_then_else (match_operand 2 "const_int_operand" "")
1aed5204 7499 (const_string "mov_imm")
7500 (const_string "mov_reg"))
7501 (const_string "mvn_imm")
65f68e55 7502 (if_then_else (match_operand 1 "const_int_operand" "")
1aed5204 7503 (const_string "mov_imm")
7504 (const_string "mov_reg"))
7505 (const_string "mvn_imm")
7506 (const_string "mov_reg")
7507 (const_string "mov_reg")
7508 (const_string "mov_reg")
7509 (const_string "mov_reg")])]
215b30b3 7510)
39b5e676 7511
39b5e676 7512(define_insn "*movsfcc_soft_insn"
f082f1c4 7513 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
8fa3ba89 7514 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
8a18b90c 7515 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 7516 (match_operand:SF 1 "s_register_operand" "0,r")
7517 (match_operand:SF 2 "s_register_operand" "r,0")))]
cffb2a26 7518 "TARGET_ARM && TARGET_SOFT_FLOAT"
f082f1c4 7519 "@
7520 mov%D3\\t%0, %2
7521 mov%d3\\t%0, %1"
d2a518d1 7522 [(set_attr "conds" "use")
1aed5204 7523 (set_attr "type" "mov_reg")]
8fa3ba89 7524)
39b5e676 7525
39b5e676 7526\f
9c08d1fa 7527;; Jump and linkage insns
7528
cffb2a26 7529(define_expand "jump"
9c08d1fa 7530 [(set (pc)
7531 (label_ref (match_operand 0 "" "")))]
cffb2a26 7532 "TARGET_EITHER"
9c08d1fa 7533 ""
cffb2a26 7534)
7535
7536(define_insn "*arm_jump"
7537 [(set (pc)
7538 (label_ref (match_operand 0 "" "")))]
25f905c2 7539 "TARGET_32BIT"
9c08d1fa 7540 "*
0d66636f 7541 {
7542 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7543 {
7544 arm_ccfsm_state += 2;
7545 return \"\";
7546 }
7547 return \"b%?\\t%l0\";
7548 }
7549 "
a6864a24 7550 [(set_attr "predicable" "yes")
7551 (set (attr "length")
7552 (if_then_else
0bf497f5 7553 (and (match_test "TARGET_THUMB2")
a6864a24 7554 (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
7555 (le (minus (match_dup 0) (pc)) (const_int 2048))))
7556 (const_int 2)
1b7da4ac 7557 (const_int 4)))
7558 (set_attr "type" "branch")]
0d66636f 7559)
9c08d1fa 7560
d3373b54 7561(define_expand "call"
7562 [(parallel [(call (match_operand 0 "memory_operand" "")
7563 (match_operand 1 "general_operand" ""))
cffb2a26 7564 (use (match_operand 2 "" ""))
bd5b4116 7565 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 7566 "TARGET_EITHER"
6c4c2133 7567 "
7568 {
bac7fc85 7569 rtx callee, pat;
bbe777ea 7570
bbe777ea 7571 /* In an untyped call, we can get NULL for operand 2. */
7572 if (operands[2] == NULL_RTX)
7573 operands[2] = const0_rtx;
7574
de55252a 7575 /* Decide if we should generate indirect calls by loading the
85c36fd1 7576 32-bit address of the callee into a register before performing the
de55252a 7577 branch and link. */
7578 callee = XEXP (operands[0], 0);
7579 if (GET_CODE (callee) == SYMBOL_REF
7580 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
7581 : !REG_P (callee))
bbe777ea 7582 XEXP (operands[0], 0) = force_reg (Pmode, callee);
bac7fc85 7583
7584 pat = gen_call_internal (operands[0], operands[1], operands[2]);
ca373797 7585 arm_emit_call_insn (pat, XEXP (operands[0], 0), false);
bac7fc85 7586 DONE;
6c4c2133 7587 }"
7588)
d3373b54 7589
bac7fc85 7590(define_expand "call_internal"
7591 [(parallel [(call (match_operand 0 "memory_operand" "")
7592 (match_operand 1 "general_operand" ""))
7593 (use (match_operand 2 "" ""))
7594 (clobber (reg:SI LR_REGNUM))])])
7595
f1039640 7596(define_insn "*call_reg_armv5"
d3373b54 7597 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
cffb2a26 7598 (match_operand 1 "" ""))
7599 (use (match_operand 2 "" ""))
bd5b4116 7600 (clobber (reg:SI LR_REGNUM))]
33ae7c4b 7601 "TARGET_ARM && arm_arch5 && !SIBLING_CALL_P (insn)"
f1039640 7602 "blx%?\\t%0"
7603 [(set_attr "type" "call")]
7604)
7605
7606(define_insn "*call_reg_arm"
7607 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7608 (match_operand 1 "" ""))
7609 (use (match_operand 2 "" ""))
7610 (clobber (reg:SI LR_REGNUM))]
33ae7c4b 7611 "TARGET_ARM && !arm_arch5 && !SIBLING_CALL_P (insn)"
9c08d1fa 7612 "*
5565501b 7613 return output_call (operands);
cffb2a26 7614 "
7615 ;; length is worst case, normally it is only two
7616 [(set_attr "length" "12")
7617 (set_attr "type" "call")]
7618)
9c08d1fa 7619
89504fc1 7620
7621;; Note: not used for armv5+ because the sequence used (ldr pc, ...) is not
7622;; considered a function call by the branch predictor of some cores (PR40887).
7623;; Falls back to blx rN (*call_reg_armv5).
7624
f7fbdd4a 7625(define_insn "*call_mem"
a3c63a9d 7626 [(call (mem:SI (match_operand:SI 0 "call_memory_operand" "m"))
cffb2a26 7627 (match_operand 1 "" ""))
7628 (use (match_operand 2 "" ""))
bd5b4116 7629 (clobber (reg:SI LR_REGNUM))]
33ae7c4b 7630 "TARGET_ARM && !arm_arch5 && !SIBLING_CALL_P (insn)"
9c08d1fa 7631 "*
5565501b 7632 return output_call_mem (operands);
cffb2a26 7633 "
7634 [(set_attr "length" "12")
7635 (set_attr "type" "call")]
7636)
7637
d3373b54 7638(define_expand "call_value"
e0698af7 7639 [(parallel [(set (match_operand 0 "" "")
7640 (call (match_operand 1 "memory_operand" "")
7641 (match_operand 2 "general_operand" "")))
cffb2a26 7642 (use (match_operand 3 "" ""))
bd5b4116 7643 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 7644 "TARGET_EITHER"
6c4c2133 7645 "
7646 {
bac7fc85 7647 rtx pat, callee;
bbe777ea 7648
7649 /* In an untyped call, we can get NULL for operand 2. */
7650 if (operands[3] == 0)
7651 operands[3] = const0_rtx;
7652
de55252a 7653 /* Decide if we should generate indirect calls by loading the
7654 32-bit address of the callee into a register before performing the
7655 branch and link. */
7656 callee = XEXP (operands[1], 0);
7657 if (GET_CODE (callee) == SYMBOL_REF
7658 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
7659 : !REG_P (callee))
78fe751b 7660 XEXP (operands[1], 0) = force_reg (Pmode, callee);
bac7fc85 7661
7662 pat = gen_call_value_internal (operands[0], operands[1],
7663 operands[2], operands[3]);
ca373797 7664 arm_emit_call_insn (pat, XEXP (operands[1], 0), false);
bac7fc85 7665 DONE;
6c4c2133 7666 }"
7667)
d3373b54 7668
bac7fc85 7669(define_expand "call_value_internal"
7670 [(parallel [(set (match_operand 0 "" "")
7671 (call (match_operand 1 "memory_operand" "")
7672 (match_operand 2 "general_operand" "")))
7673 (use (match_operand 3 "" ""))
7674 (clobber (reg:SI LR_REGNUM))])])
7675
f1039640 7676(define_insn "*call_value_reg_armv5"
27ed6835 7677 [(set (match_operand 0 "" "")
755eb2b4 7678 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
cffb2a26 7679 (match_operand 2 "" "")))
bbe777ea 7680 (use (match_operand 3 "" ""))
bd5b4116 7681 (clobber (reg:SI LR_REGNUM))]
33ae7c4b 7682 "TARGET_ARM && arm_arch5 && !SIBLING_CALL_P (insn)"
f1039640 7683 "blx%?\\t%1"
7684 [(set_attr "type" "call")]
7685)
7686
7687(define_insn "*call_value_reg_arm"
7688 [(set (match_operand 0 "" "")
7689 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7690 (match_operand 2 "" "")))
7691 (use (match_operand 3 "" ""))
7692 (clobber (reg:SI LR_REGNUM))]
33ae7c4b 7693 "TARGET_ARM && !arm_arch5 && !SIBLING_CALL_P (insn)"
9c08d1fa 7694 "*
215b30b3 7695 return output_call (&operands[1]);
cffb2a26 7696 "
7697 [(set_attr "length" "12")
7698 (set_attr "type" "call")]
7699)
9c08d1fa 7700
89504fc1 7701;; Note: see *call_mem
7702
f7fbdd4a 7703(define_insn "*call_value_mem"
27ed6835 7704 [(set (match_operand 0 "" "")
a3c63a9d 7705 (call (mem:SI (match_operand:SI 1 "call_memory_operand" "m"))
cffb2a26 7706 (match_operand 2 "" "")))
bbe777ea 7707 (use (match_operand 3 "" ""))
bd5b4116 7708 (clobber (reg:SI LR_REGNUM))]
33ae7c4b 7709 "TARGET_ARM && !arm_arch5 && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
7710 && !SIBLING_CALL_P (insn)"
9c08d1fa 7711 "*
215b30b3 7712 return output_call_mem (&operands[1]);
cffb2a26 7713 "
7714 [(set_attr "length" "12")
7715 (set_attr "type" "call")]
7716)
9c08d1fa 7717
7718;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
7719;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
7720
f7fbdd4a 7721(define_insn "*call_symbol"
27ed6835 7722 [(call (mem:SI (match_operand:SI 0 "" ""))
cffb2a26 7723 (match_operand 1 "" ""))
bbe777ea 7724 (use (match_operand 2 "" ""))
bd5b4116 7725 (clobber (reg:SI LR_REGNUM))]
d68c2c10 7726 "TARGET_32BIT
33ae7c4b 7727 && !SIBLING_CALL_P (insn)
cffb2a26 7728 && (GET_CODE (operands[0]) == SYMBOL_REF)
de55252a 7729 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
6ebaa29d 7730 "*
7731 {
55c1e470 7732 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
6ebaa29d 7733 }"
cffb2a26 7734 [(set_attr "type" "call")]
7735)
9c08d1fa 7736
f7fbdd4a 7737(define_insn "*call_value_symbol"
ccd90aaa 7738 [(set (match_operand 0 "" "")
27ed6835 7739 (call (mem:SI (match_operand:SI 1 "" ""))
dd6d7504 7740 (match_operand:SI 2 "" "")))
bbe777ea 7741 (use (match_operand 3 "" ""))
bd5b4116 7742 (clobber (reg:SI LR_REGNUM))]
d68c2c10 7743 "TARGET_32BIT
33ae7c4b 7744 && !SIBLING_CALL_P (insn)
cffb2a26 7745 && (GET_CODE (operands[1]) == SYMBOL_REF)
de55252a 7746 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
6ebaa29d 7747 "*
7748 {
55c1e470 7749 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
6ebaa29d 7750 }"
cffb2a26 7751 [(set_attr "type" "call")]
7752)
7753
ca373797 7754(define_expand "sibcall_internal"
7755 [(parallel [(call (match_operand 0 "memory_operand" "")
7756 (match_operand 1 "general_operand" ""))
7757 (return)
7758 (use (match_operand 2 "" ""))])])
7759
1c494086 7760;; We may also be able to do sibcalls for Thumb, but it's much harder...
7761(define_expand "sibcall"
7762 [(parallel [(call (match_operand 0 "memory_operand" "")
7763 (match_operand 1 "general_operand" ""))
2ba80634 7764 (return)
7765 (use (match_operand 2 "" ""))])]
d68c2c10 7766 "TARGET_32BIT"
1c494086 7767 "
7768 {
ca373797 7769 rtx pat;
7770
3112c3f7 7771 if ((!REG_P (XEXP (operands[0], 0))
7772 && GET_CODE (XEXP (operands[0], 0)) != SYMBOL_REF)
7773 || (GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
7774 && arm_is_long_call_p (SYMBOL_REF_DECL (XEXP (operands[0], 0)))))
33ae7c4b 7775 XEXP (operands[0], 0) = force_reg (SImode, XEXP (operands[0], 0));
7776
1c494086 7777 if (operands[2] == NULL_RTX)
7778 operands[2] = const0_rtx;
ca373797 7779
7780 pat = gen_sibcall_internal (operands[0], operands[1], operands[2]);
7781 arm_emit_call_insn (pat, operands[0], true);
7782 DONE;
1c494086 7783 }"
7784)
7785
ca373797 7786(define_expand "sibcall_value_internal"
7787 [(parallel [(set (match_operand 0 "" "")
7788 (call (match_operand 1 "memory_operand" "")
7789 (match_operand 2 "general_operand" "")))
7790 (return)
7791 (use (match_operand 3 "" ""))])])
7792
1c494086 7793(define_expand "sibcall_value"
ccd90aaa 7794 [(parallel [(set (match_operand 0 "" "")
1c494086 7795 (call (match_operand 1 "memory_operand" "")
7796 (match_operand 2 "general_operand" "")))
2ba80634 7797 (return)
7798 (use (match_operand 3 "" ""))])]
d68c2c10 7799 "TARGET_32BIT"
1c494086 7800 "
7801 {
ca373797 7802 rtx pat;
7803
3112c3f7 7804 if ((!REG_P (XEXP (operands[1], 0))
7805 && GET_CODE (XEXP (operands[1], 0)) != SYMBOL_REF)
7806 || (GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
7807 && arm_is_long_call_p (SYMBOL_REF_DECL (XEXP (operands[1], 0)))))
33ae7c4b 7808 XEXP (operands[1], 0) = force_reg (SImode, XEXP (operands[1], 0));
7809
1c494086 7810 if (operands[3] == NULL_RTX)
7811 operands[3] = const0_rtx;
ca373797 7812
7813 pat = gen_sibcall_value_internal (operands[0], operands[1],
7814 operands[2], operands[3]);
7815 arm_emit_call_insn (pat, operands[1], true);
7816 DONE;
1c494086 7817 }"
7818)
7819
7820(define_insn "*sibcall_insn"
84ce8e5c 7821 [(call (mem:SI (match_operand:SI 0 "call_insn_operand" "Cs, US"))
1c494086 7822 (match_operand 1 "" ""))
2ba80634 7823 (return)
7824 (use (match_operand 2 "" ""))]
33ae7c4b 7825 "TARGET_32BIT && SIBLING_CALL_P (insn)"
1c494086 7826 "*
33ae7c4b 7827 if (which_alternative == 1)
7828 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
7829 else
7830 {
7831 if (arm_arch5 || arm_arch4t)
947d113e 7832 return \"bx%?\\t%0\\t%@ indirect register sibling call\";
33ae7c4b 7833 else
7834 return \"mov%?\\t%|pc, %0\\t%@ indirect register sibling call\";
7835 }
1c494086 7836 "
7837 [(set_attr "type" "call")]
7838)
7839
7840(define_insn "*sibcall_value_insn"
84ce8e5c 7841 [(set (match_operand 0 "" "")
7842 (call (mem:SI (match_operand:SI 1 "call_insn_operand" "Cs,US"))
1c494086 7843 (match_operand 2 "" "")))
2ba80634 7844 (return)
7845 (use (match_operand 3 "" ""))]
33ae7c4b 7846 "TARGET_32BIT && SIBLING_CALL_P (insn)"
1c494086 7847 "*
33ae7c4b 7848 if (which_alternative == 1)
7849 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
7850 else
7851 {
7852 if (arm_arch5 || arm_arch4t)
84ce8e5c 7853 return \"bx%?\\t%1\";
33ae7c4b 7854 else
7855 return \"mov%?\\t%|pc, %1\\t@ indirect sibling call \";
7856 }
1c494086 7857 "
7858 [(set_attr "type" "call")]
7859)
7860
0686440e 7861(define_expand "<return_str>return"
7862 [(returns)]
8cba51a5 7863 "(TARGET_ARM || (TARGET_THUMB2
7864 && ARM_FUNC_TYPE (arm_current_func_type ()) == ARM_FT_NORMAL
7865 && !IS_STACKALIGN (arm_current_func_type ())))
0686440e 7866 <return_cond_false>"
8cba51a5 7867 "
7868 {
7869 if (TARGET_THUMB2)
7870 {
0686440e 7871 thumb2_expand_return (<return_simple_p>);
8cba51a5 7872 DONE;
7873 }
7874 }
7875 "
7876)
d68c2c10 7877
9c08d1fa 7878;; Often the return insn will be the same as loading from memory, so set attr
d68c2c10 7879(define_insn "*arm_return"
9c08d1fa 7880 [(return)]
cffb2a26 7881 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
9c08d1fa 7882 "*
9c08d1fa 7883 {
cffb2a26 7884 if (arm_ccfsm_state == 2)
7885 {
7886 arm_ccfsm_state += 2;
7887 return \"\";
7888 }
e2549f81 7889 return output_return_instruction (const_true_rtx, true, false, false);
cffb2a26 7890 }"
a2cd141b 7891 [(set_attr "type" "load1")
755eb2b4 7892 (set_attr "length" "12")
0d66636f 7893 (set_attr "predicable" "yes")]
cffb2a26 7894)
9c08d1fa 7895
0686440e 7896(define_insn "*cond_<return_str>return"
9c08d1fa 7897 [(set (pc)
8fa3ba89 7898 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 7899 [(match_operand 1 "cc_register" "") (const_int 0)])
0686440e 7900 (returns)
9c08d1fa 7901 (pc)))]
0686440e 7902 "TARGET_ARM <return_cond_true>"
9c08d1fa 7903 "*
8fa3ba89 7904 {
7905 if (arm_ccfsm_state == 2)
7906 {
7907 arm_ccfsm_state += 2;
7908 return \"\";
7909 }
0686440e 7910 return output_return_instruction (operands[0], true, false,
7911 <return_simple_p>);
8fa3ba89 7912 }"
7913 [(set_attr "conds" "use")
755eb2b4 7914 (set_attr "length" "12")
a2cd141b 7915 (set_attr "type" "load1")]
8fa3ba89 7916)
9c08d1fa 7917
0686440e 7918(define_insn "*cond_<return_str>return_inverted"
9c08d1fa 7919 [(set (pc)
8fa3ba89 7920 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 7921 [(match_operand 1 "cc_register" "") (const_int 0)])
9c08d1fa 7922 (pc)
0686440e 7923 (returns)))]
7924 "TARGET_ARM <return_cond_true>"
9c08d1fa 7925 "*
8fa3ba89 7926 {
7927 if (arm_ccfsm_state == 2)
7928 {
7929 arm_ccfsm_state += 2;
7930 return \"\";
7931 }
0686440e 7932 return output_return_instruction (operands[0], true, true,
7933 <return_simple_p>);
8fa3ba89 7934 }"
7935 [(set_attr "conds" "use")
37a1317b 7936 (set_attr "length" "12")
a2cd141b 7937 (set_attr "type" "load1")]
8fa3ba89 7938)
9c08d1fa 7939
e2549f81 7940(define_insn "*arm_simple_return"
7941 [(simple_return)]
7942 "TARGET_ARM"
7943 "*
7944 {
7945 if (arm_ccfsm_state == 2)
7946 {
7947 arm_ccfsm_state += 2;
7948 return \"\";
7949 }
7950 return output_return_instruction (const_true_rtx, true, false, true);
7951 }"
7952 [(set_attr "type" "branch")
7953 (set_attr "length" "4")
7954 (set_attr "predicable" "yes")]
7955)
7956
68121397 7957;; Generate a sequence of instructions to determine if the processor is
7958;; in 26-bit or 32-bit mode, and return the appropriate return address
7959;; mask.
7960
7961(define_expand "return_addr_mask"
7962 [(set (match_dup 1)
7963 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7964 (const_int 0)))
7965 (set (match_operand:SI 0 "s_register_operand" "")
7966 (if_then_else:SI (eq (match_dup 1) (const_int 0))
7967 (const_int -1)
7968 (const_int 67108860)))] ; 0x03fffffc
7969 "TARGET_ARM"
7970 "
62eddbd4 7971 operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
68121397 7972 ")
7973
7974(define_insn "*check_arch2"
7975 [(set (match_operand:CC_NOOV 0 "cc_register" "")
7976 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7977 (const_int 0)))]
7978 "TARGET_ARM"
7979 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
7980 [(set_attr "length" "8")
1b7da4ac 7981 (set_attr "conds" "set")
7982 (set_attr "type" "multiple")]
68121397 7983)
7984
9c08d1fa 7985;; Call subroutine returning any type.
7986
7987(define_expand "untyped_call"
7988 [(parallel [(call (match_operand 0 "" "")
7989 (const_int 0))
7990 (match_operand 1 "" "")
7991 (match_operand 2 "" "")])]
ccd90aaa 7992 "TARGET_EITHER"
9c08d1fa 7993 "
215b30b3 7994 {
7995 int i;
ccd90aaa 7996 rtx par = gen_rtx_PARALLEL (VOIDmode,
7997 rtvec_alloc (XVECLEN (operands[2], 0)));
7998 rtx addr = gen_reg_rtx (Pmode);
7999 rtx mem;
8000 int size = 0;
9c08d1fa 8001
ccd90aaa 8002 emit_move_insn (addr, XEXP (operands[1], 0));
8003 mem = change_address (operands[1], BLKmode, addr);
9c08d1fa 8004
215b30b3 8005 for (i = 0; i < XVECLEN (operands[2], 0); i++)
8006 {
ccd90aaa 8007 rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
9c08d1fa 8008
ccd90aaa 8009 /* Default code only uses r0 as a return value, but we could
8010 be using anything up to 4 registers. */
8011 if (REGNO (src) == R0_REGNUM)
8012 src = gen_rtx_REG (TImode, R0_REGNUM);
8013
8014 XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
8015 GEN_INT (size));
8016 size += GET_MODE_SIZE (GET_MODE (src));
8017 }
8018
8019 emit_call_insn (GEN_CALL_VALUE (par, operands[0], const0_rtx, NULL,
8020 const0_rtx));
8021
8022 size = 0;
8023
8024 for (i = 0; i < XVECLEN (par, 0); i++)
8025 {
8026 HOST_WIDE_INT offset = 0;
8027 rtx reg = XEXP (XVECEXP (par, 0, i), 0);
8028
8029 if (size != 0)
29c05e22 8030 emit_move_insn (addr, plus_constant (Pmode, addr, size));
ccd90aaa 8031
8032 mem = change_address (mem, GET_MODE (reg), NULL);
8033 if (REGNO (reg) == R0_REGNUM)
8034 {
8035 /* On thumb we have to use a write-back instruction. */
320ea44d 8036 emit_insn (arm_gen_store_multiple (arm_regs_in_sequence, 4, addr,
8037 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
ccd90aaa 8038 size = TARGET_ARM ? 16 : 0;
8039 }
8040 else
8041 {
8042 emit_move_insn (mem, reg);
8043 size = GET_MODE_SIZE (GET_MODE (reg));
8044 }
215b30b3 8045 }
9c08d1fa 8046
215b30b3 8047 /* The optimizer does not know that the call sets the function value
8048 registers we stored in the result block. We avoid problems by
8049 claiming that all hard registers are used and clobbered at this
8050 point. */
8051 emit_insn (gen_blockage ());
8052
8053 DONE;
8054 }"
8055)
9c08d1fa 8056
ccd90aaa 8057(define_expand "untyped_return"
8058 [(match_operand:BLK 0 "memory_operand" "")
8059 (match_operand 1 "" "")]
8060 "TARGET_EITHER"
8061 "
8062 {
8063 int i;
8064 rtx addr = gen_reg_rtx (Pmode);
8065 rtx mem;
8066 int size = 0;
8067
8068 emit_move_insn (addr, XEXP (operands[0], 0));
8069 mem = change_address (operands[0], BLKmode, addr);
8070
8071 for (i = 0; i < XVECLEN (operands[1], 0); i++)
8072 {
8073 HOST_WIDE_INT offset = 0;
8074 rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
8075
8076 if (size != 0)
29c05e22 8077 emit_move_insn (addr, plus_constant (Pmode, addr, size));
ccd90aaa 8078
8079 mem = change_address (mem, GET_MODE (reg), NULL);
8080 if (REGNO (reg) == R0_REGNUM)
8081 {
8082 /* On thumb we have to use a write-back instruction. */
320ea44d 8083 emit_insn (arm_gen_load_multiple (arm_regs_in_sequence, 4, addr,
8084 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
ccd90aaa 8085 size = TARGET_ARM ? 16 : 0;
8086 }
8087 else
8088 {
8089 emit_move_insn (reg, mem);
8090 size = GET_MODE_SIZE (GET_MODE (reg));
8091 }
8092 }
8093
8094 /* Emit USE insns before the return. */
8095 for (i = 0; i < XVECLEN (operands[1], 0); i++)
18b42941 8096 emit_use (SET_DEST (XVECEXP (operands[1], 0, i)));
ccd90aaa 8097
8098 /* Construct the return. */
8099 expand_naked_return ();
8100
8101 DONE;
8102 }"
8103)
8104
9c08d1fa 8105;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
8106;; all of memory. This blocks insns from being moved across this point.
8107
8108(define_insn "blockage"
e1159bbe 8109 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
cffb2a26 8110 "TARGET_EITHER"
9c08d1fa 8111 ""
cffb2a26 8112 [(set_attr "length" "0")
8113 (set_attr "type" "block")]
8114)
9c08d1fa 8115
f7fbdd4a 8116(define_expand "casesi"
8117 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
aea4c774 8118 (match_operand:SI 1 "const_int_operand" "") ; lower bound
8119 (match_operand:SI 2 "const_int_operand" "") ; total range
f7fbdd4a 8120 (match_operand:SI 3 "" "") ; table label
8121 (match_operand:SI 4 "" "")] ; Out of range label
e6ac8414 8122 "TARGET_32BIT || optimize_size || flag_pic"
f7fbdd4a 8123 "
215b30b3 8124 {
e6ac8414 8125 enum insn_code code;
215b30b3 8126 if (operands[1] != const0_rtx)
8127 {
e6ac8414 8128 rtx reg = gen_reg_rtx (SImode);
f7fbdd4a 8129
215b30b3 8130 emit_insn (gen_addsi3 (reg, operands[0],
d022fa24 8131 gen_int_mode (-INTVAL (operands[1]),
8132 SImode)));
215b30b3 8133 operands[0] = reg;
8134 }
9c08d1fa 8135
25f905c2 8136 if (TARGET_ARM)
e6ac8414 8137 code = CODE_FOR_arm_casesi_internal;
3db2019b 8138 else if (TARGET_THUMB1)
e6ac8414 8139 code = CODE_FOR_thumb1_casesi_internal_pic;
25f905c2 8140 else if (flag_pic)
e6ac8414 8141 code = CODE_FOR_thumb2_casesi_internal_pic;
25f905c2 8142 else
e6ac8414 8143 code = CODE_FOR_thumb2_casesi_internal;
8144
8145 if (!insn_data[(int) code].operand[1].predicate(operands[2], SImode))
8146 operands[2] = force_reg (SImode, operands[2]);
8147
8148 emit_jump_insn (GEN_FCN ((int) code) (operands[0], operands[2],
8149 operands[3], operands[4]));
215b30b3 8150 DONE;
8151 }"
8152)
f7fbdd4a 8153
f082f1c4 8154;; The USE in this pattern is needed to tell flow analysis that this is
8155;; a CASESI insn. It has no other purpose.
25f905c2 8156(define_insn "arm_casesi_internal"
f082f1c4 8157 [(parallel [(set (pc)
8158 (if_then_else
8159 (leu (match_operand:SI 0 "s_register_operand" "r")
8160 (match_operand:SI 1 "arm_rhs_operand" "rI"))
8161 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
8162 (label_ref (match_operand 2 "" ""))))
8163 (label_ref (match_operand 3 "" ""))))
bd5b4116 8164 (clobber (reg:CC CC_REGNUM))
f082f1c4 8165 (use (label_ref (match_dup 2)))])]
cffb2a26 8166 "TARGET_ARM"
f7fbdd4a 8167 "*
0d66636f 8168 if (flag_pic)
8169 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
8170 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
8171 "
8172 [(set_attr "conds" "clob")
1b7da4ac 8173 (set_attr "length" "12")
8174 (set_attr "type" "multiple")]
0d66636f 8175)
9c08d1fa 8176
cffb2a26 8177(define_expand "indirect_jump"
9c08d1fa 8178 [(set (pc)
cffb2a26 8179 (match_operand:SI 0 "s_register_operand" ""))]
8180 "TARGET_EITHER"
25f905c2 8181 "
8182 /* Thumb-2 doesn't have mov pc, reg. Explicitly set the low bit of the
8183 address and use bx. */
8184 if (TARGET_THUMB2)
8185 {
8186 rtx tmp;
8187 tmp = gen_reg_rtx (SImode);
8188 emit_insn (gen_iorsi3 (tmp, operands[0], GEN_INT(1)));
8189 operands[0] = tmp;
8190 }
8191 "
cffb2a26 8192)
8193
f1039640 8194;; NB Never uses BX.
cffb2a26 8195(define_insn "*arm_indirect_jump"
8196 [(set (pc)
8197 (match_operand:SI 0 "s_register_operand" "r"))]
8198 "TARGET_ARM"
8199 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
1b7da4ac 8200 [(set_attr "predicable" "yes")
8201 (set_attr "type" "branch")]
cffb2a26 8202)
9c08d1fa 8203
f7fbdd4a 8204(define_insn "*load_indirect_jump"
9c08d1fa 8205 [(set (pc)
8206 (match_operand:SI 0 "memory_operand" "m"))]
cffb2a26 8207 "TARGET_ARM"
8208 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
a2cd141b 8209 [(set_attr "type" "load1")
61a2d04c 8210 (set_attr "pool_range" "4096")
8211 (set_attr "neg_pool_range" "4084")
0d66636f 8212 (set_attr "predicable" "yes")]
cffb2a26 8213)
8214
9c08d1fa 8215\f
8216;; Misc insns
8217
8218(define_insn "nop"
8219 [(const_int 0)]
cffb2a26 8220 "TARGET_EITHER"
8221 "*
25f905c2 8222 if (TARGET_UNIFIED_ASM)
8223 return \"nop\";
cffb2a26 8224 if (TARGET_ARM)
8225 return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
8226 return \"mov\\tr8, r8\";
8227 "
8228 [(set (attr "length")
8229 (if_then_else (eq_attr "is_thumb" "yes")
8230 (const_int 2)
1b7da4ac 8231 (const_int 4)))
8232 (set_attr "type" "mov_reg")]
cffb2a26 8233)
8234
ad9d4399 8235(define_insn "trap"
8236 [(trap_if (const_int 1) (const_int 0))]
8237 ""
8238 "*
8239 if (TARGET_ARM)
8240 return \".inst\\t0xe7f000f0\";
8241 else
8242 return \".inst\\t0xdeff\";
8243 "
8244 [(set (attr "length")
8245 (if_then_else (eq_attr "is_thumb" "yes")
8246 (const_int 2)
8247 (const_int 4)))
8248 (set_attr "type" "trap")
8249 (set_attr "conds" "unconditional")]
8250)
8251
9c08d1fa 8252\f
8253;; Patterns to allow combination of arithmetic, cond code and shifts
8254
0abea32c 8255(define_insn "*<arith_shift_insn>_multsi"
8256 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8257 (shiftable_ops:SI
8258 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
8259 (match_operand:SI 3 "power_of_two_operand" ""))
8260 (match_operand:SI 1 "s_register_operand" "rk,<t2_binop0>")))]
d5d4dc8d 8261 "TARGET_32BIT"
0abea32c 8262 "<arith_shift_insn>%?\\t%0, %1, %2, lsl %b3"
8263 [(set_attr "predicable" "yes")
8264 (set_attr "predicable_short_it" "no")
8265 (set_attr "shift" "4")
8266 (set_attr "arch" "a,t2")
8267 (set_attr "type" "alu_shift_imm")])
8268
8269(define_insn "*<arith_shift_insn>_shiftsi"
8270 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8271 (shiftable_ops:SI
8272 (match_operator:SI 2 "shift_nomul_operator"
8273 [(match_operand:SI 3 "s_register_operand" "r,r,r")
8274 (match_operand:SI 4 "shift_amount_operand" "M,M,r")])
8275 (match_operand:SI 1 "s_register_operand" "rk,<t2_binop0>,rk")))]
a021b821 8276 "TARGET_32BIT && GET_CODE (operands[2]) != MULT"
0abea32c 8277 "<arith_shift_insn>%?\\t%0, %1, %3%S2"
344495ea 8278 [(set_attr "predicable" "yes")
74ef923b 8279 (set_attr "predicable_short_it" "no")
331beb1a 8280 (set_attr "shift" "4")
0abea32c 8281 (set_attr "arch" "a,t2,a")
8282 (set_attr "type" "alu_shift_imm,alu_shift_imm,alu_shift_reg")])
9c08d1fa 8283
d7863cfe 8284(define_split
8285 [(set (match_operand:SI 0 "s_register_operand" "")
8286 (match_operator:SI 1 "shiftable_operator"
8287 [(match_operator:SI 2 "shiftable_operator"
8288 [(match_operator:SI 3 "shift_operator"
8289 [(match_operand:SI 4 "s_register_operand" "")
8290 (match_operand:SI 5 "reg_or_int_operand" "")])
8291 (match_operand:SI 6 "s_register_operand" "")])
8292 (match_operand:SI 7 "arm_rhs_operand" "")]))
8293 (clobber (match_operand:SI 8 "s_register_operand" ""))]
d5d4dc8d 8294 "TARGET_32BIT"
d7863cfe 8295 [(set (match_dup 8)
8296 (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8297 (match_dup 6)]))
8298 (set (match_dup 0)
8299 (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
8300 "")
8301
f7fbdd4a 8302(define_insn "*arith_shiftsi_compare0"
bd5b4116 8303 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 8304 (compare:CC_NOOV
8305 (match_operator:SI 1 "shiftable_operator"
8306 [(match_operator:SI 3 "shift_operator"
8307 [(match_operand:SI 4 "s_register_operand" "r,r")
8308 (match_operand:SI 5 "shift_amount_operand" "M,r")])
8309 (match_operand:SI 2 "s_register_operand" "r,r")])
8310 (const_int 0)))
8311 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 8312 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8313 (match_dup 2)]))]
d5d4dc8d 8314 "TARGET_32BIT"
25f905c2 8315 "%i1%.\\t%0, %2, %4%S3"
344495ea 8316 [(set_attr "conds" "set")
331beb1a 8317 (set_attr "shift" "4")
d5d4dc8d 8318 (set_attr "arch" "32,a")
d82e788e 8319 (set_attr "type" "alus_shift_imm,alus_shift_reg")])
9c08d1fa 8320
f7fbdd4a 8321(define_insn "*arith_shiftsi_compare0_scratch"
bd5b4116 8322 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 8323 (compare:CC_NOOV
8324 (match_operator:SI 1 "shiftable_operator"
8325 [(match_operator:SI 3 "shift_operator"
8326 [(match_operand:SI 4 "s_register_operand" "r,r")
8327 (match_operand:SI 5 "shift_amount_operand" "M,r")])
8328 (match_operand:SI 2 "s_register_operand" "r,r")])
8329 (const_int 0)))
8330 (clobber (match_scratch:SI 0 "=r,r"))]
8331 "TARGET_32BIT"
25f905c2 8332 "%i1%.\\t%0, %2, %4%S3"
344495ea 8333 [(set_attr "conds" "set")
331beb1a 8334 (set_attr "shift" "4")
d5d4dc8d 8335 (set_attr "arch" "32,a")
d82e788e 8336 (set_attr "type" "alus_shift_imm,alus_shift_reg")])
9c08d1fa 8337
f7fbdd4a 8338(define_insn "*sub_shiftsi"
d5d4dc8d 8339 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8340 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
9c08d1fa 8341 (match_operator:SI 2 "shift_operator"
d5d4dc8d 8342 [(match_operand:SI 3 "s_register_operand" "r,r")
8343 (match_operand:SI 4 "shift_amount_operand" "M,r")])))]
8344 "TARGET_32BIT"
6c4c2133 8345 "sub%?\\t%0, %1, %3%S2"
344495ea 8346 [(set_attr "predicable" "yes")
331beb1a 8347 (set_attr "shift" "3")
d5d4dc8d 8348 (set_attr "arch" "32,a")
d82e788e 8349 (set_attr "type" "alus_shift_imm,alus_shift_reg")])
9c08d1fa 8350
f7fbdd4a 8351(define_insn "*sub_shiftsi_compare0"
bd5b4116 8352 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 8353 (compare:CC_NOOV
d82e788e 8354 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
40dbec34 8355 (match_operator:SI 2 "shift_operator"
d82e788e 8356 [(match_operand:SI 3 "s_register_operand" "r,r,r")
8357 (match_operand:SI 4 "shift_amount_operand" "M,r,M")]))
40dbec34 8358 (const_int 0)))
d82e788e 8359 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
d5d4dc8d 8360 (minus:SI (match_dup 1)
8361 (match_op_dup 2 [(match_dup 3) (match_dup 4)])))]
8362 "TARGET_32BIT"
25f905c2 8363 "sub%.\\t%0, %1, %3%S2"
344495ea 8364 [(set_attr "conds" "set")
a2cd141b 8365 (set_attr "shift" "3")
d82e788e 8366 (set_attr "arch" "32,a,a")
8367 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
9c08d1fa 8368
f7fbdd4a 8369(define_insn "*sub_shiftsi_compare0_scratch"
bd5b4116 8370 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 8371 (compare:CC_NOOV
d82e788e 8372 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
40dbec34 8373 (match_operator:SI 2 "shift_operator"
d82e788e 8374 [(match_operand:SI 3 "s_register_operand" "r,r,r")
8375 (match_operand:SI 4 "shift_amount_operand" "M,r,M")]))
40dbec34 8376 (const_int 0)))
d82e788e 8377 (clobber (match_scratch:SI 0 "=r,r,r"))]
d5d4dc8d 8378 "TARGET_32BIT"
25f905c2 8379 "sub%.\\t%0, %1, %3%S2"
344495ea 8380 [(set_attr "conds" "set")
a2cd141b 8381 (set_attr "shift" "3")
d82e788e 8382 (set_attr "arch" "32,a,a")
8383 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
9c08d1fa 8384\f
8385
190efb17 8386(define_insn_and_split "*and_scc"
9c08d1fa 8387 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 8388 (and:SI (match_operator:SI 1 "arm_comparison_operator"
190efb17 8389 [(match_operand 2 "cc_register" "") (const_int 0)])
8390 (match_operand:SI 3 "s_register_operand" "r")))]
cffb2a26 8391 "TARGET_ARM"
190efb17 8392 "#" ; "mov%D1\\t%0, #0\;and%d1\\t%0, %3, #1"
8393 "&& reload_completed"
8394 [(cond_exec (match_dup 5) (set (match_dup 0) (const_int 0)))
8395 (cond_exec (match_dup 4) (set (match_dup 0)
8396 (and:SI (match_dup 3) (const_int 1))))]
8397 {
3754d046 8398 machine_mode mode = GET_MODE (operands[2]);
190efb17 8399 enum rtx_code rc = GET_CODE (operands[1]);
8400
8401 /* Note that operands[4] is the same as operands[1],
8402 but with VOIDmode as the result. */
8403 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
8404 if (mode == CCFPmode || mode == CCFPEmode)
8405 rc = reverse_condition_maybe_unordered (rc);
8406 else
8407 rc = reverse_condition (rc);
8408 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
8409 }
8fa3ba89 8410 [(set_attr "conds" "use")
1b7da4ac 8411 (set_attr "type" "multiple")
8fa3ba89 8412 (set_attr "length" "8")]
8413)
9c08d1fa 8414
190efb17 8415(define_insn_and_split "*ior_scc"
9c08d1fa 8416 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
190efb17 8417 (ior:SI (match_operator:SI 1 "arm_comparison_operator"
8418 [(match_operand 2 "cc_register" "") (const_int 0)])
8419 (match_operand:SI 3 "s_register_operand" "0,?r")))]
cffb2a26 8420 "TARGET_ARM"
e2348bcb 8421 "@
190efb17 8422 orr%d1\\t%0, %3, #1
8423 #"
8424 "&& reload_completed
8425 && REGNO (operands [0]) != REGNO (operands[3])"
8426 ;; && which_alternative == 1
8427 ; mov%D1\\t%0, %3\;orr%d1\\t%0, %3, #1
8428 [(cond_exec (match_dup 5) (set (match_dup 0) (match_dup 3)))
8429 (cond_exec (match_dup 4) (set (match_dup 0)
8430 (ior:SI (match_dup 3) (const_int 1))))]
8431 {
3754d046 8432 machine_mode mode = GET_MODE (operands[2]);
190efb17 8433 enum rtx_code rc = GET_CODE (operands[1]);
8434
8435 /* Note that operands[4] is the same as operands[1],
8436 but with VOIDmode as the result. */
8437 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
8438 if (mode == CCFPmode || mode == CCFPEmode)
8439 rc = reverse_condition_maybe_unordered (rc);
8440 else
8441 rc = reverse_condition (rc);
8442 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
8443 }
8fa3ba89 8444 [(set_attr "conds" "use")
1b7da4ac 8445 (set_attr "length" "4,8")
8446 (set_attr "type" "logic_imm,multiple")]
8fa3ba89 8447)
9c08d1fa 8448
2df9477b 8449; A series of splitters for the compare_scc pattern below. Note that
8450; order is important.
8451(define_split
8452 [(set (match_operand:SI 0 "s_register_operand" "")
8453 (lt:SI (match_operand:SI 1 "s_register_operand" "")
8454 (const_int 0)))
8455 (clobber (reg:CC CC_REGNUM))]
8456 "TARGET_32BIT && reload_completed"
8457 [(set (match_dup 0) (lshiftrt:SI (match_dup 1) (const_int 31)))])
8458
8459(define_split
8460 [(set (match_operand:SI 0 "s_register_operand" "")
8461 (ge:SI (match_operand:SI 1 "s_register_operand" "")
8462 (const_int 0)))
8463 (clobber (reg:CC CC_REGNUM))]
8464 "TARGET_32BIT && reload_completed"
8465 [(set (match_dup 0) (not:SI (match_dup 1)))
8466 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 31)))])
8467
98562479 8468(define_split
8469 [(set (match_operand:SI 0 "s_register_operand" "")
8470 (eq:SI (match_operand:SI 1 "s_register_operand" "")
8471 (const_int 0)))
8472 (clobber (reg:CC CC_REGNUM))]
8473 "arm_arch5 && TARGET_32BIT"
8474 [(set (match_dup 0) (clz:SI (match_dup 1)))
8475 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 5)))]
8476)
8477
2df9477b 8478(define_split
8479 [(set (match_operand:SI 0 "s_register_operand" "")
8480 (eq:SI (match_operand:SI 1 "s_register_operand" "")
8481 (const_int 0)))
8482 (clobber (reg:CC CC_REGNUM))]
8483 "TARGET_32BIT && reload_completed"
8484 [(parallel
080c0b9a 8485 [(set (reg:CC CC_REGNUM)
8486 (compare:CC (const_int 1) (match_dup 1)))
2df9477b 8487 (set (match_dup 0)
8488 (minus:SI (const_int 1) (match_dup 1)))])
080c0b9a 8489 (cond_exec (ltu:CC (reg:CC CC_REGNUM) (const_int 0))
2df9477b 8490 (set (match_dup 0) (const_int 0)))])
8491
8492(define_split
8493 [(set (match_operand:SI 0 "s_register_operand" "")
8494 (ne:SI (match_operand:SI 1 "s_register_operand" "")
8495 (match_operand:SI 2 "const_int_operand" "")))
8496 (clobber (reg:CC CC_REGNUM))]
8497 "TARGET_32BIT && reload_completed"
8498 [(parallel
8499 [(set (reg:CC CC_REGNUM)
8500 (compare:CC (match_dup 1) (match_dup 2)))
8501 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))])
8502 (cond_exec (ne:CC (reg:CC CC_REGNUM) (const_int 0))
8503 (set (match_dup 0) (const_int 1)))]
8504{
8505 operands[3] = GEN_INT (-INTVAL (operands[2]));
8506})
8507
8508(define_split
8509 [(set (match_operand:SI 0 "s_register_operand" "")
8510 (ne:SI (match_operand:SI 1 "s_register_operand" "")
8511 (match_operand:SI 2 "arm_add_operand" "")))
8512 (clobber (reg:CC CC_REGNUM))]
8513 "TARGET_32BIT && reload_completed"
8514 [(parallel
8515 [(set (reg:CC_NOOV CC_REGNUM)
8516 (compare:CC_NOOV (minus:SI (match_dup 1) (match_dup 2))
8517 (const_int 0)))
8518 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
8519 (cond_exec (ne:CC_NOOV (reg:CC_NOOV CC_REGNUM) (const_int 0))
8520 (set (match_dup 0) (const_int 1)))])
8521
8522(define_insn_and_split "*compare_scc"
fd711051 8523 [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts")
8fa3ba89 8524 (match_operator:SI 1 "arm_comparison_operator"
5565501b 8525 [(match_operand:SI 2 "s_register_operand" "r,r")
8526 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
bd5b4116 8527 (clobber (reg:CC CC_REGNUM))]
2df9477b 8528 "TARGET_32BIT"
8529 "#"
8530 "&& reload_completed"
8531 [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 3)))
8532 (cond_exec (match_dup 4) (set (match_dup 0) (const_int 0)))
8533 (cond_exec (match_dup 5) (set (match_dup 0) (const_int 1)))]
8534{
8535 rtx tmp1;
3754d046 8536 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
2df9477b 8537 operands[2], operands[3]);
8538 enum rtx_code rc = GET_CODE (operands[1]);
e2348bcb 8539
2df9477b 8540 tmp1 = gen_rtx_REG (mode, CC_REGNUM);
080c0b9a 8541
2df9477b 8542 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
8543 if (mode == CCFPmode || mode == CCFPEmode)
8544 rc = reverse_condition_maybe_unordered (rc);
8545 else
8546 rc = reverse_condition (rc);
8547 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
1b7da4ac 8548}
8549 [(set_attr "type" "multiple")]
8550)
9c08d1fa 8551
080c0b9a 8552;; Attempt to improve the sequence generated by the compare_scc splitters
8553;; not to use conditional execution.
98562479 8554
8555;; Rd = (eq (reg1) (const_int0)) // ARMv5
8556;; clz Rd, reg1
8557;; lsr Rd, Rd, #5
080c0b9a 8558(define_peephole2
8559 [(set (reg:CC CC_REGNUM)
8560 (compare:CC (match_operand:SI 1 "register_operand" "")
98562479 8561 (const_int 0)))
8562 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
8563 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
8564 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
8565 (set (match_dup 0) (const_int 1)))]
8566 "arm_arch5 && TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)"
8567 [(set (match_dup 0) (clz:SI (match_dup 1)))
8568 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 5)))]
8569)
8570
8571;; Rd = (eq (reg1) (const_int0)) // !ARMv5
8572;; negs Rd, reg1
8573;; adc Rd, Rd, reg1
8574(define_peephole2
8575 [(set (reg:CC CC_REGNUM)
8576 (compare:CC (match_operand:SI 1 "register_operand" "")
8577 (const_int 0)))
080c0b9a 8578 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
8579 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
8580 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
8581 (set (match_dup 0) (const_int 1)))
98562479 8582 (match_scratch:SI 2 "r")]
8583 "TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)"
922b6913 8584 [(parallel
8585 [(set (reg:CC CC_REGNUM)
98562479 8586 (compare:CC (const_int 0) (match_dup 1)))
8587 (set (match_dup 2) (minus:SI (const_int 0) (match_dup 1)))])
8588 (set (match_dup 0)
8589 (plus:SI (plus:SI (match_dup 1) (match_dup 2))
8590 (geu:SI (reg:CC CC_REGNUM) (const_int 0))))]
8591)
8592
31991287 8593;; Rd = (eq (reg1) (reg2/imm)) // ARMv5 and optimising for speed.
98562479 8594;; sub Rd, Reg1, reg2
8595;; clz Rd, Rd
8596;; lsr Rd, Rd, #5
8597(define_peephole2
8598 [(set (reg:CC CC_REGNUM)
8599 (compare:CC (match_operand:SI 1 "register_operand" "")
8600 (match_operand:SI 2 "arm_rhs_operand" "")))
8601 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
8602 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
8603 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
8604 (set (match_dup 0) (const_int 1)))]
31991287 8605 "arm_arch5 && TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)
8606 && !(TARGET_THUMB2 && optimize_insn_for_size_p ())"
98562479 8607 [(set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))
8608 (set (match_dup 0) (clz:SI (match_dup 0)))
8609 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 5)))]
8610)
8611
8612
31991287 8613;; Rd = (eq (reg1) (reg2)) // ! ARMv5 or optimising for size.
98562479 8614;; sub T1, Reg1, reg2
8615;; negs Rd, T1
8616;; adc Rd, Rd, T1
8617(define_peephole2
8618 [(set (reg:CC CC_REGNUM)
8619 (compare:CC (match_operand:SI 1 "register_operand" "")
8620 (match_operand:SI 2 "arm_rhs_operand" "")))
8621 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
8622 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
8623 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
8624 (set (match_dup 0) (const_int 1)))
8625 (match_scratch:SI 3 "r")]
8626 "TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)"
31991287 8627 [(set (match_dup 3) (match_dup 4))
080c0b9a 8628 (parallel
8629 [(set (reg:CC CC_REGNUM)
8630 (compare:CC (const_int 0) (match_dup 3)))
8631 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 3)))])
98562479 8632 (set (match_dup 0)
8633 (plus:SI (plus:SI (match_dup 0) (match_dup 3))
8634 (geu:SI (reg:CC CC_REGNUM) (const_int 0))))]
31991287 8635 "
8636 if (CONST_INT_P (operands[2]))
8637 operands[4] = plus_constant (SImode, operands[1], -INTVAL (operands[2]));
8638 else
8639 operands[4] = gen_rtx_MINUS (SImode, operands[1], operands[2]);
8640 ")
080c0b9a 8641
f7fbdd4a 8642(define_insn "*cond_move"
9c08d1fa 8643 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
aea4c774 8644 (if_then_else:SI (match_operator 3 "equality_operator"
8fa3ba89 8645 [(match_operator 4 "arm_comparison_operator"
8a18b90c 8646 [(match_operand 5 "cc_register" "") (const_int 0)])
aea4c774 8647 (const_int 0)])
8648 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8649 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
cffb2a26 8650 "TARGET_ARM"
9c08d1fa 8651 "*
8fa3ba89 8652 if (GET_CODE (operands[3]) == NE)
8653 {
8654 if (which_alternative != 1)
8655 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
8656 if (which_alternative != 0)
8657 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
8658 return \"\";
8659 }
8660 if (which_alternative != 0)
8661 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8662 if (which_alternative != 1)
8663 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
8664 return \"\";
8665 "
8666 [(set_attr "conds" "use")
1b7da4ac 8667 (set_attr "type" "mov_reg,mov_reg,multiple")
8fa3ba89 8668 (set_attr "length" "4,4,8")]
8669)
9c08d1fa 8670
f7fbdd4a 8671(define_insn "*cond_arith"
9c08d1fa 8672 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8673 (match_operator:SI 5 "shiftable_operator"
8fa3ba89 8674 [(match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 8675 [(match_operand:SI 2 "s_register_operand" "r,r")
8676 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8677 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 8678 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8679 "TARGET_ARM"
9c08d1fa 8680 "*
8fa3ba89 8681 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
8682 return \"%i5\\t%0, %1, %2, lsr #31\";
40dbec34 8683
8fa3ba89 8684 output_asm_insn (\"cmp\\t%2, %3\", operands);
8685 if (GET_CODE (operands[5]) == AND)
8686 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
8687 else if (GET_CODE (operands[5]) == MINUS)
8688 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
8689 else if (which_alternative != 0)
8690 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8691 return \"%i5%d4\\t%0, %1, #1\";
8692 "
8693 [(set_attr "conds" "clob")
1b7da4ac 8694 (set_attr "length" "12")
8695 (set_attr "type" "multiple")]
8fa3ba89 8696)
9c08d1fa 8697
f7fbdd4a 8698(define_insn "*cond_sub"
9c08d1fa 8699 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8700 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8fa3ba89 8701 (match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 8702 [(match_operand:SI 2 "s_register_operand" "r,r")
8703 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 8704 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8705 "TARGET_ARM"
9c08d1fa 8706 "*
8fa3ba89 8707 output_asm_insn (\"cmp\\t%2, %3\", operands);
8708 if (which_alternative != 0)
8709 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8710 return \"sub%d4\\t%0, %1, #1\";
8711 "
8712 [(set_attr "conds" "clob")
1b7da4ac 8713 (set_attr "length" "8,12")
8714 (set_attr "type" "multiple")]
8fa3ba89 8715)
9c08d1fa 8716
aea4c774 8717(define_insn "*cmp_ite0"
cffb2a26 8718 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 8719 (compare
8720 (if_then_else:SI
8fa3ba89 8721 (match_operator 4 "arm_comparison_operator"
2ff91fec 8722 [(match_operand:SI 0 "s_register_operand"
8723 "l,l,l,r,r,r,r,r,r")
8724 (match_operand:SI 1 "arm_add_operand"
8725 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
8fa3ba89 8726 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 8727 [(match_operand:SI 2 "s_register_operand"
8728 "l,r,r,l,l,r,r,r,r")
8729 (match_operand:SI 3 "arm_add_operand"
8730 "lPy,rI,L,lPy,lPy,rI,rI,L,L")])
aea4c774 8731 (const_int 0))
8732 (const_int 0)))]
2ff91fec 8733 "TARGET_32BIT"
9c08d1fa 8734 "*
aea4c774 8735 {
2ff91fec 8736 static const char * const cmp1[NUM_OF_COND_CMP][2] =
8737 {
8738 {\"cmp%d5\\t%0, %1\",
8739 \"cmp%d4\\t%2, %3\"},
8740 {\"cmn%d5\\t%0, #%n1\",
8741 \"cmp%d4\\t%2, %3\"},
8742 {\"cmp%d5\\t%0, %1\",
8743 \"cmn%d4\\t%2, #%n3\"},
8744 {\"cmn%d5\\t%0, #%n1\",
8745 \"cmn%d4\\t%2, #%n3\"}
8746 };
8747 static const char * const cmp2[NUM_OF_COND_CMP][2] =
8748 {
8749 {\"cmp\\t%2, %3\",
8750 \"cmp\\t%0, %1\"},
8751 {\"cmp\\t%2, %3\",
8752 \"cmn\\t%0, #%n1\"},
8753 {\"cmn\\t%2, #%n3\",
8754 \"cmp\\t%0, %1\"},
8755 {\"cmn\\t%2, #%n3\",
8756 \"cmn\\t%0, #%n1\"}
8757 };
8758 static const char * const ite[2] =
8fa3ba89 8759 {
2ff91fec 8760 \"it\\t%d5\",
8761 \"it\\t%d4\"
8fa3ba89 8762 };
2ff91fec 8763 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
8764 CMP_CMP, CMN_CMP, CMP_CMP,
8765 CMN_CMP, CMP_CMN, CMN_CMN};
8fa3ba89 8766 int swap =
8767 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8768
2ff91fec 8769 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
8770 if (TARGET_THUMB2) {
8771 output_asm_insn (ite[swap], operands);
8772 }
8773 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
8774 return \"\";
8fa3ba89 8775 }"
8776 [(set_attr "conds" "set")
2ff91fec 8777 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
1b7da4ac 8778 (set_attr "type" "multiple")
2ff91fec 8779 (set_attr_alternative "length"
8780 [(const_int 6)
8781 (const_int 8)
8782 (const_int 8)
8783 (const_int 8)
8784 (const_int 8)
8785 (if_then_else (eq_attr "is_thumb" "no")
8786 (const_int 8)
8787 (const_int 10))
8788 (if_then_else (eq_attr "is_thumb" "no")
8789 (const_int 8)
8790 (const_int 10))
8791 (if_then_else (eq_attr "is_thumb" "no")
8792 (const_int 8)
8793 (const_int 10))
8794 (if_then_else (eq_attr "is_thumb" "no")
8795 (const_int 8)
8796 (const_int 10))])]
8fa3ba89 8797)
9c08d1fa 8798
aea4c774 8799(define_insn "*cmp_ite1"
cffb2a26 8800 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 8801 (compare
8802 (if_then_else:SI
8fa3ba89 8803 (match_operator 4 "arm_comparison_operator"
2ff91fec 8804 [(match_operand:SI 0 "s_register_operand"
8805 "l,l,l,r,r,r,r,r,r")
8806 (match_operand:SI 1 "arm_add_operand"
8807 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
8fa3ba89 8808 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 8809 [(match_operand:SI 2 "s_register_operand"
8810 "l,r,r,l,l,r,r,r,r")
8811 (match_operand:SI 3 "arm_add_operand"
8812 "lPy,rI,L,lPy,lPy,rI,rI,L,L")])
aea4c774 8813 (const_int 1))
8814 (const_int 0)))]
2ff91fec 8815 "TARGET_32BIT"
9c08d1fa 8816 "*
9c08d1fa 8817 {
2ff91fec 8818 static const char * const cmp1[NUM_OF_COND_CMP][2] =
8819 {
8820 {\"cmp\\t%0, %1\",
8821 \"cmp\\t%2, %3\"},
8822 {\"cmn\\t%0, #%n1\",
8823 \"cmp\\t%2, %3\"},
8824 {\"cmp\\t%0, %1\",
8825 \"cmn\\t%2, #%n3\"},
8826 {\"cmn\\t%0, #%n1\",
8827 \"cmn\\t%2, #%n3\"}
8828 };
8829 static const char * const cmp2[NUM_OF_COND_CMP][2] =
215b30b3 8830 {
2ff91fec 8831 {\"cmp%d4\\t%2, %3\",
8832 \"cmp%D5\\t%0, %1\"},
8833 {\"cmp%d4\\t%2, %3\",
8834 \"cmn%D5\\t%0, #%n1\"},
8835 {\"cmn%d4\\t%2, #%n3\",
8836 \"cmp%D5\\t%0, %1\"},
8837 {\"cmn%d4\\t%2, #%n3\",
8838 \"cmn%D5\\t%0, #%n1\"}
215b30b3 8839 };
2ff91fec 8840 static const char * const ite[2] =
8841 {
8842 \"it\\t%d4\",
8843 \"it\\t%D5\"
8844 };
8845 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
8846 CMP_CMP, CMN_CMP, CMP_CMP,
8847 CMN_CMP, CMP_CMN, CMN_CMN};
215b30b3 8848 int swap =
8849 comparison_dominates_p (GET_CODE (operands[5]),
8850 reverse_condition (GET_CODE (operands[4])));
8851
2ff91fec 8852 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
8853 if (TARGET_THUMB2) {
8854 output_asm_insn (ite[swap], operands);
8855 }
8856 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
8857 return \"\";
215b30b3 8858 }"
8fa3ba89 8859 [(set_attr "conds" "set")
2ff91fec 8860 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
8861 (set_attr_alternative "length"
8862 [(const_int 6)
8863 (const_int 8)
8864 (const_int 8)
8865 (const_int 8)
8866 (const_int 8)
8867 (if_then_else (eq_attr "is_thumb" "no")
8868 (const_int 8)
8869 (const_int 10))
8870 (if_then_else (eq_attr "is_thumb" "no")
8871 (const_int 8)
8872 (const_int 10))
8873 (if_then_else (eq_attr "is_thumb" "no")
8874 (const_int 8)
8875 (const_int 10))
8876 (if_then_else (eq_attr "is_thumb" "no")
8877 (const_int 8)
1b7da4ac 8878 (const_int 10))])
8879 (set_attr "type" "multiple")]
8fa3ba89 8880)
9c08d1fa 8881
f6c53574 8882(define_insn "*cmp_and"
8883 [(set (match_operand 6 "dominant_cc_register" "")
8884 (compare
8885 (and:SI
8886 (match_operator 4 "arm_comparison_operator"
2ff91fec 8887 [(match_operand:SI 0 "s_register_operand"
8888 "l,l,l,r,r,r,r,r,r")
8889 (match_operand:SI 1 "arm_add_operand"
8890 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
f6c53574 8891 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 8892 [(match_operand:SI 2 "s_register_operand"
8893 "l,r,r,l,l,r,r,r,r")
8894 (match_operand:SI 3 "arm_add_operand"
8895 "lPy,rI,L,lPy,lPy,rI,rI,L,L")]))
f6c53574 8896 (const_int 0)))]
2ff91fec 8897 "TARGET_32BIT"
f6c53574 8898 "*
8899 {
2ff91fec 8900 static const char *const cmp1[NUM_OF_COND_CMP][2] =
f6c53574 8901 {
2ff91fec 8902 {\"cmp%d5\\t%0, %1\",
8903 \"cmp%d4\\t%2, %3\"},
8904 {\"cmn%d5\\t%0, #%n1\",
8905 \"cmp%d4\\t%2, %3\"},
8906 {\"cmp%d5\\t%0, %1\",
8907 \"cmn%d4\\t%2, #%n3\"},
8908 {\"cmn%d5\\t%0, #%n1\",
8909 \"cmn%d4\\t%2, #%n3\"}
f6c53574 8910 };
2ff91fec 8911 static const char *const cmp2[NUM_OF_COND_CMP][2] =
8912 {
8913 {\"cmp\\t%2, %3\",
8914 \"cmp\\t%0, %1\"},
8915 {\"cmp\\t%2, %3\",
8916 \"cmn\\t%0, #%n1\"},
8917 {\"cmn\\t%2, #%n3\",
8918 \"cmp\\t%0, %1\"},
8919 {\"cmn\\t%2, #%n3\",
8920 \"cmn\\t%0, #%n1\"}
8921 };
8922 static const char *const ite[2] =
8923 {
8924 \"it\\t%d5\",
8925 \"it\\t%d4\"
8926 };
8927 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
8928 CMP_CMP, CMN_CMP, CMP_CMP,
8929 CMN_CMP, CMP_CMN, CMN_CMN};
f6c53574 8930 int swap =
8931 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8932
2ff91fec 8933 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
8934 if (TARGET_THUMB2) {
8935 output_asm_insn (ite[swap], operands);
8936 }
8937 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
8938 return \"\";
f6c53574 8939 }"
8940 [(set_attr "conds" "set")
8941 (set_attr "predicable" "no")
2ff91fec 8942 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
8943 (set_attr_alternative "length"
8944 [(const_int 6)
8945 (const_int 8)
8946 (const_int 8)
8947 (const_int 8)
8948 (const_int 8)
8949 (if_then_else (eq_attr "is_thumb" "no")
8950 (const_int 8)
8951 (const_int 10))
8952 (if_then_else (eq_attr "is_thumb" "no")
8953 (const_int 8)
8954 (const_int 10))
8955 (if_then_else (eq_attr "is_thumb" "no")
8956 (const_int 8)
8957 (const_int 10))
8958 (if_then_else (eq_attr "is_thumb" "no")
8959 (const_int 8)
1b7da4ac 8960 (const_int 10))])
8961 (set_attr "type" "multiple")]
f6c53574 8962)
8963
8964(define_insn "*cmp_ior"
8965 [(set (match_operand 6 "dominant_cc_register" "")
8966 (compare
8967 (ior:SI
8968 (match_operator 4 "arm_comparison_operator"
2ff91fec 8969 [(match_operand:SI 0 "s_register_operand"
8970 "l,l,l,r,r,r,r,r,r")
8971 (match_operand:SI 1 "arm_add_operand"
8972 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
f6c53574 8973 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 8974 [(match_operand:SI 2 "s_register_operand"
8975 "l,r,r,l,l,r,r,r,r")
8976 (match_operand:SI 3 "arm_add_operand"
8977 "lPy,rI,L,lPy,lPy,rI,rI,L,L")]))
f6c53574 8978 (const_int 0)))]
2ff91fec 8979 "TARGET_32BIT"
f6c53574 8980 "*
f6c53574 8981 {
2ff91fec 8982 static const char *const cmp1[NUM_OF_COND_CMP][2] =
8983 {
8984 {\"cmp\\t%0, %1\",
8985 \"cmp\\t%2, %3\"},
8986 {\"cmn\\t%0, #%n1\",
8987 \"cmp\\t%2, %3\"},
8988 {\"cmp\\t%0, %1\",
8989 \"cmn\\t%2, #%n3\"},
8990 {\"cmn\\t%0, #%n1\",
8991 \"cmn\\t%2, #%n3\"}
8992 };
8993 static const char *const cmp2[NUM_OF_COND_CMP][2] =
8994 {
8995 {\"cmp%D4\\t%2, %3\",
8996 \"cmp%D5\\t%0, %1\"},
8997 {\"cmp%D4\\t%2, %3\",
8998 \"cmn%D5\\t%0, #%n1\"},
8999 {\"cmn%D4\\t%2, #%n3\",
9000 \"cmp%D5\\t%0, %1\"},
9001 {\"cmn%D4\\t%2, #%n3\",
9002 \"cmn%D5\\t%0, #%n1\"}
9003 };
9004 static const char *const ite[2] =
9005 {
9006 \"it\\t%D4\",
9007 \"it\\t%D5\"
9008 };
9009 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
9010 CMP_CMP, CMN_CMP, CMP_CMP,
9011 CMN_CMP, CMP_CMN, CMN_CMN};
9012 int swap =
9013 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9014
9015 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9016 if (TARGET_THUMB2) {
9017 output_asm_insn (ite[swap], operands);
9018 }
9019 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9020 return \"\";
9021 }
9022 "
f6c53574 9023 [(set_attr "conds" "set")
2ff91fec 9024 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
9025 (set_attr_alternative "length"
9026 [(const_int 6)
9027 (const_int 8)
9028 (const_int 8)
9029 (const_int 8)
9030 (const_int 8)
9031 (if_then_else (eq_attr "is_thumb" "no")
9032 (const_int 8)
9033 (const_int 10))
9034 (if_then_else (eq_attr "is_thumb" "no")
9035 (const_int 8)
9036 (const_int 10))
9037 (if_then_else (eq_attr "is_thumb" "no")
9038 (const_int 8)
9039 (const_int 10))
9040 (if_then_else (eq_attr "is_thumb" "no")
9041 (const_int 8)
1b7da4ac 9042 (const_int 10))])
9043 (set_attr "type" "multiple")]
f6c53574 9044)
9045
3c5afce6 9046(define_insn_and_split "*ior_scc_scc"
fd711051 9047 [(set (match_operand:SI 0 "s_register_operand" "=Ts")
3c5afce6 9048 (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9049 [(match_operand:SI 1 "s_register_operand" "r")
9050 (match_operand:SI 2 "arm_add_operand" "rIL")])
9051 (match_operator:SI 6 "arm_comparison_operator"
9052 [(match_operand:SI 4 "s_register_operand" "r")
9053 (match_operand:SI 5 "arm_add_operand" "rIL")])))
9054 (clobber (reg:CC CC_REGNUM))]
2ff91fec 9055 "TARGET_32BIT
3c5afce6 9056 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
9057 != CCmode)"
9058 "#"
2ff91fec 9059 "TARGET_32BIT && reload_completed"
3c5afce6 9060 [(set (match_dup 7)
9061 (compare
9062 (ior:SI
9063 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9064 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9065 (const_int 0)))
9066 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9067 "operands[7]
9068 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9069 DOM_CC_X_OR_Y),
601f584c 9070 CC_REGNUM);"
9071 [(set_attr "conds" "clob")
1b7da4ac 9072 (set_attr "length" "16")
9073 (set_attr "type" "multiple")]
9074)
601f584c 9075
9076; If the above pattern is followed by a CMP insn, then the compare is
9077; redundant, since we can rework the conditional instruction that follows.
9078(define_insn_and_split "*ior_scc_scc_cmp"
9079 [(set (match_operand 0 "dominant_cc_register" "")
9080 (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9081 [(match_operand:SI 1 "s_register_operand" "r")
9082 (match_operand:SI 2 "arm_add_operand" "rIL")])
9083 (match_operator:SI 6 "arm_comparison_operator"
9084 [(match_operand:SI 4 "s_register_operand" "r")
9085 (match_operand:SI 5 "arm_add_operand" "rIL")]))
9086 (const_int 0)))
fd711051 9087 (set (match_operand:SI 7 "s_register_operand" "=Ts")
601f584c 9088 (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9089 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
2ff91fec 9090 "TARGET_32BIT"
601f584c 9091 "#"
2ff91fec 9092 "TARGET_32BIT && reload_completed"
601f584c 9093 [(set (match_dup 0)
9094 (compare
9095 (ior:SI
9096 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9097 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9098 (const_int 0)))
9099 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9100 ""
9101 [(set_attr "conds" "set")
1b7da4ac 9102 (set_attr "length" "16")
9103 (set_attr "type" "multiple")]
9104)
3c5afce6 9105
9106(define_insn_and_split "*and_scc_scc"
fd711051 9107 [(set (match_operand:SI 0 "s_register_operand" "=Ts")
3c5afce6 9108 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9109 [(match_operand:SI 1 "s_register_operand" "r")
9110 (match_operand:SI 2 "arm_add_operand" "rIL")])
9111 (match_operator:SI 6 "arm_comparison_operator"
9112 [(match_operand:SI 4 "s_register_operand" "r")
9113 (match_operand:SI 5 "arm_add_operand" "rIL")])))
9114 (clobber (reg:CC CC_REGNUM))]
2ff91fec 9115 "TARGET_32BIT
3c5afce6 9116 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9117 != CCmode)"
9118 "#"
2ff91fec 9119 "TARGET_32BIT && reload_completed
601f584c 9120 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9121 != CCmode)"
3c5afce6 9122 [(set (match_dup 7)
9123 (compare
9124 (and:SI
9125 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9126 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9127 (const_int 0)))
9128 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9129 "operands[7]
9130 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9131 DOM_CC_X_AND_Y),
601f584c 9132 CC_REGNUM);"
9133 [(set_attr "conds" "clob")
1b7da4ac 9134 (set_attr "length" "16")
9135 (set_attr "type" "multiple")]
9136)
601f584c 9137
9138; If the above pattern is followed by a CMP insn, then the compare is
9139; redundant, since we can rework the conditional instruction that follows.
9140(define_insn_and_split "*and_scc_scc_cmp"
9141 [(set (match_operand 0 "dominant_cc_register" "")
9142 (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
9143 [(match_operand:SI 1 "s_register_operand" "r")
9144 (match_operand:SI 2 "arm_add_operand" "rIL")])
9145 (match_operator:SI 6 "arm_comparison_operator"
9146 [(match_operand:SI 4 "s_register_operand" "r")
9147 (match_operand:SI 5 "arm_add_operand" "rIL")]))
9148 (const_int 0)))
fd711051 9149 (set (match_operand:SI 7 "s_register_operand" "=Ts")
601f584c 9150 (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9151 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
2ff91fec 9152 "TARGET_32BIT"
601f584c 9153 "#"
2ff91fec 9154 "TARGET_32BIT && reload_completed"
601f584c 9155 [(set (match_dup 0)
9156 (compare
9157 (and:SI
9158 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9159 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9160 (const_int 0)))
9161 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9162 ""
9163 [(set_attr "conds" "set")
1b7da4ac 9164 (set_attr "length" "16")
9165 (set_attr "type" "multiple")]
9166)
601f584c 9167
9168;; If there is no dominance in the comparison, then we can still save an
9169;; instruction in the AND case, since we can know that the second compare
9170;; need only zero the value if false (if true, then the value is already
9171;; correct).
9172(define_insn_and_split "*and_scc_scc_nodom"
fd711051 9173 [(set (match_operand:SI 0 "s_register_operand" "=&Ts,&Ts,&Ts")
601f584c 9174 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9175 [(match_operand:SI 1 "s_register_operand" "r,r,0")
9176 (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
9177 (match_operator:SI 6 "arm_comparison_operator"
9178 [(match_operand:SI 4 "s_register_operand" "r,r,r")
9179 (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
9180 (clobber (reg:CC CC_REGNUM))]
2ff91fec 9181 "TARGET_32BIT
601f584c 9182 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9183 == CCmode)"
9184 "#"
2ff91fec 9185 "TARGET_32BIT && reload_completed"
601f584c 9186 [(parallel [(set (match_dup 0)
9187 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
9188 (clobber (reg:CC CC_REGNUM))])
9189 (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
9190 (set (match_dup 0)
9191 (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
9192 (match_dup 0)
9193 (const_int 0)))]
9194 "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
9195 operands[4], operands[5]),
9196 CC_REGNUM);
9197 operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
9198 operands[5]);"
9199 [(set_attr "conds" "clob")
1b7da4ac 9200 (set_attr "length" "20")
9201 (set_attr "type" "multiple")]
9202)
3c5afce6 9203
3a0bdee0 9204(define_split
9205 [(set (reg:CC_NOOV CC_REGNUM)
9206 (compare:CC_NOOV (ior:SI
9207 (and:SI (match_operand:SI 0 "s_register_operand" "")
9208 (const_int 1))
b0694be0 9209 (match_operator:SI 1 "arm_comparison_operator"
3a0bdee0 9210 [(match_operand:SI 2 "s_register_operand" "")
9211 (match_operand:SI 3 "arm_add_operand" "")]))
9212 (const_int 0)))
9213 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9214 "TARGET_ARM"
9215 [(set (match_dup 4)
9216 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9217 (match_dup 0)))
9218 (set (reg:CC_NOOV CC_REGNUM)
9219 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9220 (const_int 0)))]
9221 "")
9222
9223(define_split
9224 [(set (reg:CC_NOOV CC_REGNUM)
9225 (compare:CC_NOOV (ior:SI
b0694be0 9226 (match_operator:SI 1 "arm_comparison_operator"
3a0bdee0 9227 [(match_operand:SI 2 "s_register_operand" "")
9228 (match_operand:SI 3 "arm_add_operand" "")])
9229 (and:SI (match_operand:SI 0 "s_register_operand" "")
9230 (const_int 1)))
9231 (const_int 0)))
9232 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9233 "TARGET_ARM"
9234 [(set (match_dup 4)
9235 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9236 (match_dup 0)))
9237 (set (reg:CC_NOOV CC_REGNUM)
9238 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9239 (const_int 0)))]
9240 "")
25f905c2 9241;; ??? The conditional patterns above need checking for Thumb-2 usefulness
3a0bdee0 9242
190efb17 9243(define_insn_and_split "*negscc"
9c08d1fa 9244 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9245 (neg:SI (match_operator 3 "arm_comparison_operator"
9c08d1fa 9246 [(match_operand:SI 1 "s_register_operand" "r")
9247 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
bd5b4116 9248 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9249 "TARGET_ARM"
190efb17 9250 "#"
9251 "&& reload_completed"
9252 [(const_int 0)]
9253 {
9254 rtx cc_reg = gen_rtx_REG (CCmode, CC_REGNUM);
e2348bcb 9255
190efb17 9256 if (GET_CODE (operands[3]) == LT && operands[2] == const0_rtx)
9257 {
9258 /* Emit mov\\t%0, %1, asr #31 */
9259 emit_insn (gen_rtx_SET (VOIDmode,
9260 operands[0],
9261 gen_rtx_ASHIFTRT (SImode,
9262 operands[1],
9263 GEN_INT (31))));
9264 DONE;
9265 }
9266 else if (GET_CODE (operands[3]) == NE)
9267 {
9268 /* Emit subs\\t%0, %1, %2\;mvnne\\t%0, #0 */
9269 if (CONST_INT_P (operands[2]))
9270 emit_insn (gen_cmpsi2_addneg (operands[0], operands[1], operands[2],
9271 GEN_INT (- INTVAL (operands[2]))));
9272 else
9273 emit_insn (gen_subsi3_compare (operands[0], operands[1], operands[2]));
9274
9275 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
9276 gen_rtx_NE (SImode,
9277 cc_reg,
9278 const0_rtx),
9279 gen_rtx_SET (SImode,
9280 operands[0],
9281 GEN_INT (~0))));
9282 DONE;
9283 }
9284 else
9285 {
9286 /* Emit: cmp\\t%1, %2\;mov%D3\\t%0, #0\;mvn%d3\\t%0, #0 */
9287 emit_insn (gen_rtx_SET (VOIDmode,
9288 cc_reg,
9289 gen_rtx_COMPARE (CCmode, operands[1], operands[2])));
9290 enum rtx_code rc = GET_CODE (operands[3]);
9291
9292 rc = reverse_condition (rc);
9293 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
9294 gen_rtx_fmt_ee (rc,
9295 VOIDmode,
9296 cc_reg,
9297 const0_rtx),
9298 gen_rtx_SET (VOIDmode, operands[0], const0_rtx)));
9299 rc = GET_CODE (operands[3]);
9300 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
9301 gen_rtx_fmt_ee (rc,
9302 VOIDmode,
9303 cc_reg,
9304 const0_rtx),
9305 gen_rtx_SET (VOIDmode,
9306 operands[0],
9307 GEN_INT (~0))));
9308 DONE;
9309 }
9310 FAIL;
9311 }
8fa3ba89 9312 [(set_attr "conds" "clob")
1b7da4ac 9313 (set_attr "length" "12")
9314 (set_attr "type" "multiple")]
8fa3ba89 9315)
9c08d1fa 9316
90404b57 9317(define_insn_and_split "movcond_addsi"
9318 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r")
9319 (if_then_else:SI
9320 (match_operator 5 "comparison_operator"
9321 [(plus:SI (match_operand:SI 3 "s_register_operand" "r,r,r")
9322 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL"))
9323 (const_int 0)])
9324 (match_operand:SI 1 "arm_rhs_operand" "rI,rPy,r")
9325 (match_operand:SI 2 "arm_rhs_operand" "rI,rPy,r")))
9326 (clobber (reg:CC CC_REGNUM))]
9327 "TARGET_32BIT"
9328 "#"
9329 "&& reload_completed"
9330 [(set (reg:CC_NOOV CC_REGNUM)
9331 (compare:CC_NOOV
9332 (plus:SI (match_dup 3)
9333 (match_dup 4))
9334 (const_int 0)))
9335 (set (match_dup 0) (match_dup 1))
9336 (cond_exec (match_dup 6)
9337 (set (match_dup 0) (match_dup 2)))]
9338 "
9339 {
3754d046 9340 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[5]),
90404b57 9341 operands[3], operands[4]);
9342 enum rtx_code rc = GET_CODE (operands[5]);
90404b57 9343 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9344 gcc_assert (!(mode == CCFPmode || mode == CCFPEmode));
4d01ce2f 9345 if (REGNO (operands[2]) != REGNO (operands[0]))
9346 rc = reverse_condition (rc);
f145bcba 9347 else
9348 std::swap (operands[1], operands[2]);
90404b57 9349
9350 operands[6] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9351 }
9352 "
9353 [(set_attr "conds" "clob")
1b7da4ac 9354 (set_attr "enabled_for_depr_it" "no,yes,yes")
9355 (set_attr "type" "multiple")]
90404b57 9356)
9357
9c08d1fa 9358(define_insn "movcond"
9359 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 9360 (if_then_else:SI
8fa3ba89 9361 (match_operator 5 "arm_comparison_operator"
5565501b 9362 [(match_operand:SI 3 "s_register_operand" "r,r,r")
9363 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
9364 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9365 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 9366 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9367 "TARGET_ARM"
9c08d1fa 9368 "*
9369 if (GET_CODE (operands[5]) == LT
9370 && (operands[4] == const0_rtx))
9371 {
0438d37f 9372 if (which_alternative != 1 && REG_P (operands[1]))
9c08d1fa 9373 {
9c08d1fa 9374 if (operands[2] == const0_rtx)
e2348bcb 9375 return \"and\\t%0, %1, %3, asr #31\";
9376 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
9c08d1fa 9377 }
0438d37f 9378 else if (which_alternative != 0 && REG_P (operands[2]))
9c08d1fa 9379 {
9c08d1fa 9380 if (operands[1] == const0_rtx)
e2348bcb 9381 return \"bic\\t%0, %2, %3, asr #31\";
9382 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
9c08d1fa 9383 }
9384 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 9385 are constants. */
9c08d1fa 9386 }
e2348bcb 9387
9c08d1fa 9388 if (GET_CODE (operands[5]) == GE
9389 && (operands[4] == const0_rtx))
9390 {
0438d37f 9391 if (which_alternative != 1 && REG_P (operands[1]))
9c08d1fa 9392 {
9c08d1fa 9393 if (operands[2] == const0_rtx)
e2348bcb 9394 return \"bic\\t%0, %1, %3, asr #31\";
9395 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
9c08d1fa 9396 }
0438d37f 9397 else if (which_alternative != 0 && REG_P (operands[2]))
9c08d1fa 9398 {
9c08d1fa 9399 if (operands[1] == const0_rtx)
e2348bcb 9400 return \"and\\t%0, %2, %3, asr #31\";
9401 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
9c08d1fa 9402 }
9403 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 9404 are constants. */
9c08d1fa 9405 }
0438d37f 9406 if (CONST_INT_P (operands[4])
9c08d1fa 9407 && !const_ok_for_arm (INTVAL (operands[4])))
e2348bcb 9408 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
9c08d1fa 9409 else
e2348bcb 9410 output_asm_insn (\"cmp\\t%3, %4\", operands);
9c08d1fa 9411 if (which_alternative != 0)
e2348bcb 9412 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
9c08d1fa 9413 if (which_alternative != 1)
e2348bcb 9414 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
9c08d1fa 9415 return \"\";
215b30b3 9416 "
8fa3ba89 9417 [(set_attr "conds" "clob")
1b7da4ac 9418 (set_attr "length" "8,8,12")
9419 (set_attr "type" "multiple")]
8fa3ba89 9420)
9c08d1fa 9421
25f905c2 9422;; ??? The patterns below need checking for Thumb-2 usefulness.
9423
8a18b90c 9424(define_insn "*ifcompare_plus_move"
9425 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9426 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 9427 [(match_operand:SI 4 "s_register_operand" "r,r")
9428 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9429 (plus:SI
9430 (match_operand:SI 2 "s_register_operand" "r,r")
9431 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
129a2fe4 9432 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 9433 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9434 "TARGET_ARM"
8a18b90c 9435 "#"
8fa3ba89 9436 [(set_attr "conds" "clob")
1b7da4ac 9437 (set_attr "length" "8,12")
9438 (set_attr "type" "multiple")]
8fa3ba89 9439)
8a18b90c 9440
9441(define_insn "*if_plus_move"
129a2fe4 9442 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 9443 (if_then_else:SI
8fa3ba89 9444 (match_operator 4 "arm_comparison_operator"
8a18b90c 9445 [(match_operand 5 "cc_register" "") (const_int 0)])
9446 (plus:SI
129a2fe4 9447 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9448 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
9449 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
cffb2a26 9450 "TARGET_ARM"
8a18b90c 9451 "@
9452 add%d4\\t%0, %2, %3
9453 sub%d4\\t%0, %2, #%n3
9454 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
129a2fe4 9455 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8fa3ba89 9456 [(set_attr "conds" "use")
9457 (set_attr "length" "4,4,8,8")
65f68e55 9458 (set_attr_alternative "type"
9459 [(if_then_else (match_operand 3 "const_int_operand" "")
d82e788e 9460 (const_string "alu_imm" )
112eda6f 9461 (const_string "alu_sreg"))
d82e788e 9462 (const_string "alu_imm")
112eda6f 9463 (const_string "alu_sreg")
9464 (const_string "alu_sreg")])]
8fa3ba89 9465)
8a18b90c 9466
9467(define_insn "*ifcompare_move_plus"
5565501b 9468 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9469 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 9470 [(match_operand:SI 4 "s_register_operand" "r,r")
9471 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 9472 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 9473 (plus:SI
9474 (match_operand:SI 2 "s_register_operand" "r,r")
9475 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
bd5b4116 9476 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9477 "TARGET_ARM"
8a18b90c 9478 "#"
8fa3ba89 9479 [(set_attr "conds" "clob")
1b7da4ac 9480 (set_attr "length" "8,12")
9481 (set_attr "type" "multiple")]
8fa3ba89 9482)
8a18b90c 9483
9484(define_insn "*if_move_plus"
129a2fe4 9485 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 9486 (if_then_else:SI
8fa3ba89 9487 (match_operator 4 "arm_comparison_operator"
8a18b90c 9488 [(match_operand 5 "cc_register" "") (const_int 0)])
129a2fe4 9489 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8a18b90c 9490 (plus:SI
129a2fe4 9491 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9492 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
cffb2a26 9493 "TARGET_ARM"
8a18b90c 9494 "@
9495 add%D4\\t%0, %2, %3
9496 sub%D4\\t%0, %2, #%n3
9497 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
129a2fe4 9498 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8fa3ba89 9499 [(set_attr "conds" "use")
9500 (set_attr "length" "4,4,8,8")
112eda6f 9501 (set_attr "type" "alu_sreg,alu_imm,multiple,multiple")]
8fa3ba89 9502)
8a18b90c 9503
9504(define_insn "*ifcompare_arith_arith"
9505 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9506 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8a18b90c 9507 [(match_operand:SI 5 "s_register_operand" "r")
9508 (match_operand:SI 6 "arm_add_operand" "rIL")])
9c08d1fa 9509 (match_operator:SI 8 "shiftable_operator"
8a18b90c 9510 [(match_operand:SI 1 "s_register_operand" "r")
9511 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9c08d1fa 9512 (match_operator:SI 7 "shiftable_operator"
8a18b90c 9513 [(match_operand:SI 3 "s_register_operand" "r")
9514 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
bd5b4116 9515 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9516 "TARGET_ARM"
8a18b90c 9517 "#"
8fa3ba89 9518 [(set_attr "conds" "clob")
1b7da4ac 9519 (set_attr "length" "12")
9520 (set_attr "type" "multiple")]
8fa3ba89 9521)
9c08d1fa 9522
8a18b90c 9523(define_insn "*if_arith_arith"
9524 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9525 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8a18b90c 9526 [(match_operand 8 "cc_register" "") (const_int 0)])
9527 (match_operator:SI 6 "shiftable_operator"
9528 [(match_operand:SI 1 "s_register_operand" "r")
9529 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9530 (match_operator:SI 7 "shiftable_operator"
9531 [(match_operand:SI 3 "s_register_operand" "r")
9532 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
cffb2a26 9533 "TARGET_ARM"
8a18b90c 9534 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8fa3ba89 9535 [(set_attr "conds" "use")
1b7da4ac 9536 (set_attr "length" "8")
9537 (set_attr "type" "multiple")]
8fa3ba89 9538)
8a18b90c 9539
f7fbdd4a 9540(define_insn "*ifcompare_arith_move"
9c08d1fa 9541 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9542 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 9543 [(match_operand:SI 2 "s_register_operand" "r,r")
5565501b 9544 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
9c08d1fa 9545 (match_operator:SI 7 "shiftable_operator"
9546 [(match_operand:SI 4 "s_register_operand" "r,r")
9547 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
129a2fe4 9548 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 9549 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9550 "TARGET_ARM"
9c08d1fa 9551 "*
9c08d1fa 9552 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 9553 the conditional operator is LT or GE and we are comparing against zero and
674a8f0b 9554 everything is in registers then we can do this in two instructions. */
9c08d1fa 9555 if (operands[3] == const0_rtx
9556 && GET_CODE (operands[7]) != AND
0438d37f 9557 && REG_P (operands[5])
9558 && REG_P (operands[1])
9c08d1fa 9559 && REGNO (operands[1]) == REGNO (operands[4])
9560 && REGNO (operands[4]) != REGNO (operands[0]))
9561 {
9562 if (GET_CODE (operands[6]) == LT)
40dbec34 9563 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 9564 else if (GET_CODE (operands[6]) == GE)
40dbec34 9565 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 9566 }
0438d37f 9567 if (CONST_INT_P (operands[3])
9c08d1fa 9568 && !const_ok_for_arm (INTVAL (operands[3])))
e2348bcb 9569 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
9c08d1fa 9570 else
e2348bcb 9571 output_asm_insn (\"cmp\\t%2, %3\", operands);
40dbec34 9572 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
9c08d1fa 9573 if (which_alternative != 0)
129a2fe4 9574 return \"mov%D6\\t%0, %1\";
9c08d1fa 9575 return \"\";
215b30b3 9576 "
8fa3ba89 9577 [(set_attr "conds" "clob")
1b7da4ac 9578 (set_attr "length" "8,12")
9579 (set_attr "type" "multiple")]
8fa3ba89 9580)
9c08d1fa 9581
8a18b90c 9582(define_insn "*if_arith_move"
129a2fe4 9583 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9584 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8a18b90c 9585 [(match_operand 6 "cc_register" "") (const_int 0)])
9586 (match_operator:SI 5 "shiftable_operator"
129a2fe4 9587 [(match_operand:SI 2 "s_register_operand" "r,r")
9588 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
9589 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
cffb2a26 9590 "TARGET_ARM"
8a18b90c 9591 "@
9592 %I5%d4\\t%0, %2, %3
129a2fe4 9593 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8fa3ba89 9594 [(set_attr "conds" "use")
9595 (set_attr "length" "4,8")
1b7da4ac 9596 (set_attr "type" "alu_shift_reg,multiple")]
8fa3ba89 9597)
8a18b90c 9598
f7fbdd4a 9599(define_insn "*ifcompare_move_arith"
9c08d1fa 9600 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9601 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 9602 [(match_operand:SI 4 "s_register_operand" "r,r")
5565501b 9603 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 9604 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9c08d1fa 9605 (match_operator:SI 7 "shiftable_operator"
9606 [(match_operand:SI 2 "s_register_operand" "r,r")
9607 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 9608 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9609 "TARGET_ARM"
9c08d1fa 9610 "*
9c08d1fa 9611 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 9612 the conditional operator is LT or GE and we are comparing against zero and
9c08d1fa 9613 everything is in registers then we can do this in two instructions */
9614 if (operands[5] == const0_rtx
9615 && GET_CODE (operands[7]) != AND
0438d37f 9616 && REG_P (operands[3])
9617 && REG_P (operands[1])
9c08d1fa 9618 && REGNO (operands[1]) == REGNO (operands[2])
9619 && REGNO (operands[2]) != REGNO (operands[0]))
9620 {
9621 if (GET_CODE (operands[6]) == GE)
40dbec34 9622 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 9623 else if (GET_CODE (operands[6]) == LT)
40dbec34 9624 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 9625 }
40dbec34 9626
0438d37f 9627 if (CONST_INT_P (operands[5])
9c08d1fa 9628 && !const_ok_for_arm (INTVAL (operands[5])))
e2348bcb 9629 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
9c08d1fa 9630 else
e2348bcb 9631 output_asm_insn (\"cmp\\t%4, %5\", operands);
40dbec34 9632
9c08d1fa 9633 if (which_alternative != 0)
129a2fe4 9634 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
40dbec34 9635 return \"%I7%D6\\t%0, %2, %3\";
215b30b3 9636 "
8fa3ba89 9637 [(set_attr "conds" "clob")
1b7da4ac 9638 (set_attr "length" "8,12")
9639 (set_attr "type" "multiple")]
8fa3ba89 9640)
9c08d1fa 9641
8a18b90c 9642(define_insn "*if_move_arith"
129a2fe4 9643 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9644 (if_then_else:SI
8fa3ba89 9645 (match_operator 4 "arm_comparison_operator"
8a18b90c 9646 [(match_operand 6 "cc_register" "") (const_int 0)])
129a2fe4 9647 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 9648 (match_operator:SI 5 "shiftable_operator"
129a2fe4 9649 [(match_operand:SI 2 "s_register_operand" "r,r")
9650 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
cffb2a26 9651 "TARGET_ARM"
8a18b90c 9652 "@
9653 %I5%D4\\t%0, %2, %3
129a2fe4 9654 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
8fa3ba89 9655 [(set_attr "conds" "use")
9656 (set_attr "length" "4,8")
1b7da4ac 9657 (set_attr "type" "alu_shift_reg,multiple")]
8fa3ba89 9658)
8a18b90c 9659
9660(define_insn "*ifcompare_move_not"
9c08d1fa 9661 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9662 (if_then_else:SI
8fa3ba89 9663 (match_operator 5 "arm_comparison_operator"
8a18b90c 9664 [(match_operand:SI 3 "s_register_operand" "r,r")
9665 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9666 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9667 (not:SI
9668 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 9669 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9670 "TARGET_ARM"
8a18b90c 9671 "#"
8fa3ba89 9672 [(set_attr "conds" "clob")
1b7da4ac 9673 (set_attr "length" "8,12")
9674 (set_attr "type" "multiple")]
8fa3ba89 9675)
9c08d1fa 9676
8a18b90c 9677(define_insn "*if_move_not"
9678 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9679 (if_then_else:SI
8fa3ba89 9680 (match_operator 4 "arm_comparison_operator"
8a18b90c 9681 [(match_operand 3 "cc_register" "") (const_int 0)])
9682 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9683 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
cffb2a26 9684 "TARGET_ARM"
8a18b90c 9685 "@
9686 mvn%D4\\t%0, %2
9687 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
9688 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
8fa3ba89 9689 [(set_attr "conds" "use")
1aed5204 9690 (set_attr "type" "mvn_reg")
1b7da4ac 9691 (set_attr "length" "4,8,8")
9692 (set_attr "type" "mvn_reg,multiple,multiple")]
8fa3ba89 9693)
8a18b90c 9694
9695(define_insn "*ifcompare_not_move"
9c08d1fa 9696 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9697 (if_then_else:SI
8fa3ba89 9698 (match_operator 5 "arm_comparison_operator"
8a18b90c 9699 [(match_operand:SI 3 "s_register_operand" "r,r")
9700 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9701 (not:SI
9702 (match_operand:SI 2 "s_register_operand" "r,r"))
9703 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 9704 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9705 "TARGET_ARM"
8a18b90c 9706 "#"
8fa3ba89 9707 [(set_attr "conds" "clob")
1b7da4ac 9708 (set_attr "length" "8,12")
9709 (set_attr "type" "multiple")]
8fa3ba89 9710)
9c08d1fa 9711
8a18b90c 9712(define_insn "*if_not_move"
9713 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9714 (if_then_else:SI
8fa3ba89 9715 (match_operator 4 "arm_comparison_operator"
8a18b90c 9716 [(match_operand 3 "cc_register" "") (const_int 0)])
9717 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9718 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 9719 "TARGET_ARM"
8a18b90c 9720 "@
9721 mvn%d4\\t%0, %2
9722 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
9723 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
8fa3ba89 9724 [(set_attr "conds" "use")
1b7da4ac 9725 (set_attr "type" "mvn_reg,multiple,multiple")
8fa3ba89 9726 (set_attr "length" "4,8,8")]
9727)
8a18b90c 9728
9729(define_insn "*ifcompare_shift_move"
9c08d1fa 9730 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9731 (if_then_else:SI
8fa3ba89 9732 (match_operator 6 "arm_comparison_operator"
8a18b90c 9733 [(match_operand:SI 4 "s_register_operand" "r,r")
9734 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9735 (match_operator:SI 7 "shift_operator"
9736 [(match_operand:SI 2 "s_register_operand" "r,r")
9737 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
9738 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 9739 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9740 "TARGET_ARM"
9c08d1fa 9741 "#"
8fa3ba89 9742 [(set_attr "conds" "clob")
1b7da4ac 9743 (set_attr "length" "8,12")
9744 (set_attr "type" "multiple")]
8fa3ba89 9745)
9c08d1fa 9746
8a18b90c 9747(define_insn "*if_shift_move"
9748 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9749 (if_then_else:SI
8fa3ba89 9750 (match_operator 5 "arm_comparison_operator"
8a18b90c 9751 [(match_operand 6 "cc_register" "") (const_int 0)])
9752 (match_operator:SI 4 "shift_operator"
9753 [(match_operand:SI 2 "s_register_operand" "r,r,r")
9754 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
9755 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 9756 "TARGET_ARM"
5565501b 9757 "@
8a18b90c 9758 mov%d5\\t%0, %2%S4
9759 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
9760 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
8fa3ba89 9761 [(set_attr "conds" "use")
331beb1a 9762 (set_attr "shift" "2")
a2cd141b 9763 (set_attr "length" "4,8,8")
1b7da4ac 9764 (set_attr "type" "mov_shift_reg,multiple,multiple")]
8fa3ba89 9765)
5565501b 9766
8a18b90c 9767(define_insn "*ifcompare_move_shift"
9768 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 9769 (if_then_else:SI
8fa3ba89 9770 (match_operator 6 "arm_comparison_operator"
8a18b90c 9771 [(match_operand:SI 4 "s_register_operand" "r,r")
9772 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9773 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
5565501b 9774 (match_operator:SI 7 "shift_operator"
8a18b90c 9775 [(match_operand:SI 2 "s_register_operand" "r,r")
9776 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
bd5b4116 9777 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9778 "TARGET_ARM"
8a18b90c 9779 "#"
8fa3ba89 9780 [(set_attr "conds" "clob")
1b7da4ac 9781 (set_attr "length" "8,12")
9782 (set_attr "type" "multiple")]
8fa3ba89 9783)
5565501b 9784
8a18b90c 9785(define_insn "*if_move_shift"
9786 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 9787 (if_then_else:SI
8fa3ba89 9788 (match_operator 5 "arm_comparison_operator"
8a18b90c 9789 [(match_operand 6 "cc_register" "") (const_int 0)])
9790 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9791 (match_operator:SI 4 "shift_operator"
9792 [(match_operand:SI 2 "s_register_operand" "r,r,r")
9793 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
cffb2a26 9794 "TARGET_ARM"
5565501b 9795 "@
8a18b90c 9796 mov%D5\\t%0, %2%S4
9797 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
9798 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
8fa3ba89 9799 [(set_attr "conds" "use")
331beb1a 9800 (set_attr "shift" "2")
a2cd141b 9801 (set_attr "length" "4,8,8")
1b7da4ac 9802 (set_attr "type" "mov_shift_reg,multiple,multiple")]
8fa3ba89 9803)
9c08d1fa 9804
f7fbdd4a 9805(define_insn "*ifcompare_shift_shift"
8a18b90c 9806 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 9807 (if_then_else:SI
8fa3ba89 9808 (match_operator 7 "arm_comparison_operator"
8a18b90c 9809 [(match_operand:SI 5 "s_register_operand" "r")
9810 (match_operand:SI 6 "arm_add_operand" "rIL")])
5565501b 9811 (match_operator:SI 8 "shift_operator"
8a18b90c 9812 [(match_operand:SI 1 "s_register_operand" "r")
9813 (match_operand:SI 2 "arm_rhs_operand" "rM")])
5565501b 9814 (match_operator:SI 9 "shift_operator"
8a18b90c 9815 [(match_operand:SI 3 "s_register_operand" "r")
9816 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
bd5b4116 9817 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9818 "TARGET_ARM"
8a18b90c 9819 "#"
8fa3ba89 9820 [(set_attr "conds" "clob")
1b7da4ac 9821 (set_attr "length" "12")
9822 (set_attr "type" "multiple")]
8fa3ba89 9823)
9c08d1fa 9824
8a18b90c 9825(define_insn "*if_shift_shift"
9826 [(set (match_operand:SI 0 "s_register_operand" "=r")
9827 (if_then_else:SI
8fa3ba89 9828 (match_operator 5 "arm_comparison_operator"
8a18b90c 9829 [(match_operand 8 "cc_register" "") (const_int 0)])
9830 (match_operator:SI 6 "shift_operator"
9831 [(match_operand:SI 1 "s_register_operand" "r")
9832 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9833 (match_operator:SI 7 "shift_operator"
9834 [(match_operand:SI 3 "s_register_operand" "r")
9835 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
cffb2a26 9836 "TARGET_ARM"
8a18b90c 9837 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
8fa3ba89 9838 [(set_attr "conds" "use")
331beb1a 9839 (set_attr "shift" "1")
a2cd141b 9840 (set_attr "length" "8")
9841 (set (attr "type") (if_then_else
9842 (and (match_operand 2 "const_int_operand" "")
9843 (match_operand 4 "const_int_operand" ""))
1aed5204 9844 (const_string "mov_shift")
9845 (const_string "mov_shift_reg")))]
8fa3ba89 9846)
8a18b90c 9847
f7fbdd4a 9848(define_insn "*ifcompare_not_arith"
8a18b90c 9849 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 9850 (if_then_else:SI
8fa3ba89 9851 (match_operator 6 "arm_comparison_operator"
8a18b90c 9852 [(match_operand:SI 4 "s_register_operand" "r")
9853 (match_operand:SI 5 "arm_add_operand" "rIL")])
9854 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5565501b 9855 (match_operator:SI 7 "shiftable_operator"
8a18b90c 9856 [(match_operand:SI 2 "s_register_operand" "r")
9857 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
bd5b4116 9858 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9859 "TARGET_ARM"
8a18b90c 9860 "#"
8fa3ba89 9861 [(set_attr "conds" "clob")
1b7da4ac 9862 (set_attr "length" "12")
9863 (set_attr "type" "multiple")]
8fa3ba89 9864)
9c08d1fa 9865
8a18b90c 9866(define_insn "*if_not_arith"
9867 [(set (match_operand:SI 0 "s_register_operand" "=r")
9868 (if_then_else:SI
8fa3ba89 9869 (match_operator 5 "arm_comparison_operator"
8a18b90c 9870 [(match_operand 4 "cc_register" "") (const_int 0)])
9871 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9872 (match_operator:SI 6 "shiftable_operator"
9873 [(match_operand:SI 2 "s_register_operand" "r")
9874 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
cffb2a26 9875 "TARGET_ARM"
8a18b90c 9876 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
8fa3ba89 9877 [(set_attr "conds" "use")
1aed5204 9878 (set_attr "type" "mvn_reg")
8fa3ba89 9879 (set_attr "length" "8")]
9880)
8a18b90c 9881
9882(define_insn "*ifcompare_arith_not"
9883 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 9884 (if_then_else:SI
8fa3ba89 9885 (match_operator 6 "arm_comparison_operator"
8a18b90c 9886 [(match_operand:SI 4 "s_register_operand" "r")
9887 (match_operand:SI 5 "arm_add_operand" "rIL")])
5565501b 9888 (match_operator:SI 7 "shiftable_operator"
8a18b90c 9889 [(match_operand:SI 2 "s_register_operand" "r")
9890 (match_operand:SI 3 "arm_rhs_operand" "rI")])
9891 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
bd5b4116 9892 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9893 "TARGET_ARM"
8a18b90c 9894 "#"
8fa3ba89 9895 [(set_attr "conds" "clob")
1b7da4ac 9896 (set_attr "length" "12")
9897 (set_attr "type" "multiple")]
8fa3ba89 9898)
9c08d1fa 9899
8a18b90c 9900(define_insn "*if_arith_not"
9901 [(set (match_operand:SI 0 "s_register_operand" "=r")
9902 (if_then_else:SI
8fa3ba89 9903 (match_operator 5 "arm_comparison_operator"
8a18b90c 9904 [(match_operand 4 "cc_register" "") (const_int 0)])
9905 (match_operator:SI 6 "shiftable_operator"
9906 [(match_operand:SI 2 "s_register_operand" "r")
9907 (match_operand:SI 3 "arm_rhs_operand" "rI")])
9908 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
cffb2a26 9909 "TARGET_ARM"
8a18b90c 9910 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
8fa3ba89 9911 [(set_attr "conds" "use")
1b7da4ac 9912 (set_attr "type" "multiple")
8fa3ba89 9913 (set_attr "length" "8")]
9914)
8a18b90c 9915
f7fbdd4a 9916(define_insn "*ifcompare_neg_move"
8a18b90c 9917 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 9918 (if_then_else:SI
8fa3ba89 9919 (match_operator 5 "arm_comparison_operator"
8a18b90c 9920 [(match_operand:SI 3 "s_register_operand" "r,r")
9921 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9922 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
9923 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 9924 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9925 "TARGET_ARM"
8a18b90c 9926 "#"
8fa3ba89 9927 [(set_attr "conds" "clob")
1b7da4ac 9928 (set_attr "length" "8,12")
9929 (set_attr "type" "multiple")]
8fa3ba89 9930)
8a18b90c 9931
9932(define_insn "*if_neg_move"
9933 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9934 (if_then_else:SI
8fa3ba89 9935 (match_operator 4 "arm_comparison_operator"
8a18b90c 9936 [(match_operand 3 "cc_register" "") (const_int 0)])
9937 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9938 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 9939 "TARGET_ARM"
8a18b90c 9940 "@
9941 rsb%d4\\t%0, %2, #0
9942 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
9943 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
8fa3ba89 9944 [(set_attr "conds" "use")
1b7da4ac 9945 (set_attr "length" "4,8,8")
9946 (set_attr "type" "logic_shift_imm,multiple,multiple")]
8fa3ba89 9947)
9c08d1fa 9948
f7fbdd4a 9949(define_insn "*ifcompare_move_neg"
8a18b90c 9950 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 9951 (if_then_else:SI
8fa3ba89 9952 (match_operator 5 "arm_comparison_operator"
8a18b90c 9953 [(match_operand:SI 3 "s_register_operand" "r,r")
9954 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9955 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9956 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 9957 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9958 "TARGET_ARM"
8a18b90c 9959 "#"
8fa3ba89 9960 [(set_attr "conds" "clob")
1b7da4ac 9961 (set_attr "length" "8,12")
9962 (set_attr "type" "multiple")]
8fa3ba89 9963)
8a18b90c 9964
9965(define_insn "*if_move_neg"
9966 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9967 (if_then_else:SI
8fa3ba89 9968 (match_operator 4 "arm_comparison_operator"
8a18b90c 9969 [(match_operand 3 "cc_register" "") (const_int 0)])
9970 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9971 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
cffb2a26 9972 "TARGET_ARM"
8a18b90c 9973 "@
9974 rsb%D4\\t%0, %2, #0
9975 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
9976 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
0d66636f 9977 [(set_attr "conds" "use")
1b7da4ac 9978 (set_attr "length" "4,8,8")
9979 (set_attr "type" "logic_shift_imm,multiple,multiple")]
0d66636f 9980)
9c08d1fa 9981
f7fbdd4a 9982(define_insn "*arith_adjacentmem"
9c08d1fa 9983 [(set (match_operand:SI 0 "s_register_operand" "=r")
9984 (match_operator:SI 1 "shiftable_operator"
9985 [(match_operand:SI 2 "memory_operand" "m")
9986 (match_operand:SI 3 "memory_operand" "m")]))
9987 (clobber (match_scratch:SI 4 "=r"))]
cffb2a26 9988 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9c08d1fa 9989 "*
215b30b3 9990 {
9991 rtx ldm[3];
9992 rtx arith[4];
94dee231 9993 rtx base_reg;
9994 HOST_WIDE_INT val1 = 0, val2 = 0;
9c08d1fa 9995
215b30b3 9996 if (REGNO (operands[0]) > REGNO (operands[4]))
9997 {
9998 ldm[1] = operands[4];
9999 ldm[2] = operands[0];
10000 }
10001 else
10002 {
10003 ldm[1] = operands[0];
10004 ldm[2] = operands[4];
10005 }
94dee231 10006
10007 base_reg = XEXP (operands[2], 0);
10008
10009 if (!REG_P (base_reg))
10010 {
10011 val1 = INTVAL (XEXP (base_reg, 1));
10012 base_reg = XEXP (base_reg, 0);
10013 }
10014
10015 if (!REG_P (XEXP (operands[3], 0)))
215b30b3 10016 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
94dee231 10017
215b30b3 10018 arith[0] = operands[0];
10019 arith[3] = operands[1];
94dee231 10020
215b30b3 10021 if (val1 < val2)
10022 {
10023 arith[1] = ldm[1];
10024 arith[2] = ldm[2];
10025 }
10026 else
10027 {
10028 arith[1] = ldm[2];
10029 arith[2] = ldm[1];
10030 }
94dee231 10031
10032 ldm[0] = base_reg;
10033 if (val1 !=0 && val2 != 0)
215b30b3 10034 {
cdb1295a 10035 rtx ops[3];
10036
94dee231 10037 if (val1 == 4 || val2 == 4)
10038 /* Other val must be 8, since we know they are adjacent and neither
10039 is zero. */
25f905c2 10040 output_asm_insn (\"ldm%(ib%)\\t%0, {%1, %2}\", ldm);
cdb1295a 10041 else if (const_ok_for_arm (val1) || const_ok_for_arm (-val1))
94dee231 10042 {
94dee231 10043 ldm[0] = ops[0] = operands[4];
10044 ops[1] = base_reg;
10045 ops[2] = GEN_INT (val1);
10046 output_add_immediate (ops);
10047 if (val1 < val2)
25f905c2 10048 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
94dee231 10049 else
25f905c2 10050 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
94dee231 10051 }
cdb1295a 10052 else
10053 {
10054 /* Offset is out of range for a single add, so use two ldr. */
10055 ops[0] = ldm[1];
10056 ops[1] = base_reg;
10057 ops[2] = GEN_INT (val1);
10058 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10059 ops[0] = ldm[2];
10060 ops[2] = GEN_INT (val2);
10061 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10062 }
215b30b3 10063 }
94dee231 10064 else if (val1 != 0)
215b30b3 10065 {
215b30b3 10066 if (val1 < val2)
25f905c2 10067 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
215b30b3 10068 else
25f905c2 10069 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
215b30b3 10070 }
10071 else
10072 {
215b30b3 10073 if (val1 < val2)
25f905c2 10074 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
215b30b3 10075 else
25f905c2 10076 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
215b30b3 10077 }
10078 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
10079 return \"\";
10080 }"
10081 [(set_attr "length" "12")
10082 (set_attr "predicable" "yes")
a2cd141b 10083 (set_attr "type" "load1")]
215b30b3 10084)
9c08d1fa 10085
9c08d1fa 10086; This pattern is never tried by combine, so do it as a peephole
10087
a0f94409 10088(define_peephole2
372575c7 10089 [(set (match_operand:SI 0 "arm_general_register_operand" "")
10090 (match_operand:SI 1 "arm_general_register_operand" ""))
bd5b4116 10091 (set (reg:CC CC_REGNUM)
aea4c774 10092 (compare:CC (match_dup 1) (const_int 0)))]
372575c7 10093 "TARGET_ARM"
a0f94409 10094 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
10095 (set (match_dup 0) (match_dup 1))])]
10096 ""
0d66636f 10097)
9c08d1fa 10098
9c08d1fa 10099(define_split
10100 [(set (match_operand:SI 0 "s_register_operand" "")
10101 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
10102 (const_int 0))
8fa3ba89 10103 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9c08d1fa 10104 [(match_operand:SI 3 "s_register_operand" "")
10105 (match_operand:SI 4 "arm_rhs_operand" "")]))))
10106 (clobber (match_operand:SI 5 "s_register_operand" ""))]
cffb2a26 10107 "TARGET_ARM"
9c08d1fa 10108 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
10109 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
10110 (match_dup 5)))]
215b30b3 10111 ""
10112)
9c08d1fa 10113
aea4c774 10114;; This split can be used because CC_Z mode implies that the following
10115;; branch will be an equality, or an unsigned inequality, so the sign
10116;; extension is not needed.
9c08d1fa 10117
aea4c774 10118(define_split
bd5b4116 10119 [(set (reg:CC_Z CC_REGNUM)
aea4c774 10120 (compare:CC_Z
10121 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9c08d1fa 10122 (const_int 24))
aea4c774 10123 (match_operand 1 "const_int_operand" "")))
10124 (clobber (match_scratch:SI 2 ""))]
cffb2a26 10125 "TARGET_ARM
10126 && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
10127 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
aea4c774 10128 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
bd5b4116 10129 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
aea4c774 10130 "
9c08d1fa 10131 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
215b30b3 10132 "
10133)
25f905c2 10134;; ??? Check the patterns above for Thumb-2 usefulness
9c08d1fa 10135
87b22bf7 10136(define_expand "prologue"
10137 [(clobber (const_int 0))]
cffb2a26 10138 "TARGET_EITHER"
25f905c2 10139 "if (TARGET_32BIT)
cffb2a26 10140 arm_expand_prologue ();
10141 else
25f905c2 10142 thumb1_expand_prologue ();
87b22bf7 10143 DONE;
cffb2a26 10144 "
10145)
87b22bf7 10146
56d27660 10147(define_expand "epilogue"
4c44712e 10148 [(clobber (const_int 0))]
cffb2a26 10149 "TARGET_EITHER"
56d27660 10150 "
18d50ae6 10151 if (crtl->calls_eh_return)
fb94f18b 10152 emit_insn (gen_force_register_use (gen_rtx_REG (Pmode, 2)));
25f905c2 10153 if (TARGET_THUMB1)
c3635784 10154 {
10155 thumb1_expand_epilogue ();
10156 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
10157 gen_rtvec (1, ret_rtx), VUNSPEC_EPILOGUE));
10158 }
10159 else if (HAVE_return)
10160 {
10161 /* HAVE_return is testing for USE_RETURN_INSN (FALSE). Hence,
10162 no need for explicit testing again. */
10163 emit_jump_insn (gen_return ());
10164 }
10165 else if (TARGET_32BIT)
10166 {
10167 arm_expand_epilogue (true);
10168 }
cffb2a26 10169 DONE;
10170 "
10171)
56d27660 10172
ef5651d0 10173;; Note - although unspec_volatile's USE all hard registers,
10174;; USEs are ignored after relaod has completed. Thus we need
10175;; to add an unspec of the link register to ensure that flow
10176;; does not think that it is unused by the sibcall branch that
10177;; will replace the standard function epilogue.
c3635784 10178(define_expand "sibcall_epilogue"
fb94f18b 10179 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_REGISTER_USE)
c3635784 10180 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
10181 "TARGET_32BIT"
10182 "
10183 arm_expand_epilogue (false);
10184 DONE;
10185 "
1c494086 10186)
10187
cffb2a26 10188(define_expand "eh_epilogue"
7db9af5d 10189 [(use (match_operand:SI 0 "register_operand" ""))
10190 (use (match_operand:SI 1 "register_operand" ""))
10191 (use (match_operand:SI 2 "register_operand" ""))]
cffb2a26 10192 "TARGET_EITHER"
10193 "
215b30b3 10194 {
10195 cfun->machine->eh_epilogue_sp_ofs = operands[1];
0438d37f 10196 if (!REG_P (operands[2]) || REGNO (operands[2]) != 2)
215b30b3 10197 {
10198 rtx ra = gen_rtx_REG (Pmode, 2);
10199
10200 emit_move_insn (ra, operands[2]);
10201 operands[2] = ra;
10202 }
5cf3595a 10203 /* This is a hack -- we may have crystalized the function type too
10204 early. */
10205 cfun->machine->func_type = 0;
215b30b3 10206 }"
10207)
56d27660 10208
9c08d1fa 10209;; This split is only used during output to reduce the number of patterns
10210;; that need assembler instructions adding to them. We allowed the setting
10211;; of the conditions to be implicit during rtl generation so that
10212;; the conditional compare patterns would work. However this conflicts to
8a18b90c 10213;; some extent with the conditional data operations, so we have to split them
9c08d1fa 10214;; up again here.
10215
25f905c2 10216;; ??? Need to audit these splitters for Thumb-2. Why isn't normal
10217;; conditional execution sufficient?
10218
9c08d1fa 10219(define_split
10220 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 10221 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10222 [(match_operand 2 "" "") (match_operand 3 "" "")])
10223 (match_dup 0)
10224 (match_operand 4 "" "")))
bd5b4116 10225 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10226 "TARGET_ARM && reload_completed"
8fa3ba89 10227 [(set (match_dup 5) (match_dup 6))
10228 (cond_exec (match_dup 7)
10229 (set (match_dup 0) (match_dup 4)))]
10230 "
10231 {
3754d046 10232 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8fa3ba89 10233 operands[2], operands[3]);
10234 enum rtx_code rc = GET_CODE (operands[1]);
10235
bd5b4116 10236 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10237 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10238 if (mode == CCFPmode || mode == CCFPEmode)
10239 rc = reverse_condition_maybe_unordered (rc);
10240 else
10241 rc = reverse_condition (rc);
10242
10243 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
10244 }"
10245)
10246
10247(define_split
10248 [(set (match_operand:SI 0 "s_register_operand" "")
10249 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10250 [(match_operand 2 "" "") (match_operand 3 "" "")])
10251 (match_operand 4 "" "")
10252 (match_dup 0)))
bd5b4116 10253 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10254 "TARGET_ARM && reload_completed"
8fa3ba89 10255 [(set (match_dup 5) (match_dup 6))
10256 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
10257 (set (match_dup 0) (match_dup 4)))]
10258 "
10259 {
3754d046 10260 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8fa3ba89 10261 operands[2], operands[3]);
10262
bd5b4116 10263 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10264 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10265 }"
10266)
10267
10268(define_split
10269 [(set (match_operand:SI 0 "s_register_operand" "")
10270 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9c08d1fa 10271 [(match_operand 2 "" "") (match_operand 3 "" "")])
10272 (match_operand 4 "" "")
10273 (match_operand 5 "" "")))
bd5b4116 10274 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10275 "TARGET_ARM && reload_completed"
8fa3ba89 10276 [(set (match_dup 6) (match_dup 7))
10277 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10278 (set (match_dup 0) (match_dup 4)))
10279 (cond_exec (match_dup 8)
10280 (set (match_dup 0) (match_dup 5)))]
10281 "
10282 {
3754d046 10283 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8fa3ba89 10284 operands[2], operands[3]);
10285 enum rtx_code rc = GET_CODE (operands[1]);
10286
bd5b4116 10287 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10288 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10289 if (mode == CCFPmode || mode == CCFPEmode)
10290 rc = reverse_condition_maybe_unordered (rc);
10291 else
10292 rc = reverse_condition (rc);
10293
10294 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10295 }"
10296)
10297
cffb2a26 10298(define_split
10299 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 10300 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
cffb2a26 10301 [(match_operand:SI 2 "s_register_operand" "")
10302 (match_operand:SI 3 "arm_add_operand" "")])
10303 (match_operand:SI 4 "arm_rhs_operand" "")
10304 (not:SI
10305 (match_operand:SI 5 "s_register_operand" ""))))
bd5b4116 10306 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10307 "TARGET_ARM && reload_completed"
cffb2a26 10308 [(set (match_dup 6) (match_dup 7))
f6c53574 10309 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10310 (set (match_dup 0) (match_dup 4)))
10311 (cond_exec (match_dup 8)
10312 (set (match_dup 0) (not:SI (match_dup 5))))]
cffb2a26 10313 "
215b30b3 10314 {
3754d046 10315 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
215b30b3 10316 operands[2], operands[3]);
f6c53574 10317 enum rtx_code rc = GET_CODE (operands[1]);
cffb2a26 10318
bd5b4116 10319 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
1a83b3ff 10320 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
f6c53574 10321 if (mode == CCFPmode || mode == CCFPEmode)
10322 rc = reverse_condition_maybe_unordered (rc);
10323 else
10324 rc = reverse_condition (rc);
10325
10326 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
215b30b3 10327 }"
10328)
cffb2a26 10329
10330(define_insn "*cond_move_not"
10331 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10332 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
cffb2a26 10333 [(match_operand 3 "cc_register" "") (const_int 0)])
10334 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10335 (not:SI
10336 (match_operand:SI 2 "s_register_operand" "r,r"))))]
10337 "TARGET_ARM"
10338 "@
10339 mvn%D4\\t%0, %2
10340 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
0d66636f 10341 [(set_attr "conds" "use")
1b7da4ac 10342 (set_attr "type" "mvn_reg,multiple")
0d66636f 10343 (set_attr "length" "4,8")]
10344)
cffb2a26 10345
9c08d1fa 10346;; The next two patterns occur when an AND operation is followed by a
10347;; scc insn sequence
10348
f7fbdd4a 10349(define_insn "*sign_extract_onebit"
9c08d1fa 10350 [(set (match_operand:SI 0 "s_register_operand" "=r")
10351 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10352 (const_int 1)
ed750274 10353 (match_operand:SI 2 "const_int_operand" "n")))
10354 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10355 "TARGET_ARM"
9c08d1fa 10356 "*
0d66636f 10357 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10358 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
10359 return \"mvnne\\t%0, #0\";
10360 "
10361 [(set_attr "conds" "clob")
1b7da4ac 10362 (set_attr "length" "8")
10363 (set_attr "type" "multiple")]
0d66636f 10364)
9c08d1fa 10365
f7fbdd4a 10366(define_insn "*not_signextract_onebit"
9c08d1fa 10367 [(set (match_operand:SI 0 "s_register_operand" "=r")
10368 (not:SI
10369 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10370 (const_int 1)
ed750274 10371 (match_operand:SI 2 "const_int_operand" "n"))))
10372 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10373 "TARGET_ARM"
9c08d1fa 10374 "*
0d66636f 10375 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10376 output_asm_insn (\"tst\\t%1, %2\", operands);
10377 output_asm_insn (\"mvneq\\t%0, #0\", operands);
10378 return \"movne\\t%0, #0\";
10379 "
10380 [(set_attr "conds" "clob")
1b7da4ac 10381 (set_attr "length" "12")
10382 (set_attr "type" "multiple")]
0d66636f 10383)
25f905c2 10384;; ??? The above patterns need auditing for Thumb-2
87b22bf7 10385
0d66636f 10386;; Push multiple registers to the stack. Registers are in parallel (use ...)
10387;; expressions. For simplicity, the first register is also in the unspec
10388;; part.
08508cbf 10389;; To avoid the usage of GNU extension, the length attribute is computed
10390;; in a C function arm_attr_length_push_multi.
f7fbdd4a 10391(define_insn "*push_multi"
87b22bf7 10392 [(match_parallel 2 "multi_register_push"
7571d3f7 10393 [(set (match_operand:BLK 0 "push_mult_memory_operand" "")
3cc80a30 10394 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "")]
e1159bbe 10395 UNSPEC_PUSH_MULT))])]
7571d3f7 10396 ""
87b22bf7 10397 "*
215b30b3 10398 {
10399 int num_saves = XVECLEN (operands[2], 0);
ed593f11 10400
215b30b3 10401 /* For the StrongARM at least it is faster to
25f905c2 10402 use STR to store only a single register.
542d5028 10403 In Thumb mode always use push, and the assembler will pick
10404 something appropriate. */
25f905c2 10405 if (num_saves == 1 && TARGET_ARM)
61309563 10406 output_asm_insn (\"str%?\\t%1, [%m0, #-4]!\", operands);
215b30b3 10407 else
10408 {
10409 int i;
10410 char pattern[100];
ed593f11 10411
25f905c2 10412 if (TARGET_ARM)
61309563 10413 strcpy (pattern, \"stm%(fd%)\\t%m0!, {%1\");
10414 else if (TARGET_THUMB2)
10415 strcpy (pattern, \"push%?\\t{%1\");
25f905c2 10416 else
10417 strcpy (pattern, \"push\\t{%1\");
215b30b3 10418
6079f055 10419 for (i = 1; i < num_saves; i++)
215b30b3 10420 {
10421 strcat (pattern, \", %|\");
10422 strcat (pattern,
10423 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
10424 }
10425
10426 strcat (pattern, \"}\");
10427 output_asm_insn (pattern, operands);
10428 }
10429
10430 return \"\";
10431 }"
a6864a24 10432 [(set_attr "type" "store4")
10433 (set (attr "length")
08508cbf 10434 (symbol_ref "arm_attr_length_push_multi (operands[2], operands[1])"))]
215b30b3 10435)
f7fbdd4a 10436
4c58c898 10437(define_insn "stack_tie"
10438 [(set (mem:BLK (scratch))
aaa37ad6 10439 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "rk")
10440 (match_operand:SI 1 "s_register_operand" "rk")]
4c58c898 10441 UNSPEC_PRLG_STK))]
10442 ""
10443 ""
1b7da4ac 10444 [(set_attr "length" "0")
10445 (set_attr "type" "block")]
4c58c898 10446)
10447
426be8c5 10448;; Pop (as used in epilogue RTL)
10449;;
10450(define_insn "*load_multiple_with_writeback"
10451 [(match_parallel 0 "load_multiple_operation"
10452 [(set (match_operand:SI 1 "s_register_operand" "+rk")
10453 (plus:SI (match_dup 1)
809003b3 10454 (match_operand:SI 2 "const_int_I_operand" "I")))
426be8c5 10455 (set (match_operand:SI 3 "s_register_operand" "=rk")
10456 (mem:SI (match_dup 1)))
10457 ])]
10458 "TARGET_32BIT && (reload_in_progress || reload_completed)"
10459 "*
10460 {
10461 arm_output_multireg_pop (operands, /*return_pc=*/false,
10462 /*cond=*/const_true_rtx,
10463 /*reverse=*/false,
10464 /*update=*/true);
10465 return \"\";
10466 }
10467 "
10468 [(set_attr "type" "load4")
10469 (set_attr "predicable" "yes")]
10470)
10471
10472;; Pop with return (as used in epilogue RTL)
10473;;
10474;; This instruction is generated when the registers are popped at the end of
10475;; epilogue. Here, instead of popping the value into LR and then generating
10476;; jump to LR, value is popped into PC directly. Hence, the pattern is combined
10477;; with (return).
10478(define_insn "*pop_multiple_with_writeback_and_return"
10479 [(match_parallel 0 "pop_multiple_return"
10480 [(return)
10481 (set (match_operand:SI 1 "s_register_operand" "+rk")
10482 (plus:SI (match_dup 1)
809003b3 10483 (match_operand:SI 2 "const_int_I_operand" "I")))
426be8c5 10484 (set (match_operand:SI 3 "s_register_operand" "=rk")
10485 (mem:SI (match_dup 1)))
10486 ])]
10487 "TARGET_32BIT && (reload_in_progress || reload_completed)"
10488 "*
10489 {
10490 arm_output_multireg_pop (operands, /*return_pc=*/true,
10491 /*cond=*/const_true_rtx,
10492 /*reverse=*/false,
10493 /*update=*/true);
10494 return \"\";
10495 }
10496 "
10497 [(set_attr "type" "load4")
10498 (set_attr "predicable" "yes")]
10499)
10500
10501(define_insn "*pop_multiple_with_return"
10502 [(match_parallel 0 "pop_multiple_return"
10503 [(return)
10504 (set (match_operand:SI 2 "s_register_operand" "=rk")
10505 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
10506 ])]
10507 "TARGET_32BIT && (reload_in_progress || reload_completed)"
10508 "*
10509 {
10510 arm_output_multireg_pop (operands, /*return_pc=*/true,
10511 /*cond=*/const_true_rtx,
10512 /*reverse=*/false,
10513 /*update=*/false);
10514 return \"\";
10515 }
10516 "
10517 [(set_attr "type" "load4")
10518 (set_attr "predicable" "yes")]
10519)
10520
10521;; Load into PC and return
10522(define_insn "*ldr_with_return"
10523 [(return)
10524 (set (reg:SI PC_REGNUM)
10525 (mem:SI (post_inc:SI (match_operand:SI 0 "s_register_operand" "+rk"))))]
10526 "TARGET_32BIT && (reload_in_progress || reload_completed)"
10527 "ldr%?\t%|pc, [%0], #4"
10528 [(set_attr "type" "load1")
10529 (set_attr "predicable" "yes")]
10530)
1a0b0f12 10531;; Pop for floating point registers (as used in epilogue RTL)
10532(define_insn "*vfp_pop_multiple_with_writeback"
10533 [(match_parallel 0 "pop_multiple_fp"
10534 [(set (match_operand:SI 1 "s_register_operand" "+rk")
10535 (plus:SI (match_dup 1)
809003b3 10536 (match_operand:SI 2 "const_int_I_operand" "I")))
2f2163a4 10537 (set (match_operand:DF 3 "vfp_hard_register_operand" "")
1a0b0f12 10538 (mem:DF (match_dup 1)))])]
10539 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
10540 "*
10541 {
10542 int num_regs = XVECLEN (operands[0], 0);
10543 char pattern[100];
10544 rtx op_list[2];
b34d8dac 10545 strcpy (pattern, \"vldm\\t\");
1a0b0f12 10546 strcat (pattern, reg_names[REGNO (SET_DEST (XVECEXP (operands[0], 0, 0)))]);
10547 strcat (pattern, \"!, {\");
10548 op_list[0] = XEXP (XVECEXP (operands[0], 0, 1), 0);
10549 strcat (pattern, \"%P0\");
10550 if ((num_regs - 1) > 1)
10551 {
10552 strcat (pattern, \"-%P1\");
10553 op_list [1] = XEXP (XVECEXP (operands[0], 0, num_regs - 1), 0);
10554 }
10555
10556 strcat (pattern, \"}\");
10557 output_asm_insn (pattern, op_list);
10558 return \"\";
10559 }
10560 "
10561 [(set_attr "type" "load4")
10562 (set_attr "conds" "unconditional")
10563 (set_attr "predicable" "no")]
10564)
10565
f7fbdd4a 10566;; Special patterns for dealing with the constant pool
10567
cffb2a26 10568(define_insn "align_4"
e1159bbe 10569 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
cffb2a26 10570 "TARGET_EITHER"
f7fbdd4a 10571 "*
cffb2a26 10572 assemble_align (32);
f7fbdd4a 10573 return \"\";
cffb2a26 10574 "
1b7da4ac 10575 [(set_attr "type" "no_insn")]
cffb2a26 10576)
f7fbdd4a 10577
755eb2b4 10578(define_insn "align_8"
10579 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
f9273c43 10580 "TARGET_EITHER"
755eb2b4 10581 "*
10582 assemble_align (64);
10583 return \"\";
10584 "
1b7da4ac 10585 [(set_attr "type" "no_insn")]
755eb2b4 10586)
10587
cffb2a26 10588(define_insn "consttable_end"
e1159bbe 10589 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
cffb2a26 10590 "TARGET_EITHER"
f7fbdd4a 10591 "*
cffb2a26 10592 making_const_table = FALSE;
f7fbdd4a 10593 return \"\";
cffb2a26 10594 "
1b7da4ac 10595 [(set_attr "type" "no_insn")]
cffb2a26 10596)
f7fbdd4a 10597
0e207eb8 10598(define_insn "consttable_1"
10599 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
10600 "TARGET_EITHER"
10601 "*
10602 making_const_table = TRUE;
10603 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
10604 assemble_zeros (3);
10605 return \"\";
10606 "
10607 [(set_attr "length" "4")
10608 (set_attr "type" "no_insn")]
10609)
10610
10611(define_insn "consttable_2"
10612 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
10613 "TARGET_EITHER"
10614 "*
10615 {
10616 rtx x = operands[0];
10617 making_const_table = TRUE;
10618 switch (GET_MODE_CLASS (GET_MODE (x)))
10619 {
10620 case MODE_FLOAT:
10621 arm_emit_fp16_const (x);
10622 break;
10623 default:
10624 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
10625 assemble_zeros (2);
10626 break;
10627 }
10628 return \"\";
10629 }"
10630 [(set_attr "length" "4")
10631 (set_attr "type" "no_insn")]
10632)
10633
cffb2a26 10634(define_insn "consttable_4"
e1159bbe 10635 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
cffb2a26 10636 "TARGET_EITHER"
10637 "*
10638 {
9b8516be 10639 rtx x = operands[0];
cffb2a26 10640 making_const_table = TRUE;
9b8516be 10641 switch (GET_MODE_CLASS (GET_MODE (x)))
cffb2a26 10642 {
10643 case MODE_FLOAT:
0e207eb8 10644 {
10645 REAL_VALUE_TYPE r;
10646 REAL_VALUE_FROM_CONST_DOUBLE (r, x);
10647 assemble_real (r, GET_MODE (x), BITS_PER_WORD);
10648 break;
10649 }
cffb2a26 10650 default:
7b04c5d5 10651 /* XXX: Sometimes gcc does something really dumb and ends up with
10652 a HIGH in a constant pool entry, usually because it's trying to
10653 load into a VFP register. We know this will always be used in
10654 combination with a LO_SUM which ignores the high bits, so just
10655 strip off the HIGH. */
10656 if (GET_CODE (x) == HIGH)
10657 x = XEXP (x, 0);
9b8516be 10658 assemble_integer (x, 4, BITS_PER_WORD, 1);
10659 mark_symbol_refs_as_used (x);
cffb2a26 10660 break;
10661 }
10662 return \"\";
10663 }"
1b7da4ac 10664 [(set_attr "length" "4")
10665 (set_attr "type" "no_insn")]
cffb2a26 10666)
10667
10668(define_insn "consttable_8"
e1159bbe 10669 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
cffb2a26 10670 "TARGET_EITHER"
10671 "*
10672 {
10673 making_const_table = TRUE;
10674 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10675 {
10676 case MODE_FLOAT:
10677 {
badfe841 10678 REAL_VALUE_TYPE r;
10679 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10680 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
cffb2a26 10681 break;
10682 }
10683 default:
09d688ff 10684 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
cffb2a26 10685 break;
10686 }
10687 return \"\";
10688 }"
1b7da4ac 10689 [(set_attr "length" "8")
10690 (set_attr "type" "no_insn")]
cffb2a26 10691)
10692
d98a3884 10693(define_insn "consttable_16"
10694 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_16)]
10695 "TARGET_EITHER"
10696 "*
10697 {
10698 making_const_table = TRUE;
10699 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10700 {
10701 case MODE_FLOAT:
10702 {
10703 REAL_VALUE_TYPE r;
10704 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10705 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10706 break;
10707 }
10708 default:
10709 assemble_integer (operands[0], 16, BITS_PER_WORD, 1);
10710 break;
10711 }
10712 return \"\";
10713 }"
1b7da4ac 10714 [(set_attr "length" "16")
10715 (set_attr "type" "no_insn")]
d98a3884 10716)
10717
331beb1a 10718;; V5 Instructions,
10719
8f4be2be 10720(define_insn "clzsi2"
10721 [(set (match_operand:SI 0 "s_register_operand" "=r")
10722 (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 10723 "TARGET_32BIT && arm_arch5"
ee7cbe0e 10724 "clz%?\\t%0, %1"
bcaec148 10725 [(set_attr "predicable" "yes")
4a510717 10726 (set_attr "predicable_short_it" "no")
bebe9bbb 10727 (set_attr "type" "clz")])
331beb1a 10728
099ad98b 10729(define_insn "rbitsi2"
10730 [(set (match_operand:SI 0 "s_register_operand" "=r")
10731 (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")] UNSPEC_RBIT))]
10732 "TARGET_32BIT && arm_arch_thumb2"
10733 "rbit%?\\t%0, %1"
10734 [(set_attr "predicable" "yes")
4a510717 10735 (set_attr "predicable_short_it" "no")
bebe9bbb 10736 (set_attr "type" "clz")])
099ad98b 10737
10738(define_expand "ctzsi2"
10739 [(set (match_operand:SI 0 "s_register_operand" "")
10740 (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
10741 "TARGET_32BIT && arm_arch_thumb2"
10742 "
30191172 10743 {
10744 rtx tmp = gen_reg_rtx (SImode);
10745 emit_insn (gen_rbitsi2 (tmp, operands[1]));
10746 emit_insn (gen_clzsi2 (operands[0], tmp));
10747 }
099ad98b 10748 DONE;
10749 "
10750)
10751
e1159bbe 10752;; V5E instructions.
331beb1a 10753
10754(define_insn "prefetch"
f4e79814 10755 [(prefetch (match_operand:SI 0 "address_operand" "p")
10756 (match_operand:SI 1 "" "")
10757 (match_operand:SI 2 "" ""))]
25f905c2 10758 "TARGET_32BIT && arm_arch5e"
1b7da4ac 10759 "pld\\t%a0"
10760 [(set_attr "type" "load1")]
10761)
331beb1a 10762
0d66636f 10763;; General predication pattern
10764
10765(define_cond_exec
10766 [(match_operator 0 "arm_comparison_operator"
10767 [(match_operand 1 "cc_register" "")
10768 (const_int 0)])]
25f905c2 10769 "TARGET_32BIT"
0d66636f 10770 ""
c7a58118 10771[(set_attr "predicated" "yes")]
0d66636f 10772)
10773
fb94f18b 10774(define_insn "force_register_use"
10775 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_REGISTER_USE)]
063a05c7 10776 ""
fb94f18b 10777 "%@ %0 needed"
1b7da4ac 10778 [(set_attr "length" "0")
10779 (set_attr "type" "no_insn")]
063a05c7 10780)
7db9af5d 10781
4c44712e 10782
10783;; Patterns for exception handling
10784
10785(define_expand "eh_return"
10786 [(use (match_operand 0 "general_operand" ""))]
10787 "TARGET_EITHER"
10788 "
10789 {
25f905c2 10790 if (TARGET_32BIT)
4c44712e 10791 emit_insn (gen_arm_eh_return (operands[0]));
10792 else
10793 emit_insn (gen_thumb_eh_return (operands[0]));
10794 DONE;
10795 }"
10796)
10797
10798;; We can't expand this before we know where the link register is stored.
10799(define_insn_and_split "arm_eh_return"
10800 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
10801 VUNSPEC_EH_RETURN)
10802 (clobber (match_scratch:SI 1 "=&r"))]
10803 "TARGET_ARM"
10804 "#"
10805 "&& reload_completed"
10806 [(const_int 0)]
10807 "
10808 {
10809 arm_set_return_address (operands[0], operands[1]);
10810 DONE;
10811 }"
10812)
10813
f655717d 10814\f
10815;; TLS support
10816
10817(define_insn "load_tp_hard"
10818 [(set (match_operand:SI 0 "register_operand" "=r")
10819 (unspec:SI [(const_int 0)] UNSPEC_TLS))]
10820 "TARGET_HARD_TP"
10821 "mrc%?\\tp15, 0, %0, c13, c0, 3\\t@ load_tp_hard"
1b7da4ac 10822 [(set_attr "predicable" "yes")
4b5d7374 10823 (set_attr "type" "mrs")]
f655717d 10824)
10825
10826;; Doesn't clobber R1-R3. Must use r0 for the first operand.
10827(define_insn "load_tp_soft"
10828 [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
10829 (clobber (reg:SI LR_REGNUM))
10830 (clobber (reg:SI IP_REGNUM))
10831 (clobber (reg:CC CC_REGNUM))]
10832 "TARGET_SOFT_TP"
10833 "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
1b7da4ac 10834 [(set_attr "conds" "clob")
10835 (set_attr "type" "branch")]
f655717d 10836)
10837
f41e4452 10838;; tls descriptor call
10839(define_insn "tlscall"
10840 [(set (reg:SI R0_REGNUM)
10841 (unspec:SI [(reg:SI R0_REGNUM)
10842 (match_operand:SI 0 "" "X")
10843 (match_operand 1 "" "")] UNSPEC_TLS))
10844 (clobber (reg:SI R1_REGNUM))
10845 (clobber (reg:SI LR_REGNUM))
10846 (clobber (reg:SI CC_REGNUM))]
10847 "TARGET_GNU2_TLS"
10848 {
10849 targetm.asm_out.internal_label (asm_out_file, "LPIC",
10850 INTVAL (operands[1]));
10851 return "bl\\t%c0(tlscall)";
10852 }
10853 [(set_attr "conds" "clob")
1b7da4ac 10854 (set_attr "length" "4")
10855 (set_attr "type" "branch")]
f41e4452 10856)
10857
1fe0edab 10858;; For thread pointer builtin
10859(define_expand "get_thread_pointersi"
10860 [(match_operand:SI 0 "s_register_operand" "=r")]
10861 ""
10862 "
10863 {
10864 arm_load_tp (operands[0]);
10865 DONE;
10866 }")
10867
f41e4452 10868;;
10869
aabe09ac 10870;; We only care about the lower 16 bits of the constant
10871;; being inserted into the upper 16 bits of the register.
eca5c984 10872(define_insn "*arm_movtas_ze"
10873 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
10874 (const_int 16)
10875 (const_int 16))
10876 (match_operand:SI 1 "const_int_operand" ""))]
181ab277 10877 "arm_arch_thumb2"
aabe09ac 10878 "movt%?\t%0, %L1"
eca5c984 10879 [(set_attr "predicable" "yes")
7c36fe71 10880 (set_attr "predicable_short_it" "no")
1b7da4ac 10881 (set_attr "length" "4")
10882 (set_attr "type" "mov_imm")]
eca5c984 10883)
10884
c0fc3696 10885(define_insn "*arm_rev"
a486b499 10886 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
10887 (bswap:SI (match_operand:SI 1 "s_register_operand" "l,l,r")))]
10888 "arm_arch6"
10889 "@
10890 rev\t%0, %1
10891 rev%?\t%0, %1
10892 rev%?\t%0, %1"
10893 [(set_attr "arch" "t1,t2,32")
1b7da4ac 10894 (set_attr "length" "2,2,4")
4a510717 10895 (set_attr "predicable" "no,yes,yes")
10896 (set_attr "predicable_short_it" "no")
1b7da4ac 10897 (set_attr "type" "rev")]
ff82f757 10898)
10899
10900(define_expand "arm_legacy_rev"
10901 [(set (match_operand:SI 2 "s_register_operand" "")
10902 (xor:SI (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
10903 (const_int 16))
10904 (match_dup 1)))
10905 (set (match_dup 2)
10906 (lshiftrt:SI (match_dup 2)
10907 (const_int 8)))
10908 (set (match_operand:SI 3 "s_register_operand" "")
10909 (rotatert:SI (match_dup 1)
10910 (const_int 8)))
10911 (set (match_dup 2)
10912 (and:SI (match_dup 2)
10913 (const_int -65281)))
10914 (set (match_operand:SI 0 "s_register_operand" "")
10915 (xor:SI (match_dup 3)
10916 (match_dup 2)))]
10917 "TARGET_32BIT"
10918 ""
10919)
10920
10921;; Reuse temporaries to keep register pressure down.
10922(define_expand "thumb_legacy_rev"
10923 [(set (match_operand:SI 2 "s_register_operand" "")
10924 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
10925 (const_int 24)))
10926 (set (match_operand:SI 3 "s_register_operand" "")
10927 (lshiftrt:SI (match_dup 1)
10928 (const_int 24)))
10929 (set (match_dup 3)
10930 (ior:SI (match_dup 3)
10931 (match_dup 2)))
10932 (set (match_operand:SI 4 "s_register_operand" "")
10933 (const_int 16))
10934 (set (match_operand:SI 5 "s_register_operand" "")
10935 (rotatert:SI (match_dup 1)
10936 (match_dup 4)))
10937 (set (match_dup 2)
10938 (ashift:SI (match_dup 5)
10939 (const_int 24)))
10940 (set (match_dup 5)
10941 (lshiftrt:SI (match_dup 5)
10942 (const_int 24)))
10943 (set (match_dup 5)
10944 (ior:SI (match_dup 5)
10945 (match_dup 2)))
10946 (set (match_dup 5)
10947 (rotatert:SI (match_dup 5)
10948 (match_dup 4)))
10949 (set (match_operand:SI 0 "s_register_operand" "")
10950 (ior:SI (match_dup 5)
10951 (match_dup 3)))]
10952 "TARGET_THUMB"
10953 ""
10954)
10955
10956(define_expand "bswapsi2"
10957 [(set (match_operand:SI 0 "s_register_operand" "=r")
10958 (bswap:SI (match_operand:SI 1 "s_register_operand" "r")))]
8d1af482 10959"TARGET_EITHER && (arm_arch6 || !optimize_size)"
ff82f757 10960"
8d1af482 10961 if (!arm_arch6)
10962 {
10963 rtx op2 = gen_reg_rtx (SImode);
10964 rtx op3 = gen_reg_rtx (SImode);
ff82f757 10965
8d1af482 10966 if (TARGET_THUMB)
10967 {
10968 rtx op4 = gen_reg_rtx (SImode);
10969 rtx op5 = gen_reg_rtx (SImode);
ff82f757 10970
8d1af482 10971 emit_insn (gen_thumb_legacy_rev (operands[0], operands[1],
10972 op2, op3, op4, op5));
10973 }
10974 else
10975 {
10976 emit_insn (gen_arm_legacy_rev (operands[0], operands[1],
10977 op2, op3));
10978 }
ff82f757 10979
8d1af482 10980 DONE;
10981 }
ff82f757 10982 "
10983)
10984
a486b499 10985;; bswap16 patterns: use revsh and rev16 instructions for the signed
10986;; and unsigned variants, respectively. For rev16, expose
10987;; byte-swapping in the lower 16 bits only.
10988(define_insn "*arm_revsh"
10989 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
10990 (sign_extend:SI (bswap:HI (match_operand:HI 1 "s_register_operand" "l,l,r"))))]
10991 "arm_arch6"
10992 "@
10993 revsh\t%0, %1
10994 revsh%?\t%0, %1
10995 revsh%?\t%0, %1"
10996 [(set_attr "arch" "t1,t2,32")
1b7da4ac 10997 (set_attr "length" "2,2,4")
10998 (set_attr "type" "rev")]
a486b499 10999)
11000
11001(define_insn "*arm_rev16"
11002 [(set (match_operand:HI 0 "s_register_operand" "=l,l,r")
11003 (bswap:HI (match_operand:HI 1 "s_register_operand" "l,l,r")))]
11004 "arm_arch6"
11005 "@
11006 rev16\t%0, %1
11007 rev16%?\t%0, %1
11008 rev16%?\t%0, %1"
11009 [(set_attr "arch" "t1,t2,32")
1b7da4ac 11010 (set_attr "length" "2,2,4")
11011 (set_attr "type" "rev")]
09f69e55 11012)
11013
11014;; There are no canonicalisation rules for the position of the lshiftrt, ashift
11015;; operations within an IOR/AND RTX, therefore we have two patterns matching
11016;; each valid permutation.
11017
11018(define_insn "arm_rev16si2"
11019 [(set (match_operand:SI 0 "register_operand" "=l,l,r")
11020 (ior:SI (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "l,l,r")
11021 (const_int 8))
11022 (match_operand:SI 3 "const_int_operand" "n,n,n"))
11023 (and:SI (lshiftrt:SI (match_dup 1)
11024 (const_int 8))
11025 (match_operand:SI 2 "const_int_operand" "n,n,n"))))]
11026 "arm_arch6
11027 && aarch_rev16_shleft_mask_imm_p (operands[3], SImode)
11028 && aarch_rev16_shright_mask_imm_p (operands[2], SImode)"
11029 "rev16\\t%0, %1"
11030 [(set_attr "arch" "t1,t2,32")
11031 (set_attr "length" "2,2,4")
11032 (set_attr "type" "rev")]
11033)
11034
11035(define_insn "arm_rev16si2_alt"
11036 [(set (match_operand:SI 0 "register_operand" "=l,l,r")
11037 (ior:SI (and:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,l,r")
11038 (const_int 8))
11039 (match_operand:SI 2 "const_int_operand" "n,n,n"))
11040 (and:SI (ashift:SI (match_dup 1)
11041 (const_int 8))
11042 (match_operand:SI 3 "const_int_operand" "n,n,n"))))]
11043 "arm_arch6
11044 && aarch_rev16_shleft_mask_imm_p (operands[3], SImode)
11045 && aarch_rev16_shright_mask_imm_p (operands[2], SImode)"
11046 "rev16\\t%0, %1"
11047 [(set_attr "arch" "t1,t2,32")
11048 (set_attr "length" "2,2,4")
11049 (set_attr "type" "rev")]
a486b499 11050)
11051
11052(define_expand "bswaphi2"
11053 [(set (match_operand:HI 0 "s_register_operand" "=r")
11054 (bswap:HI (match_operand:HI 1 "s_register_operand" "r")))]
11055"arm_arch6"
11056""
11057)
11058
1653cf17 11059;; Patterns for LDRD/STRD in Thumb2 mode
11060
11061(define_insn "*thumb2_ldrd"
11062 [(set (match_operand:SI 0 "s_register_operand" "=r")
11063 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
11064 (match_operand:SI 2 "ldrd_strd_offset_operand" "Do"))))
11065 (set (match_operand:SI 3 "s_register_operand" "=r")
11066 (mem:SI (plus:SI (match_dup 1)
11067 (match_operand:SI 4 "const_int_operand" ""))))]
11068 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11069 && current_tune->prefer_ldrd_strd
11070 && ((INTVAL (operands[2]) + 4) == INTVAL (operands[4]))
11071 && (operands_ok_ldrd_strd (operands[0], operands[3],
11072 operands[1], INTVAL (operands[2]),
11073 false, true))"
11074 "ldrd%?\t%0, %3, [%1, %2]"
11075 [(set_attr "type" "load2")
d952d547 11076 (set_attr "predicable" "yes")
11077 (set_attr "predicable_short_it" "no")])
1653cf17 11078
11079(define_insn "*thumb2_ldrd_base"
11080 [(set (match_operand:SI 0 "s_register_operand" "=r")
11081 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
11082 (set (match_operand:SI 2 "s_register_operand" "=r")
11083 (mem:SI (plus:SI (match_dup 1)
11084 (const_int 4))))]
11085 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11086 && current_tune->prefer_ldrd_strd
11087 && (operands_ok_ldrd_strd (operands[0], operands[2],
11088 operands[1], 0, false, true))"
11089 "ldrd%?\t%0, %2, [%1]"
11090 [(set_attr "type" "load2")
d952d547 11091 (set_attr "predicable" "yes")
11092 (set_attr "predicable_short_it" "no")])
1653cf17 11093
11094(define_insn "*thumb2_ldrd_base_neg"
11095 [(set (match_operand:SI 0 "s_register_operand" "=r")
11096 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
11097 (const_int -4))))
11098 (set (match_operand:SI 2 "s_register_operand" "=r")
11099 (mem:SI (match_dup 1)))]
11100 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11101 && current_tune->prefer_ldrd_strd
11102 && (operands_ok_ldrd_strd (operands[0], operands[2],
11103 operands[1], -4, false, true))"
11104 "ldrd%?\t%0, %2, [%1, #-4]"
11105 [(set_attr "type" "load2")
d952d547 11106 (set_attr "predicable" "yes")
11107 (set_attr "predicable_short_it" "no")])
1653cf17 11108
11109(define_insn "*thumb2_strd"
11110 [(set (mem:SI (plus:SI (match_operand:SI 0 "s_register_operand" "rk")
11111 (match_operand:SI 1 "ldrd_strd_offset_operand" "Do")))
11112 (match_operand:SI 2 "s_register_operand" "r"))
11113 (set (mem:SI (plus:SI (match_dup 0)
11114 (match_operand:SI 3 "const_int_operand" "")))
11115 (match_operand:SI 4 "s_register_operand" "r"))]
11116 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11117 && current_tune->prefer_ldrd_strd
11118 && ((INTVAL (operands[1]) + 4) == INTVAL (operands[3]))
11119 && (operands_ok_ldrd_strd (operands[2], operands[4],
11120 operands[0], INTVAL (operands[1]),
11121 false, false))"
11122 "strd%?\t%2, %4, [%0, %1]"
11123 [(set_attr "type" "store2")
d952d547 11124 (set_attr "predicable" "yes")
11125 (set_attr "predicable_short_it" "no")])
1653cf17 11126
11127(define_insn "*thumb2_strd_base"
11128 [(set (mem:SI (match_operand:SI 0 "s_register_operand" "rk"))
11129 (match_operand:SI 1 "s_register_operand" "r"))
11130 (set (mem:SI (plus:SI (match_dup 0)
11131 (const_int 4)))
11132 (match_operand:SI 2 "s_register_operand" "r"))]
11133 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11134 && current_tune->prefer_ldrd_strd
11135 && (operands_ok_ldrd_strd (operands[1], operands[2],
11136 operands[0], 0, false, false))"
11137 "strd%?\t%1, %2, [%0]"
11138 [(set_attr "type" "store2")
d952d547 11139 (set_attr "predicable" "yes")
11140 (set_attr "predicable_short_it" "no")])
1653cf17 11141
11142(define_insn "*thumb2_strd_base_neg"
11143 [(set (mem:SI (plus:SI (match_operand:SI 0 "s_register_operand" "rk")
11144 (const_int -4)))
11145 (match_operand:SI 1 "s_register_operand" "r"))
11146 (set (mem:SI (match_dup 0))
11147 (match_operand:SI 2 "s_register_operand" "r"))]
11148 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11149 && current_tune->prefer_ldrd_strd
11150 && (operands_ok_ldrd_strd (operands[1], operands[2],
11151 operands[0], -4, false, false))"
11152 "strd%?\t%1, %2, [%0, #-4]"
11153 [(set_attr "type" "store2")
d952d547 11154 (set_attr "predicable" "yes")
11155 (set_attr "predicable_short_it" "no")])
1653cf17 11156
2a0c73f2 11157;; ARMv8 CRC32 instructions.
11158(define_insn "<crc_variant>"
11159 [(set (match_operand:SI 0 "s_register_operand" "=r")
11160 (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")
11161 (match_operand:<crc_mode> 2 "s_register_operand" "r")]
11162 CRC))]
11163 "TARGET_CRC32"
11164 "<crc_variant>\\t%0, %1, %2"
11165 [(set_attr "type" "crc")
11166 (set_attr "conds" "unconditional")]
11167)
1653cf17 11168
353cf59a 11169;; Load the load/store double peephole optimizations.
11170(include "ldrdstrd.md")
11171
320ea44d 11172;; Load the load/store multiple patterns
11173(include "ldmstm.md")
426be8c5 11174
11175;; Patterns in ldmstm.md don't cover more than 4 registers. This pattern covers
11176;; large lists without explicit writeback generated for APCS_FRAME epilogue.
11177(define_insn "*load_multiple"
11178 [(match_parallel 0 "load_multiple_operation"
11179 [(set (match_operand:SI 2 "s_register_operand" "=rk")
11180 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
11181 ])]
11182 "TARGET_32BIT"
11183 "*
11184 {
11185 arm_output_multireg_pop (operands, /*return_pc=*/false,
11186 /*cond=*/const_true_rtx,
11187 /*reverse=*/false,
11188 /*update=*/false);
11189 return \"\";
11190 }
11191 "
11192 [(set_attr "predicable" "yes")]
11193)
11194
d98a3884 11195;; Vector bits common to IWMMXT and Neon
11196(include "vec-common.md")
755eb2b4 11197;; Load the Intel Wireless Multimedia Extension patterns
11198(include "iwmmxt.md")
a2cd141b 11199;; Load the VFP co-processor patterns
11200(include "vfp.md")
bc360af8 11201;; Thumb-1 patterns
11202(include "thumb1.md")
25f905c2 11203;; Thumb-2 patterns
11204(include "thumb2.md")
d98a3884 11205;; Neon patterns
11206(include "neon.md")
e84fdf6e 11207;; Crypto patterns
11208(include "crypto.md")
06df6b17 11209;; Synchronization Primitives
11210(include "sync.md")
bbbe4599 11211;; Fixed-point patterns
11212(include "arm-fixed.md")