]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/arm/arm.md
c/c++: Add fix-it hints for suggested missing #includes
[thirdparty/gcc.git] / gcc / config / arm / arm.md
CommitLineData
129a2fe4 1;;- Machine description for ARM for GNU compiler
aad93da1 2;; Copyright (C) 1991-2017 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
417e5cc5 121; arm_arch6. "v6t2" for Thumb-2 with arm_arch6 and "v8mb" for ARMv8-M
122; Baseline. This attribute is used to compute attribute "enabled",
123; use type "any" to enable an alternative in all cases.
124(define_attr "arch" "any,a,t,32,t1,t2,v6,nov6,v6t2,v8mb,neon_for_64bits,avoid_neon_for_64bits,iwmmxt,iwmmxt2,armv6_or_vfpv3,neon"
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
417e5cc5 163 (and (eq_attr "arch" "v8mb")
164 (match_test "TARGET_THUMB1 && arm_arch8"))
165 (const_string "yes")
166
b6779ddc 167 (and (eq_attr "arch" "avoid_neon_for_64bits")
168 (match_test "TARGET_NEON")
169 (not (match_test "TARGET_PREFER_NEON_64BITS")))
a651f34d 170 (const_string "yes")
171
b6779ddc 172 (and (eq_attr "arch" "neon_for_64bits")
173 (match_test "TARGET_NEON")
174 (match_test "TARGET_PREFER_NEON_64BITS"))
6b8f7c28 175 (const_string "yes")
176
177 (and (eq_attr "arch" "iwmmxt2")
178 (match_test "TARGET_REALLY_IWMMXT2"))
21cc9773 179 (const_string "yes")
180
181 (and (eq_attr "arch" "armv6_or_vfpv3")
182 (match_test "arm_arch6 || TARGET_VFP3"))
183 (const_string "yes")
ac876af5 184
185 (and (eq_attr "arch" "neon")
186 (match_test "TARGET_NEON"))
187 (const_string "yes")
21cc9773 188 ]
6b8f7c28 189
d5d4dc8d 190 (const_string "no")))
191
aa06c51c 192(define_attr "opt" "any,speed,size"
193 (const_string "any"))
194
195(define_attr "opt_enabled" "no,yes"
196 (cond [(eq_attr "opt" "any")
197 (const_string "yes")
198
199 (and (eq_attr "opt" "speed")
200 (match_test "optimize_function_for_speed_p (cfun)"))
201 (const_string "yes")
202
203 (and (eq_attr "opt" "size")
204 (match_test "optimize_function_for_size_p (cfun)"))
205 (const_string "yes")]
206 (const_string "no")))
207
861033d5 208(define_attr "use_literal_pool" "no,yes"
209 (cond [(and (eq_attr "type" "f_loads,f_loadd")
210 (match_test "CONSTANT_P (operands[1])"))
211 (const_string "yes")]
212 (const_string "no")))
213
d5d4dc8d 214; Enable all alternatives that are both arch_enabled and insn_enabled.
951a3f72 215; FIXME:: opt_enabled has been temporarily removed till the time we have
216; an attribute that allows the use of such alternatives.
217; This depends on caching of speed_p, size_p on a per
218; alternative basis. The problem is that the enabled attribute
219; cannot depend on any state that is not cached or is not constant
220; for a compilation unit. We probably need a generic "hot/cold"
221; alternative which if implemented can help with this. We disable this
222; until such a time as this is implemented and / or the improvements or
223; regressions with removing this attribute are double checked.
224; See ashldi3_neon and <shift>di3_neon in neon.md.
225
93b431d9 226 (define_attr "enabled" "no,yes"
0abea32c 227 (cond [(and (eq_attr "predicable_short_it" "no")
c7a58118 228 (and (eq_attr "predicated" "yes")
229 (match_test "arm_restrict_it")))
230 (const_string "no")
231
232 (and (eq_attr "enabled_for_depr_it" "no")
233 (match_test "arm_restrict_it"))
234 (const_string "no")
235
aa06c51c 236 (eq_attr "arch_enabled" "no")
aa06c51c 237 (const_string "no")]
238 (const_string "yes")))
d5d4dc8d 239
56d27660 240; POOL_RANGE is how far away from a constant pool entry that this insn
241; can be placed. If the distance is zero, then this insn will never
242; reference the pool.
42e1de19 243; Note that for Thumb constant pools the PC value is rounded down to the
244; nearest multiple of four. Therefore, THUMB2_POOL_RANGE (and POOL_RANGE for
245; Thumb insns) should be set to <max_range> - 2.
cffb2a26 246; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
8848d797 247; before its address. It is set to <max_range> - (8 + <data_size>).
cde1623a 248(define_attr "arm_pool_range" "" (const_int 0))
249(define_attr "thumb2_pool_range" "" (const_int 0))
250(define_attr "arm_neg_pool_range" "" (const_int 0))
251(define_attr "thumb2_neg_pool_range" "" (const_int 0))
252
253(define_attr "pool_range" ""
254 (cond [(eq_attr "is_thumb" "yes") (attr "thumb2_pool_range")]
255 (attr "arm_pool_range")))
256(define_attr "neg_pool_range" ""
257 (cond [(eq_attr "is_thumb" "yes") (attr "thumb2_neg_pool_range")]
258 (attr "arm_neg_pool_range")))
56d27660 259
215b30b3 260; An assembler sequence may clobber the condition codes without us knowing.
4d7a8451 261; If such an insn references the pool, then we have no way of knowing how,
262; so use the most conservative value for pool_range.
9c08d1fa 263(define_asm_attributes
4d7a8451 264 [(set_attr "conds" "clob")
265 (set_attr "length" "4")
266 (set_attr "pool_range" "250")])
9c08d1fa 267
9888ad6d 268; Load scheduling, set from the arm_ld_sched variable
4c834714 269; initialized by arm_option_override()
9888ad6d 270(define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
849170fd 271
f7fbdd4a 272; condition codes: this one is used by final_prescan_insn to speed up
273; conditionalizing instructions. It saves having to scan the rtl to see if
274; it uses or alters the condition codes.
215b30b3 275;
f7fbdd4a 276; USE means that the condition codes are used by the insn in the process of
215b30b3 277; outputting code, this means (at present) that we can't use the insn in
278; inlined branches
279;
f7fbdd4a 280; SET means that the purpose of the insn is to set the condition codes in a
215b30b3 281; well defined manner.
282;
f7fbdd4a 283; CLOB means that the condition codes are altered in an undefined manner, if
215b30b3 284; they are altered at all
285;
ad6d3e2a 286; UNCONDITIONAL means the instruction can not be conditionally executed and
287; that the instruction does not use or alter the condition codes.
c52acdd2 288;
ad6d3e2a 289; NOCOND means that the instruction does not use or alter the condition
290; codes but can be converted into a conditionally exectuted instruction.
f7fbdd4a 291
b0694be0 292(define_attr "conds" "use,set,clob,unconditional,nocond"
747b7458 293 (if_then_else
294 (ior (eq_attr "is_thumb1" "yes")
295 (eq_attr "type" "call"))
c1a66faf 296 (const_string "clob")
32093010 297 (if_then_else (eq_attr "is_neon_type" "no")
52432540 298 (const_string "nocond")
299 (const_string "unconditional"))))
f7fbdd4a 300
215b30b3 301; Predicable means that the insn can be conditionally executed based on
302; an automatically added predicate (additional patterns are generated by
303; gen...). We default to 'no' because no Thumb patterns match this rule
304; and not all ARM patterns do.
0d66636f 305(define_attr "predicable" "no,yes" (const_string "no"))
306
129a2fe4 307; Only model the write buffer for ARM6 and ARM7. Earlier processors don't
308; have one. Later ones, such as StrongARM, have write-back caches, so don't
8d232dc7 309; suffer blockages enough to warrant modelling this (and it can adversely
129a2fe4 310; affect the schedule).
74a71f7d 311(define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_tune_wbuf")))
129a2fe4 312
215b30b3 313; WRITE_CONFLICT implies that a read following an unrelated write is likely
314; to stall the processor. Used with model_wbuf above.
9c08d1fa 315(define_attr "write_conflict" "no,yes"
316 (if_then_else (eq_attr "type"
96854199 317 "block,call,load1")
9c08d1fa 318 (const_string "yes")
319 (const_string "no")))
320
215b30b3 321; Classify the insns into those that take one cycle and those that take more
322; than one on the main cpu execution unit.
f7fbdd4a 323(define_attr "core_cycles" "single,multi"
324 (if_then_else (eq_attr "type"
112eda6f 325 "adc_imm, adc_reg, adcs_imm, adcs_reg, adr, alu_ext, alu_imm, alu_sreg,\
326 alu_shift_imm, alu_shift_reg, alu_dsp_reg, alus_ext, alus_imm, alus_sreg,\
d82e788e 327 alus_shift_imm, alus_shift_reg, bfm, csel, rev, logic_imm, logic_reg,\
328 logic_shift_imm, logic_shift_reg, logics_imm, logics_reg,\
329 logics_shift_imm, logics_shift_reg, extend, shift_imm, float, fcsel,\
7cb6c048 330 wmmx_wor, wmmx_wxor, wmmx_wand, wmmx_wandn, wmmx_wmov, wmmx_tmcrr,\
331 wmmx_tmrrc, wmmx_wldr, wmmx_wstr, wmmx_tmcr, wmmx_tmrc, wmmx_wadd,\
332 wmmx_wsub, wmmx_wmul, wmmx_wmac, wmmx_wavg2, wmmx_tinsr, wmmx_textrm,\
333 wmmx_wshufh, wmmx_wcmpeq, wmmx_wcmpgt, wmmx_wmax, wmmx_wmin, wmmx_wpack,\
334 wmmx_wunpckih, wmmx_wunpckil, wmmx_wunpckeh, wmmx_wunpckel, wmmx_wror,\
335 wmmx_wsra, wmmx_wsrl, wmmx_wsll, wmmx_wmadd, wmmx_tmia, wmmx_tmiaph,\
336 wmmx_tmiaxy, wmmx_tbcst, wmmx_tmovmsk, wmmx_wacc, wmmx_waligni,\
337 wmmx_walignr, wmmx_tandc, wmmx_textrc, wmmx_torc, wmmx_torvsc, wmmx_wsad,\
338 wmmx_wabs, wmmx_wabsdiff, wmmx_waddsubhx, wmmx_wsubaddhx, wmmx_wavg4,\
339 wmmx_wmulw, wmmx_wqmulm, wmmx_wqmulwm, wmmx_waddbhus, wmmx_wqmiaxy,\
340 wmmx_wmiaxy, wmmx_wmiawxy, wmmx_wmerge")
f7fbdd4a 341 (const_string "single")
342 (const_string "multi")))
343
cffb2a26 344;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
215b30b3 345;; distant label. Only applicable to Thumb code.
cffb2a26 346(define_attr "far_jump" "yes,no" (const_string "no"))
347
d51f92df 348
25f905c2 349;; The number of machine instructions this pattern expands to.
350;; Used for Thumb-2 conditional execution.
351(define_attr "ce_count" "" (const_int 1))
352
4182b724 353;;---------------------------------------------------------------------------
354;; Unspecs
355
356(include "unspecs.md")
357
d51f92df 358;;---------------------------------------------------------------------------
fd781bb2 359;; Mode iterators
d51f92df 360
3de0dec6 361(include "iterators.md")
03770691 362
d51f92df 363;;---------------------------------------------------------------------------
364;; Predicates
365
9c9db025 366(include "predicates.md")
234f6557 367(include "constraints.md")
9c9db025 368
a2cd141b 369;;---------------------------------------------------------------------------
370;; Pipeline descriptions
215b30b3 371
e3879fd0 372(define_attr "tune_cortexr4" "yes,no"
373 (const (if_then_else
7d3cda8c 374 (eq_attr "tune" "cortexr4,cortexr4f,cortexr5")
e3879fd0 375 (const_string "yes")
376 (const_string "no"))))
377
a2cd141b 378;; True if the generic scheduling description should be used.
379
380(define_attr "generic_sched" "yes,no"
2546d93a 381 (const (if_then_else
e18862f3 382 (ior (eq_attr "tune" "fa526,fa626,fa606te,fa626te,fmp626,fa726te,\
383 arm926ejs,arm1020e,arm1026ejs,arm1136js,\
384 arm1136jfs,cortexa5,cortexa7,cortexa8,\
42e7b263 385 cortexa9,cortexa12,cortexa15,cortexa17,\
b1099bfd 386 cortexa53,cortexa57,cortexm4,cortexm7,\
802e6377 387 exynosm1,marvell_pj4,xgene1")
2546d93a 388 (eq_attr "tune_cortexr4" "yes"))
4d5cb40d 389 (const_string "no")
390 (const_string "yes"))))
391
c0e1af52 392(define_attr "generic_vfp" "yes,no"
393 (const (if_then_else
394 (and (eq_attr "fpu" "vfp")
e18862f3 395 (eq_attr "tune" "!arm1020e,arm1022e,cortexa5,cortexa7,\
396 cortexa8,cortexa9,cortexa53,cortexm4,\
55a94dda 397 cortexm7,marvell_pj4,xgene1")
e3879fd0 398 (eq_attr "tune_cortexr4" "no"))
c0e1af52 399 (const_string "yes")
400 (const_string "no"))))
401
6b8f7c28 402(include "marvell-f-iwmmxt.md")
a2cd141b 403(include "arm-generic.md")
404(include "arm926ejs.md")
c0e1af52 405(include "arm1020e.md")
a2cd141b 406(include "arm1026ejs.md")
407(include "arm1136jfs.md")
0e266d06 408(include "fa526.md")
409(include "fa606te.md")
410(include "fa626te.md")
411(include "fmp626.md")
412(include "fa726te.md")
3f1e069f 413(include "cortex-a5.md")
d6b7f019 414(include "cortex-a7.md")
bcaec148 415(include "cortex-a8.md")
036068af 416(include "cortex-a9.md")
65f2f758 417(include "cortex-a15.md")
42e7b263 418(include "cortex-a17.md")
da10bc87 419(include "cortex-a53.md")
b1099bfd 420(include "cortex-a57.md")
934a1e72 421(include "cortex-r4.md")
e3879fd0 422(include "cortex-r4f.md")
e18862f3 423(include "cortex-m7.md")
2546d93a 424(include "cortex-m4.md")
425(include "cortex-m4-fpu.md")
802e6377 426(include "exynos-m1.md")
55e3ada8 427(include "vfp11.md")
ea7d210b 428(include "marvell-pj4.md")
55a94dda 429(include "xgene1.md")
3586df96 430
9c08d1fa 431\f
215b30b3 432;;---------------------------------------------------------------------------
e1159bbe 433;; Insn patterns
434;;
a0f94409 435;; Addition insns.
215b30b3 436
9c08d1fa 437;; Note: For DImode insns, there is normally no reason why operands should
438;; not be in the same register, what we don't want is for something being
439;; written to partially overlap something that is an input.
440
cffb2a26 441(define_expand "adddi3"
442 [(parallel
215b30b3 443 [(set (match_operand:DI 0 "s_register_operand" "")
cffb2a26 444 (plus:DI (match_operand:DI 1 "s_register_operand" "")
10e5ccd5 445 (match_operand:DI 2 "arm_adddi_operand" "")))
bd5b4116 446 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 447 "TARGET_EITHER"
448 "
25f905c2 449 if (TARGET_THUMB1)
cffb2a26 450 {
0438d37f 451 if (!REG_P (operands[1]))
bc5a93af 452 operands[1] = force_reg (DImode, operands[1]);
0438d37f 453 if (!REG_P (operands[2]))
bc5a93af 454 operands[2] = force_reg (DImode, operands[2]);
cffb2a26 455 }
456 "
457)
458
a0f94409 459(define_insn_and_split "*arm_adddi3"
10e5ccd5 460 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r,&r,&r")
461 (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0, r, 0, r")
462 (match_operand:DI 2 "arm_adddi_operand" "r, 0, r, Dd, Dd")))
bd5b4116 463 (clobber (reg:CC CC_REGNUM))]
b805622c 464 "TARGET_32BIT && !TARGET_NEON"
33782ec7 465 "#"
94829feb 466 "TARGET_32BIT && reload_completed
467 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))"
a0f94409 468 [(parallel [(set (reg:CC_C CC_REGNUM)
469 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
470 (match_dup 1)))
471 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 472 (set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (match_dup 5))
473 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
a0f94409 474 "
475 {
476 operands[3] = gen_highpart (SImode, operands[0]);
477 operands[0] = gen_lowpart (SImode, operands[0]);
478 operands[4] = gen_highpart (SImode, operands[1]);
479 operands[1] = gen_lowpart (SImode, operands[1]);
10e5ccd5 480 operands[5] = gen_highpart_mode (SImode, DImode, operands[2]);
a0f94409 481 operands[2] = gen_lowpart (SImode, operands[2]);
482 }"
cffb2a26 483 [(set_attr "conds" "clob")
1b7da4ac 484 (set_attr "length" "8")
485 (set_attr "type" "multiple")]
cffb2a26 486)
9c08d1fa 487
a0f94409 488(define_insn_and_split "*adddi_sesidi_di"
9c08d1fa 489 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
490 (plus:DI (sign_extend:DI
97499065 491 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 492 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 493 (clobber (reg:CC CC_REGNUM))]
b805622c 494 "TARGET_32BIT"
33782ec7 495 "#"
25f905c2 496 "TARGET_32BIT && reload_completed"
a0f94409 497 [(parallel [(set (reg:CC_C CC_REGNUM)
498 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
499 (match_dup 1)))
500 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 501 (set (match_dup 3) (plus:SI (plus:SI (ashiftrt:SI (match_dup 2)
a0f94409 502 (const_int 31))
080c0b9a 503 (match_dup 4))
504 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
a0f94409 505 "
506 {
507 operands[3] = gen_highpart (SImode, operands[0]);
508 operands[0] = gen_lowpart (SImode, operands[0]);
509 operands[4] = gen_highpart (SImode, operands[1]);
510 operands[1] = gen_lowpart (SImode, operands[1]);
511 operands[2] = gen_lowpart (SImode, operands[2]);
512 }"
215b30b3 513 [(set_attr "conds" "clob")
1b7da4ac 514 (set_attr "length" "8")
515 (set_attr "type" "multiple")]
215b30b3 516)
9c08d1fa 517
a0f94409 518(define_insn_and_split "*adddi_zesidi_di"
9c08d1fa 519 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
520 (plus:DI (zero_extend:DI
97499065 521 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 522 (match_operand:DI 1 "s_register_operand" "0,r")))
a0f94409 523 (clobber (reg:CC CC_REGNUM))]
b805622c 524 "TARGET_32BIT"
33782ec7 525 "#"
25f905c2 526 "TARGET_32BIT && reload_completed"
a0f94409 527 [(parallel [(set (reg:CC_C CC_REGNUM)
528 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
529 (match_dup 1)))
530 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 531 (set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (const_int 0))
532 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
a0f94409 533 "
534 {
535 operands[3] = gen_highpart (SImode, operands[0]);
536 operands[0] = gen_lowpart (SImode, operands[0]);
537 operands[4] = gen_highpart (SImode, operands[1]);
538 operands[1] = gen_lowpart (SImode, operands[1]);
539 operands[2] = gen_lowpart (SImode, operands[2]);
540 }"
cffb2a26 541 [(set_attr "conds" "clob")
1b7da4ac 542 (set_attr "length" "8")
543 (set_attr "type" "multiple")]
cffb2a26 544)
b11cae9e 545
f6c98a9a 546(define_expand "addv<mode>4"
547 [(match_operand:SIDI 0 "register_operand")
548 (match_operand:SIDI 1 "register_operand")
549 (match_operand:SIDI 2 "register_operand")
550 (match_operand 3 "")]
551 "TARGET_32BIT"
552{
553 emit_insn (gen_add<mode>3_compareV (operands[0], operands[1], operands[2]));
554 arm_gen_unlikely_cbranch (NE, CC_Vmode, operands[3]);
555
556 DONE;
557})
558
559(define_expand "uaddv<mode>4"
560 [(match_operand:SIDI 0 "register_operand")
561 (match_operand:SIDI 1 "register_operand")
562 (match_operand:SIDI 2 "register_operand")
563 (match_operand 3 "")]
564 "TARGET_32BIT"
565{
566 emit_insn (gen_add<mode>3_compareC (operands[0], operands[1], operands[2]));
567 arm_gen_unlikely_cbranch (NE, CC_Cmode, operands[3]);
568
569 DONE;
570})
571
87b22bf7 572(define_expand "addsi3"
cffb2a26 573 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 574 (plus:SI (match_operand:SI 1 "s_register_operand" "")
575 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 576 "TARGET_EITHER"
87b22bf7 577 "
0438d37f 578 if (TARGET_32BIT && CONST_INT_P (operands[2]))
87b22bf7 579 {
96f57e36 580 arm_split_constant (PLUS, SImode, NULL_RTX,
581 INTVAL (operands[2]), operands[0], operands[1],
e1ba4a27 582 optimize && can_create_pseudo_p ());
87b22bf7 583 DONE;
584 }
cffb2a26 585 "
586)
87b22bf7 587
5bd751ff 588; If there is a scratch available, this will be faster than synthesizing the
a0f94409 589; addition.
590(define_peephole2
591 [(match_scratch:SI 3 "r")
372575c7 592 (set (match_operand:SI 0 "arm_general_register_operand" "")
593 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
cffb2a26 594 (match_operand:SI 2 "const_int_operand" "")))]
25f905c2 595 "TARGET_32BIT &&
a0f94409 596 !(const_ok_for_arm (INTVAL (operands[2]))
597 || const_ok_for_arm (-INTVAL (operands[2])))
598 && const_ok_for_arm (~INTVAL (operands[2]))"
599 [(set (match_dup 3) (match_dup 2))
600 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
601 ""
602)
87b22bf7 603
2f02c19f 604;; The r/r/k alternative is required when reloading the address
605;; (plus (reg rN) (reg sp)) into (reg rN). In this case reload will
606;; put the duplicated register first, and not try the commutative version.
a0f94409 607(define_insn_and_split "*arm_addsi3"
fa1f9c9e 608 [(set (match_operand:SI 0 "s_register_operand" "=rk,l,l ,l ,r ,k ,r,k ,r ,k ,r ,k,k,r ,k ,r")
609 (plus:SI (match_operand:SI 1 "s_register_operand" "%0 ,l,0 ,l ,rk,k ,r,r ,rk,k ,rk,k,r,rk,k ,rk")
610 (match_operand:SI 2 "reg_or_int_operand" "rk ,l,Py,Pd,rI,rI,k,rI,Pj,Pj,L ,L,L,PJ,PJ,?n")))]
25f905c2 611 "TARGET_32BIT"
5565501b 612 "@
c24d855d 613 add%?\\t%0, %0, %2
5565501b 614 add%?\\t%0, %1, %2
a0b3420a 615 add%?\\t%0, %1, %2
7c36fe71 616 add%?\\t%0, %1, %2
617 add%?\\t%0, %1, %2
aaa37ad6 618 add%?\\t%0, %1, %2
2f02c19f 619 add%?\\t%0, %2, %1
fa1f9c9e 620 add%?\\t%0, %1, %2
d5cbae34 621 addw%?\\t%0, %1, %2
622 addw%?\\t%0, %1, %2
aaa37ad6 623 sub%?\\t%0, %1, #%n2
87b22bf7 624 sub%?\\t%0, %1, #%n2
d7757711 625 sub%?\\t%0, %1, #%n2
d5cbae34 626 subw%?\\t%0, %1, #%n2
627 subw%?\\t%0, %1, #%n2
87b22bf7 628 #"
a3ffc315 629 "TARGET_32BIT
0438d37f 630 && CONST_INT_P (operands[2])
d5cbae34 631 && !const_ok_for_op (INTVAL (operands[2]), PLUS)
a3ffc315 632 && (reload_completed || !arm_eliminable_register (operands[1]))"
a0f94409 633 [(clobber (const_int 0))]
634 "
96f57e36 635 arm_split_constant (PLUS, SImode, curr_insn,
636 INTVAL (operands[2]), operands[0],
a0f94409 637 operands[1], 0);
638 DONE;
639 "
fa1f9c9e 640 [(set_attr "length" "2,4,4,4,4,4,4,4,4,4,4,4,4,4,4,16")
d5cbae34 641 (set_attr "predicable" "yes")
fa1f9c9e 642 (set_attr "predicable_short_it" "yes,yes,yes,yes,no,no,no,no,no,no,no,no,no,no,no,no")
643 (set_attr "arch" "t2,t2,t2,t2,*,*,*,a,t2,t2,*,*,a,t2,t2,*")
65f68e55 644 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
d82e788e 645 (const_string "alu_imm")
112eda6f 646 (const_string "alu_sreg")))
65f68e55 647 ]
cffb2a26 648)
649
f6c98a9a 650(define_insn_and_split "adddi3_compareV"
651 [(set (reg:CC_V CC_REGNUM)
652 (ne:CC_V
653 (plus:TI
654 (sign_extend:TI (match_operand:DI 1 "register_operand" "r"))
655 (sign_extend:TI (match_operand:DI 2 "register_operand" "r")))
656 (sign_extend:TI (plus:DI (match_dup 1) (match_dup 2)))))
657 (set (match_operand:DI 0 "register_operand" "=&r")
658 (plus:DI (match_dup 1) (match_dup 2)))]
659 "TARGET_32BIT"
660 "#"
661 "&& reload_completed"
662 [(parallel [(set (reg:CC_C CC_REGNUM)
663 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
664 (match_dup 1)))
665 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
666 (parallel [(set (reg:CC_V CC_REGNUM)
667 (ne:CC_V
668 (plus:DI (plus:DI
669 (sign_extend:DI (match_dup 4))
670 (sign_extend:DI (match_dup 5)))
671 (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0)))
672 (plus:DI (sign_extend:DI
673 (plus:SI (match_dup 4) (match_dup 5)))
674 (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0)))))
675 (set (match_dup 3) (plus:SI (plus:SI
676 (match_dup 4) (match_dup 5))
677 (ltu:SI (reg:CC_C CC_REGNUM)
678 (const_int 0))))])]
679 "
680 {
681 operands[3] = gen_highpart (SImode, operands[0]);
682 operands[0] = gen_lowpart (SImode, operands[0]);
683 operands[4] = gen_highpart (SImode, operands[1]);
684 operands[1] = gen_lowpart (SImode, operands[1]);
685 operands[5] = gen_highpart (SImode, operands[2]);
686 operands[2] = gen_lowpart (SImode, operands[2]);
687 }"
688 [(set_attr "conds" "set")
689 (set_attr "length" "8")
690 (set_attr "type" "multiple")]
691)
692
693(define_insn "addsi3_compareV"
694 [(set (reg:CC_V CC_REGNUM)
695 (ne:CC_V
696 (plus:DI
697 (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
698 (sign_extend:DI (match_operand:SI 2 "register_operand" "r")))
699 (sign_extend:DI (plus:SI (match_dup 1) (match_dup 2)))))
700 (set (match_operand:SI 0 "register_operand" "=r")
701 (plus:SI (match_dup 1) (match_dup 2)))]
702 "TARGET_32BIT"
703 "adds%?\\t%0, %1, %2"
704 [(set_attr "conds" "set")
705 (set_attr "type" "alus_sreg")]
706)
707
708(define_insn "*addsi3_compareV_upper"
709 [(set (reg:CC_V CC_REGNUM)
710 (ne:CC_V
711 (plus:DI
712 (plus:DI
713 (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
714 (sign_extend:DI (match_operand:SI 2 "register_operand" "r")))
715 (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0)))
716 (plus:DI (sign_extend:DI
717 (plus:SI (match_dup 1) (match_dup 2)))
718 (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0)))))
719 (set (match_operand:SI 0 "register_operand" "=r")
720 (plus:SI
721 (plus:SI (match_dup 1) (match_dup 2))
722 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
723 "TARGET_32BIT"
724 "adcs%?\\t%0, %1, %2"
725 [(set_attr "conds" "set")
726 (set_attr "type" "adcs_reg")]
727)
728
729(define_insn_and_split "adddi3_compareC"
730 [(set (reg:CC_C CC_REGNUM)
731 (ne:CC_C
732 (plus:TI
733 (zero_extend:TI (match_operand:DI 1 "register_operand" "r"))
734 (zero_extend:TI (match_operand:DI 2 "register_operand" "r")))
735 (zero_extend:TI (plus:DI (match_dup 1) (match_dup 2)))))
736 (set (match_operand:DI 0 "register_operand" "=&r")
737 (plus:DI (match_dup 1) (match_dup 2)))]
738 "TARGET_32BIT"
739 "#"
740 "&& reload_completed"
741 [(parallel [(set (reg:CC_C CC_REGNUM)
742 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
743 (match_dup 1)))
744 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
745 (parallel [(set (reg:CC_C CC_REGNUM)
746 (ne:CC_C
747 (plus:DI (plus:DI
748 (zero_extend:DI (match_dup 4))
749 (zero_extend:DI (match_dup 5)))
750 (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0)))
751 (plus:DI (zero_extend:DI
752 (plus:SI (match_dup 4) (match_dup 5)))
753 (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0)))))
754 (set (match_dup 3) (plus:SI
755 (plus:SI (match_dup 4) (match_dup 5))
756 (ltu:SI (reg:CC_C CC_REGNUM)
757 (const_int 0))))])]
758 "
759 {
760 operands[3] = gen_highpart (SImode, operands[0]);
761 operands[0] = gen_lowpart (SImode, operands[0]);
762 operands[4] = gen_highpart (SImode, operands[1]);
763 operands[5] = gen_highpart (SImode, operands[2]);
764 operands[1] = gen_lowpart (SImode, operands[1]);
765 operands[2] = gen_lowpart (SImode, operands[2]);
766 }"
767 [(set_attr "conds" "set")
768 (set_attr "length" "8")
769 (set_attr "type" "multiple")]
770)
771
772(define_insn "*addsi3_compareC_upper"
773 [(set (reg:CC_C CC_REGNUM)
774 (ne:CC_C
775 (plus:DI
776 (plus:DI
777 (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
778 (zero_extend:DI (match_operand:SI 2 "register_operand" "r")))
779 (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0)))
780 (plus:DI (zero_extend:DI
781 (plus:SI (match_dup 1) (match_dup 2)))
782 (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0)))))
783 (set (match_operand:SI 0 "register_operand" "=r")
784 (plus:SI
785 (plus:SI (match_dup 1) (match_dup 2))
786 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
787 "TARGET_32BIT"
788 "adcs%?\\t%0, %1, %2"
789 [(set_attr "conds" "set")
790 (set_attr "type" "adcs_reg")]
791)
792
793(define_insn "addsi3_compareC"
794 [(set (reg:CC_C CC_REGNUM)
795 (ne:CC_C
796 (plus:DI
797 (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
798 (zero_extend:DI (match_operand:SI 2 "register_operand" "r")))
799 (zero_extend:DI
800 (plus:SI (match_dup 1) (match_dup 2)))))
801 (set (match_operand:SI 0 "register_operand" "=r")
802 (plus:SI (match_dup 1) (match_dup 2)))]
803 "TARGET_32BIT"
804 "adds%?\\t%0, %1, %2"
805 [(set_attr "conds" "set")
806 (set_attr "type" "alus_sreg")]
807)
808
90c2bcf0 809(define_insn "addsi3_compare0"
bd5b4116 810 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 811 (compare:CC_NOOV
65f68e55 812 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r,r")
813 (match_operand:SI 2 "arm_add_operand" "I,L,r"))
5565501b 814 (const_int 0)))
65f68e55 815 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9c08d1fa 816 (plus:SI (match_dup 1) (match_dup 2)))]
ec792a7b 817 "TARGET_ARM"
5565501b 818 "@
3ef90e77 819 adds%?\\t%0, %1, %2
820 subs%?\\t%0, %1, #%n2
821 adds%?\\t%0, %1, %2"
65f68e55 822 [(set_attr "conds" "set")
112eda6f 823 (set_attr "type" "alus_imm,alus_imm,alus_sreg")]
cffb2a26 824)
9c08d1fa 825
aea4c774 826(define_insn "*addsi3_compare0_scratch"
bd5b4116 827 [(set (reg:CC_NOOV CC_REGNUM)
aea4c774 828 (compare:CC_NOOV
65f68e55 829 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r, r")
830 (match_operand:SI 1 "arm_add_operand" "I,L, r"))
aea4c774 831 (const_int 0)))]
ec792a7b 832 "TARGET_ARM"
cffb2a26 833 "@
834 cmn%?\\t%0, %1
65f68e55 835 cmp%?\\t%0, #%n1
836 cmn%?\\t%0, %1"
596e5e8f 837 [(set_attr "conds" "set")
65f68e55 838 (set_attr "predicable" "yes")
112eda6f 839 (set_attr "type" "alus_imm,alus_imm,alus_sreg")]
0d66636f 840)
cffb2a26 841
aed179ae 842(define_insn "*compare_negsi_si"
843 [(set (reg:CC_Z CC_REGNUM)
844 (compare:CC_Z
7c36fe71 845 (neg:SI (match_operand:SI 0 "s_register_operand" "l,r"))
846 (match_operand:SI 1 "s_register_operand" "l,r")))]
25f905c2 847 "TARGET_32BIT"
aed179ae 848 "cmn%?\\t%1, %0"
596e5e8f 849 [(set_attr "conds" "set")
7c36fe71 850 (set_attr "predicable" "yes")
851 (set_attr "arch" "t2,*")
852 (set_attr "length" "2,4")
1b7da4ac 853 (set_attr "predicable_short_it" "yes,no")
112eda6f 854 (set_attr "type" "alus_sreg")]
0d66636f 855)
aea4c774 856
203c488f 857;; This is the canonicalization of addsi3_compare0_for_combiner when the
858;; addend is a constant.
190efb17 859(define_insn "cmpsi2_addneg"
203c488f 860 [(set (reg:CC CC_REGNUM)
861 (compare:CC
862 (match_operand:SI 1 "s_register_operand" "r,r")
2a977b78 863 (match_operand:SI 2 "arm_addimm_operand" "L,I")))
203c488f 864 (set (match_operand:SI 0 "s_register_operand" "=r,r")
865 (plus:SI (match_dup 1)
2a977b78 866 (match_operand:SI 3 "arm_addimm_operand" "I,L")))]
25f905c2 867 "TARGET_32BIT && INTVAL (operands[2]) == -INTVAL (operands[3])"
203c488f 868 "@
3ef90e77 869 adds%?\\t%0, %1, %3
870 subs%?\\t%0, %1, #%n3"
1b7da4ac 871 [(set_attr "conds" "set")
112eda6f 872 (set_attr "type" "alus_sreg")]
203c488f 873)
874
875;; Convert the sequence
876;; sub rd, rn, #1
877;; cmn rd, #1 (equivalent to cmp rd, #-1)
878;; bne dest
879;; into
880;; subs rd, rn, #1
881;; bcs dest ((unsigned)rn >= 1)
882;; similarly for the beq variant using bcc.
883;; This is a common looping idiom (while (n--))
884(define_peephole2
372575c7 885 [(set (match_operand:SI 0 "arm_general_register_operand" "")
886 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
203c488f 887 (const_int -1)))
888 (set (match_operand 2 "cc_register" "")
889 (compare (match_dup 0) (const_int -1)))
890 (set (pc)
891 (if_then_else (match_operator 3 "equality_operator"
892 [(match_dup 2) (const_int 0)])
893 (match_operand 4 "" "")
894 (match_operand 5 "" "")))]
25f905c2 895 "TARGET_32BIT && peep2_reg_dead_p (3, operands[2])"
203c488f 896 [(parallel[
897 (set (match_dup 2)
898 (compare:CC
899 (match_dup 1) (const_int 1)))
900 (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
901 (set (pc)
902 (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
903 (match_dup 4)
904 (match_dup 5)))]
905 "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
906 operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
907 ? GEU : LTU),
908 VOIDmode,
909 operands[2], const0_rtx);"
910)
911
ebcc79bc 912;; The next four insns work because they compare the result with one of
913;; the operands, and we know that the use of the condition code is
914;; either GEU or LTU, so we can use the carry flag from the addition
915;; instead of doing the compare a second time.
916(define_insn "*addsi3_compare_op1"
bd5b4116 917 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 918 (compare:CC_C
65f68e55 919 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
920 (match_operand:SI 2 "arm_add_operand" "I,L,r"))
ebcc79bc 921 (match_dup 1)))
65f68e55 922 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
ebcc79bc 923 (plus:SI (match_dup 1) (match_dup 2)))]
25f905c2 924 "TARGET_32BIT"
ebcc79bc 925 "@
3ef90e77 926 adds%?\\t%0, %1, %2
927 subs%?\\t%0, %1, #%n2
928 adds%?\\t%0, %1, %2"
65f68e55 929 [(set_attr "conds" "set")
112eda6f 930 (set_attr "type" "alus_imm,alus_imm,alus_sreg")]
0d66636f 931)
ebcc79bc 932
933(define_insn "*addsi3_compare_op2"
bd5b4116 934 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 935 (compare:CC_C
65f68e55 936 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
937 (match_operand:SI 2 "arm_add_operand" "I,L,r"))
ebcc79bc 938 (match_dup 2)))
65f68e55 939 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9c08d1fa 940 (plus:SI (match_dup 1) (match_dup 2)))]
25f905c2 941 "TARGET_32BIT"
5565501b 942 "@
3ef90e77 943 adds%?\\t%0, %1, %2
38128b57 944 subs%?\\t%0, %1, #%n2
945 adds%?\\t%0, %1, %2"
65f68e55 946 [(set_attr "conds" "set")
112eda6f 947 (set_attr "type" "alus_imm,alus_imm,alus_sreg")]
0d66636f 948)
9c08d1fa 949
ebcc79bc 950(define_insn "*compare_addsi2_op0"
bd5b4116 951 [(set (reg:CC_C CC_REGNUM)
7c36fe71 952 (compare:CC_C
953 (plus:SI (match_operand:SI 0 "s_register_operand" "l,l,r,r,r")
954 (match_operand:SI 1 "arm_add_operand" "Pv,l,I,L,r"))
955 (match_dup 0)))]
25f905c2 956 "TARGET_32BIT"
ebcc79bc 957 "@
7c36fe71 958 cmp%?\\t%0, #%n1
959 cmn%?\\t%0, %1
ebcc79bc 960 cmn%?\\t%0, %1
65f68e55 961 cmp%?\\t%0, #%n1
962 cmn%?\\t%0, %1"
596e5e8f 963 [(set_attr "conds" "set")
65f68e55 964 (set_attr "predicable" "yes")
7c36fe71 965 (set_attr "arch" "t2,t2,*,*,*")
966 (set_attr "predicable_short_it" "yes,yes,no,no,no")
967 (set_attr "length" "2,2,4,4,4")
112eda6f 968 (set_attr "type" "alus_imm,alus_sreg,alus_imm,alus_imm,alus_sreg")]
0d66636f 969)
ebcc79bc 970
971(define_insn "*compare_addsi2_op1"
bd5b4116 972 [(set (reg:CC_C CC_REGNUM)
7c36fe71 973 (compare:CC_C
974 (plus:SI (match_operand:SI 0 "s_register_operand" "l,l,r,r,r")
975 (match_operand:SI 1 "arm_add_operand" "Pv,l,I,L,r"))
976 (match_dup 1)))]
25f905c2 977 "TARGET_32BIT"
ebcc79bc 978 "@
7c36fe71 979 cmp%?\\t%0, #%n1
980 cmn%?\\t%0, %1
ebcc79bc 981 cmn%?\\t%0, %1
65f68e55 982 cmp%?\\t%0, #%n1
983 cmn%?\\t%0, %1"
596e5e8f 984 [(set_attr "conds" "set")
65f68e55 985 (set_attr "predicable" "yes")
7c36fe71 986 (set_attr "arch" "t2,t2,*,*,*")
987 (set_attr "predicable_short_it" "yes,yes,no,no,no")
988 (set_attr "length" "2,2,4,4,4")
112eda6f 989 (set_attr "type" "alus_imm,alus_sreg,alus_imm,alus_imm,alus_sreg")]
7c36fe71 990 )
ebcc79bc 991
080c0b9a 992(define_insn "*addsi3_carryin_<optab>"
7c36fe71 993 [(set (match_operand:SI 0 "s_register_operand" "=l,r,r")
994 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%l,r,r")
995 (match_operand:SI 2 "arm_not_operand" "0,rI,K"))
996 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))]
25f905c2 997 "TARGET_32BIT"
10e5ccd5 998 "@
a0b3420a 999 adc%?\\t%0, %1, %2
10e5ccd5 1000 adc%?\\t%0, %1, %2
1001 sbc%?\\t%0, %1, #%B2"
a7de272d 1002 [(set_attr "conds" "use")
7c36fe71 1003 (set_attr "predicable" "yes")
1004 (set_attr "arch" "t2,*,*")
1005 (set_attr "length" "4")
1b7da4ac 1006 (set_attr "predicable_short_it" "yes,no,no")
1007 (set_attr "type" "adc_reg,adc_reg,adc_imm")]
cffb2a26 1008)
ebcc79bc 1009
080c0b9a 1010(define_insn "*addsi3_carryin_alt2_<optab>"
7c36fe71 1011 [(set (match_operand:SI 0 "s_register_operand" "=l,r,r")
1012 (plus:SI (plus:SI (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))
1013 (match_operand:SI 1 "s_register_operand" "%l,r,r"))
1014 (match_operand:SI 2 "arm_rhs_operand" "l,rI,K")))]
25f905c2 1015 "TARGET_32BIT"
10e5ccd5 1016 "@
a0b3420a 1017 adc%?\\t%0, %1, %2
10e5ccd5 1018 adc%?\\t%0, %1, %2
1019 sbc%?\\t%0, %1, #%B2"
a7de272d 1020 [(set_attr "conds" "use")
7c36fe71 1021 (set_attr "predicable" "yes")
1022 (set_attr "arch" "t2,*,*")
1023 (set_attr "length" "4")
1b7da4ac 1024 (set_attr "predicable_short_it" "yes,no,no")
1025 (set_attr "type" "adc_reg,adc_reg,adc_imm")]
0d66636f 1026)
ebcc79bc 1027
080c0b9a 1028(define_insn "*addsi3_carryin_shift_<optab>"
ebcc79bc 1029 [(set (match_operand:SI 0 "s_register_operand" "=r")
080c0b9a 1030 (plus:SI (plus:SI
1031 (match_operator:SI 2 "shift_operator"
1032 [(match_operand:SI 3 "s_register_operand" "r")
1033 (match_operand:SI 4 "reg_or_int_operand" "rM")])
1034 (match_operand:SI 1 "s_register_operand" "r"))
1035 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))]
25f905c2 1036 "TARGET_32BIT"
080c0b9a 1037 "adc%?\\t%0, %1, %3%S2"
1038 [(set_attr "conds" "use")
a7de272d 1039 (set_attr "predicable" "yes")
7c36fe71 1040 (set_attr "predicable_short_it" "no")
080c0b9a 1041 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
d82e788e 1042 (const_string "alu_shift_imm")
1043 (const_string "alu_shift_reg")))]
cffb2a26 1044)
ebcc79bc 1045
922b6913 1046(define_insn "*addsi3_carryin_clobercc_<optab>"
1047 [(set (match_operand:SI 0 "s_register_operand" "=r")
1048 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%r")
1049 (match_operand:SI 2 "arm_rhs_operand" "rI"))
1050 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))
1051 (clobber (reg:CC CC_REGNUM))]
1052 "TARGET_32BIT"
3ef90e77 1053 "adcs%?\\t%0, %1, %2"
1b7da4ac 1054 [(set_attr "conds" "set")
1055 (set_attr "type" "adcs_reg")]
922b6913 1056)
1057
f6c98a9a 1058(define_expand "subv<mode>4"
1059 [(match_operand:SIDI 0 "register_operand")
1060 (match_operand:SIDI 1 "register_operand")
1061 (match_operand:SIDI 2 "register_operand")
1062 (match_operand 3 "")]
1063 "TARGET_32BIT"
1064{
1065 emit_insn (gen_sub<mode>3_compare1 (operands[0], operands[1], operands[2]));
1066 arm_gen_unlikely_cbranch (NE, CC_Vmode, operands[3]);
1067
1068 DONE;
1069})
1070
1071(define_expand "usubv<mode>4"
1072 [(match_operand:SIDI 0 "register_operand")
1073 (match_operand:SIDI 1 "register_operand")
1074 (match_operand:SIDI 2 "register_operand")
1075 (match_operand 3 "")]
1076 "TARGET_32BIT"
1077{
1078 emit_insn (gen_sub<mode>3_compare1 (operands[0], operands[1], operands[2]));
1079 arm_gen_unlikely_cbranch (LTU, CCmode, operands[3]);
1080
1081 DONE;
1082})
1083
1084(define_insn_and_split "subdi3_compare1"
1085 [(set (reg:CC CC_REGNUM)
1086 (compare:CC
1087 (match_operand:DI 1 "register_operand" "r")
1088 (match_operand:DI 2 "register_operand" "r")))
1089 (set (match_operand:DI 0 "register_operand" "=&r")
1090 (minus:DI (match_dup 1) (match_dup 2)))]
1091 "TARGET_32BIT"
1092 "#"
1093 "&& reload_completed"
1094 [(parallel [(set (reg:CC CC_REGNUM)
1095 (compare:CC (match_dup 1) (match_dup 2)))
1096 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1097 (parallel [(set (reg:CC CC_REGNUM)
1098 (compare:CC (match_dup 4) (match_dup 5)))
1099 (set (match_dup 3) (minus:SI (minus:SI (match_dup 4) (match_dup 5))
1100 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))])]
1101 {
1102 operands[3] = gen_highpart (SImode, operands[0]);
1103 operands[0] = gen_lowpart (SImode, operands[0]);
1104 operands[4] = gen_highpart (SImode, operands[1]);
1105 operands[1] = gen_lowpart (SImode, operands[1]);
1106 operands[5] = gen_highpart (SImode, operands[2]);
1107 operands[2] = gen_lowpart (SImode, operands[2]);
1108 }
1109 [(set_attr "conds" "set")
1110 (set_attr "length" "8")
1111 (set_attr "type" "multiple")]
1112)
1113
1114(define_insn "subsi3_compare1"
1115 [(set (reg:CC CC_REGNUM)
1116 (compare:CC
1117 (match_operand:SI 1 "register_operand" "r")
1118 (match_operand:SI 2 "register_operand" "r")))
1119 (set (match_operand:SI 0 "register_operand" "=r")
1120 (minus:SI (match_dup 1) (match_dup 2)))]
1121 "TARGET_32BIT"
1122 "subs%?\\t%0, %1, %2"
1123 [(set_attr "conds" "set")
1124 (set_attr "type" "alus_sreg")]
1125)
1126
9154bd82 1127(define_insn "*subsi3_carryin"
d5bf2b53 1128 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1129 (minus:SI (minus:SI (match_operand:SI 1 "reg_or_int_operand" "r,I,Pz")
1130 (match_operand:SI 2 "s_register_operand" "r,r,r"))
1131 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
9154bd82 1132 "TARGET_32BIT"
1133 "@
1134 sbc%?\\t%0, %1, %2
d5bf2b53 1135 rsc%?\\t%0, %2, %1
1136 sbc%?\\t%0, %2, %2, lsl #1"
9154bd82 1137 [(set_attr "conds" "use")
d5bf2b53 1138 (set_attr "arch" "*,a,t2")
7c36fe71 1139 (set_attr "predicable" "yes")
1b7da4ac 1140 (set_attr "predicable_short_it" "no")
d5bf2b53 1141 (set_attr "type" "adc_reg,adc_imm,alu_shift_imm")]
9154bd82 1142)
1143
1144(define_insn "*subsi3_carryin_const"
1145 [(set (match_operand:SI 0 "s_register_operand" "=r")
df46fd5e 1146 (minus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1147 (match_operand:SI 2 "arm_not_immediate_operand" "K"))
9154bd82 1148 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1149 "TARGET_32BIT"
1150 "sbc\\t%0, %1, #%B2"
1b7da4ac 1151 [(set_attr "conds" "use")
1152 (set_attr "type" "adc_imm")]
9154bd82 1153)
1154
1155(define_insn "*subsi3_carryin_compare"
1156 [(set (reg:CC CC_REGNUM)
1157 (compare:CC (match_operand:SI 1 "s_register_operand" "r")
1158 (match_operand:SI 2 "s_register_operand" "r")))
1159 (set (match_operand:SI 0 "s_register_operand" "=r")
1160 (minus:SI (minus:SI (match_dup 1)
1161 (match_dup 2))
1162 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1163 "TARGET_32BIT"
1164 "sbcs\\t%0, %1, %2"
1b7da4ac 1165 [(set_attr "conds" "set")
1166 (set_attr "type" "adcs_reg")]
9154bd82 1167)
1168
1169(define_insn "*subsi3_carryin_compare_const"
1170 [(set (reg:CC CC_REGNUM)
1171 (compare:CC (match_operand:SI 1 "reg_or_int_operand" "r")
1172 (match_operand:SI 2 "arm_not_operand" "K")))
1173 (set (match_operand:SI 0 "s_register_operand" "=r")
1174 (minus:SI (plus:SI (match_dup 1)
1175 (match_dup 2))
1176 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1177 "TARGET_32BIT"
1178 "sbcs\\t%0, %1, #%B2"
1b7da4ac 1179 [(set_attr "conds" "set")
1180 (set_attr "type" "adcs_imm")]
9154bd82 1181)
1182
1183(define_insn "*subsi3_carryin_shift"
1184 [(set (match_operand:SI 0 "s_register_operand" "=r")
1185 (minus:SI (minus:SI
1186 (match_operand:SI 1 "s_register_operand" "r")
1187 (match_operator:SI 2 "shift_operator"
1188 [(match_operand:SI 3 "s_register_operand" "r")
1189 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
1190 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1191 "TARGET_32BIT"
1192 "sbc%?\\t%0, %1, %3%S2"
1193 [(set_attr "conds" "use")
1194 (set_attr "predicable" "yes")
1195 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
d82e788e 1196 (const_string "alu_shift_imm")
1197 (const_string "alu_shift_reg")))]
9154bd82 1198)
1199
1200(define_insn "*rsbsi3_carryin_shift"
1201 [(set (match_operand:SI 0 "s_register_operand" "=r")
1202 (minus:SI (minus:SI
1203 (match_operator:SI 2 "shift_operator"
1204 [(match_operand:SI 3 "s_register_operand" "r")
1205 (match_operand:SI 4 "reg_or_int_operand" "rM")])
1206 (match_operand:SI 1 "s_register_operand" "r"))
1207 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1208 "TARGET_ARM"
1209 "rsc%?\\t%0, %1, %3%S2"
1210 [(set_attr "conds" "use")
1211 (set_attr "predicable" "yes")
1212 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
d82e788e 1213 (const_string "alu_shift_imm")
1214 (const_string "alu_shift_reg")))]
9154bd82 1215)
1216
d795fb69 1217; transform ((x << y) - 1) to ~(~(x-1) << y) Where X is a constant.
1218(define_split
1219 [(set (match_operand:SI 0 "s_register_operand" "")
1220 (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
1221 (match_operand:SI 2 "s_register_operand" ""))
1222 (const_int -1)))
1223 (clobber (match_operand:SI 3 "s_register_operand" ""))]
25f905c2 1224 "TARGET_32BIT"
d795fb69 1225 [(set (match_dup 3) (match_dup 1))
1226 (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
1227 "
1228 operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
1229")
1230
604f3a0a 1231(define_expand "addsf3"
1232 [(set (match_operand:SF 0 "s_register_operand" "")
1233 (plus:SF (match_operand:SF 1 "s_register_operand" "")
d86c91f6 1234 (match_operand:SF 2 "s_register_operand" "")))]
25f905c2 1235 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1236 "
604f3a0a 1237")
1238
604f3a0a 1239(define_expand "adddf3"
1240 [(set (match_operand:DF 0 "s_register_operand" "")
1241 (plus:DF (match_operand:DF 1 "s_register_operand" "")
d86c91f6 1242 (match_operand:DF 2 "s_register_operand" "")))]
a50d7267 1243 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 1244 "
604f3a0a 1245")
1246
cffb2a26 1247(define_expand "subdi3"
1248 [(parallel
1249 [(set (match_operand:DI 0 "s_register_operand" "")
1250 (minus:DI (match_operand:DI 1 "s_register_operand" "")
1251 (match_operand:DI 2 "s_register_operand" "")))
bd5b4116 1252 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 1253 "TARGET_EITHER"
1254 "
25f905c2 1255 if (TARGET_THUMB1)
cffb2a26 1256 {
0438d37f 1257 if (!REG_P (operands[1]))
5aa8c5f0 1258 operands[1] = force_reg (DImode, operands[1]);
0438d37f 1259 if (!REG_P (operands[2]))
5aa8c5f0 1260 operands[2] = force_reg (DImode, operands[2]);
cffb2a26 1261 }
1262 "
1263)
1264
2f9b23e3 1265(define_insn_and_split "*arm_subdi3"
cffb2a26 1266 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
9c08d1fa 1267 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
1268 (match_operand:DI 2 "s_register_operand" "r,0,0")))
bd5b4116 1269 (clobber (reg:CC CC_REGNUM))]
94829feb 1270 "TARGET_32BIT && !TARGET_NEON"
2f9b23e3 1271 "#" ; "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
1272 "&& reload_completed"
1273 [(parallel [(set (reg:CC CC_REGNUM)
1274 (compare:CC (match_dup 1) (match_dup 2)))
1275 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1276 (set (match_dup 3) (minus:SI (minus:SI (match_dup 4) (match_dup 5))
1277 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1278 {
1279 operands[3] = gen_highpart (SImode, operands[0]);
1280 operands[0] = gen_lowpart (SImode, operands[0]);
1281 operands[4] = gen_highpart (SImode, operands[1]);
1282 operands[1] = gen_lowpart (SImode, operands[1]);
1283 operands[5] = gen_highpart (SImode, operands[2]);
1284 operands[2] = gen_lowpart (SImode, operands[2]);
1285 }
cffb2a26 1286 [(set_attr "conds" "clob")
1b7da4ac 1287 (set_attr "length" "8")
1288 (set_attr "type" "multiple")]
cffb2a26 1289)
1290
2f9b23e3 1291(define_insn_and_split "*subdi_di_zesidi"
cffb2a26 1292 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 1293 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r")
9c08d1fa 1294 (zero_extend:DI
cffb2a26 1295 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 1296 (clobber (reg:CC CC_REGNUM))]
25f905c2 1297 "TARGET_32BIT"
2f9b23e3 1298 "#" ; "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
1299 "&& reload_completed"
1300 [(parallel [(set (reg:CC CC_REGNUM)
1301 (compare:CC (match_dup 1) (match_dup 2)))
1302 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1303 (set (match_dup 3) (minus:SI (plus:SI (match_dup 4) (match_dup 5))
1304 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1305 {
1306 operands[3] = gen_highpart (SImode, operands[0]);
1307 operands[0] = gen_lowpart (SImode, operands[0]);
1308 operands[4] = gen_highpart (SImode, operands[1]);
1309 operands[1] = gen_lowpart (SImode, operands[1]);
1310 operands[5] = GEN_INT (~0);
1311 }
cffb2a26 1312 [(set_attr "conds" "clob")
1b7da4ac 1313 (set_attr "length" "8")
1314 (set_attr "type" "multiple")]
cffb2a26 1315)
9c08d1fa 1316
2f9b23e3 1317(define_insn_and_split "*subdi_di_sesidi"
cffb2a26 1318 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 1319 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r")
9c08d1fa 1320 (sign_extend:DI
cffb2a26 1321 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 1322 (clobber (reg:CC CC_REGNUM))]
25f905c2 1323 "TARGET_32BIT"
2f9b23e3 1324 "#" ; "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
1325 "&& reload_completed"
1326 [(parallel [(set (reg:CC CC_REGNUM)
1327 (compare:CC (match_dup 1) (match_dup 2)))
1328 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1329 (set (match_dup 3) (minus:SI (minus:SI (match_dup 4)
1330 (ashiftrt:SI (match_dup 2)
1331 (const_int 31)))
1332 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1333 {
1334 operands[3] = gen_highpart (SImode, operands[0]);
1335 operands[0] = gen_lowpart (SImode, operands[0]);
1336 operands[4] = gen_highpart (SImode, operands[1]);
1337 operands[1] = gen_lowpart (SImode, operands[1]);
1338 }
cffb2a26 1339 [(set_attr "conds" "clob")
1b7da4ac 1340 (set_attr "length" "8")
1341 (set_attr "type" "multiple")]
cffb2a26 1342)
9c08d1fa 1343
2f9b23e3 1344(define_insn_and_split "*subdi_zesidi_di"
cffb2a26 1345 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1346 (minus:DI (zero_extend:DI
cffb2a26 1347 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 1348 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 1349 (clobber (reg:CC CC_REGNUM))]
cffb2a26 1350 "TARGET_ARM"
2f9b23e3 1351 "#" ; "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
1352 ; is equivalent to:
1353 ; "subs\\t%Q0, %2, %Q1\;rsc\\t%R0, %R1, #0"
1354 "&& reload_completed"
1355 [(parallel [(set (reg:CC CC_REGNUM)
1356 (compare:CC (match_dup 2) (match_dup 1)))
1357 (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))])
1358 (set (match_dup 3) (minus:SI (minus:SI (const_int 0) (match_dup 4))
1359 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1360 {
1361 operands[3] = gen_highpart (SImode, operands[0]);
1362 operands[0] = gen_lowpart (SImode, operands[0]);
1363 operands[4] = gen_highpart (SImode, operands[1]);
1364 operands[1] = gen_lowpart (SImode, operands[1]);
1365 }
cffb2a26 1366 [(set_attr "conds" "clob")
1b7da4ac 1367 (set_attr "length" "8")
1368 (set_attr "type" "multiple")]
cffb2a26 1369)
9c08d1fa 1370
2f9b23e3 1371(define_insn_and_split "*subdi_sesidi_di"
cffb2a26 1372 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1373 (minus:DI (sign_extend:DI
cffb2a26 1374 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 1375 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 1376 (clobber (reg:CC CC_REGNUM))]
cffb2a26 1377 "TARGET_ARM"
2f9b23e3 1378 "#" ; "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
1379 ; is equivalent to:
1380 ; "subs\\t%Q0, %2, %Q1\;rsc\\t%R0, %R1, %2, asr #31"
1381 "&& reload_completed"
1382 [(parallel [(set (reg:CC CC_REGNUM)
1383 (compare:CC (match_dup 2) (match_dup 1)))
1384 (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))])
1385 (set (match_dup 3) (minus:SI (minus:SI
1386 (ashiftrt:SI (match_dup 2)
1387 (const_int 31))
1388 (match_dup 4))
1389 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1390 {
1391 operands[3] = gen_highpart (SImode, operands[0]);
1392 operands[0] = gen_lowpart (SImode, operands[0]);
1393 operands[4] = gen_highpart (SImode, operands[1]);
1394 operands[1] = gen_lowpart (SImode, operands[1]);
1395 }
cffb2a26 1396 [(set_attr "conds" "clob")
1b7da4ac 1397 (set_attr "length" "8")
1398 (set_attr "type" "multiple")]
cffb2a26 1399)
9c08d1fa 1400
2f9b23e3 1401(define_insn_and_split "*subdi_zesidi_zesidi"
cffb2a26 1402 [(set (match_operand:DI 0 "s_register_operand" "=r")
9c08d1fa 1403 (minus:DI (zero_extend:DI
cffb2a26 1404 (match_operand:SI 1 "s_register_operand" "r"))
9c08d1fa 1405 (zero_extend:DI
cffb2a26 1406 (match_operand:SI 2 "s_register_operand" "r"))))
bd5b4116 1407 (clobber (reg:CC CC_REGNUM))]
25f905c2 1408 "TARGET_32BIT"
2f9b23e3 1409 "#" ; "subs\\t%Q0, %1, %2\;sbc\\t%R0, %1, %1"
1410 "&& reload_completed"
1411 [(parallel [(set (reg:CC CC_REGNUM)
1412 (compare:CC (match_dup 1) (match_dup 2)))
1413 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1414 (set (match_dup 3) (minus:SI (minus:SI (match_dup 1) (match_dup 1))
1415 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1416 {
1417 operands[3] = gen_highpart (SImode, operands[0]);
1418 operands[0] = gen_lowpart (SImode, operands[0]);
1419 }
cffb2a26 1420 [(set_attr "conds" "clob")
1b7da4ac 1421 (set_attr "length" "8")
1422 (set_attr "type" "multiple")]
cffb2a26 1423)
b11cae9e 1424
87b22bf7 1425(define_expand "subsi3"
cffb2a26 1426 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 1427 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
1428 (match_operand:SI 2 "s_register_operand" "")))]
cffb2a26 1429 "TARGET_EITHER"
87b22bf7 1430 "
0438d37f 1431 if (CONST_INT_P (operands[1]))
87b22bf7 1432 {
25f905c2 1433 if (TARGET_32BIT)
cffb2a26 1434 {
17202aa5 1435 if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[1]), MINUS))
1436 operands[1] = force_reg (SImode, operands[1]);
1437 else
1438 {
1439 arm_split_constant (MINUS, SImode, NULL_RTX,
1440 INTVAL (operands[1]), operands[0],
1441 operands[2],
1442 optimize && can_create_pseudo_p ());
1443 DONE;
1444 }
cffb2a26 1445 }
25f905c2 1446 else /* TARGET_THUMB1 */
cffb2a26 1447 operands[1] = force_reg (SImode, operands[1]);
87b22bf7 1448 }
cffb2a26 1449 "
1450)
87b22bf7 1451
25f905c2 1452; ??? Check Thumb-2 split length
a0f94409 1453(define_insn_and_split "*arm_subsi3_insn"
3a44c5a9 1454 [(set (match_operand:SI 0 "s_register_operand" "=l,l ,l ,l ,r,r,r,rk,r")
1455 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "l ,0 ,l ,Pz,I,r,r,k ,?n")
1456 (match_operand:SI 2 "reg_or_int_operand" "l ,Py,Pd,l ,r,I,r,r ,r")))]
25f905c2 1457 "TARGET_32BIT"
e2348bcb 1458 "@
7c36fe71 1459 sub%?\\t%0, %1, %2
1460 sub%?\\t%0, %2
1461 sub%?\\t%0, %1, %2
1462 rsb%?\\t%0, %2, %1
87b22bf7 1463 rsb%?\\t%0, %2, %1
aaa37ad6 1464 sub%?\\t%0, %1, %2
080c0b9a 1465 sub%?\\t%0, %1, %2
65f68e55 1466 sub%?\\t%0, %1, %2
87b22bf7 1467 #"
0438d37f 1468 "&& (CONST_INT_P (operands[1])
91a5e339 1469 && !const_ok_for_arm (INTVAL (operands[1])))"
87b22bf7 1470 [(clobber (const_int 0))]
1471 "
96f57e36 1472 arm_split_constant (MINUS, SImode, curr_insn,
1473 INTVAL (operands[1]), operands[0], operands[2], 0);
87b22bf7 1474 DONE;
cffb2a26 1475 "
7c36fe71 1476 [(set_attr "length" "4,4,4,4,4,4,4,4,16")
1477 (set_attr "arch" "t2,t2,t2,t2,*,*,*,*,*")
65f68e55 1478 (set_attr "predicable" "yes")
7c36fe71 1479 (set_attr "predicable_short_it" "yes,yes,yes,yes,no,no,no,no,no")
112eda6f 1480 (set_attr "type" "alu_sreg,alu_sreg,alu_sreg,alu_sreg,alu_imm,alu_imm,alu_sreg,alu_sreg,multiple")]
a0f94409 1481)
1482
1483(define_peephole2
1484 [(match_scratch:SI 3 "r")
372575c7 1485 (set (match_operand:SI 0 "arm_general_register_operand" "")
a0f94409 1486 (minus:SI (match_operand:SI 1 "const_int_operand" "")
372575c7 1487 (match_operand:SI 2 "arm_general_register_operand" "")))]
25f905c2 1488 "TARGET_32BIT
a0f94409 1489 && !const_ok_for_arm (INTVAL (operands[1]))
1490 && const_ok_for_arm (~INTVAL (operands[1]))"
1491 [(set (match_dup 3) (match_dup 1))
1492 (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1493 ""
cffb2a26 1494)
b11cae9e 1495
62e39b06 1496(define_insn "subsi3_compare0"
bd5b4116 1497 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1498 (compare:CC_NOOV
65f68e55 1499 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,r,I")
1500 (match_operand:SI 2 "arm_rhs_operand" "I,r,r"))
215b30b3 1501 (const_int 0)))
65f68e55 1502 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9c08d1fa 1503 (minus:SI (match_dup 1) (match_dup 2)))]
25f905c2 1504 "TARGET_32BIT"
e2348bcb 1505 "@
3ef90e77 1506 subs%?\\t%0, %1, %2
1507 subs%?\\t%0, %1, %2
1508 rsbs%?\\t%0, %2, %1"
65f68e55 1509 [(set_attr "conds" "set")
112eda6f 1510 (set_attr "type" "alus_imm,alus_sreg,alus_sreg")]
cffb2a26 1511)
9c08d1fa 1512
190efb17 1513(define_insn "subsi3_compare"
080c0b9a 1514 [(set (reg:CC CC_REGNUM)
65f68e55 1515 (compare:CC (match_operand:SI 1 "arm_rhs_operand" "r,r,I")
1516 (match_operand:SI 2 "arm_rhs_operand" "I,r,r")))
1517 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2df9477b 1518 (minus:SI (match_dup 1) (match_dup 2)))]
1519 "TARGET_32BIT"
1520 "@
3ef90e77 1521 subs%?\\t%0, %1, %2
1522 subs%?\\t%0, %1, %2
1523 rsbs%?\\t%0, %2, %1"
65f68e55 1524 [(set_attr "conds" "set")
112eda6f 1525 (set_attr "type" "alus_imm,alus_sreg,alus_sreg")]
2df9477b 1526)
1527
604f3a0a 1528(define_expand "subsf3"
1529 [(set (match_operand:SF 0 "s_register_operand" "")
d86c91f6 1530 (minus:SF (match_operand:SF 1 "s_register_operand" "")
1531 (match_operand:SF 2 "s_register_operand" "")))]
25f905c2 1532 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1533 "
604f3a0a 1534")
1535
604f3a0a 1536(define_expand "subdf3"
1537 [(set (match_operand:DF 0 "s_register_operand" "")
d86c91f6 1538 (minus:DF (match_operand:DF 1 "s_register_operand" "")
1539 (match_operand:DF 2 "s_register_operand" "")))]
a50d7267 1540 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 1541 "
604f3a0a 1542")
1543
b11cae9e 1544\f
1545;; Multiplication insns
1546
4422d91f 1547(define_expand "mulhi3"
1548 [(set (match_operand:HI 0 "s_register_operand" "")
1549 (mult:HI (match_operand:HI 1 "s_register_operand" "")
1550 (match_operand:HI 2 "s_register_operand" "")))]
1551 "TARGET_DSP_MULTIPLY"
1552 "
1553 {
1554 rtx result = gen_reg_rtx (SImode);
1555 emit_insn (gen_mulhisi3 (result, operands[1], operands[2]));
1556 emit_move_insn (operands[0], gen_lowpart (HImode, result));
1557 DONE;
1558 }"
1559)
1560
cffb2a26 1561(define_expand "mulsi3"
1562 [(set (match_operand:SI 0 "s_register_operand" "")
1563 (mult:SI (match_operand:SI 2 "s_register_operand" "")
1564 (match_operand:SI 1 "s_register_operand" "")))]
1565 "TARGET_EITHER"
1566 ""
1567)
1568
9c08d1fa 1569;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
cffb2a26 1570(define_insn "*arm_mulsi3"
1571 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1572 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1573 (match_operand:SI 1 "s_register_operand" "%0,r")))]
58d7d654 1574 "TARGET_32BIT && !arm_arch6"
f7fbdd4a 1575 "mul%?\\t%0, %2, %1"
9da0ec36 1576 [(set_attr "type" "mul")
0d66636f 1577 (set_attr "predicable" "yes")]
cffb2a26 1578)
1579
58d7d654 1580(define_insn "*arm_mulsi3_v6"
d952d547 1581 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
1582 (mult:SI (match_operand:SI 1 "s_register_operand" "0,l,r")
1583 (match_operand:SI 2 "s_register_operand" "l,0,r")))]
58d7d654 1584 "TARGET_32BIT && arm_arch6"
1585 "mul%?\\t%0, %1, %2"
9da0ec36 1586 [(set_attr "type" "mul")
d952d547 1587 (set_attr "predicable" "yes")
1588 (set_attr "arch" "t2,t2,*")
1589 (set_attr "length" "4")
1590 (set_attr "predicable_short_it" "yes,yes,no")]
58d7d654 1591)
1592
f7fbdd4a 1593(define_insn "*mulsi3_compare0"
bd5b4116 1594 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1595 (compare:CC_NOOV (mult:SI
1596 (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1597 (match_operand:SI 1 "s_register_operand" "%0,r"))
9c08d1fa 1598 (const_int 0)))
1599 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1600 (mult:SI (match_dup 2) (match_dup 1)))]
58d7d654 1601 "TARGET_ARM && !arm_arch6"
3ef90e77 1602 "muls%?\\t%0, %2, %1"
58d7d654 1603 [(set_attr "conds" "set")
9da0ec36 1604 (set_attr "type" "muls")]
58d7d654 1605)
1606
1607(define_insn "*mulsi3_compare0_v6"
1608 [(set (reg:CC_NOOV CC_REGNUM)
1609 (compare:CC_NOOV (mult:SI
1610 (match_operand:SI 2 "s_register_operand" "r")
1611 (match_operand:SI 1 "s_register_operand" "r"))
1612 (const_int 0)))
1613 (set (match_operand:SI 0 "s_register_operand" "=r")
1614 (mult:SI (match_dup 2) (match_dup 1)))]
1615 "TARGET_ARM && arm_arch6 && optimize_size"
3ef90e77 1616 "muls%?\\t%0, %2, %1"
cffb2a26 1617 [(set_attr "conds" "set")
9da0ec36 1618 (set_attr "type" "muls")]
cffb2a26 1619)
9c08d1fa 1620
f7fbdd4a 1621(define_insn "*mulsi_compare0_scratch"
bd5b4116 1622 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1623 (compare:CC_NOOV (mult:SI
1624 (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1625 (match_operand:SI 1 "s_register_operand" "%0,r"))
9c08d1fa 1626 (const_int 0)))
1627 (clobber (match_scratch:SI 0 "=&r,&r"))]
58d7d654 1628 "TARGET_ARM && !arm_arch6"
3ef90e77 1629 "muls%?\\t%0, %2, %1"
58d7d654 1630 [(set_attr "conds" "set")
9da0ec36 1631 (set_attr "type" "muls")]
58d7d654 1632)
1633
1634(define_insn "*mulsi_compare0_scratch_v6"
1635 [(set (reg:CC_NOOV CC_REGNUM)
1636 (compare:CC_NOOV (mult:SI
1637 (match_operand:SI 2 "s_register_operand" "r")
1638 (match_operand:SI 1 "s_register_operand" "r"))
1639 (const_int 0)))
1640 (clobber (match_scratch:SI 0 "=r"))]
1641 "TARGET_ARM && arm_arch6 && optimize_size"
3ef90e77 1642 "muls%?\\t%0, %2, %1"
cffb2a26 1643 [(set_attr "conds" "set")
9da0ec36 1644 (set_attr "type" "muls")]
cffb2a26 1645)
9c08d1fa 1646
b11cae9e 1647;; Unnamed templates to match MLA instruction.
1648
f7fbdd4a 1649(define_insn "*mulsi3addsi"
9c08d1fa 1650 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
c8f69309 1651 (plus:SI
9c08d1fa 1652 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1653 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1654 (match_operand:SI 3 "s_register_operand" "r,r,0,0")))]
58d7d654 1655 "TARGET_32BIT && !arm_arch6"
1656 "mla%?\\t%0, %2, %1, %3"
9da0ec36 1657 [(set_attr "type" "mla")
58d7d654 1658 (set_attr "predicable" "yes")]
1659)
1660
1661(define_insn "*mulsi3addsi_v6"
1662 [(set (match_operand:SI 0 "s_register_operand" "=r")
1663 (plus:SI
1664 (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1665 (match_operand:SI 1 "s_register_operand" "r"))
1666 (match_operand:SI 3 "s_register_operand" "r")))]
1667 "TARGET_32BIT && arm_arch6"
f7fbdd4a 1668 "mla%?\\t%0, %2, %1, %3"
9da0ec36 1669 [(set_attr "type" "mla")
d952d547 1670 (set_attr "predicable" "yes")
1671 (set_attr "predicable_short_it" "no")]
0d66636f 1672)
b11cae9e 1673
f7fbdd4a 1674(define_insn "*mulsi3addsi_compare0"
bd5b4116 1675 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1676 (compare:CC_NOOV
1677 (plus:SI (mult:SI
1678 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1679 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1680 (match_operand:SI 3 "s_register_operand" "r,r,0,0"))
215b30b3 1681 (const_int 0)))
9c08d1fa 1682 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1683 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1684 (match_dup 3)))]
58d7d654 1685 "TARGET_ARM && arm_arch6"
3ef90e77 1686 "mlas%?\\t%0, %2, %1, %3"
58d7d654 1687 [(set_attr "conds" "set")
9da0ec36 1688 (set_attr "type" "mlas")]
58d7d654 1689)
1690
1691(define_insn "*mulsi3addsi_compare0_v6"
1692 [(set (reg:CC_NOOV CC_REGNUM)
1693 (compare:CC_NOOV
1694 (plus:SI (mult:SI
1695 (match_operand:SI 2 "s_register_operand" "r")
1696 (match_operand:SI 1 "s_register_operand" "r"))
1697 (match_operand:SI 3 "s_register_operand" "r"))
1698 (const_int 0)))
1699 (set (match_operand:SI 0 "s_register_operand" "=r")
1700 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1701 (match_dup 3)))]
1702 "TARGET_ARM && arm_arch6 && optimize_size"
3ef90e77 1703 "mlas%?\\t%0, %2, %1, %3"
0d66636f 1704 [(set_attr "conds" "set")
9da0ec36 1705 (set_attr "type" "mlas")]
0d66636f 1706)
9c08d1fa 1707
f7fbdd4a 1708(define_insn "*mulsi3addsi_compare0_scratch"
bd5b4116 1709 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1710 (compare:CC_NOOV
1711 (plus:SI (mult:SI
1712 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1713 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
215b30b3 1714 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1715 (const_int 0)))
9c08d1fa 1716 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
58d7d654 1717 "TARGET_ARM && !arm_arch6"
3ef90e77 1718 "mlas%?\\t%0, %2, %1, %3"
58d7d654 1719 [(set_attr "conds" "set")
9da0ec36 1720 (set_attr "type" "mlas")]
58d7d654 1721)
1722
1723(define_insn "*mulsi3addsi_compare0_scratch_v6"
1724 [(set (reg:CC_NOOV CC_REGNUM)
1725 (compare:CC_NOOV
1726 (plus:SI (mult:SI
1727 (match_operand:SI 2 "s_register_operand" "r")
1728 (match_operand:SI 1 "s_register_operand" "r"))
1729 (match_operand:SI 3 "s_register_operand" "r"))
1730 (const_int 0)))
1731 (clobber (match_scratch:SI 0 "=r"))]
1732 "TARGET_ARM && arm_arch6 && optimize_size"
3ef90e77 1733 "mlas%?\\t%0, %2, %1, %3"
cffb2a26 1734 [(set_attr "conds" "set")
9da0ec36 1735 (set_attr "type" "mlas")]
cffb2a26 1736)
f7fbdd4a 1737
89545238 1738(define_insn "*mulsi3subsi"
1739 [(set (match_operand:SI 0 "s_register_operand" "=r")
1740 (minus:SI
1741 (match_operand:SI 3 "s_register_operand" "r")
1742 (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1743 (match_operand:SI 1 "s_register_operand" "r"))))]
1744 "TARGET_32BIT && arm_arch_thumb2"
1745 "mls%?\\t%0, %2, %1, %3"
9da0ec36 1746 [(set_attr "type" "mla")
d952d547 1747 (set_attr "predicable" "yes")
1748 (set_attr "predicable_short_it" "no")]
89545238 1749)
1750
5cdca009 1751(define_expand "maddsidi4"
1752 [(set (match_operand:DI 0 "s_register_operand" "")
1753 (plus:DI
1754 (mult:DI
1755 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1756 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1757 (match_operand:DI 3 "s_register_operand" "")))]
1758 "TARGET_32BIT && arm_arch3m"
1759 "")
82b85d08 1760
1761(define_insn "*mulsidi3adddi"
fe8dbf85 1762 [(set (match_operand:DI 0 "s_register_operand" "=&r")
82b85d08 1763 (plus:DI
215b30b3 1764 (mult:DI
fe8dbf85 1765 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1766 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1767 (match_operand:DI 1 "s_register_operand" "0")))]
58d7d654 1768 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1769 "smlal%?\\t%Q0, %R0, %3, %2"
9da0ec36 1770 [(set_attr "type" "smlal")
58d7d654 1771 (set_attr "predicable" "yes")]
1772)
1773
1774(define_insn "*mulsidi3adddi_v6"
1775 [(set (match_operand:DI 0 "s_register_operand" "=r")
1776 (plus:DI
1777 (mult:DI
1778 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1779 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1780 (match_operand:DI 1 "s_register_operand" "0")))]
1781 "TARGET_32BIT && arm_arch6"
fe8dbf85 1782 "smlal%?\\t%Q0, %R0, %3, %2"
9da0ec36 1783 [(set_attr "type" "smlal")
d952d547 1784 (set_attr "predicable" "yes")
1785 (set_attr "predicable_short_it" "no")]
0d66636f 1786)
82b85d08 1787
957788b0 1788;; 32x32->64 widening multiply.
1789;; As with mulsi3, the only difference between the v3-5 and v6+
1790;; versions of these patterns is the requirement that the output not
1791;; overlap the inputs, but that still means we have to have a named
1792;; expander and two different starred insns.
1793
1794(define_expand "mulsidi3"
1795 [(set (match_operand:DI 0 "s_register_operand" "")
1796 (mult:DI
1797 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1798 (sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1799 "TARGET_32BIT && arm_arch3m"
1800 ""
1801)
1802
1803(define_insn "*mulsidi3_nov6"
f7fbdd4a 1804 [(set (match_operand:DI 0 "s_register_operand" "=&r")
215b30b3 1805 (mult:DI
1806 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1807 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
58d7d654 1808 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1809 "smull%?\\t%Q0, %R0, %1, %2"
9da0ec36 1810 [(set_attr "type" "smull")
58d7d654 1811 (set_attr "predicable" "yes")]
1812)
1813
957788b0 1814(define_insn "*mulsidi3_v6"
58d7d654 1815 [(set (match_operand:DI 0 "s_register_operand" "=r")
1816 (mult:DI
1817 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1818 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1819 "TARGET_32BIT && arm_arch6"
97499065 1820 "smull%?\\t%Q0, %R0, %1, %2"
9da0ec36 1821 [(set_attr "type" "smull")
d952d547 1822 (set_attr "predicable" "yes")
1823 (set_attr "predicable_short_it" "no")]
0d66636f 1824)
f7fbdd4a 1825
957788b0 1826(define_expand "umulsidi3"
1827 [(set (match_operand:DI 0 "s_register_operand" "")
1828 (mult:DI
1829 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1830 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1831 "TARGET_32BIT && arm_arch3m"
1832 ""
1833)
1834
1835(define_insn "*umulsidi3_nov6"
f7fbdd4a 1836 [(set (match_operand:DI 0 "s_register_operand" "=&r")
215b30b3 1837 (mult:DI
1838 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1839 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
58d7d654 1840 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1841 "umull%?\\t%Q0, %R0, %1, %2"
9da0ec36 1842 [(set_attr "type" "umull")
58d7d654 1843 (set_attr "predicable" "yes")]
1844)
1845
957788b0 1846(define_insn "*umulsidi3_v6"
58d7d654 1847 [(set (match_operand:DI 0 "s_register_operand" "=r")
1848 (mult:DI
1849 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1850 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1851 "TARGET_32BIT && arm_arch6"
97499065 1852 "umull%?\\t%Q0, %R0, %1, %2"
9da0ec36 1853 [(set_attr "type" "umull")
d952d547 1854 (set_attr "predicable" "yes")
1855 (set_attr "predicable_short_it" "no")]
0d66636f 1856)
b11cae9e 1857
5cdca009 1858(define_expand "umaddsidi4"
1859 [(set (match_operand:DI 0 "s_register_operand" "")
1860 (plus:DI
1861 (mult:DI
1862 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1863 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1864 (match_operand:DI 3 "s_register_operand" "")))]
1865 "TARGET_32BIT && arm_arch3m"
1866 "")
82b85d08 1867
1868(define_insn "*umulsidi3adddi"
8ead09f9 1869 [(set (match_operand:DI 0 "s_register_operand" "=&r")
82b85d08 1870 (plus:DI
215b30b3 1871 (mult:DI
fe8dbf85 1872 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1873 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1874 (match_operand:DI 1 "s_register_operand" "0")))]
58d7d654 1875 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1876 "umlal%?\\t%Q0, %R0, %3, %2"
9da0ec36 1877 [(set_attr "type" "umlal")
58d7d654 1878 (set_attr "predicable" "yes")]
1879)
1880
1881(define_insn "*umulsidi3adddi_v6"
1882 [(set (match_operand:DI 0 "s_register_operand" "=r")
1883 (plus:DI
1884 (mult:DI
1885 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1886 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1887 (match_operand:DI 1 "s_register_operand" "0")))]
1888 "TARGET_32BIT && arm_arch6"
fe8dbf85 1889 "umlal%?\\t%Q0, %R0, %3, %2"
9da0ec36 1890 [(set_attr "type" "umlal")
d952d547 1891 (set_attr "predicable" "yes")
1892 (set_attr "predicable_short_it" "no")]
0d66636f 1893)
82b85d08 1894
957788b0 1895(define_expand "smulsi3_highpart"
1896 [(parallel
1897 [(set (match_operand:SI 0 "s_register_operand" "")
1898 (truncate:SI
1899 (lshiftrt:DI
1900 (mult:DI
1901 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1902 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1903 (const_int 32))))
1904 (clobber (match_scratch:SI 3 ""))])]
1905 "TARGET_32BIT && arm_arch3m"
1906 ""
1907)
1908
1909(define_insn "*smulsi3_highpart_nov6"
f082f1c4 1910 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1911 (truncate:SI
1912 (lshiftrt:DI
215b30b3 1913 (mult:DI
e5fea38e 1914 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
215b30b3 1915 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
f082f1c4 1916 (const_int 32))))
1917 (clobber (match_scratch:SI 3 "=&r,&r"))]
58d7d654 1918 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1919 "smull%?\\t%3, %0, %2, %1"
9da0ec36 1920 [(set_attr "type" "smull")
58d7d654 1921 (set_attr "predicable" "yes")]
1922)
1923
957788b0 1924(define_insn "*smulsi3_highpart_v6"
58d7d654 1925 [(set (match_operand:SI 0 "s_register_operand" "=r")
1926 (truncate:SI
1927 (lshiftrt:DI
1928 (mult:DI
1929 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1930 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1931 (const_int 32))))
1932 (clobber (match_scratch:SI 3 "=r"))]
1933 "TARGET_32BIT && arm_arch6"
f082f1c4 1934 "smull%?\\t%3, %0, %2, %1"
9da0ec36 1935 [(set_attr "type" "smull")
d952d547 1936 (set_attr "predicable" "yes")
1937 (set_attr "predicable_short_it" "no")]
cffb2a26 1938)
f082f1c4 1939
957788b0 1940(define_expand "umulsi3_highpart"
1941 [(parallel
1942 [(set (match_operand:SI 0 "s_register_operand" "")
1943 (truncate:SI
1944 (lshiftrt:DI
1945 (mult:DI
1946 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1947 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1948 (const_int 32))))
1949 (clobber (match_scratch:SI 3 ""))])]
1950 "TARGET_32BIT && arm_arch3m"
1951 ""
1952)
1953
1954(define_insn "*umulsi3_highpart_nov6"
f082f1c4 1955 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1956 (truncate:SI
1957 (lshiftrt:DI
215b30b3 1958 (mult:DI
e5fea38e 1959 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
215b30b3 1960 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
f082f1c4 1961 (const_int 32))))
1962 (clobber (match_scratch:SI 3 "=&r,&r"))]
58d7d654 1963 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1964 "umull%?\\t%3, %0, %2, %1"
9da0ec36 1965 [(set_attr "type" "umull")
58d7d654 1966 (set_attr "predicable" "yes")]
1967)
1968
957788b0 1969(define_insn "*umulsi3_highpart_v6"
58d7d654 1970 [(set (match_operand:SI 0 "s_register_operand" "=r")
1971 (truncate:SI
1972 (lshiftrt:DI
1973 (mult:DI
1974 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1975 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1976 (const_int 32))))
1977 (clobber (match_scratch:SI 3 "=r"))]
1978 "TARGET_32BIT && arm_arch6"
f082f1c4 1979 "umull%?\\t%3, %0, %2, %1"
9da0ec36 1980 [(set_attr "type" "umull")
d952d547 1981 (set_attr "predicable" "yes")
1982 (set_attr "predicable_short_it" "no")]
cffb2a26 1983)
f082f1c4 1984
331beb1a 1985(define_insn "mulhisi3"
1986 [(set (match_operand:SI 0 "s_register_operand" "=r")
1987 (mult:SI (sign_extend:SI
1988 (match_operand:HI 1 "s_register_operand" "%r"))
1989 (sign_extend:SI
1990 (match_operand:HI 2 "s_register_operand" "r"))))]
25f905c2 1991 "TARGET_DSP_MULTIPLY"
61a2d04c 1992 "smulbb%?\\t%0, %1, %2"
9da0ec36 1993 [(set_attr "type" "smulxy")
fec538d9 1994 (set_attr "predicable" "yes")]
1995)
1996
1997(define_insn "*mulhisi3tb"
1998 [(set (match_operand:SI 0 "s_register_operand" "=r")
1999 (mult:SI (ashiftrt:SI
2000 (match_operand:SI 1 "s_register_operand" "r")
2001 (const_int 16))
2002 (sign_extend:SI
2003 (match_operand:HI 2 "s_register_operand" "r"))))]
25f905c2 2004 "TARGET_DSP_MULTIPLY"
fec538d9 2005 "smultb%?\\t%0, %1, %2"
9da0ec36 2006 [(set_attr "type" "smulxy")
d952d547 2007 (set_attr "predicable" "yes")
2008 (set_attr "predicable_short_it" "no")]
fec538d9 2009)
2010
2011(define_insn "*mulhisi3bt"
2012 [(set (match_operand:SI 0 "s_register_operand" "=r")
2013 (mult:SI (sign_extend:SI
2014 (match_operand:HI 1 "s_register_operand" "r"))
2015 (ashiftrt:SI
2016 (match_operand:SI 2 "s_register_operand" "r")
2017 (const_int 16))))]
25f905c2 2018 "TARGET_DSP_MULTIPLY"
fec538d9 2019 "smulbt%?\\t%0, %1, %2"
9da0ec36 2020 [(set_attr "type" "smulxy")
d952d547 2021 (set_attr "predicable" "yes")
2022 (set_attr "predicable_short_it" "no")]
fec538d9 2023)
2024
2025(define_insn "*mulhisi3tt"
2026 [(set (match_operand:SI 0 "s_register_operand" "=r")
2027 (mult:SI (ashiftrt:SI
2028 (match_operand:SI 1 "s_register_operand" "r")
2029 (const_int 16))
2030 (ashiftrt:SI
2031 (match_operand:SI 2 "s_register_operand" "r")
2032 (const_int 16))))]
25f905c2 2033 "TARGET_DSP_MULTIPLY"
fec538d9 2034 "smultt%?\\t%0, %1, %2"
9da0ec36 2035 [(set_attr "type" "smulxy")
d952d547 2036 (set_attr "predicable" "yes")
2037 (set_attr "predicable_short_it" "no")]
331beb1a 2038)
2039
5cdca009 2040(define_insn "maddhisi4"
331beb1a 2041 [(set (match_operand:SI 0 "s_register_operand" "=r")
cfa6c608 2042 (plus:SI (mult:SI (sign_extend:SI
2043 (match_operand:HI 1 "s_register_operand" "r"))
331beb1a 2044 (sign_extend:SI
cfa6c608 2045 (match_operand:HI 2 "s_register_operand" "r")))
2046 (match_operand:SI 3 "s_register_operand" "r")))]
25f905c2 2047 "TARGET_DSP_MULTIPLY"
5cdca009 2048 "smlabb%?\\t%0, %1, %2, %3"
9da0ec36 2049 [(set_attr "type" "smlaxy")
d952d547 2050 (set_attr "predicable" "yes")
2051 (set_attr "predicable_short_it" "no")]
331beb1a 2052)
2053
9a92f368 2054;; Note: there is no maddhisi4ibt because this one is canonical form
2055(define_insn "*maddhisi4tb"
2056 [(set (match_operand:SI 0 "s_register_operand" "=r")
2057 (plus:SI (mult:SI (ashiftrt:SI
2058 (match_operand:SI 1 "s_register_operand" "r")
2059 (const_int 16))
2060 (sign_extend:SI
2061 (match_operand:HI 2 "s_register_operand" "r")))
2062 (match_operand:SI 3 "s_register_operand" "r")))]
2063 "TARGET_DSP_MULTIPLY"
2064 "smlatb%?\\t%0, %1, %2, %3"
9da0ec36 2065 [(set_attr "type" "smlaxy")
d952d547 2066 (set_attr "predicable" "yes")
2067 (set_attr "predicable_short_it" "no")]
9a92f368 2068)
2069
2070(define_insn "*maddhisi4tt"
2071 [(set (match_operand:SI 0 "s_register_operand" "=r")
2072 (plus:SI (mult:SI (ashiftrt:SI
2073 (match_operand:SI 1 "s_register_operand" "r")
2074 (const_int 16))
2075 (ashiftrt:SI
2076 (match_operand:SI 2 "s_register_operand" "r")
2077 (const_int 16)))
2078 (match_operand:SI 3 "s_register_operand" "r")))]
2079 "TARGET_DSP_MULTIPLY"
2080 "smlatt%?\\t%0, %1, %2, %3"
9da0ec36 2081 [(set_attr "type" "smlaxy")
d952d547 2082 (set_attr "predicable" "yes")
2083 (set_attr "predicable_short_it" "no")]
9a92f368 2084)
2085
aff5fb4d 2086(define_insn "maddhidi4"
331beb1a 2087 [(set (match_operand:DI 0 "s_register_operand" "=r")
2088 (plus:DI
331beb1a 2089 (mult:DI (sign_extend:DI
d952d547 2090 (match_operand:HI 1 "s_register_operand" "r"))
331beb1a 2091 (sign_extend:DI
cfa6c608 2092 (match_operand:HI 2 "s_register_operand" "r")))
2093 (match_operand:DI 3 "s_register_operand" "0")))]
25f905c2 2094 "TARGET_DSP_MULTIPLY"
5cdca009 2095 "smlalbb%?\\t%Q0, %R0, %1, %2"
9da0ec36 2096 [(set_attr "type" "smlalxy")
d952d547 2097 (set_attr "predicable" "yes")
2098 (set_attr "predicable_short_it" "no")])
331beb1a 2099
9a92f368 2100;; Note: there is no maddhidi4ibt because this one is canonical form
2101(define_insn "*maddhidi4tb"
2102 [(set (match_operand:DI 0 "s_register_operand" "=r")
2103 (plus:DI
2104 (mult:DI (sign_extend:DI
2105 (ashiftrt:SI
2106 (match_operand:SI 1 "s_register_operand" "r")
2107 (const_int 16)))
2108 (sign_extend:DI
2109 (match_operand:HI 2 "s_register_operand" "r")))
2110 (match_operand:DI 3 "s_register_operand" "0")))]
2111 "TARGET_DSP_MULTIPLY"
2112 "smlaltb%?\\t%Q0, %R0, %1, %2"
9da0ec36 2113 [(set_attr "type" "smlalxy")
d952d547 2114 (set_attr "predicable" "yes")
2115 (set_attr "predicable_short_it" "no")])
9a92f368 2116
2117(define_insn "*maddhidi4tt"
2118 [(set (match_operand:DI 0 "s_register_operand" "=r")
2119 (plus:DI
2120 (mult:DI (sign_extend:DI
2121 (ashiftrt:SI
2122 (match_operand:SI 1 "s_register_operand" "r")
2123 (const_int 16)))
2124 (sign_extend:DI
2125 (ashiftrt:SI
2126 (match_operand:SI 2 "s_register_operand" "r")
2127 (const_int 16))))
2128 (match_operand:DI 3 "s_register_operand" "0")))]
2129 "TARGET_DSP_MULTIPLY"
2130 "smlaltt%?\\t%Q0, %R0, %1, %2"
9da0ec36 2131 [(set_attr "type" "smlalxy")
d952d547 2132 (set_attr "predicable" "yes")
2133 (set_attr "predicable_short_it" "no")])
9a92f368 2134
604f3a0a 2135(define_expand "mulsf3"
2136 [(set (match_operand:SF 0 "s_register_operand" "")
2137 (mult:SF (match_operand:SF 1 "s_register_operand" "")
d86c91f6 2138 (match_operand:SF 2 "s_register_operand" "")))]
25f905c2 2139 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 2140 "
604f3a0a 2141")
2142
604f3a0a 2143(define_expand "muldf3"
2144 [(set (match_operand:DF 0 "s_register_operand" "")
2145 (mult:DF (match_operand:DF 1 "s_register_operand" "")
d86c91f6 2146 (match_operand:DF 2 "s_register_operand" "")))]
a50d7267 2147 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 2148 "
604f3a0a 2149")
b11cae9e 2150\f
2151;; Division insns
2152
7db9af5d 2153(define_expand "divsf3"
2154 [(set (match_operand:SF 0 "s_register_operand" "")
d86c91f6 2155 (div:SF (match_operand:SF 1 "s_register_operand" "")
2156 (match_operand:SF 2 "s_register_operand" "")))]
d7216193 2157 "TARGET_32BIT && TARGET_HARD_FLOAT"
7db9af5d 2158 "")
9c08d1fa 2159
7db9af5d 2160(define_expand "divdf3"
2161 [(set (match_operand:DF 0 "s_register_operand" "")
d86c91f6 2162 (div:DF (match_operand:DF 1 "s_register_operand" "")
2163 (match_operand:DF 2 "s_register_operand" "")))]
994606f8 2164 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
7db9af5d 2165 "")
b11cae9e 2166\f
2167;; Boolean and,ior,xor insns
2168
f6ebffac 2169;; Split up double word logical operations
2170
2171;; Split up simple DImode logical operations. Simply perform the logical
2172;; operation on the upper and lower halves of the registers.
2173(define_split
2174 [(set (match_operand:DI 0 "s_register_operand" "")
2175 (match_operator:DI 6 "logical_binary_operator"
2176 [(match_operand:DI 1 "s_register_operand" "")
2177 (match_operand:DI 2 "s_register_operand" "")]))]
25f905c2 2178 "TARGET_32BIT && reload_completed
e2669ea7 2179 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))
25f905c2 2180 && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
f6ebffac 2181 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
2182 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
2183 "
215b30b3 2184 {
2185 operands[3] = gen_highpart (SImode, operands[0]);
2186 operands[0] = gen_lowpart (SImode, operands[0]);
2187 operands[4] = gen_highpart (SImode, operands[1]);
2188 operands[1] = gen_lowpart (SImode, operands[1]);
2189 operands[5] = gen_highpart (SImode, operands[2]);
2190 operands[2] = gen_lowpart (SImode, operands[2]);
2191 }"
2192)
f6ebffac 2193
f6ebffac 2194(define_split
2195 [(set (match_operand:DI 0 "s_register_operand" "")
2196 (match_operator:DI 6 "logical_binary_operator"
2197 [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
2198 (match_operand:DI 1 "s_register_operand" "")]))]
25f905c2 2199 "TARGET_32BIT && reload_completed"
f6ebffac 2200 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
2201 (set (match_dup 3) (match_op_dup:SI 6
2202 [(ashiftrt:SI (match_dup 2) (const_int 31))
2203 (match_dup 4)]))]
2204 "
215b30b3 2205 {
2206 operands[3] = gen_highpart (SImode, operands[0]);
2207 operands[0] = gen_lowpart (SImode, operands[0]);
2208 operands[4] = gen_highpart (SImode, operands[1]);
2209 operands[1] = gen_lowpart (SImode, operands[1]);
2210 operands[5] = gen_highpart (SImode, operands[2]);
2211 operands[2] = gen_lowpart (SImode, operands[2]);
2212 }"
2213)
f6ebffac 2214
f6ebffac 2215;; The zero extend of operand 2 means we can just copy the high part of
2216;; operand1 into operand0.
2217(define_split
2218 [(set (match_operand:DI 0 "s_register_operand" "")
2219 (ior:DI
2220 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
2221 (match_operand:DI 1 "s_register_operand" "")))]
25f905c2 2222 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
f6ebffac 2223 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
2224 (set (match_dup 3) (match_dup 4))]
2225 "
215b30b3 2226 {
2227 operands[4] = gen_highpart (SImode, operands[1]);
2228 operands[3] = gen_highpart (SImode, operands[0]);
2229 operands[0] = gen_lowpart (SImode, operands[0]);
2230 operands[1] = gen_lowpart (SImode, operands[1]);
2231 }"
2232)
f6ebffac 2233
2234;; The zero extend of operand 2 means we can just copy the high part of
2235;; operand1 into operand0.
2236(define_split
2237 [(set (match_operand:DI 0 "s_register_operand" "")
2238 (xor:DI
2239 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
2240 (match_operand:DI 1 "s_register_operand" "")))]
25f905c2 2241 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
f6ebffac 2242 [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
2243 (set (match_dup 3) (match_dup 4))]
2244 "
215b30b3 2245 {
2246 operands[4] = gen_highpart (SImode, operands[1]);
2247 operands[3] = gen_highpart (SImode, operands[0]);
2248 operands[0] = gen_lowpart (SImode, operands[0]);
2249 operands[1] = gen_lowpart (SImode, operands[1]);
2250 }"
2251)
f6ebffac 2252
e2669ea7 2253(define_expand "anddi3"
2254 [(set (match_operand:DI 0 "s_register_operand" "")
2255 (and:DI (match_operand:DI 1 "s_register_operand" "")
2256 (match_operand:DI 2 "neon_inv_logic_op2" "")))]
2257 "TARGET_32BIT"
2258 ""
2259)
2260
f6bbdcf6 2261(define_insn_and_split "*anddi3_insn"
0a314dcd 2262 [(set (match_operand:DI 0 "s_register_operand" "=w,w ,&r,&r,&r,&r,?w,?w")
2263 (and:DI (match_operand:DI 1 "s_register_operand" "%w,0 ,0 ,r ,0 ,r ,w ,0")
2264 (match_operand:DI 2 "arm_anddi_operand_neon" "w ,DL,r ,r ,De,De,w ,DL")))]
f6bbdcf6 2265 "TARGET_32BIT && !TARGET_IWMMXT"
2266{
2267 switch (which_alternative)
2268 {
0a314dcd 2269 case 0: /* fall through */
2270 case 6: return "vand\t%P0, %P1, %P2";
2271 case 1: /* fall through */
2272 case 7: return neon_output_logic_immediate ("vand", &operands[2],
2273 DImode, 1, VALID_NEON_QREG_MODE (DImode));
f6bbdcf6 2274 case 2:
0a314dcd 2275 case 3:
2276 case 4:
f6bbdcf6 2277 case 5: /* fall through */
0a314dcd 2278 return "#";
f6bbdcf6 2279 default: gcc_unreachable ();
2280 }
2281}
0a314dcd 2282 "TARGET_32BIT && !TARGET_IWMMXT && reload_completed
2283 && !(IS_VFP_REGNUM (REGNO (operands[0])))"
f6bbdcf6 2284 [(set (match_dup 3) (match_dup 4))
2285 (set (match_dup 5) (match_dup 6))]
2286 "
2287 {
2288 operands[3] = gen_lowpart (SImode, operands[0]);
2289 operands[5] = gen_highpart (SImode, operands[0]);
2290
2291 operands[4] = simplify_gen_binary (AND, SImode,
2292 gen_lowpart (SImode, operands[1]),
2293 gen_lowpart (SImode, operands[2]));
2294 operands[6] = simplify_gen_binary (AND, SImode,
2295 gen_highpart (SImode, operands[1]),
2296 gen_highpart_mode (SImode, DImode, operands[2]));
2297
2298 }"
32093010 2299 [(set_attr "type" "neon_logic,neon_logic,multiple,multiple,\
2300 multiple,multiple,neon_logic,neon_logic")
0a314dcd 2301 (set_attr "arch" "neon_for_64bits,neon_for_64bits,*,*,*,*,
f6bbdcf6 2302 avoid_neon_for_64bits,avoid_neon_for_64bits")
0a314dcd 2303 (set_attr "length" "*,*,8,8,8,8,*,*")
2304 ]
215b30b3 2305)
b11cae9e 2306
a0f94409 2307(define_insn_and_split "*anddi_zesidi_di"
9c08d1fa 2308 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2309 (and:DI (zero_extend:DI
2310 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 2311 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2312 "TARGET_32BIT"
f6ebffac 2313 "#"
25f905c2 2314 "TARGET_32BIT && reload_completed"
a0f94409 2315 ; The zero extend of operand 2 clears the high word of the output
2316 ; operand.
2317 [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
2318 (set (match_dup 3) (const_int 0))]
2319 "
2320 {
2321 operands[3] = gen_highpart (SImode, operands[0]);
2322 operands[0] = gen_lowpart (SImode, operands[0]);
2323 operands[1] = gen_lowpart (SImode, operands[1]);
2324 }"
1b7da4ac 2325 [(set_attr "length" "8")
2326 (set_attr "type" "multiple")]
215b30b3 2327)
b11cae9e 2328
f7fbdd4a 2329(define_insn "*anddi_sesdi_di"
cffb2a26 2330 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 2331 (and:DI (sign_extend:DI
2332 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 2333 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2334 "TARGET_32BIT"
f6ebffac 2335 "#"
1b7da4ac 2336 [(set_attr "length" "8")
2337 (set_attr "type" "multiple")]
cffb2a26 2338)
b11cae9e 2339
87b22bf7 2340(define_expand "andsi3"
cffb2a26 2341 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2342 (and:SI (match_operand:SI 1 "s_register_operand" "")
2343 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 2344 "TARGET_EITHER"
87b22bf7 2345 "
25f905c2 2346 if (TARGET_32BIT)
87b22bf7 2347 {
0438d37f 2348 if (CONST_INT_P (operands[2]))
cffb2a26 2349 {
47b5b27b 2350 if (INTVAL (operands[2]) == 255 && arm_arch6)
2351 {
2352 operands[1] = convert_to_mode (QImode, operands[1], 1);
2353 emit_insn (gen_thumb2_zero_extendqisi2_v6 (operands[0],
2354 operands[1]));
17202aa5 2355 DONE;
47b5b27b 2356 }
17202aa5 2357 else if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[2]), AND))
2358 operands[2] = force_reg (SImode, operands[2]);
47b5b27b 2359 else
17202aa5 2360 {
2361 arm_split_constant (AND, SImode, NULL_RTX,
2362 INTVAL (operands[2]), operands[0],
2363 operands[1],
2364 optimize && can_create_pseudo_p ());
615caa51 2365
17202aa5 2366 DONE;
2367 }
cffb2a26 2368 }
87b22bf7 2369 }
25f905c2 2370 else /* TARGET_THUMB1 */
cffb2a26 2371 {
0438d37f 2372 if (!CONST_INT_P (operands[2]))
923ffadb 2373 {
2374 rtx tmp = force_reg (SImode, operands[2]);
2375 if (rtx_equal_p (operands[0], operands[1]))
2376 operands[2] = tmp;
2377 else
2378 {
2379 operands[2] = operands[1];
2380 operands[1] = tmp;
2381 }
2382 }
cffb2a26 2383 else
2384 {
2385 int i;
2386
215b30b3 2387 if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
cffb2a26 2388 {
215b30b3 2389 operands[2] = force_reg (SImode,
2390 GEN_INT (~INTVAL (operands[2])));
cffb2a26 2391
747b7458 2392 emit_insn (gen_thumb1_bicsi3 (operands[0], operands[2], operands[1]));
cffb2a26 2393
2394 DONE;
2395 }
87b22bf7 2396
cffb2a26 2397 for (i = 9; i <= 31; i++)
2398 {
db2faf44 2399 if ((HOST_WIDE_INT_1 << i) - 1 == INTVAL (operands[2]))
cffb2a26 2400 {
2401 emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
2402 const0_rtx));
2403 DONE;
2404 }
db2faf44 2405 else if ((HOST_WIDE_INT_1 << i) - 1
215b30b3 2406 == ~INTVAL (operands[2]))
cffb2a26 2407 {
2408 rtx shift = GEN_INT (i);
2409 rtx reg = gen_reg_rtx (SImode);
2410
2411 emit_insn (gen_lshrsi3 (reg, operands[1], shift));
2412 emit_insn (gen_ashlsi3 (operands[0], reg, shift));
2413
2414 DONE;
2415 }
2416 }
2417
2418 operands[2] = force_reg (SImode, operands[2]);
2419 }
215b30b3 2420 }
2421 "
cffb2a26 2422)
2423
25f905c2 2424; ??? Check split length for Thumb-2
a0f94409 2425(define_insn_and_split "*arm_andsi3_insn"
29e234a3 2426 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r,r,r")
2427 (and:SI (match_operand:SI 1 "s_register_operand" "%r,0,r,r,r")
2428 (match_operand:SI 2 "reg_or_int_operand" "I,l,K,r,?n")))]
25f905c2 2429 "TARGET_32BIT"
5565501b 2430 "@
29e234a3 2431 and%?\\t%0, %1, %2
5565501b 2432 and%?\\t%0, %1, %2
87b22bf7 2433 bic%?\\t%0, %1, #%B2
65f68e55 2434 and%?\\t%0, %1, %2
87b22bf7 2435 #"
25f905c2 2436 "TARGET_32BIT
0438d37f 2437 && CONST_INT_P (operands[2])
a0f94409 2438 && !(const_ok_for_arm (INTVAL (operands[2]))
2439 || const_ok_for_arm (~INTVAL (operands[2])))"
2440 [(clobber (const_int 0))]
2441 "
96f57e36 2442 arm_split_constant (AND, SImode, curr_insn,
2443 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 2444 DONE;
2445 "
29e234a3 2446 [(set_attr "length" "4,4,4,4,16")
65f68e55 2447 (set_attr "predicable" "yes")
29e234a3 2448 (set_attr "predicable_short_it" "no,yes,no,no,no")
d82e788e 2449 (set_attr "type" "logic_imm,logic_imm,logic_reg,logic_reg,logic_imm")]
cffb2a26 2450)
2451
f7fbdd4a 2452(define_insn "*andsi3_compare0"
bd5b4116 2453 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 2454 (compare:CC_NOOV
65f68e55 2455 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
2456 (match_operand:SI 2 "arm_not_operand" "I,K,r"))
5565501b 2457 (const_int 0)))
65f68e55 2458 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9c08d1fa 2459 (and:SI (match_dup 1) (match_dup 2)))]
25f905c2 2460 "TARGET_32BIT"
5565501b 2461 "@
3ef90e77 2462 ands%?\\t%0, %1, %2
2463 bics%?\\t%0, %1, #%B2
2464 ands%?\\t%0, %1, %2"
65f68e55 2465 [(set_attr "conds" "set")
d82e788e 2466 (set_attr "type" "logics_imm,logics_imm,logics_reg")]
cffb2a26 2467)
9c08d1fa 2468
f7fbdd4a 2469(define_insn "*andsi3_compare0_scratch"
bd5b4116 2470 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 2471 (compare:CC_NOOV
65f68e55 2472 (and:SI (match_operand:SI 0 "s_register_operand" "r,r,r")
2473 (match_operand:SI 1 "arm_not_operand" "I,K,r"))
5565501b 2474 (const_int 0)))
65f68e55 2475 (clobber (match_scratch:SI 2 "=X,r,X"))]
25f905c2 2476 "TARGET_32BIT"
5565501b 2477 "@
2478 tst%?\\t%0, %1
3ef90e77 2479 bics%?\\t%2, %0, #%B1
65f68e55 2480 tst%?\\t%0, %1"
2481 [(set_attr "conds" "set")
d82e788e 2482 (set_attr "type" "logics_imm,logics_imm,logics_reg")]
0d66636f 2483)
9c08d1fa 2484
f7fbdd4a 2485(define_insn "*zeroextractsi_compare0_scratch"
bd5b4116 2486 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2487 (compare:CC_NOOV (zero_extract:SI
2488 (match_operand:SI 0 "s_register_operand" "r")
d952d547 2489 (match_operand 1 "const_int_operand" "n")
206ee9a2 2490 (match_operand 2 "const_int_operand" "n"))
9c08d1fa 2491 (const_int 0)))]
25f905c2 2492 "TARGET_32BIT
cffb2a26 2493 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
2494 && INTVAL (operands[1]) > 0
2495 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
2496 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
9c08d1fa 2497 "*
5c49a439 2498 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
2499 << INTVAL (operands[2]));
40dbec34 2500 output_asm_insn (\"tst%?\\t%0, %1\", operands);
e2348bcb 2501 return \"\";
0d66636f 2502 "
596e5e8f 2503 [(set_attr "conds" "set")
65f68e55 2504 (set_attr "predicable" "yes")
d952d547 2505 (set_attr "predicable_short_it" "no")
d82e788e 2506 (set_attr "type" "logics_imm")]
0d66636f 2507)
9c08d1fa 2508
f4462328 2509(define_insn_and_split "*ne_zeroextractsi"
c4034607 2510 [(set (match_operand:SI 0 "s_register_operand" "=r")
2511 (ne:SI (zero_extract:SI
2512 (match_operand:SI 1 "s_register_operand" "r")
2513 (match_operand:SI 2 "const_int_operand" "n")
2514 (match_operand:SI 3 "const_int_operand" "n"))
3b8c7f7a 2515 (const_int 0)))
2516 (clobber (reg:CC CC_REGNUM))]
25f905c2 2517 "TARGET_32BIT
cffb2a26 2518 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2519 && INTVAL (operands[2]) > 0
2520 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2521 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
f4462328 2522 "#"
25f905c2 2523 "TARGET_32BIT
f4462328 2524 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2525 && INTVAL (operands[2]) > 0
2526 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2527 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
2528 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2529 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2530 (const_int 0)))
2531 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2532 (set (match_dup 0)
2533 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2534 (match_dup 0) (const_int 1)))]
2535 "
2536 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
2537 << INTVAL (operands[3]));
2538 "
2539 [(set_attr "conds" "clob")
25f905c2 2540 (set (attr "length")
2541 (if_then_else (eq_attr "is_thumb" "yes")
2542 (const_int 12)
1b7da4ac 2543 (const_int 8)))
2544 (set_attr "type" "multiple")]
f4462328 2545)
2546
2547(define_insn_and_split "*ne_zeroextractsi_shifted"
2548 [(set (match_operand:SI 0 "s_register_operand" "=r")
2549 (ne:SI (zero_extract:SI
2550 (match_operand:SI 1 "s_register_operand" "r")
2551 (match_operand:SI 2 "const_int_operand" "n")
2552 (const_int 0))
2553 (const_int 0)))
2554 (clobber (reg:CC CC_REGNUM))]
2555 "TARGET_ARM"
2556 "#"
2557 "TARGET_ARM"
2558 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2559 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2560 (const_int 0)))
2561 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2562 (set (match_dup 0)
2563 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2564 (match_dup 0) (const_int 1)))]
2565 "
2566 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
2567 "
2568 [(set_attr "conds" "clob")
1b7da4ac 2569 (set_attr "length" "8")
2570 (set_attr "type" "multiple")]
f4462328 2571)
2572
2573(define_insn_and_split "*ite_ne_zeroextractsi"
2574 [(set (match_operand:SI 0 "s_register_operand" "=r")
2575 (if_then_else:SI (ne (zero_extract:SI
2576 (match_operand:SI 1 "s_register_operand" "r")
2577 (match_operand:SI 2 "const_int_operand" "n")
2578 (match_operand:SI 3 "const_int_operand" "n"))
2579 (const_int 0))
2580 (match_operand:SI 4 "arm_not_operand" "rIK")
2581 (const_int 0)))
2582 (clobber (reg:CC CC_REGNUM))]
2583 "TARGET_ARM
2584 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2585 && INTVAL (operands[2]) > 0
2586 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 2587 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2588 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 2589 "#"
2590 "TARGET_ARM
2591 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2592 && INTVAL (operands[2]) > 0
2593 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 2594 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2595 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 2596 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2597 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2598 (const_int 0)))
2599 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2600 (set (match_dup 0)
2601 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2602 (match_dup 0) (match_dup 4)))]
2603 "
c4034607 2604 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
f4462328 2605 << INTVAL (operands[3]));
2606 "
2607 [(set_attr "conds" "clob")
1b7da4ac 2608 (set_attr "length" "8")
2609 (set_attr "type" "multiple")]
f4462328 2610)
2611
2612(define_insn_and_split "*ite_ne_zeroextractsi_shifted"
2613 [(set (match_operand:SI 0 "s_register_operand" "=r")
2614 (if_then_else:SI (ne (zero_extract:SI
2615 (match_operand:SI 1 "s_register_operand" "r")
2616 (match_operand:SI 2 "const_int_operand" "n")
2617 (const_int 0))
2618 (const_int 0))
2619 (match_operand:SI 3 "arm_not_operand" "rIK")
2620 (const_int 0)))
2621 (clobber (reg:CC CC_REGNUM))]
f8d7bf2f 2622 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 2623 "#"
f8d7bf2f 2624 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 2625 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2626 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2627 (const_int 0)))
2628 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2629 (set (match_dup 0)
2630 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2631 (match_dup 0) (match_dup 3)))]
2632 "
2633 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
0d66636f 2634 "
2635 [(set_attr "conds" "clob")
1b7da4ac 2636 (set_attr "length" "8")
2637 (set_attr "type" "multiple")]
215b30b3 2638)
9c08d1fa 2639
25f905c2 2640;; ??? Use Thumb-2 has bitfield insert/extract instructions.
d7863cfe 2641(define_split
2642 [(set (match_operand:SI 0 "s_register_operand" "")
2643 (match_operator:SI 1 "shiftable_operator"
2644 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2645 (match_operand:SI 3 "const_int_operand" "")
2646 (match_operand:SI 4 "const_int_operand" ""))
2647 (match_operand:SI 5 "s_register_operand" "")]))
2648 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2649 "TARGET_ARM"
2650 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2651 (set (match_dup 0)
2652 (match_op_dup 1
2653 [(lshiftrt:SI (match_dup 6) (match_dup 4))
2654 (match_dup 5)]))]
2655 "{
2656 HOST_WIDE_INT temp = INTVAL (operands[3]);
2657
2658 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2659 operands[4] = GEN_INT (32 - temp);
2660 }"
2661)
2662
d7863cfe 2663(define_split
2664 [(set (match_operand:SI 0 "s_register_operand" "")
2665 (match_operator:SI 1 "shiftable_operator"
2666 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2667 (match_operand:SI 3 "const_int_operand" "")
2668 (match_operand:SI 4 "const_int_operand" ""))
2669 (match_operand:SI 5 "s_register_operand" "")]))
2670 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2671 "TARGET_ARM"
2672 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2673 (set (match_dup 0)
2674 (match_op_dup 1
2675 [(ashiftrt:SI (match_dup 6) (match_dup 4))
2676 (match_dup 5)]))]
2677 "{
2678 HOST_WIDE_INT temp = INTVAL (operands[3]);
2679
2680 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2681 operands[4] = GEN_INT (32 - temp);
2682 }"
2683)
2684
a42059fd 2685;;; ??? This pattern is bogus. If operand3 has bits outside the range
2686;;; represented by the bitfield, then this will produce incorrect results.
2687;;; Somewhere, the value needs to be truncated. On targets like the m68k,
ceb2fe0f 2688;;; which have a real bit-field insert instruction, the truncation happens
2689;;; in the bit-field insert instruction itself. Since arm does not have a
2690;;; bit-field insert instruction, we would have to emit code here to truncate
a42059fd 2691;;; the value before we insert. This loses some of the advantage of having
2692;;; this insv pattern, so this pattern needs to be reevalutated.
2693
8a18b90c 2694(define_expand "insv"
eb04cafb 2695 [(set (zero_extract (match_operand 0 "nonimmediate_operand" "")
2696 (match_operand 1 "general_operand" "")
2697 (match_operand 2 "general_operand" ""))
2698 (match_operand 3 "reg_or_int_operand" ""))]
8b054d5a 2699 "TARGET_ARM || arm_arch_thumb2"
8a18b90c 2700 "
215b30b3 2701 {
2702 int start_bit = INTVAL (operands[2]);
2703 int width = INTVAL (operands[1]);
db2faf44 2704 HOST_WIDE_INT mask = (HOST_WIDE_INT_1 << width) - 1;
215b30b3 2705 rtx target, subtarget;
2706
8b054d5a 2707 if (arm_arch_thumb2)
2708 {
eb04cafb 2709 if (unaligned_access && MEM_P (operands[0])
2710 && s_register_operand (operands[3], GET_MODE (operands[3]))
2711 && (width == 16 || width == 32) && (start_bit % BITS_PER_UNIT) == 0)
8b054d5a 2712 {
eb04cafb 2713 rtx base_addr;
2714
2715 if (BYTES_BIG_ENDIAN)
2716 start_bit = GET_MODE_BITSIZE (GET_MODE (operands[3])) - width
2717 - start_bit;
8b054d5a 2718
eb04cafb 2719 if (width == 32)
8b054d5a 2720 {
eb04cafb 2721 base_addr = adjust_address (operands[0], SImode,
2722 start_bit / BITS_PER_UNIT);
2723 emit_insn (gen_unaligned_storesi (base_addr, operands[3]));
8b054d5a 2724 }
eb04cafb 2725 else
2726 {
2727 rtx tmp = gen_reg_rtx (HImode);
8b054d5a 2728
eb04cafb 2729 base_addr = adjust_address (operands[0], HImode,
2730 start_bit / BITS_PER_UNIT);
2731 emit_move_insn (tmp, gen_lowpart (HImode, operands[3]));
2732 emit_insn (gen_unaligned_storehi (base_addr, tmp));
2733 }
2734 DONE;
8b054d5a 2735 }
eb04cafb 2736 else if (s_register_operand (operands[0], GET_MODE (operands[0])))
8b054d5a 2737 {
eb04cafb 2738 bool use_bfi = TRUE;
8b054d5a 2739
0438d37f 2740 if (CONST_INT_P (operands[3]))
eb04cafb 2741 {
2742 HOST_WIDE_INT val = INTVAL (operands[3]) & mask;
2743
2744 if (val == 0)
2745 {
2746 emit_insn (gen_insv_zero (operands[0], operands[1],
2747 operands[2]));
2748 DONE;
2749 }
2750
2751 /* See if the set can be done with a single orr instruction. */
2752 if (val == mask && const_ok_for_arm (val << start_bit))
2753 use_bfi = FALSE;
2754 }
2755
2756 if (use_bfi)
2757 {
0438d37f 2758 if (!REG_P (operands[3]))
eb04cafb 2759 operands[3] = force_reg (SImode, operands[3]);
2760
2761 emit_insn (gen_insv_t2 (operands[0], operands[1], operands[2],
2762 operands[3]));
2763 DONE;
2764 }
8b054d5a 2765 }
eb04cafb 2766 else
2767 FAIL;
8b054d5a 2768 }
2769
eb04cafb 2770 if (!s_register_operand (operands[0], GET_MODE (operands[0])))
2771 FAIL;
2772
3f8fde42 2773 target = copy_rtx (operands[0]);
215b30b3 2774 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
2775 subreg as the final target. */
2776 if (GET_CODE (target) == SUBREG)
2777 {
2778 subtarget = gen_reg_rtx (SImode);
2779 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
2780 < GET_MODE_SIZE (SImode))
2781 target = SUBREG_REG (target);
2782 }
2783 else
2784 subtarget = target;
8a18b90c 2785
0438d37f 2786 if (CONST_INT_P (operands[3]))
215b30b3 2787 {
2788 /* Since we are inserting a known constant, we may be able to
2789 reduce the number of bits that we have to clear so that
2790 the mask becomes simple. */
2791 /* ??? This code does not check to see if the new mask is actually
2792 simpler. It may not be. */
2793 rtx op1 = gen_reg_rtx (SImode);
2794 /* ??? Truncate operand3 to fit in the bitfield. See comment before
2795 start of this pattern. */
2796 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
2797 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
2798
c5b3a71b 2799 emit_insn (gen_andsi3 (op1, operands[0],
2800 gen_int_mode (~mask2, SImode)));
215b30b3 2801 emit_insn (gen_iorsi3 (subtarget, op1,
4292ca6b 2802 gen_int_mode (op3_value << start_bit, SImode)));
215b30b3 2803 }
2804 else if (start_bit == 0
2805 && !(const_ok_for_arm (mask)
2806 || const_ok_for_arm (~mask)))
2807 {
2808 /* A Trick, since we are setting the bottom bits in the word,
2809 we can shift operand[3] up, operand[0] down, OR them together
2810 and rotate the result back again. This takes 3 insns, and
5910bb95 2811 the third might be mergeable into another op. */
215b30b3 2812 /* The shift up copes with the possibility that operand[3] is
2813 wider than the bitfield. */
2814 rtx op0 = gen_reg_rtx (SImode);
2815 rtx op1 = gen_reg_rtx (SImode);
2816
2817 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2818 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
2819 emit_insn (gen_iorsi3 (op1, op1, op0));
2820 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
2821 }
2822 else if ((width + start_bit == 32)
2823 && !(const_ok_for_arm (mask)
2824 || const_ok_for_arm (~mask)))
2825 {
2826 /* Similar trick, but slightly less efficient. */
8a18b90c 2827
215b30b3 2828 rtx op0 = gen_reg_rtx (SImode);
2829 rtx op1 = gen_reg_rtx (SImode);
8a18b90c 2830
215b30b3 2831 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2832 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
2833 emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
2834 emit_insn (gen_iorsi3 (subtarget, op1, op0));
2835 }
2836 else
2837 {
c5b3a71b 2838 rtx op0 = gen_int_mode (mask, SImode);
215b30b3 2839 rtx op1 = gen_reg_rtx (SImode);
2840 rtx op2 = gen_reg_rtx (SImode);
8a18b90c 2841
215b30b3 2842 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
2843 {
2844 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 2845
215b30b3 2846 emit_insn (gen_movsi (tmp, op0));
2847 op0 = tmp;
2848 }
8a18b90c 2849
215b30b3 2850 /* Mask out any bits in operand[3] that are not needed. */
2851 emit_insn (gen_andsi3 (op1, operands[3], op0));
8a18b90c 2852
0438d37f 2853 if (CONST_INT_P (op0)
215b30b3 2854 && (const_ok_for_arm (mask << start_bit)
2855 || const_ok_for_arm (~(mask << start_bit))))
2856 {
c5b3a71b 2857 op0 = gen_int_mode (~(mask << start_bit), SImode);
215b30b3 2858 emit_insn (gen_andsi3 (op2, operands[0], op0));
2859 }
2860 else
2861 {
0438d37f 2862 if (CONST_INT_P (op0))
215b30b3 2863 {
2864 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 2865
215b30b3 2866 emit_insn (gen_movsi (tmp, op0));
2867 op0 = tmp;
2868 }
2869
2870 if (start_bit != 0)
2871 emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
a42059fd 2872
215b30b3 2873 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
2874 }
8a18b90c 2875
215b30b3 2876 if (start_bit != 0)
2877 emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
8a18b90c 2878
215b30b3 2879 emit_insn (gen_iorsi3 (subtarget, op1, op2));
2880 }
f082f1c4 2881
215b30b3 2882 if (subtarget != target)
2883 {
2884 /* If TARGET is still a SUBREG, then it must be wider than a word,
2885 so we must be careful only to set the subword we were asked to. */
2886 if (GET_CODE (target) == SUBREG)
2887 emit_move_insn (target, subtarget);
2888 else
2889 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
2890 }
8a18b90c 2891
215b30b3 2892 DONE;
2893 }"
2894)
8a18b90c 2895
8b054d5a 2896(define_insn "insv_zero"
2897 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
809003b3 2898 (match_operand:SI 1 "const_int_M_operand" "M")
2899 (match_operand:SI 2 "const_int_M_operand" "M"))
8b054d5a 2900 (const_int 0))]
2901 "arm_arch_thumb2"
2902 "bfc%?\t%0, %2, %1"
2903 [(set_attr "length" "4")
d952d547 2904 (set_attr "predicable" "yes")
d82e788e 2905 (set_attr "predicable_short_it" "no")
2906 (set_attr "type" "bfm")]
8b054d5a 2907)
2908
2909(define_insn "insv_t2"
2910 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
809003b3 2911 (match_operand:SI 1 "const_int_M_operand" "M")
2912 (match_operand:SI 2 "const_int_M_operand" "M"))
8b054d5a 2913 (match_operand:SI 3 "s_register_operand" "r"))]
2914 "arm_arch_thumb2"
2915 "bfi%?\t%0, %3, %2, %1"
2916 [(set_attr "length" "4")
d952d547 2917 (set_attr "predicable" "yes")
d82e788e 2918 (set_attr "predicable_short_it" "no")
2919 (set_attr "type" "bfm")]
8b054d5a 2920)
2921
215b30b3 2922; constants for op 2 will never be given to these patterns.
a0f94409 2923(define_insn_and_split "*anddi_notdi_di"
9c08d1fa 2924 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 2925 (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "0,r"))
2926 (match_operand:DI 2 "s_register_operand" "r,0")))]
25f905c2 2927 "TARGET_32BIT"
f6ebffac 2928 "#"
e2669ea7 2929 "TARGET_32BIT && reload_completed
2930 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))
2931 && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
a0f94409 2932 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2933 (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2934 "
2935 {
2936 operands[3] = gen_highpart (SImode, operands[0]);
2937 operands[0] = gen_lowpart (SImode, operands[0]);
2938 operands[4] = gen_highpart (SImode, operands[1]);
2939 operands[1] = gen_lowpart (SImode, operands[1]);
2940 operands[5] = gen_highpart (SImode, operands[2]);
2941 operands[2] = gen_lowpart (SImode, operands[2]);
2942 }"
0d66636f 2943 [(set_attr "length" "8")
1b7da4ac 2944 (set_attr "predicable" "yes")
2945 (set_attr "type" "multiple")]
0d66636f 2946)
d952d547 2947
a0f94409 2948(define_insn_and_split "*anddi_notzesidi_di"
9c08d1fa 2949 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2950 (and:DI (not:DI (zero_extend:DI
2951 (match_operand:SI 2 "s_register_operand" "r,r")))
e2348bcb 2952 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 2953 "TARGET_32BIT"
e2348bcb 2954 "@
97499065 2955 bic%?\\t%Q0, %Q1, %2
f6ebffac 2956 #"
a0f94409 2957 ; (not (zero_extend ...)) allows us to just copy the high word from
2958 ; operand1 to operand0.
25f905c2 2959 "TARGET_32BIT
a0f94409 2960 && reload_completed
2961 && operands[0] != operands[1]"
5a097f7d 2962 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
a0f94409 2963 (set (match_dup 3) (match_dup 4))]
2964 "
2965 {
2966 operands[3] = gen_highpart (SImode, operands[0]);
2967 operands[0] = gen_lowpart (SImode, operands[0]);
2968 operands[4] = gen_highpart (SImode, operands[1]);
2969 operands[1] = gen_lowpart (SImode, operands[1]);
2970 }"
0d66636f 2971 [(set_attr "length" "4,8")
d952d547 2972 (set_attr "predicable" "yes")
1b7da4ac 2973 (set_attr "predicable_short_it" "no")
2974 (set_attr "type" "multiple")]
0d66636f 2975)
d952d547 2976
d8cd5fa0 2977(define_insn_and_split "*anddi_notdi_zesidi"
2978 [(set (match_operand:DI 0 "s_register_operand" "=r")
2979 (and:DI (not:DI (match_operand:DI 2 "s_register_operand" "r"))
2980 (zero_extend:DI
2981 (match_operand:SI 1 "s_register_operand" "r"))))]
2982 "TARGET_32BIT"
2983 "#"
2984 "TARGET_32BIT && reload_completed"
2985 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2986 (set (match_dup 3) (const_int 0))]
2987 "
2988 {
2989 operands[3] = gen_highpart (SImode, operands[0]);
2990 operands[0] = gen_lowpart (SImode, operands[0]);
2991 operands[2] = gen_lowpart (SImode, operands[2]);
2992 }"
2993 [(set_attr "length" "8")
2994 (set_attr "predicable" "yes")
2995 (set_attr "predicable_short_it" "no")
2996 (set_attr "type" "multiple")]
2997)
2998
a0f94409 2999(define_insn_and_split "*anddi_notsesidi_di"
9c08d1fa 3000 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3001 (and:DI (not:DI (sign_extend:DI
3002 (match_operand:SI 2 "s_register_operand" "r,r")))
5a097f7d 3003 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 3004 "TARGET_32BIT"
f6ebffac 3005 "#"
25f905c2 3006 "TARGET_32BIT && reload_completed"
5a097f7d 3007 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
a0f94409 3008 (set (match_dup 3) (and:SI (not:SI
3009 (ashiftrt:SI (match_dup 2) (const_int 31)))
3010 (match_dup 4)))]
3011 "
3012 {
3013 operands[3] = gen_highpart (SImode, operands[0]);
3014 operands[0] = gen_lowpart (SImode, operands[0]);
3015 operands[4] = gen_highpart (SImode, operands[1]);
3016 operands[1] = gen_lowpart (SImode, operands[1]);
3017 }"
0d66636f 3018 [(set_attr "length" "8")
d952d547 3019 (set_attr "predicable" "yes")
1b7da4ac 3020 (set_attr "predicable_short_it" "no")
3021 (set_attr "type" "multiple")]
0d66636f 3022)
d952d547 3023
8a18b90c 3024(define_insn "andsi_notsi_si"
9c08d1fa 3025 [(set (match_operand:SI 0 "s_register_operand" "=r")
3026 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
3027 (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 3028 "TARGET_32BIT"
0d66636f 3029 "bic%?\\t%0, %1, %2"
d952d547 3030 [(set_attr "predicable" "yes")
1b7da4ac 3031 (set_attr "predicable_short_it" "no")
3032 (set_attr "type" "logic_reg")]
0d66636f 3033)
b11cae9e 3034
8a18b90c 3035(define_insn "andsi_not_shiftsi_si"
a2cd141b 3036 [(set (match_operand:SI 0 "s_register_operand" "=r")
3037 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
3038 [(match_operand:SI 2 "s_register_operand" "r")
3039 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
3040 (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 3041 "TARGET_ARM"
6c4c2133 3042 "bic%?\\t%0, %1, %2%S4"
344495ea 3043 [(set_attr "predicable" "yes")
331beb1a 3044 (set_attr "shift" "2")
a2cd141b 3045 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
d82e788e 3046 (const_string "logic_shift_imm")
3047 (const_string "logic_shift_reg")))]
6c4c2133 3048)
8a18b90c 3049
9ed784d8 3050;; Shifted bics pattern used to set up CC status register and not reusing
3051;; bics output. Pattern restricts Thumb2 shift operand as bics for Thumb2
3052;; does not support shift by register.
3053(define_insn "andsi_not_shiftsi_si_scc_no_reuse"
3054 [(set (reg:CC_NOOV CC_REGNUM)
3055 (compare:CC_NOOV
3056 (and:SI (not:SI (match_operator:SI 0 "shift_operator"
3057 [(match_operand:SI 1 "s_register_operand" "r")
3058 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
3059 (match_operand:SI 3 "s_register_operand" "r"))
3060 (const_int 0)))
3061 (clobber (match_scratch:SI 4 "=r"))]
3062 "TARGET_ARM || (TARGET_THUMB2 && CONST_INT_P (operands[2]))"
3ef90e77 3063 "bics%?\\t%4, %3, %1%S0"
9ed784d8 3064 [(set_attr "predicable" "yes")
3065 (set_attr "predicable_short_it" "no")
3066 (set_attr "conds" "set")
3067 (set_attr "shift" "1")
3068 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3069 (const_string "logic_shift_imm")
3070 (const_string "logic_shift_reg")))]
3071)
3072
3073;; Same as andsi_not_shiftsi_si_scc_no_reuse, but the bics result is also
3074;; getting reused later.
3075(define_insn "andsi_not_shiftsi_si_scc"
3076 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
3077 (compare:CC_NOOV
3078 (and:SI (not:SI (match_operator:SI 0 "shift_operator"
3079 [(match_operand:SI 1 "s_register_operand" "r")
3080 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
3081 (match_operand:SI 3 "s_register_operand" "r"))
3082 (const_int 0)))
3083 (set (match_operand:SI 4 "s_register_operand" "=r")
3084 (and:SI (not:SI (match_op_dup 0
3085 [(match_dup 1)
3086 (match_dup 2)]))
3087 (match_dup 3)))])]
3088 "TARGET_ARM || (TARGET_THUMB2 && CONST_INT_P (operands[2]))"
3ef90e77 3089 "bics%?\\t%4, %3, %1%S0"
9ed784d8 3090 [(set_attr "predicable" "yes")
3091 (set_attr "predicable_short_it" "no")
3092 (set_attr "conds" "set")
3093 (set_attr "shift" "1")
3094 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3095 (const_string "logic_shift_imm")
3096 (const_string "logic_shift_reg")))]
3097)
3098
f7fbdd4a 3099(define_insn "*andsi_notsi_si_compare0"
bd5b4116 3100 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 3101 (compare:CC_NOOV
3102 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
3103 (match_operand:SI 1 "s_register_operand" "r"))
3104 (const_int 0)))
9c08d1fa 3105 (set (match_operand:SI 0 "s_register_operand" "=r")
3106 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
25f905c2 3107 "TARGET_32BIT"
3ef90e77 3108 "bics\\t%0, %1, %2"
d82e788e 3109 [(set_attr "conds" "set")
3110 (set_attr "type" "logics_shift_reg")]
0d66636f 3111)
9c08d1fa 3112
f7fbdd4a 3113(define_insn "*andsi_notsi_si_compare0_scratch"
bd5b4116 3114 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 3115 (compare:CC_NOOV
3116 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
3117 (match_operand:SI 1 "s_register_operand" "r"))
3118 (const_int 0)))
9c08d1fa 3119 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 3120 "TARGET_32BIT"
3ef90e77 3121 "bics\\t%0, %1, %2"
d82e788e 3122 [(set_attr "conds" "set")
3123 (set_attr "type" "logics_shift_reg")]
0d66636f 3124)
9c08d1fa 3125
e2669ea7 3126(define_expand "iordi3"
3127 [(set (match_operand:DI 0 "s_register_operand" "")
3128 (ior:DI (match_operand:DI 1 "s_register_operand" "")
3129 (match_operand:DI 2 "neon_logic_op2" "")))]
3130 "TARGET_32BIT"
3131 ""
3132)
3133
74d6113f 3134(define_insn_and_split "*iordi3_insn"
3135 [(set (match_operand:DI 0 "s_register_operand" "=w,w ,&r,&r,&r,&r,?w,?w")
3136 (ior:DI (match_operand:DI 1 "s_register_operand" "%w,0 ,0 ,r ,0 ,r ,w ,0")
e0fe6977 3137 (match_operand:DI 2 "arm_iordi_operand_neon" "w ,Dl,r ,r ,Df,Df,w ,Dl")))]
74d6113f 3138 "TARGET_32BIT && !TARGET_IWMMXT"
3139 {
3140 switch (which_alternative)
3141 {
3142 case 0: /* fall through */
3143 case 6: return "vorr\t%P0, %P1, %P2";
3144 case 1: /* fall through */
3145 case 7: return neon_output_logic_immediate ("vorr", &operands[2],
3146 DImode, 0, VALID_NEON_QREG_MODE (DImode));
3147 case 2:
3148 case 3:
3149 case 4:
3150 case 5:
3151 return "#";
3152 default: gcc_unreachable ();
3153 }
3154 }
3155 "TARGET_32BIT && !TARGET_IWMMXT && reload_completed
3156 && !(IS_VFP_REGNUM (REGNO (operands[0])))"
3157 [(set (match_dup 3) (match_dup 4))
3158 (set (match_dup 5) (match_dup 6))]
3159 "
3160 {
3161 operands[3] = gen_lowpart (SImode, operands[0]);
3162 operands[5] = gen_highpart (SImode, operands[0]);
3163
3164 operands[4] = simplify_gen_binary (IOR, SImode,
3165 gen_lowpart (SImode, operands[1]),
3166 gen_lowpart (SImode, operands[2]));
3167 operands[6] = simplify_gen_binary (IOR, SImode,
3168 gen_highpart (SImode, operands[1]),
3169 gen_highpart_mode (SImode, DImode, operands[2]));
3170
3171 }"
32093010 3172 [(set_attr "type" "neon_logic,neon_logic,multiple,multiple,multiple,\
3173 multiple,neon_logic,neon_logic")
e0fe6977 3174 (set_attr "length" "*,*,8,8,8,8,*,*")
74d6113f 3175 (set_attr "arch" "neon_for_64bits,neon_for_64bits,*,*,*,*,avoid_neon_for_64bits,avoid_neon_for_64bits")]
cffb2a26 3176)
9c08d1fa 3177
f7fbdd4a 3178(define_insn "*iordi_zesidi_di"
9c08d1fa 3179 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3180 (ior:DI (zero_extend:DI
3181 (match_operand:SI 2 "s_register_operand" "r,r"))
e2348bcb 3182 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 3183 "TARGET_32BIT"
e2348bcb 3184 "@
97499065 3185 orr%?\\t%Q0, %Q1, %2
f6ebffac 3186 #"
0d66636f 3187 [(set_attr "length" "4,8")
d952d547 3188 (set_attr "predicable" "yes")
1b7da4ac 3189 (set_attr "predicable_short_it" "no")
3190 (set_attr "type" "logic_reg,multiple")]
cffb2a26 3191)
9c08d1fa 3192
f7fbdd4a 3193(define_insn "*iordi_sesidi_di"
9c08d1fa 3194 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3195 (ior:DI (sign_extend:DI
3196 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 3197 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 3198 "TARGET_32BIT"
f6ebffac 3199 "#"
0d66636f 3200 [(set_attr "length" "8")
1b7da4ac 3201 (set_attr "predicable" "yes")
3202 (set_attr "type" "multiple")]
cffb2a26 3203)
9c08d1fa 3204
87b22bf7 3205(define_expand "iorsi3"
cffb2a26 3206 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3207 (ior:SI (match_operand:SI 1 "s_register_operand" "")
3208 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 3209 "TARGET_EITHER"
87b22bf7 3210 "
0438d37f 3211 if (CONST_INT_P (operands[2]))
87b22bf7 3212 {
25f905c2 3213 if (TARGET_32BIT)
cffb2a26 3214 {
17202aa5 3215 if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[2]), IOR))
3216 operands[2] = force_reg (SImode, operands[2]);
3217 else
3218 {
3219 arm_split_constant (IOR, SImode, NULL_RTX,
3220 INTVAL (operands[2]), operands[0],
3221 operands[1],
3222 optimize && can_create_pseudo_p ());
3223 DONE;
3224 }
cffb2a26 3225 }
25f905c2 3226 else /* TARGET_THUMB1 */
923ffadb 3227 {
3228 rtx tmp = force_reg (SImode, operands[2]);
3229 if (rtx_equal_p (operands[0], operands[1]))
3230 operands[2] = tmp;
3231 else
3232 {
3233 operands[2] = operands[1];
3234 operands[1] = tmp;
3235 }
3236 }
87b22bf7 3237 }
cffb2a26 3238 "
3239)
87b22bf7 3240
d5d4dc8d 3241(define_insn_and_split "*iorsi3_insn"
29e234a3 3242 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r,r,r")
3243 (ior:SI (match_operand:SI 1 "s_register_operand" "%r,0,r,r,r")
3244 (match_operand:SI 2 "reg_or_int_operand" "I,l,K,r,?n")))]
d5d4dc8d 3245 "TARGET_32BIT"
87b22bf7 3246 "@
29e234a3 3247 orr%?\\t%0, %1, %2
87b22bf7 3248 orr%?\\t%0, %1, %2
d5d4dc8d 3249 orn%?\\t%0, %1, #%B2
65f68e55 3250 orr%?\\t%0, %1, %2
87b22bf7 3251 #"
d5d4dc8d 3252 "TARGET_32BIT
0438d37f 3253 && CONST_INT_P (operands[2])
d5d4dc8d 3254 && !(const_ok_for_arm (INTVAL (operands[2]))
3255 || (TARGET_THUMB2 && const_ok_for_arm (~INTVAL (operands[2]))))"
a0f94409 3256 [(clobber (const_int 0))]
d5d4dc8d 3257{
29e234a3 3258 arm_split_constant (IOR, SImode, curr_insn,
96f57e36 3259 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 3260 DONE;
d5d4dc8d 3261}
29e234a3 3262 [(set_attr "length" "4,4,4,4,16")
3263 (set_attr "arch" "32,t2,t2,32,32")
65f68e55 3264 (set_attr "predicable" "yes")
29e234a3 3265 (set_attr "predicable_short_it" "no,yes,no,no,no")
d82e788e 3266 (set_attr "type" "logic_imm,logic_reg,logic_imm,logic_reg,logic_reg")]
65f68e55 3267)
cffb2a26 3268
a0f94409 3269(define_peephole2
3270 [(match_scratch:SI 3 "r")
372575c7 3271 (set (match_operand:SI 0 "arm_general_register_operand" "")
3272 (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
87b22bf7 3273 (match_operand:SI 2 "const_int_operand" "")))]
90560cad 3274 "TARGET_ARM
a0f94409 3275 && !const_ok_for_arm (INTVAL (operands[2]))
3276 && const_ok_for_arm (~INTVAL (operands[2]))"
3277 [(set (match_dup 3) (match_dup 2))
3278 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
3279 ""
215b30b3 3280)
a0f94409 3281
f7fbdd4a 3282(define_insn "*iorsi3_compare0"
bd5b4116 3283 [(set (reg:CC_NOOV CC_REGNUM)
65f68e55 3284 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r,r")
3285 (match_operand:SI 2 "arm_rhs_operand" "I,r"))
9c08d1fa 3286 (const_int 0)))
65f68e55 3287 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 3288 (ior:SI (match_dup 1) (match_dup 2)))]
25f905c2 3289 "TARGET_32BIT"
3ef90e77 3290 "orrs%?\\t%0, %1, %2"
65f68e55 3291 [(set_attr "conds" "set")
d82e788e 3292 (set_attr "type" "logics_imm,logics_reg")]
cffb2a26 3293)
9c08d1fa 3294
f7fbdd4a 3295(define_insn "*iorsi3_compare0_scratch"
bd5b4116 3296 [(set (reg:CC_NOOV CC_REGNUM)
65f68e55 3297 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r,r")
3298 (match_operand:SI 2 "arm_rhs_operand" "I,r"))
9c08d1fa 3299 (const_int 0)))
65f68e55 3300 (clobber (match_scratch:SI 0 "=r,r"))]
25f905c2 3301 "TARGET_32BIT"
3ef90e77 3302 "orrs%?\\t%0, %1, %2"
65f68e55 3303 [(set_attr "conds" "set")
d82e788e 3304 (set_attr "type" "logics_imm,logics_reg")]
0d66636f 3305)
9c08d1fa 3306
e2669ea7 3307(define_expand "xordi3"
3308 [(set (match_operand:DI 0 "s_register_operand" "")
3309 (xor:DI (match_operand:DI 1 "s_register_operand" "")
8ee7dc6f 3310 (match_operand:DI 2 "arm_xordi_operand" "")))]
e2669ea7 3311 "TARGET_32BIT"
8df5e205 3312 {
3313 /* The iWMMXt pattern for xordi3 accepts only register operands but we want
3314 to reuse this expander for all TARGET_32BIT targets so just force the
3315 constants into a register. Unlike for the anddi3 and iordi3 there are
3316 no NEON instructions that take an immediate. */
3317 if (TARGET_IWMMXT && !REG_P (operands[2]))
3318 operands[2] = force_reg (DImode, operands[2]);
3319 }
e2669ea7 3320)
3321
8ee7dc6f 3322(define_insn_and_split "*xordi3_insn"
3323 [(set (match_operand:DI 0 "s_register_operand" "=w,&r,&r,&r,&r,?w")
205c3b0a 3324 (xor:DI (match_operand:DI 1 "s_register_operand" "%w ,0,r ,0 ,r ,w")
8ee7dc6f 3325 (match_operand:DI 2 "arm_xordi_operand" "w ,r ,r ,Dg,Dg,w")))]
3326 "TARGET_32BIT && !TARGET_IWMMXT"
3327{
3328 switch (which_alternative)
3329 {
3330 case 1:
3331 case 2:
3332 case 3:
3333 case 4: /* fall through */
3334 return "#";
3335 case 0: /* fall through */
3336 case 5: return "veor\t%P0, %P1, %P2";
3337 default: gcc_unreachable ();
3338 }
3339}
3340 "TARGET_32BIT && !TARGET_IWMMXT && reload_completed
3341 && !(IS_VFP_REGNUM (REGNO (operands[0])))"
3342 [(set (match_dup 3) (match_dup 4))
3343 (set (match_dup 5) (match_dup 6))]
3344 "
3345 {
3346 operands[3] = gen_lowpart (SImode, operands[0]);
3347 operands[5] = gen_highpart (SImode, operands[0]);
3348
3349 operands[4] = simplify_gen_binary (XOR, SImode,
3350 gen_lowpart (SImode, operands[1]),
3351 gen_lowpart (SImode, operands[2]));
3352 operands[6] = simplify_gen_binary (XOR, SImode,
3353 gen_highpart (SImode, operands[1]),
3354 gen_highpart_mode (SImode, DImode, operands[2]));
3355
3356 }"
3357 [(set_attr "length" "*,8,8,8,8,*")
32093010 3358 (set_attr "type" "neon_logic,multiple,multiple,multiple,multiple,neon_logic")
8ee7dc6f 3359 (set_attr "arch" "neon_for_64bits,*,*,*,*,avoid_neon_for_64bits")]
cffb2a26 3360)
9c08d1fa 3361
f7fbdd4a 3362(define_insn "*xordi_zesidi_di"
9c08d1fa 3363 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3364 (xor:DI (zero_extend:DI
3365 (match_operand:SI 2 "s_register_operand" "r,r"))
e2348bcb 3366 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 3367 "TARGET_32BIT"
e2348bcb 3368 "@
97499065 3369 eor%?\\t%Q0, %Q1, %2
f6ebffac 3370 #"
0d66636f 3371 [(set_attr "length" "4,8")
d952d547 3372 (set_attr "predicable" "yes")
1b7da4ac 3373 (set_attr "predicable_short_it" "no")
3374 (set_attr "type" "logic_reg")]
cffb2a26 3375)
9c08d1fa 3376
f7fbdd4a 3377(define_insn "*xordi_sesidi_di"
9c08d1fa 3378 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3379 (xor:DI (sign_extend:DI
3380 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 3381 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 3382 "TARGET_32BIT"
f6ebffac 3383 "#"
0d66636f 3384 [(set_attr "length" "8")
1b7da4ac 3385 (set_attr "predicable" "yes")
3386 (set_attr "type" "multiple")]
cffb2a26 3387)
9c08d1fa 3388
cffb2a26 3389(define_expand "xorsi3"
3390 [(set (match_operand:SI 0 "s_register_operand" "")
3391 (xor:SI (match_operand:SI 1 "s_register_operand" "")
923ffadb 3392 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 3393 "TARGET_EITHER"
0438d37f 3394 "if (CONST_INT_P (operands[2]))
923ffadb 3395 {
3396 if (TARGET_32BIT)
3397 {
17202aa5 3398 if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[2]), XOR))
3399 operands[2] = force_reg (SImode, operands[2]);
3400 else
3401 {
3402 arm_split_constant (XOR, SImode, NULL_RTX,
3403 INTVAL (operands[2]), operands[0],
3404 operands[1],
3405 optimize && can_create_pseudo_p ());
3406 DONE;
3407 }
923ffadb 3408 }
3409 else /* TARGET_THUMB1 */
3410 {
3411 rtx tmp = force_reg (SImode, operands[2]);
3412 if (rtx_equal_p (operands[0], operands[1]))
3413 operands[2] = tmp;
3414 else
3415 {
3416 operands[2] = operands[1];
3417 operands[1] = tmp;
3418 }
3419 }
3420 }"
cffb2a26 3421)
3422
5dcb35d9 3423(define_insn_and_split "*arm_xorsi3"
29e234a3 3424 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r,r")
3425 (xor:SI (match_operand:SI 1 "s_register_operand" "%r,0,r,r")
3426 (match_operand:SI 2 "reg_or_int_operand" "I,l,r,?n")))]
25f905c2 3427 "TARGET_32BIT"
5dcb35d9 3428 "@
29e234a3 3429 eor%?\\t%0, %1, %2
65f68e55 3430 eor%?\\t%0, %1, %2
5dcb35d9 3431 eor%?\\t%0, %1, %2
3432 #"
3433 "TARGET_32BIT
0438d37f 3434 && CONST_INT_P (operands[2])
5dcb35d9 3435 && !const_ok_for_arm (INTVAL (operands[2]))"
3436 [(clobber (const_int 0))]
3437{
3438 arm_split_constant (XOR, SImode, curr_insn,
3439 INTVAL (operands[2]), operands[0], operands[1], 0);
3440 DONE;
3441}
29e234a3 3442 [(set_attr "length" "4,4,4,16")
65f68e55 3443 (set_attr "predicable" "yes")
29e234a3 3444 (set_attr "predicable_short_it" "no,yes,no,no")
1b7da4ac 3445 (set_attr "type" "logic_imm,logic_reg,logic_reg,multiple")]
cffb2a26 3446)
3447
f7fbdd4a 3448(define_insn "*xorsi3_compare0"
bd5b4116 3449 [(set (reg:CC_NOOV CC_REGNUM)
65f68e55 3450 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r,r")
3451 (match_operand:SI 2 "arm_rhs_operand" "I,r"))
9c08d1fa 3452 (const_int 0)))
65f68e55 3453 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 3454 (xor:SI (match_dup 1) (match_dup 2)))]
25f905c2 3455 "TARGET_32BIT"
3ef90e77 3456 "eors%?\\t%0, %1, %2"
65f68e55 3457 [(set_attr "conds" "set")
d82e788e 3458 (set_attr "type" "logics_imm,logics_reg")]
0d66636f 3459)
9c08d1fa 3460
f7fbdd4a 3461(define_insn "*xorsi3_compare0_scratch"
bd5b4116 3462 [(set (reg:CC_NOOV CC_REGNUM)
65f68e55 3463 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r,r")
3464 (match_operand:SI 1 "arm_rhs_operand" "I,r"))
9c08d1fa 3465 (const_int 0)))]
25f905c2 3466 "TARGET_32BIT"
40dbec34 3467 "teq%?\\t%0, %1"
65f68e55 3468 [(set_attr "conds" "set")
d82e788e 3469 (set_attr "type" "logics_imm,logics_reg")]
cffb2a26 3470)
9c08d1fa 3471
215b30b3 3472; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
3473; (NOT D) we can sometimes merge the final NOT into one of the following
3474; insns.
9c08d1fa 3475
3476(define_split
a058e94a 3477 [(set (match_operand:SI 0 "s_register_operand" "")
3478 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
3479 (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
3480 (match_operand:SI 3 "arm_rhs_operand" "")))
3481 (clobber (match_operand:SI 4 "s_register_operand" ""))]
25f905c2 3482 "TARGET_32BIT"
9c08d1fa 3483 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
3484 (not:SI (match_dup 3))))
3485 (set (match_dup 0) (not:SI (match_dup 4)))]
3486 ""
3487)
3488
ba6a3b2f 3489(define_insn_and_split "*andsi_iorsi3_notsi"
9c08d1fa 3490 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
e5fea38e 3491 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "%0,r,r")
9c08d1fa 3492 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
3493 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
25f905c2 3494 "TARGET_32BIT"
ba6a3b2f 3495 "#" ; "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
3496 "&& reload_completed"
3497 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
054fd237 3498 (set (match_dup 0) (and:SI (match_dup 4) (match_dup 5)))]
3499 {
3500 /* If operands[3] is a constant make sure to fold the NOT into it
3501 to avoid creating a NOT of a CONST_INT. */
3502 rtx not_rtx = simplify_gen_unary (NOT, SImode, operands[3], SImode);
3503 if (CONST_INT_P (not_rtx))
3504 {
3505 operands[4] = operands[0];
3506 operands[5] = not_rtx;
3507 }
3508 else
3509 {
3510 operands[5] = operands[0];
3511 operands[4] = not_rtx;
3512 }
3513 }
0d66636f 3514 [(set_attr "length" "8")
25f905c2 3515 (set_attr "ce_count" "2")
d952d547 3516 (set_attr "predicable" "yes")
1b7da4ac 3517 (set_attr "predicable_short_it" "no")
3518 (set_attr "type" "multiple")]
cffb2a26 3519)
9c08d1fa 3520
25f905c2 3521; ??? Are these four splitters still beneficial when the Thumb-2 bitfield
3522; insns are available?
d7863cfe 3523(define_split
3524 [(set (match_operand:SI 0 "s_register_operand" "")
3525 (match_operator:SI 1 "logical_binary_operator"
3526 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
3527 (match_operand:SI 3 "const_int_operand" "")
3528 (match_operand:SI 4 "const_int_operand" ""))
3529 (match_operator:SI 9 "logical_binary_operator"
3530 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3531 (match_operand:SI 6 "const_int_operand" ""))
3532 (match_operand:SI 7 "s_register_operand" "")])]))
3533 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3534 "TARGET_32BIT
d7863cfe 3535 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3536 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3537 [(set (match_dup 8)
3538 (match_op_dup 1
3539 [(ashift:SI (match_dup 2) (match_dup 4))
3540 (match_dup 5)]))
3541 (set (match_dup 0)
3542 (match_op_dup 1
3543 [(lshiftrt:SI (match_dup 8) (match_dup 6))
3544 (match_dup 7)]))]
3545 "
3546 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3547")
3548
3549(define_split
3550 [(set (match_operand:SI 0 "s_register_operand" "")
3551 (match_operator:SI 1 "logical_binary_operator"
3552 [(match_operator:SI 9 "logical_binary_operator"
3553 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3554 (match_operand:SI 6 "const_int_operand" ""))
3555 (match_operand:SI 7 "s_register_operand" "")])
3556 (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
3557 (match_operand:SI 3 "const_int_operand" "")
3558 (match_operand:SI 4 "const_int_operand" ""))]))
3559 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3560 "TARGET_32BIT
d7863cfe 3561 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3562 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3563 [(set (match_dup 8)
3564 (match_op_dup 1
3565 [(ashift:SI (match_dup 2) (match_dup 4))
3566 (match_dup 5)]))
3567 (set (match_dup 0)
3568 (match_op_dup 1
3569 [(lshiftrt:SI (match_dup 8) (match_dup 6))
3570 (match_dup 7)]))]
3571 "
3572 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3573")
3574
3575(define_split
3576 [(set (match_operand:SI 0 "s_register_operand" "")
3577 (match_operator:SI 1 "logical_binary_operator"
3578 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
3579 (match_operand:SI 3 "const_int_operand" "")
3580 (match_operand:SI 4 "const_int_operand" ""))
3581 (match_operator:SI 9 "logical_binary_operator"
3582 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3583 (match_operand:SI 6 "const_int_operand" ""))
3584 (match_operand:SI 7 "s_register_operand" "")])]))
3585 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3586 "TARGET_32BIT
d7863cfe 3587 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3588 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3589 [(set (match_dup 8)
3590 (match_op_dup 1
3591 [(ashift:SI (match_dup 2) (match_dup 4))
3592 (match_dup 5)]))
3593 (set (match_dup 0)
3594 (match_op_dup 1
3595 [(ashiftrt:SI (match_dup 8) (match_dup 6))
3596 (match_dup 7)]))]
3597 "
3598 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3599")
3600
3601(define_split
3602 [(set (match_operand:SI 0 "s_register_operand" "")
3603 (match_operator:SI 1 "logical_binary_operator"
3604 [(match_operator:SI 9 "logical_binary_operator"
3605 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3606 (match_operand:SI 6 "const_int_operand" ""))
3607 (match_operand:SI 7 "s_register_operand" "")])
3608 (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
3609 (match_operand:SI 3 "const_int_operand" "")
3610 (match_operand:SI 4 "const_int_operand" ""))]))
3611 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3612 "TARGET_32BIT
d7863cfe 3613 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3614 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3615 [(set (match_dup 8)
3616 (match_op_dup 1
3617 [(ashift:SI (match_dup 2) (match_dup 4))
3618 (match_dup 5)]))
3619 (set (match_dup 0)
3620 (match_op_dup 1
3621 [(ashiftrt:SI (match_dup 8) (match_dup 6))
3622 (match_dup 7)]))]
3623 "
3624 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3625")
9c08d1fa 3626\f
3627
3628;; Minimum and maximum insns
3629
8b9dc177 3630(define_expand "smaxsi3"
3631 [(parallel [
3632 (set (match_operand:SI 0 "s_register_operand" "")
3633 (smax:SI (match_operand:SI 1 "s_register_operand" "")
3634 (match_operand:SI 2 "arm_rhs_operand" "")))
3635 (clobber (reg:CC CC_REGNUM))])]
25f905c2 3636 "TARGET_32BIT"
8b9dc177 3637 "
8774928b 3638 if (operands[2] == const0_rtx || operands[2] == constm1_rtx)
8b9dc177 3639 {
3640 /* No need for a clobber of the condition code register here. */
d1f9b275 3641 emit_insn (gen_rtx_SET (operands[0],
8b9dc177 3642 gen_rtx_SMAX (SImode, operands[1],
3643 operands[2])));
3644 DONE;
3645 }
3646")
3647
3648(define_insn "*smax_0"
3649 [(set (match_operand:SI 0 "s_register_operand" "=r")
3650 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3651 (const_int 0)))]
25f905c2 3652 "TARGET_32BIT"
8b9dc177 3653 "bic%?\\t%0, %1, %1, asr #31"
d952d547 3654 [(set_attr "predicable" "yes")
1b7da4ac 3655 (set_attr "predicable_short_it" "no")
3656 (set_attr "type" "logic_shift_reg")]
8b9dc177 3657)
3658
8774928b 3659(define_insn "*smax_m1"
3660 [(set (match_operand:SI 0 "s_register_operand" "=r")
3661 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3662 (const_int -1)))]
25f905c2 3663 "TARGET_32BIT"
8774928b 3664 "orr%?\\t%0, %1, %1, asr #31"
d952d547 3665 [(set_attr "predicable" "yes")
1b7da4ac 3666 (set_attr "predicable_short_it" "no")
3667 (set_attr "type" "logic_shift_reg")]
8774928b 3668)
3669
3dc953f2 3670(define_insn_and_split "*arm_smax_insn"
8b9dc177 3671 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3672 (smax:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3673 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
bd5b4116 3674 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3675 "TARGET_ARM"
3dc953f2 3676 "#"
3677 ; cmp\\t%1, %2\;movlt\\t%0, %2
3678 ; cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
3679 "TARGET_ARM"
3680 [(set (reg:CC CC_REGNUM)
3681 (compare:CC (match_dup 1) (match_dup 2)))
3682 (set (match_dup 0)
3683 (if_then_else:SI (ge:SI (reg:CC CC_REGNUM) (const_int 0))
3684 (match_dup 1)
3685 (match_dup 2)))]
3686 ""
cffb2a26 3687 [(set_attr "conds" "clob")
1b7da4ac 3688 (set_attr "length" "8,12")
3689 (set_attr "type" "multiple")]
cffb2a26 3690)
9c08d1fa 3691
8b9dc177 3692(define_expand "sminsi3"
3693 [(parallel [
3694 (set (match_operand:SI 0 "s_register_operand" "")
3695 (smin:SI (match_operand:SI 1 "s_register_operand" "")
3696 (match_operand:SI 2 "arm_rhs_operand" "")))
3697 (clobber (reg:CC CC_REGNUM))])]
25f905c2 3698 "TARGET_32BIT"
8b9dc177 3699 "
3700 if (operands[2] == const0_rtx)
3701 {
3702 /* No need for a clobber of the condition code register here. */
d1f9b275 3703 emit_insn (gen_rtx_SET (operands[0],
8b9dc177 3704 gen_rtx_SMIN (SImode, operands[1],
3705 operands[2])));
3706 DONE;
3707 }
3708")
3709
3710(define_insn "*smin_0"
3711 [(set (match_operand:SI 0 "s_register_operand" "=r")
3712 (smin:SI (match_operand:SI 1 "s_register_operand" "r")
3713 (const_int 0)))]
25f905c2 3714 "TARGET_32BIT"
8b9dc177 3715 "and%?\\t%0, %1, %1, asr #31"
d952d547 3716 [(set_attr "predicable" "yes")
1b7da4ac 3717 (set_attr "predicable_short_it" "no")
3718 (set_attr "type" "logic_shift_reg")]
8b9dc177 3719)
3720
3dc953f2 3721(define_insn_and_split "*arm_smin_insn"
8b9dc177 3722 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3723 (smin:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3724 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
bd5b4116 3725 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3726 "TARGET_ARM"
3dc953f2 3727 "#"
3728 ; cmp\\t%1, %2\;movge\\t%0, %2
3729 ; cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
3730 "TARGET_ARM"
3731 [(set (reg:CC CC_REGNUM)
3732 (compare:CC (match_dup 1) (match_dup 2)))
3733 (set (match_dup 0)
3734 (if_then_else:SI (lt:SI (reg:CC CC_REGNUM) (const_int 0))
3735 (match_dup 1)
3736 (match_dup 2)))]
3737 ""
0d66636f 3738 [(set_attr "conds" "clob")
1b7da4ac 3739 (set_attr "length" "8,12")
3740 (set_attr "type" "multiple,multiple")]
0d66636f 3741)
9c08d1fa 3742
25f905c2 3743(define_expand "umaxsi3"
3744 [(parallel [
3745 (set (match_operand:SI 0 "s_register_operand" "")
3746 (umax:SI (match_operand:SI 1 "s_register_operand" "")
3747 (match_operand:SI 2 "arm_rhs_operand" "")))
3748 (clobber (reg:CC CC_REGNUM))])]
3749 "TARGET_32BIT"
3750 ""
3751)
3752
3dc953f2 3753(define_insn_and_split "*arm_umaxsi3"
9c08d1fa 3754 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3755 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3756 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 3757 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3758 "TARGET_ARM"
3dc953f2 3759 "#"
3760 ; cmp\\t%1, %2\;movcc\\t%0, %2
3761 ; cmp\\t%1, %2\;movcs\\t%0, %1
3762 ; cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
3763 "TARGET_ARM"
3764 [(set (reg:CC CC_REGNUM)
3765 (compare:CC (match_dup 1) (match_dup 2)))
3766 (set (match_dup 0)
3767 (if_then_else:SI (geu:SI (reg:CC CC_REGNUM) (const_int 0))
3768 (match_dup 1)
3769 (match_dup 2)))]
3770 ""
0d66636f 3771 [(set_attr "conds" "clob")
1b7da4ac 3772 (set_attr "length" "8,8,12")
3773 (set_attr "type" "store1")]
0d66636f 3774)
9c08d1fa 3775
25f905c2 3776(define_expand "uminsi3"
3777 [(parallel [
3778 (set (match_operand:SI 0 "s_register_operand" "")
3779 (umin:SI (match_operand:SI 1 "s_register_operand" "")
3780 (match_operand:SI 2 "arm_rhs_operand" "")))
3781 (clobber (reg:CC CC_REGNUM))])]
3782 "TARGET_32BIT"
3783 ""
3784)
3785
3dc953f2 3786(define_insn_and_split "*arm_uminsi3"
9c08d1fa 3787 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3788 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3789 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 3790 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3791 "TARGET_ARM"
3dc953f2 3792 "#"
3793 ; cmp\\t%1, %2\;movcs\\t%0, %2
3794 ; cmp\\t%1, %2\;movcc\\t%0, %1
3795 ; cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
3796 "TARGET_ARM"
3797 [(set (reg:CC CC_REGNUM)
3798 (compare:CC (match_dup 1) (match_dup 2)))
3799 (set (match_dup 0)
3800 (if_then_else:SI (ltu:SI (reg:CC CC_REGNUM) (const_int 0))
3801 (match_dup 1)
3802 (match_dup 2)))]
3803 ""
0d66636f 3804 [(set_attr "conds" "clob")
1b7da4ac 3805 (set_attr "length" "8,8,12")
3806 (set_attr "type" "store1")]
0d66636f 3807)
9c08d1fa 3808
8a18b90c 3809(define_insn "*store_minmaxsi"
9c08d1fa 3810 [(set (match_operand:SI 0 "memory_operand" "=m")
3811 (match_operator:SI 3 "minmax_operator"
3812 [(match_operand:SI 1 "s_register_operand" "r")
3813 (match_operand:SI 2 "s_register_operand" "r")]))
bd5b4116 3814 (clobber (reg:CC CC_REGNUM))]
b207d152 3815 "TARGET_32BIT && optimize_function_for_size_p (cfun) && !arm_restrict_it"
9c08d1fa 3816 "*
dc55b8a9 3817 operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
3818 operands[1], operands[2]);
e2348bcb 3819 output_asm_insn (\"cmp\\t%1, %2\", operands);
25f905c2 3820 if (TARGET_THUMB2)
3821 output_asm_insn (\"ite\t%d3\", operands);
e2348bcb 3822 output_asm_insn (\"str%d3\\t%1, %0\", operands);
3823 output_asm_insn (\"str%D3\\t%2, %0\", operands);
3824 return \"\";
0d66636f 3825 "
3826 [(set_attr "conds" "clob")
25f905c2 3827 (set (attr "length")
3828 (if_then_else (eq_attr "is_thumb" "yes")
3829 (const_int 14)
3830 (const_int 12)))
0d66636f 3831 (set_attr "type" "store1")]
3832)
9c08d1fa 3833
8a18b90c 3834; Reject the frame pointer in operand[1], since reloading this after
3835; it has been eliminated can cause carnage.
f7fbdd4a 3836(define_insn "*minmax_arithsi"
9c08d1fa 3837 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3838 (match_operator:SI 4 "shiftable_operator"
3839 [(match_operator:SI 5 "minmax_operator"
3840 [(match_operand:SI 2 "s_register_operand" "r,r")
3841 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
3842 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 3843 (clobber (reg:CC CC_REGNUM))]
7c36fe71 3844 "TARGET_32BIT && !arm_eliminable_register (operands[1]) && !arm_restrict_it"
9c08d1fa 3845 "*
0d66636f 3846 {
3847 enum rtx_code code = GET_CODE (operands[4]);
25f905c2 3848 bool need_else;
3849
3850 if (which_alternative != 0 || operands[3] != const0_rtx
ca0fc5a2 3851 || (code != PLUS && code != IOR && code != XOR))
25f905c2 3852 need_else = true;
3853 else
3854 need_else = false;
0d66636f 3855
dc55b8a9 3856 operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
3857 operands[2], operands[3]);
0d66636f 3858 output_asm_insn (\"cmp\\t%2, %3\", operands);
25f905c2 3859 if (TARGET_THUMB2)
3860 {
3861 if (need_else)
3862 output_asm_insn (\"ite\\t%d5\", operands);
3863 else
3864 output_asm_insn (\"it\\t%d5\", operands);
3865 }
0d66636f 3866 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
25f905c2 3867 if (need_else)
0d66636f 3868 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
3869 return \"\";
215b30b3 3870 }"
0d66636f 3871 [(set_attr "conds" "clob")
25f905c2 3872 (set (attr "length")
3873 (if_then_else (eq_attr "is_thumb" "yes")
3874 (const_int 14)
1b7da4ac 3875 (const_int 12)))
3876 (set_attr "type" "multiple")]
0d66636f 3877)
9c08d1fa 3878
4164bca1 3879; Reject the frame pointer in operand[1], since reloading this after
3880; it has been eliminated can cause carnage.
3881(define_insn_and_split "*minmax_arithsi_non_canon"
7c36fe71 3882 [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts")
4164bca1 3883 (minus:SI
7c36fe71 3884 (match_operand:SI 1 "s_register_operand" "0,?Ts")
4164bca1 3885 (match_operator:SI 4 "minmax_operator"
7c36fe71 3886 [(match_operand:SI 2 "s_register_operand" "Ts,Ts")
3887 (match_operand:SI 3 "arm_rhs_operand" "TsI,TsI")])))
4164bca1 3888 (clobber (reg:CC CC_REGNUM))]
7c36fe71 3889 "TARGET_32BIT && !arm_eliminable_register (operands[1])
3890 && !(arm_restrict_it && CONST_INT_P (operands[3]))"
4164bca1 3891 "#"
3892 "TARGET_32BIT && !arm_eliminable_register (operands[1]) && reload_completed"
3893 [(set (reg:CC CC_REGNUM)
3894 (compare:CC (match_dup 2) (match_dup 3)))
3895
3896 (cond_exec (match_op_dup 4 [(reg:CC CC_REGNUM) (const_int 0)])
3897 (set (match_dup 0)
3898 (minus:SI (match_dup 1)
3899 (match_dup 2))))
3900 (cond_exec (match_op_dup 5 [(reg:CC CC_REGNUM) (const_int 0)])
3901 (set (match_dup 0)
36ee0cde 3902 (match_dup 6)))]
4164bca1 3903 {
3754d046 3904 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
4164bca1 3905 operands[2], operands[3]);
3906 enum rtx_code rc = minmax_code (operands[4]);
3907 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode,
3908 operands[2], operands[3]);
3909
3910 if (mode == CCFPmode || mode == CCFPEmode)
3911 rc = reverse_condition_maybe_unordered (rc);
3912 else
3913 rc = reverse_condition (rc);
3914 operands[5] = gen_rtx_fmt_ee (rc, SImode, operands[2], operands[3]);
36ee0cde 3915 if (CONST_INT_P (operands[3]))
3916 operands[6] = plus_constant (SImode, operands[1], -INTVAL (operands[3]));
3917 else
3918 operands[6] = gen_rtx_MINUS (SImode, operands[1], operands[3]);
4164bca1 3919 }
3920 [(set_attr "conds" "clob")
3921 (set (attr "length")
3922 (if_then_else (eq_attr "is_thumb" "yes")
3923 (const_int 14)
1b7da4ac 3924 (const_int 12)))
3925 (set_attr "type" "multiple")]
4164bca1 3926)
3927
b49e3742 3928(define_code_iterator SAT [smin smax])
3929(define_code_iterator SATrev [smin smax])
3930(define_code_attr SATlo [(smin "1") (smax "2")])
3931(define_code_attr SAThi [(smin "2") (smax "1")])
3932
3933(define_insn "*satsi_<SAT:code>"
3934 [(set (match_operand:SI 0 "s_register_operand" "=r")
3935 (SAT:SI (SATrev:SI (match_operand:SI 3 "s_register_operand" "r")
3936 (match_operand:SI 1 "const_int_operand" "i"))
3937 (match_operand:SI 2 "const_int_operand" "i")))]
3938 "TARGET_32BIT && arm_arch6 && <SAT:CODE> != <SATrev:CODE>
3939 && arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>], NULL, NULL)"
3940{
3941 int mask;
3942 bool signed_sat;
3943 if (!arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>],
3944 &mask, &signed_sat))
3945 gcc_unreachable ();
3946
3947 operands[1] = GEN_INT (mask);
3948 if (signed_sat)
3949 return "ssat%?\t%0, %1, %3";
3950 else
3951 return "usat%?\t%0, %1, %3";
3952}
7c36fe71 3953 [(set_attr "predicable" "yes")
1b7da4ac 3954 (set_attr "predicable_short_it" "no")
3955 (set_attr "type" "alus_imm")]
bebe9bbb 3956)
b49e3742 3957
3958(define_insn "*satsi_<SAT:code>_shift"
3959 [(set (match_operand:SI 0 "s_register_operand" "=r")
3960 (SAT:SI (SATrev:SI (match_operator:SI 3 "sat_shift_operator"
3961 [(match_operand:SI 4 "s_register_operand" "r")
3962 (match_operand:SI 5 "const_int_operand" "i")])
3963 (match_operand:SI 1 "const_int_operand" "i"))
3964 (match_operand:SI 2 "const_int_operand" "i")))]
3965 "TARGET_32BIT && arm_arch6 && <SAT:CODE> != <SATrev:CODE>
3966 && arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>], NULL, NULL)"
3967{
3968 int mask;
3969 bool signed_sat;
3970 if (!arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>],
3971 &mask, &signed_sat))
3972 gcc_unreachable ();
3973
3974 operands[1] = GEN_INT (mask);
3975 if (signed_sat)
3976 return "ssat%?\t%0, %1, %4%S3";
3977 else
3978 return "usat%?\t%0, %1, %4%S3";
3979}
3980 [(set_attr "predicable" "yes")
7c36fe71 3981 (set_attr "predicable_short_it" "no")
b49e3742 3982 (set_attr "shift" "3")
d82e788e 3983 (set_attr "type" "logic_shift_reg")])
b11cae9e 3984\f
3985;; Shift and rotation insns
3986
a2cd141b 3987(define_expand "ashldi3"
3988 [(set (match_operand:DI 0 "s_register_operand" "")
3989 (ashift:DI (match_operand:DI 1 "s_register_operand" "")
aa06c51c 3990 (match_operand:SI 2 "general_operand" "")))]
25f905c2 3991 "TARGET_32BIT"
a2cd141b 3992 "
aa06c51c 3993 if (TARGET_NEON)
3994 {
3995 /* Delay the decision whether to use NEON or core-regs until
3996 register allocation. */
3997 emit_insn (gen_ashldi3_neon (operands[0], operands[1], operands[2]));
3998 DONE;
3999 }
4000 else
4001 {
4002 /* Only the NEON case can handle in-memory shift counts. */
4003 if (!reg_or_int_operand (operands[2], SImode))
4004 operands[2] = force_reg (SImode, operands[2]);
4005 }
4006
b805622c 4007 if (!CONST_INT_P (operands[2]) && TARGET_REALLY_IWMMXT)
ffcc986d 4008 ; /* No special preparation statements; expand pattern as above. */
4009 else
a2cd141b 4010 {
ffcc986d 4011 rtx scratch1, scratch2;
4012
8c4e8755 4013 if (operands[2] == CONST1_RTX (SImode))
a2cd141b 4014 {
4015 emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
4016 DONE;
4017 }
ffcc986d 4018
4019 /* Ideally we should use iwmmxt here if we could know that operands[1]
4020 ends up already living in an iwmmxt register. Otherwise it's
4021 cheaper to have the alternate code being generated than moving
4022 values to iwmmxt regs and back. */
4023
ffcc986d 4024 /* Expand operation using core-registers.
4025 'FAIL' would achieve the same thing, but this is a bit smarter. */
4026 scratch1 = gen_reg_rtx (SImode);
4027 scratch2 = gen_reg_rtx (SImode);
4028 arm_emit_coreregs_64bit_shift (ASHIFT, operands[0], operands[1],
4029 operands[2], scratch1, scratch2);
4030 DONE;
a2cd141b 4031 }
a2cd141b 4032 "
4033)
4034
2837e3fb 4035(define_insn "arm_ashldi3_1bit"
50ad1bf9 4036 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 4037 (ashift:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 4038 (const_int 1)))
4039 (clobber (reg:CC CC_REGNUM))]
25f905c2 4040 "TARGET_32BIT"
2837e3fb 4041 "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
a2cd141b 4042 [(set_attr "conds" "clob")
1b7da4ac 4043 (set_attr "length" "8")
4044 (set_attr "type" "multiple")]
a2cd141b 4045)
4046
87b22bf7 4047(define_expand "ashlsi3"
cffb2a26 4048 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 4049 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
4050 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 4051 "TARGET_EITHER"
87b22bf7 4052 "
0438d37f 4053 if (CONST_INT_P (operands[2])
8c4e8755 4054 && (UINTVAL (operands[2])) > 31)
87b22bf7 4055 {
4056 emit_insn (gen_movsi (operands[0], const0_rtx));
4057 DONE;
4058 }
cffb2a26 4059 "
4060)
4061
a2cd141b 4062(define_expand "ashrdi3"
4063 [(set (match_operand:DI 0 "s_register_operand" "")
4064 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
4065 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 4066 "TARGET_32BIT"
a2cd141b 4067 "
aa06c51c 4068 if (TARGET_NEON)
4069 {
4070 /* Delay the decision whether to use NEON or core-regs until
4071 register allocation. */
4072 emit_insn (gen_ashrdi3_neon (operands[0], operands[1], operands[2]));
4073 DONE;
4074 }
4075
b805622c 4076 if (!CONST_INT_P (operands[2]) && TARGET_REALLY_IWMMXT)
ffcc986d 4077 ; /* No special preparation statements; expand pattern as above. */
4078 else
a2cd141b 4079 {
ffcc986d 4080 rtx scratch1, scratch2;
4081
8c4e8755 4082 if (operands[2] == CONST1_RTX (SImode))
a2cd141b 4083 {
4084 emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
4085 DONE;
4086 }
ffcc986d 4087
4088 /* Ideally we should use iwmmxt here if we could know that operands[1]
4089 ends up already living in an iwmmxt register. Otherwise it's
4090 cheaper to have the alternate code being generated than moving
4091 values to iwmmxt regs and back. */
4092
ffcc986d 4093 /* Expand operation using core-registers.
4094 'FAIL' would achieve the same thing, but this is a bit smarter. */
4095 scratch1 = gen_reg_rtx (SImode);
4096 scratch2 = gen_reg_rtx (SImode);
4097 arm_emit_coreregs_64bit_shift (ASHIFTRT, operands[0], operands[1],
4098 operands[2], scratch1, scratch2);
4099 DONE;
a2cd141b 4100 }
a2cd141b 4101 "
4102)
4103
2837e3fb 4104(define_insn "arm_ashrdi3_1bit"
50ad1bf9 4105 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 4106 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 4107 (const_int 1)))
4108 (clobber (reg:CC CC_REGNUM))]
25f905c2 4109 "TARGET_32BIT"
2837e3fb 4110 "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
a2cd141b 4111 [(set_attr "conds" "clob")
1b7da4ac 4112 (set_attr "length" "8")
4113 (set_attr "type" "multiple")]
a2cd141b 4114)
4115
87b22bf7 4116(define_expand "ashrsi3"
cffb2a26 4117 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 4118 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
4119 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 4120 "TARGET_EITHER"
87b22bf7 4121 "
0438d37f 4122 if (CONST_INT_P (operands[2])
8c4e8755 4123 && UINTVAL (operands[2]) > 31)
87b22bf7 4124 operands[2] = GEN_INT (31);
cffb2a26 4125 "
4126)
4127
a2cd141b 4128(define_expand "lshrdi3"
4129 [(set (match_operand:DI 0 "s_register_operand" "")
4130 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
4131 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 4132 "TARGET_32BIT"
a2cd141b 4133 "
aa06c51c 4134 if (TARGET_NEON)
4135 {
4136 /* Delay the decision whether to use NEON or core-regs until
4137 register allocation. */
4138 emit_insn (gen_lshrdi3_neon (operands[0], operands[1], operands[2]));
4139 DONE;
4140 }
4141
b805622c 4142 if (!CONST_INT_P (operands[2]) && TARGET_REALLY_IWMMXT)
ffcc986d 4143 ; /* No special preparation statements; expand pattern as above. */
4144 else
a2cd141b 4145 {
ffcc986d 4146 rtx scratch1, scratch2;
4147
8c4e8755 4148 if (operands[2] == CONST1_RTX (SImode))
a2cd141b 4149 {
4150 emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
4151 DONE;
4152 }
ffcc986d 4153
4154 /* Ideally we should use iwmmxt here if we could know that operands[1]
4155 ends up already living in an iwmmxt register. Otherwise it's
4156 cheaper to have the alternate code being generated than moving
4157 values to iwmmxt regs and back. */
4158
ffcc986d 4159 /* Expand operation using core-registers.
4160 'FAIL' would achieve the same thing, but this is a bit smarter. */
4161 scratch1 = gen_reg_rtx (SImode);
4162 scratch2 = gen_reg_rtx (SImode);
4163 arm_emit_coreregs_64bit_shift (LSHIFTRT, operands[0], operands[1],
4164 operands[2], scratch1, scratch2);
4165 DONE;
a2cd141b 4166 }
a2cd141b 4167 "
4168)
4169
2837e3fb 4170(define_insn "arm_lshrdi3_1bit"
50ad1bf9 4171 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 4172 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 4173 (const_int 1)))
4174 (clobber (reg:CC CC_REGNUM))]
25f905c2 4175 "TARGET_32BIT"
2837e3fb 4176 "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
a2cd141b 4177 [(set_attr "conds" "clob")
1b7da4ac 4178 (set_attr "length" "8")
4179 (set_attr "type" "multiple")]
a2cd141b 4180)
4181
87b22bf7 4182(define_expand "lshrsi3"
cffb2a26 4183 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 4184 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
4185 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 4186 "TARGET_EITHER"
87b22bf7 4187 "
0438d37f 4188 if (CONST_INT_P (operands[2])
8c4e8755 4189 && (UINTVAL (operands[2])) > 31)
87b22bf7 4190 {
4191 emit_insn (gen_movsi (operands[0], const0_rtx));
4192 DONE;
4193 }
cffb2a26 4194 "
4195)
4196
87b22bf7 4197(define_expand "rotlsi3"
cffb2a26 4198 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 4199 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
4200 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 4201 "TARGET_32BIT"
87b22bf7 4202 "
0438d37f 4203 if (CONST_INT_P (operands[2]))
87b22bf7 4204 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
4205 else
b11cae9e 4206 {
87b22bf7 4207 rtx reg = gen_reg_rtx (SImode);
4208 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
4209 operands[2] = reg;
b11cae9e 4210 }
cffb2a26 4211 "
4212)
9c08d1fa 4213
87b22bf7 4214(define_expand "rotrsi3"
cffb2a26 4215 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 4216 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
4217 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 4218 "TARGET_EITHER"
87b22bf7 4219 "
25f905c2 4220 if (TARGET_32BIT)
cffb2a26 4221 {
0438d37f 4222 if (CONST_INT_P (operands[2])
8c4e8755 4223 && UINTVAL (operands[2]) > 31)
cffb2a26 4224 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
4225 }
25f905c2 4226 else /* TARGET_THUMB1 */
cffb2a26 4227 {
0438d37f 4228 if (CONST_INT_P (operands [2]))
cffb2a26 4229 operands [2] = force_reg (SImode, operands[2]);
4230 }
4231 "
4232)
87b22bf7 4233
cffb2a26 4234(define_insn "*arm_shiftsi3"
88c29385 4235 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r,r")
cffb2a26 4236 (match_operator:SI 3 "shift_operator"
88c29385 4237 [(match_operand:SI 1 "s_register_operand" "0,l,r,r")
4238 (match_operand:SI 2 "reg_or_int_operand" "l,M,M,r")]))]
25f905c2 4239 "TARGET_32BIT"
4240 "* return arm_output_shift(operands, 0);"
344495ea 4241 [(set_attr "predicable" "yes")
88c29385 4242 (set_attr "arch" "t2,t2,*,*")
4243 (set_attr "predicable_short_it" "yes,yes,no,no")
7c36fe71 4244 (set_attr "length" "4")
331beb1a 4245 (set_attr "shift" "1")
88c29385 4246 (set_attr "type" "alu_shift_reg,alu_shift_imm,alu_shift_imm,alu_shift_reg")]
6c4c2133 4247)
87b22bf7 4248
f7fbdd4a 4249(define_insn "*shiftsi3_compare0"
bd5b4116 4250 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 4251 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
6b6abc9c 4252 [(match_operand:SI 1 "s_register_operand" "r,r")
4253 (match_operand:SI 2 "arm_rhs_operand" "M,r")])
9c08d1fa 4254 (const_int 0)))
6b6abc9c 4255 (set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 4256 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
25f905c2 4257 "TARGET_32BIT"
4258 "* return arm_output_shift(operands, 1);"
344495ea 4259 [(set_attr "conds" "set")
331beb1a 4260 (set_attr "shift" "1")
d82e788e 4261 (set_attr "type" "alus_shift_imm,alus_shift_reg")]
0d66636f 4262)
9c08d1fa 4263
f7fbdd4a 4264(define_insn "*shiftsi3_compare0_scratch"
bd5b4116 4265 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 4266 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
6b6abc9c 4267 [(match_operand:SI 1 "s_register_operand" "r,r")
4268 (match_operand:SI 2 "arm_rhs_operand" "M,r")])
9c08d1fa 4269 (const_int 0)))
6b6abc9c 4270 (clobber (match_scratch:SI 0 "=r,r"))]
25f905c2 4271 "TARGET_32BIT"
4272 "* return arm_output_shift(operands, 1);"
344495ea 4273 [(set_attr "conds" "set")
6b6abc9c 4274 (set_attr "shift" "1")
d82e788e 4275 (set_attr "type" "shift_imm,shift_reg")]
0d66636f 4276)
9c08d1fa 4277
d5d4dc8d 4278(define_insn "*not_shiftsi"
4279 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 4280 (not:SI (match_operator:SI 3 "shift_operator"
d5d4dc8d 4281 [(match_operand:SI 1 "s_register_operand" "r,r")
4282 (match_operand:SI 2 "shift_amount_operand" "M,rM")])))]
4283 "TARGET_32BIT"
6c4c2133 4284 "mvn%?\\t%0, %1%S3"
344495ea 4285 [(set_attr "predicable" "yes")
d952d547 4286 (set_attr "predicable_short_it" "no")
331beb1a 4287 (set_attr "shift" "1")
d5d4dc8d 4288 (set_attr "arch" "32,a")
1aed5204 4289 (set_attr "type" "mvn_shift,mvn_shift_reg")])
9c08d1fa 4290
d5d4dc8d 4291(define_insn "*not_shiftsi_compare0"
bd5b4116 4292 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 4293 (compare:CC_NOOV
4294 (not:SI (match_operator:SI 3 "shift_operator"
4295 [(match_operand:SI 1 "s_register_operand" "r,r")
4296 (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
4297 (const_int 0)))
4298 (set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 4299 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
d5d4dc8d 4300 "TARGET_32BIT"
3ef90e77 4301 "mvns%?\\t%0, %1%S3"
344495ea 4302 [(set_attr "conds" "set")
331beb1a 4303 (set_attr "shift" "1")
d5d4dc8d 4304 (set_attr "arch" "32,a")
1aed5204 4305 (set_attr "type" "mvn_shift,mvn_shift_reg")])
9c08d1fa 4306
d5d4dc8d 4307(define_insn "*not_shiftsi_compare0_scratch"
bd5b4116 4308 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 4309 (compare:CC_NOOV
4310 (not:SI (match_operator:SI 3 "shift_operator"
4311 [(match_operand:SI 1 "s_register_operand" "r,r")
4312 (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
4313 (const_int 0)))
4314 (clobber (match_scratch:SI 0 "=r,r"))]
4315 "TARGET_32BIT"
3ef90e77 4316 "mvns%?\\t%0, %1%S3"
344495ea 4317 [(set_attr "conds" "set")
331beb1a 4318 (set_attr "shift" "1")
d5d4dc8d 4319 (set_attr "arch" "32,a")
1aed5204 4320 (set_attr "type" "mvn_shift,mvn_shift_reg")])
9c08d1fa 4321
cffb2a26 4322;; We don't really have extzv, but defining this using shifts helps
4323;; to reduce register pressure later on.
4324
4325(define_expand "extzv"
eb04cafb 4326 [(set (match_operand 0 "s_register_operand" "")
4327 (zero_extract (match_operand 1 "nonimmediate_operand" "")
4328 (match_operand 2 "const_int_operand" "")
4329 (match_operand 3 "const_int_operand" "")))]
8b054d5a 4330 "TARGET_THUMB1 || arm_arch_thumb2"
cffb2a26 4331 "
4332 {
4333 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
4334 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
4335
8b054d5a 4336 if (arm_arch_thumb2)
4337 {
eb04cafb 4338 HOST_WIDE_INT width = INTVAL (operands[2]);
4339 HOST_WIDE_INT bitpos = INTVAL (operands[3]);
4340
4341 if (unaligned_access && MEM_P (operands[1])
4342 && (width == 16 || width == 32) && (bitpos % BITS_PER_UNIT) == 0)
4343 {
4344 rtx base_addr;
4345
4346 if (BYTES_BIG_ENDIAN)
4347 bitpos = GET_MODE_BITSIZE (GET_MODE (operands[0])) - width
4348 - bitpos;
4349
4350 if (width == 32)
4351 {
4352 base_addr = adjust_address (operands[1], SImode,
4353 bitpos / BITS_PER_UNIT);
4354 emit_insn (gen_unaligned_loadsi (operands[0], base_addr));
4355 }
4356 else
4357 {
4358 rtx dest = operands[0];
4359 rtx tmp = gen_reg_rtx (SImode);
4360
4361 /* We may get a paradoxical subreg here. Strip it off. */
4362 if (GET_CODE (dest) == SUBREG
4363 && GET_MODE (dest) == SImode
4364 && GET_MODE (SUBREG_REG (dest)) == HImode)
4365 dest = SUBREG_REG (dest);
4366
4367 if (GET_MODE_BITSIZE (GET_MODE (dest)) != width)
4368 FAIL;
4369
4370 base_addr = adjust_address (operands[1], HImode,
4371 bitpos / BITS_PER_UNIT);
4372 emit_insn (gen_unaligned_loadhiu (tmp, base_addr));
4373 emit_move_insn (gen_lowpart (SImode, dest), tmp);
4374 }
4375 DONE;
4376 }
4377 else if (s_register_operand (operands[1], GET_MODE (operands[1])))
4378 {
4379 emit_insn (gen_extzv_t2 (operands[0], operands[1], operands[2],
4380 operands[3]));
4381 DONE;
4382 }
4383 else
4384 FAIL;
8b054d5a 4385 }
eb04cafb 4386
4387 if (!s_register_operand (operands[1], GET_MODE (operands[1])))
4388 FAIL;
8b054d5a 4389
cffb2a26 4390 operands[3] = GEN_INT (rshift);
4391
4392 if (lshift == 0)
4393 {
4394 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
4395 DONE;
4396 }
4397
eb04cafb 4398 emit_insn (gen_extzv_t1 (operands[0], operands[1], GEN_INT (lshift),
4399 operands[3], gen_reg_rtx (SImode)));
4400 DONE;
215b30b3 4401 }"
cffb2a26 4402)
4403
eb04cafb 4404;; Helper for extzv, for the Thumb-1 register-shifts case.
4405
4406(define_expand "extzv_t1"
4407 [(set (match_operand:SI 4 "s_register_operand" "")
4408 (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "")
4409 (match_operand:SI 2 "const_int_operand" "")))
4410 (set (match_operand:SI 0 "s_register_operand" "")
4411 (lshiftrt:SI (match_dup 4)
4412 (match_operand:SI 3 "const_int_operand" "")))]
4413 "TARGET_THUMB1"
4414 "")
4415
4416(define_expand "extv"
4417 [(set (match_operand 0 "s_register_operand" "")
4418 (sign_extract (match_operand 1 "nonimmediate_operand" "")
4419 (match_operand 2 "const_int_operand" "")
4420 (match_operand 3 "const_int_operand" "")))]
4421 "arm_arch_thumb2"
4422{
4423 HOST_WIDE_INT width = INTVAL (operands[2]);
4424 HOST_WIDE_INT bitpos = INTVAL (operands[3]);
4425
4426 if (unaligned_access && MEM_P (operands[1]) && (width == 16 || width == 32)
4427 && (bitpos % BITS_PER_UNIT) == 0)
4428 {
4429 rtx base_addr;
4430
4431 if (BYTES_BIG_ENDIAN)
4432 bitpos = GET_MODE_BITSIZE (GET_MODE (operands[0])) - width - bitpos;
4433
4434 if (width == 32)
4435 {
4436 base_addr = adjust_address (operands[1], SImode,
4437 bitpos / BITS_PER_UNIT);
4438 emit_insn (gen_unaligned_loadsi (operands[0], base_addr));
4439 }
4440 else
4441 {
4442 rtx dest = operands[0];
4443 rtx tmp = gen_reg_rtx (SImode);
4444
4445 /* We may get a paradoxical subreg here. Strip it off. */
4446 if (GET_CODE (dest) == SUBREG
4447 && GET_MODE (dest) == SImode
4448 && GET_MODE (SUBREG_REG (dest)) == HImode)
4449 dest = SUBREG_REG (dest);
4450
4451 if (GET_MODE_BITSIZE (GET_MODE (dest)) != width)
4452 FAIL;
4453
4454 base_addr = adjust_address (operands[1], HImode,
4455 bitpos / BITS_PER_UNIT);
4456 emit_insn (gen_unaligned_loadhis (tmp, base_addr));
4457 emit_move_insn (gen_lowpart (SImode, dest), tmp);
4458 }
4459
4460 DONE;
4461 }
4462 else if (!s_register_operand (operands[1], GET_MODE (operands[1])))
4463 FAIL;
4464 else if (GET_MODE (operands[0]) == SImode
4465 && GET_MODE (operands[1]) == SImode)
4466 {
4467 emit_insn (gen_extv_regsi (operands[0], operands[1], operands[2],
4468 operands[3]));
4469 DONE;
4470 }
4471
4472 FAIL;
4473})
4474
4475; Helper to expand register forms of extv with the proper modes.
4476
4477(define_expand "extv_regsi"
4478 [(set (match_operand:SI 0 "s_register_operand" "")
4479 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
4480 (match_operand 2 "const_int_operand" "")
4481 (match_operand 3 "const_int_operand" "")))]
4482 ""
4483{
4484})
4485
4486; ARMv6+ unaligned load/store instructions (used for packed structure accesses).
4487
4488(define_insn "unaligned_loadsi"
4489 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4490 (unspec:SI [(match_operand:SI 1 "memory_operand" "Uw,m")]
4491 UNSPEC_UNALIGNED_LOAD))]
8fe38eb2 4492 "unaligned_access"
eb04cafb 4493 "ldr%?\t%0, %1\t@ unaligned"
4494 [(set_attr "arch" "t2,any")
4495 (set_attr "length" "2,4")
4496 (set_attr "predicable" "yes")
d952d547 4497 (set_attr "predicable_short_it" "yes,no")
eb04cafb 4498 (set_attr "type" "load1")])
4499
4500(define_insn "unaligned_loadhis"
4501 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4502 (sign_extend:SI
e3f4ccee 4503 (unspec:HI [(match_operand:HI 1 "memory_operand" "Uw,Uh")]
eb04cafb 4504 UNSPEC_UNALIGNED_LOAD)))]
8fe38eb2 4505 "unaligned_access"
3ef90e77 4506 "ldrsh%?\t%0, %1\t@ unaligned"
eb04cafb 4507 [(set_attr "arch" "t2,any")
4508 (set_attr "length" "2,4")
4509 (set_attr "predicable" "yes")
d952d547 4510 (set_attr "predicable_short_it" "yes,no")
eb04cafb 4511 (set_attr "type" "load_byte")])
4512
4513(define_insn "unaligned_loadhiu"
4514 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4515 (zero_extend:SI
4516 (unspec:HI [(match_operand:HI 1 "memory_operand" "Uw,m")]
4517 UNSPEC_UNALIGNED_LOAD)))]
8fe38eb2 4518 "unaligned_access"
3ef90e77 4519 "ldrh%?\t%0, %1\t@ unaligned"
eb04cafb 4520 [(set_attr "arch" "t2,any")
4521 (set_attr "length" "2,4")
4522 (set_attr "predicable" "yes")
d952d547 4523 (set_attr "predicable_short_it" "yes,no")
eb04cafb 4524 (set_attr "type" "load_byte")])
4525
4526(define_insn "unaligned_storesi"
4527 [(set (match_operand:SI 0 "memory_operand" "=Uw,m")
4528 (unspec:SI [(match_operand:SI 1 "s_register_operand" "l,r")]
4529 UNSPEC_UNALIGNED_STORE))]
8fe38eb2 4530 "unaligned_access"
eb04cafb 4531 "str%?\t%1, %0\t@ unaligned"
4532 [(set_attr "arch" "t2,any")
4533 (set_attr "length" "2,4")
4534 (set_attr "predicable" "yes")
d952d547 4535 (set_attr "predicable_short_it" "yes,no")
eb04cafb 4536 (set_attr "type" "store1")])
4537
4538(define_insn "unaligned_storehi"
4539 [(set (match_operand:HI 0 "memory_operand" "=Uw,m")
4540 (unspec:HI [(match_operand:HI 1 "s_register_operand" "l,r")]
4541 UNSPEC_UNALIGNED_STORE))]
8fe38eb2 4542 "unaligned_access"
3ef90e77 4543 "strh%?\t%1, %0\t@ unaligned"
eb04cafb 4544 [(set_attr "arch" "t2,any")
4545 (set_attr "length" "2,4")
4546 (set_attr "predicable" "yes")
d952d547 4547 (set_attr "predicable_short_it" "yes,no")
eb04cafb 4548 (set_attr "type" "store1")])
4549
ae51a965 4550
eb04cafb 4551(define_insn "*extv_reg"
8b054d5a 4552 [(set (match_operand:SI 0 "s_register_operand" "=r")
4553 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
13051f13 4554 (match_operand:SI 2 "const_int_operand" "n")
4555 (match_operand:SI 3 "const_int_operand" "n")))]
4556 "arm_arch_thumb2
4557 && IN_RANGE (INTVAL (operands[3]), 0, 31)
4558 && IN_RANGE (INTVAL (operands[2]), 1, 32 - INTVAL (operands[3]))"
8b054d5a 4559 "sbfx%?\t%0, %1, %3, %2"
4560 [(set_attr "length" "4")
d952d547 4561 (set_attr "predicable" "yes")
d82e788e 4562 (set_attr "predicable_short_it" "no")
4563 (set_attr "type" "bfm")]
8b054d5a 4564)
4565
4566(define_insn "extzv_t2"
4567 [(set (match_operand:SI 0 "s_register_operand" "=r")
4568 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "r")
13051f13 4569 (match_operand:SI 2 "const_int_operand" "n")
4570 (match_operand:SI 3 "const_int_operand" "n")))]
4571 "arm_arch_thumb2
4572 && IN_RANGE (INTVAL (operands[3]), 0, 31)
4573 && IN_RANGE (INTVAL (operands[2]), 1, 32 - INTVAL (operands[3]))"
8b054d5a 4574 "ubfx%?\t%0, %1, %3, %2"
4575 [(set_attr "length" "4")
d952d547 4576 (set_attr "predicable" "yes")
d82e788e 4577 (set_attr "predicable_short_it" "no")
4578 (set_attr "type" "bfm")]
8b054d5a 4579)
4580
7d3cda8c 4581
4582;; Division instructions
4583(define_insn "divsi3"
8f5f2788 4584 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4585 (div:SI (match_operand:SI 1 "s_register_operand" "r,r")
4586 (match_operand:SI 2 "s_register_operand" "r,r")))]
7d3cda8c 4587 "TARGET_IDIV"
8f5f2788 4588 "@
4589 sdiv%?\t%0, %1, %2
4590 sdiv\t%0, %1, %2"
4591 [(set_attr "arch" "32,v8mb")
4592 (set_attr "predicable" "yes")
d952d547 4593 (set_attr "predicable_short_it" "no")
9da0ec36 4594 (set_attr "type" "sdiv")]
7d3cda8c 4595)
4596
4597(define_insn "udivsi3"
8f5f2788 4598 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4599 (udiv:SI (match_operand:SI 1 "s_register_operand" "r,r")
4600 (match_operand:SI 2 "s_register_operand" "r,r")))]
7d3cda8c 4601 "TARGET_IDIV"
8f5f2788 4602 "@
4603 udiv%?\t%0, %1, %2
4604 udiv\t%0, %1, %2"
4605 [(set_attr "arch" "32,v8mb")
4606 (set_attr "predicable" "yes")
d952d547 4607 (set_attr "predicable_short_it" "no")
9da0ec36 4608 (set_attr "type" "udiv")]
7d3cda8c 4609)
4610
b11cae9e 4611\f
4612;; Unary arithmetic insns
4613
f6c98a9a 4614(define_expand "negvsi3"
4615 [(match_operand:SI 0 "register_operand")
4616 (match_operand:SI 1 "register_operand")
4617 (match_operand 2 "")]
4618 "TARGET_32BIT"
4619{
4620 emit_insn (gen_subsi3_compare (operands[0], const0_rtx, operands[1]));
4621 arm_gen_unlikely_cbranch (NE, CC_Vmode, operands[2]);
4622
4623 DONE;
4624})
4625
4626(define_expand "negvdi3"
4627 [(match_operand:DI 0 "register_operand")
4628 (match_operand:DI 1 "register_operand")
4629 (match_operand 2 "")]
4630 "TARGET_ARM"
4631{
4632 emit_insn (gen_negdi2_compare (operands[0], operands[1]));
4633 arm_gen_unlikely_cbranch (NE, CC_Vmode, operands[2]);
4634
4635 DONE;
4636})
4637
4638
4639(define_insn_and_split "negdi2_compare"
4640 [(set (reg:CC CC_REGNUM)
4641 (compare:CC
4642 (const_int 0)
4643 (match_operand:DI 1 "register_operand" "0,r")))
4644 (set (match_operand:DI 0 "register_operand" "=r,&r")
4645 (minus:DI (const_int 0) (match_dup 1)))]
4646 "TARGET_ARM"
4647 "#"
4648 "&& reload_completed"
4649 [(parallel [(set (reg:CC CC_REGNUM)
4650 (compare:CC (const_int 0) (match_dup 1)))
4651 (set (match_dup 0) (minus:SI (const_int 0)
4652 (match_dup 1)))])
4653 (parallel [(set (reg:CC CC_REGNUM)
4654 (compare:CC (const_int 0) (match_dup 3)))
4655 (set (match_dup 2)
4656 (minus:SI
4657 (minus:SI (const_int 0) (match_dup 3))
4658 (ltu:SI (reg:CC_C CC_REGNUM)
4659 (const_int 0))))])]
4660 {
4661 operands[2] = gen_highpart (SImode, operands[0]);
4662 operands[0] = gen_lowpart (SImode, operands[0]);
4663 operands[3] = gen_highpart (SImode, operands[1]);
4664 operands[1] = gen_lowpart (SImode, operands[1]);
4665 }
4666 [(set_attr "conds" "set")
4667 (set_attr "length" "8")
4668 (set_attr "type" "multiple")]
4669)
4670
cffb2a26 4671(define_expand "negdi2"
4672 [(parallel
8135a42b 4673 [(set (match_operand:DI 0 "s_register_operand" "")
4674 (neg:DI (match_operand:DI 1 "s_register_operand" "")))
bd5b4116 4675 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 4676 "TARGET_EITHER"
774d2fbb 4677 {
4678 if (TARGET_NEON)
4679 {
4680 emit_insn (gen_negdi2_neon (operands[0], operands[1]));
4681 DONE;
4682 }
4683 }
cffb2a26 4684)
4685
4686;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
e5fea38e 4687;; The first alternative allows the common case of a *full* overlap.
d5bf2b53 4688(define_insn_and_split "*negdi2_insn"
458a8706 4689 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 4690 (neg:DI (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 4691 (clobber (reg:CC CC_REGNUM))]
d5bf2b53 4692 "TARGET_32BIT"
4693 "#" ; rsbs %Q0, %Q1, #0; rsc %R0, %R1, #0 (ARM)
4694 ; negs %Q0, %Q1 ; sbc %R0, %R1, %R1, lsl #1 (Thumb-2)
ba6a3b2f 4695 "&& reload_completed"
4696 [(parallel [(set (reg:CC CC_REGNUM)
4697 (compare:CC (const_int 0) (match_dup 1)))
4698 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 1)))])
4699 (set (match_dup 2) (minus:SI (minus:SI (const_int 0) (match_dup 3))
4700 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
4701 {
4702 operands[2] = gen_highpart (SImode, operands[0]);
4703 operands[0] = gen_lowpart (SImode, operands[0]);
4704 operands[3] = gen_highpart (SImode, operands[1]);
4705 operands[1] = gen_lowpart (SImode, operands[1]);
4706 }
cffb2a26 4707 [(set_attr "conds" "clob")
1b7da4ac 4708 (set_attr "length" "8")
4709 (set_attr "type" "multiple")]
cffb2a26 4710)
b11cae9e 4711
f6c98a9a 4712(define_insn "*negsi2_carryin_compare"
4713 [(set (reg:CC CC_REGNUM)
4714 (compare:CC (const_int 0)
4715 (match_operand:SI 1 "s_register_operand" "r")))
4716 (set (match_operand:SI 0 "s_register_operand" "=r")
4717 (minus:SI (minus:SI (const_int 0)
4718 (match_dup 1))
4719 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
4720 "TARGET_ARM"
4721 "rscs\\t%0, %1, #0"
4722 [(set_attr "conds" "set")
4723 (set_attr "type" "alus_imm")]
4724)
4725
cffb2a26 4726(define_expand "negsi2"
4727 [(set (match_operand:SI 0 "s_register_operand" "")
4728 (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
4729 "TARGET_EITHER"
b11cae9e 4730 ""
cffb2a26 4731)
4732
4733(define_insn "*arm_negsi2"
d952d547 4734 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4735 (neg:SI (match_operand:SI 1 "s_register_operand" "l,r")))]
25f905c2 4736 "TARGET_32BIT"
cffb2a26 4737 "rsb%?\\t%0, %1, #0"
d952d547 4738 [(set_attr "predicable" "yes")
4739 (set_attr "predicable_short_it" "yes,no")
4740 (set_attr "arch" "t2,*")
1b7da4ac 4741 (set_attr "length" "4")
112eda6f 4742 (set_attr "type" "alu_sreg")]
cffb2a26 4743)
4744
604f3a0a 4745(define_expand "negsf2"
4746 [(set (match_operand:SF 0 "s_register_operand" "")
4747 (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
d7216193 4748 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 4749 ""
4750)
4751
4752(define_expand "negdf2"
4753 [(set (match_operand:DF 0 "s_register_operand" "")
4754 (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
994606f8 4755 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
604f3a0a 4756 "")
4757
7eaf2be0 4758(define_insn_and_split "*zextendsidi_negsi"
4759 [(set (match_operand:DI 0 "s_register_operand" "=r")
4760 (zero_extend:DI (neg:SI (match_operand:SI 1 "s_register_operand" "r"))))]
4761 "TARGET_32BIT"
4762 "#"
4763 ""
4764 [(set (match_dup 2)
4765 (neg:SI (match_dup 1)))
4766 (set (match_dup 3)
4767 (const_int 0))]
4768 {
4769 operands[2] = gen_lowpart (SImode, operands[0]);
4770 operands[3] = gen_highpart (SImode, operands[0]);
4771 }
4772 [(set_attr "length" "8")
4773 (set_attr "type" "multiple")]
4774)
4775
83e2b922 4776;; Negate an extended 32-bit value.
4777(define_insn_and_split "*negdi_extendsidi"
61fa8ff2 4778 [(set (match_operand:DI 0 "s_register_operand" "=l,r")
4779 (neg:DI (sign_extend:DI
4780 (match_operand:SI 1 "s_register_operand" "l,r"))))
83e2b922 4781 (clobber (reg:CC CC_REGNUM))]
4782 "TARGET_32BIT"
61fa8ff2 4783 "#"
83e2b922 4784 "&& reload_completed"
4785 [(const_int 0)]
4786 {
61fa8ff2 4787 rtx low = gen_lowpart (SImode, operands[0]);
4788 rtx high = gen_highpart (SImode, operands[0]);
4789
4790 if (reg_overlap_mentioned_p (low, operands[1]))
4791 {
4792 /* Input overlaps the low word of the output. Use:
4793 asr Rhi, Rin, #31
4794 rsbs Rlo, Rin, #0
4795 rsc Rhi, Rhi, #0 (thumb2: sbc Rhi, Rhi, Rhi, lsl #1). */
4796 rtx cc_reg = gen_rtx_REG (CC_Cmode, CC_REGNUM);
4797
d1f9b275 4798 emit_insn (gen_rtx_SET (high,
61fa8ff2 4799 gen_rtx_ASHIFTRT (SImode, operands[1],
4800 GEN_INT (31))));
4801
4802 emit_insn (gen_subsi3_compare (low, const0_rtx, operands[1]));
4803 if (TARGET_ARM)
d1f9b275 4804 emit_insn (gen_rtx_SET (high,
61fa8ff2 4805 gen_rtx_MINUS (SImode,
4806 gen_rtx_MINUS (SImode,
4807 const0_rtx,
4808 high),
4809 gen_rtx_LTU (SImode,
4810 cc_reg,
4811 const0_rtx))));
4812 else
4813 {
4814 rtx two_x = gen_rtx_ASHIFT (SImode, high, GEN_INT (1));
d1f9b275 4815 emit_insn (gen_rtx_SET (high,
61fa8ff2 4816 gen_rtx_MINUS (SImode,
4817 gen_rtx_MINUS (SImode,
4818 high,
4819 two_x),
4820 gen_rtx_LTU (SImode,
4821 cc_reg,
4822 const0_rtx))));
4823 }
4824 }
4825 else
4826 {
4827 /* No overlap, or overlap on high word. Use:
4828 rsb Rlo, Rin, #0
4829 bic Rhi, Rlo, Rin
4830 asr Rhi, Rhi, #31
4831 Flags not needed for this sequence. */
d1f9b275 4832 emit_insn (gen_rtx_SET (low, gen_rtx_NEG (SImode, operands[1])));
4833 emit_insn (gen_rtx_SET (high,
61fa8ff2 4834 gen_rtx_AND (SImode,
4835 gen_rtx_NOT (SImode, operands[1]),
4836 low)));
d1f9b275 4837 emit_insn (gen_rtx_SET (high,
61fa8ff2 4838 gen_rtx_ASHIFTRT (SImode, high,
4839 GEN_INT (31))));
4840 }
4841 DONE;
83e2b922 4842 }
61fa8ff2 4843 [(set_attr "length" "12")
4844 (set_attr "arch" "t2,*")
1b7da4ac 4845 (set_attr "type" "multiple")]
83e2b922 4846)
4847
4848(define_insn_and_split "*negdi_zero_extendsidi"
4849 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
4850 (neg:DI (zero_extend:DI (match_operand:SI 1 "s_register_operand" "0,r"))))
4851 (clobber (reg:CC CC_REGNUM))]
4852 "TARGET_32BIT"
4853 "#" ; "rsbs\\t%Q0, %1, #0\;sbc\\t%R0,%R0,%R0"
4854 ;; Don't care what register is input to sbc,
47ae02b7 4855 ;; since we just need to propagate the carry.
83e2b922 4856 "&& reload_completed"
4857 [(parallel [(set (reg:CC CC_REGNUM)
4858 (compare:CC (const_int 0) (match_dup 1)))
4859 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 1)))])
4860 (set (match_dup 2) (minus:SI (minus:SI (match_dup 2) (match_dup 2))
4861 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
4862 {
4863 operands[2] = gen_highpart (SImode, operands[0]);
4864 operands[0] = gen_lowpart (SImode, operands[0]);
4865 }
4866 [(set_attr "conds" "clob")
1b7da4ac 4867 (set_attr "length" "8")
4868 (set_attr "type" "multiple")] ;; length in thumb is 4
83e2b922 4869)
4870
9c08d1fa 4871;; abssi2 doesn't really clobber the condition codes if a different register
4872;; is being set. To keep things simple, assume during rtl manipulations that
4873;; it does, but tell the final scan operator the truth. Similarly for
4874;; (neg (abs...))
4875
604f3a0a 4876(define_expand "abssi2"
4877 [(parallel
4878 [(set (match_operand:SI 0 "s_register_operand" "")
4879 (abs:SI (match_operand:SI 1 "s_register_operand" "")))
ba156559 4880 (clobber (match_dup 2))])]
4881 "TARGET_EITHER"
4882 "
25f905c2 4883 if (TARGET_THUMB1)
ba156559 4884 operands[2] = gen_rtx_SCRATCH (SImode);
4885 else
4886 operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
4887")
604f3a0a 4888
ba6a3b2f 4889(define_insn_and_split "*arm_abssi2"
ba156559 4890 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
9c08d1fa 4891 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
bd5b4116 4892 (clobber (reg:CC CC_REGNUM))]
cffb2a26 4893 "TARGET_ARM"
ba6a3b2f 4894 "#"
4895 "&& reload_completed"
4896 [(const_int 0)]
4897 {
4898 /* if (which_alternative == 0) */
4899 if (REGNO(operands[0]) == REGNO(operands[1]))
4900 {
4901 /* Emit the pattern:
4902 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
4903 [(set (reg:CC CC_REGNUM)
4904 (compare:CC (match_dup 0) (const_int 0)))
4905 (cond_exec (lt:CC (reg:CC CC_REGNUM) (const_int 0))
4906 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 1))))]
4907 */
d1f9b275 4908 emit_insn (gen_rtx_SET (gen_rtx_REG (CCmode, CC_REGNUM),
ba6a3b2f 4909 gen_rtx_COMPARE (CCmode, operands[0], const0_rtx)));
4910 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
4911 (gen_rtx_LT (SImode,
4912 gen_rtx_REG (CCmode, CC_REGNUM),
4913 const0_rtx)),
d1f9b275 4914 (gen_rtx_SET (operands[0],
ba6a3b2f 4915 (gen_rtx_MINUS (SImode,
4916 const0_rtx,
4917 operands[1]))))));
4918 DONE;
4919 }
4920 else
4921 {
4922 /* Emit the pattern:
4923 alt1: eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31
4924 [(set (match_dup 0)
4925 (xor:SI (match_dup 1)
4926 (ashiftrt:SI (match_dup 1) (const_int 31))))
4927 (set (match_dup 0)
4928 (minus:SI (match_dup 0)
4929 (ashiftrt:SI (match_dup 1) (const_int 31))))]
4930 */
d1f9b275 4931 emit_insn (gen_rtx_SET (operands[0],
ba6a3b2f 4932 gen_rtx_XOR (SImode,
4933 gen_rtx_ASHIFTRT (SImode,
4934 operands[1],
4935 GEN_INT (31)),
4936 operands[1])));
d1f9b275 4937 emit_insn (gen_rtx_SET (operands[0],
ba6a3b2f 4938 gen_rtx_MINUS (SImode,
4939 operands[0],
4940 gen_rtx_ASHIFTRT (SImode,
4941 operands[1],
4942 GEN_INT (31)))));
4943 DONE;
4944 }
4945 }
cffb2a26 4946 [(set_attr "conds" "clob,*")
331beb1a 4947 (set_attr "shift" "1")
2ad08b65 4948 (set_attr "predicable" "no, yes")
1b7da4ac 4949 (set_attr "length" "8")
4950 (set_attr "type" "multiple")]
cffb2a26 4951)
9c08d1fa 4952
ba6a3b2f 4953(define_insn_and_split "*arm_neg_abssi2"
9c08d1fa 4954 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
4955 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
bd5b4116 4956 (clobber (reg:CC CC_REGNUM))]
cffb2a26 4957 "TARGET_ARM"
ba6a3b2f 4958 "#"
4959 "&& reload_completed"
4960 [(const_int 0)]
4961 {
4962 /* if (which_alternative == 0) */
4963 if (REGNO (operands[0]) == REGNO (operands[1]))
4964 {
4965 /* Emit the pattern:
4966 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
4967 */
d1f9b275 4968 emit_insn (gen_rtx_SET (gen_rtx_REG (CCmode, CC_REGNUM),
ba6a3b2f 4969 gen_rtx_COMPARE (CCmode, operands[0], const0_rtx)));
4970 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
4971 gen_rtx_GT (SImode,
4972 gen_rtx_REG (CCmode, CC_REGNUM),
4973 const0_rtx),
d1f9b275 4974 gen_rtx_SET (operands[0],
ba6a3b2f 4975 (gen_rtx_MINUS (SImode,
4976 const0_rtx,
4977 operands[1])))));
4978 }
4979 else
4980 {
4981 /* Emit the pattern:
4982 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31
4983 */
d1f9b275 4984 emit_insn (gen_rtx_SET (operands[0],
ba6a3b2f 4985 gen_rtx_XOR (SImode,
4986 gen_rtx_ASHIFTRT (SImode,
4987 operands[1],
4988 GEN_INT (31)),
4989 operands[1])));
d1f9b275 4990 emit_insn (gen_rtx_SET (operands[0],
ba6a3b2f 4991 gen_rtx_MINUS (SImode,
4992 gen_rtx_ASHIFTRT (SImode,
4993 operands[1],
4994 GEN_INT (31)),
4995 operands[0])));
4996 }
4997 DONE;
4998 }
cffb2a26 4999 [(set_attr "conds" "clob,*")
331beb1a 5000 (set_attr "shift" "1")
2ad08b65 5001 (set_attr "predicable" "no, yes")
1b7da4ac 5002 (set_attr "length" "8")
5003 (set_attr "type" "multiple")]
cffb2a26 5004)
b11cae9e 5005
604f3a0a 5006(define_expand "abssf2"
5007 [(set (match_operand:SF 0 "s_register_operand" "")
5008 (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
25f905c2 5009 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 5010 "")
5011
604f3a0a 5012(define_expand "absdf2"
5013 [(set (match_operand:DF 0 "s_register_operand" "")
5014 (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 5015 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 5016 "")
5017
7db9af5d 5018(define_expand "sqrtsf2"
5019 [(set (match_operand:SF 0 "s_register_operand" "")
5020 (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
d7216193 5021 "TARGET_32BIT && TARGET_HARD_FLOAT"
7db9af5d 5022 "")
9c08d1fa 5023
7db9af5d 5024(define_expand "sqrtdf2"
5025 [(set (match_operand:DF 0 "s_register_operand" "")
5026 (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
994606f8 5027 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
7db9af5d 5028 "")
9c08d1fa 5029
a0f94409 5030(define_insn_and_split "one_cmpldi2"
10efb95f 5031 [(set (match_operand:DI 0 "s_register_operand" "=w,&r,&r,?w")
5032 (not:DI (match_operand:DI 1 "s_register_operand" " w, 0, r, w")))]
25f905c2 5033 "TARGET_32BIT"
10efb95f 5034 "@
5035 vmvn\t%P0, %P1
5036 #
5037 #
5038 vmvn\t%P0, %P1"
5039 "TARGET_32BIT && reload_completed
5040 && arm_general_register_operand (operands[0], DImode)"
a0f94409 5041 [(set (match_dup 0) (not:SI (match_dup 1)))
5042 (set (match_dup 2) (not:SI (match_dup 3)))]
5043 "
5044 {
5045 operands[2] = gen_highpart (SImode, operands[0]);
5046 operands[0] = gen_lowpart (SImode, operands[0]);
5047 operands[3] = gen_highpart (SImode, operands[1]);
5048 operands[1] = gen_lowpart (SImode, operands[1]);
5049 }"
10efb95f 5050 [(set_attr "length" "*,8,8,*")
5051 (set_attr "predicable" "no,yes,yes,no")
32093010 5052 (set_attr "type" "neon_move,multiple,multiple,neon_move")
b6779ddc 5053 (set_attr "arch" "neon_for_64bits,*,*,avoid_neon_for_64bits")]
cffb2a26 5054)
b11cae9e 5055
cffb2a26 5056(define_expand "one_cmplsi2"
5057 [(set (match_operand:SI 0 "s_register_operand" "")
5058 (not:SI (match_operand:SI 1 "s_register_operand" "")))]
5059 "TARGET_EITHER"
b11cae9e 5060 ""
cffb2a26 5061)
5062
5063(define_insn "*arm_one_cmplsi2"
d952d547 5064 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
5065 (not:SI (match_operand:SI 1 "s_register_operand" "l,r")))]
25f905c2 5066 "TARGET_32BIT"
cffb2a26 5067 "mvn%?\\t%0, %1"
d2a518d1 5068 [(set_attr "predicable" "yes")
d952d547 5069 (set_attr "predicable_short_it" "yes,no")
5070 (set_attr "arch" "t2,*")
5071 (set_attr "length" "4")
1aed5204 5072 (set_attr "type" "mvn_reg")]
cffb2a26 5073)
5074
f7fbdd4a 5075(define_insn "*notsi_compare0"
bd5b4116 5076 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 5077 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5078 (const_int 0)))
5079 (set (match_operand:SI 0 "s_register_operand" "=r")
5080 (not:SI (match_dup 1)))]
25f905c2 5081 "TARGET_32BIT"
3ef90e77 5082 "mvns%?\\t%0, %1"
d2a518d1 5083 [(set_attr "conds" "set")
1aed5204 5084 (set_attr "type" "mvn_reg")]
cffb2a26 5085)
9c08d1fa 5086
f7fbdd4a 5087(define_insn "*notsi_compare0_scratch"
bd5b4116 5088 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 5089 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5090 (const_int 0)))
5091 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 5092 "TARGET_32BIT"
3ef90e77 5093 "mvns%?\\t%0, %1"
d2a518d1 5094 [(set_attr "conds" "set")
1aed5204 5095 (set_attr "type" "mvn_reg")]
cffb2a26 5096)
b11cae9e 5097\f
5098;; Fixed <--> Floating conversion insns
5099
9b8516be 5100(define_expand "floatsihf2"
5101 [(set (match_operand:HF 0 "general_operand" "")
5102 (float:HF (match_operand:SI 1 "general_operand" "")))]
5103 "TARGET_EITHER"
5104 "
5105 {
5106 rtx op1 = gen_reg_rtx (SFmode);
5107 expand_float (op1, operands[1], 0);
5108 op1 = convert_to_mode (HFmode, op1, 0);
5109 emit_move_insn (operands[0], op1);
5110 DONE;
5111 }"
5112)
5113
5114(define_expand "floatdihf2"
5115 [(set (match_operand:HF 0 "general_operand" "")
5116 (float:HF (match_operand:DI 1 "general_operand" "")))]
5117 "TARGET_EITHER"
5118 "
5119 {
5120 rtx op1 = gen_reg_rtx (SFmode);
5121 expand_float (op1, operands[1], 0);
5122 op1 = convert_to_mode (HFmode, op1, 0);
5123 emit_move_insn (operands[0], op1);
5124 DONE;
5125 }"
5126)
5127
604f3a0a 5128(define_expand "floatsisf2"
5129 [(set (match_operand:SF 0 "s_register_operand" "")
5130 (float:SF (match_operand:SI 1 "s_register_operand" "")))]
25f905c2 5131 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 5132 "
604f3a0a 5133")
5134
604f3a0a 5135(define_expand "floatsidf2"
5136 [(set (match_operand:DF 0 "s_register_operand" "")
5137 (float:DF (match_operand:SI 1 "s_register_operand" "")))]
a50d7267 5138 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 5139 "
604f3a0a 5140")
5141
9b8516be 5142(define_expand "fix_trunchfsi2"
5143 [(set (match_operand:SI 0 "general_operand" "")
5144 (fix:SI (fix:HF (match_operand:HF 1 "general_operand" ""))))]
5145 "TARGET_EITHER"
5146 "
5147 {
5148 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
5149 expand_fix (operands[0], op1, 0);
5150 DONE;
5151 }"
5152)
5153
5154(define_expand "fix_trunchfdi2"
5155 [(set (match_operand:DI 0 "general_operand" "")
5156 (fix:DI (fix:HF (match_operand:HF 1 "general_operand" ""))))]
5157 "TARGET_EITHER"
5158 "
5159 {
5160 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
5161 expand_fix (operands[0], op1, 0);
5162 DONE;
5163 }"
5164)
5165
604f3a0a 5166(define_expand "fix_truncsfsi2"
5167 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 5168 (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" ""))))]
25f905c2 5169 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 5170 "
604f3a0a 5171")
5172
604f3a0a 5173(define_expand "fix_truncdfsi2"
5174 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 5175 (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" ""))))]
a50d7267 5176 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 5177 "
604f3a0a 5178")
5179
f544c6d2 5180;; Truncation insns
b11cae9e 5181
604f3a0a 5182(define_expand "truncdfsf2"
5183 [(set (match_operand:SF 0 "s_register_operand" "")
5184 (float_truncate:SF
5185 (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 5186 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 5187 ""
5188)
9b8516be 5189
539b44ee 5190;; DFmode to HFmode conversions on targets without a single-step hardware
5191;; instruction for it would have to go through SFmode. This is dangerous
5192;; as it introduces double rounding.
5193;;
5194;; Disable this pattern unless we are in an unsafe math mode, or we have
5195;; a single-step instruction.
5196
9b8516be 5197(define_expand "truncdfhf2"
539b44ee 5198 [(set (match_operand:HF 0 "s_register_operand" "")
9b8516be 5199 (float_truncate:HF
539b44ee 5200 (match_operand:DF 1 "s_register_operand" "")))]
5201 "(TARGET_EITHER && flag_unsafe_math_optimizations)
5202 || (TARGET_32BIT && TARGET_FP16_TO_DOUBLE)"
5203{
5204 /* We don't have a direct instruction for this, so we must be in
5205 an unsafe math mode, and going via SFmode. */
5206
5207 if (!(TARGET_32BIT && TARGET_FP16_TO_DOUBLE))
5208 {
5209 rtx op1;
5210 op1 = convert_to_mode (SFmode, operands[1], 0);
5211 op1 = convert_to_mode (HFmode, op1, 0);
5212 emit_move_insn (operands[0], op1);
5213 DONE;
5214 }
5215 /* Otherwise, we will pick this up as a single instruction with
5216 no intermediary rounding. */
5217}
9b8516be 5218)
b11cae9e 5219\f
9c08d1fa 5220;; Zero and sign extension instructions.
b11cae9e 5221
848e66ac 5222(define_insn "zero_extend<mode>di2"
6aa689e8 5223 [(set (match_operand:DI 0 "s_register_operand" "=w,r,?r,w")
6d97728e 5224 (zero_extend:DI (match_operand:QHSI 1 "<qhs_zextenddi_op>"
5225 "<qhs_zextenddi_cstr>")))]
848e66ac 5226 "TARGET_32BIT <qhs_zextenddi_cond>"
5227 "#"
6aa689e8 5228 [(set_attr "length" "8,4,8,8")
b6779ddc 5229 (set_attr "arch" "neon_for_64bits,*,*,avoid_neon_for_64bits")
848e66ac 5230 (set_attr "ce_count" "2")
efbb5e19 5231 (set_attr "predicable" "yes")
5232 (set_attr "type" "multiple,mov_reg,multiple,multiple")]
25f905c2 5233)
5234
848e66ac 5235(define_insn "extend<mode>di2"
6aa689e8 5236 [(set (match_operand:DI 0 "s_register_operand" "=w,r,?r,?r,w")
63d204a8 5237 (sign_extend:DI (match_operand:QHSI 1 "<qhs_extenddi_op>"
5238 "<qhs_extenddi_cstr>")))]
848e66ac 5239 "TARGET_32BIT <qhs_sextenddi_cond>"
5240 "#"
6aa689e8 5241 [(set_attr "length" "8,4,8,8,8")
848e66ac 5242 (set_attr "ce_count" "2")
5243 (set_attr "shift" "1")
8012d2c2 5244 (set_attr "predicable" "yes")
1b7da4ac 5245 (set_attr "arch" "neon_for_64bits,*,a,t,avoid_neon_for_64bits")
5246 (set_attr "type" "multiple,mov_reg,multiple,multiple,multiple")]
0d66636f 5247)
9c08d1fa 5248
848e66ac 5249;; Splits for all extensions to DImode
5250(define_split
5251 [(set (match_operand:DI 0 "s_register_operand" "")
5252 (zero_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
6aa689e8 5253 "TARGET_32BIT && reload_completed && !IS_VFP_REGNUM (REGNO (operands[0]))"
848e66ac 5254 [(set (match_dup 0) (match_dup 1))]
5255{
848e66ac 5256 rtx lo_part = gen_lowpart (SImode, operands[0]);
3754d046 5257 machine_mode src_mode = GET_MODE (operands[1]);
848e66ac 5258
5259 if (REG_P (operands[0])
5260 && !reg_overlap_mentioned_p (operands[0], operands[1]))
5261 emit_clobber (operands[0]);
5262 if (!REG_P (lo_part) || src_mode != SImode
5263 || !rtx_equal_p (lo_part, operands[1]))
5264 {
5265 if (src_mode == SImode)
5266 emit_move_insn (lo_part, operands[1]);
5267 else
d1f9b275 5268 emit_insn (gen_rtx_SET (lo_part,
848e66ac 5269 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
5270 operands[1] = lo_part;
5271 }
5272 operands[0] = gen_highpart (SImode, operands[0]);
5273 operands[1] = const0_rtx;
5274})
9c08d1fa 5275
848e66ac 5276(define_split
25f905c2 5277 [(set (match_operand:DI 0 "s_register_operand" "")
848e66ac 5278 (sign_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
6aa689e8 5279 "TARGET_32BIT && reload_completed && !IS_VFP_REGNUM (REGNO (operands[0]))"
848e66ac 5280 [(set (match_dup 0) (ashiftrt:SI (match_dup 1) (const_int 31)))]
5281{
5282 rtx lo_part = gen_lowpart (SImode, operands[0]);
3754d046 5283 machine_mode src_mode = GET_MODE (operands[1]);
25f905c2 5284
848e66ac 5285 if (REG_P (operands[0])
5286 && !reg_overlap_mentioned_p (operands[0], operands[1]))
5287 emit_clobber (operands[0]);
5288
5289 if (!REG_P (lo_part) || src_mode != SImode
5290 || !rtx_equal_p (lo_part, operands[1]))
5291 {
5292 if (src_mode == SImode)
5293 emit_move_insn (lo_part, operands[1]);
5294 else
d1f9b275 5295 emit_insn (gen_rtx_SET (lo_part,
848e66ac 5296 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
5297 operands[1] = lo_part;
5298 }
5299 operands[0] = gen_highpart (SImode, operands[0]);
5300})
9c08d1fa 5301
5302(define_expand "zero_extendhisi2"
ef51b8e1 5303 [(set (match_operand:SI 0 "s_register_operand" "")
5304 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
cffb2a26 5305 "TARGET_EITHER"
ef51b8e1 5306{
5307 if (TARGET_ARM && !arm_arch4 && MEM_P (operands[1]))
f7fbdd4a 5308 {
ef51b8e1 5309 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
5310 DONE;
25f7a26e 5311 }
ef51b8e1 5312 if (!arm_arch6 && !MEM_P (operands[1]))
5313 {
5314 rtx t = gen_lowpart (SImode, operands[1]);
5315 rtx tmp = gen_reg_rtx (SImode);
5316 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
5317 emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (16)));
5318 DONE;
5319 }
5320})
9c08d1fa 5321
ef51b8e1 5322(define_split
b146458f 5323 [(set (match_operand:SI 0 "s_register_operand" "")
5324 (zero_extend:SI (match_operand:HI 1 "s_register_operand" "")))]
ef51b8e1 5325 "!TARGET_THUMB2 && !arm_arch6"
5326 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
5327 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 16)))]
5328{
5329 operands[2] = gen_lowpart (SImode, operands[1]);
5330})
5331
cffb2a26 5332(define_insn "*arm_zero_extendhisi2"
ef51b8e1 5333 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5334 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 5335 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 5336 "@
5337 #
3ef90e77 5338 ldrh%?\\t%0, %1"
d82e788e 5339 [(set_attr "type" "alu_shift_reg,load_byte")
848e66ac 5340 (set_attr "predicable" "yes")]
cffb2a26 5341)
f7fbdd4a 5342
a2cd141b 5343(define_insn "*arm_zero_extendhisi2_v6"
5344 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
e3f4ccee 5345 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,Uh")))]
a2cd141b 5346 "TARGET_ARM && arm_arch6"
5347 "@
5348 uxth%?\\t%0, %1
3ef90e77 5349 ldrh%?\\t%0, %1"
65f68e55 5350 [(set_attr "predicable" "yes")
6b6abc9c 5351 (set_attr "type" "extend,load_byte")]
a2cd141b 5352)
5353
5354(define_insn "*arm_zero_extendhisi2addsi"
5355 [(set (match_operand:SI 0 "s_register_operand" "=r")
5356 (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
5357 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 5358 "TARGET_INT_SIMD"
a2cd141b 5359 "uxtah%?\\t%0, %2, %1"
d82e788e 5360 [(set_attr "type" "alu_shift_reg")
d952d547 5361 (set_attr "predicable" "yes")
5362 (set_attr "predicable_short_it" "no")]
a2cd141b 5363)
5364
87b22bf7 5365(define_expand "zero_extendqisi2"
cffb2a26 5366 [(set (match_operand:SI 0 "s_register_operand" "")
5367 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
5368 "TARGET_EITHER"
ef51b8e1 5369{
0438d37f 5370 if (TARGET_ARM && !arm_arch6 && !MEM_P (operands[1]))
87b22bf7 5371 {
ef51b8e1 5372 emit_insn (gen_andsi3 (operands[0],
5373 gen_lowpart (SImode, operands[1]),
5374 GEN_INT (255)));
5375 DONE;
5376 }
5377 if (!arm_arch6 && !MEM_P (operands[1]))
5378 {
5379 rtx t = gen_lowpart (SImode, operands[1]);
5380 rtx tmp = gen_reg_rtx (SImode);
5381 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
5382 emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (24)));
5383 DONE;
5384 }
5385})
cffb2a26 5386
ef51b8e1 5387(define_split
b146458f 5388 [(set (match_operand:SI 0 "s_register_operand" "")
5389 (zero_extend:SI (match_operand:QI 1 "s_register_operand" "")))]
ef51b8e1 5390 "!arm_arch6"
5391 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
5392 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 24)))]
5393{
5394 operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
5395 if (TARGET_ARM)
5396 {
5397 emit_insn (gen_andsi3 (operands[0], operands[2], GEN_INT (255)));
87b22bf7 5398 DONE;
5399 }
ef51b8e1 5400})
9c08d1fa 5401
cffb2a26 5402(define_insn "*arm_zero_extendqisi2"
ef51b8e1 5403 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5404 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 5405 "TARGET_ARM && !arm_arch6"
ef51b8e1 5406 "@
5407 #
3ef90e77 5408 ldrb%?\\t%0, %1\\t%@ zero_extendqisi2"
ef51b8e1 5409 [(set_attr "length" "8,4")
d82e788e 5410 (set_attr "type" "alu_shift_reg,load_byte")
848e66ac 5411 (set_attr "predicable" "yes")]
cffb2a26 5412)
87b22bf7 5413
a2cd141b 5414(define_insn "*arm_zero_extendqisi2_v6"
5415 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
e3f4ccee 5416 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,Uh")))]
a2cd141b 5417 "TARGET_ARM && arm_arch6"
5418 "@
3ef90e77 5419 uxtb%?\\t%0, %1
5420 ldrb%?\\t%0, %1\\t%@ zero_extendqisi2"
6b6abc9c 5421 [(set_attr "type" "extend,load_byte")
848e66ac 5422 (set_attr "predicable" "yes")]
a2cd141b 5423)
5424
5425(define_insn "*arm_zero_extendqisi2addsi"
5426 [(set (match_operand:SI 0 "s_register_operand" "=r")
5427 (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
5428 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 5429 "TARGET_INT_SIMD"
a2cd141b 5430 "uxtab%?\\t%0, %2, %1"
5431 [(set_attr "predicable" "yes")
d952d547 5432 (set_attr "predicable_short_it" "no")
d82e788e 5433 (set_attr "type" "alu_shift_reg")]
a2cd141b 5434)
5435
87b22bf7 5436(define_split
5437 [(set (match_operand:SI 0 "s_register_operand" "")
5438 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
5439 (clobber (match_operand:SI 2 "s_register_operand" ""))]
0438d37f 5440 "TARGET_32BIT && (!MEM_P (operands[1])) && ! BYTES_BIG_ENDIAN"
87b22bf7 5441 [(set (match_dup 2) (match_dup 1))
5442 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
cffb2a26 5443 ""
5444)
9c08d1fa 5445
8a4d25d6 5446(define_split
5447 [(set (match_operand:SI 0 "s_register_operand" "")
5448 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 3)))
5449 (clobber (match_operand:SI 2 "s_register_operand" ""))]
0438d37f 5450 "TARGET_32BIT && (!MEM_P (operands[1])) && BYTES_BIG_ENDIAN"
8a4d25d6 5451 [(set (match_dup 2) (match_dup 1))
5452 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
5453 ""
5454)
5455
1c274529 5456
5457(define_split
5458 [(set (match_operand:SI 0 "s_register_operand" "")
9b23f0a7 5459 (IOR_XOR:SI (and:SI (ashift:SI
1c274529 5460 (match_operand:SI 1 "s_register_operand" "")
5461 (match_operand:SI 2 "const_int_operand" ""))
5462 (match_operand:SI 3 "const_int_operand" ""))
5463 (zero_extend:SI
5464 (match_operator 5 "subreg_lowpart_operator"
5465 [(match_operand:SI 4 "s_register_operand" "")]))))]
5466 "TARGET_32BIT
8c4e8755 5467 && (UINTVAL (operands[3])
1c274529 5468 == (GET_MODE_MASK (GET_MODE (operands[5]))
5469 & (GET_MODE_MASK (GET_MODE (operands[5]))
5470 << (INTVAL (operands[2])))))"
9b23f0a7 5471 [(set (match_dup 0) (IOR_XOR:SI (ashift:SI (match_dup 1) (match_dup 2))
1c274529 5472 (match_dup 4)))
5473 (set (match_dup 0) (zero_extend:SI (match_dup 5)))]
5474 "operands[5] = gen_lowpart (GET_MODE (operands[5]), operands[0]);"
5475)
5476
f7fbdd4a 5477(define_insn "*compareqi_eq0"
bd5b4116 5478 [(set (reg:CC_Z CC_REGNUM)
206ee9a2 5479 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
87b22bf7 5480 (const_int 0)))]
25f905c2 5481 "TARGET_32BIT"
596e5e8f 5482 "tst%?\\t%0, #255"
5483 [(set_attr "conds" "set")
d952d547 5484 (set_attr "predicable" "yes")
1b7da4ac 5485 (set_attr "predicable_short_it" "no")
5486 (set_attr "type" "logic_imm")]
cffb2a26 5487)
b11cae9e 5488
b11cae9e 5489(define_expand "extendhisi2"
ef51b8e1 5490 [(set (match_operand:SI 0 "s_register_operand" "")
5491 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
cffb2a26 5492 "TARGET_EITHER"
ef51b8e1 5493{
5494 if (TARGET_THUMB1)
5495 {
5496 emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1]));
5497 DONE;
5498 }
5499 if (MEM_P (operands[1]) && TARGET_ARM && !arm_arch4)
5500 {
5501 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
5502 DONE;
5503 }
ed29c566 5504
ef51b8e1 5505 if (!arm_arch6 && !MEM_P (operands[1]))
5506 {
5507 rtx t = gen_lowpart (SImode, operands[1]);
5508 rtx tmp = gen_reg_rtx (SImode);
5509 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
5510 emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (16)));
5511 DONE;
5512 }
5513})
cffb2a26 5514
ef51b8e1 5515(define_split
5516 [(parallel
5517 [(set (match_operand:SI 0 "register_operand" "")
5518 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))
5519 (clobber (match_scratch:SI 2 ""))])]
5520 "!arm_arch6"
5521 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
5522 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
5523{
5524 operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
5525})
25f7a26e 5526
25f905c2 5527;; This pattern will only be used when ldsh is not available
25f7a26e 5528(define_expand "extendhisi2_mem"
eab14235 5529 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 5530 (set (match_dup 3)
eab14235 5531 (zero_extend:SI (match_dup 7)))
25f7a26e 5532 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
5533 (set (match_operand:SI 0 "" "")
5534 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
cffb2a26 5535 "TARGET_ARM"
25f7a26e 5536 "
215b30b3 5537 {
5538 rtx mem1, mem2;
5539 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
5540
788fcce0 5541 mem1 = change_address (operands[1], QImode, addr);
29c05e22 5542 mem2 = change_address (operands[1], QImode,
5543 plus_constant (Pmode, addr, 1));
215b30b3 5544 operands[0] = gen_lowpart (SImode, operands[0]);
5545 operands[1] = mem1;
5546 operands[2] = gen_reg_rtx (SImode);
5547 operands[3] = gen_reg_rtx (SImode);
5548 operands[6] = gen_reg_rtx (SImode);
5549 operands[7] = mem2;
25f7a26e 5550
215b30b3 5551 if (BYTES_BIG_ENDIAN)
5552 {
5553 operands[4] = operands[2];
5554 operands[5] = operands[3];
5555 }
5556 else
5557 {
5558 operands[4] = operands[3];
5559 operands[5] = operands[2];
5560 }
5561 }"
5562)
b11cae9e 5563
ef51b8e1 5564(define_split
5565 [(set (match_operand:SI 0 "register_operand" "")
5566 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
5567 "!arm_arch6"
5568 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
5569 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
5570{
5571 operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
5572})
5573
a2cd141b 5574(define_insn "*arm_extendhisi2"
ef51b8e1 5575 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
e3f4ccee 5576 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,Uh")))]
a2cd141b 5577 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 5578 "@
5579 #
3ef90e77 5580 ldrsh%?\\t%0, %1"
ef51b8e1 5581 [(set_attr "length" "8,4")
d82e788e 5582 (set_attr "type" "alu_shift_reg,load_byte")
e3f4ccee 5583 (set_attr "predicable" "yes")]
cffb2a26 5584)
f7fbdd4a 5585
25f905c2 5586;; ??? Check Thumb-2 pool range
a2cd141b 5587(define_insn "*arm_extendhisi2_v6"
5588 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
e3f4ccee 5589 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,Uh")))]
25f905c2 5590 "TARGET_32BIT && arm_arch6"
a2cd141b 5591 "@
5592 sxth%?\\t%0, %1
3ef90e77 5593 ldrsh%?\\t%0, %1"
6b6abc9c 5594 [(set_attr "type" "extend,load_byte")
a2cd141b 5595 (set_attr "predicable" "yes")
e3f4ccee 5596 (set_attr "predicable_short_it" "no")]
a2cd141b 5597)
5598
5599(define_insn "*arm_extendhisi2addsi"
5600 [(set (match_operand:SI 0 "s_register_operand" "=r")
5601 (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
5602 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 5603 "TARGET_INT_SIMD"
a2cd141b 5604 "sxtah%?\\t%0, %2, %1"
1b7da4ac 5605 [(set_attr "type" "alu_shift_reg")]
a2cd141b 5606)
5607
c8f69309 5608(define_expand "extendqihi2"
5609 [(set (match_dup 2)
bed7d9a5 5610 (ashift:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")
c8f69309 5611 (const_int 24)))
9c08d1fa 5612 (set (match_operand:HI 0 "s_register_operand" "")
c8f69309 5613 (ashiftrt:SI (match_dup 2)
5614 (const_int 24)))]
cffb2a26 5615 "TARGET_ARM"
c8f69309 5616 "
215b30b3 5617 {
0438d37f 5618 if (arm_arch4 && MEM_P (operands[1]))
215b30b3 5619 {
d1f9b275 5620 emit_insn (gen_rtx_SET (operands[0],
215b30b3 5621 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
5622 DONE;
5623 }
5624 if (!s_register_operand (operands[1], QImode))
5625 operands[1] = copy_to_mode_reg (QImode, operands[1]);
5626 operands[0] = gen_lowpart (SImode, operands[0]);
5627 operands[1] = gen_lowpart (SImode, operands[1]);
5628 operands[2] = gen_reg_rtx (SImode);
5629 }"
5630)
f7fbdd4a 5631
25f905c2 5632(define_insn "*arm_extendqihi_insn"
b4e8a300 5633 [(set (match_operand:HI 0 "s_register_operand" "=r")
bed7d9a5 5634 (sign_extend:HI (match_operand:QI 1 "arm_extendqisi_mem_op" "Uq")))]
cffb2a26 5635 "TARGET_ARM && arm_arch4"
3ef90e77 5636 "ldrsb%?\\t%0, %1"
a2cd141b 5637 [(set_attr "type" "load_byte")
e3f4ccee 5638 (set_attr "predicable" "yes")]
cffb2a26 5639)
3fc2009e 5640
b11cae9e 5641(define_expand "extendqisi2"
ef51b8e1 5642 [(set (match_operand:SI 0 "s_register_operand" "")
5643 (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")))]
cffb2a26 5644 "TARGET_EITHER"
ef51b8e1 5645{
5646 if (!arm_arch4 && MEM_P (operands[1]))
5647 operands[1] = copy_to_mode_reg (QImode, operands[1]);
a2cd141b 5648
ef51b8e1 5649 if (!arm_arch6 && !MEM_P (operands[1]))
5650 {
5651 rtx t = gen_lowpart (SImode, operands[1]);
5652 rtx tmp = gen_reg_rtx (SImode);
5653 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
5654 emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (24)));
5655 DONE;
5656 }
5657})
a2cd141b 5658
ef51b8e1 5659(define_split
5660 [(set (match_operand:SI 0 "register_operand" "")
5661 (sign_extend:SI (match_operand:QI 1 "register_operand" "")))]
5662 "!arm_arch6"
5663 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
5664 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))]
5665{
5666 operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
5667})
f7fbdd4a 5668
a2cd141b 5669(define_insn "*arm_extendqisi"
ef51b8e1 5670 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5671 (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
a2cd141b 5672 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 5673 "@
5674 #
3ef90e77 5675 ldrsb%?\\t%0, %1"
ef51b8e1 5676 [(set_attr "length" "8,4")
d82e788e 5677 (set_attr "type" "alu_shift_reg,load_byte")
e3f4ccee 5678 (set_attr "predicable" "yes")]
cffb2a26 5679)
3fc2009e 5680
a2cd141b 5681(define_insn "*arm_extendqisi_v6"
5682 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
bed7d9a5 5683 (sign_extend:SI
5684 (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
a2cd141b 5685 "TARGET_ARM && arm_arch6"
b4e8a300 5686 "@
5687 sxtb%?\\t%0, %1
3ef90e77 5688 ldrsb%?\\t%0, %1"
6b6abc9c 5689 [(set_attr "type" "extend,load_byte")
e3f4ccee 5690 (set_attr "predicable" "yes")]
a2cd141b 5691)
5692
5693(define_insn "*arm_extendqisi2addsi"
5694 [(set (match_operand:SI 0 "s_register_operand" "=r")
5695 (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
5696 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 5697 "TARGET_INT_SIMD"
a2cd141b 5698 "sxtab%?\\t%0, %2, %1"
d82e788e 5699 [(set_attr "type" "alu_shift_reg")
d952d547 5700 (set_attr "predicable" "yes")
5701 (set_attr "predicable_short_it" "no")]
a2cd141b 5702)
5703
caedf871 5704(define_expand "extendsfdf2"
5705 [(set (match_operand:DF 0 "s_register_operand" "")
5706 (float_extend:DF (match_operand:SF 1 "s_register_operand" "")))]
a50d7267 5707 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
caedf871 5708 ""
5709)
9b8516be 5710
539b44ee 5711;; HFmode -> DFmode conversions where we don't have an instruction for it
5712;; must go through SFmode.
5713;;
5714;; This is always safe for an extend.
5715
9b8516be 5716(define_expand "extendhfdf2"
539b44ee 5717 [(set (match_operand:DF 0 "s_register_operand" "")
5718 (float_extend:DF (match_operand:HF 1 "s_register_operand" "")))]
9b8516be 5719 "TARGET_EITHER"
539b44ee 5720{
5721 /* We don't have a direct instruction for this, so go via SFmode. */
5722 if (!(TARGET_32BIT && TARGET_FP16_TO_DOUBLE))
5723 {
5724 rtx op1;
5725 op1 = convert_to_mode (SFmode, operands[1], 0);
5726 op1 = convert_to_mode (DFmode, op1, 0);
5727 emit_insn (gen_movdf (operands[0], op1));
5728 DONE;
5729 }
5730 /* Otherwise, we're done producing RTL and will pick up the correct
5731 pattern to do this with one rounding-step in a single instruction. */
5732}
9b8516be 5733)
b11cae9e 5734\f
5735;; Move insns (including loads and stores)
5736
5737;; XXX Just some ideas about movti.
9c08d1fa 5738;; I don't think these are a good idea on the arm, there just aren't enough
5739;; registers
b11cae9e 5740;;(define_expand "loadti"
9c08d1fa 5741;; [(set (match_operand:TI 0 "s_register_operand" "")
b11cae9e 5742;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
5743;; "" "")
5744
5745;;(define_expand "storeti"
5746;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
9c08d1fa 5747;; (match_operand:TI 1 "s_register_operand" ""))]
b11cae9e 5748;; "" "")
5749
5750;;(define_expand "movti"
5751;; [(set (match_operand:TI 0 "general_operand" "")
5752;; (match_operand:TI 1 "general_operand" ""))]
5753;; ""
5754;; "
5755;;{
5756;; rtx insn;
5757;;
0438d37f 5758;; if (MEM_P (operands[0]) && MEM_P (operands[1]))
b11cae9e 5759;; operands[1] = copy_to_reg (operands[1]);
0438d37f 5760;; if (MEM_P (operands[0]))
b11cae9e 5761;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
0438d37f 5762;; else if (MEM_P (operands[1]))
b11cae9e 5763;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
5764;; else
5765;; FAIL;
5766;;
5767;; emit_insn (insn);
5768;; DONE;
5769;;}")
5770
a2f10574 5771;; Recognize garbage generated above.
b11cae9e 5772
5773;;(define_insn ""
5774;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
5775;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
5776;; ""
5777;; "*
5778;; {
5779;; register mem = (which_alternative < 3);
0d66636f 5780;; register const char *template;
b11cae9e 5781;;
5782;; operands[mem] = XEXP (operands[mem], 0);
5783;; switch (which_alternative)
5784;; {
5785;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
5786;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
5787;; case 2: template = \"ldmia\\t%1, %M0\"; break;
5788;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
5789;; case 4: template = \"stmia\\t%0!, %M1\"; break;
5790;; case 5: template = \"stmia\\t%0, %M1\"; break;
5791;; }
e2348bcb 5792;; output_asm_insn (template, operands);
5793;; return \"\";
b11cae9e 5794;; }")
5795
cffb2a26 5796(define_expand "movdi"
5797 [(set (match_operand:DI 0 "general_operand" "")
5798 (match_operand:DI 1 "general_operand" ""))]
5799 "TARGET_EITHER"
5800 "
e1ba4a27 5801 if (can_create_pseudo_p ())
cffb2a26 5802 {
0438d37f 5803 if (!REG_P (operands[0]))
b2778788 5804 operands[1] = force_reg (DImode, operands[1]);
cffb2a26 5805 }
6b97fdcc 5806 if (REG_P (operands[0]) && REGNO (operands[0]) <= LAST_ARM_REGNUM
4f0e25ca 5807 && !HARD_REGNO_MODE_OK (REGNO (operands[0]), DImode))
5808 {
5809 /* Avoid LDRD's into an odd-numbered register pair in ARM state
5810 when expanding function calls. */
5811 gcc_assert (can_create_pseudo_p ());
5812 if (MEM_P (operands[1]) && MEM_VOLATILE_P (operands[1]))
5813 {
5814 /* Perform load into legal reg pair first, then move. */
5815 rtx reg = gen_reg_rtx (DImode);
5816 emit_insn (gen_movdi (reg, operands[1]));
5817 operands[1] = reg;
5818 }
5819 emit_move_insn (gen_lowpart (SImode, operands[0]),
5820 gen_lowpart (SImode, operands[1]));
5821 emit_move_insn (gen_highpart (SImode, operands[0]),
5822 gen_highpart (SImode, operands[1]));
5823 DONE;
5824 }
6b97fdcc 5825 else if (REG_P (operands[1]) && REGNO (operands[1]) <= LAST_ARM_REGNUM
4f0e25ca 5826 && !HARD_REGNO_MODE_OK (REGNO (operands[1]), DImode))
5827 {
5828 /* Avoid STRD's from an odd-numbered register pair in ARM state
5829 when expanding function prologue. */
5830 gcc_assert (can_create_pseudo_p ());
5831 rtx split_dest = (MEM_P (operands[0]) && MEM_VOLATILE_P (operands[0]))
5832 ? gen_reg_rtx (DImode)
5833 : operands[0];
5834 emit_move_insn (gen_lowpart (SImode, split_dest),
5835 gen_lowpart (SImode, operands[1]));
5836 emit_move_insn (gen_highpart (SImode, split_dest),
5837 gen_highpart (SImode, operands[1]));
5838 if (split_dest != operands[0])
5839 emit_insn (gen_movdi (operands[0], split_dest));
5840 DONE;
5841 }
cffb2a26 5842 "
5843)
b11cae9e 5844
cffb2a26 5845(define_insn "*arm_movdi"
353cf59a 5846 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, q, m")
5847 (match_operand:DI 1 "di_operand" "rDa,Db,Dc,mi,q"))]
cde1623a 5848 "TARGET_32BIT
d7216193 5849 && !(TARGET_HARD_FLOAT)
b2778788 5850 && !TARGET_IWMMXT
5851 && ( register_operand (operands[0], DImode)
5852 || register_operand (operands[1], DImode))"
b11cae9e 5853 "*
d51f92df 5854 switch (which_alternative)
5855 {
5856 case 0:
5857 case 1:
5858 case 2:
5859 return \"#\";
5860 default:
26ff80c0 5861 return output_move_double (operands, true, NULL);
d51f92df 5862 }
cffb2a26 5863 "
359a6e9f 5864 [(set_attr "length" "8,12,16,8,8")
1b7da4ac 5865 (set_attr "type" "multiple,multiple,multiple,load2,store2")
cde1623a 5866 (set_attr "arm_pool_range" "*,*,*,1020,*")
8848d797 5867 (set_attr "arm_neg_pool_range" "*,*,*,1004,*")
42e1de19 5868 (set_attr "thumb2_pool_range" "*,*,*,4094,*")
cde1623a 5869 (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
cffb2a26 5870)
5871
d51f92df 5872(define_split
5873 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
e6dd3afa 5874 (match_operand:ANY64 1 "immediate_operand" ""))]
25f905c2 5875 "TARGET_32BIT
d51f92df 5876 && reload_completed
a869c476 5877 && (arm_disable_literal_pool
5878 || (arm_const_double_inline_cost (operands[1])
5879 <= arm_max_const_double_inline_cost ()))"
d51f92df 5880 [(const_int 0)]
5881 "
5882 arm_split_constant (SET, SImode, curr_insn,
5883 INTVAL (gen_lowpart (SImode, operands[1])),
5884 gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
5885 arm_split_constant (SET, SImode, curr_insn,
5886 INTVAL (gen_highpart_mode (SImode,
5887 GET_MODE (operands[0]),
5888 operands[1])),
5889 gen_highpart (SImode, operands[0]), NULL_RTX, 0);
5890 DONE;
5891 "
5892)
5893
e5ba9289 5894; If optimizing for size, or if we have load delay slots, then
5895; we want to split the constant into two separate operations.
5896; In both cases this may split a trivial part into a single data op
5897; leaving a single complex constant to load. We can also get longer
5898; offsets in a LDR which means we get better chances of sharing the pool
5899; entries. Finally, we can normally do a better job of scheduling
5900; LDR instructions than we can with LDM.
5901; This pattern will only match if the one above did not.
5902(define_split
5903 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
5904 (match_operand:ANY64 1 "const_double_operand" ""))]
5905 "TARGET_ARM && reload_completed
5906 && arm_const_double_by_parts (operands[1])"
5907 [(set (match_dup 0) (match_dup 1))
5908 (set (match_dup 2) (match_dup 3))]
5909 "
5910 operands[2] = gen_highpart (SImode, operands[0]);
5911 operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
5912 operands[1]);
5913 operands[0] = gen_lowpart (SImode, operands[0]);
5914 operands[1] = gen_lowpart (SImode, operands[1]);
5915 "
5916)
5917
d51f92df 5918(define_split
5919 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
5920 (match_operand:ANY64 1 "arm_general_register_operand" ""))]
5921 "TARGET_EITHER && reload_completed"
5922 [(set (match_dup 0) (match_dup 1))
5923 (set (match_dup 2) (match_dup 3))]
5924 "
5925 operands[2] = gen_highpart (SImode, operands[0]);
5926 operands[3] = gen_highpart (SImode, operands[1]);
5927 operands[0] = gen_lowpart (SImode, operands[0]);
5928 operands[1] = gen_lowpart (SImode, operands[1]);
5929
5930 /* Handle a partial overlap. */
5931 if (rtx_equal_p (operands[0], operands[3]))
5932 {
5933 rtx tmp0 = operands[0];
5934 rtx tmp1 = operands[1];
5935
5936 operands[0] = operands[2];
5937 operands[1] = operands[3];
5938 operands[2] = tmp0;
5939 operands[3] = tmp1;
5940 }
5941 "
5942)
5943
a8a3b539 5944;; We can't actually do base+index doubleword loads if the index and
5945;; destination overlap. Split here so that we at least have chance to
5946;; schedule.
5947(define_split
5948 [(set (match_operand:DI 0 "s_register_operand" "")
5949 (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
5950 (match_operand:SI 2 "s_register_operand" ""))))]
5951 "TARGET_LDRD
5952 && reg_overlap_mentioned_p (operands[0], operands[1])
5953 && reg_overlap_mentioned_p (operands[0], operands[2])"
5954 [(set (match_dup 4)
5955 (plus:SI (match_dup 1)
5956 (match_dup 2)))
5957 (set (match_dup 0)
5958 (mem:DI (match_dup 4)))]
5959 "
5960 operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
5961 "
5962)
5963
9c08d1fa 5964(define_expand "movsi"
5965 [(set (match_operand:SI 0 "general_operand" "")
5966 (match_operand:SI 1 "general_operand" ""))]
cffb2a26 5967 "TARGET_EITHER"
9c08d1fa 5968 "
befb0bac 5969 {
e348ff3e 5970 rtx base, offset, tmp;
5971
6e291830 5972 if (TARGET_32BIT || TARGET_HAVE_MOVT)
9c08d1fa 5973 {
674a8f0b 5974 /* Everything except mem = const or mem = mem can be done easily. */
0438d37f 5975 if (MEM_P (operands[0]))
cffb2a26 5976 operands[1] = force_reg (SImode, operands[1]);
a2cd141b 5977 if (arm_general_register_operand (operands[0], SImode)
0438d37f 5978 && CONST_INT_P (operands[1])
cffb2a26 5979 && !(const_ok_for_arm (INTVAL (operands[1]))
5980 || const_ok_for_arm (~INTVAL (operands[1]))))
5981 {
17202aa5 5982 if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[1]), SET))
5983 {
5984 emit_insn (gen_rtx_SET (operands[0], operands[1]));
5985 DONE;
5986 }
5987 else
5988 {
5989 arm_split_constant (SET, SImode, NULL_RTX,
5990 INTVAL (operands[1]), operands[0], NULL_RTX,
5991 optimize && can_create_pseudo_p ());
5992 DONE;
5993 }
cffb2a26 5994 }
5995 }
75612252 5996 else /* Target doesn't have MOVT... */
cffb2a26 5997 {
e1ba4a27 5998 if (can_create_pseudo_p ())
cffb2a26 5999 {
0438d37f 6000 if (!REG_P (operands[0]))
cffb2a26 6001 operands[1] = force_reg (SImode, operands[1]);
6002 }
9c08d1fa 6003 }
f655717d 6004
e348ff3e 6005 if (ARM_OFFSETS_MUST_BE_WITHIN_SECTIONS_P)
6006 {
6007 split_const (operands[1], &base, &offset);
6008 if (GET_CODE (base) == SYMBOL_REF
6009 && !offset_within_block_p (base, INTVAL (offset)))
6010 {
b308ddcf 6011 tmp = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
e348ff3e 6012 emit_move_insn (tmp, base);
6013 emit_insn (gen_addsi3 (operands[0], tmp, offset));
6014 DONE;
6015 }
6016 }
6017
f655717d 6018 /* Recognize the case where operand[1] is a reference to thread-local
6019 data and load its address to a register. */
6020 if (arm_tls_referenced_p (operands[1]))
6021 {
6022 rtx tmp = operands[1];
6023 rtx addend = NULL;
6024
6025 if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
6026 {
6027 addend = XEXP (XEXP (tmp, 0), 1);
6028 tmp = XEXP (XEXP (tmp, 0), 0);
6029 }
6030
6031 gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
6032 gcc_assert (SYMBOL_REF_TLS_MODEL (tmp) != 0);
6033
e1ba4a27 6034 tmp = legitimize_tls_address (tmp,
6035 !can_create_pseudo_p () ? operands[0] : 0);
f655717d 6036 if (addend)
6037 {
6038 tmp = gen_rtx_PLUS (SImode, tmp, addend);
6039 tmp = force_operand (tmp, operands[0]);
6040 }
6041 operands[1] = tmp;
6042 }
6043 else if (flag_pic
6044 && (CONSTANT_P (operands[1])
6045 || symbol_mentioned_p (operands[1])
6046 || label_mentioned_p (operands[1])))
6047 operands[1] = legitimize_pic_address (operands[1], SImode,
e1ba4a27 6048 (!can_create_pseudo_p ()
6049 ? operands[0]
6050 : 0));
befb0bac 6051 }
215b30b3 6052 "
6053)
9c08d1fa 6054
d0e6a121 6055;; The ARM LO_SUM and HIGH are backwards - HIGH sets the low bits, and
6056;; LO_SUM adds in the high bits. Fortunately these are opaque operations
6057;; so this does not matter.
6058(define_insn "*arm_movt"
417e5cc5 6059 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r")
6060 (lo_sum:SI (match_operand:SI 1 "nonimmediate_operand" "0,0")
6061 (match_operand:SI 2 "general_operand" "i,i")))]
60a48e7d 6062 "TARGET_HAVE_MOVT && arm_valid_symbolic_address_p (operands[2])"
417e5cc5 6063 "@
6064 movt%?\t%0, #:upper16:%c2
6065 movt\t%0, #:upper16:%c2"
6066 [(set_attr "arch" "32,v8mb")
6067 (set_attr "predicable" "yes")
d952d547 6068 (set_attr "predicable_short_it" "no")
1b7da4ac 6069 (set_attr "length" "4")
282b4c75 6070 (set_attr "type" "alu_sreg")]
d0e6a121 6071)
6072
cffb2a26 6073(define_insn "*arm_movsi_insn"
aaa37ad6 6074 [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,rk,m")
110eae03 6075 (match_operand:SI 1 "general_operand" "rk, I,K,j,mi,rk"))]
d7216193 6076 "TARGET_ARM && !TARGET_IWMMXT && !TARGET_HARD_FLOAT
cffb2a26 6077 && ( register_operand (operands[0], SImode)
6078 || register_operand (operands[1], SImode))"
f7fbdd4a 6079 "@
aaa37ad6 6080 mov%?\\t%0, %1
f7fbdd4a 6081 mov%?\\t%0, %1
6082 mvn%?\\t%0, #%B1
25f905c2 6083 movw%?\\t%0, %1
f7fbdd4a 6084 ldr%?\\t%0, %1
6085 str%?\\t%1, %0"
1aed5204 6086 [(set_attr "type" "mov_reg,mov_imm,mvn_imm,mov_imm,load1,store1")
0d66636f 6087 (set_attr "predicable" "yes")
100cd063 6088 (set_attr "arch" "*,*,*,v6t2,*,*")
aaa37ad6 6089 (set_attr "pool_range" "*,*,*,*,4096,*")
6090 (set_attr "neg_pool_range" "*,*,*,*,4084,*")]
cffb2a26 6091)
87b22bf7 6092
6093(define_split
a2cd141b 6094 [(set (match_operand:SI 0 "arm_general_register_operand" "")
87b22bf7 6095 (match_operand:SI 1 "const_int_operand" ""))]
6e291830 6096 "(TARGET_32BIT || TARGET_HAVE_MOVT)
215b30b3 6097 && (!(const_ok_for_arm (INTVAL (operands[1]))
6098 || const_ok_for_arm (~INTVAL (operands[1]))))"
87b22bf7 6099 [(clobber (const_int 0))]
6100 "
96f57e36 6101 arm_split_constant (SET, SImode, NULL_RTX,
6102 INTVAL (operands[1]), operands[0], NULL_RTX, 0);
87b22bf7 6103 DONE;
215b30b3 6104 "
6105)
9c08d1fa 6106
861033d5 6107;; A normal way to do (symbol + offset) requires three instructions at least
6108;; (depends on how big the offset is) as below:
6109;; movw r0, #:lower16:g
6110;; movw r0, #:upper16:g
6111;; adds r0, #4
6112;;
6113;; A better way would be:
6114;; movw r0, #:lower16:g+4
6115;; movw r0, #:upper16:g+4
6116;;
6117;; The limitation of this way is that the length of offset should be a 16-bit
6118;; signed value, because current assembler only supports REL type relocation for
6119;; such case. If the more powerful RELA type is supported in future, we should
6120;; update this pattern to go with better way.
6121(define_split
6122 [(set (match_operand:SI 0 "arm_general_register_operand" "")
6123 (const:SI (plus:SI (match_operand:SI 1 "general_operand" "")
6124 (match_operand:SI 2 "const_int_operand" ""))))]
60a48e7d 6125 "TARGET_THUMB
6126 && TARGET_HAVE_MOVT
861033d5 6127 && arm_disable_literal_pool
6128 && reload_completed
6129 && GET_CODE (operands[1]) == SYMBOL_REF"
6130 [(clobber (const_int 0))]
6131 "
6132 int offset = INTVAL (operands[2]);
6133
6134 if (offset < -0x8000 || offset > 0x7fff)
6135 {
6136 arm_emit_movpair (operands[0], operands[1]);
d1f9b275 6137 emit_insn (gen_rtx_SET (operands[0],
861033d5 6138 gen_rtx_PLUS (SImode, operands[0], operands[2])));
6139 }
6140 else
6141 {
6142 rtx op = gen_rtx_CONST (SImode,
6143 gen_rtx_PLUS (SImode, operands[1], operands[2]));
6144 arm_emit_movpair (operands[0], op);
6145 }
6146 "
6147)
6148
b8d5d078 6149;; Split symbol_refs at the later stage (after cprop), instead of generating
6150;; movt/movw pair directly at expand. Otherwise corresponding high_sum
6151;; and lo_sum would be merged back into memory load at cprop. However,
6152;; if the default is to prefer movt/movw rather than a load from the constant
6153;; pool, the performance is better.
6154(define_split
6155 [(set (match_operand:SI 0 "arm_general_register_operand" "")
6156 (match_operand:SI 1 "general_operand" ""))]
60a48e7d 6157 "TARGET_USE_MOVT && GET_CODE (operands[1]) == SYMBOL_REF
b8d5d078 6158 && !flag_pic && !target_word_relocations
6159 && !arm_tls_referenced_p (operands[1])"
6160 [(clobber (const_int 0))]
6161{
6162 arm_emit_movpair (operands[0], operands[1]);
6163 DONE;
6164})
6165
bc360af8 6166;; When generating pic, we need to load the symbol offset into a register.
6167;; So that the optimizer does not confuse this with a normal symbol load
6168;; we use an unspec. The offset will be loaded from a constant pool entry,
6169;; since that is the only type of relocation we can use.
cffb2a26 6170
bc360af8 6171;; Wrap calculation of the whole PIC address in a single pattern for the
6172;; benefit of optimizers, particularly, PRE and HOIST. Calculation of
6173;; a PIC address involves two loads from memory, so we want to CSE it
6174;; as often as possible.
6175;; This pattern will be split into one of the pic_load_addr_* patterns
6176;; and a move after GCSE optimizations.
6177;;
6178;; Note: Update arm.c: legitimize_pic_address() when changing this pattern.
6179(define_expand "calculate_pic_address"
94f8caca 6180 [(set (match_operand:SI 0 "register_operand" "")
6181 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "")
6182 (unspec:SI [(match_operand:SI 2 "" "")]
6183 UNSPEC_PIC_SYM))))]
6184 "flag_pic"
6185)
6186
6187;; Split calculate_pic_address into pic_load_addr_* and a move.
6188(define_split
6189 [(set (match_operand:SI 0 "register_operand" "")
6190 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "")
6191 (unspec:SI [(match_operand:SI 2 "" "")]
6192 UNSPEC_PIC_SYM))))]
6193 "flag_pic"
6194 [(set (match_dup 3) (unspec:SI [(match_dup 2)] UNSPEC_PIC_SYM))
6195 (set (match_dup 0) (mem:SI (plus:SI (match_dup 1) (match_dup 3))))]
6196 "operands[3] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];"
6197)
6198
350ccca5 6199;; operand1 is the memory address to go into
6200;; pic_load_addr_32bit.
6201;; operand2 is the PIC label to be emitted
6202;; from pic_add_dot_plus_eight.
6203;; We do this to allow hoisting of the entire insn.
6204(define_insn_and_split "pic_load_addr_unified"
6205 [(set (match_operand:SI 0 "s_register_operand" "=r,r,l")
6206 (unspec:SI [(match_operand:SI 1 "" "mX,mX,mX")
6207 (match_operand:SI 2 "" "")]
6208 UNSPEC_PIC_UNIFIED))]
6209 "flag_pic"
6210 "#"
6211 "&& reload_completed"
6212 [(set (match_dup 0) (unspec:SI [(match_dup 1)] UNSPEC_PIC_SYM))
6213 (set (match_dup 0) (unspec:SI [(match_dup 0) (match_dup 3)
6214 (match_dup 2)] UNSPEC_PIC_BASE))]
6215 "operands[3] = TARGET_THUMB ? GEN_INT (4) : GEN_INT (8);"
6216 [(set_attr "type" "load1,load1,load1")
42e1de19 6217 (set_attr "pool_range" "4096,4094,1022")
350ccca5 6218 (set_attr "neg_pool_range" "4084,0,0")
6219 (set_attr "arch" "a,t2,t1")
6220 (set_attr "length" "8,6,4")]
6221)
6222
67336bcf 6223;; The rather odd constraints on the following are to force reload to leave
6224;; the insn alone, and to force the minipool generation pass to then move
6225;; the GOT symbol to memory.
849170fd 6226
b3cd5f55 6227(define_insn "pic_load_addr_32bit"
849170fd 6228 [(set (match_operand:SI 0 "s_register_operand" "=r")
e1159bbe 6229 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
b3cd5f55 6230 "TARGET_32BIT && flag_pic"
67336bcf 6231 "ldr%?\\t%0, %1"
a2cd141b 6232 [(set_attr "type" "load1")
42e1de19 6233 (set (attr "pool_range")
6234 (if_then_else (eq_attr "is_thumb" "no")
6235 (const_int 4096)
6236 (const_int 4094)))
b3cd5f55 6237 (set (attr "neg_pool_range")
6238 (if_then_else (eq_attr "is_thumb" "no")
6239 (const_int 4084)
6240 (const_int 0)))]
8c4d8060 6241)
6242
25f905c2 6243(define_insn "pic_load_addr_thumb1"
8c4d8060 6244 [(set (match_operand:SI 0 "s_register_operand" "=l")
e1159bbe 6245 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
25f905c2 6246 "TARGET_THUMB1 && flag_pic"
8c4d8060 6247 "ldr\\t%0, %1"
a2cd141b 6248 [(set_attr "type" "load1")
42e1de19 6249 (set (attr "pool_range") (const_int 1018))]
cffb2a26 6250)
849170fd 6251
cffb2a26 6252(define_insn "pic_add_dot_plus_four"
15d5d060 6253 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 6254 (unspec:SI [(match_operand:SI 1 "register_operand" "0")
6255 (const_int 4)
beef0fb5 6256 (match_operand 2 "" "")]
6257 UNSPEC_PIC_BASE))]
b3cd5f55 6258 "TARGET_THUMB"
cffb2a26 6259 "*
6cdcb15c 6260 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
6261 INTVAL (operands[2]));
cffb2a26 6262 return \"add\\t%0, %|pc\";
6263 "
1b7da4ac 6264 [(set_attr "length" "2")
112eda6f 6265 (set_attr "type" "alu_sreg")]
cffb2a26 6266)
849170fd 6267
6268(define_insn "pic_add_dot_plus_eight"
15d5d060 6269 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 6270 (unspec:SI [(match_operand:SI 1 "register_operand" "r")
6271 (const_int 8)
beef0fb5 6272 (match_operand 2 "" "")]
6273 UNSPEC_PIC_BASE))]
f655717d 6274 "TARGET_ARM"
c4034607 6275 "*
6cdcb15c 6276 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
6277 INTVAL (operands[2]));
15d5d060 6278 return \"add%?\\t%0, %|pc, %1\";
cffb2a26 6279 "
1b7da4ac 6280 [(set_attr "predicable" "yes")
112eda6f 6281 (set_attr "type" "alu_sreg")]
cffb2a26 6282)
849170fd 6283
f655717d 6284(define_insn "tls_load_dot_plus_eight"
cc071db6 6285 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 6286 (mem:SI (unspec:SI [(match_operand:SI 1 "register_operand" "r")
6287 (const_int 8)
beef0fb5 6288 (match_operand 2 "" "")]
6289 UNSPEC_PIC_BASE)))]
f655717d 6290 "TARGET_ARM"
6291 "*
6cdcb15c 6292 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
6293 INTVAL (operands[2]));
f655717d 6294 return \"ldr%?\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_eight\";
6295 "
1b7da4ac 6296 [(set_attr "predicable" "yes")
6297 (set_attr "type" "load1")]
f655717d 6298)
6299
6300;; PIC references to local variables can generate pic_add_dot_plus_eight
6301;; followed by a load. These sequences can be crunched down to
6302;; tls_load_dot_plus_eight by a peephole.
6303
6304(define_peephole2
c0c1fba5 6305 [(set (match_operand:SI 0 "register_operand" "")
6306 (unspec:SI [(match_operand:SI 3 "register_operand" "")
6307 (const_int 8)
6308 (match_operand 1 "" "")]
6309 UNSPEC_PIC_BASE))
2d05dfad 6310 (set (match_operand:SI 2 "arm_general_register_operand" "")
6311 (mem:SI (match_dup 0)))]
f655717d 6312 "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
c0c1fba5 6313 [(set (match_dup 2)
6314 (mem:SI (unspec:SI [(match_dup 3)
6315 (const_int 8)
6316 (match_dup 1)]
6317 UNSPEC_PIC_BASE)))]
f655717d 6318 ""
6319)
6320
bac7fc85 6321(define_insn "pic_offset_arm"
6322 [(set (match_operand:SI 0 "register_operand" "=r")
6323 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
6324 (unspec:SI [(match_operand:SI 2 "" "X")]
6325 UNSPEC_PIC_OFFSET))))]
6326 "TARGET_VXWORKS_RTP && TARGET_ARM && flag_pic"
6327 "ldr%?\\t%0, [%1,%2]"
6328 [(set_attr "type" "load1")]
6329)
6330
95373f08 6331(define_expand "builtin_setjmp_receiver"
6332 [(label_ref (match_operand 0 "" ""))]
6333 "flag_pic"
6334 "
6335{
b935b306 6336 /* r3 is clobbered by set/longjmp, so we can use it as a scratch
6337 register. */
2cb7d577 6338 if (arm_pic_register != INVALID_REGNUM)
6339 arm_load_pic_register (1UL << 3);
95373f08 6340 DONE;
6341}")
6342
9c08d1fa 6343;; If copying one reg to another we can set the condition codes according to
6344;; its value. Such a move is common after a return from subroutine and the
6345;; result is being tested against zero.
6346
f7fbdd4a 6347(define_insn "*movsi_compare0"
bd5b4116 6348 [(set (reg:CC CC_REGNUM)
cffb2a26 6349 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
6350 (const_int 0)))
6351 (set (match_operand:SI 0 "s_register_operand" "=r,r")
6352 (match_dup 1))]
25f905c2 6353 "TARGET_32BIT"
e2348bcb 6354 "@
40dbec34 6355 cmp%?\\t%0, #0
3ef90e77 6356 subs%?\\t%0, %1, #0"
65f68e55 6357 [(set_attr "conds" "set")
d82e788e 6358 (set_attr "type" "alus_imm,alus_imm")]
cffb2a26 6359)
b11cae9e 6360
b11cae9e 6361;; Subroutine to store a half word from a register into memory.
6362;; Operand 0 is the source register (HImode)
c8f69309 6363;; Operand 1 is the destination address in a register (SImode)
b11cae9e 6364
9c08d1fa 6365;; In both this routine and the next, we must be careful not to spill
01cc3b75 6366;; a memory address of reg+large_const into a separate PLUS insn, since this
9c08d1fa 6367;; can generate unrecognizable rtl.
6368
b11cae9e 6369(define_expand "storehi"
c8f69309 6370 [;; store the low byte
f082f1c4 6371 (set (match_operand 1 "" "") (match_dup 3))
b11cae9e 6372 ;; extract the high byte
c8f69309 6373 (set (match_dup 2)
6374 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
b11cae9e 6375 ;; store the high byte
787f8210 6376 (set (match_dup 4) (match_dup 5))]
cffb2a26 6377 "TARGET_ARM"
b11cae9e 6378 "
215b30b3 6379 {
537ffcfc 6380 rtx op1 = operands[1];
6381 rtx addr = XEXP (op1, 0);
215b30b3 6382 enum rtx_code code = GET_CODE (addr);
6383
0438d37f 6384 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
215b30b3 6385 || code == MINUS)
537ffcfc 6386 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
215b30b3 6387
537ffcfc 6388 operands[4] = adjust_address (op1, QImode, 1);
e513d163 6389 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 6390 operands[3] = gen_lowpart (QImode, operands[0]);
6391 operands[0] = gen_lowpart (SImode, operands[0]);
787f8210 6392 operands[2] = gen_reg_rtx (SImode);
6393 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 6394 }"
6395)
b11cae9e 6396
c7597b5d 6397(define_expand "storehi_bigend"
f082f1c4 6398 [(set (match_dup 4) (match_dup 3))
c7597b5d 6399 (set (match_dup 2)
6400 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
787f8210 6401 (set (match_operand 1 "" "") (match_dup 5))]
cffb2a26 6402 "TARGET_ARM"
b11cae9e 6403 "
215b30b3 6404 {
537ffcfc 6405 rtx op1 = operands[1];
6406 rtx addr = XEXP (op1, 0);
215b30b3 6407 enum rtx_code code = GET_CODE (addr);
6408
0438d37f 6409 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
215b30b3 6410 || code == MINUS)
537ffcfc 6411 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
215b30b3 6412
537ffcfc 6413 operands[4] = adjust_address (op1, QImode, 1);
e513d163 6414 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 6415 operands[3] = gen_lowpart (QImode, operands[0]);
6416 operands[0] = gen_lowpart (SImode, operands[0]);
6417 operands[2] = gen_reg_rtx (SImode);
787f8210 6418 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 6419 }"
6420)
c7597b5d 6421
6422;; Subroutine to store a half word integer constant into memory.
6423(define_expand "storeinthi"
f082f1c4 6424 [(set (match_operand 0 "" "")
787f8210 6425 (match_operand 1 "" ""))
9e8503e6 6426 (set (match_dup 3) (match_dup 2))]
cffb2a26 6427 "TARGET_ARM"
c7597b5d 6428 "
215b30b3 6429 {
6430 HOST_WIDE_INT value = INTVAL (operands[1]);
6431 rtx addr = XEXP (operands[0], 0);
537ffcfc 6432 rtx op0 = operands[0];
215b30b3 6433 enum rtx_code code = GET_CODE (addr);
c7597b5d 6434
0438d37f 6435 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
215b30b3 6436 || code == MINUS)
537ffcfc 6437 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
c7597b5d 6438
215b30b3 6439 operands[1] = gen_reg_rtx (SImode);
6440 if (BYTES_BIG_ENDIAN)
6441 {
6442 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
6443 if ((value & 255) == ((value >> 8) & 255))
6444 operands[2] = operands[1];
6445 else
6446 {
6447 operands[2] = gen_reg_rtx (SImode);
6448 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
6449 }
6450 }
6451 else
6452 {
6453 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
6454 if ((value & 255) == ((value >> 8) & 255))
6455 operands[2] = operands[1];
6456 else
6457 {
6458 operands[2] = gen_reg_rtx (SImode);
6459 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
6460 }
6461 }
c7597b5d 6462
537ffcfc 6463 operands[3] = adjust_address (op0, QImode, 1);
e513d163 6464 operands[0] = adjust_address (operands[0], QImode, 0);
9e8503e6 6465 operands[2] = gen_lowpart (QImode, operands[2]);
787f8210 6466 operands[1] = gen_lowpart (QImode, operands[1]);
215b30b3 6467 }"
6468)
b11cae9e 6469
f7fbdd4a 6470(define_expand "storehi_single_op"
6471 [(set (match_operand:HI 0 "memory_operand" "")
6472 (match_operand:HI 1 "general_operand" ""))]
25f905c2 6473 "TARGET_32BIT && arm_arch4"
f7fbdd4a 6474 "
215b30b3 6475 if (!s_register_operand (operands[1], HImode))
f7fbdd4a 6476 operands[1] = copy_to_mode_reg (HImode, operands[1]);
215b30b3 6477 "
6478)
f7fbdd4a 6479
b11cae9e 6480(define_expand "movhi"
6481 [(set (match_operand:HI 0 "general_operand" "")
c8f69309 6482 (match_operand:HI 1 "general_operand" ""))]
cffb2a26 6483 "TARGET_EITHER"
b11cae9e 6484 "
cffb2a26 6485 if (TARGET_ARM)
b11cae9e 6486 {
e1ba4a27 6487 if (can_create_pseudo_p ())
cffb2a26 6488 {
0438d37f 6489 if (MEM_P (operands[0]))
b11cae9e 6490 {
cffb2a26 6491 if (arm_arch4)
6492 {
6493 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
6494 DONE;
6495 }
0438d37f 6496 if (CONST_INT_P (operands[1]))
cffb2a26 6497 emit_insn (gen_storeinthi (operands[0], operands[1]));
c7597b5d 6498 else
cffb2a26 6499 {
0438d37f 6500 if (MEM_P (operands[1]))
cffb2a26 6501 operands[1] = force_reg (HImode, operands[1]);
6502 if (BYTES_BIG_ENDIAN)
6503 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
6504 else
6505 emit_insn (gen_storehi (operands[1], operands[0]));
6506 }
6507 DONE;
b11cae9e 6508 }
cffb2a26 6509 /* Sign extend a constant, and keep it in an SImode reg. */
0438d37f 6510 else if (CONST_INT_P (operands[1]))
9c08d1fa 6511 {
cffb2a26 6512 rtx reg = gen_reg_rtx (SImode);
6513 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
6514
6515 /* If the constant is already valid, leave it alone. */
215b30b3 6516 if (!const_ok_for_arm (val))
cffb2a26 6517 {
6518 /* If setting all the top bits will make the constant
6519 loadable in a single instruction, then set them.
6520 Otherwise, sign extend the number. */
6521
215b30b3 6522 if (const_ok_for_arm (~(val | ~0xffff)))
cffb2a26 6523 val |= ~0xffff;
6524 else if (val & 0x8000)
6525 val |= ~0xffff;
6526 }
6527
6528 emit_insn (gen_movsi (reg, GEN_INT (val)));
9e8503e6 6529 operands[1] = gen_lowpart (HImode, reg);
9c08d1fa 6530 }
e1ba4a27 6531 else if (arm_arch4 && optimize && can_create_pseudo_p ()
0438d37f 6532 && MEM_P (operands[1]))
0045890a 6533 {
6534 rtx reg = gen_reg_rtx (SImode);
6535
6536 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
6537 operands[1] = gen_lowpart (HImode, reg);
6538 }
215b30b3 6539 else if (!arm_arch4)
f7fbdd4a 6540 {
0438d37f 6541 if (MEM_P (operands[1]))
cffb2a26 6542 {
c1a66faf 6543 rtx base;
6544 rtx offset = const0_rtx;
6545 rtx reg = gen_reg_rtx (SImode);
6546
0438d37f 6547 if ((REG_P (base = XEXP (operands[1], 0))
c1a66faf 6548 || (GET_CODE (base) == PLUS
0438d37f 6549 && (CONST_INT_P (offset = XEXP (base, 1)))
c1a66faf 6550 && ((INTVAL(offset) & 1) != 1)
0438d37f 6551 && REG_P (base = XEXP (base, 0))))
c1a66faf 6552 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
206ee9a2 6553 {
8deb3959 6554 rtx new_rtx;
c1a66faf 6555
8deb3959 6556 new_rtx = widen_memory_access (operands[1], SImode,
6557 ((INTVAL (offset) & ~3)
6558 - INTVAL (offset)));
6559 emit_insn (gen_movsi (reg, new_rtx));
c1a66faf 6560 if (((INTVAL (offset) & 2) != 0)
6561 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
6562 {
6563 rtx reg2 = gen_reg_rtx (SImode);
6564
6565 emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
6566 reg = reg2;
6567 }
206ee9a2 6568 }
c1a66faf 6569 else
6570 emit_insn (gen_movhi_bytes (reg, operands[1]));
6571
6572 operands[1] = gen_lowpart (HImode, reg);
cffb2a26 6573 }
6574 }
6575 }
674a8f0b 6576 /* Handle loading a large integer during reload. */
0438d37f 6577 else if (CONST_INT_P (operands[1])
215b30b3 6578 && !const_ok_for_arm (INTVAL (operands[1]))
6579 && !const_ok_for_arm (~INTVAL (operands[1])))
cffb2a26 6580 {
6581 /* Writing a constant to memory needs a scratch, which should
6582 be handled with SECONDARY_RELOADs. */
0438d37f 6583 gcc_assert (REG_P (operands[0]));
cffb2a26 6584
6585 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
6586 emit_insn (gen_movsi (operands[0], operands[1]));
6587 DONE;
6588 }
6589 }
25f905c2 6590 else if (TARGET_THUMB2)
6591 {
6592 /* Thumb-2 can do everything except mem=mem and mem=const easily. */
e1ba4a27 6593 if (can_create_pseudo_p ())
25f905c2 6594 {
0438d37f 6595 if (!REG_P (operands[0]))
25f905c2 6596 operands[1] = force_reg (HImode, operands[1]);
6597 /* Zero extend a constant, and keep it in an SImode reg. */
0438d37f 6598 else if (CONST_INT_P (operands[1]))
25f905c2 6599 {
6600 rtx reg = gen_reg_rtx (SImode);
6601 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
6602
6603 emit_insn (gen_movsi (reg, GEN_INT (val)));
6604 operands[1] = gen_lowpart (HImode, reg);
6605 }
6606 }
6607 }
6608 else /* TARGET_THUMB1 */
cffb2a26 6609 {
e1ba4a27 6610 if (can_create_pseudo_p ())
cffb2a26 6611 {
0438d37f 6612 if (CONST_INT_P (operands[1]))
6cffc037 6613 {
6614 rtx reg = gen_reg_rtx (SImode);
6615
6616 emit_insn (gen_movsi (reg, operands[1]));
6617 operands[1] = gen_lowpart (HImode, reg);
6618 }
cffb2a26 6619
6620 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 6621 happen if we are passed a SP (never OK for HImode/QImode) or
bc409cb4 6622 virtual register (also rejected as illegitimate for HImode/QImode)
6623 relative address. */
cffb2a26 6624 /* ??? This should perhaps be fixed elsewhere, for instance, in
6625 fixup_stack_1, by checking for other kinds of invalid addresses,
6626 e.g. a bare reference to a virtual register. This may confuse the
6627 alpha though, which must handle this case differently. */
0438d37f 6628 if (MEM_P (operands[0])
215b30b3 6629 && !memory_address_p (GET_MODE (operands[0]),
6630 XEXP (operands[0], 0)))
537ffcfc 6631 operands[0]
6632 = replace_equiv_address (operands[0],
6633 copy_to_reg (XEXP (operands[0], 0)));
cffb2a26 6634
0438d37f 6635 if (MEM_P (operands[1])
215b30b3 6636 && !memory_address_p (GET_MODE (operands[1]),
6637 XEXP (operands[1], 0)))
537ffcfc 6638 operands[1]
6639 = replace_equiv_address (operands[1],
6640 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 6641
0438d37f 6642 if (MEM_P (operands[1]) && optimize > 0)
6cffc037 6643 {
6644 rtx reg = gen_reg_rtx (SImode);
6645
6646 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
6647 operands[1] = gen_lowpart (HImode, reg);
6648 }
6649
0438d37f 6650 if (MEM_P (operands[0]))
6cffc037 6651 operands[1] = force_reg (HImode, operands[1]);
cffb2a26 6652 }
0438d37f 6653 else if (CONST_INT_P (operands[1])
234f6557 6654 && !satisfies_constraint_I (operands[1]))
cffb2a26 6655 {
6cffc037 6656 /* Handle loading a large integer during reload. */
6657
cffb2a26 6658 /* Writing a constant to memory needs a scratch, which should
6659 be handled with SECONDARY_RELOADs. */
0438d37f 6660 gcc_assert (REG_P (operands[0]));
cffb2a26 6661
1a83b3ff 6662 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
cffb2a26 6663 emit_insn (gen_movsi (operands[0], operands[1]));
6664 DONE;
6665 }
b11cae9e 6666 }
cffb2a26 6667 "
6668)
6669
25f7a26e 6670(define_expand "movhi_bytes"
eab14235 6671 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 6672 (set (match_dup 3)
eab14235 6673 (zero_extend:SI (match_dup 6)))
25f7a26e 6674 (set (match_operand:SI 0 "" "")
6675 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
cffb2a26 6676 "TARGET_ARM"
25f7a26e 6677 "
215b30b3 6678 {
6679 rtx mem1, mem2;
6680 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
6681
788fcce0 6682 mem1 = change_address (operands[1], QImode, addr);
29c05e22 6683 mem2 = change_address (operands[1], QImode,
6684 plus_constant (Pmode, addr, 1));
215b30b3 6685 operands[0] = gen_lowpart (SImode, operands[0]);
6686 operands[1] = mem1;
6687 operands[2] = gen_reg_rtx (SImode);
6688 operands[3] = gen_reg_rtx (SImode);
6689 operands[6] = mem2;
25f7a26e 6690
215b30b3 6691 if (BYTES_BIG_ENDIAN)
6692 {
6693 operands[4] = operands[2];
6694 operands[5] = operands[3];
6695 }
6696 else
6697 {
6698 operands[4] = operands[3];
6699 operands[5] = operands[2];
6700 }
6701 }"
6702)
25f7a26e 6703
c7597b5d 6704(define_expand "movhi_bigend"
6705 [(set (match_dup 2)
6706 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
6707 (const_int 16)))
6708 (set (match_dup 3)
6709 (ashiftrt:SI (match_dup 2) (const_int 16)))
6710 (set (match_operand:HI 0 "s_register_operand" "")
787f8210 6711 (match_dup 4))]
cffb2a26 6712 "TARGET_ARM"
c7597b5d 6713 "
6714 operands[2] = gen_reg_rtx (SImode);
6715 operands[3] = gen_reg_rtx (SImode);
787f8210 6716 operands[4] = gen_lowpart (HImode, operands[3]);
215b30b3 6717 "
6718)
b11cae9e 6719
a2f10574 6720;; Pattern to recognize insn generated default case above
f7fbdd4a 6721(define_insn "*movhi_insn_arch4"
e4585731 6722 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r,m,r")
6723 (match_operand:HI 1 "general_operand" "rIk,K,n,r,mi"))]
cffb2a26 6724 "TARGET_ARM
d7216193 6725 && arm_arch4 && !TARGET_HARD_FLOAT
85e02ccb 6726 && (register_operand (operands[0], HImode)
6727 || register_operand (operands[1], HImode))"
f7fbdd4a 6728 "@
6729 mov%?\\t%0, %1\\t%@ movhi
6730 mvn%?\\t%0, #%B1\\t%@ movhi
b1c1a101 6731 movw%?\\t%0, %L1\\t%@ movhi
3ef90e77 6732 strh%?\\t%1, %0\\t%@ movhi
6733 ldrh%?\\t%0, %1\\t%@ movhi"
65f68e55 6734 [(set_attr "predicable" "yes")
e4585731 6735 (set_attr "pool_range" "*,*,*,*,256")
6736 (set_attr "neg_pool_range" "*,*,*,*,244")
6737 (set_attr "arch" "*,*,v6t2,*,*")
65f68e55 6738 (set_attr_alternative "type"
6739 [(if_then_else (match_operand 1 "const_int_operand" "")
1aed5204 6740 (const_string "mov_imm" )
6741 (const_string "mov_reg"))
6742 (const_string "mvn_imm")
e4585731 6743 (const_string "mov_imm")
65f68e55 6744 (const_string "store1")
6745 (const_string "load1")])]
cffb2a26 6746)
f7fbdd4a 6747
f7fbdd4a 6748(define_insn "*movhi_bytes"
65f68e55 6749 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
5fd254ed 6750 (match_operand:HI 1 "arm_rhs_operand" "I,rk,K"))]
d7216193 6751 "TARGET_ARM && !TARGET_HARD_FLOAT"
25f7a26e 6752 "@
65f68e55 6753 mov%?\\t%0, %1\\t%@ movhi
25f7a26e 6754 mov%?\\t%0, %1\\t%@ movhi
0d66636f 6755 mvn%?\\t%0, #%B1\\t%@ movhi"
d2a518d1 6756 [(set_attr "predicable" "yes")
1aed5204 6757 (set_attr "type" "mov_imm,mov_reg,mvn_imm")]
0d66636f 6758)
837bb76e 6759
bc5c7e08 6760;; We use a DImode scratch because we may occasionally need an additional
6761;; temporary if the address isn't offsettable -- push_reload doesn't seem
6762;; to take any notice of the "o" constraints on reload_memory_operand operand.
d3373b54 6763(define_expand "reload_outhi"
cffb2a26 6764 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
215b30b3 6765 (match_operand:HI 1 "s_register_operand" "r")
6766 (match_operand:DI 2 "s_register_operand" "=&l")])]
cffb2a26 6767 "TARGET_EITHER"
6768 "if (TARGET_ARM)
6769 arm_reload_out_hi (operands);
6770 else
6771 thumb_reload_out_hi (operands);
d3373b54 6772 DONE;
cffb2a26 6773 "
6774)
d3373b54 6775
25f7a26e 6776(define_expand "reload_inhi"
6777 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
cffb2a26 6778 (match_operand:HI 1 "arm_reload_memory_operand" "o")
bc5c7e08 6779 (match_operand:DI 2 "s_register_operand" "=&r")])]
c1a66faf 6780 "TARGET_EITHER"
25f7a26e 6781 "
cffb2a26 6782 if (TARGET_ARM)
6783 arm_reload_in_hi (operands);
6784 else
6785 thumb_reload_out_hi (operands);
25f7a26e 6786 DONE;
6787")
6788
9c08d1fa 6789(define_expand "movqi"
6790 [(set (match_operand:QI 0 "general_operand" "")
6791 (match_operand:QI 1 "general_operand" ""))]
cffb2a26 6792 "TARGET_EITHER"
9c08d1fa 6793 "
6cffc037 6794 /* Everything except mem = const or mem = mem can be done easily */
0045890a 6795
e1ba4a27 6796 if (can_create_pseudo_p ())
cffb2a26 6797 {
0438d37f 6798 if (CONST_INT_P (operands[1]))
6cffc037 6799 {
6800 rtx reg = gen_reg_rtx (SImode);
6801
03770691 6802 /* For thumb we want an unsigned immediate, then we are more likely
6803 to be able to use a movs insn. */
6804 if (TARGET_THUMB)
6805 operands[1] = GEN_INT (INTVAL (operands[1]) & 255);
6806
6cffc037 6807 emit_insn (gen_movsi (reg, operands[1]));
6808 operands[1] = gen_lowpart (QImode, reg);
6809 }
cffb2a26 6810
6cffc037 6811 if (TARGET_THUMB)
6812 {
cffb2a26 6813 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 6814 happen if we are passed a SP (never OK for HImode/QImode) or
bc409cb4 6815 virtual register (also rejected as illegitimate for HImode/QImode)
6816 relative address. */
cffb2a26 6817 /* ??? This should perhaps be fixed elsewhere, for instance, in
6818 fixup_stack_1, by checking for other kinds of invalid addresses,
6819 e.g. a bare reference to a virtual register. This may confuse the
6820 alpha though, which must handle this case differently. */
0438d37f 6821 if (MEM_P (operands[0])
215b30b3 6822 && !memory_address_p (GET_MODE (operands[0]),
cffb2a26 6823 XEXP (operands[0], 0)))
537ffcfc 6824 operands[0]
6825 = replace_equiv_address (operands[0],
6826 copy_to_reg (XEXP (operands[0], 0)));
0438d37f 6827 if (MEM_P (operands[1])
215b30b3 6828 && !memory_address_p (GET_MODE (operands[1]),
cffb2a26 6829 XEXP (operands[1], 0)))
537ffcfc 6830 operands[1]
6831 = replace_equiv_address (operands[1],
6832 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 6833 }
6834
0438d37f 6835 if (MEM_P (operands[1]) && optimize > 0)
6cffc037 6836 {
6837 rtx reg = gen_reg_rtx (SImode);
6838
6839 emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
6840 operands[1] = gen_lowpart (QImode, reg);
6841 }
6842
0438d37f 6843 if (MEM_P (operands[0]))
6cffc037 6844 operands[1] = force_reg (QImode, operands[1]);
6845 }
6846 else if (TARGET_THUMB
0438d37f 6847 && CONST_INT_P (operands[1])
234f6557 6848 && !satisfies_constraint_I (operands[1]))
6cffc037 6849 {
674a8f0b 6850 /* Handle loading a large integer during reload. */
cffb2a26 6851
6cffc037 6852 /* Writing a constant to memory needs a scratch, which should
6853 be handled with SECONDARY_RELOADs. */
0438d37f 6854 gcc_assert (REG_P (operands[0]));
6cffc037 6855
6856 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
6857 emit_insn (gen_movsi (operands[0], operands[1]));
6858 DONE;
cffb2a26 6859 }
6860 "
6861)
b11cae9e 6862
cffb2a26 6863(define_insn "*arm_movqi_insn"
fd711051 6864 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,l,r,l,Uu,r,m")
490f62ca 6865 (match_operand:QI 1 "general_operand" "rk,rk,I,Py,K,Uu,l,Uh,r"))]
25f905c2 6866 "TARGET_32BIT
cffb2a26 6867 && ( register_operand (operands[0], QImode)
6868 || register_operand (operands[1], QImode))"
5565501b 6869 "@
fd711051 6870 mov%?\\t%0, %1
6871 mov%?\\t%0, %1
65f68e55 6872 mov%?\\t%0, %1
5565501b 6873 mov%?\\t%0, %1
6874 mvn%?\\t%0, #%B1
3ef90e77 6875 ldrb%?\\t%0, %1
6876 strb%?\\t%1, %0
6877 ldrb%?\\t%0, %1
6878 strb%?\\t%1, %0"
1aed5204 6879 [(set_attr "type" "mov_reg,mov_reg,mov_imm,mov_imm,mvn_imm,load1,store1,load1,store1")
a54e3e7b 6880 (set_attr "predicable" "yes")
5233bf6a 6881 (set_attr "predicable_short_it" "yes,yes,no,yes,no,no,no,no,no")
fd711051 6882 (set_attr "arch" "t2,any,any,t2,any,t2,t2,any,any")
6883 (set_attr "length" "2,4,4,2,4,2,2,4,4")]
cffb2a26 6884)
6885
9b8516be 6886;; HFmode moves
6887(define_expand "movhf"
6888 [(set (match_operand:HF 0 "general_operand" "")
6889 (match_operand:HF 1 "general_operand" ""))]
6890 "TARGET_EITHER"
6891 "
6892 if (TARGET_32BIT)
6893 {
0438d37f 6894 if (MEM_P (operands[0]))
9b8516be 6895 operands[1] = force_reg (HFmode, operands[1]);
6896 }
6897 else /* TARGET_THUMB1 */
6898 {
6899 if (can_create_pseudo_p ())
6900 {
0438d37f 6901 if (!REG_P (operands[0]))
9b8516be 6902 operands[1] = force_reg (HFmode, operands[1]);
6903 }
6904 }
6905 "
6906)
6907
6908(define_insn "*arm32_movhf"
6909 [(set (match_operand:HF 0 "nonimmediate_operand" "=r,m,r,r")
6910 (match_operand:HF 1 "general_operand" " m,r,r,F"))]
d7216193 6911 "TARGET_32BIT && !TARGET_HARD_FLOAT
9b8516be 6912 && ( s_register_operand (operands[0], HFmode)
6913 || s_register_operand (operands[1], HFmode))"
6914 "*
6915 switch (which_alternative)
6916 {
6917 case 0: /* ARM register from memory */
3ef90e77 6918 return \"ldrh%?\\t%0, %1\\t%@ __fp16\";
9b8516be 6919 case 1: /* memory from ARM register */
3ef90e77 6920 return \"strh%?\\t%1, %0\\t%@ __fp16\";
9b8516be 6921 case 2: /* ARM register from ARM register */
6922 return \"mov%?\\t%0, %1\\t%@ __fp16\";
6923 case 3: /* ARM register from constant */
6924 {
9b8516be 6925 long bits;
6926 rtx ops[4];
6927
945f7b03 6928 bits = real_to_target (NULL, CONST_DOUBLE_REAL_VALUE (operands[1]),
6929 HFmode);
9b8516be 6930 ops[0] = operands[0];
6931 ops[1] = GEN_INT (bits);
6932 ops[2] = GEN_INT (bits & 0xff00);
6933 ops[3] = GEN_INT (bits & 0x00ff);
6934
6935 if (arm_arch_thumb2)
6936 output_asm_insn (\"movw%?\\t%0, %1\", ops);
6937 else
6938 output_asm_insn (\"mov%?\\t%0, %2\;orr%?\\t%0, %0, %3\", ops);
6939 return \"\";
6940 }
6941 default:
6942 gcc_unreachable ();
6943 }
6944 "
6945 [(set_attr "conds" "unconditional")
ad4fc3c0 6946 (set_attr "type" "load1,store1,mov_reg,multiple")
9b8516be 6947 (set_attr "length" "4,4,4,8")
ea501323 6948 (set_attr "predicable" "yes")
6949 (set_attr "predicable_short_it" "no")]
9b8516be 6950)
6951
87b22bf7 6952(define_expand "movsf"
6953 [(set (match_operand:SF 0 "general_operand" "")
6954 (match_operand:SF 1 "general_operand" ""))]
cffb2a26 6955 "TARGET_EITHER"
87b22bf7 6956 "
25f905c2 6957 if (TARGET_32BIT)
cffb2a26 6958 {
0438d37f 6959 if (MEM_P (operands[0]))
cffb2a26 6960 operands[1] = force_reg (SFmode, operands[1]);
6961 }
25f905c2 6962 else /* TARGET_THUMB1 */
cffb2a26 6963 {
e1ba4a27 6964 if (can_create_pseudo_p ())
cffb2a26 6965 {
0438d37f 6966 if (!REG_P (operands[0]))
cffb2a26 6967 operands[1] = force_reg (SFmode, operands[1]);
6968 }
6969 }
6970 "
6971)
6972
03d440a6 6973;; Transform a floating-point move of a constant into a core register into
6974;; an SImode operation.
cffb2a26 6975(define_split
03d440a6 6976 [(set (match_operand:SF 0 "arm_general_register_operand" "")
cffb2a26 6977 (match_operand:SF 1 "immediate_operand" ""))]
339034d0 6978 "TARGET_EITHER
cffb2a26 6979 && reload_completed
0438d37f 6980 && CONST_DOUBLE_P (operands[1])"
cffb2a26 6981 [(set (match_dup 2) (match_dup 3))]
6982 "
6983 operands[2] = gen_lowpart (SImode, operands[0]);
6984 operands[3] = gen_lowpart (SImode, operands[1]);
6985 if (operands[2] == 0 || operands[3] == 0)
6986 FAIL;
215b30b3 6987 "
6988)
87b22bf7 6989
cffb2a26 6990(define_insn "*arm_movsf_soft_insn"
6991 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
6992 (match_operand:SF 1 "general_operand" "r,mE,r"))]
cde1623a 6993 "TARGET_32BIT
cffb2a26 6994 && TARGET_SOFT_FLOAT
0438d37f 6995 && (!MEM_P (operands[0])
215b30b3 6996 || register_operand (operands[1], SFmode))"
9a1112d7 6997 "@
6998 mov%?\\t%0, %1
6999 ldr%?\\t%0, %1\\t%@ float
7000 str%?\\t%1, %0\\t%@ float"
cde1623a 7001 [(set_attr "predicable" "yes")
7c36fe71 7002 (set_attr "predicable_short_it" "no")
1aed5204 7003 (set_attr "type" "mov_reg,load1,store1")
42e1de19 7004 (set_attr "arm_pool_range" "*,4096,*")
7005 (set_attr "thumb2_pool_range" "*,4094,*")
cde1623a 7006 (set_attr "arm_neg_pool_range" "*,4084,*")
7007 (set_attr "thumb2_neg_pool_range" "*,0,*")]
cffb2a26 7008)
7009
9c08d1fa 7010(define_expand "movdf"
87b22bf7 7011 [(set (match_operand:DF 0 "general_operand" "")
7012 (match_operand:DF 1 "general_operand" ""))]
cffb2a26 7013 "TARGET_EITHER"
9c08d1fa 7014 "
25f905c2 7015 if (TARGET_32BIT)
cffb2a26 7016 {
0438d37f 7017 if (MEM_P (operands[0]))
cffb2a26 7018 operands[1] = force_reg (DFmode, operands[1]);
7019 }
7020 else /* TARGET_THUMB */
7021 {
e1ba4a27 7022 if (can_create_pseudo_p ())
cffb2a26 7023 {
0438d37f 7024 if (!REG_P (operands[0]))
cffb2a26 7025 operands[1] = force_reg (DFmode, operands[1]);
7026 }
7027 }
7028 "
7029)
b11cae9e 7030
9c08d1fa 7031;; Reloading a df mode value stored in integer regs to memory can require a
7032;; scratch reg.
7033(define_expand "reload_outdf"
cffb2a26 7034 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
87b22bf7 7035 (match_operand:DF 1 "s_register_operand" "r")
7036 (match_operand:SI 2 "s_register_operand" "=&r")]
06adefdc 7037 "TARGET_THUMB2"
87b22bf7 7038 "
215b30b3 7039 {
7040 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
f7fbdd4a 7041
215b30b3 7042 if (code == REG)
7043 operands[2] = XEXP (operands[0], 0);
7044 else if (code == POST_INC || code == PRE_DEC)
7045 {
7046 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
7047 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
7048 emit_insn (gen_movdi (operands[0], operands[1]));
7049 DONE;
7050 }
7051 else if (code == PRE_INC)
7052 {
7053 rtx reg = XEXP (XEXP (operands[0], 0), 0);
f7fbdd4a 7054
215b30b3 7055 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
7056 operands[2] = reg;
7057 }
7058 else if (code == POST_DEC)
7059 operands[2] = XEXP (XEXP (operands[0], 0), 0);
7060 else
7061 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
7062 XEXP (XEXP (operands[0], 0), 1)));
f7fbdd4a 7063
d1f9b275 7064 emit_insn (gen_rtx_SET (replace_equiv_address (operands[0], operands[2]),
215b30b3 7065 operands[1]));
f7fbdd4a 7066
215b30b3 7067 if (code == POST_DEC)
7068 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
7069
7070 DONE;
7071 }"
7072)
9c08d1fa 7073
9a1112d7 7074(define_insn "*movdf_soft_insn"
353cf59a 7075 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,q,m")
7076 (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,q"))]
cde1623a 7077 "TARGET_32BIT && TARGET_SOFT_FLOAT
b2778788 7078 && ( register_operand (operands[0], DFmode)
7079 || register_operand (operands[1], DFmode))"
d51f92df 7080 "*
7081 switch (which_alternative)
7082 {
7083 case 0:
7084 case 1:
7085 case 2:
7086 return \"#\";
7087 default:
26ff80c0 7088 return output_move_double (operands, true, NULL);
d51f92df 7089 }
7090 "
359a6e9f 7091 [(set_attr "length" "8,12,16,8,8")
1b7da4ac 7092 (set_attr "type" "multiple,multiple,multiple,load2,store2")
42e1de19 7093 (set_attr "arm_pool_range" "*,*,*,1020,*")
7094 (set_attr "thumb2_pool_range" "*,*,*,1018,*")
8848d797 7095 (set_attr "arm_neg_pool_range" "*,*,*,1004,*")
cde1623a 7096 (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
cffb2a26 7097)
b11cae9e 7098\f
b11cae9e 7099
9c08d1fa 7100;; load- and store-multiple insns
7101;; The arm can load/store any set of registers, provided that they are in
320ea44d 7102;; ascending order, but these expanders assume a contiguous set.
b11cae9e 7103
9c08d1fa 7104(define_expand "load_multiple"
7105 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
7106 (match_operand:SI 1 "" ""))
7107 (use (match_operand:SI 2 "" ""))])]
25f905c2 7108 "TARGET_32BIT"
9580c25f 7109{
7110 HOST_WIDE_INT offset = 0;
7111
bd5b4116 7112 /* Support only fixed point registers. */
0438d37f 7113 if (!CONST_INT_P (operands[2])
6e628811 7114 || INTVAL (operands[2]) > MAX_LDM_STM_OPS
9c08d1fa 7115 || INTVAL (operands[2]) < 2
0438d37f 7116 || !MEM_P (operands[1])
7117 || !REG_P (operands[0])
bd5b4116 7118 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
7119 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 7120 FAIL;
7121
7122 operands[3]
320ea44d 7123 = arm_gen_load_multiple (arm_regs_in_sequence + REGNO (operands[0]),
7124 INTVAL (operands[2]),
f082f1c4 7125 force_reg (SImode, XEXP (operands[1], 0)),
320ea44d 7126 FALSE, operands[1], &offset);
9580c25f 7127})
b11cae9e 7128
9c08d1fa 7129(define_expand "store_multiple"
7130 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
7131 (match_operand:SI 1 "" ""))
7132 (use (match_operand:SI 2 "" ""))])]
25f905c2 7133 "TARGET_32BIT"
9580c25f 7134{
7135 HOST_WIDE_INT offset = 0;
7136
674a8f0b 7137 /* Support only fixed point registers. */
0438d37f 7138 if (!CONST_INT_P (operands[2])
6e628811 7139 || INTVAL (operands[2]) > MAX_LDM_STM_OPS
9c08d1fa 7140 || INTVAL (operands[2]) < 2
0438d37f 7141 || !REG_P (operands[1])
7142 || !MEM_P (operands[0])
bd5b4116 7143 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
7144 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 7145 FAIL;
7146
7147 operands[3]
320ea44d 7148 = arm_gen_store_multiple (arm_regs_in_sequence + REGNO (operands[1]),
7149 INTVAL (operands[2]),
f082f1c4 7150 force_reg (SImode, XEXP (operands[0], 0)),
320ea44d 7151 FALSE, operands[0], &offset);
9580c25f 7152})
b11cae9e 7153
9c08d1fa 7154
e34ebfca 7155(define_expand "setmemsi"
7156 [(match_operand:BLK 0 "general_operand" "")
7157 (match_operand:SI 1 "const_int_operand" "")
7158 (match_operand:SI 2 "const_int_operand" "")
7159 (match_operand:SI 3 "const_int_operand" "")]
7160 "TARGET_32BIT"
7161{
7162 if (arm_gen_setmem (operands))
7163 DONE;
7164
7165 FAIL;
7166})
7167
7168
9c08d1fa 7169;; Move a block of memory if it is word aligned and MORE than 2 words long.
7170;; We could let this apply for blocks of less than this, but it clobbers so
7171;; many registers that there is then probably a better way.
7172
008c057d 7173(define_expand "movmemqi"
34191dd1 7174 [(match_operand:BLK 0 "general_operand" "")
7175 (match_operand:BLK 1 "general_operand" "")
7176 (match_operand:SI 2 "const_int_operand" "")
7177 (match_operand:SI 3 "const_int_operand" "")]
ae51a965 7178 ""
9c08d1fa 7179 "
25f905c2 7180 if (TARGET_32BIT)
cffb2a26 7181 {
ae51a965 7182 if (TARGET_LDRD && current_tune->prefer_ldrd_strd
7183 && !optimize_function_for_size_p (cfun))
7184 {
7185 if (gen_movmem_ldrd_strd (operands))
7186 DONE;
7187 FAIL;
7188 }
7189
008c057d 7190 if (arm_gen_movmemqi (operands))
cffb2a26 7191 DONE;
7192 FAIL;
7193 }
25f905c2 7194 else /* TARGET_THUMB1 */
cffb2a26 7195 {
7196 if ( INTVAL (operands[3]) != 4
7197 || INTVAL (operands[2]) > 48)
7198 FAIL;
7199
008c057d 7200 thumb_expand_movmemqi (operands);
cffb2a26 7201 DONE;
7202 }
7203 "
7204)
9c08d1fa 7205\f
b11cae9e 7206
341940e8 7207;; Compare & branch insns
8d232dc7 7208;; The range calculations are based as follows:
341940e8 7209;; For forward branches, the address calculation returns the address of
7210;; the next instruction. This is 2 beyond the branch instruction.
7211;; For backward branches, the address calculation returns the address of
7212;; the first instruction in this pattern (cmp). This is 2 before the branch
7213;; instruction for the shortest sequence, and 4 before the branch instruction
7214;; if we have to jump around an unconditional branch.
7215;; To the basic branch range the PC offset must be added (this is +4).
7216;; So for forward branches we have
7217;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
7218;; And for backward branches we have
7219;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
7220;;
7221;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
7222;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
cffb2a26 7223
aeac46d4 7224(define_expand "cbranchsi4"
7225 [(set (pc) (if_then_else
aa06947a 7226 (match_operator 0 "expandable_comparison_operator"
aeac46d4 7227 [(match_operand:SI 1 "s_register_operand" "")
7228 (match_operand:SI 2 "nonmemory_operand" "")])
7229 (label_ref (match_operand 3 "" ""))
7230 (pc)))]
f9aa4160 7231 "TARGET_EITHER"
aeac46d4 7232 "
74f4459c 7233 if (!TARGET_THUMB1)
7234 {
f9aa4160 7235 if (!arm_validize_comparison (&operands[0], &operands[1], &operands[2]))
7236 FAIL;
74f4459c 7237 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
7238 operands[3]));
7239 DONE;
7240 }
25f905c2 7241 if (thumb1_cmpneg_operand (operands[2], SImode))
aeac46d4 7242 {
7243 emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
7244 operands[3], operands[0]));
7245 DONE;
7246 }
25f905c2 7247 if (!thumb1_cmp_operand (operands[2], SImode))
aeac46d4 7248 operands[2] = force_reg (SImode, operands[2]);
7249 ")
7250
74f4459c 7251(define_expand "cbranchsf4"
7252 [(set (pc) (if_then_else
aa06947a 7253 (match_operator 0 "expandable_comparison_operator"
74f4459c 7254 [(match_operand:SF 1 "s_register_operand" "")
d7216193 7255 (match_operand:SF 2 "vfp_compare_operand" "")])
74f4459c 7256 (label_ref (match_operand 3 "" ""))
7257 (pc)))]
7258 "TARGET_32BIT && TARGET_HARD_FLOAT"
7259 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
7260 operands[3])); DONE;"
7261)
7262
7263(define_expand "cbranchdf4"
7264 [(set (pc) (if_then_else
aa06947a 7265 (match_operator 0 "expandable_comparison_operator"
74f4459c 7266 [(match_operand:DF 1 "s_register_operand" "")
d7216193 7267 (match_operand:DF 2 "vfp_compare_operand" "")])
74f4459c 7268 (label_ref (match_operand 3 "" ""))
7269 (pc)))]
a50d7267 7270 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
74f4459c 7271 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
7272 operands[3])); DONE;"
7273)
7274
74f4459c 7275(define_expand "cbranchdi4"
7276 [(set (pc) (if_then_else
aa06947a 7277 (match_operator 0 "expandable_comparison_operator"
b8eae306 7278 [(match_operand:DI 1 "s_register_operand" "")
a8045a4f 7279 (match_operand:DI 2 "cmpdi_operand" "")])
74f4459c 7280 (label_ref (match_operand 3 "" ""))
7281 (pc)))]
a8045a4f 7282 "TARGET_32BIT"
7283 "{
0438d37f 7284 if (!arm_validize_comparison (&operands[0], &operands[1], &operands[2]))
f9aa4160 7285 FAIL;
7286 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
a8045a4f 7287 operands[3]));
7288 DONE;
7289 }"
74f4459c 7290)
7291
9c08d1fa 7292;; Comparison and test insns
7293
cffb2a26 7294(define_insn "*arm_cmpsi_insn"
bd5b4116 7295 [(set (reg:CC CC_REGNUM)
f9f234ec 7296 (compare:CC (match_operand:SI 0 "s_register_operand" "l,r,r,r,r")
7297 (match_operand:SI 1 "arm_add_operand" "Py,r,r,I,L")))]
25f905c2 7298 "TARGET_32BIT"
5565501b 7299 "@
a6864a24 7300 cmp%?\\t%0, %1
7301 cmp%?\\t%0, %1
aea4c774 7302 cmp%?\\t%0, %1
f9f234ec 7303 cmp%?\\t%0, %1
aea4c774 7304 cmn%?\\t%0, #%n1"
a6864a24 7305 [(set_attr "conds" "set")
f9f234ec 7306 (set_attr "arch" "t2,t2,any,any,any")
7307 (set_attr "length" "2,2,4,4,4")
65f68e55 7308 (set_attr "predicable" "yes")
f9f234ec 7309 (set_attr "predicable_short_it" "yes,yes,yes,no,no")
112eda6f 7310 (set_attr "type" "alus_imm,alus_sreg,alus_sreg,alus_imm,alus_imm")]
cffb2a26 7311)
b11cae9e 7312
d5d4dc8d 7313(define_insn "*cmpsi_shiftsi"
bd5b4116 7314 [(set (reg:CC CC_REGNUM)
d82e788e 7315 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r,r")
cffb2a26 7316 (match_operator:SI 3 "shift_operator"
d82e788e 7317 [(match_operand:SI 1 "s_register_operand" "r,r,r")
7318 (match_operand:SI 2 "shift_amount_operand" "M,r,M")])))]
d5d4dc8d 7319 "TARGET_32BIT"
f9f234ec 7320 "cmp\\t%0, %1%S3"
344495ea 7321 [(set_attr "conds" "set")
331beb1a 7322 (set_attr "shift" "1")
d82e788e 7323 (set_attr "arch" "32,a,a")
282b4c75 7324 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
b11cae9e 7325
d5d4dc8d 7326(define_insn "*cmpsi_shiftsi_swp"
bd5b4116 7327 [(set (reg:CC_SWP CC_REGNUM)
aea4c774 7328 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
d82e788e 7329 [(match_operand:SI 1 "s_register_operand" "r,r,r")
7330 (match_operand:SI 2 "shift_amount_operand" "M,r,M")])
7331 (match_operand:SI 0 "s_register_operand" "r,r,r")))]
d5d4dc8d 7332 "TARGET_32BIT"
aea4c774 7333 "cmp%?\\t%0, %1%S3"
344495ea 7334 [(set_attr "conds" "set")
331beb1a 7335 (set_attr "shift" "1")
d82e788e 7336 (set_attr "arch" "32,a,a")
282b4c75 7337 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
b11cae9e 7338
25f905c2 7339(define_insn "*arm_cmpsi_negshiftsi_si"
aed179ae 7340 [(set (reg:CC_Z CC_REGNUM)
7341 (compare:CC_Z
7342 (neg:SI (match_operator:SI 1 "shift_operator"
7343 [(match_operand:SI 2 "s_register_operand" "r")
7344 (match_operand:SI 3 "reg_or_int_operand" "rM")]))
7345 (match_operand:SI 0 "s_register_operand" "r")))]
cffb2a26 7346 "TARGET_ARM"
aed179ae 7347 "cmn%?\\t%0, %2%S1"
344495ea 7348 [(set_attr "conds" "set")
aed179ae 7349 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
d82e788e 7350 (const_string "alus_shift_imm")
7351 (const_string "alus_shift_reg")))
596e5e8f 7352 (set_attr "predicable" "yes")]
0d66636f 7353)
b11cae9e 7354
a8045a4f 7355;; DImode comparisons. The generic code generates branches that
7356;; if-conversion can not reduce to a conditional compare, so we do
7357;; that directly.
7358
ba6a3b2f 7359(define_insn_and_split "*arm_cmpdi_insn"
a8045a4f 7360 [(set (reg:CC_NCV CC_REGNUM)
7361 (compare:CC_NCV (match_operand:DI 0 "s_register_operand" "r")
7362 (match_operand:DI 1 "arm_di_operand" "rDi")))
7363 (clobber (match_scratch:SI 2 "=r"))]
b805622c 7364 "TARGET_32BIT"
ba6a3b2f 7365 "#" ; "cmp\\t%Q0, %Q1\;sbcs\\t%2, %R0, %R1"
7366 "&& reload_completed"
7367 [(set (reg:CC CC_REGNUM)
7368 (compare:CC (match_dup 0) (match_dup 1)))
7369 (parallel [(set (reg:CC CC_REGNUM)
7370 (compare:CC (match_dup 3) (match_dup 4)))
7371 (set (match_dup 2)
7372 (minus:SI (match_dup 5)
7373 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))])]
7374 {
7375 operands[3] = gen_highpart (SImode, operands[0]);
7376 operands[0] = gen_lowpart (SImode, operands[0]);
7377 if (CONST_INT_P (operands[1]))
7378 {
7379 operands[4] = GEN_INT (~INTVAL (gen_highpart_mode (SImode,
7380 DImode,
7381 operands[1])));
7382 operands[5] = gen_rtx_PLUS (SImode, operands[3], operands[4]);
7383 }
7384 else
7385 {
7386 operands[4] = gen_highpart (SImode, operands[1]);
7387 operands[5] = gen_rtx_MINUS (SImode, operands[3], operands[4]);
7388 }
7389 operands[1] = gen_lowpart (SImode, operands[1]);
7390 operands[2] = gen_lowpart (SImode, operands[2]);
7391 }
a8045a4f 7392 [(set_attr "conds" "set")
1b7da4ac 7393 (set_attr "length" "8")
7394 (set_attr "type" "multiple")]
a8045a4f 7395)
7396
ba6a3b2f 7397(define_insn_and_split "*arm_cmpdi_unsigned"
a8045a4f 7398 [(set (reg:CC_CZ CC_REGNUM)
1a86364b 7399 (compare:CC_CZ (match_operand:DI 0 "s_register_operand" "l,r,r,r")
7400 (match_operand:DI 1 "arm_di_operand" "Py,r,Di,rDi")))]
7c36fe71 7401
48a98053 7402 "TARGET_32BIT"
ba6a3b2f 7403 "#" ; "cmp\\t%R0, %R1\;it eq\;cmpeq\\t%Q0, %Q1"
7404 "&& reload_completed"
7405 [(set (reg:CC CC_REGNUM)
7406 (compare:CC (match_dup 2) (match_dup 3)))
7407 (cond_exec (eq:SI (reg:CC CC_REGNUM) (const_int 0))
7408 (set (reg:CC CC_REGNUM)
7409 (compare:CC (match_dup 0) (match_dup 1))))]
7410 {
7411 operands[2] = gen_highpart (SImode, operands[0]);
7412 operands[0] = gen_lowpart (SImode, operands[0]);
7413 if (CONST_INT_P (operands[1]))
7414 operands[3] = gen_highpart_mode (SImode, DImode, operands[1]);
7415 else
7416 operands[3] = gen_highpart (SImode, operands[1]);
7417 operands[1] = gen_lowpart (SImode, operands[1]);
7418 }
a8045a4f 7419 [(set_attr "conds" "set")
1a86364b 7420 (set_attr "enabled_for_depr_it" "yes,yes,no,*")
7421 (set_attr "arch" "t2,t2,t2,a")
7422 (set_attr "length" "6,6,10,8")
1b7da4ac 7423 (set_attr "type" "multiple")]
a8045a4f 7424)
7425
7426(define_insn "*arm_cmpdi_zero"
7427 [(set (reg:CC_Z CC_REGNUM)
7428 (compare:CC_Z (match_operand:DI 0 "s_register_operand" "r")
7429 (const_int 0)))
7430 (clobber (match_scratch:SI 1 "=r"))]
7431 "TARGET_32BIT"
3ef90e77 7432 "orrs%?\\t%1, %Q0, %R0"
1b7da4ac 7433 [(set_attr "conds" "set")
7434 (set_attr "type" "logics_reg")]
a8045a4f 7435)
7436
9c08d1fa 7437; This insn allows redundant compares to be removed by cse, nothing should
7438; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
7439; is deleted later on. The match_dup will match the mode here, so that
7440; mode changes of the condition codes aren't lost by this even though we don't
7441; specify what they are.
7442
8a18b90c 7443(define_insn "*deleted_compare"
9c08d1fa 7444 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
25f905c2 7445 "TARGET_32BIT"
40dbec34 7446 "\\t%@ deleted compare"
cffb2a26 7447 [(set_attr "conds" "set")
1b7da4ac 7448 (set_attr "length" "0")
7449 (set_attr "type" "no_insn")]
cffb2a26 7450)
9c08d1fa 7451
7452\f
7453;; Conditional branch insns
7454
74f4459c 7455(define_expand "cbranch_cc"
9c08d1fa 7456 [(set (pc)
74f4459c 7457 (if_then_else (match_operator 0 "" [(match_operand 1 "" "")
7458 (match_operand 2 "" "")])
7459 (label_ref (match_operand 3 "" ""))
9c08d1fa 7460 (pc)))]
25f905c2 7461 "TARGET_32BIT"
74f4459c 7462 "operands[1] = arm_gen_compare_reg (GET_CODE (operands[0]),
e1b93706 7463 operands[1], operands[2], NULL_RTX);
74f4459c 7464 operands[2] = const0_rtx;"
8fa3ba89 7465)
7466
7467;;
7468;; Patterns to match conditional branch insns.
7469;;
7470
ffcc986d 7471(define_insn "arm_cond_branch"
9c08d1fa 7472 [(set (pc)
8fa3ba89 7473 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 7474 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 7475 (label_ref (match_operand 0 "" ""))
7476 (pc)))]
25f905c2 7477 "TARGET_32BIT"
d75350ce 7478 "*
9c08d1fa 7479 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 7480 {
7481 arm_ccfsm_state += 2;
7482 return \"\";
7483 }
e2348bcb 7484 return \"b%d1\\t%l0\";
cffb2a26 7485 "
a2cd141b 7486 [(set_attr "conds" "use")
a6864a24 7487 (set_attr "type" "branch")
7488 (set (attr "length")
7489 (if_then_else
0bf497f5 7490 (and (match_test "TARGET_THUMB2")
a6864a24 7491 (and (ge (minus (match_dup 0) (pc)) (const_int -250))
7492 (le (minus (match_dup 0) (pc)) (const_int 256))))
7493 (const_int 2)
7494 (const_int 4)))]
cffb2a26 7495)
d75350ce 7496
cffb2a26 7497(define_insn "*arm_cond_branch_reversed"
9c08d1fa 7498 [(set (pc)
8fa3ba89 7499 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 7500 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 7501 (pc)
7502 (label_ref (match_operand 0 "" ""))))]
25f905c2 7503 "TARGET_32BIT"
d75350ce 7504 "*
9c08d1fa 7505 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 7506 {
7507 arm_ccfsm_state += 2;
7508 return \"\";
7509 }
e2348bcb 7510 return \"b%D1\\t%l0\";
cffb2a26 7511 "
a2cd141b 7512 [(set_attr "conds" "use")
a6864a24 7513 (set_attr "type" "branch")
7514 (set (attr "length")
7515 (if_then_else
0bf497f5 7516 (and (match_test "TARGET_THUMB2")
a6864a24 7517 (and (ge (minus (match_dup 0) (pc)) (const_int -250))
7518 (le (minus (match_dup 0) (pc)) (const_int 256))))
7519 (const_int 2)
7520 (const_int 4)))]
cffb2a26 7521)
7522
b11cae9e 7523\f
9c08d1fa 7524
7525; scc insns
7526
74f4459c 7527(define_expand "cstore_cc"
7db9af5d 7528 [(set (match_operand:SI 0 "s_register_operand" "")
74f4459c 7529 (match_operator:SI 1 "" [(match_operand 2 "" "")
7530 (match_operand 3 "" "")]))]
25f905c2 7531 "TARGET_32BIT"
74f4459c 7532 "operands[2] = arm_gen_compare_reg (GET_CODE (operands[1]),
e1b93706 7533 operands[2], operands[3], NULL_RTX);
74f4459c 7534 operands[3] = const0_rtx;"
8fa3ba89 7535)
7536
a3b84066 7537(define_insn_and_split "*mov_scc"
9c08d1fa 7538 [(set (match_operand:SI 0 "s_register_operand" "=r")
ff74dd54 7539 (match_operator:SI 1 "arm_comparison_operator_mode"
8a18b90c 7540 [(match_operand 2 "cc_register" "") (const_int 0)]))]
cffb2a26 7541 "TARGET_ARM"
a3b84066 7542 "#" ; "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
7543 "TARGET_ARM"
7544 [(set (match_dup 0)
7545 (if_then_else:SI (match_dup 1)
7546 (const_int 1)
7547 (const_int 0)))]
7548 ""
cffb2a26 7549 [(set_attr "conds" "use")
1b7da4ac 7550 (set_attr "length" "8")
7551 (set_attr "type" "multiple")]
cffb2a26 7552)
9c08d1fa 7553
a3b84066 7554(define_insn_and_split "*mov_negscc"
9c08d1fa 7555 [(set (match_operand:SI 0 "s_register_operand" "=r")
ff74dd54 7556 (neg:SI (match_operator:SI 1 "arm_comparison_operator_mode"
8a18b90c 7557 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 7558 "TARGET_ARM"
a3b84066 7559 "#" ; "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
7560 "TARGET_ARM"
7561 [(set (match_dup 0)
7562 (if_then_else:SI (match_dup 1)
7563 (match_dup 3)
7564 (const_int 0)))]
7565 {
7566 operands[3] = GEN_INT (~0);
7567 }
cffb2a26 7568 [(set_attr "conds" "use")
1b7da4ac 7569 (set_attr "length" "8")
7570 (set_attr "type" "multiple")]
cffb2a26 7571)
9c08d1fa 7572
a3b84066 7573(define_insn_and_split "*mov_notscc"
9c08d1fa 7574 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7575 (not:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7576 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 7577 "TARGET_ARM"
a3b84066 7578 "#" ; "mvn%D1\\t%0, #0\;mvn%d1\\t%0, #1"
7579 "TARGET_ARM"
7580 [(set (match_dup 0)
7581 (if_then_else:SI (match_dup 1)
7582 (match_dup 3)
7583 (match_dup 4)))]
7584 {
7585 operands[3] = GEN_INT (~1);
7586 operands[4] = GEN_INT (~0);
7587 }
cffb2a26 7588 [(set_attr "conds" "use")
1b7da4ac 7589 (set_attr "length" "8")
7590 (set_attr "type" "multiple")]
cffb2a26 7591)
9c08d1fa 7592
595d88b5 7593(define_expand "cstoresi4"
7594 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 7595 (match_operator:SI 1 "expandable_comparison_operator"
595d88b5 7596 [(match_operand:SI 2 "s_register_operand" "")
7597 (match_operand:SI 3 "reg_or_int_operand" "")]))]
74f4459c 7598 "TARGET_32BIT || TARGET_THUMB1"
595d88b5 7599 "{
7600 rtx op3, scratch, scratch2;
7601
74f4459c 7602 if (!TARGET_THUMB1)
7603 {
7604 if (!arm_add_operand (operands[3], SImode))
7605 operands[3] = force_reg (SImode, operands[3]);
7606 emit_insn (gen_cstore_cc (operands[0], operands[1],
7607 operands[2], operands[3]));
7608 DONE;
7609 }
7610
595d88b5 7611 if (operands[3] == const0_rtx)
7612 {
7613 switch (GET_CODE (operands[1]))
7614 {
7615 case EQ:
25f905c2 7616 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], operands[2]));
595d88b5 7617 break;
7618
7619 case NE:
25f905c2 7620 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], operands[2]));
595d88b5 7621 break;
7622
7623 case LE:
7624 scratch = expand_binop (SImode, add_optab, operands[2], constm1_rtx,
7625 NULL_RTX, 0, OPTAB_WIDEN);
7626 scratch = expand_binop (SImode, ior_optab, operands[2], scratch,
7627 NULL_RTX, 0, OPTAB_WIDEN);
7628 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7629 operands[0], 1, OPTAB_WIDEN);
7630 break;
7631
7632 case GE:
7633 scratch = expand_unop (SImode, one_cmpl_optab, operands[2],
7634 NULL_RTX, 1);
7635 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7636 NULL_RTX, 1, OPTAB_WIDEN);
7637 break;
7638
7639 case GT:
7640 scratch = expand_binop (SImode, ashr_optab, operands[2],
7641 GEN_INT (31), NULL_RTX, 0, OPTAB_WIDEN);
7642 scratch = expand_binop (SImode, sub_optab, scratch, operands[2],
7643 NULL_RTX, 0, OPTAB_WIDEN);
7644 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31), operands[0],
7645 0, OPTAB_WIDEN);
7646 break;
7647
7648 /* LT is handled by generic code. No need for unsigned with 0. */
7649 default:
7650 FAIL;
7651 }
7652 DONE;
7653 }
7654
7655 switch (GET_CODE (operands[1]))
7656 {
7657 case EQ:
7658 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7659 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7660 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], scratch));
595d88b5 7661 break;
7662
7663 case NE:
7664 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7665 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7666 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], scratch));
595d88b5 7667 break;
7668
7669 case LE:
7670 op3 = force_reg (SImode, operands[3]);
7671
7672 scratch = expand_binop (SImode, lshr_optab, operands[2], GEN_INT (31),
7673 NULL_RTX, 1, OPTAB_WIDEN);
7674 scratch2 = expand_binop (SImode, ashr_optab, op3, GEN_INT (31),
7675 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7676 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
595d88b5 7677 op3, operands[2]));
7678 break;
7679
7680 case GE:
7681 op3 = operands[3];
25f905c2 7682 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7683 op3 = force_reg (SImode, op3);
7684 scratch = expand_binop (SImode, ashr_optab, operands[2], GEN_INT (31),
7685 NULL_RTX, 0, OPTAB_WIDEN);
7686 scratch2 = expand_binop (SImode, lshr_optab, op3, GEN_INT (31),
7687 NULL_RTX, 1, OPTAB_WIDEN);
25f905c2 7688 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
595d88b5 7689 operands[2], op3));
7690 break;
7691
7692 case LEU:
7693 op3 = force_reg (SImode, operands[3]);
7694 scratch = force_reg (SImode, const0_rtx);
25f905c2 7695 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
595d88b5 7696 op3, operands[2]));
7697 break;
7698
7699 case GEU:
7700 op3 = operands[3];
25f905c2 7701 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7702 op3 = force_reg (SImode, op3);
7703 scratch = force_reg (SImode, const0_rtx);
25f905c2 7704 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
595d88b5 7705 operands[2], op3));
7706 break;
7707
7708 case LTU:
7709 op3 = operands[3];
25f905c2 7710 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7711 op3 = force_reg (SImode, op3);
7712 scratch = gen_reg_rtx (SImode);
408b7ae5 7713 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], operands[2], op3));
595d88b5 7714 break;
7715
7716 case GTU:
7717 op3 = force_reg (SImode, operands[3]);
7718 scratch = gen_reg_rtx (SImode);
408b7ae5 7719 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], op3, operands[2]));
595d88b5 7720 break;
7721
7722 /* No good sequences for GT, LT. */
7723 default:
7724 FAIL;
7725 }
7726 DONE;
7727}")
7728
9854d864 7729(define_expand "cstorehf4"
7730 [(set (match_operand:SI 0 "s_register_operand")
7731 (match_operator:SI 1 "expandable_comparison_operator"
7732 [(match_operand:HF 2 "s_register_operand")
d7216193 7733 (match_operand:HF 3 "vfp_compare_operand")]))]
9854d864 7734 "TARGET_VFP_FP16INST"
7735 {
7736 if (!arm_validize_comparison (&operands[1],
7737 &operands[2],
7738 &operands[3]))
7739 FAIL;
7740
7741 emit_insn (gen_cstore_cc (operands[0], operands[1],
7742 operands[2], operands[3]));
7743 DONE;
7744 }
7745)
7746
74f4459c 7747(define_expand "cstoresf4"
7748 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 7749 (match_operator:SI 1 "expandable_comparison_operator"
74f4459c 7750 [(match_operand:SF 2 "s_register_operand" "")
d7216193 7751 (match_operand:SF 3 "vfp_compare_operand" "")]))]
74f4459c 7752 "TARGET_32BIT && TARGET_HARD_FLOAT"
7753 "emit_insn (gen_cstore_cc (operands[0], operands[1],
7754 operands[2], operands[3])); DONE;"
7755)
7756
7757(define_expand "cstoredf4"
7758 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 7759 (match_operator:SI 1 "expandable_comparison_operator"
74f4459c 7760 [(match_operand:DF 2 "s_register_operand" "")
d7216193 7761 (match_operand:DF 3 "vfp_compare_operand" "")]))]
d63ed457 7762 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
74f4459c 7763 "emit_insn (gen_cstore_cc (operands[0], operands[1],
7764 operands[2], operands[3])); DONE;"
7765)
7766
74f4459c 7767(define_expand "cstoredi4"
7768 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 7769 (match_operator:SI 1 "expandable_comparison_operator"
b8eae306 7770 [(match_operand:DI 2 "s_register_operand" "")
a8045a4f 7771 (match_operand:DI 3 "cmpdi_operand" "")]))]
7772 "TARGET_32BIT"
7773 "{
f9aa4160 7774 if (!arm_validize_comparison (&operands[1],
7775 &operands[2],
7776 &operands[3]))
7777 FAIL;
7778 emit_insn (gen_cstore_cc (operands[0], operands[1], operands[2],
a8045a4f 7779 operands[3]));
7780 DONE;
7781 }"
74f4459c 7782)
7783
9c08d1fa 7784\f
39b5e676 7785;; Conditional move insns
7786
7787(define_expand "movsicc"
8a18b90c 7788 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 7789 (if_then_else:SI (match_operand 1 "expandable_comparison_operator" "")
aea4c774 7790 (match_operand:SI 2 "arm_not_operand" "")
8a18b90c 7791 (match_operand:SI 3 "arm_not_operand" "")))]
25f905c2 7792 "TARGET_32BIT"
39b5e676 7793 "
215b30b3 7794 {
f9aa4160 7795 enum rtx_code code;
278b301d 7796 rtx ccreg;
7797
f9aa4160 7798 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
9854d864 7799 &XEXP (operands[1], 1)))
278b301d 7800 FAIL;
9854d864 7801
7802 code = GET_CODE (operands[1]);
7803 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
7804 XEXP (operands[1], 1), NULL_RTX);
7805 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7806 }"
7807)
7808
7809(define_expand "movhfcc"
7810 [(set (match_operand:HF 0 "s_register_operand")
7811 (if_then_else:HF (match_operand 1 "arm_cond_move_operator")
7812 (match_operand:HF 2 "s_register_operand")
7813 (match_operand:HF 3 "s_register_operand")))]
7814 "TARGET_VFP_FP16INST"
7815 "
7816 {
7817 enum rtx_code code = GET_CODE (operands[1]);
7818 rtx ccreg;
7819
7820 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
7821 &XEXP (operands[1], 1)))
7822 FAIL;
7823
f9aa4160 7824 code = GET_CODE (operands[1]);
74f4459c 7825 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
e1b93706 7826 XEXP (operands[1], 1), NULL_RTX);
29bb088d 7827 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7828 }"
7829)
39b5e676 7830
7831(define_expand "movsfcc"
8a18b90c 7832 [(set (match_operand:SF 0 "s_register_operand" "")
4df97ffc 7833 (if_then_else:SF (match_operand 1 "arm_cond_move_operator" "")
8a18b90c 7834 (match_operand:SF 2 "s_register_operand" "")
d86c91f6 7835 (match_operand:SF 3 "s_register_operand" "")))]
19f6bf8d 7836 "TARGET_32BIT && TARGET_HARD_FLOAT"
39b5e676 7837 "
215b30b3 7838 {
7839 enum rtx_code code = GET_CODE (operands[1]);
7840 rtx ccreg;
f082f1c4 7841
9854d864 7842 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
f9aa4160 7843 &XEXP (operands[1], 1)))
7844 FAIL;
39b5e676 7845
f9aa4160 7846 code = GET_CODE (operands[1]);
74f4459c 7847 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
e1b93706 7848 XEXP (operands[1], 1), NULL_RTX);
29bb088d 7849 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7850 }"
7851)
39b5e676 7852
7853(define_expand "movdfcc"
8a18b90c 7854 [(set (match_operand:DF 0 "s_register_operand" "")
4df97ffc 7855 (if_then_else:DF (match_operand 1 "arm_cond_move_operator" "")
8a18b90c 7856 (match_operand:DF 2 "s_register_operand" "")
d86c91f6 7857 (match_operand:DF 3 "s_register_operand" "")))]
994606f8 7858 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
39b5e676 7859 "
215b30b3 7860 {
7861 enum rtx_code code = GET_CODE (operands[1]);
278b301d 7862 rtx ccreg;
39b5e676 7863
f9aa4160 7864 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
7865 &XEXP (operands[1], 1)))
7866 FAIL;
7867 code = GET_CODE (operands[1]);
74f4459c 7868 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
e1b93706 7869 XEXP (operands[1], 1), NULL_RTX);
29bb088d 7870 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7871 }"
7872)
39b5e676 7873
91cb50d2 7874(define_insn "*cmov<mode>"
7875 [(set (match_operand:SDF 0 "s_register_operand" "=<F_constraint>")
7876 (if_then_else:SDF (match_operator 1 "arm_vsel_comparison_operator"
7877 [(match_operand 2 "cc_register" "") (const_int 0)])
7878 (match_operand:SDF 3 "s_register_operand"
7879 "<F_constraint>")
7880 (match_operand:SDF 4 "s_register_operand"
7881 "<F_constraint>")))]
7882 "TARGET_HARD_FLOAT && TARGET_FPU_ARMV8 <vfp_double_cond>"
7883 "*
7884 {
7885 enum arm_cond_code code = maybe_get_arm_condition_code (operands[1]);
7886 switch (code)
7887 {
7888 case ARM_GE:
7889 case ARM_GT:
7890 case ARM_EQ:
7891 case ARM_VS:
7892 return \"vsel%d1.<V_if_elem>\\t%<V_reg>0, %<V_reg>3, %<V_reg>4\";
7893 case ARM_LT:
7894 case ARM_LE:
7895 case ARM_NE:
7896 case ARM_VC:
7897 return \"vsel%D1.<V_if_elem>\\t%<V_reg>0, %<V_reg>4, %<V_reg>3\";
7898 default:
7899 gcc_unreachable ();
7900 }
7901 return \"\";
7902 }"
7903 [(set_attr "conds" "use")
6664d308 7904 (set_attr "type" "fcsel")]
91cb50d2 7905)
7906
9854d864 7907(define_insn "*cmovhf"
7908 [(set (match_operand:HF 0 "s_register_operand" "=t")
7909 (if_then_else:HF (match_operator 1 "arm_vsel_comparison_operator"
7910 [(match_operand 2 "cc_register" "") (const_int 0)])
7911 (match_operand:HF 3 "s_register_operand" "t")
7912 (match_operand:HF 4 "s_register_operand" "t")))]
7913 "TARGET_VFP_FP16INST"
7914 "*
7915 {
7916 enum arm_cond_code code = maybe_get_arm_condition_code (operands[1]);
7917 switch (code)
7918 {
7919 case ARM_GE:
7920 case ARM_GT:
7921 case ARM_EQ:
7922 case ARM_VS:
7923 return \"vsel%d1.f16\\t%0, %3, %4\";
7924 case ARM_LT:
7925 case ARM_LE:
7926 case ARM_NE:
7927 case ARM_VC:
7928 return \"vsel%D1.f16\\t%0, %4, %3\";
7929 default:
7930 gcc_unreachable ();
7931 }
7932 return \"\";
7933 }"
7934 [(set_attr "conds" "use")
7935 (set_attr "type" "fcsel")]
7936)
7937
190efb17 7938(define_insn_and_split "*movsicc_insn"
f082f1c4 7939 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
8a18b90c 7940 (if_then_else:SI
8fa3ba89 7941 (match_operator 3 "arm_comparison_operator"
8a18b90c 7942 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 7943 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
7944 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
cffb2a26 7945 "TARGET_ARM"
39b5e676 7946 "@
8a18b90c 7947 mov%D3\\t%0, %2
7948 mvn%D3\\t%0, #%B2
f082f1c4 7949 mov%d3\\t%0, %1
7950 mvn%d3\\t%0, #%B1
190efb17 7951 #
7952 #
7953 #
7954 #"
7955 ; alt4: mov%d3\\t%0, %1\;mov%D3\\t%0, %2
7956 ; alt5: mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
7957 ; alt6: mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
7958 ; alt7: mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
7959 "&& reload_completed"
7960 [(const_int 0)]
7961 {
7962 enum rtx_code rev_code;
3754d046 7963 machine_mode mode;
190efb17 7964 rtx rev_cond;
7965
7966 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
7967 operands[3],
d1f9b275 7968 gen_rtx_SET (operands[0], operands[1])));
190efb17 7969
7970 rev_code = GET_CODE (operands[3]);
7971 mode = GET_MODE (operands[4]);
7972 if (mode == CCFPmode || mode == CCFPEmode)
7973 rev_code = reverse_condition_maybe_unordered (rev_code);
7974 else
7975 rev_code = reverse_condition (rev_code);
7976
7977 rev_cond = gen_rtx_fmt_ee (rev_code,
7978 VOIDmode,
7979 operands[4],
7980 const0_rtx);
7981 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
7982 rev_cond,
d1f9b275 7983 gen_rtx_SET (operands[0], operands[2])));
190efb17 7984 DONE;
7985 }
f082f1c4 7986 [(set_attr "length" "4,4,4,4,8,8,8,8")
d2a518d1 7987 (set_attr "conds" "use")
65f68e55 7988 (set_attr_alternative "type"
7989 [(if_then_else (match_operand 2 "const_int_operand" "")
1aed5204 7990 (const_string "mov_imm")
7991 (const_string "mov_reg"))
7992 (const_string "mvn_imm")
65f68e55 7993 (if_then_else (match_operand 1 "const_int_operand" "")
1aed5204 7994 (const_string "mov_imm")
7995 (const_string "mov_reg"))
7996 (const_string "mvn_imm")
282b4c75 7997 (const_string "multiple")
7998 (const_string "multiple")
7999 (const_string "multiple")
8000 (const_string "multiple")])]
215b30b3 8001)
39b5e676 8002
39b5e676 8003(define_insn "*movsfcc_soft_insn"
f082f1c4 8004 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
8fa3ba89 8005 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
8a18b90c 8006 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 8007 (match_operand:SF 1 "s_register_operand" "0,r")
8008 (match_operand:SF 2 "s_register_operand" "r,0")))]
cffb2a26 8009 "TARGET_ARM && TARGET_SOFT_FLOAT"
f082f1c4 8010 "@
8011 mov%D3\\t%0, %2
8012 mov%d3\\t%0, %1"
d2a518d1 8013 [(set_attr "conds" "use")
1aed5204 8014 (set_attr "type" "mov_reg")]
8fa3ba89 8015)
39b5e676 8016
39b5e676 8017\f
9c08d1fa 8018;; Jump and linkage insns
8019
cffb2a26 8020(define_expand "jump"
9c08d1fa 8021 [(set (pc)
8022 (label_ref (match_operand 0 "" "")))]
cffb2a26 8023 "TARGET_EITHER"
9c08d1fa 8024 ""
cffb2a26 8025)
8026
8027(define_insn "*arm_jump"
8028 [(set (pc)
8029 (label_ref (match_operand 0 "" "")))]
25f905c2 8030 "TARGET_32BIT"
9c08d1fa 8031 "*
0d66636f 8032 {
8033 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
8034 {
8035 arm_ccfsm_state += 2;
8036 return \"\";
8037 }
8038 return \"b%?\\t%l0\";
8039 }
8040 "
a6864a24 8041 [(set_attr "predicable" "yes")
8042 (set (attr "length")
8043 (if_then_else
0bf497f5 8044 (and (match_test "TARGET_THUMB2")
a6864a24 8045 (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
8046 (le (minus (match_dup 0) (pc)) (const_int 2048))))
8047 (const_int 2)
1b7da4ac 8048 (const_int 4)))
8049 (set_attr "type" "branch")]
0d66636f 8050)
9c08d1fa 8051
d3373b54 8052(define_expand "call"
8053 [(parallel [(call (match_operand 0 "memory_operand" "")
8054 (match_operand 1 "general_operand" ""))
cffb2a26 8055 (use (match_operand 2 "" ""))
bd5b4116 8056 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 8057 "TARGET_EITHER"
6c4c2133 8058 "
8059 {
bac7fc85 8060 rtx callee, pat;
2d3a01a7 8061 tree addr = MEM_EXPR (operands[0]);
bbe777ea 8062
bbe777ea 8063 /* In an untyped call, we can get NULL for operand 2. */
8064 if (operands[2] == NULL_RTX)
8065 operands[2] = const0_rtx;
8066
de55252a 8067 /* Decide if we should generate indirect calls by loading the
85c36fd1 8068 32-bit address of the callee into a register before performing the
de55252a 8069 branch and link. */
8070 callee = XEXP (operands[0], 0);
8071 if (GET_CODE (callee) == SYMBOL_REF
8072 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
8073 : !REG_P (callee))
bbe777ea 8074 XEXP (operands[0], 0) = force_reg (Pmode, callee);
bac7fc85 8075
2d3a01a7 8076 if (detect_cmse_nonsecure_call (addr))
8077 {
8078 pat = gen_nonsecure_call_internal (operands[0], operands[1],
8079 operands[2]);
8080 emit_call_insn (pat);
8081 }
8082 else
8083 {
8084 pat = gen_call_internal (operands[0], operands[1], operands[2]);
8085 arm_emit_call_insn (pat, XEXP (operands[0], 0), false);
8086 }
bac7fc85 8087 DONE;
6c4c2133 8088 }"
8089)
d3373b54 8090
bac7fc85 8091(define_expand "call_internal"
8092 [(parallel [(call (match_operand 0 "memory_operand" "")
8093 (match_operand 1 "general_operand" ""))
8094 (use (match_operand 2 "" ""))
8095 (clobber (reg:SI LR_REGNUM))])])
8096
2d3a01a7 8097(define_expand "nonsecure_call_internal"
8098 [(parallel [(call (unspec:SI [(match_operand 0 "memory_operand" "")]
8099 UNSPEC_NONSECURE_MEM)
8100 (match_operand 1 "general_operand" ""))
8101 (use (match_operand 2 "" ""))
8102 (clobber (reg:SI LR_REGNUM))
8103 (clobber (reg:SI 4))])]
8104 "use_cmse"
8105 "
8106 {
8107 rtx tmp;
8108 tmp = copy_to_suggested_reg (XEXP (operands[0], 0),
8109 gen_rtx_REG (SImode, 4),
8110 SImode);
8111
8112 operands[0] = replace_equiv_address (operands[0], tmp);
8113 }")
8114
f1039640 8115(define_insn "*call_reg_armv5"
d3373b54 8116 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
cffb2a26 8117 (match_operand 1 "" ""))
8118 (use (match_operand 2 "" ""))
bd5b4116 8119 (clobber (reg:SI LR_REGNUM))]
33ae7c4b 8120 "TARGET_ARM && arm_arch5 && !SIBLING_CALL_P (insn)"
f1039640 8121 "blx%?\\t%0"
8122 [(set_attr "type" "call")]
8123)
8124
8125(define_insn "*call_reg_arm"
8126 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
8127 (match_operand 1 "" ""))
8128 (use (match_operand 2 "" ""))
8129 (clobber (reg:SI LR_REGNUM))]
33ae7c4b 8130 "TARGET_ARM && !arm_arch5 && !SIBLING_CALL_P (insn)"
9c08d1fa 8131 "*
5565501b 8132 return output_call (operands);
cffb2a26 8133 "
8134 ;; length is worst case, normally it is only two
8135 [(set_attr "length" "12")
8136 (set_attr "type" "call")]
8137)
9c08d1fa 8138
89504fc1 8139
d3373b54 8140(define_expand "call_value"
e0698af7 8141 [(parallel [(set (match_operand 0 "" "")
8142 (call (match_operand 1 "memory_operand" "")
8143 (match_operand 2 "general_operand" "")))
cffb2a26 8144 (use (match_operand 3 "" ""))
bd5b4116 8145 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 8146 "TARGET_EITHER"
6c4c2133 8147 "
8148 {
bac7fc85 8149 rtx pat, callee;
2d3a01a7 8150 tree addr = MEM_EXPR (operands[1]);
bbe777ea 8151
8152 /* In an untyped call, we can get NULL for operand 2. */
8153 if (operands[3] == 0)
8154 operands[3] = const0_rtx;
8155
de55252a 8156 /* Decide if we should generate indirect calls by loading the
8157 32-bit address of the callee into a register before performing the
8158 branch and link. */
8159 callee = XEXP (operands[1], 0);
8160 if (GET_CODE (callee) == SYMBOL_REF
8161 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
8162 : !REG_P (callee))
78fe751b 8163 XEXP (operands[1], 0) = force_reg (Pmode, callee);
bac7fc85 8164
2d3a01a7 8165 if (detect_cmse_nonsecure_call (addr))
8166 {
8167 pat = gen_nonsecure_call_value_internal (operands[0], operands[1],
8168 operands[2], operands[3]);
8169 emit_call_insn (pat);
8170 }
8171 else
8172 {
8173 pat = gen_call_value_internal (operands[0], operands[1],
8174 operands[2], operands[3]);
8175 arm_emit_call_insn (pat, XEXP (operands[1], 0), false);
8176 }
bac7fc85 8177 DONE;
6c4c2133 8178 }"
8179)
d3373b54 8180
bac7fc85 8181(define_expand "call_value_internal"
8182 [(parallel [(set (match_operand 0 "" "")
8183 (call (match_operand 1 "memory_operand" "")
8184 (match_operand 2 "general_operand" "")))
8185 (use (match_operand 3 "" ""))
8186 (clobber (reg:SI LR_REGNUM))])])
8187
2d3a01a7 8188(define_expand "nonsecure_call_value_internal"
8189 [(parallel [(set (match_operand 0 "" "")
8190 (call (unspec:SI [(match_operand 1 "memory_operand" "")]
8191 UNSPEC_NONSECURE_MEM)
8192 (match_operand 2 "general_operand" "")))
8193 (use (match_operand 3 "" ""))
8194 (clobber (reg:SI LR_REGNUM))
8195 (clobber (reg:SI 4))])]
8196 "use_cmse"
8197 "
8198 {
8199 rtx tmp;
8200 tmp = copy_to_suggested_reg (XEXP (operands[1], 0),
8201 gen_rtx_REG (SImode, 4),
8202 SImode);
8203
8204 operands[1] = replace_equiv_address (operands[1], tmp);
8205 }")
8206
f1039640 8207(define_insn "*call_value_reg_armv5"
27ed6835 8208 [(set (match_operand 0 "" "")
755eb2b4 8209 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
cffb2a26 8210 (match_operand 2 "" "")))
bbe777ea 8211 (use (match_operand 3 "" ""))
bd5b4116 8212 (clobber (reg:SI LR_REGNUM))]
33ae7c4b 8213 "TARGET_ARM && arm_arch5 && !SIBLING_CALL_P (insn)"
f1039640 8214 "blx%?\\t%1"
8215 [(set_attr "type" "call")]
8216)
8217
8218(define_insn "*call_value_reg_arm"
8219 [(set (match_operand 0 "" "")
8220 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
8221 (match_operand 2 "" "")))
8222 (use (match_operand 3 "" ""))
8223 (clobber (reg:SI LR_REGNUM))]
33ae7c4b 8224 "TARGET_ARM && !arm_arch5 && !SIBLING_CALL_P (insn)"
9c08d1fa 8225 "*
215b30b3 8226 return output_call (&operands[1]);
cffb2a26 8227 "
8228 [(set_attr "length" "12")
8229 (set_attr "type" "call")]
8230)
9c08d1fa 8231
9c08d1fa 8232;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
8233;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
8234
f7fbdd4a 8235(define_insn "*call_symbol"
27ed6835 8236 [(call (mem:SI (match_operand:SI 0 "" ""))
cffb2a26 8237 (match_operand 1 "" ""))
bbe777ea 8238 (use (match_operand 2 "" ""))
bd5b4116 8239 (clobber (reg:SI LR_REGNUM))]
d68c2c10 8240 "TARGET_32BIT
33ae7c4b 8241 && !SIBLING_CALL_P (insn)
cffb2a26 8242 && (GET_CODE (operands[0]) == SYMBOL_REF)
de55252a 8243 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
6ebaa29d 8244 "*
8245 {
95f1e0d1 8246 rtx op = operands[0];
8247
8248 /* Switch mode now when possible. */
8249 if (SYMBOL_REF_DECL (op) && !TREE_PUBLIC (SYMBOL_REF_DECL (op))
8250 && arm_arch5 && arm_change_mode_p (SYMBOL_REF_DECL (op)))
8251 return NEED_PLT_RELOC ? \"blx%?\\t%a0(PLT)\" : \"blx%?\\t(%a0)\";
8252
55c1e470 8253 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
6ebaa29d 8254 }"
cffb2a26 8255 [(set_attr "type" "call")]
8256)
9c08d1fa 8257
f7fbdd4a 8258(define_insn "*call_value_symbol"
ccd90aaa 8259 [(set (match_operand 0 "" "")
27ed6835 8260 (call (mem:SI (match_operand:SI 1 "" ""))
dd6d7504 8261 (match_operand:SI 2 "" "")))
bbe777ea 8262 (use (match_operand 3 "" ""))
bd5b4116 8263 (clobber (reg:SI LR_REGNUM))]
d68c2c10 8264 "TARGET_32BIT
33ae7c4b 8265 && !SIBLING_CALL_P (insn)
cffb2a26 8266 && (GET_CODE (operands[1]) == SYMBOL_REF)
de55252a 8267 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
6ebaa29d 8268 "*
8269 {
95f1e0d1 8270 rtx op = operands[1];
8271
8272 /* Switch mode now when possible. */
8273 if (SYMBOL_REF_DECL (op) && !TREE_PUBLIC (SYMBOL_REF_DECL (op))
8274 && arm_arch5 && arm_change_mode_p (SYMBOL_REF_DECL (op)))
3f6b66fa 8275 return NEED_PLT_RELOC ? \"blx%?\\t%a1(PLT)\" : \"blx%?\\t(%a1)\";
95f1e0d1 8276
55c1e470 8277 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
6ebaa29d 8278 }"
cffb2a26 8279 [(set_attr "type" "call")]
8280)
8281
ca373797 8282(define_expand "sibcall_internal"
8283 [(parallel [(call (match_operand 0 "memory_operand" "")
8284 (match_operand 1 "general_operand" ""))
8285 (return)
8286 (use (match_operand 2 "" ""))])])
8287
1c494086 8288;; We may also be able to do sibcalls for Thumb, but it's much harder...
8289(define_expand "sibcall"
8290 [(parallel [(call (match_operand 0 "memory_operand" "")
8291 (match_operand 1 "general_operand" ""))
2ba80634 8292 (return)
8293 (use (match_operand 2 "" ""))])]
d68c2c10 8294 "TARGET_32BIT"
1c494086 8295 "
8296 {
ca373797 8297 rtx pat;
8298
3112c3f7 8299 if ((!REG_P (XEXP (operands[0], 0))
8300 && GET_CODE (XEXP (operands[0], 0)) != SYMBOL_REF)
8301 || (GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
8302 && arm_is_long_call_p (SYMBOL_REF_DECL (XEXP (operands[0], 0)))))
33ae7c4b 8303 XEXP (operands[0], 0) = force_reg (SImode, XEXP (operands[0], 0));
8304
1c494086 8305 if (operands[2] == NULL_RTX)
8306 operands[2] = const0_rtx;
ca373797 8307
8308 pat = gen_sibcall_internal (operands[0], operands[1], operands[2]);
8309 arm_emit_call_insn (pat, operands[0], true);
8310 DONE;
1c494086 8311 }"
8312)
8313
ca373797 8314(define_expand "sibcall_value_internal"
8315 [(parallel [(set (match_operand 0 "" "")
8316 (call (match_operand 1 "memory_operand" "")
8317 (match_operand 2 "general_operand" "")))
8318 (return)
8319 (use (match_operand 3 "" ""))])])
8320
1c494086 8321(define_expand "sibcall_value"
ccd90aaa 8322 [(parallel [(set (match_operand 0 "" "")
1c494086 8323 (call (match_operand 1 "memory_operand" "")
8324 (match_operand 2 "general_operand" "")))
2ba80634 8325 (return)
8326 (use (match_operand 3 "" ""))])]
d68c2c10 8327 "TARGET_32BIT"
1c494086 8328 "
8329 {
ca373797 8330 rtx pat;
8331
3112c3f7 8332 if ((!REG_P (XEXP (operands[1], 0))
8333 && GET_CODE (XEXP (operands[1], 0)) != SYMBOL_REF)
8334 || (GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
8335 && arm_is_long_call_p (SYMBOL_REF_DECL (XEXP (operands[1], 0)))))
33ae7c4b 8336 XEXP (operands[1], 0) = force_reg (SImode, XEXP (operands[1], 0));
8337
1c494086 8338 if (operands[3] == NULL_RTX)
8339 operands[3] = const0_rtx;
ca373797 8340
8341 pat = gen_sibcall_value_internal (operands[0], operands[1],
8342 operands[2], operands[3]);
8343 arm_emit_call_insn (pat, operands[1], true);
8344 DONE;
1c494086 8345 }"
8346)
8347
8348(define_insn "*sibcall_insn"
84ce8e5c 8349 [(call (mem:SI (match_operand:SI 0 "call_insn_operand" "Cs, US"))
1c494086 8350 (match_operand 1 "" ""))
2ba80634 8351 (return)
8352 (use (match_operand 2 "" ""))]
33ae7c4b 8353 "TARGET_32BIT && SIBLING_CALL_P (insn)"
1c494086 8354 "*
33ae7c4b 8355 if (which_alternative == 1)
8356 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
8357 else
8358 {
8359 if (arm_arch5 || arm_arch4t)
947d113e 8360 return \"bx%?\\t%0\\t%@ indirect register sibling call\";
33ae7c4b 8361 else
8362 return \"mov%?\\t%|pc, %0\\t%@ indirect register sibling call\";
8363 }
1c494086 8364 "
8365 [(set_attr "type" "call")]
8366)
8367
8368(define_insn "*sibcall_value_insn"
84ce8e5c 8369 [(set (match_operand 0 "" "")
8370 (call (mem:SI (match_operand:SI 1 "call_insn_operand" "Cs,US"))
1c494086 8371 (match_operand 2 "" "")))
2ba80634 8372 (return)
8373 (use (match_operand 3 "" ""))]
33ae7c4b 8374 "TARGET_32BIT && SIBLING_CALL_P (insn)"
1c494086 8375 "*
33ae7c4b 8376 if (which_alternative == 1)
8377 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
8378 else
8379 {
8380 if (arm_arch5 || arm_arch4t)
84ce8e5c 8381 return \"bx%?\\t%1\";
33ae7c4b 8382 else
8383 return \"mov%?\\t%|pc, %1\\t@ indirect sibling call \";
8384 }
1c494086 8385 "
8386 [(set_attr "type" "call")]
8387)
8388
0686440e 8389(define_expand "<return_str>return"
9b23f0a7 8390 [(RETURNS)]
8cba51a5 8391 "(TARGET_ARM || (TARGET_THUMB2
8392 && ARM_FUNC_TYPE (arm_current_func_type ()) == ARM_FT_NORMAL
8393 && !IS_STACKALIGN (arm_current_func_type ())))
0686440e 8394 <return_cond_false>"
8cba51a5 8395 "
8396 {
8397 if (TARGET_THUMB2)
8398 {
0686440e 8399 thumb2_expand_return (<return_simple_p>);
8cba51a5 8400 DONE;
8401 }
8402 }
8403 "
8404)
d68c2c10 8405
9c08d1fa 8406;; Often the return insn will be the same as loading from memory, so set attr
d68c2c10 8407(define_insn "*arm_return"
9c08d1fa 8408 [(return)]
cffb2a26 8409 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
9c08d1fa 8410 "*
9c08d1fa 8411 {
cffb2a26 8412 if (arm_ccfsm_state == 2)
8413 {
8414 arm_ccfsm_state += 2;
8415 return \"\";
8416 }
e2549f81 8417 return output_return_instruction (const_true_rtx, true, false, false);
cffb2a26 8418 }"
a2cd141b 8419 [(set_attr "type" "load1")
755eb2b4 8420 (set_attr "length" "12")
0d66636f 8421 (set_attr "predicable" "yes")]
cffb2a26 8422)
9c08d1fa 8423
0686440e 8424(define_insn "*cond_<return_str>return"
9c08d1fa 8425 [(set (pc)
8fa3ba89 8426 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 8427 [(match_operand 1 "cc_register" "") (const_int 0)])
9b23f0a7 8428 (RETURNS)
9c08d1fa 8429 (pc)))]
0686440e 8430 "TARGET_ARM <return_cond_true>"
9c08d1fa 8431 "*
8fa3ba89 8432 {
8433 if (arm_ccfsm_state == 2)
8434 {
8435 arm_ccfsm_state += 2;
8436 return \"\";
8437 }
0686440e 8438 return output_return_instruction (operands[0], true, false,
8439 <return_simple_p>);
8fa3ba89 8440 }"
8441 [(set_attr "conds" "use")
755eb2b4 8442 (set_attr "length" "12")
a2cd141b 8443 (set_attr "type" "load1")]
8fa3ba89 8444)
9c08d1fa 8445
0686440e 8446(define_insn "*cond_<return_str>return_inverted"
9c08d1fa 8447 [(set (pc)
8fa3ba89 8448 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 8449 [(match_operand 1 "cc_register" "") (const_int 0)])
9c08d1fa 8450 (pc)
9b23f0a7 8451 (RETURNS)))]
0686440e 8452 "TARGET_ARM <return_cond_true>"
9c08d1fa 8453 "*
8fa3ba89 8454 {
8455 if (arm_ccfsm_state == 2)
8456 {
8457 arm_ccfsm_state += 2;
8458 return \"\";
8459 }
0686440e 8460 return output_return_instruction (operands[0], true, true,
8461 <return_simple_p>);
8fa3ba89 8462 }"
8463 [(set_attr "conds" "use")
37a1317b 8464 (set_attr "length" "12")
a2cd141b 8465 (set_attr "type" "load1")]
8fa3ba89 8466)
9c08d1fa 8467
e2549f81 8468(define_insn "*arm_simple_return"
8469 [(simple_return)]
8470 "TARGET_ARM"
8471 "*
8472 {
8473 if (arm_ccfsm_state == 2)
8474 {
8475 arm_ccfsm_state += 2;
8476 return \"\";
8477 }
8478 return output_return_instruction (const_true_rtx, true, false, true);
8479 }"
8480 [(set_attr "type" "branch")
8481 (set_attr "length" "4")
8482 (set_attr "predicable" "yes")]
8483)
8484
68121397 8485;; Generate a sequence of instructions to determine if the processor is
8486;; in 26-bit or 32-bit mode, and return the appropriate return address
8487;; mask.
8488
8489(define_expand "return_addr_mask"
8490 [(set (match_dup 1)
8491 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8492 (const_int 0)))
8493 (set (match_operand:SI 0 "s_register_operand" "")
8494 (if_then_else:SI (eq (match_dup 1) (const_int 0))
8495 (const_int -1)
8496 (const_int 67108860)))] ; 0x03fffffc
8497 "TARGET_ARM"
8498 "
62eddbd4 8499 operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
68121397 8500 ")
8501
8502(define_insn "*check_arch2"
8503 [(set (match_operand:CC_NOOV 0 "cc_register" "")
8504 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8505 (const_int 0)))]
8506 "TARGET_ARM"
8507 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
8508 [(set_attr "length" "8")
1b7da4ac 8509 (set_attr "conds" "set")
8510 (set_attr "type" "multiple")]
68121397 8511)
8512
9c08d1fa 8513;; Call subroutine returning any type.
8514
8515(define_expand "untyped_call"
8516 [(parallel [(call (match_operand 0 "" "")
8517 (const_int 0))
8518 (match_operand 1 "" "")
8519 (match_operand 2 "" "")])]
ccd90aaa 8520 "TARGET_EITHER"
9c08d1fa 8521 "
215b30b3 8522 {
8523 int i;
ccd90aaa 8524 rtx par = gen_rtx_PARALLEL (VOIDmode,
8525 rtvec_alloc (XVECLEN (operands[2], 0)));
8526 rtx addr = gen_reg_rtx (Pmode);
8527 rtx mem;
8528 int size = 0;
9c08d1fa 8529
ccd90aaa 8530 emit_move_insn (addr, XEXP (operands[1], 0));
8531 mem = change_address (operands[1], BLKmode, addr);
9c08d1fa 8532
215b30b3 8533 for (i = 0; i < XVECLEN (operands[2], 0); i++)
8534 {
ccd90aaa 8535 rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
9c08d1fa 8536
ccd90aaa 8537 /* Default code only uses r0 as a return value, but we could
8538 be using anything up to 4 registers. */
8539 if (REGNO (src) == R0_REGNUM)
8540 src = gen_rtx_REG (TImode, R0_REGNUM);
8541
8542 XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
8543 GEN_INT (size));
8544 size += GET_MODE_SIZE (GET_MODE (src));
8545 }
8546
7f265a08 8547 emit_call_insn (gen_call_value (par, operands[0], const0_rtx, NULL));
ccd90aaa 8548
8549 size = 0;
8550
8551 for (i = 0; i < XVECLEN (par, 0); i++)
8552 {
8553 HOST_WIDE_INT offset = 0;
8554 rtx reg = XEXP (XVECEXP (par, 0, i), 0);
8555
8556 if (size != 0)
29c05e22 8557 emit_move_insn (addr, plus_constant (Pmode, addr, size));
ccd90aaa 8558
8559 mem = change_address (mem, GET_MODE (reg), NULL);
8560 if (REGNO (reg) == R0_REGNUM)
8561 {
8562 /* On thumb we have to use a write-back instruction. */
320ea44d 8563 emit_insn (arm_gen_store_multiple (arm_regs_in_sequence, 4, addr,
8564 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
ccd90aaa 8565 size = TARGET_ARM ? 16 : 0;
8566 }
8567 else
8568 {
8569 emit_move_insn (mem, reg);
8570 size = GET_MODE_SIZE (GET_MODE (reg));
8571 }
215b30b3 8572 }
9c08d1fa 8573
215b30b3 8574 /* The optimizer does not know that the call sets the function value
8575 registers we stored in the result block. We avoid problems by
8576 claiming that all hard registers are used and clobbered at this
8577 point. */
8578 emit_insn (gen_blockage ());
8579
8580 DONE;
8581 }"
8582)
9c08d1fa 8583
ccd90aaa 8584(define_expand "untyped_return"
8585 [(match_operand:BLK 0 "memory_operand" "")
8586 (match_operand 1 "" "")]
8587 "TARGET_EITHER"
8588 "
8589 {
8590 int i;
8591 rtx addr = gen_reg_rtx (Pmode);
8592 rtx mem;
8593 int size = 0;
8594
8595 emit_move_insn (addr, XEXP (operands[0], 0));
8596 mem = change_address (operands[0], BLKmode, addr);
8597
8598 for (i = 0; i < XVECLEN (operands[1], 0); i++)
8599 {
8600 HOST_WIDE_INT offset = 0;
8601 rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
8602
8603 if (size != 0)
29c05e22 8604 emit_move_insn (addr, plus_constant (Pmode, addr, size));
ccd90aaa 8605
8606 mem = change_address (mem, GET_MODE (reg), NULL);
8607 if (REGNO (reg) == R0_REGNUM)
8608 {
8609 /* On thumb we have to use a write-back instruction. */
320ea44d 8610 emit_insn (arm_gen_load_multiple (arm_regs_in_sequence, 4, addr,
8611 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
ccd90aaa 8612 size = TARGET_ARM ? 16 : 0;
8613 }
8614 else
8615 {
8616 emit_move_insn (reg, mem);
8617 size = GET_MODE_SIZE (GET_MODE (reg));
8618 }
8619 }
8620
8621 /* Emit USE insns before the return. */
8622 for (i = 0; i < XVECLEN (operands[1], 0); i++)
18b42941 8623 emit_use (SET_DEST (XVECEXP (operands[1], 0, i)));
ccd90aaa 8624
8625 /* Construct the return. */
8626 expand_naked_return ();
8627
8628 DONE;
8629 }"
8630)
8631
9c08d1fa 8632;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
8633;; all of memory. This blocks insns from being moved across this point.
8634
8635(define_insn "blockage"
e1159bbe 8636 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
cffb2a26 8637 "TARGET_EITHER"
9c08d1fa 8638 ""
cffb2a26 8639 [(set_attr "length" "0")
8640 (set_attr "type" "block")]
8641)
9c08d1fa 8642
706dca65 8643(define_insn "probe_stack"
f8570abe 8644 [(set (match_operand:SI 0 "memory_operand" "=m")
8645 (unspec:SI [(const_int 0)] UNSPEC_PROBE_STACK))]
706dca65 8646 "TARGET_32BIT"
154ae8e6 8647 "str%?\\tr0, %0"
706dca65 8648 [(set_attr "type" "store1")
8649 (set_attr "predicable" "yes")]
8650)
8651
8652(define_insn "probe_stack_range"
8653 [(set (match_operand:SI 0 "register_operand" "=r")
8654 (unspec_volatile:SI [(match_operand:SI 1 "register_operand" "0")
8655 (match_operand:SI 2 "register_operand" "r")]
dd8aabc9 8656 VUNSPEC_PROBE_STACK_RANGE))]
706dca65 8657 "TARGET_32BIT"
8658{
8659 return output_probe_stack_range (operands[0], operands[2]);
8660}
8661 [(set_attr "type" "multiple")
8662 (set_attr "conds" "clob")]
8663)
8664
f7fbdd4a 8665(define_expand "casesi"
8666 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
aea4c774 8667 (match_operand:SI 1 "const_int_operand" "") ; lower bound
8668 (match_operand:SI 2 "const_int_operand" "") ; total range
f7fbdd4a 8669 (match_operand:SI 3 "" "") ; table label
8670 (match_operand:SI 4 "" "")] ; Out of range label
9753b549 8671 "(TARGET_32BIT || optimize_size || flag_pic) && !target_pure_code"
f7fbdd4a 8672 "
215b30b3 8673 {
e6ac8414 8674 enum insn_code code;
215b30b3 8675 if (operands[1] != const0_rtx)
8676 {
e6ac8414 8677 rtx reg = gen_reg_rtx (SImode);
f7fbdd4a 8678
215b30b3 8679 emit_insn (gen_addsi3 (reg, operands[0],
d022fa24 8680 gen_int_mode (-INTVAL (operands[1]),
8681 SImode)));
215b30b3 8682 operands[0] = reg;
8683 }
9c08d1fa 8684
25f905c2 8685 if (TARGET_ARM)
e6ac8414 8686 code = CODE_FOR_arm_casesi_internal;
3db2019b 8687 else if (TARGET_THUMB1)
e6ac8414 8688 code = CODE_FOR_thumb1_casesi_internal_pic;
25f905c2 8689 else if (flag_pic)
e6ac8414 8690 code = CODE_FOR_thumb2_casesi_internal_pic;
25f905c2 8691 else
e6ac8414 8692 code = CODE_FOR_thumb2_casesi_internal;
8693
8694 if (!insn_data[(int) code].operand[1].predicate(operands[2], SImode))
8695 operands[2] = force_reg (SImode, operands[2]);
8696
8697 emit_jump_insn (GEN_FCN ((int) code) (operands[0], operands[2],
8698 operands[3], operands[4]));
215b30b3 8699 DONE;
8700 }"
8701)
f7fbdd4a 8702
f082f1c4 8703;; The USE in this pattern is needed to tell flow analysis that this is
8704;; a CASESI insn. It has no other purpose.
25f905c2 8705(define_insn "arm_casesi_internal"
f082f1c4 8706 [(parallel [(set (pc)
8707 (if_then_else
8708 (leu (match_operand:SI 0 "s_register_operand" "r")
8709 (match_operand:SI 1 "arm_rhs_operand" "rI"))
8710 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
8711 (label_ref (match_operand 2 "" ""))))
8712 (label_ref (match_operand 3 "" ""))))
bd5b4116 8713 (clobber (reg:CC CC_REGNUM))
f082f1c4 8714 (use (label_ref (match_dup 2)))])]
cffb2a26 8715 "TARGET_ARM"
f7fbdd4a 8716 "*
0d66636f 8717 if (flag_pic)
8718 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
8719 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
8720 "
8721 [(set_attr "conds" "clob")
1b7da4ac 8722 (set_attr "length" "12")
8723 (set_attr "type" "multiple")]
0d66636f 8724)
9c08d1fa 8725
cffb2a26 8726(define_expand "indirect_jump"
9c08d1fa 8727 [(set (pc)
cffb2a26 8728 (match_operand:SI 0 "s_register_operand" ""))]
8729 "TARGET_EITHER"
25f905c2 8730 "
8731 /* Thumb-2 doesn't have mov pc, reg. Explicitly set the low bit of the
8732 address and use bx. */
8733 if (TARGET_THUMB2)
8734 {
8735 rtx tmp;
8736 tmp = gen_reg_rtx (SImode);
8737 emit_insn (gen_iorsi3 (tmp, operands[0], GEN_INT(1)));
8738 operands[0] = tmp;
8739 }
8740 "
cffb2a26 8741)
8742
f1039640 8743;; NB Never uses BX.
cffb2a26 8744(define_insn "*arm_indirect_jump"
8745 [(set (pc)
8746 (match_operand:SI 0 "s_register_operand" "r"))]
8747 "TARGET_ARM"
8748 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
1b7da4ac 8749 [(set_attr "predicable" "yes")
8750 (set_attr "type" "branch")]
cffb2a26 8751)
9c08d1fa 8752
f7fbdd4a 8753(define_insn "*load_indirect_jump"
9c08d1fa 8754 [(set (pc)
8755 (match_operand:SI 0 "memory_operand" "m"))]
cffb2a26 8756 "TARGET_ARM"
8757 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
a2cd141b 8758 [(set_attr "type" "load1")
61a2d04c 8759 (set_attr "pool_range" "4096")
8760 (set_attr "neg_pool_range" "4084")
0d66636f 8761 (set_attr "predicable" "yes")]
cffb2a26 8762)
8763
9c08d1fa 8764\f
8765;; Misc insns
8766
8767(define_insn "nop"
8768 [(const_int 0)]
cffb2a26 8769 "TARGET_EITHER"
3ef90e77 8770 "nop"
cffb2a26 8771 [(set (attr "length")
8772 (if_then_else (eq_attr "is_thumb" "yes")
8773 (const_int 2)
1b7da4ac 8774 (const_int 4)))
8775 (set_attr "type" "mov_reg")]
cffb2a26 8776)
8777
ad9d4399 8778(define_insn "trap"
8779 [(trap_if (const_int 1) (const_int 0))]
8780 ""
8781 "*
8782 if (TARGET_ARM)
8783 return \".inst\\t0xe7f000f0\";
8784 else
8785 return \".inst\\t0xdeff\";
8786 "
8787 [(set (attr "length")
8788 (if_then_else (eq_attr "is_thumb" "yes")
8789 (const_int 2)
8790 (const_int 4)))
8791 (set_attr "type" "trap")
8792 (set_attr "conds" "unconditional")]
8793)
8794
9c08d1fa 8795\f
8796;; Patterns to allow combination of arithmetic, cond code and shifts
8797
0abea32c 8798(define_insn "*<arith_shift_insn>_multsi"
8799 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9b23f0a7 8800 (SHIFTABLE_OPS:SI
0abea32c 8801 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
8802 (match_operand:SI 3 "power_of_two_operand" ""))
8803 (match_operand:SI 1 "s_register_operand" "rk,<t2_binop0>")))]
d5d4dc8d 8804 "TARGET_32BIT"
0abea32c 8805 "<arith_shift_insn>%?\\t%0, %1, %2, lsl %b3"
8806 [(set_attr "predicable" "yes")
8807 (set_attr "predicable_short_it" "no")
753d9835 8808 (set_attr "shift" "2")
0abea32c 8809 (set_attr "arch" "a,t2")
8810 (set_attr "type" "alu_shift_imm")])
8811
8812(define_insn "*<arith_shift_insn>_shiftsi"
8813 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9b23f0a7 8814 (SHIFTABLE_OPS:SI
0abea32c 8815 (match_operator:SI 2 "shift_nomul_operator"
8816 [(match_operand:SI 3 "s_register_operand" "r,r,r")
8817 (match_operand:SI 4 "shift_amount_operand" "M,M,r")])
8818 (match_operand:SI 1 "s_register_operand" "rk,<t2_binop0>,rk")))]
a021b821 8819 "TARGET_32BIT && GET_CODE (operands[2]) != MULT"
0abea32c 8820 "<arith_shift_insn>%?\\t%0, %1, %3%S2"
344495ea 8821 [(set_attr "predicable" "yes")
74ef923b 8822 (set_attr "predicable_short_it" "no")
753d9835 8823 (set_attr "shift" "3")
0abea32c 8824 (set_attr "arch" "a,t2,a")
8825 (set_attr "type" "alu_shift_imm,alu_shift_imm,alu_shift_reg")])
9c08d1fa 8826
d7863cfe 8827(define_split
8828 [(set (match_operand:SI 0 "s_register_operand" "")
8829 (match_operator:SI 1 "shiftable_operator"
8830 [(match_operator:SI 2 "shiftable_operator"
8831 [(match_operator:SI 3 "shift_operator"
8832 [(match_operand:SI 4 "s_register_operand" "")
8833 (match_operand:SI 5 "reg_or_int_operand" "")])
8834 (match_operand:SI 6 "s_register_operand" "")])
8835 (match_operand:SI 7 "arm_rhs_operand" "")]))
8836 (clobber (match_operand:SI 8 "s_register_operand" ""))]
d5d4dc8d 8837 "TARGET_32BIT"
d7863cfe 8838 [(set (match_dup 8)
8839 (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8840 (match_dup 6)]))
8841 (set (match_dup 0)
8842 (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
8843 "")
8844
f7fbdd4a 8845(define_insn "*arith_shiftsi_compare0"
bd5b4116 8846 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 8847 (compare:CC_NOOV
8848 (match_operator:SI 1 "shiftable_operator"
8849 [(match_operator:SI 3 "shift_operator"
8850 [(match_operand:SI 4 "s_register_operand" "r,r")
8851 (match_operand:SI 5 "shift_amount_operand" "M,r")])
8852 (match_operand:SI 2 "s_register_operand" "r,r")])
8853 (const_int 0)))
8854 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 8855 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8856 (match_dup 2)]))]
d5d4dc8d 8857 "TARGET_32BIT"
3ef90e77 8858 "%i1s%?\\t%0, %2, %4%S3"
344495ea 8859 [(set_attr "conds" "set")
331beb1a 8860 (set_attr "shift" "4")
d5d4dc8d 8861 (set_attr "arch" "32,a")
d82e788e 8862 (set_attr "type" "alus_shift_imm,alus_shift_reg")])
9c08d1fa 8863
f7fbdd4a 8864(define_insn "*arith_shiftsi_compare0_scratch"
bd5b4116 8865 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 8866 (compare:CC_NOOV
8867 (match_operator:SI 1 "shiftable_operator"
8868 [(match_operator:SI 3 "shift_operator"
8869 [(match_operand:SI 4 "s_register_operand" "r,r")
8870 (match_operand:SI 5 "shift_amount_operand" "M,r")])
8871 (match_operand:SI 2 "s_register_operand" "r,r")])
8872 (const_int 0)))
8873 (clobber (match_scratch:SI 0 "=r,r"))]
8874 "TARGET_32BIT"
3ef90e77 8875 "%i1s%?\\t%0, %2, %4%S3"
344495ea 8876 [(set_attr "conds" "set")
331beb1a 8877 (set_attr "shift" "4")
d5d4dc8d 8878 (set_attr "arch" "32,a")
d82e788e 8879 (set_attr "type" "alus_shift_imm,alus_shift_reg")])
9c08d1fa 8880
f7fbdd4a 8881(define_insn "*sub_shiftsi"
d5d4dc8d 8882 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8883 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
9c08d1fa 8884 (match_operator:SI 2 "shift_operator"
d5d4dc8d 8885 [(match_operand:SI 3 "s_register_operand" "r,r")
8886 (match_operand:SI 4 "shift_amount_operand" "M,r")])))]
8887 "TARGET_32BIT"
6c4c2133 8888 "sub%?\\t%0, %1, %3%S2"
344495ea 8889 [(set_attr "predicable" "yes")
331beb1a 8890 (set_attr "shift" "3")
d5d4dc8d 8891 (set_attr "arch" "32,a")
d82e788e 8892 (set_attr "type" "alus_shift_imm,alus_shift_reg")])
9c08d1fa 8893
f7fbdd4a 8894(define_insn "*sub_shiftsi_compare0"
bd5b4116 8895 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 8896 (compare:CC_NOOV
d82e788e 8897 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
40dbec34 8898 (match_operator:SI 2 "shift_operator"
d82e788e 8899 [(match_operand:SI 3 "s_register_operand" "r,r,r")
8900 (match_operand:SI 4 "shift_amount_operand" "M,r,M")]))
40dbec34 8901 (const_int 0)))
d82e788e 8902 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
d5d4dc8d 8903 (minus:SI (match_dup 1)
8904 (match_op_dup 2 [(match_dup 3) (match_dup 4)])))]
8905 "TARGET_32BIT"
3ef90e77 8906 "subs%?\\t%0, %1, %3%S2"
344495ea 8907 [(set_attr "conds" "set")
a2cd141b 8908 (set_attr "shift" "3")
d82e788e 8909 (set_attr "arch" "32,a,a")
8910 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
9c08d1fa 8911
f7fbdd4a 8912(define_insn "*sub_shiftsi_compare0_scratch"
bd5b4116 8913 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 8914 (compare:CC_NOOV
d82e788e 8915 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
40dbec34 8916 (match_operator:SI 2 "shift_operator"
d82e788e 8917 [(match_operand:SI 3 "s_register_operand" "r,r,r")
8918 (match_operand:SI 4 "shift_amount_operand" "M,r,M")]))
40dbec34 8919 (const_int 0)))
d82e788e 8920 (clobber (match_scratch:SI 0 "=r,r,r"))]
d5d4dc8d 8921 "TARGET_32BIT"
3ef90e77 8922 "subs%?\\t%0, %1, %3%S2"
344495ea 8923 [(set_attr "conds" "set")
a2cd141b 8924 (set_attr "shift" "3")
d82e788e 8925 (set_attr "arch" "32,a,a")
8926 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
9c08d1fa 8927\f
8928
190efb17 8929(define_insn_and_split "*and_scc"
9c08d1fa 8930 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 8931 (and:SI (match_operator:SI 1 "arm_comparison_operator"
190efb17 8932 [(match_operand 2 "cc_register" "") (const_int 0)])
8933 (match_operand:SI 3 "s_register_operand" "r")))]
cffb2a26 8934 "TARGET_ARM"
190efb17 8935 "#" ; "mov%D1\\t%0, #0\;and%d1\\t%0, %3, #1"
8936 "&& reload_completed"
8937 [(cond_exec (match_dup 5) (set (match_dup 0) (const_int 0)))
8938 (cond_exec (match_dup 4) (set (match_dup 0)
8939 (and:SI (match_dup 3) (const_int 1))))]
8940 {
3754d046 8941 machine_mode mode = GET_MODE (operands[2]);
190efb17 8942 enum rtx_code rc = GET_CODE (operands[1]);
8943
8944 /* Note that operands[4] is the same as operands[1],
8945 but with VOIDmode as the result. */
8946 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
8947 if (mode == CCFPmode || mode == CCFPEmode)
8948 rc = reverse_condition_maybe_unordered (rc);
8949 else
8950 rc = reverse_condition (rc);
8951 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
8952 }
8fa3ba89 8953 [(set_attr "conds" "use")
1b7da4ac 8954 (set_attr "type" "multiple")
8fa3ba89 8955 (set_attr "length" "8")]
8956)
9c08d1fa 8957
190efb17 8958(define_insn_and_split "*ior_scc"
9c08d1fa 8959 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
190efb17 8960 (ior:SI (match_operator:SI 1 "arm_comparison_operator"
8961 [(match_operand 2 "cc_register" "") (const_int 0)])
8962 (match_operand:SI 3 "s_register_operand" "0,?r")))]
cffb2a26 8963 "TARGET_ARM"
e2348bcb 8964 "@
190efb17 8965 orr%d1\\t%0, %3, #1
8966 #"
8967 "&& reload_completed
8968 && REGNO (operands [0]) != REGNO (operands[3])"
8969 ;; && which_alternative == 1
8970 ; mov%D1\\t%0, %3\;orr%d1\\t%0, %3, #1
8971 [(cond_exec (match_dup 5) (set (match_dup 0) (match_dup 3)))
8972 (cond_exec (match_dup 4) (set (match_dup 0)
8973 (ior:SI (match_dup 3) (const_int 1))))]
8974 {
3754d046 8975 machine_mode mode = GET_MODE (operands[2]);
190efb17 8976 enum rtx_code rc = GET_CODE (operands[1]);
8977
8978 /* Note that operands[4] is the same as operands[1],
8979 but with VOIDmode as the result. */
8980 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
8981 if (mode == CCFPmode || mode == CCFPEmode)
8982 rc = reverse_condition_maybe_unordered (rc);
8983 else
8984 rc = reverse_condition (rc);
8985 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
8986 }
8fa3ba89 8987 [(set_attr "conds" "use")
1b7da4ac 8988 (set_attr "length" "4,8")
8989 (set_attr "type" "logic_imm,multiple")]
8fa3ba89 8990)
9c08d1fa 8991
2df9477b 8992; A series of splitters for the compare_scc pattern below. Note that
8993; order is important.
8994(define_split
8995 [(set (match_operand:SI 0 "s_register_operand" "")
8996 (lt:SI (match_operand:SI 1 "s_register_operand" "")
8997 (const_int 0)))
8998 (clobber (reg:CC CC_REGNUM))]
8999 "TARGET_32BIT && reload_completed"
9000 [(set (match_dup 0) (lshiftrt:SI (match_dup 1) (const_int 31)))])
9001
9002(define_split
9003 [(set (match_operand:SI 0 "s_register_operand" "")
9004 (ge:SI (match_operand:SI 1 "s_register_operand" "")
9005 (const_int 0)))
9006 (clobber (reg:CC CC_REGNUM))]
9007 "TARGET_32BIT && reload_completed"
9008 [(set (match_dup 0) (not:SI (match_dup 1)))
9009 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 31)))])
9010
98562479 9011(define_split
9012 [(set (match_operand:SI 0 "s_register_operand" "")
9013 (eq:SI (match_operand:SI 1 "s_register_operand" "")
9014 (const_int 0)))
9015 (clobber (reg:CC CC_REGNUM))]
9016 "arm_arch5 && TARGET_32BIT"
9017 [(set (match_dup 0) (clz:SI (match_dup 1)))
9018 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 5)))]
9019)
9020
2df9477b 9021(define_split
9022 [(set (match_operand:SI 0 "s_register_operand" "")
9023 (eq:SI (match_operand:SI 1 "s_register_operand" "")
9024 (const_int 0)))
9025 (clobber (reg:CC CC_REGNUM))]
9026 "TARGET_32BIT && reload_completed"
9027 [(parallel
080c0b9a 9028 [(set (reg:CC CC_REGNUM)
9029 (compare:CC (const_int 1) (match_dup 1)))
2df9477b 9030 (set (match_dup 0)
9031 (minus:SI (const_int 1) (match_dup 1)))])
080c0b9a 9032 (cond_exec (ltu:CC (reg:CC CC_REGNUM) (const_int 0))
2df9477b 9033 (set (match_dup 0) (const_int 0)))])
9034
9035(define_split
9036 [(set (match_operand:SI 0 "s_register_operand" "")
9037 (ne:SI (match_operand:SI 1 "s_register_operand" "")
9038 (match_operand:SI 2 "const_int_operand" "")))
9039 (clobber (reg:CC CC_REGNUM))]
9040 "TARGET_32BIT && reload_completed"
9041 [(parallel
9042 [(set (reg:CC CC_REGNUM)
9043 (compare:CC (match_dup 1) (match_dup 2)))
9044 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))])
9045 (cond_exec (ne:CC (reg:CC CC_REGNUM) (const_int 0))
9046 (set (match_dup 0) (const_int 1)))]
9047{
9048 operands[3] = GEN_INT (-INTVAL (operands[2]));
9049})
9050
9051(define_split
9052 [(set (match_operand:SI 0 "s_register_operand" "")
9053 (ne:SI (match_operand:SI 1 "s_register_operand" "")
9054 (match_operand:SI 2 "arm_add_operand" "")))
9055 (clobber (reg:CC CC_REGNUM))]
9056 "TARGET_32BIT && reload_completed"
9057 [(parallel
9058 [(set (reg:CC_NOOV CC_REGNUM)
9059 (compare:CC_NOOV (minus:SI (match_dup 1) (match_dup 2))
9060 (const_int 0)))
9061 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
9062 (cond_exec (ne:CC_NOOV (reg:CC_NOOV CC_REGNUM) (const_int 0))
9063 (set (match_dup 0) (const_int 1)))])
9064
9065(define_insn_and_split "*compare_scc"
fd711051 9066 [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts")
8fa3ba89 9067 (match_operator:SI 1 "arm_comparison_operator"
5565501b 9068 [(match_operand:SI 2 "s_register_operand" "r,r")
9069 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
bd5b4116 9070 (clobber (reg:CC CC_REGNUM))]
2df9477b 9071 "TARGET_32BIT"
9072 "#"
9073 "&& reload_completed"
9074 [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 3)))
9075 (cond_exec (match_dup 4) (set (match_dup 0) (const_int 0)))
9076 (cond_exec (match_dup 5) (set (match_dup 0) (const_int 1)))]
9077{
9078 rtx tmp1;
3754d046 9079 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
2df9477b 9080 operands[2], operands[3]);
9081 enum rtx_code rc = GET_CODE (operands[1]);
e2348bcb 9082
2df9477b 9083 tmp1 = gen_rtx_REG (mode, CC_REGNUM);
080c0b9a 9084
2df9477b 9085 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
9086 if (mode == CCFPmode || mode == CCFPEmode)
9087 rc = reverse_condition_maybe_unordered (rc);
9088 else
9089 rc = reverse_condition (rc);
9090 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
1b7da4ac 9091}
9092 [(set_attr "type" "multiple")]
9093)
9c08d1fa 9094
080c0b9a 9095;; Attempt to improve the sequence generated by the compare_scc splitters
9096;; not to use conditional execution.
98562479 9097
9098;; Rd = (eq (reg1) (const_int0)) // ARMv5
9099;; clz Rd, reg1
9100;; lsr Rd, Rd, #5
080c0b9a 9101(define_peephole2
9102 [(set (reg:CC CC_REGNUM)
9103 (compare:CC (match_operand:SI 1 "register_operand" "")
98562479 9104 (const_int 0)))
9105 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
9106 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
9107 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
9108 (set (match_dup 0) (const_int 1)))]
9109 "arm_arch5 && TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)"
9110 [(set (match_dup 0) (clz:SI (match_dup 1)))
9111 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 5)))]
9112)
9113
9114;; Rd = (eq (reg1) (const_int0)) // !ARMv5
9115;; negs Rd, reg1
9116;; adc Rd, Rd, reg1
9117(define_peephole2
9118 [(set (reg:CC CC_REGNUM)
9119 (compare:CC (match_operand:SI 1 "register_operand" "")
9120 (const_int 0)))
080c0b9a 9121 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
9122 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
9123 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
9124 (set (match_dup 0) (const_int 1)))
98562479 9125 (match_scratch:SI 2 "r")]
9126 "TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)"
922b6913 9127 [(parallel
9128 [(set (reg:CC CC_REGNUM)
98562479 9129 (compare:CC (const_int 0) (match_dup 1)))
9130 (set (match_dup 2) (minus:SI (const_int 0) (match_dup 1)))])
9131 (set (match_dup 0)
9132 (plus:SI (plus:SI (match_dup 1) (match_dup 2))
9133 (geu:SI (reg:CC CC_REGNUM) (const_int 0))))]
9134)
9135
31991287 9136;; Rd = (eq (reg1) (reg2/imm)) // ARMv5 and optimising for speed.
98562479 9137;; sub Rd, Reg1, reg2
9138;; clz Rd, Rd
9139;; lsr Rd, Rd, #5
9140(define_peephole2
9141 [(set (reg:CC CC_REGNUM)
9142 (compare:CC (match_operand:SI 1 "register_operand" "")
9143 (match_operand:SI 2 "arm_rhs_operand" "")))
9144 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
9145 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
9146 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
9147 (set (match_dup 0) (const_int 1)))]
31991287 9148 "arm_arch5 && TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)
9149 && !(TARGET_THUMB2 && optimize_insn_for_size_p ())"
98562479 9150 [(set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))
9151 (set (match_dup 0) (clz:SI (match_dup 0)))
9152 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 5)))]
9153)
9154
9155
31991287 9156;; Rd = (eq (reg1) (reg2)) // ! ARMv5 or optimising for size.
98562479 9157;; sub T1, Reg1, reg2
9158;; negs Rd, T1
9159;; adc Rd, Rd, T1
9160(define_peephole2
9161 [(set (reg:CC CC_REGNUM)
9162 (compare:CC (match_operand:SI 1 "register_operand" "")
9163 (match_operand:SI 2 "arm_rhs_operand" "")))
9164 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
9165 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
9166 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
9167 (set (match_dup 0) (const_int 1)))
9168 (match_scratch:SI 3 "r")]
9169 "TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)"
31991287 9170 [(set (match_dup 3) (match_dup 4))
080c0b9a 9171 (parallel
9172 [(set (reg:CC CC_REGNUM)
9173 (compare:CC (const_int 0) (match_dup 3)))
9174 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 3)))])
98562479 9175 (set (match_dup 0)
9176 (plus:SI (plus:SI (match_dup 0) (match_dup 3))
9177 (geu:SI (reg:CC CC_REGNUM) (const_int 0))))]
31991287 9178 "
9179 if (CONST_INT_P (operands[2]))
9180 operands[4] = plus_constant (SImode, operands[1], -INTVAL (operands[2]));
9181 else
9182 operands[4] = gen_rtx_MINUS (SImode, operands[1], operands[2]);
9183 ")
080c0b9a 9184
f7fbdd4a 9185(define_insn "*cond_move"
9c08d1fa 9186 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
aea4c774 9187 (if_then_else:SI (match_operator 3 "equality_operator"
8fa3ba89 9188 [(match_operator 4 "arm_comparison_operator"
8a18b90c 9189 [(match_operand 5 "cc_register" "") (const_int 0)])
aea4c774 9190 (const_int 0)])
9191 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9192 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
cffb2a26 9193 "TARGET_ARM"
9c08d1fa 9194 "*
8fa3ba89 9195 if (GET_CODE (operands[3]) == NE)
9196 {
9197 if (which_alternative != 1)
9198 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
9199 if (which_alternative != 0)
9200 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
9201 return \"\";
9202 }
9203 if (which_alternative != 0)
9204 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9205 if (which_alternative != 1)
9206 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
9207 return \"\";
9208 "
9209 [(set_attr "conds" "use")
282b4c75 9210 (set_attr_alternative "type"
9211 [(if_then_else (match_operand 2 "const_int_operand" "")
9212 (const_string "mov_imm")
9213 (const_string "mov_reg"))
9214 (if_then_else (match_operand 1 "const_int_operand" "")
9215 (const_string "mov_imm")
9216 (const_string "mov_reg"))
9217 (const_string "multiple")])
8fa3ba89 9218 (set_attr "length" "4,4,8")]
9219)
9c08d1fa 9220
f7fbdd4a 9221(define_insn "*cond_arith"
9c08d1fa 9222 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9223 (match_operator:SI 5 "shiftable_operator"
8fa3ba89 9224 [(match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 9225 [(match_operand:SI 2 "s_register_operand" "r,r")
9226 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
9227 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 9228 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9229 "TARGET_ARM"
9c08d1fa 9230 "*
8fa3ba89 9231 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
9232 return \"%i5\\t%0, %1, %2, lsr #31\";
40dbec34 9233
8fa3ba89 9234 output_asm_insn (\"cmp\\t%2, %3\", operands);
9235 if (GET_CODE (operands[5]) == AND)
9236 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
9237 else if (GET_CODE (operands[5]) == MINUS)
9238 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
9239 else if (which_alternative != 0)
9240 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9241 return \"%i5%d4\\t%0, %1, #1\";
9242 "
9243 [(set_attr "conds" "clob")
1b7da4ac 9244 (set_attr "length" "12")
9245 (set_attr "type" "multiple")]
8fa3ba89 9246)
9c08d1fa 9247
f7fbdd4a 9248(define_insn "*cond_sub"
9c08d1fa 9249 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9250 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8fa3ba89 9251 (match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 9252 [(match_operand:SI 2 "s_register_operand" "r,r")
9253 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 9254 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9255 "TARGET_ARM"
9c08d1fa 9256 "*
8fa3ba89 9257 output_asm_insn (\"cmp\\t%2, %3\", operands);
9258 if (which_alternative != 0)
9259 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9260 return \"sub%d4\\t%0, %1, #1\";
9261 "
9262 [(set_attr "conds" "clob")
1b7da4ac 9263 (set_attr "length" "8,12")
9264 (set_attr "type" "multiple")]
8fa3ba89 9265)
9c08d1fa 9266
aea4c774 9267(define_insn "*cmp_ite0"
cffb2a26 9268 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 9269 (compare
9270 (if_then_else:SI
8fa3ba89 9271 (match_operator 4 "arm_comparison_operator"
2ff91fec 9272 [(match_operand:SI 0 "s_register_operand"
9273 "l,l,l,r,r,r,r,r,r")
9274 (match_operand:SI 1 "arm_add_operand"
9275 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
8fa3ba89 9276 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 9277 [(match_operand:SI 2 "s_register_operand"
9278 "l,r,r,l,l,r,r,r,r")
9279 (match_operand:SI 3 "arm_add_operand"
9280 "lPy,rI,L,lPy,lPy,rI,rI,L,L")])
aea4c774 9281 (const_int 0))
9282 (const_int 0)))]
2ff91fec 9283 "TARGET_32BIT"
9c08d1fa 9284 "*
aea4c774 9285 {
2ff91fec 9286 static const char * const cmp1[NUM_OF_COND_CMP][2] =
9287 {
9288 {\"cmp%d5\\t%0, %1\",
9289 \"cmp%d4\\t%2, %3\"},
9290 {\"cmn%d5\\t%0, #%n1\",
9291 \"cmp%d4\\t%2, %3\"},
9292 {\"cmp%d5\\t%0, %1\",
9293 \"cmn%d4\\t%2, #%n3\"},
9294 {\"cmn%d5\\t%0, #%n1\",
9295 \"cmn%d4\\t%2, #%n3\"}
9296 };
9297 static const char * const cmp2[NUM_OF_COND_CMP][2] =
9298 {
9299 {\"cmp\\t%2, %3\",
9300 \"cmp\\t%0, %1\"},
9301 {\"cmp\\t%2, %3\",
9302 \"cmn\\t%0, #%n1\"},
9303 {\"cmn\\t%2, #%n3\",
9304 \"cmp\\t%0, %1\"},
9305 {\"cmn\\t%2, #%n3\",
9306 \"cmn\\t%0, #%n1\"}
9307 };
9308 static const char * const ite[2] =
8fa3ba89 9309 {
2ff91fec 9310 \"it\\t%d5\",
9311 \"it\\t%d4\"
8fa3ba89 9312 };
2ff91fec 9313 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
9314 CMP_CMP, CMN_CMP, CMP_CMP,
9315 CMN_CMP, CMP_CMN, CMN_CMN};
8fa3ba89 9316 int swap =
9317 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9318
2ff91fec 9319 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9320 if (TARGET_THUMB2) {
9321 output_asm_insn (ite[swap], operands);
9322 }
9323 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9324 return \"\";
8fa3ba89 9325 }"
9326 [(set_attr "conds" "set")
2ff91fec 9327 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
1b7da4ac 9328 (set_attr "type" "multiple")
2ff91fec 9329 (set_attr_alternative "length"
9330 [(const_int 6)
9331 (const_int 8)
9332 (const_int 8)
9333 (const_int 8)
9334 (const_int 8)
9335 (if_then_else (eq_attr "is_thumb" "no")
9336 (const_int 8)
9337 (const_int 10))
9338 (if_then_else (eq_attr "is_thumb" "no")
9339 (const_int 8)
9340 (const_int 10))
9341 (if_then_else (eq_attr "is_thumb" "no")
9342 (const_int 8)
9343 (const_int 10))
9344 (if_then_else (eq_attr "is_thumb" "no")
9345 (const_int 8)
9346 (const_int 10))])]
8fa3ba89 9347)
9c08d1fa 9348
aea4c774 9349(define_insn "*cmp_ite1"
cffb2a26 9350 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 9351 (compare
9352 (if_then_else:SI
8fa3ba89 9353 (match_operator 4 "arm_comparison_operator"
2ff91fec 9354 [(match_operand:SI 0 "s_register_operand"
9355 "l,l,l,r,r,r,r,r,r")
9356 (match_operand:SI 1 "arm_add_operand"
9357 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
8fa3ba89 9358 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 9359 [(match_operand:SI 2 "s_register_operand"
9360 "l,r,r,l,l,r,r,r,r")
9361 (match_operand:SI 3 "arm_add_operand"
9362 "lPy,rI,L,lPy,lPy,rI,rI,L,L")])
aea4c774 9363 (const_int 1))
9364 (const_int 0)))]
2ff91fec 9365 "TARGET_32BIT"
9c08d1fa 9366 "*
9c08d1fa 9367 {
2ff91fec 9368 static const char * const cmp1[NUM_OF_COND_CMP][2] =
9369 {
9370 {\"cmp\\t%0, %1\",
9371 \"cmp\\t%2, %3\"},
9372 {\"cmn\\t%0, #%n1\",
9373 \"cmp\\t%2, %3\"},
9374 {\"cmp\\t%0, %1\",
9375 \"cmn\\t%2, #%n3\"},
9376 {\"cmn\\t%0, #%n1\",
9377 \"cmn\\t%2, #%n3\"}
9378 };
9379 static const char * const cmp2[NUM_OF_COND_CMP][2] =
215b30b3 9380 {
2ff91fec 9381 {\"cmp%d4\\t%2, %3\",
9382 \"cmp%D5\\t%0, %1\"},
9383 {\"cmp%d4\\t%2, %3\",
9384 \"cmn%D5\\t%0, #%n1\"},
9385 {\"cmn%d4\\t%2, #%n3\",
9386 \"cmp%D5\\t%0, %1\"},
9387 {\"cmn%d4\\t%2, #%n3\",
9388 \"cmn%D5\\t%0, #%n1\"}
215b30b3 9389 };
2ff91fec 9390 static const char * const ite[2] =
9391 {
9392 \"it\\t%d4\",
9393 \"it\\t%D5\"
9394 };
9395 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
9396 CMP_CMP, CMN_CMP, CMP_CMP,
9397 CMN_CMP, CMP_CMN, CMN_CMN};
215b30b3 9398 int swap =
9399 comparison_dominates_p (GET_CODE (operands[5]),
9400 reverse_condition (GET_CODE (operands[4])));
9401
2ff91fec 9402 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9403 if (TARGET_THUMB2) {
9404 output_asm_insn (ite[swap], operands);
9405 }
9406 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9407 return \"\";
215b30b3 9408 }"
8fa3ba89 9409 [(set_attr "conds" "set")
2ff91fec 9410 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
9411 (set_attr_alternative "length"
9412 [(const_int 6)
9413 (const_int 8)
9414 (const_int 8)
9415 (const_int 8)
9416 (const_int 8)
9417 (if_then_else (eq_attr "is_thumb" "no")
9418 (const_int 8)
9419 (const_int 10))
9420 (if_then_else (eq_attr "is_thumb" "no")
9421 (const_int 8)
9422 (const_int 10))
9423 (if_then_else (eq_attr "is_thumb" "no")
9424 (const_int 8)
9425 (const_int 10))
9426 (if_then_else (eq_attr "is_thumb" "no")
9427 (const_int 8)
1b7da4ac 9428 (const_int 10))])
9429 (set_attr "type" "multiple")]
8fa3ba89 9430)
9c08d1fa 9431
f6c53574 9432(define_insn "*cmp_and"
9433 [(set (match_operand 6 "dominant_cc_register" "")
9434 (compare
9435 (and:SI
9436 (match_operator 4 "arm_comparison_operator"
2ff91fec 9437 [(match_operand:SI 0 "s_register_operand"
9438 "l,l,l,r,r,r,r,r,r")
9439 (match_operand:SI 1 "arm_add_operand"
9440 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
f6c53574 9441 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 9442 [(match_operand:SI 2 "s_register_operand"
9443 "l,r,r,l,l,r,r,r,r")
9444 (match_operand:SI 3 "arm_add_operand"
9445 "lPy,rI,L,lPy,lPy,rI,rI,L,L")]))
f6c53574 9446 (const_int 0)))]
2ff91fec 9447 "TARGET_32BIT"
f6c53574 9448 "*
9449 {
2ff91fec 9450 static const char *const cmp1[NUM_OF_COND_CMP][2] =
f6c53574 9451 {
2ff91fec 9452 {\"cmp%d5\\t%0, %1\",
9453 \"cmp%d4\\t%2, %3\"},
9454 {\"cmn%d5\\t%0, #%n1\",
9455 \"cmp%d4\\t%2, %3\"},
9456 {\"cmp%d5\\t%0, %1\",
9457 \"cmn%d4\\t%2, #%n3\"},
9458 {\"cmn%d5\\t%0, #%n1\",
9459 \"cmn%d4\\t%2, #%n3\"}
f6c53574 9460 };
2ff91fec 9461 static const char *const cmp2[NUM_OF_COND_CMP][2] =
9462 {
9463 {\"cmp\\t%2, %3\",
9464 \"cmp\\t%0, %1\"},
9465 {\"cmp\\t%2, %3\",
9466 \"cmn\\t%0, #%n1\"},
9467 {\"cmn\\t%2, #%n3\",
9468 \"cmp\\t%0, %1\"},
9469 {\"cmn\\t%2, #%n3\",
9470 \"cmn\\t%0, #%n1\"}
9471 };
9472 static const char *const ite[2] =
9473 {
9474 \"it\\t%d5\",
9475 \"it\\t%d4\"
9476 };
9477 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
9478 CMP_CMP, CMN_CMP, CMP_CMP,
9479 CMN_CMP, CMP_CMN, CMN_CMN};
f6c53574 9480 int swap =
9481 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9482
2ff91fec 9483 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9484 if (TARGET_THUMB2) {
9485 output_asm_insn (ite[swap], operands);
9486 }
9487 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9488 return \"\";
f6c53574 9489 }"
9490 [(set_attr "conds" "set")
9491 (set_attr "predicable" "no")
2ff91fec 9492 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
9493 (set_attr_alternative "length"
9494 [(const_int 6)
9495 (const_int 8)
9496 (const_int 8)
9497 (const_int 8)
9498 (const_int 8)
9499 (if_then_else (eq_attr "is_thumb" "no")
9500 (const_int 8)
9501 (const_int 10))
9502 (if_then_else (eq_attr "is_thumb" "no")
9503 (const_int 8)
9504 (const_int 10))
9505 (if_then_else (eq_attr "is_thumb" "no")
9506 (const_int 8)
9507 (const_int 10))
9508 (if_then_else (eq_attr "is_thumb" "no")
9509 (const_int 8)
1b7da4ac 9510 (const_int 10))])
9511 (set_attr "type" "multiple")]
f6c53574 9512)
9513
9514(define_insn "*cmp_ior"
9515 [(set (match_operand 6 "dominant_cc_register" "")
9516 (compare
9517 (ior:SI
9518 (match_operator 4 "arm_comparison_operator"
2ff91fec 9519 [(match_operand:SI 0 "s_register_operand"
9520 "l,l,l,r,r,r,r,r,r")
9521 (match_operand:SI 1 "arm_add_operand"
9522 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
f6c53574 9523 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 9524 [(match_operand:SI 2 "s_register_operand"
9525 "l,r,r,l,l,r,r,r,r")
9526 (match_operand:SI 3 "arm_add_operand"
9527 "lPy,rI,L,lPy,lPy,rI,rI,L,L")]))
f6c53574 9528 (const_int 0)))]
2ff91fec 9529 "TARGET_32BIT"
f6c53574 9530 "*
f6c53574 9531 {
2ff91fec 9532 static const char *const cmp1[NUM_OF_COND_CMP][2] =
9533 {
9534 {\"cmp\\t%0, %1\",
9535 \"cmp\\t%2, %3\"},
9536 {\"cmn\\t%0, #%n1\",
9537 \"cmp\\t%2, %3\"},
9538 {\"cmp\\t%0, %1\",
9539 \"cmn\\t%2, #%n3\"},
9540 {\"cmn\\t%0, #%n1\",
9541 \"cmn\\t%2, #%n3\"}
9542 };
9543 static const char *const cmp2[NUM_OF_COND_CMP][2] =
9544 {
9545 {\"cmp%D4\\t%2, %3\",
9546 \"cmp%D5\\t%0, %1\"},
9547 {\"cmp%D4\\t%2, %3\",
9548 \"cmn%D5\\t%0, #%n1\"},
9549 {\"cmn%D4\\t%2, #%n3\",
9550 \"cmp%D5\\t%0, %1\"},
9551 {\"cmn%D4\\t%2, #%n3\",
9552 \"cmn%D5\\t%0, #%n1\"}
9553 };
9554 static const char *const ite[2] =
9555 {
9556 \"it\\t%D4\",
9557 \"it\\t%D5\"
9558 };
9559 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
9560 CMP_CMP, CMN_CMP, CMP_CMP,
9561 CMN_CMP, CMP_CMN, CMN_CMN};
9562 int swap =
9563 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9564
9565 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9566 if (TARGET_THUMB2) {
9567 output_asm_insn (ite[swap], operands);
9568 }
9569 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9570 return \"\";
9571 }
9572 "
f6c53574 9573 [(set_attr "conds" "set")
2ff91fec 9574 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
9575 (set_attr_alternative "length"
9576 [(const_int 6)
9577 (const_int 8)
9578 (const_int 8)
9579 (const_int 8)
9580 (const_int 8)
9581 (if_then_else (eq_attr "is_thumb" "no")
9582 (const_int 8)
9583 (const_int 10))
9584 (if_then_else (eq_attr "is_thumb" "no")
9585 (const_int 8)
9586 (const_int 10))
9587 (if_then_else (eq_attr "is_thumb" "no")
9588 (const_int 8)
9589 (const_int 10))
9590 (if_then_else (eq_attr "is_thumb" "no")
9591 (const_int 8)
1b7da4ac 9592 (const_int 10))])
9593 (set_attr "type" "multiple")]
f6c53574 9594)
9595
3c5afce6 9596(define_insn_and_split "*ior_scc_scc"
fd711051 9597 [(set (match_operand:SI 0 "s_register_operand" "=Ts")
3c5afce6 9598 (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9599 [(match_operand:SI 1 "s_register_operand" "r")
9600 (match_operand:SI 2 "arm_add_operand" "rIL")])
9601 (match_operator:SI 6 "arm_comparison_operator"
9602 [(match_operand:SI 4 "s_register_operand" "r")
9603 (match_operand:SI 5 "arm_add_operand" "rIL")])))
9604 (clobber (reg:CC CC_REGNUM))]
2ff91fec 9605 "TARGET_32BIT
3c5afce6 9606 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
9607 != CCmode)"
9608 "#"
2ff91fec 9609 "TARGET_32BIT && reload_completed"
3c5afce6 9610 [(set (match_dup 7)
9611 (compare
9612 (ior:SI
9613 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9614 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9615 (const_int 0)))
9616 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9617 "operands[7]
9618 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9619 DOM_CC_X_OR_Y),
601f584c 9620 CC_REGNUM);"
9621 [(set_attr "conds" "clob")
1b7da4ac 9622 (set_attr "length" "16")
9623 (set_attr "type" "multiple")]
9624)
601f584c 9625
9626; If the above pattern is followed by a CMP insn, then the compare is
9627; redundant, since we can rework the conditional instruction that follows.
9628(define_insn_and_split "*ior_scc_scc_cmp"
9629 [(set (match_operand 0 "dominant_cc_register" "")
9630 (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9631 [(match_operand:SI 1 "s_register_operand" "r")
9632 (match_operand:SI 2 "arm_add_operand" "rIL")])
9633 (match_operator:SI 6 "arm_comparison_operator"
9634 [(match_operand:SI 4 "s_register_operand" "r")
9635 (match_operand:SI 5 "arm_add_operand" "rIL")]))
9636 (const_int 0)))
fd711051 9637 (set (match_operand:SI 7 "s_register_operand" "=Ts")
601f584c 9638 (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9639 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
2ff91fec 9640 "TARGET_32BIT"
601f584c 9641 "#"
2ff91fec 9642 "TARGET_32BIT && reload_completed"
601f584c 9643 [(set (match_dup 0)
9644 (compare
9645 (ior:SI
9646 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9647 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9648 (const_int 0)))
9649 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9650 ""
9651 [(set_attr "conds" "set")
1b7da4ac 9652 (set_attr "length" "16")
9653 (set_attr "type" "multiple")]
9654)
3c5afce6 9655
9656(define_insn_and_split "*and_scc_scc"
fd711051 9657 [(set (match_operand:SI 0 "s_register_operand" "=Ts")
3c5afce6 9658 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9659 [(match_operand:SI 1 "s_register_operand" "r")
9660 (match_operand:SI 2 "arm_add_operand" "rIL")])
9661 (match_operator:SI 6 "arm_comparison_operator"
9662 [(match_operand:SI 4 "s_register_operand" "r")
9663 (match_operand:SI 5 "arm_add_operand" "rIL")])))
9664 (clobber (reg:CC CC_REGNUM))]
2ff91fec 9665 "TARGET_32BIT
3c5afce6 9666 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9667 != CCmode)"
9668 "#"
2ff91fec 9669 "TARGET_32BIT && reload_completed
601f584c 9670 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9671 != CCmode)"
3c5afce6 9672 [(set (match_dup 7)
9673 (compare
9674 (and:SI
9675 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9676 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9677 (const_int 0)))
9678 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9679 "operands[7]
9680 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9681 DOM_CC_X_AND_Y),
601f584c 9682 CC_REGNUM);"
9683 [(set_attr "conds" "clob")
1b7da4ac 9684 (set_attr "length" "16")
9685 (set_attr "type" "multiple")]
9686)
601f584c 9687
9688; If the above pattern is followed by a CMP insn, then the compare is
9689; redundant, since we can rework the conditional instruction that follows.
9690(define_insn_and_split "*and_scc_scc_cmp"
9691 [(set (match_operand 0 "dominant_cc_register" "")
9692 (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
9693 [(match_operand:SI 1 "s_register_operand" "r")
9694 (match_operand:SI 2 "arm_add_operand" "rIL")])
9695 (match_operator:SI 6 "arm_comparison_operator"
9696 [(match_operand:SI 4 "s_register_operand" "r")
9697 (match_operand:SI 5 "arm_add_operand" "rIL")]))
9698 (const_int 0)))
fd711051 9699 (set (match_operand:SI 7 "s_register_operand" "=Ts")
601f584c 9700 (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9701 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
2ff91fec 9702 "TARGET_32BIT"
601f584c 9703 "#"
2ff91fec 9704 "TARGET_32BIT && reload_completed"
601f584c 9705 [(set (match_dup 0)
9706 (compare
9707 (and:SI
9708 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9709 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9710 (const_int 0)))
9711 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9712 ""
9713 [(set_attr "conds" "set")
1b7da4ac 9714 (set_attr "length" "16")
9715 (set_attr "type" "multiple")]
9716)
601f584c 9717
9718;; If there is no dominance in the comparison, then we can still save an
9719;; instruction in the AND case, since we can know that the second compare
9720;; need only zero the value if false (if true, then the value is already
9721;; correct).
9722(define_insn_and_split "*and_scc_scc_nodom"
fd711051 9723 [(set (match_operand:SI 0 "s_register_operand" "=&Ts,&Ts,&Ts")
601f584c 9724 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9725 [(match_operand:SI 1 "s_register_operand" "r,r,0")
9726 (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
9727 (match_operator:SI 6 "arm_comparison_operator"
9728 [(match_operand:SI 4 "s_register_operand" "r,r,r")
9729 (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
9730 (clobber (reg:CC CC_REGNUM))]
2ff91fec 9731 "TARGET_32BIT
601f584c 9732 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9733 == CCmode)"
9734 "#"
2ff91fec 9735 "TARGET_32BIT && reload_completed"
601f584c 9736 [(parallel [(set (match_dup 0)
9737 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
9738 (clobber (reg:CC CC_REGNUM))])
9739 (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
9740 (set (match_dup 0)
9741 (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
9742 (match_dup 0)
9743 (const_int 0)))]
9744 "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
9745 operands[4], operands[5]),
9746 CC_REGNUM);
9747 operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
9748 operands[5]);"
9749 [(set_attr "conds" "clob")
1b7da4ac 9750 (set_attr "length" "20")
9751 (set_attr "type" "multiple")]
9752)
3c5afce6 9753
3a0bdee0 9754(define_split
9755 [(set (reg:CC_NOOV CC_REGNUM)
9756 (compare:CC_NOOV (ior:SI
9757 (and:SI (match_operand:SI 0 "s_register_operand" "")
9758 (const_int 1))
b0694be0 9759 (match_operator:SI 1 "arm_comparison_operator"
3a0bdee0 9760 [(match_operand:SI 2 "s_register_operand" "")
9761 (match_operand:SI 3 "arm_add_operand" "")]))
9762 (const_int 0)))
9763 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9764 "TARGET_ARM"
9765 [(set (match_dup 4)
9766 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9767 (match_dup 0)))
9768 (set (reg:CC_NOOV CC_REGNUM)
9769 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9770 (const_int 0)))]
9771 "")
9772
9773(define_split
9774 [(set (reg:CC_NOOV CC_REGNUM)
9775 (compare:CC_NOOV (ior:SI
b0694be0 9776 (match_operator:SI 1 "arm_comparison_operator"
3a0bdee0 9777 [(match_operand:SI 2 "s_register_operand" "")
9778 (match_operand:SI 3 "arm_add_operand" "")])
9779 (and:SI (match_operand:SI 0 "s_register_operand" "")
9780 (const_int 1)))
9781 (const_int 0)))
9782 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9783 "TARGET_ARM"
9784 [(set (match_dup 4)
9785 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9786 (match_dup 0)))
9787 (set (reg:CC_NOOV CC_REGNUM)
9788 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9789 (const_int 0)))]
9790 "")
25f905c2 9791;; ??? The conditional patterns above need checking for Thumb-2 usefulness
3a0bdee0 9792
190efb17 9793(define_insn_and_split "*negscc"
9c08d1fa 9794 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9795 (neg:SI (match_operator 3 "arm_comparison_operator"
9c08d1fa 9796 [(match_operand:SI 1 "s_register_operand" "r")
9797 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
bd5b4116 9798 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9799 "TARGET_ARM"
190efb17 9800 "#"
9801 "&& reload_completed"
9802 [(const_int 0)]
9803 {
9804 rtx cc_reg = gen_rtx_REG (CCmode, CC_REGNUM);
e2348bcb 9805
190efb17 9806 if (GET_CODE (operands[3]) == LT && operands[2] == const0_rtx)
9807 {
9808 /* Emit mov\\t%0, %1, asr #31 */
d1f9b275 9809 emit_insn (gen_rtx_SET (operands[0],
190efb17 9810 gen_rtx_ASHIFTRT (SImode,
9811 operands[1],
9812 GEN_INT (31))));
9813 DONE;
9814 }
9815 else if (GET_CODE (operands[3]) == NE)
9816 {
9817 /* Emit subs\\t%0, %1, %2\;mvnne\\t%0, #0 */
9818 if (CONST_INT_P (operands[2]))
9819 emit_insn (gen_cmpsi2_addneg (operands[0], operands[1], operands[2],
9820 GEN_INT (- INTVAL (operands[2]))));
9821 else
9822 emit_insn (gen_subsi3_compare (operands[0], operands[1], operands[2]));
9823
9824 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
9825 gen_rtx_NE (SImode,
9826 cc_reg,
9827 const0_rtx),
d1f9b275 9828 gen_rtx_SET (operands[0],
190efb17 9829 GEN_INT (~0))));
9830 DONE;
9831 }
9832 else
9833 {
9834 /* Emit: cmp\\t%1, %2\;mov%D3\\t%0, #0\;mvn%d3\\t%0, #0 */
d1f9b275 9835 emit_insn (gen_rtx_SET (cc_reg,
190efb17 9836 gen_rtx_COMPARE (CCmode, operands[1], operands[2])));
9837 enum rtx_code rc = GET_CODE (operands[3]);
9838
9839 rc = reverse_condition (rc);
9840 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
9841 gen_rtx_fmt_ee (rc,
9842 VOIDmode,
9843 cc_reg,
9844 const0_rtx),
d1f9b275 9845 gen_rtx_SET (operands[0], const0_rtx)));
190efb17 9846 rc = GET_CODE (operands[3]);
9847 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
9848 gen_rtx_fmt_ee (rc,
9849 VOIDmode,
9850 cc_reg,
9851 const0_rtx),
d1f9b275 9852 gen_rtx_SET (operands[0],
190efb17 9853 GEN_INT (~0))));
9854 DONE;
9855 }
9856 FAIL;
9857 }
8fa3ba89 9858 [(set_attr "conds" "clob")
1b7da4ac 9859 (set_attr "length" "12")
9860 (set_attr "type" "multiple")]
8fa3ba89 9861)
9c08d1fa 9862
90404b57 9863(define_insn_and_split "movcond_addsi"
9864 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r")
9865 (if_then_else:SI
9866 (match_operator 5 "comparison_operator"
9867 [(plus:SI (match_operand:SI 3 "s_register_operand" "r,r,r")
9868 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL"))
9869 (const_int 0)])
9870 (match_operand:SI 1 "arm_rhs_operand" "rI,rPy,r")
9871 (match_operand:SI 2 "arm_rhs_operand" "rI,rPy,r")))
9872 (clobber (reg:CC CC_REGNUM))]
9873 "TARGET_32BIT"
9874 "#"
9875 "&& reload_completed"
9876 [(set (reg:CC_NOOV CC_REGNUM)
9877 (compare:CC_NOOV
9878 (plus:SI (match_dup 3)
9879 (match_dup 4))
9880 (const_int 0)))
9881 (set (match_dup 0) (match_dup 1))
9882 (cond_exec (match_dup 6)
9883 (set (match_dup 0) (match_dup 2)))]
9884 "
9885 {
3754d046 9886 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[5]),
90404b57 9887 operands[3], operands[4]);
9888 enum rtx_code rc = GET_CODE (operands[5]);
90404b57 9889 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9890 gcc_assert (!(mode == CCFPmode || mode == CCFPEmode));
22440aeb 9891 if (!REG_P (operands[2]) || REGNO (operands[2]) != REGNO (operands[0]))
4d01ce2f 9892 rc = reverse_condition (rc);
f145bcba 9893 else
9894 std::swap (operands[1], operands[2]);
90404b57 9895
9896 operands[6] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9897 }
9898 "
9899 [(set_attr "conds" "clob")
1b7da4ac 9900 (set_attr "enabled_for_depr_it" "no,yes,yes")
9901 (set_attr "type" "multiple")]
90404b57 9902)
9903
9c08d1fa 9904(define_insn "movcond"
9905 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 9906 (if_then_else:SI
8fa3ba89 9907 (match_operator 5 "arm_comparison_operator"
5565501b 9908 [(match_operand:SI 3 "s_register_operand" "r,r,r")
9909 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
9910 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9911 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 9912 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9913 "TARGET_ARM"
9c08d1fa 9914 "*
9915 if (GET_CODE (operands[5]) == LT
9916 && (operands[4] == const0_rtx))
9917 {
0438d37f 9918 if (which_alternative != 1 && REG_P (operands[1]))
9c08d1fa 9919 {
9c08d1fa 9920 if (operands[2] == const0_rtx)
e2348bcb 9921 return \"and\\t%0, %1, %3, asr #31\";
9922 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
9c08d1fa 9923 }
0438d37f 9924 else if (which_alternative != 0 && REG_P (operands[2]))
9c08d1fa 9925 {
9c08d1fa 9926 if (operands[1] == const0_rtx)
e2348bcb 9927 return \"bic\\t%0, %2, %3, asr #31\";
9928 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
9c08d1fa 9929 }
9930 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 9931 are constants. */
9c08d1fa 9932 }
e2348bcb 9933
9c08d1fa 9934 if (GET_CODE (operands[5]) == GE
9935 && (operands[4] == const0_rtx))
9936 {
0438d37f 9937 if (which_alternative != 1 && REG_P (operands[1]))
9c08d1fa 9938 {
9c08d1fa 9939 if (operands[2] == const0_rtx)
e2348bcb 9940 return \"bic\\t%0, %1, %3, asr #31\";
9941 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
9c08d1fa 9942 }
0438d37f 9943 else if (which_alternative != 0 && REG_P (operands[2]))
9c08d1fa 9944 {
9c08d1fa 9945 if (operands[1] == const0_rtx)
e2348bcb 9946 return \"and\\t%0, %2, %3, asr #31\";
9947 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
9c08d1fa 9948 }
9949 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 9950 are constants. */
9c08d1fa 9951 }
0438d37f 9952 if (CONST_INT_P (operands[4])
9c08d1fa 9953 && !const_ok_for_arm (INTVAL (operands[4])))
e2348bcb 9954 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
9c08d1fa 9955 else
e2348bcb 9956 output_asm_insn (\"cmp\\t%3, %4\", operands);
9c08d1fa 9957 if (which_alternative != 0)
e2348bcb 9958 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
9c08d1fa 9959 if (which_alternative != 1)
e2348bcb 9960 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
9c08d1fa 9961 return \"\";
215b30b3 9962 "
8fa3ba89 9963 [(set_attr "conds" "clob")
1b7da4ac 9964 (set_attr "length" "8,8,12")
9965 (set_attr "type" "multiple")]
8fa3ba89 9966)
9c08d1fa 9967
25f905c2 9968;; ??? The patterns below need checking for Thumb-2 usefulness.
9969
8a18b90c 9970(define_insn "*ifcompare_plus_move"
9971 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9972 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 9973 [(match_operand:SI 4 "s_register_operand" "r,r")
9974 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9975 (plus:SI
9976 (match_operand:SI 2 "s_register_operand" "r,r")
9977 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
129a2fe4 9978 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 9979 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9980 "TARGET_ARM"
8a18b90c 9981 "#"
8fa3ba89 9982 [(set_attr "conds" "clob")
1b7da4ac 9983 (set_attr "length" "8,12")
9984 (set_attr "type" "multiple")]
8fa3ba89 9985)
8a18b90c 9986
9987(define_insn "*if_plus_move"
129a2fe4 9988 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 9989 (if_then_else:SI
8fa3ba89 9990 (match_operator 4 "arm_comparison_operator"
8a18b90c 9991 [(match_operand 5 "cc_register" "") (const_int 0)])
9992 (plus:SI
129a2fe4 9993 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9994 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
9995 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
cffb2a26 9996 "TARGET_ARM"
8a18b90c 9997 "@
9998 add%d4\\t%0, %2, %3
9999 sub%d4\\t%0, %2, #%n3
10000 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
129a2fe4 10001 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8fa3ba89 10002 [(set_attr "conds" "use")
10003 (set_attr "length" "4,4,8,8")
65f68e55 10004 (set_attr_alternative "type"
10005 [(if_then_else (match_operand 3 "const_int_operand" "")
d82e788e 10006 (const_string "alu_imm" )
112eda6f 10007 (const_string "alu_sreg"))
d82e788e 10008 (const_string "alu_imm")
282b4c75 10009 (const_string "multiple")
10010 (const_string "multiple")])]
8fa3ba89 10011)
8a18b90c 10012
10013(define_insn "*ifcompare_move_plus"
5565501b 10014 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10015 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 10016 [(match_operand:SI 4 "s_register_operand" "r,r")
10017 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 10018 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 10019 (plus:SI
10020 (match_operand:SI 2 "s_register_operand" "r,r")
10021 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
bd5b4116 10022 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10023 "TARGET_ARM"
8a18b90c 10024 "#"
8fa3ba89 10025 [(set_attr "conds" "clob")
1b7da4ac 10026 (set_attr "length" "8,12")
10027 (set_attr "type" "multiple")]
8fa3ba89 10028)
8a18b90c 10029
10030(define_insn "*if_move_plus"
129a2fe4 10031 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 10032 (if_then_else:SI
8fa3ba89 10033 (match_operator 4 "arm_comparison_operator"
8a18b90c 10034 [(match_operand 5 "cc_register" "") (const_int 0)])
129a2fe4 10035 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8a18b90c 10036 (plus:SI
129a2fe4 10037 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
10038 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
cffb2a26 10039 "TARGET_ARM"
8a18b90c 10040 "@
10041 add%D4\\t%0, %2, %3
10042 sub%D4\\t%0, %2, #%n3
10043 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
129a2fe4 10044 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8fa3ba89 10045 [(set_attr "conds" "use")
10046 (set_attr "length" "4,4,8,8")
282b4c75 10047 (set_attr_alternative "type"
10048 [(if_then_else (match_operand 3 "const_int_operand" "")
10049 (const_string "alu_imm" )
10050 (const_string "alu_sreg"))
10051 (const_string "alu_imm")
10052 (const_string "multiple")
10053 (const_string "multiple")])]
8fa3ba89 10054)
8a18b90c 10055
10056(define_insn "*ifcompare_arith_arith"
10057 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 10058 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8a18b90c 10059 [(match_operand:SI 5 "s_register_operand" "r")
10060 (match_operand:SI 6 "arm_add_operand" "rIL")])
9c08d1fa 10061 (match_operator:SI 8 "shiftable_operator"
8a18b90c 10062 [(match_operand:SI 1 "s_register_operand" "r")
10063 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9c08d1fa 10064 (match_operator:SI 7 "shiftable_operator"
8a18b90c 10065 [(match_operand:SI 3 "s_register_operand" "r")
10066 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
bd5b4116 10067 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10068 "TARGET_ARM"
8a18b90c 10069 "#"
8fa3ba89 10070 [(set_attr "conds" "clob")
1b7da4ac 10071 (set_attr "length" "12")
10072 (set_attr "type" "multiple")]
8fa3ba89 10073)
9c08d1fa 10074
8a18b90c 10075(define_insn "*if_arith_arith"
10076 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 10077 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8a18b90c 10078 [(match_operand 8 "cc_register" "") (const_int 0)])
10079 (match_operator:SI 6 "shiftable_operator"
10080 [(match_operand:SI 1 "s_register_operand" "r")
10081 (match_operand:SI 2 "arm_rhs_operand" "rI")])
10082 (match_operator:SI 7 "shiftable_operator"
10083 [(match_operand:SI 3 "s_register_operand" "r")
10084 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
cffb2a26 10085 "TARGET_ARM"
8a18b90c 10086 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8fa3ba89 10087 [(set_attr "conds" "use")
1b7da4ac 10088 (set_attr "length" "8")
10089 (set_attr "type" "multiple")]
8fa3ba89 10090)
8a18b90c 10091
f7fbdd4a 10092(define_insn "*ifcompare_arith_move"
9c08d1fa 10093 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10094 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 10095 [(match_operand:SI 2 "s_register_operand" "r,r")
5565501b 10096 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
9c08d1fa 10097 (match_operator:SI 7 "shiftable_operator"
10098 [(match_operand:SI 4 "s_register_operand" "r,r")
10099 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
129a2fe4 10100 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 10101 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10102 "TARGET_ARM"
9c08d1fa 10103 "*
9c08d1fa 10104 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 10105 the conditional operator is LT or GE and we are comparing against zero and
674a8f0b 10106 everything is in registers then we can do this in two instructions. */
9c08d1fa 10107 if (operands[3] == const0_rtx
10108 && GET_CODE (operands[7]) != AND
0438d37f 10109 && REG_P (operands[5])
10110 && REG_P (operands[1])
9c08d1fa 10111 && REGNO (operands[1]) == REGNO (operands[4])
10112 && REGNO (operands[4]) != REGNO (operands[0]))
10113 {
10114 if (GET_CODE (operands[6]) == LT)
40dbec34 10115 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 10116 else if (GET_CODE (operands[6]) == GE)
40dbec34 10117 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 10118 }
0438d37f 10119 if (CONST_INT_P (operands[3])
9c08d1fa 10120 && !const_ok_for_arm (INTVAL (operands[3])))
e2348bcb 10121 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
9c08d1fa 10122 else
e2348bcb 10123 output_asm_insn (\"cmp\\t%2, %3\", operands);
40dbec34 10124 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
9c08d1fa 10125 if (which_alternative != 0)
129a2fe4 10126 return \"mov%D6\\t%0, %1\";
9c08d1fa 10127 return \"\";
215b30b3 10128 "
8fa3ba89 10129 [(set_attr "conds" "clob")
1b7da4ac 10130 (set_attr "length" "8,12")
10131 (set_attr "type" "multiple")]
8fa3ba89 10132)
9c08d1fa 10133
8a18b90c 10134(define_insn "*if_arith_move"
129a2fe4 10135 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10136 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8a18b90c 10137 [(match_operand 6 "cc_register" "") (const_int 0)])
10138 (match_operator:SI 5 "shiftable_operator"
129a2fe4 10139 [(match_operand:SI 2 "s_register_operand" "r,r")
10140 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
10141 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
cffb2a26 10142 "TARGET_ARM"
8a18b90c 10143 "@
10144 %I5%d4\\t%0, %2, %3
129a2fe4 10145 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8fa3ba89 10146 [(set_attr "conds" "use")
10147 (set_attr "length" "4,8")
282b4c75 10148 (set_attr_alternative "type"
10149 [(if_then_else (match_operand 3 "const_int_operand" "")
10150 (const_string "alu_shift_imm" )
10151 (const_string "alu_shift_reg"))
10152 (const_string "multiple")])]
8fa3ba89 10153)
8a18b90c 10154
f7fbdd4a 10155(define_insn "*ifcompare_move_arith"
9c08d1fa 10156 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10157 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 10158 [(match_operand:SI 4 "s_register_operand" "r,r")
5565501b 10159 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 10160 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9c08d1fa 10161 (match_operator:SI 7 "shiftable_operator"
10162 [(match_operand:SI 2 "s_register_operand" "r,r")
10163 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 10164 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10165 "TARGET_ARM"
9c08d1fa 10166 "*
9c08d1fa 10167 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 10168 the conditional operator is LT or GE and we are comparing against zero and
9c08d1fa 10169 everything is in registers then we can do this in two instructions */
10170 if (operands[5] == const0_rtx
10171 && GET_CODE (operands[7]) != AND
0438d37f 10172 && REG_P (operands[3])
10173 && REG_P (operands[1])
9c08d1fa 10174 && REGNO (operands[1]) == REGNO (operands[2])
10175 && REGNO (operands[2]) != REGNO (operands[0]))
10176 {
10177 if (GET_CODE (operands[6]) == GE)
40dbec34 10178 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 10179 else if (GET_CODE (operands[6]) == LT)
40dbec34 10180 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 10181 }
40dbec34 10182
0438d37f 10183 if (CONST_INT_P (operands[5])
9c08d1fa 10184 && !const_ok_for_arm (INTVAL (operands[5])))
e2348bcb 10185 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
9c08d1fa 10186 else
e2348bcb 10187 output_asm_insn (\"cmp\\t%4, %5\", operands);
40dbec34 10188
9c08d1fa 10189 if (which_alternative != 0)
129a2fe4 10190 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
40dbec34 10191 return \"%I7%D6\\t%0, %2, %3\";
215b30b3 10192 "
8fa3ba89 10193 [(set_attr "conds" "clob")
1b7da4ac 10194 (set_attr "length" "8,12")
10195 (set_attr "type" "multiple")]
8fa3ba89 10196)
9c08d1fa 10197
8a18b90c 10198(define_insn "*if_move_arith"
129a2fe4 10199 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 10200 (if_then_else:SI
8fa3ba89 10201 (match_operator 4 "arm_comparison_operator"
8a18b90c 10202 [(match_operand 6 "cc_register" "") (const_int 0)])
129a2fe4 10203 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 10204 (match_operator:SI 5 "shiftable_operator"
129a2fe4 10205 [(match_operand:SI 2 "s_register_operand" "r,r")
10206 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
cffb2a26 10207 "TARGET_ARM"
8a18b90c 10208 "@
10209 %I5%D4\\t%0, %2, %3
129a2fe4 10210 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
8fa3ba89 10211 [(set_attr "conds" "use")
10212 (set_attr "length" "4,8")
282b4c75 10213 (set_attr_alternative "type"
10214 [(if_then_else (match_operand 3 "const_int_operand" "")
10215 (const_string "alu_shift_imm" )
10216 (const_string "alu_shift_reg"))
10217 (const_string "multiple")])]
8fa3ba89 10218)
8a18b90c 10219
10220(define_insn "*ifcompare_move_not"
9c08d1fa 10221 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 10222 (if_then_else:SI
8fa3ba89 10223 (match_operator 5 "arm_comparison_operator"
8a18b90c 10224 [(match_operand:SI 3 "s_register_operand" "r,r")
10225 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10226 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
10227 (not:SI
10228 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 10229 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10230 "TARGET_ARM"
8a18b90c 10231 "#"
8fa3ba89 10232 [(set_attr "conds" "clob")
1b7da4ac 10233 (set_attr "length" "8,12")
10234 (set_attr "type" "multiple")]
8fa3ba89 10235)
9c08d1fa 10236
8a18b90c 10237(define_insn "*if_move_not"
10238 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10239 (if_then_else:SI
8fa3ba89 10240 (match_operator 4 "arm_comparison_operator"
8a18b90c 10241 [(match_operand 3 "cc_register" "") (const_int 0)])
10242 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
10243 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
cffb2a26 10244 "TARGET_ARM"
8a18b90c 10245 "@
10246 mvn%D4\\t%0, %2
10247 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
10248 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
8fa3ba89 10249 [(set_attr "conds" "use")
1aed5204 10250 (set_attr "type" "mvn_reg")
1b7da4ac 10251 (set_attr "length" "4,8,8")
10252 (set_attr "type" "mvn_reg,multiple,multiple")]
8fa3ba89 10253)
8a18b90c 10254
10255(define_insn "*ifcompare_not_move"
9c08d1fa 10256 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 10257 (if_then_else:SI
8fa3ba89 10258 (match_operator 5 "arm_comparison_operator"
8a18b90c 10259 [(match_operand:SI 3 "s_register_operand" "r,r")
10260 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10261 (not:SI
10262 (match_operand:SI 2 "s_register_operand" "r,r"))
10263 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 10264 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10265 "TARGET_ARM"
8a18b90c 10266 "#"
8fa3ba89 10267 [(set_attr "conds" "clob")
1b7da4ac 10268 (set_attr "length" "8,12")
10269 (set_attr "type" "multiple")]
8fa3ba89 10270)
9c08d1fa 10271
8a18b90c 10272(define_insn "*if_not_move"
10273 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10274 (if_then_else:SI
8fa3ba89 10275 (match_operator 4 "arm_comparison_operator"
8a18b90c 10276 [(match_operand 3 "cc_register" "") (const_int 0)])
10277 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
10278 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 10279 "TARGET_ARM"
8a18b90c 10280 "@
10281 mvn%d4\\t%0, %2
10282 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
10283 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
8fa3ba89 10284 [(set_attr "conds" "use")
1b7da4ac 10285 (set_attr "type" "mvn_reg,multiple,multiple")
8fa3ba89 10286 (set_attr "length" "4,8,8")]
10287)
8a18b90c 10288
10289(define_insn "*ifcompare_shift_move"
9c08d1fa 10290 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 10291 (if_then_else:SI
8fa3ba89 10292 (match_operator 6 "arm_comparison_operator"
8a18b90c 10293 [(match_operand:SI 4 "s_register_operand" "r,r")
10294 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
10295 (match_operator:SI 7 "shift_operator"
10296 [(match_operand:SI 2 "s_register_operand" "r,r")
10297 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
10298 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 10299 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10300 "TARGET_ARM"
9c08d1fa 10301 "#"
8fa3ba89 10302 [(set_attr "conds" "clob")
1b7da4ac 10303 (set_attr "length" "8,12")
10304 (set_attr "type" "multiple")]
8fa3ba89 10305)
9c08d1fa 10306
8a18b90c 10307(define_insn "*if_shift_move"
10308 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10309 (if_then_else:SI
8fa3ba89 10310 (match_operator 5 "arm_comparison_operator"
8a18b90c 10311 [(match_operand 6 "cc_register" "") (const_int 0)])
10312 (match_operator:SI 4 "shift_operator"
10313 [(match_operand:SI 2 "s_register_operand" "r,r,r")
10314 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
10315 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 10316 "TARGET_ARM"
5565501b 10317 "@
8a18b90c 10318 mov%d5\\t%0, %2%S4
10319 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
10320 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
8fa3ba89 10321 [(set_attr "conds" "use")
331beb1a 10322 (set_attr "shift" "2")
a2cd141b 10323 (set_attr "length" "4,8,8")
282b4c75 10324 (set_attr_alternative "type"
10325 [(if_then_else (match_operand 3 "const_int_operand" "")
10326 (const_string "mov_shift" )
10327 (const_string "mov_shift_reg"))
10328 (const_string "multiple")
10329 (const_string "multiple")])]
8fa3ba89 10330)
5565501b 10331
8a18b90c 10332(define_insn "*ifcompare_move_shift"
10333 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 10334 (if_then_else:SI
8fa3ba89 10335 (match_operator 6 "arm_comparison_operator"
8a18b90c 10336 [(match_operand:SI 4 "s_register_operand" "r,r")
10337 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
10338 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
5565501b 10339 (match_operator:SI 7 "shift_operator"
8a18b90c 10340 [(match_operand:SI 2 "s_register_operand" "r,r")
10341 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
bd5b4116 10342 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10343 "TARGET_ARM"
8a18b90c 10344 "#"
8fa3ba89 10345 [(set_attr "conds" "clob")
1b7da4ac 10346 (set_attr "length" "8,12")
10347 (set_attr "type" "multiple")]
8fa3ba89 10348)
5565501b 10349
8a18b90c 10350(define_insn "*if_move_shift"
10351 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 10352 (if_then_else:SI
8fa3ba89 10353 (match_operator 5 "arm_comparison_operator"
8a18b90c 10354 [(match_operand 6 "cc_register" "") (const_int 0)])
10355 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
10356 (match_operator:SI 4 "shift_operator"
10357 [(match_operand:SI 2 "s_register_operand" "r,r,r")
10358 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
cffb2a26 10359 "TARGET_ARM"
5565501b 10360 "@
8a18b90c 10361 mov%D5\\t%0, %2%S4
10362 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
10363 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
8fa3ba89 10364 [(set_attr "conds" "use")
331beb1a 10365 (set_attr "shift" "2")
a2cd141b 10366 (set_attr "length" "4,8,8")
282b4c75 10367 (set_attr_alternative "type"
10368 [(if_then_else (match_operand 3 "const_int_operand" "")
10369 (const_string "mov_shift" )
10370 (const_string "mov_shift_reg"))
10371 (const_string "multiple")
10372 (const_string "multiple")])]
8fa3ba89 10373)
9c08d1fa 10374
f7fbdd4a 10375(define_insn "*ifcompare_shift_shift"
8a18b90c 10376 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 10377 (if_then_else:SI
8fa3ba89 10378 (match_operator 7 "arm_comparison_operator"
8a18b90c 10379 [(match_operand:SI 5 "s_register_operand" "r")
10380 (match_operand:SI 6 "arm_add_operand" "rIL")])
5565501b 10381 (match_operator:SI 8 "shift_operator"
8a18b90c 10382 [(match_operand:SI 1 "s_register_operand" "r")
10383 (match_operand:SI 2 "arm_rhs_operand" "rM")])
5565501b 10384 (match_operator:SI 9 "shift_operator"
8a18b90c 10385 [(match_operand:SI 3 "s_register_operand" "r")
10386 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
bd5b4116 10387 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10388 "TARGET_ARM"
8a18b90c 10389 "#"
8fa3ba89 10390 [(set_attr "conds" "clob")
1b7da4ac 10391 (set_attr "length" "12")
10392 (set_attr "type" "multiple")]
8fa3ba89 10393)
9c08d1fa 10394
8a18b90c 10395(define_insn "*if_shift_shift"
10396 [(set (match_operand:SI 0 "s_register_operand" "=r")
10397 (if_then_else:SI
8fa3ba89 10398 (match_operator 5 "arm_comparison_operator"
8a18b90c 10399 [(match_operand 8 "cc_register" "") (const_int 0)])
10400 (match_operator:SI 6 "shift_operator"
10401 [(match_operand:SI 1 "s_register_operand" "r")
10402 (match_operand:SI 2 "arm_rhs_operand" "rM")])
10403 (match_operator:SI 7 "shift_operator"
10404 [(match_operand:SI 3 "s_register_operand" "r")
10405 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
cffb2a26 10406 "TARGET_ARM"
8a18b90c 10407 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
8fa3ba89 10408 [(set_attr "conds" "use")
331beb1a 10409 (set_attr "shift" "1")
a2cd141b 10410 (set_attr "length" "8")
10411 (set (attr "type") (if_then_else
10412 (and (match_operand 2 "const_int_operand" "")
10413 (match_operand 4 "const_int_operand" ""))
1aed5204 10414 (const_string "mov_shift")
10415 (const_string "mov_shift_reg")))]
8fa3ba89 10416)
8a18b90c 10417
f7fbdd4a 10418(define_insn "*ifcompare_not_arith"
8a18b90c 10419 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 10420 (if_then_else:SI
8fa3ba89 10421 (match_operator 6 "arm_comparison_operator"
8a18b90c 10422 [(match_operand:SI 4 "s_register_operand" "r")
10423 (match_operand:SI 5 "arm_add_operand" "rIL")])
10424 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5565501b 10425 (match_operator:SI 7 "shiftable_operator"
8a18b90c 10426 [(match_operand:SI 2 "s_register_operand" "r")
10427 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
bd5b4116 10428 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10429 "TARGET_ARM"
8a18b90c 10430 "#"
8fa3ba89 10431 [(set_attr "conds" "clob")
1b7da4ac 10432 (set_attr "length" "12")
10433 (set_attr "type" "multiple")]
8fa3ba89 10434)
9c08d1fa 10435
8a18b90c 10436(define_insn "*if_not_arith"
10437 [(set (match_operand:SI 0 "s_register_operand" "=r")
10438 (if_then_else:SI
8fa3ba89 10439 (match_operator 5 "arm_comparison_operator"
8a18b90c 10440 [(match_operand 4 "cc_register" "") (const_int 0)])
10441 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
10442 (match_operator:SI 6 "shiftable_operator"
10443 [(match_operand:SI 2 "s_register_operand" "r")
10444 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
cffb2a26 10445 "TARGET_ARM"
8a18b90c 10446 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
8fa3ba89 10447 [(set_attr "conds" "use")
1aed5204 10448 (set_attr "type" "mvn_reg")
8fa3ba89 10449 (set_attr "length" "8")]
10450)
8a18b90c 10451
10452(define_insn "*ifcompare_arith_not"
10453 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 10454 (if_then_else:SI
8fa3ba89 10455 (match_operator 6 "arm_comparison_operator"
8a18b90c 10456 [(match_operand:SI 4 "s_register_operand" "r")
10457 (match_operand:SI 5 "arm_add_operand" "rIL")])
5565501b 10458 (match_operator:SI 7 "shiftable_operator"
8a18b90c 10459 [(match_operand:SI 2 "s_register_operand" "r")
10460 (match_operand:SI 3 "arm_rhs_operand" "rI")])
10461 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
bd5b4116 10462 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10463 "TARGET_ARM"
8a18b90c 10464 "#"
8fa3ba89 10465 [(set_attr "conds" "clob")
1b7da4ac 10466 (set_attr "length" "12")
10467 (set_attr "type" "multiple")]
8fa3ba89 10468)
9c08d1fa 10469
8a18b90c 10470(define_insn "*if_arith_not"
10471 [(set (match_operand:SI 0 "s_register_operand" "=r")
10472 (if_then_else:SI
8fa3ba89 10473 (match_operator 5 "arm_comparison_operator"
8a18b90c 10474 [(match_operand 4 "cc_register" "") (const_int 0)])
10475 (match_operator:SI 6 "shiftable_operator"
10476 [(match_operand:SI 2 "s_register_operand" "r")
10477 (match_operand:SI 3 "arm_rhs_operand" "rI")])
10478 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
cffb2a26 10479 "TARGET_ARM"
8a18b90c 10480 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
8fa3ba89 10481 [(set_attr "conds" "use")
1b7da4ac 10482 (set_attr "type" "multiple")
8fa3ba89 10483 (set_attr "length" "8")]
10484)
8a18b90c 10485
f7fbdd4a 10486(define_insn "*ifcompare_neg_move"
8a18b90c 10487 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 10488 (if_then_else:SI
8fa3ba89 10489 (match_operator 5 "arm_comparison_operator"
8a18b90c 10490 [(match_operand:SI 3 "s_register_operand" "r,r")
10491 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10492 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
10493 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 10494 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10495 "TARGET_ARM"
8a18b90c 10496 "#"
8fa3ba89 10497 [(set_attr "conds" "clob")
1b7da4ac 10498 (set_attr "length" "8,12")
10499 (set_attr "type" "multiple")]
8fa3ba89 10500)
8a18b90c 10501
530bb693 10502(define_insn_and_split "*if_neg_move"
10503 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
8a18b90c 10504 (if_then_else:SI
8fa3ba89 10505 (match_operator 4 "arm_comparison_operator"
8a18b90c 10506 [(match_operand 3 "cc_register" "") (const_int 0)])
530bb693 10507 (neg:SI (match_operand:SI 2 "s_register_operand" "l,r"))
10508 (match_operand:SI 1 "s_register_operand" "0,0")))]
10509 "TARGET_32BIT"
10510 "#"
10511 "&& reload_completed"
10512 [(cond_exec (match_op_dup 4 [(match_dup 3) (const_int 0)])
10513 (set (match_dup 0) (neg:SI (match_dup 2))))]
10514 ""
8fa3ba89 10515 [(set_attr "conds" "use")
530bb693 10516 (set_attr "length" "4")
10517 (set_attr "arch" "t2,32")
10518 (set_attr "enabled_for_depr_it" "yes,no")
10519 (set_attr "type" "logic_shift_imm")]
8fa3ba89 10520)
9c08d1fa 10521
f7fbdd4a 10522(define_insn "*ifcompare_move_neg"
8a18b90c 10523 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 10524 (if_then_else:SI
8fa3ba89 10525 (match_operator 5 "arm_comparison_operator"
8a18b90c 10526 [(match_operand:SI 3 "s_register_operand" "r,r")
10527 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10528 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
10529 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 10530 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10531 "TARGET_ARM"
8a18b90c 10532 "#"
8fa3ba89 10533 [(set_attr "conds" "clob")
1b7da4ac 10534 (set_attr "length" "8,12")
10535 (set_attr "type" "multiple")]
8fa3ba89 10536)
8a18b90c 10537
530bb693 10538(define_insn_and_split "*if_move_neg"
10539 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
8a18b90c 10540 (if_then_else:SI
8fa3ba89 10541 (match_operator 4 "arm_comparison_operator"
8a18b90c 10542 [(match_operand 3 "cc_register" "") (const_int 0)])
530bb693 10543 (match_operand:SI 1 "s_register_operand" "0,0")
10544 (neg:SI (match_operand:SI 2 "s_register_operand" "l,r"))))]
10545 "TARGET_32BIT"
10546 "#"
10547 "&& reload_completed"
10548 [(cond_exec (match_dup 5)
10549 (set (match_dup 0) (neg:SI (match_dup 2))))]
10550 {
10551 machine_mode mode = GET_MODE (operands[3]);
10552 rtx_code rc = GET_CODE (operands[4]);
10553
10554 if (mode == CCFPmode || mode == CCFPEmode)
10555 rc = reverse_condition_maybe_unordered (rc);
10556 else
10557 rc = reverse_condition (rc);
10558
10559 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[3], const0_rtx);
10560 }
0d66636f 10561 [(set_attr "conds" "use")
530bb693 10562 (set_attr "length" "4")
10563 (set_attr "arch" "t2,32")
10564 (set_attr "enabled_for_depr_it" "yes,no")
10565 (set_attr "type" "logic_shift_imm")]
0d66636f 10566)
9c08d1fa 10567
f7fbdd4a 10568(define_insn "*arith_adjacentmem"
9c08d1fa 10569 [(set (match_operand:SI 0 "s_register_operand" "=r")
10570 (match_operator:SI 1 "shiftable_operator"
10571 [(match_operand:SI 2 "memory_operand" "m")
10572 (match_operand:SI 3 "memory_operand" "m")]))
10573 (clobber (match_scratch:SI 4 "=r"))]
cffb2a26 10574 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9c08d1fa 10575 "*
215b30b3 10576 {
10577 rtx ldm[3];
10578 rtx arith[4];
94dee231 10579 rtx base_reg;
10580 HOST_WIDE_INT val1 = 0, val2 = 0;
9c08d1fa 10581
215b30b3 10582 if (REGNO (operands[0]) > REGNO (operands[4]))
10583 {
10584 ldm[1] = operands[4];
10585 ldm[2] = operands[0];
10586 }
10587 else
10588 {
10589 ldm[1] = operands[0];
10590 ldm[2] = operands[4];
10591 }
94dee231 10592
10593 base_reg = XEXP (operands[2], 0);
10594
10595 if (!REG_P (base_reg))
10596 {
10597 val1 = INTVAL (XEXP (base_reg, 1));
10598 base_reg = XEXP (base_reg, 0);
10599 }
10600
10601 if (!REG_P (XEXP (operands[3], 0)))
215b30b3 10602 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
94dee231 10603
215b30b3 10604 arith[0] = operands[0];
10605 arith[3] = operands[1];
94dee231 10606
215b30b3 10607 if (val1 < val2)
10608 {
10609 arith[1] = ldm[1];
10610 arith[2] = ldm[2];
10611 }
10612 else
10613 {
10614 arith[1] = ldm[2];
10615 arith[2] = ldm[1];
10616 }
94dee231 10617
10618 ldm[0] = base_reg;
10619 if (val1 !=0 && val2 != 0)
215b30b3 10620 {
cdb1295a 10621 rtx ops[3];
10622
94dee231 10623 if (val1 == 4 || val2 == 4)
10624 /* Other val must be 8, since we know they are adjacent and neither
10625 is zero. */
3ef90e77 10626 output_asm_insn (\"ldmib%?\\t%0, {%1, %2}\", ldm);
cdb1295a 10627 else if (const_ok_for_arm (val1) || const_ok_for_arm (-val1))
94dee231 10628 {
94dee231 10629 ldm[0] = ops[0] = operands[4];
10630 ops[1] = base_reg;
10631 ops[2] = GEN_INT (val1);
10632 output_add_immediate (ops);
10633 if (val1 < val2)
3ef90e77 10634 output_asm_insn (\"ldmia%?\\t%0, {%1, %2}\", ldm);
94dee231 10635 else
3ef90e77 10636 output_asm_insn (\"ldmda%?\\t%0, {%1, %2}\", ldm);
94dee231 10637 }
cdb1295a 10638 else
10639 {
10640 /* Offset is out of range for a single add, so use two ldr. */
10641 ops[0] = ldm[1];
10642 ops[1] = base_reg;
10643 ops[2] = GEN_INT (val1);
10644 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10645 ops[0] = ldm[2];
10646 ops[2] = GEN_INT (val2);
10647 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10648 }
215b30b3 10649 }
94dee231 10650 else if (val1 != 0)
215b30b3 10651 {
215b30b3 10652 if (val1 < val2)
3ef90e77 10653 output_asm_insn (\"ldmda%?\\t%0, {%1, %2}\", ldm);
215b30b3 10654 else
3ef90e77 10655 output_asm_insn (\"ldmia%?\\t%0, {%1, %2}\", ldm);
215b30b3 10656 }
10657 else
10658 {
215b30b3 10659 if (val1 < val2)
3ef90e77 10660 output_asm_insn (\"ldmia%?\\t%0, {%1, %2}\", ldm);
215b30b3 10661 else
3ef90e77 10662 output_asm_insn (\"ldmda%?\\t%0, {%1, %2}\", ldm);
215b30b3 10663 }
10664 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
10665 return \"\";
10666 }"
10667 [(set_attr "length" "12")
10668 (set_attr "predicable" "yes")
a2cd141b 10669 (set_attr "type" "load1")]
215b30b3 10670)
9c08d1fa 10671
9c08d1fa 10672; This pattern is never tried by combine, so do it as a peephole
10673
a0f94409 10674(define_peephole2
372575c7 10675 [(set (match_operand:SI 0 "arm_general_register_operand" "")
10676 (match_operand:SI 1 "arm_general_register_operand" ""))
bd5b4116 10677 (set (reg:CC CC_REGNUM)
aea4c774 10678 (compare:CC (match_dup 1) (const_int 0)))]
372575c7 10679 "TARGET_ARM"
a0f94409 10680 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
10681 (set (match_dup 0) (match_dup 1))])]
10682 ""
0d66636f 10683)
9c08d1fa 10684
9c08d1fa 10685(define_split
10686 [(set (match_operand:SI 0 "s_register_operand" "")
10687 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
10688 (const_int 0))
8fa3ba89 10689 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9c08d1fa 10690 [(match_operand:SI 3 "s_register_operand" "")
10691 (match_operand:SI 4 "arm_rhs_operand" "")]))))
10692 (clobber (match_operand:SI 5 "s_register_operand" ""))]
cffb2a26 10693 "TARGET_ARM"
9c08d1fa 10694 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
10695 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
10696 (match_dup 5)))]
215b30b3 10697 ""
10698)
9c08d1fa 10699
aea4c774 10700;; This split can be used because CC_Z mode implies that the following
10701;; branch will be an equality, or an unsigned inequality, so the sign
10702;; extension is not needed.
9c08d1fa 10703
aea4c774 10704(define_split
bd5b4116 10705 [(set (reg:CC_Z CC_REGNUM)
aea4c774 10706 (compare:CC_Z
10707 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9c08d1fa 10708 (const_int 24))
aea4c774 10709 (match_operand 1 "const_int_operand" "")))
10710 (clobber (match_scratch:SI 2 ""))]
cffb2a26 10711 "TARGET_ARM
8c4e8755 10712 && ((UINTVAL (operands[1]))
10713 == ((UINTVAL (operands[1])) >> 24) << 24)"
aea4c774 10714 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
bd5b4116 10715 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
aea4c774 10716 "
9c08d1fa 10717 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
215b30b3 10718 "
10719)
25f905c2 10720;; ??? Check the patterns above for Thumb-2 usefulness
9c08d1fa 10721
87b22bf7 10722(define_expand "prologue"
10723 [(clobber (const_int 0))]
cffb2a26 10724 "TARGET_EITHER"
25f905c2 10725 "if (TARGET_32BIT)
cffb2a26 10726 arm_expand_prologue ();
10727 else
25f905c2 10728 thumb1_expand_prologue ();
87b22bf7 10729 DONE;
cffb2a26 10730 "
10731)
87b22bf7 10732
56d27660 10733(define_expand "epilogue"
4c44712e 10734 [(clobber (const_int 0))]
cffb2a26 10735 "TARGET_EITHER"
56d27660 10736 "
18d50ae6 10737 if (crtl->calls_eh_return)
fb94f18b 10738 emit_insn (gen_force_register_use (gen_rtx_REG (Pmode, 2)));
25f905c2 10739 if (TARGET_THUMB1)
c3635784 10740 {
10741 thumb1_expand_epilogue ();
10742 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
10743 gen_rtvec (1, ret_rtx), VUNSPEC_EPILOGUE));
10744 }
10745 else if (HAVE_return)
10746 {
10747 /* HAVE_return is testing for USE_RETURN_INSN (FALSE). Hence,
10748 no need for explicit testing again. */
10749 emit_jump_insn (gen_return ());
10750 }
10751 else if (TARGET_32BIT)
10752 {
10753 arm_expand_epilogue (true);
10754 }
cffb2a26 10755 DONE;
10756 "
10757)
56d27660 10758
ef5651d0 10759;; Note - although unspec_volatile's USE all hard registers,
10760;; USEs are ignored after relaod has completed. Thus we need
10761;; to add an unspec of the link register to ensure that flow
10762;; does not think that it is unused by the sibcall branch that
10763;; will replace the standard function epilogue.
c3635784 10764(define_expand "sibcall_epilogue"
fb94f18b 10765 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_REGISTER_USE)
c3635784 10766 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
10767 "TARGET_32BIT"
10768 "
10769 arm_expand_epilogue (false);
10770 DONE;
10771 "
1c494086 10772)
10773
cffb2a26 10774(define_expand "eh_epilogue"
7db9af5d 10775 [(use (match_operand:SI 0 "register_operand" ""))
10776 (use (match_operand:SI 1 "register_operand" ""))
10777 (use (match_operand:SI 2 "register_operand" ""))]
cffb2a26 10778 "TARGET_EITHER"
10779 "
215b30b3 10780 {
10781 cfun->machine->eh_epilogue_sp_ofs = operands[1];
0438d37f 10782 if (!REG_P (operands[2]) || REGNO (operands[2]) != 2)
215b30b3 10783 {
10784 rtx ra = gen_rtx_REG (Pmode, 2);
10785
10786 emit_move_insn (ra, operands[2]);
10787 operands[2] = ra;
10788 }
5cf3595a 10789 /* This is a hack -- we may have crystalized the function type too
10790 early. */
10791 cfun->machine->func_type = 0;
215b30b3 10792 }"
10793)
56d27660 10794
9c08d1fa 10795;; This split is only used during output to reduce the number of patterns
10796;; that need assembler instructions adding to them. We allowed the setting
10797;; of the conditions to be implicit during rtl generation so that
10798;; the conditional compare patterns would work. However this conflicts to
8a18b90c 10799;; some extent with the conditional data operations, so we have to split them
9c08d1fa 10800;; up again here.
10801
25f905c2 10802;; ??? Need to audit these splitters for Thumb-2. Why isn't normal
10803;; conditional execution sufficient?
10804
9c08d1fa 10805(define_split
10806 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 10807 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10808 [(match_operand 2 "" "") (match_operand 3 "" "")])
10809 (match_dup 0)
10810 (match_operand 4 "" "")))
bd5b4116 10811 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10812 "TARGET_ARM && reload_completed"
8fa3ba89 10813 [(set (match_dup 5) (match_dup 6))
10814 (cond_exec (match_dup 7)
10815 (set (match_dup 0) (match_dup 4)))]
10816 "
10817 {
3754d046 10818 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8fa3ba89 10819 operands[2], operands[3]);
10820 enum rtx_code rc = GET_CODE (operands[1]);
10821
bd5b4116 10822 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10823 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10824 if (mode == CCFPmode || mode == CCFPEmode)
10825 rc = reverse_condition_maybe_unordered (rc);
10826 else
10827 rc = reverse_condition (rc);
10828
10829 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
10830 }"
10831)
10832
10833(define_split
10834 [(set (match_operand:SI 0 "s_register_operand" "")
10835 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10836 [(match_operand 2 "" "") (match_operand 3 "" "")])
10837 (match_operand 4 "" "")
10838 (match_dup 0)))
bd5b4116 10839 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10840 "TARGET_ARM && reload_completed"
8fa3ba89 10841 [(set (match_dup 5) (match_dup 6))
10842 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
10843 (set (match_dup 0) (match_dup 4)))]
10844 "
10845 {
3754d046 10846 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8fa3ba89 10847 operands[2], operands[3]);
10848
bd5b4116 10849 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10850 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10851 }"
10852)
10853
10854(define_split
10855 [(set (match_operand:SI 0 "s_register_operand" "")
10856 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9c08d1fa 10857 [(match_operand 2 "" "") (match_operand 3 "" "")])
10858 (match_operand 4 "" "")
10859 (match_operand 5 "" "")))
bd5b4116 10860 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10861 "TARGET_ARM && reload_completed"
8fa3ba89 10862 [(set (match_dup 6) (match_dup 7))
10863 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10864 (set (match_dup 0) (match_dup 4)))
10865 (cond_exec (match_dup 8)
10866 (set (match_dup 0) (match_dup 5)))]
10867 "
10868 {
3754d046 10869 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8fa3ba89 10870 operands[2], operands[3]);
10871 enum rtx_code rc = GET_CODE (operands[1]);
10872
bd5b4116 10873 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10874 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10875 if (mode == CCFPmode || mode == CCFPEmode)
10876 rc = reverse_condition_maybe_unordered (rc);
10877 else
10878 rc = reverse_condition (rc);
10879
10880 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10881 }"
10882)
10883
cffb2a26 10884(define_split
10885 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 10886 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
cffb2a26 10887 [(match_operand:SI 2 "s_register_operand" "")
10888 (match_operand:SI 3 "arm_add_operand" "")])
10889 (match_operand:SI 4 "arm_rhs_operand" "")
10890 (not:SI
10891 (match_operand:SI 5 "s_register_operand" ""))))
bd5b4116 10892 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10893 "TARGET_ARM && reload_completed"
cffb2a26 10894 [(set (match_dup 6) (match_dup 7))
f6c53574 10895 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10896 (set (match_dup 0) (match_dup 4)))
10897 (cond_exec (match_dup 8)
10898 (set (match_dup 0) (not:SI (match_dup 5))))]
cffb2a26 10899 "
215b30b3 10900 {
3754d046 10901 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
215b30b3 10902 operands[2], operands[3]);
f6c53574 10903 enum rtx_code rc = GET_CODE (operands[1]);
cffb2a26 10904
bd5b4116 10905 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
1a83b3ff 10906 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
f6c53574 10907 if (mode == CCFPmode || mode == CCFPEmode)
10908 rc = reverse_condition_maybe_unordered (rc);
10909 else
10910 rc = reverse_condition (rc);
10911
10912 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
215b30b3 10913 }"
10914)
cffb2a26 10915
10916(define_insn "*cond_move_not"
10917 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10918 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
cffb2a26 10919 [(match_operand 3 "cc_register" "") (const_int 0)])
10920 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10921 (not:SI
10922 (match_operand:SI 2 "s_register_operand" "r,r"))))]
10923 "TARGET_ARM"
10924 "@
10925 mvn%D4\\t%0, %2
10926 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
0d66636f 10927 [(set_attr "conds" "use")
1b7da4ac 10928 (set_attr "type" "mvn_reg,multiple")
0d66636f 10929 (set_attr "length" "4,8")]
10930)
cffb2a26 10931
9c08d1fa 10932;; The next two patterns occur when an AND operation is followed by a
10933;; scc insn sequence
10934
f7fbdd4a 10935(define_insn "*sign_extract_onebit"
9c08d1fa 10936 [(set (match_operand:SI 0 "s_register_operand" "=r")
10937 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10938 (const_int 1)
ed750274 10939 (match_operand:SI 2 "const_int_operand" "n")))
10940 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10941 "TARGET_ARM"
9c08d1fa 10942 "*
0d66636f 10943 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10944 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
10945 return \"mvnne\\t%0, #0\";
10946 "
10947 [(set_attr "conds" "clob")
1b7da4ac 10948 (set_attr "length" "8")
10949 (set_attr "type" "multiple")]
0d66636f 10950)
9c08d1fa 10951
f7fbdd4a 10952(define_insn "*not_signextract_onebit"
9c08d1fa 10953 [(set (match_operand:SI 0 "s_register_operand" "=r")
10954 (not:SI
10955 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10956 (const_int 1)
ed750274 10957 (match_operand:SI 2 "const_int_operand" "n"))))
10958 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10959 "TARGET_ARM"
9c08d1fa 10960 "*
0d66636f 10961 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10962 output_asm_insn (\"tst\\t%1, %2\", operands);
10963 output_asm_insn (\"mvneq\\t%0, #0\", operands);
10964 return \"movne\\t%0, #0\";
10965 "
10966 [(set_attr "conds" "clob")
1b7da4ac 10967 (set_attr "length" "12")
10968 (set_attr "type" "multiple")]
0d66636f 10969)
25f905c2 10970;; ??? The above patterns need auditing for Thumb-2
87b22bf7 10971
0d66636f 10972;; Push multiple registers to the stack. Registers are in parallel (use ...)
10973;; expressions. For simplicity, the first register is also in the unspec
10974;; part.
08508cbf 10975;; To avoid the usage of GNU extension, the length attribute is computed
10976;; in a C function arm_attr_length_push_multi.
f7fbdd4a 10977(define_insn "*push_multi"
87b22bf7 10978 [(match_parallel 2 "multi_register_push"
7571d3f7 10979 [(set (match_operand:BLK 0 "push_mult_memory_operand" "")
3cc80a30 10980 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "")]
e1159bbe 10981 UNSPEC_PUSH_MULT))])]
7571d3f7 10982 ""
87b22bf7 10983 "*
215b30b3 10984 {
10985 int num_saves = XVECLEN (operands[2], 0);
ed593f11 10986
215b30b3 10987 /* For the StrongARM at least it is faster to
25f905c2 10988 use STR to store only a single register.
542d5028 10989 In Thumb mode always use push, and the assembler will pick
10990 something appropriate. */
25f905c2 10991 if (num_saves == 1 && TARGET_ARM)
61309563 10992 output_asm_insn (\"str%?\\t%1, [%m0, #-4]!\", operands);
215b30b3 10993 else
10994 {
10995 int i;
10996 char pattern[100];
ed593f11 10997
3ef90e77 10998 if (TARGET_32BIT)
61309563 10999 strcpy (pattern, \"push%?\\t{%1\");
25f905c2 11000 else
11001 strcpy (pattern, \"push\\t{%1\");
215b30b3 11002
6079f055 11003 for (i = 1; i < num_saves; i++)
215b30b3 11004 {
11005 strcat (pattern, \", %|\");
11006 strcat (pattern,
11007 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
11008 }
11009
11010 strcat (pattern, \"}\");
11011 output_asm_insn (pattern, operands);
11012 }
11013
11014 return \"\";
11015 }"
a6864a24 11016 [(set_attr "type" "store4")
11017 (set (attr "length")
08508cbf 11018 (symbol_ref "arm_attr_length_push_multi (operands[2], operands[1])"))]
215b30b3 11019)
f7fbdd4a 11020
4c58c898 11021(define_insn "stack_tie"
11022 [(set (mem:BLK (scratch))
aaa37ad6 11023 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "rk")
11024 (match_operand:SI 1 "s_register_operand" "rk")]
4c58c898 11025 UNSPEC_PRLG_STK))]
11026 ""
11027 ""
1b7da4ac 11028 [(set_attr "length" "0")
11029 (set_attr "type" "block")]
4c58c898 11030)
11031
426be8c5 11032;; Pop (as used in epilogue RTL)
11033;;
11034(define_insn "*load_multiple_with_writeback"
11035 [(match_parallel 0 "load_multiple_operation"
11036 [(set (match_operand:SI 1 "s_register_operand" "+rk")
11037 (plus:SI (match_dup 1)
809003b3 11038 (match_operand:SI 2 "const_int_I_operand" "I")))
426be8c5 11039 (set (match_operand:SI 3 "s_register_operand" "=rk")
11040 (mem:SI (match_dup 1)))
11041 ])]
11042 "TARGET_32BIT && (reload_in_progress || reload_completed)"
11043 "*
11044 {
11045 arm_output_multireg_pop (operands, /*return_pc=*/false,
11046 /*cond=*/const_true_rtx,
11047 /*reverse=*/false,
11048 /*update=*/true);
11049 return \"\";
11050 }
11051 "
11052 [(set_attr "type" "load4")
5431c9c9 11053 (set_attr "predicable" "yes")
11054 (set (attr "length")
11055 (symbol_ref "arm_attr_length_pop_multi (operands,
11056 /*return_pc=*/false,
11057 /*write_back_p=*/true)"))]
426be8c5 11058)
11059
11060;; Pop with return (as used in epilogue RTL)
11061;;
11062;; This instruction is generated when the registers are popped at the end of
11063;; epilogue. Here, instead of popping the value into LR and then generating
11064;; jump to LR, value is popped into PC directly. Hence, the pattern is combined
11065;; with (return).
11066(define_insn "*pop_multiple_with_writeback_and_return"
11067 [(match_parallel 0 "pop_multiple_return"
11068 [(return)
11069 (set (match_operand:SI 1 "s_register_operand" "+rk")
11070 (plus:SI (match_dup 1)
809003b3 11071 (match_operand:SI 2 "const_int_I_operand" "I")))
426be8c5 11072 (set (match_operand:SI 3 "s_register_operand" "=rk")
11073 (mem:SI (match_dup 1)))
11074 ])]
11075 "TARGET_32BIT && (reload_in_progress || reload_completed)"
11076 "*
11077 {
11078 arm_output_multireg_pop (operands, /*return_pc=*/true,
11079 /*cond=*/const_true_rtx,
11080 /*reverse=*/false,
11081 /*update=*/true);
11082 return \"\";
11083 }
11084 "
11085 [(set_attr "type" "load4")
5431c9c9 11086 (set_attr "predicable" "yes")
11087 (set (attr "length")
11088 (symbol_ref "arm_attr_length_pop_multi (operands, /*return_pc=*/true,
11089 /*write_back_p=*/true)"))]
426be8c5 11090)
11091
11092(define_insn "*pop_multiple_with_return"
11093 [(match_parallel 0 "pop_multiple_return"
11094 [(return)
11095 (set (match_operand:SI 2 "s_register_operand" "=rk")
11096 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
11097 ])]
11098 "TARGET_32BIT && (reload_in_progress || reload_completed)"
11099 "*
11100 {
11101 arm_output_multireg_pop (operands, /*return_pc=*/true,
11102 /*cond=*/const_true_rtx,
11103 /*reverse=*/false,
11104 /*update=*/false);
11105 return \"\";
11106 }
11107 "
11108 [(set_attr "type" "load4")
5431c9c9 11109 (set_attr "predicable" "yes")
11110 (set (attr "length")
11111 (symbol_ref "arm_attr_length_pop_multi (operands, /*return_pc=*/true,
11112 /*write_back_p=*/false)"))]
426be8c5 11113)
11114
11115;; Load into PC and return
11116(define_insn "*ldr_with_return"
11117 [(return)
11118 (set (reg:SI PC_REGNUM)
11119 (mem:SI (post_inc:SI (match_operand:SI 0 "s_register_operand" "+rk"))))]
11120 "TARGET_32BIT && (reload_in_progress || reload_completed)"
11121 "ldr%?\t%|pc, [%0], #4"
11122 [(set_attr "type" "load1")
11123 (set_attr "predicable" "yes")]
11124)
1a0b0f12 11125;; Pop for floating point registers (as used in epilogue RTL)
11126(define_insn "*vfp_pop_multiple_with_writeback"
11127 [(match_parallel 0 "pop_multiple_fp"
11128 [(set (match_operand:SI 1 "s_register_operand" "+rk")
11129 (plus:SI (match_dup 1)
809003b3 11130 (match_operand:SI 2 "const_int_I_operand" "I")))
2f2163a4 11131 (set (match_operand:DF 3 "vfp_hard_register_operand" "")
1a0b0f12 11132 (mem:DF (match_dup 1)))])]
d7216193 11133 "TARGET_32BIT && TARGET_HARD_FLOAT"
1a0b0f12 11134 "*
11135 {
11136 int num_regs = XVECLEN (operands[0], 0);
11137 char pattern[100];
11138 rtx op_list[2];
b34d8dac 11139 strcpy (pattern, \"vldm\\t\");
1a0b0f12 11140 strcat (pattern, reg_names[REGNO (SET_DEST (XVECEXP (operands[0], 0, 0)))]);
11141 strcat (pattern, \"!, {\");
11142 op_list[0] = XEXP (XVECEXP (operands[0], 0, 1), 0);
11143 strcat (pattern, \"%P0\");
11144 if ((num_regs - 1) > 1)
11145 {
11146 strcat (pattern, \"-%P1\");
11147 op_list [1] = XEXP (XVECEXP (operands[0], 0, num_regs - 1), 0);
11148 }
11149
11150 strcat (pattern, \"}\");
11151 output_asm_insn (pattern, op_list);
11152 return \"\";
11153 }
11154 "
11155 [(set_attr "type" "load4")
11156 (set_attr "conds" "unconditional")
11157 (set_attr "predicable" "no")]
11158)
11159
f7fbdd4a 11160;; Special patterns for dealing with the constant pool
11161
cffb2a26 11162(define_insn "align_4"
e1159bbe 11163 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
cffb2a26 11164 "TARGET_EITHER"
f7fbdd4a 11165 "*
cffb2a26 11166 assemble_align (32);
f7fbdd4a 11167 return \"\";
cffb2a26 11168 "
1b7da4ac 11169 [(set_attr "type" "no_insn")]
cffb2a26 11170)
f7fbdd4a 11171
755eb2b4 11172(define_insn "align_8"
11173 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
f9273c43 11174 "TARGET_EITHER"
755eb2b4 11175 "*
11176 assemble_align (64);
11177 return \"\";
11178 "
1b7da4ac 11179 [(set_attr "type" "no_insn")]
755eb2b4 11180)
11181
cffb2a26 11182(define_insn "consttable_end"
e1159bbe 11183 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
cffb2a26 11184 "TARGET_EITHER"
f7fbdd4a 11185 "*
cffb2a26 11186 making_const_table = FALSE;
f7fbdd4a 11187 return \"\";
cffb2a26 11188 "
1b7da4ac 11189 [(set_attr "type" "no_insn")]
cffb2a26 11190)
f7fbdd4a 11191
0e207eb8 11192(define_insn "consttable_1"
11193 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
11194 "TARGET_EITHER"
11195 "*
11196 making_const_table = TRUE;
11197 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
11198 assemble_zeros (3);
11199 return \"\";
11200 "
11201 [(set_attr "length" "4")
11202 (set_attr "type" "no_insn")]
11203)
11204
11205(define_insn "consttable_2"
11206 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
11207 "TARGET_EITHER"
11208 "*
11209 {
11210 rtx x = operands[0];
11211 making_const_table = TRUE;
11212 switch (GET_MODE_CLASS (GET_MODE (x)))
11213 {
11214 case MODE_FLOAT:
11215 arm_emit_fp16_const (x);
11216 break;
11217 default:
11218 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
11219 assemble_zeros (2);
11220 break;
11221 }
11222 return \"\";
11223 }"
11224 [(set_attr "length" "4")
11225 (set_attr "type" "no_insn")]
11226)
11227
cffb2a26 11228(define_insn "consttable_4"
e1159bbe 11229 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
cffb2a26 11230 "TARGET_EITHER"
11231 "*
11232 {
9b8516be 11233 rtx x = operands[0];
cffb2a26 11234 making_const_table = TRUE;
9b8516be 11235 switch (GET_MODE_CLASS (GET_MODE (x)))
cffb2a26 11236 {
11237 case MODE_FLOAT:
945f7b03 11238 assemble_real (*CONST_DOUBLE_REAL_VALUE (x), GET_MODE (x),
11239 BITS_PER_WORD);
11240 break;
cffb2a26 11241 default:
7b04c5d5 11242 /* XXX: Sometimes gcc does something really dumb and ends up with
11243 a HIGH in a constant pool entry, usually because it's trying to
11244 load into a VFP register. We know this will always be used in
11245 combination with a LO_SUM which ignores the high bits, so just
11246 strip off the HIGH. */
11247 if (GET_CODE (x) == HIGH)
11248 x = XEXP (x, 0);
9b8516be 11249 assemble_integer (x, 4, BITS_PER_WORD, 1);
11250 mark_symbol_refs_as_used (x);
cffb2a26 11251 break;
11252 }
11253 return \"\";
11254 }"
1b7da4ac 11255 [(set_attr "length" "4")
11256 (set_attr "type" "no_insn")]
cffb2a26 11257)
11258
11259(define_insn "consttable_8"
e1159bbe 11260 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
cffb2a26 11261 "TARGET_EITHER"
11262 "*
11263 {
11264 making_const_table = TRUE;
11265 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
11266 {
945f7b03 11267 case MODE_FLOAT:
11268 assemble_real (*CONST_DOUBLE_REAL_VALUE (operands[0]),
11269 GET_MODE (operands[0]), BITS_PER_WORD);
11270 break;
cffb2a26 11271 default:
09d688ff 11272 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
cffb2a26 11273 break;
11274 }
11275 return \"\";
11276 }"
1b7da4ac 11277 [(set_attr "length" "8")
11278 (set_attr "type" "no_insn")]
cffb2a26 11279)
11280
d98a3884 11281(define_insn "consttable_16"
11282 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_16)]
11283 "TARGET_EITHER"
11284 "*
11285 {
11286 making_const_table = TRUE;
11287 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
11288 {
945f7b03 11289 case MODE_FLOAT:
11290 assemble_real (*CONST_DOUBLE_REAL_VALUE (operands[0]),
11291 GET_MODE (operands[0]), BITS_PER_WORD);
11292 break;
d98a3884 11293 default:
11294 assemble_integer (operands[0], 16, BITS_PER_WORD, 1);
11295 break;
11296 }
11297 return \"\";
11298 }"
1b7da4ac 11299 [(set_attr "length" "16")
11300 (set_attr "type" "no_insn")]
d98a3884 11301)
11302
331beb1a 11303;; V5 Instructions,
11304
8f4be2be 11305(define_insn "clzsi2"
11306 [(set (match_operand:SI 0 "s_register_operand" "=r")
11307 (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 11308 "TARGET_32BIT && arm_arch5"
ee7cbe0e 11309 "clz%?\\t%0, %1"
bcaec148 11310 [(set_attr "predicable" "yes")
4a510717 11311 (set_attr "predicable_short_it" "no")
bebe9bbb 11312 (set_attr "type" "clz")])
331beb1a 11313
099ad98b 11314(define_insn "rbitsi2"
11315 [(set (match_operand:SI 0 "s_register_operand" "=r")
11316 (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")] UNSPEC_RBIT))]
11317 "TARGET_32BIT && arm_arch_thumb2"
11318 "rbit%?\\t%0, %1"
11319 [(set_attr "predicable" "yes")
4a510717 11320 (set_attr "predicable_short_it" "no")
bebe9bbb 11321 (set_attr "type" "clz")])
099ad98b 11322
99ffa689 11323;; Keep this as a CTZ expression until after reload and then split
11324;; into RBIT + CLZ. Since RBIT is represented as an UNSPEC it is unlikely
11325;; to fold with any other expression.
11326
11327(define_insn_and_split "ctzsi2"
11328 [(set (match_operand:SI 0 "s_register_operand" "=r")
11329 (ctz:SI (match_operand:SI 1 "s_register_operand" "r")))]
099ad98b 11330 "TARGET_32BIT && arm_arch_thumb2"
99ffa689 11331 "#"
11332 "&& reload_completed"
11333 [(const_int 0)]
099ad98b 11334 "
99ffa689 11335 emit_insn (gen_rbitsi2 (operands[0], operands[1]));
11336 emit_insn (gen_clzsi2 (operands[0], operands[0]));
11337 DONE;
11338")
099ad98b 11339
e1159bbe 11340;; V5E instructions.
331beb1a 11341
11342(define_insn "prefetch"
f4e79814 11343 [(prefetch (match_operand:SI 0 "address_operand" "p")
11344 (match_operand:SI 1 "" "")
11345 (match_operand:SI 2 "" ""))]
25f905c2 11346 "TARGET_32BIT && arm_arch5e"
1b7da4ac 11347 "pld\\t%a0"
11348 [(set_attr "type" "load1")]
11349)
331beb1a 11350
0d66636f 11351;; General predication pattern
11352
11353(define_cond_exec
11354 [(match_operator 0 "arm_comparison_operator"
11355 [(match_operand 1 "cc_register" "")
11356 (const_int 0)])]
580f4c48 11357 "TARGET_32BIT
11358 && (!TARGET_NO_VOLATILE_CE || !volatile_refs_p (PATTERN (insn)))"
0d66636f 11359 ""
c7a58118 11360[(set_attr "predicated" "yes")]
0d66636f 11361)
11362
fb94f18b 11363(define_insn "force_register_use"
11364 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_REGISTER_USE)]
063a05c7 11365 ""
fb94f18b 11366 "%@ %0 needed"
1b7da4ac 11367 [(set_attr "length" "0")
11368 (set_attr "type" "no_insn")]
063a05c7 11369)
7db9af5d 11370
4c44712e 11371
11372;; Patterns for exception handling
11373
11374(define_expand "eh_return"
11375 [(use (match_operand 0 "general_operand" ""))]
11376 "TARGET_EITHER"
11377 "
11378 {
25f905c2 11379 if (TARGET_32BIT)
4c44712e 11380 emit_insn (gen_arm_eh_return (operands[0]));
11381 else
11382 emit_insn (gen_thumb_eh_return (operands[0]));
11383 DONE;
11384 }"
11385)
11386
11387;; We can't expand this before we know where the link register is stored.
11388(define_insn_and_split "arm_eh_return"
11389 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
11390 VUNSPEC_EH_RETURN)
11391 (clobber (match_scratch:SI 1 "=&r"))]
11392 "TARGET_ARM"
11393 "#"
11394 "&& reload_completed"
11395 [(const_int 0)]
11396 "
11397 {
11398 arm_set_return_address (operands[0], operands[1]);
11399 DONE;
11400 }"
11401)
11402
f655717d 11403\f
11404;; TLS support
11405
11406(define_insn "load_tp_hard"
11407 [(set (match_operand:SI 0 "register_operand" "=r")
11408 (unspec:SI [(const_int 0)] UNSPEC_TLS))]
11409 "TARGET_HARD_TP"
11410 "mrc%?\\tp15, 0, %0, c13, c0, 3\\t@ load_tp_hard"
1b7da4ac 11411 [(set_attr "predicable" "yes")
4b5d7374 11412 (set_attr "type" "mrs")]
f655717d 11413)
11414
11415;; Doesn't clobber R1-R3. Must use r0 for the first operand.
11416(define_insn "load_tp_soft"
11417 [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
11418 (clobber (reg:SI LR_REGNUM))
11419 (clobber (reg:SI IP_REGNUM))
11420 (clobber (reg:CC CC_REGNUM))]
11421 "TARGET_SOFT_TP"
11422 "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
1b7da4ac 11423 [(set_attr "conds" "clob")
11424 (set_attr "type" "branch")]
f655717d 11425)
11426
f41e4452 11427;; tls descriptor call
11428(define_insn "tlscall"
11429 [(set (reg:SI R0_REGNUM)
11430 (unspec:SI [(reg:SI R0_REGNUM)
11431 (match_operand:SI 0 "" "X")
11432 (match_operand 1 "" "")] UNSPEC_TLS))
11433 (clobber (reg:SI R1_REGNUM))
11434 (clobber (reg:SI LR_REGNUM))
11435 (clobber (reg:SI CC_REGNUM))]
11436 "TARGET_GNU2_TLS"
11437 {
11438 targetm.asm_out.internal_label (asm_out_file, "LPIC",
11439 INTVAL (operands[1]));
11440 return "bl\\t%c0(tlscall)";
11441 }
11442 [(set_attr "conds" "clob")
1b7da4ac 11443 (set_attr "length" "4")
11444 (set_attr "type" "branch")]
f41e4452 11445)
11446
1fe0edab 11447;; For thread pointer builtin
11448(define_expand "get_thread_pointersi"
11449 [(match_operand:SI 0 "s_register_operand" "=r")]
11450 ""
11451 "
11452 {
11453 arm_load_tp (operands[0]);
11454 DONE;
11455 }")
11456
f41e4452 11457;;
11458
aabe09ac 11459;; We only care about the lower 16 bits of the constant
11460;; being inserted into the upper 16 bits of the register.
eca5c984 11461(define_insn "*arm_movtas_ze"
417e5cc5 11462 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r,r")
eca5c984 11463 (const_int 16)
11464 (const_int 16))
11465 (match_operand:SI 1 "const_int_operand" ""))]
60a48e7d 11466 "TARGET_HAVE_MOVT"
417e5cc5 11467 "@
11468 movt%?\t%0, %L1
11469 movt\t%0, %L1"
11470 [(set_attr "arch" "32,v8mb")
11471 (set_attr "predicable" "yes")
7c36fe71 11472 (set_attr "predicable_short_it" "no")
1b7da4ac 11473 (set_attr "length" "4")
282b4c75 11474 (set_attr "type" "alu_sreg")]
eca5c984 11475)
11476
c0fc3696 11477(define_insn "*arm_rev"
a486b499 11478 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
11479 (bswap:SI (match_operand:SI 1 "s_register_operand" "l,l,r")))]
11480 "arm_arch6"
11481 "@
11482 rev\t%0, %1
11483 rev%?\t%0, %1
11484 rev%?\t%0, %1"
11485 [(set_attr "arch" "t1,t2,32")
1b7da4ac 11486 (set_attr "length" "2,2,4")
4a510717 11487 (set_attr "predicable" "no,yes,yes")
11488 (set_attr "predicable_short_it" "no")
1b7da4ac 11489 (set_attr "type" "rev")]
ff82f757 11490)
11491
11492(define_expand "arm_legacy_rev"
11493 [(set (match_operand:SI 2 "s_register_operand" "")
11494 (xor:SI (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
11495 (const_int 16))
11496 (match_dup 1)))
11497 (set (match_dup 2)
11498 (lshiftrt:SI (match_dup 2)
11499 (const_int 8)))
11500 (set (match_operand:SI 3 "s_register_operand" "")
11501 (rotatert:SI (match_dup 1)
11502 (const_int 8)))
11503 (set (match_dup 2)
11504 (and:SI (match_dup 2)
11505 (const_int -65281)))
11506 (set (match_operand:SI 0 "s_register_operand" "")
11507 (xor:SI (match_dup 3)
11508 (match_dup 2)))]
11509 "TARGET_32BIT"
11510 ""
11511)
11512
11513;; Reuse temporaries to keep register pressure down.
11514(define_expand "thumb_legacy_rev"
11515 [(set (match_operand:SI 2 "s_register_operand" "")
11516 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
11517 (const_int 24)))
11518 (set (match_operand:SI 3 "s_register_operand" "")
11519 (lshiftrt:SI (match_dup 1)
11520 (const_int 24)))
11521 (set (match_dup 3)
11522 (ior:SI (match_dup 3)
11523 (match_dup 2)))
11524 (set (match_operand:SI 4 "s_register_operand" "")
11525 (const_int 16))
11526 (set (match_operand:SI 5 "s_register_operand" "")
11527 (rotatert:SI (match_dup 1)
11528 (match_dup 4)))
11529 (set (match_dup 2)
11530 (ashift:SI (match_dup 5)
11531 (const_int 24)))
11532 (set (match_dup 5)
11533 (lshiftrt:SI (match_dup 5)
11534 (const_int 24)))
11535 (set (match_dup 5)
11536 (ior:SI (match_dup 5)
11537 (match_dup 2)))
11538 (set (match_dup 5)
11539 (rotatert:SI (match_dup 5)
11540 (match_dup 4)))
11541 (set (match_operand:SI 0 "s_register_operand" "")
11542 (ior:SI (match_dup 5)
11543 (match_dup 3)))]
11544 "TARGET_THUMB"
11545 ""
11546)
11547
62e39b06 11548;; ARM-specific expansion of signed mod by power of 2
11549;; using conditional negate.
11550;; For r0 % n where n is a power of 2 produce:
11551;; rsbs r1, r0, #0
11552;; and r0, r0, #(n - 1)
11553;; and r1, r1, #(n - 1)
11554;; rsbpl r0, r1, #0
11555
11556(define_expand "modsi3"
11557 [(match_operand:SI 0 "register_operand" "")
11558 (match_operand:SI 1 "register_operand" "")
11559 (match_operand:SI 2 "const_int_operand" "")]
11560 "TARGET_32BIT"
11561 {
11562 HOST_WIDE_INT val = INTVAL (operands[2]);
11563
11564 if (val <= 0
11565 || exact_log2 (val) <= 0)
11566 FAIL;
11567
11568 rtx mask = GEN_INT (val - 1);
11569
11570 /* In the special case of x0 % 2 we can do the even shorter:
11571 cmp r0, #0
11572 and r0, r0, #1
11573 rsblt r0, r0, #0. */
11574
11575 if (val == 2)
11576 {
11577 rtx cc_reg = arm_gen_compare_reg (LT,
11578 operands[1], const0_rtx, NULL_RTX);
11579 rtx cond = gen_rtx_LT (SImode, cc_reg, const0_rtx);
11580 rtx masked = gen_reg_rtx (SImode);
11581
11582 emit_insn (gen_andsi3 (masked, operands[1], mask));
11583 emit_move_insn (operands[0],
11584 gen_rtx_IF_THEN_ELSE (SImode, cond,
11585 gen_rtx_NEG (SImode,
11586 masked),
11587 masked));
11588 DONE;
11589 }
11590
11591 rtx neg_op = gen_reg_rtx (SImode);
11592 rtx_insn *insn = emit_insn (gen_subsi3_compare0 (neg_op, const0_rtx,
11593 operands[1]));
11594
11595 /* Extract the condition register and mode. */
11596 rtx cmp = XVECEXP (PATTERN (insn), 0, 0);
11597 rtx cc_reg = SET_DEST (cmp);
11598 rtx cond = gen_rtx_GE (SImode, cc_reg, const0_rtx);
11599
11600 emit_insn (gen_andsi3 (operands[0], operands[1], mask));
11601
11602 rtx masked_neg = gen_reg_rtx (SImode);
11603 emit_insn (gen_andsi3 (masked_neg, neg_op, mask));
11604
11605 /* We want a conditional negate here, but emitting COND_EXEC rtxes
11606 during expand does not always work. Do an IF_THEN_ELSE instead. */
11607 emit_move_insn (operands[0],
11608 gen_rtx_IF_THEN_ELSE (SImode, cond,
11609 gen_rtx_NEG (SImode, masked_neg),
11610 operands[0]));
11611
11612
11613 DONE;
11614 }
11615)
11616
ff82f757 11617(define_expand "bswapsi2"
11618 [(set (match_operand:SI 0 "s_register_operand" "=r")
11619 (bswap:SI (match_operand:SI 1 "s_register_operand" "r")))]
8d1af482 11620"TARGET_EITHER && (arm_arch6 || !optimize_size)"
ff82f757 11621"
8d1af482 11622 if (!arm_arch6)
11623 {
11624 rtx op2 = gen_reg_rtx (SImode);
11625 rtx op3 = gen_reg_rtx (SImode);
ff82f757 11626
8d1af482 11627 if (TARGET_THUMB)
11628 {
11629 rtx op4 = gen_reg_rtx (SImode);
11630 rtx op5 = gen_reg_rtx (SImode);
ff82f757 11631
8d1af482 11632 emit_insn (gen_thumb_legacy_rev (operands[0], operands[1],
11633 op2, op3, op4, op5));
11634 }
11635 else
11636 {
11637 emit_insn (gen_arm_legacy_rev (operands[0], operands[1],
11638 op2, op3));
11639 }
ff82f757 11640
8d1af482 11641 DONE;
11642 }
ff82f757 11643 "
11644)
11645
a486b499 11646;; bswap16 patterns: use revsh and rev16 instructions for the signed
11647;; and unsigned variants, respectively. For rev16, expose
11648;; byte-swapping in the lower 16 bits only.
11649(define_insn "*arm_revsh"
11650 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
11651 (sign_extend:SI (bswap:HI (match_operand:HI 1 "s_register_operand" "l,l,r"))))]
11652 "arm_arch6"
11653 "@
11654 revsh\t%0, %1
11655 revsh%?\t%0, %1
11656 revsh%?\t%0, %1"
11657 [(set_attr "arch" "t1,t2,32")
1b7da4ac 11658 (set_attr "length" "2,2,4")
11659 (set_attr "type" "rev")]
a486b499 11660)
11661
11662(define_insn "*arm_rev16"
11663 [(set (match_operand:HI 0 "s_register_operand" "=l,l,r")
11664 (bswap:HI (match_operand:HI 1 "s_register_operand" "l,l,r")))]
11665 "arm_arch6"
11666 "@
11667 rev16\t%0, %1
11668 rev16%?\t%0, %1
11669 rev16%?\t%0, %1"
11670 [(set_attr "arch" "t1,t2,32")
1b7da4ac 11671 (set_attr "length" "2,2,4")
11672 (set_attr "type" "rev")]
09f69e55 11673)
11674
11675;; There are no canonicalisation rules for the position of the lshiftrt, ashift
11676;; operations within an IOR/AND RTX, therefore we have two patterns matching
11677;; each valid permutation.
11678
11679(define_insn "arm_rev16si2"
11680 [(set (match_operand:SI 0 "register_operand" "=l,l,r")
11681 (ior:SI (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "l,l,r")
11682 (const_int 8))
11683 (match_operand:SI 3 "const_int_operand" "n,n,n"))
11684 (and:SI (lshiftrt:SI (match_dup 1)
11685 (const_int 8))
11686 (match_operand:SI 2 "const_int_operand" "n,n,n"))))]
11687 "arm_arch6
11688 && aarch_rev16_shleft_mask_imm_p (operands[3], SImode)
11689 && aarch_rev16_shright_mask_imm_p (operands[2], SImode)"
11690 "rev16\\t%0, %1"
11691 [(set_attr "arch" "t1,t2,32")
11692 (set_attr "length" "2,2,4")
11693 (set_attr "type" "rev")]
11694)
11695
11696(define_insn "arm_rev16si2_alt"
11697 [(set (match_operand:SI 0 "register_operand" "=l,l,r")
11698 (ior:SI (and:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,l,r")
11699 (const_int 8))
11700 (match_operand:SI 2 "const_int_operand" "n,n,n"))
11701 (and:SI (ashift:SI (match_dup 1)
11702 (const_int 8))
11703 (match_operand:SI 3 "const_int_operand" "n,n,n"))))]
11704 "arm_arch6
11705 && aarch_rev16_shleft_mask_imm_p (operands[3], SImode)
11706 && aarch_rev16_shright_mask_imm_p (operands[2], SImode)"
11707 "rev16\\t%0, %1"
11708 [(set_attr "arch" "t1,t2,32")
11709 (set_attr "length" "2,2,4")
11710 (set_attr "type" "rev")]
a486b499 11711)
11712
11713(define_expand "bswaphi2"
11714 [(set (match_operand:HI 0 "s_register_operand" "=r")
11715 (bswap:HI (match_operand:HI 1 "s_register_operand" "r")))]
11716"arm_arch6"
11717""
11718)
11719
1653cf17 11720;; Patterns for LDRD/STRD in Thumb2 mode
11721
11722(define_insn "*thumb2_ldrd"
11723 [(set (match_operand:SI 0 "s_register_operand" "=r")
11724 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
11725 (match_operand:SI 2 "ldrd_strd_offset_operand" "Do"))))
11726 (set (match_operand:SI 3 "s_register_operand" "=r")
11727 (mem:SI (plus:SI (match_dup 1)
11728 (match_operand:SI 4 "const_int_operand" ""))))]
11729 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
1653cf17 11730 && ((INTVAL (operands[2]) + 4) == INTVAL (operands[4]))
11731 && (operands_ok_ldrd_strd (operands[0], operands[3],
11732 operands[1], INTVAL (operands[2]),
11733 false, true))"
11734 "ldrd%?\t%0, %3, [%1, %2]"
11735 [(set_attr "type" "load2")
d952d547 11736 (set_attr "predicable" "yes")
11737 (set_attr "predicable_short_it" "no")])
1653cf17 11738
11739(define_insn "*thumb2_ldrd_base"
11740 [(set (match_operand:SI 0 "s_register_operand" "=r")
11741 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
11742 (set (match_operand:SI 2 "s_register_operand" "=r")
11743 (mem:SI (plus:SI (match_dup 1)
11744 (const_int 4))))]
11745 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
1653cf17 11746 && (operands_ok_ldrd_strd (operands[0], operands[2],
11747 operands[1], 0, false, true))"
11748 "ldrd%?\t%0, %2, [%1]"
11749 [(set_attr "type" "load2")
d952d547 11750 (set_attr "predicable" "yes")
11751 (set_attr "predicable_short_it" "no")])
1653cf17 11752
11753(define_insn "*thumb2_ldrd_base_neg"
11754 [(set (match_operand:SI 0 "s_register_operand" "=r")
11755 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
11756 (const_int -4))))
11757 (set (match_operand:SI 2 "s_register_operand" "=r")
11758 (mem:SI (match_dup 1)))]
11759 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
1653cf17 11760 && (operands_ok_ldrd_strd (operands[0], operands[2],
11761 operands[1], -4, false, true))"
11762 "ldrd%?\t%0, %2, [%1, #-4]"
11763 [(set_attr "type" "load2")
d952d547 11764 (set_attr "predicable" "yes")
11765 (set_attr "predicable_short_it" "no")])
1653cf17 11766
11767(define_insn "*thumb2_strd"
11768 [(set (mem:SI (plus:SI (match_operand:SI 0 "s_register_operand" "rk")
11769 (match_operand:SI 1 "ldrd_strd_offset_operand" "Do")))
11770 (match_operand:SI 2 "s_register_operand" "r"))
11771 (set (mem:SI (plus:SI (match_dup 0)
11772 (match_operand:SI 3 "const_int_operand" "")))
11773 (match_operand:SI 4 "s_register_operand" "r"))]
11774 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
1653cf17 11775 && ((INTVAL (operands[1]) + 4) == INTVAL (operands[3]))
11776 && (operands_ok_ldrd_strd (operands[2], operands[4],
11777 operands[0], INTVAL (operands[1]),
11778 false, false))"
11779 "strd%?\t%2, %4, [%0, %1]"
11780 [(set_attr "type" "store2")
d952d547 11781 (set_attr "predicable" "yes")
11782 (set_attr "predicable_short_it" "no")])
1653cf17 11783
11784(define_insn "*thumb2_strd_base"
11785 [(set (mem:SI (match_operand:SI 0 "s_register_operand" "rk"))
11786 (match_operand:SI 1 "s_register_operand" "r"))
11787 (set (mem:SI (plus:SI (match_dup 0)
11788 (const_int 4)))
11789 (match_operand:SI 2 "s_register_operand" "r"))]
11790 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
1653cf17 11791 && (operands_ok_ldrd_strd (operands[1], operands[2],
11792 operands[0], 0, false, false))"
11793 "strd%?\t%1, %2, [%0]"
11794 [(set_attr "type" "store2")
d952d547 11795 (set_attr "predicable" "yes")
11796 (set_attr "predicable_short_it" "no")])
1653cf17 11797
11798(define_insn "*thumb2_strd_base_neg"
11799 [(set (mem:SI (plus:SI (match_operand:SI 0 "s_register_operand" "rk")
11800 (const_int -4)))
11801 (match_operand:SI 1 "s_register_operand" "r"))
11802 (set (mem:SI (match_dup 0))
11803 (match_operand:SI 2 "s_register_operand" "r"))]
11804 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
1653cf17 11805 && (operands_ok_ldrd_strd (operands[1], operands[2],
11806 operands[0], -4, false, false))"
11807 "strd%?\t%1, %2, [%0, #-4]"
11808 [(set_attr "type" "store2")
d952d547 11809 (set_attr "predicable" "yes")
11810 (set_attr "predicable_short_it" "no")])
1653cf17 11811
2a0c73f2 11812;; ARMv8 CRC32 instructions.
11813(define_insn "<crc_variant>"
11814 [(set (match_operand:SI 0 "s_register_operand" "=r")
11815 (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")
11816 (match_operand:<crc_mode> 2 "s_register_operand" "r")]
11817 CRC))]
11818 "TARGET_CRC32"
11819 "<crc_variant>\\t%0, %1, %2"
11820 [(set_attr "type" "crc")
11821 (set_attr "conds" "unconditional")]
11822)
1653cf17 11823
353cf59a 11824;; Load the load/store double peephole optimizations.
11825(include "ldrdstrd.md")
11826
320ea44d 11827;; Load the load/store multiple patterns
11828(include "ldmstm.md")
426be8c5 11829
11830;; Patterns in ldmstm.md don't cover more than 4 registers. This pattern covers
11831;; large lists without explicit writeback generated for APCS_FRAME epilogue.
3873efff 11832;; The operands are validated through the load_multiple_operation
11833;; match_parallel predicate rather than through constraints so enable it only
11834;; after reload.
426be8c5 11835(define_insn "*load_multiple"
11836 [(match_parallel 0 "load_multiple_operation"
11837 [(set (match_operand:SI 2 "s_register_operand" "=rk")
11838 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
11839 ])]
3873efff 11840 "TARGET_32BIT && reload_completed"
426be8c5 11841 "*
11842 {
11843 arm_output_multireg_pop (operands, /*return_pc=*/false,
11844 /*cond=*/const_true_rtx,
11845 /*reverse=*/false,
11846 /*update=*/false);
11847 return \"\";
11848 }
11849 "
11850 [(set_attr "predicable" "yes")]
11851)
11852
84450ddc 11853(define_expand "copysignsf3"
11854 [(match_operand:SF 0 "register_operand")
11855 (match_operand:SF 1 "register_operand")
11856 (match_operand:SF 2 "register_operand")]
11857 "TARGET_SOFT_FLOAT && arm_arch_thumb2"
11858 "{
11859 emit_move_insn (operands[0], operands[2]);
11860 emit_insn (gen_insv_t2 (simplify_gen_subreg (SImode, operands[0], SFmode, 0),
11861 GEN_INT (31), GEN_INT (0),
11862 simplify_gen_subreg (SImode, operands[1], SFmode, 0)));
11863 DONE;
11864 }"
11865)
11866
11867(define_expand "copysigndf3"
11868 [(match_operand:DF 0 "register_operand")
11869 (match_operand:DF 1 "register_operand")
11870 (match_operand:DF 2 "register_operand")]
11871 "TARGET_SOFT_FLOAT && arm_arch_thumb2"
11872 "{
11873 rtx op0_low = gen_lowpart (SImode, operands[0]);
11874 rtx op0_high = gen_highpart (SImode, operands[0]);
11875 rtx op1_low = gen_lowpart (SImode, operands[1]);
11876 rtx op1_high = gen_highpart (SImode, operands[1]);
11877 rtx op2_high = gen_highpart (SImode, operands[2]);
11878
11879 rtx scratch1 = gen_reg_rtx (SImode);
11880 rtx scratch2 = gen_reg_rtx (SImode);
11881 emit_move_insn (scratch1, op2_high);
11882 emit_move_insn (scratch2, op1_high);
11883
d1f9b275 11884 emit_insn(gen_rtx_SET(scratch1,
84450ddc 11885 gen_rtx_LSHIFTRT (SImode, op2_high, GEN_INT(31))));
11886 emit_insn(gen_insv_t2(scratch2, GEN_INT(1), GEN_INT(31), scratch1));
11887 emit_move_insn (op0_low, op1_low);
11888 emit_move_insn (op0_high, scratch2);
11889
11890 DONE;
11891 }"
11892)
11893
115857ef 11894;; movmisalign patterns for HImode and SImode.
11895(define_expand "movmisalign<mode>"
11896 [(match_operand:HSI 0 "general_operand")
11897 (match_operand:HSI 1 "general_operand")]
11898 "unaligned_access"
11899{
11900 /* This pattern is not permitted to fail during expansion: if both arguments
11901 are non-registers (e.g. memory := constant), force operand 1 into a
11902 register. */
11903 rtx (* gen_unaligned_load)(rtx, rtx);
11904 rtx tmp_dest = operands[0];
11905 if (!s_register_operand (operands[0], <MODE>mode)
11906 && !s_register_operand (operands[1], <MODE>mode))
11907 operands[1] = force_reg (<MODE>mode, operands[1]);
11908
11909 if (<MODE>mode == HImode)
11910 {
11911 gen_unaligned_load = gen_unaligned_loadhiu;
11912 tmp_dest = gen_reg_rtx (SImode);
11913 }
11914 else
11915 gen_unaligned_load = gen_unaligned_loadsi;
11916
11917 if (MEM_P (operands[1]))
11918 {
11919 emit_insn (gen_unaligned_load (tmp_dest, operands[1]));
11920 if (<MODE>mode == HImode)
11921 emit_move_insn (operands[0], gen_lowpart (HImode, tmp_dest));
11922 }
11923 else
11924 emit_insn (gen_unaligned_store<mode> (operands[0], operands[1]));
11925
11926 DONE;
11927})
11928
1be6395a 11929(define_insn "<cdp>"
11930 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "n")
11931 (match_operand:SI 1 "immediate_operand" "n")
11932 (match_operand:SI 2 "immediate_operand" "n")
11933 (match_operand:SI 3 "immediate_operand" "n")
11934 (match_operand:SI 4 "immediate_operand" "n")
11935 (match_operand:SI 5 "immediate_operand" "n")] CDPI)]
11936 "arm_coproc_builtin_available (VUNSPEC_<CDP>)"
11937{
11938 arm_const_bounds (operands[0], 0, 16);
11939 arm_const_bounds (operands[1], 0, 16);
11940 arm_const_bounds (operands[2], 0, (1 << 5));
11941 arm_const_bounds (operands[3], 0, (1 << 5));
11942 arm_const_bounds (operands[4], 0, (1 << 5));
11943 arm_const_bounds (operands[5], 0, 8);
11944 return "<cdp>\\tp%c0, %1, CR%c2, CR%c3, CR%c4, %5";
11945}
11946 [(set_attr "length" "4")
11947 (set_attr "type" "coproc")])
11948
638b44bd 11949(define_insn "*ldc"
11950 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "n")
11951 (match_operand:SI 1 "immediate_operand" "n")
11952 (match_operand:SI 2 "memory_operand" "Uz")] LDCI)]
11953 "arm_coproc_builtin_available (VUNSPEC_<LDC>)"
11954{
11955 arm_const_bounds (operands[0], 0, 16);
11956 arm_const_bounds (operands[1], 0, (1 << 5));
11957 return "<ldc>\\tp%c0, CR%c1, %2";
11958}
11959 [(set_attr "length" "4")
11960 (set_attr "type" "coproc")])
11961
11962(define_insn "*stc"
11963 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "n")
11964 (match_operand:SI 1 "immediate_operand" "n")
11965 (match_operand:SI 2 "memory_operand" "=Uz")] STCI)]
11966 "arm_coproc_builtin_available (VUNSPEC_<STC>)"
11967{
11968 arm_const_bounds (operands[0], 0, 16);
11969 arm_const_bounds (operands[1], 0, (1 << 5));
11970 return "<stc>\\tp%c0, CR%c1, %2";
11971}
11972 [(set_attr "length" "4")
11973 (set_attr "type" "coproc")])
11974
11975(define_expand "<ldc>"
11976 [(unspec_volatile [(match_operand:SI 0 "immediate_operand")
11977 (match_operand:SI 1 "immediate_operand")
11978 (mem:SI (match_operand:SI 2 "s_register_operand"))] LDCI)]
11979 "arm_coproc_builtin_available (VUNSPEC_<LDC>)")
11980
11981(define_expand "<stc>"
11982 [(unspec_volatile [(match_operand:SI 0 "immediate_operand")
11983 (match_operand:SI 1 "immediate_operand")
11984 (mem:SI (match_operand:SI 2 "s_register_operand"))] STCI)]
11985 "arm_coproc_builtin_available (VUNSPEC_<STC>)")
11986
415e9b1f 11987(define_insn "<mcr>"
11988 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "n")
11989 (match_operand:SI 1 "immediate_operand" "n")
11990 (match_operand:SI 2 "s_register_operand" "r")
11991 (match_operand:SI 3 "immediate_operand" "n")
11992 (match_operand:SI 4 "immediate_operand" "n")
11993 (match_operand:SI 5 "immediate_operand" "n")] MCRI)
11994 (use (match_dup 2))]
11995 "arm_coproc_builtin_available (VUNSPEC_<MCR>)"
11996{
11997 arm_const_bounds (operands[0], 0, 16);
11998 arm_const_bounds (operands[1], 0, 8);
11999 arm_const_bounds (operands[3], 0, (1 << 5));
12000 arm_const_bounds (operands[4], 0, (1 << 5));
12001 arm_const_bounds (operands[5], 0, 8);
12002 return "<mcr>\\tp%c0, %1, %2, CR%c3, CR%c4, %5";
12003}
12004 [(set_attr "length" "4")
12005 (set_attr "type" "coproc")])
12006
12007(define_insn "<mrc>"
12008 [(set (match_operand:SI 0 "s_register_operand" "=r")
6f8d7784 12009 (unspec_volatile:SI [(match_operand:SI 1 "immediate_operand" "n")
415e9b1f 12010 (match_operand:SI 2 "immediate_operand" "n")
12011 (match_operand:SI 3 "immediate_operand" "n")
12012 (match_operand:SI 4 "immediate_operand" "n")
12013 (match_operand:SI 5 "immediate_operand" "n")] MRCI))]
12014 "arm_coproc_builtin_available (VUNSPEC_<MRC>)"
12015{
12016 arm_const_bounds (operands[1], 0, 16);
12017 arm_const_bounds (operands[2], 0, 8);
12018 arm_const_bounds (operands[3], 0, (1 << 5));
12019 arm_const_bounds (operands[4], 0, (1 << 5));
12020 arm_const_bounds (operands[5], 0, 8);
12021 return "<mrc>\\tp%c1, %2, %0, CR%c3, CR%c4, %5";
12022}
12023 [(set_attr "length" "4")
12024 (set_attr "type" "coproc")])
12025
cabfd710 12026(define_insn "<mcrr>"
12027 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "n")
12028 (match_operand:SI 1 "immediate_operand" "n")
12029 (match_operand:DI 2 "s_register_operand" "r")
12030 (match_operand:SI 3 "immediate_operand" "n")] MCRRI)
12031 (use (match_dup 2))]
12032 "arm_coproc_builtin_available (VUNSPEC_<MCRR>)"
12033{
12034 arm_const_bounds (operands[0], 0, 16);
12035 arm_const_bounds (operands[1], 0, 8);
12036 arm_const_bounds (operands[3], 0, (1 << 5));
12037 return "<mcrr>\\tp%c0, %1, %Q2, %R2, CR%c3";
12038}
12039 [(set_attr "length" "4")
12040 (set_attr "type" "coproc")])
12041
12042(define_insn "<mrrc>"
12043 [(set (match_operand:DI 0 "s_register_operand" "=r")
6f8d7784 12044 (unspec_volatile:DI [(match_operand:SI 1 "immediate_operand" "n")
cabfd710 12045 (match_operand:SI 2 "immediate_operand" "n")
12046 (match_operand:SI 3 "immediate_operand" "n")] MRRCI))]
12047 "arm_coproc_builtin_available (VUNSPEC_<MRRC>)"
12048{
12049 arm_const_bounds (operands[1], 0, 16);
12050 arm_const_bounds (operands[2], 0, 8);
12051 arm_const_bounds (operands[3], 0, (1 << 5));
12052 return "<mrrc>\\tp%c1, %2, %Q0, %R0, CR%c3";
12053}
12054 [(set_attr "length" "4")
12055 (set_attr "type" "coproc")])
12056
d98a3884 12057;; Vector bits common to IWMMXT and Neon
12058(include "vec-common.md")
755eb2b4 12059;; Load the Intel Wireless Multimedia Extension patterns
12060(include "iwmmxt.md")
a2cd141b 12061;; Load the VFP co-processor patterns
12062(include "vfp.md")
bc360af8 12063;; Thumb-1 patterns
12064(include "thumb1.md")
25f905c2 12065;; Thumb-2 patterns
12066(include "thumb2.md")
d98a3884 12067;; Neon patterns
12068(include "neon.md")
e84fdf6e 12069;; Crypto patterns
12070(include "crypto.md")
06df6b17 12071;; Synchronization Primitives
12072(include "sync.md")
bbbe4599 12073;; Fixed-point patterns
12074(include "arm-fixed.md")