]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/arm/arm.md
Update copyright years.
[thirdparty/gcc.git] / gcc / config / arm / arm.md
CommitLineData
129a2fe4 1;;- Machine description for ARM for GNU compiler
f1717362 2;; Copyright (C) 1991-2016 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
9c08d1fa 25\f
e1159bbe 26;;---------------------------------------------------------------------------
27;; Constants
28
bffbb863 29;; Register numbers -- All machine registers should be defined here
e1159bbe 30(define_constants
bffbb863 31 [(R0_REGNUM 0) ; First CORE register
32 (R1_REGNUM 1) ; Second CORE register
33 (IP_REGNUM 12) ; Scratch register
34 (SP_REGNUM 13) ; Stack pointer
35 (LR_REGNUM 14) ; Return address register
36 (PC_REGNUM 15) ; Program counter
37 (LAST_ARM_REGNUM 15) ;
38 (CC_REGNUM 100) ; Condition code pseudo register
39 (VFPCC_REGNUM 101) ; VFP Condition code pseudo register
e1159bbe 40 ]
41)
3c5afce6 42;; 3rd operand to select_dominance_cc_mode
43(define_constants
44 [(DOM_CC_X_AND_Y 0)
45 (DOM_CC_NX_OR_Y 1)
46 (DOM_CC_X_OR_Y 2)
47 ]
48)
2ff91fec 49;; conditional compare combination
50(define_constants
51 [(CMP_CMP 0)
52 (CMN_CMP 1)
53 (CMP_CMN 2)
54 (CMN_CMN 3)
55 (NUM_OF_COND_CMP 4)
56 ]
57)
e1159bbe 58
b11cae9e 59\f
e1159bbe 60;;---------------------------------------------------------------------------
9c08d1fa 61;; Attributes
62
a651f34d 63;; Processor type. This is created automatically from arm-cores.def.
64(include "arm-tune.md")
65
861033d5 66;; Instruction classification types
67(include "types.md")
68
215b30b3 69; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
70; generating ARM code. This is used to control the length of some insn
71; patterns that share the same RTL in both ARM and Thumb code.
8724f216 72(define_attr "is_thumb" "yes,no"
73 (const (if_then_else (symbol_ref "TARGET_THUMB")
74 (const_string "yes") (const_string "no"))))
cffb2a26 75
ef51b8e1 76; IS_ARCH6 is set to 'yes' when we are generating code form ARMv6.
77(define_attr "is_arch6" "no,yes" (const (symbol_ref "arm_arch6")))
78
747b7458 79; IS_THUMB1 is set to 'yes' iff we are generating Thumb-1 code.
8724f216 80(define_attr "is_thumb1" "yes,no"
81 (const (if_then_else (symbol_ref "TARGET_THUMB1")
82 (const_string "yes") (const_string "no"))))
747b7458 83
c7a58118 84; We use this attribute to disable alternatives that can produce 32-bit
85; instructions inside an IT-block in Thumb2 state. ARMv8 deprecates IT blocks
86; that contain 32-bit instructions.
87(define_attr "enabled_for_depr_it" "no,yes" (const_string "yes"))
88
89; This attribute is used to disable a predicated alternative when we have
90; arm_restrict_it.
91(define_attr "predicable_short_it" "no,yes" (const_string "yes"))
92
331beb1a 93;; Operand number of an input operand that is shifted. Zero if the
94;; given instruction does not shift one of its input operands.
331beb1a 95(define_attr "shift" "" (const_int 0))
96
55a94dda 97;; [For compatibility with AArch64 in pipeline models]
98;; Attribute that specifies whether or not the instruction touches fp
99;; registers.
100(define_attr "fp" "no,yes" (const_string "no"))
101
3d91c5d6 102; Floating Point Unit. If we only have floating point emulation, then there
103; is no point in scheduling the floating point insns. (Well, for best
104; performance we should try and group them together).
bffbb863 105(define_attr "fpu" "none,vfp"
c7f506fd 106 (const (symbol_ref "arm_fpu_attr")))
3d91c5d6 107
b2bcff19 108; Predicated means that the insn form is conditionally executed based on a
109; predicate. We default to 'no' because no Thumb patterns match this rule
110; and not all ARM insns do.
c7a58118 111(define_attr "predicated" "yes,no" (const_string "no"))
112
094e994f 113; LENGTH of an instruction (in bytes)
06df6b17 114(define_attr "length" ""
e1b93706 115 (const_int 4))
9c08d1fa 116
d5d4dc8d 117; The architecture which supports the instruction (or alternative).
118; This can be "a" for ARM, "t" for either of the Thumbs, "32" for
119; TARGET_32BIT, "t1" or "t2" to specify a specific Thumb mode. "v6"
120; for ARM or Thumb-2 with arm_arch6, and nov6 for ARM without
e4585731 121; arm_arch6. "v6t2" for Thumb-2 with arm_arch6. This attribute is
122; used to compute attribute "enabled", use type "any" to enable an
123; alternative in all cases.
124(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 125 (const_string "any"))
126
127(define_attr "arch_enabled" "no,yes"
128 (cond [(eq_attr "arch" "any")
129 (const_string "yes")
130
131 (and (eq_attr "arch" "a")
0bf497f5 132 (match_test "TARGET_ARM"))
d5d4dc8d 133 (const_string "yes")
134
135 (and (eq_attr "arch" "t")
0bf497f5 136 (match_test "TARGET_THUMB"))
d5d4dc8d 137 (const_string "yes")
138
139 (and (eq_attr "arch" "t1")
0bf497f5 140 (match_test "TARGET_THUMB1"))
d5d4dc8d 141 (const_string "yes")
142
143 (and (eq_attr "arch" "t2")
0bf497f5 144 (match_test "TARGET_THUMB2"))
d5d4dc8d 145 (const_string "yes")
146
147 (and (eq_attr "arch" "32")
0bf497f5 148 (match_test "TARGET_32BIT"))
d5d4dc8d 149 (const_string "yes")
150
151 (and (eq_attr "arch" "v6")
0bf497f5 152 (match_test "TARGET_32BIT && arm_arch6"))
d5d4dc8d 153 (const_string "yes")
154
155 (and (eq_attr "arch" "nov6")
0bf497f5 156 (match_test "TARGET_32BIT && !arm_arch6"))
a651f34d 157 (const_string "yes")
158
e4585731 159 (and (eq_attr "arch" "v6t2")
160 (match_test "TARGET_32BIT && arm_arch6 && arm_arch_thumb2"))
161 (const_string "yes")
162
b6779ddc 163 (and (eq_attr "arch" "avoid_neon_for_64bits")
164 (match_test "TARGET_NEON")
165 (not (match_test "TARGET_PREFER_NEON_64BITS")))
a651f34d 166 (const_string "yes")
167
b6779ddc 168 (and (eq_attr "arch" "neon_for_64bits")
169 (match_test "TARGET_NEON")
170 (match_test "TARGET_PREFER_NEON_64BITS"))
6b8f7c28 171 (const_string "yes")
172
173 (and (eq_attr "arch" "iwmmxt2")
174 (match_test "TARGET_REALLY_IWMMXT2"))
21cc9773 175 (const_string "yes")
176
177 (and (eq_attr "arch" "armv6_or_vfpv3")
178 (match_test "arm_arch6 || TARGET_VFP3"))
179 (const_string "yes")
180 ]
6b8f7c28 181
d5d4dc8d 182 (const_string "no")))
183
aa06c51c 184(define_attr "opt" "any,speed,size"
185 (const_string "any"))
186
187(define_attr "opt_enabled" "no,yes"
188 (cond [(eq_attr "opt" "any")
189 (const_string "yes")
190
191 (and (eq_attr "opt" "speed")
192 (match_test "optimize_function_for_speed_p (cfun)"))
193 (const_string "yes")
194
195 (and (eq_attr "opt" "size")
196 (match_test "optimize_function_for_size_p (cfun)"))
197 (const_string "yes")]
198 (const_string "no")))
199
861033d5 200(define_attr "use_literal_pool" "no,yes"
201 (cond [(and (eq_attr "type" "f_loads,f_loadd")
202 (match_test "CONSTANT_P (operands[1])"))
203 (const_string "yes")]
204 (const_string "no")))
205
d5d4dc8d 206; Enable all alternatives that are both arch_enabled and insn_enabled.
951a3f72 207; FIXME:: opt_enabled has been temporarily removed till the time we have
208; an attribute that allows the use of such alternatives.
209; This depends on caching of speed_p, size_p on a per
210; alternative basis. The problem is that the enabled attribute
211; cannot depend on any state that is not cached or is not constant
212; for a compilation unit. We probably need a generic "hot/cold"
213; alternative which if implemented can help with this. We disable this
214; until such a time as this is implemented and / or the improvements or
215; regressions with removing this attribute are double checked.
216; See ashldi3_neon and <shift>di3_neon in neon.md.
217
93b431d9 218 (define_attr "enabled" "no,yes"
0abea32c 219 (cond [(and (eq_attr "predicable_short_it" "no")
c7a58118 220 (and (eq_attr "predicated" "yes")
221 (match_test "arm_restrict_it")))
222 (const_string "no")
223
224 (and (eq_attr "enabled_for_depr_it" "no")
225 (match_test "arm_restrict_it"))
226 (const_string "no")
227
861033d5 228 (and (eq_attr "use_literal_pool" "yes")
229 (match_test "arm_disable_literal_pool"))
230 (const_string "no")
231
aa06c51c 232 (eq_attr "arch_enabled" "no")
aa06c51c 233 (const_string "no")]
234 (const_string "yes")))
d5d4dc8d 235
56d27660 236; POOL_RANGE is how far away from a constant pool entry that this insn
237; can be placed. If the distance is zero, then this insn will never
238; reference the pool.
42e1de19 239; Note that for Thumb constant pools the PC value is rounded down to the
240; nearest multiple of four. Therefore, THUMB2_POOL_RANGE (and POOL_RANGE for
241; Thumb insns) should be set to <max_range> - 2.
cffb2a26 242; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
8848d797 243; before its address. It is set to <max_range> - (8 + <data_size>).
cde1623a 244(define_attr "arm_pool_range" "" (const_int 0))
245(define_attr "thumb2_pool_range" "" (const_int 0))
246(define_attr "arm_neg_pool_range" "" (const_int 0))
247(define_attr "thumb2_neg_pool_range" "" (const_int 0))
248
249(define_attr "pool_range" ""
250 (cond [(eq_attr "is_thumb" "yes") (attr "thumb2_pool_range")]
251 (attr "arm_pool_range")))
252(define_attr "neg_pool_range" ""
253 (cond [(eq_attr "is_thumb" "yes") (attr "thumb2_neg_pool_range")]
254 (attr "arm_neg_pool_range")))
56d27660 255
215b30b3 256; An assembler sequence may clobber the condition codes without us knowing.
4d7a8451 257; If such an insn references the pool, then we have no way of knowing how,
258; so use the most conservative value for pool_range.
9c08d1fa 259(define_asm_attributes
4d7a8451 260 [(set_attr "conds" "clob")
261 (set_attr "length" "4")
262 (set_attr "pool_range" "250")])
9c08d1fa 263
9888ad6d 264; Load scheduling, set from the arm_ld_sched variable
4c834714 265; initialized by arm_option_override()
9888ad6d 266(define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
849170fd 267
f7fbdd4a 268; condition codes: this one is used by final_prescan_insn to speed up
269; conditionalizing instructions. It saves having to scan the rtl to see if
270; it uses or alters the condition codes.
215b30b3 271;
f7fbdd4a 272; USE means that the condition codes are used by the insn in the process of
215b30b3 273; outputting code, this means (at present) that we can't use the insn in
274; inlined branches
275;
f7fbdd4a 276; SET means that the purpose of the insn is to set the condition codes in a
215b30b3 277; well defined manner.
278;
f7fbdd4a 279; CLOB means that the condition codes are altered in an undefined manner, if
215b30b3 280; they are altered at all
281;
ad6d3e2a 282; UNCONDITIONAL means the instruction can not be conditionally executed and
283; that the instruction does not use or alter the condition codes.
c52acdd2 284;
ad6d3e2a 285; NOCOND means that the instruction does not use or alter the condition
286; codes but can be converted into a conditionally exectuted instruction.
f7fbdd4a 287
b0694be0 288(define_attr "conds" "use,set,clob,unconditional,nocond"
747b7458 289 (if_then_else
290 (ior (eq_attr "is_thumb1" "yes")
291 (eq_attr "type" "call"))
c1a66faf 292 (const_string "clob")
32093010 293 (if_then_else (eq_attr "is_neon_type" "no")
52432540 294 (const_string "nocond")
295 (const_string "unconditional"))))
f7fbdd4a 296
215b30b3 297; Predicable means that the insn can be conditionally executed based on
298; an automatically added predicate (additional patterns are generated by
299; gen...). We default to 'no' because no Thumb patterns match this rule
300; and not all ARM patterns do.
0d66636f 301(define_attr "predicable" "no,yes" (const_string "no"))
302
129a2fe4 303; Only model the write buffer for ARM6 and ARM7. Earlier processors don't
304; have one. Later ones, such as StrongARM, have write-back caches, so don't
8d232dc7 305; suffer blockages enough to warrant modelling this (and it can adversely
129a2fe4 306; affect the schedule).
74a71f7d 307(define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_tune_wbuf")))
129a2fe4 308
215b30b3 309; WRITE_CONFLICT implies that a read following an unrelated write is likely
310; to stall the processor. Used with model_wbuf above.
9c08d1fa 311(define_attr "write_conflict" "no,yes"
312 (if_then_else (eq_attr "type"
96854199 313 "block,call,load1")
9c08d1fa 314 (const_string "yes")
315 (const_string "no")))
316
215b30b3 317; Classify the insns into those that take one cycle and those that take more
318; than one on the main cpu execution unit.
f7fbdd4a 319(define_attr "core_cycles" "single,multi"
320 (if_then_else (eq_attr "type"
112eda6f 321 "adc_imm, adc_reg, adcs_imm, adcs_reg, adr, alu_ext, alu_imm, alu_sreg,\
322 alu_shift_imm, alu_shift_reg, alu_dsp_reg, alus_ext, alus_imm, alus_sreg,\
d82e788e 323 alus_shift_imm, alus_shift_reg, bfm, csel, rev, logic_imm, logic_reg,\
324 logic_shift_imm, logic_shift_reg, logics_imm, logics_reg,\
325 logics_shift_imm, logics_shift_reg, extend, shift_imm, float, fcsel,\
7cb6c048 326 wmmx_wor, wmmx_wxor, wmmx_wand, wmmx_wandn, wmmx_wmov, wmmx_tmcrr,\
327 wmmx_tmrrc, wmmx_wldr, wmmx_wstr, wmmx_tmcr, wmmx_tmrc, wmmx_wadd,\
328 wmmx_wsub, wmmx_wmul, wmmx_wmac, wmmx_wavg2, wmmx_tinsr, wmmx_textrm,\
329 wmmx_wshufh, wmmx_wcmpeq, wmmx_wcmpgt, wmmx_wmax, wmmx_wmin, wmmx_wpack,\
330 wmmx_wunpckih, wmmx_wunpckil, wmmx_wunpckeh, wmmx_wunpckel, wmmx_wror,\
331 wmmx_wsra, wmmx_wsrl, wmmx_wsll, wmmx_wmadd, wmmx_tmia, wmmx_tmiaph,\
332 wmmx_tmiaxy, wmmx_tbcst, wmmx_tmovmsk, wmmx_wacc, wmmx_waligni,\
333 wmmx_walignr, wmmx_tandc, wmmx_textrc, wmmx_torc, wmmx_torvsc, wmmx_wsad,\
334 wmmx_wabs, wmmx_wabsdiff, wmmx_waddsubhx, wmmx_wsubaddhx, wmmx_wavg4,\
335 wmmx_wmulw, wmmx_wqmulm, wmmx_wqmulwm, wmmx_waddbhus, wmmx_wqmiaxy,\
336 wmmx_wmiaxy, wmmx_wmiawxy, wmmx_wmerge")
f7fbdd4a 337 (const_string "single")
338 (const_string "multi")))
339
cffb2a26 340;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
215b30b3 341;; distant label. Only applicable to Thumb code.
cffb2a26 342(define_attr "far_jump" "yes,no" (const_string "no"))
343
d51f92df 344
25f905c2 345;; The number of machine instructions this pattern expands to.
346;; Used for Thumb-2 conditional execution.
347(define_attr "ce_count" "" (const_int 1))
348
4182b724 349;;---------------------------------------------------------------------------
350;; Unspecs
351
352(include "unspecs.md")
353
d51f92df 354;;---------------------------------------------------------------------------
fd781bb2 355;; Mode iterators
d51f92df 356
3de0dec6 357(include "iterators.md")
03770691 358
d51f92df 359;;---------------------------------------------------------------------------
360;; Predicates
361
9c9db025 362(include "predicates.md")
234f6557 363(include "constraints.md")
9c9db025 364
a2cd141b 365;;---------------------------------------------------------------------------
366;; Pipeline descriptions
215b30b3 367
e3879fd0 368(define_attr "tune_cortexr4" "yes,no"
369 (const (if_then_else
7d3cda8c 370 (eq_attr "tune" "cortexr4,cortexr4f,cortexr5")
e3879fd0 371 (const_string "yes")
372 (const_string "no"))))
373
a2cd141b 374;; True if the generic scheduling description should be used.
375
376(define_attr "generic_sched" "yes,no"
2546d93a 377 (const (if_then_else
e18862f3 378 (ior (eq_attr "tune" "fa526,fa626,fa606te,fa626te,fmp626,fa726te,\
379 arm926ejs,arm1020e,arm1026ejs,arm1136js,\
380 arm1136jfs,cortexa5,cortexa7,cortexa8,\
42e7b263 381 cortexa9,cortexa12,cortexa15,cortexa17,\
b1099bfd 382 cortexa53,cortexa57,cortexm4,cortexm7,\
802e6377 383 exynosm1,marvell_pj4,xgene1")
2546d93a 384 (eq_attr "tune_cortexr4" "yes"))
4d5cb40d 385 (const_string "no")
386 (const_string "yes"))))
387
c0e1af52 388(define_attr "generic_vfp" "yes,no"
389 (const (if_then_else
390 (and (eq_attr "fpu" "vfp")
e18862f3 391 (eq_attr "tune" "!arm1020e,arm1022e,cortexa5,cortexa7,\
392 cortexa8,cortexa9,cortexa53,cortexm4,\
55a94dda 393 cortexm7,marvell_pj4,xgene1")
e3879fd0 394 (eq_attr "tune_cortexr4" "no"))
c0e1af52 395 (const_string "yes")
396 (const_string "no"))))
397
6b8f7c28 398(include "marvell-f-iwmmxt.md")
a2cd141b 399(include "arm-generic.md")
400(include "arm926ejs.md")
c0e1af52 401(include "arm1020e.md")
a2cd141b 402(include "arm1026ejs.md")
403(include "arm1136jfs.md")
0e266d06 404(include "fa526.md")
405(include "fa606te.md")
406(include "fa626te.md")
407(include "fmp626.md")
408(include "fa726te.md")
3f1e069f 409(include "cortex-a5.md")
d6b7f019 410(include "cortex-a7.md")
bcaec148 411(include "cortex-a8.md")
036068af 412(include "cortex-a9.md")
65f2f758 413(include "cortex-a15.md")
42e7b263 414(include "cortex-a17.md")
da10bc87 415(include "cortex-a53.md")
b1099bfd 416(include "cortex-a57.md")
934a1e72 417(include "cortex-r4.md")
e3879fd0 418(include "cortex-r4f.md")
e18862f3 419(include "cortex-m7.md")
2546d93a 420(include "cortex-m4.md")
421(include "cortex-m4-fpu.md")
802e6377 422(include "exynos-m1.md")
55e3ada8 423(include "vfp11.md")
ea7d210b 424(include "marvell-pj4.md")
55a94dda 425(include "xgene1.md")
3586df96 426
9c08d1fa 427\f
215b30b3 428;;---------------------------------------------------------------------------
e1159bbe 429;; Insn patterns
430;;
a0f94409 431;; Addition insns.
215b30b3 432
9c08d1fa 433;; Note: For DImode insns, there is normally no reason why operands should
434;; not be in the same register, what we don't want is for something being
435;; written to partially overlap something that is an input.
436
cffb2a26 437(define_expand "adddi3"
438 [(parallel
215b30b3 439 [(set (match_operand:DI 0 "s_register_operand" "")
cffb2a26 440 (plus:DI (match_operand:DI 1 "s_register_operand" "")
10e5ccd5 441 (match_operand:DI 2 "arm_adddi_operand" "")))
bd5b4116 442 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 443 "TARGET_EITHER"
444 "
25f905c2 445 if (TARGET_THUMB1)
cffb2a26 446 {
0438d37f 447 if (!REG_P (operands[1]))
bc5a93af 448 operands[1] = force_reg (DImode, operands[1]);
0438d37f 449 if (!REG_P (operands[2]))
bc5a93af 450 operands[2] = force_reg (DImode, operands[2]);
cffb2a26 451 }
452 "
453)
454
a0f94409 455(define_insn_and_split "*arm_adddi3"
10e5ccd5 456 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r,&r,&r")
457 (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0, r, 0, r")
458 (match_operand:DI 2 "arm_adddi_operand" "r, 0, r, Dd, Dd")))
bd5b4116 459 (clobber (reg:CC CC_REGNUM))]
b805622c 460 "TARGET_32BIT && !TARGET_NEON"
33782ec7 461 "#"
94829feb 462 "TARGET_32BIT && reload_completed
463 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))"
a0f94409 464 [(parallel [(set (reg:CC_C CC_REGNUM)
465 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
466 (match_dup 1)))
467 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 468 (set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (match_dup 5))
469 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
a0f94409 470 "
471 {
472 operands[3] = gen_highpart (SImode, operands[0]);
473 operands[0] = gen_lowpart (SImode, operands[0]);
474 operands[4] = gen_highpart (SImode, operands[1]);
475 operands[1] = gen_lowpart (SImode, operands[1]);
10e5ccd5 476 operands[5] = gen_highpart_mode (SImode, DImode, operands[2]);
a0f94409 477 operands[2] = gen_lowpart (SImode, operands[2]);
478 }"
cffb2a26 479 [(set_attr "conds" "clob")
1b7da4ac 480 (set_attr "length" "8")
481 (set_attr "type" "multiple")]
cffb2a26 482)
9c08d1fa 483
a0f94409 484(define_insn_and_split "*adddi_sesidi_di"
9c08d1fa 485 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
486 (plus:DI (sign_extend:DI
97499065 487 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 488 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 489 (clobber (reg:CC CC_REGNUM))]
b805622c 490 "TARGET_32BIT"
33782ec7 491 "#"
25f905c2 492 "TARGET_32BIT && reload_completed"
a0f94409 493 [(parallel [(set (reg:CC_C CC_REGNUM)
494 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
495 (match_dup 1)))
496 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 497 (set (match_dup 3) (plus:SI (plus:SI (ashiftrt:SI (match_dup 2)
a0f94409 498 (const_int 31))
080c0b9a 499 (match_dup 4))
500 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
a0f94409 501 "
502 {
503 operands[3] = gen_highpart (SImode, operands[0]);
504 operands[0] = gen_lowpart (SImode, operands[0]);
505 operands[4] = gen_highpart (SImode, operands[1]);
506 operands[1] = gen_lowpart (SImode, operands[1]);
507 operands[2] = gen_lowpart (SImode, operands[2]);
508 }"
215b30b3 509 [(set_attr "conds" "clob")
1b7da4ac 510 (set_attr "length" "8")
511 (set_attr "type" "multiple")]
215b30b3 512)
9c08d1fa 513
a0f94409 514(define_insn_and_split "*adddi_zesidi_di"
9c08d1fa 515 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
516 (plus:DI (zero_extend:DI
97499065 517 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 518 (match_operand:DI 1 "s_register_operand" "0,r")))
a0f94409 519 (clobber (reg:CC CC_REGNUM))]
b805622c 520 "TARGET_32BIT"
33782ec7 521 "#"
25f905c2 522 "TARGET_32BIT && reload_completed"
a0f94409 523 [(parallel [(set (reg:CC_C CC_REGNUM)
524 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
525 (match_dup 1)))
526 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 527 (set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (const_int 0))
528 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
a0f94409 529 "
530 {
531 operands[3] = gen_highpart (SImode, operands[0]);
532 operands[0] = gen_lowpart (SImode, operands[0]);
533 operands[4] = gen_highpart (SImode, operands[1]);
534 operands[1] = gen_lowpart (SImode, operands[1]);
535 operands[2] = gen_lowpart (SImode, operands[2]);
536 }"
cffb2a26 537 [(set_attr "conds" "clob")
1b7da4ac 538 (set_attr "length" "8")
539 (set_attr "type" "multiple")]
cffb2a26 540)
b11cae9e 541
87b22bf7 542(define_expand "addsi3"
cffb2a26 543 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 544 (plus:SI (match_operand:SI 1 "s_register_operand" "")
545 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 546 "TARGET_EITHER"
87b22bf7 547 "
0438d37f 548 if (TARGET_32BIT && CONST_INT_P (operands[2]))
87b22bf7 549 {
96f57e36 550 arm_split_constant (PLUS, SImode, NULL_RTX,
551 INTVAL (operands[2]), operands[0], operands[1],
e1ba4a27 552 optimize && can_create_pseudo_p ());
87b22bf7 553 DONE;
554 }
cffb2a26 555 "
556)
87b22bf7 557
5bd751ff 558; If there is a scratch available, this will be faster than synthesizing the
a0f94409 559; addition.
560(define_peephole2
561 [(match_scratch:SI 3 "r")
372575c7 562 (set (match_operand:SI 0 "arm_general_register_operand" "")
563 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
cffb2a26 564 (match_operand:SI 2 "const_int_operand" "")))]
25f905c2 565 "TARGET_32BIT &&
a0f94409 566 !(const_ok_for_arm (INTVAL (operands[2]))
567 || const_ok_for_arm (-INTVAL (operands[2])))
568 && const_ok_for_arm (~INTVAL (operands[2]))"
569 [(set (match_dup 3) (match_dup 2))
570 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
571 ""
572)
87b22bf7 573
2f02c19f 574;; The r/r/k alternative is required when reloading the address
575;; (plus (reg rN) (reg sp)) into (reg rN). In this case reload will
576;; put the duplicated register first, and not try the commutative version.
a0f94409 577(define_insn_and_split "*arm_addsi3"
7c36fe71 578 [(set (match_operand:SI 0 "s_register_operand" "=rk,l,l ,l ,r ,k ,r,r ,k ,r ,k,k,r ,k ,r")
579 (plus:SI (match_operand:SI 1 "s_register_operand" "%0 ,l,0 ,l ,rk,k ,r,rk,k ,rk,k,r,rk,k ,rk")
580 (match_operand:SI 2 "reg_or_int_operand" "rk ,l,Py,Pd,rI,rI,k,Pj,Pj,L ,L,L,PJ,PJ,?n")))]
25f905c2 581 "TARGET_32BIT"
5565501b 582 "@
c24d855d 583 add%?\\t%0, %0, %2
5565501b 584 add%?\\t%0, %1, %2
a0b3420a 585 add%?\\t%0, %1, %2
7c36fe71 586 add%?\\t%0, %1, %2
587 add%?\\t%0, %1, %2
aaa37ad6 588 add%?\\t%0, %1, %2
2f02c19f 589 add%?\\t%0, %2, %1
d5cbae34 590 addw%?\\t%0, %1, %2
591 addw%?\\t%0, %1, %2
aaa37ad6 592 sub%?\\t%0, %1, #%n2
87b22bf7 593 sub%?\\t%0, %1, #%n2
d7757711 594 sub%?\\t%0, %1, #%n2
d5cbae34 595 subw%?\\t%0, %1, #%n2
596 subw%?\\t%0, %1, #%n2
87b22bf7 597 #"
a3ffc315 598 "TARGET_32BIT
0438d37f 599 && CONST_INT_P (operands[2])
d5cbae34 600 && !const_ok_for_op (INTVAL (operands[2]), PLUS)
a3ffc315 601 && (reload_completed || !arm_eliminable_register (operands[1]))"
a0f94409 602 [(clobber (const_int 0))]
603 "
96f57e36 604 arm_split_constant (PLUS, SImode, curr_insn,
605 INTVAL (operands[2]), operands[0],
a0f94409 606 operands[1], 0);
607 DONE;
608 "
7c36fe71 609 [(set_attr "length" "2,4,4,4,4,4,4,4,4,4,4,4,4,4,16")
d5cbae34 610 (set_attr "predicable" "yes")
7c36fe71 611 (set_attr "predicable_short_it" "yes,yes,yes,yes,no,no,no,no,no,no,no,no,no,no,no")
612 (set_attr "arch" "t2,t2,t2,t2,*,*,*,t2,t2,*,*,a,t2,t2,*")
65f68e55 613 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
d82e788e 614 (const_string "alu_imm")
112eda6f 615 (const_string "alu_sreg")))
65f68e55 616 ]
cffb2a26 617)
618
90c2bcf0 619(define_insn "addsi3_compare0"
bd5b4116 620 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 621 (compare:CC_NOOV
65f68e55 622 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r,r")
623 (match_operand:SI 2 "arm_add_operand" "I,L,r"))
5565501b 624 (const_int 0)))
65f68e55 625 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9c08d1fa 626 (plus:SI (match_dup 1) (match_dup 2)))]
ec792a7b 627 "TARGET_ARM"
5565501b 628 "@
3ef90e77 629 adds%?\\t%0, %1, %2
630 subs%?\\t%0, %1, #%n2
631 adds%?\\t%0, %1, %2"
65f68e55 632 [(set_attr "conds" "set")
112eda6f 633 (set_attr "type" "alus_imm,alus_imm,alus_sreg")]
cffb2a26 634)
9c08d1fa 635
aea4c774 636(define_insn "*addsi3_compare0_scratch"
bd5b4116 637 [(set (reg:CC_NOOV CC_REGNUM)
aea4c774 638 (compare:CC_NOOV
65f68e55 639 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r, r")
640 (match_operand:SI 1 "arm_add_operand" "I,L, r"))
aea4c774 641 (const_int 0)))]
ec792a7b 642 "TARGET_ARM"
cffb2a26 643 "@
644 cmn%?\\t%0, %1
65f68e55 645 cmp%?\\t%0, #%n1
646 cmn%?\\t%0, %1"
596e5e8f 647 [(set_attr "conds" "set")
65f68e55 648 (set_attr "predicable" "yes")
112eda6f 649 (set_attr "type" "alus_imm,alus_imm,alus_sreg")]
0d66636f 650)
cffb2a26 651
aed179ae 652(define_insn "*compare_negsi_si"
653 [(set (reg:CC_Z CC_REGNUM)
654 (compare:CC_Z
7c36fe71 655 (neg:SI (match_operand:SI 0 "s_register_operand" "l,r"))
656 (match_operand:SI 1 "s_register_operand" "l,r")))]
25f905c2 657 "TARGET_32BIT"
aed179ae 658 "cmn%?\\t%1, %0"
596e5e8f 659 [(set_attr "conds" "set")
7c36fe71 660 (set_attr "predicable" "yes")
661 (set_attr "arch" "t2,*")
662 (set_attr "length" "2,4")
1b7da4ac 663 (set_attr "predicable_short_it" "yes,no")
112eda6f 664 (set_attr "type" "alus_sreg")]
0d66636f 665)
aea4c774 666
203c488f 667;; This is the canonicalization of addsi3_compare0_for_combiner when the
668;; addend is a constant.
190efb17 669(define_insn "cmpsi2_addneg"
203c488f 670 [(set (reg:CC CC_REGNUM)
671 (compare:CC
672 (match_operand:SI 1 "s_register_operand" "r,r")
2a977b78 673 (match_operand:SI 2 "arm_addimm_operand" "L,I")))
203c488f 674 (set (match_operand:SI 0 "s_register_operand" "=r,r")
675 (plus:SI (match_dup 1)
2a977b78 676 (match_operand:SI 3 "arm_addimm_operand" "I,L")))]
25f905c2 677 "TARGET_32BIT && INTVAL (operands[2]) == -INTVAL (operands[3])"
203c488f 678 "@
3ef90e77 679 adds%?\\t%0, %1, %3
680 subs%?\\t%0, %1, #%n3"
1b7da4ac 681 [(set_attr "conds" "set")
112eda6f 682 (set_attr "type" "alus_sreg")]
203c488f 683)
684
685;; Convert the sequence
686;; sub rd, rn, #1
687;; cmn rd, #1 (equivalent to cmp rd, #-1)
688;; bne dest
689;; into
690;; subs rd, rn, #1
691;; bcs dest ((unsigned)rn >= 1)
692;; similarly for the beq variant using bcc.
693;; This is a common looping idiom (while (n--))
694(define_peephole2
372575c7 695 [(set (match_operand:SI 0 "arm_general_register_operand" "")
696 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
203c488f 697 (const_int -1)))
698 (set (match_operand 2 "cc_register" "")
699 (compare (match_dup 0) (const_int -1)))
700 (set (pc)
701 (if_then_else (match_operator 3 "equality_operator"
702 [(match_dup 2) (const_int 0)])
703 (match_operand 4 "" "")
704 (match_operand 5 "" "")))]
25f905c2 705 "TARGET_32BIT && peep2_reg_dead_p (3, operands[2])"
203c488f 706 [(parallel[
707 (set (match_dup 2)
708 (compare:CC
709 (match_dup 1) (const_int 1)))
710 (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
711 (set (pc)
712 (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
713 (match_dup 4)
714 (match_dup 5)))]
715 "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
716 operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
717 ? GEU : LTU),
718 VOIDmode,
719 operands[2], const0_rtx);"
720)
721
ebcc79bc 722;; The next four insns work because they compare the result with one of
723;; the operands, and we know that the use of the condition code is
724;; either GEU or LTU, so we can use the carry flag from the addition
725;; instead of doing the compare a second time.
726(define_insn "*addsi3_compare_op1"
bd5b4116 727 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 728 (compare:CC_C
65f68e55 729 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
730 (match_operand:SI 2 "arm_add_operand" "I,L,r"))
ebcc79bc 731 (match_dup 1)))
65f68e55 732 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
ebcc79bc 733 (plus:SI (match_dup 1) (match_dup 2)))]
25f905c2 734 "TARGET_32BIT"
ebcc79bc 735 "@
3ef90e77 736 adds%?\\t%0, %1, %2
737 subs%?\\t%0, %1, #%n2
738 adds%?\\t%0, %1, %2"
65f68e55 739 [(set_attr "conds" "set")
112eda6f 740 (set_attr "type" "alus_imm,alus_imm,alus_sreg")]
0d66636f 741)
ebcc79bc 742
743(define_insn "*addsi3_compare_op2"
bd5b4116 744 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 745 (compare:CC_C
65f68e55 746 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
747 (match_operand:SI 2 "arm_add_operand" "I,L,r"))
ebcc79bc 748 (match_dup 2)))
65f68e55 749 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9c08d1fa 750 (plus:SI (match_dup 1) (match_dup 2)))]
25f905c2 751 "TARGET_32BIT"
5565501b 752 "@
3ef90e77 753 adds%?\\t%0, %1, %2
38128b57 754 subs%?\\t%0, %1, #%n2
755 adds%?\\t%0, %1, %2"
65f68e55 756 [(set_attr "conds" "set")
112eda6f 757 (set_attr "type" "alus_imm,alus_imm,alus_sreg")]
0d66636f 758)
9c08d1fa 759
ebcc79bc 760(define_insn "*compare_addsi2_op0"
bd5b4116 761 [(set (reg:CC_C CC_REGNUM)
7c36fe71 762 (compare:CC_C
763 (plus:SI (match_operand:SI 0 "s_register_operand" "l,l,r,r,r")
764 (match_operand:SI 1 "arm_add_operand" "Pv,l,I,L,r"))
765 (match_dup 0)))]
25f905c2 766 "TARGET_32BIT"
ebcc79bc 767 "@
7c36fe71 768 cmp%?\\t%0, #%n1
769 cmn%?\\t%0, %1
ebcc79bc 770 cmn%?\\t%0, %1
65f68e55 771 cmp%?\\t%0, #%n1
772 cmn%?\\t%0, %1"
596e5e8f 773 [(set_attr "conds" "set")
65f68e55 774 (set_attr "predicable" "yes")
7c36fe71 775 (set_attr "arch" "t2,t2,*,*,*")
776 (set_attr "predicable_short_it" "yes,yes,no,no,no")
777 (set_attr "length" "2,2,4,4,4")
112eda6f 778 (set_attr "type" "alus_imm,alus_sreg,alus_imm,alus_imm,alus_sreg")]
0d66636f 779)
ebcc79bc 780
781(define_insn "*compare_addsi2_op1"
bd5b4116 782 [(set (reg:CC_C CC_REGNUM)
7c36fe71 783 (compare:CC_C
784 (plus:SI (match_operand:SI 0 "s_register_operand" "l,l,r,r,r")
785 (match_operand:SI 1 "arm_add_operand" "Pv,l,I,L,r"))
786 (match_dup 1)))]
25f905c2 787 "TARGET_32BIT"
ebcc79bc 788 "@
7c36fe71 789 cmp%?\\t%0, #%n1
790 cmn%?\\t%0, %1
ebcc79bc 791 cmn%?\\t%0, %1
65f68e55 792 cmp%?\\t%0, #%n1
793 cmn%?\\t%0, %1"
596e5e8f 794 [(set_attr "conds" "set")
65f68e55 795 (set_attr "predicable" "yes")
7c36fe71 796 (set_attr "arch" "t2,t2,*,*,*")
797 (set_attr "predicable_short_it" "yes,yes,no,no,no")
798 (set_attr "length" "2,2,4,4,4")
112eda6f 799 (set_attr "type" "alus_imm,alus_sreg,alus_imm,alus_imm,alus_sreg")]
7c36fe71 800 )
ebcc79bc 801
080c0b9a 802(define_insn "*addsi3_carryin_<optab>"
7c36fe71 803 [(set (match_operand:SI 0 "s_register_operand" "=l,r,r")
804 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%l,r,r")
805 (match_operand:SI 2 "arm_not_operand" "0,rI,K"))
806 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))]
25f905c2 807 "TARGET_32BIT"
10e5ccd5 808 "@
a0b3420a 809 adc%?\\t%0, %1, %2
10e5ccd5 810 adc%?\\t%0, %1, %2
811 sbc%?\\t%0, %1, #%B2"
a7de272d 812 [(set_attr "conds" "use")
7c36fe71 813 (set_attr "predicable" "yes")
814 (set_attr "arch" "t2,*,*")
815 (set_attr "length" "4")
1b7da4ac 816 (set_attr "predicable_short_it" "yes,no,no")
817 (set_attr "type" "adc_reg,adc_reg,adc_imm")]
cffb2a26 818)
ebcc79bc 819
080c0b9a 820(define_insn "*addsi3_carryin_alt2_<optab>"
7c36fe71 821 [(set (match_operand:SI 0 "s_register_operand" "=l,r,r")
822 (plus:SI (plus:SI (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))
823 (match_operand:SI 1 "s_register_operand" "%l,r,r"))
824 (match_operand:SI 2 "arm_rhs_operand" "l,rI,K")))]
25f905c2 825 "TARGET_32BIT"
10e5ccd5 826 "@
a0b3420a 827 adc%?\\t%0, %1, %2
10e5ccd5 828 adc%?\\t%0, %1, %2
829 sbc%?\\t%0, %1, #%B2"
a7de272d 830 [(set_attr "conds" "use")
7c36fe71 831 (set_attr "predicable" "yes")
832 (set_attr "arch" "t2,*,*")
833 (set_attr "length" "4")
1b7da4ac 834 (set_attr "predicable_short_it" "yes,no,no")
835 (set_attr "type" "adc_reg,adc_reg,adc_imm")]
0d66636f 836)
ebcc79bc 837
080c0b9a 838(define_insn "*addsi3_carryin_shift_<optab>"
ebcc79bc 839 [(set (match_operand:SI 0 "s_register_operand" "=r")
080c0b9a 840 (plus:SI (plus:SI
841 (match_operator:SI 2 "shift_operator"
842 [(match_operand:SI 3 "s_register_operand" "r")
843 (match_operand:SI 4 "reg_or_int_operand" "rM")])
844 (match_operand:SI 1 "s_register_operand" "r"))
845 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))]
25f905c2 846 "TARGET_32BIT"
080c0b9a 847 "adc%?\\t%0, %1, %3%S2"
848 [(set_attr "conds" "use")
a7de272d 849 (set_attr "predicable" "yes")
7c36fe71 850 (set_attr "predicable_short_it" "no")
080c0b9a 851 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
d82e788e 852 (const_string "alu_shift_imm")
853 (const_string "alu_shift_reg")))]
cffb2a26 854)
ebcc79bc 855
922b6913 856(define_insn "*addsi3_carryin_clobercc_<optab>"
857 [(set (match_operand:SI 0 "s_register_operand" "=r")
858 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%r")
859 (match_operand:SI 2 "arm_rhs_operand" "rI"))
860 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))
861 (clobber (reg:CC CC_REGNUM))]
862 "TARGET_32BIT"
3ef90e77 863 "adcs%?\\t%0, %1, %2"
1b7da4ac 864 [(set_attr "conds" "set")
865 (set_attr "type" "adcs_reg")]
922b6913 866)
867
9154bd82 868(define_insn "*subsi3_carryin"
869 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
870 (minus:SI (minus:SI (match_operand:SI 1 "reg_or_int_operand" "r,I")
871 (match_operand:SI 2 "s_register_operand" "r,r"))
872 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
873 "TARGET_32BIT"
874 "@
875 sbc%?\\t%0, %1, %2
876 rsc%?\\t%0, %2, %1"
877 [(set_attr "conds" "use")
878 (set_attr "arch" "*,a")
7c36fe71 879 (set_attr "predicable" "yes")
1b7da4ac 880 (set_attr "predicable_short_it" "no")
881 (set_attr "type" "adc_reg,adc_imm")]
9154bd82 882)
883
884(define_insn "*subsi3_carryin_const"
885 [(set (match_operand:SI 0 "s_register_operand" "=r")
886 (minus:SI (plus:SI (match_operand:SI 1 "reg_or_int_operand" "r")
887 (match_operand:SI 2 "arm_not_operand" "K"))
888 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
889 "TARGET_32BIT"
890 "sbc\\t%0, %1, #%B2"
1b7da4ac 891 [(set_attr "conds" "use")
892 (set_attr "type" "adc_imm")]
9154bd82 893)
894
895(define_insn "*subsi3_carryin_compare"
896 [(set (reg:CC CC_REGNUM)
897 (compare:CC (match_operand:SI 1 "s_register_operand" "r")
898 (match_operand:SI 2 "s_register_operand" "r")))
899 (set (match_operand:SI 0 "s_register_operand" "=r")
900 (minus:SI (minus:SI (match_dup 1)
901 (match_dup 2))
902 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
903 "TARGET_32BIT"
904 "sbcs\\t%0, %1, %2"
1b7da4ac 905 [(set_attr "conds" "set")
906 (set_attr "type" "adcs_reg")]
9154bd82 907)
908
909(define_insn "*subsi3_carryin_compare_const"
910 [(set (reg:CC CC_REGNUM)
911 (compare:CC (match_operand:SI 1 "reg_or_int_operand" "r")
912 (match_operand:SI 2 "arm_not_operand" "K")))
913 (set (match_operand:SI 0 "s_register_operand" "=r")
914 (minus:SI (plus:SI (match_dup 1)
915 (match_dup 2))
916 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
917 "TARGET_32BIT"
918 "sbcs\\t%0, %1, #%B2"
1b7da4ac 919 [(set_attr "conds" "set")
920 (set_attr "type" "adcs_imm")]
9154bd82 921)
922
923(define_insn "*subsi3_carryin_shift"
924 [(set (match_operand:SI 0 "s_register_operand" "=r")
925 (minus:SI (minus:SI
926 (match_operand:SI 1 "s_register_operand" "r")
927 (match_operator:SI 2 "shift_operator"
928 [(match_operand:SI 3 "s_register_operand" "r")
929 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
930 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
931 "TARGET_32BIT"
932 "sbc%?\\t%0, %1, %3%S2"
933 [(set_attr "conds" "use")
934 (set_attr "predicable" "yes")
935 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
d82e788e 936 (const_string "alu_shift_imm")
937 (const_string "alu_shift_reg")))]
9154bd82 938)
939
940(define_insn "*rsbsi3_carryin_shift"
941 [(set (match_operand:SI 0 "s_register_operand" "=r")
942 (minus:SI (minus:SI
943 (match_operator:SI 2 "shift_operator"
944 [(match_operand:SI 3 "s_register_operand" "r")
945 (match_operand:SI 4 "reg_or_int_operand" "rM")])
946 (match_operand:SI 1 "s_register_operand" "r"))
947 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
948 "TARGET_ARM"
949 "rsc%?\\t%0, %1, %3%S2"
950 [(set_attr "conds" "use")
951 (set_attr "predicable" "yes")
952 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
d82e788e 953 (const_string "alu_shift_imm")
954 (const_string "alu_shift_reg")))]
9154bd82 955)
956
d795fb69 957; transform ((x << y) - 1) to ~(~(x-1) << y) Where X is a constant.
958(define_split
959 [(set (match_operand:SI 0 "s_register_operand" "")
960 (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
961 (match_operand:SI 2 "s_register_operand" ""))
962 (const_int -1)))
963 (clobber (match_operand:SI 3 "s_register_operand" ""))]
25f905c2 964 "TARGET_32BIT"
d795fb69 965 [(set (match_dup 3) (match_dup 1))
966 (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
967 "
968 operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
969")
970
604f3a0a 971(define_expand "addsf3"
972 [(set (match_operand:SF 0 "s_register_operand" "")
973 (plus:SF (match_operand:SF 1 "s_register_operand" "")
d86c91f6 974 (match_operand:SF 2 "s_register_operand" "")))]
25f905c2 975 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 976 "
604f3a0a 977")
978
604f3a0a 979(define_expand "adddf3"
980 [(set (match_operand:DF 0 "s_register_operand" "")
981 (plus:DF (match_operand:DF 1 "s_register_operand" "")
d86c91f6 982 (match_operand:DF 2 "s_register_operand" "")))]
a50d7267 983 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 984 "
604f3a0a 985")
986
cffb2a26 987(define_expand "subdi3"
988 [(parallel
989 [(set (match_operand:DI 0 "s_register_operand" "")
990 (minus:DI (match_operand:DI 1 "s_register_operand" "")
991 (match_operand:DI 2 "s_register_operand" "")))
bd5b4116 992 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 993 "TARGET_EITHER"
994 "
25f905c2 995 if (TARGET_THUMB1)
cffb2a26 996 {
0438d37f 997 if (!REG_P (operands[1]))
5aa8c5f0 998 operands[1] = force_reg (DImode, operands[1]);
0438d37f 999 if (!REG_P (operands[2]))
5aa8c5f0 1000 operands[2] = force_reg (DImode, operands[2]);
cffb2a26 1001 }
1002 "
1003)
1004
2f9b23e3 1005(define_insn_and_split "*arm_subdi3"
cffb2a26 1006 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
9c08d1fa 1007 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
1008 (match_operand:DI 2 "s_register_operand" "r,0,0")))
bd5b4116 1009 (clobber (reg:CC CC_REGNUM))]
94829feb 1010 "TARGET_32BIT && !TARGET_NEON"
2f9b23e3 1011 "#" ; "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
1012 "&& reload_completed"
1013 [(parallel [(set (reg:CC CC_REGNUM)
1014 (compare:CC (match_dup 1) (match_dup 2)))
1015 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1016 (set (match_dup 3) (minus:SI (minus:SI (match_dup 4) (match_dup 5))
1017 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1018 {
1019 operands[3] = gen_highpart (SImode, operands[0]);
1020 operands[0] = gen_lowpart (SImode, operands[0]);
1021 operands[4] = gen_highpart (SImode, operands[1]);
1022 operands[1] = gen_lowpart (SImode, operands[1]);
1023 operands[5] = gen_highpart (SImode, operands[2]);
1024 operands[2] = gen_lowpart (SImode, operands[2]);
1025 }
cffb2a26 1026 [(set_attr "conds" "clob")
1b7da4ac 1027 (set_attr "length" "8")
1028 (set_attr "type" "multiple")]
cffb2a26 1029)
1030
2f9b23e3 1031(define_insn_and_split "*subdi_di_zesidi"
cffb2a26 1032 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 1033 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r")
9c08d1fa 1034 (zero_extend:DI
cffb2a26 1035 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 1036 (clobber (reg:CC CC_REGNUM))]
25f905c2 1037 "TARGET_32BIT"
2f9b23e3 1038 "#" ; "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
1039 "&& reload_completed"
1040 [(parallel [(set (reg:CC CC_REGNUM)
1041 (compare:CC (match_dup 1) (match_dup 2)))
1042 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1043 (set (match_dup 3) (minus:SI (plus:SI (match_dup 4) (match_dup 5))
1044 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1045 {
1046 operands[3] = gen_highpart (SImode, operands[0]);
1047 operands[0] = gen_lowpart (SImode, operands[0]);
1048 operands[4] = gen_highpart (SImode, operands[1]);
1049 operands[1] = gen_lowpart (SImode, operands[1]);
1050 operands[5] = GEN_INT (~0);
1051 }
cffb2a26 1052 [(set_attr "conds" "clob")
1b7da4ac 1053 (set_attr "length" "8")
1054 (set_attr "type" "multiple")]
cffb2a26 1055)
9c08d1fa 1056
2f9b23e3 1057(define_insn_and_split "*subdi_di_sesidi"
cffb2a26 1058 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 1059 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r")
9c08d1fa 1060 (sign_extend:DI
cffb2a26 1061 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 1062 (clobber (reg:CC CC_REGNUM))]
25f905c2 1063 "TARGET_32BIT"
2f9b23e3 1064 "#" ; "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
1065 "&& reload_completed"
1066 [(parallel [(set (reg:CC CC_REGNUM)
1067 (compare:CC (match_dup 1) (match_dup 2)))
1068 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1069 (set (match_dup 3) (minus:SI (minus:SI (match_dup 4)
1070 (ashiftrt:SI (match_dup 2)
1071 (const_int 31)))
1072 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1073 {
1074 operands[3] = gen_highpart (SImode, operands[0]);
1075 operands[0] = gen_lowpart (SImode, operands[0]);
1076 operands[4] = gen_highpart (SImode, operands[1]);
1077 operands[1] = gen_lowpart (SImode, operands[1]);
1078 }
cffb2a26 1079 [(set_attr "conds" "clob")
1b7da4ac 1080 (set_attr "length" "8")
1081 (set_attr "type" "multiple")]
cffb2a26 1082)
9c08d1fa 1083
2f9b23e3 1084(define_insn_and_split "*subdi_zesidi_di"
cffb2a26 1085 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1086 (minus:DI (zero_extend:DI
cffb2a26 1087 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 1088 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 1089 (clobber (reg:CC CC_REGNUM))]
cffb2a26 1090 "TARGET_ARM"
2f9b23e3 1091 "#" ; "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
1092 ; is equivalent to:
1093 ; "subs\\t%Q0, %2, %Q1\;rsc\\t%R0, %R1, #0"
1094 "&& reload_completed"
1095 [(parallel [(set (reg:CC CC_REGNUM)
1096 (compare:CC (match_dup 2) (match_dup 1)))
1097 (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))])
1098 (set (match_dup 3) (minus:SI (minus:SI (const_int 0) (match_dup 4))
1099 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1100 {
1101 operands[3] = gen_highpart (SImode, operands[0]);
1102 operands[0] = gen_lowpart (SImode, operands[0]);
1103 operands[4] = gen_highpart (SImode, operands[1]);
1104 operands[1] = gen_lowpart (SImode, operands[1]);
1105 }
cffb2a26 1106 [(set_attr "conds" "clob")
1b7da4ac 1107 (set_attr "length" "8")
1108 (set_attr "type" "multiple")]
cffb2a26 1109)
9c08d1fa 1110
2f9b23e3 1111(define_insn_and_split "*subdi_sesidi_di"
cffb2a26 1112 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1113 (minus:DI (sign_extend:DI
cffb2a26 1114 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 1115 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 1116 (clobber (reg:CC CC_REGNUM))]
cffb2a26 1117 "TARGET_ARM"
2f9b23e3 1118 "#" ; "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
1119 ; is equivalent to:
1120 ; "subs\\t%Q0, %2, %Q1\;rsc\\t%R0, %R1, %2, asr #31"
1121 "&& reload_completed"
1122 [(parallel [(set (reg:CC CC_REGNUM)
1123 (compare:CC (match_dup 2) (match_dup 1)))
1124 (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))])
1125 (set (match_dup 3) (minus:SI (minus:SI
1126 (ashiftrt:SI (match_dup 2)
1127 (const_int 31))
1128 (match_dup 4))
1129 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1130 {
1131 operands[3] = gen_highpart (SImode, operands[0]);
1132 operands[0] = gen_lowpart (SImode, operands[0]);
1133 operands[4] = gen_highpart (SImode, operands[1]);
1134 operands[1] = gen_lowpart (SImode, operands[1]);
1135 }
cffb2a26 1136 [(set_attr "conds" "clob")
1b7da4ac 1137 (set_attr "length" "8")
1138 (set_attr "type" "multiple")]
cffb2a26 1139)
9c08d1fa 1140
2f9b23e3 1141(define_insn_and_split "*subdi_zesidi_zesidi"
cffb2a26 1142 [(set (match_operand:DI 0 "s_register_operand" "=r")
9c08d1fa 1143 (minus:DI (zero_extend:DI
cffb2a26 1144 (match_operand:SI 1 "s_register_operand" "r"))
9c08d1fa 1145 (zero_extend:DI
cffb2a26 1146 (match_operand:SI 2 "s_register_operand" "r"))))
bd5b4116 1147 (clobber (reg:CC CC_REGNUM))]
25f905c2 1148 "TARGET_32BIT"
2f9b23e3 1149 "#" ; "subs\\t%Q0, %1, %2\;sbc\\t%R0, %1, %1"
1150 "&& reload_completed"
1151 [(parallel [(set (reg:CC CC_REGNUM)
1152 (compare:CC (match_dup 1) (match_dup 2)))
1153 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1154 (set (match_dup 3) (minus:SI (minus:SI (match_dup 1) (match_dup 1))
1155 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1156 {
1157 operands[3] = gen_highpart (SImode, operands[0]);
1158 operands[0] = gen_lowpart (SImode, operands[0]);
1159 }
cffb2a26 1160 [(set_attr "conds" "clob")
1b7da4ac 1161 (set_attr "length" "8")
1162 (set_attr "type" "multiple")]
cffb2a26 1163)
b11cae9e 1164
87b22bf7 1165(define_expand "subsi3"
cffb2a26 1166 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 1167 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
1168 (match_operand:SI 2 "s_register_operand" "")))]
cffb2a26 1169 "TARGET_EITHER"
87b22bf7 1170 "
0438d37f 1171 if (CONST_INT_P (operands[1]))
87b22bf7 1172 {
25f905c2 1173 if (TARGET_32BIT)
cffb2a26 1174 {
17202aa5 1175 if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[1]), MINUS))
1176 operands[1] = force_reg (SImode, operands[1]);
1177 else
1178 {
1179 arm_split_constant (MINUS, SImode, NULL_RTX,
1180 INTVAL (operands[1]), operands[0],
1181 operands[2],
1182 optimize && can_create_pseudo_p ());
1183 DONE;
1184 }
cffb2a26 1185 }
25f905c2 1186 else /* TARGET_THUMB1 */
cffb2a26 1187 operands[1] = force_reg (SImode, operands[1]);
87b22bf7 1188 }
cffb2a26 1189 "
1190)
87b22bf7 1191
25f905c2 1192; ??? Check Thumb-2 split length
a0f94409 1193(define_insn_and_split "*arm_subsi3_insn"
3a44c5a9 1194 [(set (match_operand:SI 0 "s_register_operand" "=l,l ,l ,l ,r,r,r,rk,r")
1195 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "l ,0 ,l ,Pz,I,r,r,k ,?n")
1196 (match_operand:SI 2 "reg_or_int_operand" "l ,Py,Pd,l ,r,I,r,r ,r")))]
25f905c2 1197 "TARGET_32BIT"
e2348bcb 1198 "@
7c36fe71 1199 sub%?\\t%0, %1, %2
1200 sub%?\\t%0, %2
1201 sub%?\\t%0, %1, %2
1202 rsb%?\\t%0, %2, %1
87b22bf7 1203 rsb%?\\t%0, %2, %1
aaa37ad6 1204 sub%?\\t%0, %1, %2
080c0b9a 1205 sub%?\\t%0, %1, %2
65f68e55 1206 sub%?\\t%0, %1, %2
87b22bf7 1207 #"
0438d37f 1208 "&& (CONST_INT_P (operands[1])
91a5e339 1209 && !const_ok_for_arm (INTVAL (operands[1])))"
87b22bf7 1210 [(clobber (const_int 0))]
1211 "
96f57e36 1212 arm_split_constant (MINUS, SImode, curr_insn,
1213 INTVAL (operands[1]), operands[0], operands[2], 0);
87b22bf7 1214 DONE;
cffb2a26 1215 "
7c36fe71 1216 [(set_attr "length" "4,4,4,4,4,4,4,4,16")
1217 (set_attr "arch" "t2,t2,t2,t2,*,*,*,*,*")
65f68e55 1218 (set_attr "predicable" "yes")
7c36fe71 1219 (set_attr "predicable_short_it" "yes,yes,yes,yes,no,no,no,no,no")
112eda6f 1220 (set_attr "type" "alu_sreg,alu_sreg,alu_sreg,alu_sreg,alu_imm,alu_imm,alu_sreg,alu_sreg,multiple")]
a0f94409 1221)
1222
1223(define_peephole2
1224 [(match_scratch:SI 3 "r")
372575c7 1225 (set (match_operand:SI 0 "arm_general_register_operand" "")
a0f94409 1226 (minus:SI (match_operand:SI 1 "const_int_operand" "")
372575c7 1227 (match_operand:SI 2 "arm_general_register_operand" "")))]
25f905c2 1228 "TARGET_32BIT
a0f94409 1229 && !const_ok_for_arm (INTVAL (operands[1]))
1230 && const_ok_for_arm (~INTVAL (operands[1]))"
1231 [(set (match_dup 3) (match_dup 1))
1232 (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1233 ""
cffb2a26 1234)
b11cae9e 1235
62e39b06 1236(define_insn "subsi3_compare0"
bd5b4116 1237 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1238 (compare:CC_NOOV
65f68e55 1239 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,r,I")
1240 (match_operand:SI 2 "arm_rhs_operand" "I,r,r"))
215b30b3 1241 (const_int 0)))
65f68e55 1242 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9c08d1fa 1243 (minus:SI (match_dup 1) (match_dup 2)))]
25f905c2 1244 "TARGET_32BIT"
e2348bcb 1245 "@
3ef90e77 1246 subs%?\\t%0, %1, %2
1247 subs%?\\t%0, %1, %2
1248 rsbs%?\\t%0, %2, %1"
65f68e55 1249 [(set_attr "conds" "set")
112eda6f 1250 (set_attr "type" "alus_imm,alus_sreg,alus_sreg")]
cffb2a26 1251)
9c08d1fa 1252
190efb17 1253(define_insn "subsi3_compare"
080c0b9a 1254 [(set (reg:CC CC_REGNUM)
65f68e55 1255 (compare:CC (match_operand:SI 1 "arm_rhs_operand" "r,r,I")
1256 (match_operand:SI 2 "arm_rhs_operand" "I,r,r")))
1257 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2df9477b 1258 (minus:SI (match_dup 1) (match_dup 2)))]
1259 "TARGET_32BIT"
1260 "@
3ef90e77 1261 subs%?\\t%0, %1, %2
1262 subs%?\\t%0, %1, %2
1263 rsbs%?\\t%0, %2, %1"
65f68e55 1264 [(set_attr "conds" "set")
112eda6f 1265 (set_attr "type" "alus_imm,alus_sreg,alus_sreg")]
2df9477b 1266)
1267
604f3a0a 1268(define_expand "subsf3"
1269 [(set (match_operand:SF 0 "s_register_operand" "")
d86c91f6 1270 (minus:SF (match_operand:SF 1 "s_register_operand" "")
1271 (match_operand:SF 2 "s_register_operand" "")))]
25f905c2 1272 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1273 "
604f3a0a 1274")
1275
604f3a0a 1276(define_expand "subdf3"
1277 [(set (match_operand:DF 0 "s_register_operand" "")
d86c91f6 1278 (minus:DF (match_operand:DF 1 "s_register_operand" "")
1279 (match_operand:DF 2 "s_register_operand" "")))]
a50d7267 1280 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 1281 "
604f3a0a 1282")
1283
b11cae9e 1284\f
1285;; Multiplication insns
1286
4422d91f 1287(define_expand "mulhi3"
1288 [(set (match_operand:HI 0 "s_register_operand" "")
1289 (mult:HI (match_operand:HI 1 "s_register_operand" "")
1290 (match_operand:HI 2 "s_register_operand" "")))]
1291 "TARGET_DSP_MULTIPLY"
1292 "
1293 {
1294 rtx result = gen_reg_rtx (SImode);
1295 emit_insn (gen_mulhisi3 (result, operands[1], operands[2]));
1296 emit_move_insn (operands[0], gen_lowpart (HImode, result));
1297 DONE;
1298 }"
1299)
1300
cffb2a26 1301(define_expand "mulsi3"
1302 [(set (match_operand:SI 0 "s_register_operand" "")
1303 (mult:SI (match_operand:SI 2 "s_register_operand" "")
1304 (match_operand:SI 1 "s_register_operand" "")))]
1305 "TARGET_EITHER"
1306 ""
1307)
1308
9c08d1fa 1309;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
cffb2a26 1310(define_insn "*arm_mulsi3"
1311 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1312 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1313 (match_operand:SI 1 "s_register_operand" "%0,r")))]
58d7d654 1314 "TARGET_32BIT && !arm_arch6"
f7fbdd4a 1315 "mul%?\\t%0, %2, %1"
9da0ec36 1316 [(set_attr "type" "mul")
0d66636f 1317 (set_attr "predicable" "yes")]
cffb2a26 1318)
1319
58d7d654 1320(define_insn "*arm_mulsi3_v6"
d952d547 1321 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
1322 (mult:SI (match_operand:SI 1 "s_register_operand" "0,l,r")
1323 (match_operand:SI 2 "s_register_operand" "l,0,r")))]
58d7d654 1324 "TARGET_32BIT && arm_arch6"
1325 "mul%?\\t%0, %1, %2"
9da0ec36 1326 [(set_attr "type" "mul")
d952d547 1327 (set_attr "predicable" "yes")
1328 (set_attr "arch" "t2,t2,*")
1329 (set_attr "length" "4")
1330 (set_attr "predicable_short_it" "yes,yes,no")]
58d7d654 1331)
1332
f7fbdd4a 1333(define_insn "*mulsi3_compare0"
bd5b4116 1334 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1335 (compare:CC_NOOV (mult:SI
1336 (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1337 (match_operand:SI 1 "s_register_operand" "%0,r"))
9c08d1fa 1338 (const_int 0)))
1339 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1340 (mult:SI (match_dup 2) (match_dup 1)))]
58d7d654 1341 "TARGET_ARM && !arm_arch6"
3ef90e77 1342 "muls%?\\t%0, %2, %1"
58d7d654 1343 [(set_attr "conds" "set")
9da0ec36 1344 (set_attr "type" "muls")]
58d7d654 1345)
1346
1347(define_insn "*mulsi3_compare0_v6"
1348 [(set (reg:CC_NOOV CC_REGNUM)
1349 (compare:CC_NOOV (mult:SI
1350 (match_operand:SI 2 "s_register_operand" "r")
1351 (match_operand:SI 1 "s_register_operand" "r"))
1352 (const_int 0)))
1353 (set (match_operand:SI 0 "s_register_operand" "=r")
1354 (mult:SI (match_dup 2) (match_dup 1)))]
1355 "TARGET_ARM && arm_arch6 && optimize_size"
3ef90e77 1356 "muls%?\\t%0, %2, %1"
cffb2a26 1357 [(set_attr "conds" "set")
9da0ec36 1358 (set_attr "type" "muls")]
cffb2a26 1359)
9c08d1fa 1360
f7fbdd4a 1361(define_insn "*mulsi_compare0_scratch"
bd5b4116 1362 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1363 (compare:CC_NOOV (mult:SI
1364 (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1365 (match_operand:SI 1 "s_register_operand" "%0,r"))
9c08d1fa 1366 (const_int 0)))
1367 (clobber (match_scratch:SI 0 "=&r,&r"))]
58d7d654 1368 "TARGET_ARM && !arm_arch6"
3ef90e77 1369 "muls%?\\t%0, %2, %1"
58d7d654 1370 [(set_attr "conds" "set")
9da0ec36 1371 (set_attr "type" "muls")]
58d7d654 1372)
1373
1374(define_insn "*mulsi_compare0_scratch_v6"
1375 [(set (reg:CC_NOOV CC_REGNUM)
1376 (compare:CC_NOOV (mult:SI
1377 (match_operand:SI 2 "s_register_operand" "r")
1378 (match_operand:SI 1 "s_register_operand" "r"))
1379 (const_int 0)))
1380 (clobber (match_scratch:SI 0 "=r"))]
1381 "TARGET_ARM && arm_arch6 && optimize_size"
3ef90e77 1382 "muls%?\\t%0, %2, %1"
cffb2a26 1383 [(set_attr "conds" "set")
9da0ec36 1384 (set_attr "type" "muls")]
cffb2a26 1385)
9c08d1fa 1386
b11cae9e 1387;; Unnamed templates to match MLA instruction.
1388
f7fbdd4a 1389(define_insn "*mulsi3addsi"
9c08d1fa 1390 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
c8f69309 1391 (plus:SI
9c08d1fa 1392 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1393 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1394 (match_operand:SI 3 "s_register_operand" "r,r,0,0")))]
58d7d654 1395 "TARGET_32BIT && !arm_arch6"
1396 "mla%?\\t%0, %2, %1, %3"
9da0ec36 1397 [(set_attr "type" "mla")
58d7d654 1398 (set_attr "predicable" "yes")]
1399)
1400
1401(define_insn "*mulsi3addsi_v6"
1402 [(set (match_operand:SI 0 "s_register_operand" "=r")
1403 (plus:SI
1404 (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1405 (match_operand:SI 1 "s_register_operand" "r"))
1406 (match_operand:SI 3 "s_register_operand" "r")))]
1407 "TARGET_32BIT && arm_arch6"
f7fbdd4a 1408 "mla%?\\t%0, %2, %1, %3"
9da0ec36 1409 [(set_attr "type" "mla")
d952d547 1410 (set_attr "predicable" "yes")
1411 (set_attr "predicable_short_it" "no")]
0d66636f 1412)
b11cae9e 1413
f7fbdd4a 1414(define_insn "*mulsi3addsi_compare0"
bd5b4116 1415 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1416 (compare:CC_NOOV
1417 (plus:SI (mult:SI
1418 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1419 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1420 (match_operand:SI 3 "s_register_operand" "r,r,0,0"))
215b30b3 1421 (const_int 0)))
9c08d1fa 1422 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1423 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1424 (match_dup 3)))]
58d7d654 1425 "TARGET_ARM && arm_arch6"
3ef90e77 1426 "mlas%?\\t%0, %2, %1, %3"
58d7d654 1427 [(set_attr "conds" "set")
9da0ec36 1428 (set_attr "type" "mlas")]
58d7d654 1429)
1430
1431(define_insn "*mulsi3addsi_compare0_v6"
1432 [(set (reg:CC_NOOV CC_REGNUM)
1433 (compare:CC_NOOV
1434 (plus:SI (mult:SI
1435 (match_operand:SI 2 "s_register_operand" "r")
1436 (match_operand:SI 1 "s_register_operand" "r"))
1437 (match_operand:SI 3 "s_register_operand" "r"))
1438 (const_int 0)))
1439 (set (match_operand:SI 0 "s_register_operand" "=r")
1440 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1441 (match_dup 3)))]
1442 "TARGET_ARM && arm_arch6 && optimize_size"
3ef90e77 1443 "mlas%?\\t%0, %2, %1, %3"
0d66636f 1444 [(set_attr "conds" "set")
9da0ec36 1445 (set_attr "type" "mlas")]
0d66636f 1446)
9c08d1fa 1447
f7fbdd4a 1448(define_insn "*mulsi3addsi_compare0_scratch"
bd5b4116 1449 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1450 (compare:CC_NOOV
1451 (plus:SI (mult:SI
1452 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1453 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
215b30b3 1454 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1455 (const_int 0)))
9c08d1fa 1456 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
58d7d654 1457 "TARGET_ARM && !arm_arch6"
3ef90e77 1458 "mlas%?\\t%0, %2, %1, %3"
58d7d654 1459 [(set_attr "conds" "set")
9da0ec36 1460 (set_attr "type" "mlas")]
58d7d654 1461)
1462
1463(define_insn "*mulsi3addsi_compare0_scratch_v6"
1464 [(set (reg:CC_NOOV CC_REGNUM)
1465 (compare:CC_NOOV
1466 (plus:SI (mult:SI
1467 (match_operand:SI 2 "s_register_operand" "r")
1468 (match_operand:SI 1 "s_register_operand" "r"))
1469 (match_operand:SI 3 "s_register_operand" "r"))
1470 (const_int 0)))
1471 (clobber (match_scratch:SI 0 "=r"))]
1472 "TARGET_ARM && arm_arch6 && optimize_size"
3ef90e77 1473 "mlas%?\\t%0, %2, %1, %3"
cffb2a26 1474 [(set_attr "conds" "set")
9da0ec36 1475 (set_attr "type" "mlas")]
cffb2a26 1476)
f7fbdd4a 1477
89545238 1478(define_insn "*mulsi3subsi"
1479 [(set (match_operand:SI 0 "s_register_operand" "=r")
1480 (minus:SI
1481 (match_operand:SI 3 "s_register_operand" "r")
1482 (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1483 (match_operand:SI 1 "s_register_operand" "r"))))]
1484 "TARGET_32BIT && arm_arch_thumb2"
1485 "mls%?\\t%0, %2, %1, %3"
9da0ec36 1486 [(set_attr "type" "mla")
d952d547 1487 (set_attr "predicable" "yes")
1488 (set_attr "predicable_short_it" "no")]
89545238 1489)
1490
5cdca009 1491(define_expand "maddsidi4"
1492 [(set (match_operand:DI 0 "s_register_operand" "")
1493 (plus:DI
1494 (mult:DI
1495 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1496 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1497 (match_operand:DI 3 "s_register_operand" "")))]
1498 "TARGET_32BIT && arm_arch3m"
1499 "")
82b85d08 1500
1501(define_insn "*mulsidi3adddi"
fe8dbf85 1502 [(set (match_operand:DI 0 "s_register_operand" "=&r")
82b85d08 1503 (plus:DI
215b30b3 1504 (mult:DI
fe8dbf85 1505 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1506 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1507 (match_operand:DI 1 "s_register_operand" "0")))]
58d7d654 1508 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1509 "smlal%?\\t%Q0, %R0, %3, %2"
9da0ec36 1510 [(set_attr "type" "smlal")
58d7d654 1511 (set_attr "predicable" "yes")]
1512)
1513
1514(define_insn "*mulsidi3adddi_v6"
1515 [(set (match_operand:DI 0 "s_register_operand" "=r")
1516 (plus:DI
1517 (mult:DI
1518 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1519 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1520 (match_operand:DI 1 "s_register_operand" "0")))]
1521 "TARGET_32BIT && arm_arch6"
fe8dbf85 1522 "smlal%?\\t%Q0, %R0, %3, %2"
9da0ec36 1523 [(set_attr "type" "smlal")
d952d547 1524 (set_attr "predicable" "yes")
1525 (set_attr "predicable_short_it" "no")]
0d66636f 1526)
82b85d08 1527
957788b0 1528;; 32x32->64 widening multiply.
1529;; As with mulsi3, the only difference between the v3-5 and v6+
1530;; versions of these patterns is the requirement that the output not
1531;; overlap the inputs, but that still means we have to have a named
1532;; expander and two different starred insns.
1533
1534(define_expand "mulsidi3"
1535 [(set (match_operand:DI 0 "s_register_operand" "")
1536 (mult:DI
1537 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1538 (sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1539 "TARGET_32BIT && arm_arch3m"
1540 ""
1541)
1542
1543(define_insn "*mulsidi3_nov6"
f7fbdd4a 1544 [(set (match_operand:DI 0 "s_register_operand" "=&r")
215b30b3 1545 (mult:DI
1546 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1547 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
58d7d654 1548 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1549 "smull%?\\t%Q0, %R0, %1, %2"
9da0ec36 1550 [(set_attr "type" "smull")
58d7d654 1551 (set_attr "predicable" "yes")]
1552)
1553
957788b0 1554(define_insn "*mulsidi3_v6"
58d7d654 1555 [(set (match_operand:DI 0 "s_register_operand" "=r")
1556 (mult:DI
1557 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1558 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1559 "TARGET_32BIT && arm_arch6"
97499065 1560 "smull%?\\t%Q0, %R0, %1, %2"
9da0ec36 1561 [(set_attr "type" "smull")
d952d547 1562 (set_attr "predicable" "yes")
1563 (set_attr "predicable_short_it" "no")]
0d66636f 1564)
f7fbdd4a 1565
957788b0 1566(define_expand "umulsidi3"
1567 [(set (match_operand:DI 0 "s_register_operand" "")
1568 (mult:DI
1569 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1570 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1571 "TARGET_32BIT && arm_arch3m"
1572 ""
1573)
1574
1575(define_insn "*umulsidi3_nov6"
f7fbdd4a 1576 [(set (match_operand:DI 0 "s_register_operand" "=&r")
215b30b3 1577 (mult:DI
1578 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1579 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
58d7d654 1580 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1581 "umull%?\\t%Q0, %R0, %1, %2"
9da0ec36 1582 [(set_attr "type" "umull")
58d7d654 1583 (set_attr "predicable" "yes")]
1584)
1585
957788b0 1586(define_insn "*umulsidi3_v6"
58d7d654 1587 [(set (match_operand:DI 0 "s_register_operand" "=r")
1588 (mult:DI
1589 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1590 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1591 "TARGET_32BIT && arm_arch6"
97499065 1592 "umull%?\\t%Q0, %R0, %1, %2"
9da0ec36 1593 [(set_attr "type" "umull")
d952d547 1594 (set_attr "predicable" "yes")
1595 (set_attr "predicable_short_it" "no")]
0d66636f 1596)
b11cae9e 1597
5cdca009 1598(define_expand "umaddsidi4"
1599 [(set (match_operand:DI 0 "s_register_operand" "")
1600 (plus:DI
1601 (mult:DI
1602 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1603 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1604 (match_operand:DI 3 "s_register_operand" "")))]
1605 "TARGET_32BIT && arm_arch3m"
1606 "")
82b85d08 1607
1608(define_insn "*umulsidi3adddi"
8ead09f9 1609 [(set (match_operand:DI 0 "s_register_operand" "=&r")
82b85d08 1610 (plus:DI
215b30b3 1611 (mult:DI
fe8dbf85 1612 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1613 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1614 (match_operand:DI 1 "s_register_operand" "0")))]
58d7d654 1615 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1616 "umlal%?\\t%Q0, %R0, %3, %2"
9da0ec36 1617 [(set_attr "type" "umlal")
58d7d654 1618 (set_attr "predicable" "yes")]
1619)
1620
1621(define_insn "*umulsidi3adddi_v6"
1622 [(set (match_operand:DI 0 "s_register_operand" "=r")
1623 (plus:DI
1624 (mult:DI
1625 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1626 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1627 (match_operand:DI 1 "s_register_operand" "0")))]
1628 "TARGET_32BIT && arm_arch6"
fe8dbf85 1629 "umlal%?\\t%Q0, %R0, %3, %2"
9da0ec36 1630 [(set_attr "type" "umlal")
d952d547 1631 (set_attr "predicable" "yes")
1632 (set_attr "predicable_short_it" "no")]
0d66636f 1633)
82b85d08 1634
957788b0 1635(define_expand "smulsi3_highpart"
1636 [(parallel
1637 [(set (match_operand:SI 0 "s_register_operand" "")
1638 (truncate:SI
1639 (lshiftrt:DI
1640 (mult:DI
1641 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1642 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1643 (const_int 32))))
1644 (clobber (match_scratch:SI 3 ""))])]
1645 "TARGET_32BIT && arm_arch3m"
1646 ""
1647)
1648
1649(define_insn "*smulsi3_highpart_nov6"
f082f1c4 1650 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1651 (truncate:SI
1652 (lshiftrt:DI
215b30b3 1653 (mult:DI
e5fea38e 1654 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
215b30b3 1655 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
f082f1c4 1656 (const_int 32))))
1657 (clobber (match_scratch:SI 3 "=&r,&r"))]
58d7d654 1658 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1659 "smull%?\\t%3, %0, %2, %1"
9da0ec36 1660 [(set_attr "type" "smull")
58d7d654 1661 (set_attr "predicable" "yes")]
1662)
1663
957788b0 1664(define_insn "*smulsi3_highpart_v6"
58d7d654 1665 [(set (match_operand:SI 0 "s_register_operand" "=r")
1666 (truncate:SI
1667 (lshiftrt:DI
1668 (mult:DI
1669 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1670 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1671 (const_int 32))))
1672 (clobber (match_scratch:SI 3 "=r"))]
1673 "TARGET_32BIT && arm_arch6"
f082f1c4 1674 "smull%?\\t%3, %0, %2, %1"
9da0ec36 1675 [(set_attr "type" "smull")
d952d547 1676 (set_attr "predicable" "yes")
1677 (set_attr "predicable_short_it" "no")]
cffb2a26 1678)
f082f1c4 1679
957788b0 1680(define_expand "umulsi3_highpart"
1681 [(parallel
1682 [(set (match_operand:SI 0 "s_register_operand" "")
1683 (truncate:SI
1684 (lshiftrt:DI
1685 (mult:DI
1686 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1687 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1688 (const_int 32))))
1689 (clobber (match_scratch:SI 3 ""))])]
1690 "TARGET_32BIT && arm_arch3m"
1691 ""
1692)
1693
1694(define_insn "*umulsi3_highpart_nov6"
f082f1c4 1695 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1696 (truncate:SI
1697 (lshiftrt:DI
215b30b3 1698 (mult:DI
e5fea38e 1699 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
215b30b3 1700 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
f082f1c4 1701 (const_int 32))))
1702 (clobber (match_scratch:SI 3 "=&r,&r"))]
58d7d654 1703 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1704 "umull%?\\t%3, %0, %2, %1"
9da0ec36 1705 [(set_attr "type" "umull")
58d7d654 1706 (set_attr "predicable" "yes")]
1707)
1708
957788b0 1709(define_insn "*umulsi3_highpart_v6"
58d7d654 1710 [(set (match_operand:SI 0 "s_register_operand" "=r")
1711 (truncate:SI
1712 (lshiftrt:DI
1713 (mult:DI
1714 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1715 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1716 (const_int 32))))
1717 (clobber (match_scratch:SI 3 "=r"))]
1718 "TARGET_32BIT && arm_arch6"
f082f1c4 1719 "umull%?\\t%3, %0, %2, %1"
9da0ec36 1720 [(set_attr "type" "umull")
d952d547 1721 (set_attr "predicable" "yes")
1722 (set_attr "predicable_short_it" "no")]
cffb2a26 1723)
f082f1c4 1724
331beb1a 1725(define_insn "mulhisi3"
1726 [(set (match_operand:SI 0 "s_register_operand" "=r")
1727 (mult:SI (sign_extend:SI
1728 (match_operand:HI 1 "s_register_operand" "%r"))
1729 (sign_extend:SI
1730 (match_operand:HI 2 "s_register_operand" "r"))))]
25f905c2 1731 "TARGET_DSP_MULTIPLY"
61a2d04c 1732 "smulbb%?\\t%0, %1, %2"
9da0ec36 1733 [(set_attr "type" "smulxy")
fec538d9 1734 (set_attr "predicable" "yes")]
1735)
1736
1737(define_insn "*mulhisi3tb"
1738 [(set (match_operand:SI 0 "s_register_operand" "=r")
1739 (mult:SI (ashiftrt:SI
1740 (match_operand:SI 1 "s_register_operand" "r")
1741 (const_int 16))
1742 (sign_extend:SI
1743 (match_operand:HI 2 "s_register_operand" "r"))))]
25f905c2 1744 "TARGET_DSP_MULTIPLY"
fec538d9 1745 "smultb%?\\t%0, %1, %2"
9da0ec36 1746 [(set_attr "type" "smulxy")
d952d547 1747 (set_attr "predicable" "yes")
1748 (set_attr "predicable_short_it" "no")]
fec538d9 1749)
1750
1751(define_insn "*mulhisi3bt"
1752 [(set (match_operand:SI 0 "s_register_operand" "=r")
1753 (mult:SI (sign_extend:SI
1754 (match_operand:HI 1 "s_register_operand" "r"))
1755 (ashiftrt:SI
1756 (match_operand:SI 2 "s_register_operand" "r")
1757 (const_int 16))))]
25f905c2 1758 "TARGET_DSP_MULTIPLY"
fec538d9 1759 "smulbt%?\\t%0, %1, %2"
9da0ec36 1760 [(set_attr "type" "smulxy")
d952d547 1761 (set_attr "predicable" "yes")
1762 (set_attr "predicable_short_it" "no")]
fec538d9 1763)
1764
1765(define_insn "*mulhisi3tt"
1766 [(set (match_operand:SI 0 "s_register_operand" "=r")
1767 (mult:SI (ashiftrt:SI
1768 (match_operand:SI 1 "s_register_operand" "r")
1769 (const_int 16))
1770 (ashiftrt:SI
1771 (match_operand:SI 2 "s_register_operand" "r")
1772 (const_int 16))))]
25f905c2 1773 "TARGET_DSP_MULTIPLY"
fec538d9 1774 "smultt%?\\t%0, %1, %2"
9da0ec36 1775 [(set_attr "type" "smulxy")
d952d547 1776 (set_attr "predicable" "yes")
1777 (set_attr "predicable_short_it" "no")]
331beb1a 1778)
1779
5cdca009 1780(define_insn "maddhisi4"
331beb1a 1781 [(set (match_operand:SI 0 "s_register_operand" "=r")
cfa6c608 1782 (plus:SI (mult:SI (sign_extend:SI
1783 (match_operand:HI 1 "s_register_operand" "r"))
331beb1a 1784 (sign_extend:SI
cfa6c608 1785 (match_operand:HI 2 "s_register_operand" "r")))
1786 (match_operand:SI 3 "s_register_operand" "r")))]
25f905c2 1787 "TARGET_DSP_MULTIPLY"
5cdca009 1788 "smlabb%?\\t%0, %1, %2, %3"
9da0ec36 1789 [(set_attr "type" "smlaxy")
d952d547 1790 (set_attr "predicable" "yes")
1791 (set_attr "predicable_short_it" "no")]
331beb1a 1792)
1793
9a92f368 1794;; Note: there is no maddhisi4ibt because this one is canonical form
1795(define_insn "*maddhisi4tb"
1796 [(set (match_operand:SI 0 "s_register_operand" "=r")
1797 (plus:SI (mult:SI (ashiftrt:SI
1798 (match_operand:SI 1 "s_register_operand" "r")
1799 (const_int 16))
1800 (sign_extend:SI
1801 (match_operand:HI 2 "s_register_operand" "r")))
1802 (match_operand:SI 3 "s_register_operand" "r")))]
1803 "TARGET_DSP_MULTIPLY"
1804 "smlatb%?\\t%0, %1, %2, %3"
9da0ec36 1805 [(set_attr "type" "smlaxy")
d952d547 1806 (set_attr "predicable" "yes")
1807 (set_attr "predicable_short_it" "no")]
9a92f368 1808)
1809
1810(define_insn "*maddhisi4tt"
1811 [(set (match_operand:SI 0 "s_register_operand" "=r")
1812 (plus:SI (mult:SI (ashiftrt:SI
1813 (match_operand:SI 1 "s_register_operand" "r")
1814 (const_int 16))
1815 (ashiftrt:SI
1816 (match_operand:SI 2 "s_register_operand" "r")
1817 (const_int 16)))
1818 (match_operand:SI 3 "s_register_operand" "r")))]
1819 "TARGET_DSP_MULTIPLY"
1820 "smlatt%?\\t%0, %1, %2, %3"
9da0ec36 1821 [(set_attr "type" "smlaxy")
d952d547 1822 (set_attr "predicable" "yes")
1823 (set_attr "predicable_short_it" "no")]
9a92f368 1824)
1825
aff5fb4d 1826(define_insn "maddhidi4"
331beb1a 1827 [(set (match_operand:DI 0 "s_register_operand" "=r")
1828 (plus:DI
331beb1a 1829 (mult:DI (sign_extend:DI
d952d547 1830 (match_operand:HI 1 "s_register_operand" "r"))
331beb1a 1831 (sign_extend:DI
cfa6c608 1832 (match_operand:HI 2 "s_register_operand" "r")))
1833 (match_operand:DI 3 "s_register_operand" "0")))]
25f905c2 1834 "TARGET_DSP_MULTIPLY"
5cdca009 1835 "smlalbb%?\\t%Q0, %R0, %1, %2"
9da0ec36 1836 [(set_attr "type" "smlalxy")
d952d547 1837 (set_attr "predicable" "yes")
1838 (set_attr "predicable_short_it" "no")])
331beb1a 1839
9a92f368 1840;; Note: there is no maddhidi4ibt because this one is canonical form
1841(define_insn "*maddhidi4tb"
1842 [(set (match_operand:DI 0 "s_register_operand" "=r")
1843 (plus:DI
1844 (mult:DI (sign_extend:DI
1845 (ashiftrt:SI
1846 (match_operand:SI 1 "s_register_operand" "r")
1847 (const_int 16)))
1848 (sign_extend:DI
1849 (match_operand:HI 2 "s_register_operand" "r")))
1850 (match_operand:DI 3 "s_register_operand" "0")))]
1851 "TARGET_DSP_MULTIPLY"
1852 "smlaltb%?\\t%Q0, %R0, %1, %2"
9da0ec36 1853 [(set_attr "type" "smlalxy")
d952d547 1854 (set_attr "predicable" "yes")
1855 (set_attr "predicable_short_it" "no")])
9a92f368 1856
1857(define_insn "*maddhidi4tt"
1858 [(set (match_operand:DI 0 "s_register_operand" "=r")
1859 (plus:DI
1860 (mult:DI (sign_extend:DI
1861 (ashiftrt:SI
1862 (match_operand:SI 1 "s_register_operand" "r")
1863 (const_int 16)))
1864 (sign_extend:DI
1865 (ashiftrt:SI
1866 (match_operand:SI 2 "s_register_operand" "r")
1867 (const_int 16))))
1868 (match_operand:DI 3 "s_register_operand" "0")))]
1869 "TARGET_DSP_MULTIPLY"
1870 "smlaltt%?\\t%Q0, %R0, %1, %2"
9da0ec36 1871 [(set_attr "type" "smlalxy")
d952d547 1872 (set_attr "predicable" "yes")
1873 (set_attr "predicable_short_it" "no")])
9a92f368 1874
604f3a0a 1875(define_expand "mulsf3"
1876 [(set (match_operand:SF 0 "s_register_operand" "")
1877 (mult:SF (match_operand:SF 1 "s_register_operand" "")
d86c91f6 1878 (match_operand:SF 2 "s_register_operand" "")))]
25f905c2 1879 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1880 "
604f3a0a 1881")
1882
604f3a0a 1883(define_expand "muldf3"
1884 [(set (match_operand:DF 0 "s_register_operand" "")
1885 (mult:DF (match_operand:DF 1 "s_register_operand" "")
d86c91f6 1886 (match_operand:DF 2 "s_register_operand" "")))]
a50d7267 1887 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 1888 "
604f3a0a 1889")
b11cae9e 1890\f
1891;; Division insns
1892
7db9af5d 1893(define_expand "divsf3"
1894 [(set (match_operand:SF 0 "s_register_operand" "")
d86c91f6 1895 (div:SF (match_operand:SF 1 "s_register_operand" "")
1896 (match_operand:SF 2 "s_register_operand" "")))]
994606f8 1897 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
7db9af5d 1898 "")
9c08d1fa 1899
7db9af5d 1900(define_expand "divdf3"
1901 [(set (match_operand:DF 0 "s_register_operand" "")
d86c91f6 1902 (div:DF (match_operand:DF 1 "s_register_operand" "")
1903 (match_operand:DF 2 "s_register_operand" "")))]
994606f8 1904 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
7db9af5d 1905 "")
b11cae9e 1906\f
1907;; Boolean and,ior,xor insns
1908
f6ebffac 1909;; Split up double word logical operations
1910
1911;; Split up simple DImode logical operations. Simply perform the logical
1912;; operation on the upper and lower halves of the registers.
1913(define_split
1914 [(set (match_operand:DI 0 "s_register_operand" "")
1915 (match_operator:DI 6 "logical_binary_operator"
1916 [(match_operand:DI 1 "s_register_operand" "")
1917 (match_operand:DI 2 "s_register_operand" "")]))]
25f905c2 1918 "TARGET_32BIT && reload_completed
e2669ea7 1919 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))
25f905c2 1920 && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
f6ebffac 1921 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1922 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1923 "
215b30b3 1924 {
1925 operands[3] = gen_highpart (SImode, operands[0]);
1926 operands[0] = gen_lowpart (SImode, operands[0]);
1927 operands[4] = gen_highpart (SImode, operands[1]);
1928 operands[1] = gen_lowpart (SImode, operands[1]);
1929 operands[5] = gen_highpart (SImode, operands[2]);
1930 operands[2] = gen_lowpart (SImode, operands[2]);
1931 }"
1932)
f6ebffac 1933
f6ebffac 1934(define_split
1935 [(set (match_operand:DI 0 "s_register_operand" "")
1936 (match_operator:DI 6 "logical_binary_operator"
1937 [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1938 (match_operand:DI 1 "s_register_operand" "")]))]
25f905c2 1939 "TARGET_32BIT && reload_completed"
f6ebffac 1940 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1941 (set (match_dup 3) (match_op_dup:SI 6
1942 [(ashiftrt:SI (match_dup 2) (const_int 31))
1943 (match_dup 4)]))]
1944 "
215b30b3 1945 {
1946 operands[3] = gen_highpart (SImode, operands[0]);
1947 operands[0] = gen_lowpart (SImode, operands[0]);
1948 operands[4] = gen_highpart (SImode, operands[1]);
1949 operands[1] = gen_lowpart (SImode, operands[1]);
1950 operands[5] = gen_highpart (SImode, operands[2]);
1951 operands[2] = gen_lowpart (SImode, operands[2]);
1952 }"
1953)
f6ebffac 1954
f6ebffac 1955;; The zero extend of operand 2 means we can just copy the high part of
1956;; operand1 into operand0.
1957(define_split
1958 [(set (match_operand:DI 0 "s_register_operand" "")
1959 (ior:DI
1960 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1961 (match_operand:DI 1 "s_register_operand" "")))]
25f905c2 1962 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
f6ebffac 1963 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1964 (set (match_dup 3) (match_dup 4))]
1965 "
215b30b3 1966 {
1967 operands[4] = gen_highpart (SImode, operands[1]);
1968 operands[3] = gen_highpart (SImode, operands[0]);
1969 operands[0] = gen_lowpart (SImode, operands[0]);
1970 operands[1] = gen_lowpart (SImode, operands[1]);
1971 }"
1972)
f6ebffac 1973
1974;; The zero extend of operand 2 means we can just copy the high part of
1975;; operand1 into operand0.
1976(define_split
1977 [(set (match_operand:DI 0 "s_register_operand" "")
1978 (xor:DI
1979 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1980 (match_operand:DI 1 "s_register_operand" "")))]
25f905c2 1981 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
f6ebffac 1982 [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1983 (set (match_dup 3) (match_dup 4))]
1984 "
215b30b3 1985 {
1986 operands[4] = gen_highpart (SImode, operands[1]);
1987 operands[3] = gen_highpart (SImode, operands[0]);
1988 operands[0] = gen_lowpart (SImode, operands[0]);
1989 operands[1] = gen_lowpart (SImode, operands[1]);
1990 }"
1991)
f6ebffac 1992
e2669ea7 1993(define_expand "anddi3"
1994 [(set (match_operand:DI 0 "s_register_operand" "")
1995 (and:DI (match_operand:DI 1 "s_register_operand" "")
1996 (match_operand:DI 2 "neon_inv_logic_op2" "")))]
1997 "TARGET_32BIT"
1998 ""
1999)
2000
f6bbdcf6 2001(define_insn_and_split "*anddi3_insn"
0a314dcd 2002 [(set (match_operand:DI 0 "s_register_operand" "=w,w ,&r,&r,&r,&r,?w,?w")
2003 (and:DI (match_operand:DI 1 "s_register_operand" "%w,0 ,0 ,r ,0 ,r ,w ,0")
2004 (match_operand:DI 2 "arm_anddi_operand_neon" "w ,DL,r ,r ,De,De,w ,DL")))]
f6bbdcf6 2005 "TARGET_32BIT && !TARGET_IWMMXT"
2006{
2007 switch (which_alternative)
2008 {
0a314dcd 2009 case 0: /* fall through */
2010 case 6: return "vand\t%P0, %P1, %P2";
2011 case 1: /* fall through */
2012 case 7: return neon_output_logic_immediate ("vand", &operands[2],
2013 DImode, 1, VALID_NEON_QREG_MODE (DImode));
f6bbdcf6 2014 case 2:
0a314dcd 2015 case 3:
2016 case 4:
f6bbdcf6 2017 case 5: /* fall through */
0a314dcd 2018 return "#";
f6bbdcf6 2019 default: gcc_unreachable ();
2020 }
2021}
0a314dcd 2022 "TARGET_32BIT && !TARGET_IWMMXT && reload_completed
2023 && !(IS_VFP_REGNUM (REGNO (operands[0])))"
f6bbdcf6 2024 [(set (match_dup 3) (match_dup 4))
2025 (set (match_dup 5) (match_dup 6))]
2026 "
2027 {
2028 operands[3] = gen_lowpart (SImode, operands[0]);
2029 operands[5] = gen_highpart (SImode, operands[0]);
2030
2031 operands[4] = simplify_gen_binary (AND, SImode,
2032 gen_lowpart (SImode, operands[1]),
2033 gen_lowpart (SImode, operands[2]));
2034 operands[6] = simplify_gen_binary (AND, SImode,
2035 gen_highpart (SImode, operands[1]),
2036 gen_highpart_mode (SImode, DImode, operands[2]));
2037
2038 }"
32093010 2039 [(set_attr "type" "neon_logic,neon_logic,multiple,multiple,\
2040 multiple,multiple,neon_logic,neon_logic")
0a314dcd 2041 (set_attr "arch" "neon_for_64bits,neon_for_64bits,*,*,*,*,
f6bbdcf6 2042 avoid_neon_for_64bits,avoid_neon_for_64bits")
0a314dcd 2043 (set_attr "length" "*,*,8,8,8,8,*,*")
2044 ]
215b30b3 2045)
b11cae9e 2046
a0f94409 2047(define_insn_and_split "*anddi_zesidi_di"
9c08d1fa 2048 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2049 (and:DI (zero_extend:DI
2050 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 2051 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2052 "TARGET_32BIT"
f6ebffac 2053 "#"
25f905c2 2054 "TARGET_32BIT && reload_completed"
a0f94409 2055 ; The zero extend of operand 2 clears the high word of the output
2056 ; operand.
2057 [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
2058 (set (match_dup 3) (const_int 0))]
2059 "
2060 {
2061 operands[3] = gen_highpart (SImode, operands[0]);
2062 operands[0] = gen_lowpart (SImode, operands[0]);
2063 operands[1] = gen_lowpart (SImode, operands[1]);
2064 }"
1b7da4ac 2065 [(set_attr "length" "8")
2066 (set_attr "type" "multiple")]
215b30b3 2067)
b11cae9e 2068
f7fbdd4a 2069(define_insn "*anddi_sesdi_di"
cffb2a26 2070 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 2071 (and:DI (sign_extend:DI
2072 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 2073 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2074 "TARGET_32BIT"
f6ebffac 2075 "#"
1b7da4ac 2076 [(set_attr "length" "8")
2077 (set_attr "type" "multiple")]
cffb2a26 2078)
b11cae9e 2079
87b22bf7 2080(define_expand "andsi3"
cffb2a26 2081 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2082 (and:SI (match_operand:SI 1 "s_register_operand" "")
2083 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 2084 "TARGET_EITHER"
87b22bf7 2085 "
25f905c2 2086 if (TARGET_32BIT)
87b22bf7 2087 {
0438d37f 2088 if (CONST_INT_P (operands[2]))
cffb2a26 2089 {
47b5b27b 2090 if (INTVAL (operands[2]) == 255 && arm_arch6)
2091 {
2092 operands[1] = convert_to_mode (QImode, operands[1], 1);
2093 emit_insn (gen_thumb2_zero_extendqisi2_v6 (operands[0],
2094 operands[1]));
17202aa5 2095 DONE;
47b5b27b 2096 }
17202aa5 2097 else if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[2]), AND))
2098 operands[2] = force_reg (SImode, operands[2]);
47b5b27b 2099 else
17202aa5 2100 {
2101 arm_split_constant (AND, SImode, NULL_RTX,
2102 INTVAL (operands[2]), operands[0],
2103 operands[1],
2104 optimize && can_create_pseudo_p ());
615caa51 2105
17202aa5 2106 DONE;
2107 }
cffb2a26 2108 }
87b22bf7 2109 }
25f905c2 2110 else /* TARGET_THUMB1 */
cffb2a26 2111 {
0438d37f 2112 if (!CONST_INT_P (operands[2]))
923ffadb 2113 {
2114 rtx tmp = force_reg (SImode, operands[2]);
2115 if (rtx_equal_p (operands[0], operands[1]))
2116 operands[2] = tmp;
2117 else
2118 {
2119 operands[2] = operands[1];
2120 operands[1] = tmp;
2121 }
2122 }
cffb2a26 2123 else
2124 {
2125 int i;
2126
215b30b3 2127 if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
cffb2a26 2128 {
215b30b3 2129 operands[2] = force_reg (SImode,
2130 GEN_INT (~INTVAL (operands[2])));
cffb2a26 2131
747b7458 2132 emit_insn (gen_thumb1_bicsi3 (operands[0], operands[2], operands[1]));
cffb2a26 2133
2134 DONE;
2135 }
87b22bf7 2136
cffb2a26 2137 for (i = 9; i <= 31; i++)
2138 {
2139 if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
2140 {
2141 emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
2142 const0_rtx));
2143 DONE;
2144 }
215b30b3 2145 else if ((((HOST_WIDE_INT) 1) << i) - 1
2146 == ~INTVAL (operands[2]))
cffb2a26 2147 {
2148 rtx shift = GEN_INT (i);
2149 rtx reg = gen_reg_rtx (SImode);
2150
2151 emit_insn (gen_lshrsi3 (reg, operands[1], shift));
2152 emit_insn (gen_ashlsi3 (operands[0], reg, shift));
2153
2154 DONE;
2155 }
2156 }
2157
2158 operands[2] = force_reg (SImode, operands[2]);
2159 }
215b30b3 2160 }
2161 "
cffb2a26 2162)
2163
25f905c2 2164; ??? Check split length for Thumb-2
a0f94409 2165(define_insn_and_split "*arm_andsi3_insn"
29e234a3 2166 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r,r,r")
2167 (and:SI (match_operand:SI 1 "s_register_operand" "%r,0,r,r,r")
2168 (match_operand:SI 2 "reg_or_int_operand" "I,l,K,r,?n")))]
25f905c2 2169 "TARGET_32BIT"
5565501b 2170 "@
29e234a3 2171 and%?\\t%0, %1, %2
5565501b 2172 and%?\\t%0, %1, %2
87b22bf7 2173 bic%?\\t%0, %1, #%B2
65f68e55 2174 and%?\\t%0, %1, %2
87b22bf7 2175 #"
25f905c2 2176 "TARGET_32BIT
0438d37f 2177 && CONST_INT_P (operands[2])
a0f94409 2178 && !(const_ok_for_arm (INTVAL (operands[2]))
2179 || const_ok_for_arm (~INTVAL (operands[2])))"
2180 [(clobber (const_int 0))]
2181 "
96f57e36 2182 arm_split_constant (AND, SImode, curr_insn,
2183 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 2184 DONE;
2185 "
29e234a3 2186 [(set_attr "length" "4,4,4,4,16")
65f68e55 2187 (set_attr "predicable" "yes")
29e234a3 2188 (set_attr "predicable_short_it" "no,yes,no,no,no")
d82e788e 2189 (set_attr "type" "logic_imm,logic_imm,logic_reg,logic_reg,logic_imm")]
cffb2a26 2190)
2191
f7fbdd4a 2192(define_insn "*andsi3_compare0"
bd5b4116 2193 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 2194 (compare:CC_NOOV
65f68e55 2195 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
2196 (match_operand:SI 2 "arm_not_operand" "I,K,r"))
5565501b 2197 (const_int 0)))
65f68e55 2198 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9c08d1fa 2199 (and:SI (match_dup 1) (match_dup 2)))]
25f905c2 2200 "TARGET_32BIT"
5565501b 2201 "@
3ef90e77 2202 ands%?\\t%0, %1, %2
2203 bics%?\\t%0, %1, #%B2
2204 ands%?\\t%0, %1, %2"
65f68e55 2205 [(set_attr "conds" "set")
d82e788e 2206 (set_attr "type" "logics_imm,logics_imm,logics_reg")]
cffb2a26 2207)
9c08d1fa 2208
f7fbdd4a 2209(define_insn "*andsi3_compare0_scratch"
bd5b4116 2210 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 2211 (compare:CC_NOOV
65f68e55 2212 (and:SI (match_operand:SI 0 "s_register_operand" "r,r,r")
2213 (match_operand:SI 1 "arm_not_operand" "I,K,r"))
5565501b 2214 (const_int 0)))
65f68e55 2215 (clobber (match_scratch:SI 2 "=X,r,X"))]
25f905c2 2216 "TARGET_32BIT"
5565501b 2217 "@
2218 tst%?\\t%0, %1
3ef90e77 2219 bics%?\\t%2, %0, #%B1
65f68e55 2220 tst%?\\t%0, %1"
2221 [(set_attr "conds" "set")
d82e788e 2222 (set_attr "type" "logics_imm,logics_imm,logics_reg")]
0d66636f 2223)
9c08d1fa 2224
f7fbdd4a 2225(define_insn "*zeroextractsi_compare0_scratch"
bd5b4116 2226 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2227 (compare:CC_NOOV (zero_extract:SI
2228 (match_operand:SI 0 "s_register_operand" "r")
d952d547 2229 (match_operand 1 "const_int_operand" "n")
206ee9a2 2230 (match_operand 2 "const_int_operand" "n"))
9c08d1fa 2231 (const_int 0)))]
25f905c2 2232 "TARGET_32BIT
cffb2a26 2233 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
2234 && INTVAL (operands[1]) > 0
2235 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
2236 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
9c08d1fa 2237 "*
5c49a439 2238 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
2239 << INTVAL (operands[2]));
40dbec34 2240 output_asm_insn (\"tst%?\\t%0, %1\", operands);
e2348bcb 2241 return \"\";
0d66636f 2242 "
596e5e8f 2243 [(set_attr "conds" "set")
65f68e55 2244 (set_attr "predicable" "yes")
d952d547 2245 (set_attr "predicable_short_it" "no")
d82e788e 2246 (set_attr "type" "logics_imm")]
0d66636f 2247)
9c08d1fa 2248
f4462328 2249(define_insn_and_split "*ne_zeroextractsi"
c4034607 2250 [(set (match_operand:SI 0 "s_register_operand" "=r")
2251 (ne:SI (zero_extract:SI
2252 (match_operand:SI 1 "s_register_operand" "r")
2253 (match_operand:SI 2 "const_int_operand" "n")
2254 (match_operand:SI 3 "const_int_operand" "n"))
3b8c7f7a 2255 (const_int 0)))
2256 (clobber (reg:CC CC_REGNUM))]
25f905c2 2257 "TARGET_32BIT
cffb2a26 2258 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2259 && INTVAL (operands[2]) > 0
2260 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2261 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
f4462328 2262 "#"
25f905c2 2263 "TARGET_32BIT
f4462328 2264 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2265 && INTVAL (operands[2]) > 0
2266 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2267 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
2268 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2269 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2270 (const_int 0)))
2271 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2272 (set (match_dup 0)
2273 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2274 (match_dup 0) (const_int 1)))]
2275 "
2276 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
2277 << INTVAL (operands[3]));
2278 "
2279 [(set_attr "conds" "clob")
25f905c2 2280 (set (attr "length")
2281 (if_then_else (eq_attr "is_thumb" "yes")
2282 (const_int 12)
1b7da4ac 2283 (const_int 8)))
2284 (set_attr "type" "multiple")]
f4462328 2285)
2286
2287(define_insn_and_split "*ne_zeroextractsi_shifted"
2288 [(set (match_operand:SI 0 "s_register_operand" "=r")
2289 (ne:SI (zero_extract:SI
2290 (match_operand:SI 1 "s_register_operand" "r")
2291 (match_operand:SI 2 "const_int_operand" "n")
2292 (const_int 0))
2293 (const_int 0)))
2294 (clobber (reg:CC CC_REGNUM))]
2295 "TARGET_ARM"
2296 "#"
2297 "TARGET_ARM"
2298 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2299 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2300 (const_int 0)))
2301 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2302 (set (match_dup 0)
2303 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2304 (match_dup 0) (const_int 1)))]
2305 "
2306 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
2307 "
2308 [(set_attr "conds" "clob")
1b7da4ac 2309 (set_attr "length" "8")
2310 (set_attr "type" "multiple")]
f4462328 2311)
2312
2313(define_insn_and_split "*ite_ne_zeroextractsi"
2314 [(set (match_operand:SI 0 "s_register_operand" "=r")
2315 (if_then_else:SI (ne (zero_extract:SI
2316 (match_operand:SI 1 "s_register_operand" "r")
2317 (match_operand:SI 2 "const_int_operand" "n")
2318 (match_operand:SI 3 "const_int_operand" "n"))
2319 (const_int 0))
2320 (match_operand:SI 4 "arm_not_operand" "rIK")
2321 (const_int 0)))
2322 (clobber (reg:CC CC_REGNUM))]
2323 "TARGET_ARM
2324 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2325 && INTVAL (operands[2]) > 0
2326 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 2327 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2328 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 2329 "#"
2330 "TARGET_ARM
2331 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2332 && INTVAL (operands[2]) > 0
2333 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 2334 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2335 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 2336 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2337 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2338 (const_int 0)))
2339 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2340 (set (match_dup 0)
2341 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2342 (match_dup 0) (match_dup 4)))]
2343 "
c4034607 2344 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
f4462328 2345 << INTVAL (operands[3]));
2346 "
2347 [(set_attr "conds" "clob")
1b7da4ac 2348 (set_attr "length" "8")
2349 (set_attr "type" "multiple")]
f4462328 2350)
2351
2352(define_insn_and_split "*ite_ne_zeroextractsi_shifted"
2353 [(set (match_operand:SI 0 "s_register_operand" "=r")
2354 (if_then_else:SI (ne (zero_extract:SI
2355 (match_operand:SI 1 "s_register_operand" "r")
2356 (match_operand:SI 2 "const_int_operand" "n")
2357 (const_int 0))
2358 (const_int 0))
2359 (match_operand:SI 3 "arm_not_operand" "rIK")
2360 (const_int 0)))
2361 (clobber (reg:CC CC_REGNUM))]
f8d7bf2f 2362 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 2363 "#"
f8d7bf2f 2364 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 2365 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2366 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2367 (const_int 0)))
2368 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2369 (set (match_dup 0)
2370 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2371 (match_dup 0) (match_dup 3)))]
2372 "
2373 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
0d66636f 2374 "
2375 [(set_attr "conds" "clob")
1b7da4ac 2376 (set_attr "length" "8")
2377 (set_attr "type" "multiple")]
215b30b3 2378)
9c08d1fa 2379
25f905c2 2380;; ??? Use Thumb-2 has bitfield insert/extract instructions.
d7863cfe 2381(define_split
2382 [(set (match_operand:SI 0 "s_register_operand" "")
2383 (match_operator:SI 1 "shiftable_operator"
2384 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2385 (match_operand:SI 3 "const_int_operand" "")
2386 (match_operand:SI 4 "const_int_operand" ""))
2387 (match_operand:SI 5 "s_register_operand" "")]))
2388 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2389 "TARGET_ARM"
2390 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2391 (set (match_dup 0)
2392 (match_op_dup 1
2393 [(lshiftrt:SI (match_dup 6) (match_dup 4))
2394 (match_dup 5)]))]
2395 "{
2396 HOST_WIDE_INT temp = INTVAL (operands[3]);
2397
2398 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2399 operands[4] = GEN_INT (32 - temp);
2400 }"
2401)
2402
d7863cfe 2403(define_split
2404 [(set (match_operand:SI 0 "s_register_operand" "")
2405 (match_operator:SI 1 "shiftable_operator"
2406 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2407 (match_operand:SI 3 "const_int_operand" "")
2408 (match_operand:SI 4 "const_int_operand" ""))
2409 (match_operand:SI 5 "s_register_operand" "")]))
2410 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2411 "TARGET_ARM"
2412 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2413 (set (match_dup 0)
2414 (match_op_dup 1
2415 [(ashiftrt:SI (match_dup 6) (match_dup 4))
2416 (match_dup 5)]))]
2417 "{
2418 HOST_WIDE_INT temp = INTVAL (operands[3]);
2419
2420 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2421 operands[4] = GEN_INT (32 - temp);
2422 }"
2423)
2424
a42059fd 2425;;; ??? This pattern is bogus. If operand3 has bits outside the range
2426;;; represented by the bitfield, then this will produce incorrect results.
2427;;; Somewhere, the value needs to be truncated. On targets like the m68k,
ceb2fe0f 2428;;; which have a real bit-field insert instruction, the truncation happens
2429;;; in the bit-field insert instruction itself. Since arm does not have a
2430;;; bit-field insert instruction, we would have to emit code here to truncate
a42059fd 2431;;; the value before we insert. This loses some of the advantage of having
2432;;; this insv pattern, so this pattern needs to be reevalutated.
2433
8a18b90c 2434(define_expand "insv"
eb04cafb 2435 [(set (zero_extract (match_operand 0 "nonimmediate_operand" "")
2436 (match_operand 1 "general_operand" "")
2437 (match_operand 2 "general_operand" ""))
2438 (match_operand 3 "reg_or_int_operand" ""))]
8b054d5a 2439 "TARGET_ARM || arm_arch_thumb2"
8a18b90c 2440 "
215b30b3 2441 {
2442 int start_bit = INTVAL (operands[2]);
2443 int width = INTVAL (operands[1]);
2444 HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
2445 rtx target, subtarget;
2446
8b054d5a 2447 if (arm_arch_thumb2)
2448 {
eb04cafb 2449 if (unaligned_access && MEM_P (operands[0])
2450 && s_register_operand (operands[3], GET_MODE (operands[3]))
2451 && (width == 16 || width == 32) && (start_bit % BITS_PER_UNIT) == 0)
8b054d5a 2452 {
eb04cafb 2453 rtx base_addr;
2454
2455 if (BYTES_BIG_ENDIAN)
2456 start_bit = GET_MODE_BITSIZE (GET_MODE (operands[3])) - width
2457 - start_bit;
8b054d5a 2458
eb04cafb 2459 if (width == 32)
8b054d5a 2460 {
eb04cafb 2461 base_addr = adjust_address (operands[0], SImode,
2462 start_bit / BITS_PER_UNIT);
2463 emit_insn (gen_unaligned_storesi (base_addr, operands[3]));
8b054d5a 2464 }
eb04cafb 2465 else
2466 {
2467 rtx tmp = gen_reg_rtx (HImode);
8b054d5a 2468
eb04cafb 2469 base_addr = adjust_address (operands[0], HImode,
2470 start_bit / BITS_PER_UNIT);
2471 emit_move_insn (tmp, gen_lowpart (HImode, operands[3]));
2472 emit_insn (gen_unaligned_storehi (base_addr, tmp));
2473 }
2474 DONE;
8b054d5a 2475 }
eb04cafb 2476 else if (s_register_operand (operands[0], GET_MODE (operands[0])))
8b054d5a 2477 {
eb04cafb 2478 bool use_bfi = TRUE;
8b054d5a 2479
0438d37f 2480 if (CONST_INT_P (operands[3]))
eb04cafb 2481 {
2482 HOST_WIDE_INT val = INTVAL (operands[3]) & mask;
2483
2484 if (val == 0)
2485 {
2486 emit_insn (gen_insv_zero (operands[0], operands[1],
2487 operands[2]));
2488 DONE;
2489 }
2490
2491 /* See if the set can be done with a single orr instruction. */
2492 if (val == mask && const_ok_for_arm (val << start_bit))
2493 use_bfi = FALSE;
2494 }
2495
2496 if (use_bfi)
2497 {
0438d37f 2498 if (!REG_P (operands[3]))
eb04cafb 2499 operands[3] = force_reg (SImode, operands[3]);
2500
2501 emit_insn (gen_insv_t2 (operands[0], operands[1], operands[2],
2502 operands[3]));
2503 DONE;
2504 }
8b054d5a 2505 }
eb04cafb 2506 else
2507 FAIL;
8b054d5a 2508 }
2509
eb04cafb 2510 if (!s_register_operand (operands[0], GET_MODE (operands[0])))
2511 FAIL;
2512
3f8fde42 2513 target = copy_rtx (operands[0]);
215b30b3 2514 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
2515 subreg as the final target. */
2516 if (GET_CODE (target) == SUBREG)
2517 {
2518 subtarget = gen_reg_rtx (SImode);
2519 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
2520 < GET_MODE_SIZE (SImode))
2521 target = SUBREG_REG (target);
2522 }
2523 else
2524 subtarget = target;
8a18b90c 2525
0438d37f 2526 if (CONST_INT_P (operands[3]))
215b30b3 2527 {
2528 /* Since we are inserting a known constant, we may be able to
2529 reduce the number of bits that we have to clear so that
2530 the mask becomes simple. */
2531 /* ??? This code does not check to see if the new mask is actually
2532 simpler. It may not be. */
2533 rtx op1 = gen_reg_rtx (SImode);
2534 /* ??? Truncate operand3 to fit in the bitfield. See comment before
2535 start of this pattern. */
2536 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
2537 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
2538
c5b3a71b 2539 emit_insn (gen_andsi3 (op1, operands[0],
2540 gen_int_mode (~mask2, SImode)));
215b30b3 2541 emit_insn (gen_iorsi3 (subtarget, op1,
4292ca6b 2542 gen_int_mode (op3_value << start_bit, SImode)));
215b30b3 2543 }
2544 else if (start_bit == 0
2545 && !(const_ok_for_arm (mask)
2546 || const_ok_for_arm (~mask)))
2547 {
2548 /* A Trick, since we are setting the bottom bits in the word,
2549 we can shift operand[3] up, operand[0] down, OR them together
2550 and rotate the result back again. This takes 3 insns, and
5910bb95 2551 the third might be mergeable into another op. */
215b30b3 2552 /* The shift up copes with the possibility that operand[3] is
2553 wider than the bitfield. */
2554 rtx op0 = gen_reg_rtx (SImode);
2555 rtx op1 = gen_reg_rtx (SImode);
2556
2557 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2558 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
2559 emit_insn (gen_iorsi3 (op1, op1, op0));
2560 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
2561 }
2562 else if ((width + start_bit == 32)
2563 && !(const_ok_for_arm (mask)
2564 || const_ok_for_arm (~mask)))
2565 {
2566 /* Similar trick, but slightly less efficient. */
8a18b90c 2567
215b30b3 2568 rtx op0 = gen_reg_rtx (SImode);
2569 rtx op1 = gen_reg_rtx (SImode);
8a18b90c 2570
215b30b3 2571 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2572 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
2573 emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
2574 emit_insn (gen_iorsi3 (subtarget, op1, op0));
2575 }
2576 else
2577 {
c5b3a71b 2578 rtx op0 = gen_int_mode (mask, SImode);
215b30b3 2579 rtx op1 = gen_reg_rtx (SImode);
2580 rtx op2 = gen_reg_rtx (SImode);
8a18b90c 2581
215b30b3 2582 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
2583 {
2584 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 2585
215b30b3 2586 emit_insn (gen_movsi (tmp, op0));
2587 op0 = tmp;
2588 }
8a18b90c 2589
215b30b3 2590 /* Mask out any bits in operand[3] that are not needed. */
2591 emit_insn (gen_andsi3 (op1, operands[3], op0));
8a18b90c 2592
0438d37f 2593 if (CONST_INT_P (op0)
215b30b3 2594 && (const_ok_for_arm (mask << start_bit)
2595 || const_ok_for_arm (~(mask << start_bit))))
2596 {
c5b3a71b 2597 op0 = gen_int_mode (~(mask << start_bit), SImode);
215b30b3 2598 emit_insn (gen_andsi3 (op2, operands[0], op0));
2599 }
2600 else
2601 {
0438d37f 2602 if (CONST_INT_P (op0))
215b30b3 2603 {
2604 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 2605
215b30b3 2606 emit_insn (gen_movsi (tmp, op0));
2607 op0 = tmp;
2608 }
2609
2610 if (start_bit != 0)
2611 emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
a42059fd 2612
215b30b3 2613 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
2614 }
8a18b90c 2615
215b30b3 2616 if (start_bit != 0)
2617 emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
8a18b90c 2618
215b30b3 2619 emit_insn (gen_iorsi3 (subtarget, op1, op2));
2620 }
f082f1c4 2621
215b30b3 2622 if (subtarget != target)
2623 {
2624 /* If TARGET is still a SUBREG, then it must be wider than a word,
2625 so we must be careful only to set the subword we were asked to. */
2626 if (GET_CODE (target) == SUBREG)
2627 emit_move_insn (target, subtarget);
2628 else
2629 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
2630 }
8a18b90c 2631
215b30b3 2632 DONE;
2633 }"
2634)
8a18b90c 2635
8b054d5a 2636(define_insn "insv_zero"
2637 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
809003b3 2638 (match_operand:SI 1 "const_int_M_operand" "M")
2639 (match_operand:SI 2 "const_int_M_operand" "M"))
8b054d5a 2640 (const_int 0))]
2641 "arm_arch_thumb2"
2642 "bfc%?\t%0, %2, %1"
2643 [(set_attr "length" "4")
d952d547 2644 (set_attr "predicable" "yes")
d82e788e 2645 (set_attr "predicable_short_it" "no")
2646 (set_attr "type" "bfm")]
8b054d5a 2647)
2648
2649(define_insn "insv_t2"
2650 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
809003b3 2651 (match_operand:SI 1 "const_int_M_operand" "M")
2652 (match_operand:SI 2 "const_int_M_operand" "M"))
8b054d5a 2653 (match_operand:SI 3 "s_register_operand" "r"))]
2654 "arm_arch_thumb2"
2655 "bfi%?\t%0, %3, %2, %1"
2656 [(set_attr "length" "4")
d952d547 2657 (set_attr "predicable" "yes")
d82e788e 2658 (set_attr "predicable_short_it" "no")
2659 (set_attr "type" "bfm")]
8b054d5a 2660)
2661
215b30b3 2662; constants for op 2 will never be given to these patterns.
a0f94409 2663(define_insn_and_split "*anddi_notdi_di"
9c08d1fa 2664 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 2665 (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "0,r"))
2666 (match_operand:DI 2 "s_register_operand" "r,0")))]
25f905c2 2667 "TARGET_32BIT"
f6ebffac 2668 "#"
e2669ea7 2669 "TARGET_32BIT && reload_completed
2670 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))
2671 && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
a0f94409 2672 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2673 (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2674 "
2675 {
2676 operands[3] = gen_highpart (SImode, operands[0]);
2677 operands[0] = gen_lowpart (SImode, operands[0]);
2678 operands[4] = gen_highpart (SImode, operands[1]);
2679 operands[1] = gen_lowpart (SImode, operands[1]);
2680 operands[5] = gen_highpart (SImode, operands[2]);
2681 operands[2] = gen_lowpart (SImode, operands[2]);
2682 }"
0d66636f 2683 [(set_attr "length" "8")
1b7da4ac 2684 (set_attr "predicable" "yes")
2685 (set_attr "type" "multiple")]
0d66636f 2686)
d952d547 2687
a0f94409 2688(define_insn_and_split "*anddi_notzesidi_di"
9c08d1fa 2689 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2690 (and:DI (not:DI (zero_extend:DI
2691 (match_operand:SI 2 "s_register_operand" "r,r")))
e2348bcb 2692 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 2693 "TARGET_32BIT"
e2348bcb 2694 "@
97499065 2695 bic%?\\t%Q0, %Q1, %2
f6ebffac 2696 #"
a0f94409 2697 ; (not (zero_extend ...)) allows us to just copy the high word from
2698 ; operand1 to operand0.
25f905c2 2699 "TARGET_32BIT
a0f94409 2700 && reload_completed
2701 && operands[0] != operands[1]"
5a097f7d 2702 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
a0f94409 2703 (set (match_dup 3) (match_dup 4))]
2704 "
2705 {
2706 operands[3] = gen_highpart (SImode, operands[0]);
2707 operands[0] = gen_lowpart (SImode, operands[0]);
2708 operands[4] = gen_highpart (SImode, operands[1]);
2709 operands[1] = gen_lowpart (SImode, operands[1]);
2710 }"
0d66636f 2711 [(set_attr "length" "4,8")
d952d547 2712 (set_attr "predicable" "yes")
1b7da4ac 2713 (set_attr "predicable_short_it" "no")
2714 (set_attr "type" "multiple")]
0d66636f 2715)
d952d547 2716
d8cd5fa0 2717(define_insn_and_split "*anddi_notdi_zesidi"
2718 [(set (match_operand:DI 0 "s_register_operand" "=r")
2719 (and:DI (not:DI (match_operand:DI 2 "s_register_operand" "r"))
2720 (zero_extend:DI
2721 (match_operand:SI 1 "s_register_operand" "r"))))]
2722 "TARGET_32BIT"
2723 "#"
2724 "TARGET_32BIT && reload_completed"
2725 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2726 (set (match_dup 3) (const_int 0))]
2727 "
2728 {
2729 operands[3] = gen_highpart (SImode, operands[0]);
2730 operands[0] = gen_lowpart (SImode, operands[0]);
2731 operands[2] = gen_lowpart (SImode, operands[2]);
2732 }"
2733 [(set_attr "length" "8")
2734 (set_attr "predicable" "yes")
2735 (set_attr "predicable_short_it" "no")
2736 (set_attr "type" "multiple")]
2737)
2738
a0f94409 2739(define_insn_and_split "*anddi_notsesidi_di"
9c08d1fa 2740 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2741 (and:DI (not:DI (sign_extend:DI
2742 (match_operand:SI 2 "s_register_operand" "r,r")))
5a097f7d 2743 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2744 "TARGET_32BIT"
f6ebffac 2745 "#"
25f905c2 2746 "TARGET_32BIT && reload_completed"
5a097f7d 2747 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
a0f94409 2748 (set (match_dup 3) (and:SI (not:SI
2749 (ashiftrt:SI (match_dup 2) (const_int 31)))
2750 (match_dup 4)))]
2751 "
2752 {
2753 operands[3] = gen_highpart (SImode, operands[0]);
2754 operands[0] = gen_lowpart (SImode, operands[0]);
2755 operands[4] = gen_highpart (SImode, operands[1]);
2756 operands[1] = gen_lowpart (SImode, operands[1]);
2757 }"
0d66636f 2758 [(set_attr "length" "8")
d952d547 2759 (set_attr "predicable" "yes")
1b7da4ac 2760 (set_attr "predicable_short_it" "no")
2761 (set_attr "type" "multiple")]
0d66636f 2762)
d952d547 2763
8a18b90c 2764(define_insn "andsi_notsi_si"
9c08d1fa 2765 [(set (match_operand:SI 0 "s_register_operand" "=r")
2766 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2767 (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 2768 "TARGET_32BIT"
0d66636f 2769 "bic%?\\t%0, %1, %2"
d952d547 2770 [(set_attr "predicable" "yes")
1b7da4ac 2771 (set_attr "predicable_short_it" "no")
2772 (set_attr "type" "logic_reg")]
0d66636f 2773)
b11cae9e 2774
8a18b90c 2775(define_insn "andsi_not_shiftsi_si"
a2cd141b 2776 [(set (match_operand:SI 0 "s_register_operand" "=r")
2777 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2778 [(match_operand:SI 2 "s_register_operand" "r")
2779 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2780 (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 2781 "TARGET_ARM"
6c4c2133 2782 "bic%?\\t%0, %1, %2%S4"
344495ea 2783 [(set_attr "predicable" "yes")
331beb1a 2784 (set_attr "shift" "2")
a2cd141b 2785 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
d82e788e 2786 (const_string "logic_shift_imm")
2787 (const_string "logic_shift_reg")))]
6c4c2133 2788)
8a18b90c 2789
9ed784d8 2790;; Shifted bics pattern used to set up CC status register and not reusing
2791;; bics output. Pattern restricts Thumb2 shift operand as bics for Thumb2
2792;; does not support shift by register.
2793(define_insn "andsi_not_shiftsi_si_scc_no_reuse"
2794 [(set (reg:CC_NOOV CC_REGNUM)
2795 (compare:CC_NOOV
2796 (and:SI (not:SI (match_operator:SI 0 "shift_operator"
2797 [(match_operand:SI 1 "s_register_operand" "r")
2798 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2799 (match_operand:SI 3 "s_register_operand" "r"))
2800 (const_int 0)))
2801 (clobber (match_scratch:SI 4 "=r"))]
2802 "TARGET_ARM || (TARGET_THUMB2 && CONST_INT_P (operands[2]))"
3ef90e77 2803 "bics%?\\t%4, %3, %1%S0"
9ed784d8 2804 [(set_attr "predicable" "yes")
2805 (set_attr "predicable_short_it" "no")
2806 (set_attr "conds" "set")
2807 (set_attr "shift" "1")
2808 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2809 (const_string "logic_shift_imm")
2810 (const_string "logic_shift_reg")))]
2811)
2812
2813;; Same as andsi_not_shiftsi_si_scc_no_reuse, but the bics result is also
2814;; getting reused later.
2815(define_insn "andsi_not_shiftsi_si_scc"
2816 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2817 (compare:CC_NOOV
2818 (and:SI (not:SI (match_operator:SI 0 "shift_operator"
2819 [(match_operand:SI 1 "s_register_operand" "r")
2820 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2821 (match_operand:SI 3 "s_register_operand" "r"))
2822 (const_int 0)))
2823 (set (match_operand:SI 4 "s_register_operand" "=r")
2824 (and:SI (not:SI (match_op_dup 0
2825 [(match_dup 1)
2826 (match_dup 2)]))
2827 (match_dup 3)))])]
2828 "TARGET_ARM || (TARGET_THUMB2 && CONST_INT_P (operands[2]))"
3ef90e77 2829 "bics%?\\t%4, %3, %1%S0"
9ed784d8 2830 [(set_attr "predicable" "yes")
2831 (set_attr "predicable_short_it" "no")
2832 (set_attr "conds" "set")
2833 (set_attr "shift" "1")
2834 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2835 (const_string "logic_shift_imm")
2836 (const_string "logic_shift_reg")))]
2837)
2838
f7fbdd4a 2839(define_insn "*andsi_notsi_si_compare0"
bd5b4116 2840 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 2841 (compare:CC_NOOV
2842 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2843 (match_operand:SI 1 "s_register_operand" "r"))
2844 (const_int 0)))
9c08d1fa 2845 (set (match_operand:SI 0 "s_register_operand" "=r")
2846 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
25f905c2 2847 "TARGET_32BIT"
3ef90e77 2848 "bics\\t%0, %1, %2"
d82e788e 2849 [(set_attr "conds" "set")
2850 (set_attr "type" "logics_shift_reg")]
0d66636f 2851)
9c08d1fa 2852
f7fbdd4a 2853(define_insn "*andsi_notsi_si_compare0_scratch"
bd5b4116 2854 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 2855 (compare:CC_NOOV
2856 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2857 (match_operand:SI 1 "s_register_operand" "r"))
2858 (const_int 0)))
9c08d1fa 2859 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 2860 "TARGET_32BIT"
3ef90e77 2861 "bics\\t%0, %1, %2"
d82e788e 2862 [(set_attr "conds" "set")
2863 (set_attr "type" "logics_shift_reg")]
0d66636f 2864)
9c08d1fa 2865
e2669ea7 2866(define_expand "iordi3"
2867 [(set (match_operand:DI 0 "s_register_operand" "")
2868 (ior:DI (match_operand:DI 1 "s_register_operand" "")
2869 (match_operand:DI 2 "neon_logic_op2" "")))]
2870 "TARGET_32BIT"
2871 ""
2872)
2873
74d6113f 2874(define_insn_and_split "*iordi3_insn"
2875 [(set (match_operand:DI 0 "s_register_operand" "=w,w ,&r,&r,&r,&r,?w,?w")
2876 (ior:DI (match_operand:DI 1 "s_register_operand" "%w,0 ,0 ,r ,0 ,r ,w ,0")
e0fe6977 2877 (match_operand:DI 2 "arm_iordi_operand_neon" "w ,Dl,r ,r ,Df,Df,w ,Dl")))]
74d6113f 2878 "TARGET_32BIT && !TARGET_IWMMXT"
2879 {
2880 switch (which_alternative)
2881 {
2882 case 0: /* fall through */
2883 case 6: return "vorr\t%P0, %P1, %P2";
2884 case 1: /* fall through */
2885 case 7: return neon_output_logic_immediate ("vorr", &operands[2],
2886 DImode, 0, VALID_NEON_QREG_MODE (DImode));
2887 case 2:
2888 case 3:
2889 case 4:
2890 case 5:
2891 return "#";
2892 default: gcc_unreachable ();
2893 }
2894 }
2895 "TARGET_32BIT && !TARGET_IWMMXT && reload_completed
2896 && !(IS_VFP_REGNUM (REGNO (operands[0])))"
2897 [(set (match_dup 3) (match_dup 4))
2898 (set (match_dup 5) (match_dup 6))]
2899 "
2900 {
2901 operands[3] = gen_lowpart (SImode, operands[0]);
2902 operands[5] = gen_highpart (SImode, operands[0]);
2903
2904 operands[4] = simplify_gen_binary (IOR, SImode,
2905 gen_lowpart (SImode, operands[1]),
2906 gen_lowpart (SImode, operands[2]));
2907 operands[6] = simplify_gen_binary (IOR, SImode,
2908 gen_highpart (SImode, operands[1]),
2909 gen_highpart_mode (SImode, DImode, operands[2]));
2910
2911 }"
32093010 2912 [(set_attr "type" "neon_logic,neon_logic,multiple,multiple,multiple,\
2913 multiple,neon_logic,neon_logic")
e0fe6977 2914 (set_attr "length" "*,*,8,8,8,8,*,*")
74d6113f 2915 (set_attr "arch" "neon_for_64bits,neon_for_64bits,*,*,*,*,avoid_neon_for_64bits,avoid_neon_for_64bits")]
cffb2a26 2916)
9c08d1fa 2917
f7fbdd4a 2918(define_insn "*iordi_zesidi_di"
9c08d1fa 2919 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2920 (ior:DI (zero_extend:DI
2921 (match_operand:SI 2 "s_register_operand" "r,r"))
e2348bcb 2922 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 2923 "TARGET_32BIT"
e2348bcb 2924 "@
97499065 2925 orr%?\\t%Q0, %Q1, %2
f6ebffac 2926 #"
0d66636f 2927 [(set_attr "length" "4,8")
d952d547 2928 (set_attr "predicable" "yes")
1b7da4ac 2929 (set_attr "predicable_short_it" "no")
2930 (set_attr "type" "logic_reg,multiple")]
cffb2a26 2931)
9c08d1fa 2932
f7fbdd4a 2933(define_insn "*iordi_sesidi_di"
9c08d1fa 2934 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2935 (ior:DI (sign_extend:DI
2936 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 2937 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2938 "TARGET_32BIT"
f6ebffac 2939 "#"
0d66636f 2940 [(set_attr "length" "8")
1b7da4ac 2941 (set_attr "predicable" "yes")
2942 (set_attr "type" "multiple")]
cffb2a26 2943)
9c08d1fa 2944
87b22bf7 2945(define_expand "iorsi3"
cffb2a26 2946 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2947 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2948 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 2949 "TARGET_EITHER"
87b22bf7 2950 "
0438d37f 2951 if (CONST_INT_P (operands[2]))
87b22bf7 2952 {
25f905c2 2953 if (TARGET_32BIT)
cffb2a26 2954 {
17202aa5 2955 if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[2]), IOR))
2956 operands[2] = force_reg (SImode, operands[2]);
2957 else
2958 {
2959 arm_split_constant (IOR, SImode, NULL_RTX,
2960 INTVAL (operands[2]), operands[0],
2961 operands[1],
2962 optimize && can_create_pseudo_p ());
2963 DONE;
2964 }
cffb2a26 2965 }
25f905c2 2966 else /* TARGET_THUMB1 */
923ffadb 2967 {
2968 rtx tmp = force_reg (SImode, operands[2]);
2969 if (rtx_equal_p (operands[0], operands[1]))
2970 operands[2] = tmp;
2971 else
2972 {
2973 operands[2] = operands[1];
2974 operands[1] = tmp;
2975 }
2976 }
87b22bf7 2977 }
cffb2a26 2978 "
2979)
87b22bf7 2980
d5d4dc8d 2981(define_insn_and_split "*iorsi3_insn"
29e234a3 2982 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r,r,r")
2983 (ior:SI (match_operand:SI 1 "s_register_operand" "%r,0,r,r,r")
2984 (match_operand:SI 2 "reg_or_int_operand" "I,l,K,r,?n")))]
d5d4dc8d 2985 "TARGET_32BIT"
87b22bf7 2986 "@
29e234a3 2987 orr%?\\t%0, %1, %2
87b22bf7 2988 orr%?\\t%0, %1, %2
d5d4dc8d 2989 orn%?\\t%0, %1, #%B2
65f68e55 2990 orr%?\\t%0, %1, %2
87b22bf7 2991 #"
d5d4dc8d 2992 "TARGET_32BIT
0438d37f 2993 && CONST_INT_P (operands[2])
d5d4dc8d 2994 && !(const_ok_for_arm (INTVAL (operands[2]))
2995 || (TARGET_THUMB2 && const_ok_for_arm (~INTVAL (operands[2]))))"
a0f94409 2996 [(clobber (const_int 0))]
d5d4dc8d 2997{
29e234a3 2998 arm_split_constant (IOR, SImode, curr_insn,
96f57e36 2999 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 3000 DONE;
d5d4dc8d 3001}
29e234a3 3002 [(set_attr "length" "4,4,4,4,16")
3003 (set_attr "arch" "32,t2,t2,32,32")
65f68e55 3004 (set_attr "predicable" "yes")
29e234a3 3005 (set_attr "predicable_short_it" "no,yes,no,no,no")
d82e788e 3006 (set_attr "type" "logic_imm,logic_reg,logic_imm,logic_reg,logic_reg")]
65f68e55 3007)
cffb2a26 3008
a0f94409 3009(define_peephole2
3010 [(match_scratch:SI 3 "r")
372575c7 3011 (set (match_operand:SI 0 "arm_general_register_operand" "")
3012 (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
87b22bf7 3013 (match_operand:SI 2 "const_int_operand" "")))]
90560cad 3014 "TARGET_ARM
a0f94409 3015 && !const_ok_for_arm (INTVAL (operands[2]))
3016 && const_ok_for_arm (~INTVAL (operands[2]))"
3017 [(set (match_dup 3) (match_dup 2))
3018 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
3019 ""
215b30b3 3020)
a0f94409 3021
f7fbdd4a 3022(define_insn "*iorsi3_compare0"
bd5b4116 3023 [(set (reg:CC_NOOV CC_REGNUM)
65f68e55 3024 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r,r")
3025 (match_operand:SI 2 "arm_rhs_operand" "I,r"))
9c08d1fa 3026 (const_int 0)))
65f68e55 3027 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 3028 (ior:SI (match_dup 1) (match_dup 2)))]
25f905c2 3029 "TARGET_32BIT"
3ef90e77 3030 "orrs%?\\t%0, %1, %2"
65f68e55 3031 [(set_attr "conds" "set")
d82e788e 3032 (set_attr "type" "logics_imm,logics_reg")]
cffb2a26 3033)
9c08d1fa 3034
f7fbdd4a 3035(define_insn "*iorsi3_compare0_scratch"
bd5b4116 3036 [(set (reg:CC_NOOV CC_REGNUM)
65f68e55 3037 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r,r")
3038 (match_operand:SI 2 "arm_rhs_operand" "I,r"))
9c08d1fa 3039 (const_int 0)))
65f68e55 3040 (clobber (match_scratch:SI 0 "=r,r"))]
25f905c2 3041 "TARGET_32BIT"
3ef90e77 3042 "orrs%?\\t%0, %1, %2"
65f68e55 3043 [(set_attr "conds" "set")
d82e788e 3044 (set_attr "type" "logics_imm,logics_reg")]
0d66636f 3045)
9c08d1fa 3046
e2669ea7 3047(define_expand "xordi3"
3048 [(set (match_operand:DI 0 "s_register_operand" "")
3049 (xor:DI (match_operand:DI 1 "s_register_operand" "")
8ee7dc6f 3050 (match_operand:DI 2 "arm_xordi_operand" "")))]
e2669ea7 3051 "TARGET_32BIT"
3052 ""
3053)
3054
8ee7dc6f 3055(define_insn_and_split "*xordi3_insn"
3056 [(set (match_operand:DI 0 "s_register_operand" "=w,&r,&r,&r,&r,?w")
205c3b0a 3057 (xor:DI (match_operand:DI 1 "s_register_operand" "%w ,0,r ,0 ,r ,w")
8ee7dc6f 3058 (match_operand:DI 2 "arm_xordi_operand" "w ,r ,r ,Dg,Dg,w")))]
3059 "TARGET_32BIT && !TARGET_IWMMXT"
3060{
3061 switch (which_alternative)
3062 {
3063 case 1:
3064 case 2:
3065 case 3:
3066 case 4: /* fall through */
3067 return "#";
3068 case 0: /* fall through */
3069 case 5: return "veor\t%P0, %P1, %P2";
3070 default: gcc_unreachable ();
3071 }
3072}
3073 "TARGET_32BIT && !TARGET_IWMMXT && reload_completed
3074 && !(IS_VFP_REGNUM (REGNO (operands[0])))"
3075 [(set (match_dup 3) (match_dup 4))
3076 (set (match_dup 5) (match_dup 6))]
3077 "
3078 {
3079 operands[3] = gen_lowpart (SImode, operands[0]);
3080 operands[5] = gen_highpart (SImode, operands[0]);
3081
3082 operands[4] = simplify_gen_binary (XOR, SImode,
3083 gen_lowpart (SImode, operands[1]),
3084 gen_lowpart (SImode, operands[2]));
3085 operands[6] = simplify_gen_binary (XOR, SImode,
3086 gen_highpart (SImode, operands[1]),
3087 gen_highpart_mode (SImode, DImode, operands[2]));
3088
3089 }"
3090 [(set_attr "length" "*,8,8,8,8,*")
32093010 3091 (set_attr "type" "neon_logic,multiple,multiple,multiple,multiple,neon_logic")
8ee7dc6f 3092 (set_attr "arch" "neon_for_64bits,*,*,*,*,avoid_neon_for_64bits")]
cffb2a26 3093)
9c08d1fa 3094
f7fbdd4a 3095(define_insn "*xordi_zesidi_di"
9c08d1fa 3096 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3097 (xor:DI (zero_extend:DI
3098 (match_operand:SI 2 "s_register_operand" "r,r"))
e2348bcb 3099 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 3100 "TARGET_32BIT"
e2348bcb 3101 "@
97499065 3102 eor%?\\t%Q0, %Q1, %2
f6ebffac 3103 #"
0d66636f 3104 [(set_attr "length" "4,8")
d952d547 3105 (set_attr "predicable" "yes")
1b7da4ac 3106 (set_attr "predicable_short_it" "no")
3107 (set_attr "type" "logic_reg")]
cffb2a26 3108)
9c08d1fa 3109
f7fbdd4a 3110(define_insn "*xordi_sesidi_di"
9c08d1fa 3111 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3112 (xor:DI (sign_extend:DI
3113 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 3114 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 3115 "TARGET_32BIT"
f6ebffac 3116 "#"
0d66636f 3117 [(set_attr "length" "8")
1b7da4ac 3118 (set_attr "predicable" "yes")
3119 (set_attr "type" "multiple")]
cffb2a26 3120)
9c08d1fa 3121
cffb2a26 3122(define_expand "xorsi3"
3123 [(set (match_operand:SI 0 "s_register_operand" "")
3124 (xor:SI (match_operand:SI 1 "s_register_operand" "")
923ffadb 3125 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 3126 "TARGET_EITHER"
0438d37f 3127 "if (CONST_INT_P (operands[2]))
923ffadb 3128 {
3129 if (TARGET_32BIT)
3130 {
17202aa5 3131 if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[2]), XOR))
3132 operands[2] = force_reg (SImode, operands[2]);
3133 else
3134 {
3135 arm_split_constant (XOR, SImode, NULL_RTX,
3136 INTVAL (operands[2]), operands[0],
3137 operands[1],
3138 optimize && can_create_pseudo_p ());
3139 DONE;
3140 }
923ffadb 3141 }
3142 else /* TARGET_THUMB1 */
3143 {
3144 rtx tmp = force_reg (SImode, operands[2]);
3145 if (rtx_equal_p (operands[0], operands[1]))
3146 operands[2] = tmp;
3147 else
3148 {
3149 operands[2] = operands[1];
3150 operands[1] = tmp;
3151 }
3152 }
3153 }"
cffb2a26 3154)
3155
5dcb35d9 3156(define_insn_and_split "*arm_xorsi3"
29e234a3 3157 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r,r")
3158 (xor:SI (match_operand:SI 1 "s_register_operand" "%r,0,r,r")
3159 (match_operand:SI 2 "reg_or_int_operand" "I,l,r,?n")))]
25f905c2 3160 "TARGET_32BIT"
5dcb35d9 3161 "@
29e234a3 3162 eor%?\\t%0, %1, %2
65f68e55 3163 eor%?\\t%0, %1, %2
5dcb35d9 3164 eor%?\\t%0, %1, %2
3165 #"
3166 "TARGET_32BIT
0438d37f 3167 && CONST_INT_P (operands[2])
5dcb35d9 3168 && !const_ok_for_arm (INTVAL (operands[2]))"
3169 [(clobber (const_int 0))]
3170{
3171 arm_split_constant (XOR, SImode, curr_insn,
3172 INTVAL (operands[2]), operands[0], operands[1], 0);
3173 DONE;
3174}
29e234a3 3175 [(set_attr "length" "4,4,4,16")
65f68e55 3176 (set_attr "predicable" "yes")
29e234a3 3177 (set_attr "predicable_short_it" "no,yes,no,no")
1b7da4ac 3178 (set_attr "type" "logic_imm,logic_reg,logic_reg,multiple")]
cffb2a26 3179)
3180
f7fbdd4a 3181(define_insn "*xorsi3_compare0"
bd5b4116 3182 [(set (reg:CC_NOOV CC_REGNUM)
65f68e55 3183 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r,r")
3184 (match_operand:SI 2 "arm_rhs_operand" "I,r"))
9c08d1fa 3185 (const_int 0)))
65f68e55 3186 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 3187 (xor:SI (match_dup 1) (match_dup 2)))]
25f905c2 3188 "TARGET_32BIT"
3ef90e77 3189 "eors%?\\t%0, %1, %2"
65f68e55 3190 [(set_attr "conds" "set")
d82e788e 3191 (set_attr "type" "logics_imm,logics_reg")]
0d66636f 3192)
9c08d1fa 3193
f7fbdd4a 3194(define_insn "*xorsi3_compare0_scratch"
bd5b4116 3195 [(set (reg:CC_NOOV CC_REGNUM)
65f68e55 3196 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r,r")
3197 (match_operand:SI 1 "arm_rhs_operand" "I,r"))
9c08d1fa 3198 (const_int 0)))]
25f905c2 3199 "TARGET_32BIT"
40dbec34 3200 "teq%?\\t%0, %1"
65f68e55 3201 [(set_attr "conds" "set")
d82e788e 3202 (set_attr "type" "logics_imm,logics_reg")]
cffb2a26 3203)
9c08d1fa 3204
215b30b3 3205; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
3206; (NOT D) we can sometimes merge the final NOT into one of the following
3207; insns.
9c08d1fa 3208
3209(define_split
a058e94a 3210 [(set (match_operand:SI 0 "s_register_operand" "")
3211 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
3212 (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
3213 (match_operand:SI 3 "arm_rhs_operand" "")))
3214 (clobber (match_operand:SI 4 "s_register_operand" ""))]
25f905c2 3215 "TARGET_32BIT"
9c08d1fa 3216 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
3217 (not:SI (match_dup 3))))
3218 (set (match_dup 0) (not:SI (match_dup 4)))]
3219 ""
3220)
3221
ba6a3b2f 3222(define_insn_and_split "*andsi_iorsi3_notsi"
9c08d1fa 3223 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
e5fea38e 3224 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "%0,r,r")
9c08d1fa 3225 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
3226 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
25f905c2 3227 "TARGET_32BIT"
ba6a3b2f 3228 "#" ; "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
3229 "&& reload_completed"
3230 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
054fd237 3231 (set (match_dup 0) (and:SI (match_dup 4) (match_dup 5)))]
3232 {
3233 /* If operands[3] is a constant make sure to fold the NOT into it
3234 to avoid creating a NOT of a CONST_INT. */
3235 rtx not_rtx = simplify_gen_unary (NOT, SImode, operands[3], SImode);
3236 if (CONST_INT_P (not_rtx))
3237 {
3238 operands[4] = operands[0];
3239 operands[5] = not_rtx;
3240 }
3241 else
3242 {
3243 operands[5] = operands[0];
3244 operands[4] = not_rtx;
3245 }
3246 }
0d66636f 3247 [(set_attr "length" "8")
25f905c2 3248 (set_attr "ce_count" "2")
d952d547 3249 (set_attr "predicable" "yes")
1b7da4ac 3250 (set_attr "predicable_short_it" "no")
3251 (set_attr "type" "multiple")]
cffb2a26 3252)
9c08d1fa 3253
25f905c2 3254; ??? Are these four splitters still beneficial when the Thumb-2 bitfield
3255; insns are available?
d7863cfe 3256(define_split
3257 [(set (match_operand:SI 0 "s_register_operand" "")
3258 (match_operator:SI 1 "logical_binary_operator"
3259 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
3260 (match_operand:SI 3 "const_int_operand" "")
3261 (match_operand:SI 4 "const_int_operand" ""))
3262 (match_operator:SI 9 "logical_binary_operator"
3263 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3264 (match_operand:SI 6 "const_int_operand" ""))
3265 (match_operand:SI 7 "s_register_operand" "")])]))
3266 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3267 "TARGET_32BIT
d7863cfe 3268 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3269 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3270 [(set (match_dup 8)
3271 (match_op_dup 1
3272 [(ashift:SI (match_dup 2) (match_dup 4))
3273 (match_dup 5)]))
3274 (set (match_dup 0)
3275 (match_op_dup 1
3276 [(lshiftrt:SI (match_dup 8) (match_dup 6))
3277 (match_dup 7)]))]
3278 "
3279 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3280")
3281
3282(define_split
3283 [(set (match_operand:SI 0 "s_register_operand" "")
3284 (match_operator:SI 1 "logical_binary_operator"
3285 [(match_operator:SI 9 "logical_binary_operator"
3286 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3287 (match_operand:SI 6 "const_int_operand" ""))
3288 (match_operand:SI 7 "s_register_operand" "")])
3289 (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
3290 (match_operand:SI 3 "const_int_operand" "")
3291 (match_operand:SI 4 "const_int_operand" ""))]))
3292 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3293 "TARGET_32BIT
d7863cfe 3294 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3295 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3296 [(set (match_dup 8)
3297 (match_op_dup 1
3298 [(ashift:SI (match_dup 2) (match_dup 4))
3299 (match_dup 5)]))
3300 (set (match_dup 0)
3301 (match_op_dup 1
3302 [(lshiftrt:SI (match_dup 8) (match_dup 6))
3303 (match_dup 7)]))]
3304 "
3305 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3306")
3307
3308(define_split
3309 [(set (match_operand:SI 0 "s_register_operand" "")
3310 (match_operator:SI 1 "logical_binary_operator"
3311 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
3312 (match_operand:SI 3 "const_int_operand" "")
3313 (match_operand:SI 4 "const_int_operand" ""))
3314 (match_operator:SI 9 "logical_binary_operator"
3315 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3316 (match_operand:SI 6 "const_int_operand" ""))
3317 (match_operand:SI 7 "s_register_operand" "")])]))
3318 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3319 "TARGET_32BIT
d7863cfe 3320 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3321 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3322 [(set (match_dup 8)
3323 (match_op_dup 1
3324 [(ashift:SI (match_dup 2) (match_dup 4))
3325 (match_dup 5)]))
3326 (set (match_dup 0)
3327 (match_op_dup 1
3328 [(ashiftrt:SI (match_dup 8) (match_dup 6))
3329 (match_dup 7)]))]
3330 "
3331 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3332")
3333
3334(define_split
3335 [(set (match_operand:SI 0 "s_register_operand" "")
3336 (match_operator:SI 1 "logical_binary_operator"
3337 [(match_operator:SI 9 "logical_binary_operator"
3338 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3339 (match_operand:SI 6 "const_int_operand" ""))
3340 (match_operand:SI 7 "s_register_operand" "")])
3341 (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
3342 (match_operand:SI 3 "const_int_operand" "")
3343 (match_operand:SI 4 "const_int_operand" ""))]))
3344 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3345 "TARGET_32BIT
d7863cfe 3346 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3347 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3348 [(set (match_dup 8)
3349 (match_op_dup 1
3350 [(ashift:SI (match_dup 2) (match_dup 4))
3351 (match_dup 5)]))
3352 (set (match_dup 0)
3353 (match_op_dup 1
3354 [(ashiftrt:SI (match_dup 8) (match_dup 6))
3355 (match_dup 7)]))]
3356 "
3357 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3358")
9c08d1fa 3359\f
3360
3361;; Minimum and maximum insns
3362
8b9dc177 3363(define_expand "smaxsi3"
3364 [(parallel [
3365 (set (match_operand:SI 0 "s_register_operand" "")
3366 (smax:SI (match_operand:SI 1 "s_register_operand" "")
3367 (match_operand:SI 2 "arm_rhs_operand" "")))
3368 (clobber (reg:CC CC_REGNUM))])]
25f905c2 3369 "TARGET_32BIT"
8b9dc177 3370 "
8774928b 3371 if (operands[2] == const0_rtx || operands[2] == constm1_rtx)
8b9dc177 3372 {
3373 /* No need for a clobber of the condition code register here. */
d1f9b275 3374 emit_insn (gen_rtx_SET (operands[0],
8b9dc177 3375 gen_rtx_SMAX (SImode, operands[1],
3376 operands[2])));
3377 DONE;
3378 }
3379")
3380
3381(define_insn "*smax_0"
3382 [(set (match_operand:SI 0 "s_register_operand" "=r")
3383 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3384 (const_int 0)))]
25f905c2 3385 "TARGET_32BIT"
8b9dc177 3386 "bic%?\\t%0, %1, %1, asr #31"
d952d547 3387 [(set_attr "predicable" "yes")
1b7da4ac 3388 (set_attr "predicable_short_it" "no")
3389 (set_attr "type" "logic_shift_reg")]
8b9dc177 3390)
3391
8774928b 3392(define_insn "*smax_m1"
3393 [(set (match_operand:SI 0 "s_register_operand" "=r")
3394 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3395 (const_int -1)))]
25f905c2 3396 "TARGET_32BIT"
8774928b 3397 "orr%?\\t%0, %1, %1, asr #31"
d952d547 3398 [(set_attr "predicable" "yes")
1b7da4ac 3399 (set_attr "predicable_short_it" "no")
3400 (set_attr "type" "logic_shift_reg")]
8774928b 3401)
3402
3dc953f2 3403(define_insn_and_split "*arm_smax_insn"
8b9dc177 3404 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3405 (smax:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3406 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
bd5b4116 3407 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3408 "TARGET_ARM"
3dc953f2 3409 "#"
3410 ; cmp\\t%1, %2\;movlt\\t%0, %2
3411 ; cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
3412 "TARGET_ARM"
3413 [(set (reg:CC CC_REGNUM)
3414 (compare:CC (match_dup 1) (match_dup 2)))
3415 (set (match_dup 0)
3416 (if_then_else:SI (ge:SI (reg:CC CC_REGNUM) (const_int 0))
3417 (match_dup 1)
3418 (match_dup 2)))]
3419 ""
cffb2a26 3420 [(set_attr "conds" "clob")
1b7da4ac 3421 (set_attr "length" "8,12")
3422 (set_attr "type" "multiple")]
cffb2a26 3423)
9c08d1fa 3424
8b9dc177 3425(define_expand "sminsi3"
3426 [(parallel [
3427 (set (match_operand:SI 0 "s_register_operand" "")
3428 (smin:SI (match_operand:SI 1 "s_register_operand" "")
3429 (match_operand:SI 2 "arm_rhs_operand" "")))
3430 (clobber (reg:CC CC_REGNUM))])]
25f905c2 3431 "TARGET_32BIT"
8b9dc177 3432 "
3433 if (operands[2] == const0_rtx)
3434 {
3435 /* No need for a clobber of the condition code register here. */
d1f9b275 3436 emit_insn (gen_rtx_SET (operands[0],
8b9dc177 3437 gen_rtx_SMIN (SImode, operands[1],
3438 operands[2])));
3439 DONE;
3440 }
3441")
3442
3443(define_insn "*smin_0"
3444 [(set (match_operand:SI 0 "s_register_operand" "=r")
3445 (smin:SI (match_operand:SI 1 "s_register_operand" "r")
3446 (const_int 0)))]
25f905c2 3447 "TARGET_32BIT"
8b9dc177 3448 "and%?\\t%0, %1, %1, asr #31"
d952d547 3449 [(set_attr "predicable" "yes")
1b7da4ac 3450 (set_attr "predicable_short_it" "no")
3451 (set_attr "type" "logic_shift_reg")]
8b9dc177 3452)
3453
3dc953f2 3454(define_insn_and_split "*arm_smin_insn"
8b9dc177 3455 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3456 (smin:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3457 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
bd5b4116 3458 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3459 "TARGET_ARM"
3dc953f2 3460 "#"
3461 ; cmp\\t%1, %2\;movge\\t%0, %2
3462 ; cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
3463 "TARGET_ARM"
3464 [(set (reg:CC CC_REGNUM)
3465 (compare:CC (match_dup 1) (match_dup 2)))
3466 (set (match_dup 0)
3467 (if_then_else:SI (lt:SI (reg:CC CC_REGNUM) (const_int 0))
3468 (match_dup 1)
3469 (match_dup 2)))]
3470 ""
0d66636f 3471 [(set_attr "conds" "clob")
1b7da4ac 3472 (set_attr "length" "8,12")
3473 (set_attr "type" "multiple,multiple")]
0d66636f 3474)
9c08d1fa 3475
25f905c2 3476(define_expand "umaxsi3"
3477 [(parallel [
3478 (set (match_operand:SI 0 "s_register_operand" "")
3479 (umax:SI (match_operand:SI 1 "s_register_operand" "")
3480 (match_operand:SI 2 "arm_rhs_operand" "")))
3481 (clobber (reg:CC CC_REGNUM))])]
3482 "TARGET_32BIT"
3483 ""
3484)
3485
3dc953f2 3486(define_insn_and_split "*arm_umaxsi3"
9c08d1fa 3487 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3488 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3489 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 3490 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3491 "TARGET_ARM"
3dc953f2 3492 "#"
3493 ; cmp\\t%1, %2\;movcc\\t%0, %2
3494 ; cmp\\t%1, %2\;movcs\\t%0, %1
3495 ; cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
3496 "TARGET_ARM"
3497 [(set (reg:CC CC_REGNUM)
3498 (compare:CC (match_dup 1) (match_dup 2)))
3499 (set (match_dup 0)
3500 (if_then_else:SI (geu:SI (reg:CC CC_REGNUM) (const_int 0))
3501 (match_dup 1)
3502 (match_dup 2)))]
3503 ""
0d66636f 3504 [(set_attr "conds" "clob")
1b7da4ac 3505 (set_attr "length" "8,8,12")
3506 (set_attr "type" "store1")]
0d66636f 3507)
9c08d1fa 3508
25f905c2 3509(define_expand "uminsi3"
3510 [(parallel [
3511 (set (match_operand:SI 0 "s_register_operand" "")
3512 (umin:SI (match_operand:SI 1 "s_register_operand" "")
3513 (match_operand:SI 2 "arm_rhs_operand" "")))
3514 (clobber (reg:CC CC_REGNUM))])]
3515 "TARGET_32BIT"
3516 ""
3517)
3518
3dc953f2 3519(define_insn_and_split "*arm_uminsi3"
9c08d1fa 3520 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3521 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3522 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 3523 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3524 "TARGET_ARM"
3dc953f2 3525 "#"
3526 ; cmp\\t%1, %2\;movcs\\t%0, %2
3527 ; cmp\\t%1, %2\;movcc\\t%0, %1
3528 ; cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
3529 "TARGET_ARM"
3530 [(set (reg:CC CC_REGNUM)
3531 (compare:CC (match_dup 1) (match_dup 2)))
3532 (set (match_dup 0)
3533 (if_then_else:SI (ltu:SI (reg:CC CC_REGNUM) (const_int 0))
3534 (match_dup 1)
3535 (match_dup 2)))]
3536 ""
0d66636f 3537 [(set_attr "conds" "clob")
1b7da4ac 3538 (set_attr "length" "8,8,12")
3539 (set_attr "type" "store1")]
0d66636f 3540)
9c08d1fa 3541
8a18b90c 3542(define_insn "*store_minmaxsi"
9c08d1fa 3543 [(set (match_operand:SI 0 "memory_operand" "=m")
3544 (match_operator:SI 3 "minmax_operator"
3545 [(match_operand:SI 1 "s_register_operand" "r")
3546 (match_operand:SI 2 "s_register_operand" "r")]))
bd5b4116 3547 (clobber (reg:CC CC_REGNUM))]
b207d152 3548 "TARGET_32BIT && optimize_function_for_size_p (cfun) && !arm_restrict_it"
9c08d1fa 3549 "*
dc55b8a9 3550 operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
3551 operands[1], operands[2]);
e2348bcb 3552 output_asm_insn (\"cmp\\t%1, %2\", operands);
25f905c2 3553 if (TARGET_THUMB2)
3554 output_asm_insn (\"ite\t%d3\", operands);
e2348bcb 3555 output_asm_insn (\"str%d3\\t%1, %0\", operands);
3556 output_asm_insn (\"str%D3\\t%2, %0\", operands);
3557 return \"\";
0d66636f 3558 "
3559 [(set_attr "conds" "clob")
25f905c2 3560 (set (attr "length")
3561 (if_then_else (eq_attr "is_thumb" "yes")
3562 (const_int 14)
3563 (const_int 12)))
0d66636f 3564 (set_attr "type" "store1")]
3565)
9c08d1fa 3566
8a18b90c 3567; Reject the frame pointer in operand[1], since reloading this after
3568; it has been eliminated can cause carnage.
f7fbdd4a 3569(define_insn "*minmax_arithsi"
9c08d1fa 3570 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3571 (match_operator:SI 4 "shiftable_operator"
3572 [(match_operator:SI 5 "minmax_operator"
3573 [(match_operand:SI 2 "s_register_operand" "r,r")
3574 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
3575 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 3576 (clobber (reg:CC CC_REGNUM))]
7c36fe71 3577 "TARGET_32BIT && !arm_eliminable_register (operands[1]) && !arm_restrict_it"
9c08d1fa 3578 "*
0d66636f 3579 {
3580 enum rtx_code code = GET_CODE (operands[4]);
25f905c2 3581 bool need_else;
3582
3583 if (which_alternative != 0 || operands[3] != const0_rtx
ca0fc5a2 3584 || (code != PLUS && code != IOR && code != XOR))
25f905c2 3585 need_else = true;
3586 else
3587 need_else = false;
0d66636f 3588
dc55b8a9 3589 operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
3590 operands[2], operands[3]);
0d66636f 3591 output_asm_insn (\"cmp\\t%2, %3\", operands);
25f905c2 3592 if (TARGET_THUMB2)
3593 {
3594 if (need_else)
3595 output_asm_insn (\"ite\\t%d5\", operands);
3596 else
3597 output_asm_insn (\"it\\t%d5\", operands);
3598 }
0d66636f 3599 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
25f905c2 3600 if (need_else)
0d66636f 3601 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
3602 return \"\";
215b30b3 3603 }"
0d66636f 3604 [(set_attr "conds" "clob")
25f905c2 3605 (set (attr "length")
3606 (if_then_else (eq_attr "is_thumb" "yes")
3607 (const_int 14)
1b7da4ac 3608 (const_int 12)))
3609 (set_attr "type" "multiple")]
0d66636f 3610)
9c08d1fa 3611
4164bca1 3612; Reject the frame pointer in operand[1], since reloading this after
3613; it has been eliminated can cause carnage.
3614(define_insn_and_split "*minmax_arithsi_non_canon"
7c36fe71 3615 [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts")
4164bca1 3616 (minus:SI
7c36fe71 3617 (match_operand:SI 1 "s_register_operand" "0,?Ts")
4164bca1 3618 (match_operator:SI 4 "minmax_operator"
7c36fe71 3619 [(match_operand:SI 2 "s_register_operand" "Ts,Ts")
3620 (match_operand:SI 3 "arm_rhs_operand" "TsI,TsI")])))
4164bca1 3621 (clobber (reg:CC CC_REGNUM))]
7c36fe71 3622 "TARGET_32BIT && !arm_eliminable_register (operands[1])
3623 && !(arm_restrict_it && CONST_INT_P (operands[3]))"
4164bca1 3624 "#"
3625 "TARGET_32BIT && !arm_eliminable_register (operands[1]) && reload_completed"
3626 [(set (reg:CC CC_REGNUM)
3627 (compare:CC (match_dup 2) (match_dup 3)))
3628
3629 (cond_exec (match_op_dup 4 [(reg:CC CC_REGNUM) (const_int 0)])
3630 (set (match_dup 0)
3631 (minus:SI (match_dup 1)
3632 (match_dup 2))))
3633 (cond_exec (match_op_dup 5 [(reg:CC CC_REGNUM) (const_int 0)])
3634 (set (match_dup 0)
36ee0cde 3635 (match_dup 6)))]
4164bca1 3636 {
3754d046 3637 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
4164bca1 3638 operands[2], operands[3]);
3639 enum rtx_code rc = minmax_code (operands[4]);
3640 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode,
3641 operands[2], operands[3]);
3642
3643 if (mode == CCFPmode || mode == CCFPEmode)
3644 rc = reverse_condition_maybe_unordered (rc);
3645 else
3646 rc = reverse_condition (rc);
3647 operands[5] = gen_rtx_fmt_ee (rc, SImode, operands[2], operands[3]);
36ee0cde 3648 if (CONST_INT_P (operands[3]))
3649 operands[6] = plus_constant (SImode, operands[1], -INTVAL (operands[3]));
3650 else
3651 operands[6] = gen_rtx_MINUS (SImode, operands[1], operands[3]);
4164bca1 3652 }
3653 [(set_attr "conds" "clob")
3654 (set (attr "length")
3655 (if_then_else (eq_attr "is_thumb" "yes")
3656 (const_int 14)
1b7da4ac 3657 (const_int 12)))
3658 (set_attr "type" "multiple")]
4164bca1 3659)
3660
b49e3742 3661(define_code_iterator SAT [smin smax])
3662(define_code_iterator SATrev [smin smax])
3663(define_code_attr SATlo [(smin "1") (smax "2")])
3664(define_code_attr SAThi [(smin "2") (smax "1")])
3665
3666(define_insn "*satsi_<SAT:code>"
3667 [(set (match_operand:SI 0 "s_register_operand" "=r")
3668 (SAT:SI (SATrev:SI (match_operand:SI 3 "s_register_operand" "r")
3669 (match_operand:SI 1 "const_int_operand" "i"))
3670 (match_operand:SI 2 "const_int_operand" "i")))]
3671 "TARGET_32BIT && arm_arch6 && <SAT:CODE> != <SATrev:CODE>
3672 && arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>], NULL, NULL)"
3673{
3674 int mask;
3675 bool signed_sat;
3676 if (!arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>],
3677 &mask, &signed_sat))
3678 gcc_unreachable ();
3679
3680 operands[1] = GEN_INT (mask);
3681 if (signed_sat)
3682 return "ssat%?\t%0, %1, %3";
3683 else
3684 return "usat%?\t%0, %1, %3";
3685}
7c36fe71 3686 [(set_attr "predicable" "yes")
1b7da4ac 3687 (set_attr "predicable_short_it" "no")
3688 (set_attr "type" "alus_imm")]
bebe9bbb 3689)
b49e3742 3690
3691(define_insn "*satsi_<SAT:code>_shift"
3692 [(set (match_operand:SI 0 "s_register_operand" "=r")
3693 (SAT:SI (SATrev:SI (match_operator:SI 3 "sat_shift_operator"
3694 [(match_operand:SI 4 "s_register_operand" "r")
3695 (match_operand:SI 5 "const_int_operand" "i")])
3696 (match_operand:SI 1 "const_int_operand" "i"))
3697 (match_operand:SI 2 "const_int_operand" "i")))]
3698 "TARGET_32BIT && arm_arch6 && <SAT:CODE> != <SATrev:CODE>
3699 && arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>], NULL, NULL)"
3700{
3701 int mask;
3702 bool signed_sat;
3703 if (!arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>],
3704 &mask, &signed_sat))
3705 gcc_unreachable ();
3706
3707 operands[1] = GEN_INT (mask);
3708 if (signed_sat)
3709 return "ssat%?\t%0, %1, %4%S3";
3710 else
3711 return "usat%?\t%0, %1, %4%S3";
3712}
3713 [(set_attr "predicable" "yes")
7c36fe71 3714 (set_attr "predicable_short_it" "no")
b49e3742 3715 (set_attr "shift" "3")
d82e788e 3716 (set_attr "type" "logic_shift_reg")])
b11cae9e 3717\f
3718;; Shift and rotation insns
3719
a2cd141b 3720(define_expand "ashldi3"
3721 [(set (match_operand:DI 0 "s_register_operand" "")
3722 (ashift:DI (match_operand:DI 1 "s_register_operand" "")
aa06c51c 3723 (match_operand:SI 2 "general_operand" "")))]
25f905c2 3724 "TARGET_32BIT"
a2cd141b 3725 "
aa06c51c 3726 if (TARGET_NEON)
3727 {
3728 /* Delay the decision whether to use NEON or core-regs until
3729 register allocation. */
3730 emit_insn (gen_ashldi3_neon (operands[0], operands[1], operands[2]));
3731 DONE;
3732 }
3733 else
3734 {
3735 /* Only the NEON case can handle in-memory shift counts. */
3736 if (!reg_or_int_operand (operands[2], SImode))
3737 operands[2] = force_reg (SImode, operands[2]);
3738 }
3739
b805622c 3740 if (!CONST_INT_P (operands[2]) && TARGET_REALLY_IWMMXT)
ffcc986d 3741 ; /* No special preparation statements; expand pattern as above. */
3742 else
a2cd141b 3743 {
ffcc986d 3744 rtx scratch1, scratch2;
3745
3746 if (CONST_INT_P (operands[2])
3747 && (HOST_WIDE_INT) INTVAL (operands[2]) == 1)
a2cd141b 3748 {
3749 emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
3750 DONE;
3751 }
ffcc986d 3752
3753 /* Ideally we should use iwmmxt here if we could know that operands[1]
3754 ends up already living in an iwmmxt register. Otherwise it's
3755 cheaper to have the alternate code being generated than moving
3756 values to iwmmxt regs and back. */
3757
3758 /* If we're optimizing for size, we prefer the libgcc calls. */
3759 if (optimize_function_for_size_p (cfun))
3760 FAIL;
3761
3762 /* Expand operation using core-registers.
3763 'FAIL' would achieve the same thing, but this is a bit smarter. */
3764 scratch1 = gen_reg_rtx (SImode);
3765 scratch2 = gen_reg_rtx (SImode);
3766 arm_emit_coreregs_64bit_shift (ASHIFT, operands[0], operands[1],
3767 operands[2], scratch1, scratch2);
3768 DONE;
a2cd141b 3769 }
a2cd141b 3770 "
3771)
3772
2837e3fb 3773(define_insn "arm_ashldi3_1bit"
50ad1bf9 3774 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 3775 (ashift:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 3776 (const_int 1)))
3777 (clobber (reg:CC CC_REGNUM))]
25f905c2 3778 "TARGET_32BIT"
2837e3fb 3779 "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
a2cd141b 3780 [(set_attr "conds" "clob")
1b7da4ac 3781 (set_attr "length" "8")
3782 (set_attr "type" "multiple")]
a2cd141b 3783)
3784
87b22bf7 3785(define_expand "ashlsi3"
cffb2a26 3786 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3787 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
3788 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3789 "TARGET_EITHER"
87b22bf7 3790 "
0438d37f 3791 if (CONST_INT_P (operands[2])
87b22bf7 3792 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3793 {
3794 emit_insn (gen_movsi (operands[0], const0_rtx));
3795 DONE;
3796 }
cffb2a26 3797 "
3798)
3799
a2cd141b 3800(define_expand "ashrdi3"
3801 [(set (match_operand:DI 0 "s_register_operand" "")
3802 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
3803 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3804 "TARGET_32BIT"
a2cd141b 3805 "
aa06c51c 3806 if (TARGET_NEON)
3807 {
3808 /* Delay the decision whether to use NEON or core-regs until
3809 register allocation. */
3810 emit_insn (gen_ashrdi3_neon (operands[0], operands[1], operands[2]));
3811 DONE;
3812 }
3813
b805622c 3814 if (!CONST_INT_P (operands[2]) && TARGET_REALLY_IWMMXT)
ffcc986d 3815 ; /* No special preparation statements; expand pattern as above. */
3816 else
a2cd141b 3817 {
ffcc986d 3818 rtx scratch1, scratch2;
3819
3820 if (CONST_INT_P (operands[2])
3821 && (HOST_WIDE_INT) INTVAL (operands[2]) == 1)
a2cd141b 3822 {
3823 emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
3824 DONE;
3825 }
ffcc986d 3826
3827 /* Ideally we should use iwmmxt here if we could know that operands[1]
3828 ends up already living in an iwmmxt register. Otherwise it's
3829 cheaper to have the alternate code being generated than moving
3830 values to iwmmxt regs and back. */
3831
3832 /* If we're optimizing for size, we prefer the libgcc calls. */
3833 if (optimize_function_for_size_p (cfun))
3834 FAIL;
3835
3836 /* Expand operation using core-registers.
3837 'FAIL' would achieve the same thing, but this is a bit smarter. */
3838 scratch1 = gen_reg_rtx (SImode);
3839 scratch2 = gen_reg_rtx (SImode);
3840 arm_emit_coreregs_64bit_shift (ASHIFTRT, operands[0], operands[1],
3841 operands[2], scratch1, scratch2);
3842 DONE;
a2cd141b 3843 }
a2cd141b 3844 "
3845)
3846
2837e3fb 3847(define_insn "arm_ashrdi3_1bit"
50ad1bf9 3848 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 3849 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 3850 (const_int 1)))
3851 (clobber (reg:CC CC_REGNUM))]
25f905c2 3852 "TARGET_32BIT"
2837e3fb 3853 "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
a2cd141b 3854 [(set_attr "conds" "clob")
1b7da4ac 3855 (set_attr "length" "8")
3856 (set_attr "type" "multiple")]
a2cd141b 3857)
3858
87b22bf7 3859(define_expand "ashrsi3"
cffb2a26 3860 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3861 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
3862 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3863 "TARGET_EITHER"
87b22bf7 3864 "
0438d37f 3865 if (CONST_INT_P (operands[2])
87b22bf7 3866 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3867 operands[2] = GEN_INT (31);
cffb2a26 3868 "
3869)
3870
a2cd141b 3871(define_expand "lshrdi3"
3872 [(set (match_operand:DI 0 "s_register_operand" "")
3873 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
3874 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3875 "TARGET_32BIT"
a2cd141b 3876 "
aa06c51c 3877 if (TARGET_NEON)
3878 {
3879 /* Delay the decision whether to use NEON or core-regs until
3880 register allocation. */
3881 emit_insn (gen_lshrdi3_neon (operands[0], operands[1], operands[2]));
3882 DONE;
3883 }
3884
b805622c 3885 if (!CONST_INT_P (operands[2]) && TARGET_REALLY_IWMMXT)
ffcc986d 3886 ; /* No special preparation statements; expand pattern as above. */
3887 else
a2cd141b 3888 {
ffcc986d 3889 rtx scratch1, scratch2;
3890
3891 if (CONST_INT_P (operands[2])
3892 && (HOST_WIDE_INT) INTVAL (operands[2]) == 1)
a2cd141b 3893 {
3894 emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
3895 DONE;
3896 }
ffcc986d 3897
3898 /* Ideally we should use iwmmxt here if we could know that operands[1]
3899 ends up already living in an iwmmxt register. Otherwise it's
3900 cheaper to have the alternate code being generated than moving
3901 values to iwmmxt regs and back. */
3902
3903 /* If we're optimizing for size, we prefer the libgcc calls. */
3904 if (optimize_function_for_size_p (cfun))
3905 FAIL;
3906
3907 /* Expand operation using core-registers.
3908 'FAIL' would achieve the same thing, but this is a bit smarter. */
3909 scratch1 = gen_reg_rtx (SImode);
3910 scratch2 = gen_reg_rtx (SImode);
3911 arm_emit_coreregs_64bit_shift (LSHIFTRT, operands[0], operands[1],
3912 operands[2], scratch1, scratch2);
3913 DONE;
a2cd141b 3914 }
a2cd141b 3915 "
3916)
3917
2837e3fb 3918(define_insn "arm_lshrdi3_1bit"
50ad1bf9 3919 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 3920 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 3921 (const_int 1)))
3922 (clobber (reg:CC CC_REGNUM))]
25f905c2 3923 "TARGET_32BIT"
2837e3fb 3924 "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
a2cd141b 3925 [(set_attr "conds" "clob")
1b7da4ac 3926 (set_attr "length" "8")
3927 (set_attr "type" "multiple")]
a2cd141b 3928)
3929
87b22bf7 3930(define_expand "lshrsi3"
cffb2a26 3931 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3932 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
3933 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3934 "TARGET_EITHER"
87b22bf7 3935 "
0438d37f 3936 if (CONST_INT_P (operands[2])
87b22bf7 3937 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3938 {
3939 emit_insn (gen_movsi (operands[0], const0_rtx));
3940 DONE;
3941 }
cffb2a26 3942 "
3943)
3944
87b22bf7 3945(define_expand "rotlsi3"
cffb2a26 3946 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3947 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
3948 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3949 "TARGET_32BIT"
87b22bf7 3950 "
0438d37f 3951 if (CONST_INT_P (operands[2]))
87b22bf7 3952 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
3953 else
b11cae9e 3954 {
87b22bf7 3955 rtx reg = gen_reg_rtx (SImode);
3956 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
3957 operands[2] = reg;
b11cae9e 3958 }
cffb2a26 3959 "
3960)
9c08d1fa 3961
87b22bf7 3962(define_expand "rotrsi3"
cffb2a26 3963 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3964 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
3965 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3966 "TARGET_EITHER"
87b22bf7 3967 "
25f905c2 3968 if (TARGET_32BIT)
cffb2a26 3969 {
0438d37f 3970 if (CONST_INT_P (operands[2])
cffb2a26 3971 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3972 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
3973 }
25f905c2 3974 else /* TARGET_THUMB1 */
cffb2a26 3975 {
0438d37f 3976 if (CONST_INT_P (operands [2]))
cffb2a26 3977 operands [2] = force_reg (SImode, operands[2]);
3978 }
3979 "
3980)
87b22bf7 3981
cffb2a26 3982(define_insn "*arm_shiftsi3"
88c29385 3983 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r,r")
cffb2a26 3984 (match_operator:SI 3 "shift_operator"
88c29385 3985 [(match_operand:SI 1 "s_register_operand" "0,l,r,r")
3986 (match_operand:SI 2 "reg_or_int_operand" "l,M,M,r")]))]
25f905c2 3987 "TARGET_32BIT"
3988 "* return arm_output_shift(operands, 0);"
344495ea 3989 [(set_attr "predicable" "yes")
88c29385 3990 (set_attr "arch" "t2,t2,*,*")
3991 (set_attr "predicable_short_it" "yes,yes,no,no")
7c36fe71 3992 (set_attr "length" "4")
331beb1a 3993 (set_attr "shift" "1")
88c29385 3994 (set_attr "type" "alu_shift_reg,alu_shift_imm,alu_shift_imm,alu_shift_reg")]
6c4c2133 3995)
87b22bf7 3996
f7fbdd4a 3997(define_insn "*shiftsi3_compare0"
bd5b4116 3998 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 3999 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
6b6abc9c 4000 [(match_operand:SI 1 "s_register_operand" "r,r")
4001 (match_operand:SI 2 "arm_rhs_operand" "M,r")])
9c08d1fa 4002 (const_int 0)))
6b6abc9c 4003 (set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 4004 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
25f905c2 4005 "TARGET_32BIT"
4006 "* return arm_output_shift(operands, 1);"
344495ea 4007 [(set_attr "conds" "set")
331beb1a 4008 (set_attr "shift" "1")
d82e788e 4009 (set_attr "type" "alus_shift_imm,alus_shift_reg")]
0d66636f 4010)
9c08d1fa 4011
f7fbdd4a 4012(define_insn "*shiftsi3_compare0_scratch"
bd5b4116 4013 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 4014 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
6b6abc9c 4015 [(match_operand:SI 1 "s_register_operand" "r,r")
4016 (match_operand:SI 2 "arm_rhs_operand" "M,r")])
9c08d1fa 4017 (const_int 0)))
6b6abc9c 4018 (clobber (match_scratch:SI 0 "=r,r"))]
25f905c2 4019 "TARGET_32BIT"
4020 "* return arm_output_shift(operands, 1);"
344495ea 4021 [(set_attr "conds" "set")
6b6abc9c 4022 (set_attr "shift" "1")
d82e788e 4023 (set_attr "type" "shift_imm,shift_reg")]
0d66636f 4024)
9c08d1fa 4025
d5d4dc8d 4026(define_insn "*not_shiftsi"
4027 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 4028 (not:SI (match_operator:SI 3 "shift_operator"
d5d4dc8d 4029 [(match_operand:SI 1 "s_register_operand" "r,r")
4030 (match_operand:SI 2 "shift_amount_operand" "M,rM")])))]
4031 "TARGET_32BIT"
6c4c2133 4032 "mvn%?\\t%0, %1%S3"
344495ea 4033 [(set_attr "predicable" "yes")
d952d547 4034 (set_attr "predicable_short_it" "no")
331beb1a 4035 (set_attr "shift" "1")
d5d4dc8d 4036 (set_attr "arch" "32,a")
1aed5204 4037 (set_attr "type" "mvn_shift,mvn_shift_reg")])
9c08d1fa 4038
d5d4dc8d 4039(define_insn "*not_shiftsi_compare0"
bd5b4116 4040 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 4041 (compare:CC_NOOV
4042 (not:SI (match_operator:SI 3 "shift_operator"
4043 [(match_operand:SI 1 "s_register_operand" "r,r")
4044 (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
4045 (const_int 0)))
4046 (set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 4047 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
d5d4dc8d 4048 "TARGET_32BIT"
3ef90e77 4049 "mvns%?\\t%0, %1%S3"
344495ea 4050 [(set_attr "conds" "set")
331beb1a 4051 (set_attr "shift" "1")
d5d4dc8d 4052 (set_attr "arch" "32,a")
1aed5204 4053 (set_attr "type" "mvn_shift,mvn_shift_reg")])
9c08d1fa 4054
d5d4dc8d 4055(define_insn "*not_shiftsi_compare0_scratch"
bd5b4116 4056 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 4057 (compare:CC_NOOV
4058 (not:SI (match_operator:SI 3 "shift_operator"
4059 [(match_operand:SI 1 "s_register_operand" "r,r")
4060 (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
4061 (const_int 0)))
4062 (clobber (match_scratch:SI 0 "=r,r"))]
4063 "TARGET_32BIT"
3ef90e77 4064 "mvns%?\\t%0, %1%S3"
344495ea 4065 [(set_attr "conds" "set")
331beb1a 4066 (set_attr "shift" "1")
d5d4dc8d 4067 (set_attr "arch" "32,a")
1aed5204 4068 (set_attr "type" "mvn_shift,mvn_shift_reg")])
9c08d1fa 4069
cffb2a26 4070;; We don't really have extzv, but defining this using shifts helps
4071;; to reduce register pressure later on.
4072
4073(define_expand "extzv"
eb04cafb 4074 [(set (match_operand 0 "s_register_operand" "")
4075 (zero_extract (match_operand 1 "nonimmediate_operand" "")
4076 (match_operand 2 "const_int_operand" "")
4077 (match_operand 3 "const_int_operand" "")))]
8b054d5a 4078 "TARGET_THUMB1 || arm_arch_thumb2"
cffb2a26 4079 "
4080 {
4081 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
4082 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
4083
8b054d5a 4084 if (arm_arch_thumb2)
4085 {
eb04cafb 4086 HOST_WIDE_INT width = INTVAL (operands[2]);
4087 HOST_WIDE_INT bitpos = INTVAL (operands[3]);
4088
4089 if (unaligned_access && MEM_P (operands[1])
4090 && (width == 16 || width == 32) && (bitpos % BITS_PER_UNIT) == 0)
4091 {
4092 rtx base_addr;
4093
4094 if (BYTES_BIG_ENDIAN)
4095 bitpos = GET_MODE_BITSIZE (GET_MODE (operands[0])) - width
4096 - bitpos;
4097
4098 if (width == 32)
4099 {
4100 base_addr = adjust_address (operands[1], SImode,
4101 bitpos / BITS_PER_UNIT);
4102 emit_insn (gen_unaligned_loadsi (operands[0], base_addr));
4103 }
4104 else
4105 {
4106 rtx dest = operands[0];
4107 rtx tmp = gen_reg_rtx (SImode);
4108
4109 /* We may get a paradoxical subreg here. Strip it off. */
4110 if (GET_CODE (dest) == SUBREG
4111 && GET_MODE (dest) == SImode
4112 && GET_MODE (SUBREG_REG (dest)) == HImode)
4113 dest = SUBREG_REG (dest);
4114
4115 if (GET_MODE_BITSIZE (GET_MODE (dest)) != width)
4116 FAIL;
4117
4118 base_addr = adjust_address (operands[1], HImode,
4119 bitpos / BITS_PER_UNIT);
4120 emit_insn (gen_unaligned_loadhiu (tmp, base_addr));
4121 emit_move_insn (gen_lowpart (SImode, dest), tmp);
4122 }
4123 DONE;
4124 }
4125 else if (s_register_operand (operands[1], GET_MODE (operands[1])))
4126 {
4127 emit_insn (gen_extzv_t2 (operands[0], operands[1], operands[2],
4128 operands[3]));
4129 DONE;
4130 }
4131 else
4132 FAIL;
8b054d5a 4133 }
eb04cafb 4134
4135 if (!s_register_operand (operands[1], GET_MODE (operands[1])))
4136 FAIL;
8b054d5a 4137
cffb2a26 4138 operands[3] = GEN_INT (rshift);
4139
4140 if (lshift == 0)
4141 {
4142 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
4143 DONE;
4144 }
4145
eb04cafb 4146 emit_insn (gen_extzv_t1 (operands[0], operands[1], GEN_INT (lshift),
4147 operands[3], gen_reg_rtx (SImode)));
4148 DONE;
215b30b3 4149 }"
cffb2a26 4150)
4151
eb04cafb 4152;; Helper for extzv, for the Thumb-1 register-shifts case.
4153
4154(define_expand "extzv_t1"
4155 [(set (match_operand:SI 4 "s_register_operand" "")
4156 (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "")
4157 (match_operand:SI 2 "const_int_operand" "")))
4158 (set (match_operand:SI 0 "s_register_operand" "")
4159 (lshiftrt:SI (match_dup 4)
4160 (match_operand:SI 3 "const_int_operand" "")))]
4161 "TARGET_THUMB1"
4162 "")
4163
4164(define_expand "extv"
4165 [(set (match_operand 0 "s_register_operand" "")
4166 (sign_extract (match_operand 1 "nonimmediate_operand" "")
4167 (match_operand 2 "const_int_operand" "")
4168 (match_operand 3 "const_int_operand" "")))]
4169 "arm_arch_thumb2"
4170{
4171 HOST_WIDE_INT width = INTVAL (operands[2]);
4172 HOST_WIDE_INT bitpos = INTVAL (operands[3]);
4173
4174 if (unaligned_access && MEM_P (operands[1]) && (width == 16 || width == 32)
4175 && (bitpos % BITS_PER_UNIT) == 0)
4176 {
4177 rtx base_addr;
4178
4179 if (BYTES_BIG_ENDIAN)
4180 bitpos = GET_MODE_BITSIZE (GET_MODE (operands[0])) - width - bitpos;
4181
4182 if (width == 32)
4183 {
4184 base_addr = adjust_address (operands[1], SImode,
4185 bitpos / BITS_PER_UNIT);
4186 emit_insn (gen_unaligned_loadsi (operands[0], base_addr));
4187 }
4188 else
4189 {
4190 rtx dest = operands[0];
4191 rtx tmp = gen_reg_rtx (SImode);
4192
4193 /* We may get a paradoxical subreg here. Strip it off. */
4194 if (GET_CODE (dest) == SUBREG
4195 && GET_MODE (dest) == SImode
4196 && GET_MODE (SUBREG_REG (dest)) == HImode)
4197 dest = SUBREG_REG (dest);
4198
4199 if (GET_MODE_BITSIZE (GET_MODE (dest)) != width)
4200 FAIL;
4201
4202 base_addr = adjust_address (operands[1], HImode,
4203 bitpos / BITS_PER_UNIT);
4204 emit_insn (gen_unaligned_loadhis (tmp, base_addr));
4205 emit_move_insn (gen_lowpart (SImode, dest), tmp);
4206 }
4207
4208 DONE;
4209 }
4210 else if (!s_register_operand (operands[1], GET_MODE (operands[1])))
4211 FAIL;
4212 else if (GET_MODE (operands[0]) == SImode
4213 && GET_MODE (operands[1]) == SImode)
4214 {
4215 emit_insn (gen_extv_regsi (operands[0], operands[1], operands[2],
4216 operands[3]));
4217 DONE;
4218 }
4219
4220 FAIL;
4221})
4222
4223; Helper to expand register forms of extv with the proper modes.
4224
4225(define_expand "extv_regsi"
4226 [(set (match_operand:SI 0 "s_register_operand" "")
4227 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
4228 (match_operand 2 "const_int_operand" "")
4229 (match_operand 3 "const_int_operand" "")))]
4230 ""
4231{
4232})
4233
4234; ARMv6+ unaligned load/store instructions (used for packed structure accesses).
4235
4236(define_insn "unaligned_loadsi"
4237 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4238 (unspec:SI [(match_operand:SI 1 "memory_operand" "Uw,m")]
4239 UNSPEC_UNALIGNED_LOAD))]
8fe38eb2 4240 "unaligned_access"
eb04cafb 4241 "ldr%?\t%0, %1\t@ unaligned"
4242 [(set_attr "arch" "t2,any")
4243 (set_attr "length" "2,4")
4244 (set_attr "predicable" "yes")
d952d547 4245 (set_attr "predicable_short_it" "yes,no")
eb04cafb 4246 (set_attr "type" "load1")])
4247
4248(define_insn "unaligned_loadhis"
4249 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4250 (sign_extend:SI
e3f4ccee 4251 (unspec:HI [(match_operand:HI 1 "memory_operand" "Uw,Uh")]
eb04cafb 4252 UNSPEC_UNALIGNED_LOAD)))]
8fe38eb2 4253 "unaligned_access"
3ef90e77 4254 "ldrsh%?\t%0, %1\t@ unaligned"
eb04cafb 4255 [(set_attr "arch" "t2,any")
4256 (set_attr "length" "2,4")
4257 (set_attr "predicable" "yes")
d952d547 4258 (set_attr "predicable_short_it" "yes,no")
eb04cafb 4259 (set_attr "type" "load_byte")])
4260
4261(define_insn "unaligned_loadhiu"
4262 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4263 (zero_extend:SI
4264 (unspec:HI [(match_operand:HI 1 "memory_operand" "Uw,m")]
4265 UNSPEC_UNALIGNED_LOAD)))]
8fe38eb2 4266 "unaligned_access"
3ef90e77 4267 "ldrh%?\t%0, %1\t@ unaligned"
eb04cafb 4268 [(set_attr "arch" "t2,any")
4269 (set_attr "length" "2,4")
4270 (set_attr "predicable" "yes")
d952d547 4271 (set_attr "predicable_short_it" "yes,no")
eb04cafb 4272 (set_attr "type" "load_byte")])
4273
4274(define_insn "unaligned_storesi"
4275 [(set (match_operand:SI 0 "memory_operand" "=Uw,m")
4276 (unspec:SI [(match_operand:SI 1 "s_register_operand" "l,r")]
4277 UNSPEC_UNALIGNED_STORE))]
8fe38eb2 4278 "unaligned_access"
eb04cafb 4279 "str%?\t%1, %0\t@ unaligned"
4280 [(set_attr "arch" "t2,any")
4281 (set_attr "length" "2,4")
4282 (set_attr "predicable" "yes")
d952d547 4283 (set_attr "predicable_short_it" "yes,no")
eb04cafb 4284 (set_attr "type" "store1")])
4285
4286(define_insn "unaligned_storehi"
4287 [(set (match_operand:HI 0 "memory_operand" "=Uw,m")
4288 (unspec:HI [(match_operand:HI 1 "s_register_operand" "l,r")]
4289 UNSPEC_UNALIGNED_STORE))]
8fe38eb2 4290 "unaligned_access"
3ef90e77 4291 "strh%?\t%1, %0\t@ unaligned"
eb04cafb 4292 [(set_attr "arch" "t2,any")
4293 (set_attr "length" "2,4")
4294 (set_attr "predicable" "yes")
d952d547 4295 (set_attr "predicable_short_it" "yes,no")
eb04cafb 4296 (set_attr "type" "store1")])
4297
ae51a965 4298
eb04cafb 4299(define_insn "*extv_reg"
8b054d5a 4300 [(set (match_operand:SI 0 "s_register_operand" "=r")
4301 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
809003b3 4302 (match_operand:SI 2 "const_int_M_operand" "M")
4303 (match_operand:SI 3 "const_int_M_operand" "M")))]
8b054d5a 4304 "arm_arch_thumb2"
4305 "sbfx%?\t%0, %1, %3, %2"
4306 [(set_attr "length" "4")
d952d547 4307 (set_attr "predicable" "yes")
d82e788e 4308 (set_attr "predicable_short_it" "no")
4309 (set_attr "type" "bfm")]
8b054d5a 4310)
4311
4312(define_insn "extzv_t2"
4313 [(set (match_operand:SI 0 "s_register_operand" "=r")
4314 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "r")
809003b3 4315 (match_operand:SI 2 "const_int_M_operand" "M")
4316 (match_operand:SI 3 "const_int_M_operand" "M")))]
8b054d5a 4317 "arm_arch_thumb2"
4318 "ubfx%?\t%0, %1, %3, %2"
4319 [(set_attr "length" "4")
d952d547 4320 (set_attr "predicable" "yes")
d82e788e 4321 (set_attr "predicable_short_it" "no")
4322 (set_attr "type" "bfm")]
8b054d5a 4323)
4324
7d3cda8c 4325
4326;; Division instructions
4327(define_insn "divsi3"
4328 [(set (match_operand:SI 0 "s_register_operand" "=r")
4329 (div:SI (match_operand:SI 1 "s_register_operand" "r")
4330 (match_operand:SI 2 "s_register_operand" "r")))]
4331 "TARGET_IDIV"
4332 "sdiv%?\t%0, %1, %2"
4333 [(set_attr "predicable" "yes")
d952d547 4334 (set_attr "predicable_short_it" "no")
9da0ec36 4335 (set_attr "type" "sdiv")]
7d3cda8c 4336)
4337
4338(define_insn "udivsi3"
4339 [(set (match_operand:SI 0 "s_register_operand" "=r")
4340 (udiv:SI (match_operand:SI 1 "s_register_operand" "r")
4341 (match_operand:SI 2 "s_register_operand" "r")))]
4342 "TARGET_IDIV"
4343 "udiv%?\t%0, %1, %2"
4344 [(set_attr "predicable" "yes")
d952d547 4345 (set_attr "predicable_short_it" "no")
9da0ec36 4346 (set_attr "type" "udiv")]
7d3cda8c 4347)
4348
b11cae9e 4349\f
4350;; Unary arithmetic insns
4351
cffb2a26 4352(define_expand "negdi2"
4353 [(parallel
8135a42b 4354 [(set (match_operand:DI 0 "s_register_operand" "")
4355 (neg:DI (match_operand:DI 1 "s_register_operand" "")))
bd5b4116 4356 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 4357 "TARGET_EITHER"
774d2fbb 4358 {
4359 if (TARGET_NEON)
4360 {
4361 emit_insn (gen_negdi2_neon (operands[0], operands[1]));
4362 DONE;
4363 }
4364 }
cffb2a26 4365)
4366
4367;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
e5fea38e 4368;; The first alternative allows the common case of a *full* overlap.
ba6a3b2f 4369(define_insn_and_split "*arm_negdi2"
458a8706 4370 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 4371 (neg:DI (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 4372 (clobber (reg:CC CC_REGNUM))]
cffb2a26 4373 "TARGET_ARM"
ba6a3b2f 4374 "#" ; "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
4375 "&& reload_completed"
4376 [(parallel [(set (reg:CC CC_REGNUM)
4377 (compare:CC (const_int 0) (match_dup 1)))
4378 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 1)))])
4379 (set (match_dup 2) (minus:SI (minus:SI (const_int 0) (match_dup 3))
4380 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
4381 {
4382 operands[2] = gen_highpart (SImode, operands[0]);
4383 operands[0] = gen_lowpart (SImode, operands[0]);
4384 operands[3] = gen_highpart (SImode, operands[1]);
4385 operands[1] = gen_lowpart (SImode, operands[1]);
4386 }
cffb2a26 4387 [(set_attr "conds" "clob")
1b7da4ac 4388 (set_attr "length" "8")
4389 (set_attr "type" "multiple")]
cffb2a26 4390)
b11cae9e 4391
cffb2a26 4392(define_expand "negsi2"
4393 [(set (match_operand:SI 0 "s_register_operand" "")
4394 (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
4395 "TARGET_EITHER"
b11cae9e 4396 ""
cffb2a26 4397)
4398
4399(define_insn "*arm_negsi2"
d952d547 4400 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4401 (neg:SI (match_operand:SI 1 "s_register_operand" "l,r")))]
25f905c2 4402 "TARGET_32BIT"
cffb2a26 4403 "rsb%?\\t%0, %1, #0"
d952d547 4404 [(set_attr "predicable" "yes")
4405 (set_attr "predicable_short_it" "yes,no")
4406 (set_attr "arch" "t2,*")
1b7da4ac 4407 (set_attr "length" "4")
112eda6f 4408 (set_attr "type" "alu_sreg")]
cffb2a26 4409)
4410
604f3a0a 4411(define_expand "negsf2"
4412 [(set (match_operand:SF 0 "s_register_operand" "")
4413 (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
994606f8 4414 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
604f3a0a 4415 ""
4416)
4417
4418(define_expand "negdf2"
4419 [(set (match_operand:DF 0 "s_register_operand" "")
4420 (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
994606f8 4421 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
604f3a0a 4422 "")
4423
7eaf2be0 4424(define_insn_and_split "*zextendsidi_negsi"
4425 [(set (match_operand:DI 0 "s_register_operand" "=r")
4426 (zero_extend:DI (neg:SI (match_operand:SI 1 "s_register_operand" "r"))))]
4427 "TARGET_32BIT"
4428 "#"
4429 ""
4430 [(set (match_dup 2)
4431 (neg:SI (match_dup 1)))
4432 (set (match_dup 3)
4433 (const_int 0))]
4434 {
4435 operands[2] = gen_lowpart (SImode, operands[0]);
4436 operands[3] = gen_highpart (SImode, operands[0]);
4437 }
4438 [(set_attr "length" "8")
4439 (set_attr "type" "multiple")]
4440)
4441
83e2b922 4442;; Negate an extended 32-bit value.
4443(define_insn_and_split "*negdi_extendsidi"
61fa8ff2 4444 [(set (match_operand:DI 0 "s_register_operand" "=l,r")
4445 (neg:DI (sign_extend:DI
4446 (match_operand:SI 1 "s_register_operand" "l,r"))))
83e2b922 4447 (clobber (reg:CC CC_REGNUM))]
4448 "TARGET_32BIT"
61fa8ff2 4449 "#"
83e2b922 4450 "&& reload_completed"
4451 [(const_int 0)]
4452 {
61fa8ff2 4453 rtx low = gen_lowpart (SImode, operands[0]);
4454 rtx high = gen_highpart (SImode, operands[0]);
4455
4456 if (reg_overlap_mentioned_p (low, operands[1]))
4457 {
4458 /* Input overlaps the low word of the output. Use:
4459 asr Rhi, Rin, #31
4460 rsbs Rlo, Rin, #0
4461 rsc Rhi, Rhi, #0 (thumb2: sbc Rhi, Rhi, Rhi, lsl #1). */
4462 rtx cc_reg = gen_rtx_REG (CC_Cmode, CC_REGNUM);
4463
d1f9b275 4464 emit_insn (gen_rtx_SET (high,
61fa8ff2 4465 gen_rtx_ASHIFTRT (SImode, operands[1],
4466 GEN_INT (31))));
4467
4468 emit_insn (gen_subsi3_compare (low, const0_rtx, operands[1]));
4469 if (TARGET_ARM)
d1f9b275 4470 emit_insn (gen_rtx_SET (high,
61fa8ff2 4471 gen_rtx_MINUS (SImode,
4472 gen_rtx_MINUS (SImode,
4473 const0_rtx,
4474 high),
4475 gen_rtx_LTU (SImode,
4476 cc_reg,
4477 const0_rtx))));
4478 else
4479 {
4480 rtx two_x = gen_rtx_ASHIFT (SImode, high, GEN_INT (1));
d1f9b275 4481 emit_insn (gen_rtx_SET (high,
61fa8ff2 4482 gen_rtx_MINUS (SImode,
4483 gen_rtx_MINUS (SImode,
4484 high,
4485 two_x),
4486 gen_rtx_LTU (SImode,
4487 cc_reg,
4488 const0_rtx))));
4489 }
4490 }
4491 else
4492 {
4493 /* No overlap, or overlap on high word. Use:
4494 rsb Rlo, Rin, #0
4495 bic Rhi, Rlo, Rin
4496 asr Rhi, Rhi, #31
4497 Flags not needed for this sequence. */
d1f9b275 4498 emit_insn (gen_rtx_SET (low, gen_rtx_NEG (SImode, operands[1])));
4499 emit_insn (gen_rtx_SET (high,
61fa8ff2 4500 gen_rtx_AND (SImode,
4501 gen_rtx_NOT (SImode, operands[1]),
4502 low)));
d1f9b275 4503 emit_insn (gen_rtx_SET (high,
61fa8ff2 4504 gen_rtx_ASHIFTRT (SImode, high,
4505 GEN_INT (31))));
4506 }
4507 DONE;
83e2b922 4508 }
61fa8ff2 4509 [(set_attr "length" "12")
4510 (set_attr "arch" "t2,*")
1b7da4ac 4511 (set_attr "type" "multiple")]
83e2b922 4512)
4513
4514(define_insn_and_split "*negdi_zero_extendsidi"
4515 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
4516 (neg:DI (zero_extend:DI (match_operand:SI 1 "s_register_operand" "0,r"))))
4517 (clobber (reg:CC CC_REGNUM))]
4518 "TARGET_32BIT"
4519 "#" ; "rsbs\\t%Q0, %1, #0\;sbc\\t%R0,%R0,%R0"
4520 ;; Don't care what register is input to sbc,
47ae02b7 4521 ;; since we just need to propagate the carry.
83e2b922 4522 "&& reload_completed"
4523 [(parallel [(set (reg:CC CC_REGNUM)
4524 (compare:CC (const_int 0) (match_dup 1)))
4525 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 1)))])
4526 (set (match_dup 2) (minus:SI (minus:SI (match_dup 2) (match_dup 2))
4527 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
4528 {
4529 operands[2] = gen_highpart (SImode, operands[0]);
4530 operands[0] = gen_lowpart (SImode, operands[0]);
4531 }
4532 [(set_attr "conds" "clob")
1b7da4ac 4533 (set_attr "length" "8")
4534 (set_attr "type" "multiple")] ;; length in thumb is 4
83e2b922 4535)
4536
9c08d1fa 4537;; abssi2 doesn't really clobber the condition codes if a different register
4538;; is being set. To keep things simple, assume during rtl manipulations that
4539;; it does, but tell the final scan operator the truth. Similarly for
4540;; (neg (abs...))
4541
604f3a0a 4542(define_expand "abssi2"
4543 [(parallel
4544 [(set (match_operand:SI 0 "s_register_operand" "")
4545 (abs:SI (match_operand:SI 1 "s_register_operand" "")))
ba156559 4546 (clobber (match_dup 2))])]
4547 "TARGET_EITHER"
4548 "
25f905c2 4549 if (TARGET_THUMB1)
ba156559 4550 operands[2] = gen_rtx_SCRATCH (SImode);
4551 else
4552 operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
4553")
604f3a0a 4554
ba6a3b2f 4555(define_insn_and_split "*arm_abssi2"
ba156559 4556 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
9c08d1fa 4557 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
bd5b4116 4558 (clobber (reg:CC CC_REGNUM))]
cffb2a26 4559 "TARGET_ARM"
ba6a3b2f 4560 "#"
4561 "&& reload_completed"
4562 [(const_int 0)]
4563 {
4564 /* if (which_alternative == 0) */
4565 if (REGNO(operands[0]) == REGNO(operands[1]))
4566 {
4567 /* Emit the pattern:
4568 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
4569 [(set (reg:CC CC_REGNUM)
4570 (compare:CC (match_dup 0) (const_int 0)))
4571 (cond_exec (lt:CC (reg:CC CC_REGNUM) (const_int 0))
4572 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 1))))]
4573 */
d1f9b275 4574 emit_insn (gen_rtx_SET (gen_rtx_REG (CCmode, CC_REGNUM),
ba6a3b2f 4575 gen_rtx_COMPARE (CCmode, operands[0], const0_rtx)));
4576 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
4577 (gen_rtx_LT (SImode,
4578 gen_rtx_REG (CCmode, CC_REGNUM),
4579 const0_rtx)),
d1f9b275 4580 (gen_rtx_SET (operands[0],
ba6a3b2f 4581 (gen_rtx_MINUS (SImode,
4582 const0_rtx,
4583 operands[1]))))));
4584 DONE;
4585 }
4586 else
4587 {
4588 /* Emit the pattern:
4589 alt1: eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31
4590 [(set (match_dup 0)
4591 (xor:SI (match_dup 1)
4592 (ashiftrt:SI (match_dup 1) (const_int 31))))
4593 (set (match_dup 0)
4594 (minus:SI (match_dup 0)
4595 (ashiftrt:SI (match_dup 1) (const_int 31))))]
4596 */
d1f9b275 4597 emit_insn (gen_rtx_SET (operands[0],
ba6a3b2f 4598 gen_rtx_XOR (SImode,
4599 gen_rtx_ASHIFTRT (SImode,
4600 operands[1],
4601 GEN_INT (31)),
4602 operands[1])));
d1f9b275 4603 emit_insn (gen_rtx_SET (operands[0],
ba6a3b2f 4604 gen_rtx_MINUS (SImode,
4605 operands[0],
4606 gen_rtx_ASHIFTRT (SImode,
4607 operands[1],
4608 GEN_INT (31)))));
4609 DONE;
4610 }
4611 }
cffb2a26 4612 [(set_attr "conds" "clob,*")
331beb1a 4613 (set_attr "shift" "1")
2ad08b65 4614 (set_attr "predicable" "no, yes")
1b7da4ac 4615 (set_attr "length" "8")
4616 (set_attr "type" "multiple")]
cffb2a26 4617)
9c08d1fa 4618
ba6a3b2f 4619(define_insn_and_split "*arm_neg_abssi2"
9c08d1fa 4620 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
4621 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
bd5b4116 4622 (clobber (reg:CC CC_REGNUM))]
cffb2a26 4623 "TARGET_ARM"
ba6a3b2f 4624 "#"
4625 "&& reload_completed"
4626 [(const_int 0)]
4627 {
4628 /* if (which_alternative == 0) */
4629 if (REGNO (operands[0]) == REGNO (operands[1]))
4630 {
4631 /* Emit the pattern:
4632 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
4633 */
d1f9b275 4634 emit_insn (gen_rtx_SET (gen_rtx_REG (CCmode, CC_REGNUM),
ba6a3b2f 4635 gen_rtx_COMPARE (CCmode, operands[0], const0_rtx)));
4636 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
4637 gen_rtx_GT (SImode,
4638 gen_rtx_REG (CCmode, CC_REGNUM),
4639 const0_rtx),
d1f9b275 4640 gen_rtx_SET (operands[0],
ba6a3b2f 4641 (gen_rtx_MINUS (SImode,
4642 const0_rtx,
4643 operands[1])))));
4644 }
4645 else
4646 {
4647 /* Emit the pattern:
4648 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31
4649 */
d1f9b275 4650 emit_insn (gen_rtx_SET (operands[0],
ba6a3b2f 4651 gen_rtx_XOR (SImode,
4652 gen_rtx_ASHIFTRT (SImode,
4653 operands[1],
4654 GEN_INT (31)),
4655 operands[1])));
d1f9b275 4656 emit_insn (gen_rtx_SET (operands[0],
ba6a3b2f 4657 gen_rtx_MINUS (SImode,
4658 gen_rtx_ASHIFTRT (SImode,
4659 operands[1],
4660 GEN_INT (31)),
4661 operands[0])));
4662 }
4663 DONE;
4664 }
cffb2a26 4665 [(set_attr "conds" "clob,*")
331beb1a 4666 (set_attr "shift" "1")
2ad08b65 4667 (set_attr "predicable" "no, yes")
1b7da4ac 4668 (set_attr "length" "8")
4669 (set_attr "type" "multiple")]
cffb2a26 4670)
b11cae9e 4671
604f3a0a 4672(define_expand "abssf2"
4673 [(set (match_operand:SF 0 "s_register_operand" "")
4674 (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
25f905c2 4675 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 4676 "")
4677
604f3a0a 4678(define_expand "absdf2"
4679 [(set (match_operand:DF 0 "s_register_operand" "")
4680 (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 4681 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 4682 "")
4683
7db9af5d 4684(define_expand "sqrtsf2"
4685 [(set (match_operand:SF 0 "s_register_operand" "")
4686 (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
994606f8 4687 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
7db9af5d 4688 "")
9c08d1fa 4689
7db9af5d 4690(define_expand "sqrtdf2"
4691 [(set (match_operand:DF 0 "s_register_operand" "")
4692 (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
994606f8 4693 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
7db9af5d 4694 "")
9c08d1fa 4695
a0f94409 4696(define_insn_and_split "one_cmpldi2"
10efb95f 4697 [(set (match_operand:DI 0 "s_register_operand" "=w,&r,&r,?w")
4698 (not:DI (match_operand:DI 1 "s_register_operand" " w, 0, r, w")))]
25f905c2 4699 "TARGET_32BIT"
10efb95f 4700 "@
4701 vmvn\t%P0, %P1
4702 #
4703 #
4704 vmvn\t%P0, %P1"
4705 "TARGET_32BIT && reload_completed
4706 && arm_general_register_operand (operands[0], DImode)"
a0f94409 4707 [(set (match_dup 0) (not:SI (match_dup 1)))
4708 (set (match_dup 2) (not:SI (match_dup 3)))]
4709 "
4710 {
4711 operands[2] = gen_highpart (SImode, operands[0]);
4712 operands[0] = gen_lowpart (SImode, operands[0]);
4713 operands[3] = gen_highpart (SImode, operands[1]);
4714 operands[1] = gen_lowpart (SImode, operands[1]);
4715 }"
10efb95f 4716 [(set_attr "length" "*,8,8,*")
4717 (set_attr "predicable" "no,yes,yes,no")
32093010 4718 (set_attr "type" "neon_move,multiple,multiple,neon_move")
b6779ddc 4719 (set_attr "arch" "neon_for_64bits,*,*,avoid_neon_for_64bits")]
cffb2a26 4720)
b11cae9e 4721
cffb2a26 4722(define_expand "one_cmplsi2"
4723 [(set (match_operand:SI 0 "s_register_operand" "")
4724 (not:SI (match_operand:SI 1 "s_register_operand" "")))]
4725 "TARGET_EITHER"
b11cae9e 4726 ""
cffb2a26 4727)
4728
4729(define_insn "*arm_one_cmplsi2"
d952d547 4730 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4731 (not:SI (match_operand:SI 1 "s_register_operand" "l,r")))]
25f905c2 4732 "TARGET_32BIT"
cffb2a26 4733 "mvn%?\\t%0, %1"
d2a518d1 4734 [(set_attr "predicable" "yes")
d952d547 4735 (set_attr "predicable_short_it" "yes,no")
4736 (set_attr "arch" "t2,*")
4737 (set_attr "length" "4")
1aed5204 4738 (set_attr "type" "mvn_reg")]
cffb2a26 4739)
4740
f7fbdd4a 4741(define_insn "*notsi_compare0"
bd5b4116 4742 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 4743 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
4744 (const_int 0)))
4745 (set (match_operand:SI 0 "s_register_operand" "=r")
4746 (not:SI (match_dup 1)))]
25f905c2 4747 "TARGET_32BIT"
3ef90e77 4748 "mvns%?\\t%0, %1"
d2a518d1 4749 [(set_attr "conds" "set")
1aed5204 4750 (set_attr "type" "mvn_reg")]
cffb2a26 4751)
9c08d1fa 4752
f7fbdd4a 4753(define_insn "*notsi_compare0_scratch"
bd5b4116 4754 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 4755 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
4756 (const_int 0)))
4757 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 4758 "TARGET_32BIT"
3ef90e77 4759 "mvns%?\\t%0, %1"
d2a518d1 4760 [(set_attr "conds" "set")
1aed5204 4761 (set_attr "type" "mvn_reg")]
cffb2a26 4762)
b11cae9e 4763\f
4764;; Fixed <--> Floating conversion insns
4765
9b8516be 4766(define_expand "floatsihf2"
4767 [(set (match_operand:HF 0 "general_operand" "")
4768 (float:HF (match_operand:SI 1 "general_operand" "")))]
4769 "TARGET_EITHER"
4770 "
4771 {
4772 rtx op1 = gen_reg_rtx (SFmode);
4773 expand_float (op1, operands[1], 0);
4774 op1 = convert_to_mode (HFmode, op1, 0);
4775 emit_move_insn (operands[0], op1);
4776 DONE;
4777 }"
4778)
4779
4780(define_expand "floatdihf2"
4781 [(set (match_operand:HF 0 "general_operand" "")
4782 (float:HF (match_operand:DI 1 "general_operand" "")))]
4783 "TARGET_EITHER"
4784 "
4785 {
4786 rtx op1 = gen_reg_rtx (SFmode);
4787 expand_float (op1, operands[1], 0);
4788 op1 = convert_to_mode (HFmode, op1, 0);
4789 emit_move_insn (operands[0], op1);
4790 DONE;
4791 }"
4792)
4793
604f3a0a 4794(define_expand "floatsisf2"
4795 [(set (match_operand:SF 0 "s_register_operand" "")
4796 (float:SF (match_operand:SI 1 "s_register_operand" "")))]
25f905c2 4797 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 4798 "
604f3a0a 4799")
4800
604f3a0a 4801(define_expand "floatsidf2"
4802 [(set (match_operand:DF 0 "s_register_operand" "")
4803 (float:DF (match_operand:SI 1 "s_register_operand" "")))]
a50d7267 4804 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 4805 "
604f3a0a 4806")
4807
9b8516be 4808(define_expand "fix_trunchfsi2"
4809 [(set (match_operand:SI 0 "general_operand" "")
4810 (fix:SI (fix:HF (match_operand:HF 1 "general_operand" ""))))]
4811 "TARGET_EITHER"
4812 "
4813 {
4814 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
4815 expand_fix (operands[0], op1, 0);
4816 DONE;
4817 }"
4818)
4819
4820(define_expand "fix_trunchfdi2"
4821 [(set (match_operand:DI 0 "general_operand" "")
4822 (fix:DI (fix:HF (match_operand:HF 1 "general_operand" ""))))]
4823 "TARGET_EITHER"
4824 "
4825 {
4826 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
4827 expand_fix (operands[0], op1, 0);
4828 DONE;
4829 }"
4830)
4831
604f3a0a 4832(define_expand "fix_truncsfsi2"
4833 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 4834 (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" ""))))]
25f905c2 4835 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 4836 "
604f3a0a 4837")
4838
604f3a0a 4839(define_expand "fix_truncdfsi2"
4840 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 4841 (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" ""))))]
a50d7267 4842 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 4843 "
604f3a0a 4844")
4845
f544c6d2 4846;; Truncation insns
b11cae9e 4847
604f3a0a 4848(define_expand "truncdfsf2"
4849 [(set (match_operand:SF 0 "s_register_operand" "")
4850 (float_truncate:SF
4851 (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 4852 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 4853 ""
4854)
9b8516be 4855
4856/* DFmode -> HFmode conversions have to go through SFmode. */
4857(define_expand "truncdfhf2"
4858 [(set (match_operand:HF 0 "general_operand" "")
4859 (float_truncate:HF
4860 (match_operand:DF 1 "general_operand" "")))]
4861 "TARGET_EITHER"
4862 "
4863 {
4864 rtx op1;
4865 op1 = convert_to_mode (SFmode, operands[1], 0);
4866 op1 = convert_to_mode (HFmode, op1, 0);
4867 emit_move_insn (operands[0], op1);
4868 DONE;
4869 }"
4870)
b11cae9e 4871\f
9c08d1fa 4872;; Zero and sign extension instructions.
b11cae9e 4873
848e66ac 4874(define_insn "zero_extend<mode>di2"
6aa689e8 4875 [(set (match_operand:DI 0 "s_register_operand" "=w,r,?r,w")
6d97728e 4876 (zero_extend:DI (match_operand:QHSI 1 "<qhs_zextenddi_op>"
4877 "<qhs_zextenddi_cstr>")))]
848e66ac 4878 "TARGET_32BIT <qhs_zextenddi_cond>"
4879 "#"
6aa689e8 4880 [(set_attr "length" "8,4,8,8")
b6779ddc 4881 (set_attr "arch" "neon_for_64bits,*,*,avoid_neon_for_64bits")
848e66ac 4882 (set_attr "ce_count" "2")
efbb5e19 4883 (set_attr "predicable" "yes")
4884 (set_attr "type" "multiple,mov_reg,multiple,multiple")]
25f905c2 4885)
4886
848e66ac 4887(define_insn "extend<mode>di2"
6aa689e8 4888 [(set (match_operand:DI 0 "s_register_operand" "=w,r,?r,?r,w")
63d204a8 4889 (sign_extend:DI (match_operand:QHSI 1 "<qhs_extenddi_op>"
4890 "<qhs_extenddi_cstr>")))]
848e66ac 4891 "TARGET_32BIT <qhs_sextenddi_cond>"
4892 "#"
6aa689e8 4893 [(set_attr "length" "8,4,8,8,8")
848e66ac 4894 (set_attr "ce_count" "2")
4895 (set_attr "shift" "1")
8012d2c2 4896 (set_attr "predicable" "yes")
1b7da4ac 4897 (set_attr "arch" "neon_for_64bits,*,a,t,avoid_neon_for_64bits")
4898 (set_attr "type" "multiple,mov_reg,multiple,multiple,multiple")]
0d66636f 4899)
9c08d1fa 4900
848e66ac 4901;; Splits for all extensions to DImode
4902(define_split
4903 [(set (match_operand:DI 0 "s_register_operand" "")
4904 (zero_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
6aa689e8 4905 "TARGET_32BIT && reload_completed && !IS_VFP_REGNUM (REGNO (operands[0]))"
848e66ac 4906 [(set (match_dup 0) (match_dup 1))]
4907{
848e66ac 4908 rtx lo_part = gen_lowpart (SImode, operands[0]);
3754d046 4909 machine_mode src_mode = GET_MODE (operands[1]);
848e66ac 4910
4911 if (REG_P (operands[0])
4912 && !reg_overlap_mentioned_p (operands[0], operands[1]))
4913 emit_clobber (operands[0]);
4914 if (!REG_P (lo_part) || src_mode != SImode
4915 || !rtx_equal_p (lo_part, operands[1]))
4916 {
4917 if (src_mode == SImode)
4918 emit_move_insn (lo_part, operands[1]);
4919 else
d1f9b275 4920 emit_insn (gen_rtx_SET (lo_part,
848e66ac 4921 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
4922 operands[1] = lo_part;
4923 }
4924 operands[0] = gen_highpart (SImode, operands[0]);
4925 operands[1] = const0_rtx;
4926})
9c08d1fa 4927
848e66ac 4928(define_split
25f905c2 4929 [(set (match_operand:DI 0 "s_register_operand" "")
848e66ac 4930 (sign_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
6aa689e8 4931 "TARGET_32BIT && reload_completed && !IS_VFP_REGNUM (REGNO (operands[0]))"
848e66ac 4932 [(set (match_dup 0) (ashiftrt:SI (match_dup 1) (const_int 31)))]
4933{
4934 rtx lo_part = gen_lowpart (SImode, operands[0]);
3754d046 4935 machine_mode src_mode = GET_MODE (operands[1]);
25f905c2 4936
848e66ac 4937 if (REG_P (operands[0])
4938 && !reg_overlap_mentioned_p (operands[0], operands[1]))
4939 emit_clobber (operands[0]);
4940
4941 if (!REG_P (lo_part) || src_mode != SImode
4942 || !rtx_equal_p (lo_part, operands[1]))
4943 {
4944 if (src_mode == SImode)
4945 emit_move_insn (lo_part, operands[1]);
4946 else
d1f9b275 4947 emit_insn (gen_rtx_SET (lo_part,
848e66ac 4948 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
4949 operands[1] = lo_part;
4950 }
4951 operands[0] = gen_highpart (SImode, operands[0]);
4952})
9c08d1fa 4953
4954(define_expand "zero_extendhisi2"
ef51b8e1 4955 [(set (match_operand:SI 0 "s_register_operand" "")
4956 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
cffb2a26 4957 "TARGET_EITHER"
ef51b8e1 4958{
4959 if (TARGET_ARM && !arm_arch4 && MEM_P (operands[1]))
f7fbdd4a 4960 {
ef51b8e1 4961 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
4962 DONE;
25f7a26e 4963 }
ef51b8e1 4964 if (!arm_arch6 && !MEM_P (operands[1]))
4965 {
4966 rtx t = gen_lowpart (SImode, operands[1]);
4967 rtx tmp = gen_reg_rtx (SImode);
4968 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
4969 emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (16)));
4970 DONE;
4971 }
4972})
9c08d1fa 4973
ef51b8e1 4974(define_split
b146458f 4975 [(set (match_operand:SI 0 "s_register_operand" "")
4976 (zero_extend:SI (match_operand:HI 1 "s_register_operand" "")))]
ef51b8e1 4977 "!TARGET_THUMB2 && !arm_arch6"
4978 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4979 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 16)))]
4980{
4981 operands[2] = gen_lowpart (SImode, operands[1]);
4982})
4983
cffb2a26 4984(define_insn "*arm_zero_extendhisi2"
ef51b8e1 4985 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4986 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 4987 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 4988 "@
4989 #
3ef90e77 4990 ldrh%?\\t%0, %1"
d82e788e 4991 [(set_attr "type" "alu_shift_reg,load_byte")
848e66ac 4992 (set_attr "predicable" "yes")]
cffb2a26 4993)
f7fbdd4a 4994
a2cd141b 4995(define_insn "*arm_zero_extendhisi2_v6"
4996 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
e3f4ccee 4997 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,Uh")))]
a2cd141b 4998 "TARGET_ARM && arm_arch6"
4999 "@
5000 uxth%?\\t%0, %1
3ef90e77 5001 ldrh%?\\t%0, %1"
65f68e55 5002 [(set_attr "predicable" "yes")
6b6abc9c 5003 (set_attr "type" "extend,load_byte")]
a2cd141b 5004)
5005
5006(define_insn "*arm_zero_extendhisi2addsi"
5007 [(set (match_operand:SI 0 "s_register_operand" "=r")
5008 (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
5009 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 5010 "TARGET_INT_SIMD"
a2cd141b 5011 "uxtah%?\\t%0, %2, %1"
d82e788e 5012 [(set_attr "type" "alu_shift_reg")
d952d547 5013 (set_attr "predicable" "yes")
5014 (set_attr "predicable_short_it" "no")]
a2cd141b 5015)
5016
87b22bf7 5017(define_expand "zero_extendqisi2"
cffb2a26 5018 [(set (match_operand:SI 0 "s_register_operand" "")
5019 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
5020 "TARGET_EITHER"
ef51b8e1 5021{
0438d37f 5022 if (TARGET_ARM && !arm_arch6 && !MEM_P (operands[1]))
87b22bf7 5023 {
ef51b8e1 5024 emit_insn (gen_andsi3 (operands[0],
5025 gen_lowpart (SImode, operands[1]),
5026 GEN_INT (255)));
5027 DONE;
5028 }
5029 if (!arm_arch6 && !MEM_P (operands[1]))
5030 {
5031 rtx t = gen_lowpart (SImode, operands[1]);
5032 rtx tmp = gen_reg_rtx (SImode);
5033 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
5034 emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (24)));
5035 DONE;
5036 }
5037})
cffb2a26 5038
ef51b8e1 5039(define_split
b146458f 5040 [(set (match_operand:SI 0 "s_register_operand" "")
5041 (zero_extend:SI (match_operand:QI 1 "s_register_operand" "")))]
ef51b8e1 5042 "!arm_arch6"
5043 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
5044 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 24)))]
5045{
5046 operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
5047 if (TARGET_ARM)
5048 {
5049 emit_insn (gen_andsi3 (operands[0], operands[2], GEN_INT (255)));
87b22bf7 5050 DONE;
5051 }
ef51b8e1 5052})
9c08d1fa 5053
cffb2a26 5054(define_insn "*arm_zero_extendqisi2"
ef51b8e1 5055 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5056 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 5057 "TARGET_ARM && !arm_arch6"
ef51b8e1 5058 "@
5059 #
3ef90e77 5060 ldrb%?\\t%0, %1\\t%@ zero_extendqisi2"
ef51b8e1 5061 [(set_attr "length" "8,4")
d82e788e 5062 (set_attr "type" "alu_shift_reg,load_byte")
848e66ac 5063 (set_attr "predicable" "yes")]
cffb2a26 5064)
87b22bf7 5065
a2cd141b 5066(define_insn "*arm_zero_extendqisi2_v6"
5067 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
e3f4ccee 5068 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,Uh")))]
a2cd141b 5069 "TARGET_ARM && arm_arch6"
5070 "@
3ef90e77 5071 uxtb%?\\t%0, %1
5072 ldrb%?\\t%0, %1\\t%@ zero_extendqisi2"
6b6abc9c 5073 [(set_attr "type" "extend,load_byte")
848e66ac 5074 (set_attr "predicable" "yes")]
a2cd141b 5075)
5076
5077(define_insn "*arm_zero_extendqisi2addsi"
5078 [(set (match_operand:SI 0 "s_register_operand" "=r")
5079 (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
5080 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 5081 "TARGET_INT_SIMD"
a2cd141b 5082 "uxtab%?\\t%0, %2, %1"
5083 [(set_attr "predicable" "yes")
d952d547 5084 (set_attr "predicable_short_it" "no")
d82e788e 5085 (set_attr "type" "alu_shift_reg")]
a2cd141b 5086)
5087
87b22bf7 5088(define_split
5089 [(set (match_operand:SI 0 "s_register_operand" "")
5090 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
5091 (clobber (match_operand:SI 2 "s_register_operand" ""))]
0438d37f 5092 "TARGET_32BIT && (!MEM_P (operands[1])) && ! BYTES_BIG_ENDIAN"
87b22bf7 5093 [(set (match_dup 2) (match_dup 1))
5094 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
cffb2a26 5095 ""
5096)
9c08d1fa 5097
8a4d25d6 5098(define_split
5099 [(set (match_operand:SI 0 "s_register_operand" "")
5100 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 3)))
5101 (clobber (match_operand:SI 2 "s_register_operand" ""))]
0438d37f 5102 "TARGET_32BIT && (!MEM_P (operands[1])) && BYTES_BIG_ENDIAN"
8a4d25d6 5103 [(set (match_dup 2) (match_dup 1))
5104 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
5105 ""
5106)
5107
1c274529 5108
5109(define_split
5110 [(set (match_operand:SI 0 "s_register_operand" "")
9b23f0a7 5111 (IOR_XOR:SI (and:SI (ashift:SI
1c274529 5112 (match_operand:SI 1 "s_register_operand" "")
5113 (match_operand:SI 2 "const_int_operand" ""))
5114 (match_operand:SI 3 "const_int_operand" ""))
5115 (zero_extend:SI
5116 (match_operator 5 "subreg_lowpart_operator"
5117 [(match_operand:SI 4 "s_register_operand" "")]))))]
5118 "TARGET_32BIT
63787642 5119 && ((unsigned HOST_WIDE_INT) INTVAL (operands[3])
1c274529 5120 == (GET_MODE_MASK (GET_MODE (operands[5]))
5121 & (GET_MODE_MASK (GET_MODE (operands[5]))
5122 << (INTVAL (operands[2])))))"
9b23f0a7 5123 [(set (match_dup 0) (IOR_XOR:SI (ashift:SI (match_dup 1) (match_dup 2))
1c274529 5124 (match_dup 4)))
5125 (set (match_dup 0) (zero_extend:SI (match_dup 5)))]
5126 "operands[5] = gen_lowpart (GET_MODE (operands[5]), operands[0]);"
5127)
5128
f7fbdd4a 5129(define_insn "*compareqi_eq0"
bd5b4116 5130 [(set (reg:CC_Z CC_REGNUM)
206ee9a2 5131 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
87b22bf7 5132 (const_int 0)))]
25f905c2 5133 "TARGET_32BIT"
596e5e8f 5134 "tst%?\\t%0, #255"
5135 [(set_attr "conds" "set")
d952d547 5136 (set_attr "predicable" "yes")
1b7da4ac 5137 (set_attr "predicable_short_it" "no")
5138 (set_attr "type" "logic_imm")]
cffb2a26 5139)
b11cae9e 5140
b11cae9e 5141(define_expand "extendhisi2"
ef51b8e1 5142 [(set (match_operand:SI 0 "s_register_operand" "")
5143 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
cffb2a26 5144 "TARGET_EITHER"
ef51b8e1 5145{
5146 if (TARGET_THUMB1)
5147 {
5148 emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1]));
5149 DONE;
5150 }
5151 if (MEM_P (operands[1]) && TARGET_ARM && !arm_arch4)
5152 {
5153 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
5154 DONE;
5155 }
ed29c566 5156
ef51b8e1 5157 if (!arm_arch6 && !MEM_P (operands[1]))
5158 {
5159 rtx t = gen_lowpart (SImode, operands[1]);
5160 rtx tmp = gen_reg_rtx (SImode);
5161 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
5162 emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (16)));
5163 DONE;
5164 }
5165})
cffb2a26 5166
ef51b8e1 5167(define_split
5168 [(parallel
5169 [(set (match_operand:SI 0 "register_operand" "")
5170 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))
5171 (clobber (match_scratch:SI 2 ""))])]
5172 "!arm_arch6"
5173 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
5174 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
5175{
5176 operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
5177})
25f7a26e 5178
25f905c2 5179;; This pattern will only be used when ldsh is not available
25f7a26e 5180(define_expand "extendhisi2_mem"
eab14235 5181 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 5182 (set (match_dup 3)
eab14235 5183 (zero_extend:SI (match_dup 7)))
25f7a26e 5184 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
5185 (set (match_operand:SI 0 "" "")
5186 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
cffb2a26 5187 "TARGET_ARM"
25f7a26e 5188 "
215b30b3 5189 {
5190 rtx mem1, mem2;
5191 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
5192
788fcce0 5193 mem1 = change_address (operands[1], QImode, addr);
29c05e22 5194 mem2 = change_address (operands[1], QImode,
5195 plus_constant (Pmode, addr, 1));
215b30b3 5196 operands[0] = gen_lowpart (SImode, operands[0]);
5197 operands[1] = mem1;
5198 operands[2] = gen_reg_rtx (SImode);
5199 operands[3] = gen_reg_rtx (SImode);
5200 operands[6] = gen_reg_rtx (SImode);
5201 operands[7] = mem2;
25f7a26e 5202
215b30b3 5203 if (BYTES_BIG_ENDIAN)
5204 {
5205 operands[4] = operands[2];
5206 operands[5] = operands[3];
5207 }
5208 else
5209 {
5210 operands[4] = operands[3];
5211 operands[5] = operands[2];
5212 }
5213 }"
5214)
b11cae9e 5215
ef51b8e1 5216(define_split
5217 [(set (match_operand:SI 0 "register_operand" "")
5218 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
5219 "!arm_arch6"
5220 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
5221 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
5222{
5223 operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
5224})
5225
a2cd141b 5226(define_insn "*arm_extendhisi2"
ef51b8e1 5227 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
e3f4ccee 5228 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,Uh")))]
a2cd141b 5229 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 5230 "@
5231 #
3ef90e77 5232 ldrsh%?\\t%0, %1"
ef51b8e1 5233 [(set_attr "length" "8,4")
d82e788e 5234 (set_attr "type" "alu_shift_reg,load_byte")
e3f4ccee 5235 (set_attr "predicable" "yes")]
cffb2a26 5236)
f7fbdd4a 5237
25f905c2 5238;; ??? Check Thumb-2 pool range
a2cd141b 5239(define_insn "*arm_extendhisi2_v6"
5240 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
e3f4ccee 5241 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,Uh")))]
25f905c2 5242 "TARGET_32BIT && arm_arch6"
a2cd141b 5243 "@
5244 sxth%?\\t%0, %1
3ef90e77 5245 ldrsh%?\\t%0, %1"
6b6abc9c 5246 [(set_attr "type" "extend,load_byte")
a2cd141b 5247 (set_attr "predicable" "yes")
e3f4ccee 5248 (set_attr "predicable_short_it" "no")]
a2cd141b 5249)
5250
5251(define_insn "*arm_extendhisi2addsi"
5252 [(set (match_operand:SI 0 "s_register_operand" "=r")
5253 (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
5254 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 5255 "TARGET_INT_SIMD"
a2cd141b 5256 "sxtah%?\\t%0, %2, %1"
1b7da4ac 5257 [(set_attr "type" "alu_shift_reg")]
a2cd141b 5258)
5259
c8f69309 5260(define_expand "extendqihi2"
5261 [(set (match_dup 2)
bed7d9a5 5262 (ashift:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")
c8f69309 5263 (const_int 24)))
9c08d1fa 5264 (set (match_operand:HI 0 "s_register_operand" "")
c8f69309 5265 (ashiftrt:SI (match_dup 2)
5266 (const_int 24)))]
cffb2a26 5267 "TARGET_ARM"
c8f69309 5268 "
215b30b3 5269 {
0438d37f 5270 if (arm_arch4 && MEM_P (operands[1]))
215b30b3 5271 {
d1f9b275 5272 emit_insn (gen_rtx_SET (operands[0],
215b30b3 5273 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
5274 DONE;
5275 }
5276 if (!s_register_operand (operands[1], QImode))
5277 operands[1] = copy_to_mode_reg (QImode, operands[1]);
5278 operands[0] = gen_lowpart (SImode, operands[0]);
5279 operands[1] = gen_lowpart (SImode, operands[1]);
5280 operands[2] = gen_reg_rtx (SImode);
5281 }"
5282)
f7fbdd4a 5283
25f905c2 5284(define_insn "*arm_extendqihi_insn"
b4e8a300 5285 [(set (match_operand:HI 0 "s_register_operand" "=r")
bed7d9a5 5286 (sign_extend:HI (match_operand:QI 1 "arm_extendqisi_mem_op" "Uq")))]
cffb2a26 5287 "TARGET_ARM && arm_arch4"
3ef90e77 5288 "ldrsb%?\\t%0, %1"
a2cd141b 5289 [(set_attr "type" "load_byte")
e3f4ccee 5290 (set_attr "predicable" "yes")]
cffb2a26 5291)
3fc2009e 5292
b11cae9e 5293(define_expand "extendqisi2"
ef51b8e1 5294 [(set (match_operand:SI 0 "s_register_operand" "")
5295 (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")))]
cffb2a26 5296 "TARGET_EITHER"
ef51b8e1 5297{
5298 if (!arm_arch4 && MEM_P (operands[1]))
5299 operands[1] = copy_to_mode_reg (QImode, operands[1]);
a2cd141b 5300
ef51b8e1 5301 if (!arm_arch6 && !MEM_P (operands[1]))
5302 {
5303 rtx t = gen_lowpart (SImode, operands[1]);
5304 rtx tmp = gen_reg_rtx (SImode);
5305 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
5306 emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (24)));
5307 DONE;
5308 }
5309})
a2cd141b 5310
ef51b8e1 5311(define_split
5312 [(set (match_operand:SI 0 "register_operand" "")
5313 (sign_extend:SI (match_operand:QI 1 "register_operand" "")))]
5314 "!arm_arch6"
5315 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
5316 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))]
5317{
5318 operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
5319})
f7fbdd4a 5320
a2cd141b 5321(define_insn "*arm_extendqisi"
ef51b8e1 5322 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5323 (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
a2cd141b 5324 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 5325 "@
5326 #
3ef90e77 5327 ldrsb%?\\t%0, %1"
ef51b8e1 5328 [(set_attr "length" "8,4")
d82e788e 5329 (set_attr "type" "alu_shift_reg,load_byte")
e3f4ccee 5330 (set_attr "predicable" "yes")]
cffb2a26 5331)
3fc2009e 5332
a2cd141b 5333(define_insn "*arm_extendqisi_v6"
5334 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
bed7d9a5 5335 (sign_extend:SI
5336 (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
a2cd141b 5337 "TARGET_ARM && arm_arch6"
b4e8a300 5338 "@
5339 sxtb%?\\t%0, %1
3ef90e77 5340 ldrsb%?\\t%0, %1"
6b6abc9c 5341 [(set_attr "type" "extend,load_byte")
e3f4ccee 5342 (set_attr "predicable" "yes")]
a2cd141b 5343)
5344
5345(define_insn "*arm_extendqisi2addsi"
5346 [(set (match_operand:SI 0 "s_register_operand" "=r")
5347 (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
5348 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 5349 "TARGET_INT_SIMD"
a2cd141b 5350 "sxtab%?\\t%0, %2, %1"
d82e788e 5351 [(set_attr "type" "alu_shift_reg")
d952d547 5352 (set_attr "predicable" "yes")
5353 (set_attr "predicable_short_it" "no")]
a2cd141b 5354)
5355
caedf871 5356(define_expand "extendsfdf2"
5357 [(set (match_operand:DF 0 "s_register_operand" "")
5358 (float_extend:DF (match_operand:SF 1 "s_register_operand" "")))]
a50d7267 5359 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
caedf871 5360 ""
5361)
9b8516be 5362
5363/* HFmode -> DFmode conversions have to go through SFmode. */
5364(define_expand "extendhfdf2"
5365 [(set (match_operand:DF 0 "general_operand" "")
5366 (float_extend:DF (match_operand:HF 1 "general_operand" "")))]
5367 "TARGET_EITHER"
5368 "
5369 {
5370 rtx op1;
5371 op1 = convert_to_mode (SFmode, operands[1], 0);
5372 op1 = convert_to_mode (DFmode, op1, 0);
5373 emit_insn (gen_movdf (operands[0], op1));
5374 DONE;
5375 }"
5376)
b11cae9e 5377\f
5378;; Move insns (including loads and stores)
5379
5380;; XXX Just some ideas about movti.
9c08d1fa 5381;; I don't think these are a good idea on the arm, there just aren't enough
5382;; registers
b11cae9e 5383;;(define_expand "loadti"
9c08d1fa 5384;; [(set (match_operand:TI 0 "s_register_operand" "")
b11cae9e 5385;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
5386;; "" "")
5387
5388;;(define_expand "storeti"
5389;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
9c08d1fa 5390;; (match_operand:TI 1 "s_register_operand" ""))]
b11cae9e 5391;; "" "")
5392
5393;;(define_expand "movti"
5394;; [(set (match_operand:TI 0 "general_operand" "")
5395;; (match_operand:TI 1 "general_operand" ""))]
5396;; ""
5397;; "
5398;;{
5399;; rtx insn;
5400;;
0438d37f 5401;; if (MEM_P (operands[0]) && MEM_P (operands[1]))
b11cae9e 5402;; operands[1] = copy_to_reg (operands[1]);
0438d37f 5403;; if (MEM_P (operands[0]))
b11cae9e 5404;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
0438d37f 5405;; else if (MEM_P (operands[1]))
b11cae9e 5406;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
5407;; else
5408;; FAIL;
5409;;
5410;; emit_insn (insn);
5411;; DONE;
5412;;}")
5413
a2f10574 5414;; Recognize garbage generated above.
b11cae9e 5415
5416;;(define_insn ""
5417;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
5418;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
5419;; ""
5420;; "*
5421;; {
5422;; register mem = (which_alternative < 3);
0d66636f 5423;; register const char *template;
b11cae9e 5424;;
5425;; operands[mem] = XEXP (operands[mem], 0);
5426;; switch (which_alternative)
5427;; {
5428;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
5429;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
5430;; case 2: template = \"ldmia\\t%1, %M0\"; break;
5431;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
5432;; case 4: template = \"stmia\\t%0!, %M1\"; break;
5433;; case 5: template = \"stmia\\t%0, %M1\"; break;
5434;; }
e2348bcb 5435;; output_asm_insn (template, operands);
5436;; return \"\";
b11cae9e 5437;; }")
5438
cffb2a26 5439(define_expand "movdi"
5440 [(set (match_operand:DI 0 "general_operand" "")
5441 (match_operand:DI 1 "general_operand" ""))]
5442 "TARGET_EITHER"
5443 "
e1ba4a27 5444 if (can_create_pseudo_p ())
cffb2a26 5445 {
0438d37f 5446 if (!REG_P (operands[0]))
b2778788 5447 operands[1] = force_reg (DImode, operands[1]);
cffb2a26 5448 }
6b97fdcc 5449 if (REG_P (operands[0]) && REGNO (operands[0]) <= LAST_ARM_REGNUM
4f0e25ca 5450 && !HARD_REGNO_MODE_OK (REGNO (operands[0]), DImode))
5451 {
5452 /* Avoid LDRD's into an odd-numbered register pair in ARM state
5453 when expanding function calls. */
5454 gcc_assert (can_create_pseudo_p ());
5455 if (MEM_P (operands[1]) && MEM_VOLATILE_P (operands[1]))
5456 {
5457 /* Perform load into legal reg pair first, then move. */
5458 rtx reg = gen_reg_rtx (DImode);
5459 emit_insn (gen_movdi (reg, operands[1]));
5460 operands[1] = reg;
5461 }
5462 emit_move_insn (gen_lowpart (SImode, operands[0]),
5463 gen_lowpart (SImode, operands[1]));
5464 emit_move_insn (gen_highpart (SImode, operands[0]),
5465 gen_highpart (SImode, operands[1]));
5466 DONE;
5467 }
6b97fdcc 5468 else if (REG_P (operands[1]) && REGNO (operands[1]) <= LAST_ARM_REGNUM
4f0e25ca 5469 && !HARD_REGNO_MODE_OK (REGNO (operands[1]), DImode))
5470 {
5471 /* Avoid STRD's from an odd-numbered register pair in ARM state
5472 when expanding function prologue. */
5473 gcc_assert (can_create_pseudo_p ());
5474 rtx split_dest = (MEM_P (operands[0]) && MEM_VOLATILE_P (operands[0]))
5475 ? gen_reg_rtx (DImode)
5476 : operands[0];
5477 emit_move_insn (gen_lowpart (SImode, split_dest),
5478 gen_lowpart (SImode, operands[1]));
5479 emit_move_insn (gen_highpart (SImode, split_dest),
5480 gen_highpart (SImode, operands[1]));
5481 if (split_dest != operands[0])
5482 emit_insn (gen_movdi (operands[0], split_dest));
5483 DONE;
5484 }
cffb2a26 5485 "
5486)
b11cae9e 5487
cffb2a26 5488(define_insn "*arm_movdi"
353cf59a 5489 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, q, m")
5490 (match_operand:DI 1 "di_operand" "rDa,Db,Dc,mi,q"))]
cde1623a 5491 "TARGET_32BIT
b805622c 5492 && !(TARGET_HARD_FLOAT && TARGET_VFP)
b2778788 5493 && !TARGET_IWMMXT
5494 && ( register_operand (operands[0], DImode)
5495 || register_operand (operands[1], DImode))"
b11cae9e 5496 "*
d51f92df 5497 switch (which_alternative)
5498 {
5499 case 0:
5500 case 1:
5501 case 2:
5502 return \"#\";
5503 default:
26ff80c0 5504 return output_move_double (operands, true, NULL);
d51f92df 5505 }
cffb2a26 5506 "
359a6e9f 5507 [(set_attr "length" "8,12,16,8,8")
1b7da4ac 5508 (set_attr "type" "multiple,multiple,multiple,load2,store2")
cde1623a 5509 (set_attr "arm_pool_range" "*,*,*,1020,*")
8848d797 5510 (set_attr "arm_neg_pool_range" "*,*,*,1004,*")
42e1de19 5511 (set_attr "thumb2_pool_range" "*,*,*,4094,*")
cde1623a 5512 (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
cffb2a26 5513)
5514
d51f92df 5515(define_split
5516 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
e6dd3afa 5517 (match_operand:ANY64 1 "immediate_operand" ""))]
25f905c2 5518 "TARGET_32BIT
d51f92df 5519 && reload_completed
5520 && (arm_const_double_inline_cost (operands[1])
861033d5 5521 <= arm_max_const_double_inline_cost ())"
d51f92df 5522 [(const_int 0)]
5523 "
5524 arm_split_constant (SET, SImode, curr_insn,
5525 INTVAL (gen_lowpart (SImode, operands[1])),
5526 gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
5527 arm_split_constant (SET, SImode, curr_insn,
5528 INTVAL (gen_highpart_mode (SImode,
5529 GET_MODE (operands[0]),
5530 operands[1])),
5531 gen_highpart (SImode, operands[0]), NULL_RTX, 0);
5532 DONE;
5533 "
5534)
5535
e5ba9289 5536; If optimizing for size, or if we have load delay slots, then
5537; we want to split the constant into two separate operations.
5538; In both cases this may split a trivial part into a single data op
5539; leaving a single complex constant to load. We can also get longer
5540; offsets in a LDR which means we get better chances of sharing the pool
5541; entries. Finally, we can normally do a better job of scheduling
5542; LDR instructions than we can with LDM.
5543; This pattern will only match if the one above did not.
5544(define_split
5545 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
5546 (match_operand:ANY64 1 "const_double_operand" ""))]
5547 "TARGET_ARM && reload_completed
5548 && arm_const_double_by_parts (operands[1])"
5549 [(set (match_dup 0) (match_dup 1))
5550 (set (match_dup 2) (match_dup 3))]
5551 "
5552 operands[2] = gen_highpart (SImode, operands[0]);
5553 operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
5554 operands[1]);
5555 operands[0] = gen_lowpart (SImode, operands[0]);
5556 operands[1] = gen_lowpart (SImode, operands[1]);
5557 "
5558)
5559
d51f92df 5560(define_split
5561 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
5562 (match_operand:ANY64 1 "arm_general_register_operand" ""))]
5563 "TARGET_EITHER && reload_completed"
5564 [(set (match_dup 0) (match_dup 1))
5565 (set (match_dup 2) (match_dup 3))]
5566 "
5567 operands[2] = gen_highpart (SImode, operands[0]);
5568 operands[3] = gen_highpart (SImode, operands[1]);
5569 operands[0] = gen_lowpart (SImode, operands[0]);
5570 operands[1] = gen_lowpart (SImode, operands[1]);
5571
5572 /* Handle a partial overlap. */
5573 if (rtx_equal_p (operands[0], operands[3]))
5574 {
5575 rtx tmp0 = operands[0];
5576 rtx tmp1 = operands[1];
5577
5578 operands[0] = operands[2];
5579 operands[1] = operands[3];
5580 operands[2] = tmp0;
5581 operands[3] = tmp1;
5582 }
5583 "
5584)
5585
a8a3b539 5586;; We can't actually do base+index doubleword loads if the index and
5587;; destination overlap. Split here so that we at least have chance to
5588;; schedule.
5589(define_split
5590 [(set (match_operand:DI 0 "s_register_operand" "")
5591 (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
5592 (match_operand:SI 2 "s_register_operand" ""))))]
5593 "TARGET_LDRD
5594 && reg_overlap_mentioned_p (operands[0], operands[1])
5595 && reg_overlap_mentioned_p (operands[0], operands[2])"
5596 [(set (match_dup 4)
5597 (plus:SI (match_dup 1)
5598 (match_dup 2)))
5599 (set (match_dup 0)
5600 (mem:DI (match_dup 4)))]
5601 "
5602 operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
5603 "
5604)
5605
9c08d1fa 5606(define_expand "movsi"
5607 [(set (match_operand:SI 0 "general_operand" "")
5608 (match_operand:SI 1 "general_operand" ""))]
cffb2a26 5609 "TARGET_EITHER"
9c08d1fa 5610 "
befb0bac 5611 {
e348ff3e 5612 rtx base, offset, tmp;
5613
25f905c2 5614 if (TARGET_32BIT)
9c08d1fa 5615 {
674a8f0b 5616 /* Everything except mem = const or mem = mem can be done easily. */
0438d37f 5617 if (MEM_P (operands[0]))
cffb2a26 5618 operands[1] = force_reg (SImode, operands[1]);
a2cd141b 5619 if (arm_general_register_operand (operands[0], SImode)
0438d37f 5620 && CONST_INT_P (operands[1])
cffb2a26 5621 && !(const_ok_for_arm (INTVAL (operands[1]))
5622 || const_ok_for_arm (~INTVAL (operands[1]))))
5623 {
17202aa5 5624 if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[1]), SET))
5625 {
5626 emit_insn (gen_rtx_SET (operands[0], operands[1]));
5627 DONE;
5628 }
5629 else
5630 {
5631 arm_split_constant (SET, SImode, NULL_RTX,
5632 INTVAL (operands[1]), operands[0], NULL_RTX,
5633 optimize && can_create_pseudo_p ());
5634 DONE;
5635 }
cffb2a26 5636 }
5637 }
25f905c2 5638 else /* TARGET_THUMB1... */
cffb2a26 5639 {
e1ba4a27 5640 if (can_create_pseudo_p ())
cffb2a26 5641 {
0438d37f 5642 if (!REG_P (operands[0]))
cffb2a26 5643 operands[1] = force_reg (SImode, operands[1]);
5644 }
9c08d1fa 5645 }
f655717d 5646
e348ff3e 5647 if (ARM_OFFSETS_MUST_BE_WITHIN_SECTIONS_P)
5648 {
5649 split_const (operands[1], &base, &offset);
5650 if (GET_CODE (base) == SYMBOL_REF
5651 && !offset_within_block_p (base, INTVAL (offset)))
5652 {
b308ddcf 5653 tmp = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
e348ff3e 5654 emit_move_insn (tmp, base);
5655 emit_insn (gen_addsi3 (operands[0], tmp, offset));
5656 DONE;
5657 }
5658 }
5659
f655717d 5660 /* Recognize the case where operand[1] is a reference to thread-local
5661 data and load its address to a register. */
5662 if (arm_tls_referenced_p (operands[1]))
5663 {
5664 rtx tmp = operands[1];
5665 rtx addend = NULL;
5666
5667 if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
5668 {
5669 addend = XEXP (XEXP (tmp, 0), 1);
5670 tmp = XEXP (XEXP (tmp, 0), 0);
5671 }
5672
5673 gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
5674 gcc_assert (SYMBOL_REF_TLS_MODEL (tmp) != 0);
5675
e1ba4a27 5676 tmp = legitimize_tls_address (tmp,
5677 !can_create_pseudo_p () ? operands[0] : 0);
f655717d 5678 if (addend)
5679 {
5680 tmp = gen_rtx_PLUS (SImode, tmp, addend);
5681 tmp = force_operand (tmp, operands[0]);
5682 }
5683 operands[1] = tmp;
5684 }
5685 else if (flag_pic
5686 && (CONSTANT_P (operands[1])
5687 || symbol_mentioned_p (operands[1])
5688 || label_mentioned_p (operands[1])))
5689 operands[1] = legitimize_pic_address (operands[1], SImode,
e1ba4a27 5690 (!can_create_pseudo_p ()
5691 ? operands[0]
5692 : 0));
befb0bac 5693 }
215b30b3 5694 "
5695)
9c08d1fa 5696
d0e6a121 5697;; The ARM LO_SUM and HIGH are backwards - HIGH sets the low bits, and
5698;; LO_SUM adds in the high bits. Fortunately these are opaque operations
5699;; so this does not matter.
5700(define_insn "*arm_movt"
5701 [(set (match_operand:SI 0 "nonimmediate_operand" "=r")
5702 (lo_sum:SI (match_operand:SI 1 "nonimmediate_operand" "0")
5703 (match_operand:SI 2 "general_operand" "i")))]
ac528743 5704 "arm_arch_thumb2 && arm_valid_symbolic_address_p (operands[2])"
d0e6a121 5705 "movt%?\t%0, #:upper16:%c2"
5706 [(set_attr "predicable" "yes")
d952d547 5707 (set_attr "predicable_short_it" "no")
1b7da4ac 5708 (set_attr "length" "4")
282b4c75 5709 (set_attr "type" "alu_sreg")]
d0e6a121 5710)
5711
cffb2a26 5712(define_insn "*arm_movsi_insn"
aaa37ad6 5713 [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,rk,m")
110eae03 5714 (match_operand:SI 1 "general_operand" "rk, I,K,j,mi,rk"))]
755eb2b4 5715 "TARGET_ARM && ! TARGET_IWMMXT
a2cd141b 5716 && !(TARGET_HARD_FLOAT && TARGET_VFP)
cffb2a26 5717 && ( register_operand (operands[0], SImode)
5718 || register_operand (operands[1], SImode))"
f7fbdd4a 5719 "@
aaa37ad6 5720 mov%?\\t%0, %1
f7fbdd4a 5721 mov%?\\t%0, %1
5722 mvn%?\\t%0, #%B1
25f905c2 5723 movw%?\\t%0, %1
f7fbdd4a 5724 ldr%?\\t%0, %1
5725 str%?\\t%1, %0"
1aed5204 5726 [(set_attr "type" "mov_reg,mov_imm,mvn_imm,mov_imm,load1,store1")
0d66636f 5727 (set_attr "predicable" "yes")
aaa37ad6 5728 (set_attr "pool_range" "*,*,*,*,4096,*")
5729 (set_attr "neg_pool_range" "*,*,*,*,4084,*")]
cffb2a26 5730)
87b22bf7 5731
5732(define_split
a2cd141b 5733 [(set (match_operand:SI 0 "arm_general_register_operand" "")
87b22bf7 5734 (match_operand:SI 1 "const_int_operand" ""))]
25f905c2 5735 "TARGET_32BIT
215b30b3 5736 && (!(const_ok_for_arm (INTVAL (operands[1]))
5737 || const_ok_for_arm (~INTVAL (operands[1]))))"
87b22bf7 5738 [(clobber (const_int 0))]
5739 "
96f57e36 5740 arm_split_constant (SET, SImode, NULL_RTX,
5741 INTVAL (operands[1]), operands[0], NULL_RTX, 0);
87b22bf7 5742 DONE;
215b30b3 5743 "
5744)
9c08d1fa 5745
861033d5 5746;; A normal way to do (symbol + offset) requires three instructions at least
5747;; (depends on how big the offset is) as below:
5748;; movw r0, #:lower16:g
5749;; movw r0, #:upper16:g
5750;; adds r0, #4
5751;;
5752;; A better way would be:
5753;; movw r0, #:lower16:g+4
5754;; movw r0, #:upper16:g+4
5755;;
5756;; The limitation of this way is that the length of offset should be a 16-bit
5757;; signed value, because current assembler only supports REL type relocation for
5758;; such case. If the more powerful RELA type is supported in future, we should
5759;; update this pattern to go with better way.
5760(define_split
5761 [(set (match_operand:SI 0 "arm_general_register_operand" "")
5762 (const:SI (plus:SI (match_operand:SI 1 "general_operand" "")
5763 (match_operand:SI 2 "const_int_operand" ""))))]
5764 "TARGET_THUMB2
5765 && arm_disable_literal_pool
5766 && reload_completed
5767 && GET_CODE (operands[1]) == SYMBOL_REF"
5768 [(clobber (const_int 0))]
5769 "
5770 int offset = INTVAL (operands[2]);
5771
5772 if (offset < -0x8000 || offset > 0x7fff)
5773 {
5774 arm_emit_movpair (operands[0], operands[1]);
d1f9b275 5775 emit_insn (gen_rtx_SET (operands[0],
861033d5 5776 gen_rtx_PLUS (SImode, operands[0], operands[2])));
5777 }
5778 else
5779 {
5780 rtx op = gen_rtx_CONST (SImode,
5781 gen_rtx_PLUS (SImode, operands[1], operands[2]));
5782 arm_emit_movpair (operands[0], op);
5783 }
5784 "
5785)
5786
b8d5d078 5787;; Split symbol_refs at the later stage (after cprop), instead of generating
5788;; movt/movw pair directly at expand. Otherwise corresponding high_sum
5789;; and lo_sum would be merged back into memory load at cprop. However,
5790;; if the default is to prefer movt/movw rather than a load from the constant
5791;; pool, the performance is better.
5792(define_split
5793 [(set (match_operand:SI 0 "arm_general_register_operand" "")
5794 (match_operand:SI 1 "general_operand" ""))]
5795 "TARGET_32BIT
5796 && TARGET_USE_MOVT && GET_CODE (operands[1]) == SYMBOL_REF
5797 && !flag_pic && !target_word_relocations
5798 && !arm_tls_referenced_p (operands[1])"
5799 [(clobber (const_int 0))]
5800{
5801 arm_emit_movpair (operands[0], operands[1]);
5802 DONE;
5803})
5804
bc360af8 5805;; When generating pic, we need to load the symbol offset into a register.
5806;; So that the optimizer does not confuse this with a normal symbol load
5807;; we use an unspec. The offset will be loaded from a constant pool entry,
5808;; since that is the only type of relocation we can use.
cffb2a26 5809
bc360af8 5810;; Wrap calculation of the whole PIC address in a single pattern for the
5811;; benefit of optimizers, particularly, PRE and HOIST. Calculation of
5812;; a PIC address involves two loads from memory, so we want to CSE it
5813;; as often as possible.
5814;; This pattern will be split into one of the pic_load_addr_* patterns
5815;; and a move after GCSE optimizations.
5816;;
5817;; Note: Update arm.c: legitimize_pic_address() when changing this pattern.
5818(define_expand "calculate_pic_address"
94f8caca 5819 [(set (match_operand:SI 0 "register_operand" "")
5820 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "")
5821 (unspec:SI [(match_operand:SI 2 "" "")]
5822 UNSPEC_PIC_SYM))))]
5823 "flag_pic"
5824)
5825
5826;; Split calculate_pic_address into pic_load_addr_* and a move.
5827(define_split
5828 [(set (match_operand:SI 0 "register_operand" "")
5829 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "")
5830 (unspec:SI [(match_operand:SI 2 "" "")]
5831 UNSPEC_PIC_SYM))))]
5832 "flag_pic"
5833 [(set (match_dup 3) (unspec:SI [(match_dup 2)] UNSPEC_PIC_SYM))
5834 (set (match_dup 0) (mem:SI (plus:SI (match_dup 1) (match_dup 3))))]
5835 "operands[3] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];"
5836)
5837
350ccca5 5838;; operand1 is the memory address to go into
5839;; pic_load_addr_32bit.
5840;; operand2 is the PIC label to be emitted
5841;; from pic_add_dot_plus_eight.
5842;; We do this to allow hoisting of the entire insn.
5843(define_insn_and_split "pic_load_addr_unified"
5844 [(set (match_operand:SI 0 "s_register_operand" "=r,r,l")
5845 (unspec:SI [(match_operand:SI 1 "" "mX,mX,mX")
5846 (match_operand:SI 2 "" "")]
5847 UNSPEC_PIC_UNIFIED))]
5848 "flag_pic"
5849 "#"
5850 "&& reload_completed"
5851 [(set (match_dup 0) (unspec:SI [(match_dup 1)] UNSPEC_PIC_SYM))
5852 (set (match_dup 0) (unspec:SI [(match_dup 0) (match_dup 3)
5853 (match_dup 2)] UNSPEC_PIC_BASE))]
5854 "operands[3] = TARGET_THUMB ? GEN_INT (4) : GEN_INT (8);"
5855 [(set_attr "type" "load1,load1,load1")
42e1de19 5856 (set_attr "pool_range" "4096,4094,1022")
350ccca5 5857 (set_attr "neg_pool_range" "4084,0,0")
5858 (set_attr "arch" "a,t2,t1")
5859 (set_attr "length" "8,6,4")]
5860)
5861
67336bcf 5862;; The rather odd constraints on the following are to force reload to leave
5863;; the insn alone, and to force the minipool generation pass to then move
5864;; the GOT symbol to memory.
849170fd 5865
b3cd5f55 5866(define_insn "pic_load_addr_32bit"
849170fd 5867 [(set (match_operand:SI 0 "s_register_operand" "=r")
e1159bbe 5868 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
b3cd5f55 5869 "TARGET_32BIT && flag_pic"
67336bcf 5870 "ldr%?\\t%0, %1"
a2cd141b 5871 [(set_attr "type" "load1")
42e1de19 5872 (set (attr "pool_range")
5873 (if_then_else (eq_attr "is_thumb" "no")
5874 (const_int 4096)
5875 (const_int 4094)))
b3cd5f55 5876 (set (attr "neg_pool_range")
5877 (if_then_else (eq_attr "is_thumb" "no")
5878 (const_int 4084)
5879 (const_int 0)))]
8c4d8060 5880)
5881
25f905c2 5882(define_insn "pic_load_addr_thumb1"
8c4d8060 5883 [(set (match_operand:SI 0 "s_register_operand" "=l")
e1159bbe 5884 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
25f905c2 5885 "TARGET_THUMB1 && flag_pic"
8c4d8060 5886 "ldr\\t%0, %1"
a2cd141b 5887 [(set_attr "type" "load1")
42e1de19 5888 (set (attr "pool_range") (const_int 1018))]
cffb2a26 5889)
849170fd 5890
cffb2a26 5891(define_insn "pic_add_dot_plus_four"
15d5d060 5892 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5893 (unspec:SI [(match_operand:SI 1 "register_operand" "0")
5894 (const_int 4)
beef0fb5 5895 (match_operand 2 "" "")]
5896 UNSPEC_PIC_BASE))]
b3cd5f55 5897 "TARGET_THUMB"
cffb2a26 5898 "*
6cdcb15c 5899 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5900 INTVAL (operands[2]));
cffb2a26 5901 return \"add\\t%0, %|pc\";
5902 "
1b7da4ac 5903 [(set_attr "length" "2")
112eda6f 5904 (set_attr "type" "alu_sreg")]
cffb2a26 5905)
849170fd 5906
5907(define_insn "pic_add_dot_plus_eight"
15d5d060 5908 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5909 (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5910 (const_int 8)
beef0fb5 5911 (match_operand 2 "" "")]
5912 UNSPEC_PIC_BASE))]
f655717d 5913 "TARGET_ARM"
c4034607 5914 "*
6cdcb15c 5915 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5916 INTVAL (operands[2]));
15d5d060 5917 return \"add%?\\t%0, %|pc, %1\";
cffb2a26 5918 "
1b7da4ac 5919 [(set_attr "predicable" "yes")
112eda6f 5920 (set_attr "type" "alu_sreg")]
cffb2a26 5921)
849170fd 5922
f655717d 5923(define_insn "tls_load_dot_plus_eight"
cc071db6 5924 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5925 (mem:SI (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5926 (const_int 8)
beef0fb5 5927 (match_operand 2 "" "")]
5928 UNSPEC_PIC_BASE)))]
f655717d 5929 "TARGET_ARM"
5930 "*
6cdcb15c 5931 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5932 INTVAL (operands[2]));
f655717d 5933 return \"ldr%?\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_eight\";
5934 "
1b7da4ac 5935 [(set_attr "predicable" "yes")
5936 (set_attr "type" "load1")]
f655717d 5937)
5938
5939;; PIC references to local variables can generate pic_add_dot_plus_eight
5940;; followed by a load. These sequences can be crunched down to
5941;; tls_load_dot_plus_eight by a peephole.
5942
5943(define_peephole2
c0c1fba5 5944 [(set (match_operand:SI 0 "register_operand" "")
5945 (unspec:SI [(match_operand:SI 3 "register_operand" "")
5946 (const_int 8)
5947 (match_operand 1 "" "")]
5948 UNSPEC_PIC_BASE))
2d05dfad 5949 (set (match_operand:SI 2 "arm_general_register_operand" "")
5950 (mem:SI (match_dup 0)))]
f655717d 5951 "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
c0c1fba5 5952 [(set (match_dup 2)
5953 (mem:SI (unspec:SI [(match_dup 3)
5954 (const_int 8)
5955 (match_dup 1)]
5956 UNSPEC_PIC_BASE)))]
f655717d 5957 ""
5958)
5959
bac7fc85 5960(define_insn "pic_offset_arm"
5961 [(set (match_operand:SI 0 "register_operand" "=r")
5962 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
5963 (unspec:SI [(match_operand:SI 2 "" "X")]
5964 UNSPEC_PIC_OFFSET))))]
5965 "TARGET_VXWORKS_RTP && TARGET_ARM && flag_pic"
5966 "ldr%?\\t%0, [%1,%2]"
5967 [(set_attr "type" "load1")]
5968)
5969
95373f08 5970(define_expand "builtin_setjmp_receiver"
5971 [(label_ref (match_operand 0 "" ""))]
5972 "flag_pic"
5973 "
5974{
b935b306 5975 /* r3 is clobbered by set/longjmp, so we can use it as a scratch
5976 register. */
2cb7d577 5977 if (arm_pic_register != INVALID_REGNUM)
5978 arm_load_pic_register (1UL << 3);
95373f08 5979 DONE;
5980}")
5981
9c08d1fa 5982;; If copying one reg to another we can set the condition codes according to
5983;; its value. Such a move is common after a return from subroutine and the
5984;; result is being tested against zero.
5985
f7fbdd4a 5986(define_insn "*movsi_compare0"
bd5b4116 5987 [(set (reg:CC CC_REGNUM)
cffb2a26 5988 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
5989 (const_int 0)))
5990 (set (match_operand:SI 0 "s_register_operand" "=r,r")
5991 (match_dup 1))]
25f905c2 5992 "TARGET_32BIT"
e2348bcb 5993 "@
40dbec34 5994 cmp%?\\t%0, #0
3ef90e77 5995 subs%?\\t%0, %1, #0"
65f68e55 5996 [(set_attr "conds" "set")
d82e788e 5997 (set_attr "type" "alus_imm,alus_imm")]
cffb2a26 5998)
b11cae9e 5999
b11cae9e 6000;; Subroutine to store a half word from a register into memory.
6001;; Operand 0 is the source register (HImode)
c8f69309 6002;; Operand 1 is the destination address in a register (SImode)
b11cae9e 6003
9c08d1fa 6004;; In both this routine and the next, we must be careful not to spill
01cc3b75 6005;; a memory address of reg+large_const into a separate PLUS insn, since this
9c08d1fa 6006;; can generate unrecognizable rtl.
6007
b11cae9e 6008(define_expand "storehi"
c8f69309 6009 [;; store the low byte
f082f1c4 6010 (set (match_operand 1 "" "") (match_dup 3))
b11cae9e 6011 ;; extract the high byte
c8f69309 6012 (set (match_dup 2)
6013 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
b11cae9e 6014 ;; store the high byte
787f8210 6015 (set (match_dup 4) (match_dup 5))]
cffb2a26 6016 "TARGET_ARM"
b11cae9e 6017 "
215b30b3 6018 {
537ffcfc 6019 rtx op1 = operands[1];
6020 rtx addr = XEXP (op1, 0);
215b30b3 6021 enum rtx_code code = GET_CODE (addr);
6022
0438d37f 6023 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
215b30b3 6024 || code == MINUS)
537ffcfc 6025 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
215b30b3 6026
537ffcfc 6027 operands[4] = adjust_address (op1, QImode, 1);
e513d163 6028 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 6029 operands[3] = gen_lowpart (QImode, operands[0]);
6030 operands[0] = gen_lowpart (SImode, operands[0]);
787f8210 6031 operands[2] = gen_reg_rtx (SImode);
6032 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 6033 }"
6034)
b11cae9e 6035
c7597b5d 6036(define_expand "storehi_bigend"
f082f1c4 6037 [(set (match_dup 4) (match_dup 3))
c7597b5d 6038 (set (match_dup 2)
6039 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
787f8210 6040 (set (match_operand 1 "" "") (match_dup 5))]
cffb2a26 6041 "TARGET_ARM"
b11cae9e 6042 "
215b30b3 6043 {
537ffcfc 6044 rtx op1 = operands[1];
6045 rtx addr = XEXP (op1, 0);
215b30b3 6046 enum rtx_code code = GET_CODE (addr);
6047
0438d37f 6048 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
215b30b3 6049 || code == MINUS)
537ffcfc 6050 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
215b30b3 6051
537ffcfc 6052 operands[4] = adjust_address (op1, QImode, 1);
e513d163 6053 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 6054 operands[3] = gen_lowpart (QImode, operands[0]);
6055 operands[0] = gen_lowpart (SImode, operands[0]);
6056 operands[2] = gen_reg_rtx (SImode);
787f8210 6057 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 6058 }"
6059)
c7597b5d 6060
6061;; Subroutine to store a half word integer constant into memory.
6062(define_expand "storeinthi"
f082f1c4 6063 [(set (match_operand 0 "" "")
787f8210 6064 (match_operand 1 "" ""))
9e8503e6 6065 (set (match_dup 3) (match_dup 2))]
cffb2a26 6066 "TARGET_ARM"
c7597b5d 6067 "
215b30b3 6068 {
6069 HOST_WIDE_INT value = INTVAL (operands[1]);
6070 rtx addr = XEXP (operands[0], 0);
537ffcfc 6071 rtx op0 = operands[0];
215b30b3 6072 enum rtx_code code = GET_CODE (addr);
c7597b5d 6073
0438d37f 6074 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
215b30b3 6075 || code == MINUS)
537ffcfc 6076 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
c7597b5d 6077
215b30b3 6078 operands[1] = gen_reg_rtx (SImode);
6079 if (BYTES_BIG_ENDIAN)
6080 {
6081 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
6082 if ((value & 255) == ((value >> 8) & 255))
6083 operands[2] = operands[1];
6084 else
6085 {
6086 operands[2] = gen_reg_rtx (SImode);
6087 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
6088 }
6089 }
6090 else
6091 {
6092 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
6093 if ((value & 255) == ((value >> 8) & 255))
6094 operands[2] = operands[1];
6095 else
6096 {
6097 operands[2] = gen_reg_rtx (SImode);
6098 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
6099 }
6100 }
c7597b5d 6101
537ffcfc 6102 operands[3] = adjust_address (op0, QImode, 1);
e513d163 6103 operands[0] = adjust_address (operands[0], QImode, 0);
9e8503e6 6104 operands[2] = gen_lowpart (QImode, operands[2]);
787f8210 6105 operands[1] = gen_lowpart (QImode, operands[1]);
215b30b3 6106 }"
6107)
b11cae9e 6108
f7fbdd4a 6109(define_expand "storehi_single_op"
6110 [(set (match_operand:HI 0 "memory_operand" "")
6111 (match_operand:HI 1 "general_operand" ""))]
25f905c2 6112 "TARGET_32BIT && arm_arch4"
f7fbdd4a 6113 "
215b30b3 6114 if (!s_register_operand (operands[1], HImode))
f7fbdd4a 6115 operands[1] = copy_to_mode_reg (HImode, operands[1]);
215b30b3 6116 "
6117)
f7fbdd4a 6118
b11cae9e 6119(define_expand "movhi"
6120 [(set (match_operand:HI 0 "general_operand" "")
c8f69309 6121 (match_operand:HI 1 "general_operand" ""))]
cffb2a26 6122 "TARGET_EITHER"
b11cae9e 6123 "
cffb2a26 6124 if (TARGET_ARM)
b11cae9e 6125 {
e1ba4a27 6126 if (can_create_pseudo_p ())
cffb2a26 6127 {
0438d37f 6128 if (MEM_P (operands[0]))
b11cae9e 6129 {
cffb2a26 6130 if (arm_arch4)
6131 {
6132 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
6133 DONE;
6134 }
0438d37f 6135 if (CONST_INT_P (operands[1]))
cffb2a26 6136 emit_insn (gen_storeinthi (operands[0], operands[1]));
c7597b5d 6137 else
cffb2a26 6138 {
0438d37f 6139 if (MEM_P (operands[1]))
cffb2a26 6140 operands[1] = force_reg (HImode, operands[1]);
6141 if (BYTES_BIG_ENDIAN)
6142 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
6143 else
6144 emit_insn (gen_storehi (operands[1], operands[0]));
6145 }
6146 DONE;
b11cae9e 6147 }
cffb2a26 6148 /* Sign extend a constant, and keep it in an SImode reg. */
0438d37f 6149 else if (CONST_INT_P (operands[1]))
9c08d1fa 6150 {
cffb2a26 6151 rtx reg = gen_reg_rtx (SImode);
6152 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
6153
6154 /* If the constant is already valid, leave it alone. */
215b30b3 6155 if (!const_ok_for_arm (val))
cffb2a26 6156 {
6157 /* If setting all the top bits will make the constant
6158 loadable in a single instruction, then set them.
6159 Otherwise, sign extend the number. */
6160
215b30b3 6161 if (const_ok_for_arm (~(val | ~0xffff)))
cffb2a26 6162 val |= ~0xffff;
6163 else if (val & 0x8000)
6164 val |= ~0xffff;
6165 }
6166
6167 emit_insn (gen_movsi (reg, GEN_INT (val)));
9e8503e6 6168 operands[1] = gen_lowpart (HImode, reg);
9c08d1fa 6169 }
e1ba4a27 6170 else if (arm_arch4 && optimize && can_create_pseudo_p ()
0438d37f 6171 && MEM_P (operands[1]))
0045890a 6172 {
6173 rtx reg = gen_reg_rtx (SImode);
6174
6175 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
6176 operands[1] = gen_lowpart (HImode, reg);
6177 }
215b30b3 6178 else if (!arm_arch4)
f7fbdd4a 6179 {
0438d37f 6180 if (MEM_P (operands[1]))
cffb2a26 6181 {
c1a66faf 6182 rtx base;
6183 rtx offset = const0_rtx;
6184 rtx reg = gen_reg_rtx (SImode);
6185
0438d37f 6186 if ((REG_P (base = XEXP (operands[1], 0))
c1a66faf 6187 || (GET_CODE (base) == PLUS
0438d37f 6188 && (CONST_INT_P (offset = XEXP (base, 1)))
c1a66faf 6189 && ((INTVAL(offset) & 1) != 1)
0438d37f 6190 && REG_P (base = XEXP (base, 0))))
c1a66faf 6191 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
206ee9a2 6192 {
8deb3959 6193 rtx new_rtx;
c1a66faf 6194
8deb3959 6195 new_rtx = widen_memory_access (operands[1], SImode,
6196 ((INTVAL (offset) & ~3)
6197 - INTVAL (offset)));
6198 emit_insn (gen_movsi (reg, new_rtx));
c1a66faf 6199 if (((INTVAL (offset) & 2) != 0)
6200 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
6201 {
6202 rtx reg2 = gen_reg_rtx (SImode);
6203
6204 emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
6205 reg = reg2;
6206 }
206ee9a2 6207 }
c1a66faf 6208 else
6209 emit_insn (gen_movhi_bytes (reg, operands[1]));
6210
6211 operands[1] = gen_lowpart (HImode, reg);
cffb2a26 6212 }
6213 }
6214 }
674a8f0b 6215 /* Handle loading a large integer during reload. */
0438d37f 6216 else if (CONST_INT_P (operands[1])
215b30b3 6217 && !const_ok_for_arm (INTVAL (operands[1]))
6218 && !const_ok_for_arm (~INTVAL (operands[1])))
cffb2a26 6219 {
6220 /* Writing a constant to memory needs a scratch, which should
6221 be handled with SECONDARY_RELOADs. */
0438d37f 6222 gcc_assert (REG_P (operands[0]));
cffb2a26 6223
6224 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
6225 emit_insn (gen_movsi (operands[0], operands[1]));
6226 DONE;
6227 }
6228 }
25f905c2 6229 else if (TARGET_THUMB2)
6230 {
6231 /* Thumb-2 can do everything except mem=mem and mem=const easily. */
e1ba4a27 6232 if (can_create_pseudo_p ())
25f905c2 6233 {
0438d37f 6234 if (!REG_P (operands[0]))
25f905c2 6235 operands[1] = force_reg (HImode, operands[1]);
6236 /* Zero extend a constant, and keep it in an SImode reg. */
0438d37f 6237 else if (CONST_INT_P (operands[1]))
25f905c2 6238 {
6239 rtx reg = gen_reg_rtx (SImode);
6240 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
6241
6242 emit_insn (gen_movsi (reg, GEN_INT (val)));
6243 operands[1] = gen_lowpart (HImode, reg);
6244 }
6245 }
6246 }
6247 else /* TARGET_THUMB1 */
cffb2a26 6248 {
e1ba4a27 6249 if (can_create_pseudo_p ())
cffb2a26 6250 {
0438d37f 6251 if (CONST_INT_P (operands[1]))
6cffc037 6252 {
6253 rtx reg = gen_reg_rtx (SImode);
6254
6255 emit_insn (gen_movsi (reg, operands[1]));
6256 operands[1] = gen_lowpart (HImode, reg);
6257 }
cffb2a26 6258
6259 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 6260 happen if we are passed a SP (never OK for HImode/QImode) or
bc409cb4 6261 virtual register (also rejected as illegitimate for HImode/QImode)
6262 relative address. */
cffb2a26 6263 /* ??? This should perhaps be fixed elsewhere, for instance, in
6264 fixup_stack_1, by checking for other kinds of invalid addresses,
6265 e.g. a bare reference to a virtual register. This may confuse the
6266 alpha though, which must handle this case differently. */
0438d37f 6267 if (MEM_P (operands[0])
215b30b3 6268 && !memory_address_p (GET_MODE (operands[0]),
6269 XEXP (operands[0], 0)))
537ffcfc 6270 operands[0]
6271 = replace_equiv_address (operands[0],
6272 copy_to_reg (XEXP (operands[0], 0)));
cffb2a26 6273
0438d37f 6274 if (MEM_P (operands[1])
215b30b3 6275 && !memory_address_p (GET_MODE (operands[1]),
6276 XEXP (operands[1], 0)))
537ffcfc 6277 operands[1]
6278 = replace_equiv_address (operands[1],
6279 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 6280
0438d37f 6281 if (MEM_P (operands[1]) && optimize > 0)
6cffc037 6282 {
6283 rtx reg = gen_reg_rtx (SImode);
6284
6285 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
6286 operands[1] = gen_lowpart (HImode, reg);
6287 }
6288
0438d37f 6289 if (MEM_P (operands[0]))
6cffc037 6290 operands[1] = force_reg (HImode, operands[1]);
cffb2a26 6291 }
0438d37f 6292 else if (CONST_INT_P (operands[1])
234f6557 6293 && !satisfies_constraint_I (operands[1]))
cffb2a26 6294 {
6cffc037 6295 /* Handle loading a large integer during reload. */
6296
cffb2a26 6297 /* Writing a constant to memory needs a scratch, which should
6298 be handled with SECONDARY_RELOADs. */
0438d37f 6299 gcc_assert (REG_P (operands[0]));
cffb2a26 6300
1a83b3ff 6301 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
cffb2a26 6302 emit_insn (gen_movsi (operands[0], operands[1]));
6303 DONE;
6304 }
b11cae9e 6305 }
cffb2a26 6306 "
6307)
6308
25f7a26e 6309(define_expand "movhi_bytes"
eab14235 6310 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 6311 (set (match_dup 3)
eab14235 6312 (zero_extend:SI (match_dup 6)))
25f7a26e 6313 (set (match_operand:SI 0 "" "")
6314 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
cffb2a26 6315 "TARGET_ARM"
25f7a26e 6316 "
215b30b3 6317 {
6318 rtx mem1, mem2;
6319 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
6320
788fcce0 6321 mem1 = change_address (operands[1], QImode, addr);
29c05e22 6322 mem2 = change_address (operands[1], QImode,
6323 plus_constant (Pmode, addr, 1));
215b30b3 6324 operands[0] = gen_lowpart (SImode, operands[0]);
6325 operands[1] = mem1;
6326 operands[2] = gen_reg_rtx (SImode);
6327 operands[3] = gen_reg_rtx (SImode);
6328 operands[6] = mem2;
25f7a26e 6329
215b30b3 6330 if (BYTES_BIG_ENDIAN)
6331 {
6332 operands[4] = operands[2];
6333 operands[5] = operands[3];
6334 }
6335 else
6336 {
6337 operands[4] = operands[3];
6338 operands[5] = operands[2];
6339 }
6340 }"
6341)
25f7a26e 6342
c7597b5d 6343(define_expand "movhi_bigend"
6344 [(set (match_dup 2)
6345 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
6346 (const_int 16)))
6347 (set (match_dup 3)
6348 (ashiftrt:SI (match_dup 2) (const_int 16)))
6349 (set (match_operand:HI 0 "s_register_operand" "")
787f8210 6350 (match_dup 4))]
cffb2a26 6351 "TARGET_ARM"
c7597b5d 6352 "
6353 operands[2] = gen_reg_rtx (SImode);
6354 operands[3] = gen_reg_rtx (SImode);
787f8210 6355 operands[4] = gen_lowpart (HImode, operands[3]);
215b30b3 6356 "
6357)
b11cae9e 6358
a2f10574 6359;; Pattern to recognize insn generated default case above
f7fbdd4a 6360(define_insn "*movhi_insn_arch4"
e4585731 6361 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r,m,r")
6362 (match_operand:HI 1 "general_operand" "rIk,K,n,r,mi"))]
cffb2a26 6363 "TARGET_ARM
6364 && arm_arch4
85e02ccb 6365 && (register_operand (operands[0], HImode)
6366 || register_operand (operands[1], HImode))"
f7fbdd4a 6367 "@
6368 mov%?\\t%0, %1\\t%@ movhi
6369 mvn%?\\t%0, #%B1\\t%@ movhi
b1c1a101 6370 movw%?\\t%0, %L1\\t%@ movhi
3ef90e77 6371 strh%?\\t%1, %0\\t%@ movhi
6372 ldrh%?\\t%0, %1\\t%@ movhi"
65f68e55 6373 [(set_attr "predicable" "yes")
e4585731 6374 (set_attr "pool_range" "*,*,*,*,256")
6375 (set_attr "neg_pool_range" "*,*,*,*,244")
6376 (set_attr "arch" "*,*,v6t2,*,*")
65f68e55 6377 (set_attr_alternative "type"
6378 [(if_then_else (match_operand 1 "const_int_operand" "")
1aed5204 6379 (const_string "mov_imm" )
6380 (const_string "mov_reg"))
6381 (const_string "mvn_imm")
e4585731 6382 (const_string "mov_imm")
65f68e55 6383 (const_string "store1")
6384 (const_string "load1")])]
cffb2a26 6385)
f7fbdd4a 6386
f7fbdd4a 6387(define_insn "*movhi_bytes"
65f68e55 6388 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
5fd254ed 6389 (match_operand:HI 1 "arm_rhs_operand" "I,rk,K"))]
c1a66faf 6390 "TARGET_ARM"
25f7a26e 6391 "@
65f68e55 6392 mov%?\\t%0, %1\\t%@ movhi
25f7a26e 6393 mov%?\\t%0, %1\\t%@ movhi
0d66636f 6394 mvn%?\\t%0, #%B1\\t%@ movhi"
d2a518d1 6395 [(set_attr "predicable" "yes")
1aed5204 6396 (set_attr "type" "mov_imm,mov_reg,mvn_imm")]
0d66636f 6397)
cffb2a26 6398
bc5c7e08 6399;; We use a DImode scratch because we may occasionally need an additional
6400;; temporary if the address isn't offsettable -- push_reload doesn't seem
6401;; to take any notice of the "o" constraints on reload_memory_operand operand.
d3373b54 6402(define_expand "reload_outhi"
cffb2a26 6403 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
215b30b3 6404 (match_operand:HI 1 "s_register_operand" "r")
6405 (match_operand:DI 2 "s_register_operand" "=&l")])]
cffb2a26 6406 "TARGET_EITHER"
6407 "if (TARGET_ARM)
6408 arm_reload_out_hi (operands);
6409 else
6410 thumb_reload_out_hi (operands);
d3373b54 6411 DONE;
cffb2a26 6412 "
6413)
d3373b54 6414
25f7a26e 6415(define_expand "reload_inhi"
6416 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
cffb2a26 6417 (match_operand:HI 1 "arm_reload_memory_operand" "o")
bc5c7e08 6418 (match_operand:DI 2 "s_register_operand" "=&r")])]
c1a66faf 6419 "TARGET_EITHER"
25f7a26e 6420 "
cffb2a26 6421 if (TARGET_ARM)
6422 arm_reload_in_hi (operands);
6423 else
6424 thumb_reload_out_hi (operands);
25f7a26e 6425 DONE;
6426")
6427
9c08d1fa 6428(define_expand "movqi"
6429 [(set (match_operand:QI 0 "general_operand" "")
6430 (match_operand:QI 1 "general_operand" ""))]
cffb2a26 6431 "TARGET_EITHER"
9c08d1fa 6432 "
6cffc037 6433 /* Everything except mem = const or mem = mem can be done easily */
0045890a 6434
e1ba4a27 6435 if (can_create_pseudo_p ())
cffb2a26 6436 {
0438d37f 6437 if (CONST_INT_P (operands[1]))
6cffc037 6438 {
6439 rtx reg = gen_reg_rtx (SImode);
6440
03770691 6441 /* For thumb we want an unsigned immediate, then we are more likely
6442 to be able to use a movs insn. */
6443 if (TARGET_THUMB)
6444 operands[1] = GEN_INT (INTVAL (operands[1]) & 255);
6445
6cffc037 6446 emit_insn (gen_movsi (reg, operands[1]));
6447 operands[1] = gen_lowpart (QImode, reg);
6448 }
cffb2a26 6449
6cffc037 6450 if (TARGET_THUMB)
6451 {
cffb2a26 6452 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 6453 happen if we are passed a SP (never OK for HImode/QImode) or
bc409cb4 6454 virtual register (also rejected as illegitimate for HImode/QImode)
6455 relative address. */
cffb2a26 6456 /* ??? This should perhaps be fixed elsewhere, for instance, in
6457 fixup_stack_1, by checking for other kinds of invalid addresses,
6458 e.g. a bare reference to a virtual register. This may confuse the
6459 alpha though, which must handle this case differently. */
0438d37f 6460 if (MEM_P (operands[0])
215b30b3 6461 && !memory_address_p (GET_MODE (operands[0]),
cffb2a26 6462 XEXP (operands[0], 0)))
537ffcfc 6463 operands[0]
6464 = replace_equiv_address (operands[0],
6465 copy_to_reg (XEXP (operands[0], 0)));
0438d37f 6466 if (MEM_P (operands[1])
215b30b3 6467 && !memory_address_p (GET_MODE (operands[1]),
cffb2a26 6468 XEXP (operands[1], 0)))
537ffcfc 6469 operands[1]
6470 = replace_equiv_address (operands[1],
6471 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 6472 }
6473
0438d37f 6474 if (MEM_P (operands[1]) && optimize > 0)
6cffc037 6475 {
6476 rtx reg = gen_reg_rtx (SImode);
6477
6478 emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
6479 operands[1] = gen_lowpart (QImode, reg);
6480 }
6481
0438d37f 6482 if (MEM_P (operands[0]))
6cffc037 6483 operands[1] = force_reg (QImode, operands[1]);
6484 }
6485 else if (TARGET_THUMB
0438d37f 6486 && CONST_INT_P (operands[1])
234f6557 6487 && !satisfies_constraint_I (operands[1]))
6cffc037 6488 {
674a8f0b 6489 /* Handle loading a large integer during reload. */
cffb2a26 6490
6cffc037 6491 /* Writing a constant to memory needs a scratch, which should
6492 be handled with SECONDARY_RELOADs. */
0438d37f 6493 gcc_assert (REG_P (operands[0]));
6cffc037 6494
6495 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
6496 emit_insn (gen_movsi (operands[0], operands[1]));
6497 DONE;
cffb2a26 6498 }
6499 "
6500)
b11cae9e 6501
cffb2a26 6502(define_insn "*arm_movqi_insn"
fd711051 6503 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,l,r,l,Uu,r,m")
490f62ca 6504 (match_operand:QI 1 "general_operand" "rk,rk,I,Py,K,Uu,l,Uh,r"))]
25f905c2 6505 "TARGET_32BIT
cffb2a26 6506 && ( register_operand (operands[0], QImode)
6507 || register_operand (operands[1], QImode))"
5565501b 6508 "@
fd711051 6509 mov%?\\t%0, %1
6510 mov%?\\t%0, %1
65f68e55 6511 mov%?\\t%0, %1
5565501b 6512 mov%?\\t%0, %1
6513 mvn%?\\t%0, #%B1
3ef90e77 6514 ldrb%?\\t%0, %1
6515 strb%?\\t%1, %0
6516 ldrb%?\\t%0, %1
6517 strb%?\\t%1, %0"
1aed5204 6518 [(set_attr "type" "mov_reg,mov_reg,mov_imm,mov_imm,mvn_imm,load1,store1,load1,store1")
a54e3e7b 6519 (set_attr "predicable" "yes")
fd711051 6520 (set_attr "predicable_short_it" "yes,yes,yes,no,no,no,no,no,no")
6521 (set_attr "arch" "t2,any,any,t2,any,t2,t2,any,any")
6522 (set_attr "length" "2,4,4,2,4,2,2,4,4")]
cffb2a26 6523)
6524
9b8516be 6525;; HFmode moves
6526(define_expand "movhf"
6527 [(set (match_operand:HF 0 "general_operand" "")
6528 (match_operand:HF 1 "general_operand" ""))]
6529 "TARGET_EITHER"
6530 "
6531 if (TARGET_32BIT)
6532 {
0438d37f 6533 if (MEM_P (operands[0]))
9b8516be 6534 operands[1] = force_reg (HFmode, operands[1]);
6535 }
6536 else /* TARGET_THUMB1 */
6537 {
6538 if (can_create_pseudo_p ())
6539 {
0438d37f 6540 if (!REG_P (operands[0]))
9b8516be 6541 operands[1] = force_reg (HFmode, operands[1]);
6542 }
6543 }
6544 "
6545)
6546
6547(define_insn "*arm32_movhf"
6548 [(set (match_operand:HF 0 "nonimmediate_operand" "=r,m,r,r")
6549 (match_operand:HF 1 "general_operand" " m,r,r,F"))]
ea501323 6550 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_FP16)
9b8516be 6551 && ( s_register_operand (operands[0], HFmode)
6552 || s_register_operand (operands[1], HFmode))"
6553 "*
6554 switch (which_alternative)
6555 {
6556 case 0: /* ARM register from memory */
3ef90e77 6557 return \"ldrh%?\\t%0, %1\\t%@ __fp16\";
9b8516be 6558 case 1: /* memory from ARM register */
3ef90e77 6559 return \"strh%?\\t%1, %0\\t%@ __fp16\";
9b8516be 6560 case 2: /* ARM register from ARM register */
6561 return \"mov%?\\t%0, %1\\t%@ __fp16\";
6562 case 3: /* ARM register from constant */
6563 {
9b8516be 6564 long bits;
6565 rtx ops[4];
6566
945f7b03 6567 bits = real_to_target (NULL, CONST_DOUBLE_REAL_VALUE (operands[1]),
6568 HFmode);
9b8516be 6569 ops[0] = operands[0];
6570 ops[1] = GEN_INT (bits);
6571 ops[2] = GEN_INT (bits & 0xff00);
6572 ops[3] = GEN_INT (bits & 0x00ff);
6573
6574 if (arm_arch_thumb2)
6575 output_asm_insn (\"movw%?\\t%0, %1\", ops);
6576 else
6577 output_asm_insn (\"mov%?\\t%0, %2\;orr%?\\t%0, %0, %3\", ops);
6578 return \"\";
6579 }
6580 default:
6581 gcc_unreachable ();
6582 }
6583 "
6584 [(set_attr "conds" "unconditional")
ad4fc3c0 6585 (set_attr "type" "load1,store1,mov_reg,multiple")
9b8516be 6586 (set_attr "length" "4,4,4,8")
ea501323 6587 (set_attr "predicable" "yes")
6588 (set_attr "predicable_short_it" "no")]
9b8516be 6589)
6590
87b22bf7 6591(define_expand "movsf"
6592 [(set (match_operand:SF 0 "general_operand" "")
6593 (match_operand:SF 1 "general_operand" ""))]
cffb2a26 6594 "TARGET_EITHER"
87b22bf7 6595 "
25f905c2 6596 if (TARGET_32BIT)
cffb2a26 6597 {
0438d37f 6598 if (MEM_P (operands[0]))
cffb2a26 6599 operands[1] = force_reg (SFmode, operands[1]);
6600 }
25f905c2 6601 else /* TARGET_THUMB1 */
cffb2a26 6602 {
e1ba4a27 6603 if (can_create_pseudo_p ())
cffb2a26 6604 {
0438d37f 6605 if (!REG_P (operands[0]))
cffb2a26 6606 operands[1] = force_reg (SFmode, operands[1]);
6607 }
6608 }
6609 "
6610)
6611
03d440a6 6612;; Transform a floating-point move of a constant into a core register into
6613;; an SImode operation.
cffb2a26 6614(define_split
03d440a6 6615 [(set (match_operand:SF 0 "arm_general_register_operand" "")
cffb2a26 6616 (match_operand:SF 1 "immediate_operand" ""))]
339034d0 6617 "TARGET_EITHER
cffb2a26 6618 && reload_completed
0438d37f 6619 && CONST_DOUBLE_P (operands[1])"
cffb2a26 6620 [(set (match_dup 2) (match_dup 3))]
6621 "
6622 operands[2] = gen_lowpart (SImode, operands[0]);
6623 operands[3] = gen_lowpart (SImode, operands[1]);
6624 if (operands[2] == 0 || operands[3] == 0)
6625 FAIL;
215b30b3 6626 "
6627)
87b22bf7 6628
cffb2a26 6629(define_insn "*arm_movsf_soft_insn"
6630 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
6631 (match_operand:SF 1 "general_operand" "r,mE,r"))]
cde1623a 6632 "TARGET_32BIT
cffb2a26 6633 && TARGET_SOFT_FLOAT
0438d37f 6634 && (!MEM_P (operands[0])
215b30b3 6635 || register_operand (operands[1], SFmode))"
9a1112d7 6636 "@
6637 mov%?\\t%0, %1
6638 ldr%?\\t%0, %1\\t%@ float
6639 str%?\\t%1, %0\\t%@ float"
cde1623a 6640 [(set_attr "predicable" "yes")
7c36fe71 6641 (set_attr "predicable_short_it" "no")
1aed5204 6642 (set_attr "type" "mov_reg,load1,store1")
42e1de19 6643 (set_attr "arm_pool_range" "*,4096,*")
6644 (set_attr "thumb2_pool_range" "*,4094,*")
cde1623a 6645 (set_attr "arm_neg_pool_range" "*,4084,*")
6646 (set_attr "thumb2_neg_pool_range" "*,0,*")]
cffb2a26 6647)
6648
9c08d1fa 6649(define_expand "movdf"
87b22bf7 6650 [(set (match_operand:DF 0 "general_operand" "")
6651 (match_operand:DF 1 "general_operand" ""))]
cffb2a26 6652 "TARGET_EITHER"
9c08d1fa 6653 "
25f905c2 6654 if (TARGET_32BIT)
cffb2a26 6655 {
0438d37f 6656 if (MEM_P (operands[0]))
cffb2a26 6657 operands[1] = force_reg (DFmode, operands[1]);
6658 }
6659 else /* TARGET_THUMB */
6660 {
e1ba4a27 6661 if (can_create_pseudo_p ())
cffb2a26 6662 {
0438d37f 6663 if (!REG_P (operands[0]))
cffb2a26 6664 operands[1] = force_reg (DFmode, operands[1]);
6665 }
6666 }
6667 "
6668)
b11cae9e 6669
9c08d1fa 6670;; Reloading a df mode value stored in integer regs to memory can require a
6671;; scratch reg.
6672(define_expand "reload_outdf"
cffb2a26 6673 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
87b22bf7 6674 (match_operand:DF 1 "s_register_operand" "r")
6675 (match_operand:SI 2 "s_register_operand" "=&r")]
06adefdc 6676 "TARGET_THUMB2"
87b22bf7 6677 "
215b30b3 6678 {
6679 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
f7fbdd4a 6680
215b30b3 6681 if (code == REG)
6682 operands[2] = XEXP (operands[0], 0);
6683 else if (code == POST_INC || code == PRE_DEC)
6684 {
6685 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
6686 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
6687 emit_insn (gen_movdi (operands[0], operands[1]));
6688 DONE;
6689 }
6690 else if (code == PRE_INC)
6691 {
6692 rtx reg = XEXP (XEXP (operands[0], 0), 0);
f7fbdd4a 6693
215b30b3 6694 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
6695 operands[2] = reg;
6696 }
6697 else if (code == POST_DEC)
6698 operands[2] = XEXP (XEXP (operands[0], 0), 0);
6699 else
6700 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
6701 XEXP (XEXP (operands[0], 0), 1)));
f7fbdd4a 6702
d1f9b275 6703 emit_insn (gen_rtx_SET (replace_equiv_address (operands[0], operands[2]),
215b30b3 6704 operands[1]));
f7fbdd4a 6705
215b30b3 6706 if (code == POST_DEC)
6707 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
6708
6709 DONE;
6710 }"
6711)
9c08d1fa 6712
9a1112d7 6713(define_insn "*movdf_soft_insn"
353cf59a 6714 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,q,m")
6715 (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,q"))]
cde1623a 6716 "TARGET_32BIT && TARGET_SOFT_FLOAT
b2778788 6717 && ( register_operand (operands[0], DFmode)
6718 || register_operand (operands[1], DFmode))"
d51f92df 6719 "*
6720 switch (which_alternative)
6721 {
6722 case 0:
6723 case 1:
6724 case 2:
6725 return \"#\";
6726 default:
26ff80c0 6727 return output_move_double (operands, true, NULL);
d51f92df 6728 }
6729 "
359a6e9f 6730 [(set_attr "length" "8,12,16,8,8")
1b7da4ac 6731 (set_attr "type" "multiple,multiple,multiple,load2,store2")
42e1de19 6732 (set_attr "arm_pool_range" "*,*,*,1020,*")
6733 (set_attr "thumb2_pool_range" "*,*,*,1018,*")
8848d797 6734 (set_attr "arm_neg_pool_range" "*,*,*,1004,*")
cde1623a 6735 (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
cffb2a26 6736)
b11cae9e 6737\f
b11cae9e 6738
9c08d1fa 6739;; load- and store-multiple insns
6740;; The arm can load/store any set of registers, provided that they are in
320ea44d 6741;; ascending order, but these expanders assume a contiguous set.
b11cae9e 6742
9c08d1fa 6743(define_expand "load_multiple"
6744 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6745 (match_operand:SI 1 "" ""))
6746 (use (match_operand:SI 2 "" ""))])]
25f905c2 6747 "TARGET_32BIT"
9580c25f 6748{
6749 HOST_WIDE_INT offset = 0;
6750
bd5b4116 6751 /* Support only fixed point registers. */
0438d37f 6752 if (!CONST_INT_P (operands[2])
6e628811 6753 || INTVAL (operands[2]) > MAX_LDM_STM_OPS
9c08d1fa 6754 || INTVAL (operands[2]) < 2
0438d37f 6755 || !MEM_P (operands[1])
6756 || !REG_P (operands[0])
bd5b4116 6757 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
6758 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 6759 FAIL;
6760
6761 operands[3]
320ea44d 6762 = arm_gen_load_multiple (arm_regs_in_sequence + REGNO (operands[0]),
6763 INTVAL (operands[2]),
f082f1c4 6764 force_reg (SImode, XEXP (operands[1], 0)),
320ea44d 6765 FALSE, operands[1], &offset);
9580c25f 6766})
b11cae9e 6767
9c08d1fa 6768(define_expand "store_multiple"
6769 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6770 (match_operand:SI 1 "" ""))
6771 (use (match_operand:SI 2 "" ""))])]
25f905c2 6772 "TARGET_32BIT"
9580c25f 6773{
6774 HOST_WIDE_INT offset = 0;
6775
674a8f0b 6776 /* Support only fixed point registers. */
0438d37f 6777 if (!CONST_INT_P (operands[2])
6e628811 6778 || INTVAL (operands[2]) > MAX_LDM_STM_OPS
9c08d1fa 6779 || INTVAL (operands[2]) < 2
0438d37f 6780 || !REG_P (operands[1])
6781 || !MEM_P (operands[0])
bd5b4116 6782 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
6783 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 6784 FAIL;
6785
6786 operands[3]
320ea44d 6787 = arm_gen_store_multiple (arm_regs_in_sequence + REGNO (operands[1]),
6788 INTVAL (operands[2]),
f082f1c4 6789 force_reg (SImode, XEXP (operands[0], 0)),
320ea44d 6790 FALSE, operands[0], &offset);
9580c25f 6791})
b11cae9e 6792
9c08d1fa 6793
e34ebfca 6794(define_expand "setmemsi"
6795 [(match_operand:BLK 0 "general_operand" "")
6796 (match_operand:SI 1 "const_int_operand" "")
6797 (match_operand:SI 2 "const_int_operand" "")
6798 (match_operand:SI 3 "const_int_operand" "")]
6799 "TARGET_32BIT"
6800{
6801 if (arm_gen_setmem (operands))
6802 DONE;
6803
6804 FAIL;
6805})
6806
6807
9c08d1fa 6808;; Move a block of memory if it is word aligned and MORE than 2 words long.
6809;; We could let this apply for blocks of less than this, but it clobbers so
6810;; many registers that there is then probably a better way.
6811
008c057d 6812(define_expand "movmemqi"
34191dd1 6813 [(match_operand:BLK 0 "general_operand" "")
6814 (match_operand:BLK 1 "general_operand" "")
6815 (match_operand:SI 2 "const_int_operand" "")
6816 (match_operand:SI 3 "const_int_operand" "")]
ae51a965 6817 ""
9c08d1fa 6818 "
25f905c2 6819 if (TARGET_32BIT)
cffb2a26 6820 {
ae51a965 6821 if (TARGET_LDRD && current_tune->prefer_ldrd_strd
6822 && !optimize_function_for_size_p (cfun))
6823 {
6824 if (gen_movmem_ldrd_strd (operands))
6825 DONE;
6826 FAIL;
6827 }
6828
008c057d 6829 if (arm_gen_movmemqi (operands))
cffb2a26 6830 DONE;
6831 FAIL;
6832 }
25f905c2 6833 else /* TARGET_THUMB1 */
cffb2a26 6834 {
6835 if ( INTVAL (operands[3]) != 4
6836 || INTVAL (operands[2]) > 48)
6837 FAIL;
6838
008c057d 6839 thumb_expand_movmemqi (operands);
cffb2a26 6840 DONE;
6841 }
6842 "
6843)
9c08d1fa 6844\f
b11cae9e 6845
341940e8 6846;; Compare & branch insns
8d232dc7 6847;; The range calculations are based as follows:
341940e8 6848;; For forward branches, the address calculation returns the address of
6849;; the next instruction. This is 2 beyond the branch instruction.
6850;; For backward branches, the address calculation returns the address of
6851;; the first instruction in this pattern (cmp). This is 2 before the branch
6852;; instruction for the shortest sequence, and 4 before the branch instruction
6853;; if we have to jump around an unconditional branch.
6854;; To the basic branch range the PC offset must be added (this is +4).
6855;; So for forward branches we have
6856;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
6857;; And for backward branches we have
6858;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
6859;;
6860;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
6861;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
cffb2a26 6862
aeac46d4 6863(define_expand "cbranchsi4"
6864 [(set (pc) (if_then_else
aa06947a 6865 (match_operator 0 "expandable_comparison_operator"
aeac46d4 6866 [(match_operand:SI 1 "s_register_operand" "")
6867 (match_operand:SI 2 "nonmemory_operand" "")])
6868 (label_ref (match_operand 3 "" ""))
6869 (pc)))]
f9aa4160 6870 "TARGET_EITHER"
aeac46d4 6871 "
74f4459c 6872 if (!TARGET_THUMB1)
6873 {
f9aa4160 6874 if (!arm_validize_comparison (&operands[0], &operands[1], &operands[2]))
6875 FAIL;
74f4459c 6876 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6877 operands[3]));
6878 DONE;
6879 }
25f905c2 6880 if (thumb1_cmpneg_operand (operands[2], SImode))
aeac46d4 6881 {
6882 emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
6883 operands[3], operands[0]));
6884 DONE;
6885 }
25f905c2 6886 if (!thumb1_cmp_operand (operands[2], SImode))
aeac46d4 6887 operands[2] = force_reg (SImode, operands[2]);
6888 ")
6889
74f4459c 6890(define_expand "cbranchsf4"
6891 [(set (pc) (if_then_else
aa06947a 6892 (match_operator 0 "expandable_comparison_operator"
74f4459c 6893 [(match_operand:SF 1 "s_register_operand" "")
6894 (match_operand:SF 2 "arm_float_compare_operand" "")])
6895 (label_ref (match_operand 3 "" ""))
6896 (pc)))]
6897 "TARGET_32BIT && TARGET_HARD_FLOAT"
6898 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6899 operands[3])); DONE;"
6900)
6901
6902(define_expand "cbranchdf4"
6903 [(set (pc) (if_then_else
aa06947a 6904 (match_operator 0 "expandable_comparison_operator"
74f4459c 6905 [(match_operand:DF 1 "s_register_operand" "")
6906 (match_operand:DF 2 "arm_float_compare_operand" "")])
6907 (label_ref (match_operand 3 "" ""))
6908 (pc)))]
a50d7267 6909 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
74f4459c 6910 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6911 operands[3])); DONE;"
6912)
6913
74f4459c 6914(define_expand "cbranchdi4"
6915 [(set (pc) (if_then_else
aa06947a 6916 (match_operator 0 "expandable_comparison_operator"
b8eae306 6917 [(match_operand:DI 1 "s_register_operand" "")
a8045a4f 6918 (match_operand:DI 2 "cmpdi_operand" "")])
74f4459c 6919 (label_ref (match_operand 3 "" ""))
6920 (pc)))]
a8045a4f 6921 "TARGET_32BIT"
6922 "{
0438d37f 6923 if (!arm_validize_comparison (&operands[0], &operands[1], &operands[2]))
f9aa4160 6924 FAIL;
6925 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
a8045a4f 6926 operands[3]));
6927 DONE;
6928 }"
74f4459c 6929)
6930
9c08d1fa 6931;; Comparison and test insns
6932
cffb2a26 6933(define_insn "*arm_cmpsi_insn"
bd5b4116 6934 [(set (reg:CC CC_REGNUM)
f9f234ec 6935 (compare:CC (match_operand:SI 0 "s_register_operand" "l,r,r,r,r")
6936 (match_operand:SI 1 "arm_add_operand" "Py,r,r,I,L")))]
25f905c2 6937 "TARGET_32BIT"
5565501b 6938 "@
a6864a24 6939 cmp%?\\t%0, %1
6940 cmp%?\\t%0, %1
aea4c774 6941 cmp%?\\t%0, %1
f9f234ec 6942 cmp%?\\t%0, %1
aea4c774 6943 cmn%?\\t%0, #%n1"
a6864a24 6944 [(set_attr "conds" "set")
f9f234ec 6945 (set_attr "arch" "t2,t2,any,any,any")
6946 (set_attr "length" "2,2,4,4,4")
65f68e55 6947 (set_attr "predicable" "yes")
f9f234ec 6948 (set_attr "predicable_short_it" "yes,yes,yes,no,no")
112eda6f 6949 (set_attr "type" "alus_imm,alus_sreg,alus_sreg,alus_imm,alus_imm")]
cffb2a26 6950)
b11cae9e 6951
d5d4dc8d 6952(define_insn "*cmpsi_shiftsi"
bd5b4116 6953 [(set (reg:CC CC_REGNUM)
d82e788e 6954 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r,r")
cffb2a26 6955 (match_operator:SI 3 "shift_operator"
d82e788e 6956 [(match_operand:SI 1 "s_register_operand" "r,r,r")
6957 (match_operand:SI 2 "shift_amount_operand" "M,r,M")])))]
d5d4dc8d 6958 "TARGET_32BIT"
f9f234ec 6959 "cmp\\t%0, %1%S3"
344495ea 6960 [(set_attr "conds" "set")
331beb1a 6961 (set_attr "shift" "1")
d82e788e 6962 (set_attr "arch" "32,a,a")
282b4c75 6963 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
b11cae9e 6964
d5d4dc8d 6965(define_insn "*cmpsi_shiftsi_swp"
bd5b4116 6966 [(set (reg:CC_SWP CC_REGNUM)
aea4c774 6967 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
d82e788e 6968 [(match_operand:SI 1 "s_register_operand" "r,r,r")
6969 (match_operand:SI 2 "shift_amount_operand" "M,r,M")])
6970 (match_operand:SI 0 "s_register_operand" "r,r,r")))]
d5d4dc8d 6971 "TARGET_32BIT"
aea4c774 6972 "cmp%?\\t%0, %1%S3"
344495ea 6973 [(set_attr "conds" "set")
331beb1a 6974 (set_attr "shift" "1")
d82e788e 6975 (set_attr "arch" "32,a,a")
282b4c75 6976 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
b11cae9e 6977
25f905c2 6978(define_insn "*arm_cmpsi_negshiftsi_si"
aed179ae 6979 [(set (reg:CC_Z CC_REGNUM)
6980 (compare:CC_Z
6981 (neg:SI (match_operator:SI 1 "shift_operator"
6982 [(match_operand:SI 2 "s_register_operand" "r")
6983 (match_operand:SI 3 "reg_or_int_operand" "rM")]))
6984 (match_operand:SI 0 "s_register_operand" "r")))]
cffb2a26 6985 "TARGET_ARM"
aed179ae 6986 "cmn%?\\t%0, %2%S1"
344495ea 6987 [(set_attr "conds" "set")
aed179ae 6988 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
d82e788e 6989 (const_string "alus_shift_imm")
6990 (const_string "alus_shift_reg")))
596e5e8f 6991 (set_attr "predicable" "yes")]
0d66636f 6992)
b11cae9e 6993
a8045a4f 6994;; DImode comparisons. The generic code generates branches that
6995;; if-conversion can not reduce to a conditional compare, so we do
6996;; that directly.
6997
ba6a3b2f 6998(define_insn_and_split "*arm_cmpdi_insn"
a8045a4f 6999 [(set (reg:CC_NCV CC_REGNUM)
7000 (compare:CC_NCV (match_operand:DI 0 "s_register_operand" "r")
7001 (match_operand:DI 1 "arm_di_operand" "rDi")))
7002 (clobber (match_scratch:SI 2 "=r"))]
b805622c 7003 "TARGET_32BIT"
ba6a3b2f 7004 "#" ; "cmp\\t%Q0, %Q1\;sbcs\\t%2, %R0, %R1"
7005 "&& reload_completed"
7006 [(set (reg:CC CC_REGNUM)
7007 (compare:CC (match_dup 0) (match_dup 1)))
7008 (parallel [(set (reg:CC CC_REGNUM)
7009 (compare:CC (match_dup 3) (match_dup 4)))
7010 (set (match_dup 2)
7011 (minus:SI (match_dup 5)
7012 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))])]
7013 {
7014 operands[3] = gen_highpart (SImode, operands[0]);
7015 operands[0] = gen_lowpart (SImode, operands[0]);
7016 if (CONST_INT_P (operands[1]))
7017 {
7018 operands[4] = GEN_INT (~INTVAL (gen_highpart_mode (SImode,
7019 DImode,
7020 operands[1])));
7021 operands[5] = gen_rtx_PLUS (SImode, operands[3], operands[4]);
7022 }
7023 else
7024 {
7025 operands[4] = gen_highpart (SImode, operands[1]);
7026 operands[5] = gen_rtx_MINUS (SImode, operands[3], operands[4]);
7027 }
7028 operands[1] = gen_lowpart (SImode, operands[1]);
7029 operands[2] = gen_lowpart (SImode, operands[2]);
7030 }
a8045a4f 7031 [(set_attr "conds" "set")
1b7da4ac 7032 (set_attr "length" "8")
7033 (set_attr "type" "multiple")]
a8045a4f 7034)
7035
ba6a3b2f 7036(define_insn_and_split "*arm_cmpdi_unsigned"
a8045a4f 7037 [(set (reg:CC_CZ CC_REGNUM)
1a86364b 7038 (compare:CC_CZ (match_operand:DI 0 "s_register_operand" "l,r,r,r")
7039 (match_operand:DI 1 "arm_di_operand" "Py,r,Di,rDi")))]
7c36fe71 7040
48a98053 7041 "TARGET_32BIT"
ba6a3b2f 7042 "#" ; "cmp\\t%R0, %R1\;it eq\;cmpeq\\t%Q0, %Q1"
7043 "&& reload_completed"
7044 [(set (reg:CC CC_REGNUM)
7045 (compare:CC (match_dup 2) (match_dup 3)))
7046 (cond_exec (eq:SI (reg:CC CC_REGNUM) (const_int 0))
7047 (set (reg:CC CC_REGNUM)
7048 (compare:CC (match_dup 0) (match_dup 1))))]
7049 {
7050 operands[2] = gen_highpart (SImode, operands[0]);
7051 operands[0] = gen_lowpart (SImode, operands[0]);
7052 if (CONST_INT_P (operands[1]))
7053 operands[3] = gen_highpart_mode (SImode, DImode, operands[1]);
7054 else
7055 operands[3] = gen_highpart (SImode, operands[1]);
7056 operands[1] = gen_lowpart (SImode, operands[1]);
7057 }
a8045a4f 7058 [(set_attr "conds" "set")
1a86364b 7059 (set_attr "enabled_for_depr_it" "yes,yes,no,*")
7060 (set_attr "arch" "t2,t2,t2,a")
7061 (set_attr "length" "6,6,10,8")
1b7da4ac 7062 (set_attr "type" "multiple")]
a8045a4f 7063)
7064
7065(define_insn "*arm_cmpdi_zero"
7066 [(set (reg:CC_Z CC_REGNUM)
7067 (compare:CC_Z (match_operand:DI 0 "s_register_operand" "r")
7068 (const_int 0)))
7069 (clobber (match_scratch:SI 1 "=r"))]
7070 "TARGET_32BIT"
3ef90e77 7071 "orrs%?\\t%1, %Q0, %R0"
1b7da4ac 7072 [(set_attr "conds" "set")
7073 (set_attr "type" "logics_reg")]
a8045a4f 7074)
7075
9c08d1fa 7076; This insn allows redundant compares to be removed by cse, nothing should
7077; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
7078; is deleted later on. The match_dup will match the mode here, so that
7079; mode changes of the condition codes aren't lost by this even though we don't
7080; specify what they are.
7081
8a18b90c 7082(define_insn "*deleted_compare"
9c08d1fa 7083 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
25f905c2 7084 "TARGET_32BIT"
40dbec34 7085 "\\t%@ deleted compare"
cffb2a26 7086 [(set_attr "conds" "set")
1b7da4ac 7087 (set_attr "length" "0")
7088 (set_attr "type" "no_insn")]
cffb2a26 7089)
9c08d1fa 7090
7091\f
7092;; Conditional branch insns
7093
74f4459c 7094(define_expand "cbranch_cc"
9c08d1fa 7095 [(set (pc)
74f4459c 7096 (if_then_else (match_operator 0 "" [(match_operand 1 "" "")
7097 (match_operand 2 "" "")])
7098 (label_ref (match_operand 3 "" ""))
9c08d1fa 7099 (pc)))]
25f905c2 7100 "TARGET_32BIT"
74f4459c 7101 "operands[1] = arm_gen_compare_reg (GET_CODE (operands[0]),
e1b93706 7102 operands[1], operands[2], NULL_RTX);
74f4459c 7103 operands[2] = const0_rtx;"
8fa3ba89 7104)
7105
7106;;
7107;; Patterns to match conditional branch insns.
7108;;
7109
ffcc986d 7110(define_insn "arm_cond_branch"
9c08d1fa 7111 [(set (pc)
8fa3ba89 7112 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 7113 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 7114 (label_ref (match_operand 0 "" ""))
7115 (pc)))]
25f905c2 7116 "TARGET_32BIT"
d75350ce 7117 "*
9c08d1fa 7118 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 7119 {
7120 arm_ccfsm_state += 2;
7121 return \"\";
7122 }
e2348bcb 7123 return \"b%d1\\t%l0\";
cffb2a26 7124 "
a2cd141b 7125 [(set_attr "conds" "use")
a6864a24 7126 (set_attr "type" "branch")
7127 (set (attr "length")
7128 (if_then_else
0bf497f5 7129 (and (match_test "TARGET_THUMB2")
a6864a24 7130 (and (ge (minus (match_dup 0) (pc)) (const_int -250))
7131 (le (minus (match_dup 0) (pc)) (const_int 256))))
7132 (const_int 2)
7133 (const_int 4)))]
cffb2a26 7134)
d75350ce 7135
cffb2a26 7136(define_insn "*arm_cond_branch_reversed"
9c08d1fa 7137 [(set (pc)
8fa3ba89 7138 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 7139 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 7140 (pc)
7141 (label_ref (match_operand 0 "" ""))))]
25f905c2 7142 "TARGET_32BIT"
d75350ce 7143 "*
9c08d1fa 7144 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 7145 {
7146 arm_ccfsm_state += 2;
7147 return \"\";
7148 }
e2348bcb 7149 return \"b%D1\\t%l0\";
cffb2a26 7150 "
a2cd141b 7151 [(set_attr "conds" "use")
a6864a24 7152 (set_attr "type" "branch")
7153 (set (attr "length")
7154 (if_then_else
0bf497f5 7155 (and (match_test "TARGET_THUMB2")
a6864a24 7156 (and (ge (minus (match_dup 0) (pc)) (const_int -250))
7157 (le (minus (match_dup 0) (pc)) (const_int 256))))
7158 (const_int 2)
7159 (const_int 4)))]
cffb2a26 7160)
7161
b11cae9e 7162\f
9c08d1fa 7163
7164; scc insns
7165
74f4459c 7166(define_expand "cstore_cc"
7db9af5d 7167 [(set (match_operand:SI 0 "s_register_operand" "")
74f4459c 7168 (match_operator:SI 1 "" [(match_operand 2 "" "")
7169 (match_operand 3 "" "")]))]
25f905c2 7170 "TARGET_32BIT"
74f4459c 7171 "operands[2] = arm_gen_compare_reg (GET_CODE (operands[1]),
e1b93706 7172 operands[2], operands[3], NULL_RTX);
74f4459c 7173 operands[3] = const0_rtx;"
8fa3ba89 7174)
7175
a3b84066 7176(define_insn_and_split "*mov_scc"
9c08d1fa 7177 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7178 (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7179 [(match_operand 2 "cc_register" "") (const_int 0)]))]
cffb2a26 7180 "TARGET_ARM"
a3b84066 7181 "#" ; "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
7182 "TARGET_ARM"
7183 [(set (match_dup 0)
7184 (if_then_else:SI (match_dup 1)
7185 (const_int 1)
7186 (const_int 0)))]
7187 ""
cffb2a26 7188 [(set_attr "conds" "use")
1b7da4ac 7189 (set_attr "length" "8")
7190 (set_attr "type" "multiple")]
cffb2a26 7191)
9c08d1fa 7192
a3b84066 7193(define_insn_and_split "*mov_negscc"
9c08d1fa 7194 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7195 (neg:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7196 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 7197 "TARGET_ARM"
a3b84066 7198 "#" ; "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
7199 "TARGET_ARM"
7200 [(set (match_dup 0)
7201 (if_then_else:SI (match_dup 1)
7202 (match_dup 3)
7203 (const_int 0)))]
7204 {
7205 operands[3] = GEN_INT (~0);
7206 }
cffb2a26 7207 [(set_attr "conds" "use")
1b7da4ac 7208 (set_attr "length" "8")
7209 (set_attr "type" "multiple")]
cffb2a26 7210)
9c08d1fa 7211
a3b84066 7212(define_insn_and_split "*mov_notscc"
9c08d1fa 7213 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7214 (not:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7215 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 7216 "TARGET_ARM"
a3b84066 7217 "#" ; "mvn%D1\\t%0, #0\;mvn%d1\\t%0, #1"
7218 "TARGET_ARM"
7219 [(set (match_dup 0)
7220 (if_then_else:SI (match_dup 1)
7221 (match_dup 3)
7222 (match_dup 4)))]
7223 {
7224 operands[3] = GEN_INT (~1);
7225 operands[4] = GEN_INT (~0);
7226 }
cffb2a26 7227 [(set_attr "conds" "use")
1b7da4ac 7228 (set_attr "length" "8")
7229 (set_attr "type" "multiple")]
cffb2a26 7230)
9c08d1fa 7231
595d88b5 7232(define_expand "cstoresi4"
7233 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 7234 (match_operator:SI 1 "expandable_comparison_operator"
595d88b5 7235 [(match_operand:SI 2 "s_register_operand" "")
7236 (match_operand:SI 3 "reg_or_int_operand" "")]))]
74f4459c 7237 "TARGET_32BIT || TARGET_THUMB1"
595d88b5 7238 "{
7239 rtx op3, scratch, scratch2;
7240
74f4459c 7241 if (!TARGET_THUMB1)
7242 {
7243 if (!arm_add_operand (operands[3], SImode))
7244 operands[3] = force_reg (SImode, operands[3]);
7245 emit_insn (gen_cstore_cc (operands[0], operands[1],
7246 operands[2], operands[3]));
7247 DONE;
7248 }
7249
595d88b5 7250 if (operands[3] == const0_rtx)
7251 {
7252 switch (GET_CODE (operands[1]))
7253 {
7254 case EQ:
25f905c2 7255 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], operands[2]));
595d88b5 7256 break;
7257
7258 case NE:
25f905c2 7259 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], operands[2]));
595d88b5 7260 break;
7261
7262 case LE:
7263 scratch = expand_binop (SImode, add_optab, operands[2], constm1_rtx,
7264 NULL_RTX, 0, OPTAB_WIDEN);
7265 scratch = expand_binop (SImode, ior_optab, operands[2], scratch,
7266 NULL_RTX, 0, OPTAB_WIDEN);
7267 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7268 operands[0], 1, OPTAB_WIDEN);
7269 break;
7270
7271 case GE:
7272 scratch = expand_unop (SImode, one_cmpl_optab, operands[2],
7273 NULL_RTX, 1);
7274 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7275 NULL_RTX, 1, OPTAB_WIDEN);
7276 break;
7277
7278 case GT:
7279 scratch = expand_binop (SImode, ashr_optab, operands[2],
7280 GEN_INT (31), NULL_RTX, 0, OPTAB_WIDEN);
7281 scratch = expand_binop (SImode, sub_optab, scratch, operands[2],
7282 NULL_RTX, 0, OPTAB_WIDEN);
7283 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31), operands[0],
7284 0, OPTAB_WIDEN);
7285 break;
7286
7287 /* LT is handled by generic code. No need for unsigned with 0. */
7288 default:
7289 FAIL;
7290 }
7291 DONE;
7292 }
7293
7294 switch (GET_CODE (operands[1]))
7295 {
7296 case EQ:
7297 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7298 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7299 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], scratch));
595d88b5 7300 break;
7301
7302 case NE:
7303 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7304 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7305 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], scratch));
595d88b5 7306 break;
7307
7308 case LE:
7309 op3 = force_reg (SImode, operands[3]);
7310
7311 scratch = expand_binop (SImode, lshr_optab, operands[2], GEN_INT (31),
7312 NULL_RTX, 1, OPTAB_WIDEN);
7313 scratch2 = expand_binop (SImode, ashr_optab, op3, GEN_INT (31),
7314 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7315 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
595d88b5 7316 op3, operands[2]));
7317 break;
7318
7319 case GE:
7320 op3 = operands[3];
25f905c2 7321 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7322 op3 = force_reg (SImode, op3);
7323 scratch = expand_binop (SImode, ashr_optab, operands[2], GEN_INT (31),
7324 NULL_RTX, 0, OPTAB_WIDEN);
7325 scratch2 = expand_binop (SImode, lshr_optab, op3, GEN_INT (31),
7326 NULL_RTX, 1, OPTAB_WIDEN);
25f905c2 7327 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
595d88b5 7328 operands[2], op3));
7329 break;
7330
7331 case LEU:
7332 op3 = force_reg (SImode, operands[3]);
7333 scratch = force_reg (SImode, const0_rtx);
25f905c2 7334 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
595d88b5 7335 op3, operands[2]));
7336 break;
7337
7338 case GEU:
7339 op3 = operands[3];
25f905c2 7340 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7341 op3 = force_reg (SImode, op3);
7342 scratch = force_reg (SImode, const0_rtx);
25f905c2 7343 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
595d88b5 7344 operands[2], op3));
7345 break;
7346
7347 case LTU:
7348 op3 = operands[3];
25f905c2 7349 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7350 op3 = force_reg (SImode, op3);
7351 scratch = gen_reg_rtx (SImode);
408b7ae5 7352 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], operands[2], op3));
595d88b5 7353 break;
7354
7355 case GTU:
7356 op3 = force_reg (SImode, operands[3]);
7357 scratch = gen_reg_rtx (SImode);
408b7ae5 7358 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], op3, operands[2]));
595d88b5 7359 break;
7360
7361 /* No good sequences for GT, LT. */
7362 default:
7363 FAIL;
7364 }
7365 DONE;
7366}")
7367
74f4459c 7368(define_expand "cstoresf4"
7369 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 7370 (match_operator:SI 1 "expandable_comparison_operator"
74f4459c 7371 [(match_operand:SF 2 "s_register_operand" "")
7372 (match_operand:SF 3 "arm_float_compare_operand" "")]))]
7373 "TARGET_32BIT && TARGET_HARD_FLOAT"
7374 "emit_insn (gen_cstore_cc (operands[0], operands[1],
7375 operands[2], operands[3])); DONE;"
7376)
7377
7378(define_expand "cstoredf4"
7379 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 7380 (match_operator:SI 1 "expandable_comparison_operator"
74f4459c 7381 [(match_operand:DF 2 "s_register_operand" "")
7382 (match_operand:DF 3 "arm_float_compare_operand" "")]))]
d63ed457 7383 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
74f4459c 7384 "emit_insn (gen_cstore_cc (operands[0], operands[1],
7385 operands[2], operands[3])); DONE;"
7386)
7387
74f4459c 7388(define_expand "cstoredi4"
7389 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 7390 (match_operator:SI 1 "expandable_comparison_operator"
b8eae306 7391 [(match_operand:DI 2 "s_register_operand" "")
a8045a4f 7392 (match_operand:DI 3 "cmpdi_operand" "")]))]
7393 "TARGET_32BIT"
7394 "{
f9aa4160 7395 if (!arm_validize_comparison (&operands[1],
7396 &operands[2],
7397 &operands[3]))
7398 FAIL;
7399 emit_insn (gen_cstore_cc (operands[0], operands[1], operands[2],
a8045a4f 7400 operands[3]));
7401 DONE;
7402 }"
74f4459c 7403)
7404
9c08d1fa 7405\f
39b5e676 7406;; Conditional move insns
7407
7408(define_expand "movsicc"
8a18b90c 7409 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 7410 (if_then_else:SI (match_operand 1 "expandable_comparison_operator" "")
aea4c774 7411 (match_operand:SI 2 "arm_not_operand" "")
8a18b90c 7412 (match_operand:SI 3 "arm_not_operand" "")))]
25f905c2 7413 "TARGET_32BIT"
39b5e676 7414 "
215b30b3 7415 {
f9aa4160 7416 enum rtx_code code;
278b301d 7417 rtx ccreg;
7418
f9aa4160 7419 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
7420 &XEXP (operands[1], 1)))
278b301d 7421 FAIL;
f9aa4160 7422
7423 code = GET_CODE (operands[1]);
74f4459c 7424 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
e1b93706 7425 XEXP (operands[1], 1), NULL_RTX);
29bb088d 7426 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7427 }"
7428)
39b5e676 7429
7430(define_expand "movsfcc"
8a18b90c 7431 [(set (match_operand:SF 0 "s_register_operand" "")
4df97ffc 7432 (if_then_else:SF (match_operand 1 "arm_cond_move_operator" "")
8a18b90c 7433 (match_operand:SF 2 "s_register_operand" "")
d86c91f6 7434 (match_operand:SF 3 "s_register_operand" "")))]
19f6bf8d 7435 "TARGET_32BIT && TARGET_HARD_FLOAT"
39b5e676 7436 "
215b30b3 7437 {
7438 enum rtx_code code = GET_CODE (operands[1]);
7439 rtx ccreg;
f082f1c4 7440
f9aa4160 7441 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
7442 &XEXP (operands[1], 1)))
7443 FAIL;
39b5e676 7444
f9aa4160 7445 code = GET_CODE (operands[1]);
74f4459c 7446 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
e1b93706 7447 XEXP (operands[1], 1), NULL_RTX);
29bb088d 7448 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7449 }"
7450)
39b5e676 7451
7452(define_expand "movdfcc"
8a18b90c 7453 [(set (match_operand:DF 0 "s_register_operand" "")
4df97ffc 7454 (if_then_else:DF (match_operand 1 "arm_cond_move_operator" "")
8a18b90c 7455 (match_operand:DF 2 "s_register_operand" "")
d86c91f6 7456 (match_operand:DF 3 "s_register_operand" "")))]
994606f8 7457 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
39b5e676 7458 "
215b30b3 7459 {
7460 enum rtx_code code = GET_CODE (operands[1]);
278b301d 7461 rtx ccreg;
39b5e676 7462
f9aa4160 7463 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
7464 &XEXP (operands[1], 1)))
7465 FAIL;
7466 code = GET_CODE (operands[1]);
74f4459c 7467 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
e1b93706 7468 XEXP (operands[1], 1), NULL_RTX);
29bb088d 7469 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7470 }"
7471)
39b5e676 7472
91cb50d2 7473(define_insn "*cmov<mode>"
7474 [(set (match_operand:SDF 0 "s_register_operand" "=<F_constraint>")
7475 (if_then_else:SDF (match_operator 1 "arm_vsel_comparison_operator"
7476 [(match_operand 2 "cc_register" "") (const_int 0)])
7477 (match_operand:SDF 3 "s_register_operand"
7478 "<F_constraint>")
7479 (match_operand:SDF 4 "s_register_operand"
7480 "<F_constraint>")))]
7481 "TARGET_HARD_FLOAT && TARGET_FPU_ARMV8 <vfp_double_cond>"
7482 "*
7483 {
7484 enum arm_cond_code code = maybe_get_arm_condition_code (operands[1]);
7485 switch (code)
7486 {
7487 case ARM_GE:
7488 case ARM_GT:
7489 case ARM_EQ:
7490 case ARM_VS:
7491 return \"vsel%d1.<V_if_elem>\\t%<V_reg>0, %<V_reg>3, %<V_reg>4\";
7492 case ARM_LT:
7493 case ARM_LE:
7494 case ARM_NE:
7495 case ARM_VC:
7496 return \"vsel%D1.<V_if_elem>\\t%<V_reg>0, %<V_reg>4, %<V_reg>3\";
7497 default:
7498 gcc_unreachable ();
7499 }
7500 return \"\";
7501 }"
7502 [(set_attr "conds" "use")
6664d308 7503 (set_attr "type" "fcsel")]
91cb50d2 7504)
7505
190efb17 7506(define_insn_and_split "*movsicc_insn"
f082f1c4 7507 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
8a18b90c 7508 (if_then_else:SI
8fa3ba89 7509 (match_operator 3 "arm_comparison_operator"
8a18b90c 7510 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 7511 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
7512 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
cffb2a26 7513 "TARGET_ARM"
39b5e676 7514 "@
8a18b90c 7515 mov%D3\\t%0, %2
7516 mvn%D3\\t%0, #%B2
f082f1c4 7517 mov%d3\\t%0, %1
7518 mvn%d3\\t%0, #%B1
190efb17 7519 #
7520 #
7521 #
7522 #"
7523 ; alt4: mov%d3\\t%0, %1\;mov%D3\\t%0, %2
7524 ; alt5: mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
7525 ; alt6: mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
7526 ; alt7: mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
7527 "&& reload_completed"
7528 [(const_int 0)]
7529 {
7530 enum rtx_code rev_code;
3754d046 7531 machine_mode mode;
190efb17 7532 rtx rev_cond;
7533
7534 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
7535 operands[3],
d1f9b275 7536 gen_rtx_SET (operands[0], operands[1])));
190efb17 7537
7538 rev_code = GET_CODE (operands[3]);
7539 mode = GET_MODE (operands[4]);
7540 if (mode == CCFPmode || mode == CCFPEmode)
7541 rev_code = reverse_condition_maybe_unordered (rev_code);
7542 else
7543 rev_code = reverse_condition (rev_code);
7544
7545 rev_cond = gen_rtx_fmt_ee (rev_code,
7546 VOIDmode,
7547 operands[4],
7548 const0_rtx);
7549 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
7550 rev_cond,
d1f9b275 7551 gen_rtx_SET (operands[0], operands[2])));
190efb17 7552 DONE;
7553 }
f082f1c4 7554 [(set_attr "length" "4,4,4,4,8,8,8,8")
d2a518d1 7555 (set_attr "conds" "use")
65f68e55 7556 (set_attr_alternative "type"
7557 [(if_then_else (match_operand 2 "const_int_operand" "")
1aed5204 7558 (const_string "mov_imm")
7559 (const_string "mov_reg"))
7560 (const_string "mvn_imm")
65f68e55 7561 (if_then_else (match_operand 1 "const_int_operand" "")
1aed5204 7562 (const_string "mov_imm")
7563 (const_string "mov_reg"))
7564 (const_string "mvn_imm")
282b4c75 7565 (const_string "multiple")
7566 (const_string "multiple")
7567 (const_string "multiple")
7568 (const_string "multiple")])]
215b30b3 7569)
39b5e676 7570
39b5e676 7571(define_insn "*movsfcc_soft_insn"
f082f1c4 7572 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
8fa3ba89 7573 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
8a18b90c 7574 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 7575 (match_operand:SF 1 "s_register_operand" "0,r")
7576 (match_operand:SF 2 "s_register_operand" "r,0")))]
cffb2a26 7577 "TARGET_ARM && TARGET_SOFT_FLOAT"
f082f1c4 7578 "@
7579 mov%D3\\t%0, %2
7580 mov%d3\\t%0, %1"
d2a518d1 7581 [(set_attr "conds" "use")
1aed5204 7582 (set_attr "type" "mov_reg")]
8fa3ba89 7583)
39b5e676 7584
39b5e676 7585\f
9c08d1fa 7586;; Jump and linkage insns
7587
cffb2a26 7588(define_expand "jump"
9c08d1fa 7589 [(set (pc)
7590 (label_ref (match_operand 0 "" "")))]
cffb2a26 7591 "TARGET_EITHER"
9c08d1fa 7592 ""
cffb2a26 7593)
7594
7595(define_insn "*arm_jump"
7596 [(set (pc)
7597 (label_ref (match_operand 0 "" "")))]
25f905c2 7598 "TARGET_32BIT"
9c08d1fa 7599 "*
0d66636f 7600 {
7601 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7602 {
7603 arm_ccfsm_state += 2;
7604 return \"\";
7605 }
7606 return \"b%?\\t%l0\";
7607 }
7608 "
a6864a24 7609 [(set_attr "predicable" "yes")
7610 (set (attr "length")
7611 (if_then_else
0bf497f5 7612 (and (match_test "TARGET_THUMB2")
a6864a24 7613 (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
7614 (le (minus (match_dup 0) (pc)) (const_int 2048))))
7615 (const_int 2)
1b7da4ac 7616 (const_int 4)))
7617 (set_attr "type" "branch")]
0d66636f 7618)
9c08d1fa 7619
d3373b54 7620(define_expand "call"
7621 [(parallel [(call (match_operand 0 "memory_operand" "")
7622 (match_operand 1 "general_operand" ""))
cffb2a26 7623 (use (match_operand 2 "" ""))
bd5b4116 7624 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 7625 "TARGET_EITHER"
6c4c2133 7626 "
7627 {
bac7fc85 7628 rtx callee, pat;
bbe777ea 7629
bbe777ea 7630 /* In an untyped call, we can get NULL for operand 2. */
7631 if (operands[2] == NULL_RTX)
7632 operands[2] = const0_rtx;
7633
de55252a 7634 /* Decide if we should generate indirect calls by loading the
85c36fd1 7635 32-bit address of the callee into a register before performing the
de55252a 7636 branch and link. */
7637 callee = XEXP (operands[0], 0);
7638 if (GET_CODE (callee) == SYMBOL_REF
7639 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
7640 : !REG_P (callee))
bbe777ea 7641 XEXP (operands[0], 0) = force_reg (Pmode, callee);
bac7fc85 7642
7643 pat = gen_call_internal (operands[0], operands[1], operands[2]);
ca373797 7644 arm_emit_call_insn (pat, XEXP (operands[0], 0), false);
bac7fc85 7645 DONE;
6c4c2133 7646 }"
7647)
d3373b54 7648
bac7fc85 7649(define_expand "call_internal"
7650 [(parallel [(call (match_operand 0 "memory_operand" "")
7651 (match_operand 1 "general_operand" ""))
7652 (use (match_operand 2 "" ""))
7653 (clobber (reg:SI LR_REGNUM))])])
7654
f1039640 7655(define_insn "*call_reg_armv5"
d3373b54 7656 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
cffb2a26 7657 (match_operand 1 "" ""))
7658 (use (match_operand 2 "" ""))
bd5b4116 7659 (clobber (reg:SI LR_REGNUM))]
33ae7c4b 7660 "TARGET_ARM && arm_arch5 && !SIBLING_CALL_P (insn)"
f1039640 7661 "blx%?\\t%0"
7662 [(set_attr "type" "call")]
7663)
7664
7665(define_insn "*call_reg_arm"
7666 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7667 (match_operand 1 "" ""))
7668 (use (match_operand 2 "" ""))
7669 (clobber (reg:SI LR_REGNUM))]
33ae7c4b 7670 "TARGET_ARM && !arm_arch5 && !SIBLING_CALL_P (insn)"
9c08d1fa 7671 "*
5565501b 7672 return output_call (operands);
cffb2a26 7673 "
7674 ;; length is worst case, normally it is only two
7675 [(set_attr "length" "12")
7676 (set_attr "type" "call")]
7677)
9c08d1fa 7678
89504fc1 7679
d3373b54 7680(define_expand "call_value"
e0698af7 7681 [(parallel [(set (match_operand 0 "" "")
7682 (call (match_operand 1 "memory_operand" "")
7683 (match_operand 2 "general_operand" "")))
cffb2a26 7684 (use (match_operand 3 "" ""))
bd5b4116 7685 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 7686 "TARGET_EITHER"
6c4c2133 7687 "
7688 {
bac7fc85 7689 rtx pat, callee;
bbe777ea 7690
7691 /* In an untyped call, we can get NULL for operand 2. */
7692 if (operands[3] == 0)
7693 operands[3] = const0_rtx;
7694
de55252a 7695 /* Decide if we should generate indirect calls by loading the
7696 32-bit address of the callee into a register before performing the
7697 branch and link. */
7698 callee = XEXP (operands[1], 0);
7699 if (GET_CODE (callee) == SYMBOL_REF
7700 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
7701 : !REG_P (callee))
78fe751b 7702 XEXP (operands[1], 0) = force_reg (Pmode, callee);
bac7fc85 7703
7704 pat = gen_call_value_internal (operands[0], operands[1],
7705 operands[2], operands[3]);
ca373797 7706 arm_emit_call_insn (pat, XEXP (operands[1], 0), false);
bac7fc85 7707 DONE;
6c4c2133 7708 }"
7709)
d3373b54 7710
bac7fc85 7711(define_expand "call_value_internal"
7712 [(parallel [(set (match_operand 0 "" "")
7713 (call (match_operand 1 "memory_operand" "")
7714 (match_operand 2 "general_operand" "")))
7715 (use (match_operand 3 "" ""))
7716 (clobber (reg:SI LR_REGNUM))])])
7717
f1039640 7718(define_insn "*call_value_reg_armv5"
27ed6835 7719 [(set (match_operand 0 "" "")
755eb2b4 7720 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
cffb2a26 7721 (match_operand 2 "" "")))
bbe777ea 7722 (use (match_operand 3 "" ""))
bd5b4116 7723 (clobber (reg:SI LR_REGNUM))]
33ae7c4b 7724 "TARGET_ARM && arm_arch5 && !SIBLING_CALL_P (insn)"
f1039640 7725 "blx%?\\t%1"
7726 [(set_attr "type" "call")]
7727)
7728
7729(define_insn "*call_value_reg_arm"
7730 [(set (match_operand 0 "" "")
7731 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7732 (match_operand 2 "" "")))
7733 (use (match_operand 3 "" ""))
7734 (clobber (reg:SI LR_REGNUM))]
33ae7c4b 7735 "TARGET_ARM && !arm_arch5 && !SIBLING_CALL_P (insn)"
9c08d1fa 7736 "*
215b30b3 7737 return output_call (&operands[1]);
cffb2a26 7738 "
7739 [(set_attr "length" "12")
7740 (set_attr "type" "call")]
7741)
9c08d1fa 7742
9c08d1fa 7743;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
7744;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
7745
f7fbdd4a 7746(define_insn "*call_symbol"
27ed6835 7747 [(call (mem:SI (match_operand:SI 0 "" ""))
cffb2a26 7748 (match_operand 1 "" ""))
bbe777ea 7749 (use (match_operand 2 "" ""))
bd5b4116 7750 (clobber (reg:SI LR_REGNUM))]
d68c2c10 7751 "TARGET_32BIT
33ae7c4b 7752 && !SIBLING_CALL_P (insn)
cffb2a26 7753 && (GET_CODE (operands[0]) == SYMBOL_REF)
de55252a 7754 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
6ebaa29d 7755 "*
7756 {
95f1e0d1 7757 rtx op = operands[0];
7758
7759 /* Switch mode now when possible. */
7760 if (SYMBOL_REF_DECL (op) && !TREE_PUBLIC (SYMBOL_REF_DECL (op))
7761 && arm_arch5 && arm_change_mode_p (SYMBOL_REF_DECL (op)))
7762 return NEED_PLT_RELOC ? \"blx%?\\t%a0(PLT)\" : \"blx%?\\t(%a0)\";
7763
55c1e470 7764 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
6ebaa29d 7765 }"
cffb2a26 7766 [(set_attr "type" "call")]
7767)
9c08d1fa 7768
f7fbdd4a 7769(define_insn "*call_value_symbol"
ccd90aaa 7770 [(set (match_operand 0 "" "")
27ed6835 7771 (call (mem:SI (match_operand:SI 1 "" ""))
dd6d7504 7772 (match_operand:SI 2 "" "")))
bbe777ea 7773 (use (match_operand 3 "" ""))
bd5b4116 7774 (clobber (reg:SI LR_REGNUM))]
d68c2c10 7775 "TARGET_32BIT
33ae7c4b 7776 && !SIBLING_CALL_P (insn)
cffb2a26 7777 && (GET_CODE (operands[1]) == SYMBOL_REF)
de55252a 7778 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
6ebaa29d 7779 "*
7780 {
95f1e0d1 7781 rtx op = operands[1];
7782
7783 /* Switch mode now when possible. */
7784 if (SYMBOL_REF_DECL (op) && !TREE_PUBLIC (SYMBOL_REF_DECL (op))
7785 && arm_arch5 && arm_change_mode_p (SYMBOL_REF_DECL (op)))
3f6b66fa 7786 return NEED_PLT_RELOC ? \"blx%?\\t%a1(PLT)\" : \"blx%?\\t(%a1)\";
95f1e0d1 7787
55c1e470 7788 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
6ebaa29d 7789 }"
cffb2a26 7790 [(set_attr "type" "call")]
7791)
7792
ca373797 7793(define_expand "sibcall_internal"
7794 [(parallel [(call (match_operand 0 "memory_operand" "")
7795 (match_operand 1 "general_operand" ""))
7796 (return)
7797 (use (match_operand 2 "" ""))])])
7798
1c494086 7799;; We may also be able to do sibcalls for Thumb, but it's much harder...
7800(define_expand "sibcall"
7801 [(parallel [(call (match_operand 0 "memory_operand" "")
7802 (match_operand 1 "general_operand" ""))
2ba80634 7803 (return)
7804 (use (match_operand 2 "" ""))])]
d68c2c10 7805 "TARGET_32BIT"
1c494086 7806 "
7807 {
ca373797 7808 rtx pat;
7809
3112c3f7 7810 if ((!REG_P (XEXP (operands[0], 0))
7811 && GET_CODE (XEXP (operands[0], 0)) != SYMBOL_REF)
7812 || (GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
7813 && arm_is_long_call_p (SYMBOL_REF_DECL (XEXP (operands[0], 0)))))
33ae7c4b 7814 XEXP (operands[0], 0) = force_reg (SImode, XEXP (operands[0], 0));
7815
1c494086 7816 if (operands[2] == NULL_RTX)
7817 operands[2] = const0_rtx;
ca373797 7818
7819 pat = gen_sibcall_internal (operands[0], operands[1], operands[2]);
7820 arm_emit_call_insn (pat, operands[0], true);
7821 DONE;
1c494086 7822 }"
7823)
7824
ca373797 7825(define_expand "sibcall_value_internal"
7826 [(parallel [(set (match_operand 0 "" "")
7827 (call (match_operand 1 "memory_operand" "")
7828 (match_operand 2 "general_operand" "")))
7829 (return)
7830 (use (match_operand 3 "" ""))])])
7831
1c494086 7832(define_expand "sibcall_value"
ccd90aaa 7833 [(parallel [(set (match_operand 0 "" "")
1c494086 7834 (call (match_operand 1 "memory_operand" "")
7835 (match_operand 2 "general_operand" "")))
2ba80634 7836 (return)
7837 (use (match_operand 3 "" ""))])]
d68c2c10 7838 "TARGET_32BIT"
1c494086 7839 "
7840 {
ca373797 7841 rtx pat;
7842
3112c3f7 7843 if ((!REG_P (XEXP (operands[1], 0))
7844 && GET_CODE (XEXP (operands[1], 0)) != SYMBOL_REF)
7845 || (GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
7846 && arm_is_long_call_p (SYMBOL_REF_DECL (XEXP (operands[1], 0)))))
33ae7c4b 7847 XEXP (operands[1], 0) = force_reg (SImode, XEXP (operands[1], 0));
7848
1c494086 7849 if (operands[3] == NULL_RTX)
7850 operands[3] = const0_rtx;
ca373797 7851
7852 pat = gen_sibcall_value_internal (operands[0], operands[1],
7853 operands[2], operands[3]);
7854 arm_emit_call_insn (pat, operands[1], true);
7855 DONE;
1c494086 7856 }"
7857)
7858
7859(define_insn "*sibcall_insn"
84ce8e5c 7860 [(call (mem:SI (match_operand:SI 0 "call_insn_operand" "Cs, US"))
1c494086 7861 (match_operand 1 "" ""))
2ba80634 7862 (return)
7863 (use (match_operand 2 "" ""))]
33ae7c4b 7864 "TARGET_32BIT && SIBLING_CALL_P (insn)"
1c494086 7865 "*
33ae7c4b 7866 if (which_alternative == 1)
7867 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
7868 else
7869 {
7870 if (arm_arch5 || arm_arch4t)
947d113e 7871 return \"bx%?\\t%0\\t%@ indirect register sibling call\";
33ae7c4b 7872 else
7873 return \"mov%?\\t%|pc, %0\\t%@ indirect register sibling call\";
7874 }
1c494086 7875 "
7876 [(set_attr "type" "call")]
7877)
7878
7879(define_insn "*sibcall_value_insn"
84ce8e5c 7880 [(set (match_operand 0 "" "")
7881 (call (mem:SI (match_operand:SI 1 "call_insn_operand" "Cs,US"))
1c494086 7882 (match_operand 2 "" "")))
2ba80634 7883 (return)
7884 (use (match_operand 3 "" ""))]
33ae7c4b 7885 "TARGET_32BIT && SIBLING_CALL_P (insn)"
1c494086 7886 "*
33ae7c4b 7887 if (which_alternative == 1)
7888 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
7889 else
7890 {
7891 if (arm_arch5 || arm_arch4t)
84ce8e5c 7892 return \"bx%?\\t%1\";
33ae7c4b 7893 else
7894 return \"mov%?\\t%|pc, %1\\t@ indirect sibling call \";
7895 }
1c494086 7896 "
7897 [(set_attr "type" "call")]
7898)
7899
0686440e 7900(define_expand "<return_str>return"
9b23f0a7 7901 [(RETURNS)]
8cba51a5 7902 "(TARGET_ARM || (TARGET_THUMB2
7903 && ARM_FUNC_TYPE (arm_current_func_type ()) == ARM_FT_NORMAL
7904 && !IS_STACKALIGN (arm_current_func_type ())))
0686440e 7905 <return_cond_false>"
8cba51a5 7906 "
7907 {
7908 if (TARGET_THUMB2)
7909 {
0686440e 7910 thumb2_expand_return (<return_simple_p>);
8cba51a5 7911 DONE;
7912 }
7913 }
7914 "
7915)
d68c2c10 7916
9c08d1fa 7917;; Often the return insn will be the same as loading from memory, so set attr
d68c2c10 7918(define_insn "*arm_return"
9c08d1fa 7919 [(return)]
cffb2a26 7920 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
9c08d1fa 7921 "*
9c08d1fa 7922 {
cffb2a26 7923 if (arm_ccfsm_state == 2)
7924 {
7925 arm_ccfsm_state += 2;
7926 return \"\";
7927 }
e2549f81 7928 return output_return_instruction (const_true_rtx, true, false, false);
cffb2a26 7929 }"
a2cd141b 7930 [(set_attr "type" "load1")
755eb2b4 7931 (set_attr "length" "12")
0d66636f 7932 (set_attr "predicable" "yes")]
cffb2a26 7933)
9c08d1fa 7934
0686440e 7935(define_insn "*cond_<return_str>return"
9c08d1fa 7936 [(set (pc)
8fa3ba89 7937 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 7938 [(match_operand 1 "cc_register" "") (const_int 0)])
9b23f0a7 7939 (RETURNS)
9c08d1fa 7940 (pc)))]
0686440e 7941 "TARGET_ARM <return_cond_true>"
9c08d1fa 7942 "*
8fa3ba89 7943 {
7944 if (arm_ccfsm_state == 2)
7945 {
7946 arm_ccfsm_state += 2;
7947 return \"\";
7948 }
0686440e 7949 return output_return_instruction (operands[0], true, false,
7950 <return_simple_p>);
8fa3ba89 7951 }"
7952 [(set_attr "conds" "use")
755eb2b4 7953 (set_attr "length" "12")
a2cd141b 7954 (set_attr "type" "load1")]
8fa3ba89 7955)
9c08d1fa 7956
0686440e 7957(define_insn "*cond_<return_str>return_inverted"
9c08d1fa 7958 [(set (pc)
8fa3ba89 7959 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 7960 [(match_operand 1 "cc_register" "") (const_int 0)])
9c08d1fa 7961 (pc)
9b23f0a7 7962 (RETURNS)))]
0686440e 7963 "TARGET_ARM <return_cond_true>"
9c08d1fa 7964 "*
8fa3ba89 7965 {
7966 if (arm_ccfsm_state == 2)
7967 {
7968 arm_ccfsm_state += 2;
7969 return \"\";
7970 }
0686440e 7971 return output_return_instruction (operands[0], true, true,
7972 <return_simple_p>);
8fa3ba89 7973 }"
7974 [(set_attr "conds" "use")
37a1317b 7975 (set_attr "length" "12")
a2cd141b 7976 (set_attr "type" "load1")]
8fa3ba89 7977)
9c08d1fa 7978
e2549f81 7979(define_insn "*arm_simple_return"
7980 [(simple_return)]
7981 "TARGET_ARM"
7982 "*
7983 {
7984 if (arm_ccfsm_state == 2)
7985 {
7986 arm_ccfsm_state += 2;
7987 return \"\";
7988 }
7989 return output_return_instruction (const_true_rtx, true, false, true);
7990 }"
7991 [(set_attr "type" "branch")
7992 (set_attr "length" "4")
7993 (set_attr "predicable" "yes")]
7994)
7995
68121397 7996;; Generate a sequence of instructions to determine if the processor is
7997;; in 26-bit or 32-bit mode, and return the appropriate return address
7998;; mask.
7999
8000(define_expand "return_addr_mask"
8001 [(set (match_dup 1)
8002 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8003 (const_int 0)))
8004 (set (match_operand:SI 0 "s_register_operand" "")
8005 (if_then_else:SI (eq (match_dup 1) (const_int 0))
8006 (const_int -1)
8007 (const_int 67108860)))] ; 0x03fffffc
8008 "TARGET_ARM"
8009 "
62eddbd4 8010 operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
68121397 8011 ")
8012
8013(define_insn "*check_arch2"
8014 [(set (match_operand:CC_NOOV 0 "cc_register" "")
8015 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8016 (const_int 0)))]
8017 "TARGET_ARM"
8018 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
8019 [(set_attr "length" "8")
1b7da4ac 8020 (set_attr "conds" "set")
8021 (set_attr "type" "multiple")]
68121397 8022)
8023
9c08d1fa 8024;; Call subroutine returning any type.
8025
8026(define_expand "untyped_call"
8027 [(parallel [(call (match_operand 0 "" "")
8028 (const_int 0))
8029 (match_operand 1 "" "")
8030 (match_operand 2 "" "")])]
ccd90aaa 8031 "TARGET_EITHER"
9c08d1fa 8032 "
215b30b3 8033 {
8034 int i;
ccd90aaa 8035 rtx par = gen_rtx_PARALLEL (VOIDmode,
8036 rtvec_alloc (XVECLEN (operands[2], 0)));
8037 rtx addr = gen_reg_rtx (Pmode);
8038 rtx mem;
8039 int size = 0;
9c08d1fa 8040
ccd90aaa 8041 emit_move_insn (addr, XEXP (operands[1], 0));
8042 mem = change_address (operands[1], BLKmode, addr);
9c08d1fa 8043
215b30b3 8044 for (i = 0; i < XVECLEN (operands[2], 0); i++)
8045 {
ccd90aaa 8046 rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
9c08d1fa 8047
ccd90aaa 8048 /* Default code only uses r0 as a return value, but we could
8049 be using anything up to 4 registers. */
8050 if (REGNO (src) == R0_REGNUM)
8051 src = gen_rtx_REG (TImode, R0_REGNUM);
8052
8053 XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
8054 GEN_INT (size));
8055 size += GET_MODE_SIZE (GET_MODE (src));
8056 }
8057
7f265a08 8058 emit_call_insn (gen_call_value (par, operands[0], const0_rtx, NULL));
ccd90aaa 8059
8060 size = 0;
8061
8062 for (i = 0; i < XVECLEN (par, 0); i++)
8063 {
8064 HOST_WIDE_INT offset = 0;
8065 rtx reg = XEXP (XVECEXP (par, 0, i), 0);
8066
8067 if (size != 0)
29c05e22 8068 emit_move_insn (addr, plus_constant (Pmode, addr, size));
ccd90aaa 8069
8070 mem = change_address (mem, GET_MODE (reg), NULL);
8071 if (REGNO (reg) == R0_REGNUM)
8072 {
8073 /* On thumb we have to use a write-back instruction. */
320ea44d 8074 emit_insn (arm_gen_store_multiple (arm_regs_in_sequence, 4, addr,
8075 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
ccd90aaa 8076 size = TARGET_ARM ? 16 : 0;
8077 }
8078 else
8079 {
8080 emit_move_insn (mem, reg);
8081 size = GET_MODE_SIZE (GET_MODE (reg));
8082 }
215b30b3 8083 }
9c08d1fa 8084
215b30b3 8085 /* The optimizer does not know that the call sets the function value
8086 registers we stored in the result block. We avoid problems by
8087 claiming that all hard registers are used and clobbered at this
8088 point. */
8089 emit_insn (gen_blockage ());
8090
8091 DONE;
8092 }"
8093)
9c08d1fa 8094
ccd90aaa 8095(define_expand "untyped_return"
8096 [(match_operand:BLK 0 "memory_operand" "")
8097 (match_operand 1 "" "")]
8098 "TARGET_EITHER"
8099 "
8100 {
8101 int i;
8102 rtx addr = gen_reg_rtx (Pmode);
8103 rtx mem;
8104 int size = 0;
8105
8106 emit_move_insn (addr, XEXP (operands[0], 0));
8107 mem = change_address (operands[0], BLKmode, addr);
8108
8109 for (i = 0; i < XVECLEN (operands[1], 0); i++)
8110 {
8111 HOST_WIDE_INT offset = 0;
8112 rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
8113
8114 if (size != 0)
29c05e22 8115 emit_move_insn (addr, plus_constant (Pmode, addr, size));
ccd90aaa 8116
8117 mem = change_address (mem, GET_MODE (reg), NULL);
8118 if (REGNO (reg) == R0_REGNUM)
8119 {
8120 /* On thumb we have to use a write-back instruction. */
320ea44d 8121 emit_insn (arm_gen_load_multiple (arm_regs_in_sequence, 4, addr,
8122 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
ccd90aaa 8123 size = TARGET_ARM ? 16 : 0;
8124 }
8125 else
8126 {
8127 emit_move_insn (reg, mem);
8128 size = GET_MODE_SIZE (GET_MODE (reg));
8129 }
8130 }
8131
8132 /* Emit USE insns before the return. */
8133 for (i = 0; i < XVECLEN (operands[1], 0); i++)
18b42941 8134 emit_use (SET_DEST (XVECEXP (operands[1], 0, i)));
ccd90aaa 8135
8136 /* Construct the return. */
8137 expand_naked_return ();
8138
8139 DONE;
8140 }"
8141)
8142
9c08d1fa 8143;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
8144;; all of memory. This blocks insns from being moved across this point.
8145
8146(define_insn "blockage"
e1159bbe 8147 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
cffb2a26 8148 "TARGET_EITHER"
9c08d1fa 8149 ""
cffb2a26 8150 [(set_attr "length" "0")
8151 (set_attr "type" "block")]
8152)
9c08d1fa 8153
706dca65 8154(define_insn "probe_stack"
8155 [(set (match_operand 0 "memory_operand" "=m")
8156 (unspec [(const_int 0)] UNSPEC_PROBE_STACK))]
8157 "TARGET_32BIT"
154ae8e6 8158 "str%?\\tr0, %0"
706dca65 8159 [(set_attr "type" "store1")
8160 (set_attr "predicable" "yes")]
8161)
8162
8163(define_insn "probe_stack_range"
8164 [(set (match_operand:SI 0 "register_operand" "=r")
8165 (unspec_volatile:SI [(match_operand:SI 1 "register_operand" "0")
8166 (match_operand:SI 2 "register_operand" "r")]
dd8aabc9 8167 VUNSPEC_PROBE_STACK_RANGE))]
706dca65 8168 "TARGET_32BIT"
8169{
8170 return output_probe_stack_range (operands[0], operands[2]);
8171}
8172 [(set_attr "type" "multiple")
8173 (set_attr "conds" "clob")]
8174)
8175
f7fbdd4a 8176(define_expand "casesi"
8177 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
aea4c774 8178 (match_operand:SI 1 "const_int_operand" "") ; lower bound
8179 (match_operand:SI 2 "const_int_operand" "") ; total range
f7fbdd4a 8180 (match_operand:SI 3 "" "") ; table label
8181 (match_operand:SI 4 "" "")] ; Out of range label
e6ac8414 8182 "TARGET_32BIT || optimize_size || flag_pic"
f7fbdd4a 8183 "
215b30b3 8184 {
e6ac8414 8185 enum insn_code code;
215b30b3 8186 if (operands[1] != const0_rtx)
8187 {
e6ac8414 8188 rtx reg = gen_reg_rtx (SImode);
f7fbdd4a 8189
215b30b3 8190 emit_insn (gen_addsi3 (reg, operands[0],
d022fa24 8191 gen_int_mode (-INTVAL (operands[1]),
8192 SImode)));
215b30b3 8193 operands[0] = reg;
8194 }
9c08d1fa 8195
25f905c2 8196 if (TARGET_ARM)
e6ac8414 8197 code = CODE_FOR_arm_casesi_internal;
3db2019b 8198 else if (TARGET_THUMB1)
e6ac8414 8199 code = CODE_FOR_thumb1_casesi_internal_pic;
25f905c2 8200 else if (flag_pic)
e6ac8414 8201 code = CODE_FOR_thumb2_casesi_internal_pic;
25f905c2 8202 else
e6ac8414 8203 code = CODE_FOR_thumb2_casesi_internal;
8204
8205 if (!insn_data[(int) code].operand[1].predicate(operands[2], SImode))
8206 operands[2] = force_reg (SImode, operands[2]);
8207
8208 emit_jump_insn (GEN_FCN ((int) code) (operands[0], operands[2],
8209 operands[3], operands[4]));
215b30b3 8210 DONE;
8211 }"
8212)
f7fbdd4a 8213
f082f1c4 8214;; The USE in this pattern is needed to tell flow analysis that this is
8215;; a CASESI insn. It has no other purpose.
25f905c2 8216(define_insn "arm_casesi_internal"
f082f1c4 8217 [(parallel [(set (pc)
8218 (if_then_else
8219 (leu (match_operand:SI 0 "s_register_operand" "r")
8220 (match_operand:SI 1 "arm_rhs_operand" "rI"))
8221 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
8222 (label_ref (match_operand 2 "" ""))))
8223 (label_ref (match_operand 3 "" ""))))
bd5b4116 8224 (clobber (reg:CC CC_REGNUM))
f082f1c4 8225 (use (label_ref (match_dup 2)))])]
cffb2a26 8226 "TARGET_ARM"
f7fbdd4a 8227 "*
0d66636f 8228 if (flag_pic)
8229 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
8230 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
8231 "
8232 [(set_attr "conds" "clob")
1b7da4ac 8233 (set_attr "length" "12")
8234 (set_attr "type" "multiple")]
0d66636f 8235)
9c08d1fa 8236
cffb2a26 8237(define_expand "indirect_jump"
9c08d1fa 8238 [(set (pc)
cffb2a26 8239 (match_operand:SI 0 "s_register_operand" ""))]
8240 "TARGET_EITHER"
25f905c2 8241 "
8242 /* Thumb-2 doesn't have mov pc, reg. Explicitly set the low bit of the
8243 address and use bx. */
8244 if (TARGET_THUMB2)
8245 {
8246 rtx tmp;
8247 tmp = gen_reg_rtx (SImode);
8248 emit_insn (gen_iorsi3 (tmp, operands[0], GEN_INT(1)));
8249 operands[0] = tmp;
8250 }
8251 "
cffb2a26 8252)
8253
f1039640 8254;; NB Never uses BX.
cffb2a26 8255(define_insn "*arm_indirect_jump"
8256 [(set (pc)
8257 (match_operand:SI 0 "s_register_operand" "r"))]
8258 "TARGET_ARM"
8259 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
1b7da4ac 8260 [(set_attr "predicable" "yes")
8261 (set_attr "type" "branch")]
cffb2a26 8262)
9c08d1fa 8263
f7fbdd4a 8264(define_insn "*load_indirect_jump"
9c08d1fa 8265 [(set (pc)
8266 (match_operand:SI 0 "memory_operand" "m"))]
cffb2a26 8267 "TARGET_ARM"
8268 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
a2cd141b 8269 [(set_attr "type" "load1")
61a2d04c 8270 (set_attr "pool_range" "4096")
8271 (set_attr "neg_pool_range" "4084")
0d66636f 8272 (set_attr "predicable" "yes")]
cffb2a26 8273)
8274
9c08d1fa 8275\f
8276;; Misc insns
8277
8278(define_insn "nop"
8279 [(const_int 0)]
cffb2a26 8280 "TARGET_EITHER"
3ef90e77 8281 "nop"
cffb2a26 8282 [(set (attr "length")
8283 (if_then_else (eq_attr "is_thumb" "yes")
8284 (const_int 2)
1b7da4ac 8285 (const_int 4)))
8286 (set_attr "type" "mov_reg")]
cffb2a26 8287)
8288
ad9d4399 8289(define_insn "trap"
8290 [(trap_if (const_int 1) (const_int 0))]
8291 ""
8292 "*
8293 if (TARGET_ARM)
8294 return \".inst\\t0xe7f000f0\";
8295 else
8296 return \".inst\\t0xdeff\";
8297 "
8298 [(set (attr "length")
8299 (if_then_else (eq_attr "is_thumb" "yes")
8300 (const_int 2)
8301 (const_int 4)))
8302 (set_attr "type" "trap")
8303 (set_attr "conds" "unconditional")]
8304)
8305
9c08d1fa 8306\f
8307;; Patterns to allow combination of arithmetic, cond code and shifts
8308
0abea32c 8309(define_insn "*<arith_shift_insn>_multsi"
8310 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9b23f0a7 8311 (SHIFTABLE_OPS:SI
0abea32c 8312 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
8313 (match_operand:SI 3 "power_of_two_operand" ""))
8314 (match_operand:SI 1 "s_register_operand" "rk,<t2_binop0>")))]
d5d4dc8d 8315 "TARGET_32BIT"
0abea32c 8316 "<arith_shift_insn>%?\\t%0, %1, %2, lsl %b3"
8317 [(set_attr "predicable" "yes")
8318 (set_attr "predicable_short_it" "no")
753d9835 8319 (set_attr "shift" "2")
0abea32c 8320 (set_attr "arch" "a,t2")
8321 (set_attr "type" "alu_shift_imm")])
8322
8323(define_insn "*<arith_shift_insn>_shiftsi"
8324 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9b23f0a7 8325 (SHIFTABLE_OPS:SI
0abea32c 8326 (match_operator:SI 2 "shift_nomul_operator"
8327 [(match_operand:SI 3 "s_register_operand" "r,r,r")
8328 (match_operand:SI 4 "shift_amount_operand" "M,M,r")])
8329 (match_operand:SI 1 "s_register_operand" "rk,<t2_binop0>,rk")))]
a021b821 8330 "TARGET_32BIT && GET_CODE (operands[2]) != MULT"
0abea32c 8331 "<arith_shift_insn>%?\\t%0, %1, %3%S2"
344495ea 8332 [(set_attr "predicable" "yes")
74ef923b 8333 (set_attr "predicable_short_it" "no")
753d9835 8334 (set_attr "shift" "3")
0abea32c 8335 (set_attr "arch" "a,t2,a")
8336 (set_attr "type" "alu_shift_imm,alu_shift_imm,alu_shift_reg")])
9c08d1fa 8337
d7863cfe 8338(define_split
8339 [(set (match_operand:SI 0 "s_register_operand" "")
8340 (match_operator:SI 1 "shiftable_operator"
8341 [(match_operator:SI 2 "shiftable_operator"
8342 [(match_operator:SI 3 "shift_operator"
8343 [(match_operand:SI 4 "s_register_operand" "")
8344 (match_operand:SI 5 "reg_or_int_operand" "")])
8345 (match_operand:SI 6 "s_register_operand" "")])
8346 (match_operand:SI 7 "arm_rhs_operand" "")]))
8347 (clobber (match_operand:SI 8 "s_register_operand" ""))]
d5d4dc8d 8348 "TARGET_32BIT"
d7863cfe 8349 [(set (match_dup 8)
8350 (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8351 (match_dup 6)]))
8352 (set (match_dup 0)
8353 (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
8354 "")
8355
f7fbdd4a 8356(define_insn "*arith_shiftsi_compare0"
bd5b4116 8357 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 8358 (compare:CC_NOOV
8359 (match_operator:SI 1 "shiftable_operator"
8360 [(match_operator:SI 3 "shift_operator"
8361 [(match_operand:SI 4 "s_register_operand" "r,r")
8362 (match_operand:SI 5 "shift_amount_operand" "M,r")])
8363 (match_operand:SI 2 "s_register_operand" "r,r")])
8364 (const_int 0)))
8365 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 8366 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8367 (match_dup 2)]))]
d5d4dc8d 8368 "TARGET_32BIT"
3ef90e77 8369 "%i1s%?\\t%0, %2, %4%S3"
344495ea 8370 [(set_attr "conds" "set")
331beb1a 8371 (set_attr "shift" "4")
d5d4dc8d 8372 (set_attr "arch" "32,a")
d82e788e 8373 (set_attr "type" "alus_shift_imm,alus_shift_reg")])
9c08d1fa 8374
f7fbdd4a 8375(define_insn "*arith_shiftsi_compare0_scratch"
bd5b4116 8376 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 8377 (compare:CC_NOOV
8378 (match_operator:SI 1 "shiftable_operator"
8379 [(match_operator:SI 3 "shift_operator"
8380 [(match_operand:SI 4 "s_register_operand" "r,r")
8381 (match_operand:SI 5 "shift_amount_operand" "M,r")])
8382 (match_operand:SI 2 "s_register_operand" "r,r")])
8383 (const_int 0)))
8384 (clobber (match_scratch:SI 0 "=r,r"))]
8385 "TARGET_32BIT"
3ef90e77 8386 "%i1s%?\\t%0, %2, %4%S3"
344495ea 8387 [(set_attr "conds" "set")
331beb1a 8388 (set_attr "shift" "4")
d5d4dc8d 8389 (set_attr "arch" "32,a")
d82e788e 8390 (set_attr "type" "alus_shift_imm,alus_shift_reg")])
9c08d1fa 8391
f7fbdd4a 8392(define_insn "*sub_shiftsi"
d5d4dc8d 8393 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8394 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
9c08d1fa 8395 (match_operator:SI 2 "shift_operator"
d5d4dc8d 8396 [(match_operand:SI 3 "s_register_operand" "r,r")
8397 (match_operand:SI 4 "shift_amount_operand" "M,r")])))]
8398 "TARGET_32BIT"
6c4c2133 8399 "sub%?\\t%0, %1, %3%S2"
344495ea 8400 [(set_attr "predicable" "yes")
331beb1a 8401 (set_attr "shift" "3")
d5d4dc8d 8402 (set_attr "arch" "32,a")
d82e788e 8403 (set_attr "type" "alus_shift_imm,alus_shift_reg")])
9c08d1fa 8404
f7fbdd4a 8405(define_insn "*sub_shiftsi_compare0"
bd5b4116 8406 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 8407 (compare:CC_NOOV
d82e788e 8408 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
40dbec34 8409 (match_operator:SI 2 "shift_operator"
d82e788e 8410 [(match_operand:SI 3 "s_register_operand" "r,r,r")
8411 (match_operand:SI 4 "shift_amount_operand" "M,r,M")]))
40dbec34 8412 (const_int 0)))
d82e788e 8413 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
d5d4dc8d 8414 (minus:SI (match_dup 1)
8415 (match_op_dup 2 [(match_dup 3) (match_dup 4)])))]
8416 "TARGET_32BIT"
3ef90e77 8417 "subs%?\\t%0, %1, %3%S2"
344495ea 8418 [(set_attr "conds" "set")
a2cd141b 8419 (set_attr "shift" "3")
d82e788e 8420 (set_attr "arch" "32,a,a")
8421 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
9c08d1fa 8422
f7fbdd4a 8423(define_insn "*sub_shiftsi_compare0_scratch"
bd5b4116 8424 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 8425 (compare:CC_NOOV
d82e788e 8426 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
40dbec34 8427 (match_operator:SI 2 "shift_operator"
d82e788e 8428 [(match_operand:SI 3 "s_register_operand" "r,r,r")
8429 (match_operand:SI 4 "shift_amount_operand" "M,r,M")]))
40dbec34 8430 (const_int 0)))
d82e788e 8431 (clobber (match_scratch:SI 0 "=r,r,r"))]
d5d4dc8d 8432 "TARGET_32BIT"
3ef90e77 8433 "subs%?\\t%0, %1, %3%S2"
344495ea 8434 [(set_attr "conds" "set")
a2cd141b 8435 (set_attr "shift" "3")
d82e788e 8436 (set_attr "arch" "32,a,a")
8437 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
9c08d1fa 8438\f
8439
190efb17 8440(define_insn_and_split "*and_scc"
9c08d1fa 8441 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 8442 (and:SI (match_operator:SI 1 "arm_comparison_operator"
190efb17 8443 [(match_operand 2 "cc_register" "") (const_int 0)])
8444 (match_operand:SI 3 "s_register_operand" "r")))]
cffb2a26 8445 "TARGET_ARM"
190efb17 8446 "#" ; "mov%D1\\t%0, #0\;and%d1\\t%0, %3, #1"
8447 "&& reload_completed"
8448 [(cond_exec (match_dup 5) (set (match_dup 0) (const_int 0)))
8449 (cond_exec (match_dup 4) (set (match_dup 0)
8450 (and:SI (match_dup 3) (const_int 1))))]
8451 {
3754d046 8452 machine_mode mode = GET_MODE (operands[2]);
190efb17 8453 enum rtx_code rc = GET_CODE (operands[1]);
8454
8455 /* Note that operands[4] is the same as operands[1],
8456 but with VOIDmode as the result. */
8457 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
8458 if (mode == CCFPmode || mode == CCFPEmode)
8459 rc = reverse_condition_maybe_unordered (rc);
8460 else
8461 rc = reverse_condition (rc);
8462 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
8463 }
8fa3ba89 8464 [(set_attr "conds" "use")
1b7da4ac 8465 (set_attr "type" "multiple")
8fa3ba89 8466 (set_attr "length" "8")]
8467)
9c08d1fa 8468
190efb17 8469(define_insn_and_split "*ior_scc"
9c08d1fa 8470 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
190efb17 8471 (ior:SI (match_operator:SI 1 "arm_comparison_operator"
8472 [(match_operand 2 "cc_register" "") (const_int 0)])
8473 (match_operand:SI 3 "s_register_operand" "0,?r")))]
cffb2a26 8474 "TARGET_ARM"
e2348bcb 8475 "@
190efb17 8476 orr%d1\\t%0, %3, #1
8477 #"
8478 "&& reload_completed
8479 && REGNO (operands [0]) != REGNO (operands[3])"
8480 ;; && which_alternative == 1
8481 ; mov%D1\\t%0, %3\;orr%d1\\t%0, %3, #1
8482 [(cond_exec (match_dup 5) (set (match_dup 0) (match_dup 3)))
8483 (cond_exec (match_dup 4) (set (match_dup 0)
8484 (ior:SI (match_dup 3) (const_int 1))))]
8485 {
3754d046 8486 machine_mode mode = GET_MODE (operands[2]);
190efb17 8487 enum rtx_code rc = GET_CODE (operands[1]);
8488
8489 /* Note that operands[4] is the same as operands[1],
8490 but with VOIDmode as the result. */
8491 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
8492 if (mode == CCFPmode || mode == CCFPEmode)
8493 rc = reverse_condition_maybe_unordered (rc);
8494 else
8495 rc = reverse_condition (rc);
8496 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
8497 }
8fa3ba89 8498 [(set_attr "conds" "use")
1b7da4ac 8499 (set_attr "length" "4,8")
8500 (set_attr "type" "logic_imm,multiple")]
8fa3ba89 8501)
9c08d1fa 8502
2df9477b 8503; A series of splitters for the compare_scc pattern below. Note that
8504; order is important.
8505(define_split
8506 [(set (match_operand:SI 0 "s_register_operand" "")
8507 (lt:SI (match_operand:SI 1 "s_register_operand" "")
8508 (const_int 0)))
8509 (clobber (reg:CC CC_REGNUM))]
8510 "TARGET_32BIT && reload_completed"
8511 [(set (match_dup 0) (lshiftrt:SI (match_dup 1) (const_int 31)))])
8512
8513(define_split
8514 [(set (match_operand:SI 0 "s_register_operand" "")
8515 (ge:SI (match_operand:SI 1 "s_register_operand" "")
8516 (const_int 0)))
8517 (clobber (reg:CC CC_REGNUM))]
8518 "TARGET_32BIT && reload_completed"
8519 [(set (match_dup 0) (not:SI (match_dup 1)))
8520 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 31)))])
8521
98562479 8522(define_split
8523 [(set (match_operand:SI 0 "s_register_operand" "")
8524 (eq:SI (match_operand:SI 1 "s_register_operand" "")
8525 (const_int 0)))
8526 (clobber (reg:CC CC_REGNUM))]
8527 "arm_arch5 && TARGET_32BIT"
8528 [(set (match_dup 0) (clz:SI (match_dup 1)))
8529 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 5)))]
8530)
8531
2df9477b 8532(define_split
8533 [(set (match_operand:SI 0 "s_register_operand" "")
8534 (eq:SI (match_operand:SI 1 "s_register_operand" "")
8535 (const_int 0)))
8536 (clobber (reg:CC CC_REGNUM))]
8537 "TARGET_32BIT && reload_completed"
8538 [(parallel
080c0b9a 8539 [(set (reg:CC CC_REGNUM)
8540 (compare:CC (const_int 1) (match_dup 1)))
2df9477b 8541 (set (match_dup 0)
8542 (minus:SI (const_int 1) (match_dup 1)))])
080c0b9a 8543 (cond_exec (ltu:CC (reg:CC CC_REGNUM) (const_int 0))
2df9477b 8544 (set (match_dup 0) (const_int 0)))])
8545
8546(define_split
8547 [(set (match_operand:SI 0 "s_register_operand" "")
8548 (ne:SI (match_operand:SI 1 "s_register_operand" "")
8549 (match_operand:SI 2 "const_int_operand" "")))
8550 (clobber (reg:CC CC_REGNUM))]
8551 "TARGET_32BIT && reload_completed"
8552 [(parallel
8553 [(set (reg:CC CC_REGNUM)
8554 (compare:CC (match_dup 1) (match_dup 2)))
8555 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))])
8556 (cond_exec (ne:CC (reg:CC CC_REGNUM) (const_int 0))
8557 (set (match_dup 0) (const_int 1)))]
8558{
8559 operands[3] = GEN_INT (-INTVAL (operands[2]));
8560})
8561
8562(define_split
8563 [(set (match_operand:SI 0 "s_register_operand" "")
8564 (ne:SI (match_operand:SI 1 "s_register_operand" "")
8565 (match_operand:SI 2 "arm_add_operand" "")))
8566 (clobber (reg:CC CC_REGNUM))]
8567 "TARGET_32BIT && reload_completed"
8568 [(parallel
8569 [(set (reg:CC_NOOV CC_REGNUM)
8570 (compare:CC_NOOV (minus:SI (match_dup 1) (match_dup 2))
8571 (const_int 0)))
8572 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
8573 (cond_exec (ne:CC_NOOV (reg:CC_NOOV CC_REGNUM) (const_int 0))
8574 (set (match_dup 0) (const_int 1)))])
8575
8576(define_insn_and_split "*compare_scc"
fd711051 8577 [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts")
8fa3ba89 8578 (match_operator:SI 1 "arm_comparison_operator"
5565501b 8579 [(match_operand:SI 2 "s_register_operand" "r,r")
8580 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
bd5b4116 8581 (clobber (reg:CC CC_REGNUM))]
2df9477b 8582 "TARGET_32BIT"
8583 "#"
8584 "&& reload_completed"
8585 [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 3)))
8586 (cond_exec (match_dup 4) (set (match_dup 0) (const_int 0)))
8587 (cond_exec (match_dup 5) (set (match_dup 0) (const_int 1)))]
8588{
8589 rtx tmp1;
3754d046 8590 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
2df9477b 8591 operands[2], operands[3]);
8592 enum rtx_code rc = GET_CODE (operands[1]);
e2348bcb 8593
2df9477b 8594 tmp1 = gen_rtx_REG (mode, CC_REGNUM);
080c0b9a 8595
2df9477b 8596 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
8597 if (mode == CCFPmode || mode == CCFPEmode)
8598 rc = reverse_condition_maybe_unordered (rc);
8599 else
8600 rc = reverse_condition (rc);
8601 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
1b7da4ac 8602}
8603 [(set_attr "type" "multiple")]
8604)
9c08d1fa 8605
080c0b9a 8606;; Attempt to improve the sequence generated by the compare_scc splitters
8607;; not to use conditional execution.
98562479 8608
8609;; Rd = (eq (reg1) (const_int0)) // ARMv5
8610;; clz Rd, reg1
8611;; lsr Rd, Rd, #5
080c0b9a 8612(define_peephole2
8613 [(set (reg:CC CC_REGNUM)
8614 (compare:CC (match_operand:SI 1 "register_operand" "")
98562479 8615 (const_int 0)))
8616 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
8617 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
8618 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
8619 (set (match_dup 0) (const_int 1)))]
8620 "arm_arch5 && TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)"
8621 [(set (match_dup 0) (clz:SI (match_dup 1)))
8622 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 5)))]
8623)
8624
8625;; Rd = (eq (reg1) (const_int0)) // !ARMv5
8626;; negs Rd, reg1
8627;; adc Rd, Rd, reg1
8628(define_peephole2
8629 [(set (reg:CC CC_REGNUM)
8630 (compare:CC (match_operand:SI 1 "register_operand" "")
8631 (const_int 0)))
080c0b9a 8632 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
8633 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
8634 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
8635 (set (match_dup 0) (const_int 1)))
98562479 8636 (match_scratch:SI 2 "r")]
8637 "TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)"
922b6913 8638 [(parallel
8639 [(set (reg:CC CC_REGNUM)
98562479 8640 (compare:CC (const_int 0) (match_dup 1)))
8641 (set (match_dup 2) (minus:SI (const_int 0) (match_dup 1)))])
8642 (set (match_dup 0)
8643 (plus:SI (plus:SI (match_dup 1) (match_dup 2))
8644 (geu:SI (reg:CC CC_REGNUM) (const_int 0))))]
8645)
8646
31991287 8647;; Rd = (eq (reg1) (reg2/imm)) // ARMv5 and optimising for speed.
98562479 8648;; sub Rd, Reg1, reg2
8649;; clz Rd, Rd
8650;; lsr Rd, Rd, #5
8651(define_peephole2
8652 [(set (reg:CC CC_REGNUM)
8653 (compare:CC (match_operand:SI 1 "register_operand" "")
8654 (match_operand:SI 2 "arm_rhs_operand" "")))
8655 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
8656 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
8657 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
8658 (set (match_dup 0) (const_int 1)))]
31991287 8659 "arm_arch5 && TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)
8660 && !(TARGET_THUMB2 && optimize_insn_for_size_p ())"
98562479 8661 [(set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))
8662 (set (match_dup 0) (clz:SI (match_dup 0)))
8663 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 5)))]
8664)
8665
8666
31991287 8667;; Rd = (eq (reg1) (reg2)) // ! ARMv5 or optimising for size.
98562479 8668;; sub T1, Reg1, reg2
8669;; negs Rd, T1
8670;; adc Rd, Rd, T1
8671(define_peephole2
8672 [(set (reg:CC CC_REGNUM)
8673 (compare:CC (match_operand:SI 1 "register_operand" "")
8674 (match_operand:SI 2 "arm_rhs_operand" "")))
8675 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
8676 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
8677 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
8678 (set (match_dup 0) (const_int 1)))
8679 (match_scratch:SI 3 "r")]
8680 "TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)"
31991287 8681 [(set (match_dup 3) (match_dup 4))
080c0b9a 8682 (parallel
8683 [(set (reg:CC CC_REGNUM)
8684 (compare:CC (const_int 0) (match_dup 3)))
8685 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 3)))])
98562479 8686 (set (match_dup 0)
8687 (plus:SI (plus:SI (match_dup 0) (match_dup 3))
8688 (geu:SI (reg:CC CC_REGNUM) (const_int 0))))]
31991287 8689 "
8690 if (CONST_INT_P (operands[2]))
8691 operands[4] = plus_constant (SImode, operands[1], -INTVAL (operands[2]));
8692 else
8693 operands[4] = gen_rtx_MINUS (SImode, operands[1], operands[2]);
8694 ")
080c0b9a 8695
f7fbdd4a 8696(define_insn "*cond_move"
9c08d1fa 8697 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
aea4c774 8698 (if_then_else:SI (match_operator 3 "equality_operator"
8fa3ba89 8699 [(match_operator 4 "arm_comparison_operator"
8a18b90c 8700 [(match_operand 5 "cc_register" "") (const_int 0)])
aea4c774 8701 (const_int 0)])
8702 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8703 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
cffb2a26 8704 "TARGET_ARM"
9c08d1fa 8705 "*
8fa3ba89 8706 if (GET_CODE (operands[3]) == NE)
8707 {
8708 if (which_alternative != 1)
8709 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
8710 if (which_alternative != 0)
8711 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
8712 return \"\";
8713 }
8714 if (which_alternative != 0)
8715 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8716 if (which_alternative != 1)
8717 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
8718 return \"\";
8719 "
8720 [(set_attr "conds" "use")
282b4c75 8721 (set_attr_alternative "type"
8722 [(if_then_else (match_operand 2 "const_int_operand" "")
8723 (const_string "mov_imm")
8724 (const_string "mov_reg"))
8725 (if_then_else (match_operand 1 "const_int_operand" "")
8726 (const_string "mov_imm")
8727 (const_string "mov_reg"))
8728 (const_string "multiple")])
8fa3ba89 8729 (set_attr "length" "4,4,8")]
8730)
9c08d1fa 8731
f7fbdd4a 8732(define_insn "*cond_arith"
9c08d1fa 8733 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8734 (match_operator:SI 5 "shiftable_operator"
8fa3ba89 8735 [(match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 8736 [(match_operand:SI 2 "s_register_operand" "r,r")
8737 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8738 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 8739 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8740 "TARGET_ARM"
9c08d1fa 8741 "*
8fa3ba89 8742 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
8743 return \"%i5\\t%0, %1, %2, lsr #31\";
40dbec34 8744
8fa3ba89 8745 output_asm_insn (\"cmp\\t%2, %3\", operands);
8746 if (GET_CODE (operands[5]) == AND)
8747 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
8748 else if (GET_CODE (operands[5]) == MINUS)
8749 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
8750 else if (which_alternative != 0)
8751 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8752 return \"%i5%d4\\t%0, %1, #1\";
8753 "
8754 [(set_attr "conds" "clob")
1b7da4ac 8755 (set_attr "length" "12")
8756 (set_attr "type" "multiple")]
8fa3ba89 8757)
9c08d1fa 8758
f7fbdd4a 8759(define_insn "*cond_sub"
9c08d1fa 8760 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8761 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8fa3ba89 8762 (match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 8763 [(match_operand:SI 2 "s_register_operand" "r,r")
8764 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 8765 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8766 "TARGET_ARM"
9c08d1fa 8767 "*
8fa3ba89 8768 output_asm_insn (\"cmp\\t%2, %3\", operands);
8769 if (which_alternative != 0)
8770 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8771 return \"sub%d4\\t%0, %1, #1\";
8772 "
8773 [(set_attr "conds" "clob")
1b7da4ac 8774 (set_attr "length" "8,12")
8775 (set_attr "type" "multiple")]
8fa3ba89 8776)
9c08d1fa 8777
aea4c774 8778(define_insn "*cmp_ite0"
cffb2a26 8779 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 8780 (compare
8781 (if_then_else:SI
8fa3ba89 8782 (match_operator 4 "arm_comparison_operator"
2ff91fec 8783 [(match_operand:SI 0 "s_register_operand"
8784 "l,l,l,r,r,r,r,r,r")
8785 (match_operand:SI 1 "arm_add_operand"
8786 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
8fa3ba89 8787 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 8788 [(match_operand:SI 2 "s_register_operand"
8789 "l,r,r,l,l,r,r,r,r")
8790 (match_operand:SI 3 "arm_add_operand"
8791 "lPy,rI,L,lPy,lPy,rI,rI,L,L")])
aea4c774 8792 (const_int 0))
8793 (const_int 0)))]
2ff91fec 8794 "TARGET_32BIT"
9c08d1fa 8795 "*
aea4c774 8796 {
2ff91fec 8797 static const char * const cmp1[NUM_OF_COND_CMP][2] =
8798 {
8799 {\"cmp%d5\\t%0, %1\",
8800 \"cmp%d4\\t%2, %3\"},
8801 {\"cmn%d5\\t%0, #%n1\",
8802 \"cmp%d4\\t%2, %3\"},
8803 {\"cmp%d5\\t%0, %1\",
8804 \"cmn%d4\\t%2, #%n3\"},
8805 {\"cmn%d5\\t%0, #%n1\",
8806 \"cmn%d4\\t%2, #%n3\"}
8807 };
8808 static const char * const cmp2[NUM_OF_COND_CMP][2] =
8809 {
8810 {\"cmp\\t%2, %3\",
8811 \"cmp\\t%0, %1\"},
8812 {\"cmp\\t%2, %3\",
8813 \"cmn\\t%0, #%n1\"},
8814 {\"cmn\\t%2, #%n3\",
8815 \"cmp\\t%0, %1\"},
8816 {\"cmn\\t%2, #%n3\",
8817 \"cmn\\t%0, #%n1\"}
8818 };
8819 static const char * const ite[2] =
8fa3ba89 8820 {
2ff91fec 8821 \"it\\t%d5\",
8822 \"it\\t%d4\"
8fa3ba89 8823 };
2ff91fec 8824 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
8825 CMP_CMP, CMN_CMP, CMP_CMP,
8826 CMN_CMP, CMP_CMN, CMN_CMN};
8fa3ba89 8827 int swap =
8828 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8829
2ff91fec 8830 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
8831 if (TARGET_THUMB2) {
8832 output_asm_insn (ite[swap], operands);
8833 }
8834 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
8835 return \"\";
8fa3ba89 8836 }"
8837 [(set_attr "conds" "set")
2ff91fec 8838 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
1b7da4ac 8839 (set_attr "type" "multiple")
2ff91fec 8840 (set_attr_alternative "length"
8841 [(const_int 6)
8842 (const_int 8)
8843 (const_int 8)
8844 (const_int 8)
8845 (const_int 8)
8846 (if_then_else (eq_attr "is_thumb" "no")
8847 (const_int 8)
8848 (const_int 10))
8849 (if_then_else (eq_attr "is_thumb" "no")
8850 (const_int 8)
8851 (const_int 10))
8852 (if_then_else (eq_attr "is_thumb" "no")
8853 (const_int 8)
8854 (const_int 10))
8855 (if_then_else (eq_attr "is_thumb" "no")
8856 (const_int 8)
8857 (const_int 10))])]
8fa3ba89 8858)
9c08d1fa 8859
aea4c774 8860(define_insn "*cmp_ite1"
cffb2a26 8861 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 8862 (compare
8863 (if_then_else:SI
8fa3ba89 8864 (match_operator 4 "arm_comparison_operator"
2ff91fec 8865 [(match_operand:SI 0 "s_register_operand"
8866 "l,l,l,r,r,r,r,r,r")
8867 (match_operand:SI 1 "arm_add_operand"
8868 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
8fa3ba89 8869 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 8870 [(match_operand:SI 2 "s_register_operand"
8871 "l,r,r,l,l,r,r,r,r")
8872 (match_operand:SI 3 "arm_add_operand"
8873 "lPy,rI,L,lPy,lPy,rI,rI,L,L")])
aea4c774 8874 (const_int 1))
8875 (const_int 0)))]
2ff91fec 8876 "TARGET_32BIT"
9c08d1fa 8877 "*
9c08d1fa 8878 {
2ff91fec 8879 static const char * const cmp1[NUM_OF_COND_CMP][2] =
8880 {
8881 {\"cmp\\t%0, %1\",
8882 \"cmp\\t%2, %3\"},
8883 {\"cmn\\t%0, #%n1\",
8884 \"cmp\\t%2, %3\"},
8885 {\"cmp\\t%0, %1\",
8886 \"cmn\\t%2, #%n3\"},
8887 {\"cmn\\t%0, #%n1\",
8888 \"cmn\\t%2, #%n3\"}
8889 };
8890 static const char * const cmp2[NUM_OF_COND_CMP][2] =
215b30b3 8891 {
2ff91fec 8892 {\"cmp%d4\\t%2, %3\",
8893 \"cmp%D5\\t%0, %1\"},
8894 {\"cmp%d4\\t%2, %3\",
8895 \"cmn%D5\\t%0, #%n1\"},
8896 {\"cmn%d4\\t%2, #%n3\",
8897 \"cmp%D5\\t%0, %1\"},
8898 {\"cmn%d4\\t%2, #%n3\",
8899 \"cmn%D5\\t%0, #%n1\"}
215b30b3 8900 };
2ff91fec 8901 static const char * const ite[2] =
8902 {
8903 \"it\\t%d4\",
8904 \"it\\t%D5\"
8905 };
8906 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
8907 CMP_CMP, CMN_CMP, CMP_CMP,
8908 CMN_CMP, CMP_CMN, CMN_CMN};
215b30b3 8909 int swap =
8910 comparison_dominates_p (GET_CODE (operands[5]),
8911 reverse_condition (GET_CODE (operands[4])));
8912
2ff91fec 8913 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
8914 if (TARGET_THUMB2) {
8915 output_asm_insn (ite[swap], operands);
8916 }
8917 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
8918 return \"\";
215b30b3 8919 }"
8fa3ba89 8920 [(set_attr "conds" "set")
2ff91fec 8921 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
8922 (set_attr_alternative "length"
8923 [(const_int 6)
8924 (const_int 8)
8925 (const_int 8)
8926 (const_int 8)
8927 (const_int 8)
8928 (if_then_else (eq_attr "is_thumb" "no")
8929 (const_int 8)
8930 (const_int 10))
8931 (if_then_else (eq_attr "is_thumb" "no")
8932 (const_int 8)
8933 (const_int 10))
8934 (if_then_else (eq_attr "is_thumb" "no")
8935 (const_int 8)
8936 (const_int 10))
8937 (if_then_else (eq_attr "is_thumb" "no")
8938 (const_int 8)
1b7da4ac 8939 (const_int 10))])
8940 (set_attr "type" "multiple")]
8fa3ba89 8941)
9c08d1fa 8942
f6c53574 8943(define_insn "*cmp_and"
8944 [(set (match_operand 6 "dominant_cc_register" "")
8945 (compare
8946 (and:SI
8947 (match_operator 4 "arm_comparison_operator"
2ff91fec 8948 [(match_operand:SI 0 "s_register_operand"
8949 "l,l,l,r,r,r,r,r,r")
8950 (match_operand:SI 1 "arm_add_operand"
8951 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
f6c53574 8952 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 8953 [(match_operand:SI 2 "s_register_operand"
8954 "l,r,r,l,l,r,r,r,r")
8955 (match_operand:SI 3 "arm_add_operand"
8956 "lPy,rI,L,lPy,lPy,rI,rI,L,L")]))
f6c53574 8957 (const_int 0)))]
2ff91fec 8958 "TARGET_32BIT"
f6c53574 8959 "*
8960 {
2ff91fec 8961 static const char *const cmp1[NUM_OF_COND_CMP][2] =
f6c53574 8962 {
2ff91fec 8963 {\"cmp%d5\\t%0, %1\",
8964 \"cmp%d4\\t%2, %3\"},
8965 {\"cmn%d5\\t%0, #%n1\",
8966 \"cmp%d4\\t%2, %3\"},
8967 {\"cmp%d5\\t%0, %1\",
8968 \"cmn%d4\\t%2, #%n3\"},
8969 {\"cmn%d5\\t%0, #%n1\",
8970 \"cmn%d4\\t%2, #%n3\"}
f6c53574 8971 };
2ff91fec 8972 static const char *const cmp2[NUM_OF_COND_CMP][2] =
8973 {
8974 {\"cmp\\t%2, %3\",
8975 \"cmp\\t%0, %1\"},
8976 {\"cmp\\t%2, %3\",
8977 \"cmn\\t%0, #%n1\"},
8978 {\"cmn\\t%2, #%n3\",
8979 \"cmp\\t%0, %1\"},
8980 {\"cmn\\t%2, #%n3\",
8981 \"cmn\\t%0, #%n1\"}
8982 };
8983 static const char *const ite[2] =
8984 {
8985 \"it\\t%d5\",
8986 \"it\\t%d4\"
8987 };
8988 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
8989 CMP_CMP, CMN_CMP, CMP_CMP,
8990 CMN_CMP, CMP_CMN, CMN_CMN};
f6c53574 8991 int swap =
8992 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8993
2ff91fec 8994 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
8995 if (TARGET_THUMB2) {
8996 output_asm_insn (ite[swap], operands);
8997 }
8998 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
8999 return \"\";
f6c53574 9000 }"
9001 [(set_attr "conds" "set")
9002 (set_attr "predicable" "no")
2ff91fec 9003 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
9004 (set_attr_alternative "length"
9005 [(const_int 6)
9006 (const_int 8)
9007 (const_int 8)
9008 (const_int 8)
9009 (const_int 8)
9010 (if_then_else (eq_attr "is_thumb" "no")
9011 (const_int 8)
9012 (const_int 10))
9013 (if_then_else (eq_attr "is_thumb" "no")
9014 (const_int 8)
9015 (const_int 10))
9016 (if_then_else (eq_attr "is_thumb" "no")
9017 (const_int 8)
9018 (const_int 10))
9019 (if_then_else (eq_attr "is_thumb" "no")
9020 (const_int 8)
1b7da4ac 9021 (const_int 10))])
9022 (set_attr "type" "multiple")]
f6c53574 9023)
9024
9025(define_insn "*cmp_ior"
9026 [(set (match_operand 6 "dominant_cc_register" "")
9027 (compare
9028 (ior:SI
9029 (match_operator 4 "arm_comparison_operator"
2ff91fec 9030 [(match_operand:SI 0 "s_register_operand"
9031 "l,l,l,r,r,r,r,r,r")
9032 (match_operand:SI 1 "arm_add_operand"
9033 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
f6c53574 9034 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 9035 [(match_operand:SI 2 "s_register_operand"
9036 "l,r,r,l,l,r,r,r,r")
9037 (match_operand:SI 3 "arm_add_operand"
9038 "lPy,rI,L,lPy,lPy,rI,rI,L,L")]))
f6c53574 9039 (const_int 0)))]
2ff91fec 9040 "TARGET_32BIT"
f6c53574 9041 "*
f6c53574 9042 {
2ff91fec 9043 static const char *const cmp1[NUM_OF_COND_CMP][2] =
9044 {
9045 {\"cmp\\t%0, %1\",
9046 \"cmp\\t%2, %3\"},
9047 {\"cmn\\t%0, #%n1\",
9048 \"cmp\\t%2, %3\"},
9049 {\"cmp\\t%0, %1\",
9050 \"cmn\\t%2, #%n3\"},
9051 {\"cmn\\t%0, #%n1\",
9052 \"cmn\\t%2, #%n3\"}
9053 };
9054 static const char *const cmp2[NUM_OF_COND_CMP][2] =
9055 {
9056 {\"cmp%D4\\t%2, %3\",
9057 \"cmp%D5\\t%0, %1\"},
9058 {\"cmp%D4\\t%2, %3\",
9059 \"cmn%D5\\t%0, #%n1\"},
9060 {\"cmn%D4\\t%2, #%n3\",
9061 \"cmp%D5\\t%0, %1\"},
9062 {\"cmn%D4\\t%2, #%n3\",
9063 \"cmn%D5\\t%0, #%n1\"}
9064 };
9065 static const char *const ite[2] =
9066 {
9067 \"it\\t%D4\",
9068 \"it\\t%D5\"
9069 };
9070 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
9071 CMP_CMP, CMN_CMP, CMP_CMP,
9072 CMN_CMP, CMP_CMN, CMN_CMN};
9073 int swap =
9074 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9075
9076 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9077 if (TARGET_THUMB2) {
9078 output_asm_insn (ite[swap], operands);
9079 }
9080 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9081 return \"\";
9082 }
9083 "
f6c53574 9084 [(set_attr "conds" "set")
2ff91fec 9085 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
9086 (set_attr_alternative "length"
9087 [(const_int 6)
9088 (const_int 8)
9089 (const_int 8)
9090 (const_int 8)
9091 (const_int 8)
9092 (if_then_else (eq_attr "is_thumb" "no")
9093 (const_int 8)
9094 (const_int 10))
9095 (if_then_else (eq_attr "is_thumb" "no")
9096 (const_int 8)
9097 (const_int 10))
9098 (if_then_else (eq_attr "is_thumb" "no")
9099 (const_int 8)
9100 (const_int 10))
9101 (if_then_else (eq_attr "is_thumb" "no")
9102 (const_int 8)
1b7da4ac 9103 (const_int 10))])
9104 (set_attr "type" "multiple")]
f6c53574 9105)
9106
3c5afce6 9107(define_insn_and_split "*ior_scc_scc"
fd711051 9108 [(set (match_operand:SI 0 "s_register_operand" "=Ts")
3c5afce6 9109 (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9110 [(match_operand:SI 1 "s_register_operand" "r")
9111 (match_operand:SI 2 "arm_add_operand" "rIL")])
9112 (match_operator:SI 6 "arm_comparison_operator"
9113 [(match_operand:SI 4 "s_register_operand" "r")
9114 (match_operand:SI 5 "arm_add_operand" "rIL")])))
9115 (clobber (reg:CC CC_REGNUM))]
2ff91fec 9116 "TARGET_32BIT
3c5afce6 9117 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
9118 != CCmode)"
9119 "#"
2ff91fec 9120 "TARGET_32BIT && reload_completed"
3c5afce6 9121 [(set (match_dup 7)
9122 (compare
9123 (ior:SI
9124 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9125 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9126 (const_int 0)))
9127 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9128 "operands[7]
9129 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9130 DOM_CC_X_OR_Y),
601f584c 9131 CC_REGNUM);"
9132 [(set_attr "conds" "clob")
1b7da4ac 9133 (set_attr "length" "16")
9134 (set_attr "type" "multiple")]
9135)
601f584c 9136
9137; If the above pattern is followed by a CMP insn, then the compare is
9138; redundant, since we can rework the conditional instruction that follows.
9139(define_insn_and_split "*ior_scc_scc_cmp"
9140 [(set (match_operand 0 "dominant_cc_register" "")
9141 (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9142 [(match_operand:SI 1 "s_register_operand" "r")
9143 (match_operand:SI 2 "arm_add_operand" "rIL")])
9144 (match_operator:SI 6 "arm_comparison_operator"
9145 [(match_operand:SI 4 "s_register_operand" "r")
9146 (match_operand:SI 5 "arm_add_operand" "rIL")]))
9147 (const_int 0)))
fd711051 9148 (set (match_operand:SI 7 "s_register_operand" "=Ts")
601f584c 9149 (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9150 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
2ff91fec 9151 "TARGET_32BIT"
601f584c 9152 "#"
2ff91fec 9153 "TARGET_32BIT && reload_completed"
601f584c 9154 [(set (match_dup 0)
9155 (compare
9156 (ior:SI
9157 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9158 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9159 (const_int 0)))
9160 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9161 ""
9162 [(set_attr "conds" "set")
1b7da4ac 9163 (set_attr "length" "16")
9164 (set_attr "type" "multiple")]
9165)
3c5afce6 9166
9167(define_insn_and_split "*and_scc_scc"
fd711051 9168 [(set (match_operand:SI 0 "s_register_operand" "=Ts")
3c5afce6 9169 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9170 [(match_operand:SI 1 "s_register_operand" "r")
9171 (match_operand:SI 2 "arm_add_operand" "rIL")])
9172 (match_operator:SI 6 "arm_comparison_operator"
9173 [(match_operand:SI 4 "s_register_operand" "r")
9174 (match_operand:SI 5 "arm_add_operand" "rIL")])))
9175 (clobber (reg:CC CC_REGNUM))]
2ff91fec 9176 "TARGET_32BIT
3c5afce6 9177 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9178 != CCmode)"
9179 "#"
2ff91fec 9180 "TARGET_32BIT && reload_completed
601f584c 9181 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9182 != CCmode)"
3c5afce6 9183 [(set (match_dup 7)
9184 (compare
9185 (and:SI
9186 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9187 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9188 (const_int 0)))
9189 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9190 "operands[7]
9191 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9192 DOM_CC_X_AND_Y),
601f584c 9193 CC_REGNUM);"
9194 [(set_attr "conds" "clob")
1b7da4ac 9195 (set_attr "length" "16")
9196 (set_attr "type" "multiple")]
9197)
601f584c 9198
9199; If the above pattern is followed by a CMP insn, then the compare is
9200; redundant, since we can rework the conditional instruction that follows.
9201(define_insn_and_split "*and_scc_scc_cmp"
9202 [(set (match_operand 0 "dominant_cc_register" "")
9203 (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
9204 [(match_operand:SI 1 "s_register_operand" "r")
9205 (match_operand:SI 2 "arm_add_operand" "rIL")])
9206 (match_operator:SI 6 "arm_comparison_operator"
9207 [(match_operand:SI 4 "s_register_operand" "r")
9208 (match_operand:SI 5 "arm_add_operand" "rIL")]))
9209 (const_int 0)))
fd711051 9210 (set (match_operand:SI 7 "s_register_operand" "=Ts")
601f584c 9211 (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9212 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
2ff91fec 9213 "TARGET_32BIT"
601f584c 9214 "#"
2ff91fec 9215 "TARGET_32BIT && reload_completed"
601f584c 9216 [(set (match_dup 0)
9217 (compare
9218 (and:SI
9219 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9220 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9221 (const_int 0)))
9222 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9223 ""
9224 [(set_attr "conds" "set")
1b7da4ac 9225 (set_attr "length" "16")
9226 (set_attr "type" "multiple")]
9227)
601f584c 9228
9229;; If there is no dominance in the comparison, then we can still save an
9230;; instruction in the AND case, since we can know that the second compare
9231;; need only zero the value if false (if true, then the value is already
9232;; correct).
9233(define_insn_and_split "*and_scc_scc_nodom"
fd711051 9234 [(set (match_operand:SI 0 "s_register_operand" "=&Ts,&Ts,&Ts")
601f584c 9235 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9236 [(match_operand:SI 1 "s_register_operand" "r,r,0")
9237 (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
9238 (match_operator:SI 6 "arm_comparison_operator"
9239 [(match_operand:SI 4 "s_register_operand" "r,r,r")
9240 (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
9241 (clobber (reg:CC CC_REGNUM))]
2ff91fec 9242 "TARGET_32BIT
601f584c 9243 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9244 == CCmode)"
9245 "#"
2ff91fec 9246 "TARGET_32BIT && reload_completed"
601f584c 9247 [(parallel [(set (match_dup 0)
9248 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
9249 (clobber (reg:CC CC_REGNUM))])
9250 (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
9251 (set (match_dup 0)
9252 (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
9253 (match_dup 0)
9254 (const_int 0)))]
9255 "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
9256 operands[4], operands[5]),
9257 CC_REGNUM);
9258 operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
9259 operands[5]);"
9260 [(set_attr "conds" "clob")
1b7da4ac 9261 (set_attr "length" "20")
9262 (set_attr "type" "multiple")]
9263)
3c5afce6 9264
3a0bdee0 9265(define_split
9266 [(set (reg:CC_NOOV CC_REGNUM)
9267 (compare:CC_NOOV (ior:SI
9268 (and:SI (match_operand:SI 0 "s_register_operand" "")
9269 (const_int 1))
b0694be0 9270 (match_operator:SI 1 "arm_comparison_operator"
3a0bdee0 9271 [(match_operand:SI 2 "s_register_operand" "")
9272 (match_operand:SI 3 "arm_add_operand" "")]))
9273 (const_int 0)))
9274 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9275 "TARGET_ARM"
9276 [(set (match_dup 4)
9277 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9278 (match_dup 0)))
9279 (set (reg:CC_NOOV CC_REGNUM)
9280 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9281 (const_int 0)))]
9282 "")
9283
9284(define_split
9285 [(set (reg:CC_NOOV CC_REGNUM)
9286 (compare:CC_NOOV (ior:SI
b0694be0 9287 (match_operator:SI 1 "arm_comparison_operator"
3a0bdee0 9288 [(match_operand:SI 2 "s_register_operand" "")
9289 (match_operand:SI 3 "arm_add_operand" "")])
9290 (and:SI (match_operand:SI 0 "s_register_operand" "")
9291 (const_int 1)))
9292 (const_int 0)))
9293 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9294 "TARGET_ARM"
9295 [(set (match_dup 4)
9296 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9297 (match_dup 0)))
9298 (set (reg:CC_NOOV CC_REGNUM)
9299 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9300 (const_int 0)))]
9301 "")
25f905c2 9302;; ??? The conditional patterns above need checking for Thumb-2 usefulness
3a0bdee0 9303
190efb17 9304(define_insn_and_split "*negscc"
9c08d1fa 9305 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9306 (neg:SI (match_operator 3 "arm_comparison_operator"
9c08d1fa 9307 [(match_operand:SI 1 "s_register_operand" "r")
9308 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
bd5b4116 9309 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9310 "TARGET_ARM"
190efb17 9311 "#"
9312 "&& reload_completed"
9313 [(const_int 0)]
9314 {
9315 rtx cc_reg = gen_rtx_REG (CCmode, CC_REGNUM);
e2348bcb 9316
190efb17 9317 if (GET_CODE (operands[3]) == LT && operands[2] == const0_rtx)
9318 {
9319 /* Emit mov\\t%0, %1, asr #31 */
d1f9b275 9320 emit_insn (gen_rtx_SET (operands[0],
190efb17 9321 gen_rtx_ASHIFTRT (SImode,
9322 operands[1],
9323 GEN_INT (31))));
9324 DONE;
9325 }
9326 else if (GET_CODE (operands[3]) == NE)
9327 {
9328 /* Emit subs\\t%0, %1, %2\;mvnne\\t%0, #0 */
9329 if (CONST_INT_P (operands[2]))
9330 emit_insn (gen_cmpsi2_addneg (operands[0], operands[1], operands[2],
9331 GEN_INT (- INTVAL (operands[2]))));
9332 else
9333 emit_insn (gen_subsi3_compare (operands[0], operands[1], operands[2]));
9334
9335 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
9336 gen_rtx_NE (SImode,
9337 cc_reg,
9338 const0_rtx),
d1f9b275 9339 gen_rtx_SET (operands[0],
190efb17 9340 GEN_INT (~0))));
9341 DONE;
9342 }
9343 else
9344 {
9345 /* Emit: cmp\\t%1, %2\;mov%D3\\t%0, #0\;mvn%d3\\t%0, #0 */
d1f9b275 9346 emit_insn (gen_rtx_SET (cc_reg,
190efb17 9347 gen_rtx_COMPARE (CCmode, operands[1], operands[2])));
9348 enum rtx_code rc = GET_CODE (operands[3]);
9349
9350 rc = reverse_condition (rc);
9351 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
9352 gen_rtx_fmt_ee (rc,
9353 VOIDmode,
9354 cc_reg,
9355 const0_rtx),
d1f9b275 9356 gen_rtx_SET (operands[0], const0_rtx)));
190efb17 9357 rc = GET_CODE (operands[3]);
9358 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
9359 gen_rtx_fmt_ee (rc,
9360 VOIDmode,
9361 cc_reg,
9362 const0_rtx),
d1f9b275 9363 gen_rtx_SET (operands[0],
190efb17 9364 GEN_INT (~0))));
9365 DONE;
9366 }
9367 FAIL;
9368 }
8fa3ba89 9369 [(set_attr "conds" "clob")
1b7da4ac 9370 (set_attr "length" "12")
9371 (set_attr "type" "multiple")]
8fa3ba89 9372)
9c08d1fa 9373
90404b57 9374(define_insn_and_split "movcond_addsi"
9375 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r")
9376 (if_then_else:SI
9377 (match_operator 5 "comparison_operator"
9378 [(plus:SI (match_operand:SI 3 "s_register_operand" "r,r,r")
9379 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL"))
9380 (const_int 0)])
9381 (match_operand:SI 1 "arm_rhs_operand" "rI,rPy,r")
9382 (match_operand:SI 2 "arm_rhs_operand" "rI,rPy,r")))
9383 (clobber (reg:CC CC_REGNUM))]
9384 "TARGET_32BIT"
9385 "#"
9386 "&& reload_completed"
9387 [(set (reg:CC_NOOV CC_REGNUM)
9388 (compare:CC_NOOV
9389 (plus:SI (match_dup 3)
9390 (match_dup 4))
9391 (const_int 0)))
9392 (set (match_dup 0) (match_dup 1))
9393 (cond_exec (match_dup 6)
9394 (set (match_dup 0) (match_dup 2)))]
9395 "
9396 {
3754d046 9397 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[5]),
90404b57 9398 operands[3], operands[4]);
9399 enum rtx_code rc = GET_CODE (operands[5]);
90404b57 9400 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9401 gcc_assert (!(mode == CCFPmode || mode == CCFPEmode));
22440aeb 9402 if (!REG_P (operands[2]) || REGNO (operands[2]) != REGNO (operands[0]))
4d01ce2f 9403 rc = reverse_condition (rc);
f145bcba 9404 else
9405 std::swap (operands[1], operands[2]);
90404b57 9406
9407 operands[6] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9408 }
9409 "
9410 [(set_attr "conds" "clob")
1b7da4ac 9411 (set_attr "enabled_for_depr_it" "no,yes,yes")
9412 (set_attr "type" "multiple")]
90404b57 9413)
9414
9c08d1fa 9415(define_insn "movcond"
9416 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 9417 (if_then_else:SI
8fa3ba89 9418 (match_operator 5 "arm_comparison_operator"
5565501b 9419 [(match_operand:SI 3 "s_register_operand" "r,r,r")
9420 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
9421 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9422 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 9423 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9424 "TARGET_ARM"
9c08d1fa 9425 "*
9426 if (GET_CODE (operands[5]) == LT
9427 && (operands[4] == const0_rtx))
9428 {
0438d37f 9429 if (which_alternative != 1 && REG_P (operands[1]))
9c08d1fa 9430 {
9c08d1fa 9431 if (operands[2] == const0_rtx)
e2348bcb 9432 return \"and\\t%0, %1, %3, asr #31\";
9433 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
9c08d1fa 9434 }
0438d37f 9435 else if (which_alternative != 0 && REG_P (operands[2]))
9c08d1fa 9436 {
9c08d1fa 9437 if (operands[1] == const0_rtx)
e2348bcb 9438 return \"bic\\t%0, %2, %3, asr #31\";
9439 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
9c08d1fa 9440 }
9441 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 9442 are constants. */
9c08d1fa 9443 }
e2348bcb 9444
9c08d1fa 9445 if (GET_CODE (operands[5]) == GE
9446 && (operands[4] == const0_rtx))
9447 {
0438d37f 9448 if (which_alternative != 1 && REG_P (operands[1]))
9c08d1fa 9449 {
9c08d1fa 9450 if (operands[2] == const0_rtx)
e2348bcb 9451 return \"bic\\t%0, %1, %3, asr #31\";
9452 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
9c08d1fa 9453 }
0438d37f 9454 else if (which_alternative != 0 && REG_P (operands[2]))
9c08d1fa 9455 {
9c08d1fa 9456 if (operands[1] == const0_rtx)
e2348bcb 9457 return \"and\\t%0, %2, %3, asr #31\";
9458 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
9c08d1fa 9459 }
9460 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 9461 are constants. */
9c08d1fa 9462 }
0438d37f 9463 if (CONST_INT_P (operands[4])
9c08d1fa 9464 && !const_ok_for_arm (INTVAL (operands[4])))
e2348bcb 9465 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
9c08d1fa 9466 else
e2348bcb 9467 output_asm_insn (\"cmp\\t%3, %4\", operands);
9c08d1fa 9468 if (which_alternative != 0)
e2348bcb 9469 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
9c08d1fa 9470 if (which_alternative != 1)
e2348bcb 9471 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
9c08d1fa 9472 return \"\";
215b30b3 9473 "
8fa3ba89 9474 [(set_attr "conds" "clob")
1b7da4ac 9475 (set_attr "length" "8,8,12")
9476 (set_attr "type" "multiple")]
8fa3ba89 9477)
9c08d1fa 9478
25f905c2 9479;; ??? The patterns below need checking for Thumb-2 usefulness.
9480
8a18b90c 9481(define_insn "*ifcompare_plus_move"
9482 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9483 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 9484 [(match_operand:SI 4 "s_register_operand" "r,r")
9485 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9486 (plus:SI
9487 (match_operand:SI 2 "s_register_operand" "r,r")
9488 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
129a2fe4 9489 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 9490 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9491 "TARGET_ARM"
8a18b90c 9492 "#"
8fa3ba89 9493 [(set_attr "conds" "clob")
1b7da4ac 9494 (set_attr "length" "8,12")
9495 (set_attr "type" "multiple")]
8fa3ba89 9496)
8a18b90c 9497
9498(define_insn "*if_plus_move"
129a2fe4 9499 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 9500 (if_then_else:SI
8fa3ba89 9501 (match_operator 4 "arm_comparison_operator"
8a18b90c 9502 [(match_operand 5 "cc_register" "") (const_int 0)])
9503 (plus:SI
129a2fe4 9504 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9505 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
9506 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
cffb2a26 9507 "TARGET_ARM"
8a18b90c 9508 "@
9509 add%d4\\t%0, %2, %3
9510 sub%d4\\t%0, %2, #%n3
9511 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
129a2fe4 9512 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8fa3ba89 9513 [(set_attr "conds" "use")
9514 (set_attr "length" "4,4,8,8")
65f68e55 9515 (set_attr_alternative "type"
9516 [(if_then_else (match_operand 3 "const_int_operand" "")
d82e788e 9517 (const_string "alu_imm" )
112eda6f 9518 (const_string "alu_sreg"))
d82e788e 9519 (const_string "alu_imm")
282b4c75 9520 (const_string "multiple")
9521 (const_string "multiple")])]
8fa3ba89 9522)
8a18b90c 9523
9524(define_insn "*ifcompare_move_plus"
5565501b 9525 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9526 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 9527 [(match_operand:SI 4 "s_register_operand" "r,r")
9528 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 9529 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 9530 (plus:SI
9531 (match_operand:SI 2 "s_register_operand" "r,r")
9532 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
bd5b4116 9533 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9534 "TARGET_ARM"
8a18b90c 9535 "#"
8fa3ba89 9536 [(set_attr "conds" "clob")
1b7da4ac 9537 (set_attr "length" "8,12")
9538 (set_attr "type" "multiple")]
8fa3ba89 9539)
8a18b90c 9540
9541(define_insn "*if_move_plus"
129a2fe4 9542 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 9543 (if_then_else:SI
8fa3ba89 9544 (match_operator 4 "arm_comparison_operator"
8a18b90c 9545 [(match_operand 5 "cc_register" "") (const_int 0)])
129a2fe4 9546 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8a18b90c 9547 (plus:SI
129a2fe4 9548 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9549 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
cffb2a26 9550 "TARGET_ARM"
8a18b90c 9551 "@
9552 add%D4\\t%0, %2, %3
9553 sub%D4\\t%0, %2, #%n3
9554 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
129a2fe4 9555 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8fa3ba89 9556 [(set_attr "conds" "use")
9557 (set_attr "length" "4,4,8,8")
282b4c75 9558 (set_attr_alternative "type"
9559 [(if_then_else (match_operand 3 "const_int_operand" "")
9560 (const_string "alu_imm" )
9561 (const_string "alu_sreg"))
9562 (const_string "alu_imm")
9563 (const_string "multiple")
9564 (const_string "multiple")])]
8fa3ba89 9565)
8a18b90c 9566
9567(define_insn "*ifcompare_arith_arith"
9568 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9569 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8a18b90c 9570 [(match_operand:SI 5 "s_register_operand" "r")
9571 (match_operand:SI 6 "arm_add_operand" "rIL")])
9c08d1fa 9572 (match_operator:SI 8 "shiftable_operator"
8a18b90c 9573 [(match_operand:SI 1 "s_register_operand" "r")
9574 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9c08d1fa 9575 (match_operator:SI 7 "shiftable_operator"
8a18b90c 9576 [(match_operand:SI 3 "s_register_operand" "r")
9577 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
bd5b4116 9578 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9579 "TARGET_ARM"
8a18b90c 9580 "#"
8fa3ba89 9581 [(set_attr "conds" "clob")
1b7da4ac 9582 (set_attr "length" "12")
9583 (set_attr "type" "multiple")]
8fa3ba89 9584)
9c08d1fa 9585
8a18b90c 9586(define_insn "*if_arith_arith"
9587 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9588 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8a18b90c 9589 [(match_operand 8 "cc_register" "") (const_int 0)])
9590 (match_operator:SI 6 "shiftable_operator"
9591 [(match_operand:SI 1 "s_register_operand" "r")
9592 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9593 (match_operator:SI 7 "shiftable_operator"
9594 [(match_operand:SI 3 "s_register_operand" "r")
9595 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
cffb2a26 9596 "TARGET_ARM"
8a18b90c 9597 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8fa3ba89 9598 [(set_attr "conds" "use")
1b7da4ac 9599 (set_attr "length" "8")
9600 (set_attr "type" "multiple")]
8fa3ba89 9601)
8a18b90c 9602
f7fbdd4a 9603(define_insn "*ifcompare_arith_move"
9c08d1fa 9604 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9605 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 9606 [(match_operand:SI 2 "s_register_operand" "r,r")
5565501b 9607 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
9c08d1fa 9608 (match_operator:SI 7 "shiftable_operator"
9609 [(match_operand:SI 4 "s_register_operand" "r,r")
9610 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
129a2fe4 9611 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 9612 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9613 "TARGET_ARM"
9c08d1fa 9614 "*
9c08d1fa 9615 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 9616 the conditional operator is LT or GE and we are comparing against zero and
674a8f0b 9617 everything is in registers then we can do this in two instructions. */
9c08d1fa 9618 if (operands[3] == const0_rtx
9619 && GET_CODE (operands[7]) != AND
0438d37f 9620 && REG_P (operands[5])
9621 && REG_P (operands[1])
9c08d1fa 9622 && REGNO (operands[1]) == REGNO (operands[4])
9623 && REGNO (operands[4]) != REGNO (operands[0]))
9624 {
9625 if (GET_CODE (operands[6]) == LT)
40dbec34 9626 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 9627 else if (GET_CODE (operands[6]) == GE)
40dbec34 9628 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 9629 }
0438d37f 9630 if (CONST_INT_P (operands[3])
9c08d1fa 9631 && !const_ok_for_arm (INTVAL (operands[3])))
e2348bcb 9632 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
9c08d1fa 9633 else
e2348bcb 9634 output_asm_insn (\"cmp\\t%2, %3\", operands);
40dbec34 9635 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
9c08d1fa 9636 if (which_alternative != 0)
129a2fe4 9637 return \"mov%D6\\t%0, %1\";
9c08d1fa 9638 return \"\";
215b30b3 9639 "
8fa3ba89 9640 [(set_attr "conds" "clob")
1b7da4ac 9641 (set_attr "length" "8,12")
9642 (set_attr "type" "multiple")]
8fa3ba89 9643)
9c08d1fa 9644
8a18b90c 9645(define_insn "*if_arith_move"
129a2fe4 9646 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9647 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8a18b90c 9648 [(match_operand 6 "cc_register" "") (const_int 0)])
9649 (match_operator:SI 5 "shiftable_operator"
129a2fe4 9650 [(match_operand:SI 2 "s_register_operand" "r,r")
9651 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
9652 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
cffb2a26 9653 "TARGET_ARM"
8a18b90c 9654 "@
9655 %I5%d4\\t%0, %2, %3
129a2fe4 9656 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8fa3ba89 9657 [(set_attr "conds" "use")
9658 (set_attr "length" "4,8")
282b4c75 9659 (set_attr_alternative "type"
9660 [(if_then_else (match_operand 3 "const_int_operand" "")
9661 (const_string "alu_shift_imm" )
9662 (const_string "alu_shift_reg"))
9663 (const_string "multiple")])]
8fa3ba89 9664)
8a18b90c 9665
f7fbdd4a 9666(define_insn "*ifcompare_move_arith"
9c08d1fa 9667 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9668 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 9669 [(match_operand:SI 4 "s_register_operand" "r,r")
5565501b 9670 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 9671 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9c08d1fa 9672 (match_operator:SI 7 "shiftable_operator"
9673 [(match_operand:SI 2 "s_register_operand" "r,r")
9674 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 9675 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9676 "TARGET_ARM"
9c08d1fa 9677 "*
9c08d1fa 9678 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 9679 the conditional operator is LT or GE and we are comparing against zero and
9c08d1fa 9680 everything is in registers then we can do this in two instructions */
9681 if (operands[5] == const0_rtx
9682 && GET_CODE (operands[7]) != AND
0438d37f 9683 && REG_P (operands[3])
9684 && REG_P (operands[1])
9c08d1fa 9685 && REGNO (operands[1]) == REGNO (operands[2])
9686 && REGNO (operands[2]) != REGNO (operands[0]))
9687 {
9688 if (GET_CODE (operands[6]) == GE)
40dbec34 9689 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 9690 else if (GET_CODE (operands[6]) == LT)
40dbec34 9691 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 9692 }
40dbec34 9693
0438d37f 9694 if (CONST_INT_P (operands[5])
9c08d1fa 9695 && !const_ok_for_arm (INTVAL (operands[5])))
e2348bcb 9696 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
9c08d1fa 9697 else
e2348bcb 9698 output_asm_insn (\"cmp\\t%4, %5\", operands);
40dbec34 9699
9c08d1fa 9700 if (which_alternative != 0)
129a2fe4 9701 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
40dbec34 9702 return \"%I7%D6\\t%0, %2, %3\";
215b30b3 9703 "
8fa3ba89 9704 [(set_attr "conds" "clob")
1b7da4ac 9705 (set_attr "length" "8,12")
9706 (set_attr "type" "multiple")]
8fa3ba89 9707)
9c08d1fa 9708
8a18b90c 9709(define_insn "*if_move_arith"
129a2fe4 9710 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9711 (if_then_else:SI
8fa3ba89 9712 (match_operator 4 "arm_comparison_operator"
8a18b90c 9713 [(match_operand 6 "cc_register" "") (const_int 0)])
129a2fe4 9714 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 9715 (match_operator:SI 5 "shiftable_operator"
129a2fe4 9716 [(match_operand:SI 2 "s_register_operand" "r,r")
9717 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
cffb2a26 9718 "TARGET_ARM"
8a18b90c 9719 "@
9720 %I5%D4\\t%0, %2, %3
129a2fe4 9721 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
8fa3ba89 9722 [(set_attr "conds" "use")
9723 (set_attr "length" "4,8")
282b4c75 9724 (set_attr_alternative "type"
9725 [(if_then_else (match_operand 3 "const_int_operand" "")
9726 (const_string "alu_shift_imm" )
9727 (const_string "alu_shift_reg"))
9728 (const_string "multiple")])]
8fa3ba89 9729)
8a18b90c 9730
9731(define_insn "*ifcompare_move_not"
9c08d1fa 9732 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9733 (if_then_else:SI
8fa3ba89 9734 (match_operator 5 "arm_comparison_operator"
8a18b90c 9735 [(match_operand:SI 3 "s_register_operand" "r,r")
9736 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9737 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9738 (not:SI
9739 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 9740 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9741 "TARGET_ARM"
8a18b90c 9742 "#"
8fa3ba89 9743 [(set_attr "conds" "clob")
1b7da4ac 9744 (set_attr "length" "8,12")
9745 (set_attr "type" "multiple")]
8fa3ba89 9746)
9c08d1fa 9747
8a18b90c 9748(define_insn "*if_move_not"
9749 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9750 (if_then_else:SI
8fa3ba89 9751 (match_operator 4 "arm_comparison_operator"
8a18b90c 9752 [(match_operand 3 "cc_register" "") (const_int 0)])
9753 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9754 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
cffb2a26 9755 "TARGET_ARM"
8a18b90c 9756 "@
9757 mvn%D4\\t%0, %2
9758 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
9759 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
8fa3ba89 9760 [(set_attr "conds" "use")
1aed5204 9761 (set_attr "type" "mvn_reg")
1b7da4ac 9762 (set_attr "length" "4,8,8")
9763 (set_attr "type" "mvn_reg,multiple,multiple")]
8fa3ba89 9764)
8a18b90c 9765
9766(define_insn "*ifcompare_not_move"
9c08d1fa 9767 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9768 (if_then_else:SI
8fa3ba89 9769 (match_operator 5 "arm_comparison_operator"
8a18b90c 9770 [(match_operand:SI 3 "s_register_operand" "r,r")
9771 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9772 (not:SI
9773 (match_operand:SI 2 "s_register_operand" "r,r"))
9774 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 9775 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9776 "TARGET_ARM"
8a18b90c 9777 "#"
8fa3ba89 9778 [(set_attr "conds" "clob")
1b7da4ac 9779 (set_attr "length" "8,12")
9780 (set_attr "type" "multiple")]
8fa3ba89 9781)
9c08d1fa 9782
8a18b90c 9783(define_insn "*if_not_move"
9784 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9785 (if_then_else:SI
8fa3ba89 9786 (match_operator 4 "arm_comparison_operator"
8a18b90c 9787 [(match_operand 3 "cc_register" "") (const_int 0)])
9788 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9789 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 9790 "TARGET_ARM"
8a18b90c 9791 "@
9792 mvn%d4\\t%0, %2
9793 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
9794 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
8fa3ba89 9795 [(set_attr "conds" "use")
1b7da4ac 9796 (set_attr "type" "mvn_reg,multiple,multiple")
8fa3ba89 9797 (set_attr "length" "4,8,8")]
9798)
8a18b90c 9799
9800(define_insn "*ifcompare_shift_move"
9c08d1fa 9801 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9802 (if_then_else:SI
8fa3ba89 9803 (match_operator 6 "arm_comparison_operator"
8a18b90c 9804 [(match_operand:SI 4 "s_register_operand" "r,r")
9805 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9806 (match_operator:SI 7 "shift_operator"
9807 [(match_operand:SI 2 "s_register_operand" "r,r")
9808 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
9809 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 9810 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9811 "TARGET_ARM"
9c08d1fa 9812 "#"
8fa3ba89 9813 [(set_attr "conds" "clob")
1b7da4ac 9814 (set_attr "length" "8,12")
9815 (set_attr "type" "multiple")]
8fa3ba89 9816)
9c08d1fa 9817
8a18b90c 9818(define_insn "*if_shift_move"
9819 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9820 (if_then_else:SI
8fa3ba89 9821 (match_operator 5 "arm_comparison_operator"
8a18b90c 9822 [(match_operand 6 "cc_register" "") (const_int 0)])
9823 (match_operator:SI 4 "shift_operator"
9824 [(match_operand:SI 2 "s_register_operand" "r,r,r")
9825 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
9826 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 9827 "TARGET_ARM"
5565501b 9828 "@
8a18b90c 9829 mov%d5\\t%0, %2%S4
9830 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
9831 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
8fa3ba89 9832 [(set_attr "conds" "use")
331beb1a 9833 (set_attr "shift" "2")
a2cd141b 9834 (set_attr "length" "4,8,8")
282b4c75 9835 (set_attr_alternative "type"
9836 [(if_then_else (match_operand 3 "const_int_operand" "")
9837 (const_string "mov_shift" )
9838 (const_string "mov_shift_reg"))
9839 (const_string "multiple")
9840 (const_string "multiple")])]
8fa3ba89 9841)
5565501b 9842
8a18b90c 9843(define_insn "*ifcompare_move_shift"
9844 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 9845 (if_then_else:SI
8fa3ba89 9846 (match_operator 6 "arm_comparison_operator"
8a18b90c 9847 [(match_operand:SI 4 "s_register_operand" "r,r")
9848 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9849 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
5565501b 9850 (match_operator:SI 7 "shift_operator"
8a18b90c 9851 [(match_operand:SI 2 "s_register_operand" "r,r")
9852 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
bd5b4116 9853 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9854 "TARGET_ARM"
8a18b90c 9855 "#"
8fa3ba89 9856 [(set_attr "conds" "clob")
1b7da4ac 9857 (set_attr "length" "8,12")
9858 (set_attr "type" "multiple")]
8fa3ba89 9859)
5565501b 9860
8a18b90c 9861(define_insn "*if_move_shift"
9862 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 9863 (if_then_else:SI
8fa3ba89 9864 (match_operator 5 "arm_comparison_operator"
8a18b90c 9865 [(match_operand 6 "cc_register" "") (const_int 0)])
9866 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9867 (match_operator:SI 4 "shift_operator"
9868 [(match_operand:SI 2 "s_register_operand" "r,r,r")
9869 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
cffb2a26 9870 "TARGET_ARM"
5565501b 9871 "@
8a18b90c 9872 mov%D5\\t%0, %2%S4
9873 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
9874 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
8fa3ba89 9875 [(set_attr "conds" "use")
331beb1a 9876 (set_attr "shift" "2")
a2cd141b 9877 (set_attr "length" "4,8,8")
282b4c75 9878 (set_attr_alternative "type"
9879 [(if_then_else (match_operand 3 "const_int_operand" "")
9880 (const_string "mov_shift" )
9881 (const_string "mov_shift_reg"))
9882 (const_string "multiple")
9883 (const_string "multiple")])]
8fa3ba89 9884)
9c08d1fa 9885
f7fbdd4a 9886(define_insn "*ifcompare_shift_shift"
8a18b90c 9887 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 9888 (if_then_else:SI
8fa3ba89 9889 (match_operator 7 "arm_comparison_operator"
8a18b90c 9890 [(match_operand:SI 5 "s_register_operand" "r")
9891 (match_operand:SI 6 "arm_add_operand" "rIL")])
5565501b 9892 (match_operator:SI 8 "shift_operator"
8a18b90c 9893 [(match_operand:SI 1 "s_register_operand" "r")
9894 (match_operand:SI 2 "arm_rhs_operand" "rM")])
5565501b 9895 (match_operator:SI 9 "shift_operator"
8a18b90c 9896 [(match_operand:SI 3 "s_register_operand" "r")
9897 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
bd5b4116 9898 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9899 "TARGET_ARM"
8a18b90c 9900 "#"
8fa3ba89 9901 [(set_attr "conds" "clob")
1b7da4ac 9902 (set_attr "length" "12")
9903 (set_attr "type" "multiple")]
8fa3ba89 9904)
9c08d1fa 9905
8a18b90c 9906(define_insn "*if_shift_shift"
9907 [(set (match_operand:SI 0 "s_register_operand" "=r")
9908 (if_then_else:SI
8fa3ba89 9909 (match_operator 5 "arm_comparison_operator"
8a18b90c 9910 [(match_operand 8 "cc_register" "") (const_int 0)])
9911 (match_operator:SI 6 "shift_operator"
9912 [(match_operand:SI 1 "s_register_operand" "r")
9913 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9914 (match_operator:SI 7 "shift_operator"
9915 [(match_operand:SI 3 "s_register_operand" "r")
9916 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
cffb2a26 9917 "TARGET_ARM"
8a18b90c 9918 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
8fa3ba89 9919 [(set_attr "conds" "use")
331beb1a 9920 (set_attr "shift" "1")
a2cd141b 9921 (set_attr "length" "8")
9922 (set (attr "type") (if_then_else
9923 (and (match_operand 2 "const_int_operand" "")
9924 (match_operand 4 "const_int_operand" ""))
1aed5204 9925 (const_string "mov_shift")
9926 (const_string "mov_shift_reg")))]
8fa3ba89 9927)
8a18b90c 9928
f7fbdd4a 9929(define_insn "*ifcompare_not_arith"
8a18b90c 9930 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 9931 (if_then_else:SI
8fa3ba89 9932 (match_operator 6 "arm_comparison_operator"
8a18b90c 9933 [(match_operand:SI 4 "s_register_operand" "r")
9934 (match_operand:SI 5 "arm_add_operand" "rIL")])
9935 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5565501b 9936 (match_operator:SI 7 "shiftable_operator"
8a18b90c 9937 [(match_operand:SI 2 "s_register_operand" "r")
9938 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
bd5b4116 9939 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9940 "TARGET_ARM"
8a18b90c 9941 "#"
8fa3ba89 9942 [(set_attr "conds" "clob")
1b7da4ac 9943 (set_attr "length" "12")
9944 (set_attr "type" "multiple")]
8fa3ba89 9945)
9c08d1fa 9946
8a18b90c 9947(define_insn "*if_not_arith"
9948 [(set (match_operand:SI 0 "s_register_operand" "=r")
9949 (if_then_else:SI
8fa3ba89 9950 (match_operator 5 "arm_comparison_operator"
8a18b90c 9951 [(match_operand 4 "cc_register" "") (const_int 0)])
9952 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9953 (match_operator:SI 6 "shiftable_operator"
9954 [(match_operand:SI 2 "s_register_operand" "r")
9955 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
cffb2a26 9956 "TARGET_ARM"
8a18b90c 9957 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
8fa3ba89 9958 [(set_attr "conds" "use")
1aed5204 9959 (set_attr "type" "mvn_reg")
8fa3ba89 9960 (set_attr "length" "8")]
9961)
8a18b90c 9962
9963(define_insn "*ifcompare_arith_not"
9964 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 9965 (if_then_else:SI
8fa3ba89 9966 (match_operator 6 "arm_comparison_operator"
8a18b90c 9967 [(match_operand:SI 4 "s_register_operand" "r")
9968 (match_operand:SI 5 "arm_add_operand" "rIL")])
5565501b 9969 (match_operator:SI 7 "shiftable_operator"
8a18b90c 9970 [(match_operand:SI 2 "s_register_operand" "r")
9971 (match_operand:SI 3 "arm_rhs_operand" "rI")])
9972 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
bd5b4116 9973 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9974 "TARGET_ARM"
8a18b90c 9975 "#"
8fa3ba89 9976 [(set_attr "conds" "clob")
1b7da4ac 9977 (set_attr "length" "12")
9978 (set_attr "type" "multiple")]
8fa3ba89 9979)
9c08d1fa 9980
8a18b90c 9981(define_insn "*if_arith_not"
9982 [(set (match_operand:SI 0 "s_register_operand" "=r")
9983 (if_then_else:SI
8fa3ba89 9984 (match_operator 5 "arm_comparison_operator"
8a18b90c 9985 [(match_operand 4 "cc_register" "") (const_int 0)])
9986 (match_operator:SI 6 "shiftable_operator"
9987 [(match_operand:SI 2 "s_register_operand" "r")
9988 (match_operand:SI 3 "arm_rhs_operand" "rI")])
9989 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
cffb2a26 9990 "TARGET_ARM"
8a18b90c 9991 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
8fa3ba89 9992 [(set_attr "conds" "use")
1b7da4ac 9993 (set_attr "type" "multiple")
8fa3ba89 9994 (set_attr "length" "8")]
9995)
8a18b90c 9996
f7fbdd4a 9997(define_insn "*ifcompare_neg_move"
8a18b90c 9998 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 9999 (if_then_else:SI
8fa3ba89 10000 (match_operator 5 "arm_comparison_operator"
8a18b90c 10001 [(match_operand:SI 3 "s_register_operand" "r,r")
10002 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10003 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
10004 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 10005 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10006 "TARGET_ARM"
8a18b90c 10007 "#"
8fa3ba89 10008 [(set_attr "conds" "clob")
1b7da4ac 10009 (set_attr "length" "8,12")
10010 (set_attr "type" "multiple")]
8fa3ba89 10011)
8a18b90c 10012
530bb693 10013(define_insn_and_split "*if_neg_move"
10014 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
8a18b90c 10015 (if_then_else:SI
8fa3ba89 10016 (match_operator 4 "arm_comparison_operator"
8a18b90c 10017 [(match_operand 3 "cc_register" "") (const_int 0)])
530bb693 10018 (neg:SI (match_operand:SI 2 "s_register_operand" "l,r"))
10019 (match_operand:SI 1 "s_register_operand" "0,0")))]
10020 "TARGET_32BIT"
10021 "#"
10022 "&& reload_completed"
10023 [(cond_exec (match_op_dup 4 [(match_dup 3) (const_int 0)])
10024 (set (match_dup 0) (neg:SI (match_dup 2))))]
10025 ""
8fa3ba89 10026 [(set_attr "conds" "use")
530bb693 10027 (set_attr "length" "4")
10028 (set_attr "arch" "t2,32")
10029 (set_attr "enabled_for_depr_it" "yes,no")
10030 (set_attr "type" "logic_shift_imm")]
8fa3ba89 10031)
9c08d1fa 10032
f7fbdd4a 10033(define_insn "*ifcompare_move_neg"
8a18b90c 10034 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 10035 (if_then_else:SI
8fa3ba89 10036 (match_operator 5 "arm_comparison_operator"
8a18b90c 10037 [(match_operand:SI 3 "s_register_operand" "r,r")
10038 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10039 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
10040 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 10041 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10042 "TARGET_ARM"
8a18b90c 10043 "#"
8fa3ba89 10044 [(set_attr "conds" "clob")
1b7da4ac 10045 (set_attr "length" "8,12")
10046 (set_attr "type" "multiple")]
8fa3ba89 10047)
8a18b90c 10048
530bb693 10049(define_insn_and_split "*if_move_neg"
10050 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
8a18b90c 10051 (if_then_else:SI
8fa3ba89 10052 (match_operator 4 "arm_comparison_operator"
8a18b90c 10053 [(match_operand 3 "cc_register" "") (const_int 0)])
530bb693 10054 (match_operand:SI 1 "s_register_operand" "0,0")
10055 (neg:SI (match_operand:SI 2 "s_register_operand" "l,r"))))]
10056 "TARGET_32BIT"
10057 "#"
10058 "&& reload_completed"
10059 [(cond_exec (match_dup 5)
10060 (set (match_dup 0) (neg:SI (match_dup 2))))]
10061 {
10062 machine_mode mode = GET_MODE (operands[3]);
10063 rtx_code rc = GET_CODE (operands[4]);
10064
10065 if (mode == CCFPmode || mode == CCFPEmode)
10066 rc = reverse_condition_maybe_unordered (rc);
10067 else
10068 rc = reverse_condition (rc);
10069
10070 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[3], const0_rtx);
10071 }
0d66636f 10072 [(set_attr "conds" "use")
530bb693 10073 (set_attr "length" "4")
10074 (set_attr "arch" "t2,32")
10075 (set_attr "enabled_for_depr_it" "yes,no")
10076 (set_attr "type" "logic_shift_imm")]
0d66636f 10077)
9c08d1fa 10078
f7fbdd4a 10079(define_insn "*arith_adjacentmem"
9c08d1fa 10080 [(set (match_operand:SI 0 "s_register_operand" "=r")
10081 (match_operator:SI 1 "shiftable_operator"
10082 [(match_operand:SI 2 "memory_operand" "m")
10083 (match_operand:SI 3 "memory_operand" "m")]))
10084 (clobber (match_scratch:SI 4 "=r"))]
cffb2a26 10085 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9c08d1fa 10086 "*
215b30b3 10087 {
10088 rtx ldm[3];
10089 rtx arith[4];
94dee231 10090 rtx base_reg;
10091 HOST_WIDE_INT val1 = 0, val2 = 0;
9c08d1fa 10092
215b30b3 10093 if (REGNO (operands[0]) > REGNO (operands[4]))
10094 {
10095 ldm[1] = operands[4];
10096 ldm[2] = operands[0];
10097 }
10098 else
10099 {
10100 ldm[1] = operands[0];
10101 ldm[2] = operands[4];
10102 }
94dee231 10103
10104 base_reg = XEXP (operands[2], 0);
10105
10106 if (!REG_P (base_reg))
10107 {
10108 val1 = INTVAL (XEXP (base_reg, 1));
10109 base_reg = XEXP (base_reg, 0);
10110 }
10111
10112 if (!REG_P (XEXP (operands[3], 0)))
215b30b3 10113 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
94dee231 10114
215b30b3 10115 arith[0] = operands[0];
10116 arith[3] = operands[1];
94dee231 10117
215b30b3 10118 if (val1 < val2)
10119 {
10120 arith[1] = ldm[1];
10121 arith[2] = ldm[2];
10122 }
10123 else
10124 {
10125 arith[1] = ldm[2];
10126 arith[2] = ldm[1];
10127 }
94dee231 10128
10129 ldm[0] = base_reg;
10130 if (val1 !=0 && val2 != 0)
215b30b3 10131 {
cdb1295a 10132 rtx ops[3];
10133
94dee231 10134 if (val1 == 4 || val2 == 4)
10135 /* Other val must be 8, since we know they are adjacent and neither
10136 is zero. */
3ef90e77 10137 output_asm_insn (\"ldmib%?\\t%0, {%1, %2}\", ldm);
cdb1295a 10138 else if (const_ok_for_arm (val1) || const_ok_for_arm (-val1))
94dee231 10139 {
94dee231 10140 ldm[0] = ops[0] = operands[4];
10141 ops[1] = base_reg;
10142 ops[2] = GEN_INT (val1);
10143 output_add_immediate (ops);
10144 if (val1 < val2)
3ef90e77 10145 output_asm_insn (\"ldmia%?\\t%0, {%1, %2}\", ldm);
94dee231 10146 else
3ef90e77 10147 output_asm_insn (\"ldmda%?\\t%0, {%1, %2}\", ldm);
94dee231 10148 }
cdb1295a 10149 else
10150 {
10151 /* Offset is out of range for a single add, so use two ldr. */
10152 ops[0] = ldm[1];
10153 ops[1] = base_reg;
10154 ops[2] = GEN_INT (val1);
10155 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10156 ops[0] = ldm[2];
10157 ops[2] = GEN_INT (val2);
10158 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10159 }
215b30b3 10160 }
94dee231 10161 else if (val1 != 0)
215b30b3 10162 {
215b30b3 10163 if (val1 < val2)
3ef90e77 10164 output_asm_insn (\"ldmda%?\\t%0, {%1, %2}\", ldm);
215b30b3 10165 else
3ef90e77 10166 output_asm_insn (\"ldmia%?\\t%0, {%1, %2}\", ldm);
215b30b3 10167 }
10168 else
10169 {
215b30b3 10170 if (val1 < val2)
3ef90e77 10171 output_asm_insn (\"ldmia%?\\t%0, {%1, %2}\", ldm);
215b30b3 10172 else
3ef90e77 10173 output_asm_insn (\"ldmda%?\\t%0, {%1, %2}\", ldm);
215b30b3 10174 }
10175 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
10176 return \"\";
10177 }"
10178 [(set_attr "length" "12")
10179 (set_attr "predicable" "yes")
a2cd141b 10180 (set_attr "type" "load1")]
215b30b3 10181)
9c08d1fa 10182
9c08d1fa 10183; This pattern is never tried by combine, so do it as a peephole
10184
a0f94409 10185(define_peephole2
372575c7 10186 [(set (match_operand:SI 0 "arm_general_register_operand" "")
10187 (match_operand:SI 1 "arm_general_register_operand" ""))
bd5b4116 10188 (set (reg:CC CC_REGNUM)
aea4c774 10189 (compare:CC (match_dup 1) (const_int 0)))]
372575c7 10190 "TARGET_ARM"
a0f94409 10191 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
10192 (set (match_dup 0) (match_dup 1))])]
10193 ""
0d66636f 10194)
9c08d1fa 10195
9c08d1fa 10196(define_split
10197 [(set (match_operand:SI 0 "s_register_operand" "")
10198 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
10199 (const_int 0))
8fa3ba89 10200 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9c08d1fa 10201 [(match_operand:SI 3 "s_register_operand" "")
10202 (match_operand:SI 4 "arm_rhs_operand" "")]))))
10203 (clobber (match_operand:SI 5 "s_register_operand" ""))]
cffb2a26 10204 "TARGET_ARM"
9c08d1fa 10205 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
10206 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
10207 (match_dup 5)))]
215b30b3 10208 ""
10209)
9c08d1fa 10210
aea4c774 10211;; This split can be used because CC_Z mode implies that the following
10212;; branch will be an equality, or an unsigned inequality, so the sign
10213;; extension is not needed.
9c08d1fa 10214
aea4c774 10215(define_split
bd5b4116 10216 [(set (reg:CC_Z CC_REGNUM)
aea4c774 10217 (compare:CC_Z
10218 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9c08d1fa 10219 (const_int 24))
aea4c774 10220 (match_operand 1 "const_int_operand" "")))
10221 (clobber (match_scratch:SI 2 ""))]
cffb2a26 10222 "TARGET_ARM
10223 && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
10224 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
aea4c774 10225 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
bd5b4116 10226 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
aea4c774 10227 "
9c08d1fa 10228 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
215b30b3 10229 "
10230)
25f905c2 10231;; ??? Check the patterns above for Thumb-2 usefulness
9c08d1fa 10232
87b22bf7 10233(define_expand "prologue"
10234 [(clobber (const_int 0))]
cffb2a26 10235 "TARGET_EITHER"
25f905c2 10236 "if (TARGET_32BIT)
cffb2a26 10237 arm_expand_prologue ();
10238 else
25f905c2 10239 thumb1_expand_prologue ();
87b22bf7 10240 DONE;
cffb2a26 10241 "
10242)
87b22bf7 10243
56d27660 10244(define_expand "epilogue"
4c44712e 10245 [(clobber (const_int 0))]
cffb2a26 10246 "TARGET_EITHER"
56d27660 10247 "
18d50ae6 10248 if (crtl->calls_eh_return)
fb94f18b 10249 emit_insn (gen_force_register_use (gen_rtx_REG (Pmode, 2)));
25f905c2 10250 if (TARGET_THUMB1)
c3635784 10251 {
10252 thumb1_expand_epilogue ();
10253 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
10254 gen_rtvec (1, ret_rtx), VUNSPEC_EPILOGUE));
10255 }
10256 else if (HAVE_return)
10257 {
10258 /* HAVE_return is testing for USE_RETURN_INSN (FALSE). Hence,
10259 no need for explicit testing again. */
10260 emit_jump_insn (gen_return ());
10261 }
10262 else if (TARGET_32BIT)
10263 {
10264 arm_expand_epilogue (true);
10265 }
cffb2a26 10266 DONE;
10267 "
10268)
56d27660 10269
ef5651d0 10270;; Note - although unspec_volatile's USE all hard registers,
10271;; USEs are ignored after relaod has completed. Thus we need
10272;; to add an unspec of the link register to ensure that flow
10273;; does not think that it is unused by the sibcall branch that
10274;; will replace the standard function epilogue.
c3635784 10275(define_expand "sibcall_epilogue"
fb94f18b 10276 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_REGISTER_USE)
c3635784 10277 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
10278 "TARGET_32BIT"
10279 "
10280 arm_expand_epilogue (false);
10281 DONE;
10282 "
1c494086 10283)
10284
cffb2a26 10285(define_expand "eh_epilogue"
7db9af5d 10286 [(use (match_operand:SI 0 "register_operand" ""))
10287 (use (match_operand:SI 1 "register_operand" ""))
10288 (use (match_operand:SI 2 "register_operand" ""))]
cffb2a26 10289 "TARGET_EITHER"
10290 "
215b30b3 10291 {
10292 cfun->machine->eh_epilogue_sp_ofs = operands[1];
0438d37f 10293 if (!REG_P (operands[2]) || REGNO (operands[2]) != 2)
215b30b3 10294 {
10295 rtx ra = gen_rtx_REG (Pmode, 2);
10296
10297 emit_move_insn (ra, operands[2]);
10298 operands[2] = ra;
10299 }
5cf3595a 10300 /* This is a hack -- we may have crystalized the function type too
10301 early. */
10302 cfun->machine->func_type = 0;
215b30b3 10303 }"
10304)
56d27660 10305
9c08d1fa 10306;; This split is only used during output to reduce the number of patterns
10307;; that need assembler instructions adding to them. We allowed the setting
10308;; of the conditions to be implicit during rtl generation so that
10309;; the conditional compare patterns would work. However this conflicts to
8a18b90c 10310;; some extent with the conditional data operations, so we have to split them
9c08d1fa 10311;; up again here.
10312
25f905c2 10313;; ??? Need to audit these splitters for Thumb-2. Why isn't normal
10314;; conditional execution sufficient?
10315
9c08d1fa 10316(define_split
10317 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 10318 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10319 [(match_operand 2 "" "") (match_operand 3 "" "")])
10320 (match_dup 0)
10321 (match_operand 4 "" "")))
bd5b4116 10322 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10323 "TARGET_ARM && reload_completed"
8fa3ba89 10324 [(set (match_dup 5) (match_dup 6))
10325 (cond_exec (match_dup 7)
10326 (set (match_dup 0) (match_dup 4)))]
10327 "
10328 {
3754d046 10329 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8fa3ba89 10330 operands[2], operands[3]);
10331 enum rtx_code rc = GET_CODE (operands[1]);
10332
bd5b4116 10333 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10334 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10335 if (mode == CCFPmode || mode == CCFPEmode)
10336 rc = reverse_condition_maybe_unordered (rc);
10337 else
10338 rc = reverse_condition (rc);
10339
10340 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
10341 }"
10342)
10343
10344(define_split
10345 [(set (match_operand:SI 0 "s_register_operand" "")
10346 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10347 [(match_operand 2 "" "") (match_operand 3 "" "")])
10348 (match_operand 4 "" "")
10349 (match_dup 0)))
bd5b4116 10350 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10351 "TARGET_ARM && reload_completed"
8fa3ba89 10352 [(set (match_dup 5) (match_dup 6))
10353 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
10354 (set (match_dup 0) (match_dup 4)))]
10355 "
10356 {
3754d046 10357 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8fa3ba89 10358 operands[2], operands[3]);
10359
bd5b4116 10360 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10361 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10362 }"
10363)
10364
10365(define_split
10366 [(set (match_operand:SI 0 "s_register_operand" "")
10367 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9c08d1fa 10368 [(match_operand 2 "" "") (match_operand 3 "" "")])
10369 (match_operand 4 "" "")
10370 (match_operand 5 "" "")))
bd5b4116 10371 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10372 "TARGET_ARM && reload_completed"
8fa3ba89 10373 [(set (match_dup 6) (match_dup 7))
10374 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10375 (set (match_dup 0) (match_dup 4)))
10376 (cond_exec (match_dup 8)
10377 (set (match_dup 0) (match_dup 5)))]
10378 "
10379 {
3754d046 10380 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8fa3ba89 10381 operands[2], operands[3]);
10382 enum rtx_code rc = GET_CODE (operands[1]);
10383
bd5b4116 10384 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10385 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10386 if (mode == CCFPmode || mode == CCFPEmode)
10387 rc = reverse_condition_maybe_unordered (rc);
10388 else
10389 rc = reverse_condition (rc);
10390
10391 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10392 }"
10393)
10394
cffb2a26 10395(define_split
10396 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 10397 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
cffb2a26 10398 [(match_operand:SI 2 "s_register_operand" "")
10399 (match_operand:SI 3 "arm_add_operand" "")])
10400 (match_operand:SI 4 "arm_rhs_operand" "")
10401 (not:SI
10402 (match_operand:SI 5 "s_register_operand" ""))))
bd5b4116 10403 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10404 "TARGET_ARM && reload_completed"
cffb2a26 10405 [(set (match_dup 6) (match_dup 7))
f6c53574 10406 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10407 (set (match_dup 0) (match_dup 4)))
10408 (cond_exec (match_dup 8)
10409 (set (match_dup 0) (not:SI (match_dup 5))))]
cffb2a26 10410 "
215b30b3 10411 {
3754d046 10412 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
215b30b3 10413 operands[2], operands[3]);
f6c53574 10414 enum rtx_code rc = GET_CODE (operands[1]);
cffb2a26 10415
bd5b4116 10416 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
1a83b3ff 10417 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
f6c53574 10418 if (mode == CCFPmode || mode == CCFPEmode)
10419 rc = reverse_condition_maybe_unordered (rc);
10420 else
10421 rc = reverse_condition (rc);
10422
10423 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
215b30b3 10424 }"
10425)
cffb2a26 10426
10427(define_insn "*cond_move_not"
10428 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10429 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
cffb2a26 10430 [(match_operand 3 "cc_register" "") (const_int 0)])
10431 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10432 (not:SI
10433 (match_operand:SI 2 "s_register_operand" "r,r"))))]
10434 "TARGET_ARM"
10435 "@
10436 mvn%D4\\t%0, %2
10437 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
0d66636f 10438 [(set_attr "conds" "use")
1b7da4ac 10439 (set_attr "type" "mvn_reg,multiple")
0d66636f 10440 (set_attr "length" "4,8")]
10441)
cffb2a26 10442
9c08d1fa 10443;; The next two patterns occur when an AND operation is followed by a
10444;; scc insn sequence
10445
f7fbdd4a 10446(define_insn "*sign_extract_onebit"
9c08d1fa 10447 [(set (match_operand:SI 0 "s_register_operand" "=r")
10448 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10449 (const_int 1)
ed750274 10450 (match_operand:SI 2 "const_int_operand" "n")))
10451 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10452 "TARGET_ARM"
9c08d1fa 10453 "*
0d66636f 10454 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10455 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
10456 return \"mvnne\\t%0, #0\";
10457 "
10458 [(set_attr "conds" "clob")
1b7da4ac 10459 (set_attr "length" "8")
10460 (set_attr "type" "multiple")]
0d66636f 10461)
9c08d1fa 10462
f7fbdd4a 10463(define_insn "*not_signextract_onebit"
9c08d1fa 10464 [(set (match_operand:SI 0 "s_register_operand" "=r")
10465 (not:SI
10466 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10467 (const_int 1)
ed750274 10468 (match_operand:SI 2 "const_int_operand" "n"))))
10469 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10470 "TARGET_ARM"
9c08d1fa 10471 "*
0d66636f 10472 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10473 output_asm_insn (\"tst\\t%1, %2\", operands);
10474 output_asm_insn (\"mvneq\\t%0, #0\", operands);
10475 return \"movne\\t%0, #0\";
10476 "
10477 [(set_attr "conds" "clob")
1b7da4ac 10478 (set_attr "length" "12")
10479 (set_attr "type" "multiple")]
0d66636f 10480)
25f905c2 10481;; ??? The above patterns need auditing for Thumb-2
87b22bf7 10482
0d66636f 10483;; Push multiple registers to the stack. Registers are in parallel (use ...)
10484;; expressions. For simplicity, the first register is also in the unspec
10485;; part.
08508cbf 10486;; To avoid the usage of GNU extension, the length attribute is computed
10487;; in a C function arm_attr_length_push_multi.
f7fbdd4a 10488(define_insn "*push_multi"
87b22bf7 10489 [(match_parallel 2 "multi_register_push"
7571d3f7 10490 [(set (match_operand:BLK 0 "push_mult_memory_operand" "")
3cc80a30 10491 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "")]
e1159bbe 10492 UNSPEC_PUSH_MULT))])]
7571d3f7 10493 ""
87b22bf7 10494 "*
215b30b3 10495 {
10496 int num_saves = XVECLEN (operands[2], 0);
ed593f11 10497
215b30b3 10498 /* For the StrongARM at least it is faster to
25f905c2 10499 use STR to store only a single register.
542d5028 10500 In Thumb mode always use push, and the assembler will pick
10501 something appropriate. */
25f905c2 10502 if (num_saves == 1 && TARGET_ARM)
61309563 10503 output_asm_insn (\"str%?\\t%1, [%m0, #-4]!\", operands);
215b30b3 10504 else
10505 {
10506 int i;
10507 char pattern[100];
ed593f11 10508
3ef90e77 10509 if (TARGET_32BIT)
61309563 10510 strcpy (pattern, \"push%?\\t{%1\");
25f905c2 10511 else
10512 strcpy (pattern, \"push\\t{%1\");
215b30b3 10513
6079f055 10514 for (i = 1; i < num_saves; i++)
215b30b3 10515 {
10516 strcat (pattern, \", %|\");
10517 strcat (pattern,
10518 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
10519 }
10520
10521 strcat (pattern, \"}\");
10522 output_asm_insn (pattern, operands);
10523 }
10524
10525 return \"\";
10526 }"
a6864a24 10527 [(set_attr "type" "store4")
10528 (set (attr "length")
08508cbf 10529 (symbol_ref "arm_attr_length_push_multi (operands[2], operands[1])"))]
215b30b3 10530)
f7fbdd4a 10531
4c58c898 10532(define_insn "stack_tie"
10533 [(set (mem:BLK (scratch))
aaa37ad6 10534 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "rk")
10535 (match_operand:SI 1 "s_register_operand" "rk")]
4c58c898 10536 UNSPEC_PRLG_STK))]
10537 ""
10538 ""
1b7da4ac 10539 [(set_attr "length" "0")
10540 (set_attr "type" "block")]
4c58c898 10541)
10542
426be8c5 10543;; Pop (as used in epilogue RTL)
10544;;
10545(define_insn "*load_multiple_with_writeback"
10546 [(match_parallel 0 "load_multiple_operation"
10547 [(set (match_operand:SI 1 "s_register_operand" "+rk")
10548 (plus:SI (match_dup 1)
809003b3 10549 (match_operand:SI 2 "const_int_I_operand" "I")))
426be8c5 10550 (set (match_operand:SI 3 "s_register_operand" "=rk")
10551 (mem:SI (match_dup 1)))
10552 ])]
10553 "TARGET_32BIT && (reload_in_progress || reload_completed)"
10554 "*
10555 {
10556 arm_output_multireg_pop (operands, /*return_pc=*/false,
10557 /*cond=*/const_true_rtx,
10558 /*reverse=*/false,
10559 /*update=*/true);
10560 return \"\";
10561 }
10562 "
10563 [(set_attr "type" "load4")
10564 (set_attr "predicable" "yes")]
10565)
10566
10567;; Pop with return (as used in epilogue RTL)
10568;;
10569;; This instruction is generated when the registers are popped at the end of
10570;; epilogue. Here, instead of popping the value into LR and then generating
10571;; jump to LR, value is popped into PC directly. Hence, the pattern is combined
10572;; with (return).
10573(define_insn "*pop_multiple_with_writeback_and_return"
10574 [(match_parallel 0 "pop_multiple_return"
10575 [(return)
10576 (set (match_operand:SI 1 "s_register_operand" "+rk")
10577 (plus:SI (match_dup 1)
809003b3 10578 (match_operand:SI 2 "const_int_I_operand" "I")))
426be8c5 10579 (set (match_operand:SI 3 "s_register_operand" "=rk")
10580 (mem:SI (match_dup 1)))
10581 ])]
10582 "TARGET_32BIT && (reload_in_progress || reload_completed)"
10583 "*
10584 {
10585 arm_output_multireg_pop (operands, /*return_pc=*/true,
10586 /*cond=*/const_true_rtx,
10587 /*reverse=*/false,
10588 /*update=*/true);
10589 return \"\";
10590 }
10591 "
10592 [(set_attr "type" "load4")
10593 (set_attr "predicable" "yes")]
10594)
10595
10596(define_insn "*pop_multiple_with_return"
10597 [(match_parallel 0 "pop_multiple_return"
10598 [(return)
10599 (set (match_operand:SI 2 "s_register_operand" "=rk")
10600 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
10601 ])]
10602 "TARGET_32BIT && (reload_in_progress || reload_completed)"
10603 "*
10604 {
10605 arm_output_multireg_pop (operands, /*return_pc=*/true,
10606 /*cond=*/const_true_rtx,
10607 /*reverse=*/false,
10608 /*update=*/false);
10609 return \"\";
10610 }
10611 "
10612 [(set_attr "type" "load4")
10613 (set_attr "predicable" "yes")]
10614)
10615
10616;; Load into PC and return
10617(define_insn "*ldr_with_return"
10618 [(return)
10619 (set (reg:SI PC_REGNUM)
10620 (mem:SI (post_inc:SI (match_operand:SI 0 "s_register_operand" "+rk"))))]
10621 "TARGET_32BIT && (reload_in_progress || reload_completed)"
10622 "ldr%?\t%|pc, [%0], #4"
10623 [(set_attr "type" "load1")
10624 (set_attr "predicable" "yes")]
10625)
1a0b0f12 10626;; Pop for floating point registers (as used in epilogue RTL)
10627(define_insn "*vfp_pop_multiple_with_writeback"
10628 [(match_parallel 0 "pop_multiple_fp"
10629 [(set (match_operand:SI 1 "s_register_operand" "+rk")
10630 (plus:SI (match_dup 1)
809003b3 10631 (match_operand:SI 2 "const_int_I_operand" "I")))
2f2163a4 10632 (set (match_operand:DF 3 "vfp_hard_register_operand" "")
1a0b0f12 10633 (mem:DF (match_dup 1)))])]
10634 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
10635 "*
10636 {
10637 int num_regs = XVECLEN (operands[0], 0);
10638 char pattern[100];
10639 rtx op_list[2];
b34d8dac 10640 strcpy (pattern, \"vldm\\t\");
1a0b0f12 10641 strcat (pattern, reg_names[REGNO (SET_DEST (XVECEXP (operands[0], 0, 0)))]);
10642 strcat (pattern, \"!, {\");
10643 op_list[0] = XEXP (XVECEXP (operands[0], 0, 1), 0);
10644 strcat (pattern, \"%P0\");
10645 if ((num_regs - 1) > 1)
10646 {
10647 strcat (pattern, \"-%P1\");
10648 op_list [1] = XEXP (XVECEXP (operands[0], 0, num_regs - 1), 0);
10649 }
10650
10651 strcat (pattern, \"}\");
10652 output_asm_insn (pattern, op_list);
10653 return \"\";
10654 }
10655 "
10656 [(set_attr "type" "load4")
10657 (set_attr "conds" "unconditional")
10658 (set_attr "predicable" "no")]
10659)
10660
f7fbdd4a 10661;; Special patterns for dealing with the constant pool
10662
cffb2a26 10663(define_insn "align_4"
e1159bbe 10664 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
cffb2a26 10665 "TARGET_EITHER"
f7fbdd4a 10666 "*
cffb2a26 10667 assemble_align (32);
f7fbdd4a 10668 return \"\";
cffb2a26 10669 "
1b7da4ac 10670 [(set_attr "type" "no_insn")]
cffb2a26 10671)
f7fbdd4a 10672
755eb2b4 10673(define_insn "align_8"
10674 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
f9273c43 10675 "TARGET_EITHER"
755eb2b4 10676 "*
10677 assemble_align (64);
10678 return \"\";
10679 "
1b7da4ac 10680 [(set_attr "type" "no_insn")]
755eb2b4 10681)
10682
cffb2a26 10683(define_insn "consttable_end"
e1159bbe 10684 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
cffb2a26 10685 "TARGET_EITHER"
f7fbdd4a 10686 "*
cffb2a26 10687 making_const_table = FALSE;
f7fbdd4a 10688 return \"\";
cffb2a26 10689 "
1b7da4ac 10690 [(set_attr "type" "no_insn")]
cffb2a26 10691)
f7fbdd4a 10692
0e207eb8 10693(define_insn "consttable_1"
10694 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
10695 "TARGET_EITHER"
10696 "*
10697 making_const_table = TRUE;
10698 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
10699 assemble_zeros (3);
10700 return \"\";
10701 "
10702 [(set_attr "length" "4")
10703 (set_attr "type" "no_insn")]
10704)
10705
10706(define_insn "consttable_2"
10707 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
10708 "TARGET_EITHER"
10709 "*
10710 {
10711 rtx x = operands[0];
10712 making_const_table = TRUE;
10713 switch (GET_MODE_CLASS (GET_MODE (x)))
10714 {
10715 case MODE_FLOAT:
10716 arm_emit_fp16_const (x);
10717 break;
10718 default:
10719 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
10720 assemble_zeros (2);
10721 break;
10722 }
10723 return \"\";
10724 }"
10725 [(set_attr "length" "4")
10726 (set_attr "type" "no_insn")]
10727)
10728
cffb2a26 10729(define_insn "consttable_4"
e1159bbe 10730 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
cffb2a26 10731 "TARGET_EITHER"
10732 "*
10733 {
9b8516be 10734 rtx x = operands[0];
cffb2a26 10735 making_const_table = TRUE;
9b8516be 10736 switch (GET_MODE_CLASS (GET_MODE (x)))
cffb2a26 10737 {
10738 case MODE_FLOAT:
945f7b03 10739 assemble_real (*CONST_DOUBLE_REAL_VALUE (x), GET_MODE (x),
10740 BITS_PER_WORD);
10741 break;
cffb2a26 10742 default:
7b04c5d5 10743 /* XXX: Sometimes gcc does something really dumb and ends up with
10744 a HIGH in a constant pool entry, usually because it's trying to
10745 load into a VFP register. We know this will always be used in
10746 combination with a LO_SUM which ignores the high bits, so just
10747 strip off the HIGH. */
10748 if (GET_CODE (x) == HIGH)
10749 x = XEXP (x, 0);
9b8516be 10750 assemble_integer (x, 4, BITS_PER_WORD, 1);
10751 mark_symbol_refs_as_used (x);
cffb2a26 10752 break;
10753 }
10754 return \"\";
10755 }"
1b7da4ac 10756 [(set_attr "length" "4")
10757 (set_attr "type" "no_insn")]
cffb2a26 10758)
10759
10760(define_insn "consttable_8"
e1159bbe 10761 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
cffb2a26 10762 "TARGET_EITHER"
10763 "*
10764 {
10765 making_const_table = TRUE;
10766 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10767 {
945f7b03 10768 case MODE_FLOAT:
10769 assemble_real (*CONST_DOUBLE_REAL_VALUE (operands[0]),
10770 GET_MODE (operands[0]), BITS_PER_WORD);
10771 break;
cffb2a26 10772 default:
09d688ff 10773 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
cffb2a26 10774 break;
10775 }
10776 return \"\";
10777 }"
1b7da4ac 10778 [(set_attr "length" "8")
10779 (set_attr "type" "no_insn")]
cffb2a26 10780)
10781
d98a3884 10782(define_insn "consttable_16"
10783 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_16)]
10784 "TARGET_EITHER"
10785 "*
10786 {
10787 making_const_table = TRUE;
10788 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10789 {
945f7b03 10790 case MODE_FLOAT:
10791 assemble_real (*CONST_DOUBLE_REAL_VALUE (operands[0]),
10792 GET_MODE (operands[0]), BITS_PER_WORD);
10793 break;
d98a3884 10794 default:
10795 assemble_integer (operands[0], 16, BITS_PER_WORD, 1);
10796 break;
10797 }
10798 return \"\";
10799 }"
1b7da4ac 10800 [(set_attr "length" "16")
10801 (set_attr "type" "no_insn")]
d98a3884 10802)
10803
331beb1a 10804;; V5 Instructions,
10805
8f4be2be 10806(define_insn "clzsi2"
10807 [(set (match_operand:SI 0 "s_register_operand" "=r")
10808 (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 10809 "TARGET_32BIT && arm_arch5"
ee7cbe0e 10810 "clz%?\\t%0, %1"
bcaec148 10811 [(set_attr "predicable" "yes")
4a510717 10812 (set_attr "predicable_short_it" "no")
bebe9bbb 10813 (set_attr "type" "clz")])
331beb1a 10814
099ad98b 10815(define_insn "rbitsi2"
10816 [(set (match_operand:SI 0 "s_register_operand" "=r")
10817 (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")] UNSPEC_RBIT))]
10818 "TARGET_32BIT && arm_arch_thumb2"
10819 "rbit%?\\t%0, %1"
10820 [(set_attr "predicable" "yes")
4a510717 10821 (set_attr "predicable_short_it" "no")
bebe9bbb 10822 (set_attr "type" "clz")])
099ad98b 10823
10824(define_expand "ctzsi2"
10825 [(set (match_operand:SI 0 "s_register_operand" "")
10826 (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
10827 "TARGET_32BIT && arm_arch_thumb2"
10828 "
30191172 10829 {
10830 rtx tmp = gen_reg_rtx (SImode);
10831 emit_insn (gen_rbitsi2 (tmp, operands[1]));
10832 emit_insn (gen_clzsi2 (operands[0], tmp));
10833 }
099ad98b 10834 DONE;
10835 "
10836)
10837
e1159bbe 10838;; V5E instructions.
331beb1a 10839
10840(define_insn "prefetch"
f4e79814 10841 [(prefetch (match_operand:SI 0 "address_operand" "p")
10842 (match_operand:SI 1 "" "")
10843 (match_operand:SI 2 "" ""))]
25f905c2 10844 "TARGET_32BIT && arm_arch5e"
1b7da4ac 10845 "pld\\t%a0"
10846 [(set_attr "type" "load1")]
10847)
331beb1a 10848
0d66636f 10849;; General predication pattern
10850
10851(define_cond_exec
10852 [(match_operator 0 "arm_comparison_operator"
10853 [(match_operand 1 "cc_register" "")
10854 (const_int 0)])]
580f4c48 10855 "TARGET_32BIT
10856 && (!TARGET_NO_VOLATILE_CE || !volatile_refs_p (PATTERN (insn)))"
0d66636f 10857 ""
c7a58118 10858[(set_attr "predicated" "yes")]
0d66636f 10859)
10860
fb94f18b 10861(define_insn "force_register_use"
10862 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_REGISTER_USE)]
063a05c7 10863 ""
fb94f18b 10864 "%@ %0 needed"
1b7da4ac 10865 [(set_attr "length" "0")
10866 (set_attr "type" "no_insn")]
063a05c7 10867)
7db9af5d 10868
4c44712e 10869
10870;; Patterns for exception handling
10871
10872(define_expand "eh_return"
10873 [(use (match_operand 0 "general_operand" ""))]
10874 "TARGET_EITHER"
10875 "
10876 {
25f905c2 10877 if (TARGET_32BIT)
4c44712e 10878 emit_insn (gen_arm_eh_return (operands[0]));
10879 else
10880 emit_insn (gen_thumb_eh_return (operands[0]));
10881 DONE;
10882 }"
10883)
10884
10885;; We can't expand this before we know where the link register is stored.
10886(define_insn_and_split "arm_eh_return"
10887 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
10888 VUNSPEC_EH_RETURN)
10889 (clobber (match_scratch:SI 1 "=&r"))]
10890 "TARGET_ARM"
10891 "#"
10892 "&& reload_completed"
10893 [(const_int 0)]
10894 "
10895 {
10896 arm_set_return_address (operands[0], operands[1]);
10897 DONE;
10898 }"
10899)
10900
f655717d 10901\f
10902;; TLS support
10903
10904(define_insn "load_tp_hard"
10905 [(set (match_operand:SI 0 "register_operand" "=r")
10906 (unspec:SI [(const_int 0)] UNSPEC_TLS))]
10907 "TARGET_HARD_TP"
10908 "mrc%?\\tp15, 0, %0, c13, c0, 3\\t@ load_tp_hard"
1b7da4ac 10909 [(set_attr "predicable" "yes")
4b5d7374 10910 (set_attr "type" "mrs")]
f655717d 10911)
10912
10913;; Doesn't clobber R1-R3. Must use r0 for the first operand.
10914(define_insn "load_tp_soft"
10915 [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
10916 (clobber (reg:SI LR_REGNUM))
10917 (clobber (reg:SI IP_REGNUM))
10918 (clobber (reg:CC CC_REGNUM))]
10919 "TARGET_SOFT_TP"
10920 "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
1b7da4ac 10921 [(set_attr "conds" "clob")
10922 (set_attr "type" "branch")]
f655717d 10923)
10924
f41e4452 10925;; tls descriptor call
10926(define_insn "tlscall"
10927 [(set (reg:SI R0_REGNUM)
10928 (unspec:SI [(reg:SI R0_REGNUM)
10929 (match_operand:SI 0 "" "X")
10930 (match_operand 1 "" "")] UNSPEC_TLS))
10931 (clobber (reg:SI R1_REGNUM))
10932 (clobber (reg:SI LR_REGNUM))
10933 (clobber (reg:SI CC_REGNUM))]
10934 "TARGET_GNU2_TLS"
10935 {
10936 targetm.asm_out.internal_label (asm_out_file, "LPIC",
10937 INTVAL (operands[1]));
10938 return "bl\\t%c0(tlscall)";
10939 }
10940 [(set_attr "conds" "clob")
1b7da4ac 10941 (set_attr "length" "4")
10942 (set_attr "type" "branch")]
f41e4452 10943)
10944
1fe0edab 10945;; For thread pointer builtin
10946(define_expand "get_thread_pointersi"
10947 [(match_operand:SI 0 "s_register_operand" "=r")]
10948 ""
10949 "
10950 {
10951 arm_load_tp (operands[0]);
10952 DONE;
10953 }")
10954
f41e4452 10955;;
10956
aabe09ac 10957;; We only care about the lower 16 bits of the constant
10958;; being inserted into the upper 16 bits of the register.
eca5c984 10959(define_insn "*arm_movtas_ze"
10960 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
10961 (const_int 16)
10962 (const_int 16))
10963 (match_operand:SI 1 "const_int_operand" ""))]
181ab277 10964 "arm_arch_thumb2"
aabe09ac 10965 "movt%?\t%0, %L1"
eca5c984 10966 [(set_attr "predicable" "yes")
7c36fe71 10967 (set_attr "predicable_short_it" "no")
1b7da4ac 10968 (set_attr "length" "4")
282b4c75 10969 (set_attr "type" "alu_sreg")]
eca5c984 10970)
10971
c0fc3696 10972(define_insn "*arm_rev"
a486b499 10973 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
10974 (bswap:SI (match_operand:SI 1 "s_register_operand" "l,l,r")))]
10975 "arm_arch6"
10976 "@
10977 rev\t%0, %1
10978 rev%?\t%0, %1
10979 rev%?\t%0, %1"
10980 [(set_attr "arch" "t1,t2,32")
1b7da4ac 10981 (set_attr "length" "2,2,4")
4a510717 10982 (set_attr "predicable" "no,yes,yes")
10983 (set_attr "predicable_short_it" "no")
1b7da4ac 10984 (set_attr "type" "rev")]
ff82f757 10985)
10986
10987(define_expand "arm_legacy_rev"
10988 [(set (match_operand:SI 2 "s_register_operand" "")
10989 (xor:SI (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
10990 (const_int 16))
10991 (match_dup 1)))
10992 (set (match_dup 2)
10993 (lshiftrt:SI (match_dup 2)
10994 (const_int 8)))
10995 (set (match_operand:SI 3 "s_register_operand" "")
10996 (rotatert:SI (match_dup 1)
10997 (const_int 8)))
10998 (set (match_dup 2)
10999 (and:SI (match_dup 2)
11000 (const_int -65281)))
11001 (set (match_operand:SI 0 "s_register_operand" "")
11002 (xor:SI (match_dup 3)
11003 (match_dup 2)))]
11004 "TARGET_32BIT"
11005 ""
11006)
11007
11008;; Reuse temporaries to keep register pressure down.
11009(define_expand "thumb_legacy_rev"
11010 [(set (match_operand:SI 2 "s_register_operand" "")
11011 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
11012 (const_int 24)))
11013 (set (match_operand:SI 3 "s_register_operand" "")
11014 (lshiftrt:SI (match_dup 1)
11015 (const_int 24)))
11016 (set (match_dup 3)
11017 (ior:SI (match_dup 3)
11018 (match_dup 2)))
11019 (set (match_operand:SI 4 "s_register_operand" "")
11020 (const_int 16))
11021 (set (match_operand:SI 5 "s_register_operand" "")
11022 (rotatert:SI (match_dup 1)
11023 (match_dup 4)))
11024 (set (match_dup 2)
11025 (ashift:SI (match_dup 5)
11026 (const_int 24)))
11027 (set (match_dup 5)
11028 (lshiftrt:SI (match_dup 5)
11029 (const_int 24)))
11030 (set (match_dup 5)
11031 (ior:SI (match_dup 5)
11032 (match_dup 2)))
11033 (set (match_dup 5)
11034 (rotatert:SI (match_dup 5)
11035 (match_dup 4)))
11036 (set (match_operand:SI 0 "s_register_operand" "")
11037 (ior:SI (match_dup 5)
11038 (match_dup 3)))]
11039 "TARGET_THUMB"
11040 ""
11041)
11042
62e39b06 11043;; ARM-specific expansion of signed mod by power of 2
11044;; using conditional negate.
11045;; For r0 % n where n is a power of 2 produce:
11046;; rsbs r1, r0, #0
11047;; and r0, r0, #(n - 1)
11048;; and r1, r1, #(n - 1)
11049;; rsbpl r0, r1, #0
11050
11051(define_expand "modsi3"
11052 [(match_operand:SI 0 "register_operand" "")
11053 (match_operand:SI 1 "register_operand" "")
11054 (match_operand:SI 2 "const_int_operand" "")]
11055 "TARGET_32BIT"
11056 {
11057 HOST_WIDE_INT val = INTVAL (operands[2]);
11058
11059 if (val <= 0
11060 || exact_log2 (val) <= 0)
11061 FAIL;
11062
11063 rtx mask = GEN_INT (val - 1);
11064
11065 /* In the special case of x0 % 2 we can do the even shorter:
11066 cmp r0, #0
11067 and r0, r0, #1
11068 rsblt r0, r0, #0. */
11069
11070 if (val == 2)
11071 {
11072 rtx cc_reg = arm_gen_compare_reg (LT,
11073 operands[1], const0_rtx, NULL_RTX);
11074 rtx cond = gen_rtx_LT (SImode, cc_reg, const0_rtx);
11075 rtx masked = gen_reg_rtx (SImode);
11076
11077 emit_insn (gen_andsi3 (masked, operands[1], mask));
11078 emit_move_insn (operands[0],
11079 gen_rtx_IF_THEN_ELSE (SImode, cond,
11080 gen_rtx_NEG (SImode,
11081 masked),
11082 masked));
11083 DONE;
11084 }
11085
11086 rtx neg_op = gen_reg_rtx (SImode);
11087 rtx_insn *insn = emit_insn (gen_subsi3_compare0 (neg_op, const0_rtx,
11088 operands[1]));
11089
11090 /* Extract the condition register and mode. */
11091 rtx cmp = XVECEXP (PATTERN (insn), 0, 0);
11092 rtx cc_reg = SET_DEST (cmp);
11093 rtx cond = gen_rtx_GE (SImode, cc_reg, const0_rtx);
11094
11095 emit_insn (gen_andsi3 (operands[0], operands[1], mask));
11096
11097 rtx masked_neg = gen_reg_rtx (SImode);
11098 emit_insn (gen_andsi3 (masked_neg, neg_op, mask));
11099
11100 /* We want a conditional negate here, but emitting COND_EXEC rtxes
11101 during expand does not always work. Do an IF_THEN_ELSE instead. */
11102 emit_move_insn (operands[0],
11103 gen_rtx_IF_THEN_ELSE (SImode, cond,
11104 gen_rtx_NEG (SImode, masked_neg),
11105 operands[0]));
11106
11107
11108 DONE;
11109 }
11110)
11111
ff82f757 11112(define_expand "bswapsi2"
11113 [(set (match_operand:SI 0 "s_register_operand" "=r")
11114 (bswap:SI (match_operand:SI 1 "s_register_operand" "r")))]
8d1af482 11115"TARGET_EITHER && (arm_arch6 || !optimize_size)"
ff82f757 11116"
8d1af482 11117 if (!arm_arch6)
11118 {
11119 rtx op2 = gen_reg_rtx (SImode);
11120 rtx op3 = gen_reg_rtx (SImode);
ff82f757 11121
8d1af482 11122 if (TARGET_THUMB)
11123 {
11124 rtx op4 = gen_reg_rtx (SImode);
11125 rtx op5 = gen_reg_rtx (SImode);
ff82f757 11126
8d1af482 11127 emit_insn (gen_thumb_legacy_rev (operands[0], operands[1],
11128 op2, op3, op4, op5));
11129 }
11130 else
11131 {
11132 emit_insn (gen_arm_legacy_rev (operands[0], operands[1],
11133 op2, op3));
11134 }
ff82f757 11135
8d1af482 11136 DONE;
11137 }
ff82f757 11138 "
11139)
11140
a486b499 11141;; bswap16 patterns: use revsh and rev16 instructions for the signed
11142;; and unsigned variants, respectively. For rev16, expose
11143;; byte-swapping in the lower 16 bits only.
11144(define_insn "*arm_revsh"
11145 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
11146 (sign_extend:SI (bswap:HI (match_operand:HI 1 "s_register_operand" "l,l,r"))))]
11147 "arm_arch6"
11148 "@
11149 revsh\t%0, %1
11150 revsh%?\t%0, %1
11151 revsh%?\t%0, %1"
11152 [(set_attr "arch" "t1,t2,32")
1b7da4ac 11153 (set_attr "length" "2,2,4")
11154 (set_attr "type" "rev")]
a486b499 11155)
11156
11157(define_insn "*arm_rev16"
11158 [(set (match_operand:HI 0 "s_register_operand" "=l,l,r")
11159 (bswap:HI (match_operand:HI 1 "s_register_operand" "l,l,r")))]
11160 "arm_arch6"
11161 "@
11162 rev16\t%0, %1
11163 rev16%?\t%0, %1
11164 rev16%?\t%0, %1"
11165 [(set_attr "arch" "t1,t2,32")
1b7da4ac 11166 (set_attr "length" "2,2,4")
11167 (set_attr "type" "rev")]
09f69e55 11168)
11169
11170;; There are no canonicalisation rules for the position of the lshiftrt, ashift
11171;; operations within an IOR/AND RTX, therefore we have two patterns matching
11172;; each valid permutation.
11173
11174(define_insn "arm_rev16si2"
11175 [(set (match_operand:SI 0 "register_operand" "=l,l,r")
11176 (ior:SI (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "l,l,r")
11177 (const_int 8))
11178 (match_operand:SI 3 "const_int_operand" "n,n,n"))
11179 (and:SI (lshiftrt:SI (match_dup 1)
11180 (const_int 8))
11181 (match_operand:SI 2 "const_int_operand" "n,n,n"))))]
11182 "arm_arch6
11183 && aarch_rev16_shleft_mask_imm_p (operands[3], SImode)
11184 && aarch_rev16_shright_mask_imm_p (operands[2], SImode)"
11185 "rev16\\t%0, %1"
11186 [(set_attr "arch" "t1,t2,32")
11187 (set_attr "length" "2,2,4")
11188 (set_attr "type" "rev")]
11189)
11190
11191(define_insn "arm_rev16si2_alt"
11192 [(set (match_operand:SI 0 "register_operand" "=l,l,r")
11193 (ior:SI (and:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,l,r")
11194 (const_int 8))
11195 (match_operand:SI 2 "const_int_operand" "n,n,n"))
11196 (and:SI (ashift:SI (match_dup 1)
11197 (const_int 8))
11198 (match_operand:SI 3 "const_int_operand" "n,n,n"))))]
11199 "arm_arch6
11200 && aarch_rev16_shleft_mask_imm_p (operands[3], SImode)
11201 && aarch_rev16_shright_mask_imm_p (operands[2], SImode)"
11202 "rev16\\t%0, %1"
11203 [(set_attr "arch" "t1,t2,32")
11204 (set_attr "length" "2,2,4")
11205 (set_attr "type" "rev")]
a486b499 11206)
11207
11208(define_expand "bswaphi2"
11209 [(set (match_operand:HI 0 "s_register_operand" "=r")
11210 (bswap:HI (match_operand:HI 1 "s_register_operand" "r")))]
11211"arm_arch6"
11212""
11213)
11214
1653cf17 11215;; Patterns for LDRD/STRD in Thumb2 mode
11216
11217(define_insn "*thumb2_ldrd"
11218 [(set (match_operand:SI 0 "s_register_operand" "=r")
11219 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
11220 (match_operand:SI 2 "ldrd_strd_offset_operand" "Do"))))
11221 (set (match_operand:SI 3 "s_register_operand" "=r")
11222 (mem:SI (plus:SI (match_dup 1)
11223 (match_operand:SI 4 "const_int_operand" ""))))]
11224 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11225 && current_tune->prefer_ldrd_strd
11226 && ((INTVAL (operands[2]) + 4) == INTVAL (operands[4]))
11227 && (operands_ok_ldrd_strd (operands[0], operands[3],
11228 operands[1], INTVAL (operands[2]),
11229 false, true))"
11230 "ldrd%?\t%0, %3, [%1, %2]"
11231 [(set_attr "type" "load2")
d952d547 11232 (set_attr "predicable" "yes")
11233 (set_attr "predicable_short_it" "no")])
1653cf17 11234
11235(define_insn "*thumb2_ldrd_base"
11236 [(set (match_operand:SI 0 "s_register_operand" "=r")
11237 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
11238 (set (match_operand:SI 2 "s_register_operand" "=r")
11239 (mem:SI (plus:SI (match_dup 1)
11240 (const_int 4))))]
11241 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11242 && current_tune->prefer_ldrd_strd
11243 && (operands_ok_ldrd_strd (operands[0], operands[2],
11244 operands[1], 0, false, true))"
11245 "ldrd%?\t%0, %2, [%1]"
11246 [(set_attr "type" "load2")
d952d547 11247 (set_attr "predicable" "yes")
11248 (set_attr "predicable_short_it" "no")])
1653cf17 11249
11250(define_insn "*thumb2_ldrd_base_neg"
11251 [(set (match_operand:SI 0 "s_register_operand" "=r")
11252 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
11253 (const_int -4))))
11254 (set (match_operand:SI 2 "s_register_operand" "=r")
11255 (mem:SI (match_dup 1)))]
11256 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11257 && current_tune->prefer_ldrd_strd
11258 && (operands_ok_ldrd_strd (operands[0], operands[2],
11259 operands[1], -4, false, true))"
11260 "ldrd%?\t%0, %2, [%1, #-4]"
11261 [(set_attr "type" "load2")
d952d547 11262 (set_attr "predicable" "yes")
11263 (set_attr "predicable_short_it" "no")])
1653cf17 11264
11265(define_insn "*thumb2_strd"
11266 [(set (mem:SI (plus:SI (match_operand:SI 0 "s_register_operand" "rk")
11267 (match_operand:SI 1 "ldrd_strd_offset_operand" "Do")))
11268 (match_operand:SI 2 "s_register_operand" "r"))
11269 (set (mem:SI (plus:SI (match_dup 0)
11270 (match_operand:SI 3 "const_int_operand" "")))
11271 (match_operand:SI 4 "s_register_operand" "r"))]
11272 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11273 && current_tune->prefer_ldrd_strd
11274 && ((INTVAL (operands[1]) + 4) == INTVAL (operands[3]))
11275 && (operands_ok_ldrd_strd (operands[2], operands[4],
11276 operands[0], INTVAL (operands[1]),
11277 false, false))"
11278 "strd%?\t%2, %4, [%0, %1]"
11279 [(set_attr "type" "store2")
d952d547 11280 (set_attr "predicable" "yes")
11281 (set_attr "predicable_short_it" "no")])
1653cf17 11282
11283(define_insn "*thumb2_strd_base"
11284 [(set (mem:SI (match_operand:SI 0 "s_register_operand" "rk"))
11285 (match_operand:SI 1 "s_register_operand" "r"))
11286 (set (mem:SI (plus:SI (match_dup 0)
11287 (const_int 4)))
11288 (match_operand:SI 2 "s_register_operand" "r"))]
11289 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11290 && current_tune->prefer_ldrd_strd
11291 && (operands_ok_ldrd_strd (operands[1], operands[2],
11292 operands[0], 0, false, false))"
11293 "strd%?\t%1, %2, [%0]"
11294 [(set_attr "type" "store2")
d952d547 11295 (set_attr "predicable" "yes")
11296 (set_attr "predicable_short_it" "no")])
1653cf17 11297
11298(define_insn "*thumb2_strd_base_neg"
11299 [(set (mem:SI (plus:SI (match_operand:SI 0 "s_register_operand" "rk")
11300 (const_int -4)))
11301 (match_operand:SI 1 "s_register_operand" "r"))
11302 (set (mem:SI (match_dup 0))
11303 (match_operand:SI 2 "s_register_operand" "r"))]
11304 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11305 && current_tune->prefer_ldrd_strd
11306 && (operands_ok_ldrd_strd (operands[1], operands[2],
11307 operands[0], -4, false, false))"
11308 "strd%?\t%1, %2, [%0, #-4]"
11309 [(set_attr "type" "store2")
d952d547 11310 (set_attr "predicable" "yes")
11311 (set_attr "predicable_short_it" "no")])
1653cf17 11312
2a0c73f2 11313;; ARMv8 CRC32 instructions.
11314(define_insn "<crc_variant>"
11315 [(set (match_operand:SI 0 "s_register_operand" "=r")
11316 (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")
11317 (match_operand:<crc_mode> 2 "s_register_operand" "r")]
11318 CRC))]
11319 "TARGET_CRC32"
11320 "<crc_variant>\\t%0, %1, %2"
11321 [(set_attr "type" "crc")
11322 (set_attr "conds" "unconditional")]
11323)
1653cf17 11324
353cf59a 11325;; Load the load/store double peephole optimizations.
11326(include "ldrdstrd.md")
11327
320ea44d 11328;; Load the load/store multiple patterns
11329(include "ldmstm.md")
426be8c5 11330
11331;; Patterns in ldmstm.md don't cover more than 4 registers. This pattern covers
11332;; large lists without explicit writeback generated for APCS_FRAME epilogue.
11333(define_insn "*load_multiple"
11334 [(match_parallel 0 "load_multiple_operation"
11335 [(set (match_operand:SI 2 "s_register_operand" "=rk")
11336 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
11337 ])]
11338 "TARGET_32BIT"
11339 "*
11340 {
11341 arm_output_multireg_pop (operands, /*return_pc=*/false,
11342 /*cond=*/const_true_rtx,
11343 /*reverse=*/false,
11344 /*update=*/false);
11345 return \"\";
11346 }
11347 "
11348 [(set_attr "predicable" "yes")]
11349)
11350
84450ddc 11351(define_expand "copysignsf3"
11352 [(match_operand:SF 0 "register_operand")
11353 (match_operand:SF 1 "register_operand")
11354 (match_operand:SF 2 "register_operand")]
11355 "TARGET_SOFT_FLOAT && arm_arch_thumb2"
11356 "{
11357 emit_move_insn (operands[0], operands[2]);
11358 emit_insn (gen_insv_t2 (simplify_gen_subreg (SImode, operands[0], SFmode, 0),
11359 GEN_INT (31), GEN_INT (0),
11360 simplify_gen_subreg (SImode, operands[1], SFmode, 0)));
11361 DONE;
11362 }"
11363)
11364
11365(define_expand "copysigndf3"
11366 [(match_operand:DF 0 "register_operand")
11367 (match_operand:DF 1 "register_operand")
11368 (match_operand:DF 2 "register_operand")]
11369 "TARGET_SOFT_FLOAT && arm_arch_thumb2"
11370 "{
11371 rtx op0_low = gen_lowpart (SImode, operands[0]);
11372 rtx op0_high = gen_highpart (SImode, operands[0]);
11373 rtx op1_low = gen_lowpart (SImode, operands[1]);
11374 rtx op1_high = gen_highpart (SImode, operands[1]);
11375 rtx op2_high = gen_highpart (SImode, operands[2]);
11376
11377 rtx scratch1 = gen_reg_rtx (SImode);
11378 rtx scratch2 = gen_reg_rtx (SImode);
11379 emit_move_insn (scratch1, op2_high);
11380 emit_move_insn (scratch2, op1_high);
11381
d1f9b275 11382 emit_insn(gen_rtx_SET(scratch1,
84450ddc 11383 gen_rtx_LSHIFTRT (SImode, op2_high, GEN_INT(31))));
11384 emit_insn(gen_insv_t2(scratch2, GEN_INT(1), GEN_INT(31), scratch1));
11385 emit_move_insn (op0_low, op1_low);
11386 emit_move_insn (op0_high, scratch2);
11387
11388 DONE;
11389 }"
11390)
11391
115857ef 11392;; movmisalign patterns for HImode and SImode.
11393(define_expand "movmisalign<mode>"
11394 [(match_operand:HSI 0 "general_operand")
11395 (match_operand:HSI 1 "general_operand")]
11396 "unaligned_access"
11397{
11398 /* This pattern is not permitted to fail during expansion: if both arguments
11399 are non-registers (e.g. memory := constant), force operand 1 into a
11400 register. */
11401 rtx (* gen_unaligned_load)(rtx, rtx);
11402 rtx tmp_dest = operands[0];
11403 if (!s_register_operand (operands[0], <MODE>mode)
11404 && !s_register_operand (operands[1], <MODE>mode))
11405 operands[1] = force_reg (<MODE>mode, operands[1]);
11406
11407 if (<MODE>mode == HImode)
11408 {
11409 gen_unaligned_load = gen_unaligned_loadhiu;
11410 tmp_dest = gen_reg_rtx (SImode);
11411 }
11412 else
11413 gen_unaligned_load = gen_unaligned_loadsi;
11414
11415 if (MEM_P (operands[1]))
11416 {
11417 emit_insn (gen_unaligned_load (tmp_dest, operands[1]));
11418 if (<MODE>mode == HImode)
11419 emit_move_insn (operands[0], gen_lowpart (HImode, tmp_dest));
11420 }
11421 else
11422 emit_insn (gen_unaligned_store<mode> (operands[0], operands[1]));
11423
11424 DONE;
11425})
11426
d98a3884 11427;; Vector bits common to IWMMXT and Neon
11428(include "vec-common.md")
755eb2b4 11429;; Load the Intel Wireless Multimedia Extension patterns
11430(include "iwmmxt.md")
a2cd141b 11431;; Load the VFP co-processor patterns
11432(include "vfp.md")
bc360af8 11433;; Thumb-1 patterns
11434(include "thumb1.md")
25f905c2 11435;; Thumb-2 patterns
11436(include "thumb2.md")
d98a3884 11437;; Neon patterns
11438(include "neon.md")
e84fdf6e 11439;; Crypto patterns
11440(include "crypto.md")
06df6b17 11441;; Synchronization Primitives
11442(include "sync.md")
bbbe4599 11443;; Fixed-point patterns
11444(include "arm-fixed.md")