]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/arm/arm.md
[gcc]
[thirdparty/gcc.git] / gcc / config / arm / arm.md
CommitLineData
129a2fe4 1;;- Machine description for ARM for GNU compiler
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"
9f2c2a36 317 "block,call,load_4")
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"
206f0a3f 460 [(set (match_operand:DI 0 "arm_general_register_operand" "=&r,&r,&r,&r,&r")
461 (plus:DI (match_operand:DI 1 "arm_general_register_operand" "%0, 0, r, 0, r")
462 (match_operand:DI 2 "arm_general_adddi_operand" "r, 0, r, Dd, Dd")))
bd5b4116 463 (clobber (reg:CC CC_REGNUM))]
b805622c 464 "TARGET_32BIT && !TARGET_NEON"
33782ec7 465 "#"
206f0a3f 466 "TARGET_32BIT && ((!TARGET_NEON && !TARGET_IWMMXT) || reload_completed)"
a0f94409 467 [(parallel [(set (reg:CC_C CC_REGNUM)
468 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
469 (match_dup 1)))
470 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 471 (set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (match_dup 5))
472 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
a0f94409 473 "
474 {
475 operands[3] = gen_highpart (SImode, operands[0]);
476 operands[0] = gen_lowpart (SImode, operands[0]);
477 operands[4] = gen_highpart (SImode, operands[1]);
478 operands[1] = gen_lowpart (SImode, operands[1]);
10e5ccd5 479 operands[5] = gen_highpart_mode (SImode, DImode, operands[2]);
a0f94409 480 operands[2] = gen_lowpart (SImode, operands[2]);
481 }"
cffb2a26 482 [(set_attr "conds" "clob")
1b7da4ac 483 (set_attr "length" "8")
484 (set_attr "type" "multiple")]
cffb2a26 485)
9c08d1fa 486
a0f94409 487(define_insn_and_split "*adddi_sesidi_di"
9c08d1fa 488 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
489 (plus:DI (sign_extend:DI
97499065 490 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 491 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 492 (clobber (reg:CC CC_REGNUM))]
b805622c 493 "TARGET_32BIT"
33782ec7 494 "#"
25f905c2 495 "TARGET_32BIT && reload_completed"
a0f94409 496 [(parallel [(set (reg:CC_C CC_REGNUM)
497 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
498 (match_dup 1)))
499 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 500 (set (match_dup 3) (plus:SI (plus:SI (ashiftrt:SI (match_dup 2)
a0f94409 501 (const_int 31))
080c0b9a 502 (match_dup 4))
503 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
a0f94409 504 "
505 {
506 operands[3] = gen_highpart (SImode, operands[0]);
507 operands[0] = gen_lowpart (SImode, operands[0]);
508 operands[4] = gen_highpart (SImode, operands[1]);
509 operands[1] = gen_lowpart (SImode, operands[1]);
510 operands[2] = gen_lowpart (SImode, operands[2]);
511 }"
215b30b3 512 [(set_attr "conds" "clob")
1b7da4ac 513 (set_attr "length" "8")
514 (set_attr "type" "multiple")]
215b30b3 515)
9c08d1fa 516
a0f94409 517(define_insn_and_split "*adddi_zesidi_di"
9c08d1fa 518 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
519 (plus:DI (zero_extend:DI
97499065 520 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 521 (match_operand:DI 1 "s_register_operand" "0,r")))
a0f94409 522 (clobber (reg:CC CC_REGNUM))]
b805622c 523 "TARGET_32BIT"
33782ec7 524 "#"
25f905c2 525 "TARGET_32BIT && reload_completed"
a0f94409 526 [(parallel [(set (reg:CC_C CC_REGNUM)
527 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
528 (match_dup 1)))
529 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 530 (set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (const_int 0))
531 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
a0f94409 532 "
533 {
534 operands[3] = gen_highpart (SImode, operands[0]);
535 operands[0] = gen_lowpart (SImode, operands[0]);
536 operands[4] = gen_highpart (SImode, operands[1]);
537 operands[1] = gen_lowpart (SImode, operands[1]);
538 operands[2] = gen_lowpart (SImode, operands[2]);
539 }"
cffb2a26 540 [(set_attr "conds" "clob")
1b7da4ac 541 (set_attr "length" "8")
542 (set_attr "type" "multiple")]
cffb2a26 543)
b11cae9e 544
f6c98a9a 545(define_expand "addv<mode>4"
546 [(match_operand:SIDI 0 "register_operand")
547 (match_operand:SIDI 1 "register_operand")
548 (match_operand:SIDI 2 "register_operand")
549 (match_operand 3 "")]
550 "TARGET_32BIT"
551{
552 emit_insn (gen_add<mode>3_compareV (operands[0], operands[1], operands[2]));
553 arm_gen_unlikely_cbranch (NE, CC_Vmode, operands[3]);
554
555 DONE;
556})
557
558(define_expand "uaddv<mode>4"
559 [(match_operand:SIDI 0 "register_operand")
560 (match_operand:SIDI 1 "register_operand")
561 (match_operand:SIDI 2 "register_operand")
562 (match_operand 3 "")]
563 "TARGET_32BIT"
564{
565 emit_insn (gen_add<mode>3_compareC (operands[0], operands[1], operands[2]));
566 arm_gen_unlikely_cbranch (NE, CC_Cmode, operands[3]);
567
568 DONE;
569})
570
87b22bf7 571(define_expand "addsi3"
cffb2a26 572 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 573 (plus:SI (match_operand:SI 1 "s_register_operand" "")
574 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 575 "TARGET_EITHER"
87b22bf7 576 "
0438d37f 577 if (TARGET_32BIT && CONST_INT_P (operands[2]))
87b22bf7 578 {
96f57e36 579 arm_split_constant (PLUS, SImode, NULL_RTX,
580 INTVAL (operands[2]), operands[0], operands[1],
e1ba4a27 581 optimize && can_create_pseudo_p ());
87b22bf7 582 DONE;
583 }
cffb2a26 584 "
585)
87b22bf7 586
5bd751ff 587; If there is a scratch available, this will be faster than synthesizing the
a0f94409 588; addition.
589(define_peephole2
590 [(match_scratch:SI 3 "r")
372575c7 591 (set (match_operand:SI 0 "arm_general_register_operand" "")
592 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
cffb2a26 593 (match_operand:SI 2 "const_int_operand" "")))]
25f905c2 594 "TARGET_32BIT &&
a0f94409 595 !(const_ok_for_arm (INTVAL (operands[2]))
596 || const_ok_for_arm (-INTVAL (operands[2])))
597 && const_ok_for_arm (~INTVAL (operands[2]))"
598 [(set (match_dup 3) (match_dup 2))
599 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
600 ""
601)
87b22bf7 602
2f02c19f 603;; The r/r/k alternative is required when reloading the address
604;; (plus (reg rN) (reg sp)) into (reg rN). In this case reload will
605;; put the duplicated register first, and not try the commutative version.
a0f94409 606(define_insn_and_split "*arm_addsi3"
fa1f9c9e 607 [(set (match_operand:SI 0 "s_register_operand" "=rk,l,l ,l ,r ,k ,r,k ,r ,k ,r ,k,k,r ,k ,r")
608 (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")
609 (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 610 "TARGET_32BIT"
5565501b 611 "@
c24d855d 612 add%?\\t%0, %0, %2
5565501b 613 add%?\\t%0, %1, %2
a0b3420a 614 add%?\\t%0, %1, %2
7c36fe71 615 add%?\\t%0, %1, %2
616 add%?\\t%0, %1, %2
aaa37ad6 617 add%?\\t%0, %1, %2
2f02c19f 618 add%?\\t%0, %2, %1
fa1f9c9e 619 add%?\\t%0, %1, %2
d5cbae34 620 addw%?\\t%0, %1, %2
621 addw%?\\t%0, %1, %2
aaa37ad6 622 sub%?\\t%0, %1, #%n2
87b22bf7 623 sub%?\\t%0, %1, #%n2
d7757711 624 sub%?\\t%0, %1, #%n2
d5cbae34 625 subw%?\\t%0, %1, #%n2
626 subw%?\\t%0, %1, #%n2
87b22bf7 627 #"
a3ffc315 628 "TARGET_32BIT
0438d37f 629 && CONST_INT_P (operands[2])
d5cbae34 630 && !const_ok_for_op (INTVAL (operands[2]), PLUS)
a3ffc315 631 && (reload_completed || !arm_eliminable_register (operands[1]))"
a0f94409 632 [(clobber (const_int 0))]
633 "
96f57e36 634 arm_split_constant (PLUS, SImode, curr_insn,
635 INTVAL (operands[2]), operands[0],
a0f94409 636 operands[1], 0);
637 DONE;
638 "
fa1f9c9e 639 [(set_attr "length" "2,4,4,4,4,4,4,4,4,4,4,4,4,4,4,16")
d5cbae34 640 (set_attr "predicable" "yes")
fa1f9c9e 641 (set_attr "predicable_short_it" "yes,yes,yes,yes,no,no,no,no,no,no,no,no,no,no,no,no")
642 (set_attr "arch" "t2,t2,t2,t2,*,*,*,a,t2,t2,*,*,a,t2,t2,*")
65f68e55 643 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
d82e788e 644 (const_string "alu_imm")
112eda6f 645 (const_string "alu_sreg")))
65f68e55 646 ]
cffb2a26 647)
648
f6c98a9a 649(define_insn_and_split "adddi3_compareV"
650 [(set (reg:CC_V CC_REGNUM)
651 (ne:CC_V
652 (plus:TI
653 (sign_extend:TI (match_operand:DI 1 "register_operand" "r"))
654 (sign_extend:TI (match_operand:DI 2 "register_operand" "r")))
655 (sign_extend:TI (plus:DI (match_dup 1) (match_dup 2)))))
656 (set (match_operand:DI 0 "register_operand" "=&r")
657 (plus:DI (match_dup 1) (match_dup 2)))]
658 "TARGET_32BIT"
659 "#"
660 "&& reload_completed"
661 [(parallel [(set (reg:CC_C CC_REGNUM)
662 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
663 (match_dup 1)))
664 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
665 (parallel [(set (reg:CC_V CC_REGNUM)
666 (ne:CC_V
667 (plus:DI (plus:DI
668 (sign_extend:DI (match_dup 4))
669 (sign_extend:DI (match_dup 5)))
670 (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0)))
671 (plus:DI (sign_extend:DI
672 (plus:SI (match_dup 4) (match_dup 5)))
673 (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0)))))
674 (set (match_dup 3) (plus:SI (plus:SI
675 (match_dup 4) (match_dup 5))
676 (ltu:SI (reg:CC_C CC_REGNUM)
677 (const_int 0))))])]
678 "
679 {
680 operands[3] = gen_highpart (SImode, operands[0]);
681 operands[0] = gen_lowpart (SImode, operands[0]);
682 operands[4] = gen_highpart (SImode, operands[1]);
683 operands[1] = gen_lowpart (SImode, operands[1]);
684 operands[5] = gen_highpart (SImode, operands[2]);
685 operands[2] = gen_lowpart (SImode, operands[2]);
686 }"
687 [(set_attr "conds" "set")
688 (set_attr "length" "8")
689 (set_attr "type" "multiple")]
690)
691
692(define_insn "addsi3_compareV"
693 [(set (reg:CC_V CC_REGNUM)
694 (ne:CC_V
695 (plus:DI
696 (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
697 (sign_extend:DI (match_operand:SI 2 "register_operand" "r")))
698 (sign_extend:DI (plus:SI (match_dup 1) (match_dup 2)))))
699 (set (match_operand:SI 0 "register_operand" "=r")
700 (plus:SI (match_dup 1) (match_dup 2)))]
701 "TARGET_32BIT"
702 "adds%?\\t%0, %1, %2"
703 [(set_attr "conds" "set")
704 (set_attr "type" "alus_sreg")]
705)
706
707(define_insn "*addsi3_compareV_upper"
708 [(set (reg:CC_V CC_REGNUM)
709 (ne:CC_V
710 (plus:DI
711 (plus:DI
712 (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
713 (sign_extend:DI (match_operand:SI 2 "register_operand" "r")))
714 (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0)))
715 (plus:DI (sign_extend:DI
716 (plus:SI (match_dup 1) (match_dup 2)))
717 (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0)))))
718 (set (match_operand:SI 0 "register_operand" "=r")
719 (plus:SI
720 (plus:SI (match_dup 1) (match_dup 2))
721 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
722 "TARGET_32BIT"
723 "adcs%?\\t%0, %1, %2"
724 [(set_attr "conds" "set")
725 (set_attr "type" "adcs_reg")]
726)
727
728(define_insn_and_split "adddi3_compareC"
729 [(set (reg:CC_C CC_REGNUM)
730 (ne:CC_C
731 (plus:TI
732 (zero_extend:TI (match_operand:DI 1 "register_operand" "r"))
733 (zero_extend:TI (match_operand:DI 2 "register_operand" "r")))
734 (zero_extend:TI (plus:DI (match_dup 1) (match_dup 2)))))
735 (set (match_operand:DI 0 "register_operand" "=&r")
736 (plus:DI (match_dup 1) (match_dup 2)))]
737 "TARGET_32BIT"
738 "#"
739 "&& reload_completed"
740 [(parallel [(set (reg:CC_C CC_REGNUM)
741 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
742 (match_dup 1)))
743 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
744 (parallel [(set (reg:CC_C CC_REGNUM)
745 (ne:CC_C
746 (plus:DI (plus:DI
747 (zero_extend:DI (match_dup 4))
748 (zero_extend:DI (match_dup 5)))
749 (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0)))
750 (plus:DI (zero_extend:DI
751 (plus:SI (match_dup 4) (match_dup 5)))
752 (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0)))))
753 (set (match_dup 3) (plus:SI
754 (plus:SI (match_dup 4) (match_dup 5))
755 (ltu:SI (reg:CC_C CC_REGNUM)
756 (const_int 0))))])]
757 "
758 {
759 operands[3] = gen_highpart (SImode, operands[0]);
760 operands[0] = gen_lowpart (SImode, operands[0]);
761 operands[4] = gen_highpart (SImode, operands[1]);
762 operands[5] = gen_highpart (SImode, operands[2]);
763 operands[1] = gen_lowpart (SImode, operands[1]);
764 operands[2] = gen_lowpart (SImode, operands[2]);
765 }"
766 [(set_attr "conds" "set")
767 (set_attr "length" "8")
768 (set_attr "type" "multiple")]
769)
770
771(define_insn "*addsi3_compareC_upper"
772 [(set (reg:CC_C CC_REGNUM)
773 (ne:CC_C
774 (plus:DI
775 (plus:DI
776 (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
777 (zero_extend:DI (match_operand:SI 2 "register_operand" "r")))
778 (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0)))
779 (plus:DI (zero_extend:DI
780 (plus:SI (match_dup 1) (match_dup 2)))
781 (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0)))))
782 (set (match_operand:SI 0 "register_operand" "=r")
783 (plus:SI
784 (plus:SI (match_dup 1) (match_dup 2))
785 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
786 "TARGET_32BIT"
787 "adcs%?\\t%0, %1, %2"
788 [(set_attr "conds" "set")
789 (set_attr "type" "adcs_reg")]
790)
791
792(define_insn "addsi3_compareC"
793 [(set (reg:CC_C CC_REGNUM)
794 (ne:CC_C
795 (plus:DI
796 (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
797 (zero_extend:DI (match_operand:SI 2 "register_operand" "r")))
798 (zero_extend:DI
799 (plus:SI (match_dup 1) (match_dup 2)))))
800 (set (match_operand:SI 0 "register_operand" "=r")
801 (plus:SI (match_dup 1) (match_dup 2)))]
802 "TARGET_32BIT"
803 "adds%?\\t%0, %1, %2"
804 [(set_attr "conds" "set")
805 (set_attr "type" "alus_sreg")]
806)
807
90c2bcf0 808(define_insn "addsi3_compare0"
bd5b4116 809 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 810 (compare:CC_NOOV
65f68e55 811 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r,r")
812 (match_operand:SI 2 "arm_add_operand" "I,L,r"))
5565501b 813 (const_int 0)))
65f68e55 814 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9c08d1fa 815 (plus:SI (match_dup 1) (match_dup 2)))]
ec792a7b 816 "TARGET_ARM"
5565501b 817 "@
3ef90e77 818 adds%?\\t%0, %1, %2
819 subs%?\\t%0, %1, #%n2
820 adds%?\\t%0, %1, %2"
65f68e55 821 [(set_attr "conds" "set")
112eda6f 822 (set_attr "type" "alus_imm,alus_imm,alus_sreg")]
cffb2a26 823)
9c08d1fa 824
aea4c774 825(define_insn "*addsi3_compare0_scratch"
bd5b4116 826 [(set (reg:CC_NOOV CC_REGNUM)
aea4c774 827 (compare:CC_NOOV
65f68e55 828 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r, r")
829 (match_operand:SI 1 "arm_add_operand" "I,L, r"))
aea4c774 830 (const_int 0)))]
ec792a7b 831 "TARGET_ARM"
cffb2a26 832 "@
833 cmn%?\\t%0, %1
65f68e55 834 cmp%?\\t%0, #%n1
835 cmn%?\\t%0, %1"
596e5e8f 836 [(set_attr "conds" "set")
65f68e55 837 (set_attr "predicable" "yes")
112eda6f 838 (set_attr "type" "alus_imm,alus_imm,alus_sreg")]
0d66636f 839)
cffb2a26 840
aed179ae 841(define_insn "*compare_negsi_si"
842 [(set (reg:CC_Z CC_REGNUM)
843 (compare:CC_Z
7c36fe71 844 (neg:SI (match_operand:SI 0 "s_register_operand" "l,r"))
845 (match_operand:SI 1 "s_register_operand" "l,r")))]
25f905c2 846 "TARGET_32BIT"
aed179ae 847 "cmn%?\\t%1, %0"
596e5e8f 848 [(set_attr "conds" "set")
7c36fe71 849 (set_attr "predicable" "yes")
850 (set_attr "arch" "t2,*")
851 (set_attr "length" "2,4")
1b7da4ac 852 (set_attr "predicable_short_it" "yes,no")
112eda6f 853 (set_attr "type" "alus_sreg")]
0d66636f 854)
aea4c774 855
203c488f 856;; This is the canonicalization of addsi3_compare0_for_combiner when the
857;; addend is a constant.
190efb17 858(define_insn "cmpsi2_addneg"
203c488f 859 [(set (reg:CC CC_REGNUM)
860 (compare:CC
861 (match_operand:SI 1 "s_register_operand" "r,r")
2a977b78 862 (match_operand:SI 2 "arm_addimm_operand" "L,I")))
203c488f 863 (set (match_operand:SI 0 "s_register_operand" "=r,r")
864 (plus:SI (match_dup 1)
2a977b78 865 (match_operand:SI 3 "arm_addimm_operand" "I,L")))]
25f905c2 866 "TARGET_32BIT && INTVAL (operands[2]) == -INTVAL (operands[3])"
203c488f 867 "@
3ef90e77 868 adds%?\\t%0, %1, %3
869 subs%?\\t%0, %1, #%n3"
1b7da4ac 870 [(set_attr "conds" "set")
112eda6f 871 (set_attr "type" "alus_sreg")]
203c488f 872)
873
874;; Convert the sequence
875;; sub rd, rn, #1
876;; cmn rd, #1 (equivalent to cmp rd, #-1)
877;; bne dest
878;; into
879;; subs rd, rn, #1
880;; bcs dest ((unsigned)rn >= 1)
881;; similarly for the beq variant using bcc.
882;; This is a common looping idiom (while (n--))
883(define_peephole2
372575c7 884 [(set (match_operand:SI 0 "arm_general_register_operand" "")
885 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
203c488f 886 (const_int -1)))
887 (set (match_operand 2 "cc_register" "")
888 (compare (match_dup 0) (const_int -1)))
889 (set (pc)
890 (if_then_else (match_operator 3 "equality_operator"
891 [(match_dup 2) (const_int 0)])
892 (match_operand 4 "" "")
893 (match_operand 5 "" "")))]
25f905c2 894 "TARGET_32BIT && peep2_reg_dead_p (3, operands[2])"
203c488f 895 [(parallel[
896 (set (match_dup 2)
897 (compare:CC
898 (match_dup 1) (const_int 1)))
899 (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
900 (set (pc)
901 (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
902 (match_dup 4)
903 (match_dup 5)))]
904 "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
905 operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
906 ? GEU : LTU),
907 VOIDmode,
908 operands[2], const0_rtx);"
909)
910
ebcc79bc 911;; The next four insns work because they compare the result with one of
912;; the operands, and we know that the use of the condition code is
913;; either GEU or LTU, so we can use the carry flag from the addition
914;; instead of doing the compare a second time.
915(define_insn "*addsi3_compare_op1"
bd5b4116 916 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 917 (compare:CC_C
65f68e55 918 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
919 (match_operand:SI 2 "arm_add_operand" "I,L,r"))
ebcc79bc 920 (match_dup 1)))
65f68e55 921 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
ebcc79bc 922 (plus:SI (match_dup 1) (match_dup 2)))]
25f905c2 923 "TARGET_32BIT"
ebcc79bc 924 "@
3ef90e77 925 adds%?\\t%0, %1, %2
926 subs%?\\t%0, %1, #%n2
927 adds%?\\t%0, %1, %2"
65f68e55 928 [(set_attr "conds" "set")
112eda6f 929 (set_attr "type" "alus_imm,alus_imm,alus_sreg")]
0d66636f 930)
ebcc79bc 931
932(define_insn "*addsi3_compare_op2"
bd5b4116 933 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 934 (compare:CC_C
65f68e55 935 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
936 (match_operand:SI 2 "arm_add_operand" "I,L,r"))
ebcc79bc 937 (match_dup 2)))
65f68e55 938 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9c08d1fa 939 (plus:SI (match_dup 1) (match_dup 2)))]
25f905c2 940 "TARGET_32BIT"
5565501b 941 "@
3ef90e77 942 adds%?\\t%0, %1, %2
38128b57 943 subs%?\\t%0, %1, #%n2
944 adds%?\\t%0, %1, %2"
65f68e55 945 [(set_attr "conds" "set")
112eda6f 946 (set_attr "type" "alus_imm,alus_imm,alus_sreg")]
0d66636f 947)
9c08d1fa 948
ebcc79bc 949(define_insn "*compare_addsi2_op0"
bd5b4116 950 [(set (reg:CC_C CC_REGNUM)
7c36fe71 951 (compare:CC_C
952 (plus:SI (match_operand:SI 0 "s_register_operand" "l,l,r,r,r")
953 (match_operand:SI 1 "arm_add_operand" "Pv,l,I,L,r"))
954 (match_dup 0)))]
25f905c2 955 "TARGET_32BIT"
ebcc79bc 956 "@
7c36fe71 957 cmp%?\\t%0, #%n1
958 cmn%?\\t%0, %1
ebcc79bc 959 cmn%?\\t%0, %1
65f68e55 960 cmp%?\\t%0, #%n1
961 cmn%?\\t%0, %1"
596e5e8f 962 [(set_attr "conds" "set")
65f68e55 963 (set_attr "predicable" "yes")
7c36fe71 964 (set_attr "arch" "t2,t2,*,*,*")
965 (set_attr "predicable_short_it" "yes,yes,no,no,no")
966 (set_attr "length" "2,2,4,4,4")
112eda6f 967 (set_attr "type" "alus_imm,alus_sreg,alus_imm,alus_imm,alus_sreg")]
0d66636f 968)
ebcc79bc 969
970(define_insn "*compare_addsi2_op1"
bd5b4116 971 [(set (reg:CC_C CC_REGNUM)
7c36fe71 972 (compare:CC_C
973 (plus:SI (match_operand:SI 0 "s_register_operand" "l,l,r,r,r")
974 (match_operand:SI 1 "arm_add_operand" "Pv,l,I,L,r"))
975 (match_dup 1)))]
25f905c2 976 "TARGET_32BIT"
ebcc79bc 977 "@
7c36fe71 978 cmp%?\\t%0, #%n1
979 cmn%?\\t%0, %1
ebcc79bc 980 cmn%?\\t%0, %1
65f68e55 981 cmp%?\\t%0, #%n1
982 cmn%?\\t%0, %1"
596e5e8f 983 [(set_attr "conds" "set")
65f68e55 984 (set_attr "predicable" "yes")
7c36fe71 985 (set_attr "arch" "t2,t2,*,*,*")
986 (set_attr "predicable_short_it" "yes,yes,no,no,no")
987 (set_attr "length" "2,2,4,4,4")
112eda6f 988 (set_attr "type" "alus_imm,alus_sreg,alus_imm,alus_imm,alus_sreg")]
7c36fe71 989 )
ebcc79bc 990
080c0b9a 991(define_insn "*addsi3_carryin_<optab>"
7c36fe71 992 [(set (match_operand:SI 0 "s_register_operand" "=l,r,r")
993 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%l,r,r")
994 (match_operand:SI 2 "arm_not_operand" "0,rI,K"))
995 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))]
25f905c2 996 "TARGET_32BIT"
10e5ccd5 997 "@
a0b3420a 998 adc%?\\t%0, %1, %2
10e5ccd5 999 adc%?\\t%0, %1, %2
1000 sbc%?\\t%0, %1, #%B2"
a7de272d 1001 [(set_attr "conds" "use")
7c36fe71 1002 (set_attr "predicable" "yes")
1003 (set_attr "arch" "t2,*,*")
1004 (set_attr "length" "4")
1b7da4ac 1005 (set_attr "predicable_short_it" "yes,no,no")
1006 (set_attr "type" "adc_reg,adc_reg,adc_imm")]
cffb2a26 1007)
ebcc79bc 1008
080c0b9a 1009(define_insn "*addsi3_carryin_alt2_<optab>"
7c36fe71 1010 [(set (match_operand:SI 0 "s_register_operand" "=l,r,r")
1011 (plus:SI (plus:SI (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))
1012 (match_operand:SI 1 "s_register_operand" "%l,r,r"))
1013 (match_operand:SI 2 "arm_rhs_operand" "l,rI,K")))]
25f905c2 1014 "TARGET_32BIT"
10e5ccd5 1015 "@
a0b3420a 1016 adc%?\\t%0, %1, %2
10e5ccd5 1017 adc%?\\t%0, %1, %2
1018 sbc%?\\t%0, %1, #%B2"
a7de272d 1019 [(set_attr "conds" "use")
7c36fe71 1020 (set_attr "predicable" "yes")
1021 (set_attr "arch" "t2,*,*")
1022 (set_attr "length" "4")
1b7da4ac 1023 (set_attr "predicable_short_it" "yes,no,no")
1024 (set_attr "type" "adc_reg,adc_reg,adc_imm")]
0d66636f 1025)
ebcc79bc 1026
080c0b9a 1027(define_insn "*addsi3_carryin_shift_<optab>"
ebcc79bc 1028 [(set (match_operand:SI 0 "s_register_operand" "=r")
080c0b9a 1029 (plus:SI (plus:SI
1030 (match_operator:SI 2 "shift_operator"
1031 [(match_operand:SI 3 "s_register_operand" "r")
1032 (match_operand:SI 4 "reg_or_int_operand" "rM")])
1033 (match_operand:SI 1 "s_register_operand" "r"))
1034 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))]
25f905c2 1035 "TARGET_32BIT"
080c0b9a 1036 "adc%?\\t%0, %1, %3%S2"
1037 [(set_attr "conds" "use")
a7de272d 1038 (set_attr "predicable" "yes")
7c36fe71 1039 (set_attr "predicable_short_it" "no")
080c0b9a 1040 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
d82e788e 1041 (const_string "alu_shift_imm")
1042 (const_string "alu_shift_reg")))]
cffb2a26 1043)
ebcc79bc 1044
922b6913 1045(define_insn "*addsi3_carryin_clobercc_<optab>"
1046 [(set (match_operand:SI 0 "s_register_operand" "=r")
1047 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%r")
1048 (match_operand:SI 2 "arm_rhs_operand" "rI"))
1049 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))
1050 (clobber (reg:CC CC_REGNUM))]
1051 "TARGET_32BIT"
3ef90e77 1052 "adcs%?\\t%0, %1, %2"
1b7da4ac 1053 [(set_attr "conds" "set")
1054 (set_attr "type" "adcs_reg")]
922b6913 1055)
1056
f6c98a9a 1057(define_expand "subv<mode>4"
1058 [(match_operand:SIDI 0 "register_operand")
1059 (match_operand:SIDI 1 "register_operand")
1060 (match_operand:SIDI 2 "register_operand")
1061 (match_operand 3 "")]
1062 "TARGET_32BIT"
1063{
1064 emit_insn (gen_sub<mode>3_compare1 (operands[0], operands[1], operands[2]));
1065 arm_gen_unlikely_cbranch (NE, CC_Vmode, operands[3]);
1066
1067 DONE;
1068})
1069
1070(define_expand "usubv<mode>4"
1071 [(match_operand:SIDI 0 "register_operand")
1072 (match_operand:SIDI 1 "register_operand")
1073 (match_operand:SIDI 2 "register_operand")
1074 (match_operand 3 "")]
1075 "TARGET_32BIT"
1076{
1077 emit_insn (gen_sub<mode>3_compare1 (operands[0], operands[1], operands[2]));
1078 arm_gen_unlikely_cbranch (LTU, CCmode, operands[3]);
1079
1080 DONE;
1081})
1082
1083(define_insn_and_split "subdi3_compare1"
1084 [(set (reg:CC CC_REGNUM)
1085 (compare:CC
1086 (match_operand:DI 1 "register_operand" "r")
1087 (match_operand:DI 2 "register_operand" "r")))
1088 (set (match_operand:DI 0 "register_operand" "=&r")
1089 (minus:DI (match_dup 1) (match_dup 2)))]
1090 "TARGET_32BIT"
1091 "#"
1092 "&& reload_completed"
1093 [(parallel [(set (reg:CC CC_REGNUM)
1094 (compare:CC (match_dup 1) (match_dup 2)))
1095 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1096 (parallel [(set (reg:CC CC_REGNUM)
1097 (compare:CC (match_dup 4) (match_dup 5)))
1098 (set (match_dup 3) (minus:SI (minus:SI (match_dup 4) (match_dup 5))
1099 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))])]
1100 {
1101 operands[3] = gen_highpart (SImode, operands[0]);
1102 operands[0] = gen_lowpart (SImode, operands[0]);
1103 operands[4] = gen_highpart (SImode, operands[1]);
1104 operands[1] = gen_lowpart (SImode, operands[1]);
1105 operands[5] = gen_highpart (SImode, operands[2]);
1106 operands[2] = gen_lowpart (SImode, operands[2]);
1107 }
1108 [(set_attr "conds" "set")
1109 (set_attr "length" "8")
1110 (set_attr "type" "multiple")]
1111)
1112
1113(define_insn "subsi3_compare1"
1114 [(set (reg:CC CC_REGNUM)
1115 (compare:CC
1116 (match_operand:SI 1 "register_operand" "r")
1117 (match_operand:SI 2 "register_operand" "r")))
1118 (set (match_operand:SI 0 "register_operand" "=r")
1119 (minus:SI (match_dup 1) (match_dup 2)))]
1120 "TARGET_32BIT"
1121 "subs%?\\t%0, %1, %2"
1122 [(set_attr "conds" "set")
1123 (set_attr "type" "alus_sreg")]
1124)
1125
9154bd82 1126(define_insn "*subsi3_carryin"
d5bf2b53 1127 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1128 (minus:SI (minus:SI (match_operand:SI 1 "reg_or_int_operand" "r,I,Pz")
1129 (match_operand:SI 2 "s_register_operand" "r,r,r"))
1130 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
9154bd82 1131 "TARGET_32BIT"
1132 "@
1133 sbc%?\\t%0, %1, %2
d5bf2b53 1134 rsc%?\\t%0, %2, %1
1135 sbc%?\\t%0, %2, %2, lsl #1"
9154bd82 1136 [(set_attr "conds" "use")
d5bf2b53 1137 (set_attr "arch" "*,a,t2")
7c36fe71 1138 (set_attr "predicable" "yes")
1b7da4ac 1139 (set_attr "predicable_short_it" "no")
d5bf2b53 1140 (set_attr "type" "adc_reg,adc_imm,alu_shift_imm")]
9154bd82 1141)
1142
1143(define_insn "*subsi3_carryin_const"
1144 [(set (match_operand:SI 0 "s_register_operand" "=r")
df46fd5e 1145 (minus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1146 (match_operand:SI 2 "arm_not_immediate_operand" "K"))
9154bd82 1147 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1148 "TARGET_32BIT"
1149 "sbc\\t%0, %1, #%B2"
1b7da4ac 1150 [(set_attr "conds" "use")
1151 (set_attr "type" "adc_imm")]
9154bd82 1152)
1153
1154(define_insn "*subsi3_carryin_compare"
1155 [(set (reg:CC CC_REGNUM)
1156 (compare:CC (match_operand:SI 1 "s_register_operand" "r")
1157 (match_operand:SI 2 "s_register_operand" "r")))
1158 (set (match_operand:SI 0 "s_register_operand" "=r")
1159 (minus:SI (minus:SI (match_dup 1)
1160 (match_dup 2))
1161 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1162 "TARGET_32BIT"
1163 "sbcs\\t%0, %1, %2"
1b7da4ac 1164 [(set_attr "conds" "set")
1165 (set_attr "type" "adcs_reg")]
9154bd82 1166)
1167
1168(define_insn "*subsi3_carryin_compare_const"
1169 [(set (reg:CC CC_REGNUM)
1170 (compare:CC (match_operand:SI 1 "reg_or_int_operand" "r")
1171 (match_operand:SI 2 "arm_not_operand" "K")))
1172 (set (match_operand:SI 0 "s_register_operand" "=r")
1173 (minus:SI (plus:SI (match_dup 1)
1174 (match_dup 2))
1175 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1176 "TARGET_32BIT"
1177 "sbcs\\t%0, %1, #%B2"
1b7da4ac 1178 [(set_attr "conds" "set")
1179 (set_attr "type" "adcs_imm")]
9154bd82 1180)
1181
1182(define_insn "*subsi3_carryin_shift"
1183 [(set (match_operand:SI 0 "s_register_operand" "=r")
1184 (minus:SI (minus:SI
1185 (match_operand:SI 1 "s_register_operand" "r")
1186 (match_operator:SI 2 "shift_operator"
1187 [(match_operand:SI 3 "s_register_operand" "r")
1188 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
1189 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1190 "TARGET_32BIT"
1191 "sbc%?\\t%0, %1, %3%S2"
1192 [(set_attr "conds" "use")
1193 (set_attr "predicable" "yes")
1194 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
d82e788e 1195 (const_string "alu_shift_imm")
1196 (const_string "alu_shift_reg")))]
9154bd82 1197)
1198
1199(define_insn "*rsbsi3_carryin_shift"
1200 [(set (match_operand:SI 0 "s_register_operand" "=r")
1201 (minus:SI (minus:SI
1202 (match_operator:SI 2 "shift_operator"
1203 [(match_operand:SI 3 "s_register_operand" "r")
1204 (match_operand:SI 4 "reg_or_int_operand" "rM")])
1205 (match_operand:SI 1 "s_register_operand" "r"))
1206 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1207 "TARGET_ARM"
1208 "rsc%?\\t%0, %1, %3%S2"
1209 [(set_attr "conds" "use")
1210 (set_attr "predicable" "yes")
1211 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
d82e788e 1212 (const_string "alu_shift_imm")
1213 (const_string "alu_shift_reg")))]
9154bd82 1214)
1215
d795fb69 1216; transform ((x << y) - 1) to ~(~(x-1) << y) Where X is a constant.
1217(define_split
1218 [(set (match_operand:SI 0 "s_register_operand" "")
1219 (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
1220 (match_operand:SI 2 "s_register_operand" ""))
1221 (const_int -1)))
1222 (clobber (match_operand:SI 3 "s_register_operand" ""))]
25f905c2 1223 "TARGET_32BIT"
d795fb69 1224 [(set (match_dup 3) (match_dup 1))
1225 (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
1226 "
1227 operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
1228")
1229
604f3a0a 1230(define_expand "addsf3"
1231 [(set (match_operand:SF 0 "s_register_operand" "")
1232 (plus:SF (match_operand:SF 1 "s_register_operand" "")
d86c91f6 1233 (match_operand:SF 2 "s_register_operand" "")))]
25f905c2 1234 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1235 "
604f3a0a 1236")
1237
604f3a0a 1238(define_expand "adddf3"
1239 [(set (match_operand:DF 0 "s_register_operand" "")
1240 (plus:DF (match_operand:DF 1 "s_register_operand" "")
d86c91f6 1241 (match_operand:DF 2 "s_register_operand" "")))]
a50d7267 1242 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 1243 "
604f3a0a 1244")
1245
cffb2a26 1246(define_expand "subdi3"
1247 [(parallel
1248 [(set (match_operand:DI 0 "s_register_operand" "")
1249 (minus:DI (match_operand:DI 1 "s_register_operand" "")
1250 (match_operand:DI 2 "s_register_operand" "")))
bd5b4116 1251 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 1252 "TARGET_EITHER"
1253 "
25f905c2 1254 if (TARGET_THUMB1)
cffb2a26 1255 {
0438d37f 1256 if (!REG_P (operands[1]))
5aa8c5f0 1257 operands[1] = force_reg (DImode, operands[1]);
0438d37f 1258 if (!REG_P (operands[2]))
5aa8c5f0 1259 operands[2] = force_reg (DImode, operands[2]);
cffb2a26 1260 }
1261 "
1262)
1263
2f9b23e3 1264(define_insn_and_split "*arm_subdi3"
206f0a3f 1265 [(set (match_operand:DI 0 "arm_general_register_operand" "=&r,&r,&r")
1266 (minus:DI (match_operand:DI 1 "arm_general_register_operand" "0,r,0")
1267 (match_operand:DI 2 "arm_general_register_operand" "r,0,0")))
bd5b4116 1268 (clobber (reg:CC CC_REGNUM))]
94829feb 1269 "TARGET_32BIT && !TARGET_NEON"
2f9b23e3 1270 "#" ; "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
0d84c6e5 1271 "&& (!TARGET_IWMMXT || reload_completed)"
2f9b23e3 1272 [(parallel [(set (reg:CC CC_REGNUM)
1273 (compare:CC (match_dup 1) (match_dup 2)))
1274 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1275 (set (match_dup 3) (minus:SI (minus:SI (match_dup 4) (match_dup 5))
1276 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1277 {
1278 operands[3] = gen_highpart (SImode, operands[0]);
1279 operands[0] = gen_lowpart (SImode, operands[0]);
1280 operands[4] = gen_highpart (SImode, operands[1]);
1281 operands[1] = gen_lowpart (SImode, operands[1]);
1282 operands[5] = gen_highpart (SImode, operands[2]);
1283 operands[2] = gen_lowpart (SImode, operands[2]);
1284 }
cffb2a26 1285 [(set_attr "conds" "clob")
1b7da4ac 1286 (set_attr "length" "8")
1287 (set_attr "type" "multiple")]
cffb2a26 1288)
1289
2f9b23e3 1290(define_insn_and_split "*subdi_di_zesidi"
cffb2a26 1291 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 1292 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r")
9c08d1fa 1293 (zero_extend:DI
cffb2a26 1294 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 1295 (clobber (reg:CC CC_REGNUM))]
25f905c2 1296 "TARGET_32BIT"
2f9b23e3 1297 "#" ; "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
1298 "&& reload_completed"
1299 [(parallel [(set (reg:CC CC_REGNUM)
1300 (compare:CC (match_dup 1) (match_dup 2)))
1301 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1302 (set (match_dup 3) (minus:SI (plus:SI (match_dup 4) (match_dup 5))
1303 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1304 {
1305 operands[3] = gen_highpart (SImode, operands[0]);
1306 operands[0] = gen_lowpart (SImode, operands[0]);
1307 operands[4] = gen_highpart (SImode, operands[1]);
1308 operands[1] = gen_lowpart (SImode, operands[1]);
1309 operands[5] = GEN_INT (~0);
1310 }
cffb2a26 1311 [(set_attr "conds" "clob")
1b7da4ac 1312 (set_attr "length" "8")
1313 (set_attr "type" "multiple")]
cffb2a26 1314)
9c08d1fa 1315
2f9b23e3 1316(define_insn_and_split "*subdi_di_sesidi"
cffb2a26 1317 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 1318 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r")
9c08d1fa 1319 (sign_extend:DI
cffb2a26 1320 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 1321 (clobber (reg:CC CC_REGNUM))]
25f905c2 1322 "TARGET_32BIT"
2f9b23e3 1323 "#" ; "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
1324 "&& reload_completed"
1325 [(parallel [(set (reg:CC CC_REGNUM)
1326 (compare:CC (match_dup 1) (match_dup 2)))
1327 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1328 (set (match_dup 3) (minus:SI (minus:SI (match_dup 4)
1329 (ashiftrt:SI (match_dup 2)
1330 (const_int 31)))
1331 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1332 {
1333 operands[3] = gen_highpart (SImode, operands[0]);
1334 operands[0] = gen_lowpart (SImode, operands[0]);
1335 operands[4] = gen_highpart (SImode, operands[1]);
1336 operands[1] = gen_lowpart (SImode, operands[1]);
1337 }
cffb2a26 1338 [(set_attr "conds" "clob")
1b7da4ac 1339 (set_attr "length" "8")
1340 (set_attr "type" "multiple")]
cffb2a26 1341)
9c08d1fa 1342
2f9b23e3 1343(define_insn_and_split "*subdi_zesidi_di"
cffb2a26 1344 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1345 (minus:DI (zero_extend:DI
cffb2a26 1346 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 1347 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 1348 (clobber (reg:CC CC_REGNUM))]
cffb2a26 1349 "TARGET_ARM"
2f9b23e3 1350 "#" ; "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
1351 ; is equivalent to:
1352 ; "subs\\t%Q0, %2, %Q1\;rsc\\t%R0, %R1, #0"
1353 "&& reload_completed"
1354 [(parallel [(set (reg:CC CC_REGNUM)
1355 (compare:CC (match_dup 2) (match_dup 1)))
1356 (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))])
1357 (set (match_dup 3) (minus:SI (minus:SI (const_int 0) (match_dup 4))
1358 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1359 {
1360 operands[3] = gen_highpart (SImode, operands[0]);
1361 operands[0] = gen_lowpart (SImode, operands[0]);
1362 operands[4] = gen_highpart (SImode, operands[1]);
1363 operands[1] = gen_lowpart (SImode, operands[1]);
1364 }
cffb2a26 1365 [(set_attr "conds" "clob")
1b7da4ac 1366 (set_attr "length" "8")
1367 (set_attr "type" "multiple")]
cffb2a26 1368)
9c08d1fa 1369
2f9b23e3 1370(define_insn_and_split "*subdi_sesidi_di"
cffb2a26 1371 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1372 (minus:DI (sign_extend:DI
cffb2a26 1373 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 1374 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 1375 (clobber (reg:CC CC_REGNUM))]
cffb2a26 1376 "TARGET_ARM"
2f9b23e3 1377 "#" ; "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
1378 ; is equivalent to:
1379 ; "subs\\t%Q0, %2, %Q1\;rsc\\t%R0, %R1, %2, asr #31"
1380 "&& reload_completed"
1381 [(parallel [(set (reg:CC CC_REGNUM)
1382 (compare:CC (match_dup 2) (match_dup 1)))
1383 (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))])
1384 (set (match_dup 3) (minus:SI (minus:SI
1385 (ashiftrt:SI (match_dup 2)
1386 (const_int 31))
1387 (match_dup 4))
1388 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1389 {
1390 operands[3] = gen_highpart (SImode, operands[0]);
1391 operands[0] = gen_lowpart (SImode, operands[0]);
1392 operands[4] = gen_highpart (SImode, operands[1]);
1393 operands[1] = gen_lowpart (SImode, operands[1]);
1394 }
cffb2a26 1395 [(set_attr "conds" "clob")
1b7da4ac 1396 (set_attr "length" "8")
1397 (set_attr "type" "multiple")]
cffb2a26 1398)
9c08d1fa 1399
2f9b23e3 1400(define_insn_and_split "*subdi_zesidi_zesidi"
cffb2a26 1401 [(set (match_operand:DI 0 "s_register_operand" "=r")
9c08d1fa 1402 (minus:DI (zero_extend:DI
cffb2a26 1403 (match_operand:SI 1 "s_register_operand" "r"))
9c08d1fa 1404 (zero_extend:DI
cffb2a26 1405 (match_operand:SI 2 "s_register_operand" "r"))))
bd5b4116 1406 (clobber (reg:CC CC_REGNUM))]
25f905c2 1407 "TARGET_32BIT"
2f9b23e3 1408 "#" ; "subs\\t%Q0, %1, %2\;sbc\\t%R0, %1, %1"
1409 "&& reload_completed"
1410 [(parallel [(set (reg:CC CC_REGNUM)
1411 (compare:CC (match_dup 1) (match_dup 2)))
1412 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1413 (set (match_dup 3) (minus:SI (minus:SI (match_dup 1) (match_dup 1))
1414 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1415 {
1416 operands[3] = gen_highpart (SImode, operands[0]);
1417 operands[0] = gen_lowpart (SImode, operands[0]);
1418 }
cffb2a26 1419 [(set_attr "conds" "clob")
1b7da4ac 1420 (set_attr "length" "8")
1421 (set_attr "type" "multiple")]
cffb2a26 1422)
b11cae9e 1423
87b22bf7 1424(define_expand "subsi3"
cffb2a26 1425 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 1426 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
1427 (match_operand:SI 2 "s_register_operand" "")))]
cffb2a26 1428 "TARGET_EITHER"
87b22bf7 1429 "
0438d37f 1430 if (CONST_INT_P (operands[1]))
87b22bf7 1431 {
25f905c2 1432 if (TARGET_32BIT)
cffb2a26 1433 {
17202aa5 1434 if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[1]), MINUS))
1435 operands[1] = force_reg (SImode, operands[1]);
1436 else
1437 {
1438 arm_split_constant (MINUS, SImode, NULL_RTX,
1439 INTVAL (operands[1]), operands[0],
1440 operands[2],
1441 optimize && can_create_pseudo_p ());
1442 DONE;
1443 }
cffb2a26 1444 }
25f905c2 1445 else /* TARGET_THUMB1 */
cffb2a26 1446 operands[1] = force_reg (SImode, operands[1]);
87b22bf7 1447 }
cffb2a26 1448 "
1449)
87b22bf7 1450
25f905c2 1451; ??? Check Thumb-2 split length
a0f94409 1452(define_insn_and_split "*arm_subsi3_insn"
3a44c5a9 1453 [(set (match_operand:SI 0 "s_register_operand" "=l,l ,l ,l ,r,r,r,rk,r")
1454 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "l ,0 ,l ,Pz,I,r,r,k ,?n")
1455 (match_operand:SI 2 "reg_or_int_operand" "l ,Py,Pd,l ,r,I,r,r ,r")))]
25f905c2 1456 "TARGET_32BIT"
e2348bcb 1457 "@
7c36fe71 1458 sub%?\\t%0, %1, %2
1459 sub%?\\t%0, %2
1460 sub%?\\t%0, %1, %2
1461 rsb%?\\t%0, %2, %1
87b22bf7 1462 rsb%?\\t%0, %2, %1
aaa37ad6 1463 sub%?\\t%0, %1, %2
080c0b9a 1464 sub%?\\t%0, %1, %2
65f68e55 1465 sub%?\\t%0, %1, %2
87b22bf7 1466 #"
0438d37f 1467 "&& (CONST_INT_P (operands[1])
91a5e339 1468 && !const_ok_for_arm (INTVAL (operands[1])))"
87b22bf7 1469 [(clobber (const_int 0))]
1470 "
96f57e36 1471 arm_split_constant (MINUS, SImode, curr_insn,
1472 INTVAL (operands[1]), operands[0], operands[2], 0);
87b22bf7 1473 DONE;
cffb2a26 1474 "
7c36fe71 1475 [(set_attr "length" "4,4,4,4,4,4,4,4,16")
1476 (set_attr "arch" "t2,t2,t2,t2,*,*,*,*,*")
65f68e55 1477 (set_attr "predicable" "yes")
7c36fe71 1478 (set_attr "predicable_short_it" "yes,yes,yes,yes,no,no,no,no,no")
112eda6f 1479 (set_attr "type" "alu_sreg,alu_sreg,alu_sreg,alu_sreg,alu_imm,alu_imm,alu_sreg,alu_sreg,multiple")]
a0f94409 1480)
1481
1482(define_peephole2
1483 [(match_scratch:SI 3 "r")
372575c7 1484 (set (match_operand:SI 0 "arm_general_register_operand" "")
a0f94409 1485 (minus:SI (match_operand:SI 1 "const_int_operand" "")
372575c7 1486 (match_operand:SI 2 "arm_general_register_operand" "")))]
25f905c2 1487 "TARGET_32BIT
a0f94409 1488 && !const_ok_for_arm (INTVAL (operands[1]))
1489 && const_ok_for_arm (~INTVAL (operands[1]))"
1490 [(set (match_dup 3) (match_dup 1))
1491 (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1492 ""
cffb2a26 1493)
b11cae9e 1494
62e39b06 1495(define_insn "subsi3_compare0"
bd5b4116 1496 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1497 (compare:CC_NOOV
65f68e55 1498 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,r,I")
1499 (match_operand:SI 2 "arm_rhs_operand" "I,r,r"))
215b30b3 1500 (const_int 0)))
65f68e55 1501 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9c08d1fa 1502 (minus:SI (match_dup 1) (match_dup 2)))]
25f905c2 1503 "TARGET_32BIT"
e2348bcb 1504 "@
3ef90e77 1505 subs%?\\t%0, %1, %2
1506 subs%?\\t%0, %1, %2
1507 rsbs%?\\t%0, %2, %1"
65f68e55 1508 [(set_attr "conds" "set")
112eda6f 1509 (set_attr "type" "alus_imm,alus_sreg,alus_sreg")]
cffb2a26 1510)
9c08d1fa 1511
190efb17 1512(define_insn "subsi3_compare"
080c0b9a 1513 [(set (reg:CC CC_REGNUM)
65f68e55 1514 (compare:CC (match_operand:SI 1 "arm_rhs_operand" "r,r,I")
1515 (match_operand:SI 2 "arm_rhs_operand" "I,r,r")))
1516 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2df9477b 1517 (minus:SI (match_dup 1) (match_dup 2)))]
1518 "TARGET_32BIT"
1519 "@
3ef90e77 1520 subs%?\\t%0, %1, %2
1521 subs%?\\t%0, %1, %2
1522 rsbs%?\\t%0, %2, %1"
65f68e55 1523 [(set_attr "conds" "set")
112eda6f 1524 (set_attr "type" "alus_imm,alus_sreg,alus_sreg")]
2df9477b 1525)
1526
604f3a0a 1527(define_expand "subsf3"
1528 [(set (match_operand:SF 0 "s_register_operand" "")
d86c91f6 1529 (minus:SF (match_operand:SF 1 "s_register_operand" "")
1530 (match_operand:SF 2 "s_register_operand" "")))]
25f905c2 1531 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1532 "
604f3a0a 1533")
1534
604f3a0a 1535(define_expand "subdf3"
1536 [(set (match_operand:DF 0 "s_register_operand" "")
d86c91f6 1537 (minus:DF (match_operand:DF 1 "s_register_operand" "")
1538 (match_operand:DF 2 "s_register_operand" "")))]
a50d7267 1539 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 1540 "
604f3a0a 1541")
1542
b11cae9e 1543\f
1544;; Multiplication insns
1545
4422d91f 1546(define_expand "mulhi3"
1547 [(set (match_operand:HI 0 "s_register_operand" "")
1548 (mult:HI (match_operand:HI 1 "s_register_operand" "")
1549 (match_operand:HI 2 "s_register_operand" "")))]
1550 "TARGET_DSP_MULTIPLY"
1551 "
1552 {
1553 rtx result = gen_reg_rtx (SImode);
1554 emit_insn (gen_mulhisi3 (result, operands[1], operands[2]));
1555 emit_move_insn (operands[0], gen_lowpart (HImode, result));
1556 DONE;
1557 }"
1558)
1559
cffb2a26 1560(define_expand "mulsi3"
1561 [(set (match_operand:SI 0 "s_register_operand" "")
1562 (mult:SI (match_operand:SI 2 "s_register_operand" "")
1563 (match_operand:SI 1 "s_register_operand" "")))]
1564 "TARGET_EITHER"
1565 ""
1566)
1567
9c08d1fa 1568;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
cffb2a26 1569(define_insn "*arm_mulsi3"
1570 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1571 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1572 (match_operand:SI 1 "s_register_operand" "%0,r")))]
58d7d654 1573 "TARGET_32BIT && !arm_arch6"
f7fbdd4a 1574 "mul%?\\t%0, %2, %1"
9da0ec36 1575 [(set_attr "type" "mul")
0d66636f 1576 (set_attr "predicable" "yes")]
cffb2a26 1577)
1578
58d7d654 1579(define_insn "*arm_mulsi3_v6"
d952d547 1580 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
1581 (mult:SI (match_operand:SI 1 "s_register_operand" "0,l,r")
1582 (match_operand:SI 2 "s_register_operand" "l,0,r")))]
58d7d654 1583 "TARGET_32BIT && arm_arch6"
1584 "mul%?\\t%0, %1, %2"
9da0ec36 1585 [(set_attr "type" "mul")
d952d547 1586 (set_attr "predicable" "yes")
1587 (set_attr "arch" "t2,t2,*")
1588 (set_attr "length" "4")
1589 (set_attr "predicable_short_it" "yes,yes,no")]
58d7d654 1590)
1591
f7fbdd4a 1592(define_insn "*mulsi3_compare0"
bd5b4116 1593 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1594 (compare:CC_NOOV (mult:SI
1595 (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1596 (match_operand:SI 1 "s_register_operand" "%0,r"))
9c08d1fa 1597 (const_int 0)))
1598 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1599 (mult:SI (match_dup 2) (match_dup 1)))]
58d7d654 1600 "TARGET_ARM && !arm_arch6"
3ef90e77 1601 "muls%?\\t%0, %2, %1"
58d7d654 1602 [(set_attr "conds" "set")
9da0ec36 1603 (set_attr "type" "muls")]
58d7d654 1604)
1605
1606(define_insn "*mulsi3_compare0_v6"
1607 [(set (reg:CC_NOOV CC_REGNUM)
1608 (compare:CC_NOOV (mult:SI
1609 (match_operand:SI 2 "s_register_operand" "r")
1610 (match_operand:SI 1 "s_register_operand" "r"))
1611 (const_int 0)))
1612 (set (match_operand:SI 0 "s_register_operand" "=r")
1613 (mult:SI (match_dup 2) (match_dup 1)))]
1614 "TARGET_ARM && arm_arch6 && optimize_size"
3ef90e77 1615 "muls%?\\t%0, %2, %1"
cffb2a26 1616 [(set_attr "conds" "set")
9da0ec36 1617 (set_attr "type" "muls")]
cffb2a26 1618)
9c08d1fa 1619
f7fbdd4a 1620(define_insn "*mulsi_compare0_scratch"
bd5b4116 1621 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1622 (compare:CC_NOOV (mult:SI
1623 (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1624 (match_operand:SI 1 "s_register_operand" "%0,r"))
9c08d1fa 1625 (const_int 0)))
1626 (clobber (match_scratch:SI 0 "=&r,&r"))]
58d7d654 1627 "TARGET_ARM && !arm_arch6"
3ef90e77 1628 "muls%?\\t%0, %2, %1"
58d7d654 1629 [(set_attr "conds" "set")
9da0ec36 1630 (set_attr "type" "muls")]
58d7d654 1631)
1632
1633(define_insn "*mulsi_compare0_scratch_v6"
1634 [(set (reg:CC_NOOV CC_REGNUM)
1635 (compare:CC_NOOV (mult:SI
1636 (match_operand:SI 2 "s_register_operand" "r")
1637 (match_operand:SI 1 "s_register_operand" "r"))
1638 (const_int 0)))
1639 (clobber (match_scratch:SI 0 "=r"))]
1640 "TARGET_ARM && arm_arch6 && optimize_size"
3ef90e77 1641 "muls%?\\t%0, %2, %1"
cffb2a26 1642 [(set_attr "conds" "set")
9da0ec36 1643 (set_attr "type" "muls")]
cffb2a26 1644)
9c08d1fa 1645
b11cae9e 1646;; Unnamed templates to match MLA instruction.
1647
f7fbdd4a 1648(define_insn "*mulsi3addsi"
9c08d1fa 1649 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
c8f69309 1650 (plus:SI
9c08d1fa 1651 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1652 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1653 (match_operand:SI 3 "s_register_operand" "r,r,0,0")))]
58d7d654 1654 "TARGET_32BIT && !arm_arch6"
1655 "mla%?\\t%0, %2, %1, %3"
9da0ec36 1656 [(set_attr "type" "mla")
58d7d654 1657 (set_attr "predicable" "yes")]
1658)
1659
1660(define_insn "*mulsi3addsi_v6"
1661 [(set (match_operand:SI 0 "s_register_operand" "=r")
1662 (plus:SI
1663 (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1664 (match_operand:SI 1 "s_register_operand" "r"))
1665 (match_operand:SI 3 "s_register_operand" "r")))]
1666 "TARGET_32BIT && arm_arch6"
f7fbdd4a 1667 "mla%?\\t%0, %2, %1, %3"
9da0ec36 1668 [(set_attr "type" "mla")
d952d547 1669 (set_attr "predicable" "yes")
1670 (set_attr "predicable_short_it" "no")]
0d66636f 1671)
b11cae9e 1672
f7fbdd4a 1673(define_insn "*mulsi3addsi_compare0"
bd5b4116 1674 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1675 (compare:CC_NOOV
1676 (plus:SI (mult:SI
1677 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1678 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1679 (match_operand:SI 3 "s_register_operand" "r,r,0,0"))
215b30b3 1680 (const_int 0)))
9c08d1fa 1681 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1682 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1683 (match_dup 3)))]
58d7d654 1684 "TARGET_ARM && arm_arch6"
3ef90e77 1685 "mlas%?\\t%0, %2, %1, %3"
58d7d654 1686 [(set_attr "conds" "set")
9da0ec36 1687 (set_attr "type" "mlas")]
58d7d654 1688)
1689
1690(define_insn "*mulsi3addsi_compare0_v6"
1691 [(set (reg:CC_NOOV CC_REGNUM)
1692 (compare:CC_NOOV
1693 (plus:SI (mult:SI
1694 (match_operand:SI 2 "s_register_operand" "r")
1695 (match_operand:SI 1 "s_register_operand" "r"))
1696 (match_operand:SI 3 "s_register_operand" "r"))
1697 (const_int 0)))
1698 (set (match_operand:SI 0 "s_register_operand" "=r")
1699 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1700 (match_dup 3)))]
1701 "TARGET_ARM && arm_arch6 && optimize_size"
3ef90e77 1702 "mlas%?\\t%0, %2, %1, %3"
0d66636f 1703 [(set_attr "conds" "set")
9da0ec36 1704 (set_attr "type" "mlas")]
0d66636f 1705)
9c08d1fa 1706
f7fbdd4a 1707(define_insn "*mulsi3addsi_compare0_scratch"
bd5b4116 1708 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1709 (compare:CC_NOOV
1710 (plus:SI (mult:SI
1711 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1712 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
215b30b3 1713 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1714 (const_int 0)))
9c08d1fa 1715 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
58d7d654 1716 "TARGET_ARM && !arm_arch6"
3ef90e77 1717 "mlas%?\\t%0, %2, %1, %3"
58d7d654 1718 [(set_attr "conds" "set")
9da0ec36 1719 (set_attr "type" "mlas")]
58d7d654 1720)
1721
1722(define_insn "*mulsi3addsi_compare0_scratch_v6"
1723 [(set (reg:CC_NOOV CC_REGNUM)
1724 (compare:CC_NOOV
1725 (plus:SI (mult:SI
1726 (match_operand:SI 2 "s_register_operand" "r")
1727 (match_operand:SI 1 "s_register_operand" "r"))
1728 (match_operand:SI 3 "s_register_operand" "r"))
1729 (const_int 0)))
1730 (clobber (match_scratch:SI 0 "=r"))]
1731 "TARGET_ARM && arm_arch6 && optimize_size"
3ef90e77 1732 "mlas%?\\t%0, %2, %1, %3"
cffb2a26 1733 [(set_attr "conds" "set")
9da0ec36 1734 (set_attr "type" "mlas")]
cffb2a26 1735)
f7fbdd4a 1736
89545238 1737(define_insn "*mulsi3subsi"
1738 [(set (match_operand:SI 0 "s_register_operand" "=r")
1739 (minus:SI
1740 (match_operand:SI 3 "s_register_operand" "r")
1741 (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1742 (match_operand:SI 1 "s_register_operand" "r"))))]
1743 "TARGET_32BIT && arm_arch_thumb2"
1744 "mls%?\\t%0, %2, %1, %3"
9da0ec36 1745 [(set_attr "type" "mla")
d952d547 1746 (set_attr "predicable" "yes")
1747 (set_attr "predicable_short_it" "no")]
89545238 1748)
1749
5cdca009 1750(define_expand "maddsidi4"
1751 [(set (match_operand:DI 0 "s_register_operand" "")
1752 (plus:DI
1753 (mult:DI
1754 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1755 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1756 (match_operand:DI 3 "s_register_operand" "")))]
1757 "TARGET_32BIT && arm_arch3m"
1758 "")
82b85d08 1759
1760(define_insn "*mulsidi3adddi"
fe8dbf85 1761 [(set (match_operand:DI 0 "s_register_operand" "=&r")
82b85d08 1762 (plus:DI
215b30b3 1763 (mult:DI
fe8dbf85 1764 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1765 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1766 (match_operand:DI 1 "s_register_operand" "0")))]
58d7d654 1767 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1768 "smlal%?\\t%Q0, %R0, %3, %2"
9da0ec36 1769 [(set_attr "type" "smlal")
58d7d654 1770 (set_attr "predicable" "yes")]
1771)
1772
1773(define_insn "*mulsidi3adddi_v6"
1774 [(set (match_operand:DI 0 "s_register_operand" "=r")
1775 (plus:DI
1776 (mult:DI
1777 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1778 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1779 (match_operand:DI 1 "s_register_operand" "0")))]
1780 "TARGET_32BIT && arm_arch6"
fe8dbf85 1781 "smlal%?\\t%Q0, %R0, %3, %2"
9da0ec36 1782 [(set_attr "type" "smlal")
d952d547 1783 (set_attr "predicable" "yes")
1784 (set_attr "predicable_short_it" "no")]
0d66636f 1785)
82b85d08 1786
957788b0 1787;; 32x32->64 widening multiply.
1788;; As with mulsi3, the only difference between the v3-5 and v6+
1789;; versions of these patterns is the requirement that the output not
1790;; overlap the inputs, but that still means we have to have a named
1791;; expander and two different starred insns.
1792
1793(define_expand "mulsidi3"
1794 [(set (match_operand:DI 0 "s_register_operand" "")
1795 (mult:DI
1796 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1797 (sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1798 "TARGET_32BIT && arm_arch3m"
1799 ""
1800)
1801
1802(define_insn "*mulsidi3_nov6"
f7fbdd4a 1803 [(set (match_operand:DI 0 "s_register_operand" "=&r")
215b30b3 1804 (mult:DI
1805 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1806 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
58d7d654 1807 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1808 "smull%?\\t%Q0, %R0, %1, %2"
9da0ec36 1809 [(set_attr "type" "smull")
58d7d654 1810 (set_attr "predicable" "yes")]
1811)
1812
957788b0 1813(define_insn "*mulsidi3_v6"
58d7d654 1814 [(set (match_operand:DI 0 "s_register_operand" "=r")
1815 (mult:DI
1816 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1817 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1818 "TARGET_32BIT && arm_arch6"
97499065 1819 "smull%?\\t%Q0, %R0, %1, %2"
9da0ec36 1820 [(set_attr "type" "smull")
d952d547 1821 (set_attr "predicable" "yes")
1822 (set_attr "predicable_short_it" "no")]
0d66636f 1823)
f7fbdd4a 1824
957788b0 1825(define_expand "umulsidi3"
1826 [(set (match_operand:DI 0 "s_register_operand" "")
1827 (mult:DI
1828 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1829 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1830 "TARGET_32BIT && arm_arch3m"
1831 ""
1832)
1833
1834(define_insn "*umulsidi3_nov6"
f7fbdd4a 1835 [(set (match_operand:DI 0 "s_register_operand" "=&r")
215b30b3 1836 (mult:DI
1837 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1838 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
58d7d654 1839 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1840 "umull%?\\t%Q0, %R0, %1, %2"
9da0ec36 1841 [(set_attr "type" "umull")
58d7d654 1842 (set_attr "predicable" "yes")]
1843)
1844
957788b0 1845(define_insn "*umulsidi3_v6"
58d7d654 1846 [(set (match_operand:DI 0 "s_register_operand" "=r")
1847 (mult:DI
1848 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1849 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1850 "TARGET_32BIT && arm_arch6"
97499065 1851 "umull%?\\t%Q0, %R0, %1, %2"
9da0ec36 1852 [(set_attr "type" "umull")
d952d547 1853 (set_attr "predicable" "yes")
1854 (set_attr "predicable_short_it" "no")]
0d66636f 1855)
b11cae9e 1856
5cdca009 1857(define_expand "umaddsidi4"
1858 [(set (match_operand:DI 0 "s_register_operand" "")
1859 (plus:DI
1860 (mult:DI
1861 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1862 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1863 (match_operand:DI 3 "s_register_operand" "")))]
1864 "TARGET_32BIT && arm_arch3m"
1865 "")
82b85d08 1866
1867(define_insn "*umulsidi3adddi"
8ead09f9 1868 [(set (match_operand:DI 0 "s_register_operand" "=&r")
82b85d08 1869 (plus:DI
215b30b3 1870 (mult:DI
fe8dbf85 1871 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1872 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1873 (match_operand:DI 1 "s_register_operand" "0")))]
58d7d654 1874 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1875 "umlal%?\\t%Q0, %R0, %3, %2"
9da0ec36 1876 [(set_attr "type" "umlal")
58d7d654 1877 (set_attr "predicable" "yes")]
1878)
1879
1880(define_insn "*umulsidi3adddi_v6"
1881 [(set (match_operand:DI 0 "s_register_operand" "=r")
1882 (plus:DI
1883 (mult:DI
1884 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1885 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1886 (match_operand:DI 1 "s_register_operand" "0")))]
1887 "TARGET_32BIT && arm_arch6"
fe8dbf85 1888 "umlal%?\\t%Q0, %R0, %3, %2"
9da0ec36 1889 [(set_attr "type" "umlal")
d952d547 1890 (set_attr "predicable" "yes")
1891 (set_attr "predicable_short_it" "no")]
0d66636f 1892)
82b85d08 1893
957788b0 1894(define_expand "smulsi3_highpart"
1895 [(parallel
1896 [(set (match_operand:SI 0 "s_register_operand" "")
1897 (truncate:SI
1898 (lshiftrt:DI
1899 (mult:DI
1900 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1901 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1902 (const_int 32))))
1903 (clobber (match_scratch:SI 3 ""))])]
1904 "TARGET_32BIT && arm_arch3m"
1905 ""
1906)
1907
1908(define_insn "*smulsi3_highpart_nov6"
f082f1c4 1909 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1910 (truncate:SI
1911 (lshiftrt:DI
215b30b3 1912 (mult:DI
e5fea38e 1913 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
215b30b3 1914 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
f082f1c4 1915 (const_int 32))))
1916 (clobber (match_scratch:SI 3 "=&r,&r"))]
58d7d654 1917 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1918 "smull%?\\t%3, %0, %2, %1"
9da0ec36 1919 [(set_attr "type" "smull")
58d7d654 1920 (set_attr "predicable" "yes")]
1921)
1922
957788b0 1923(define_insn "*smulsi3_highpart_v6"
58d7d654 1924 [(set (match_operand:SI 0 "s_register_operand" "=r")
1925 (truncate:SI
1926 (lshiftrt:DI
1927 (mult:DI
1928 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1929 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1930 (const_int 32))))
1931 (clobber (match_scratch:SI 3 "=r"))]
1932 "TARGET_32BIT && arm_arch6"
f082f1c4 1933 "smull%?\\t%3, %0, %2, %1"
9da0ec36 1934 [(set_attr "type" "smull")
d952d547 1935 (set_attr "predicable" "yes")
1936 (set_attr "predicable_short_it" "no")]
cffb2a26 1937)
f082f1c4 1938
957788b0 1939(define_expand "umulsi3_highpart"
1940 [(parallel
1941 [(set (match_operand:SI 0 "s_register_operand" "")
1942 (truncate:SI
1943 (lshiftrt:DI
1944 (mult:DI
1945 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1946 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1947 (const_int 32))))
1948 (clobber (match_scratch:SI 3 ""))])]
1949 "TARGET_32BIT && arm_arch3m"
1950 ""
1951)
1952
1953(define_insn "*umulsi3_highpart_nov6"
f082f1c4 1954 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1955 (truncate:SI
1956 (lshiftrt:DI
215b30b3 1957 (mult:DI
e5fea38e 1958 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
215b30b3 1959 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
f082f1c4 1960 (const_int 32))))
1961 (clobber (match_scratch:SI 3 "=&r,&r"))]
58d7d654 1962 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1963 "umull%?\\t%3, %0, %2, %1"
9da0ec36 1964 [(set_attr "type" "umull")
58d7d654 1965 (set_attr "predicable" "yes")]
1966)
1967
957788b0 1968(define_insn "*umulsi3_highpart_v6"
58d7d654 1969 [(set (match_operand:SI 0 "s_register_operand" "=r")
1970 (truncate:SI
1971 (lshiftrt:DI
1972 (mult:DI
1973 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1974 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1975 (const_int 32))))
1976 (clobber (match_scratch:SI 3 "=r"))]
1977 "TARGET_32BIT && arm_arch6"
f082f1c4 1978 "umull%?\\t%3, %0, %2, %1"
9da0ec36 1979 [(set_attr "type" "umull")
d952d547 1980 (set_attr "predicable" "yes")
1981 (set_attr "predicable_short_it" "no")]
cffb2a26 1982)
f082f1c4 1983
331beb1a 1984(define_insn "mulhisi3"
1985 [(set (match_operand:SI 0 "s_register_operand" "=r")
1986 (mult:SI (sign_extend:SI
1987 (match_operand:HI 1 "s_register_operand" "%r"))
1988 (sign_extend:SI
1989 (match_operand:HI 2 "s_register_operand" "r"))))]
25f905c2 1990 "TARGET_DSP_MULTIPLY"
61a2d04c 1991 "smulbb%?\\t%0, %1, %2"
9da0ec36 1992 [(set_attr "type" "smulxy")
fec538d9 1993 (set_attr "predicable" "yes")]
1994)
1995
1996(define_insn "*mulhisi3tb"
1997 [(set (match_operand:SI 0 "s_register_operand" "=r")
1998 (mult:SI (ashiftrt:SI
1999 (match_operand:SI 1 "s_register_operand" "r")
2000 (const_int 16))
2001 (sign_extend:SI
2002 (match_operand:HI 2 "s_register_operand" "r"))))]
25f905c2 2003 "TARGET_DSP_MULTIPLY"
fec538d9 2004 "smultb%?\\t%0, %1, %2"
9da0ec36 2005 [(set_attr "type" "smulxy")
d952d547 2006 (set_attr "predicable" "yes")
2007 (set_attr "predicable_short_it" "no")]
fec538d9 2008)
2009
2010(define_insn "*mulhisi3bt"
2011 [(set (match_operand:SI 0 "s_register_operand" "=r")
2012 (mult:SI (sign_extend:SI
2013 (match_operand:HI 1 "s_register_operand" "r"))
2014 (ashiftrt:SI
2015 (match_operand:SI 2 "s_register_operand" "r")
2016 (const_int 16))))]
25f905c2 2017 "TARGET_DSP_MULTIPLY"
fec538d9 2018 "smulbt%?\\t%0, %1, %2"
9da0ec36 2019 [(set_attr "type" "smulxy")
d952d547 2020 (set_attr "predicable" "yes")
2021 (set_attr "predicable_short_it" "no")]
fec538d9 2022)
2023
2024(define_insn "*mulhisi3tt"
2025 [(set (match_operand:SI 0 "s_register_operand" "=r")
2026 (mult:SI (ashiftrt:SI
2027 (match_operand:SI 1 "s_register_operand" "r")
2028 (const_int 16))
2029 (ashiftrt:SI
2030 (match_operand:SI 2 "s_register_operand" "r")
2031 (const_int 16))))]
25f905c2 2032 "TARGET_DSP_MULTIPLY"
fec538d9 2033 "smultt%?\\t%0, %1, %2"
9da0ec36 2034 [(set_attr "type" "smulxy")
d952d547 2035 (set_attr "predicable" "yes")
2036 (set_attr "predicable_short_it" "no")]
331beb1a 2037)
2038
5cdca009 2039(define_insn "maddhisi4"
331beb1a 2040 [(set (match_operand:SI 0 "s_register_operand" "=r")
cfa6c608 2041 (plus:SI (mult:SI (sign_extend:SI
2042 (match_operand:HI 1 "s_register_operand" "r"))
331beb1a 2043 (sign_extend:SI
cfa6c608 2044 (match_operand:HI 2 "s_register_operand" "r")))
2045 (match_operand:SI 3 "s_register_operand" "r")))]
25f905c2 2046 "TARGET_DSP_MULTIPLY"
5cdca009 2047 "smlabb%?\\t%0, %1, %2, %3"
9da0ec36 2048 [(set_attr "type" "smlaxy")
d952d547 2049 (set_attr "predicable" "yes")
2050 (set_attr "predicable_short_it" "no")]
331beb1a 2051)
2052
9a92f368 2053;; Note: there is no maddhisi4ibt because this one is canonical form
2054(define_insn "*maddhisi4tb"
2055 [(set (match_operand:SI 0 "s_register_operand" "=r")
2056 (plus:SI (mult:SI (ashiftrt:SI
2057 (match_operand:SI 1 "s_register_operand" "r")
2058 (const_int 16))
2059 (sign_extend:SI
2060 (match_operand:HI 2 "s_register_operand" "r")))
2061 (match_operand:SI 3 "s_register_operand" "r")))]
2062 "TARGET_DSP_MULTIPLY"
2063 "smlatb%?\\t%0, %1, %2, %3"
9da0ec36 2064 [(set_attr "type" "smlaxy")
d952d547 2065 (set_attr "predicable" "yes")
2066 (set_attr "predicable_short_it" "no")]
9a92f368 2067)
2068
2069(define_insn "*maddhisi4tt"
2070 [(set (match_operand:SI 0 "s_register_operand" "=r")
2071 (plus:SI (mult:SI (ashiftrt:SI
2072 (match_operand:SI 1 "s_register_operand" "r")
2073 (const_int 16))
2074 (ashiftrt:SI
2075 (match_operand:SI 2 "s_register_operand" "r")
2076 (const_int 16)))
2077 (match_operand:SI 3 "s_register_operand" "r")))]
2078 "TARGET_DSP_MULTIPLY"
2079 "smlatt%?\\t%0, %1, %2, %3"
9da0ec36 2080 [(set_attr "type" "smlaxy")
d952d547 2081 (set_attr "predicable" "yes")
2082 (set_attr "predicable_short_it" "no")]
9a92f368 2083)
2084
aff5fb4d 2085(define_insn "maddhidi4"
331beb1a 2086 [(set (match_operand:DI 0 "s_register_operand" "=r")
2087 (plus:DI
331beb1a 2088 (mult:DI (sign_extend:DI
d952d547 2089 (match_operand:HI 1 "s_register_operand" "r"))
331beb1a 2090 (sign_extend:DI
cfa6c608 2091 (match_operand:HI 2 "s_register_operand" "r")))
2092 (match_operand:DI 3 "s_register_operand" "0")))]
25f905c2 2093 "TARGET_DSP_MULTIPLY"
5cdca009 2094 "smlalbb%?\\t%Q0, %R0, %1, %2"
9da0ec36 2095 [(set_attr "type" "smlalxy")
d952d547 2096 (set_attr "predicable" "yes")
2097 (set_attr "predicable_short_it" "no")])
331beb1a 2098
9a92f368 2099;; Note: there is no maddhidi4ibt because this one is canonical form
2100(define_insn "*maddhidi4tb"
2101 [(set (match_operand:DI 0 "s_register_operand" "=r")
2102 (plus:DI
2103 (mult:DI (sign_extend:DI
2104 (ashiftrt:SI
2105 (match_operand:SI 1 "s_register_operand" "r")
2106 (const_int 16)))
2107 (sign_extend:DI
2108 (match_operand:HI 2 "s_register_operand" "r")))
2109 (match_operand:DI 3 "s_register_operand" "0")))]
2110 "TARGET_DSP_MULTIPLY"
2111 "smlaltb%?\\t%Q0, %R0, %1, %2"
9da0ec36 2112 [(set_attr "type" "smlalxy")
d952d547 2113 (set_attr "predicable" "yes")
2114 (set_attr "predicable_short_it" "no")])
9a92f368 2115
2116(define_insn "*maddhidi4tt"
2117 [(set (match_operand:DI 0 "s_register_operand" "=r")
2118 (plus:DI
2119 (mult:DI (sign_extend:DI
2120 (ashiftrt:SI
2121 (match_operand:SI 1 "s_register_operand" "r")
2122 (const_int 16)))
2123 (sign_extend:DI
2124 (ashiftrt:SI
2125 (match_operand:SI 2 "s_register_operand" "r")
2126 (const_int 16))))
2127 (match_operand:DI 3 "s_register_operand" "0")))]
2128 "TARGET_DSP_MULTIPLY"
2129 "smlaltt%?\\t%Q0, %R0, %1, %2"
9da0ec36 2130 [(set_attr "type" "smlalxy")
d952d547 2131 (set_attr "predicable" "yes")
2132 (set_attr "predicable_short_it" "no")])
9a92f368 2133
604f3a0a 2134(define_expand "mulsf3"
2135 [(set (match_operand:SF 0 "s_register_operand" "")
2136 (mult:SF (match_operand:SF 1 "s_register_operand" "")
d86c91f6 2137 (match_operand:SF 2 "s_register_operand" "")))]
25f905c2 2138 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 2139 "
604f3a0a 2140")
2141
604f3a0a 2142(define_expand "muldf3"
2143 [(set (match_operand:DF 0 "s_register_operand" "")
2144 (mult:DF (match_operand:DF 1 "s_register_operand" "")
d86c91f6 2145 (match_operand:DF 2 "s_register_operand" "")))]
a50d7267 2146 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 2147 "
604f3a0a 2148")
b11cae9e 2149\f
2150;; Division insns
2151
7db9af5d 2152(define_expand "divsf3"
2153 [(set (match_operand:SF 0 "s_register_operand" "")
d86c91f6 2154 (div:SF (match_operand:SF 1 "s_register_operand" "")
2155 (match_operand:SF 2 "s_register_operand" "")))]
d7216193 2156 "TARGET_32BIT && TARGET_HARD_FLOAT"
7db9af5d 2157 "")
9c08d1fa 2158
7db9af5d 2159(define_expand "divdf3"
2160 [(set (match_operand:DF 0 "s_register_operand" "")
d86c91f6 2161 (div:DF (match_operand:DF 1 "s_register_operand" "")
2162 (match_operand:DF 2 "s_register_operand" "")))]
994606f8 2163 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
7db9af5d 2164 "")
b11cae9e 2165\f
2166;; Boolean and,ior,xor insns
2167
f6ebffac 2168;; Split up double word logical operations
2169
2170;; Split up simple DImode logical operations. Simply perform the logical
2171;; operation on the upper and lower halves of the registers.
2172(define_split
2173 [(set (match_operand:DI 0 "s_register_operand" "")
2174 (match_operator:DI 6 "logical_binary_operator"
2175 [(match_operand:DI 1 "s_register_operand" "")
2176 (match_operand:DI 2 "s_register_operand" "")]))]
25f905c2 2177 "TARGET_32BIT && reload_completed
e2669ea7 2178 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))
25f905c2 2179 && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
f6ebffac 2180 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
2181 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
2182 "
215b30b3 2183 {
2184 operands[3] = gen_highpart (SImode, operands[0]);
2185 operands[0] = gen_lowpart (SImode, operands[0]);
2186 operands[4] = gen_highpart (SImode, operands[1]);
2187 operands[1] = gen_lowpart (SImode, operands[1]);
2188 operands[5] = gen_highpart (SImode, operands[2]);
2189 operands[2] = gen_lowpart (SImode, operands[2]);
2190 }"
2191)
f6ebffac 2192
f6ebffac 2193(define_split
2194 [(set (match_operand:DI 0 "s_register_operand" "")
2195 (match_operator:DI 6 "logical_binary_operator"
2196 [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
2197 (match_operand:DI 1 "s_register_operand" "")]))]
25f905c2 2198 "TARGET_32BIT && reload_completed"
f6ebffac 2199 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
2200 (set (match_dup 3) (match_op_dup:SI 6
2201 [(ashiftrt:SI (match_dup 2) (const_int 31))
2202 (match_dup 4)]))]
2203 "
215b30b3 2204 {
2205 operands[3] = gen_highpart (SImode, operands[0]);
2206 operands[0] = gen_lowpart (SImode, operands[0]);
2207 operands[4] = gen_highpart (SImode, operands[1]);
2208 operands[1] = gen_lowpart (SImode, operands[1]);
2209 operands[5] = gen_highpart (SImode, operands[2]);
2210 operands[2] = gen_lowpart (SImode, operands[2]);
2211 }"
2212)
f6ebffac 2213
f6ebffac 2214;; The zero extend of operand 2 means we can just copy the high part of
2215;; operand1 into operand0.
2216(define_split
2217 [(set (match_operand:DI 0 "s_register_operand" "")
2218 (ior:DI
2219 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
2220 (match_operand:DI 1 "s_register_operand" "")))]
25f905c2 2221 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
f6ebffac 2222 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
2223 (set (match_dup 3) (match_dup 4))]
2224 "
215b30b3 2225 {
2226 operands[4] = gen_highpart (SImode, operands[1]);
2227 operands[3] = gen_highpart (SImode, operands[0]);
2228 operands[0] = gen_lowpart (SImode, operands[0]);
2229 operands[1] = gen_lowpart (SImode, operands[1]);
2230 }"
2231)
f6ebffac 2232
2233;; The zero extend of operand 2 means we can just copy the high part of
2234;; operand1 into operand0.
2235(define_split
2236 [(set (match_operand:DI 0 "s_register_operand" "")
2237 (xor:DI
2238 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
2239 (match_operand:DI 1 "s_register_operand" "")))]
25f905c2 2240 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
f6ebffac 2241 [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
2242 (set (match_dup 3) (match_dup 4))]
2243 "
215b30b3 2244 {
2245 operands[4] = gen_highpart (SImode, operands[1]);
2246 operands[3] = gen_highpart (SImode, operands[0]);
2247 operands[0] = gen_lowpart (SImode, operands[0]);
2248 operands[1] = gen_lowpart (SImode, operands[1]);
2249 }"
2250)
f6ebffac 2251
e2669ea7 2252(define_expand "anddi3"
2253 [(set (match_operand:DI 0 "s_register_operand" "")
2254 (and:DI (match_operand:DI 1 "s_register_operand" "")
2255 (match_operand:DI 2 "neon_inv_logic_op2" "")))]
2256 "TARGET_32BIT"
0d84c6e5 2257 "
2258 if (!TARGET_NEON && !TARGET_IWMMXT)
2259 {
2260 rtx low = simplify_gen_binary (AND, SImode,
2261 gen_lowpart (SImode, operands[1]),
2262 gen_lowpart (SImode, operands[2]));
2263 rtx high = simplify_gen_binary (AND, SImode,
2264 gen_highpart (SImode, operands[1]),
2265 gen_highpart_mode (SImode, DImode,
2266 operands[2]));
2267
2268 emit_insn (gen_rtx_SET (gen_lowpart (SImode, operands[0]), low));
2269 emit_insn (gen_rtx_SET (gen_highpart (SImode, operands[0]), high));
2270
2271 DONE;
2272 }
2273 /* Otherwise expand pattern as above. */
2274 "
e2669ea7 2275)
2276
f6bbdcf6 2277(define_insn_and_split "*anddi3_insn"
0a314dcd 2278 [(set (match_operand:DI 0 "s_register_operand" "=w,w ,&r,&r,&r,&r,?w,?w")
2279 (and:DI (match_operand:DI 1 "s_register_operand" "%w,0 ,0 ,r ,0 ,r ,w ,0")
2280 (match_operand:DI 2 "arm_anddi_operand_neon" "w ,DL,r ,r ,De,De,w ,DL")))]
f6bbdcf6 2281 "TARGET_32BIT && !TARGET_IWMMXT"
2282{
2283 switch (which_alternative)
2284 {
0a314dcd 2285 case 0: /* fall through */
2286 case 6: return "vand\t%P0, %P1, %P2";
2287 case 1: /* fall through */
2288 case 7: return neon_output_logic_immediate ("vand", &operands[2],
2289 DImode, 1, VALID_NEON_QREG_MODE (DImode));
f6bbdcf6 2290 case 2:
0a314dcd 2291 case 3:
2292 case 4:
f6bbdcf6 2293 case 5: /* fall through */
0a314dcd 2294 return "#";
f6bbdcf6 2295 default: gcc_unreachable ();
2296 }
2297}
0a314dcd 2298 "TARGET_32BIT && !TARGET_IWMMXT && reload_completed
2299 && !(IS_VFP_REGNUM (REGNO (operands[0])))"
f6bbdcf6 2300 [(set (match_dup 3) (match_dup 4))
2301 (set (match_dup 5) (match_dup 6))]
2302 "
2303 {
2304 operands[3] = gen_lowpart (SImode, operands[0]);
2305 operands[5] = gen_highpart (SImode, operands[0]);
2306
2307 operands[4] = simplify_gen_binary (AND, SImode,
2308 gen_lowpart (SImode, operands[1]),
2309 gen_lowpart (SImode, operands[2]));
2310 operands[6] = simplify_gen_binary (AND, SImode,
2311 gen_highpart (SImode, operands[1]),
2312 gen_highpart_mode (SImode, DImode, operands[2]));
2313
2314 }"
32093010 2315 [(set_attr "type" "neon_logic,neon_logic,multiple,multiple,\
2316 multiple,multiple,neon_logic,neon_logic")
0a314dcd 2317 (set_attr "arch" "neon_for_64bits,neon_for_64bits,*,*,*,*,
f6bbdcf6 2318 avoid_neon_for_64bits,avoid_neon_for_64bits")
0a314dcd 2319 (set_attr "length" "*,*,8,8,8,8,*,*")
2320 ]
215b30b3 2321)
b11cae9e 2322
a0f94409 2323(define_insn_and_split "*anddi_zesidi_di"
9c08d1fa 2324 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2325 (and:DI (zero_extend:DI
2326 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 2327 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2328 "TARGET_32BIT"
f6ebffac 2329 "#"
25f905c2 2330 "TARGET_32BIT && reload_completed"
a0f94409 2331 ; The zero extend of operand 2 clears the high word of the output
2332 ; operand.
2333 [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
2334 (set (match_dup 3) (const_int 0))]
2335 "
2336 {
2337 operands[3] = gen_highpart (SImode, operands[0]);
2338 operands[0] = gen_lowpart (SImode, operands[0]);
2339 operands[1] = gen_lowpart (SImode, operands[1]);
2340 }"
1b7da4ac 2341 [(set_attr "length" "8")
2342 (set_attr "type" "multiple")]
215b30b3 2343)
b11cae9e 2344
f7fbdd4a 2345(define_insn "*anddi_sesdi_di"
cffb2a26 2346 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 2347 (and:DI (sign_extend:DI
2348 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 2349 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2350 "TARGET_32BIT"
f6ebffac 2351 "#"
1b7da4ac 2352 [(set_attr "length" "8")
2353 (set_attr "type" "multiple")]
cffb2a26 2354)
b11cae9e 2355
87b22bf7 2356(define_expand "andsi3"
cffb2a26 2357 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2358 (and:SI (match_operand:SI 1 "s_register_operand" "")
2359 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 2360 "TARGET_EITHER"
87b22bf7 2361 "
25f905c2 2362 if (TARGET_32BIT)
87b22bf7 2363 {
0438d37f 2364 if (CONST_INT_P (operands[2]))
cffb2a26 2365 {
47b5b27b 2366 if (INTVAL (operands[2]) == 255 && arm_arch6)
2367 {
2368 operands[1] = convert_to_mode (QImode, operands[1], 1);
2369 emit_insn (gen_thumb2_zero_extendqisi2_v6 (operands[0],
2370 operands[1]));
17202aa5 2371 DONE;
47b5b27b 2372 }
17202aa5 2373 else if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[2]), AND))
2374 operands[2] = force_reg (SImode, operands[2]);
47b5b27b 2375 else
17202aa5 2376 {
2377 arm_split_constant (AND, SImode, NULL_RTX,
2378 INTVAL (operands[2]), operands[0],
2379 operands[1],
2380 optimize && can_create_pseudo_p ());
615caa51 2381
17202aa5 2382 DONE;
2383 }
cffb2a26 2384 }
87b22bf7 2385 }
25f905c2 2386 else /* TARGET_THUMB1 */
cffb2a26 2387 {
0438d37f 2388 if (!CONST_INT_P (operands[2]))
923ffadb 2389 {
2390 rtx tmp = force_reg (SImode, operands[2]);
2391 if (rtx_equal_p (operands[0], operands[1]))
2392 operands[2] = tmp;
2393 else
2394 {
2395 operands[2] = operands[1];
2396 operands[1] = tmp;
2397 }
2398 }
cffb2a26 2399 else
2400 {
2401 int i;
2402
215b30b3 2403 if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
cffb2a26 2404 {
215b30b3 2405 operands[2] = force_reg (SImode,
2406 GEN_INT (~INTVAL (operands[2])));
cffb2a26 2407
747b7458 2408 emit_insn (gen_thumb1_bicsi3 (operands[0], operands[2], operands[1]));
cffb2a26 2409
2410 DONE;
2411 }
87b22bf7 2412
cffb2a26 2413 for (i = 9; i <= 31; i++)
2414 {
db2faf44 2415 if ((HOST_WIDE_INT_1 << i) - 1 == INTVAL (operands[2]))
cffb2a26 2416 {
2417 emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
2418 const0_rtx));
2419 DONE;
2420 }
db2faf44 2421 else if ((HOST_WIDE_INT_1 << i) - 1
215b30b3 2422 == ~INTVAL (operands[2]))
cffb2a26 2423 {
2424 rtx shift = GEN_INT (i);
2425 rtx reg = gen_reg_rtx (SImode);
2426
2427 emit_insn (gen_lshrsi3 (reg, operands[1], shift));
2428 emit_insn (gen_ashlsi3 (operands[0], reg, shift));
2429
2430 DONE;
2431 }
2432 }
2433
2434 operands[2] = force_reg (SImode, operands[2]);
2435 }
215b30b3 2436 }
2437 "
cffb2a26 2438)
2439
25f905c2 2440; ??? Check split length for Thumb-2
a0f94409 2441(define_insn_and_split "*arm_andsi3_insn"
29e234a3 2442 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r,r,r")
2443 (and:SI (match_operand:SI 1 "s_register_operand" "%r,0,r,r,r")
2444 (match_operand:SI 2 "reg_or_int_operand" "I,l,K,r,?n")))]
25f905c2 2445 "TARGET_32BIT"
5565501b 2446 "@
29e234a3 2447 and%?\\t%0, %1, %2
5565501b 2448 and%?\\t%0, %1, %2
87b22bf7 2449 bic%?\\t%0, %1, #%B2
65f68e55 2450 and%?\\t%0, %1, %2
87b22bf7 2451 #"
25f905c2 2452 "TARGET_32BIT
0438d37f 2453 && CONST_INT_P (operands[2])
a0f94409 2454 && !(const_ok_for_arm (INTVAL (operands[2]))
2455 || const_ok_for_arm (~INTVAL (operands[2])))"
2456 [(clobber (const_int 0))]
2457 "
96f57e36 2458 arm_split_constant (AND, SImode, curr_insn,
2459 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 2460 DONE;
2461 "
29e234a3 2462 [(set_attr "length" "4,4,4,4,16")
65f68e55 2463 (set_attr "predicable" "yes")
29e234a3 2464 (set_attr "predicable_short_it" "no,yes,no,no,no")
d82e788e 2465 (set_attr "type" "logic_imm,logic_imm,logic_reg,logic_reg,logic_imm")]
cffb2a26 2466)
2467
f7fbdd4a 2468(define_insn "*andsi3_compare0"
bd5b4116 2469 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 2470 (compare:CC_NOOV
65f68e55 2471 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
2472 (match_operand:SI 2 "arm_not_operand" "I,K,r"))
5565501b 2473 (const_int 0)))
65f68e55 2474 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9c08d1fa 2475 (and:SI (match_dup 1) (match_dup 2)))]
25f905c2 2476 "TARGET_32BIT"
5565501b 2477 "@
3ef90e77 2478 ands%?\\t%0, %1, %2
2479 bics%?\\t%0, %1, #%B2
2480 ands%?\\t%0, %1, %2"
65f68e55 2481 [(set_attr "conds" "set")
d82e788e 2482 (set_attr "type" "logics_imm,logics_imm,logics_reg")]
cffb2a26 2483)
9c08d1fa 2484
f7fbdd4a 2485(define_insn "*andsi3_compare0_scratch"
bd5b4116 2486 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 2487 (compare:CC_NOOV
65f68e55 2488 (and:SI (match_operand:SI 0 "s_register_operand" "r,r,r")
2489 (match_operand:SI 1 "arm_not_operand" "I,K,r"))
5565501b 2490 (const_int 0)))
65f68e55 2491 (clobber (match_scratch:SI 2 "=X,r,X"))]
25f905c2 2492 "TARGET_32BIT"
5565501b 2493 "@
2494 tst%?\\t%0, %1
3ef90e77 2495 bics%?\\t%2, %0, #%B1
65f68e55 2496 tst%?\\t%0, %1"
2497 [(set_attr "conds" "set")
d82e788e 2498 (set_attr "type" "logics_imm,logics_imm,logics_reg")]
0d66636f 2499)
9c08d1fa 2500
f7fbdd4a 2501(define_insn "*zeroextractsi_compare0_scratch"
bd5b4116 2502 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2503 (compare:CC_NOOV (zero_extract:SI
2504 (match_operand:SI 0 "s_register_operand" "r")
d952d547 2505 (match_operand 1 "const_int_operand" "n")
206ee9a2 2506 (match_operand 2 "const_int_operand" "n"))
9c08d1fa 2507 (const_int 0)))]
25f905c2 2508 "TARGET_32BIT
cffb2a26 2509 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
2510 && INTVAL (operands[1]) > 0
2511 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
2512 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
9c08d1fa 2513 "*
5c49a439 2514 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
2515 << INTVAL (operands[2]));
40dbec34 2516 output_asm_insn (\"tst%?\\t%0, %1\", operands);
e2348bcb 2517 return \"\";
0d66636f 2518 "
596e5e8f 2519 [(set_attr "conds" "set")
65f68e55 2520 (set_attr "predicable" "yes")
d952d547 2521 (set_attr "predicable_short_it" "no")
d82e788e 2522 (set_attr "type" "logics_imm")]
0d66636f 2523)
9c08d1fa 2524
f4462328 2525(define_insn_and_split "*ne_zeroextractsi"
c4034607 2526 [(set (match_operand:SI 0 "s_register_operand" "=r")
2527 (ne:SI (zero_extract:SI
2528 (match_operand:SI 1 "s_register_operand" "r")
2529 (match_operand:SI 2 "const_int_operand" "n")
2530 (match_operand:SI 3 "const_int_operand" "n"))
3b8c7f7a 2531 (const_int 0)))
2532 (clobber (reg:CC CC_REGNUM))]
25f905c2 2533 "TARGET_32BIT
cffb2a26 2534 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2535 && INTVAL (operands[2]) > 0
2536 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2537 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
f4462328 2538 "#"
25f905c2 2539 "TARGET_32BIT
f4462328 2540 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2541 && INTVAL (operands[2]) > 0
2542 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2543 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
2544 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2545 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2546 (const_int 0)))
2547 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2548 (set (match_dup 0)
2549 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2550 (match_dup 0) (const_int 1)))]
2551 "
2552 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
2553 << INTVAL (operands[3]));
2554 "
2555 [(set_attr "conds" "clob")
25f905c2 2556 (set (attr "length")
2557 (if_then_else (eq_attr "is_thumb" "yes")
2558 (const_int 12)
1b7da4ac 2559 (const_int 8)))
2560 (set_attr "type" "multiple")]
f4462328 2561)
2562
2563(define_insn_and_split "*ne_zeroextractsi_shifted"
2564 [(set (match_operand:SI 0 "s_register_operand" "=r")
2565 (ne:SI (zero_extract:SI
2566 (match_operand:SI 1 "s_register_operand" "r")
2567 (match_operand:SI 2 "const_int_operand" "n")
2568 (const_int 0))
2569 (const_int 0)))
2570 (clobber (reg:CC CC_REGNUM))]
2571 "TARGET_ARM"
2572 "#"
2573 "TARGET_ARM"
2574 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2575 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2576 (const_int 0)))
2577 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2578 (set (match_dup 0)
2579 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2580 (match_dup 0) (const_int 1)))]
2581 "
2582 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
2583 "
2584 [(set_attr "conds" "clob")
1b7da4ac 2585 (set_attr "length" "8")
2586 (set_attr "type" "multiple")]
f4462328 2587)
2588
2589(define_insn_and_split "*ite_ne_zeroextractsi"
2590 [(set (match_operand:SI 0 "s_register_operand" "=r")
2591 (if_then_else:SI (ne (zero_extract:SI
2592 (match_operand:SI 1 "s_register_operand" "r")
2593 (match_operand:SI 2 "const_int_operand" "n")
2594 (match_operand:SI 3 "const_int_operand" "n"))
2595 (const_int 0))
2596 (match_operand:SI 4 "arm_not_operand" "rIK")
2597 (const_int 0)))
2598 (clobber (reg:CC CC_REGNUM))]
2599 "TARGET_ARM
2600 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2601 && INTVAL (operands[2]) > 0
2602 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 2603 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2604 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 2605 "#"
2606 "TARGET_ARM
2607 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2608 && INTVAL (operands[2]) > 0
2609 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 2610 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2611 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 2612 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2613 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2614 (const_int 0)))
2615 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2616 (set (match_dup 0)
2617 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2618 (match_dup 0) (match_dup 4)))]
2619 "
c4034607 2620 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
f4462328 2621 << INTVAL (operands[3]));
2622 "
2623 [(set_attr "conds" "clob")
1b7da4ac 2624 (set_attr "length" "8")
2625 (set_attr "type" "multiple")]
f4462328 2626)
2627
2628(define_insn_and_split "*ite_ne_zeroextractsi_shifted"
2629 [(set (match_operand:SI 0 "s_register_operand" "=r")
2630 (if_then_else:SI (ne (zero_extract:SI
2631 (match_operand:SI 1 "s_register_operand" "r")
2632 (match_operand:SI 2 "const_int_operand" "n")
2633 (const_int 0))
2634 (const_int 0))
2635 (match_operand:SI 3 "arm_not_operand" "rIK")
2636 (const_int 0)))
2637 (clobber (reg:CC CC_REGNUM))]
f8d7bf2f 2638 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 2639 "#"
f8d7bf2f 2640 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 2641 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2642 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2643 (const_int 0)))
2644 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2645 (set (match_dup 0)
2646 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2647 (match_dup 0) (match_dup 3)))]
2648 "
2649 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
0d66636f 2650 "
2651 [(set_attr "conds" "clob")
1b7da4ac 2652 (set_attr "length" "8")
2653 (set_attr "type" "multiple")]
215b30b3 2654)
9c08d1fa 2655
25f905c2 2656;; ??? Use Thumb-2 has bitfield insert/extract instructions.
d7863cfe 2657(define_split
2658 [(set (match_operand:SI 0 "s_register_operand" "")
2659 (match_operator:SI 1 "shiftable_operator"
2660 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2661 (match_operand:SI 3 "const_int_operand" "")
2662 (match_operand:SI 4 "const_int_operand" ""))
2663 (match_operand:SI 5 "s_register_operand" "")]))
2664 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2665 "TARGET_ARM"
2666 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2667 (set (match_dup 0)
2668 (match_op_dup 1
2669 [(lshiftrt:SI (match_dup 6) (match_dup 4))
2670 (match_dup 5)]))]
2671 "{
2672 HOST_WIDE_INT temp = INTVAL (operands[3]);
2673
2674 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2675 operands[4] = GEN_INT (32 - temp);
2676 }"
2677)
2678
d7863cfe 2679(define_split
2680 [(set (match_operand:SI 0 "s_register_operand" "")
2681 (match_operator:SI 1 "shiftable_operator"
2682 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2683 (match_operand:SI 3 "const_int_operand" "")
2684 (match_operand:SI 4 "const_int_operand" ""))
2685 (match_operand:SI 5 "s_register_operand" "")]))
2686 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2687 "TARGET_ARM"
2688 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2689 (set (match_dup 0)
2690 (match_op_dup 1
2691 [(ashiftrt:SI (match_dup 6) (match_dup 4))
2692 (match_dup 5)]))]
2693 "{
2694 HOST_WIDE_INT temp = INTVAL (operands[3]);
2695
2696 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2697 operands[4] = GEN_INT (32 - temp);
2698 }"
2699)
2700
a42059fd 2701;;; ??? This pattern is bogus. If operand3 has bits outside the range
2702;;; represented by the bitfield, then this will produce incorrect results.
2703;;; Somewhere, the value needs to be truncated. On targets like the m68k,
ceb2fe0f 2704;;; which have a real bit-field insert instruction, the truncation happens
2705;;; in the bit-field insert instruction itself. Since arm does not have a
2706;;; bit-field insert instruction, we would have to emit code here to truncate
a42059fd 2707;;; the value before we insert. This loses some of the advantage of having
2708;;; this insv pattern, so this pattern needs to be reevalutated.
2709
8a18b90c 2710(define_expand "insv"
eb04cafb 2711 [(set (zero_extract (match_operand 0 "nonimmediate_operand" "")
2712 (match_operand 1 "general_operand" "")
2713 (match_operand 2 "general_operand" ""))
2714 (match_operand 3 "reg_or_int_operand" ""))]
8b054d5a 2715 "TARGET_ARM || arm_arch_thumb2"
8a18b90c 2716 "
215b30b3 2717 {
2718 int start_bit = INTVAL (operands[2]);
2719 int width = INTVAL (operands[1]);
db2faf44 2720 HOST_WIDE_INT mask = (HOST_WIDE_INT_1 << width) - 1;
215b30b3 2721 rtx target, subtarget;
2722
8b054d5a 2723 if (arm_arch_thumb2)
2724 {
eb04cafb 2725 if (unaligned_access && MEM_P (operands[0])
2726 && s_register_operand (operands[3], GET_MODE (operands[3]))
2727 && (width == 16 || width == 32) && (start_bit % BITS_PER_UNIT) == 0)
8b054d5a 2728 {
eb04cafb 2729 rtx base_addr;
2730
2731 if (BYTES_BIG_ENDIAN)
2732 start_bit = GET_MODE_BITSIZE (GET_MODE (operands[3])) - width
2733 - start_bit;
8b054d5a 2734
eb04cafb 2735 if (width == 32)
8b054d5a 2736 {
eb04cafb 2737 base_addr = adjust_address (operands[0], SImode,
2738 start_bit / BITS_PER_UNIT);
2739 emit_insn (gen_unaligned_storesi (base_addr, operands[3]));
8b054d5a 2740 }
eb04cafb 2741 else
2742 {
2743 rtx tmp = gen_reg_rtx (HImode);
8b054d5a 2744
eb04cafb 2745 base_addr = adjust_address (operands[0], HImode,
2746 start_bit / BITS_PER_UNIT);
2747 emit_move_insn (tmp, gen_lowpart (HImode, operands[3]));
2748 emit_insn (gen_unaligned_storehi (base_addr, tmp));
2749 }
2750 DONE;
8b054d5a 2751 }
eb04cafb 2752 else if (s_register_operand (operands[0], GET_MODE (operands[0])))
8b054d5a 2753 {
eb04cafb 2754 bool use_bfi = TRUE;
8b054d5a 2755
0438d37f 2756 if (CONST_INT_P (operands[3]))
eb04cafb 2757 {
2758 HOST_WIDE_INT val = INTVAL (operands[3]) & mask;
2759
2760 if (val == 0)
2761 {
2762 emit_insn (gen_insv_zero (operands[0], operands[1],
2763 operands[2]));
2764 DONE;
2765 }
2766
2767 /* See if the set can be done with a single orr instruction. */
2768 if (val == mask && const_ok_for_arm (val << start_bit))
2769 use_bfi = FALSE;
2770 }
2771
2772 if (use_bfi)
2773 {
0438d37f 2774 if (!REG_P (operands[3]))
eb04cafb 2775 operands[3] = force_reg (SImode, operands[3]);
2776
2777 emit_insn (gen_insv_t2 (operands[0], operands[1], operands[2],
2778 operands[3]));
2779 DONE;
2780 }
8b054d5a 2781 }
eb04cafb 2782 else
2783 FAIL;
8b054d5a 2784 }
2785
eb04cafb 2786 if (!s_register_operand (operands[0], GET_MODE (operands[0])))
2787 FAIL;
2788
3f8fde42 2789 target = copy_rtx (operands[0]);
215b30b3 2790 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
2791 subreg as the final target. */
2792 if (GET_CODE (target) == SUBREG)
2793 {
2794 subtarget = gen_reg_rtx (SImode);
2795 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
2796 < GET_MODE_SIZE (SImode))
2797 target = SUBREG_REG (target);
2798 }
2799 else
2800 subtarget = target;
8a18b90c 2801
0438d37f 2802 if (CONST_INT_P (operands[3]))
215b30b3 2803 {
2804 /* Since we are inserting a known constant, we may be able to
2805 reduce the number of bits that we have to clear so that
2806 the mask becomes simple. */
2807 /* ??? This code does not check to see if the new mask is actually
2808 simpler. It may not be. */
2809 rtx op1 = gen_reg_rtx (SImode);
2810 /* ??? Truncate operand3 to fit in the bitfield. See comment before
2811 start of this pattern. */
2812 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
2813 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
2814
c5b3a71b 2815 emit_insn (gen_andsi3 (op1, operands[0],
2816 gen_int_mode (~mask2, SImode)));
215b30b3 2817 emit_insn (gen_iorsi3 (subtarget, op1,
4292ca6b 2818 gen_int_mode (op3_value << start_bit, SImode)));
215b30b3 2819 }
2820 else if (start_bit == 0
2821 && !(const_ok_for_arm (mask)
2822 || const_ok_for_arm (~mask)))
2823 {
2824 /* A Trick, since we are setting the bottom bits in the word,
2825 we can shift operand[3] up, operand[0] down, OR them together
2826 and rotate the result back again. This takes 3 insns, and
5910bb95 2827 the third might be mergeable into another op. */
215b30b3 2828 /* The shift up copes with the possibility that operand[3] is
2829 wider than the bitfield. */
2830 rtx op0 = gen_reg_rtx (SImode);
2831 rtx op1 = gen_reg_rtx (SImode);
2832
2833 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2834 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
2835 emit_insn (gen_iorsi3 (op1, op1, op0));
2836 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
2837 }
2838 else if ((width + start_bit == 32)
2839 && !(const_ok_for_arm (mask)
2840 || const_ok_for_arm (~mask)))
2841 {
2842 /* Similar trick, but slightly less efficient. */
8a18b90c 2843
215b30b3 2844 rtx op0 = gen_reg_rtx (SImode);
2845 rtx op1 = gen_reg_rtx (SImode);
8a18b90c 2846
215b30b3 2847 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2848 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
2849 emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
2850 emit_insn (gen_iorsi3 (subtarget, op1, op0));
2851 }
2852 else
2853 {
c5b3a71b 2854 rtx op0 = gen_int_mode (mask, SImode);
215b30b3 2855 rtx op1 = gen_reg_rtx (SImode);
2856 rtx op2 = gen_reg_rtx (SImode);
8a18b90c 2857
215b30b3 2858 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
2859 {
2860 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 2861
215b30b3 2862 emit_insn (gen_movsi (tmp, op0));
2863 op0 = tmp;
2864 }
8a18b90c 2865
215b30b3 2866 /* Mask out any bits in operand[3] that are not needed. */
2867 emit_insn (gen_andsi3 (op1, operands[3], op0));
8a18b90c 2868
0438d37f 2869 if (CONST_INT_P (op0)
215b30b3 2870 && (const_ok_for_arm (mask << start_bit)
2871 || const_ok_for_arm (~(mask << start_bit))))
2872 {
c5b3a71b 2873 op0 = gen_int_mode (~(mask << start_bit), SImode);
215b30b3 2874 emit_insn (gen_andsi3 (op2, operands[0], op0));
2875 }
2876 else
2877 {
0438d37f 2878 if (CONST_INT_P (op0))
215b30b3 2879 {
2880 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 2881
215b30b3 2882 emit_insn (gen_movsi (tmp, op0));
2883 op0 = tmp;
2884 }
2885
2886 if (start_bit != 0)
2887 emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
a42059fd 2888
215b30b3 2889 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
2890 }
8a18b90c 2891
215b30b3 2892 if (start_bit != 0)
2893 emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
8a18b90c 2894
215b30b3 2895 emit_insn (gen_iorsi3 (subtarget, op1, op2));
2896 }
f082f1c4 2897
215b30b3 2898 if (subtarget != target)
2899 {
2900 /* If TARGET is still a SUBREG, then it must be wider than a word,
2901 so we must be careful only to set the subword we were asked to. */
2902 if (GET_CODE (target) == SUBREG)
2903 emit_move_insn (target, subtarget);
2904 else
2905 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
2906 }
8a18b90c 2907
215b30b3 2908 DONE;
2909 }"
2910)
8a18b90c 2911
8b054d5a 2912(define_insn "insv_zero"
2913 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
809003b3 2914 (match_operand:SI 1 "const_int_M_operand" "M")
2915 (match_operand:SI 2 "const_int_M_operand" "M"))
8b054d5a 2916 (const_int 0))]
2917 "arm_arch_thumb2"
2918 "bfc%?\t%0, %2, %1"
2919 [(set_attr "length" "4")
d952d547 2920 (set_attr "predicable" "yes")
d82e788e 2921 (set_attr "predicable_short_it" "no")
2922 (set_attr "type" "bfm")]
8b054d5a 2923)
2924
2925(define_insn "insv_t2"
2926 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
809003b3 2927 (match_operand:SI 1 "const_int_M_operand" "M")
2928 (match_operand:SI 2 "const_int_M_operand" "M"))
8b054d5a 2929 (match_operand:SI 3 "s_register_operand" "r"))]
2930 "arm_arch_thumb2"
2931 "bfi%?\t%0, %3, %2, %1"
2932 [(set_attr "length" "4")
d952d547 2933 (set_attr "predicable" "yes")
d82e788e 2934 (set_attr "predicable_short_it" "no")
2935 (set_attr "type" "bfm")]
8b054d5a 2936)
2937
215b30b3 2938; constants for op 2 will never be given to these patterns.
a0f94409 2939(define_insn_and_split "*anddi_notdi_di"
9c08d1fa 2940 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 2941 (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "0,r"))
2942 (match_operand:DI 2 "s_register_operand" "r,0")))]
25f905c2 2943 "TARGET_32BIT"
f6ebffac 2944 "#"
e2669ea7 2945 "TARGET_32BIT && reload_completed
2946 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))
2947 && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
a0f94409 2948 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2949 (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2950 "
2951 {
2952 operands[3] = gen_highpart (SImode, operands[0]);
2953 operands[0] = gen_lowpart (SImode, operands[0]);
2954 operands[4] = gen_highpart (SImode, operands[1]);
2955 operands[1] = gen_lowpart (SImode, operands[1]);
2956 operands[5] = gen_highpart (SImode, operands[2]);
2957 operands[2] = gen_lowpart (SImode, operands[2]);
2958 }"
0d66636f 2959 [(set_attr "length" "8")
1b7da4ac 2960 (set_attr "predicable" "yes")
2961 (set_attr "type" "multiple")]
0d66636f 2962)
d952d547 2963
a0f94409 2964(define_insn_and_split "*anddi_notzesidi_di"
9c08d1fa 2965 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2966 (and:DI (not:DI (zero_extend:DI
2967 (match_operand:SI 2 "s_register_operand" "r,r")))
e2348bcb 2968 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 2969 "TARGET_32BIT"
e2348bcb 2970 "@
97499065 2971 bic%?\\t%Q0, %Q1, %2
f6ebffac 2972 #"
a0f94409 2973 ; (not (zero_extend ...)) allows us to just copy the high word from
2974 ; operand1 to operand0.
25f905c2 2975 "TARGET_32BIT
a0f94409 2976 && reload_completed
2977 && operands[0] != operands[1]"
5a097f7d 2978 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
a0f94409 2979 (set (match_dup 3) (match_dup 4))]
2980 "
2981 {
2982 operands[3] = gen_highpart (SImode, operands[0]);
2983 operands[0] = gen_lowpart (SImode, operands[0]);
2984 operands[4] = gen_highpart (SImode, operands[1]);
2985 operands[1] = gen_lowpart (SImode, operands[1]);
2986 }"
0d66636f 2987 [(set_attr "length" "4,8")
d952d547 2988 (set_attr "predicable" "yes")
1b7da4ac 2989 (set_attr "predicable_short_it" "no")
2990 (set_attr "type" "multiple")]
0d66636f 2991)
d952d547 2992
d8cd5fa0 2993(define_insn_and_split "*anddi_notdi_zesidi"
2994 [(set (match_operand:DI 0 "s_register_operand" "=r")
2995 (and:DI (not:DI (match_operand:DI 2 "s_register_operand" "r"))
2996 (zero_extend:DI
2997 (match_operand:SI 1 "s_register_operand" "r"))))]
2998 "TARGET_32BIT"
2999 "#"
3000 "TARGET_32BIT && reload_completed"
3001 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
3002 (set (match_dup 3) (const_int 0))]
3003 "
3004 {
3005 operands[3] = gen_highpart (SImode, operands[0]);
3006 operands[0] = gen_lowpart (SImode, operands[0]);
3007 operands[2] = gen_lowpart (SImode, operands[2]);
3008 }"
3009 [(set_attr "length" "8")
3010 (set_attr "predicable" "yes")
3011 (set_attr "predicable_short_it" "no")
3012 (set_attr "type" "multiple")]
3013)
3014
a0f94409 3015(define_insn_and_split "*anddi_notsesidi_di"
9c08d1fa 3016 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3017 (and:DI (not:DI (sign_extend:DI
3018 (match_operand:SI 2 "s_register_operand" "r,r")))
5a097f7d 3019 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 3020 "TARGET_32BIT"
f6ebffac 3021 "#"
25f905c2 3022 "TARGET_32BIT && reload_completed"
5a097f7d 3023 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
a0f94409 3024 (set (match_dup 3) (and:SI (not:SI
3025 (ashiftrt:SI (match_dup 2) (const_int 31)))
3026 (match_dup 4)))]
3027 "
3028 {
3029 operands[3] = gen_highpart (SImode, operands[0]);
3030 operands[0] = gen_lowpart (SImode, operands[0]);
3031 operands[4] = gen_highpart (SImode, operands[1]);
3032 operands[1] = gen_lowpart (SImode, operands[1]);
3033 }"
0d66636f 3034 [(set_attr "length" "8")
d952d547 3035 (set_attr "predicable" "yes")
1b7da4ac 3036 (set_attr "predicable_short_it" "no")
3037 (set_attr "type" "multiple")]
0d66636f 3038)
d952d547 3039
8a18b90c 3040(define_insn "andsi_notsi_si"
9c08d1fa 3041 [(set (match_operand:SI 0 "s_register_operand" "=r")
3042 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
3043 (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 3044 "TARGET_32BIT"
0d66636f 3045 "bic%?\\t%0, %1, %2"
d952d547 3046 [(set_attr "predicable" "yes")
1b7da4ac 3047 (set_attr "predicable_short_it" "no")
3048 (set_attr "type" "logic_reg")]
0d66636f 3049)
b11cae9e 3050
8a18b90c 3051(define_insn "andsi_not_shiftsi_si"
a2cd141b 3052 [(set (match_operand:SI 0 "s_register_operand" "=r")
3053 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
3054 [(match_operand:SI 2 "s_register_operand" "r")
3055 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
3056 (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 3057 "TARGET_ARM"
6c4c2133 3058 "bic%?\\t%0, %1, %2%S4"
344495ea 3059 [(set_attr "predicable" "yes")
331beb1a 3060 (set_attr "shift" "2")
a2cd141b 3061 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
d82e788e 3062 (const_string "logic_shift_imm")
3063 (const_string "logic_shift_reg")))]
6c4c2133 3064)
8a18b90c 3065
9ed784d8 3066;; Shifted bics pattern used to set up CC status register and not reusing
3067;; bics output. Pattern restricts Thumb2 shift operand as bics for Thumb2
3068;; does not support shift by register.
3069(define_insn "andsi_not_shiftsi_si_scc_no_reuse"
3070 [(set (reg:CC_NOOV CC_REGNUM)
3071 (compare:CC_NOOV
3072 (and:SI (not:SI (match_operator:SI 0 "shift_operator"
3073 [(match_operand:SI 1 "s_register_operand" "r")
3074 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
3075 (match_operand:SI 3 "s_register_operand" "r"))
3076 (const_int 0)))
3077 (clobber (match_scratch:SI 4 "=r"))]
3078 "TARGET_ARM || (TARGET_THUMB2 && CONST_INT_P (operands[2]))"
3ef90e77 3079 "bics%?\\t%4, %3, %1%S0"
9ed784d8 3080 [(set_attr "predicable" "yes")
3081 (set_attr "predicable_short_it" "no")
3082 (set_attr "conds" "set")
3083 (set_attr "shift" "1")
3084 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3085 (const_string "logic_shift_imm")
3086 (const_string "logic_shift_reg")))]
3087)
3088
3089;; Same as andsi_not_shiftsi_si_scc_no_reuse, but the bics result is also
3090;; getting reused later.
3091(define_insn "andsi_not_shiftsi_si_scc"
3092 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
3093 (compare:CC_NOOV
3094 (and:SI (not:SI (match_operator:SI 0 "shift_operator"
3095 [(match_operand:SI 1 "s_register_operand" "r")
3096 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
3097 (match_operand:SI 3 "s_register_operand" "r"))
3098 (const_int 0)))
3099 (set (match_operand:SI 4 "s_register_operand" "=r")
3100 (and:SI (not:SI (match_op_dup 0
3101 [(match_dup 1)
3102 (match_dup 2)]))
3103 (match_dup 3)))])]
3104 "TARGET_ARM || (TARGET_THUMB2 && CONST_INT_P (operands[2]))"
3ef90e77 3105 "bics%?\\t%4, %3, %1%S0"
9ed784d8 3106 [(set_attr "predicable" "yes")
3107 (set_attr "predicable_short_it" "no")
3108 (set_attr "conds" "set")
3109 (set_attr "shift" "1")
3110 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3111 (const_string "logic_shift_imm")
3112 (const_string "logic_shift_reg")))]
3113)
3114
f7fbdd4a 3115(define_insn "*andsi_notsi_si_compare0"
bd5b4116 3116 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 3117 (compare:CC_NOOV
3118 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
3119 (match_operand:SI 1 "s_register_operand" "r"))
3120 (const_int 0)))
9c08d1fa 3121 (set (match_operand:SI 0 "s_register_operand" "=r")
3122 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
25f905c2 3123 "TARGET_32BIT"
3ef90e77 3124 "bics\\t%0, %1, %2"
d82e788e 3125 [(set_attr "conds" "set")
3126 (set_attr "type" "logics_shift_reg")]
0d66636f 3127)
9c08d1fa 3128
f7fbdd4a 3129(define_insn "*andsi_notsi_si_compare0_scratch"
bd5b4116 3130 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 3131 (compare:CC_NOOV
3132 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
3133 (match_operand:SI 1 "s_register_operand" "r"))
3134 (const_int 0)))
9c08d1fa 3135 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 3136 "TARGET_32BIT"
3ef90e77 3137 "bics\\t%0, %1, %2"
d82e788e 3138 [(set_attr "conds" "set")
3139 (set_attr "type" "logics_shift_reg")]
0d66636f 3140)
9c08d1fa 3141
e2669ea7 3142(define_expand "iordi3"
3143 [(set (match_operand:DI 0 "s_register_operand" "")
3144 (ior:DI (match_operand:DI 1 "s_register_operand" "")
3145 (match_operand:DI 2 "neon_logic_op2" "")))]
3146 "TARGET_32BIT"
0d84c6e5 3147 "
3148 if (!TARGET_NEON && !TARGET_IWMMXT)
3149 {
3150 rtx low = simplify_gen_binary (IOR, SImode,
3151 gen_lowpart (SImode, operands[1]),
3152 gen_lowpart (SImode, operands[2]));
3153 rtx high = simplify_gen_binary (IOR, SImode,
3154 gen_highpart (SImode, operands[1]),
3155 gen_highpart_mode (SImode, DImode,
3156 operands[2]));
3157
3158 emit_insn (gen_rtx_SET (gen_lowpart (SImode, operands[0]), low));
3159 emit_insn (gen_rtx_SET (gen_highpart (SImode, operands[0]), high));
3160
3161 DONE;
3162 }
3163 /* Otherwise expand pattern as above. */
3164 "
e2669ea7 3165)
3166
74d6113f 3167(define_insn_and_split "*iordi3_insn"
3168 [(set (match_operand:DI 0 "s_register_operand" "=w,w ,&r,&r,&r,&r,?w,?w")
3169 (ior:DI (match_operand:DI 1 "s_register_operand" "%w,0 ,0 ,r ,0 ,r ,w ,0")
e0fe6977 3170 (match_operand:DI 2 "arm_iordi_operand_neon" "w ,Dl,r ,r ,Df,Df,w ,Dl")))]
74d6113f 3171 "TARGET_32BIT && !TARGET_IWMMXT"
3172 {
3173 switch (which_alternative)
3174 {
3175 case 0: /* fall through */
3176 case 6: return "vorr\t%P0, %P1, %P2";
3177 case 1: /* fall through */
3178 case 7: return neon_output_logic_immediate ("vorr", &operands[2],
3179 DImode, 0, VALID_NEON_QREG_MODE (DImode));
3180 case 2:
3181 case 3:
3182 case 4:
3183 case 5:
3184 return "#";
3185 default: gcc_unreachable ();
3186 }
3187 }
3188 "TARGET_32BIT && !TARGET_IWMMXT && reload_completed
3189 && !(IS_VFP_REGNUM (REGNO (operands[0])))"
3190 [(set (match_dup 3) (match_dup 4))
3191 (set (match_dup 5) (match_dup 6))]
3192 "
3193 {
3194 operands[3] = gen_lowpart (SImode, operands[0]);
3195 operands[5] = gen_highpart (SImode, operands[0]);
3196
3197 operands[4] = simplify_gen_binary (IOR, SImode,
3198 gen_lowpart (SImode, operands[1]),
3199 gen_lowpart (SImode, operands[2]));
3200 operands[6] = simplify_gen_binary (IOR, SImode,
3201 gen_highpart (SImode, operands[1]),
3202 gen_highpart_mode (SImode, DImode, operands[2]));
3203
3204 }"
32093010 3205 [(set_attr "type" "neon_logic,neon_logic,multiple,multiple,multiple,\
3206 multiple,neon_logic,neon_logic")
e0fe6977 3207 (set_attr "length" "*,*,8,8,8,8,*,*")
74d6113f 3208 (set_attr "arch" "neon_for_64bits,neon_for_64bits,*,*,*,*,avoid_neon_for_64bits,avoid_neon_for_64bits")]
cffb2a26 3209)
9c08d1fa 3210
f7fbdd4a 3211(define_insn "*iordi_zesidi_di"
9c08d1fa 3212 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3213 (ior:DI (zero_extend:DI
3214 (match_operand:SI 2 "s_register_operand" "r,r"))
e2348bcb 3215 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 3216 "TARGET_32BIT"
e2348bcb 3217 "@
97499065 3218 orr%?\\t%Q0, %Q1, %2
f6ebffac 3219 #"
0d66636f 3220 [(set_attr "length" "4,8")
d952d547 3221 (set_attr "predicable" "yes")
1b7da4ac 3222 (set_attr "predicable_short_it" "no")
3223 (set_attr "type" "logic_reg,multiple")]
cffb2a26 3224)
9c08d1fa 3225
f7fbdd4a 3226(define_insn "*iordi_sesidi_di"
9c08d1fa 3227 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3228 (ior:DI (sign_extend:DI
3229 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 3230 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 3231 "TARGET_32BIT"
f6ebffac 3232 "#"
0d66636f 3233 [(set_attr "length" "8")
1b7da4ac 3234 (set_attr "predicable" "yes")
3235 (set_attr "type" "multiple")]
cffb2a26 3236)
9c08d1fa 3237
87b22bf7 3238(define_expand "iorsi3"
cffb2a26 3239 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3240 (ior:SI (match_operand:SI 1 "s_register_operand" "")
3241 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 3242 "TARGET_EITHER"
87b22bf7 3243 "
0438d37f 3244 if (CONST_INT_P (operands[2]))
87b22bf7 3245 {
25f905c2 3246 if (TARGET_32BIT)
cffb2a26 3247 {
17202aa5 3248 if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[2]), IOR))
3249 operands[2] = force_reg (SImode, operands[2]);
3250 else
3251 {
3252 arm_split_constant (IOR, SImode, NULL_RTX,
3253 INTVAL (operands[2]), operands[0],
3254 operands[1],
3255 optimize && can_create_pseudo_p ());
3256 DONE;
3257 }
cffb2a26 3258 }
25f905c2 3259 else /* TARGET_THUMB1 */
923ffadb 3260 {
3261 rtx tmp = force_reg (SImode, operands[2]);
3262 if (rtx_equal_p (operands[0], operands[1]))
3263 operands[2] = tmp;
3264 else
3265 {
3266 operands[2] = operands[1];
3267 operands[1] = tmp;
3268 }
3269 }
87b22bf7 3270 }
cffb2a26 3271 "
3272)
87b22bf7 3273
d5d4dc8d 3274(define_insn_and_split "*iorsi3_insn"
29e234a3 3275 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r,r,r")
3276 (ior:SI (match_operand:SI 1 "s_register_operand" "%r,0,r,r,r")
3277 (match_operand:SI 2 "reg_or_int_operand" "I,l,K,r,?n")))]
d5d4dc8d 3278 "TARGET_32BIT"
87b22bf7 3279 "@
29e234a3 3280 orr%?\\t%0, %1, %2
87b22bf7 3281 orr%?\\t%0, %1, %2
d5d4dc8d 3282 orn%?\\t%0, %1, #%B2
65f68e55 3283 orr%?\\t%0, %1, %2
87b22bf7 3284 #"
d5d4dc8d 3285 "TARGET_32BIT
0438d37f 3286 && CONST_INT_P (operands[2])
d5d4dc8d 3287 && !(const_ok_for_arm (INTVAL (operands[2]))
3288 || (TARGET_THUMB2 && const_ok_for_arm (~INTVAL (operands[2]))))"
a0f94409 3289 [(clobber (const_int 0))]
d5d4dc8d 3290{
29e234a3 3291 arm_split_constant (IOR, SImode, curr_insn,
96f57e36 3292 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 3293 DONE;
d5d4dc8d 3294}
29e234a3 3295 [(set_attr "length" "4,4,4,4,16")
3296 (set_attr "arch" "32,t2,t2,32,32")
65f68e55 3297 (set_attr "predicable" "yes")
29e234a3 3298 (set_attr "predicable_short_it" "no,yes,no,no,no")
d82e788e 3299 (set_attr "type" "logic_imm,logic_reg,logic_imm,logic_reg,logic_reg")]
65f68e55 3300)
cffb2a26 3301
a0f94409 3302(define_peephole2
3303 [(match_scratch:SI 3 "r")
372575c7 3304 (set (match_operand:SI 0 "arm_general_register_operand" "")
3305 (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
87b22bf7 3306 (match_operand:SI 2 "const_int_operand" "")))]
90560cad 3307 "TARGET_ARM
a0f94409 3308 && !const_ok_for_arm (INTVAL (operands[2]))
3309 && const_ok_for_arm (~INTVAL (operands[2]))"
3310 [(set (match_dup 3) (match_dup 2))
3311 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
3312 ""
215b30b3 3313)
a0f94409 3314
f7fbdd4a 3315(define_insn "*iorsi3_compare0"
bd5b4116 3316 [(set (reg:CC_NOOV CC_REGNUM)
65f68e55 3317 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r,r")
3318 (match_operand:SI 2 "arm_rhs_operand" "I,r"))
9c08d1fa 3319 (const_int 0)))
65f68e55 3320 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 3321 (ior:SI (match_dup 1) (match_dup 2)))]
25f905c2 3322 "TARGET_32BIT"
3ef90e77 3323 "orrs%?\\t%0, %1, %2"
65f68e55 3324 [(set_attr "conds" "set")
d82e788e 3325 (set_attr "type" "logics_imm,logics_reg")]
cffb2a26 3326)
9c08d1fa 3327
f7fbdd4a 3328(define_insn "*iorsi3_compare0_scratch"
bd5b4116 3329 [(set (reg:CC_NOOV CC_REGNUM)
65f68e55 3330 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r,r")
3331 (match_operand:SI 2 "arm_rhs_operand" "I,r"))
9c08d1fa 3332 (const_int 0)))
65f68e55 3333 (clobber (match_scratch:SI 0 "=r,r"))]
25f905c2 3334 "TARGET_32BIT"
3ef90e77 3335 "orrs%?\\t%0, %1, %2"
65f68e55 3336 [(set_attr "conds" "set")
d82e788e 3337 (set_attr "type" "logics_imm,logics_reg")]
0d66636f 3338)
9c08d1fa 3339
e2669ea7 3340(define_expand "xordi3"
3341 [(set (match_operand:DI 0 "s_register_operand" "")
3342 (xor:DI (match_operand:DI 1 "s_register_operand" "")
8ee7dc6f 3343 (match_operand:DI 2 "arm_xordi_operand" "")))]
e2669ea7 3344 "TARGET_32BIT"
8df5e205 3345 {
3346 /* The iWMMXt pattern for xordi3 accepts only register operands but we want
3347 to reuse this expander for all TARGET_32BIT targets so just force the
3348 constants into a register. Unlike for the anddi3 and iordi3 there are
3349 no NEON instructions that take an immediate. */
3350 if (TARGET_IWMMXT && !REG_P (operands[2]))
3351 operands[2] = force_reg (DImode, operands[2]);
0d84c6e5 3352 if (!TARGET_NEON && !TARGET_IWMMXT)
3353 {
3354 rtx low = simplify_gen_binary (XOR, SImode,
3355 gen_lowpart (SImode, operands[1]),
3356 gen_lowpart (SImode, operands[2]));
3357 rtx high = simplify_gen_binary (XOR, SImode,
3358 gen_highpart (SImode, operands[1]),
3359 gen_highpart_mode (SImode, DImode,
3360 operands[2]));
3361
3362 emit_insn (gen_rtx_SET (gen_lowpart (SImode, operands[0]), low));
3363 emit_insn (gen_rtx_SET (gen_highpart (SImode, operands[0]), high));
3364
3365 DONE;
3366 }
3367 /* Otherwise expand pattern as above. */
8df5e205 3368 }
e2669ea7 3369)
3370
8ee7dc6f 3371(define_insn_and_split "*xordi3_insn"
3372 [(set (match_operand:DI 0 "s_register_operand" "=w,&r,&r,&r,&r,?w")
205c3b0a 3373 (xor:DI (match_operand:DI 1 "s_register_operand" "%w ,0,r ,0 ,r ,w")
8ee7dc6f 3374 (match_operand:DI 2 "arm_xordi_operand" "w ,r ,r ,Dg,Dg,w")))]
3375 "TARGET_32BIT && !TARGET_IWMMXT"
3376{
3377 switch (which_alternative)
3378 {
3379 case 1:
3380 case 2:
3381 case 3:
3382 case 4: /* fall through */
3383 return "#";
3384 case 0: /* fall through */
3385 case 5: return "veor\t%P0, %P1, %P2";
3386 default: gcc_unreachable ();
3387 }
3388}
3389 "TARGET_32BIT && !TARGET_IWMMXT && reload_completed
3390 && !(IS_VFP_REGNUM (REGNO (operands[0])))"
3391 [(set (match_dup 3) (match_dup 4))
3392 (set (match_dup 5) (match_dup 6))]
3393 "
3394 {
3395 operands[3] = gen_lowpart (SImode, operands[0]);
3396 operands[5] = gen_highpart (SImode, operands[0]);
3397
3398 operands[4] = simplify_gen_binary (XOR, SImode,
3399 gen_lowpart (SImode, operands[1]),
3400 gen_lowpart (SImode, operands[2]));
3401 operands[6] = simplify_gen_binary (XOR, SImode,
3402 gen_highpart (SImode, operands[1]),
3403 gen_highpart_mode (SImode, DImode, operands[2]));
3404
3405 }"
3406 [(set_attr "length" "*,8,8,8,8,*")
32093010 3407 (set_attr "type" "neon_logic,multiple,multiple,multiple,multiple,neon_logic")
8ee7dc6f 3408 (set_attr "arch" "neon_for_64bits,*,*,*,*,avoid_neon_for_64bits")]
cffb2a26 3409)
9c08d1fa 3410
f7fbdd4a 3411(define_insn "*xordi_zesidi_di"
9c08d1fa 3412 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3413 (xor:DI (zero_extend:DI
3414 (match_operand:SI 2 "s_register_operand" "r,r"))
e2348bcb 3415 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 3416 "TARGET_32BIT"
e2348bcb 3417 "@
97499065 3418 eor%?\\t%Q0, %Q1, %2
f6ebffac 3419 #"
0d66636f 3420 [(set_attr "length" "4,8")
d952d547 3421 (set_attr "predicable" "yes")
1b7da4ac 3422 (set_attr "predicable_short_it" "no")
3423 (set_attr "type" "logic_reg")]
cffb2a26 3424)
9c08d1fa 3425
f7fbdd4a 3426(define_insn "*xordi_sesidi_di"
9c08d1fa 3427 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3428 (xor:DI (sign_extend:DI
3429 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 3430 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 3431 "TARGET_32BIT"
f6ebffac 3432 "#"
0d66636f 3433 [(set_attr "length" "8")
1b7da4ac 3434 (set_attr "predicable" "yes")
3435 (set_attr "type" "multiple")]
cffb2a26 3436)
9c08d1fa 3437
cffb2a26 3438(define_expand "xorsi3"
3439 [(set (match_operand:SI 0 "s_register_operand" "")
3440 (xor:SI (match_operand:SI 1 "s_register_operand" "")
923ffadb 3441 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 3442 "TARGET_EITHER"
0438d37f 3443 "if (CONST_INT_P (operands[2]))
923ffadb 3444 {
3445 if (TARGET_32BIT)
3446 {
17202aa5 3447 if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[2]), XOR))
3448 operands[2] = force_reg (SImode, operands[2]);
3449 else
3450 {
3451 arm_split_constant (XOR, SImode, NULL_RTX,
3452 INTVAL (operands[2]), operands[0],
3453 operands[1],
3454 optimize && can_create_pseudo_p ());
3455 DONE;
3456 }
923ffadb 3457 }
3458 else /* TARGET_THUMB1 */
3459 {
3460 rtx tmp = force_reg (SImode, operands[2]);
3461 if (rtx_equal_p (operands[0], operands[1]))
3462 operands[2] = tmp;
3463 else
3464 {
3465 operands[2] = operands[1];
3466 operands[1] = tmp;
3467 }
3468 }
3469 }"
cffb2a26 3470)
3471
5dcb35d9 3472(define_insn_and_split "*arm_xorsi3"
29e234a3 3473 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r,r")
3474 (xor:SI (match_operand:SI 1 "s_register_operand" "%r,0,r,r")
3475 (match_operand:SI 2 "reg_or_int_operand" "I,l,r,?n")))]
25f905c2 3476 "TARGET_32BIT"
5dcb35d9 3477 "@
29e234a3 3478 eor%?\\t%0, %1, %2
65f68e55 3479 eor%?\\t%0, %1, %2
5dcb35d9 3480 eor%?\\t%0, %1, %2
3481 #"
3482 "TARGET_32BIT
0438d37f 3483 && CONST_INT_P (operands[2])
5dcb35d9 3484 && !const_ok_for_arm (INTVAL (operands[2]))"
3485 [(clobber (const_int 0))]
3486{
3487 arm_split_constant (XOR, SImode, curr_insn,
3488 INTVAL (operands[2]), operands[0], operands[1], 0);
3489 DONE;
3490}
29e234a3 3491 [(set_attr "length" "4,4,4,16")
65f68e55 3492 (set_attr "predicable" "yes")
29e234a3 3493 (set_attr "predicable_short_it" "no,yes,no,no")
1b7da4ac 3494 (set_attr "type" "logic_imm,logic_reg,logic_reg,multiple")]
cffb2a26 3495)
3496
f7fbdd4a 3497(define_insn "*xorsi3_compare0"
bd5b4116 3498 [(set (reg:CC_NOOV CC_REGNUM)
65f68e55 3499 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r,r")
3500 (match_operand:SI 2 "arm_rhs_operand" "I,r"))
9c08d1fa 3501 (const_int 0)))
65f68e55 3502 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 3503 (xor:SI (match_dup 1) (match_dup 2)))]
25f905c2 3504 "TARGET_32BIT"
3ef90e77 3505 "eors%?\\t%0, %1, %2"
65f68e55 3506 [(set_attr "conds" "set")
d82e788e 3507 (set_attr "type" "logics_imm,logics_reg")]
0d66636f 3508)
9c08d1fa 3509
f7fbdd4a 3510(define_insn "*xorsi3_compare0_scratch"
bd5b4116 3511 [(set (reg:CC_NOOV CC_REGNUM)
65f68e55 3512 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r,r")
3513 (match_operand:SI 1 "arm_rhs_operand" "I,r"))
9c08d1fa 3514 (const_int 0)))]
25f905c2 3515 "TARGET_32BIT"
40dbec34 3516 "teq%?\\t%0, %1"
65f68e55 3517 [(set_attr "conds" "set")
d82e788e 3518 (set_attr "type" "logics_imm,logics_reg")]
cffb2a26 3519)
9c08d1fa 3520
215b30b3 3521; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
3522; (NOT D) we can sometimes merge the final NOT into one of the following
3523; insns.
9c08d1fa 3524
3525(define_split
a058e94a 3526 [(set (match_operand:SI 0 "s_register_operand" "")
3527 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
3528 (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
3529 (match_operand:SI 3 "arm_rhs_operand" "")))
3530 (clobber (match_operand:SI 4 "s_register_operand" ""))]
25f905c2 3531 "TARGET_32BIT"
9c08d1fa 3532 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
3533 (not:SI (match_dup 3))))
3534 (set (match_dup 0) (not:SI (match_dup 4)))]
3535 ""
3536)
3537
ba6a3b2f 3538(define_insn_and_split "*andsi_iorsi3_notsi"
9c08d1fa 3539 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
e5fea38e 3540 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "%0,r,r")
9c08d1fa 3541 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
3542 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
25f905c2 3543 "TARGET_32BIT"
ba6a3b2f 3544 "#" ; "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
3545 "&& reload_completed"
3546 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
054fd237 3547 (set (match_dup 0) (and:SI (match_dup 4) (match_dup 5)))]
3548 {
3549 /* If operands[3] is a constant make sure to fold the NOT into it
3550 to avoid creating a NOT of a CONST_INT. */
3551 rtx not_rtx = simplify_gen_unary (NOT, SImode, operands[3], SImode);
3552 if (CONST_INT_P (not_rtx))
3553 {
3554 operands[4] = operands[0];
3555 operands[5] = not_rtx;
3556 }
3557 else
3558 {
3559 operands[5] = operands[0];
3560 operands[4] = not_rtx;
3561 }
3562 }
0d66636f 3563 [(set_attr "length" "8")
25f905c2 3564 (set_attr "ce_count" "2")
d952d547 3565 (set_attr "predicable" "yes")
1b7da4ac 3566 (set_attr "predicable_short_it" "no")
3567 (set_attr "type" "multiple")]
cffb2a26 3568)
9c08d1fa 3569
25f905c2 3570; ??? Are these four splitters still beneficial when the Thumb-2 bitfield
3571; insns are available?
d7863cfe 3572(define_split
3573 [(set (match_operand:SI 0 "s_register_operand" "")
3574 (match_operator:SI 1 "logical_binary_operator"
3575 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
3576 (match_operand:SI 3 "const_int_operand" "")
3577 (match_operand:SI 4 "const_int_operand" ""))
3578 (match_operator:SI 9 "logical_binary_operator"
3579 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3580 (match_operand:SI 6 "const_int_operand" ""))
3581 (match_operand:SI 7 "s_register_operand" "")])]))
3582 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3583 "TARGET_32BIT
d7863cfe 3584 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3585 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3586 [(set (match_dup 8)
3587 (match_op_dup 1
3588 [(ashift:SI (match_dup 2) (match_dup 4))
3589 (match_dup 5)]))
3590 (set (match_dup 0)
3591 (match_op_dup 1
3592 [(lshiftrt:SI (match_dup 8) (match_dup 6))
3593 (match_dup 7)]))]
3594 "
3595 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3596")
3597
3598(define_split
3599 [(set (match_operand:SI 0 "s_register_operand" "")
3600 (match_operator:SI 1 "logical_binary_operator"
3601 [(match_operator:SI 9 "logical_binary_operator"
3602 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3603 (match_operand:SI 6 "const_int_operand" ""))
3604 (match_operand:SI 7 "s_register_operand" "")])
3605 (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
3606 (match_operand:SI 3 "const_int_operand" "")
3607 (match_operand:SI 4 "const_int_operand" ""))]))
3608 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3609 "TARGET_32BIT
d7863cfe 3610 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3611 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3612 [(set (match_dup 8)
3613 (match_op_dup 1
3614 [(ashift:SI (match_dup 2) (match_dup 4))
3615 (match_dup 5)]))
3616 (set (match_dup 0)
3617 (match_op_dup 1
3618 [(lshiftrt:SI (match_dup 8) (match_dup 6))
3619 (match_dup 7)]))]
3620 "
3621 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3622")
3623
3624(define_split
3625 [(set (match_operand:SI 0 "s_register_operand" "")
3626 (match_operator:SI 1 "logical_binary_operator"
3627 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
3628 (match_operand:SI 3 "const_int_operand" "")
3629 (match_operand:SI 4 "const_int_operand" ""))
3630 (match_operator:SI 9 "logical_binary_operator"
3631 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3632 (match_operand:SI 6 "const_int_operand" ""))
3633 (match_operand:SI 7 "s_register_operand" "")])]))
3634 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3635 "TARGET_32BIT
d7863cfe 3636 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3637 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3638 [(set (match_dup 8)
3639 (match_op_dup 1
3640 [(ashift:SI (match_dup 2) (match_dup 4))
3641 (match_dup 5)]))
3642 (set (match_dup 0)
3643 (match_op_dup 1
3644 [(ashiftrt:SI (match_dup 8) (match_dup 6))
3645 (match_dup 7)]))]
3646 "
3647 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3648")
3649
3650(define_split
3651 [(set (match_operand:SI 0 "s_register_operand" "")
3652 (match_operator:SI 1 "logical_binary_operator"
3653 [(match_operator:SI 9 "logical_binary_operator"
3654 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3655 (match_operand:SI 6 "const_int_operand" ""))
3656 (match_operand:SI 7 "s_register_operand" "")])
3657 (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
3658 (match_operand:SI 3 "const_int_operand" "")
3659 (match_operand:SI 4 "const_int_operand" ""))]))
3660 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3661 "TARGET_32BIT
d7863cfe 3662 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3663 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3664 [(set (match_dup 8)
3665 (match_op_dup 1
3666 [(ashift:SI (match_dup 2) (match_dup 4))
3667 (match_dup 5)]))
3668 (set (match_dup 0)
3669 (match_op_dup 1
3670 [(ashiftrt:SI (match_dup 8) (match_dup 6))
3671 (match_dup 7)]))]
3672 "
3673 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3674")
9c08d1fa 3675\f
3676
3677;; Minimum and maximum insns
3678
8b9dc177 3679(define_expand "smaxsi3"
3680 [(parallel [
3681 (set (match_operand:SI 0 "s_register_operand" "")
3682 (smax:SI (match_operand:SI 1 "s_register_operand" "")
3683 (match_operand:SI 2 "arm_rhs_operand" "")))
3684 (clobber (reg:CC CC_REGNUM))])]
25f905c2 3685 "TARGET_32BIT"
8b9dc177 3686 "
8774928b 3687 if (operands[2] == const0_rtx || operands[2] == constm1_rtx)
8b9dc177 3688 {
3689 /* No need for a clobber of the condition code register here. */
d1f9b275 3690 emit_insn (gen_rtx_SET (operands[0],
8b9dc177 3691 gen_rtx_SMAX (SImode, operands[1],
3692 operands[2])));
3693 DONE;
3694 }
3695")
3696
3697(define_insn "*smax_0"
3698 [(set (match_operand:SI 0 "s_register_operand" "=r")
3699 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3700 (const_int 0)))]
25f905c2 3701 "TARGET_32BIT"
8b9dc177 3702 "bic%?\\t%0, %1, %1, asr #31"
d952d547 3703 [(set_attr "predicable" "yes")
1b7da4ac 3704 (set_attr "predicable_short_it" "no")
3705 (set_attr "type" "logic_shift_reg")]
8b9dc177 3706)
3707
8774928b 3708(define_insn "*smax_m1"
3709 [(set (match_operand:SI 0 "s_register_operand" "=r")
3710 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3711 (const_int -1)))]
25f905c2 3712 "TARGET_32BIT"
8774928b 3713 "orr%?\\t%0, %1, %1, asr #31"
d952d547 3714 [(set_attr "predicable" "yes")
1b7da4ac 3715 (set_attr "predicable_short_it" "no")
3716 (set_attr "type" "logic_shift_reg")]
8774928b 3717)
3718
3dc953f2 3719(define_insn_and_split "*arm_smax_insn"
8b9dc177 3720 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3721 (smax:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3722 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
bd5b4116 3723 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3724 "TARGET_ARM"
3dc953f2 3725 "#"
3726 ; cmp\\t%1, %2\;movlt\\t%0, %2
3727 ; cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
3728 "TARGET_ARM"
3729 [(set (reg:CC CC_REGNUM)
3730 (compare:CC (match_dup 1) (match_dup 2)))
3731 (set (match_dup 0)
3732 (if_then_else:SI (ge:SI (reg:CC CC_REGNUM) (const_int 0))
3733 (match_dup 1)
3734 (match_dup 2)))]
3735 ""
cffb2a26 3736 [(set_attr "conds" "clob")
1b7da4ac 3737 (set_attr "length" "8,12")
3738 (set_attr "type" "multiple")]
cffb2a26 3739)
9c08d1fa 3740
8b9dc177 3741(define_expand "sminsi3"
3742 [(parallel [
3743 (set (match_operand:SI 0 "s_register_operand" "")
3744 (smin:SI (match_operand:SI 1 "s_register_operand" "")
3745 (match_operand:SI 2 "arm_rhs_operand" "")))
3746 (clobber (reg:CC CC_REGNUM))])]
25f905c2 3747 "TARGET_32BIT"
8b9dc177 3748 "
3749 if (operands[2] == const0_rtx)
3750 {
3751 /* No need for a clobber of the condition code register here. */
d1f9b275 3752 emit_insn (gen_rtx_SET (operands[0],
8b9dc177 3753 gen_rtx_SMIN (SImode, operands[1],
3754 operands[2])));
3755 DONE;
3756 }
3757")
3758
3759(define_insn "*smin_0"
3760 [(set (match_operand:SI 0 "s_register_operand" "=r")
3761 (smin:SI (match_operand:SI 1 "s_register_operand" "r")
3762 (const_int 0)))]
25f905c2 3763 "TARGET_32BIT"
8b9dc177 3764 "and%?\\t%0, %1, %1, asr #31"
d952d547 3765 [(set_attr "predicable" "yes")
1b7da4ac 3766 (set_attr "predicable_short_it" "no")
3767 (set_attr "type" "logic_shift_reg")]
8b9dc177 3768)
3769
3dc953f2 3770(define_insn_and_split "*arm_smin_insn"
8b9dc177 3771 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3772 (smin:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3773 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
bd5b4116 3774 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3775 "TARGET_ARM"
3dc953f2 3776 "#"
3777 ; cmp\\t%1, %2\;movge\\t%0, %2
3778 ; cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
3779 "TARGET_ARM"
3780 [(set (reg:CC CC_REGNUM)
3781 (compare:CC (match_dup 1) (match_dup 2)))
3782 (set (match_dup 0)
3783 (if_then_else:SI (lt:SI (reg:CC CC_REGNUM) (const_int 0))
3784 (match_dup 1)
3785 (match_dup 2)))]
3786 ""
0d66636f 3787 [(set_attr "conds" "clob")
1b7da4ac 3788 (set_attr "length" "8,12")
3789 (set_attr "type" "multiple,multiple")]
0d66636f 3790)
9c08d1fa 3791
25f905c2 3792(define_expand "umaxsi3"
3793 [(parallel [
3794 (set (match_operand:SI 0 "s_register_operand" "")
3795 (umax:SI (match_operand:SI 1 "s_register_operand" "")
3796 (match_operand:SI 2 "arm_rhs_operand" "")))
3797 (clobber (reg:CC CC_REGNUM))])]
3798 "TARGET_32BIT"
3799 ""
3800)
3801
3dc953f2 3802(define_insn_and_split "*arm_umaxsi3"
9c08d1fa 3803 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3804 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3805 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 3806 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3807 "TARGET_ARM"
3dc953f2 3808 "#"
3809 ; cmp\\t%1, %2\;movcc\\t%0, %2
3810 ; cmp\\t%1, %2\;movcs\\t%0, %1
3811 ; cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
3812 "TARGET_ARM"
3813 [(set (reg:CC CC_REGNUM)
3814 (compare:CC (match_dup 1) (match_dup 2)))
3815 (set (match_dup 0)
3816 (if_then_else:SI (geu:SI (reg:CC CC_REGNUM) (const_int 0))
3817 (match_dup 1)
3818 (match_dup 2)))]
3819 ""
0d66636f 3820 [(set_attr "conds" "clob")
1b7da4ac 3821 (set_attr "length" "8,8,12")
9f2c2a36 3822 (set_attr "type" "store_4")]
0d66636f 3823)
9c08d1fa 3824
25f905c2 3825(define_expand "uminsi3"
3826 [(parallel [
3827 (set (match_operand:SI 0 "s_register_operand" "")
3828 (umin:SI (match_operand:SI 1 "s_register_operand" "")
3829 (match_operand:SI 2 "arm_rhs_operand" "")))
3830 (clobber (reg:CC CC_REGNUM))])]
3831 "TARGET_32BIT"
3832 ""
3833)
3834
3dc953f2 3835(define_insn_and_split "*arm_uminsi3"
9c08d1fa 3836 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3837 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3838 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 3839 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3840 "TARGET_ARM"
3dc953f2 3841 "#"
3842 ; cmp\\t%1, %2\;movcs\\t%0, %2
3843 ; cmp\\t%1, %2\;movcc\\t%0, %1
3844 ; cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
3845 "TARGET_ARM"
3846 [(set (reg:CC CC_REGNUM)
3847 (compare:CC (match_dup 1) (match_dup 2)))
3848 (set (match_dup 0)
3849 (if_then_else:SI (ltu:SI (reg:CC CC_REGNUM) (const_int 0))
3850 (match_dup 1)
3851 (match_dup 2)))]
3852 ""
0d66636f 3853 [(set_attr "conds" "clob")
1b7da4ac 3854 (set_attr "length" "8,8,12")
9f2c2a36 3855 (set_attr "type" "store_4")]
0d66636f 3856)
9c08d1fa 3857
8a18b90c 3858(define_insn "*store_minmaxsi"
9c08d1fa 3859 [(set (match_operand:SI 0 "memory_operand" "=m")
3860 (match_operator:SI 3 "minmax_operator"
3861 [(match_operand:SI 1 "s_register_operand" "r")
3862 (match_operand:SI 2 "s_register_operand" "r")]))
bd5b4116 3863 (clobber (reg:CC CC_REGNUM))]
b207d152 3864 "TARGET_32BIT && optimize_function_for_size_p (cfun) && !arm_restrict_it"
9c08d1fa 3865 "*
dc55b8a9 3866 operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
3867 operands[1], operands[2]);
e2348bcb 3868 output_asm_insn (\"cmp\\t%1, %2\", operands);
25f905c2 3869 if (TARGET_THUMB2)
3870 output_asm_insn (\"ite\t%d3\", operands);
e2348bcb 3871 output_asm_insn (\"str%d3\\t%1, %0\", operands);
3872 output_asm_insn (\"str%D3\\t%2, %0\", operands);
3873 return \"\";
0d66636f 3874 "
3875 [(set_attr "conds" "clob")
25f905c2 3876 (set (attr "length")
3877 (if_then_else (eq_attr "is_thumb" "yes")
3878 (const_int 14)
3879 (const_int 12)))
9f2c2a36 3880 (set_attr "type" "store_4")]
0d66636f 3881)
9c08d1fa 3882
8a18b90c 3883; Reject the frame pointer in operand[1], since reloading this after
3884; it has been eliminated can cause carnage.
f7fbdd4a 3885(define_insn "*minmax_arithsi"
9c08d1fa 3886 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3887 (match_operator:SI 4 "shiftable_operator"
3888 [(match_operator:SI 5 "minmax_operator"
3889 [(match_operand:SI 2 "s_register_operand" "r,r")
3890 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
3891 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 3892 (clobber (reg:CC CC_REGNUM))]
7c36fe71 3893 "TARGET_32BIT && !arm_eliminable_register (operands[1]) && !arm_restrict_it"
9c08d1fa 3894 "*
0d66636f 3895 {
3896 enum rtx_code code = GET_CODE (operands[4]);
25f905c2 3897 bool need_else;
3898
3899 if (which_alternative != 0 || operands[3] != const0_rtx
ca0fc5a2 3900 || (code != PLUS && code != IOR && code != XOR))
25f905c2 3901 need_else = true;
3902 else
3903 need_else = false;
0d66636f 3904
dc55b8a9 3905 operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
3906 operands[2], operands[3]);
0d66636f 3907 output_asm_insn (\"cmp\\t%2, %3\", operands);
25f905c2 3908 if (TARGET_THUMB2)
3909 {
3910 if (need_else)
3911 output_asm_insn (\"ite\\t%d5\", operands);
3912 else
3913 output_asm_insn (\"it\\t%d5\", operands);
3914 }
0d66636f 3915 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
25f905c2 3916 if (need_else)
0d66636f 3917 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
3918 return \"\";
215b30b3 3919 }"
0d66636f 3920 [(set_attr "conds" "clob")
25f905c2 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")]
0d66636f 3926)
9c08d1fa 3927
4164bca1 3928; Reject the frame pointer in operand[1], since reloading this after
3929; it has been eliminated can cause carnage.
3930(define_insn_and_split "*minmax_arithsi_non_canon"
7c36fe71 3931 [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts")
4164bca1 3932 (minus:SI
7c36fe71 3933 (match_operand:SI 1 "s_register_operand" "0,?Ts")
4164bca1 3934 (match_operator:SI 4 "minmax_operator"
7c36fe71 3935 [(match_operand:SI 2 "s_register_operand" "Ts,Ts")
3936 (match_operand:SI 3 "arm_rhs_operand" "TsI,TsI")])))
4164bca1 3937 (clobber (reg:CC CC_REGNUM))]
7c36fe71 3938 "TARGET_32BIT && !arm_eliminable_register (operands[1])
3939 && !(arm_restrict_it && CONST_INT_P (operands[3]))"
4164bca1 3940 "#"
3941 "TARGET_32BIT && !arm_eliminable_register (operands[1]) && reload_completed"
3942 [(set (reg:CC CC_REGNUM)
3943 (compare:CC (match_dup 2) (match_dup 3)))
3944
3945 (cond_exec (match_op_dup 4 [(reg:CC CC_REGNUM) (const_int 0)])
3946 (set (match_dup 0)
3947 (minus:SI (match_dup 1)
3948 (match_dup 2))))
3949 (cond_exec (match_op_dup 5 [(reg:CC CC_REGNUM) (const_int 0)])
3950 (set (match_dup 0)
36ee0cde 3951 (match_dup 6)))]
4164bca1 3952 {
3754d046 3953 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
4164bca1 3954 operands[2], operands[3]);
3955 enum rtx_code rc = minmax_code (operands[4]);
3956 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode,
3957 operands[2], operands[3]);
3958
3959 if (mode == CCFPmode || mode == CCFPEmode)
3960 rc = reverse_condition_maybe_unordered (rc);
3961 else
3962 rc = reverse_condition (rc);
3963 operands[5] = gen_rtx_fmt_ee (rc, SImode, operands[2], operands[3]);
36ee0cde 3964 if (CONST_INT_P (operands[3]))
3965 operands[6] = plus_constant (SImode, operands[1], -INTVAL (operands[3]));
3966 else
3967 operands[6] = gen_rtx_MINUS (SImode, operands[1], operands[3]);
4164bca1 3968 }
3969 [(set_attr "conds" "clob")
3970 (set (attr "length")
3971 (if_then_else (eq_attr "is_thumb" "yes")
3972 (const_int 14)
1b7da4ac 3973 (const_int 12)))
3974 (set_attr "type" "multiple")]
4164bca1 3975)
3976
b49e3742 3977(define_code_iterator SAT [smin smax])
3978(define_code_iterator SATrev [smin smax])
3979(define_code_attr SATlo [(smin "1") (smax "2")])
3980(define_code_attr SAThi [(smin "2") (smax "1")])
3981
3982(define_insn "*satsi_<SAT:code>"
3983 [(set (match_operand:SI 0 "s_register_operand" "=r")
3984 (SAT:SI (SATrev:SI (match_operand:SI 3 "s_register_operand" "r")
3985 (match_operand:SI 1 "const_int_operand" "i"))
3986 (match_operand:SI 2 "const_int_operand" "i")))]
3987 "TARGET_32BIT && arm_arch6 && <SAT:CODE> != <SATrev:CODE>
3988 && arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>], NULL, NULL)"
3989{
3990 int mask;
3991 bool signed_sat;
3992 if (!arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>],
3993 &mask, &signed_sat))
3994 gcc_unreachable ();
3995
3996 operands[1] = GEN_INT (mask);
3997 if (signed_sat)
3998 return "ssat%?\t%0, %1, %3";
3999 else
4000 return "usat%?\t%0, %1, %3";
4001}
7c36fe71 4002 [(set_attr "predicable" "yes")
1b7da4ac 4003 (set_attr "predicable_short_it" "no")
4004 (set_attr "type" "alus_imm")]
bebe9bbb 4005)
b49e3742 4006
4007(define_insn "*satsi_<SAT:code>_shift"
4008 [(set (match_operand:SI 0 "s_register_operand" "=r")
4009 (SAT:SI (SATrev:SI (match_operator:SI 3 "sat_shift_operator"
4010 [(match_operand:SI 4 "s_register_operand" "r")
4011 (match_operand:SI 5 "const_int_operand" "i")])
4012 (match_operand:SI 1 "const_int_operand" "i"))
4013 (match_operand:SI 2 "const_int_operand" "i")))]
4014 "TARGET_32BIT && arm_arch6 && <SAT:CODE> != <SATrev:CODE>
4015 && arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>], NULL, NULL)"
4016{
4017 int mask;
4018 bool signed_sat;
4019 if (!arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>],
4020 &mask, &signed_sat))
4021 gcc_unreachable ();
4022
4023 operands[1] = GEN_INT (mask);
4024 if (signed_sat)
4025 return "ssat%?\t%0, %1, %4%S3";
4026 else
4027 return "usat%?\t%0, %1, %4%S3";
4028}
4029 [(set_attr "predicable" "yes")
7c36fe71 4030 (set_attr "predicable_short_it" "no")
b49e3742 4031 (set_attr "shift" "3")
d82e788e 4032 (set_attr "type" "logic_shift_reg")])
b11cae9e 4033\f
4034;; Shift and rotation insns
4035
a2cd141b 4036(define_expand "ashldi3"
4037 [(set (match_operand:DI 0 "s_register_operand" "")
4038 (ashift:DI (match_operand:DI 1 "s_register_operand" "")
aa06c51c 4039 (match_operand:SI 2 "general_operand" "")))]
25f905c2 4040 "TARGET_32BIT"
a2cd141b 4041 "
aa06c51c 4042 if (TARGET_NEON)
4043 {
4044 /* Delay the decision whether to use NEON or core-regs until
4045 register allocation. */
4046 emit_insn (gen_ashldi3_neon (operands[0], operands[1], operands[2]));
4047 DONE;
4048 }
4049 else
4050 {
4051 /* Only the NEON case can handle in-memory shift counts. */
4052 if (!reg_or_int_operand (operands[2], SImode))
4053 operands[2] = force_reg (SImode, operands[2]);
4054 }
4055
b805622c 4056 if (!CONST_INT_P (operands[2]) && TARGET_REALLY_IWMMXT)
ffcc986d 4057 ; /* No special preparation statements; expand pattern as above. */
4058 else
a2cd141b 4059 {
ffcc986d 4060 rtx scratch1, scratch2;
4061
ffcc986d 4062 /* Ideally we should use iwmmxt here if we could know that operands[1]
4063 ends up already living in an iwmmxt register. Otherwise it's
4064 cheaper to have the alternate code being generated than moving
4065 values to iwmmxt regs and back. */
4066
ffcc986d 4067 /* Expand operation using core-registers.
4068 'FAIL' would achieve the same thing, but this is a bit smarter. */
4069 scratch1 = gen_reg_rtx (SImode);
4070 scratch2 = gen_reg_rtx (SImode);
4071 arm_emit_coreregs_64bit_shift (ASHIFT, operands[0], operands[1],
4072 operands[2], scratch1, scratch2);
4073 DONE;
a2cd141b 4074 }
a2cd141b 4075 "
4076)
4077
87b22bf7 4078(define_expand "ashlsi3"
cffb2a26 4079 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 4080 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
4081 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 4082 "TARGET_EITHER"
87b22bf7 4083 "
0438d37f 4084 if (CONST_INT_P (operands[2])
8c4e8755 4085 && (UINTVAL (operands[2])) > 31)
87b22bf7 4086 {
4087 emit_insn (gen_movsi (operands[0], const0_rtx));
4088 DONE;
4089 }
cffb2a26 4090 "
4091)
4092
a2cd141b 4093(define_expand "ashrdi3"
4094 [(set (match_operand:DI 0 "s_register_operand" "")
4095 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
4096 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 4097 "TARGET_32BIT"
a2cd141b 4098 "
aa06c51c 4099 if (TARGET_NEON)
4100 {
4101 /* Delay the decision whether to use NEON or core-regs until
4102 register allocation. */
4103 emit_insn (gen_ashrdi3_neon (operands[0], operands[1], operands[2]));
4104 DONE;
4105 }
4106
b805622c 4107 if (!CONST_INT_P (operands[2]) && TARGET_REALLY_IWMMXT)
ffcc986d 4108 ; /* No special preparation statements; expand pattern as above. */
4109 else
a2cd141b 4110 {
ffcc986d 4111 rtx scratch1, scratch2;
4112
ffcc986d 4113 /* Ideally we should use iwmmxt here if we could know that operands[1]
4114 ends up already living in an iwmmxt register. Otherwise it's
4115 cheaper to have the alternate code being generated than moving
4116 values to iwmmxt regs and back. */
4117
ffcc986d 4118 /* Expand operation using core-registers.
4119 'FAIL' would achieve the same thing, but this is a bit smarter. */
4120 scratch1 = gen_reg_rtx (SImode);
4121 scratch2 = gen_reg_rtx (SImode);
4122 arm_emit_coreregs_64bit_shift (ASHIFTRT, operands[0], operands[1],
4123 operands[2], scratch1, scratch2);
4124 DONE;
a2cd141b 4125 }
a2cd141b 4126 "
4127)
4128
87b22bf7 4129(define_expand "ashrsi3"
cffb2a26 4130 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 4131 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
4132 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 4133 "TARGET_EITHER"
87b22bf7 4134 "
0438d37f 4135 if (CONST_INT_P (operands[2])
8c4e8755 4136 && UINTVAL (operands[2]) > 31)
87b22bf7 4137 operands[2] = GEN_INT (31);
cffb2a26 4138 "
4139)
4140
a2cd141b 4141(define_expand "lshrdi3"
4142 [(set (match_operand:DI 0 "s_register_operand" "")
4143 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
4144 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 4145 "TARGET_32BIT"
a2cd141b 4146 "
aa06c51c 4147 if (TARGET_NEON)
4148 {
4149 /* Delay the decision whether to use NEON or core-regs until
4150 register allocation. */
4151 emit_insn (gen_lshrdi3_neon (operands[0], operands[1], operands[2]));
4152 DONE;
4153 }
4154
b805622c 4155 if (!CONST_INT_P (operands[2]) && TARGET_REALLY_IWMMXT)
ffcc986d 4156 ; /* No special preparation statements; expand pattern as above. */
4157 else
a2cd141b 4158 {
ffcc986d 4159 rtx scratch1, scratch2;
4160
ffcc986d 4161 /* Ideally we should use iwmmxt here if we could know that operands[1]
4162 ends up already living in an iwmmxt register. Otherwise it's
4163 cheaper to have the alternate code being generated than moving
4164 values to iwmmxt regs and back. */
4165
ffcc986d 4166 /* Expand operation using core-registers.
4167 'FAIL' would achieve the same thing, but this is a bit smarter. */
4168 scratch1 = gen_reg_rtx (SImode);
4169 scratch2 = gen_reg_rtx (SImode);
4170 arm_emit_coreregs_64bit_shift (LSHIFTRT, operands[0], operands[1],
4171 operands[2], scratch1, scratch2);
4172 DONE;
a2cd141b 4173 }
a2cd141b 4174 "
4175)
4176
87b22bf7 4177(define_expand "lshrsi3"
cffb2a26 4178 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 4179 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
4180 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 4181 "TARGET_EITHER"
87b22bf7 4182 "
0438d37f 4183 if (CONST_INT_P (operands[2])
8c4e8755 4184 && (UINTVAL (operands[2])) > 31)
87b22bf7 4185 {
4186 emit_insn (gen_movsi (operands[0], const0_rtx));
4187 DONE;
4188 }
cffb2a26 4189 "
4190)
4191
87b22bf7 4192(define_expand "rotlsi3"
cffb2a26 4193 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 4194 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
4195 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 4196 "TARGET_32BIT"
87b22bf7 4197 "
0438d37f 4198 if (CONST_INT_P (operands[2]))
87b22bf7 4199 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
4200 else
b11cae9e 4201 {
87b22bf7 4202 rtx reg = gen_reg_rtx (SImode);
4203 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
4204 operands[2] = reg;
b11cae9e 4205 }
cffb2a26 4206 "
4207)
9c08d1fa 4208
87b22bf7 4209(define_expand "rotrsi3"
cffb2a26 4210 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 4211 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
4212 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 4213 "TARGET_EITHER"
87b22bf7 4214 "
25f905c2 4215 if (TARGET_32BIT)
cffb2a26 4216 {
0438d37f 4217 if (CONST_INT_P (operands[2])
8c4e8755 4218 && UINTVAL (operands[2]) > 31)
cffb2a26 4219 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
4220 }
25f905c2 4221 else /* TARGET_THUMB1 */
cffb2a26 4222 {
0438d37f 4223 if (CONST_INT_P (operands [2]))
cffb2a26 4224 operands [2] = force_reg (SImode, operands[2]);
4225 }
4226 "
4227)
87b22bf7 4228
cffb2a26 4229(define_insn "*arm_shiftsi3"
88c29385 4230 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r,r")
cffb2a26 4231 (match_operator:SI 3 "shift_operator"
88c29385 4232 [(match_operand:SI 1 "s_register_operand" "0,l,r,r")
4233 (match_operand:SI 2 "reg_or_int_operand" "l,M,M,r")]))]
25f905c2 4234 "TARGET_32BIT"
4235 "* return arm_output_shift(operands, 0);"
344495ea 4236 [(set_attr "predicable" "yes")
88c29385 4237 (set_attr "arch" "t2,t2,*,*")
4238 (set_attr "predicable_short_it" "yes,yes,no,no")
7c36fe71 4239 (set_attr "length" "4")
331beb1a 4240 (set_attr "shift" "1")
88c29385 4241 (set_attr "type" "alu_shift_reg,alu_shift_imm,alu_shift_imm,alu_shift_reg")]
6c4c2133 4242)
87b22bf7 4243
f7fbdd4a 4244(define_insn "*shiftsi3_compare0"
bd5b4116 4245 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 4246 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
6b6abc9c 4247 [(match_operand:SI 1 "s_register_operand" "r,r")
4248 (match_operand:SI 2 "arm_rhs_operand" "M,r")])
9c08d1fa 4249 (const_int 0)))
6b6abc9c 4250 (set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 4251 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
25f905c2 4252 "TARGET_32BIT"
4253 "* return arm_output_shift(operands, 1);"
344495ea 4254 [(set_attr "conds" "set")
331beb1a 4255 (set_attr "shift" "1")
d82e788e 4256 (set_attr "type" "alus_shift_imm,alus_shift_reg")]
0d66636f 4257)
9c08d1fa 4258
f7fbdd4a 4259(define_insn "*shiftsi3_compare0_scratch"
bd5b4116 4260 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 4261 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
6b6abc9c 4262 [(match_operand:SI 1 "s_register_operand" "r,r")
4263 (match_operand:SI 2 "arm_rhs_operand" "M,r")])
9c08d1fa 4264 (const_int 0)))
6b6abc9c 4265 (clobber (match_scratch:SI 0 "=r,r"))]
25f905c2 4266 "TARGET_32BIT"
4267 "* return arm_output_shift(operands, 1);"
344495ea 4268 [(set_attr "conds" "set")
6b6abc9c 4269 (set_attr "shift" "1")
d82e788e 4270 (set_attr "type" "shift_imm,shift_reg")]
0d66636f 4271)
9c08d1fa 4272
d5d4dc8d 4273(define_insn "*not_shiftsi"
4274 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 4275 (not:SI (match_operator:SI 3 "shift_operator"
d5d4dc8d 4276 [(match_operand:SI 1 "s_register_operand" "r,r")
4277 (match_operand:SI 2 "shift_amount_operand" "M,rM")])))]
4278 "TARGET_32BIT"
6c4c2133 4279 "mvn%?\\t%0, %1%S3"
344495ea 4280 [(set_attr "predicable" "yes")
d952d547 4281 (set_attr "predicable_short_it" "no")
331beb1a 4282 (set_attr "shift" "1")
d5d4dc8d 4283 (set_attr "arch" "32,a")
1aed5204 4284 (set_attr "type" "mvn_shift,mvn_shift_reg")])
9c08d1fa 4285
d5d4dc8d 4286(define_insn "*not_shiftsi_compare0"
bd5b4116 4287 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 4288 (compare:CC_NOOV
4289 (not:SI (match_operator:SI 3 "shift_operator"
4290 [(match_operand:SI 1 "s_register_operand" "r,r")
4291 (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
4292 (const_int 0)))
4293 (set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 4294 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
d5d4dc8d 4295 "TARGET_32BIT"
3ef90e77 4296 "mvns%?\\t%0, %1%S3"
344495ea 4297 [(set_attr "conds" "set")
331beb1a 4298 (set_attr "shift" "1")
d5d4dc8d 4299 (set_attr "arch" "32,a")
1aed5204 4300 (set_attr "type" "mvn_shift,mvn_shift_reg")])
9c08d1fa 4301
d5d4dc8d 4302(define_insn "*not_shiftsi_compare0_scratch"
bd5b4116 4303 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 4304 (compare:CC_NOOV
4305 (not:SI (match_operator:SI 3 "shift_operator"
4306 [(match_operand:SI 1 "s_register_operand" "r,r")
4307 (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
4308 (const_int 0)))
4309 (clobber (match_scratch:SI 0 "=r,r"))]
4310 "TARGET_32BIT"
3ef90e77 4311 "mvns%?\\t%0, %1%S3"
344495ea 4312 [(set_attr "conds" "set")
331beb1a 4313 (set_attr "shift" "1")
d5d4dc8d 4314 (set_attr "arch" "32,a")
1aed5204 4315 (set_attr "type" "mvn_shift,mvn_shift_reg")])
9c08d1fa 4316
cffb2a26 4317;; We don't really have extzv, but defining this using shifts helps
4318;; to reduce register pressure later on.
4319
4320(define_expand "extzv"
eb04cafb 4321 [(set (match_operand 0 "s_register_operand" "")
4322 (zero_extract (match_operand 1 "nonimmediate_operand" "")
4323 (match_operand 2 "const_int_operand" "")
4324 (match_operand 3 "const_int_operand" "")))]
8b054d5a 4325 "TARGET_THUMB1 || arm_arch_thumb2"
cffb2a26 4326 "
4327 {
4328 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
4329 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
4330
8b054d5a 4331 if (arm_arch_thumb2)
4332 {
eb04cafb 4333 HOST_WIDE_INT width = INTVAL (operands[2]);
4334 HOST_WIDE_INT bitpos = INTVAL (operands[3]);
4335
4336 if (unaligned_access && MEM_P (operands[1])
4337 && (width == 16 || width == 32) && (bitpos % BITS_PER_UNIT) == 0)
4338 {
4339 rtx base_addr;
4340
4341 if (BYTES_BIG_ENDIAN)
4342 bitpos = GET_MODE_BITSIZE (GET_MODE (operands[0])) - width
4343 - bitpos;
4344
4345 if (width == 32)
4346 {
4347 base_addr = adjust_address (operands[1], SImode,
4348 bitpos / BITS_PER_UNIT);
4349 emit_insn (gen_unaligned_loadsi (operands[0], base_addr));
4350 }
4351 else
4352 {
4353 rtx dest = operands[0];
4354 rtx tmp = gen_reg_rtx (SImode);
4355
4356 /* We may get a paradoxical subreg here. Strip it off. */
4357 if (GET_CODE (dest) == SUBREG
4358 && GET_MODE (dest) == SImode
4359 && GET_MODE (SUBREG_REG (dest)) == HImode)
4360 dest = SUBREG_REG (dest);
4361
4362 if (GET_MODE_BITSIZE (GET_MODE (dest)) != width)
4363 FAIL;
4364
4365 base_addr = adjust_address (operands[1], HImode,
4366 bitpos / BITS_PER_UNIT);
4367 emit_insn (gen_unaligned_loadhiu (tmp, base_addr));
4368 emit_move_insn (gen_lowpart (SImode, dest), tmp);
4369 }
4370 DONE;
4371 }
4372 else if (s_register_operand (operands[1], GET_MODE (operands[1])))
4373 {
4374 emit_insn (gen_extzv_t2 (operands[0], operands[1], operands[2],
4375 operands[3]));
4376 DONE;
4377 }
4378 else
4379 FAIL;
8b054d5a 4380 }
eb04cafb 4381
4382 if (!s_register_operand (operands[1], GET_MODE (operands[1])))
4383 FAIL;
8b054d5a 4384
cffb2a26 4385 operands[3] = GEN_INT (rshift);
4386
4387 if (lshift == 0)
4388 {
4389 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
4390 DONE;
4391 }
4392
eb04cafb 4393 emit_insn (gen_extzv_t1 (operands[0], operands[1], GEN_INT (lshift),
4394 operands[3], gen_reg_rtx (SImode)));
4395 DONE;
215b30b3 4396 }"
cffb2a26 4397)
4398
eb04cafb 4399;; Helper for extzv, for the Thumb-1 register-shifts case.
4400
4401(define_expand "extzv_t1"
4402 [(set (match_operand:SI 4 "s_register_operand" "")
4403 (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "")
4404 (match_operand:SI 2 "const_int_operand" "")))
4405 (set (match_operand:SI 0 "s_register_operand" "")
4406 (lshiftrt:SI (match_dup 4)
4407 (match_operand:SI 3 "const_int_operand" "")))]
4408 "TARGET_THUMB1"
4409 "")
4410
4411(define_expand "extv"
4412 [(set (match_operand 0 "s_register_operand" "")
4413 (sign_extract (match_operand 1 "nonimmediate_operand" "")
4414 (match_operand 2 "const_int_operand" "")
4415 (match_operand 3 "const_int_operand" "")))]
4416 "arm_arch_thumb2"
4417{
4418 HOST_WIDE_INT width = INTVAL (operands[2]);
4419 HOST_WIDE_INT bitpos = INTVAL (operands[3]);
4420
4421 if (unaligned_access && MEM_P (operands[1]) && (width == 16 || width == 32)
4422 && (bitpos % BITS_PER_UNIT) == 0)
4423 {
4424 rtx base_addr;
4425
4426 if (BYTES_BIG_ENDIAN)
4427 bitpos = GET_MODE_BITSIZE (GET_MODE (operands[0])) - width - bitpos;
4428
4429 if (width == 32)
4430 {
4431 base_addr = adjust_address (operands[1], SImode,
4432 bitpos / BITS_PER_UNIT);
4433 emit_insn (gen_unaligned_loadsi (operands[0], base_addr));
4434 }
4435 else
4436 {
4437 rtx dest = operands[0];
4438 rtx tmp = gen_reg_rtx (SImode);
4439
4440 /* We may get a paradoxical subreg here. Strip it off. */
4441 if (GET_CODE (dest) == SUBREG
4442 && GET_MODE (dest) == SImode
4443 && GET_MODE (SUBREG_REG (dest)) == HImode)
4444 dest = SUBREG_REG (dest);
4445
4446 if (GET_MODE_BITSIZE (GET_MODE (dest)) != width)
4447 FAIL;
4448
4449 base_addr = adjust_address (operands[1], HImode,
4450 bitpos / BITS_PER_UNIT);
4451 emit_insn (gen_unaligned_loadhis (tmp, base_addr));
4452 emit_move_insn (gen_lowpart (SImode, dest), tmp);
4453 }
4454
4455 DONE;
4456 }
4457 else if (!s_register_operand (operands[1], GET_MODE (operands[1])))
4458 FAIL;
4459 else if (GET_MODE (operands[0]) == SImode
4460 && GET_MODE (operands[1]) == SImode)
4461 {
4462 emit_insn (gen_extv_regsi (operands[0], operands[1], operands[2],
4463 operands[3]));
4464 DONE;
4465 }
4466
4467 FAIL;
4468})
4469
4470; Helper to expand register forms of extv with the proper modes.
4471
4472(define_expand "extv_regsi"
4473 [(set (match_operand:SI 0 "s_register_operand" "")
4474 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
4475 (match_operand 2 "const_int_operand" "")
4476 (match_operand 3 "const_int_operand" "")))]
4477 ""
4478{
4479})
4480
4481; ARMv6+ unaligned load/store instructions (used for packed structure accesses).
4482
4483(define_insn "unaligned_loadsi"
4484 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4485 (unspec:SI [(match_operand:SI 1 "memory_operand" "Uw,m")]
4486 UNSPEC_UNALIGNED_LOAD))]
8fe38eb2 4487 "unaligned_access"
eb04cafb 4488 "ldr%?\t%0, %1\t@ unaligned"
4489 [(set_attr "arch" "t2,any")
4490 (set_attr "length" "2,4")
4491 (set_attr "predicable" "yes")
d952d547 4492 (set_attr "predicable_short_it" "yes,no")
9f2c2a36 4493 (set_attr "type" "load_4")])
eb04cafb 4494
4495(define_insn "unaligned_loadhis"
4496 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4497 (sign_extend:SI
e3f4ccee 4498 (unspec:HI [(match_operand:HI 1 "memory_operand" "Uw,Uh")]
eb04cafb 4499 UNSPEC_UNALIGNED_LOAD)))]
8fe38eb2 4500 "unaligned_access"
3ef90e77 4501 "ldrsh%?\t%0, %1\t@ unaligned"
eb04cafb 4502 [(set_attr "arch" "t2,any")
4503 (set_attr "length" "2,4")
4504 (set_attr "predicable" "yes")
d952d547 4505 (set_attr "predicable_short_it" "yes,no")
eb04cafb 4506 (set_attr "type" "load_byte")])
4507
4508(define_insn "unaligned_loadhiu"
4509 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4510 (zero_extend:SI
4511 (unspec:HI [(match_operand:HI 1 "memory_operand" "Uw,m")]
4512 UNSPEC_UNALIGNED_LOAD)))]
8fe38eb2 4513 "unaligned_access"
3ef90e77 4514 "ldrh%?\t%0, %1\t@ unaligned"
eb04cafb 4515 [(set_attr "arch" "t2,any")
4516 (set_attr "length" "2,4")
4517 (set_attr "predicable" "yes")
d952d547 4518 (set_attr "predicable_short_it" "yes,no")
eb04cafb 4519 (set_attr "type" "load_byte")])
4520
4521(define_insn "unaligned_storesi"
4522 [(set (match_operand:SI 0 "memory_operand" "=Uw,m")
4523 (unspec:SI [(match_operand:SI 1 "s_register_operand" "l,r")]
4524 UNSPEC_UNALIGNED_STORE))]
8fe38eb2 4525 "unaligned_access"
eb04cafb 4526 "str%?\t%1, %0\t@ unaligned"
4527 [(set_attr "arch" "t2,any")
4528 (set_attr "length" "2,4")
4529 (set_attr "predicable" "yes")
d952d547 4530 (set_attr "predicable_short_it" "yes,no")
9f2c2a36 4531 (set_attr "type" "store_4")])
eb04cafb 4532
4533(define_insn "unaligned_storehi"
4534 [(set (match_operand:HI 0 "memory_operand" "=Uw,m")
4535 (unspec:HI [(match_operand:HI 1 "s_register_operand" "l,r")]
4536 UNSPEC_UNALIGNED_STORE))]
8fe38eb2 4537 "unaligned_access"
3ef90e77 4538 "strh%?\t%1, %0\t@ unaligned"
eb04cafb 4539 [(set_attr "arch" "t2,any")
4540 (set_attr "length" "2,4")
4541 (set_attr "predicable" "yes")
d952d547 4542 (set_attr "predicable_short_it" "yes,no")
9f2c2a36 4543 (set_attr "type" "store_4")])
eb04cafb 4544
ae51a965 4545
eb04cafb 4546(define_insn "*extv_reg"
8b054d5a 4547 [(set (match_operand:SI 0 "s_register_operand" "=r")
4548 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
13051f13 4549 (match_operand:SI 2 "const_int_operand" "n")
4550 (match_operand:SI 3 "const_int_operand" "n")))]
4551 "arm_arch_thumb2
4552 && IN_RANGE (INTVAL (operands[3]), 0, 31)
4553 && IN_RANGE (INTVAL (operands[2]), 1, 32 - INTVAL (operands[3]))"
8b054d5a 4554 "sbfx%?\t%0, %1, %3, %2"
4555 [(set_attr "length" "4")
d952d547 4556 (set_attr "predicable" "yes")
d82e788e 4557 (set_attr "predicable_short_it" "no")
4558 (set_attr "type" "bfm")]
8b054d5a 4559)
4560
4561(define_insn "extzv_t2"
4562 [(set (match_operand:SI 0 "s_register_operand" "=r")
4563 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "r")
13051f13 4564 (match_operand:SI 2 "const_int_operand" "n")
4565 (match_operand:SI 3 "const_int_operand" "n")))]
4566 "arm_arch_thumb2
4567 && IN_RANGE (INTVAL (operands[3]), 0, 31)
4568 && IN_RANGE (INTVAL (operands[2]), 1, 32 - INTVAL (operands[3]))"
8b054d5a 4569 "ubfx%?\t%0, %1, %3, %2"
4570 [(set_attr "length" "4")
d952d547 4571 (set_attr "predicable" "yes")
d82e788e 4572 (set_attr "predicable_short_it" "no")
4573 (set_attr "type" "bfm")]
8b054d5a 4574)
4575
7d3cda8c 4576
4577;; Division instructions
4578(define_insn "divsi3"
8f5f2788 4579 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4580 (div:SI (match_operand:SI 1 "s_register_operand" "r,r")
4581 (match_operand:SI 2 "s_register_operand" "r,r")))]
7d3cda8c 4582 "TARGET_IDIV"
8f5f2788 4583 "@
4584 sdiv%?\t%0, %1, %2
4585 sdiv\t%0, %1, %2"
4586 [(set_attr "arch" "32,v8mb")
4587 (set_attr "predicable" "yes")
d952d547 4588 (set_attr "predicable_short_it" "no")
9da0ec36 4589 (set_attr "type" "sdiv")]
7d3cda8c 4590)
4591
4592(define_insn "udivsi3"
8f5f2788 4593 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4594 (udiv:SI (match_operand:SI 1 "s_register_operand" "r,r")
4595 (match_operand:SI 2 "s_register_operand" "r,r")))]
7d3cda8c 4596 "TARGET_IDIV"
8f5f2788 4597 "@
4598 udiv%?\t%0, %1, %2
4599 udiv\t%0, %1, %2"
4600 [(set_attr "arch" "32,v8mb")
4601 (set_attr "predicable" "yes")
d952d547 4602 (set_attr "predicable_short_it" "no")
9da0ec36 4603 (set_attr "type" "udiv")]
7d3cda8c 4604)
4605
b11cae9e 4606\f
4607;; Unary arithmetic insns
4608
f6c98a9a 4609(define_expand "negvsi3"
4610 [(match_operand:SI 0 "register_operand")
4611 (match_operand:SI 1 "register_operand")
4612 (match_operand 2 "")]
4613 "TARGET_32BIT"
4614{
4615 emit_insn (gen_subsi3_compare (operands[0], const0_rtx, operands[1]));
4616 arm_gen_unlikely_cbranch (NE, CC_Vmode, operands[2]);
4617
4618 DONE;
4619})
4620
4621(define_expand "negvdi3"
4622 [(match_operand:DI 0 "register_operand")
4623 (match_operand:DI 1 "register_operand")
4624 (match_operand 2 "")]
4625 "TARGET_ARM"
4626{
4627 emit_insn (gen_negdi2_compare (operands[0], operands[1]));
4628 arm_gen_unlikely_cbranch (NE, CC_Vmode, operands[2]);
4629
4630 DONE;
4631})
4632
4633
4634(define_insn_and_split "negdi2_compare"
4635 [(set (reg:CC CC_REGNUM)
4636 (compare:CC
4637 (const_int 0)
4638 (match_operand:DI 1 "register_operand" "0,r")))
4639 (set (match_operand:DI 0 "register_operand" "=r,&r")
4640 (minus:DI (const_int 0) (match_dup 1)))]
4641 "TARGET_ARM"
4642 "#"
4643 "&& reload_completed"
4644 [(parallel [(set (reg:CC CC_REGNUM)
4645 (compare:CC (const_int 0) (match_dup 1)))
4646 (set (match_dup 0) (minus:SI (const_int 0)
4647 (match_dup 1)))])
4648 (parallel [(set (reg:CC CC_REGNUM)
4649 (compare:CC (const_int 0) (match_dup 3)))
4650 (set (match_dup 2)
4651 (minus:SI
4652 (minus:SI (const_int 0) (match_dup 3))
4653 (ltu:SI (reg:CC_C CC_REGNUM)
4654 (const_int 0))))])]
4655 {
4656 operands[2] = gen_highpart (SImode, operands[0]);
4657 operands[0] = gen_lowpart (SImode, operands[0]);
4658 operands[3] = gen_highpart (SImode, operands[1]);
4659 operands[1] = gen_lowpart (SImode, operands[1]);
4660 }
4661 [(set_attr "conds" "set")
4662 (set_attr "length" "8")
4663 (set_attr "type" "multiple")]
4664)
4665
cffb2a26 4666(define_expand "negdi2"
4667 [(parallel
8135a42b 4668 [(set (match_operand:DI 0 "s_register_operand" "")
4669 (neg:DI (match_operand:DI 1 "s_register_operand" "")))
bd5b4116 4670 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 4671 "TARGET_EITHER"
774d2fbb 4672 {
4673 if (TARGET_NEON)
4674 {
4675 emit_insn (gen_negdi2_neon (operands[0], operands[1]));
4676 DONE;
4677 }
4678 }
cffb2a26 4679)
4680
4681;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
e5fea38e 4682;; The first alternative allows the common case of a *full* overlap.
d5bf2b53 4683(define_insn_and_split "*negdi2_insn"
458a8706 4684 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 4685 (neg:DI (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 4686 (clobber (reg:CC CC_REGNUM))]
d5bf2b53 4687 "TARGET_32BIT"
4688 "#" ; rsbs %Q0, %Q1, #0; rsc %R0, %R1, #0 (ARM)
4689 ; negs %Q0, %Q1 ; sbc %R0, %R1, %R1, lsl #1 (Thumb-2)
ba6a3b2f 4690 "&& reload_completed"
4691 [(parallel [(set (reg:CC CC_REGNUM)
4692 (compare:CC (const_int 0) (match_dup 1)))
4693 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 1)))])
4694 (set (match_dup 2) (minus:SI (minus:SI (const_int 0) (match_dup 3))
4695 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
4696 {
4697 operands[2] = gen_highpart (SImode, operands[0]);
4698 operands[0] = gen_lowpart (SImode, operands[0]);
4699 operands[3] = gen_highpart (SImode, operands[1]);
4700 operands[1] = gen_lowpart (SImode, operands[1]);
4701 }
cffb2a26 4702 [(set_attr "conds" "clob")
1b7da4ac 4703 (set_attr "length" "8")
4704 (set_attr "type" "multiple")]
cffb2a26 4705)
b11cae9e 4706
f6c98a9a 4707(define_insn "*negsi2_carryin_compare"
4708 [(set (reg:CC CC_REGNUM)
4709 (compare:CC (const_int 0)
4710 (match_operand:SI 1 "s_register_operand" "r")))
4711 (set (match_operand:SI 0 "s_register_operand" "=r")
4712 (minus:SI (minus:SI (const_int 0)
4713 (match_dup 1))
4714 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
4715 "TARGET_ARM"
4716 "rscs\\t%0, %1, #0"
4717 [(set_attr "conds" "set")
4718 (set_attr "type" "alus_imm")]
4719)
4720
cffb2a26 4721(define_expand "negsi2"
4722 [(set (match_operand:SI 0 "s_register_operand" "")
4723 (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
4724 "TARGET_EITHER"
b11cae9e 4725 ""
cffb2a26 4726)
4727
4728(define_insn "*arm_negsi2"
d952d547 4729 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4730 (neg:SI (match_operand:SI 1 "s_register_operand" "l,r")))]
25f905c2 4731 "TARGET_32BIT"
cffb2a26 4732 "rsb%?\\t%0, %1, #0"
d952d547 4733 [(set_attr "predicable" "yes")
4734 (set_attr "predicable_short_it" "yes,no")
4735 (set_attr "arch" "t2,*")
1b7da4ac 4736 (set_attr "length" "4")
112eda6f 4737 (set_attr "type" "alu_sreg")]
cffb2a26 4738)
4739
604f3a0a 4740(define_expand "negsf2"
4741 [(set (match_operand:SF 0 "s_register_operand" "")
4742 (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
d7216193 4743 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 4744 ""
4745)
4746
4747(define_expand "negdf2"
4748 [(set (match_operand:DF 0 "s_register_operand" "")
4749 (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
994606f8 4750 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
604f3a0a 4751 "")
4752
7eaf2be0 4753(define_insn_and_split "*zextendsidi_negsi"
4754 [(set (match_operand:DI 0 "s_register_operand" "=r")
4755 (zero_extend:DI (neg:SI (match_operand:SI 1 "s_register_operand" "r"))))]
4756 "TARGET_32BIT"
4757 "#"
4758 ""
4759 [(set (match_dup 2)
4760 (neg:SI (match_dup 1)))
4761 (set (match_dup 3)
4762 (const_int 0))]
4763 {
4764 operands[2] = gen_lowpart (SImode, operands[0]);
4765 operands[3] = gen_highpart (SImode, operands[0]);
4766 }
4767 [(set_attr "length" "8")
4768 (set_attr "type" "multiple")]
4769)
4770
83e2b922 4771;; Negate an extended 32-bit value.
4772(define_insn_and_split "*negdi_extendsidi"
61fa8ff2 4773 [(set (match_operand:DI 0 "s_register_operand" "=l,r")
4774 (neg:DI (sign_extend:DI
4775 (match_operand:SI 1 "s_register_operand" "l,r"))))
83e2b922 4776 (clobber (reg:CC CC_REGNUM))]
4777 "TARGET_32BIT"
61fa8ff2 4778 "#"
83e2b922 4779 "&& reload_completed"
4780 [(const_int 0)]
4781 {
61fa8ff2 4782 rtx low = gen_lowpart (SImode, operands[0]);
4783 rtx high = gen_highpart (SImode, operands[0]);
4784
4785 if (reg_overlap_mentioned_p (low, operands[1]))
4786 {
4787 /* Input overlaps the low word of the output. Use:
4788 asr Rhi, Rin, #31
4789 rsbs Rlo, Rin, #0
4790 rsc Rhi, Rhi, #0 (thumb2: sbc Rhi, Rhi, Rhi, lsl #1). */
4791 rtx cc_reg = gen_rtx_REG (CC_Cmode, CC_REGNUM);
4792
d1f9b275 4793 emit_insn (gen_rtx_SET (high,
61fa8ff2 4794 gen_rtx_ASHIFTRT (SImode, operands[1],
4795 GEN_INT (31))));
4796
4797 emit_insn (gen_subsi3_compare (low, const0_rtx, operands[1]));
4798 if (TARGET_ARM)
d1f9b275 4799 emit_insn (gen_rtx_SET (high,
61fa8ff2 4800 gen_rtx_MINUS (SImode,
4801 gen_rtx_MINUS (SImode,
4802 const0_rtx,
4803 high),
4804 gen_rtx_LTU (SImode,
4805 cc_reg,
4806 const0_rtx))));
4807 else
4808 {
4809 rtx two_x = gen_rtx_ASHIFT (SImode, high, GEN_INT (1));
d1f9b275 4810 emit_insn (gen_rtx_SET (high,
61fa8ff2 4811 gen_rtx_MINUS (SImode,
4812 gen_rtx_MINUS (SImode,
4813 high,
4814 two_x),
4815 gen_rtx_LTU (SImode,
4816 cc_reg,
4817 const0_rtx))));
4818 }
4819 }
4820 else
4821 {
4822 /* No overlap, or overlap on high word. Use:
4823 rsb Rlo, Rin, #0
4824 bic Rhi, Rlo, Rin
4825 asr Rhi, Rhi, #31
4826 Flags not needed for this sequence. */
d1f9b275 4827 emit_insn (gen_rtx_SET (low, gen_rtx_NEG (SImode, operands[1])));
4828 emit_insn (gen_rtx_SET (high,
61fa8ff2 4829 gen_rtx_AND (SImode,
4830 gen_rtx_NOT (SImode, operands[1]),
4831 low)));
d1f9b275 4832 emit_insn (gen_rtx_SET (high,
61fa8ff2 4833 gen_rtx_ASHIFTRT (SImode, high,
4834 GEN_INT (31))));
4835 }
4836 DONE;
83e2b922 4837 }
61fa8ff2 4838 [(set_attr "length" "12")
4839 (set_attr "arch" "t2,*")
1b7da4ac 4840 (set_attr "type" "multiple")]
83e2b922 4841)
4842
4843(define_insn_and_split "*negdi_zero_extendsidi"
4844 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
4845 (neg:DI (zero_extend:DI (match_operand:SI 1 "s_register_operand" "0,r"))))
4846 (clobber (reg:CC CC_REGNUM))]
4847 "TARGET_32BIT"
4848 "#" ; "rsbs\\t%Q0, %1, #0\;sbc\\t%R0,%R0,%R0"
4849 ;; Don't care what register is input to sbc,
47ae02b7 4850 ;; since we just need to propagate the carry.
83e2b922 4851 "&& reload_completed"
4852 [(parallel [(set (reg:CC CC_REGNUM)
4853 (compare:CC (const_int 0) (match_dup 1)))
4854 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 1)))])
4855 (set (match_dup 2) (minus:SI (minus:SI (match_dup 2) (match_dup 2))
4856 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
4857 {
4858 operands[2] = gen_highpart (SImode, operands[0]);
4859 operands[0] = gen_lowpart (SImode, operands[0]);
4860 }
4861 [(set_attr "conds" "clob")
1b7da4ac 4862 (set_attr "length" "8")
4863 (set_attr "type" "multiple")] ;; length in thumb is 4
83e2b922 4864)
4865
9c08d1fa 4866;; abssi2 doesn't really clobber the condition codes if a different register
4867;; is being set. To keep things simple, assume during rtl manipulations that
4868;; it does, but tell the final scan operator the truth. Similarly for
4869;; (neg (abs...))
4870
604f3a0a 4871(define_expand "abssi2"
4872 [(parallel
4873 [(set (match_operand:SI 0 "s_register_operand" "")
4874 (abs:SI (match_operand:SI 1 "s_register_operand" "")))
ba156559 4875 (clobber (match_dup 2))])]
4876 "TARGET_EITHER"
4877 "
25f905c2 4878 if (TARGET_THUMB1)
ba156559 4879 operands[2] = gen_rtx_SCRATCH (SImode);
4880 else
4881 operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
4882")
604f3a0a 4883
ba6a3b2f 4884(define_insn_and_split "*arm_abssi2"
ba156559 4885 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
9c08d1fa 4886 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
bd5b4116 4887 (clobber (reg:CC CC_REGNUM))]
cffb2a26 4888 "TARGET_ARM"
ba6a3b2f 4889 "#"
4890 "&& reload_completed"
4891 [(const_int 0)]
4892 {
4893 /* if (which_alternative == 0) */
4894 if (REGNO(operands[0]) == REGNO(operands[1]))
4895 {
4896 /* Emit the pattern:
4897 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
4898 [(set (reg:CC CC_REGNUM)
4899 (compare:CC (match_dup 0) (const_int 0)))
4900 (cond_exec (lt:CC (reg:CC CC_REGNUM) (const_int 0))
4901 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 1))))]
4902 */
d1f9b275 4903 emit_insn (gen_rtx_SET (gen_rtx_REG (CCmode, CC_REGNUM),
ba6a3b2f 4904 gen_rtx_COMPARE (CCmode, operands[0], const0_rtx)));
4905 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
4906 (gen_rtx_LT (SImode,
4907 gen_rtx_REG (CCmode, CC_REGNUM),
4908 const0_rtx)),
d1f9b275 4909 (gen_rtx_SET (operands[0],
ba6a3b2f 4910 (gen_rtx_MINUS (SImode,
4911 const0_rtx,
4912 operands[1]))))));
4913 DONE;
4914 }
4915 else
4916 {
4917 /* Emit the pattern:
4918 alt1: eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31
4919 [(set (match_dup 0)
4920 (xor:SI (match_dup 1)
4921 (ashiftrt:SI (match_dup 1) (const_int 31))))
4922 (set (match_dup 0)
4923 (minus:SI (match_dup 0)
4924 (ashiftrt:SI (match_dup 1) (const_int 31))))]
4925 */
d1f9b275 4926 emit_insn (gen_rtx_SET (operands[0],
ba6a3b2f 4927 gen_rtx_XOR (SImode,
4928 gen_rtx_ASHIFTRT (SImode,
4929 operands[1],
4930 GEN_INT (31)),
4931 operands[1])));
d1f9b275 4932 emit_insn (gen_rtx_SET (operands[0],
ba6a3b2f 4933 gen_rtx_MINUS (SImode,
4934 operands[0],
4935 gen_rtx_ASHIFTRT (SImode,
4936 operands[1],
4937 GEN_INT (31)))));
4938 DONE;
4939 }
4940 }
cffb2a26 4941 [(set_attr "conds" "clob,*")
331beb1a 4942 (set_attr "shift" "1")
2ad08b65 4943 (set_attr "predicable" "no, yes")
1b7da4ac 4944 (set_attr "length" "8")
4945 (set_attr "type" "multiple")]
cffb2a26 4946)
9c08d1fa 4947
ba6a3b2f 4948(define_insn_and_split "*arm_neg_abssi2"
9c08d1fa 4949 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
4950 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
bd5b4116 4951 (clobber (reg:CC CC_REGNUM))]
cffb2a26 4952 "TARGET_ARM"
ba6a3b2f 4953 "#"
4954 "&& reload_completed"
4955 [(const_int 0)]
4956 {
4957 /* if (which_alternative == 0) */
4958 if (REGNO (operands[0]) == REGNO (operands[1]))
4959 {
4960 /* Emit the pattern:
4961 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
4962 */
d1f9b275 4963 emit_insn (gen_rtx_SET (gen_rtx_REG (CCmode, CC_REGNUM),
ba6a3b2f 4964 gen_rtx_COMPARE (CCmode, operands[0], const0_rtx)));
4965 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
4966 gen_rtx_GT (SImode,
4967 gen_rtx_REG (CCmode, CC_REGNUM),
4968 const0_rtx),
d1f9b275 4969 gen_rtx_SET (operands[0],
ba6a3b2f 4970 (gen_rtx_MINUS (SImode,
4971 const0_rtx,
4972 operands[1])))));
4973 }
4974 else
4975 {
4976 /* Emit the pattern:
4977 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31
4978 */
d1f9b275 4979 emit_insn (gen_rtx_SET (operands[0],
ba6a3b2f 4980 gen_rtx_XOR (SImode,
4981 gen_rtx_ASHIFTRT (SImode,
4982 operands[1],
4983 GEN_INT (31)),
4984 operands[1])));
d1f9b275 4985 emit_insn (gen_rtx_SET (operands[0],
ba6a3b2f 4986 gen_rtx_MINUS (SImode,
4987 gen_rtx_ASHIFTRT (SImode,
4988 operands[1],
4989 GEN_INT (31)),
4990 operands[0])));
4991 }
4992 DONE;
4993 }
cffb2a26 4994 [(set_attr "conds" "clob,*")
331beb1a 4995 (set_attr "shift" "1")
2ad08b65 4996 (set_attr "predicable" "no, yes")
1b7da4ac 4997 (set_attr "length" "8")
4998 (set_attr "type" "multiple")]
cffb2a26 4999)
b11cae9e 5000
604f3a0a 5001(define_expand "abssf2"
5002 [(set (match_operand:SF 0 "s_register_operand" "")
5003 (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
25f905c2 5004 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 5005 "")
5006
604f3a0a 5007(define_expand "absdf2"
5008 [(set (match_operand:DF 0 "s_register_operand" "")
5009 (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 5010 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 5011 "")
5012
7db9af5d 5013(define_expand "sqrtsf2"
5014 [(set (match_operand:SF 0 "s_register_operand" "")
5015 (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
d7216193 5016 "TARGET_32BIT && TARGET_HARD_FLOAT"
7db9af5d 5017 "")
9c08d1fa 5018
7db9af5d 5019(define_expand "sqrtdf2"
5020 [(set (match_operand:DF 0 "s_register_operand" "")
5021 (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
994606f8 5022 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
7db9af5d 5023 "")
9c08d1fa 5024
0d84c6e5 5025(define_expand "one_cmpldi2"
5026 [(set (match_operand:DI 0 "s_register_operand" "")
5027 (not:DI (match_operand:DI 1 "s_register_operand" "")))]
5028 "TARGET_32BIT"
5029 "
5030 if (!TARGET_NEON && !TARGET_IWMMXT)
5031 {
5032 rtx low = simplify_gen_unary (NOT, SImode,
5033 gen_lowpart (SImode, operands[1]),
5034 SImode);
5035 rtx high = simplify_gen_unary (NOT, SImode,
5036 gen_highpart_mode (SImode, DImode,
5037 operands[1]),
5038 SImode);
5039
5040 emit_insn (gen_rtx_SET (gen_lowpart (SImode, operands[0]), low));
5041 emit_insn (gen_rtx_SET (gen_highpart (SImode, operands[0]), high));
5042
5043 DONE;
5044 }
5045 /* Otherwise expand pattern as above. */
5046 "
5047)
5048
5049(define_insn_and_split "*one_cmpldi2_insn"
10efb95f 5050 [(set (match_operand:DI 0 "s_register_operand" "=w,&r,&r,?w")
5051 (not:DI (match_operand:DI 1 "s_register_operand" " w, 0, r, w")))]
25f905c2 5052 "TARGET_32BIT"
10efb95f 5053 "@
5054 vmvn\t%P0, %P1
5055 #
5056 #
5057 vmvn\t%P0, %P1"
5058 "TARGET_32BIT && reload_completed
5059 && arm_general_register_operand (operands[0], DImode)"
a0f94409 5060 [(set (match_dup 0) (not:SI (match_dup 1)))
5061 (set (match_dup 2) (not:SI (match_dup 3)))]
5062 "
5063 {
5064 operands[2] = gen_highpart (SImode, operands[0]);
5065 operands[0] = gen_lowpart (SImode, operands[0]);
5066 operands[3] = gen_highpart (SImode, operands[1]);
5067 operands[1] = gen_lowpart (SImode, operands[1]);
5068 }"
10efb95f 5069 [(set_attr "length" "*,8,8,*")
5070 (set_attr "predicable" "no,yes,yes,no")
32093010 5071 (set_attr "type" "neon_move,multiple,multiple,neon_move")
b6779ddc 5072 (set_attr "arch" "neon_for_64bits,*,*,avoid_neon_for_64bits")]
cffb2a26 5073)
b11cae9e 5074
cffb2a26 5075(define_expand "one_cmplsi2"
5076 [(set (match_operand:SI 0 "s_register_operand" "")
5077 (not:SI (match_operand:SI 1 "s_register_operand" "")))]
5078 "TARGET_EITHER"
b11cae9e 5079 ""
cffb2a26 5080)
5081
5082(define_insn "*arm_one_cmplsi2"
d952d547 5083 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
5084 (not:SI (match_operand:SI 1 "s_register_operand" "l,r")))]
25f905c2 5085 "TARGET_32BIT"
cffb2a26 5086 "mvn%?\\t%0, %1"
d2a518d1 5087 [(set_attr "predicable" "yes")
d952d547 5088 (set_attr "predicable_short_it" "yes,no")
5089 (set_attr "arch" "t2,*")
5090 (set_attr "length" "4")
1aed5204 5091 (set_attr "type" "mvn_reg")]
cffb2a26 5092)
5093
f7fbdd4a 5094(define_insn "*notsi_compare0"
bd5b4116 5095 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 5096 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5097 (const_int 0)))
5098 (set (match_operand:SI 0 "s_register_operand" "=r")
5099 (not:SI (match_dup 1)))]
25f905c2 5100 "TARGET_32BIT"
3ef90e77 5101 "mvns%?\\t%0, %1"
d2a518d1 5102 [(set_attr "conds" "set")
1aed5204 5103 (set_attr "type" "mvn_reg")]
cffb2a26 5104)
9c08d1fa 5105
f7fbdd4a 5106(define_insn "*notsi_compare0_scratch"
bd5b4116 5107 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 5108 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5109 (const_int 0)))
5110 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 5111 "TARGET_32BIT"
3ef90e77 5112 "mvns%?\\t%0, %1"
d2a518d1 5113 [(set_attr "conds" "set")
1aed5204 5114 (set_attr "type" "mvn_reg")]
cffb2a26 5115)
b11cae9e 5116\f
5117;; Fixed <--> Floating conversion insns
5118
9b8516be 5119(define_expand "floatsihf2"
5120 [(set (match_operand:HF 0 "general_operand" "")
5121 (float:HF (match_operand:SI 1 "general_operand" "")))]
5122 "TARGET_EITHER"
5123 "
5124 {
5125 rtx op1 = gen_reg_rtx (SFmode);
5126 expand_float (op1, operands[1], 0);
5127 op1 = convert_to_mode (HFmode, op1, 0);
5128 emit_move_insn (operands[0], op1);
5129 DONE;
5130 }"
5131)
5132
5133(define_expand "floatdihf2"
5134 [(set (match_operand:HF 0 "general_operand" "")
5135 (float:HF (match_operand:DI 1 "general_operand" "")))]
5136 "TARGET_EITHER"
5137 "
5138 {
5139 rtx op1 = gen_reg_rtx (SFmode);
5140 expand_float (op1, operands[1], 0);
5141 op1 = convert_to_mode (HFmode, op1, 0);
5142 emit_move_insn (operands[0], op1);
5143 DONE;
5144 }"
5145)
5146
604f3a0a 5147(define_expand "floatsisf2"
5148 [(set (match_operand:SF 0 "s_register_operand" "")
5149 (float:SF (match_operand:SI 1 "s_register_operand" "")))]
25f905c2 5150 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 5151 "
604f3a0a 5152")
5153
604f3a0a 5154(define_expand "floatsidf2"
5155 [(set (match_operand:DF 0 "s_register_operand" "")
5156 (float:DF (match_operand:SI 1 "s_register_operand" "")))]
a50d7267 5157 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 5158 "
604f3a0a 5159")
5160
9b8516be 5161(define_expand "fix_trunchfsi2"
5162 [(set (match_operand:SI 0 "general_operand" "")
5163 (fix:SI (fix:HF (match_operand:HF 1 "general_operand" ""))))]
5164 "TARGET_EITHER"
5165 "
5166 {
5167 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
5168 expand_fix (operands[0], op1, 0);
5169 DONE;
5170 }"
5171)
5172
5173(define_expand "fix_trunchfdi2"
5174 [(set (match_operand:DI 0 "general_operand" "")
5175 (fix:DI (fix:HF (match_operand:HF 1 "general_operand" ""))))]
5176 "TARGET_EITHER"
5177 "
5178 {
5179 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
5180 expand_fix (operands[0], op1, 0);
5181 DONE;
5182 }"
5183)
5184
604f3a0a 5185(define_expand "fix_truncsfsi2"
5186 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 5187 (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" ""))))]
25f905c2 5188 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 5189 "
604f3a0a 5190")
5191
604f3a0a 5192(define_expand "fix_truncdfsi2"
5193 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 5194 (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" ""))))]
a50d7267 5195 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 5196 "
604f3a0a 5197")
5198
f544c6d2 5199;; Truncation insns
b11cae9e 5200
604f3a0a 5201(define_expand "truncdfsf2"
5202 [(set (match_operand:SF 0 "s_register_operand" "")
5203 (float_truncate:SF
5204 (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 5205 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 5206 ""
5207)
9b8516be 5208
539b44ee 5209;; DFmode to HFmode conversions on targets without a single-step hardware
5210;; instruction for it would have to go through SFmode. This is dangerous
5211;; as it introduces double rounding.
5212;;
5213;; Disable this pattern unless we are in an unsafe math mode, or we have
5214;; a single-step instruction.
5215
9b8516be 5216(define_expand "truncdfhf2"
539b44ee 5217 [(set (match_operand:HF 0 "s_register_operand" "")
9b8516be 5218 (float_truncate:HF
539b44ee 5219 (match_operand:DF 1 "s_register_operand" "")))]
5220 "(TARGET_EITHER && flag_unsafe_math_optimizations)
5221 || (TARGET_32BIT && TARGET_FP16_TO_DOUBLE)"
5222{
5223 /* We don't have a direct instruction for this, so we must be in
5224 an unsafe math mode, and going via SFmode. */
5225
5226 if (!(TARGET_32BIT && TARGET_FP16_TO_DOUBLE))
5227 {
5228 rtx op1;
5229 op1 = convert_to_mode (SFmode, operands[1], 0);
5230 op1 = convert_to_mode (HFmode, op1, 0);
5231 emit_move_insn (operands[0], op1);
5232 DONE;
5233 }
5234 /* Otherwise, we will pick this up as a single instruction with
5235 no intermediary rounding. */
5236}
9b8516be 5237)
b11cae9e 5238\f
9c08d1fa 5239;; Zero and sign extension instructions.
b11cae9e 5240
848e66ac 5241(define_insn "zero_extend<mode>di2"
6aa689e8 5242 [(set (match_operand:DI 0 "s_register_operand" "=w,r,?r,w")
6d97728e 5243 (zero_extend:DI (match_operand:QHSI 1 "<qhs_zextenddi_op>"
5244 "<qhs_zextenddi_cstr>")))]
848e66ac 5245 "TARGET_32BIT <qhs_zextenddi_cond>"
5246 "#"
6aa689e8 5247 [(set_attr "length" "8,4,8,8")
b6779ddc 5248 (set_attr "arch" "neon_for_64bits,*,*,avoid_neon_for_64bits")
848e66ac 5249 (set_attr "ce_count" "2")
efbb5e19 5250 (set_attr "predicable" "yes")
5251 (set_attr "type" "multiple,mov_reg,multiple,multiple")]
25f905c2 5252)
5253
848e66ac 5254(define_insn "extend<mode>di2"
6aa689e8 5255 [(set (match_operand:DI 0 "s_register_operand" "=w,r,?r,?r,w")
63d204a8 5256 (sign_extend:DI (match_operand:QHSI 1 "<qhs_extenddi_op>"
5257 "<qhs_extenddi_cstr>")))]
848e66ac 5258 "TARGET_32BIT <qhs_sextenddi_cond>"
5259 "#"
6aa689e8 5260 [(set_attr "length" "8,4,8,8,8")
848e66ac 5261 (set_attr "ce_count" "2")
5262 (set_attr "shift" "1")
8012d2c2 5263 (set_attr "predicable" "yes")
1b7da4ac 5264 (set_attr "arch" "neon_for_64bits,*,a,t,avoid_neon_for_64bits")
5265 (set_attr "type" "multiple,mov_reg,multiple,multiple,multiple")]
0d66636f 5266)
9c08d1fa 5267
848e66ac 5268;; Splits for all extensions to DImode
5269(define_split
5270 [(set (match_operand:DI 0 "s_register_operand" "")
5271 (zero_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
6aa689e8 5272 "TARGET_32BIT && reload_completed && !IS_VFP_REGNUM (REGNO (operands[0]))"
848e66ac 5273 [(set (match_dup 0) (match_dup 1))]
5274{
848e66ac 5275 rtx lo_part = gen_lowpart (SImode, operands[0]);
3754d046 5276 machine_mode src_mode = GET_MODE (operands[1]);
848e66ac 5277
5278 if (REG_P (operands[0])
5279 && !reg_overlap_mentioned_p (operands[0], operands[1]))
5280 emit_clobber (operands[0]);
5281 if (!REG_P (lo_part) || src_mode != SImode
5282 || !rtx_equal_p (lo_part, operands[1]))
5283 {
5284 if (src_mode == SImode)
5285 emit_move_insn (lo_part, operands[1]);
5286 else
d1f9b275 5287 emit_insn (gen_rtx_SET (lo_part,
848e66ac 5288 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
5289 operands[1] = lo_part;
5290 }
5291 operands[0] = gen_highpart (SImode, operands[0]);
5292 operands[1] = const0_rtx;
5293})
9c08d1fa 5294
848e66ac 5295(define_split
25f905c2 5296 [(set (match_operand:DI 0 "s_register_operand" "")
848e66ac 5297 (sign_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
6aa689e8 5298 "TARGET_32BIT && reload_completed && !IS_VFP_REGNUM (REGNO (operands[0]))"
848e66ac 5299 [(set (match_dup 0) (ashiftrt:SI (match_dup 1) (const_int 31)))]
5300{
5301 rtx lo_part = gen_lowpart (SImode, operands[0]);
3754d046 5302 machine_mode src_mode = GET_MODE (operands[1]);
25f905c2 5303
848e66ac 5304 if (REG_P (operands[0])
5305 && !reg_overlap_mentioned_p (operands[0], operands[1]))
5306 emit_clobber (operands[0]);
5307
5308 if (!REG_P (lo_part) || src_mode != SImode
5309 || !rtx_equal_p (lo_part, operands[1]))
5310 {
5311 if (src_mode == SImode)
5312 emit_move_insn (lo_part, operands[1]);
5313 else
d1f9b275 5314 emit_insn (gen_rtx_SET (lo_part,
848e66ac 5315 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
5316 operands[1] = lo_part;
5317 }
5318 operands[0] = gen_highpart (SImode, operands[0]);
5319})
9c08d1fa 5320
5321(define_expand "zero_extendhisi2"
ef51b8e1 5322 [(set (match_operand:SI 0 "s_register_operand" "")
5323 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
cffb2a26 5324 "TARGET_EITHER"
ef51b8e1 5325{
5326 if (TARGET_ARM && !arm_arch4 && MEM_P (operands[1]))
f7fbdd4a 5327 {
ef51b8e1 5328 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
5329 DONE;
25f7a26e 5330 }
ef51b8e1 5331 if (!arm_arch6 && !MEM_P (operands[1]))
5332 {
5333 rtx t = gen_lowpart (SImode, operands[1]);
5334 rtx tmp = gen_reg_rtx (SImode);
5335 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
5336 emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (16)));
5337 DONE;
5338 }
5339})
9c08d1fa 5340
ef51b8e1 5341(define_split
b146458f 5342 [(set (match_operand:SI 0 "s_register_operand" "")
5343 (zero_extend:SI (match_operand:HI 1 "s_register_operand" "")))]
ef51b8e1 5344 "!TARGET_THUMB2 && !arm_arch6"
5345 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
5346 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 16)))]
5347{
5348 operands[2] = gen_lowpart (SImode, operands[1]);
5349})
5350
cffb2a26 5351(define_insn "*arm_zero_extendhisi2"
ef51b8e1 5352 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5353 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 5354 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 5355 "@
5356 #
3ef90e77 5357 ldrh%?\\t%0, %1"
d82e788e 5358 [(set_attr "type" "alu_shift_reg,load_byte")
848e66ac 5359 (set_attr "predicable" "yes")]
cffb2a26 5360)
f7fbdd4a 5361
a2cd141b 5362(define_insn "*arm_zero_extendhisi2_v6"
5363 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
e3f4ccee 5364 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,Uh")))]
a2cd141b 5365 "TARGET_ARM && arm_arch6"
5366 "@
5367 uxth%?\\t%0, %1
3ef90e77 5368 ldrh%?\\t%0, %1"
65f68e55 5369 [(set_attr "predicable" "yes")
6b6abc9c 5370 (set_attr "type" "extend,load_byte")]
a2cd141b 5371)
5372
5373(define_insn "*arm_zero_extendhisi2addsi"
5374 [(set (match_operand:SI 0 "s_register_operand" "=r")
5375 (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
5376 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 5377 "TARGET_INT_SIMD"
a2cd141b 5378 "uxtah%?\\t%0, %2, %1"
d82e788e 5379 [(set_attr "type" "alu_shift_reg")
d952d547 5380 (set_attr "predicable" "yes")
5381 (set_attr "predicable_short_it" "no")]
a2cd141b 5382)
5383
87b22bf7 5384(define_expand "zero_extendqisi2"
cffb2a26 5385 [(set (match_operand:SI 0 "s_register_operand" "")
5386 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
5387 "TARGET_EITHER"
ef51b8e1 5388{
0438d37f 5389 if (TARGET_ARM && !arm_arch6 && !MEM_P (operands[1]))
87b22bf7 5390 {
ef51b8e1 5391 emit_insn (gen_andsi3 (operands[0],
5392 gen_lowpart (SImode, operands[1]),
5393 GEN_INT (255)));
5394 DONE;
5395 }
5396 if (!arm_arch6 && !MEM_P (operands[1]))
5397 {
5398 rtx t = gen_lowpart (SImode, operands[1]);
5399 rtx tmp = gen_reg_rtx (SImode);
5400 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
5401 emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (24)));
5402 DONE;
5403 }
5404})
cffb2a26 5405
ef51b8e1 5406(define_split
b146458f 5407 [(set (match_operand:SI 0 "s_register_operand" "")
5408 (zero_extend:SI (match_operand:QI 1 "s_register_operand" "")))]
ef51b8e1 5409 "!arm_arch6"
5410 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
5411 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 24)))]
5412{
5413 operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
5414 if (TARGET_ARM)
5415 {
5416 emit_insn (gen_andsi3 (operands[0], operands[2], GEN_INT (255)));
87b22bf7 5417 DONE;
5418 }
ef51b8e1 5419})
9c08d1fa 5420
cffb2a26 5421(define_insn "*arm_zero_extendqisi2"
ef51b8e1 5422 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5423 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 5424 "TARGET_ARM && !arm_arch6"
ef51b8e1 5425 "@
5426 #
3ef90e77 5427 ldrb%?\\t%0, %1\\t%@ zero_extendqisi2"
ef51b8e1 5428 [(set_attr "length" "8,4")
d82e788e 5429 (set_attr "type" "alu_shift_reg,load_byte")
848e66ac 5430 (set_attr "predicable" "yes")]
cffb2a26 5431)
87b22bf7 5432
a2cd141b 5433(define_insn "*arm_zero_extendqisi2_v6"
5434 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
e3f4ccee 5435 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,Uh")))]
a2cd141b 5436 "TARGET_ARM && arm_arch6"
5437 "@
3ef90e77 5438 uxtb%?\\t%0, %1
5439 ldrb%?\\t%0, %1\\t%@ zero_extendqisi2"
6b6abc9c 5440 [(set_attr "type" "extend,load_byte")
848e66ac 5441 (set_attr "predicable" "yes")]
a2cd141b 5442)
5443
5444(define_insn "*arm_zero_extendqisi2addsi"
5445 [(set (match_operand:SI 0 "s_register_operand" "=r")
5446 (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
5447 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 5448 "TARGET_INT_SIMD"
a2cd141b 5449 "uxtab%?\\t%0, %2, %1"
5450 [(set_attr "predicable" "yes")
d952d547 5451 (set_attr "predicable_short_it" "no")
d82e788e 5452 (set_attr "type" "alu_shift_reg")]
a2cd141b 5453)
5454
87b22bf7 5455(define_split
5456 [(set (match_operand:SI 0 "s_register_operand" "")
5457 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
5458 (clobber (match_operand:SI 2 "s_register_operand" ""))]
0438d37f 5459 "TARGET_32BIT && (!MEM_P (operands[1])) && ! BYTES_BIG_ENDIAN"
87b22bf7 5460 [(set (match_dup 2) (match_dup 1))
5461 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
cffb2a26 5462 ""
5463)
9c08d1fa 5464
8a4d25d6 5465(define_split
5466 [(set (match_operand:SI 0 "s_register_operand" "")
5467 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 3)))
5468 (clobber (match_operand:SI 2 "s_register_operand" ""))]
0438d37f 5469 "TARGET_32BIT && (!MEM_P (operands[1])) && BYTES_BIG_ENDIAN"
8a4d25d6 5470 [(set (match_dup 2) (match_dup 1))
5471 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
5472 ""
5473)
5474
1c274529 5475
5476(define_split
5477 [(set (match_operand:SI 0 "s_register_operand" "")
9b23f0a7 5478 (IOR_XOR:SI (and:SI (ashift:SI
1c274529 5479 (match_operand:SI 1 "s_register_operand" "")
5480 (match_operand:SI 2 "const_int_operand" ""))
5481 (match_operand:SI 3 "const_int_operand" ""))
5482 (zero_extend:SI
5483 (match_operator 5 "subreg_lowpart_operator"
5484 [(match_operand:SI 4 "s_register_operand" "")]))))]
5485 "TARGET_32BIT
8c4e8755 5486 && (UINTVAL (operands[3])
1c274529 5487 == (GET_MODE_MASK (GET_MODE (operands[5]))
5488 & (GET_MODE_MASK (GET_MODE (operands[5]))
5489 << (INTVAL (operands[2])))))"
9b23f0a7 5490 [(set (match_dup 0) (IOR_XOR:SI (ashift:SI (match_dup 1) (match_dup 2))
1c274529 5491 (match_dup 4)))
5492 (set (match_dup 0) (zero_extend:SI (match_dup 5)))]
5493 "operands[5] = gen_lowpart (GET_MODE (operands[5]), operands[0]);"
5494)
5495
f7fbdd4a 5496(define_insn "*compareqi_eq0"
bd5b4116 5497 [(set (reg:CC_Z CC_REGNUM)
206ee9a2 5498 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
87b22bf7 5499 (const_int 0)))]
25f905c2 5500 "TARGET_32BIT"
596e5e8f 5501 "tst%?\\t%0, #255"
5502 [(set_attr "conds" "set")
d952d547 5503 (set_attr "predicable" "yes")
1b7da4ac 5504 (set_attr "predicable_short_it" "no")
5505 (set_attr "type" "logic_imm")]
cffb2a26 5506)
b11cae9e 5507
b11cae9e 5508(define_expand "extendhisi2"
ef51b8e1 5509 [(set (match_operand:SI 0 "s_register_operand" "")
5510 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
cffb2a26 5511 "TARGET_EITHER"
ef51b8e1 5512{
5513 if (TARGET_THUMB1)
5514 {
5515 emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1]));
5516 DONE;
5517 }
5518 if (MEM_P (operands[1]) && TARGET_ARM && !arm_arch4)
5519 {
5520 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
5521 DONE;
5522 }
ed29c566 5523
ef51b8e1 5524 if (!arm_arch6 && !MEM_P (operands[1]))
5525 {
5526 rtx t = gen_lowpart (SImode, operands[1]);
5527 rtx tmp = gen_reg_rtx (SImode);
5528 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
5529 emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (16)));
5530 DONE;
5531 }
5532})
cffb2a26 5533
ef51b8e1 5534(define_split
5535 [(parallel
5536 [(set (match_operand:SI 0 "register_operand" "")
5537 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))
5538 (clobber (match_scratch:SI 2 ""))])]
5539 "!arm_arch6"
5540 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
5541 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
5542{
5543 operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
5544})
25f7a26e 5545
25f905c2 5546;; This pattern will only be used when ldsh is not available
25f7a26e 5547(define_expand "extendhisi2_mem"
eab14235 5548 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 5549 (set (match_dup 3)
eab14235 5550 (zero_extend:SI (match_dup 7)))
25f7a26e 5551 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
5552 (set (match_operand:SI 0 "" "")
5553 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
cffb2a26 5554 "TARGET_ARM"
25f7a26e 5555 "
215b30b3 5556 {
5557 rtx mem1, mem2;
5558 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
5559
788fcce0 5560 mem1 = change_address (operands[1], QImode, addr);
29c05e22 5561 mem2 = change_address (operands[1], QImode,
5562 plus_constant (Pmode, addr, 1));
215b30b3 5563 operands[0] = gen_lowpart (SImode, operands[0]);
5564 operands[1] = mem1;
5565 operands[2] = gen_reg_rtx (SImode);
5566 operands[3] = gen_reg_rtx (SImode);
5567 operands[6] = gen_reg_rtx (SImode);
5568 operands[7] = mem2;
25f7a26e 5569
215b30b3 5570 if (BYTES_BIG_ENDIAN)
5571 {
5572 operands[4] = operands[2];
5573 operands[5] = operands[3];
5574 }
5575 else
5576 {
5577 operands[4] = operands[3];
5578 operands[5] = operands[2];
5579 }
5580 }"
5581)
b11cae9e 5582
ef51b8e1 5583(define_split
5584 [(set (match_operand:SI 0 "register_operand" "")
5585 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
5586 "!arm_arch6"
5587 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
5588 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
5589{
5590 operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
5591})
5592
a2cd141b 5593(define_insn "*arm_extendhisi2"
ef51b8e1 5594 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
e3f4ccee 5595 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,Uh")))]
a2cd141b 5596 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 5597 "@
5598 #
3ef90e77 5599 ldrsh%?\\t%0, %1"
ef51b8e1 5600 [(set_attr "length" "8,4")
d82e788e 5601 (set_attr "type" "alu_shift_reg,load_byte")
e3f4ccee 5602 (set_attr "predicable" "yes")]
cffb2a26 5603)
f7fbdd4a 5604
25f905c2 5605;; ??? Check Thumb-2 pool range
a2cd141b 5606(define_insn "*arm_extendhisi2_v6"
5607 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
e3f4ccee 5608 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,Uh")))]
25f905c2 5609 "TARGET_32BIT && arm_arch6"
a2cd141b 5610 "@
5611 sxth%?\\t%0, %1
3ef90e77 5612 ldrsh%?\\t%0, %1"
6b6abc9c 5613 [(set_attr "type" "extend,load_byte")
a2cd141b 5614 (set_attr "predicable" "yes")
e3f4ccee 5615 (set_attr "predicable_short_it" "no")]
a2cd141b 5616)
5617
5618(define_insn "*arm_extendhisi2addsi"
5619 [(set (match_operand:SI 0 "s_register_operand" "=r")
5620 (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
5621 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 5622 "TARGET_INT_SIMD"
a2cd141b 5623 "sxtah%?\\t%0, %2, %1"
1b7da4ac 5624 [(set_attr "type" "alu_shift_reg")]
a2cd141b 5625)
5626
c8f69309 5627(define_expand "extendqihi2"
5628 [(set (match_dup 2)
bed7d9a5 5629 (ashift:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")
c8f69309 5630 (const_int 24)))
9c08d1fa 5631 (set (match_operand:HI 0 "s_register_operand" "")
c8f69309 5632 (ashiftrt:SI (match_dup 2)
5633 (const_int 24)))]
cffb2a26 5634 "TARGET_ARM"
c8f69309 5635 "
215b30b3 5636 {
0438d37f 5637 if (arm_arch4 && MEM_P (operands[1]))
215b30b3 5638 {
d1f9b275 5639 emit_insn (gen_rtx_SET (operands[0],
215b30b3 5640 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
5641 DONE;
5642 }
5643 if (!s_register_operand (operands[1], QImode))
5644 operands[1] = copy_to_mode_reg (QImode, operands[1]);
5645 operands[0] = gen_lowpart (SImode, operands[0]);
5646 operands[1] = gen_lowpart (SImode, operands[1]);
5647 operands[2] = gen_reg_rtx (SImode);
5648 }"
5649)
f7fbdd4a 5650
25f905c2 5651(define_insn "*arm_extendqihi_insn"
b4e8a300 5652 [(set (match_operand:HI 0 "s_register_operand" "=r")
bed7d9a5 5653 (sign_extend:HI (match_operand:QI 1 "arm_extendqisi_mem_op" "Uq")))]
cffb2a26 5654 "TARGET_ARM && arm_arch4"
3ef90e77 5655 "ldrsb%?\\t%0, %1"
a2cd141b 5656 [(set_attr "type" "load_byte")
e3f4ccee 5657 (set_attr "predicable" "yes")]
cffb2a26 5658)
3fc2009e 5659
b11cae9e 5660(define_expand "extendqisi2"
ef51b8e1 5661 [(set (match_operand:SI 0 "s_register_operand" "")
5662 (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")))]
cffb2a26 5663 "TARGET_EITHER"
ef51b8e1 5664{
5665 if (!arm_arch4 && MEM_P (operands[1]))
5666 operands[1] = copy_to_mode_reg (QImode, operands[1]);
a2cd141b 5667
ef51b8e1 5668 if (!arm_arch6 && !MEM_P (operands[1]))
5669 {
5670 rtx t = gen_lowpart (SImode, operands[1]);
5671 rtx tmp = gen_reg_rtx (SImode);
5672 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
5673 emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (24)));
5674 DONE;
5675 }
5676})
a2cd141b 5677
ef51b8e1 5678(define_split
5679 [(set (match_operand:SI 0 "register_operand" "")
5680 (sign_extend:SI (match_operand:QI 1 "register_operand" "")))]
5681 "!arm_arch6"
5682 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
5683 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))]
5684{
5685 operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
5686})
f7fbdd4a 5687
a2cd141b 5688(define_insn "*arm_extendqisi"
ef51b8e1 5689 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5690 (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
a2cd141b 5691 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 5692 "@
5693 #
3ef90e77 5694 ldrsb%?\\t%0, %1"
ef51b8e1 5695 [(set_attr "length" "8,4")
d82e788e 5696 (set_attr "type" "alu_shift_reg,load_byte")
e3f4ccee 5697 (set_attr "predicable" "yes")]
cffb2a26 5698)
3fc2009e 5699
a2cd141b 5700(define_insn "*arm_extendqisi_v6"
5701 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
bed7d9a5 5702 (sign_extend:SI
5703 (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
a2cd141b 5704 "TARGET_ARM && arm_arch6"
b4e8a300 5705 "@
5706 sxtb%?\\t%0, %1
3ef90e77 5707 ldrsb%?\\t%0, %1"
6b6abc9c 5708 [(set_attr "type" "extend,load_byte")
e3f4ccee 5709 (set_attr "predicable" "yes")]
a2cd141b 5710)
5711
5712(define_insn "*arm_extendqisi2addsi"
5713 [(set (match_operand:SI 0 "s_register_operand" "=r")
5714 (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
5715 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 5716 "TARGET_INT_SIMD"
a2cd141b 5717 "sxtab%?\\t%0, %2, %1"
d82e788e 5718 [(set_attr "type" "alu_shift_reg")
d952d547 5719 (set_attr "predicable" "yes")
5720 (set_attr "predicable_short_it" "no")]
a2cd141b 5721)
5722
caedf871 5723(define_expand "extendsfdf2"
5724 [(set (match_operand:DF 0 "s_register_operand" "")
5725 (float_extend:DF (match_operand:SF 1 "s_register_operand" "")))]
a50d7267 5726 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
caedf871 5727 ""
5728)
9b8516be 5729
539b44ee 5730;; HFmode -> DFmode conversions where we don't have an instruction for it
5731;; must go through SFmode.
5732;;
5733;; This is always safe for an extend.
5734
9b8516be 5735(define_expand "extendhfdf2"
539b44ee 5736 [(set (match_operand:DF 0 "s_register_operand" "")
5737 (float_extend:DF (match_operand:HF 1 "s_register_operand" "")))]
9b8516be 5738 "TARGET_EITHER"
539b44ee 5739{
5740 /* We don't have a direct instruction for this, so go via SFmode. */
5741 if (!(TARGET_32BIT && TARGET_FP16_TO_DOUBLE))
5742 {
5743 rtx op1;
5744 op1 = convert_to_mode (SFmode, operands[1], 0);
5745 op1 = convert_to_mode (DFmode, op1, 0);
5746 emit_insn (gen_movdf (operands[0], op1));
5747 DONE;
5748 }
5749 /* Otherwise, we're done producing RTL and will pick up the correct
5750 pattern to do this with one rounding-step in a single instruction. */
5751}
9b8516be 5752)
b11cae9e 5753\f
5754;; Move insns (including loads and stores)
5755
5756;; XXX Just some ideas about movti.
9c08d1fa 5757;; I don't think these are a good idea on the arm, there just aren't enough
5758;; registers
b11cae9e 5759;;(define_expand "loadti"
9c08d1fa 5760;; [(set (match_operand:TI 0 "s_register_operand" "")
b11cae9e 5761;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
5762;; "" "")
5763
5764;;(define_expand "storeti"
5765;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
9c08d1fa 5766;; (match_operand:TI 1 "s_register_operand" ""))]
b11cae9e 5767;; "" "")
5768
5769;;(define_expand "movti"
5770;; [(set (match_operand:TI 0 "general_operand" "")
5771;; (match_operand:TI 1 "general_operand" ""))]
5772;; ""
5773;; "
5774;;{
5775;; rtx insn;
5776;;
0438d37f 5777;; if (MEM_P (operands[0]) && MEM_P (operands[1]))
b11cae9e 5778;; operands[1] = copy_to_reg (operands[1]);
0438d37f 5779;; if (MEM_P (operands[0]))
b11cae9e 5780;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
0438d37f 5781;; else if (MEM_P (operands[1]))
b11cae9e 5782;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
5783;; else
5784;; FAIL;
5785;;
5786;; emit_insn (insn);
5787;; DONE;
5788;;}")
5789
a2f10574 5790;; Recognize garbage generated above.
b11cae9e 5791
5792;;(define_insn ""
5793;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
5794;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
5795;; ""
5796;; "*
5797;; {
5798;; register mem = (which_alternative < 3);
0d66636f 5799;; register const char *template;
b11cae9e 5800;;
5801;; operands[mem] = XEXP (operands[mem], 0);
5802;; switch (which_alternative)
5803;; {
5804;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
5805;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
5806;; case 2: template = \"ldmia\\t%1, %M0\"; break;
5807;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
5808;; case 4: template = \"stmia\\t%0!, %M1\"; break;
5809;; case 5: template = \"stmia\\t%0, %M1\"; break;
5810;; }
e2348bcb 5811;; output_asm_insn (template, operands);
5812;; return \"\";
b11cae9e 5813;; }")
5814
cffb2a26 5815(define_expand "movdi"
5816 [(set (match_operand:DI 0 "general_operand" "")
5817 (match_operand:DI 1 "general_operand" ""))]
5818 "TARGET_EITHER"
5819 "
e1ba4a27 5820 if (can_create_pseudo_p ())
cffb2a26 5821 {
0438d37f 5822 if (!REG_P (operands[0]))
b2778788 5823 operands[1] = force_reg (DImode, operands[1]);
cffb2a26 5824 }
6b97fdcc 5825 if (REG_P (operands[0]) && REGNO (operands[0]) <= LAST_ARM_REGNUM
b395382f 5826 && !targetm.hard_regno_mode_ok (REGNO (operands[0]), DImode))
4f0e25ca 5827 {
5828 /* Avoid LDRD's into an odd-numbered register pair in ARM state
5829 when expanding function calls. */
5830 gcc_assert (can_create_pseudo_p ());
5831 if (MEM_P (operands[1]) && MEM_VOLATILE_P (operands[1]))
5832 {
5833 /* Perform load into legal reg pair first, then move. */
5834 rtx reg = gen_reg_rtx (DImode);
5835 emit_insn (gen_movdi (reg, operands[1]));
5836 operands[1] = reg;
5837 }
5838 emit_move_insn (gen_lowpart (SImode, operands[0]),
5839 gen_lowpart (SImode, operands[1]));
5840 emit_move_insn (gen_highpart (SImode, operands[0]),
5841 gen_highpart (SImode, operands[1]));
5842 DONE;
5843 }
6b97fdcc 5844 else if (REG_P (operands[1]) && REGNO (operands[1]) <= LAST_ARM_REGNUM
b395382f 5845 && !targetm.hard_regno_mode_ok (REGNO (operands[1]), DImode))
4f0e25ca 5846 {
5847 /* Avoid STRD's from an odd-numbered register pair in ARM state
5848 when expanding function prologue. */
5849 gcc_assert (can_create_pseudo_p ());
5850 rtx split_dest = (MEM_P (operands[0]) && MEM_VOLATILE_P (operands[0]))
5851 ? gen_reg_rtx (DImode)
5852 : operands[0];
5853 emit_move_insn (gen_lowpart (SImode, split_dest),
5854 gen_lowpart (SImode, operands[1]));
5855 emit_move_insn (gen_highpart (SImode, split_dest),
5856 gen_highpart (SImode, operands[1]));
5857 if (split_dest != operands[0])
5858 emit_insn (gen_movdi (operands[0], split_dest));
5859 DONE;
5860 }
cffb2a26 5861 "
5862)
b11cae9e 5863
cffb2a26 5864(define_insn "*arm_movdi"
353cf59a 5865 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, q, m")
5866 (match_operand:DI 1 "di_operand" "rDa,Db,Dc,mi,q"))]
cde1623a 5867 "TARGET_32BIT
d7216193 5868 && !(TARGET_HARD_FLOAT)
b2778788 5869 && !TARGET_IWMMXT
5870 && ( register_operand (operands[0], DImode)
5871 || register_operand (operands[1], DImode))"
b11cae9e 5872 "*
d51f92df 5873 switch (which_alternative)
5874 {
5875 case 0:
5876 case 1:
5877 case 2:
5878 return \"#\";
5879 default:
26ff80c0 5880 return output_move_double (operands, true, NULL);
d51f92df 5881 }
cffb2a26 5882 "
359a6e9f 5883 [(set_attr "length" "8,12,16,8,8")
9f2c2a36 5884 (set_attr "type" "multiple,multiple,multiple,load_8,store_8")
cde1623a 5885 (set_attr "arm_pool_range" "*,*,*,1020,*")
8848d797 5886 (set_attr "arm_neg_pool_range" "*,*,*,1004,*")
42e1de19 5887 (set_attr "thumb2_pool_range" "*,*,*,4094,*")
cde1623a 5888 (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
cffb2a26 5889)
5890
d51f92df 5891(define_split
5892 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
e6dd3afa 5893 (match_operand:ANY64 1 "immediate_operand" ""))]
25f905c2 5894 "TARGET_32BIT
d51f92df 5895 && reload_completed
a869c476 5896 && (arm_disable_literal_pool
5897 || (arm_const_double_inline_cost (operands[1])
5898 <= arm_max_const_double_inline_cost ()))"
d51f92df 5899 [(const_int 0)]
5900 "
5901 arm_split_constant (SET, SImode, curr_insn,
5902 INTVAL (gen_lowpart (SImode, operands[1])),
5903 gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
5904 arm_split_constant (SET, SImode, curr_insn,
5905 INTVAL (gen_highpart_mode (SImode,
5906 GET_MODE (operands[0]),
5907 operands[1])),
5908 gen_highpart (SImode, operands[0]), NULL_RTX, 0);
5909 DONE;
5910 "
5911)
5912
e5ba9289 5913; If optimizing for size, or if we have load delay slots, then
5914; we want to split the constant into two separate operations.
5915; In both cases this may split a trivial part into a single data op
5916; leaving a single complex constant to load. We can also get longer
5917; offsets in a LDR which means we get better chances of sharing the pool
5918; entries. Finally, we can normally do a better job of scheduling
5919; LDR instructions than we can with LDM.
5920; This pattern will only match if the one above did not.
5921(define_split
5922 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
5923 (match_operand:ANY64 1 "const_double_operand" ""))]
5924 "TARGET_ARM && reload_completed
5925 && arm_const_double_by_parts (operands[1])"
5926 [(set (match_dup 0) (match_dup 1))
5927 (set (match_dup 2) (match_dup 3))]
5928 "
5929 operands[2] = gen_highpart (SImode, operands[0]);
5930 operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
5931 operands[1]);
5932 operands[0] = gen_lowpart (SImode, operands[0]);
5933 operands[1] = gen_lowpart (SImode, operands[1]);
5934 "
5935)
5936
d51f92df 5937(define_split
5938 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
5939 (match_operand:ANY64 1 "arm_general_register_operand" ""))]
5940 "TARGET_EITHER && reload_completed"
5941 [(set (match_dup 0) (match_dup 1))
5942 (set (match_dup 2) (match_dup 3))]
5943 "
5944 operands[2] = gen_highpart (SImode, operands[0]);
5945 operands[3] = gen_highpart (SImode, operands[1]);
5946 operands[0] = gen_lowpart (SImode, operands[0]);
5947 operands[1] = gen_lowpart (SImode, operands[1]);
5948
5949 /* Handle a partial overlap. */
5950 if (rtx_equal_p (operands[0], operands[3]))
5951 {
5952 rtx tmp0 = operands[0];
5953 rtx tmp1 = operands[1];
5954
5955 operands[0] = operands[2];
5956 operands[1] = operands[3];
5957 operands[2] = tmp0;
5958 operands[3] = tmp1;
5959 }
5960 "
5961)
5962
a8a3b539 5963;; We can't actually do base+index doubleword loads if the index and
5964;; destination overlap. Split here so that we at least have chance to
5965;; schedule.
5966(define_split
5967 [(set (match_operand:DI 0 "s_register_operand" "")
5968 (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
5969 (match_operand:SI 2 "s_register_operand" ""))))]
5970 "TARGET_LDRD
5971 && reg_overlap_mentioned_p (operands[0], operands[1])
5972 && reg_overlap_mentioned_p (operands[0], operands[2])"
5973 [(set (match_dup 4)
5974 (plus:SI (match_dup 1)
5975 (match_dup 2)))
5976 (set (match_dup 0)
5977 (mem:DI (match_dup 4)))]
5978 "
5979 operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
5980 "
5981)
5982
9c08d1fa 5983(define_expand "movsi"
5984 [(set (match_operand:SI 0 "general_operand" "")
5985 (match_operand:SI 1 "general_operand" ""))]
cffb2a26 5986 "TARGET_EITHER"
9c08d1fa 5987 "
befb0bac 5988 {
e348ff3e 5989 rtx base, offset, tmp;
5990
6e291830 5991 if (TARGET_32BIT || TARGET_HAVE_MOVT)
9c08d1fa 5992 {
674a8f0b 5993 /* Everything except mem = const or mem = mem can be done easily. */
0438d37f 5994 if (MEM_P (operands[0]))
cffb2a26 5995 operands[1] = force_reg (SImode, operands[1]);
a2cd141b 5996 if (arm_general_register_operand (operands[0], SImode)
0438d37f 5997 && CONST_INT_P (operands[1])
cffb2a26 5998 && !(const_ok_for_arm (INTVAL (operands[1]))
5999 || const_ok_for_arm (~INTVAL (operands[1]))))
6000 {
17202aa5 6001 if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[1]), SET))
6002 {
6003 emit_insn (gen_rtx_SET (operands[0], operands[1]));
6004 DONE;
6005 }
6006 else
6007 {
6008 arm_split_constant (SET, SImode, NULL_RTX,
6009 INTVAL (operands[1]), operands[0], NULL_RTX,
6010 optimize && can_create_pseudo_p ());
6011 DONE;
6012 }
cffb2a26 6013 }
6014 }
75612252 6015 else /* Target doesn't have MOVT... */
cffb2a26 6016 {
e1ba4a27 6017 if (can_create_pseudo_p ())
cffb2a26 6018 {
0438d37f 6019 if (!REG_P (operands[0]))
cffb2a26 6020 operands[1] = force_reg (SImode, operands[1]);
6021 }
9c08d1fa 6022 }
f655717d 6023
e348ff3e 6024 if (ARM_OFFSETS_MUST_BE_WITHIN_SECTIONS_P)
6025 {
6026 split_const (operands[1], &base, &offset);
6027 if (GET_CODE (base) == SYMBOL_REF
6028 && !offset_within_block_p (base, INTVAL (offset)))
6029 {
b308ddcf 6030 tmp = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
e348ff3e 6031 emit_move_insn (tmp, base);
6032 emit_insn (gen_addsi3 (operands[0], tmp, offset));
6033 DONE;
6034 }
6035 }
6036
f655717d 6037 /* Recognize the case where operand[1] is a reference to thread-local
6038 data and load its address to a register. */
6039 if (arm_tls_referenced_p (operands[1]))
6040 {
6041 rtx tmp = operands[1];
6042 rtx addend = NULL;
6043
6044 if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
6045 {
6046 addend = XEXP (XEXP (tmp, 0), 1);
6047 tmp = XEXP (XEXP (tmp, 0), 0);
6048 }
6049
6050 gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
6051 gcc_assert (SYMBOL_REF_TLS_MODEL (tmp) != 0);
6052
e1ba4a27 6053 tmp = legitimize_tls_address (tmp,
6054 !can_create_pseudo_p () ? operands[0] : 0);
f655717d 6055 if (addend)
6056 {
6057 tmp = gen_rtx_PLUS (SImode, tmp, addend);
6058 tmp = force_operand (tmp, operands[0]);
6059 }
6060 operands[1] = tmp;
6061 }
6062 else if (flag_pic
6063 && (CONSTANT_P (operands[1])
6064 || symbol_mentioned_p (operands[1])
6065 || label_mentioned_p (operands[1])))
6066 operands[1] = legitimize_pic_address (operands[1], SImode,
e1ba4a27 6067 (!can_create_pseudo_p ()
6068 ? operands[0]
6069 : 0));
befb0bac 6070 }
215b30b3 6071 "
6072)
9c08d1fa 6073
d0e6a121 6074;; The ARM LO_SUM and HIGH are backwards - HIGH sets the low bits, and
6075;; LO_SUM adds in the high bits. Fortunately these are opaque operations
6076;; so this does not matter.
6077(define_insn "*arm_movt"
417e5cc5 6078 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r")
6079 (lo_sum:SI (match_operand:SI 1 "nonimmediate_operand" "0,0")
6080 (match_operand:SI 2 "general_operand" "i,i")))]
60a48e7d 6081 "TARGET_HAVE_MOVT && arm_valid_symbolic_address_p (operands[2])"
417e5cc5 6082 "@
6083 movt%?\t%0, #:upper16:%c2
6084 movt\t%0, #:upper16:%c2"
6085 [(set_attr "arch" "32,v8mb")
6086 (set_attr "predicable" "yes")
d952d547 6087 (set_attr "predicable_short_it" "no")
1b7da4ac 6088 (set_attr "length" "4")
282b4c75 6089 (set_attr "type" "alu_sreg")]
d0e6a121 6090)
6091
cffb2a26 6092(define_insn "*arm_movsi_insn"
aaa37ad6 6093 [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,rk,m")
110eae03 6094 (match_operand:SI 1 "general_operand" "rk, I,K,j,mi,rk"))]
d7216193 6095 "TARGET_ARM && !TARGET_IWMMXT && !TARGET_HARD_FLOAT
cffb2a26 6096 && ( register_operand (operands[0], SImode)
6097 || register_operand (operands[1], SImode))"
f7fbdd4a 6098 "@
aaa37ad6 6099 mov%?\\t%0, %1
f7fbdd4a 6100 mov%?\\t%0, %1
6101 mvn%?\\t%0, #%B1
25f905c2 6102 movw%?\\t%0, %1
f7fbdd4a 6103 ldr%?\\t%0, %1
6104 str%?\\t%1, %0"
9f2c2a36 6105 [(set_attr "type" "mov_reg,mov_imm,mvn_imm,mov_imm,load_4,store_4")
0d66636f 6106 (set_attr "predicable" "yes")
100cd063 6107 (set_attr "arch" "*,*,*,v6t2,*,*")
aaa37ad6 6108 (set_attr "pool_range" "*,*,*,*,4096,*")
6109 (set_attr "neg_pool_range" "*,*,*,*,4084,*")]
cffb2a26 6110)
87b22bf7 6111
6112(define_split
a2cd141b 6113 [(set (match_operand:SI 0 "arm_general_register_operand" "")
87b22bf7 6114 (match_operand:SI 1 "const_int_operand" ""))]
6e291830 6115 "(TARGET_32BIT || TARGET_HAVE_MOVT)
215b30b3 6116 && (!(const_ok_for_arm (INTVAL (operands[1]))
6117 || const_ok_for_arm (~INTVAL (operands[1]))))"
87b22bf7 6118 [(clobber (const_int 0))]
6119 "
96f57e36 6120 arm_split_constant (SET, SImode, NULL_RTX,
6121 INTVAL (operands[1]), operands[0], NULL_RTX, 0);
87b22bf7 6122 DONE;
215b30b3 6123 "
6124)
9c08d1fa 6125
861033d5 6126;; A normal way to do (symbol + offset) requires three instructions at least
6127;; (depends on how big the offset is) as below:
6128;; movw r0, #:lower16:g
6129;; movw r0, #:upper16:g
6130;; adds r0, #4
6131;;
6132;; A better way would be:
6133;; movw r0, #:lower16:g+4
6134;; movw r0, #:upper16:g+4
6135;;
6136;; The limitation of this way is that the length of offset should be a 16-bit
6137;; signed value, because current assembler only supports REL type relocation for
6138;; such case. If the more powerful RELA type is supported in future, we should
6139;; update this pattern to go with better way.
6140(define_split
6141 [(set (match_operand:SI 0 "arm_general_register_operand" "")
6142 (const:SI (plus:SI (match_operand:SI 1 "general_operand" "")
6143 (match_operand:SI 2 "const_int_operand" ""))))]
60a48e7d 6144 "TARGET_THUMB
6145 && TARGET_HAVE_MOVT
861033d5 6146 && arm_disable_literal_pool
6147 && reload_completed
6148 && GET_CODE (operands[1]) == SYMBOL_REF"
6149 [(clobber (const_int 0))]
6150 "
6151 int offset = INTVAL (operands[2]);
6152
6153 if (offset < -0x8000 || offset > 0x7fff)
6154 {
6155 arm_emit_movpair (operands[0], operands[1]);
d1f9b275 6156 emit_insn (gen_rtx_SET (operands[0],
861033d5 6157 gen_rtx_PLUS (SImode, operands[0], operands[2])));
6158 }
6159 else
6160 {
6161 rtx op = gen_rtx_CONST (SImode,
6162 gen_rtx_PLUS (SImode, operands[1], operands[2]));
6163 arm_emit_movpair (operands[0], op);
6164 }
6165 "
6166)
6167
b8d5d078 6168;; Split symbol_refs at the later stage (after cprop), instead of generating
6169;; movt/movw pair directly at expand. Otherwise corresponding high_sum
6170;; and lo_sum would be merged back into memory load at cprop. However,
6171;; if the default is to prefer movt/movw rather than a load from the constant
6172;; pool, the performance is better.
6173(define_split
6174 [(set (match_operand:SI 0 "arm_general_register_operand" "")
6175 (match_operand:SI 1 "general_operand" ""))]
60a48e7d 6176 "TARGET_USE_MOVT && GET_CODE (operands[1]) == SYMBOL_REF
b8d5d078 6177 && !flag_pic && !target_word_relocations
6178 && !arm_tls_referenced_p (operands[1])"
6179 [(clobber (const_int 0))]
6180{
6181 arm_emit_movpair (operands[0], operands[1]);
6182 DONE;
6183})
6184
bc360af8 6185;; When generating pic, we need to load the symbol offset into a register.
6186;; So that the optimizer does not confuse this with a normal symbol load
6187;; we use an unspec. The offset will be loaded from a constant pool entry,
6188;; since that is the only type of relocation we can use.
cffb2a26 6189
bc360af8 6190;; Wrap calculation of the whole PIC address in a single pattern for the
6191;; benefit of optimizers, particularly, PRE and HOIST. Calculation of
6192;; a PIC address involves two loads from memory, so we want to CSE it
6193;; as often as possible.
6194;; This pattern will be split into one of the pic_load_addr_* patterns
6195;; and a move after GCSE optimizations.
6196;;
6197;; Note: Update arm.c: legitimize_pic_address() when changing this pattern.
6198(define_expand "calculate_pic_address"
94f8caca 6199 [(set (match_operand:SI 0 "register_operand" "")
6200 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "")
6201 (unspec:SI [(match_operand:SI 2 "" "")]
6202 UNSPEC_PIC_SYM))))]
6203 "flag_pic"
6204)
6205
6206;; Split calculate_pic_address into pic_load_addr_* and a move.
6207(define_split
6208 [(set (match_operand:SI 0 "register_operand" "")
6209 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "")
6210 (unspec:SI [(match_operand:SI 2 "" "")]
6211 UNSPEC_PIC_SYM))))]
6212 "flag_pic"
6213 [(set (match_dup 3) (unspec:SI [(match_dup 2)] UNSPEC_PIC_SYM))
6214 (set (match_dup 0) (mem:SI (plus:SI (match_dup 1) (match_dup 3))))]
6215 "operands[3] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];"
6216)
6217
350ccca5 6218;; operand1 is the memory address to go into
6219;; pic_load_addr_32bit.
6220;; operand2 is the PIC label to be emitted
6221;; from pic_add_dot_plus_eight.
6222;; We do this to allow hoisting of the entire insn.
6223(define_insn_and_split "pic_load_addr_unified"
6224 [(set (match_operand:SI 0 "s_register_operand" "=r,r,l")
6225 (unspec:SI [(match_operand:SI 1 "" "mX,mX,mX")
6226 (match_operand:SI 2 "" "")]
6227 UNSPEC_PIC_UNIFIED))]
6228 "flag_pic"
6229 "#"
6230 "&& reload_completed"
6231 [(set (match_dup 0) (unspec:SI [(match_dup 1)] UNSPEC_PIC_SYM))
6232 (set (match_dup 0) (unspec:SI [(match_dup 0) (match_dup 3)
6233 (match_dup 2)] UNSPEC_PIC_BASE))]
6234 "operands[3] = TARGET_THUMB ? GEN_INT (4) : GEN_INT (8);"
9f2c2a36 6235 [(set_attr "type" "load_4,load_4,load_4")
42e1de19 6236 (set_attr "pool_range" "4096,4094,1022")
350ccca5 6237 (set_attr "neg_pool_range" "4084,0,0")
6238 (set_attr "arch" "a,t2,t1")
6239 (set_attr "length" "8,6,4")]
6240)
6241
67336bcf 6242;; The rather odd constraints on the following are to force reload to leave
6243;; the insn alone, and to force the minipool generation pass to then move
6244;; the GOT symbol to memory.
849170fd 6245
b3cd5f55 6246(define_insn "pic_load_addr_32bit"
849170fd 6247 [(set (match_operand:SI 0 "s_register_operand" "=r")
e1159bbe 6248 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
b3cd5f55 6249 "TARGET_32BIT && flag_pic"
67336bcf 6250 "ldr%?\\t%0, %1"
9f2c2a36 6251 [(set_attr "type" "load_4")
42e1de19 6252 (set (attr "pool_range")
6253 (if_then_else (eq_attr "is_thumb" "no")
6254 (const_int 4096)
6255 (const_int 4094)))
b3cd5f55 6256 (set (attr "neg_pool_range")
6257 (if_then_else (eq_attr "is_thumb" "no")
6258 (const_int 4084)
6259 (const_int 0)))]
8c4d8060 6260)
6261
25f905c2 6262(define_insn "pic_load_addr_thumb1"
8c4d8060 6263 [(set (match_operand:SI 0 "s_register_operand" "=l")
e1159bbe 6264 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
25f905c2 6265 "TARGET_THUMB1 && flag_pic"
8c4d8060 6266 "ldr\\t%0, %1"
9f2c2a36 6267 [(set_attr "type" "load_4")
42e1de19 6268 (set (attr "pool_range") (const_int 1018))]
cffb2a26 6269)
849170fd 6270
cffb2a26 6271(define_insn "pic_add_dot_plus_four"
15d5d060 6272 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 6273 (unspec:SI [(match_operand:SI 1 "register_operand" "0")
6274 (const_int 4)
beef0fb5 6275 (match_operand 2 "" "")]
6276 UNSPEC_PIC_BASE))]
b3cd5f55 6277 "TARGET_THUMB"
cffb2a26 6278 "*
6cdcb15c 6279 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
6280 INTVAL (operands[2]));
cffb2a26 6281 return \"add\\t%0, %|pc\";
6282 "
1b7da4ac 6283 [(set_attr "length" "2")
112eda6f 6284 (set_attr "type" "alu_sreg")]
cffb2a26 6285)
849170fd 6286
6287(define_insn "pic_add_dot_plus_eight"
15d5d060 6288 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 6289 (unspec:SI [(match_operand:SI 1 "register_operand" "r")
6290 (const_int 8)
beef0fb5 6291 (match_operand 2 "" "")]
6292 UNSPEC_PIC_BASE))]
f655717d 6293 "TARGET_ARM"
c4034607 6294 "*
6cdcb15c 6295 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
6296 INTVAL (operands[2]));
15d5d060 6297 return \"add%?\\t%0, %|pc, %1\";
cffb2a26 6298 "
1b7da4ac 6299 [(set_attr "predicable" "yes")
112eda6f 6300 (set_attr "type" "alu_sreg")]
cffb2a26 6301)
849170fd 6302
f655717d 6303(define_insn "tls_load_dot_plus_eight"
cc071db6 6304 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 6305 (mem:SI (unspec:SI [(match_operand:SI 1 "register_operand" "r")
6306 (const_int 8)
beef0fb5 6307 (match_operand 2 "" "")]
6308 UNSPEC_PIC_BASE)))]
f655717d 6309 "TARGET_ARM"
6310 "*
6cdcb15c 6311 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
6312 INTVAL (operands[2]));
f655717d 6313 return \"ldr%?\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_eight\";
6314 "
1b7da4ac 6315 [(set_attr "predicable" "yes")
9f2c2a36 6316 (set_attr "type" "load_4")]
f655717d 6317)
6318
6319;; PIC references to local variables can generate pic_add_dot_plus_eight
6320;; followed by a load. These sequences can be crunched down to
6321;; tls_load_dot_plus_eight by a peephole.
6322
6323(define_peephole2
c0c1fba5 6324 [(set (match_operand:SI 0 "register_operand" "")
6325 (unspec:SI [(match_operand:SI 3 "register_operand" "")
6326 (const_int 8)
6327 (match_operand 1 "" "")]
6328 UNSPEC_PIC_BASE))
2d05dfad 6329 (set (match_operand:SI 2 "arm_general_register_operand" "")
6330 (mem:SI (match_dup 0)))]
f655717d 6331 "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
c0c1fba5 6332 [(set (match_dup 2)
6333 (mem:SI (unspec:SI [(match_dup 3)
6334 (const_int 8)
6335 (match_dup 1)]
6336 UNSPEC_PIC_BASE)))]
f655717d 6337 ""
6338)
6339
bac7fc85 6340(define_insn "pic_offset_arm"
6341 [(set (match_operand:SI 0 "register_operand" "=r")
6342 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
6343 (unspec:SI [(match_operand:SI 2 "" "X")]
6344 UNSPEC_PIC_OFFSET))))]
6345 "TARGET_VXWORKS_RTP && TARGET_ARM && flag_pic"
6346 "ldr%?\\t%0, [%1,%2]"
9f2c2a36 6347 [(set_attr "type" "load_4")]
bac7fc85 6348)
6349
95373f08 6350(define_expand "builtin_setjmp_receiver"
6351 [(label_ref (match_operand 0 "" ""))]
6352 "flag_pic"
6353 "
6354{
b935b306 6355 /* r3 is clobbered by set/longjmp, so we can use it as a scratch
6356 register. */
2cb7d577 6357 if (arm_pic_register != INVALID_REGNUM)
6358 arm_load_pic_register (1UL << 3);
95373f08 6359 DONE;
6360}")
6361
9c08d1fa 6362;; If copying one reg to another we can set the condition codes according to
6363;; its value. Such a move is common after a return from subroutine and the
6364;; result is being tested against zero.
6365
f7fbdd4a 6366(define_insn "*movsi_compare0"
bd5b4116 6367 [(set (reg:CC CC_REGNUM)
cffb2a26 6368 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
6369 (const_int 0)))
6370 (set (match_operand:SI 0 "s_register_operand" "=r,r")
6371 (match_dup 1))]
25f905c2 6372 "TARGET_32BIT"
e2348bcb 6373 "@
40dbec34 6374 cmp%?\\t%0, #0
3ef90e77 6375 subs%?\\t%0, %1, #0"
65f68e55 6376 [(set_attr "conds" "set")
d82e788e 6377 (set_attr "type" "alus_imm,alus_imm")]
cffb2a26 6378)
b11cae9e 6379
b11cae9e 6380;; Subroutine to store a half word from a register into memory.
6381;; Operand 0 is the source register (HImode)
c8f69309 6382;; Operand 1 is the destination address in a register (SImode)
b11cae9e 6383
9c08d1fa 6384;; In both this routine and the next, we must be careful not to spill
01cc3b75 6385;; a memory address of reg+large_const into a separate PLUS insn, since this
9c08d1fa 6386;; can generate unrecognizable rtl.
6387
b11cae9e 6388(define_expand "storehi"
c8f69309 6389 [;; store the low byte
f082f1c4 6390 (set (match_operand 1 "" "") (match_dup 3))
b11cae9e 6391 ;; extract the high byte
c8f69309 6392 (set (match_dup 2)
6393 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
b11cae9e 6394 ;; store the high byte
787f8210 6395 (set (match_dup 4) (match_dup 5))]
cffb2a26 6396 "TARGET_ARM"
b11cae9e 6397 "
215b30b3 6398 {
537ffcfc 6399 rtx op1 = operands[1];
6400 rtx addr = XEXP (op1, 0);
215b30b3 6401 enum rtx_code code = GET_CODE (addr);
6402
0438d37f 6403 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
215b30b3 6404 || code == MINUS)
537ffcfc 6405 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
215b30b3 6406
537ffcfc 6407 operands[4] = adjust_address (op1, QImode, 1);
e513d163 6408 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 6409 operands[3] = gen_lowpart (QImode, operands[0]);
6410 operands[0] = gen_lowpart (SImode, operands[0]);
787f8210 6411 operands[2] = gen_reg_rtx (SImode);
6412 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 6413 }"
6414)
b11cae9e 6415
c7597b5d 6416(define_expand "storehi_bigend"
f082f1c4 6417 [(set (match_dup 4) (match_dup 3))
c7597b5d 6418 (set (match_dup 2)
6419 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
787f8210 6420 (set (match_operand 1 "" "") (match_dup 5))]
cffb2a26 6421 "TARGET_ARM"
b11cae9e 6422 "
215b30b3 6423 {
537ffcfc 6424 rtx op1 = operands[1];
6425 rtx addr = XEXP (op1, 0);
215b30b3 6426 enum rtx_code code = GET_CODE (addr);
6427
0438d37f 6428 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
215b30b3 6429 || code == MINUS)
537ffcfc 6430 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
215b30b3 6431
537ffcfc 6432 operands[4] = adjust_address (op1, QImode, 1);
e513d163 6433 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 6434 operands[3] = gen_lowpart (QImode, operands[0]);
6435 operands[0] = gen_lowpart (SImode, operands[0]);
6436 operands[2] = gen_reg_rtx (SImode);
787f8210 6437 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 6438 }"
6439)
c7597b5d 6440
6441;; Subroutine to store a half word integer constant into memory.
6442(define_expand "storeinthi"
f082f1c4 6443 [(set (match_operand 0 "" "")
787f8210 6444 (match_operand 1 "" ""))
9e8503e6 6445 (set (match_dup 3) (match_dup 2))]
cffb2a26 6446 "TARGET_ARM"
c7597b5d 6447 "
215b30b3 6448 {
6449 HOST_WIDE_INT value = INTVAL (operands[1]);
6450 rtx addr = XEXP (operands[0], 0);
537ffcfc 6451 rtx op0 = operands[0];
215b30b3 6452 enum rtx_code code = GET_CODE (addr);
c7597b5d 6453
0438d37f 6454 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
215b30b3 6455 || code == MINUS)
537ffcfc 6456 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
c7597b5d 6457
215b30b3 6458 operands[1] = gen_reg_rtx (SImode);
6459 if (BYTES_BIG_ENDIAN)
6460 {
6461 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
6462 if ((value & 255) == ((value >> 8) & 255))
6463 operands[2] = operands[1];
6464 else
6465 {
6466 operands[2] = gen_reg_rtx (SImode);
6467 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
6468 }
6469 }
6470 else
6471 {
6472 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
6473 if ((value & 255) == ((value >> 8) & 255))
6474 operands[2] = operands[1];
6475 else
6476 {
6477 operands[2] = gen_reg_rtx (SImode);
6478 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
6479 }
6480 }
c7597b5d 6481
537ffcfc 6482 operands[3] = adjust_address (op0, QImode, 1);
e513d163 6483 operands[0] = adjust_address (operands[0], QImode, 0);
9e8503e6 6484 operands[2] = gen_lowpart (QImode, operands[2]);
787f8210 6485 operands[1] = gen_lowpart (QImode, operands[1]);
215b30b3 6486 }"
6487)
b11cae9e 6488
f7fbdd4a 6489(define_expand "storehi_single_op"
6490 [(set (match_operand:HI 0 "memory_operand" "")
6491 (match_operand:HI 1 "general_operand" ""))]
25f905c2 6492 "TARGET_32BIT && arm_arch4"
f7fbdd4a 6493 "
215b30b3 6494 if (!s_register_operand (operands[1], HImode))
f7fbdd4a 6495 operands[1] = copy_to_mode_reg (HImode, operands[1]);
215b30b3 6496 "
6497)
f7fbdd4a 6498
b11cae9e 6499(define_expand "movhi"
6500 [(set (match_operand:HI 0 "general_operand" "")
c8f69309 6501 (match_operand:HI 1 "general_operand" ""))]
cffb2a26 6502 "TARGET_EITHER"
b11cae9e 6503 "
cffb2a26 6504 if (TARGET_ARM)
b11cae9e 6505 {
e1ba4a27 6506 if (can_create_pseudo_p ())
cffb2a26 6507 {
0438d37f 6508 if (MEM_P (operands[0]))
b11cae9e 6509 {
cffb2a26 6510 if (arm_arch4)
6511 {
6512 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
6513 DONE;
6514 }
0438d37f 6515 if (CONST_INT_P (operands[1]))
cffb2a26 6516 emit_insn (gen_storeinthi (operands[0], operands[1]));
c7597b5d 6517 else
cffb2a26 6518 {
0438d37f 6519 if (MEM_P (operands[1]))
cffb2a26 6520 operands[1] = force_reg (HImode, operands[1]);
6521 if (BYTES_BIG_ENDIAN)
6522 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
6523 else
6524 emit_insn (gen_storehi (operands[1], operands[0]));
6525 }
6526 DONE;
b11cae9e 6527 }
cffb2a26 6528 /* Sign extend a constant, and keep it in an SImode reg. */
0438d37f 6529 else if (CONST_INT_P (operands[1]))
9c08d1fa 6530 {
cffb2a26 6531 rtx reg = gen_reg_rtx (SImode);
6532 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
6533
6534 /* If the constant is already valid, leave it alone. */
215b30b3 6535 if (!const_ok_for_arm (val))
cffb2a26 6536 {
6537 /* If setting all the top bits will make the constant
6538 loadable in a single instruction, then set them.
6539 Otherwise, sign extend the number. */
6540
215b30b3 6541 if (const_ok_for_arm (~(val | ~0xffff)))
cffb2a26 6542 val |= ~0xffff;
6543 else if (val & 0x8000)
6544 val |= ~0xffff;
6545 }
6546
6547 emit_insn (gen_movsi (reg, GEN_INT (val)));
9e8503e6 6548 operands[1] = gen_lowpart (HImode, reg);
9c08d1fa 6549 }
e1ba4a27 6550 else if (arm_arch4 && optimize && can_create_pseudo_p ()
0438d37f 6551 && MEM_P (operands[1]))
0045890a 6552 {
6553 rtx reg = gen_reg_rtx (SImode);
6554
6555 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
6556 operands[1] = gen_lowpart (HImode, reg);
6557 }
215b30b3 6558 else if (!arm_arch4)
f7fbdd4a 6559 {
0438d37f 6560 if (MEM_P (operands[1]))
cffb2a26 6561 {
c1a66faf 6562 rtx base;
6563 rtx offset = const0_rtx;
6564 rtx reg = gen_reg_rtx (SImode);
6565
0438d37f 6566 if ((REG_P (base = XEXP (operands[1], 0))
c1a66faf 6567 || (GET_CODE (base) == PLUS
0438d37f 6568 && (CONST_INT_P (offset = XEXP (base, 1)))
c1a66faf 6569 && ((INTVAL(offset) & 1) != 1)
0438d37f 6570 && REG_P (base = XEXP (base, 0))))
c1a66faf 6571 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
206ee9a2 6572 {
8deb3959 6573 rtx new_rtx;
c1a66faf 6574
8deb3959 6575 new_rtx = widen_memory_access (operands[1], SImode,
6576 ((INTVAL (offset) & ~3)
6577 - INTVAL (offset)));
6578 emit_insn (gen_movsi (reg, new_rtx));
c1a66faf 6579 if (((INTVAL (offset) & 2) != 0)
6580 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
6581 {
6582 rtx reg2 = gen_reg_rtx (SImode);
6583
6584 emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
6585 reg = reg2;
6586 }
206ee9a2 6587 }
c1a66faf 6588 else
6589 emit_insn (gen_movhi_bytes (reg, operands[1]));
6590
6591 operands[1] = gen_lowpart (HImode, reg);
cffb2a26 6592 }
6593 }
6594 }
674a8f0b 6595 /* Handle loading a large integer during reload. */
0438d37f 6596 else if (CONST_INT_P (operands[1])
215b30b3 6597 && !const_ok_for_arm (INTVAL (operands[1]))
6598 && !const_ok_for_arm (~INTVAL (operands[1])))
cffb2a26 6599 {
6600 /* Writing a constant to memory needs a scratch, which should
6601 be handled with SECONDARY_RELOADs. */
0438d37f 6602 gcc_assert (REG_P (operands[0]));
cffb2a26 6603
6604 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
6605 emit_insn (gen_movsi (operands[0], operands[1]));
6606 DONE;
6607 }
6608 }
25f905c2 6609 else if (TARGET_THUMB2)
6610 {
6611 /* Thumb-2 can do everything except mem=mem and mem=const easily. */
e1ba4a27 6612 if (can_create_pseudo_p ())
25f905c2 6613 {
0438d37f 6614 if (!REG_P (operands[0]))
25f905c2 6615 operands[1] = force_reg (HImode, operands[1]);
6616 /* Zero extend a constant, and keep it in an SImode reg. */
0438d37f 6617 else if (CONST_INT_P (operands[1]))
25f905c2 6618 {
6619 rtx reg = gen_reg_rtx (SImode);
6620 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
6621
6622 emit_insn (gen_movsi (reg, GEN_INT (val)));
6623 operands[1] = gen_lowpart (HImode, reg);
6624 }
6625 }
6626 }
6627 else /* TARGET_THUMB1 */
cffb2a26 6628 {
e1ba4a27 6629 if (can_create_pseudo_p ())
cffb2a26 6630 {
0438d37f 6631 if (CONST_INT_P (operands[1]))
6cffc037 6632 {
6633 rtx reg = gen_reg_rtx (SImode);
6634
6635 emit_insn (gen_movsi (reg, operands[1]));
6636 operands[1] = gen_lowpart (HImode, reg);
6637 }
cffb2a26 6638
6639 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 6640 happen if we are passed a SP (never OK for HImode/QImode) or
bc409cb4 6641 virtual register (also rejected as illegitimate for HImode/QImode)
6642 relative address. */
cffb2a26 6643 /* ??? This should perhaps be fixed elsewhere, for instance, in
6644 fixup_stack_1, by checking for other kinds of invalid addresses,
6645 e.g. a bare reference to a virtual register. This may confuse the
6646 alpha though, which must handle this case differently. */
0438d37f 6647 if (MEM_P (operands[0])
215b30b3 6648 && !memory_address_p (GET_MODE (operands[0]),
6649 XEXP (operands[0], 0)))
537ffcfc 6650 operands[0]
6651 = replace_equiv_address (operands[0],
6652 copy_to_reg (XEXP (operands[0], 0)));
cffb2a26 6653
0438d37f 6654 if (MEM_P (operands[1])
215b30b3 6655 && !memory_address_p (GET_MODE (operands[1]),
6656 XEXP (operands[1], 0)))
537ffcfc 6657 operands[1]
6658 = replace_equiv_address (operands[1],
6659 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 6660
0438d37f 6661 if (MEM_P (operands[1]) && optimize > 0)
6cffc037 6662 {
6663 rtx reg = gen_reg_rtx (SImode);
6664
6665 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
6666 operands[1] = gen_lowpart (HImode, reg);
6667 }
6668
0438d37f 6669 if (MEM_P (operands[0]))
6cffc037 6670 operands[1] = force_reg (HImode, operands[1]);
cffb2a26 6671 }
0438d37f 6672 else if (CONST_INT_P (operands[1])
234f6557 6673 && !satisfies_constraint_I (operands[1]))
cffb2a26 6674 {
6cffc037 6675 /* Handle loading a large integer during reload. */
6676
cffb2a26 6677 /* Writing a constant to memory needs a scratch, which should
6678 be handled with SECONDARY_RELOADs. */
0438d37f 6679 gcc_assert (REG_P (operands[0]));
cffb2a26 6680
1a83b3ff 6681 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
cffb2a26 6682 emit_insn (gen_movsi (operands[0], operands[1]));
6683 DONE;
6684 }
b11cae9e 6685 }
cffb2a26 6686 "
6687)
6688
25f7a26e 6689(define_expand "movhi_bytes"
eab14235 6690 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 6691 (set (match_dup 3)
eab14235 6692 (zero_extend:SI (match_dup 6)))
25f7a26e 6693 (set (match_operand:SI 0 "" "")
6694 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
cffb2a26 6695 "TARGET_ARM"
25f7a26e 6696 "
215b30b3 6697 {
6698 rtx mem1, mem2;
6699 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
6700
788fcce0 6701 mem1 = change_address (operands[1], QImode, addr);
29c05e22 6702 mem2 = change_address (operands[1], QImode,
6703 plus_constant (Pmode, addr, 1));
215b30b3 6704 operands[0] = gen_lowpart (SImode, operands[0]);
6705 operands[1] = mem1;
6706 operands[2] = gen_reg_rtx (SImode);
6707 operands[3] = gen_reg_rtx (SImode);
6708 operands[6] = mem2;
25f7a26e 6709
215b30b3 6710 if (BYTES_BIG_ENDIAN)
6711 {
6712 operands[4] = operands[2];
6713 operands[5] = operands[3];
6714 }
6715 else
6716 {
6717 operands[4] = operands[3];
6718 operands[5] = operands[2];
6719 }
6720 }"
6721)
25f7a26e 6722
c7597b5d 6723(define_expand "movhi_bigend"
6724 [(set (match_dup 2)
6725 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
6726 (const_int 16)))
6727 (set (match_dup 3)
6728 (ashiftrt:SI (match_dup 2) (const_int 16)))
6729 (set (match_operand:HI 0 "s_register_operand" "")
787f8210 6730 (match_dup 4))]
cffb2a26 6731 "TARGET_ARM"
c7597b5d 6732 "
6733 operands[2] = gen_reg_rtx (SImode);
6734 operands[3] = gen_reg_rtx (SImode);
787f8210 6735 operands[4] = gen_lowpart (HImode, operands[3]);
215b30b3 6736 "
6737)
b11cae9e 6738
a2f10574 6739;; Pattern to recognize insn generated default case above
f7fbdd4a 6740(define_insn "*movhi_insn_arch4"
e4585731 6741 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r,m,r")
6742 (match_operand:HI 1 "general_operand" "rIk,K,n,r,mi"))]
cffb2a26 6743 "TARGET_ARM
d7216193 6744 && arm_arch4 && !TARGET_HARD_FLOAT
85e02ccb 6745 && (register_operand (operands[0], HImode)
6746 || register_operand (operands[1], HImode))"
f7fbdd4a 6747 "@
6748 mov%?\\t%0, %1\\t%@ movhi
6749 mvn%?\\t%0, #%B1\\t%@ movhi
b1c1a101 6750 movw%?\\t%0, %L1\\t%@ movhi
3ef90e77 6751 strh%?\\t%1, %0\\t%@ movhi
6752 ldrh%?\\t%0, %1\\t%@ movhi"
65f68e55 6753 [(set_attr "predicable" "yes")
e4585731 6754 (set_attr "pool_range" "*,*,*,*,256")
6755 (set_attr "neg_pool_range" "*,*,*,*,244")
6756 (set_attr "arch" "*,*,v6t2,*,*")
65f68e55 6757 (set_attr_alternative "type"
6758 [(if_then_else (match_operand 1 "const_int_operand" "")
1aed5204 6759 (const_string "mov_imm" )
6760 (const_string "mov_reg"))
6761 (const_string "mvn_imm")
e4585731 6762 (const_string "mov_imm")
9f2c2a36 6763 (const_string "store_4")
6764 (const_string "load_4")])]
cffb2a26 6765)
f7fbdd4a 6766
f7fbdd4a 6767(define_insn "*movhi_bytes"
65f68e55 6768 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
5fd254ed 6769 (match_operand:HI 1 "arm_rhs_operand" "I,rk,K"))]
d7216193 6770 "TARGET_ARM && !TARGET_HARD_FLOAT"
25f7a26e 6771 "@
65f68e55 6772 mov%?\\t%0, %1\\t%@ movhi
25f7a26e 6773 mov%?\\t%0, %1\\t%@ movhi
0d66636f 6774 mvn%?\\t%0, #%B1\\t%@ movhi"
d2a518d1 6775 [(set_attr "predicable" "yes")
1aed5204 6776 (set_attr "type" "mov_imm,mov_reg,mvn_imm")]
0d66636f 6777)
837bb76e 6778
bc5c7e08 6779;; We use a DImode scratch because we may occasionally need an additional
6780;; temporary if the address isn't offsettable -- push_reload doesn't seem
6781;; to take any notice of the "o" constraints on reload_memory_operand operand.
d3373b54 6782(define_expand "reload_outhi"
cffb2a26 6783 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
215b30b3 6784 (match_operand:HI 1 "s_register_operand" "r")
6785 (match_operand:DI 2 "s_register_operand" "=&l")])]
cffb2a26 6786 "TARGET_EITHER"
6787 "if (TARGET_ARM)
6788 arm_reload_out_hi (operands);
6789 else
6790 thumb_reload_out_hi (operands);
d3373b54 6791 DONE;
cffb2a26 6792 "
6793)
d3373b54 6794
25f7a26e 6795(define_expand "reload_inhi"
6796 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
cffb2a26 6797 (match_operand:HI 1 "arm_reload_memory_operand" "o")
bc5c7e08 6798 (match_operand:DI 2 "s_register_operand" "=&r")])]
c1a66faf 6799 "TARGET_EITHER"
25f7a26e 6800 "
cffb2a26 6801 if (TARGET_ARM)
6802 arm_reload_in_hi (operands);
6803 else
6804 thumb_reload_out_hi (operands);
25f7a26e 6805 DONE;
6806")
6807
9c08d1fa 6808(define_expand "movqi"
6809 [(set (match_operand:QI 0 "general_operand" "")
6810 (match_operand:QI 1 "general_operand" ""))]
cffb2a26 6811 "TARGET_EITHER"
9c08d1fa 6812 "
6cffc037 6813 /* Everything except mem = const or mem = mem can be done easily */
0045890a 6814
e1ba4a27 6815 if (can_create_pseudo_p ())
cffb2a26 6816 {
0438d37f 6817 if (CONST_INT_P (operands[1]))
6cffc037 6818 {
6819 rtx reg = gen_reg_rtx (SImode);
6820
03770691 6821 /* For thumb we want an unsigned immediate, then we are more likely
6822 to be able to use a movs insn. */
6823 if (TARGET_THUMB)
6824 operands[1] = GEN_INT (INTVAL (operands[1]) & 255);
6825
6cffc037 6826 emit_insn (gen_movsi (reg, operands[1]));
6827 operands[1] = gen_lowpart (QImode, reg);
6828 }
cffb2a26 6829
6cffc037 6830 if (TARGET_THUMB)
6831 {
cffb2a26 6832 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 6833 happen if we are passed a SP (never OK for HImode/QImode) or
bc409cb4 6834 virtual register (also rejected as illegitimate for HImode/QImode)
6835 relative address. */
cffb2a26 6836 /* ??? This should perhaps be fixed elsewhere, for instance, in
6837 fixup_stack_1, by checking for other kinds of invalid addresses,
6838 e.g. a bare reference to a virtual register. This may confuse the
6839 alpha though, which must handle this case differently. */
0438d37f 6840 if (MEM_P (operands[0])
215b30b3 6841 && !memory_address_p (GET_MODE (operands[0]),
cffb2a26 6842 XEXP (operands[0], 0)))
537ffcfc 6843 operands[0]
6844 = replace_equiv_address (operands[0],
6845 copy_to_reg (XEXP (operands[0], 0)));
0438d37f 6846 if (MEM_P (operands[1])
215b30b3 6847 && !memory_address_p (GET_MODE (operands[1]),
cffb2a26 6848 XEXP (operands[1], 0)))
537ffcfc 6849 operands[1]
6850 = replace_equiv_address (operands[1],
6851 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 6852 }
6853
0438d37f 6854 if (MEM_P (operands[1]) && optimize > 0)
6cffc037 6855 {
6856 rtx reg = gen_reg_rtx (SImode);
6857
6858 emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
6859 operands[1] = gen_lowpart (QImode, reg);
6860 }
6861
0438d37f 6862 if (MEM_P (operands[0]))
6cffc037 6863 operands[1] = force_reg (QImode, operands[1]);
6864 }
6865 else if (TARGET_THUMB
0438d37f 6866 && CONST_INT_P (operands[1])
234f6557 6867 && !satisfies_constraint_I (operands[1]))
6cffc037 6868 {
674a8f0b 6869 /* Handle loading a large integer during reload. */
cffb2a26 6870
6cffc037 6871 /* Writing a constant to memory needs a scratch, which should
6872 be handled with SECONDARY_RELOADs. */
0438d37f 6873 gcc_assert (REG_P (operands[0]));
6cffc037 6874
6875 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
6876 emit_insn (gen_movsi (operands[0], operands[1]));
6877 DONE;
cffb2a26 6878 }
6879 "
6880)
b11cae9e 6881
cffb2a26 6882(define_insn "*arm_movqi_insn"
fd711051 6883 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,l,r,l,Uu,r,m")
490f62ca 6884 (match_operand:QI 1 "general_operand" "rk,rk,I,Py,K,Uu,l,Uh,r"))]
25f905c2 6885 "TARGET_32BIT
cffb2a26 6886 && ( register_operand (operands[0], QImode)
6887 || register_operand (operands[1], QImode))"
5565501b 6888 "@
fd711051 6889 mov%?\\t%0, %1
6890 mov%?\\t%0, %1
65f68e55 6891 mov%?\\t%0, %1
5565501b 6892 mov%?\\t%0, %1
6893 mvn%?\\t%0, #%B1
3ef90e77 6894 ldrb%?\\t%0, %1
6895 strb%?\\t%1, %0
6896 ldrb%?\\t%0, %1
6897 strb%?\\t%1, %0"
9f2c2a36 6898 [(set_attr "type" "mov_reg,mov_reg,mov_imm,mov_imm,mvn_imm,load_4,store_4,load_4,store_4")
a54e3e7b 6899 (set_attr "predicable" "yes")
5233bf6a 6900 (set_attr "predicable_short_it" "yes,yes,no,yes,no,no,no,no,no")
fd711051 6901 (set_attr "arch" "t2,any,any,t2,any,t2,t2,any,any")
6902 (set_attr "length" "2,4,4,2,4,2,2,4,4")]
cffb2a26 6903)
6904
9b8516be 6905;; HFmode moves
6906(define_expand "movhf"
6907 [(set (match_operand:HF 0 "general_operand" "")
6908 (match_operand:HF 1 "general_operand" ""))]
6909 "TARGET_EITHER"
6910 "
6911 if (TARGET_32BIT)
6912 {
0438d37f 6913 if (MEM_P (operands[0]))
9b8516be 6914 operands[1] = force_reg (HFmode, operands[1]);
6915 }
6916 else /* TARGET_THUMB1 */
6917 {
6918 if (can_create_pseudo_p ())
6919 {
0438d37f 6920 if (!REG_P (operands[0]))
9b8516be 6921 operands[1] = force_reg (HFmode, operands[1]);
6922 }
6923 }
6924 "
6925)
6926
6927(define_insn "*arm32_movhf"
6928 [(set (match_operand:HF 0 "nonimmediate_operand" "=r,m,r,r")
6929 (match_operand:HF 1 "general_operand" " m,r,r,F"))]
d7216193 6930 "TARGET_32BIT && !TARGET_HARD_FLOAT
9b8516be 6931 && ( s_register_operand (operands[0], HFmode)
6932 || s_register_operand (operands[1], HFmode))"
6933 "*
6934 switch (which_alternative)
6935 {
6936 case 0: /* ARM register from memory */
3ef90e77 6937 return \"ldrh%?\\t%0, %1\\t%@ __fp16\";
9b8516be 6938 case 1: /* memory from ARM register */
3ef90e77 6939 return \"strh%?\\t%1, %0\\t%@ __fp16\";
9b8516be 6940 case 2: /* ARM register from ARM register */
6941 return \"mov%?\\t%0, %1\\t%@ __fp16\";
6942 case 3: /* ARM register from constant */
6943 {
9b8516be 6944 long bits;
6945 rtx ops[4];
6946
945f7b03 6947 bits = real_to_target (NULL, CONST_DOUBLE_REAL_VALUE (operands[1]),
6948 HFmode);
9b8516be 6949 ops[0] = operands[0];
6950 ops[1] = GEN_INT (bits);
6951 ops[2] = GEN_INT (bits & 0xff00);
6952 ops[3] = GEN_INT (bits & 0x00ff);
6953
6954 if (arm_arch_thumb2)
6955 output_asm_insn (\"movw%?\\t%0, %1\", ops);
6956 else
6957 output_asm_insn (\"mov%?\\t%0, %2\;orr%?\\t%0, %0, %3\", ops);
6958 return \"\";
6959 }
6960 default:
6961 gcc_unreachable ();
6962 }
6963 "
6964 [(set_attr "conds" "unconditional")
9f2c2a36 6965 (set_attr "type" "load_4,store_4,mov_reg,multiple")
9b8516be 6966 (set_attr "length" "4,4,4,8")
ea501323 6967 (set_attr "predicable" "yes")
6968 (set_attr "predicable_short_it" "no")]
9b8516be 6969)
6970
87b22bf7 6971(define_expand "movsf"
6972 [(set (match_operand:SF 0 "general_operand" "")
6973 (match_operand:SF 1 "general_operand" ""))]
cffb2a26 6974 "TARGET_EITHER"
87b22bf7 6975 "
25f905c2 6976 if (TARGET_32BIT)
cffb2a26 6977 {
0438d37f 6978 if (MEM_P (operands[0]))
cffb2a26 6979 operands[1] = force_reg (SFmode, operands[1]);
6980 }
25f905c2 6981 else /* TARGET_THUMB1 */
cffb2a26 6982 {
e1ba4a27 6983 if (can_create_pseudo_p ())
cffb2a26 6984 {
0438d37f 6985 if (!REG_P (operands[0]))
cffb2a26 6986 operands[1] = force_reg (SFmode, operands[1]);
6987 }
6988 }
6989 "
6990)
6991
03d440a6 6992;; Transform a floating-point move of a constant into a core register into
6993;; an SImode operation.
cffb2a26 6994(define_split
03d440a6 6995 [(set (match_operand:SF 0 "arm_general_register_operand" "")
cffb2a26 6996 (match_operand:SF 1 "immediate_operand" ""))]
339034d0 6997 "TARGET_EITHER
cffb2a26 6998 && reload_completed
0438d37f 6999 && CONST_DOUBLE_P (operands[1])"
cffb2a26 7000 [(set (match_dup 2) (match_dup 3))]
7001 "
7002 operands[2] = gen_lowpart (SImode, operands[0]);
7003 operands[3] = gen_lowpart (SImode, operands[1]);
7004 if (operands[2] == 0 || operands[3] == 0)
7005 FAIL;
215b30b3 7006 "
7007)
87b22bf7 7008
cffb2a26 7009(define_insn "*arm_movsf_soft_insn"
7010 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
7011 (match_operand:SF 1 "general_operand" "r,mE,r"))]
cde1623a 7012 "TARGET_32BIT
cffb2a26 7013 && TARGET_SOFT_FLOAT
0438d37f 7014 && (!MEM_P (operands[0])
215b30b3 7015 || register_operand (operands[1], SFmode))"
9a1112d7 7016 "@
7017 mov%?\\t%0, %1
7018 ldr%?\\t%0, %1\\t%@ float
7019 str%?\\t%1, %0\\t%@ float"
cde1623a 7020 [(set_attr "predicable" "yes")
7c36fe71 7021 (set_attr "predicable_short_it" "no")
9f2c2a36 7022 (set_attr "type" "mov_reg,load_4,store_4")
42e1de19 7023 (set_attr "arm_pool_range" "*,4096,*")
7024 (set_attr "thumb2_pool_range" "*,4094,*")
cde1623a 7025 (set_attr "arm_neg_pool_range" "*,4084,*")
7026 (set_attr "thumb2_neg_pool_range" "*,0,*")]
cffb2a26 7027)
7028
9c08d1fa 7029(define_expand "movdf"
87b22bf7 7030 [(set (match_operand:DF 0 "general_operand" "")
7031 (match_operand:DF 1 "general_operand" ""))]
cffb2a26 7032 "TARGET_EITHER"
9c08d1fa 7033 "
25f905c2 7034 if (TARGET_32BIT)
cffb2a26 7035 {
0438d37f 7036 if (MEM_P (operands[0]))
cffb2a26 7037 operands[1] = force_reg (DFmode, operands[1]);
7038 }
7039 else /* TARGET_THUMB */
7040 {
e1ba4a27 7041 if (can_create_pseudo_p ())
cffb2a26 7042 {
0438d37f 7043 if (!REG_P (operands[0]))
cffb2a26 7044 operands[1] = force_reg (DFmode, operands[1]);
7045 }
7046 }
7047 "
7048)
b11cae9e 7049
9c08d1fa 7050;; Reloading a df mode value stored in integer regs to memory can require a
7051;; scratch reg.
7052(define_expand "reload_outdf"
cffb2a26 7053 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
87b22bf7 7054 (match_operand:DF 1 "s_register_operand" "r")
7055 (match_operand:SI 2 "s_register_operand" "=&r")]
06adefdc 7056 "TARGET_THUMB2"
87b22bf7 7057 "
215b30b3 7058 {
7059 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
f7fbdd4a 7060
215b30b3 7061 if (code == REG)
7062 operands[2] = XEXP (operands[0], 0);
7063 else if (code == POST_INC || code == PRE_DEC)
7064 {
7065 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
7066 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
7067 emit_insn (gen_movdi (operands[0], operands[1]));
7068 DONE;
7069 }
7070 else if (code == PRE_INC)
7071 {
7072 rtx reg = XEXP (XEXP (operands[0], 0), 0);
f7fbdd4a 7073
215b30b3 7074 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
7075 operands[2] = reg;
7076 }
7077 else if (code == POST_DEC)
7078 operands[2] = XEXP (XEXP (operands[0], 0), 0);
7079 else
7080 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
7081 XEXP (XEXP (operands[0], 0), 1)));
f7fbdd4a 7082
d1f9b275 7083 emit_insn (gen_rtx_SET (replace_equiv_address (operands[0], operands[2]),
215b30b3 7084 operands[1]));
f7fbdd4a 7085
215b30b3 7086 if (code == POST_DEC)
7087 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
7088
7089 DONE;
7090 }"
7091)
9c08d1fa 7092
9a1112d7 7093(define_insn "*movdf_soft_insn"
353cf59a 7094 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,q,m")
7095 (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,q"))]
cde1623a 7096 "TARGET_32BIT && TARGET_SOFT_FLOAT
b2778788 7097 && ( register_operand (operands[0], DFmode)
7098 || register_operand (operands[1], DFmode))"
d51f92df 7099 "*
7100 switch (which_alternative)
7101 {
7102 case 0:
7103 case 1:
7104 case 2:
7105 return \"#\";
7106 default:
26ff80c0 7107 return output_move_double (operands, true, NULL);
d51f92df 7108 }
7109 "
359a6e9f 7110 [(set_attr "length" "8,12,16,8,8")
9f2c2a36 7111 (set_attr "type" "multiple,multiple,multiple,load_8,store_8")
42e1de19 7112 (set_attr "arm_pool_range" "*,*,*,1020,*")
7113 (set_attr "thumb2_pool_range" "*,*,*,1018,*")
8848d797 7114 (set_attr "arm_neg_pool_range" "*,*,*,1004,*")
cde1623a 7115 (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
cffb2a26 7116)
b11cae9e 7117\f
b11cae9e 7118
9c08d1fa 7119;; load- and store-multiple insns
7120;; The arm can load/store any set of registers, provided that they are in
320ea44d 7121;; ascending order, but these expanders assume a contiguous set.
b11cae9e 7122
9c08d1fa 7123(define_expand "load_multiple"
7124 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
7125 (match_operand:SI 1 "" ""))
7126 (use (match_operand:SI 2 "" ""))])]
25f905c2 7127 "TARGET_32BIT"
9580c25f 7128{
7129 HOST_WIDE_INT offset = 0;
7130
bd5b4116 7131 /* Support only fixed point registers. */
0438d37f 7132 if (!CONST_INT_P (operands[2])
6e628811 7133 || INTVAL (operands[2]) > MAX_LDM_STM_OPS
9c08d1fa 7134 || INTVAL (operands[2]) < 2
0438d37f 7135 || !MEM_P (operands[1])
7136 || !REG_P (operands[0])
bd5b4116 7137 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
7138 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 7139 FAIL;
7140
7141 operands[3]
320ea44d 7142 = arm_gen_load_multiple (arm_regs_in_sequence + REGNO (operands[0]),
7143 INTVAL (operands[2]),
f082f1c4 7144 force_reg (SImode, XEXP (operands[1], 0)),
320ea44d 7145 FALSE, operands[1], &offset);
9580c25f 7146})
b11cae9e 7147
9c08d1fa 7148(define_expand "store_multiple"
7149 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
7150 (match_operand:SI 1 "" ""))
7151 (use (match_operand:SI 2 "" ""))])]
25f905c2 7152 "TARGET_32BIT"
9580c25f 7153{
7154 HOST_WIDE_INT offset = 0;
7155
674a8f0b 7156 /* Support only fixed point registers. */
0438d37f 7157 if (!CONST_INT_P (operands[2])
6e628811 7158 || INTVAL (operands[2]) > MAX_LDM_STM_OPS
9c08d1fa 7159 || INTVAL (operands[2]) < 2
0438d37f 7160 || !REG_P (operands[1])
7161 || !MEM_P (operands[0])
bd5b4116 7162 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
7163 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 7164 FAIL;
7165
7166 operands[3]
320ea44d 7167 = arm_gen_store_multiple (arm_regs_in_sequence + REGNO (operands[1]),
7168 INTVAL (operands[2]),
f082f1c4 7169 force_reg (SImode, XEXP (operands[0], 0)),
320ea44d 7170 FALSE, operands[0], &offset);
9580c25f 7171})
b11cae9e 7172
9c08d1fa 7173
e34ebfca 7174(define_expand "setmemsi"
7175 [(match_operand:BLK 0 "general_operand" "")
7176 (match_operand:SI 1 "const_int_operand" "")
7177 (match_operand:SI 2 "const_int_operand" "")
7178 (match_operand:SI 3 "const_int_operand" "")]
7179 "TARGET_32BIT"
7180{
7181 if (arm_gen_setmem (operands))
7182 DONE;
7183
7184 FAIL;
7185})
7186
7187
9c08d1fa 7188;; Move a block of memory if it is word aligned and MORE than 2 words long.
7189;; We could let this apply for blocks of less than this, but it clobbers so
7190;; many registers that there is then probably a better way.
7191
008c057d 7192(define_expand "movmemqi"
34191dd1 7193 [(match_operand:BLK 0 "general_operand" "")
7194 (match_operand:BLK 1 "general_operand" "")
7195 (match_operand:SI 2 "const_int_operand" "")
7196 (match_operand:SI 3 "const_int_operand" "")]
ae51a965 7197 ""
9c08d1fa 7198 "
25f905c2 7199 if (TARGET_32BIT)
cffb2a26 7200 {
ae51a965 7201 if (TARGET_LDRD && current_tune->prefer_ldrd_strd
7202 && !optimize_function_for_size_p (cfun))
7203 {
7204 if (gen_movmem_ldrd_strd (operands))
7205 DONE;
7206 FAIL;
7207 }
7208
008c057d 7209 if (arm_gen_movmemqi (operands))
cffb2a26 7210 DONE;
7211 FAIL;
7212 }
25f905c2 7213 else /* TARGET_THUMB1 */
cffb2a26 7214 {
7215 if ( INTVAL (operands[3]) != 4
7216 || INTVAL (operands[2]) > 48)
7217 FAIL;
7218
008c057d 7219 thumb_expand_movmemqi (operands);
cffb2a26 7220 DONE;
7221 }
7222 "
7223)
9c08d1fa 7224\f
b11cae9e 7225
341940e8 7226;; Compare & branch insns
8d232dc7 7227;; The range calculations are based as follows:
341940e8 7228;; For forward branches, the address calculation returns the address of
7229;; the next instruction. This is 2 beyond the branch instruction.
7230;; For backward branches, the address calculation returns the address of
7231;; the first instruction in this pattern (cmp). This is 2 before the branch
7232;; instruction for the shortest sequence, and 4 before the branch instruction
7233;; if we have to jump around an unconditional branch.
7234;; To the basic branch range the PC offset must be added (this is +4).
7235;; So for forward branches we have
7236;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
7237;; And for backward branches we have
7238;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
7239;;
7240;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
7241;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
cffb2a26 7242
aeac46d4 7243(define_expand "cbranchsi4"
7244 [(set (pc) (if_then_else
aa06947a 7245 (match_operator 0 "expandable_comparison_operator"
aeac46d4 7246 [(match_operand:SI 1 "s_register_operand" "")
7247 (match_operand:SI 2 "nonmemory_operand" "")])
7248 (label_ref (match_operand 3 "" ""))
7249 (pc)))]
f9aa4160 7250 "TARGET_EITHER"
aeac46d4 7251 "
74f4459c 7252 if (!TARGET_THUMB1)
7253 {
f9aa4160 7254 if (!arm_validize_comparison (&operands[0], &operands[1], &operands[2]))
7255 FAIL;
74f4459c 7256 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
7257 operands[3]));
7258 DONE;
7259 }
25f905c2 7260 if (thumb1_cmpneg_operand (operands[2], SImode))
aeac46d4 7261 {
7262 emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
7263 operands[3], operands[0]));
7264 DONE;
7265 }
25f905c2 7266 if (!thumb1_cmp_operand (operands[2], SImode))
aeac46d4 7267 operands[2] = force_reg (SImode, operands[2]);
7268 ")
7269
74f4459c 7270(define_expand "cbranchsf4"
7271 [(set (pc) (if_then_else
aa06947a 7272 (match_operator 0 "expandable_comparison_operator"
74f4459c 7273 [(match_operand:SF 1 "s_register_operand" "")
d7216193 7274 (match_operand:SF 2 "vfp_compare_operand" "")])
74f4459c 7275 (label_ref (match_operand 3 "" ""))
7276 (pc)))]
7277 "TARGET_32BIT && TARGET_HARD_FLOAT"
7278 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
7279 operands[3])); DONE;"
7280)
7281
7282(define_expand "cbranchdf4"
7283 [(set (pc) (if_then_else
aa06947a 7284 (match_operator 0 "expandable_comparison_operator"
74f4459c 7285 [(match_operand:DF 1 "s_register_operand" "")
d7216193 7286 (match_operand:DF 2 "vfp_compare_operand" "")])
74f4459c 7287 (label_ref (match_operand 3 "" ""))
7288 (pc)))]
a50d7267 7289 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
74f4459c 7290 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
7291 operands[3])); DONE;"
7292)
7293
74f4459c 7294(define_expand "cbranchdi4"
7295 [(set (pc) (if_then_else
aa06947a 7296 (match_operator 0 "expandable_comparison_operator"
b8eae306 7297 [(match_operand:DI 1 "s_register_operand" "")
a8045a4f 7298 (match_operand:DI 2 "cmpdi_operand" "")])
74f4459c 7299 (label_ref (match_operand 3 "" ""))
7300 (pc)))]
a8045a4f 7301 "TARGET_32BIT"
7302 "{
0438d37f 7303 if (!arm_validize_comparison (&operands[0], &operands[1], &operands[2]))
f9aa4160 7304 FAIL;
7305 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
a8045a4f 7306 operands[3]));
7307 DONE;
7308 }"
74f4459c 7309)
7310
9c08d1fa 7311;; Comparison and test insns
7312
cffb2a26 7313(define_insn "*arm_cmpsi_insn"
bd5b4116 7314 [(set (reg:CC CC_REGNUM)
f9f234ec 7315 (compare:CC (match_operand:SI 0 "s_register_operand" "l,r,r,r,r")
7316 (match_operand:SI 1 "arm_add_operand" "Py,r,r,I,L")))]
25f905c2 7317 "TARGET_32BIT"
5565501b 7318 "@
a6864a24 7319 cmp%?\\t%0, %1
7320 cmp%?\\t%0, %1
aea4c774 7321 cmp%?\\t%0, %1
f9f234ec 7322 cmp%?\\t%0, %1
aea4c774 7323 cmn%?\\t%0, #%n1"
a6864a24 7324 [(set_attr "conds" "set")
f9f234ec 7325 (set_attr "arch" "t2,t2,any,any,any")
7326 (set_attr "length" "2,2,4,4,4")
65f68e55 7327 (set_attr "predicable" "yes")
f9f234ec 7328 (set_attr "predicable_short_it" "yes,yes,yes,no,no")
112eda6f 7329 (set_attr "type" "alus_imm,alus_sreg,alus_sreg,alus_imm,alus_imm")]
cffb2a26 7330)
b11cae9e 7331
d5d4dc8d 7332(define_insn "*cmpsi_shiftsi"
bd5b4116 7333 [(set (reg:CC CC_REGNUM)
d82e788e 7334 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r,r")
cffb2a26 7335 (match_operator:SI 3 "shift_operator"
d82e788e 7336 [(match_operand:SI 1 "s_register_operand" "r,r,r")
7337 (match_operand:SI 2 "shift_amount_operand" "M,r,M")])))]
d5d4dc8d 7338 "TARGET_32BIT"
f9f234ec 7339 "cmp\\t%0, %1%S3"
344495ea 7340 [(set_attr "conds" "set")
331beb1a 7341 (set_attr "shift" "1")
d82e788e 7342 (set_attr "arch" "32,a,a")
282b4c75 7343 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
b11cae9e 7344
d5d4dc8d 7345(define_insn "*cmpsi_shiftsi_swp"
bd5b4116 7346 [(set (reg:CC_SWP CC_REGNUM)
aea4c774 7347 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
d82e788e 7348 [(match_operand:SI 1 "s_register_operand" "r,r,r")
7349 (match_operand:SI 2 "shift_amount_operand" "M,r,M")])
7350 (match_operand:SI 0 "s_register_operand" "r,r,r")))]
d5d4dc8d 7351 "TARGET_32BIT"
aea4c774 7352 "cmp%?\\t%0, %1%S3"
344495ea 7353 [(set_attr "conds" "set")
331beb1a 7354 (set_attr "shift" "1")
d82e788e 7355 (set_attr "arch" "32,a,a")
282b4c75 7356 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
b11cae9e 7357
25f905c2 7358(define_insn "*arm_cmpsi_negshiftsi_si"
aed179ae 7359 [(set (reg:CC_Z CC_REGNUM)
7360 (compare:CC_Z
7361 (neg:SI (match_operator:SI 1 "shift_operator"
7362 [(match_operand:SI 2 "s_register_operand" "r")
7363 (match_operand:SI 3 "reg_or_int_operand" "rM")]))
7364 (match_operand:SI 0 "s_register_operand" "r")))]
cffb2a26 7365 "TARGET_ARM"
aed179ae 7366 "cmn%?\\t%0, %2%S1"
344495ea 7367 [(set_attr "conds" "set")
aed179ae 7368 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
d82e788e 7369 (const_string "alus_shift_imm")
7370 (const_string "alus_shift_reg")))
596e5e8f 7371 (set_attr "predicable" "yes")]
0d66636f 7372)
b11cae9e 7373
a8045a4f 7374;; DImode comparisons. The generic code generates branches that
7375;; if-conversion can not reduce to a conditional compare, so we do
7376;; that directly.
7377
ba6a3b2f 7378(define_insn_and_split "*arm_cmpdi_insn"
a8045a4f 7379 [(set (reg:CC_NCV CC_REGNUM)
7380 (compare:CC_NCV (match_operand:DI 0 "s_register_operand" "r")
7381 (match_operand:DI 1 "arm_di_operand" "rDi")))
7382 (clobber (match_scratch:SI 2 "=r"))]
b805622c 7383 "TARGET_32BIT"
ba6a3b2f 7384 "#" ; "cmp\\t%Q0, %Q1\;sbcs\\t%2, %R0, %R1"
7385 "&& reload_completed"
7386 [(set (reg:CC CC_REGNUM)
7387 (compare:CC (match_dup 0) (match_dup 1)))
7388 (parallel [(set (reg:CC CC_REGNUM)
7389 (compare:CC (match_dup 3) (match_dup 4)))
7390 (set (match_dup 2)
7391 (minus:SI (match_dup 5)
7392 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))])]
7393 {
7394 operands[3] = gen_highpart (SImode, operands[0]);
7395 operands[0] = gen_lowpart (SImode, operands[0]);
7396 if (CONST_INT_P (operands[1]))
7397 {
7398 operands[4] = GEN_INT (~INTVAL (gen_highpart_mode (SImode,
7399 DImode,
7400 operands[1])));
7401 operands[5] = gen_rtx_PLUS (SImode, operands[3], operands[4]);
7402 }
7403 else
7404 {
7405 operands[4] = gen_highpart (SImode, operands[1]);
7406 operands[5] = gen_rtx_MINUS (SImode, operands[3], operands[4]);
7407 }
7408 operands[1] = gen_lowpart (SImode, operands[1]);
7409 operands[2] = gen_lowpart (SImode, operands[2]);
7410 }
a8045a4f 7411 [(set_attr "conds" "set")
1b7da4ac 7412 (set_attr "length" "8")
7413 (set_attr "type" "multiple")]
a8045a4f 7414)
7415
ba6a3b2f 7416(define_insn_and_split "*arm_cmpdi_unsigned"
a8045a4f 7417 [(set (reg:CC_CZ CC_REGNUM)
1a86364b 7418 (compare:CC_CZ (match_operand:DI 0 "s_register_operand" "l,r,r,r")
7419 (match_operand:DI 1 "arm_di_operand" "Py,r,Di,rDi")))]
7c36fe71 7420
48a98053 7421 "TARGET_32BIT"
ba6a3b2f 7422 "#" ; "cmp\\t%R0, %R1\;it eq\;cmpeq\\t%Q0, %Q1"
7423 "&& reload_completed"
7424 [(set (reg:CC CC_REGNUM)
7425 (compare:CC (match_dup 2) (match_dup 3)))
7426 (cond_exec (eq:SI (reg:CC CC_REGNUM) (const_int 0))
7427 (set (reg:CC CC_REGNUM)
7428 (compare:CC (match_dup 0) (match_dup 1))))]
7429 {
7430 operands[2] = gen_highpart (SImode, operands[0]);
7431 operands[0] = gen_lowpart (SImode, operands[0]);
7432 if (CONST_INT_P (operands[1]))
7433 operands[3] = gen_highpart_mode (SImode, DImode, operands[1]);
7434 else
7435 operands[3] = gen_highpart (SImode, operands[1]);
7436 operands[1] = gen_lowpart (SImode, operands[1]);
7437 }
a8045a4f 7438 [(set_attr "conds" "set")
1a86364b 7439 (set_attr "enabled_for_depr_it" "yes,yes,no,*")
7440 (set_attr "arch" "t2,t2,t2,a")
7441 (set_attr "length" "6,6,10,8")
1b7da4ac 7442 (set_attr "type" "multiple")]
a8045a4f 7443)
7444
7445(define_insn "*arm_cmpdi_zero"
7446 [(set (reg:CC_Z CC_REGNUM)
7447 (compare:CC_Z (match_operand:DI 0 "s_register_operand" "r")
7448 (const_int 0)))
7449 (clobber (match_scratch:SI 1 "=r"))]
7450 "TARGET_32BIT"
3ef90e77 7451 "orrs%?\\t%1, %Q0, %R0"
1b7da4ac 7452 [(set_attr "conds" "set")
7453 (set_attr "type" "logics_reg")]
a8045a4f 7454)
7455
9c08d1fa 7456; This insn allows redundant compares to be removed by cse, nothing should
7457; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
7458; is deleted later on. The match_dup will match the mode here, so that
7459; mode changes of the condition codes aren't lost by this even though we don't
7460; specify what they are.
7461
8a18b90c 7462(define_insn "*deleted_compare"
9c08d1fa 7463 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
25f905c2 7464 "TARGET_32BIT"
40dbec34 7465 "\\t%@ deleted compare"
cffb2a26 7466 [(set_attr "conds" "set")
1b7da4ac 7467 (set_attr "length" "0")
7468 (set_attr "type" "no_insn")]
cffb2a26 7469)
9c08d1fa 7470
7471\f
7472;; Conditional branch insns
7473
74f4459c 7474(define_expand "cbranch_cc"
9c08d1fa 7475 [(set (pc)
74f4459c 7476 (if_then_else (match_operator 0 "" [(match_operand 1 "" "")
7477 (match_operand 2 "" "")])
7478 (label_ref (match_operand 3 "" ""))
9c08d1fa 7479 (pc)))]
25f905c2 7480 "TARGET_32BIT"
74f4459c 7481 "operands[1] = arm_gen_compare_reg (GET_CODE (operands[0]),
e1b93706 7482 operands[1], operands[2], NULL_RTX);
74f4459c 7483 operands[2] = const0_rtx;"
8fa3ba89 7484)
7485
7486;;
7487;; Patterns to match conditional branch insns.
7488;;
7489
ffcc986d 7490(define_insn "arm_cond_branch"
9c08d1fa 7491 [(set (pc)
8fa3ba89 7492 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 7493 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 7494 (label_ref (match_operand 0 "" ""))
7495 (pc)))]
25f905c2 7496 "TARGET_32BIT"
d75350ce 7497 "*
9c08d1fa 7498 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 7499 {
7500 arm_ccfsm_state += 2;
7501 return \"\";
7502 }
e2348bcb 7503 return \"b%d1\\t%l0\";
cffb2a26 7504 "
a2cd141b 7505 [(set_attr "conds" "use")
a6864a24 7506 (set_attr "type" "branch")
7507 (set (attr "length")
7508 (if_then_else
0bf497f5 7509 (and (match_test "TARGET_THUMB2")
a6864a24 7510 (and (ge (minus (match_dup 0) (pc)) (const_int -250))
7511 (le (minus (match_dup 0) (pc)) (const_int 256))))
7512 (const_int 2)
7513 (const_int 4)))]
cffb2a26 7514)
d75350ce 7515
cffb2a26 7516(define_insn "*arm_cond_branch_reversed"
9c08d1fa 7517 [(set (pc)
8fa3ba89 7518 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 7519 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 7520 (pc)
7521 (label_ref (match_operand 0 "" ""))))]
25f905c2 7522 "TARGET_32BIT"
d75350ce 7523 "*
9c08d1fa 7524 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 7525 {
7526 arm_ccfsm_state += 2;
7527 return \"\";
7528 }
e2348bcb 7529 return \"b%D1\\t%l0\";
cffb2a26 7530 "
a2cd141b 7531 [(set_attr "conds" "use")
a6864a24 7532 (set_attr "type" "branch")
7533 (set (attr "length")
7534 (if_then_else
0bf497f5 7535 (and (match_test "TARGET_THUMB2")
a6864a24 7536 (and (ge (minus (match_dup 0) (pc)) (const_int -250))
7537 (le (minus (match_dup 0) (pc)) (const_int 256))))
7538 (const_int 2)
7539 (const_int 4)))]
cffb2a26 7540)
7541
b11cae9e 7542\f
9c08d1fa 7543
7544; scc insns
7545
74f4459c 7546(define_expand "cstore_cc"
7db9af5d 7547 [(set (match_operand:SI 0 "s_register_operand" "")
74f4459c 7548 (match_operator:SI 1 "" [(match_operand 2 "" "")
7549 (match_operand 3 "" "")]))]
25f905c2 7550 "TARGET_32BIT"
74f4459c 7551 "operands[2] = arm_gen_compare_reg (GET_CODE (operands[1]),
e1b93706 7552 operands[2], operands[3], NULL_RTX);
74f4459c 7553 operands[3] = const0_rtx;"
8fa3ba89 7554)
7555
a3b84066 7556(define_insn_and_split "*mov_scc"
9c08d1fa 7557 [(set (match_operand:SI 0 "s_register_operand" "=r")
ff74dd54 7558 (match_operator:SI 1 "arm_comparison_operator_mode"
8a18b90c 7559 [(match_operand 2 "cc_register" "") (const_int 0)]))]
cffb2a26 7560 "TARGET_ARM"
a3b84066 7561 "#" ; "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
7562 "TARGET_ARM"
7563 [(set (match_dup 0)
7564 (if_then_else:SI (match_dup 1)
7565 (const_int 1)
7566 (const_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_negscc"
9c08d1fa 7574 [(set (match_operand:SI 0 "s_register_operand" "=r")
ff74dd54 7575 (neg:SI (match_operator:SI 1 "arm_comparison_operator_mode"
8a18b90c 7576 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 7577 "TARGET_ARM"
a3b84066 7578 "#" ; "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
7579 "TARGET_ARM"
7580 [(set (match_dup 0)
7581 (if_then_else:SI (match_dup 1)
7582 (match_dup 3)
7583 (const_int 0)))]
7584 {
7585 operands[3] = GEN_INT (~0);
7586 }
cffb2a26 7587 [(set_attr "conds" "use")
1b7da4ac 7588 (set_attr "length" "8")
7589 (set_attr "type" "multiple")]
cffb2a26 7590)
9c08d1fa 7591
a3b84066 7592(define_insn_and_split "*mov_notscc"
9c08d1fa 7593 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7594 (not:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7595 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 7596 "TARGET_ARM"
a3b84066 7597 "#" ; "mvn%D1\\t%0, #0\;mvn%d1\\t%0, #1"
7598 "TARGET_ARM"
7599 [(set (match_dup 0)
7600 (if_then_else:SI (match_dup 1)
7601 (match_dup 3)
7602 (match_dup 4)))]
7603 {
7604 operands[3] = GEN_INT (~1);
7605 operands[4] = GEN_INT (~0);
7606 }
cffb2a26 7607 [(set_attr "conds" "use")
1b7da4ac 7608 (set_attr "length" "8")
7609 (set_attr "type" "multiple")]
cffb2a26 7610)
9c08d1fa 7611
595d88b5 7612(define_expand "cstoresi4"
7613 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 7614 (match_operator:SI 1 "expandable_comparison_operator"
595d88b5 7615 [(match_operand:SI 2 "s_register_operand" "")
7616 (match_operand:SI 3 "reg_or_int_operand" "")]))]
74f4459c 7617 "TARGET_32BIT || TARGET_THUMB1"
595d88b5 7618 "{
7619 rtx op3, scratch, scratch2;
7620
74f4459c 7621 if (!TARGET_THUMB1)
7622 {
7623 if (!arm_add_operand (operands[3], SImode))
7624 operands[3] = force_reg (SImode, operands[3]);
7625 emit_insn (gen_cstore_cc (operands[0], operands[1],
7626 operands[2], operands[3]));
7627 DONE;
7628 }
7629
595d88b5 7630 if (operands[3] == const0_rtx)
7631 {
7632 switch (GET_CODE (operands[1]))
7633 {
7634 case EQ:
25f905c2 7635 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], operands[2]));
595d88b5 7636 break;
7637
7638 case NE:
25f905c2 7639 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], operands[2]));
595d88b5 7640 break;
7641
7642 case LE:
7643 scratch = expand_binop (SImode, add_optab, operands[2], constm1_rtx,
7644 NULL_RTX, 0, OPTAB_WIDEN);
7645 scratch = expand_binop (SImode, ior_optab, operands[2], scratch,
7646 NULL_RTX, 0, OPTAB_WIDEN);
7647 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7648 operands[0], 1, OPTAB_WIDEN);
7649 break;
7650
7651 case GE:
7652 scratch = expand_unop (SImode, one_cmpl_optab, operands[2],
7653 NULL_RTX, 1);
7654 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7655 NULL_RTX, 1, OPTAB_WIDEN);
7656 break;
7657
7658 case GT:
7659 scratch = expand_binop (SImode, ashr_optab, operands[2],
7660 GEN_INT (31), NULL_RTX, 0, OPTAB_WIDEN);
7661 scratch = expand_binop (SImode, sub_optab, scratch, operands[2],
7662 NULL_RTX, 0, OPTAB_WIDEN);
7663 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31), operands[0],
7664 0, OPTAB_WIDEN);
7665 break;
7666
7667 /* LT is handled by generic code. No need for unsigned with 0. */
7668 default:
7669 FAIL;
7670 }
7671 DONE;
7672 }
7673
7674 switch (GET_CODE (operands[1]))
7675 {
7676 case EQ:
7677 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7678 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7679 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], scratch));
595d88b5 7680 break;
7681
7682 case NE:
7683 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7684 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7685 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], scratch));
595d88b5 7686 break;
7687
7688 case LE:
7689 op3 = force_reg (SImode, operands[3]);
7690
7691 scratch = expand_binop (SImode, lshr_optab, operands[2], GEN_INT (31),
7692 NULL_RTX, 1, OPTAB_WIDEN);
7693 scratch2 = expand_binop (SImode, ashr_optab, op3, GEN_INT (31),
7694 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7695 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
595d88b5 7696 op3, operands[2]));
7697 break;
7698
7699 case GE:
7700 op3 = operands[3];
25f905c2 7701 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7702 op3 = force_reg (SImode, op3);
7703 scratch = expand_binop (SImode, ashr_optab, operands[2], GEN_INT (31),
7704 NULL_RTX, 0, OPTAB_WIDEN);
7705 scratch2 = expand_binop (SImode, lshr_optab, op3, GEN_INT (31),
7706 NULL_RTX, 1, OPTAB_WIDEN);
25f905c2 7707 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
595d88b5 7708 operands[2], op3));
7709 break;
7710
7711 case LEU:
7712 op3 = force_reg (SImode, operands[3]);
7713 scratch = force_reg (SImode, const0_rtx);
25f905c2 7714 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
595d88b5 7715 op3, operands[2]));
7716 break;
7717
7718 case GEU:
7719 op3 = operands[3];
25f905c2 7720 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7721 op3 = force_reg (SImode, op3);
7722 scratch = force_reg (SImode, const0_rtx);
25f905c2 7723 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
595d88b5 7724 operands[2], op3));
7725 break;
7726
7727 case LTU:
7728 op3 = operands[3];
25f905c2 7729 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7730 op3 = force_reg (SImode, op3);
7731 scratch = gen_reg_rtx (SImode);
408b7ae5 7732 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], operands[2], op3));
595d88b5 7733 break;
7734
7735 case GTU:
7736 op3 = force_reg (SImode, operands[3]);
7737 scratch = gen_reg_rtx (SImode);
408b7ae5 7738 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], op3, operands[2]));
595d88b5 7739 break;
7740
7741 /* No good sequences for GT, LT. */
7742 default:
7743 FAIL;
7744 }
7745 DONE;
7746}")
7747
9854d864 7748(define_expand "cstorehf4"
7749 [(set (match_operand:SI 0 "s_register_operand")
7750 (match_operator:SI 1 "expandable_comparison_operator"
7751 [(match_operand:HF 2 "s_register_operand")
d7216193 7752 (match_operand:HF 3 "vfp_compare_operand")]))]
9854d864 7753 "TARGET_VFP_FP16INST"
7754 {
7755 if (!arm_validize_comparison (&operands[1],
7756 &operands[2],
7757 &operands[3]))
7758 FAIL;
7759
7760 emit_insn (gen_cstore_cc (operands[0], operands[1],
7761 operands[2], operands[3]));
7762 DONE;
7763 }
7764)
7765
74f4459c 7766(define_expand "cstoresf4"
7767 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 7768 (match_operator:SI 1 "expandable_comparison_operator"
74f4459c 7769 [(match_operand:SF 2 "s_register_operand" "")
d7216193 7770 (match_operand:SF 3 "vfp_compare_operand" "")]))]
74f4459c 7771 "TARGET_32BIT && TARGET_HARD_FLOAT"
7772 "emit_insn (gen_cstore_cc (operands[0], operands[1],
7773 operands[2], operands[3])); DONE;"
7774)
7775
7776(define_expand "cstoredf4"
7777 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 7778 (match_operator:SI 1 "expandable_comparison_operator"
74f4459c 7779 [(match_operand:DF 2 "s_register_operand" "")
d7216193 7780 (match_operand:DF 3 "vfp_compare_operand" "")]))]
d63ed457 7781 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
74f4459c 7782 "emit_insn (gen_cstore_cc (operands[0], operands[1],
7783 operands[2], operands[3])); DONE;"
7784)
7785
74f4459c 7786(define_expand "cstoredi4"
7787 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 7788 (match_operator:SI 1 "expandable_comparison_operator"
b8eae306 7789 [(match_operand:DI 2 "s_register_operand" "")
a8045a4f 7790 (match_operand:DI 3 "cmpdi_operand" "")]))]
7791 "TARGET_32BIT"
7792 "{
f9aa4160 7793 if (!arm_validize_comparison (&operands[1],
7794 &operands[2],
7795 &operands[3]))
7796 FAIL;
7797 emit_insn (gen_cstore_cc (operands[0], operands[1], operands[2],
a8045a4f 7798 operands[3]));
7799 DONE;
7800 }"
74f4459c 7801)
7802
9c08d1fa 7803\f
39b5e676 7804;; Conditional move insns
7805
7806(define_expand "movsicc"
8a18b90c 7807 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 7808 (if_then_else:SI (match_operand 1 "expandable_comparison_operator" "")
aea4c774 7809 (match_operand:SI 2 "arm_not_operand" "")
8a18b90c 7810 (match_operand:SI 3 "arm_not_operand" "")))]
25f905c2 7811 "TARGET_32BIT"
39b5e676 7812 "
215b30b3 7813 {
f9aa4160 7814 enum rtx_code code;
278b301d 7815 rtx ccreg;
7816
f9aa4160 7817 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
9854d864 7818 &XEXP (operands[1], 1)))
278b301d 7819 FAIL;
9854d864 7820
7821 code = GET_CODE (operands[1]);
7822 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
7823 XEXP (operands[1], 1), NULL_RTX);
7824 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7825 }"
7826)
7827
7828(define_expand "movhfcc"
7829 [(set (match_operand:HF 0 "s_register_operand")
7830 (if_then_else:HF (match_operand 1 "arm_cond_move_operator")
7831 (match_operand:HF 2 "s_register_operand")
7832 (match_operand:HF 3 "s_register_operand")))]
7833 "TARGET_VFP_FP16INST"
7834 "
7835 {
7836 enum rtx_code code = GET_CODE (operands[1]);
7837 rtx ccreg;
7838
7839 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
7840 &XEXP (operands[1], 1)))
7841 FAIL;
7842
f9aa4160 7843 code = GET_CODE (operands[1]);
74f4459c 7844 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
e1b93706 7845 XEXP (operands[1], 1), NULL_RTX);
29bb088d 7846 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7847 }"
7848)
39b5e676 7849
7850(define_expand "movsfcc"
8a18b90c 7851 [(set (match_operand:SF 0 "s_register_operand" "")
4df97ffc 7852 (if_then_else:SF (match_operand 1 "arm_cond_move_operator" "")
8a18b90c 7853 (match_operand:SF 2 "s_register_operand" "")
d86c91f6 7854 (match_operand:SF 3 "s_register_operand" "")))]
19f6bf8d 7855 "TARGET_32BIT && TARGET_HARD_FLOAT"
39b5e676 7856 "
215b30b3 7857 {
7858 enum rtx_code code = GET_CODE (operands[1]);
7859 rtx ccreg;
f082f1c4 7860
9854d864 7861 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
f9aa4160 7862 &XEXP (operands[1], 1)))
7863 FAIL;
39b5e676 7864
f9aa4160 7865 code = GET_CODE (operands[1]);
74f4459c 7866 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
e1b93706 7867 XEXP (operands[1], 1), NULL_RTX);
29bb088d 7868 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7869 }"
7870)
39b5e676 7871
7872(define_expand "movdfcc"
8a18b90c 7873 [(set (match_operand:DF 0 "s_register_operand" "")
4df97ffc 7874 (if_then_else:DF (match_operand 1 "arm_cond_move_operator" "")
8a18b90c 7875 (match_operand:DF 2 "s_register_operand" "")
d86c91f6 7876 (match_operand:DF 3 "s_register_operand" "")))]
994606f8 7877 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
39b5e676 7878 "
215b30b3 7879 {
7880 enum rtx_code code = GET_CODE (operands[1]);
278b301d 7881 rtx ccreg;
39b5e676 7882
f9aa4160 7883 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
7884 &XEXP (operands[1], 1)))
7885 FAIL;
7886 code = GET_CODE (operands[1]);
74f4459c 7887 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
e1b93706 7888 XEXP (operands[1], 1), NULL_RTX);
29bb088d 7889 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7890 }"
7891)
39b5e676 7892
91cb50d2 7893(define_insn "*cmov<mode>"
7894 [(set (match_operand:SDF 0 "s_register_operand" "=<F_constraint>")
7895 (if_then_else:SDF (match_operator 1 "arm_vsel_comparison_operator"
7896 [(match_operand 2 "cc_register" "") (const_int 0)])
7897 (match_operand:SDF 3 "s_register_operand"
7898 "<F_constraint>")
7899 (match_operand:SDF 4 "s_register_operand"
7900 "<F_constraint>")))]
c79c1b1b 7901 "TARGET_HARD_FLOAT && TARGET_VFP5 <vfp_double_cond>"
91cb50d2 7902 "*
7903 {
7904 enum arm_cond_code code = maybe_get_arm_condition_code (operands[1]);
7905 switch (code)
7906 {
7907 case ARM_GE:
7908 case ARM_GT:
7909 case ARM_EQ:
7910 case ARM_VS:
7911 return \"vsel%d1.<V_if_elem>\\t%<V_reg>0, %<V_reg>3, %<V_reg>4\";
7912 case ARM_LT:
7913 case ARM_LE:
7914 case ARM_NE:
7915 case ARM_VC:
7916 return \"vsel%D1.<V_if_elem>\\t%<V_reg>0, %<V_reg>4, %<V_reg>3\";
7917 default:
7918 gcc_unreachable ();
7919 }
7920 return \"\";
7921 }"
7922 [(set_attr "conds" "use")
6664d308 7923 (set_attr "type" "fcsel")]
91cb50d2 7924)
7925
9854d864 7926(define_insn "*cmovhf"
7927 [(set (match_operand:HF 0 "s_register_operand" "=t")
7928 (if_then_else:HF (match_operator 1 "arm_vsel_comparison_operator"
7929 [(match_operand 2 "cc_register" "") (const_int 0)])
7930 (match_operand:HF 3 "s_register_operand" "t")
7931 (match_operand:HF 4 "s_register_operand" "t")))]
7932 "TARGET_VFP_FP16INST"
7933 "*
7934 {
7935 enum arm_cond_code code = maybe_get_arm_condition_code (operands[1]);
7936 switch (code)
7937 {
7938 case ARM_GE:
7939 case ARM_GT:
7940 case ARM_EQ:
7941 case ARM_VS:
7942 return \"vsel%d1.f16\\t%0, %3, %4\";
7943 case ARM_LT:
7944 case ARM_LE:
7945 case ARM_NE:
7946 case ARM_VC:
7947 return \"vsel%D1.f16\\t%0, %4, %3\";
7948 default:
7949 gcc_unreachable ();
7950 }
7951 return \"\";
7952 }"
7953 [(set_attr "conds" "use")
7954 (set_attr "type" "fcsel")]
7955)
7956
190efb17 7957(define_insn_and_split "*movsicc_insn"
f082f1c4 7958 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
8a18b90c 7959 (if_then_else:SI
8fa3ba89 7960 (match_operator 3 "arm_comparison_operator"
8a18b90c 7961 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 7962 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
7963 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
cffb2a26 7964 "TARGET_ARM"
39b5e676 7965 "@
8a18b90c 7966 mov%D3\\t%0, %2
7967 mvn%D3\\t%0, #%B2
f082f1c4 7968 mov%d3\\t%0, %1
7969 mvn%d3\\t%0, #%B1
190efb17 7970 #
7971 #
7972 #
7973 #"
7974 ; alt4: mov%d3\\t%0, %1\;mov%D3\\t%0, %2
7975 ; alt5: mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
7976 ; alt6: mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
7977 ; alt7: mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
7978 "&& reload_completed"
7979 [(const_int 0)]
7980 {
7981 enum rtx_code rev_code;
3754d046 7982 machine_mode mode;
190efb17 7983 rtx rev_cond;
7984
7985 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
7986 operands[3],
d1f9b275 7987 gen_rtx_SET (operands[0], operands[1])));
190efb17 7988
7989 rev_code = GET_CODE (operands[3]);
7990 mode = GET_MODE (operands[4]);
7991 if (mode == CCFPmode || mode == CCFPEmode)
7992 rev_code = reverse_condition_maybe_unordered (rev_code);
7993 else
7994 rev_code = reverse_condition (rev_code);
7995
7996 rev_cond = gen_rtx_fmt_ee (rev_code,
7997 VOIDmode,
7998 operands[4],
7999 const0_rtx);
8000 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
8001 rev_cond,
d1f9b275 8002 gen_rtx_SET (operands[0], operands[2])));
190efb17 8003 DONE;
8004 }
f082f1c4 8005 [(set_attr "length" "4,4,4,4,8,8,8,8")
d2a518d1 8006 (set_attr "conds" "use")
65f68e55 8007 (set_attr_alternative "type"
8008 [(if_then_else (match_operand 2 "const_int_operand" "")
1aed5204 8009 (const_string "mov_imm")
8010 (const_string "mov_reg"))
8011 (const_string "mvn_imm")
65f68e55 8012 (if_then_else (match_operand 1 "const_int_operand" "")
1aed5204 8013 (const_string "mov_imm")
8014 (const_string "mov_reg"))
8015 (const_string "mvn_imm")
282b4c75 8016 (const_string "multiple")
8017 (const_string "multiple")
8018 (const_string "multiple")
8019 (const_string "multiple")])]
215b30b3 8020)
39b5e676 8021
39b5e676 8022(define_insn "*movsfcc_soft_insn"
f082f1c4 8023 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
8fa3ba89 8024 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
8a18b90c 8025 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 8026 (match_operand:SF 1 "s_register_operand" "0,r")
8027 (match_operand:SF 2 "s_register_operand" "r,0")))]
cffb2a26 8028 "TARGET_ARM && TARGET_SOFT_FLOAT"
f082f1c4 8029 "@
8030 mov%D3\\t%0, %2
8031 mov%d3\\t%0, %1"
d2a518d1 8032 [(set_attr "conds" "use")
1aed5204 8033 (set_attr "type" "mov_reg")]
8fa3ba89 8034)
39b5e676 8035
39b5e676 8036\f
9c08d1fa 8037;; Jump and linkage insns
8038
cffb2a26 8039(define_expand "jump"
9c08d1fa 8040 [(set (pc)
8041 (label_ref (match_operand 0 "" "")))]
cffb2a26 8042 "TARGET_EITHER"
9c08d1fa 8043 ""
cffb2a26 8044)
8045
8046(define_insn "*arm_jump"
8047 [(set (pc)
8048 (label_ref (match_operand 0 "" "")))]
25f905c2 8049 "TARGET_32BIT"
9c08d1fa 8050 "*
0d66636f 8051 {
8052 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
8053 {
8054 arm_ccfsm_state += 2;
8055 return \"\";
8056 }
8057 return \"b%?\\t%l0\";
8058 }
8059 "
a6864a24 8060 [(set_attr "predicable" "yes")
8061 (set (attr "length")
8062 (if_then_else
0bf497f5 8063 (and (match_test "TARGET_THUMB2")
a6864a24 8064 (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
8065 (le (minus (match_dup 0) (pc)) (const_int 2048))))
8066 (const_int 2)
1b7da4ac 8067 (const_int 4)))
8068 (set_attr "type" "branch")]
0d66636f 8069)
9c08d1fa 8070
d3373b54 8071(define_expand "call"
8072 [(parallel [(call (match_operand 0 "memory_operand" "")
8073 (match_operand 1 "general_operand" ""))
cffb2a26 8074 (use (match_operand 2 "" ""))
bd5b4116 8075 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 8076 "TARGET_EITHER"
6c4c2133 8077 "
8078 {
bac7fc85 8079 rtx callee, pat;
2d3a01a7 8080 tree addr = MEM_EXPR (operands[0]);
bbe777ea 8081
bbe777ea 8082 /* In an untyped call, we can get NULL for operand 2. */
8083 if (operands[2] == NULL_RTX)
8084 operands[2] = const0_rtx;
8085
de55252a 8086 /* Decide if we should generate indirect calls by loading the
85c36fd1 8087 32-bit address of the callee into a register before performing the
de55252a 8088 branch and link. */
8089 callee = XEXP (operands[0], 0);
8090 if (GET_CODE (callee) == SYMBOL_REF
8091 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
8092 : !REG_P (callee))
bbe777ea 8093 XEXP (operands[0], 0) = force_reg (Pmode, callee);
bac7fc85 8094
2d3a01a7 8095 if (detect_cmse_nonsecure_call (addr))
8096 {
8097 pat = gen_nonsecure_call_internal (operands[0], operands[1],
8098 operands[2]);
8099 emit_call_insn (pat);
8100 }
8101 else
8102 {
8103 pat = gen_call_internal (operands[0], operands[1], operands[2]);
8104 arm_emit_call_insn (pat, XEXP (operands[0], 0), false);
8105 }
bac7fc85 8106 DONE;
6c4c2133 8107 }"
8108)
d3373b54 8109
bac7fc85 8110(define_expand "call_internal"
8111 [(parallel [(call (match_operand 0 "memory_operand" "")
8112 (match_operand 1 "general_operand" ""))
8113 (use (match_operand 2 "" ""))
8114 (clobber (reg:SI LR_REGNUM))])])
8115
2d3a01a7 8116(define_expand "nonsecure_call_internal"
8117 [(parallel [(call (unspec:SI [(match_operand 0 "memory_operand" "")]
8118 UNSPEC_NONSECURE_MEM)
8119 (match_operand 1 "general_operand" ""))
8120 (use (match_operand 2 "" ""))
8121 (clobber (reg:SI LR_REGNUM))
8122 (clobber (reg:SI 4))])]
8123 "use_cmse"
8124 "
8125 {
8126 rtx tmp;
8127 tmp = copy_to_suggested_reg (XEXP (operands[0], 0),
8128 gen_rtx_REG (SImode, 4),
8129 SImode);
8130
8131 operands[0] = replace_equiv_address (operands[0], tmp);
8132 }")
8133
f1039640 8134(define_insn "*call_reg_armv5"
d3373b54 8135 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
cffb2a26 8136 (match_operand 1 "" ""))
8137 (use (match_operand 2 "" ""))
bd5b4116 8138 (clobber (reg:SI LR_REGNUM))]
33ae7c4b 8139 "TARGET_ARM && arm_arch5 && !SIBLING_CALL_P (insn)"
f1039640 8140 "blx%?\\t%0"
8141 [(set_attr "type" "call")]
8142)
8143
8144(define_insn "*call_reg_arm"
8145 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
8146 (match_operand 1 "" ""))
8147 (use (match_operand 2 "" ""))
8148 (clobber (reg:SI LR_REGNUM))]
33ae7c4b 8149 "TARGET_ARM && !arm_arch5 && !SIBLING_CALL_P (insn)"
9c08d1fa 8150 "*
5565501b 8151 return output_call (operands);
cffb2a26 8152 "
8153 ;; length is worst case, normally it is only two
8154 [(set_attr "length" "12")
8155 (set_attr "type" "call")]
8156)
9c08d1fa 8157
89504fc1 8158
d3373b54 8159(define_expand "call_value"
e0698af7 8160 [(parallel [(set (match_operand 0 "" "")
8161 (call (match_operand 1 "memory_operand" "")
8162 (match_operand 2 "general_operand" "")))
cffb2a26 8163 (use (match_operand 3 "" ""))
bd5b4116 8164 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 8165 "TARGET_EITHER"
6c4c2133 8166 "
8167 {
bac7fc85 8168 rtx pat, callee;
2d3a01a7 8169 tree addr = MEM_EXPR (operands[1]);
bbe777ea 8170
8171 /* In an untyped call, we can get NULL for operand 2. */
8172 if (operands[3] == 0)
8173 operands[3] = const0_rtx;
8174
de55252a 8175 /* Decide if we should generate indirect calls by loading the
8176 32-bit address of the callee into a register before performing the
8177 branch and link. */
8178 callee = XEXP (operands[1], 0);
8179 if (GET_CODE (callee) == SYMBOL_REF
8180 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
8181 : !REG_P (callee))
78fe751b 8182 XEXP (operands[1], 0) = force_reg (Pmode, callee);
bac7fc85 8183
2d3a01a7 8184 if (detect_cmse_nonsecure_call (addr))
8185 {
8186 pat = gen_nonsecure_call_value_internal (operands[0], operands[1],
8187 operands[2], operands[3]);
8188 emit_call_insn (pat);
8189 }
8190 else
8191 {
8192 pat = gen_call_value_internal (operands[0], operands[1],
8193 operands[2], operands[3]);
8194 arm_emit_call_insn (pat, XEXP (operands[1], 0), false);
8195 }
bac7fc85 8196 DONE;
6c4c2133 8197 }"
8198)
d3373b54 8199
bac7fc85 8200(define_expand "call_value_internal"
8201 [(parallel [(set (match_operand 0 "" "")
8202 (call (match_operand 1 "memory_operand" "")
8203 (match_operand 2 "general_operand" "")))
8204 (use (match_operand 3 "" ""))
8205 (clobber (reg:SI LR_REGNUM))])])
8206
2d3a01a7 8207(define_expand "nonsecure_call_value_internal"
8208 [(parallel [(set (match_operand 0 "" "")
8209 (call (unspec:SI [(match_operand 1 "memory_operand" "")]
8210 UNSPEC_NONSECURE_MEM)
8211 (match_operand 2 "general_operand" "")))
8212 (use (match_operand 3 "" ""))
8213 (clobber (reg:SI LR_REGNUM))
8214 (clobber (reg:SI 4))])]
8215 "use_cmse"
8216 "
8217 {
8218 rtx tmp;
8219 tmp = copy_to_suggested_reg (XEXP (operands[1], 0),
8220 gen_rtx_REG (SImode, 4),
8221 SImode);
8222
8223 operands[1] = replace_equiv_address (operands[1], tmp);
8224 }")
8225
f1039640 8226(define_insn "*call_value_reg_armv5"
27ed6835 8227 [(set (match_operand 0 "" "")
755eb2b4 8228 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
cffb2a26 8229 (match_operand 2 "" "")))
bbe777ea 8230 (use (match_operand 3 "" ""))
bd5b4116 8231 (clobber (reg:SI LR_REGNUM))]
33ae7c4b 8232 "TARGET_ARM && arm_arch5 && !SIBLING_CALL_P (insn)"
f1039640 8233 "blx%?\\t%1"
8234 [(set_attr "type" "call")]
8235)
8236
8237(define_insn "*call_value_reg_arm"
8238 [(set (match_operand 0 "" "")
8239 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
8240 (match_operand 2 "" "")))
8241 (use (match_operand 3 "" ""))
8242 (clobber (reg:SI LR_REGNUM))]
33ae7c4b 8243 "TARGET_ARM && !arm_arch5 && !SIBLING_CALL_P (insn)"
9c08d1fa 8244 "*
215b30b3 8245 return output_call (&operands[1]);
cffb2a26 8246 "
8247 [(set_attr "length" "12")
8248 (set_attr "type" "call")]
8249)
9c08d1fa 8250
9c08d1fa 8251;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
8252;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
8253
f7fbdd4a 8254(define_insn "*call_symbol"
27ed6835 8255 [(call (mem:SI (match_operand:SI 0 "" ""))
cffb2a26 8256 (match_operand 1 "" ""))
bbe777ea 8257 (use (match_operand 2 "" ""))
bd5b4116 8258 (clobber (reg:SI LR_REGNUM))]
d68c2c10 8259 "TARGET_32BIT
33ae7c4b 8260 && !SIBLING_CALL_P (insn)
cffb2a26 8261 && (GET_CODE (operands[0]) == SYMBOL_REF)
de55252a 8262 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
6ebaa29d 8263 "*
8264 {
95f1e0d1 8265 rtx op = operands[0];
8266
8267 /* Switch mode now when possible. */
8268 if (SYMBOL_REF_DECL (op) && !TREE_PUBLIC (SYMBOL_REF_DECL (op))
8269 && arm_arch5 && arm_change_mode_p (SYMBOL_REF_DECL (op)))
8270 return NEED_PLT_RELOC ? \"blx%?\\t%a0(PLT)\" : \"blx%?\\t(%a0)\";
8271
55c1e470 8272 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
6ebaa29d 8273 }"
cffb2a26 8274 [(set_attr "type" "call")]
8275)
9c08d1fa 8276
f7fbdd4a 8277(define_insn "*call_value_symbol"
ccd90aaa 8278 [(set (match_operand 0 "" "")
27ed6835 8279 (call (mem:SI (match_operand:SI 1 "" ""))
dd6d7504 8280 (match_operand:SI 2 "" "")))
bbe777ea 8281 (use (match_operand 3 "" ""))
bd5b4116 8282 (clobber (reg:SI LR_REGNUM))]
d68c2c10 8283 "TARGET_32BIT
33ae7c4b 8284 && !SIBLING_CALL_P (insn)
cffb2a26 8285 && (GET_CODE (operands[1]) == SYMBOL_REF)
de55252a 8286 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
6ebaa29d 8287 "*
8288 {
95f1e0d1 8289 rtx op = operands[1];
8290
8291 /* Switch mode now when possible. */
8292 if (SYMBOL_REF_DECL (op) && !TREE_PUBLIC (SYMBOL_REF_DECL (op))
8293 && arm_arch5 && arm_change_mode_p (SYMBOL_REF_DECL (op)))
3f6b66fa 8294 return NEED_PLT_RELOC ? \"blx%?\\t%a1(PLT)\" : \"blx%?\\t(%a1)\";
95f1e0d1 8295
55c1e470 8296 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
6ebaa29d 8297 }"
cffb2a26 8298 [(set_attr "type" "call")]
8299)
8300
ca373797 8301(define_expand "sibcall_internal"
8302 [(parallel [(call (match_operand 0 "memory_operand" "")
8303 (match_operand 1 "general_operand" ""))
8304 (return)
8305 (use (match_operand 2 "" ""))])])
8306
1c494086 8307;; We may also be able to do sibcalls for Thumb, but it's much harder...
8308(define_expand "sibcall"
8309 [(parallel [(call (match_operand 0 "memory_operand" "")
8310 (match_operand 1 "general_operand" ""))
2ba80634 8311 (return)
8312 (use (match_operand 2 "" ""))])]
d68c2c10 8313 "TARGET_32BIT"
1c494086 8314 "
8315 {
ca373797 8316 rtx pat;
8317
3112c3f7 8318 if ((!REG_P (XEXP (operands[0], 0))
8319 && GET_CODE (XEXP (operands[0], 0)) != SYMBOL_REF)
8320 || (GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
8321 && arm_is_long_call_p (SYMBOL_REF_DECL (XEXP (operands[0], 0)))))
33ae7c4b 8322 XEXP (operands[0], 0) = force_reg (SImode, XEXP (operands[0], 0));
8323
1c494086 8324 if (operands[2] == NULL_RTX)
8325 operands[2] = const0_rtx;
ca373797 8326
8327 pat = gen_sibcall_internal (operands[0], operands[1], operands[2]);
8328 arm_emit_call_insn (pat, operands[0], true);
8329 DONE;
1c494086 8330 }"
8331)
8332
ca373797 8333(define_expand "sibcall_value_internal"
8334 [(parallel [(set (match_operand 0 "" "")
8335 (call (match_operand 1 "memory_operand" "")
8336 (match_operand 2 "general_operand" "")))
8337 (return)
8338 (use (match_operand 3 "" ""))])])
8339
1c494086 8340(define_expand "sibcall_value"
ccd90aaa 8341 [(parallel [(set (match_operand 0 "" "")
1c494086 8342 (call (match_operand 1 "memory_operand" "")
8343 (match_operand 2 "general_operand" "")))
2ba80634 8344 (return)
8345 (use (match_operand 3 "" ""))])]
d68c2c10 8346 "TARGET_32BIT"
1c494086 8347 "
8348 {
ca373797 8349 rtx pat;
8350
3112c3f7 8351 if ((!REG_P (XEXP (operands[1], 0))
8352 && GET_CODE (XEXP (operands[1], 0)) != SYMBOL_REF)
8353 || (GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
8354 && arm_is_long_call_p (SYMBOL_REF_DECL (XEXP (operands[1], 0)))))
33ae7c4b 8355 XEXP (operands[1], 0) = force_reg (SImode, XEXP (operands[1], 0));
8356
1c494086 8357 if (operands[3] == NULL_RTX)
8358 operands[3] = const0_rtx;
ca373797 8359
8360 pat = gen_sibcall_value_internal (operands[0], operands[1],
8361 operands[2], operands[3]);
8362 arm_emit_call_insn (pat, operands[1], true);
8363 DONE;
1c494086 8364 }"
8365)
8366
8367(define_insn "*sibcall_insn"
84ce8e5c 8368 [(call (mem:SI (match_operand:SI 0 "call_insn_operand" "Cs, US"))
1c494086 8369 (match_operand 1 "" ""))
2ba80634 8370 (return)
8371 (use (match_operand 2 "" ""))]
33ae7c4b 8372 "TARGET_32BIT && SIBLING_CALL_P (insn)"
1c494086 8373 "*
33ae7c4b 8374 if (which_alternative == 1)
8375 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
8376 else
8377 {
8378 if (arm_arch5 || arm_arch4t)
947d113e 8379 return \"bx%?\\t%0\\t%@ indirect register sibling call\";
33ae7c4b 8380 else
8381 return \"mov%?\\t%|pc, %0\\t%@ indirect register sibling call\";
8382 }
1c494086 8383 "
8384 [(set_attr "type" "call")]
8385)
8386
8387(define_insn "*sibcall_value_insn"
84ce8e5c 8388 [(set (match_operand 0 "" "")
8389 (call (mem:SI (match_operand:SI 1 "call_insn_operand" "Cs,US"))
1c494086 8390 (match_operand 2 "" "")))
2ba80634 8391 (return)
8392 (use (match_operand 3 "" ""))]
33ae7c4b 8393 "TARGET_32BIT && SIBLING_CALL_P (insn)"
1c494086 8394 "*
33ae7c4b 8395 if (which_alternative == 1)
8396 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
8397 else
8398 {
8399 if (arm_arch5 || arm_arch4t)
84ce8e5c 8400 return \"bx%?\\t%1\";
33ae7c4b 8401 else
8402 return \"mov%?\\t%|pc, %1\\t@ indirect sibling call \";
8403 }
1c494086 8404 "
8405 [(set_attr "type" "call")]
8406)
8407
0686440e 8408(define_expand "<return_str>return"
9b23f0a7 8409 [(RETURNS)]
8cba51a5 8410 "(TARGET_ARM || (TARGET_THUMB2
8411 && ARM_FUNC_TYPE (arm_current_func_type ()) == ARM_FT_NORMAL
8412 && !IS_STACKALIGN (arm_current_func_type ())))
0686440e 8413 <return_cond_false>"
8cba51a5 8414 "
8415 {
8416 if (TARGET_THUMB2)
8417 {
0686440e 8418 thumb2_expand_return (<return_simple_p>);
8cba51a5 8419 DONE;
8420 }
8421 }
8422 "
8423)
d68c2c10 8424
9c08d1fa 8425;; Often the return insn will be the same as loading from memory, so set attr
d68c2c10 8426(define_insn "*arm_return"
9c08d1fa 8427 [(return)]
cffb2a26 8428 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
9c08d1fa 8429 "*
9c08d1fa 8430 {
cffb2a26 8431 if (arm_ccfsm_state == 2)
8432 {
8433 arm_ccfsm_state += 2;
8434 return \"\";
8435 }
e2549f81 8436 return output_return_instruction (const_true_rtx, true, false, false);
cffb2a26 8437 }"
9f2c2a36 8438 [(set_attr "type" "load_4")
755eb2b4 8439 (set_attr "length" "12")
0d66636f 8440 (set_attr "predicable" "yes")]
cffb2a26 8441)
9c08d1fa 8442
0686440e 8443(define_insn "*cond_<return_str>return"
9c08d1fa 8444 [(set (pc)
8fa3ba89 8445 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 8446 [(match_operand 1 "cc_register" "") (const_int 0)])
9b23f0a7 8447 (RETURNS)
9c08d1fa 8448 (pc)))]
0686440e 8449 "TARGET_ARM <return_cond_true>"
9c08d1fa 8450 "*
8fa3ba89 8451 {
8452 if (arm_ccfsm_state == 2)
8453 {
8454 arm_ccfsm_state += 2;
8455 return \"\";
8456 }
0686440e 8457 return output_return_instruction (operands[0], true, false,
8458 <return_simple_p>);
8fa3ba89 8459 }"
8460 [(set_attr "conds" "use")
755eb2b4 8461 (set_attr "length" "12")
9f2c2a36 8462 (set_attr "type" "load_4")]
8fa3ba89 8463)
9c08d1fa 8464
0686440e 8465(define_insn "*cond_<return_str>return_inverted"
9c08d1fa 8466 [(set (pc)
8fa3ba89 8467 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 8468 [(match_operand 1 "cc_register" "") (const_int 0)])
9c08d1fa 8469 (pc)
9b23f0a7 8470 (RETURNS)))]
0686440e 8471 "TARGET_ARM <return_cond_true>"
9c08d1fa 8472 "*
8fa3ba89 8473 {
8474 if (arm_ccfsm_state == 2)
8475 {
8476 arm_ccfsm_state += 2;
8477 return \"\";
8478 }
0686440e 8479 return output_return_instruction (operands[0], true, true,
8480 <return_simple_p>);
8fa3ba89 8481 }"
8482 [(set_attr "conds" "use")
37a1317b 8483 (set_attr "length" "12")
9f2c2a36 8484 (set_attr "type" "load_4")]
8fa3ba89 8485)
9c08d1fa 8486
e2549f81 8487(define_insn "*arm_simple_return"
8488 [(simple_return)]
8489 "TARGET_ARM"
8490 "*
8491 {
8492 if (arm_ccfsm_state == 2)
8493 {
8494 arm_ccfsm_state += 2;
8495 return \"\";
8496 }
8497 return output_return_instruction (const_true_rtx, true, false, true);
8498 }"
8499 [(set_attr "type" "branch")
8500 (set_attr "length" "4")
8501 (set_attr "predicable" "yes")]
8502)
8503
68121397 8504;; Generate a sequence of instructions to determine if the processor is
8505;; in 26-bit or 32-bit mode, and return the appropriate return address
8506;; mask.
8507
8508(define_expand "return_addr_mask"
8509 [(set (match_dup 1)
8510 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8511 (const_int 0)))
8512 (set (match_operand:SI 0 "s_register_operand" "")
8513 (if_then_else:SI (eq (match_dup 1) (const_int 0))
8514 (const_int -1)
8515 (const_int 67108860)))] ; 0x03fffffc
8516 "TARGET_ARM"
8517 "
62eddbd4 8518 operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
68121397 8519 ")
8520
8521(define_insn "*check_arch2"
8522 [(set (match_operand:CC_NOOV 0 "cc_register" "")
8523 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8524 (const_int 0)))]
8525 "TARGET_ARM"
8526 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
8527 [(set_attr "length" "8")
1b7da4ac 8528 (set_attr "conds" "set")
8529 (set_attr "type" "multiple")]
68121397 8530)
8531
9c08d1fa 8532;; Call subroutine returning any type.
8533
8534(define_expand "untyped_call"
8535 [(parallel [(call (match_operand 0 "" "")
8536 (const_int 0))
8537 (match_operand 1 "" "")
8538 (match_operand 2 "" "")])]
ccd90aaa 8539 "TARGET_EITHER"
9c08d1fa 8540 "
215b30b3 8541 {
8542 int i;
ccd90aaa 8543 rtx par = gen_rtx_PARALLEL (VOIDmode,
8544 rtvec_alloc (XVECLEN (operands[2], 0)));
8545 rtx addr = gen_reg_rtx (Pmode);
8546 rtx mem;
8547 int size = 0;
9c08d1fa 8548
ccd90aaa 8549 emit_move_insn (addr, XEXP (operands[1], 0));
8550 mem = change_address (operands[1], BLKmode, addr);
9c08d1fa 8551
215b30b3 8552 for (i = 0; i < XVECLEN (operands[2], 0); i++)
8553 {
ccd90aaa 8554 rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
9c08d1fa 8555
ccd90aaa 8556 /* Default code only uses r0 as a return value, but we could
8557 be using anything up to 4 registers. */
8558 if (REGNO (src) == R0_REGNUM)
8559 src = gen_rtx_REG (TImode, R0_REGNUM);
8560
8561 XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
8562 GEN_INT (size));
8563 size += GET_MODE_SIZE (GET_MODE (src));
8564 }
8565
7f265a08 8566 emit_call_insn (gen_call_value (par, operands[0], const0_rtx, NULL));
ccd90aaa 8567
8568 size = 0;
8569
8570 for (i = 0; i < XVECLEN (par, 0); i++)
8571 {
8572 HOST_WIDE_INT offset = 0;
8573 rtx reg = XEXP (XVECEXP (par, 0, i), 0);
8574
8575 if (size != 0)
29c05e22 8576 emit_move_insn (addr, plus_constant (Pmode, addr, size));
ccd90aaa 8577
8578 mem = change_address (mem, GET_MODE (reg), NULL);
8579 if (REGNO (reg) == R0_REGNUM)
8580 {
8581 /* On thumb we have to use a write-back instruction. */
320ea44d 8582 emit_insn (arm_gen_store_multiple (arm_regs_in_sequence, 4, addr,
8583 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
ccd90aaa 8584 size = TARGET_ARM ? 16 : 0;
8585 }
8586 else
8587 {
8588 emit_move_insn (mem, reg);
8589 size = GET_MODE_SIZE (GET_MODE (reg));
8590 }
215b30b3 8591 }
9c08d1fa 8592
215b30b3 8593 /* The optimizer does not know that the call sets the function value
8594 registers we stored in the result block. We avoid problems by
8595 claiming that all hard registers are used and clobbered at this
8596 point. */
8597 emit_insn (gen_blockage ());
8598
8599 DONE;
8600 }"
8601)
9c08d1fa 8602
ccd90aaa 8603(define_expand "untyped_return"
8604 [(match_operand:BLK 0 "memory_operand" "")
8605 (match_operand 1 "" "")]
8606 "TARGET_EITHER"
8607 "
8608 {
8609 int i;
8610 rtx addr = gen_reg_rtx (Pmode);
8611 rtx mem;
8612 int size = 0;
8613
8614 emit_move_insn (addr, XEXP (operands[0], 0));
8615 mem = change_address (operands[0], BLKmode, addr);
8616
8617 for (i = 0; i < XVECLEN (operands[1], 0); i++)
8618 {
8619 HOST_WIDE_INT offset = 0;
8620 rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
8621
8622 if (size != 0)
29c05e22 8623 emit_move_insn (addr, plus_constant (Pmode, addr, size));
ccd90aaa 8624
8625 mem = change_address (mem, GET_MODE (reg), NULL);
8626 if (REGNO (reg) == R0_REGNUM)
8627 {
8628 /* On thumb we have to use a write-back instruction. */
320ea44d 8629 emit_insn (arm_gen_load_multiple (arm_regs_in_sequence, 4, addr,
8630 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
ccd90aaa 8631 size = TARGET_ARM ? 16 : 0;
8632 }
8633 else
8634 {
8635 emit_move_insn (reg, mem);
8636 size = GET_MODE_SIZE (GET_MODE (reg));
8637 }
8638 }
8639
8640 /* Emit USE insns before the return. */
8641 for (i = 0; i < XVECLEN (operands[1], 0); i++)
18b42941 8642 emit_use (SET_DEST (XVECEXP (operands[1], 0, i)));
ccd90aaa 8643
8644 /* Construct the return. */
8645 expand_naked_return ();
8646
8647 DONE;
8648 }"
8649)
8650
9c08d1fa 8651;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
8652;; all of memory. This blocks insns from being moved across this point.
8653
8654(define_insn "blockage"
e1159bbe 8655 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
cffb2a26 8656 "TARGET_EITHER"
9c08d1fa 8657 ""
cffb2a26 8658 [(set_attr "length" "0")
8659 (set_attr "type" "block")]
8660)
9c08d1fa 8661
706dca65 8662(define_insn "probe_stack"
f8570abe 8663 [(set (match_operand:SI 0 "memory_operand" "=m")
8664 (unspec:SI [(const_int 0)] UNSPEC_PROBE_STACK))]
706dca65 8665 "TARGET_32BIT"
154ae8e6 8666 "str%?\\tr0, %0"
9f2c2a36 8667 [(set_attr "type" "store_4")
706dca65 8668 (set_attr "predicable" "yes")]
8669)
8670
8671(define_insn "probe_stack_range"
8672 [(set (match_operand:SI 0 "register_operand" "=r")
8673 (unspec_volatile:SI [(match_operand:SI 1 "register_operand" "0")
8674 (match_operand:SI 2 "register_operand" "r")]
dd8aabc9 8675 VUNSPEC_PROBE_STACK_RANGE))]
706dca65 8676 "TARGET_32BIT"
8677{
8678 return output_probe_stack_range (operands[0], operands[2]);
8679}
8680 [(set_attr "type" "multiple")
8681 (set_attr "conds" "clob")]
8682)
8683
f7fbdd4a 8684(define_expand "casesi"
8685 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
aea4c774 8686 (match_operand:SI 1 "const_int_operand" "") ; lower bound
8687 (match_operand:SI 2 "const_int_operand" "") ; total range
f7fbdd4a 8688 (match_operand:SI 3 "" "") ; table label
8689 (match_operand:SI 4 "" "")] ; Out of range label
9753b549 8690 "(TARGET_32BIT || optimize_size || flag_pic) && !target_pure_code"
f7fbdd4a 8691 "
215b30b3 8692 {
e6ac8414 8693 enum insn_code code;
215b30b3 8694 if (operands[1] != const0_rtx)
8695 {
e6ac8414 8696 rtx reg = gen_reg_rtx (SImode);
f7fbdd4a 8697
215b30b3 8698 emit_insn (gen_addsi3 (reg, operands[0],
d022fa24 8699 gen_int_mode (-INTVAL (operands[1]),
8700 SImode)));
215b30b3 8701 operands[0] = reg;
8702 }
9c08d1fa 8703
25f905c2 8704 if (TARGET_ARM)
e6ac8414 8705 code = CODE_FOR_arm_casesi_internal;
3db2019b 8706 else if (TARGET_THUMB1)
e6ac8414 8707 code = CODE_FOR_thumb1_casesi_internal_pic;
25f905c2 8708 else if (flag_pic)
e6ac8414 8709 code = CODE_FOR_thumb2_casesi_internal_pic;
25f905c2 8710 else
e6ac8414 8711 code = CODE_FOR_thumb2_casesi_internal;
8712
8713 if (!insn_data[(int) code].operand[1].predicate(operands[2], SImode))
8714 operands[2] = force_reg (SImode, operands[2]);
8715
8716 emit_jump_insn (GEN_FCN ((int) code) (operands[0], operands[2],
8717 operands[3], operands[4]));
215b30b3 8718 DONE;
8719 }"
8720)
f7fbdd4a 8721
f082f1c4 8722;; The USE in this pattern is needed to tell flow analysis that this is
8723;; a CASESI insn. It has no other purpose.
25f905c2 8724(define_insn "arm_casesi_internal"
f082f1c4 8725 [(parallel [(set (pc)
8726 (if_then_else
8727 (leu (match_operand:SI 0 "s_register_operand" "r")
8728 (match_operand:SI 1 "arm_rhs_operand" "rI"))
8729 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
8730 (label_ref (match_operand 2 "" ""))))
8731 (label_ref (match_operand 3 "" ""))))
bd5b4116 8732 (clobber (reg:CC CC_REGNUM))
f082f1c4 8733 (use (label_ref (match_dup 2)))])]
cffb2a26 8734 "TARGET_ARM"
f7fbdd4a 8735 "*
0d66636f 8736 if (flag_pic)
8737 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
8738 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
8739 "
8740 [(set_attr "conds" "clob")
1b7da4ac 8741 (set_attr "length" "12")
8742 (set_attr "type" "multiple")]
0d66636f 8743)
9c08d1fa 8744
cffb2a26 8745(define_expand "indirect_jump"
9c08d1fa 8746 [(set (pc)
cffb2a26 8747 (match_operand:SI 0 "s_register_operand" ""))]
8748 "TARGET_EITHER"
25f905c2 8749 "
8750 /* Thumb-2 doesn't have mov pc, reg. Explicitly set the low bit of the
8751 address and use bx. */
8752 if (TARGET_THUMB2)
8753 {
8754 rtx tmp;
8755 tmp = gen_reg_rtx (SImode);
8756 emit_insn (gen_iorsi3 (tmp, operands[0], GEN_INT(1)));
8757 operands[0] = tmp;
8758 }
8759 "
cffb2a26 8760)
8761
f1039640 8762;; NB Never uses BX.
cffb2a26 8763(define_insn "*arm_indirect_jump"
8764 [(set (pc)
8765 (match_operand:SI 0 "s_register_operand" "r"))]
8766 "TARGET_ARM"
8767 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
1b7da4ac 8768 [(set_attr "predicable" "yes")
8769 (set_attr "type" "branch")]
cffb2a26 8770)
9c08d1fa 8771
f7fbdd4a 8772(define_insn "*load_indirect_jump"
9c08d1fa 8773 [(set (pc)
8774 (match_operand:SI 0 "memory_operand" "m"))]
cffb2a26 8775 "TARGET_ARM"
8776 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
9f2c2a36 8777 [(set_attr "type" "load_4")
61a2d04c 8778 (set_attr "pool_range" "4096")
8779 (set_attr "neg_pool_range" "4084")
0d66636f 8780 (set_attr "predicable" "yes")]
cffb2a26 8781)
8782
9c08d1fa 8783\f
8784;; Misc insns
8785
8786(define_insn "nop"
8787 [(const_int 0)]
cffb2a26 8788 "TARGET_EITHER"
3ef90e77 8789 "nop"
cffb2a26 8790 [(set (attr "length")
8791 (if_then_else (eq_attr "is_thumb" "yes")
8792 (const_int 2)
1b7da4ac 8793 (const_int 4)))
8794 (set_attr "type" "mov_reg")]
cffb2a26 8795)
8796
ad9d4399 8797(define_insn "trap"
8798 [(trap_if (const_int 1) (const_int 0))]
8799 ""
8800 "*
8801 if (TARGET_ARM)
8802 return \".inst\\t0xe7f000f0\";
8803 else
8804 return \".inst\\t0xdeff\";
8805 "
8806 [(set (attr "length")
8807 (if_then_else (eq_attr "is_thumb" "yes")
8808 (const_int 2)
8809 (const_int 4)))
8810 (set_attr "type" "trap")
8811 (set_attr "conds" "unconditional")]
8812)
8813
9c08d1fa 8814\f
8815;; Patterns to allow combination of arithmetic, cond code and shifts
8816
0abea32c 8817(define_insn "*<arith_shift_insn>_multsi"
8818 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9b23f0a7 8819 (SHIFTABLE_OPS:SI
0abea32c 8820 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
8821 (match_operand:SI 3 "power_of_two_operand" ""))
8822 (match_operand:SI 1 "s_register_operand" "rk,<t2_binop0>")))]
d5d4dc8d 8823 "TARGET_32BIT"
0abea32c 8824 "<arith_shift_insn>%?\\t%0, %1, %2, lsl %b3"
8825 [(set_attr "predicable" "yes")
8826 (set_attr "predicable_short_it" "no")
753d9835 8827 (set_attr "shift" "2")
0abea32c 8828 (set_attr "arch" "a,t2")
8829 (set_attr "type" "alu_shift_imm")])
8830
8831(define_insn "*<arith_shift_insn>_shiftsi"
8832 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9b23f0a7 8833 (SHIFTABLE_OPS:SI
0abea32c 8834 (match_operator:SI 2 "shift_nomul_operator"
8835 [(match_operand:SI 3 "s_register_operand" "r,r,r")
8836 (match_operand:SI 4 "shift_amount_operand" "M,M,r")])
8837 (match_operand:SI 1 "s_register_operand" "rk,<t2_binop0>,rk")))]
a021b821 8838 "TARGET_32BIT && GET_CODE (operands[2]) != MULT"
0abea32c 8839 "<arith_shift_insn>%?\\t%0, %1, %3%S2"
344495ea 8840 [(set_attr "predicable" "yes")
74ef923b 8841 (set_attr "predicable_short_it" "no")
753d9835 8842 (set_attr "shift" "3")
0abea32c 8843 (set_attr "arch" "a,t2,a")
8844 (set_attr "type" "alu_shift_imm,alu_shift_imm,alu_shift_reg")])
9c08d1fa 8845
d7863cfe 8846(define_split
8847 [(set (match_operand:SI 0 "s_register_operand" "")
8848 (match_operator:SI 1 "shiftable_operator"
8849 [(match_operator:SI 2 "shiftable_operator"
8850 [(match_operator:SI 3 "shift_operator"
8851 [(match_operand:SI 4 "s_register_operand" "")
8852 (match_operand:SI 5 "reg_or_int_operand" "")])
8853 (match_operand:SI 6 "s_register_operand" "")])
8854 (match_operand:SI 7 "arm_rhs_operand" "")]))
8855 (clobber (match_operand:SI 8 "s_register_operand" ""))]
d5d4dc8d 8856 "TARGET_32BIT"
d7863cfe 8857 [(set (match_dup 8)
8858 (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8859 (match_dup 6)]))
8860 (set (match_dup 0)
8861 (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
8862 "")
8863
f7fbdd4a 8864(define_insn "*arith_shiftsi_compare0"
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 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 8874 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8875 (match_dup 2)]))]
d5d4dc8d 8876 "TARGET_32BIT"
3ef90e77 8877 "%i1s%?\\t%0, %2, %4%S3"
344495ea 8878 [(set_attr "conds" "set")
331beb1a 8879 (set_attr "shift" "4")
d5d4dc8d 8880 (set_attr "arch" "32,a")
d82e788e 8881 (set_attr "type" "alus_shift_imm,alus_shift_reg")])
9c08d1fa 8882
f7fbdd4a 8883(define_insn "*arith_shiftsi_compare0_scratch"
bd5b4116 8884 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 8885 (compare:CC_NOOV
8886 (match_operator:SI 1 "shiftable_operator"
8887 [(match_operator:SI 3 "shift_operator"
8888 [(match_operand:SI 4 "s_register_operand" "r,r")
8889 (match_operand:SI 5 "shift_amount_operand" "M,r")])
8890 (match_operand:SI 2 "s_register_operand" "r,r")])
8891 (const_int 0)))
8892 (clobber (match_scratch:SI 0 "=r,r"))]
8893 "TARGET_32BIT"
3ef90e77 8894 "%i1s%?\\t%0, %2, %4%S3"
344495ea 8895 [(set_attr "conds" "set")
331beb1a 8896 (set_attr "shift" "4")
d5d4dc8d 8897 (set_attr "arch" "32,a")
d82e788e 8898 (set_attr "type" "alus_shift_imm,alus_shift_reg")])
9c08d1fa 8899
f7fbdd4a 8900(define_insn "*sub_shiftsi"
d5d4dc8d 8901 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8902 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
9c08d1fa 8903 (match_operator:SI 2 "shift_operator"
d5d4dc8d 8904 [(match_operand:SI 3 "s_register_operand" "r,r")
8905 (match_operand:SI 4 "shift_amount_operand" "M,r")])))]
8906 "TARGET_32BIT"
6c4c2133 8907 "sub%?\\t%0, %1, %3%S2"
344495ea 8908 [(set_attr "predicable" "yes")
2df5a382 8909 (set_attr "predicable_short_it" "no")
331beb1a 8910 (set_attr "shift" "3")
d5d4dc8d 8911 (set_attr "arch" "32,a")
d82e788e 8912 (set_attr "type" "alus_shift_imm,alus_shift_reg")])
9c08d1fa 8913
f7fbdd4a 8914(define_insn "*sub_shiftsi_compare0"
bd5b4116 8915 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 8916 (compare:CC_NOOV
d82e788e 8917 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
40dbec34 8918 (match_operator:SI 2 "shift_operator"
d82e788e 8919 [(match_operand:SI 3 "s_register_operand" "r,r,r")
8920 (match_operand:SI 4 "shift_amount_operand" "M,r,M")]))
40dbec34 8921 (const_int 0)))
d82e788e 8922 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
d5d4dc8d 8923 (minus:SI (match_dup 1)
8924 (match_op_dup 2 [(match_dup 3) (match_dup 4)])))]
8925 "TARGET_32BIT"
3ef90e77 8926 "subs%?\\t%0, %1, %3%S2"
344495ea 8927 [(set_attr "conds" "set")
a2cd141b 8928 (set_attr "shift" "3")
d82e788e 8929 (set_attr "arch" "32,a,a")
8930 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
9c08d1fa 8931
f7fbdd4a 8932(define_insn "*sub_shiftsi_compare0_scratch"
bd5b4116 8933 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 8934 (compare:CC_NOOV
d82e788e 8935 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
40dbec34 8936 (match_operator:SI 2 "shift_operator"
d82e788e 8937 [(match_operand:SI 3 "s_register_operand" "r,r,r")
8938 (match_operand:SI 4 "shift_amount_operand" "M,r,M")]))
40dbec34 8939 (const_int 0)))
d82e788e 8940 (clobber (match_scratch:SI 0 "=r,r,r"))]
d5d4dc8d 8941 "TARGET_32BIT"
3ef90e77 8942 "subs%?\\t%0, %1, %3%S2"
344495ea 8943 [(set_attr "conds" "set")
a2cd141b 8944 (set_attr "shift" "3")
d82e788e 8945 (set_attr "arch" "32,a,a")
8946 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
9c08d1fa 8947\f
8948
190efb17 8949(define_insn_and_split "*and_scc"
9c08d1fa 8950 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 8951 (and:SI (match_operator:SI 1 "arm_comparison_operator"
190efb17 8952 [(match_operand 2 "cc_register" "") (const_int 0)])
8953 (match_operand:SI 3 "s_register_operand" "r")))]
cffb2a26 8954 "TARGET_ARM"
190efb17 8955 "#" ; "mov%D1\\t%0, #0\;and%d1\\t%0, %3, #1"
8956 "&& reload_completed"
8957 [(cond_exec (match_dup 5) (set (match_dup 0) (const_int 0)))
8958 (cond_exec (match_dup 4) (set (match_dup 0)
8959 (and:SI (match_dup 3) (const_int 1))))]
8960 {
3754d046 8961 machine_mode mode = GET_MODE (operands[2]);
190efb17 8962 enum rtx_code rc = GET_CODE (operands[1]);
8963
8964 /* Note that operands[4] is the same as operands[1],
8965 but with VOIDmode as the result. */
8966 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
8967 if (mode == CCFPmode || mode == CCFPEmode)
8968 rc = reverse_condition_maybe_unordered (rc);
8969 else
8970 rc = reverse_condition (rc);
8971 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
8972 }
8fa3ba89 8973 [(set_attr "conds" "use")
1b7da4ac 8974 (set_attr "type" "multiple")
8fa3ba89 8975 (set_attr "length" "8")]
8976)
9c08d1fa 8977
190efb17 8978(define_insn_and_split "*ior_scc"
9c08d1fa 8979 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
190efb17 8980 (ior:SI (match_operator:SI 1 "arm_comparison_operator"
8981 [(match_operand 2 "cc_register" "") (const_int 0)])
8982 (match_operand:SI 3 "s_register_operand" "0,?r")))]
cffb2a26 8983 "TARGET_ARM"
e2348bcb 8984 "@
190efb17 8985 orr%d1\\t%0, %3, #1
8986 #"
8987 "&& reload_completed
8988 && REGNO (operands [0]) != REGNO (operands[3])"
8989 ;; && which_alternative == 1
8990 ; mov%D1\\t%0, %3\;orr%d1\\t%0, %3, #1
8991 [(cond_exec (match_dup 5) (set (match_dup 0) (match_dup 3)))
8992 (cond_exec (match_dup 4) (set (match_dup 0)
8993 (ior:SI (match_dup 3) (const_int 1))))]
8994 {
3754d046 8995 machine_mode mode = GET_MODE (operands[2]);
190efb17 8996 enum rtx_code rc = GET_CODE (operands[1]);
8997
8998 /* Note that operands[4] is the same as operands[1],
8999 but with VOIDmode as the result. */
9000 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
9001 if (mode == CCFPmode || mode == CCFPEmode)
9002 rc = reverse_condition_maybe_unordered (rc);
9003 else
9004 rc = reverse_condition (rc);
9005 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
9006 }
8fa3ba89 9007 [(set_attr "conds" "use")
1b7da4ac 9008 (set_attr "length" "4,8")
9009 (set_attr "type" "logic_imm,multiple")]
8fa3ba89 9010)
9c08d1fa 9011
2df9477b 9012; A series of splitters for the compare_scc pattern below. Note that
9013; order is important.
9014(define_split
9015 [(set (match_operand:SI 0 "s_register_operand" "")
9016 (lt:SI (match_operand:SI 1 "s_register_operand" "")
9017 (const_int 0)))
9018 (clobber (reg:CC CC_REGNUM))]
9019 "TARGET_32BIT && reload_completed"
9020 [(set (match_dup 0) (lshiftrt:SI (match_dup 1) (const_int 31)))])
9021
9022(define_split
9023 [(set (match_operand:SI 0 "s_register_operand" "")
9024 (ge:SI (match_operand:SI 1 "s_register_operand" "")
9025 (const_int 0)))
9026 (clobber (reg:CC CC_REGNUM))]
9027 "TARGET_32BIT && reload_completed"
9028 [(set (match_dup 0) (not:SI (match_dup 1)))
9029 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 31)))])
9030
98562479 9031(define_split
9032 [(set (match_operand:SI 0 "s_register_operand" "")
9033 (eq:SI (match_operand:SI 1 "s_register_operand" "")
9034 (const_int 0)))
9035 (clobber (reg:CC CC_REGNUM))]
9036 "arm_arch5 && TARGET_32BIT"
9037 [(set (match_dup 0) (clz:SI (match_dup 1)))
9038 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 5)))]
9039)
9040
2df9477b 9041(define_split
9042 [(set (match_operand:SI 0 "s_register_operand" "")
9043 (eq:SI (match_operand:SI 1 "s_register_operand" "")
9044 (const_int 0)))
9045 (clobber (reg:CC CC_REGNUM))]
9046 "TARGET_32BIT && reload_completed"
9047 [(parallel
080c0b9a 9048 [(set (reg:CC CC_REGNUM)
9049 (compare:CC (const_int 1) (match_dup 1)))
2df9477b 9050 (set (match_dup 0)
9051 (minus:SI (const_int 1) (match_dup 1)))])
080c0b9a 9052 (cond_exec (ltu:CC (reg:CC CC_REGNUM) (const_int 0))
2df9477b 9053 (set (match_dup 0) (const_int 0)))])
9054
9055(define_split
9056 [(set (match_operand:SI 0 "s_register_operand" "")
9057 (ne:SI (match_operand:SI 1 "s_register_operand" "")
9058 (match_operand:SI 2 "const_int_operand" "")))
9059 (clobber (reg:CC CC_REGNUM))]
9060 "TARGET_32BIT && reload_completed"
9061 [(parallel
9062 [(set (reg:CC CC_REGNUM)
9063 (compare:CC (match_dup 1) (match_dup 2)))
9064 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))])
9065 (cond_exec (ne:CC (reg:CC CC_REGNUM) (const_int 0))
9066 (set (match_dup 0) (const_int 1)))]
9067{
9068 operands[3] = GEN_INT (-INTVAL (operands[2]));
9069})
9070
9071(define_split
9072 [(set (match_operand:SI 0 "s_register_operand" "")
9073 (ne:SI (match_operand:SI 1 "s_register_operand" "")
9074 (match_operand:SI 2 "arm_add_operand" "")))
9075 (clobber (reg:CC CC_REGNUM))]
9076 "TARGET_32BIT && reload_completed"
9077 [(parallel
9078 [(set (reg:CC_NOOV CC_REGNUM)
9079 (compare:CC_NOOV (minus:SI (match_dup 1) (match_dup 2))
9080 (const_int 0)))
9081 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
9082 (cond_exec (ne:CC_NOOV (reg:CC_NOOV CC_REGNUM) (const_int 0))
9083 (set (match_dup 0) (const_int 1)))])
9084
9085(define_insn_and_split "*compare_scc"
fd711051 9086 [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts")
8fa3ba89 9087 (match_operator:SI 1 "arm_comparison_operator"
5565501b 9088 [(match_operand:SI 2 "s_register_operand" "r,r")
9089 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
bd5b4116 9090 (clobber (reg:CC CC_REGNUM))]
2df9477b 9091 "TARGET_32BIT"
9092 "#"
9093 "&& reload_completed"
9094 [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 3)))
9095 (cond_exec (match_dup 4) (set (match_dup 0) (const_int 0)))
9096 (cond_exec (match_dup 5) (set (match_dup 0) (const_int 1)))]
9097{
9098 rtx tmp1;
3754d046 9099 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
2df9477b 9100 operands[2], operands[3]);
9101 enum rtx_code rc = GET_CODE (operands[1]);
e2348bcb 9102
2df9477b 9103 tmp1 = gen_rtx_REG (mode, CC_REGNUM);
080c0b9a 9104
2df9477b 9105 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
9106 if (mode == CCFPmode || mode == CCFPEmode)
9107 rc = reverse_condition_maybe_unordered (rc);
9108 else
9109 rc = reverse_condition (rc);
9110 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
1b7da4ac 9111}
9112 [(set_attr "type" "multiple")]
9113)
9c08d1fa 9114
080c0b9a 9115;; Attempt to improve the sequence generated by the compare_scc splitters
9116;; not to use conditional execution.
98562479 9117
9118;; Rd = (eq (reg1) (const_int0)) // ARMv5
9119;; clz Rd, reg1
9120;; lsr Rd, Rd, #5
080c0b9a 9121(define_peephole2
9122 [(set (reg:CC CC_REGNUM)
9123 (compare:CC (match_operand:SI 1 "register_operand" "")
98562479 9124 (const_int 0)))
9125 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
9126 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
9127 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
9128 (set (match_dup 0) (const_int 1)))]
9129 "arm_arch5 && TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)"
9130 [(set (match_dup 0) (clz:SI (match_dup 1)))
9131 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 5)))]
9132)
9133
9134;; Rd = (eq (reg1) (const_int0)) // !ARMv5
9135;; negs Rd, reg1
9136;; adc Rd, Rd, reg1
9137(define_peephole2
9138 [(set (reg:CC CC_REGNUM)
9139 (compare:CC (match_operand:SI 1 "register_operand" "")
9140 (const_int 0)))
080c0b9a 9141 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
9142 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
9143 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
9144 (set (match_dup 0) (const_int 1)))
98562479 9145 (match_scratch:SI 2 "r")]
9146 "TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)"
922b6913 9147 [(parallel
9148 [(set (reg:CC CC_REGNUM)
98562479 9149 (compare:CC (const_int 0) (match_dup 1)))
9150 (set (match_dup 2) (minus:SI (const_int 0) (match_dup 1)))])
9151 (set (match_dup 0)
9152 (plus:SI (plus:SI (match_dup 1) (match_dup 2))
9153 (geu:SI (reg:CC CC_REGNUM) (const_int 0))))]
9154)
9155
31991287 9156;; Rd = (eq (reg1) (reg2/imm)) // ARMv5 and optimising for speed.
98562479 9157;; sub Rd, Reg1, reg2
9158;; clz Rd, Rd
9159;; lsr Rd, Rd, #5
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)))]
31991287 9168 "arm_arch5 && TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)
9169 && !(TARGET_THUMB2 && optimize_insn_for_size_p ())"
98562479 9170 [(set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))
9171 (set (match_dup 0) (clz:SI (match_dup 0)))
9172 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 5)))]
9173)
9174
9175
31991287 9176;; Rd = (eq (reg1) (reg2)) // ! ARMv5 or optimising for size.
98562479 9177;; sub T1, Reg1, reg2
9178;; negs Rd, T1
9179;; adc Rd, Rd, T1
9180(define_peephole2
9181 [(set (reg:CC CC_REGNUM)
9182 (compare:CC (match_operand:SI 1 "register_operand" "")
9183 (match_operand:SI 2 "arm_rhs_operand" "")))
9184 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
9185 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
9186 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
9187 (set (match_dup 0) (const_int 1)))
9188 (match_scratch:SI 3 "r")]
9189 "TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)"
31991287 9190 [(set (match_dup 3) (match_dup 4))
080c0b9a 9191 (parallel
9192 [(set (reg:CC CC_REGNUM)
9193 (compare:CC (const_int 0) (match_dup 3)))
9194 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 3)))])
98562479 9195 (set (match_dup 0)
9196 (plus:SI (plus:SI (match_dup 0) (match_dup 3))
9197 (geu:SI (reg:CC CC_REGNUM) (const_int 0))))]
31991287 9198 "
9199 if (CONST_INT_P (operands[2]))
9200 operands[4] = plus_constant (SImode, operands[1], -INTVAL (operands[2]));
9201 else
9202 operands[4] = gen_rtx_MINUS (SImode, operands[1], operands[2]);
9203 ")
080c0b9a 9204
f7fbdd4a 9205(define_insn "*cond_move"
9c08d1fa 9206 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
aea4c774 9207 (if_then_else:SI (match_operator 3 "equality_operator"
8fa3ba89 9208 [(match_operator 4 "arm_comparison_operator"
8a18b90c 9209 [(match_operand 5 "cc_register" "") (const_int 0)])
aea4c774 9210 (const_int 0)])
9211 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9212 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
cffb2a26 9213 "TARGET_ARM"
9c08d1fa 9214 "*
8fa3ba89 9215 if (GET_CODE (operands[3]) == NE)
9216 {
9217 if (which_alternative != 1)
9218 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
9219 if (which_alternative != 0)
9220 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
9221 return \"\";
9222 }
9223 if (which_alternative != 0)
9224 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9225 if (which_alternative != 1)
9226 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
9227 return \"\";
9228 "
9229 [(set_attr "conds" "use")
282b4c75 9230 (set_attr_alternative "type"
9231 [(if_then_else (match_operand 2 "const_int_operand" "")
9232 (const_string "mov_imm")
9233 (const_string "mov_reg"))
9234 (if_then_else (match_operand 1 "const_int_operand" "")
9235 (const_string "mov_imm")
9236 (const_string "mov_reg"))
9237 (const_string "multiple")])
8fa3ba89 9238 (set_attr "length" "4,4,8")]
9239)
9c08d1fa 9240
f7fbdd4a 9241(define_insn "*cond_arith"
9c08d1fa 9242 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9243 (match_operator:SI 5 "shiftable_operator"
8fa3ba89 9244 [(match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 9245 [(match_operand:SI 2 "s_register_operand" "r,r")
9246 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
9247 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 9248 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9249 "TARGET_ARM"
9c08d1fa 9250 "*
8fa3ba89 9251 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
9252 return \"%i5\\t%0, %1, %2, lsr #31\";
40dbec34 9253
8fa3ba89 9254 output_asm_insn (\"cmp\\t%2, %3\", operands);
9255 if (GET_CODE (operands[5]) == AND)
9256 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
9257 else if (GET_CODE (operands[5]) == MINUS)
9258 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
9259 else if (which_alternative != 0)
9260 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9261 return \"%i5%d4\\t%0, %1, #1\";
9262 "
9263 [(set_attr "conds" "clob")
1b7da4ac 9264 (set_attr "length" "12")
9265 (set_attr "type" "multiple")]
8fa3ba89 9266)
9c08d1fa 9267
f7fbdd4a 9268(define_insn "*cond_sub"
9c08d1fa 9269 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9270 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8fa3ba89 9271 (match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 9272 [(match_operand:SI 2 "s_register_operand" "r,r")
9273 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 9274 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9275 "TARGET_ARM"
9c08d1fa 9276 "*
8fa3ba89 9277 output_asm_insn (\"cmp\\t%2, %3\", operands);
9278 if (which_alternative != 0)
9279 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9280 return \"sub%d4\\t%0, %1, #1\";
9281 "
9282 [(set_attr "conds" "clob")
1b7da4ac 9283 (set_attr "length" "8,12")
9284 (set_attr "type" "multiple")]
8fa3ba89 9285)
9c08d1fa 9286
aea4c774 9287(define_insn "*cmp_ite0"
cffb2a26 9288 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 9289 (compare
9290 (if_then_else:SI
8fa3ba89 9291 (match_operator 4 "arm_comparison_operator"
2ff91fec 9292 [(match_operand:SI 0 "s_register_operand"
9293 "l,l,l,r,r,r,r,r,r")
9294 (match_operand:SI 1 "arm_add_operand"
9295 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
8fa3ba89 9296 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 9297 [(match_operand:SI 2 "s_register_operand"
9298 "l,r,r,l,l,r,r,r,r")
9299 (match_operand:SI 3 "arm_add_operand"
9300 "lPy,rI,L,lPy,lPy,rI,rI,L,L")])
aea4c774 9301 (const_int 0))
9302 (const_int 0)))]
2ff91fec 9303 "TARGET_32BIT"
9c08d1fa 9304 "*
aea4c774 9305 {
2ff91fec 9306 static const char * const cmp1[NUM_OF_COND_CMP][2] =
9307 {
9308 {\"cmp%d5\\t%0, %1\",
9309 \"cmp%d4\\t%2, %3\"},
9310 {\"cmn%d5\\t%0, #%n1\",
9311 \"cmp%d4\\t%2, %3\"},
9312 {\"cmp%d5\\t%0, %1\",
9313 \"cmn%d4\\t%2, #%n3\"},
9314 {\"cmn%d5\\t%0, #%n1\",
9315 \"cmn%d4\\t%2, #%n3\"}
9316 };
9317 static const char * const cmp2[NUM_OF_COND_CMP][2] =
9318 {
9319 {\"cmp\\t%2, %3\",
9320 \"cmp\\t%0, %1\"},
9321 {\"cmp\\t%2, %3\",
9322 \"cmn\\t%0, #%n1\"},
9323 {\"cmn\\t%2, #%n3\",
9324 \"cmp\\t%0, %1\"},
9325 {\"cmn\\t%2, #%n3\",
9326 \"cmn\\t%0, #%n1\"}
9327 };
9328 static const char * const ite[2] =
8fa3ba89 9329 {
2ff91fec 9330 \"it\\t%d5\",
9331 \"it\\t%d4\"
8fa3ba89 9332 };
2ff91fec 9333 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
9334 CMP_CMP, CMN_CMP, CMP_CMP,
9335 CMN_CMP, CMP_CMN, CMN_CMN};
8fa3ba89 9336 int swap =
9337 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9338
2ff91fec 9339 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9340 if (TARGET_THUMB2) {
9341 output_asm_insn (ite[swap], operands);
9342 }
9343 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9344 return \"\";
8fa3ba89 9345 }"
9346 [(set_attr "conds" "set")
2ff91fec 9347 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
2df5a382 9348 (set_attr "enabled_for_depr_it" "yes,no,no,no,no,no,no,no,no")
1b7da4ac 9349 (set_attr "type" "multiple")
2ff91fec 9350 (set_attr_alternative "length"
9351 [(const_int 6)
9352 (const_int 8)
9353 (const_int 8)
9354 (const_int 8)
9355 (const_int 8)
9356 (if_then_else (eq_attr "is_thumb" "no")
9357 (const_int 8)
9358 (const_int 10))
9359 (if_then_else (eq_attr "is_thumb" "no")
9360 (const_int 8)
9361 (const_int 10))
9362 (if_then_else (eq_attr "is_thumb" "no")
9363 (const_int 8)
9364 (const_int 10))
9365 (if_then_else (eq_attr "is_thumb" "no")
9366 (const_int 8)
9367 (const_int 10))])]
8fa3ba89 9368)
9c08d1fa 9369
aea4c774 9370(define_insn "*cmp_ite1"
cffb2a26 9371 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 9372 (compare
9373 (if_then_else:SI
8fa3ba89 9374 (match_operator 4 "arm_comparison_operator"
2ff91fec 9375 [(match_operand:SI 0 "s_register_operand"
9376 "l,l,l,r,r,r,r,r,r")
9377 (match_operand:SI 1 "arm_add_operand"
9378 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
8fa3ba89 9379 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 9380 [(match_operand:SI 2 "s_register_operand"
9381 "l,r,r,l,l,r,r,r,r")
9382 (match_operand:SI 3 "arm_add_operand"
9383 "lPy,rI,L,lPy,lPy,rI,rI,L,L")])
aea4c774 9384 (const_int 1))
9385 (const_int 0)))]
2ff91fec 9386 "TARGET_32BIT"
9c08d1fa 9387 "*
9c08d1fa 9388 {
2ff91fec 9389 static const char * const cmp1[NUM_OF_COND_CMP][2] =
9390 {
9391 {\"cmp\\t%0, %1\",
9392 \"cmp\\t%2, %3\"},
9393 {\"cmn\\t%0, #%n1\",
9394 \"cmp\\t%2, %3\"},
9395 {\"cmp\\t%0, %1\",
9396 \"cmn\\t%2, #%n3\"},
9397 {\"cmn\\t%0, #%n1\",
9398 \"cmn\\t%2, #%n3\"}
9399 };
9400 static const char * const cmp2[NUM_OF_COND_CMP][2] =
215b30b3 9401 {
2ff91fec 9402 {\"cmp%d4\\t%2, %3\",
9403 \"cmp%D5\\t%0, %1\"},
9404 {\"cmp%d4\\t%2, %3\",
9405 \"cmn%D5\\t%0, #%n1\"},
9406 {\"cmn%d4\\t%2, #%n3\",
9407 \"cmp%D5\\t%0, %1\"},
9408 {\"cmn%d4\\t%2, #%n3\",
9409 \"cmn%D5\\t%0, #%n1\"}
215b30b3 9410 };
2ff91fec 9411 static const char * const ite[2] =
9412 {
9413 \"it\\t%d4\",
9414 \"it\\t%D5\"
9415 };
9416 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
9417 CMP_CMP, CMN_CMP, CMP_CMP,
9418 CMN_CMP, CMP_CMN, CMN_CMN};
215b30b3 9419 int swap =
9420 comparison_dominates_p (GET_CODE (operands[5]),
9421 reverse_condition (GET_CODE (operands[4])));
9422
2ff91fec 9423 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9424 if (TARGET_THUMB2) {
9425 output_asm_insn (ite[swap], operands);
9426 }
9427 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9428 return \"\";
215b30b3 9429 }"
8fa3ba89 9430 [(set_attr "conds" "set")
2ff91fec 9431 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
2df5a382 9432 (set_attr "enabled_for_depr_it" "yes,no,no,no,no,no,no,no,no")
2ff91fec 9433 (set_attr_alternative "length"
9434 [(const_int 6)
9435 (const_int 8)
9436 (const_int 8)
9437 (const_int 8)
9438 (const_int 8)
9439 (if_then_else (eq_attr "is_thumb" "no")
9440 (const_int 8)
9441 (const_int 10))
9442 (if_then_else (eq_attr "is_thumb" "no")
9443 (const_int 8)
9444 (const_int 10))
9445 (if_then_else (eq_attr "is_thumb" "no")
9446 (const_int 8)
9447 (const_int 10))
9448 (if_then_else (eq_attr "is_thumb" "no")
9449 (const_int 8)
1b7da4ac 9450 (const_int 10))])
9451 (set_attr "type" "multiple")]
8fa3ba89 9452)
9c08d1fa 9453
f6c53574 9454(define_insn "*cmp_and"
9455 [(set (match_operand 6 "dominant_cc_register" "")
9456 (compare
9457 (and:SI
9458 (match_operator 4 "arm_comparison_operator"
2ff91fec 9459 [(match_operand:SI 0 "s_register_operand"
9460 "l,l,l,r,r,r,r,r,r")
9461 (match_operand:SI 1 "arm_add_operand"
9462 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
f6c53574 9463 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 9464 [(match_operand:SI 2 "s_register_operand"
9465 "l,r,r,l,l,r,r,r,r")
9466 (match_operand:SI 3 "arm_add_operand"
9467 "lPy,rI,L,lPy,lPy,rI,rI,L,L")]))
f6c53574 9468 (const_int 0)))]
2ff91fec 9469 "TARGET_32BIT"
f6c53574 9470 "*
9471 {
2ff91fec 9472 static const char *const cmp1[NUM_OF_COND_CMP][2] =
f6c53574 9473 {
2ff91fec 9474 {\"cmp%d5\\t%0, %1\",
9475 \"cmp%d4\\t%2, %3\"},
9476 {\"cmn%d5\\t%0, #%n1\",
9477 \"cmp%d4\\t%2, %3\"},
9478 {\"cmp%d5\\t%0, %1\",
9479 \"cmn%d4\\t%2, #%n3\"},
9480 {\"cmn%d5\\t%0, #%n1\",
9481 \"cmn%d4\\t%2, #%n3\"}
f6c53574 9482 };
2ff91fec 9483 static const char *const cmp2[NUM_OF_COND_CMP][2] =
9484 {
9485 {\"cmp\\t%2, %3\",
9486 \"cmp\\t%0, %1\"},
9487 {\"cmp\\t%2, %3\",
9488 \"cmn\\t%0, #%n1\"},
9489 {\"cmn\\t%2, #%n3\",
9490 \"cmp\\t%0, %1\"},
9491 {\"cmn\\t%2, #%n3\",
9492 \"cmn\\t%0, #%n1\"}
9493 };
9494 static const char *const ite[2] =
9495 {
9496 \"it\\t%d5\",
9497 \"it\\t%d4\"
9498 };
9499 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
9500 CMP_CMP, CMN_CMP, CMP_CMP,
9501 CMN_CMP, CMP_CMN, CMN_CMN};
f6c53574 9502 int swap =
9503 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9504
2ff91fec 9505 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9506 if (TARGET_THUMB2) {
9507 output_asm_insn (ite[swap], operands);
9508 }
9509 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9510 return \"\";
f6c53574 9511 }"
9512 [(set_attr "conds" "set")
9513 (set_attr "predicable" "no")
2ff91fec 9514 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
f9d240a0 9515 (set_attr "enabled_for_depr_it" "yes,no,no,no,no,no,no,no,no")
2ff91fec 9516 (set_attr_alternative "length"
9517 [(const_int 6)
9518 (const_int 8)
9519 (const_int 8)
9520 (const_int 8)
9521 (const_int 8)
9522 (if_then_else (eq_attr "is_thumb" "no")
9523 (const_int 8)
9524 (const_int 10))
9525 (if_then_else (eq_attr "is_thumb" "no")
9526 (const_int 8)
9527 (const_int 10))
9528 (if_then_else (eq_attr "is_thumb" "no")
9529 (const_int 8)
9530 (const_int 10))
9531 (if_then_else (eq_attr "is_thumb" "no")
9532 (const_int 8)
1b7da4ac 9533 (const_int 10))])
9534 (set_attr "type" "multiple")]
f6c53574 9535)
9536
9537(define_insn "*cmp_ior"
9538 [(set (match_operand 6 "dominant_cc_register" "")
9539 (compare
9540 (ior:SI
9541 (match_operator 4 "arm_comparison_operator"
2ff91fec 9542 [(match_operand:SI 0 "s_register_operand"
9543 "l,l,l,r,r,r,r,r,r")
9544 (match_operand:SI 1 "arm_add_operand"
9545 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
f6c53574 9546 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 9547 [(match_operand:SI 2 "s_register_operand"
9548 "l,r,r,l,l,r,r,r,r")
9549 (match_operand:SI 3 "arm_add_operand"
9550 "lPy,rI,L,lPy,lPy,rI,rI,L,L")]))
f6c53574 9551 (const_int 0)))]
2ff91fec 9552 "TARGET_32BIT"
f6c53574 9553 "*
f6c53574 9554 {
2ff91fec 9555 static const char *const cmp1[NUM_OF_COND_CMP][2] =
9556 {
9557 {\"cmp\\t%0, %1\",
9558 \"cmp\\t%2, %3\"},
9559 {\"cmn\\t%0, #%n1\",
9560 \"cmp\\t%2, %3\"},
9561 {\"cmp\\t%0, %1\",
9562 \"cmn\\t%2, #%n3\"},
9563 {\"cmn\\t%0, #%n1\",
9564 \"cmn\\t%2, #%n3\"}
9565 };
9566 static const char *const cmp2[NUM_OF_COND_CMP][2] =
9567 {
9568 {\"cmp%D4\\t%2, %3\",
9569 \"cmp%D5\\t%0, %1\"},
9570 {\"cmp%D4\\t%2, %3\",
9571 \"cmn%D5\\t%0, #%n1\"},
9572 {\"cmn%D4\\t%2, #%n3\",
9573 \"cmp%D5\\t%0, %1\"},
9574 {\"cmn%D4\\t%2, #%n3\",
9575 \"cmn%D5\\t%0, #%n1\"}
9576 };
9577 static const char *const ite[2] =
9578 {
9579 \"it\\t%D4\",
9580 \"it\\t%D5\"
9581 };
9582 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
9583 CMP_CMP, CMN_CMP, CMP_CMP,
9584 CMN_CMP, CMP_CMN, CMN_CMN};
9585 int swap =
9586 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9587
9588 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9589 if (TARGET_THUMB2) {
9590 output_asm_insn (ite[swap], operands);
9591 }
9592 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9593 return \"\";
9594 }
9595 "
f6c53574 9596 [(set_attr "conds" "set")
2ff91fec 9597 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
f9d240a0 9598 (set_attr "enabled_for_depr_it" "yes,no,no,no,no,no,no,no,no")
2ff91fec 9599 (set_attr_alternative "length"
9600 [(const_int 6)
9601 (const_int 8)
9602 (const_int 8)
9603 (const_int 8)
9604 (const_int 8)
9605 (if_then_else (eq_attr "is_thumb" "no")
9606 (const_int 8)
9607 (const_int 10))
9608 (if_then_else (eq_attr "is_thumb" "no")
9609 (const_int 8)
9610 (const_int 10))
9611 (if_then_else (eq_attr "is_thumb" "no")
9612 (const_int 8)
9613 (const_int 10))
9614 (if_then_else (eq_attr "is_thumb" "no")
9615 (const_int 8)
1b7da4ac 9616 (const_int 10))])
9617 (set_attr "type" "multiple")]
f6c53574 9618)
9619
3c5afce6 9620(define_insn_and_split "*ior_scc_scc"
f9d240a0 9621 [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts")
3c5afce6 9622 (ior:SI (match_operator:SI 3 "arm_comparison_operator"
f9d240a0 9623 [(match_operand:SI 1 "s_register_operand" "l,r")
9624 (match_operand:SI 2 "arm_add_operand" "lPy,rIL")])
3c5afce6 9625 (match_operator:SI 6 "arm_comparison_operator"
f9d240a0 9626 [(match_operand:SI 4 "s_register_operand" "l,r")
9627 (match_operand:SI 5 "arm_add_operand" "lPy,rIL")])))
3c5afce6 9628 (clobber (reg:CC CC_REGNUM))]
2ff91fec 9629 "TARGET_32BIT
3c5afce6 9630 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
9631 != CCmode)"
9632 "#"
2ff91fec 9633 "TARGET_32BIT && reload_completed"
3c5afce6 9634 [(set (match_dup 7)
9635 (compare
9636 (ior:SI
9637 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9638 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9639 (const_int 0)))
9640 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9641 "operands[7]
9642 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9643 DOM_CC_X_OR_Y),
601f584c 9644 CC_REGNUM);"
9645 [(set_attr "conds" "clob")
f9d240a0 9646 (set_attr "enabled_for_depr_it" "yes,no")
1b7da4ac 9647 (set_attr "length" "16")
9648 (set_attr "type" "multiple")]
9649)
601f584c 9650
9651; If the above pattern is followed by a CMP insn, then the compare is
9652; redundant, since we can rework the conditional instruction that follows.
9653(define_insn_and_split "*ior_scc_scc_cmp"
9654 [(set (match_operand 0 "dominant_cc_register" "")
9655 (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
f9d240a0 9656 [(match_operand:SI 1 "s_register_operand" "l,r")
9657 (match_operand:SI 2 "arm_add_operand" "lPy,rIL")])
601f584c 9658 (match_operator:SI 6 "arm_comparison_operator"
f9d240a0 9659 [(match_operand:SI 4 "s_register_operand" "l,r")
9660 (match_operand:SI 5 "arm_add_operand" "lPy,rIL")]))
601f584c 9661 (const_int 0)))
f9d240a0 9662 (set (match_operand:SI 7 "s_register_operand" "=Ts,Ts")
601f584c 9663 (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9664 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
2ff91fec 9665 "TARGET_32BIT"
601f584c 9666 "#"
2ff91fec 9667 "TARGET_32BIT && reload_completed"
601f584c 9668 [(set (match_dup 0)
9669 (compare
9670 (ior:SI
9671 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9672 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9673 (const_int 0)))
9674 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9675 ""
9676 [(set_attr "conds" "set")
f9d240a0 9677 (set_attr "enabled_for_depr_it" "yes,no")
1b7da4ac 9678 (set_attr "length" "16")
9679 (set_attr "type" "multiple")]
9680)
3c5afce6 9681
9682(define_insn_and_split "*and_scc_scc"
f9d240a0 9683 [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts")
3c5afce6 9684 (and:SI (match_operator:SI 3 "arm_comparison_operator"
f9d240a0 9685 [(match_operand:SI 1 "s_register_operand" "l,r")
9686 (match_operand:SI 2 "arm_add_operand" "lPy,rIL")])
3c5afce6 9687 (match_operator:SI 6 "arm_comparison_operator"
f9d240a0 9688 [(match_operand:SI 4 "s_register_operand" "l,r")
9689 (match_operand:SI 5 "arm_add_operand" "lPy,rIL")])))
3c5afce6 9690 (clobber (reg:CC CC_REGNUM))]
2ff91fec 9691 "TARGET_32BIT
3c5afce6 9692 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9693 != CCmode)"
9694 "#"
2ff91fec 9695 "TARGET_32BIT && reload_completed
601f584c 9696 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9697 != CCmode)"
3c5afce6 9698 [(set (match_dup 7)
9699 (compare
9700 (and:SI
9701 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9702 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9703 (const_int 0)))
9704 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9705 "operands[7]
9706 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9707 DOM_CC_X_AND_Y),
601f584c 9708 CC_REGNUM);"
9709 [(set_attr "conds" "clob")
f9d240a0 9710 (set_attr "enabled_for_depr_it" "yes,no")
1b7da4ac 9711 (set_attr "length" "16")
9712 (set_attr "type" "multiple")]
9713)
601f584c 9714
9715; If the above pattern is followed by a CMP insn, then the compare is
9716; redundant, since we can rework the conditional instruction that follows.
9717(define_insn_and_split "*and_scc_scc_cmp"
9718 [(set (match_operand 0 "dominant_cc_register" "")
9719 (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
f9d240a0 9720 [(match_operand:SI 1 "s_register_operand" "l,r")
9721 (match_operand:SI 2 "arm_add_operand" "lPy,rIL")])
601f584c 9722 (match_operator:SI 6 "arm_comparison_operator"
f9d240a0 9723 [(match_operand:SI 4 "s_register_operand" "l,r")
9724 (match_operand:SI 5 "arm_add_operand" "lPy,rIL")]))
601f584c 9725 (const_int 0)))
f9d240a0 9726 (set (match_operand:SI 7 "s_register_operand" "=Ts,Ts")
601f584c 9727 (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9728 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
2ff91fec 9729 "TARGET_32BIT"
601f584c 9730 "#"
2ff91fec 9731 "TARGET_32BIT && reload_completed"
601f584c 9732 [(set (match_dup 0)
9733 (compare
9734 (and:SI
9735 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9736 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9737 (const_int 0)))
9738 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9739 ""
9740 [(set_attr "conds" "set")
f9d240a0 9741 (set_attr "enabled_for_depr_it" "yes,no")
1b7da4ac 9742 (set_attr "length" "16")
9743 (set_attr "type" "multiple")]
9744)
601f584c 9745
9746;; If there is no dominance in the comparison, then we can still save an
9747;; instruction in the AND case, since we can know that the second compare
9748;; need only zero the value if false (if true, then the value is already
9749;; correct).
9750(define_insn_and_split "*and_scc_scc_nodom"
fd711051 9751 [(set (match_operand:SI 0 "s_register_operand" "=&Ts,&Ts,&Ts")
601f584c 9752 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9753 [(match_operand:SI 1 "s_register_operand" "r,r,0")
9754 (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
9755 (match_operator:SI 6 "arm_comparison_operator"
9756 [(match_operand:SI 4 "s_register_operand" "r,r,r")
9757 (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
9758 (clobber (reg:CC CC_REGNUM))]
2ff91fec 9759 "TARGET_32BIT
601f584c 9760 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9761 == CCmode)"
9762 "#"
2ff91fec 9763 "TARGET_32BIT && reload_completed"
601f584c 9764 [(parallel [(set (match_dup 0)
9765 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
9766 (clobber (reg:CC CC_REGNUM))])
9767 (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
9768 (set (match_dup 0)
9769 (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
9770 (match_dup 0)
9771 (const_int 0)))]
9772 "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
9773 operands[4], operands[5]),
9774 CC_REGNUM);
9775 operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
9776 operands[5]);"
9777 [(set_attr "conds" "clob")
1b7da4ac 9778 (set_attr "length" "20")
9779 (set_attr "type" "multiple")]
9780)
3c5afce6 9781
3a0bdee0 9782(define_split
9783 [(set (reg:CC_NOOV CC_REGNUM)
9784 (compare:CC_NOOV (ior:SI
9785 (and:SI (match_operand:SI 0 "s_register_operand" "")
9786 (const_int 1))
b0694be0 9787 (match_operator:SI 1 "arm_comparison_operator"
3a0bdee0 9788 [(match_operand:SI 2 "s_register_operand" "")
9789 (match_operand:SI 3 "arm_add_operand" "")]))
9790 (const_int 0)))
9791 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9792 "TARGET_ARM"
9793 [(set (match_dup 4)
9794 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9795 (match_dup 0)))
9796 (set (reg:CC_NOOV CC_REGNUM)
9797 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9798 (const_int 0)))]
9799 "")
9800
9801(define_split
9802 [(set (reg:CC_NOOV CC_REGNUM)
9803 (compare:CC_NOOV (ior:SI
b0694be0 9804 (match_operator:SI 1 "arm_comparison_operator"
3a0bdee0 9805 [(match_operand:SI 2 "s_register_operand" "")
9806 (match_operand:SI 3 "arm_add_operand" "")])
9807 (and:SI (match_operand:SI 0 "s_register_operand" "")
9808 (const_int 1)))
9809 (const_int 0)))
9810 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9811 "TARGET_ARM"
9812 [(set (match_dup 4)
9813 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9814 (match_dup 0)))
9815 (set (reg:CC_NOOV CC_REGNUM)
9816 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9817 (const_int 0)))]
9818 "")
25f905c2 9819;; ??? The conditional patterns above need checking for Thumb-2 usefulness
3a0bdee0 9820
190efb17 9821(define_insn_and_split "*negscc"
9c08d1fa 9822 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9823 (neg:SI (match_operator 3 "arm_comparison_operator"
9c08d1fa 9824 [(match_operand:SI 1 "s_register_operand" "r")
9825 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
bd5b4116 9826 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9827 "TARGET_ARM"
190efb17 9828 "#"
9829 "&& reload_completed"
9830 [(const_int 0)]
9831 {
9832 rtx cc_reg = gen_rtx_REG (CCmode, CC_REGNUM);
e2348bcb 9833
190efb17 9834 if (GET_CODE (operands[3]) == LT && operands[2] == const0_rtx)
9835 {
9836 /* Emit mov\\t%0, %1, asr #31 */
d1f9b275 9837 emit_insn (gen_rtx_SET (operands[0],
190efb17 9838 gen_rtx_ASHIFTRT (SImode,
9839 operands[1],
9840 GEN_INT (31))));
9841 DONE;
9842 }
9843 else if (GET_CODE (operands[3]) == NE)
9844 {
9845 /* Emit subs\\t%0, %1, %2\;mvnne\\t%0, #0 */
9846 if (CONST_INT_P (operands[2]))
9847 emit_insn (gen_cmpsi2_addneg (operands[0], operands[1], operands[2],
9848 GEN_INT (- INTVAL (operands[2]))));
9849 else
9850 emit_insn (gen_subsi3_compare (operands[0], operands[1], operands[2]));
9851
9852 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
9853 gen_rtx_NE (SImode,
9854 cc_reg,
9855 const0_rtx),
d1f9b275 9856 gen_rtx_SET (operands[0],
190efb17 9857 GEN_INT (~0))));
9858 DONE;
9859 }
9860 else
9861 {
9862 /* Emit: cmp\\t%1, %2\;mov%D3\\t%0, #0\;mvn%d3\\t%0, #0 */
d1f9b275 9863 emit_insn (gen_rtx_SET (cc_reg,
190efb17 9864 gen_rtx_COMPARE (CCmode, operands[1], operands[2])));
9865 enum rtx_code rc = GET_CODE (operands[3]);
9866
9867 rc = reverse_condition (rc);
9868 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
9869 gen_rtx_fmt_ee (rc,
9870 VOIDmode,
9871 cc_reg,
9872 const0_rtx),
d1f9b275 9873 gen_rtx_SET (operands[0], const0_rtx)));
190efb17 9874 rc = GET_CODE (operands[3]);
9875 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
9876 gen_rtx_fmt_ee (rc,
9877 VOIDmode,
9878 cc_reg,
9879 const0_rtx),
d1f9b275 9880 gen_rtx_SET (operands[0],
190efb17 9881 GEN_INT (~0))));
9882 DONE;
9883 }
9884 FAIL;
9885 }
8fa3ba89 9886 [(set_attr "conds" "clob")
1b7da4ac 9887 (set_attr "length" "12")
9888 (set_attr "type" "multiple")]
8fa3ba89 9889)
9c08d1fa 9890
90404b57 9891(define_insn_and_split "movcond_addsi"
9892 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r")
9893 (if_then_else:SI
9894 (match_operator 5 "comparison_operator"
9895 [(plus:SI (match_operand:SI 3 "s_register_operand" "r,r,r")
9896 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL"))
9897 (const_int 0)])
9898 (match_operand:SI 1 "arm_rhs_operand" "rI,rPy,r")
9899 (match_operand:SI 2 "arm_rhs_operand" "rI,rPy,r")))
9900 (clobber (reg:CC CC_REGNUM))]
9901 "TARGET_32BIT"
9902 "#"
9903 "&& reload_completed"
9904 [(set (reg:CC_NOOV CC_REGNUM)
9905 (compare:CC_NOOV
9906 (plus:SI (match_dup 3)
9907 (match_dup 4))
9908 (const_int 0)))
9909 (set (match_dup 0) (match_dup 1))
9910 (cond_exec (match_dup 6)
9911 (set (match_dup 0) (match_dup 2)))]
9912 "
9913 {
3754d046 9914 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[5]),
90404b57 9915 operands[3], operands[4]);
9916 enum rtx_code rc = GET_CODE (operands[5]);
90404b57 9917 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9918 gcc_assert (!(mode == CCFPmode || mode == CCFPEmode));
22440aeb 9919 if (!REG_P (operands[2]) || REGNO (operands[2]) != REGNO (operands[0]))
4d01ce2f 9920 rc = reverse_condition (rc);
f145bcba 9921 else
9922 std::swap (operands[1], operands[2]);
90404b57 9923
9924 operands[6] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9925 }
9926 "
9927 [(set_attr "conds" "clob")
1b7da4ac 9928 (set_attr "enabled_for_depr_it" "no,yes,yes")
9929 (set_attr "type" "multiple")]
90404b57 9930)
9931
9c08d1fa 9932(define_insn "movcond"
9933 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 9934 (if_then_else:SI
8fa3ba89 9935 (match_operator 5 "arm_comparison_operator"
5565501b 9936 [(match_operand:SI 3 "s_register_operand" "r,r,r")
9937 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
9938 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9939 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 9940 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9941 "TARGET_ARM"
9c08d1fa 9942 "*
9943 if (GET_CODE (operands[5]) == LT
9944 && (operands[4] == const0_rtx))
9945 {
0438d37f 9946 if (which_alternative != 1 && REG_P (operands[1]))
9c08d1fa 9947 {
9c08d1fa 9948 if (operands[2] == const0_rtx)
e2348bcb 9949 return \"and\\t%0, %1, %3, asr #31\";
9950 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
9c08d1fa 9951 }
0438d37f 9952 else if (which_alternative != 0 && REG_P (operands[2]))
9c08d1fa 9953 {
9c08d1fa 9954 if (operands[1] == const0_rtx)
e2348bcb 9955 return \"bic\\t%0, %2, %3, asr #31\";
9956 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
9c08d1fa 9957 }
9958 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 9959 are constants. */
9c08d1fa 9960 }
e2348bcb 9961
9c08d1fa 9962 if (GET_CODE (operands[5]) == GE
9963 && (operands[4] == const0_rtx))
9964 {
0438d37f 9965 if (which_alternative != 1 && REG_P (operands[1]))
9c08d1fa 9966 {
9c08d1fa 9967 if (operands[2] == const0_rtx)
e2348bcb 9968 return \"bic\\t%0, %1, %3, asr #31\";
9969 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
9c08d1fa 9970 }
0438d37f 9971 else if (which_alternative != 0 && REG_P (operands[2]))
9c08d1fa 9972 {
9c08d1fa 9973 if (operands[1] == const0_rtx)
e2348bcb 9974 return \"and\\t%0, %2, %3, asr #31\";
9975 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
9c08d1fa 9976 }
9977 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 9978 are constants. */
9c08d1fa 9979 }
0438d37f 9980 if (CONST_INT_P (operands[4])
9c08d1fa 9981 && !const_ok_for_arm (INTVAL (operands[4])))
e2348bcb 9982 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
9c08d1fa 9983 else
e2348bcb 9984 output_asm_insn (\"cmp\\t%3, %4\", operands);
9c08d1fa 9985 if (which_alternative != 0)
e2348bcb 9986 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
9c08d1fa 9987 if (which_alternative != 1)
e2348bcb 9988 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
9c08d1fa 9989 return \"\";
215b30b3 9990 "
8fa3ba89 9991 [(set_attr "conds" "clob")
1b7da4ac 9992 (set_attr "length" "8,8,12")
9993 (set_attr "type" "multiple")]
8fa3ba89 9994)
9c08d1fa 9995
25f905c2 9996;; ??? The patterns below need checking for Thumb-2 usefulness.
9997
8a18b90c 9998(define_insn "*ifcompare_plus_move"
9999 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10000 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 10001 [(match_operand:SI 4 "s_register_operand" "r,r")
10002 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
10003 (plus:SI
10004 (match_operand:SI 2 "s_register_operand" "r,r")
10005 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
129a2fe4 10006 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 10007 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10008 "TARGET_ARM"
8a18b90c 10009 "#"
8fa3ba89 10010 [(set_attr "conds" "clob")
1b7da4ac 10011 (set_attr "length" "8,12")
10012 (set_attr "type" "multiple")]
8fa3ba89 10013)
8a18b90c 10014
10015(define_insn "*if_plus_move"
129a2fe4 10016 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 10017 (if_then_else:SI
8fa3ba89 10018 (match_operator 4 "arm_comparison_operator"
8a18b90c 10019 [(match_operand 5 "cc_register" "") (const_int 0)])
10020 (plus:SI
129a2fe4 10021 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
10022 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
10023 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
cffb2a26 10024 "TARGET_ARM"
8a18b90c 10025 "@
10026 add%d4\\t%0, %2, %3
10027 sub%d4\\t%0, %2, #%n3
10028 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
129a2fe4 10029 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8fa3ba89 10030 [(set_attr "conds" "use")
10031 (set_attr "length" "4,4,8,8")
65f68e55 10032 (set_attr_alternative "type"
10033 [(if_then_else (match_operand 3 "const_int_operand" "")
d82e788e 10034 (const_string "alu_imm" )
112eda6f 10035 (const_string "alu_sreg"))
d82e788e 10036 (const_string "alu_imm")
282b4c75 10037 (const_string "multiple")
10038 (const_string "multiple")])]
8fa3ba89 10039)
8a18b90c 10040
10041(define_insn "*ifcompare_move_plus"
5565501b 10042 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10043 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 10044 [(match_operand:SI 4 "s_register_operand" "r,r")
10045 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 10046 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 10047 (plus:SI
10048 (match_operand:SI 2 "s_register_operand" "r,r")
10049 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
bd5b4116 10050 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10051 "TARGET_ARM"
8a18b90c 10052 "#"
8fa3ba89 10053 [(set_attr "conds" "clob")
1b7da4ac 10054 (set_attr "length" "8,12")
10055 (set_attr "type" "multiple")]
8fa3ba89 10056)
8a18b90c 10057
10058(define_insn "*if_move_plus"
129a2fe4 10059 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 10060 (if_then_else:SI
8fa3ba89 10061 (match_operator 4 "arm_comparison_operator"
8a18b90c 10062 [(match_operand 5 "cc_register" "") (const_int 0)])
129a2fe4 10063 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8a18b90c 10064 (plus:SI
129a2fe4 10065 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
10066 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
cffb2a26 10067 "TARGET_ARM"
8a18b90c 10068 "@
10069 add%D4\\t%0, %2, %3
10070 sub%D4\\t%0, %2, #%n3
10071 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
129a2fe4 10072 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8fa3ba89 10073 [(set_attr "conds" "use")
10074 (set_attr "length" "4,4,8,8")
282b4c75 10075 (set_attr_alternative "type"
10076 [(if_then_else (match_operand 3 "const_int_operand" "")
10077 (const_string "alu_imm" )
10078 (const_string "alu_sreg"))
10079 (const_string "alu_imm")
10080 (const_string "multiple")
10081 (const_string "multiple")])]
8fa3ba89 10082)
8a18b90c 10083
10084(define_insn "*ifcompare_arith_arith"
10085 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 10086 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8a18b90c 10087 [(match_operand:SI 5 "s_register_operand" "r")
10088 (match_operand:SI 6 "arm_add_operand" "rIL")])
9c08d1fa 10089 (match_operator:SI 8 "shiftable_operator"
8a18b90c 10090 [(match_operand:SI 1 "s_register_operand" "r")
10091 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9c08d1fa 10092 (match_operator:SI 7 "shiftable_operator"
8a18b90c 10093 [(match_operand:SI 3 "s_register_operand" "r")
10094 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
bd5b4116 10095 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10096 "TARGET_ARM"
8a18b90c 10097 "#"
8fa3ba89 10098 [(set_attr "conds" "clob")
1b7da4ac 10099 (set_attr "length" "12")
10100 (set_attr "type" "multiple")]
8fa3ba89 10101)
9c08d1fa 10102
8a18b90c 10103(define_insn "*if_arith_arith"
10104 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 10105 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8a18b90c 10106 [(match_operand 8 "cc_register" "") (const_int 0)])
10107 (match_operator:SI 6 "shiftable_operator"
10108 [(match_operand:SI 1 "s_register_operand" "r")
10109 (match_operand:SI 2 "arm_rhs_operand" "rI")])
10110 (match_operator:SI 7 "shiftable_operator"
10111 [(match_operand:SI 3 "s_register_operand" "r")
10112 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
cffb2a26 10113 "TARGET_ARM"
8a18b90c 10114 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8fa3ba89 10115 [(set_attr "conds" "use")
1b7da4ac 10116 (set_attr "length" "8")
10117 (set_attr "type" "multiple")]
8fa3ba89 10118)
8a18b90c 10119
f7fbdd4a 10120(define_insn "*ifcompare_arith_move"
9c08d1fa 10121 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10122 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 10123 [(match_operand:SI 2 "s_register_operand" "r,r")
5565501b 10124 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
9c08d1fa 10125 (match_operator:SI 7 "shiftable_operator"
10126 [(match_operand:SI 4 "s_register_operand" "r,r")
10127 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
129a2fe4 10128 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 10129 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10130 "TARGET_ARM"
9c08d1fa 10131 "*
9c08d1fa 10132 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 10133 the conditional operator is LT or GE and we are comparing against zero and
674a8f0b 10134 everything is in registers then we can do this in two instructions. */
9c08d1fa 10135 if (operands[3] == const0_rtx
10136 && GET_CODE (operands[7]) != AND
0438d37f 10137 && REG_P (operands[5])
10138 && REG_P (operands[1])
9c08d1fa 10139 && REGNO (operands[1]) == REGNO (operands[4])
10140 && REGNO (operands[4]) != REGNO (operands[0]))
10141 {
10142 if (GET_CODE (operands[6]) == LT)
40dbec34 10143 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 10144 else if (GET_CODE (operands[6]) == GE)
40dbec34 10145 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 10146 }
0438d37f 10147 if (CONST_INT_P (operands[3])
9c08d1fa 10148 && !const_ok_for_arm (INTVAL (operands[3])))
e2348bcb 10149 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
9c08d1fa 10150 else
e2348bcb 10151 output_asm_insn (\"cmp\\t%2, %3\", operands);
40dbec34 10152 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
9c08d1fa 10153 if (which_alternative != 0)
129a2fe4 10154 return \"mov%D6\\t%0, %1\";
9c08d1fa 10155 return \"\";
215b30b3 10156 "
8fa3ba89 10157 [(set_attr "conds" "clob")
1b7da4ac 10158 (set_attr "length" "8,12")
10159 (set_attr "type" "multiple")]
8fa3ba89 10160)
9c08d1fa 10161
8a18b90c 10162(define_insn "*if_arith_move"
129a2fe4 10163 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10164 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8a18b90c 10165 [(match_operand 6 "cc_register" "") (const_int 0)])
10166 (match_operator:SI 5 "shiftable_operator"
129a2fe4 10167 [(match_operand:SI 2 "s_register_operand" "r,r")
10168 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
10169 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
cffb2a26 10170 "TARGET_ARM"
8a18b90c 10171 "@
10172 %I5%d4\\t%0, %2, %3
129a2fe4 10173 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8fa3ba89 10174 [(set_attr "conds" "use")
10175 (set_attr "length" "4,8")
282b4c75 10176 (set_attr_alternative "type"
10177 [(if_then_else (match_operand 3 "const_int_operand" "")
10178 (const_string "alu_shift_imm" )
10179 (const_string "alu_shift_reg"))
10180 (const_string "multiple")])]
8fa3ba89 10181)
8a18b90c 10182
f7fbdd4a 10183(define_insn "*ifcompare_move_arith"
9c08d1fa 10184 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10185 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 10186 [(match_operand:SI 4 "s_register_operand" "r,r")
5565501b 10187 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 10188 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9c08d1fa 10189 (match_operator:SI 7 "shiftable_operator"
10190 [(match_operand:SI 2 "s_register_operand" "r,r")
10191 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 10192 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10193 "TARGET_ARM"
9c08d1fa 10194 "*
9c08d1fa 10195 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 10196 the conditional operator is LT or GE and we are comparing against zero and
9c08d1fa 10197 everything is in registers then we can do this in two instructions */
10198 if (operands[5] == const0_rtx
10199 && GET_CODE (operands[7]) != AND
0438d37f 10200 && REG_P (operands[3])
10201 && REG_P (operands[1])
9c08d1fa 10202 && REGNO (operands[1]) == REGNO (operands[2])
10203 && REGNO (operands[2]) != REGNO (operands[0]))
10204 {
10205 if (GET_CODE (operands[6]) == GE)
40dbec34 10206 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 10207 else if (GET_CODE (operands[6]) == LT)
40dbec34 10208 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 10209 }
40dbec34 10210
0438d37f 10211 if (CONST_INT_P (operands[5])
9c08d1fa 10212 && !const_ok_for_arm (INTVAL (operands[5])))
e2348bcb 10213 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
9c08d1fa 10214 else
e2348bcb 10215 output_asm_insn (\"cmp\\t%4, %5\", operands);
40dbec34 10216
9c08d1fa 10217 if (which_alternative != 0)
129a2fe4 10218 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
40dbec34 10219 return \"%I7%D6\\t%0, %2, %3\";
215b30b3 10220 "
8fa3ba89 10221 [(set_attr "conds" "clob")
1b7da4ac 10222 (set_attr "length" "8,12")
10223 (set_attr "type" "multiple")]
8fa3ba89 10224)
9c08d1fa 10225
8a18b90c 10226(define_insn "*if_move_arith"
129a2fe4 10227 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 10228 (if_then_else:SI
8fa3ba89 10229 (match_operator 4 "arm_comparison_operator"
8a18b90c 10230 [(match_operand 6 "cc_register" "") (const_int 0)])
129a2fe4 10231 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 10232 (match_operator:SI 5 "shiftable_operator"
129a2fe4 10233 [(match_operand:SI 2 "s_register_operand" "r,r")
10234 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
cffb2a26 10235 "TARGET_ARM"
8a18b90c 10236 "@
10237 %I5%D4\\t%0, %2, %3
129a2fe4 10238 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
8fa3ba89 10239 [(set_attr "conds" "use")
10240 (set_attr "length" "4,8")
282b4c75 10241 (set_attr_alternative "type"
10242 [(if_then_else (match_operand 3 "const_int_operand" "")
10243 (const_string "alu_shift_imm" )
10244 (const_string "alu_shift_reg"))
10245 (const_string "multiple")])]
8fa3ba89 10246)
8a18b90c 10247
10248(define_insn "*ifcompare_move_not"
9c08d1fa 10249 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 10250 (if_then_else:SI
8fa3ba89 10251 (match_operator 5 "arm_comparison_operator"
8a18b90c 10252 [(match_operand:SI 3 "s_register_operand" "r,r")
10253 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10254 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
10255 (not:SI
10256 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 10257 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10258 "TARGET_ARM"
8a18b90c 10259 "#"
8fa3ba89 10260 [(set_attr "conds" "clob")
1b7da4ac 10261 (set_attr "length" "8,12")
10262 (set_attr "type" "multiple")]
8fa3ba89 10263)
9c08d1fa 10264
8a18b90c 10265(define_insn "*if_move_not"
10266 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10267 (if_then_else:SI
8fa3ba89 10268 (match_operator 4 "arm_comparison_operator"
8a18b90c 10269 [(match_operand 3 "cc_register" "") (const_int 0)])
10270 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
10271 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
cffb2a26 10272 "TARGET_ARM"
8a18b90c 10273 "@
10274 mvn%D4\\t%0, %2
10275 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
10276 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
8fa3ba89 10277 [(set_attr "conds" "use")
1aed5204 10278 (set_attr "type" "mvn_reg")
1b7da4ac 10279 (set_attr "length" "4,8,8")
10280 (set_attr "type" "mvn_reg,multiple,multiple")]
8fa3ba89 10281)
8a18b90c 10282
10283(define_insn "*ifcompare_not_move"
9c08d1fa 10284 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 10285 (if_then_else:SI
8fa3ba89 10286 (match_operator 5 "arm_comparison_operator"
8a18b90c 10287 [(match_operand:SI 3 "s_register_operand" "r,r")
10288 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10289 (not:SI
10290 (match_operand:SI 2 "s_register_operand" "r,r"))
10291 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 10292 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10293 "TARGET_ARM"
8a18b90c 10294 "#"
8fa3ba89 10295 [(set_attr "conds" "clob")
1b7da4ac 10296 (set_attr "length" "8,12")
10297 (set_attr "type" "multiple")]
8fa3ba89 10298)
9c08d1fa 10299
8a18b90c 10300(define_insn "*if_not_move"
10301 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10302 (if_then_else:SI
8fa3ba89 10303 (match_operator 4 "arm_comparison_operator"
8a18b90c 10304 [(match_operand 3 "cc_register" "") (const_int 0)])
10305 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
10306 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 10307 "TARGET_ARM"
8a18b90c 10308 "@
10309 mvn%d4\\t%0, %2
10310 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
10311 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
8fa3ba89 10312 [(set_attr "conds" "use")
1b7da4ac 10313 (set_attr "type" "mvn_reg,multiple,multiple")
8fa3ba89 10314 (set_attr "length" "4,8,8")]
10315)
8a18b90c 10316
10317(define_insn "*ifcompare_shift_move"
9c08d1fa 10318 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 10319 (if_then_else:SI
8fa3ba89 10320 (match_operator 6 "arm_comparison_operator"
8a18b90c 10321 [(match_operand:SI 4 "s_register_operand" "r,r")
10322 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
10323 (match_operator:SI 7 "shift_operator"
10324 [(match_operand:SI 2 "s_register_operand" "r,r")
10325 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
10326 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 10327 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10328 "TARGET_ARM"
9c08d1fa 10329 "#"
8fa3ba89 10330 [(set_attr "conds" "clob")
1b7da4ac 10331 (set_attr "length" "8,12")
10332 (set_attr "type" "multiple")]
8fa3ba89 10333)
9c08d1fa 10334
8a18b90c 10335(define_insn "*if_shift_move"
10336 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10337 (if_then_else:SI
8fa3ba89 10338 (match_operator 5 "arm_comparison_operator"
8a18b90c 10339 [(match_operand 6 "cc_register" "") (const_int 0)])
10340 (match_operator:SI 4 "shift_operator"
10341 [(match_operand:SI 2 "s_register_operand" "r,r,r")
10342 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
10343 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 10344 "TARGET_ARM"
5565501b 10345 "@
8a18b90c 10346 mov%d5\\t%0, %2%S4
10347 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
10348 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
8fa3ba89 10349 [(set_attr "conds" "use")
331beb1a 10350 (set_attr "shift" "2")
a2cd141b 10351 (set_attr "length" "4,8,8")
282b4c75 10352 (set_attr_alternative "type"
10353 [(if_then_else (match_operand 3 "const_int_operand" "")
10354 (const_string "mov_shift" )
10355 (const_string "mov_shift_reg"))
10356 (const_string "multiple")
10357 (const_string "multiple")])]
8fa3ba89 10358)
5565501b 10359
8a18b90c 10360(define_insn "*ifcompare_move_shift"
10361 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 10362 (if_then_else:SI
8fa3ba89 10363 (match_operator 6 "arm_comparison_operator"
8a18b90c 10364 [(match_operand:SI 4 "s_register_operand" "r,r")
10365 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
10366 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
5565501b 10367 (match_operator:SI 7 "shift_operator"
8a18b90c 10368 [(match_operand:SI 2 "s_register_operand" "r,r")
10369 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
bd5b4116 10370 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10371 "TARGET_ARM"
8a18b90c 10372 "#"
8fa3ba89 10373 [(set_attr "conds" "clob")
1b7da4ac 10374 (set_attr "length" "8,12")
10375 (set_attr "type" "multiple")]
8fa3ba89 10376)
5565501b 10377
8a18b90c 10378(define_insn "*if_move_shift"
10379 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 10380 (if_then_else:SI
8fa3ba89 10381 (match_operator 5 "arm_comparison_operator"
8a18b90c 10382 [(match_operand 6 "cc_register" "") (const_int 0)])
10383 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
10384 (match_operator:SI 4 "shift_operator"
10385 [(match_operand:SI 2 "s_register_operand" "r,r,r")
10386 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
cffb2a26 10387 "TARGET_ARM"
5565501b 10388 "@
8a18b90c 10389 mov%D5\\t%0, %2%S4
10390 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
10391 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
8fa3ba89 10392 [(set_attr "conds" "use")
331beb1a 10393 (set_attr "shift" "2")
a2cd141b 10394 (set_attr "length" "4,8,8")
282b4c75 10395 (set_attr_alternative "type"
10396 [(if_then_else (match_operand 3 "const_int_operand" "")
10397 (const_string "mov_shift" )
10398 (const_string "mov_shift_reg"))
10399 (const_string "multiple")
10400 (const_string "multiple")])]
8fa3ba89 10401)
9c08d1fa 10402
f7fbdd4a 10403(define_insn "*ifcompare_shift_shift"
8a18b90c 10404 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 10405 (if_then_else:SI
8fa3ba89 10406 (match_operator 7 "arm_comparison_operator"
8a18b90c 10407 [(match_operand:SI 5 "s_register_operand" "r")
10408 (match_operand:SI 6 "arm_add_operand" "rIL")])
5565501b 10409 (match_operator:SI 8 "shift_operator"
8a18b90c 10410 [(match_operand:SI 1 "s_register_operand" "r")
10411 (match_operand:SI 2 "arm_rhs_operand" "rM")])
5565501b 10412 (match_operator:SI 9 "shift_operator"
8a18b90c 10413 [(match_operand:SI 3 "s_register_operand" "r")
10414 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
bd5b4116 10415 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10416 "TARGET_ARM"
8a18b90c 10417 "#"
8fa3ba89 10418 [(set_attr "conds" "clob")
1b7da4ac 10419 (set_attr "length" "12")
10420 (set_attr "type" "multiple")]
8fa3ba89 10421)
9c08d1fa 10422
8a18b90c 10423(define_insn "*if_shift_shift"
10424 [(set (match_operand:SI 0 "s_register_operand" "=r")
10425 (if_then_else:SI
8fa3ba89 10426 (match_operator 5 "arm_comparison_operator"
8a18b90c 10427 [(match_operand 8 "cc_register" "") (const_int 0)])
10428 (match_operator:SI 6 "shift_operator"
10429 [(match_operand:SI 1 "s_register_operand" "r")
10430 (match_operand:SI 2 "arm_rhs_operand" "rM")])
10431 (match_operator:SI 7 "shift_operator"
10432 [(match_operand:SI 3 "s_register_operand" "r")
10433 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
cffb2a26 10434 "TARGET_ARM"
8a18b90c 10435 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
8fa3ba89 10436 [(set_attr "conds" "use")
331beb1a 10437 (set_attr "shift" "1")
a2cd141b 10438 (set_attr "length" "8")
10439 (set (attr "type") (if_then_else
10440 (and (match_operand 2 "const_int_operand" "")
10441 (match_operand 4 "const_int_operand" ""))
1aed5204 10442 (const_string "mov_shift")
10443 (const_string "mov_shift_reg")))]
8fa3ba89 10444)
8a18b90c 10445
f7fbdd4a 10446(define_insn "*ifcompare_not_arith"
8a18b90c 10447 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 10448 (if_then_else:SI
8fa3ba89 10449 (match_operator 6 "arm_comparison_operator"
8a18b90c 10450 [(match_operand:SI 4 "s_register_operand" "r")
10451 (match_operand:SI 5 "arm_add_operand" "rIL")])
10452 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5565501b 10453 (match_operator:SI 7 "shiftable_operator"
8a18b90c 10454 [(match_operand:SI 2 "s_register_operand" "r")
10455 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
bd5b4116 10456 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10457 "TARGET_ARM"
8a18b90c 10458 "#"
8fa3ba89 10459 [(set_attr "conds" "clob")
1b7da4ac 10460 (set_attr "length" "12")
10461 (set_attr "type" "multiple")]
8fa3ba89 10462)
9c08d1fa 10463
8a18b90c 10464(define_insn "*if_not_arith"
10465 [(set (match_operand:SI 0 "s_register_operand" "=r")
10466 (if_then_else:SI
8fa3ba89 10467 (match_operator 5 "arm_comparison_operator"
8a18b90c 10468 [(match_operand 4 "cc_register" "") (const_int 0)])
10469 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
10470 (match_operator:SI 6 "shiftable_operator"
10471 [(match_operand:SI 2 "s_register_operand" "r")
10472 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
cffb2a26 10473 "TARGET_ARM"
8a18b90c 10474 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
8fa3ba89 10475 [(set_attr "conds" "use")
1aed5204 10476 (set_attr "type" "mvn_reg")
8fa3ba89 10477 (set_attr "length" "8")]
10478)
8a18b90c 10479
10480(define_insn "*ifcompare_arith_not"
10481 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 10482 (if_then_else:SI
8fa3ba89 10483 (match_operator 6 "arm_comparison_operator"
8a18b90c 10484 [(match_operand:SI 4 "s_register_operand" "r")
10485 (match_operand:SI 5 "arm_add_operand" "rIL")])
5565501b 10486 (match_operator:SI 7 "shiftable_operator"
8a18b90c 10487 [(match_operand:SI 2 "s_register_operand" "r")
10488 (match_operand:SI 3 "arm_rhs_operand" "rI")])
10489 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
bd5b4116 10490 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10491 "TARGET_ARM"
8a18b90c 10492 "#"
8fa3ba89 10493 [(set_attr "conds" "clob")
1b7da4ac 10494 (set_attr "length" "12")
10495 (set_attr "type" "multiple")]
8fa3ba89 10496)
9c08d1fa 10497
8a18b90c 10498(define_insn "*if_arith_not"
10499 [(set (match_operand:SI 0 "s_register_operand" "=r")
10500 (if_then_else:SI
8fa3ba89 10501 (match_operator 5 "arm_comparison_operator"
8a18b90c 10502 [(match_operand 4 "cc_register" "") (const_int 0)])
10503 (match_operator:SI 6 "shiftable_operator"
10504 [(match_operand:SI 2 "s_register_operand" "r")
10505 (match_operand:SI 3 "arm_rhs_operand" "rI")])
10506 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
cffb2a26 10507 "TARGET_ARM"
8a18b90c 10508 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
8fa3ba89 10509 [(set_attr "conds" "use")
1b7da4ac 10510 (set_attr "type" "multiple")
8fa3ba89 10511 (set_attr "length" "8")]
10512)
8a18b90c 10513
f7fbdd4a 10514(define_insn "*ifcompare_neg_move"
8a18b90c 10515 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 10516 (if_then_else:SI
8fa3ba89 10517 (match_operator 5 "arm_comparison_operator"
8a18b90c 10518 [(match_operand:SI 3 "s_register_operand" "r,r")
10519 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10520 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
10521 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 10522 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10523 "TARGET_ARM"
8a18b90c 10524 "#"
8fa3ba89 10525 [(set_attr "conds" "clob")
1b7da4ac 10526 (set_attr "length" "8,12")
10527 (set_attr "type" "multiple")]
8fa3ba89 10528)
8a18b90c 10529
530bb693 10530(define_insn_and_split "*if_neg_move"
10531 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
8a18b90c 10532 (if_then_else:SI
8fa3ba89 10533 (match_operator 4 "arm_comparison_operator"
8a18b90c 10534 [(match_operand 3 "cc_register" "") (const_int 0)])
530bb693 10535 (neg:SI (match_operand:SI 2 "s_register_operand" "l,r"))
10536 (match_operand:SI 1 "s_register_operand" "0,0")))]
10537 "TARGET_32BIT"
10538 "#"
10539 "&& reload_completed"
10540 [(cond_exec (match_op_dup 4 [(match_dup 3) (const_int 0)])
10541 (set (match_dup 0) (neg:SI (match_dup 2))))]
10542 ""
8fa3ba89 10543 [(set_attr "conds" "use")
530bb693 10544 (set_attr "length" "4")
10545 (set_attr "arch" "t2,32")
10546 (set_attr "enabled_for_depr_it" "yes,no")
10547 (set_attr "type" "logic_shift_imm")]
8fa3ba89 10548)
9c08d1fa 10549
f7fbdd4a 10550(define_insn "*ifcompare_move_neg"
8a18b90c 10551 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 10552 (if_then_else:SI
8fa3ba89 10553 (match_operator 5 "arm_comparison_operator"
8a18b90c 10554 [(match_operand:SI 3 "s_register_operand" "r,r")
10555 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10556 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
10557 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 10558 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10559 "TARGET_ARM"
8a18b90c 10560 "#"
8fa3ba89 10561 [(set_attr "conds" "clob")
1b7da4ac 10562 (set_attr "length" "8,12")
10563 (set_attr "type" "multiple")]
8fa3ba89 10564)
8a18b90c 10565
530bb693 10566(define_insn_and_split "*if_move_neg"
10567 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
8a18b90c 10568 (if_then_else:SI
8fa3ba89 10569 (match_operator 4 "arm_comparison_operator"
8a18b90c 10570 [(match_operand 3 "cc_register" "") (const_int 0)])
530bb693 10571 (match_operand:SI 1 "s_register_operand" "0,0")
10572 (neg:SI (match_operand:SI 2 "s_register_operand" "l,r"))))]
10573 "TARGET_32BIT"
10574 "#"
10575 "&& reload_completed"
10576 [(cond_exec (match_dup 5)
10577 (set (match_dup 0) (neg:SI (match_dup 2))))]
10578 {
10579 machine_mode mode = GET_MODE (operands[3]);
10580 rtx_code rc = GET_CODE (operands[4]);
10581
10582 if (mode == CCFPmode || mode == CCFPEmode)
10583 rc = reverse_condition_maybe_unordered (rc);
10584 else
10585 rc = reverse_condition (rc);
10586
10587 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[3], const0_rtx);
10588 }
0d66636f 10589 [(set_attr "conds" "use")
530bb693 10590 (set_attr "length" "4")
10591 (set_attr "arch" "t2,32")
10592 (set_attr "enabled_for_depr_it" "yes,no")
10593 (set_attr "type" "logic_shift_imm")]
0d66636f 10594)
9c08d1fa 10595
f7fbdd4a 10596(define_insn "*arith_adjacentmem"
9c08d1fa 10597 [(set (match_operand:SI 0 "s_register_operand" "=r")
10598 (match_operator:SI 1 "shiftable_operator"
10599 [(match_operand:SI 2 "memory_operand" "m")
10600 (match_operand:SI 3 "memory_operand" "m")]))
10601 (clobber (match_scratch:SI 4 "=r"))]
cffb2a26 10602 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9c08d1fa 10603 "*
215b30b3 10604 {
10605 rtx ldm[3];
10606 rtx arith[4];
94dee231 10607 rtx base_reg;
10608 HOST_WIDE_INT val1 = 0, val2 = 0;
9c08d1fa 10609
215b30b3 10610 if (REGNO (operands[0]) > REGNO (operands[4]))
10611 {
10612 ldm[1] = operands[4];
10613 ldm[2] = operands[0];
10614 }
10615 else
10616 {
10617 ldm[1] = operands[0];
10618 ldm[2] = operands[4];
10619 }
94dee231 10620
10621 base_reg = XEXP (operands[2], 0);
10622
10623 if (!REG_P (base_reg))
10624 {
10625 val1 = INTVAL (XEXP (base_reg, 1));
10626 base_reg = XEXP (base_reg, 0);
10627 }
10628
10629 if (!REG_P (XEXP (operands[3], 0)))
215b30b3 10630 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
94dee231 10631
215b30b3 10632 arith[0] = operands[0];
10633 arith[3] = operands[1];
94dee231 10634
215b30b3 10635 if (val1 < val2)
10636 {
10637 arith[1] = ldm[1];
10638 arith[2] = ldm[2];
10639 }
10640 else
10641 {
10642 arith[1] = ldm[2];
10643 arith[2] = ldm[1];
10644 }
94dee231 10645
10646 ldm[0] = base_reg;
10647 if (val1 !=0 && val2 != 0)
215b30b3 10648 {
cdb1295a 10649 rtx ops[3];
10650
94dee231 10651 if (val1 == 4 || val2 == 4)
10652 /* Other val must be 8, since we know they are adjacent and neither
10653 is zero. */
3ef90e77 10654 output_asm_insn (\"ldmib%?\\t%0, {%1, %2}\", ldm);
cdb1295a 10655 else if (const_ok_for_arm (val1) || const_ok_for_arm (-val1))
94dee231 10656 {
94dee231 10657 ldm[0] = ops[0] = operands[4];
10658 ops[1] = base_reg;
10659 ops[2] = GEN_INT (val1);
10660 output_add_immediate (ops);
10661 if (val1 < val2)
3ef90e77 10662 output_asm_insn (\"ldmia%?\\t%0, {%1, %2}\", ldm);
94dee231 10663 else
3ef90e77 10664 output_asm_insn (\"ldmda%?\\t%0, {%1, %2}\", ldm);
94dee231 10665 }
cdb1295a 10666 else
10667 {
10668 /* Offset is out of range for a single add, so use two ldr. */
10669 ops[0] = ldm[1];
10670 ops[1] = base_reg;
10671 ops[2] = GEN_INT (val1);
10672 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10673 ops[0] = ldm[2];
10674 ops[2] = GEN_INT (val2);
10675 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10676 }
215b30b3 10677 }
94dee231 10678 else if (val1 != 0)
215b30b3 10679 {
215b30b3 10680 if (val1 < val2)
3ef90e77 10681 output_asm_insn (\"ldmda%?\\t%0, {%1, %2}\", ldm);
215b30b3 10682 else
3ef90e77 10683 output_asm_insn (\"ldmia%?\\t%0, {%1, %2}\", ldm);
215b30b3 10684 }
10685 else
10686 {
215b30b3 10687 if (val1 < val2)
3ef90e77 10688 output_asm_insn (\"ldmia%?\\t%0, {%1, %2}\", ldm);
215b30b3 10689 else
3ef90e77 10690 output_asm_insn (\"ldmda%?\\t%0, {%1, %2}\", ldm);
215b30b3 10691 }
10692 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
10693 return \"\";
10694 }"
10695 [(set_attr "length" "12")
10696 (set_attr "predicable" "yes")
9f2c2a36 10697 (set_attr "type" "load_4")]
215b30b3 10698)
9c08d1fa 10699
9c08d1fa 10700; This pattern is never tried by combine, so do it as a peephole
10701
a0f94409 10702(define_peephole2
372575c7 10703 [(set (match_operand:SI 0 "arm_general_register_operand" "")
10704 (match_operand:SI 1 "arm_general_register_operand" ""))
bd5b4116 10705 (set (reg:CC CC_REGNUM)
aea4c774 10706 (compare:CC (match_dup 1) (const_int 0)))]
372575c7 10707 "TARGET_ARM"
a0f94409 10708 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
10709 (set (match_dup 0) (match_dup 1))])]
10710 ""
0d66636f 10711)
9c08d1fa 10712
9c08d1fa 10713(define_split
10714 [(set (match_operand:SI 0 "s_register_operand" "")
10715 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
10716 (const_int 0))
8fa3ba89 10717 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9c08d1fa 10718 [(match_operand:SI 3 "s_register_operand" "")
10719 (match_operand:SI 4 "arm_rhs_operand" "")]))))
10720 (clobber (match_operand:SI 5 "s_register_operand" ""))]
cffb2a26 10721 "TARGET_ARM"
9c08d1fa 10722 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
10723 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
10724 (match_dup 5)))]
215b30b3 10725 ""
10726)
9c08d1fa 10727
aea4c774 10728;; This split can be used because CC_Z mode implies that the following
10729;; branch will be an equality, or an unsigned inequality, so the sign
10730;; extension is not needed.
9c08d1fa 10731
aea4c774 10732(define_split
bd5b4116 10733 [(set (reg:CC_Z CC_REGNUM)
aea4c774 10734 (compare:CC_Z
10735 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9c08d1fa 10736 (const_int 24))
aea4c774 10737 (match_operand 1 "const_int_operand" "")))
10738 (clobber (match_scratch:SI 2 ""))]
cffb2a26 10739 "TARGET_ARM
8c4e8755 10740 && ((UINTVAL (operands[1]))
10741 == ((UINTVAL (operands[1])) >> 24) << 24)"
aea4c774 10742 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
bd5b4116 10743 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
aea4c774 10744 "
9c08d1fa 10745 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
215b30b3 10746 "
10747)
25f905c2 10748;; ??? Check the patterns above for Thumb-2 usefulness
9c08d1fa 10749
87b22bf7 10750(define_expand "prologue"
10751 [(clobber (const_int 0))]
cffb2a26 10752 "TARGET_EITHER"
25f905c2 10753 "if (TARGET_32BIT)
cffb2a26 10754 arm_expand_prologue ();
10755 else
25f905c2 10756 thumb1_expand_prologue ();
87b22bf7 10757 DONE;
cffb2a26 10758 "
10759)
87b22bf7 10760
56d27660 10761(define_expand "epilogue"
4c44712e 10762 [(clobber (const_int 0))]
cffb2a26 10763 "TARGET_EITHER"
56d27660 10764 "
18d50ae6 10765 if (crtl->calls_eh_return)
fb94f18b 10766 emit_insn (gen_force_register_use (gen_rtx_REG (Pmode, 2)));
25f905c2 10767 if (TARGET_THUMB1)
c3635784 10768 {
10769 thumb1_expand_epilogue ();
10770 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
10771 gen_rtvec (1, ret_rtx), VUNSPEC_EPILOGUE));
10772 }
10773 else if (HAVE_return)
10774 {
10775 /* HAVE_return is testing for USE_RETURN_INSN (FALSE). Hence,
10776 no need for explicit testing again. */
10777 emit_jump_insn (gen_return ());
10778 }
10779 else if (TARGET_32BIT)
10780 {
10781 arm_expand_epilogue (true);
10782 }
cffb2a26 10783 DONE;
10784 "
10785)
56d27660 10786
ef5651d0 10787;; Note - although unspec_volatile's USE all hard registers,
10788;; USEs are ignored after relaod has completed. Thus we need
10789;; to add an unspec of the link register to ensure that flow
10790;; does not think that it is unused by the sibcall branch that
10791;; will replace the standard function epilogue.
c3635784 10792(define_expand "sibcall_epilogue"
fb94f18b 10793 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_REGISTER_USE)
c3635784 10794 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
10795 "TARGET_32BIT"
10796 "
10797 arm_expand_epilogue (false);
10798 DONE;
10799 "
1c494086 10800)
10801
cffb2a26 10802(define_expand "eh_epilogue"
7db9af5d 10803 [(use (match_operand:SI 0 "register_operand" ""))
10804 (use (match_operand:SI 1 "register_operand" ""))
10805 (use (match_operand:SI 2 "register_operand" ""))]
cffb2a26 10806 "TARGET_EITHER"
10807 "
215b30b3 10808 {
10809 cfun->machine->eh_epilogue_sp_ofs = operands[1];
0438d37f 10810 if (!REG_P (operands[2]) || REGNO (operands[2]) != 2)
215b30b3 10811 {
10812 rtx ra = gen_rtx_REG (Pmode, 2);
10813
10814 emit_move_insn (ra, operands[2]);
10815 operands[2] = ra;
10816 }
5cf3595a 10817 /* This is a hack -- we may have crystalized the function type too
10818 early. */
10819 cfun->machine->func_type = 0;
215b30b3 10820 }"
10821)
56d27660 10822
9c08d1fa 10823;; This split is only used during output to reduce the number of patterns
10824;; that need assembler instructions adding to them. We allowed the setting
10825;; of the conditions to be implicit during rtl generation so that
10826;; the conditional compare patterns would work. However this conflicts to
8a18b90c 10827;; some extent with the conditional data operations, so we have to split them
9c08d1fa 10828;; up again here.
10829
25f905c2 10830;; ??? Need to audit these splitters for Thumb-2. Why isn't normal
10831;; conditional execution sufficient?
10832
9c08d1fa 10833(define_split
10834 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 10835 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10836 [(match_operand 2 "" "") (match_operand 3 "" "")])
10837 (match_dup 0)
10838 (match_operand 4 "" "")))
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_dup 7)
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 enum rtx_code rc = GET_CODE (operands[1]);
10849
bd5b4116 10850 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10851 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10852 if (mode == CCFPmode || mode == CCFPEmode)
10853 rc = reverse_condition_maybe_unordered (rc);
10854 else
10855 rc = reverse_condition (rc);
10856
10857 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
10858 }"
10859)
10860
10861(define_split
10862 [(set (match_operand:SI 0 "s_register_operand" "")
10863 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10864 [(match_operand 2 "" "") (match_operand 3 "" "")])
10865 (match_operand 4 "" "")
10866 (match_dup 0)))
bd5b4116 10867 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10868 "TARGET_ARM && reload_completed"
8fa3ba89 10869 [(set (match_dup 5) (match_dup 6))
10870 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
10871 (set (match_dup 0) (match_dup 4)))]
10872 "
10873 {
3754d046 10874 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8fa3ba89 10875 operands[2], operands[3]);
10876
bd5b4116 10877 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10878 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10879 }"
10880)
10881
10882(define_split
10883 [(set (match_operand:SI 0 "s_register_operand" "")
10884 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9c08d1fa 10885 [(match_operand 2 "" "") (match_operand 3 "" "")])
10886 (match_operand 4 "" "")
10887 (match_operand 5 "" "")))
bd5b4116 10888 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10889 "TARGET_ARM && reload_completed"
8fa3ba89 10890 [(set (match_dup 6) (match_dup 7))
10891 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10892 (set (match_dup 0) (match_dup 4)))
10893 (cond_exec (match_dup 8)
10894 (set (match_dup 0) (match_dup 5)))]
10895 "
10896 {
3754d046 10897 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8fa3ba89 10898 operands[2], operands[3]);
10899 enum rtx_code rc = GET_CODE (operands[1]);
10900
bd5b4116 10901 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10902 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10903 if (mode == CCFPmode || mode == CCFPEmode)
10904 rc = reverse_condition_maybe_unordered (rc);
10905 else
10906 rc = reverse_condition (rc);
10907
10908 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10909 }"
10910)
10911
cffb2a26 10912(define_split
10913 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 10914 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
cffb2a26 10915 [(match_operand:SI 2 "s_register_operand" "")
10916 (match_operand:SI 3 "arm_add_operand" "")])
10917 (match_operand:SI 4 "arm_rhs_operand" "")
10918 (not:SI
10919 (match_operand:SI 5 "s_register_operand" ""))))
bd5b4116 10920 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10921 "TARGET_ARM && reload_completed"
cffb2a26 10922 [(set (match_dup 6) (match_dup 7))
f6c53574 10923 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10924 (set (match_dup 0) (match_dup 4)))
10925 (cond_exec (match_dup 8)
10926 (set (match_dup 0) (not:SI (match_dup 5))))]
cffb2a26 10927 "
215b30b3 10928 {
3754d046 10929 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
215b30b3 10930 operands[2], operands[3]);
f6c53574 10931 enum rtx_code rc = GET_CODE (operands[1]);
cffb2a26 10932
bd5b4116 10933 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
1a83b3ff 10934 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
f6c53574 10935 if (mode == CCFPmode || mode == CCFPEmode)
10936 rc = reverse_condition_maybe_unordered (rc);
10937 else
10938 rc = reverse_condition (rc);
10939
10940 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
215b30b3 10941 }"
10942)
cffb2a26 10943
10944(define_insn "*cond_move_not"
10945 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10946 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
cffb2a26 10947 [(match_operand 3 "cc_register" "") (const_int 0)])
10948 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10949 (not:SI
10950 (match_operand:SI 2 "s_register_operand" "r,r"))))]
10951 "TARGET_ARM"
10952 "@
10953 mvn%D4\\t%0, %2
10954 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
0d66636f 10955 [(set_attr "conds" "use")
1b7da4ac 10956 (set_attr "type" "mvn_reg,multiple")
0d66636f 10957 (set_attr "length" "4,8")]
10958)
cffb2a26 10959
9c08d1fa 10960;; The next two patterns occur when an AND operation is followed by a
10961;; scc insn sequence
10962
f7fbdd4a 10963(define_insn "*sign_extract_onebit"
9c08d1fa 10964 [(set (match_operand:SI 0 "s_register_operand" "=r")
10965 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10966 (const_int 1)
ed750274 10967 (match_operand:SI 2 "const_int_operand" "n")))
10968 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10969 "TARGET_ARM"
9c08d1fa 10970 "*
0d66636f 10971 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10972 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
10973 return \"mvnne\\t%0, #0\";
10974 "
10975 [(set_attr "conds" "clob")
1b7da4ac 10976 (set_attr "length" "8")
10977 (set_attr "type" "multiple")]
0d66636f 10978)
9c08d1fa 10979
f7fbdd4a 10980(define_insn "*not_signextract_onebit"
9c08d1fa 10981 [(set (match_operand:SI 0 "s_register_operand" "=r")
10982 (not:SI
10983 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10984 (const_int 1)
ed750274 10985 (match_operand:SI 2 "const_int_operand" "n"))))
10986 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10987 "TARGET_ARM"
9c08d1fa 10988 "*
0d66636f 10989 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10990 output_asm_insn (\"tst\\t%1, %2\", operands);
10991 output_asm_insn (\"mvneq\\t%0, #0\", operands);
10992 return \"movne\\t%0, #0\";
10993 "
10994 [(set_attr "conds" "clob")
1b7da4ac 10995 (set_attr "length" "12")
10996 (set_attr "type" "multiple")]
0d66636f 10997)
25f905c2 10998;; ??? The above patterns need auditing for Thumb-2
87b22bf7 10999
0d66636f 11000;; Push multiple registers to the stack. Registers are in parallel (use ...)
11001;; expressions. For simplicity, the first register is also in the unspec
11002;; part.
08508cbf 11003;; To avoid the usage of GNU extension, the length attribute is computed
11004;; in a C function arm_attr_length_push_multi.
f7fbdd4a 11005(define_insn "*push_multi"
87b22bf7 11006 [(match_parallel 2 "multi_register_push"
7571d3f7 11007 [(set (match_operand:BLK 0 "push_mult_memory_operand" "")
3cc80a30 11008 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "")]
e1159bbe 11009 UNSPEC_PUSH_MULT))])]
7571d3f7 11010 ""
87b22bf7 11011 "*
215b30b3 11012 {
11013 int num_saves = XVECLEN (operands[2], 0);
ed593f11 11014
215b30b3 11015 /* For the StrongARM at least it is faster to
25f905c2 11016 use STR to store only a single register.
542d5028 11017 In Thumb mode always use push, and the assembler will pick
11018 something appropriate. */
25f905c2 11019 if (num_saves == 1 && TARGET_ARM)
61309563 11020 output_asm_insn (\"str%?\\t%1, [%m0, #-4]!\", operands);
215b30b3 11021 else
11022 {
11023 int i;
11024 char pattern[100];
ed593f11 11025
3ef90e77 11026 if (TARGET_32BIT)
61309563 11027 strcpy (pattern, \"push%?\\t{%1\");
25f905c2 11028 else
11029 strcpy (pattern, \"push\\t{%1\");
215b30b3 11030
6079f055 11031 for (i = 1; i < num_saves; i++)
215b30b3 11032 {
11033 strcat (pattern, \", %|\");
11034 strcat (pattern,
11035 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
11036 }
11037
11038 strcat (pattern, \"}\");
11039 output_asm_insn (pattern, operands);
11040 }
11041
11042 return \"\";
11043 }"
9f2c2a36 11044 [(set_attr "type" "store_16")
a6864a24 11045 (set (attr "length")
08508cbf 11046 (symbol_ref "arm_attr_length_push_multi (operands[2], operands[1])"))]
215b30b3 11047)
f7fbdd4a 11048
4c58c898 11049(define_insn "stack_tie"
11050 [(set (mem:BLK (scratch))
aaa37ad6 11051 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "rk")
11052 (match_operand:SI 1 "s_register_operand" "rk")]
4c58c898 11053 UNSPEC_PRLG_STK))]
11054 ""
11055 ""
1b7da4ac 11056 [(set_attr "length" "0")
11057 (set_attr "type" "block")]
4c58c898 11058)
11059
426be8c5 11060;; Pop (as used in epilogue RTL)
11061;;
11062(define_insn "*load_multiple_with_writeback"
11063 [(match_parallel 0 "load_multiple_operation"
11064 [(set (match_operand:SI 1 "s_register_operand" "+rk")
11065 (plus:SI (match_dup 1)
809003b3 11066 (match_operand:SI 2 "const_int_I_operand" "I")))
426be8c5 11067 (set (match_operand:SI 3 "s_register_operand" "=rk")
11068 (mem:SI (match_dup 1)))
11069 ])]
11070 "TARGET_32BIT && (reload_in_progress || reload_completed)"
11071 "*
11072 {
11073 arm_output_multireg_pop (operands, /*return_pc=*/false,
11074 /*cond=*/const_true_rtx,
11075 /*reverse=*/false,
11076 /*update=*/true);
11077 return \"\";
11078 }
11079 "
9f2c2a36 11080 [(set_attr "type" "load_16")
5431c9c9 11081 (set_attr "predicable" "yes")
11082 (set (attr "length")
11083 (symbol_ref "arm_attr_length_pop_multi (operands,
11084 /*return_pc=*/false,
11085 /*write_back_p=*/true)"))]
426be8c5 11086)
11087
11088;; Pop with return (as used in epilogue RTL)
11089;;
11090;; This instruction is generated when the registers are popped at the end of
11091;; epilogue. Here, instead of popping the value into LR and then generating
11092;; jump to LR, value is popped into PC directly. Hence, the pattern is combined
11093;; with (return).
11094(define_insn "*pop_multiple_with_writeback_and_return"
11095 [(match_parallel 0 "pop_multiple_return"
11096 [(return)
11097 (set (match_operand:SI 1 "s_register_operand" "+rk")
11098 (plus:SI (match_dup 1)
809003b3 11099 (match_operand:SI 2 "const_int_I_operand" "I")))
426be8c5 11100 (set (match_operand:SI 3 "s_register_operand" "=rk")
11101 (mem:SI (match_dup 1)))
11102 ])]
11103 "TARGET_32BIT && (reload_in_progress || reload_completed)"
11104 "*
11105 {
11106 arm_output_multireg_pop (operands, /*return_pc=*/true,
11107 /*cond=*/const_true_rtx,
11108 /*reverse=*/false,
11109 /*update=*/true);
11110 return \"\";
11111 }
11112 "
9f2c2a36 11113 [(set_attr "type" "load_16")
5431c9c9 11114 (set_attr "predicable" "yes")
11115 (set (attr "length")
11116 (symbol_ref "arm_attr_length_pop_multi (operands, /*return_pc=*/true,
11117 /*write_back_p=*/true)"))]
426be8c5 11118)
11119
11120(define_insn "*pop_multiple_with_return"
11121 [(match_parallel 0 "pop_multiple_return"
11122 [(return)
11123 (set (match_operand:SI 2 "s_register_operand" "=rk")
11124 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
11125 ])]
11126 "TARGET_32BIT && (reload_in_progress || reload_completed)"
11127 "*
11128 {
11129 arm_output_multireg_pop (operands, /*return_pc=*/true,
11130 /*cond=*/const_true_rtx,
11131 /*reverse=*/false,
11132 /*update=*/false);
11133 return \"\";
11134 }
11135 "
9f2c2a36 11136 [(set_attr "type" "load_16")
5431c9c9 11137 (set_attr "predicable" "yes")
11138 (set (attr "length")
11139 (symbol_ref "arm_attr_length_pop_multi (operands, /*return_pc=*/true,
11140 /*write_back_p=*/false)"))]
426be8c5 11141)
11142
11143;; Load into PC and return
11144(define_insn "*ldr_with_return"
11145 [(return)
11146 (set (reg:SI PC_REGNUM)
11147 (mem:SI (post_inc:SI (match_operand:SI 0 "s_register_operand" "+rk"))))]
11148 "TARGET_32BIT && (reload_in_progress || reload_completed)"
11149 "ldr%?\t%|pc, [%0], #4"
9f2c2a36 11150 [(set_attr "type" "load_4")
426be8c5 11151 (set_attr "predicable" "yes")]
11152)
1a0b0f12 11153;; Pop for floating point registers (as used in epilogue RTL)
11154(define_insn "*vfp_pop_multiple_with_writeback"
11155 [(match_parallel 0 "pop_multiple_fp"
11156 [(set (match_operand:SI 1 "s_register_operand" "+rk")
11157 (plus:SI (match_dup 1)
809003b3 11158 (match_operand:SI 2 "const_int_I_operand" "I")))
2f2163a4 11159 (set (match_operand:DF 3 "vfp_hard_register_operand" "")
1a0b0f12 11160 (mem:DF (match_dup 1)))])]
d7216193 11161 "TARGET_32BIT && TARGET_HARD_FLOAT"
1a0b0f12 11162 "*
11163 {
11164 int num_regs = XVECLEN (operands[0], 0);
11165 char pattern[100];
11166 rtx op_list[2];
b34d8dac 11167 strcpy (pattern, \"vldm\\t\");
1a0b0f12 11168 strcat (pattern, reg_names[REGNO (SET_DEST (XVECEXP (operands[0], 0, 0)))]);
11169 strcat (pattern, \"!, {\");
11170 op_list[0] = XEXP (XVECEXP (operands[0], 0, 1), 0);
11171 strcat (pattern, \"%P0\");
11172 if ((num_regs - 1) > 1)
11173 {
11174 strcat (pattern, \"-%P1\");
11175 op_list [1] = XEXP (XVECEXP (operands[0], 0, num_regs - 1), 0);
11176 }
11177
11178 strcat (pattern, \"}\");
11179 output_asm_insn (pattern, op_list);
11180 return \"\";
11181 }
11182 "
9f2c2a36 11183 [(set_attr "type" "load_16")
1a0b0f12 11184 (set_attr "conds" "unconditional")
11185 (set_attr "predicable" "no")]
11186)
11187
f7fbdd4a 11188;; Special patterns for dealing with the constant pool
11189
cffb2a26 11190(define_insn "align_4"
e1159bbe 11191 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
cffb2a26 11192 "TARGET_EITHER"
f7fbdd4a 11193 "*
cffb2a26 11194 assemble_align (32);
f7fbdd4a 11195 return \"\";
cffb2a26 11196 "
1b7da4ac 11197 [(set_attr "type" "no_insn")]
cffb2a26 11198)
f7fbdd4a 11199
755eb2b4 11200(define_insn "align_8"
11201 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
f9273c43 11202 "TARGET_EITHER"
755eb2b4 11203 "*
11204 assemble_align (64);
11205 return \"\";
11206 "
1b7da4ac 11207 [(set_attr "type" "no_insn")]
755eb2b4 11208)
11209
cffb2a26 11210(define_insn "consttable_end"
e1159bbe 11211 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
cffb2a26 11212 "TARGET_EITHER"
f7fbdd4a 11213 "*
cffb2a26 11214 making_const_table = FALSE;
f7fbdd4a 11215 return \"\";
cffb2a26 11216 "
1b7da4ac 11217 [(set_attr "type" "no_insn")]
cffb2a26 11218)
f7fbdd4a 11219
0e207eb8 11220(define_insn "consttable_1"
11221 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
11222 "TARGET_EITHER"
11223 "*
11224 making_const_table = TRUE;
11225 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
11226 assemble_zeros (3);
11227 return \"\";
11228 "
11229 [(set_attr "length" "4")
11230 (set_attr "type" "no_insn")]
11231)
11232
11233(define_insn "consttable_2"
11234 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
11235 "TARGET_EITHER"
11236 "*
11237 {
11238 rtx x = operands[0];
11239 making_const_table = TRUE;
11240 switch (GET_MODE_CLASS (GET_MODE (x)))
11241 {
11242 case MODE_FLOAT:
11243 arm_emit_fp16_const (x);
11244 break;
11245 default:
11246 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
11247 assemble_zeros (2);
11248 break;
11249 }
11250 return \"\";
11251 }"
11252 [(set_attr "length" "4")
11253 (set_attr "type" "no_insn")]
11254)
11255
cffb2a26 11256(define_insn "consttable_4"
e1159bbe 11257 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
cffb2a26 11258 "TARGET_EITHER"
11259 "*
11260 {
9b8516be 11261 rtx x = operands[0];
cffb2a26 11262 making_const_table = TRUE;
0f97e0f5 11263 scalar_float_mode float_mode;
11264 if (is_a <scalar_float_mode> (GET_MODE (x), &float_mode))
11265 assemble_real (*CONST_DOUBLE_REAL_VALUE (x), float_mode, BITS_PER_WORD);
11266 else
cffb2a26 11267 {
7b04c5d5 11268 /* XXX: Sometimes gcc does something really dumb and ends up with
11269 a HIGH in a constant pool entry, usually because it's trying to
11270 load into a VFP register. We know this will always be used in
11271 combination with a LO_SUM which ignores the high bits, so just
11272 strip off the HIGH. */
11273 if (GET_CODE (x) == HIGH)
11274 x = XEXP (x, 0);
9b8516be 11275 assemble_integer (x, 4, BITS_PER_WORD, 1);
11276 mark_symbol_refs_as_used (x);
cffb2a26 11277 }
11278 return \"\";
11279 }"
1b7da4ac 11280 [(set_attr "length" "4")
11281 (set_attr "type" "no_insn")]
cffb2a26 11282)
11283
11284(define_insn "consttable_8"
e1159bbe 11285 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
cffb2a26 11286 "TARGET_EITHER"
11287 "*
11288 {
11289 making_const_table = TRUE;
0f97e0f5 11290 scalar_float_mode float_mode;
11291 if (is_a <scalar_float_mode> (GET_MODE (operands[0]), &float_mode))
11292 assemble_real (*CONST_DOUBLE_REAL_VALUE (operands[0]),
11293 float_mode, BITS_PER_WORD);
11294 else
11295 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
cffb2a26 11296 return \"\";
11297 }"
1b7da4ac 11298 [(set_attr "length" "8")
11299 (set_attr "type" "no_insn")]
cffb2a26 11300)
11301
d98a3884 11302(define_insn "consttable_16"
11303 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_16)]
11304 "TARGET_EITHER"
11305 "*
11306 {
11307 making_const_table = TRUE;
0f97e0f5 11308 scalar_float_mode float_mode;
11309 if (is_a <scalar_float_mode> (GET_MODE (operands[0]), &float_mode))
11310 assemble_real (*CONST_DOUBLE_REAL_VALUE (operands[0]),
11311 float_mode, BITS_PER_WORD);
11312 else
11313 assemble_integer (operands[0], 16, BITS_PER_WORD, 1);
d98a3884 11314 return \"\";
11315 }"
1b7da4ac 11316 [(set_attr "length" "16")
11317 (set_attr "type" "no_insn")]
d98a3884 11318)
11319
331beb1a 11320;; V5 Instructions,
11321
8f4be2be 11322(define_insn "clzsi2"
11323 [(set (match_operand:SI 0 "s_register_operand" "=r")
11324 (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 11325 "TARGET_32BIT && arm_arch5"
ee7cbe0e 11326 "clz%?\\t%0, %1"
bcaec148 11327 [(set_attr "predicable" "yes")
4a510717 11328 (set_attr "predicable_short_it" "no")
bebe9bbb 11329 (set_attr "type" "clz")])
331beb1a 11330
099ad98b 11331(define_insn "rbitsi2"
11332 [(set (match_operand:SI 0 "s_register_operand" "=r")
11333 (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")] UNSPEC_RBIT))]
11334 "TARGET_32BIT && arm_arch_thumb2"
11335 "rbit%?\\t%0, %1"
11336 [(set_attr "predicable" "yes")
4a510717 11337 (set_attr "predicable_short_it" "no")
bebe9bbb 11338 (set_attr "type" "clz")])
099ad98b 11339
99ffa689 11340;; Keep this as a CTZ expression until after reload and then split
11341;; into RBIT + CLZ. Since RBIT is represented as an UNSPEC it is unlikely
11342;; to fold with any other expression.
11343
11344(define_insn_and_split "ctzsi2"
11345 [(set (match_operand:SI 0 "s_register_operand" "=r")
11346 (ctz:SI (match_operand:SI 1 "s_register_operand" "r")))]
099ad98b 11347 "TARGET_32BIT && arm_arch_thumb2"
99ffa689 11348 "#"
11349 "&& reload_completed"
11350 [(const_int 0)]
099ad98b 11351 "
99ffa689 11352 emit_insn (gen_rbitsi2 (operands[0], operands[1]));
11353 emit_insn (gen_clzsi2 (operands[0], operands[0]));
11354 DONE;
11355")
099ad98b 11356
e1159bbe 11357;; V5E instructions.
331beb1a 11358
11359(define_insn "prefetch"
f4e79814 11360 [(prefetch (match_operand:SI 0 "address_operand" "p")
11361 (match_operand:SI 1 "" "")
11362 (match_operand:SI 2 "" ""))]
25f905c2 11363 "TARGET_32BIT && arm_arch5e"
1b7da4ac 11364 "pld\\t%a0"
9f2c2a36 11365 [(set_attr "type" "load_4")]
1b7da4ac 11366)
331beb1a 11367
0d66636f 11368;; General predication pattern
11369
11370(define_cond_exec
11371 [(match_operator 0 "arm_comparison_operator"
11372 [(match_operand 1 "cc_register" "")
11373 (const_int 0)])]
580f4c48 11374 "TARGET_32BIT
11375 && (!TARGET_NO_VOLATILE_CE || !volatile_refs_p (PATTERN (insn)))"
0d66636f 11376 ""
c7a58118 11377[(set_attr "predicated" "yes")]
0d66636f 11378)
11379
fb94f18b 11380(define_insn "force_register_use"
11381 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_REGISTER_USE)]
063a05c7 11382 ""
fb94f18b 11383 "%@ %0 needed"
1b7da4ac 11384 [(set_attr "length" "0")
11385 (set_attr "type" "no_insn")]
063a05c7 11386)
7db9af5d 11387
4c44712e 11388
11389;; Patterns for exception handling
11390
11391(define_expand "eh_return"
11392 [(use (match_operand 0 "general_operand" ""))]
11393 "TARGET_EITHER"
11394 "
11395 {
25f905c2 11396 if (TARGET_32BIT)
4c44712e 11397 emit_insn (gen_arm_eh_return (operands[0]));
11398 else
11399 emit_insn (gen_thumb_eh_return (operands[0]));
11400 DONE;
11401 }"
11402)
11403
11404;; We can't expand this before we know where the link register is stored.
11405(define_insn_and_split "arm_eh_return"
11406 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
11407 VUNSPEC_EH_RETURN)
11408 (clobber (match_scratch:SI 1 "=&r"))]
11409 "TARGET_ARM"
11410 "#"
11411 "&& reload_completed"
11412 [(const_int 0)]
11413 "
11414 {
11415 arm_set_return_address (operands[0], operands[1]);
11416 DONE;
11417 }"
11418)
11419
f655717d 11420\f
11421;; TLS support
11422
11423(define_insn "load_tp_hard"
11424 [(set (match_operand:SI 0 "register_operand" "=r")
11425 (unspec:SI [(const_int 0)] UNSPEC_TLS))]
11426 "TARGET_HARD_TP"
11427 "mrc%?\\tp15, 0, %0, c13, c0, 3\\t@ load_tp_hard"
1b7da4ac 11428 [(set_attr "predicable" "yes")
4b5d7374 11429 (set_attr "type" "mrs")]
f655717d 11430)
11431
11432;; Doesn't clobber R1-R3. Must use r0 for the first operand.
11433(define_insn "load_tp_soft"
11434 [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
11435 (clobber (reg:SI LR_REGNUM))
11436 (clobber (reg:SI IP_REGNUM))
11437 (clobber (reg:CC CC_REGNUM))]
11438 "TARGET_SOFT_TP"
11439 "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
1b7da4ac 11440 [(set_attr "conds" "clob")
11441 (set_attr "type" "branch")]
f655717d 11442)
11443
f41e4452 11444;; tls descriptor call
11445(define_insn "tlscall"
11446 [(set (reg:SI R0_REGNUM)
11447 (unspec:SI [(reg:SI R0_REGNUM)
11448 (match_operand:SI 0 "" "X")
11449 (match_operand 1 "" "")] UNSPEC_TLS))
11450 (clobber (reg:SI R1_REGNUM))
11451 (clobber (reg:SI LR_REGNUM))
11452 (clobber (reg:SI CC_REGNUM))]
11453 "TARGET_GNU2_TLS"
11454 {
11455 targetm.asm_out.internal_label (asm_out_file, "LPIC",
11456 INTVAL (operands[1]));
11457 return "bl\\t%c0(tlscall)";
11458 }
11459 [(set_attr "conds" "clob")
1b7da4ac 11460 (set_attr "length" "4")
11461 (set_attr "type" "branch")]
f41e4452 11462)
11463
1fe0edab 11464;; For thread pointer builtin
11465(define_expand "get_thread_pointersi"
11466 [(match_operand:SI 0 "s_register_operand" "=r")]
11467 ""
11468 "
11469 {
11470 arm_load_tp (operands[0]);
11471 DONE;
11472 }")
11473
f41e4452 11474;;
11475
aabe09ac 11476;; We only care about the lower 16 bits of the constant
11477;; being inserted into the upper 16 bits of the register.
eca5c984 11478(define_insn "*arm_movtas_ze"
417e5cc5 11479 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r,r")
eca5c984 11480 (const_int 16)
11481 (const_int 16))
11482 (match_operand:SI 1 "const_int_operand" ""))]
60a48e7d 11483 "TARGET_HAVE_MOVT"
417e5cc5 11484 "@
11485 movt%?\t%0, %L1
11486 movt\t%0, %L1"
11487 [(set_attr "arch" "32,v8mb")
11488 (set_attr "predicable" "yes")
7c36fe71 11489 (set_attr "predicable_short_it" "no")
1b7da4ac 11490 (set_attr "length" "4")
282b4c75 11491 (set_attr "type" "alu_sreg")]
eca5c984 11492)
11493
c0fc3696 11494(define_insn "*arm_rev"
a486b499 11495 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
11496 (bswap:SI (match_operand:SI 1 "s_register_operand" "l,l,r")))]
11497 "arm_arch6"
11498 "@
11499 rev\t%0, %1
11500 rev%?\t%0, %1
11501 rev%?\t%0, %1"
11502 [(set_attr "arch" "t1,t2,32")
1b7da4ac 11503 (set_attr "length" "2,2,4")
4a510717 11504 (set_attr "predicable" "no,yes,yes")
11505 (set_attr "predicable_short_it" "no")
1b7da4ac 11506 (set_attr "type" "rev")]
ff82f757 11507)
11508
11509(define_expand "arm_legacy_rev"
11510 [(set (match_operand:SI 2 "s_register_operand" "")
11511 (xor:SI (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
11512 (const_int 16))
11513 (match_dup 1)))
11514 (set (match_dup 2)
11515 (lshiftrt:SI (match_dup 2)
11516 (const_int 8)))
11517 (set (match_operand:SI 3 "s_register_operand" "")
11518 (rotatert:SI (match_dup 1)
11519 (const_int 8)))
11520 (set (match_dup 2)
11521 (and:SI (match_dup 2)
11522 (const_int -65281)))
11523 (set (match_operand:SI 0 "s_register_operand" "")
11524 (xor:SI (match_dup 3)
11525 (match_dup 2)))]
11526 "TARGET_32BIT"
11527 ""
11528)
11529
11530;; Reuse temporaries to keep register pressure down.
11531(define_expand "thumb_legacy_rev"
11532 [(set (match_operand:SI 2 "s_register_operand" "")
11533 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
11534 (const_int 24)))
11535 (set (match_operand:SI 3 "s_register_operand" "")
11536 (lshiftrt:SI (match_dup 1)
11537 (const_int 24)))
11538 (set (match_dup 3)
11539 (ior:SI (match_dup 3)
11540 (match_dup 2)))
11541 (set (match_operand:SI 4 "s_register_operand" "")
11542 (const_int 16))
11543 (set (match_operand:SI 5 "s_register_operand" "")
11544 (rotatert:SI (match_dup 1)
11545 (match_dup 4)))
11546 (set (match_dup 2)
11547 (ashift:SI (match_dup 5)
11548 (const_int 24)))
11549 (set (match_dup 5)
11550 (lshiftrt:SI (match_dup 5)
11551 (const_int 24)))
11552 (set (match_dup 5)
11553 (ior:SI (match_dup 5)
11554 (match_dup 2)))
11555 (set (match_dup 5)
11556 (rotatert:SI (match_dup 5)
11557 (match_dup 4)))
11558 (set (match_operand:SI 0 "s_register_operand" "")
11559 (ior:SI (match_dup 5)
11560 (match_dup 3)))]
11561 "TARGET_THUMB"
11562 ""
11563)
11564
62e39b06 11565;; ARM-specific expansion of signed mod by power of 2
11566;; using conditional negate.
11567;; For r0 % n where n is a power of 2 produce:
11568;; rsbs r1, r0, #0
11569;; and r0, r0, #(n - 1)
11570;; and r1, r1, #(n - 1)
11571;; rsbpl r0, r1, #0
11572
11573(define_expand "modsi3"
11574 [(match_operand:SI 0 "register_operand" "")
11575 (match_operand:SI 1 "register_operand" "")
11576 (match_operand:SI 2 "const_int_operand" "")]
11577 "TARGET_32BIT"
11578 {
11579 HOST_WIDE_INT val = INTVAL (operands[2]);
11580
11581 if (val <= 0
11582 || exact_log2 (val) <= 0)
11583 FAIL;
11584
11585 rtx mask = GEN_INT (val - 1);
11586
11587 /* In the special case of x0 % 2 we can do the even shorter:
11588 cmp r0, #0
11589 and r0, r0, #1
11590 rsblt r0, r0, #0. */
11591
11592 if (val == 2)
11593 {
11594 rtx cc_reg = arm_gen_compare_reg (LT,
11595 operands[1], const0_rtx, NULL_RTX);
11596 rtx cond = gen_rtx_LT (SImode, cc_reg, const0_rtx);
11597 rtx masked = gen_reg_rtx (SImode);
11598
11599 emit_insn (gen_andsi3 (masked, operands[1], mask));
11600 emit_move_insn (operands[0],
11601 gen_rtx_IF_THEN_ELSE (SImode, cond,
11602 gen_rtx_NEG (SImode,
11603 masked),
11604 masked));
11605 DONE;
11606 }
11607
11608 rtx neg_op = gen_reg_rtx (SImode);
11609 rtx_insn *insn = emit_insn (gen_subsi3_compare0 (neg_op, const0_rtx,
11610 operands[1]));
11611
11612 /* Extract the condition register and mode. */
11613 rtx cmp = XVECEXP (PATTERN (insn), 0, 0);
11614 rtx cc_reg = SET_DEST (cmp);
11615 rtx cond = gen_rtx_GE (SImode, cc_reg, const0_rtx);
11616
11617 emit_insn (gen_andsi3 (operands[0], operands[1], mask));
11618
11619 rtx masked_neg = gen_reg_rtx (SImode);
11620 emit_insn (gen_andsi3 (masked_neg, neg_op, mask));
11621
11622 /* We want a conditional negate here, but emitting COND_EXEC rtxes
11623 during expand does not always work. Do an IF_THEN_ELSE instead. */
11624 emit_move_insn (operands[0],
11625 gen_rtx_IF_THEN_ELSE (SImode, cond,
11626 gen_rtx_NEG (SImode, masked_neg),
11627 operands[0]));
11628
11629
11630 DONE;
11631 }
11632)
11633
ff82f757 11634(define_expand "bswapsi2"
11635 [(set (match_operand:SI 0 "s_register_operand" "=r")
11636 (bswap:SI (match_operand:SI 1 "s_register_operand" "r")))]
8d1af482 11637"TARGET_EITHER && (arm_arch6 || !optimize_size)"
ff82f757 11638"
8d1af482 11639 if (!arm_arch6)
11640 {
11641 rtx op2 = gen_reg_rtx (SImode);
11642 rtx op3 = gen_reg_rtx (SImode);
ff82f757 11643
8d1af482 11644 if (TARGET_THUMB)
11645 {
11646 rtx op4 = gen_reg_rtx (SImode);
11647 rtx op5 = gen_reg_rtx (SImode);
ff82f757 11648
8d1af482 11649 emit_insn (gen_thumb_legacy_rev (operands[0], operands[1],
11650 op2, op3, op4, op5));
11651 }
11652 else
11653 {
11654 emit_insn (gen_arm_legacy_rev (operands[0], operands[1],
11655 op2, op3));
11656 }
ff82f757 11657
8d1af482 11658 DONE;
11659 }
ff82f757 11660 "
11661)
11662
a486b499 11663;; bswap16 patterns: use revsh and rev16 instructions for the signed
11664;; and unsigned variants, respectively. For rev16, expose
11665;; byte-swapping in the lower 16 bits only.
11666(define_insn "*arm_revsh"
11667 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
11668 (sign_extend:SI (bswap:HI (match_operand:HI 1 "s_register_operand" "l,l,r"))))]
11669 "arm_arch6"
11670 "@
11671 revsh\t%0, %1
11672 revsh%?\t%0, %1
11673 revsh%?\t%0, %1"
11674 [(set_attr "arch" "t1,t2,32")
1b7da4ac 11675 (set_attr "length" "2,2,4")
11676 (set_attr "type" "rev")]
a486b499 11677)
11678
11679(define_insn "*arm_rev16"
11680 [(set (match_operand:HI 0 "s_register_operand" "=l,l,r")
11681 (bswap:HI (match_operand:HI 1 "s_register_operand" "l,l,r")))]
11682 "arm_arch6"
11683 "@
11684 rev16\t%0, %1
11685 rev16%?\t%0, %1
11686 rev16%?\t%0, %1"
11687 [(set_attr "arch" "t1,t2,32")
1b7da4ac 11688 (set_attr "length" "2,2,4")
11689 (set_attr "type" "rev")]
09f69e55 11690)
11691
11692;; There are no canonicalisation rules for the position of the lshiftrt, ashift
11693;; operations within an IOR/AND RTX, therefore we have two patterns matching
11694;; each valid permutation.
11695
11696(define_insn "arm_rev16si2"
11697 [(set (match_operand:SI 0 "register_operand" "=l,l,r")
11698 (ior:SI (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "l,l,r")
11699 (const_int 8))
11700 (match_operand:SI 3 "const_int_operand" "n,n,n"))
11701 (and:SI (lshiftrt:SI (match_dup 1)
11702 (const_int 8))
11703 (match_operand:SI 2 "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")]
11711)
11712
11713(define_insn "arm_rev16si2_alt"
11714 [(set (match_operand:SI 0 "register_operand" "=l,l,r")
11715 (ior:SI (and:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,l,r")
11716 (const_int 8))
11717 (match_operand:SI 2 "const_int_operand" "n,n,n"))
11718 (and:SI (ashift:SI (match_dup 1)
11719 (const_int 8))
11720 (match_operand:SI 3 "const_int_operand" "n,n,n"))))]
11721 "arm_arch6
11722 && aarch_rev16_shleft_mask_imm_p (operands[3], SImode)
11723 && aarch_rev16_shright_mask_imm_p (operands[2], SImode)"
11724 "rev16\\t%0, %1"
11725 [(set_attr "arch" "t1,t2,32")
11726 (set_attr "length" "2,2,4")
11727 (set_attr "type" "rev")]
a486b499 11728)
11729
11730(define_expand "bswaphi2"
11731 [(set (match_operand:HI 0 "s_register_operand" "=r")
11732 (bswap:HI (match_operand:HI 1 "s_register_operand" "r")))]
11733"arm_arch6"
11734""
11735)
11736
1653cf17 11737;; Patterns for LDRD/STRD in Thumb2 mode
11738
11739(define_insn "*thumb2_ldrd"
11740 [(set (match_operand:SI 0 "s_register_operand" "=r")
11741 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
11742 (match_operand:SI 2 "ldrd_strd_offset_operand" "Do"))))
11743 (set (match_operand:SI 3 "s_register_operand" "=r")
11744 (mem:SI (plus:SI (match_dup 1)
11745 (match_operand:SI 4 "const_int_operand" ""))))]
11746 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
1653cf17 11747 && ((INTVAL (operands[2]) + 4) == INTVAL (operands[4]))
11748 && (operands_ok_ldrd_strd (operands[0], operands[3],
11749 operands[1], INTVAL (operands[2]),
11750 false, true))"
11751 "ldrd%?\t%0, %3, [%1, %2]"
9f2c2a36 11752 [(set_attr "type" "load_8")
d952d547 11753 (set_attr "predicable" "yes")
11754 (set_attr "predicable_short_it" "no")])
1653cf17 11755
11756(define_insn "*thumb2_ldrd_base"
11757 [(set (match_operand:SI 0 "s_register_operand" "=r")
11758 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
11759 (set (match_operand:SI 2 "s_register_operand" "=r")
11760 (mem:SI (plus:SI (match_dup 1)
11761 (const_int 4))))]
11762 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
1653cf17 11763 && (operands_ok_ldrd_strd (operands[0], operands[2],
11764 operands[1], 0, false, true))"
11765 "ldrd%?\t%0, %2, [%1]"
9f2c2a36 11766 [(set_attr "type" "load_8")
d952d547 11767 (set_attr "predicable" "yes")
11768 (set_attr "predicable_short_it" "no")])
1653cf17 11769
11770(define_insn "*thumb2_ldrd_base_neg"
11771 [(set (match_operand:SI 0 "s_register_operand" "=r")
11772 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
11773 (const_int -4))))
11774 (set (match_operand:SI 2 "s_register_operand" "=r")
11775 (mem:SI (match_dup 1)))]
11776 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
1653cf17 11777 && (operands_ok_ldrd_strd (operands[0], operands[2],
11778 operands[1], -4, false, true))"
11779 "ldrd%?\t%0, %2, [%1, #-4]"
9f2c2a36 11780 [(set_attr "type" "load_8")
d952d547 11781 (set_attr "predicable" "yes")
11782 (set_attr "predicable_short_it" "no")])
1653cf17 11783
11784(define_insn "*thumb2_strd"
11785 [(set (mem:SI (plus:SI (match_operand:SI 0 "s_register_operand" "rk")
11786 (match_operand:SI 1 "ldrd_strd_offset_operand" "Do")))
11787 (match_operand:SI 2 "s_register_operand" "r"))
11788 (set (mem:SI (plus:SI (match_dup 0)
11789 (match_operand:SI 3 "const_int_operand" "")))
11790 (match_operand:SI 4 "s_register_operand" "r"))]
11791 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
1653cf17 11792 && ((INTVAL (operands[1]) + 4) == INTVAL (operands[3]))
11793 && (operands_ok_ldrd_strd (operands[2], operands[4],
11794 operands[0], INTVAL (operands[1]),
11795 false, false))"
11796 "strd%?\t%2, %4, [%0, %1]"
9f2c2a36 11797 [(set_attr "type" "store_8")
d952d547 11798 (set_attr "predicable" "yes")
11799 (set_attr "predicable_short_it" "no")])
1653cf17 11800
11801(define_insn "*thumb2_strd_base"
11802 [(set (mem:SI (match_operand:SI 0 "s_register_operand" "rk"))
11803 (match_operand:SI 1 "s_register_operand" "r"))
11804 (set (mem:SI (plus:SI (match_dup 0)
11805 (const_int 4)))
11806 (match_operand:SI 2 "s_register_operand" "r"))]
11807 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
1653cf17 11808 && (operands_ok_ldrd_strd (operands[1], operands[2],
11809 operands[0], 0, false, false))"
11810 "strd%?\t%1, %2, [%0]"
9f2c2a36 11811 [(set_attr "type" "store_8")
d952d547 11812 (set_attr "predicable" "yes")
11813 (set_attr "predicable_short_it" "no")])
1653cf17 11814
11815(define_insn "*thumb2_strd_base_neg"
11816 [(set (mem:SI (plus:SI (match_operand:SI 0 "s_register_operand" "rk")
11817 (const_int -4)))
11818 (match_operand:SI 1 "s_register_operand" "r"))
11819 (set (mem:SI (match_dup 0))
11820 (match_operand:SI 2 "s_register_operand" "r"))]
11821 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
1653cf17 11822 && (operands_ok_ldrd_strd (operands[1], operands[2],
11823 operands[0], -4, false, false))"
11824 "strd%?\t%1, %2, [%0, #-4]"
9f2c2a36 11825 [(set_attr "type" "store_8")
d952d547 11826 (set_attr "predicable" "yes")
11827 (set_attr "predicable_short_it" "no")])
1653cf17 11828
2a0c73f2 11829;; ARMv8 CRC32 instructions.
11830(define_insn "<crc_variant>"
11831 [(set (match_operand:SI 0 "s_register_operand" "=r")
11832 (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")
11833 (match_operand:<crc_mode> 2 "s_register_operand" "r")]
11834 CRC))]
11835 "TARGET_CRC32"
11836 "<crc_variant>\\t%0, %1, %2"
11837 [(set_attr "type" "crc")
11838 (set_attr "conds" "unconditional")]
11839)
1653cf17 11840
353cf59a 11841;; Load the load/store double peephole optimizations.
11842(include "ldrdstrd.md")
11843
320ea44d 11844;; Load the load/store multiple patterns
11845(include "ldmstm.md")
426be8c5 11846
11847;; Patterns in ldmstm.md don't cover more than 4 registers. This pattern covers
11848;; large lists without explicit writeback generated for APCS_FRAME epilogue.
3873efff 11849;; The operands are validated through the load_multiple_operation
11850;; match_parallel predicate rather than through constraints so enable it only
11851;; after reload.
426be8c5 11852(define_insn "*load_multiple"
11853 [(match_parallel 0 "load_multiple_operation"
11854 [(set (match_operand:SI 2 "s_register_operand" "=rk")
11855 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
11856 ])]
3873efff 11857 "TARGET_32BIT && reload_completed"
426be8c5 11858 "*
11859 {
11860 arm_output_multireg_pop (operands, /*return_pc=*/false,
11861 /*cond=*/const_true_rtx,
11862 /*reverse=*/false,
11863 /*update=*/false);
11864 return \"\";
11865 }
11866 "
11867 [(set_attr "predicable" "yes")]
11868)
11869
84450ddc 11870(define_expand "copysignsf3"
11871 [(match_operand:SF 0 "register_operand")
11872 (match_operand:SF 1 "register_operand")
11873 (match_operand:SF 2 "register_operand")]
11874 "TARGET_SOFT_FLOAT && arm_arch_thumb2"
11875 "{
11876 emit_move_insn (operands[0], operands[2]);
11877 emit_insn (gen_insv_t2 (simplify_gen_subreg (SImode, operands[0], SFmode, 0),
11878 GEN_INT (31), GEN_INT (0),
11879 simplify_gen_subreg (SImode, operands[1], SFmode, 0)));
11880 DONE;
11881 }"
11882)
11883
11884(define_expand "copysigndf3"
11885 [(match_operand:DF 0 "register_operand")
11886 (match_operand:DF 1 "register_operand")
11887 (match_operand:DF 2 "register_operand")]
11888 "TARGET_SOFT_FLOAT && arm_arch_thumb2"
11889 "{
11890 rtx op0_low = gen_lowpart (SImode, operands[0]);
11891 rtx op0_high = gen_highpart (SImode, operands[0]);
11892 rtx op1_low = gen_lowpart (SImode, operands[1]);
11893 rtx op1_high = gen_highpart (SImode, operands[1]);
11894 rtx op2_high = gen_highpart (SImode, operands[2]);
11895
11896 rtx scratch1 = gen_reg_rtx (SImode);
11897 rtx scratch2 = gen_reg_rtx (SImode);
11898 emit_move_insn (scratch1, op2_high);
11899 emit_move_insn (scratch2, op1_high);
11900
d1f9b275 11901 emit_insn(gen_rtx_SET(scratch1,
84450ddc 11902 gen_rtx_LSHIFTRT (SImode, op2_high, GEN_INT(31))));
11903 emit_insn(gen_insv_t2(scratch2, GEN_INT(1), GEN_INT(31), scratch1));
11904 emit_move_insn (op0_low, op1_low);
11905 emit_move_insn (op0_high, scratch2);
11906
11907 DONE;
11908 }"
11909)
11910
115857ef 11911;; movmisalign patterns for HImode and SImode.
11912(define_expand "movmisalign<mode>"
11913 [(match_operand:HSI 0 "general_operand")
11914 (match_operand:HSI 1 "general_operand")]
11915 "unaligned_access"
11916{
11917 /* This pattern is not permitted to fail during expansion: if both arguments
11918 are non-registers (e.g. memory := constant), force operand 1 into a
11919 register. */
11920 rtx (* gen_unaligned_load)(rtx, rtx);
11921 rtx tmp_dest = operands[0];
11922 if (!s_register_operand (operands[0], <MODE>mode)
11923 && !s_register_operand (operands[1], <MODE>mode))
11924 operands[1] = force_reg (<MODE>mode, operands[1]);
11925
11926 if (<MODE>mode == HImode)
11927 {
11928 gen_unaligned_load = gen_unaligned_loadhiu;
11929 tmp_dest = gen_reg_rtx (SImode);
11930 }
11931 else
11932 gen_unaligned_load = gen_unaligned_loadsi;
11933
11934 if (MEM_P (operands[1]))
11935 {
11936 emit_insn (gen_unaligned_load (tmp_dest, operands[1]));
11937 if (<MODE>mode == HImode)
11938 emit_move_insn (operands[0], gen_lowpart (HImode, tmp_dest));
11939 }
11940 else
11941 emit_insn (gen_unaligned_store<mode> (operands[0], operands[1]));
11942
11943 DONE;
11944})
11945
1be6395a 11946(define_insn "<cdp>"
11947 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "n")
11948 (match_operand:SI 1 "immediate_operand" "n")
11949 (match_operand:SI 2 "immediate_operand" "n")
11950 (match_operand:SI 3 "immediate_operand" "n")
11951 (match_operand:SI 4 "immediate_operand" "n")
11952 (match_operand:SI 5 "immediate_operand" "n")] CDPI)]
11953 "arm_coproc_builtin_available (VUNSPEC_<CDP>)"
11954{
11955 arm_const_bounds (operands[0], 0, 16);
11956 arm_const_bounds (operands[1], 0, 16);
11957 arm_const_bounds (operands[2], 0, (1 << 5));
11958 arm_const_bounds (operands[3], 0, (1 << 5));
11959 arm_const_bounds (operands[4], 0, (1 << 5));
11960 arm_const_bounds (operands[5], 0, 8);
11961 return "<cdp>\\tp%c0, %1, CR%c2, CR%c3, CR%c4, %5";
11962}
11963 [(set_attr "length" "4")
11964 (set_attr "type" "coproc")])
11965
638b44bd 11966(define_insn "*ldc"
11967 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "n")
11968 (match_operand:SI 1 "immediate_operand" "n")
11969 (match_operand:SI 2 "memory_operand" "Uz")] LDCI)]
11970 "arm_coproc_builtin_available (VUNSPEC_<LDC>)"
11971{
11972 arm_const_bounds (operands[0], 0, 16);
11973 arm_const_bounds (operands[1], 0, (1 << 5));
11974 return "<ldc>\\tp%c0, CR%c1, %2";
11975}
11976 [(set_attr "length" "4")
11977 (set_attr "type" "coproc")])
11978
11979(define_insn "*stc"
11980 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "n")
11981 (match_operand:SI 1 "immediate_operand" "n")
11982 (match_operand:SI 2 "memory_operand" "=Uz")] STCI)]
11983 "arm_coproc_builtin_available (VUNSPEC_<STC>)"
11984{
11985 arm_const_bounds (operands[0], 0, 16);
11986 arm_const_bounds (operands[1], 0, (1 << 5));
11987 return "<stc>\\tp%c0, CR%c1, %2";
11988}
11989 [(set_attr "length" "4")
11990 (set_attr "type" "coproc")])
11991
11992(define_expand "<ldc>"
11993 [(unspec_volatile [(match_operand:SI 0 "immediate_operand")
11994 (match_operand:SI 1 "immediate_operand")
11995 (mem:SI (match_operand:SI 2 "s_register_operand"))] LDCI)]
11996 "arm_coproc_builtin_available (VUNSPEC_<LDC>)")
11997
11998(define_expand "<stc>"
11999 [(unspec_volatile [(match_operand:SI 0 "immediate_operand")
12000 (match_operand:SI 1 "immediate_operand")
12001 (mem:SI (match_operand:SI 2 "s_register_operand"))] STCI)]
12002 "arm_coproc_builtin_available (VUNSPEC_<STC>)")
12003
415e9b1f 12004(define_insn "<mcr>"
12005 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "n")
12006 (match_operand:SI 1 "immediate_operand" "n")
12007 (match_operand:SI 2 "s_register_operand" "r")
12008 (match_operand:SI 3 "immediate_operand" "n")
12009 (match_operand:SI 4 "immediate_operand" "n")
12010 (match_operand:SI 5 "immediate_operand" "n")] MCRI)
12011 (use (match_dup 2))]
12012 "arm_coproc_builtin_available (VUNSPEC_<MCR>)"
12013{
12014 arm_const_bounds (operands[0], 0, 16);
12015 arm_const_bounds (operands[1], 0, 8);
12016 arm_const_bounds (operands[3], 0, (1 << 5));
12017 arm_const_bounds (operands[4], 0, (1 << 5));
12018 arm_const_bounds (operands[5], 0, 8);
12019 return "<mcr>\\tp%c0, %1, %2, CR%c3, CR%c4, %5";
12020}
12021 [(set_attr "length" "4")
12022 (set_attr "type" "coproc")])
12023
12024(define_insn "<mrc>"
12025 [(set (match_operand:SI 0 "s_register_operand" "=r")
6f8d7784 12026 (unspec_volatile:SI [(match_operand:SI 1 "immediate_operand" "n")
415e9b1f 12027 (match_operand:SI 2 "immediate_operand" "n")
12028 (match_operand:SI 3 "immediate_operand" "n")
12029 (match_operand:SI 4 "immediate_operand" "n")
12030 (match_operand:SI 5 "immediate_operand" "n")] MRCI))]
12031 "arm_coproc_builtin_available (VUNSPEC_<MRC>)"
12032{
12033 arm_const_bounds (operands[1], 0, 16);
12034 arm_const_bounds (operands[2], 0, 8);
12035 arm_const_bounds (operands[3], 0, (1 << 5));
12036 arm_const_bounds (operands[4], 0, (1 << 5));
12037 arm_const_bounds (operands[5], 0, 8);
12038 return "<mrc>\\tp%c1, %2, %0, CR%c3, CR%c4, %5";
12039}
12040 [(set_attr "length" "4")
12041 (set_attr "type" "coproc")])
12042
cabfd710 12043(define_insn "<mcrr>"
12044 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "n")
12045 (match_operand:SI 1 "immediate_operand" "n")
12046 (match_operand:DI 2 "s_register_operand" "r")
12047 (match_operand:SI 3 "immediate_operand" "n")] MCRRI)
12048 (use (match_dup 2))]
12049 "arm_coproc_builtin_available (VUNSPEC_<MCRR>)"
12050{
12051 arm_const_bounds (operands[0], 0, 16);
12052 arm_const_bounds (operands[1], 0, 8);
12053 arm_const_bounds (operands[3], 0, (1 << 5));
12054 return "<mcrr>\\tp%c0, %1, %Q2, %R2, CR%c3";
12055}
12056 [(set_attr "length" "4")
12057 (set_attr "type" "coproc")])
12058
12059(define_insn "<mrrc>"
12060 [(set (match_operand:DI 0 "s_register_operand" "=r")
6f8d7784 12061 (unspec_volatile:DI [(match_operand:SI 1 "immediate_operand" "n")
cabfd710 12062 (match_operand:SI 2 "immediate_operand" "n")
12063 (match_operand:SI 3 "immediate_operand" "n")] MRRCI))]
12064 "arm_coproc_builtin_available (VUNSPEC_<MRRC>)"
12065{
12066 arm_const_bounds (operands[1], 0, 16);
12067 arm_const_bounds (operands[2], 0, 8);
12068 arm_const_bounds (operands[3], 0, (1 << 5));
12069 return "<mrrc>\\tp%c1, %2, %Q0, %R0, CR%c3";
12070}
12071 [(set_attr "length" "4")
12072 (set_attr "type" "coproc")])
12073
d98a3884 12074;; Vector bits common to IWMMXT and Neon
12075(include "vec-common.md")
755eb2b4 12076;; Load the Intel Wireless Multimedia Extension patterns
12077(include "iwmmxt.md")
a2cd141b 12078;; Load the VFP co-processor patterns
12079(include "vfp.md")
bc360af8 12080;; Thumb-1 patterns
12081(include "thumb1.md")
25f905c2 12082;; Thumb-2 patterns
12083(include "thumb2.md")
d98a3884 12084;; Neon patterns
12085(include "neon.md")
e84fdf6e 12086;; Crypto patterns
12087(include "crypto.md")
06df6b17 12088;; Synchronization Primitives
12089(include "sync.md")
bbbe4599 12090;; Fixed-point patterns
12091(include "arm-fixed.md")