]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/arm/arm.md
Turn CANNOT_CHANGE_MODE_CLASS into a hook
[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
8c4e8755 4062 if (operands[2] == CONST1_RTX (SImode))
a2cd141b 4063 {
4064 emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
4065 DONE;
4066 }
ffcc986d 4067
4068 /* Ideally we should use iwmmxt here if we could know that operands[1]
4069 ends up already living in an iwmmxt register. Otherwise it's
4070 cheaper to have the alternate code being generated than moving
4071 values to iwmmxt regs and back. */
4072
ffcc986d 4073 /* Expand operation using core-registers.
4074 'FAIL' would achieve the same thing, but this is a bit smarter. */
4075 scratch1 = gen_reg_rtx (SImode);
4076 scratch2 = gen_reg_rtx (SImode);
4077 arm_emit_coreregs_64bit_shift (ASHIFT, operands[0], operands[1],
4078 operands[2], scratch1, scratch2);
4079 DONE;
a2cd141b 4080 }
a2cd141b 4081 "
4082)
4083
2837e3fb 4084(define_insn "arm_ashldi3_1bit"
50ad1bf9 4085 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 4086 (ashift:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 4087 (const_int 1)))
4088 (clobber (reg:CC CC_REGNUM))]
25f905c2 4089 "TARGET_32BIT"
2837e3fb 4090 "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
a2cd141b 4091 [(set_attr "conds" "clob")
1b7da4ac 4092 (set_attr "length" "8")
4093 (set_attr "type" "multiple")]
a2cd141b 4094)
4095
87b22bf7 4096(define_expand "ashlsi3"
cffb2a26 4097 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 4098 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
4099 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 4100 "TARGET_EITHER"
87b22bf7 4101 "
0438d37f 4102 if (CONST_INT_P (operands[2])
8c4e8755 4103 && (UINTVAL (operands[2])) > 31)
87b22bf7 4104 {
4105 emit_insn (gen_movsi (operands[0], const0_rtx));
4106 DONE;
4107 }
cffb2a26 4108 "
4109)
4110
a2cd141b 4111(define_expand "ashrdi3"
4112 [(set (match_operand:DI 0 "s_register_operand" "")
4113 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
4114 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 4115 "TARGET_32BIT"
a2cd141b 4116 "
aa06c51c 4117 if (TARGET_NEON)
4118 {
4119 /* Delay the decision whether to use NEON or core-regs until
4120 register allocation. */
4121 emit_insn (gen_ashrdi3_neon (operands[0], operands[1], operands[2]));
4122 DONE;
4123 }
4124
b805622c 4125 if (!CONST_INT_P (operands[2]) && TARGET_REALLY_IWMMXT)
ffcc986d 4126 ; /* No special preparation statements; expand pattern as above. */
4127 else
a2cd141b 4128 {
ffcc986d 4129 rtx scratch1, scratch2;
4130
8c4e8755 4131 if (operands[2] == CONST1_RTX (SImode))
a2cd141b 4132 {
4133 emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
4134 DONE;
4135 }
ffcc986d 4136
4137 /* Ideally we should use iwmmxt here if we could know that operands[1]
4138 ends up already living in an iwmmxt register. Otherwise it's
4139 cheaper to have the alternate code being generated than moving
4140 values to iwmmxt regs and back. */
4141
ffcc986d 4142 /* Expand operation using core-registers.
4143 'FAIL' would achieve the same thing, but this is a bit smarter. */
4144 scratch1 = gen_reg_rtx (SImode);
4145 scratch2 = gen_reg_rtx (SImode);
4146 arm_emit_coreregs_64bit_shift (ASHIFTRT, operands[0], operands[1],
4147 operands[2], scratch1, scratch2);
4148 DONE;
a2cd141b 4149 }
a2cd141b 4150 "
4151)
4152
2837e3fb 4153(define_insn "arm_ashrdi3_1bit"
50ad1bf9 4154 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 4155 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 4156 (const_int 1)))
4157 (clobber (reg:CC CC_REGNUM))]
25f905c2 4158 "TARGET_32BIT"
2837e3fb 4159 "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
a2cd141b 4160 [(set_attr "conds" "clob")
1b7da4ac 4161 (set_attr "length" "8")
4162 (set_attr "type" "multiple")]
a2cd141b 4163)
4164
87b22bf7 4165(define_expand "ashrsi3"
cffb2a26 4166 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 4167 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
4168 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 4169 "TARGET_EITHER"
87b22bf7 4170 "
0438d37f 4171 if (CONST_INT_P (operands[2])
8c4e8755 4172 && UINTVAL (operands[2]) > 31)
87b22bf7 4173 operands[2] = GEN_INT (31);
cffb2a26 4174 "
4175)
4176
a2cd141b 4177(define_expand "lshrdi3"
4178 [(set (match_operand:DI 0 "s_register_operand" "")
4179 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
4180 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 4181 "TARGET_32BIT"
a2cd141b 4182 "
aa06c51c 4183 if (TARGET_NEON)
4184 {
4185 /* Delay the decision whether to use NEON or core-regs until
4186 register allocation. */
4187 emit_insn (gen_lshrdi3_neon (operands[0], operands[1], operands[2]));
4188 DONE;
4189 }
4190
b805622c 4191 if (!CONST_INT_P (operands[2]) && TARGET_REALLY_IWMMXT)
ffcc986d 4192 ; /* No special preparation statements; expand pattern as above. */
4193 else
a2cd141b 4194 {
ffcc986d 4195 rtx scratch1, scratch2;
4196
8c4e8755 4197 if (operands[2] == CONST1_RTX (SImode))
a2cd141b 4198 {
4199 emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
4200 DONE;
4201 }
ffcc986d 4202
4203 /* Ideally we should use iwmmxt here if we could know that operands[1]
4204 ends up already living in an iwmmxt register. Otherwise it's
4205 cheaper to have the alternate code being generated than moving
4206 values to iwmmxt regs and back. */
4207
ffcc986d 4208 /* Expand operation using core-registers.
4209 'FAIL' would achieve the same thing, but this is a bit smarter. */
4210 scratch1 = gen_reg_rtx (SImode);
4211 scratch2 = gen_reg_rtx (SImode);
4212 arm_emit_coreregs_64bit_shift (LSHIFTRT, operands[0], operands[1],
4213 operands[2], scratch1, scratch2);
4214 DONE;
a2cd141b 4215 }
a2cd141b 4216 "
4217)
4218
2837e3fb 4219(define_insn "arm_lshrdi3_1bit"
50ad1bf9 4220 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 4221 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 4222 (const_int 1)))
4223 (clobber (reg:CC CC_REGNUM))]
25f905c2 4224 "TARGET_32BIT"
2837e3fb 4225 "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
a2cd141b 4226 [(set_attr "conds" "clob")
1b7da4ac 4227 (set_attr "length" "8")
4228 (set_attr "type" "multiple")]
a2cd141b 4229)
4230
87b22bf7 4231(define_expand "lshrsi3"
cffb2a26 4232 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 4233 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
4234 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 4235 "TARGET_EITHER"
87b22bf7 4236 "
0438d37f 4237 if (CONST_INT_P (operands[2])
8c4e8755 4238 && (UINTVAL (operands[2])) > 31)
87b22bf7 4239 {
4240 emit_insn (gen_movsi (operands[0], const0_rtx));
4241 DONE;
4242 }
cffb2a26 4243 "
4244)
4245
87b22bf7 4246(define_expand "rotlsi3"
cffb2a26 4247 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 4248 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
4249 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 4250 "TARGET_32BIT"
87b22bf7 4251 "
0438d37f 4252 if (CONST_INT_P (operands[2]))
87b22bf7 4253 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
4254 else
b11cae9e 4255 {
87b22bf7 4256 rtx reg = gen_reg_rtx (SImode);
4257 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
4258 operands[2] = reg;
b11cae9e 4259 }
cffb2a26 4260 "
4261)
9c08d1fa 4262
87b22bf7 4263(define_expand "rotrsi3"
cffb2a26 4264 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 4265 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
4266 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 4267 "TARGET_EITHER"
87b22bf7 4268 "
25f905c2 4269 if (TARGET_32BIT)
cffb2a26 4270 {
0438d37f 4271 if (CONST_INT_P (operands[2])
8c4e8755 4272 && UINTVAL (operands[2]) > 31)
cffb2a26 4273 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
4274 }
25f905c2 4275 else /* TARGET_THUMB1 */
cffb2a26 4276 {
0438d37f 4277 if (CONST_INT_P (operands [2]))
cffb2a26 4278 operands [2] = force_reg (SImode, operands[2]);
4279 }
4280 "
4281)
87b22bf7 4282
cffb2a26 4283(define_insn "*arm_shiftsi3"
88c29385 4284 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r,r")
cffb2a26 4285 (match_operator:SI 3 "shift_operator"
88c29385 4286 [(match_operand:SI 1 "s_register_operand" "0,l,r,r")
4287 (match_operand:SI 2 "reg_or_int_operand" "l,M,M,r")]))]
25f905c2 4288 "TARGET_32BIT"
4289 "* return arm_output_shift(operands, 0);"
344495ea 4290 [(set_attr "predicable" "yes")
88c29385 4291 (set_attr "arch" "t2,t2,*,*")
4292 (set_attr "predicable_short_it" "yes,yes,no,no")
7c36fe71 4293 (set_attr "length" "4")
331beb1a 4294 (set_attr "shift" "1")
88c29385 4295 (set_attr "type" "alu_shift_reg,alu_shift_imm,alu_shift_imm,alu_shift_reg")]
6c4c2133 4296)
87b22bf7 4297
f7fbdd4a 4298(define_insn "*shiftsi3_compare0"
bd5b4116 4299 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 4300 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
6b6abc9c 4301 [(match_operand:SI 1 "s_register_operand" "r,r")
4302 (match_operand:SI 2 "arm_rhs_operand" "M,r")])
9c08d1fa 4303 (const_int 0)))
6b6abc9c 4304 (set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 4305 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
25f905c2 4306 "TARGET_32BIT"
4307 "* return arm_output_shift(operands, 1);"
344495ea 4308 [(set_attr "conds" "set")
331beb1a 4309 (set_attr "shift" "1")
d82e788e 4310 (set_attr "type" "alus_shift_imm,alus_shift_reg")]
0d66636f 4311)
9c08d1fa 4312
f7fbdd4a 4313(define_insn "*shiftsi3_compare0_scratch"
bd5b4116 4314 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 4315 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
6b6abc9c 4316 [(match_operand:SI 1 "s_register_operand" "r,r")
4317 (match_operand:SI 2 "arm_rhs_operand" "M,r")])
9c08d1fa 4318 (const_int 0)))
6b6abc9c 4319 (clobber (match_scratch:SI 0 "=r,r"))]
25f905c2 4320 "TARGET_32BIT"
4321 "* return arm_output_shift(operands, 1);"
344495ea 4322 [(set_attr "conds" "set")
6b6abc9c 4323 (set_attr "shift" "1")
d82e788e 4324 (set_attr "type" "shift_imm,shift_reg")]
0d66636f 4325)
9c08d1fa 4326
d5d4dc8d 4327(define_insn "*not_shiftsi"
4328 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 4329 (not:SI (match_operator:SI 3 "shift_operator"
d5d4dc8d 4330 [(match_operand:SI 1 "s_register_operand" "r,r")
4331 (match_operand:SI 2 "shift_amount_operand" "M,rM")])))]
4332 "TARGET_32BIT"
6c4c2133 4333 "mvn%?\\t%0, %1%S3"
344495ea 4334 [(set_attr "predicable" "yes")
d952d547 4335 (set_attr "predicable_short_it" "no")
331beb1a 4336 (set_attr "shift" "1")
d5d4dc8d 4337 (set_attr "arch" "32,a")
1aed5204 4338 (set_attr "type" "mvn_shift,mvn_shift_reg")])
9c08d1fa 4339
d5d4dc8d 4340(define_insn "*not_shiftsi_compare0"
bd5b4116 4341 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 4342 (compare:CC_NOOV
4343 (not:SI (match_operator:SI 3 "shift_operator"
4344 [(match_operand:SI 1 "s_register_operand" "r,r")
4345 (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
4346 (const_int 0)))
4347 (set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 4348 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
d5d4dc8d 4349 "TARGET_32BIT"
3ef90e77 4350 "mvns%?\\t%0, %1%S3"
344495ea 4351 [(set_attr "conds" "set")
331beb1a 4352 (set_attr "shift" "1")
d5d4dc8d 4353 (set_attr "arch" "32,a")
1aed5204 4354 (set_attr "type" "mvn_shift,mvn_shift_reg")])
9c08d1fa 4355
d5d4dc8d 4356(define_insn "*not_shiftsi_compare0_scratch"
bd5b4116 4357 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 4358 (compare:CC_NOOV
4359 (not:SI (match_operator:SI 3 "shift_operator"
4360 [(match_operand:SI 1 "s_register_operand" "r,r")
4361 (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
4362 (const_int 0)))
4363 (clobber (match_scratch:SI 0 "=r,r"))]
4364 "TARGET_32BIT"
3ef90e77 4365 "mvns%?\\t%0, %1%S3"
344495ea 4366 [(set_attr "conds" "set")
331beb1a 4367 (set_attr "shift" "1")
d5d4dc8d 4368 (set_attr "arch" "32,a")
1aed5204 4369 (set_attr "type" "mvn_shift,mvn_shift_reg")])
9c08d1fa 4370
cffb2a26 4371;; We don't really have extzv, but defining this using shifts helps
4372;; to reduce register pressure later on.
4373
4374(define_expand "extzv"
eb04cafb 4375 [(set (match_operand 0 "s_register_operand" "")
4376 (zero_extract (match_operand 1 "nonimmediate_operand" "")
4377 (match_operand 2 "const_int_operand" "")
4378 (match_operand 3 "const_int_operand" "")))]
8b054d5a 4379 "TARGET_THUMB1 || arm_arch_thumb2"
cffb2a26 4380 "
4381 {
4382 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
4383 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
4384
8b054d5a 4385 if (arm_arch_thumb2)
4386 {
eb04cafb 4387 HOST_WIDE_INT width = INTVAL (operands[2]);
4388 HOST_WIDE_INT bitpos = INTVAL (operands[3]);
4389
4390 if (unaligned_access && MEM_P (operands[1])
4391 && (width == 16 || width == 32) && (bitpos % BITS_PER_UNIT) == 0)
4392 {
4393 rtx base_addr;
4394
4395 if (BYTES_BIG_ENDIAN)
4396 bitpos = GET_MODE_BITSIZE (GET_MODE (operands[0])) - width
4397 - bitpos;
4398
4399 if (width == 32)
4400 {
4401 base_addr = adjust_address (operands[1], SImode,
4402 bitpos / BITS_PER_UNIT);
4403 emit_insn (gen_unaligned_loadsi (operands[0], base_addr));
4404 }
4405 else
4406 {
4407 rtx dest = operands[0];
4408 rtx tmp = gen_reg_rtx (SImode);
4409
4410 /* We may get a paradoxical subreg here. Strip it off. */
4411 if (GET_CODE (dest) == SUBREG
4412 && GET_MODE (dest) == SImode
4413 && GET_MODE (SUBREG_REG (dest)) == HImode)
4414 dest = SUBREG_REG (dest);
4415
4416 if (GET_MODE_BITSIZE (GET_MODE (dest)) != width)
4417 FAIL;
4418
4419 base_addr = adjust_address (operands[1], HImode,
4420 bitpos / BITS_PER_UNIT);
4421 emit_insn (gen_unaligned_loadhiu (tmp, base_addr));
4422 emit_move_insn (gen_lowpart (SImode, dest), tmp);
4423 }
4424 DONE;
4425 }
4426 else if (s_register_operand (operands[1], GET_MODE (operands[1])))
4427 {
4428 emit_insn (gen_extzv_t2 (operands[0], operands[1], operands[2],
4429 operands[3]));
4430 DONE;
4431 }
4432 else
4433 FAIL;
8b054d5a 4434 }
eb04cafb 4435
4436 if (!s_register_operand (operands[1], GET_MODE (operands[1])))
4437 FAIL;
8b054d5a 4438
cffb2a26 4439 operands[3] = GEN_INT (rshift);
4440
4441 if (lshift == 0)
4442 {
4443 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
4444 DONE;
4445 }
4446
eb04cafb 4447 emit_insn (gen_extzv_t1 (operands[0], operands[1], GEN_INT (lshift),
4448 operands[3], gen_reg_rtx (SImode)));
4449 DONE;
215b30b3 4450 }"
cffb2a26 4451)
4452
eb04cafb 4453;; Helper for extzv, for the Thumb-1 register-shifts case.
4454
4455(define_expand "extzv_t1"
4456 [(set (match_operand:SI 4 "s_register_operand" "")
4457 (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "")
4458 (match_operand:SI 2 "const_int_operand" "")))
4459 (set (match_operand:SI 0 "s_register_operand" "")
4460 (lshiftrt:SI (match_dup 4)
4461 (match_operand:SI 3 "const_int_operand" "")))]
4462 "TARGET_THUMB1"
4463 "")
4464
4465(define_expand "extv"
4466 [(set (match_operand 0 "s_register_operand" "")
4467 (sign_extract (match_operand 1 "nonimmediate_operand" "")
4468 (match_operand 2 "const_int_operand" "")
4469 (match_operand 3 "const_int_operand" "")))]
4470 "arm_arch_thumb2"
4471{
4472 HOST_WIDE_INT width = INTVAL (operands[2]);
4473 HOST_WIDE_INT bitpos = INTVAL (operands[3]);
4474
4475 if (unaligned_access && MEM_P (operands[1]) && (width == 16 || width == 32)
4476 && (bitpos % BITS_PER_UNIT) == 0)
4477 {
4478 rtx base_addr;
4479
4480 if (BYTES_BIG_ENDIAN)
4481 bitpos = GET_MODE_BITSIZE (GET_MODE (operands[0])) - width - bitpos;
4482
4483 if (width == 32)
4484 {
4485 base_addr = adjust_address (operands[1], SImode,
4486 bitpos / BITS_PER_UNIT);
4487 emit_insn (gen_unaligned_loadsi (operands[0], base_addr));
4488 }
4489 else
4490 {
4491 rtx dest = operands[0];
4492 rtx tmp = gen_reg_rtx (SImode);
4493
4494 /* We may get a paradoxical subreg here. Strip it off. */
4495 if (GET_CODE (dest) == SUBREG
4496 && GET_MODE (dest) == SImode
4497 && GET_MODE (SUBREG_REG (dest)) == HImode)
4498 dest = SUBREG_REG (dest);
4499
4500 if (GET_MODE_BITSIZE (GET_MODE (dest)) != width)
4501 FAIL;
4502
4503 base_addr = adjust_address (operands[1], HImode,
4504 bitpos / BITS_PER_UNIT);
4505 emit_insn (gen_unaligned_loadhis (tmp, base_addr));
4506 emit_move_insn (gen_lowpart (SImode, dest), tmp);
4507 }
4508
4509 DONE;
4510 }
4511 else if (!s_register_operand (operands[1], GET_MODE (operands[1])))
4512 FAIL;
4513 else if (GET_MODE (operands[0]) == SImode
4514 && GET_MODE (operands[1]) == SImode)
4515 {
4516 emit_insn (gen_extv_regsi (operands[0], operands[1], operands[2],
4517 operands[3]));
4518 DONE;
4519 }
4520
4521 FAIL;
4522})
4523
4524; Helper to expand register forms of extv with the proper modes.
4525
4526(define_expand "extv_regsi"
4527 [(set (match_operand:SI 0 "s_register_operand" "")
4528 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
4529 (match_operand 2 "const_int_operand" "")
4530 (match_operand 3 "const_int_operand" "")))]
4531 ""
4532{
4533})
4534
4535; ARMv6+ unaligned load/store instructions (used for packed structure accesses).
4536
4537(define_insn "unaligned_loadsi"
4538 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4539 (unspec:SI [(match_operand:SI 1 "memory_operand" "Uw,m")]
4540 UNSPEC_UNALIGNED_LOAD))]
8fe38eb2 4541 "unaligned_access"
eb04cafb 4542 "ldr%?\t%0, %1\t@ unaligned"
4543 [(set_attr "arch" "t2,any")
4544 (set_attr "length" "2,4")
4545 (set_attr "predicable" "yes")
d952d547 4546 (set_attr "predicable_short_it" "yes,no")
9f2c2a36 4547 (set_attr "type" "load_4")])
eb04cafb 4548
4549(define_insn "unaligned_loadhis"
4550 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4551 (sign_extend:SI
e3f4ccee 4552 (unspec:HI [(match_operand:HI 1 "memory_operand" "Uw,Uh")]
eb04cafb 4553 UNSPEC_UNALIGNED_LOAD)))]
8fe38eb2 4554 "unaligned_access"
3ef90e77 4555 "ldrsh%?\t%0, %1\t@ unaligned"
eb04cafb 4556 [(set_attr "arch" "t2,any")
4557 (set_attr "length" "2,4")
4558 (set_attr "predicable" "yes")
d952d547 4559 (set_attr "predicable_short_it" "yes,no")
eb04cafb 4560 (set_attr "type" "load_byte")])
4561
4562(define_insn "unaligned_loadhiu"
4563 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4564 (zero_extend:SI
4565 (unspec:HI [(match_operand:HI 1 "memory_operand" "Uw,m")]
4566 UNSPEC_UNALIGNED_LOAD)))]
8fe38eb2 4567 "unaligned_access"
3ef90e77 4568 "ldrh%?\t%0, %1\t@ unaligned"
eb04cafb 4569 [(set_attr "arch" "t2,any")
4570 (set_attr "length" "2,4")
4571 (set_attr "predicable" "yes")
d952d547 4572 (set_attr "predicable_short_it" "yes,no")
eb04cafb 4573 (set_attr "type" "load_byte")])
4574
4575(define_insn "unaligned_storesi"
4576 [(set (match_operand:SI 0 "memory_operand" "=Uw,m")
4577 (unspec:SI [(match_operand:SI 1 "s_register_operand" "l,r")]
4578 UNSPEC_UNALIGNED_STORE))]
8fe38eb2 4579 "unaligned_access"
eb04cafb 4580 "str%?\t%1, %0\t@ unaligned"
4581 [(set_attr "arch" "t2,any")
4582 (set_attr "length" "2,4")
4583 (set_attr "predicable" "yes")
d952d547 4584 (set_attr "predicable_short_it" "yes,no")
9f2c2a36 4585 (set_attr "type" "store_4")])
eb04cafb 4586
4587(define_insn "unaligned_storehi"
4588 [(set (match_operand:HI 0 "memory_operand" "=Uw,m")
4589 (unspec:HI [(match_operand:HI 1 "s_register_operand" "l,r")]
4590 UNSPEC_UNALIGNED_STORE))]
8fe38eb2 4591 "unaligned_access"
3ef90e77 4592 "strh%?\t%1, %0\t@ unaligned"
eb04cafb 4593 [(set_attr "arch" "t2,any")
4594 (set_attr "length" "2,4")
4595 (set_attr "predicable" "yes")
d952d547 4596 (set_attr "predicable_short_it" "yes,no")
9f2c2a36 4597 (set_attr "type" "store_4")])
eb04cafb 4598
ae51a965 4599
eb04cafb 4600(define_insn "*extv_reg"
8b054d5a 4601 [(set (match_operand:SI 0 "s_register_operand" "=r")
4602 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
13051f13 4603 (match_operand:SI 2 "const_int_operand" "n")
4604 (match_operand:SI 3 "const_int_operand" "n")))]
4605 "arm_arch_thumb2
4606 && IN_RANGE (INTVAL (operands[3]), 0, 31)
4607 && IN_RANGE (INTVAL (operands[2]), 1, 32 - INTVAL (operands[3]))"
8b054d5a 4608 "sbfx%?\t%0, %1, %3, %2"
4609 [(set_attr "length" "4")
d952d547 4610 (set_attr "predicable" "yes")
d82e788e 4611 (set_attr "predicable_short_it" "no")
4612 (set_attr "type" "bfm")]
8b054d5a 4613)
4614
4615(define_insn "extzv_t2"
4616 [(set (match_operand:SI 0 "s_register_operand" "=r")
4617 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "r")
13051f13 4618 (match_operand:SI 2 "const_int_operand" "n")
4619 (match_operand:SI 3 "const_int_operand" "n")))]
4620 "arm_arch_thumb2
4621 && IN_RANGE (INTVAL (operands[3]), 0, 31)
4622 && IN_RANGE (INTVAL (operands[2]), 1, 32 - INTVAL (operands[3]))"
8b054d5a 4623 "ubfx%?\t%0, %1, %3, %2"
4624 [(set_attr "length" "4")
d952d547 4625 (set_attr "predicable" "yes")
d82e788e 4626 (set_attr "predicable_short_it" "no")
4627 (set_attr "type" "bfm")]
8b054d5a 4628)
4629
7d3cda8c 4630
4631;; Division instructions
4632(define_insn "divsi3"
8f5f2788 4633 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4634 (div:SI (match_operand:SI 1 "s_register_operand" "r,r")
4635 (match_operand:SI 2 "s_register_operand" "r,r")))]
7d3cda8c 4636 "TARGET_IDIV"
8f5f2788 4637 "@
4638 sdiv%?\t%0, %1, %2
4639 sdiv\t%0, %1, %2"
4640 [(set_attr "arch" "32,v8mb")
4641 (set_attr "predicable" "yes")
d952d547 4642 (set_attr "predicable_short_it" "no")
9da0ec36 4643 (set_attr "type" "sdiv")]
7d3cda8c 4644)
4645
4646(define_insn "udivsi3"
8f5f2788 4647 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4648 (udiv:SI (match_operand:SI 1 "s_register_operand" "r,r")
4649 (match_operand:SI 2 "s_register_operand" "r,r")))]
7d3cda8c 4650 "TARGET_IDIV"
8f5f2788 4651 "@
4652 udiv%?\t%0, %1, %2
4653 udiv\t%0, %1, %2"
4654 [(set_attr "arch" "32,v8mb")
4655 (set_attr "predicable" "yes")
d952d547 4656 (set_attr "predicable_short_it" "no")
9da0ec36 4657 (set_attr "type" "udiv")]
7d3cda8c 4658)
4659
b11cae9e 4660\f
4661;; Unary arithmetic insns
4662
f6c98a9a 4663(define_expand "negvsi3"
4664 [(match_operand:SI 0 "register_operand")
4665 (match_operand:SI 1 "register_operand")
4666 (match_operand 2 "")]
4667 "TARGET_32BIT"
4668{
4669 emit_insn (gen_subsi3_compare (operands[0], const0_rtx, operands[1]));
4670 arm_gen_unlikely_cbranch (NE, CC_Vmode, operands[2]);
4671
4672 DONE;
4673})
4674
4675(define_expand "negvdi3"
4676 [(match_operand:DI 0 "register_operand")
4677 (match_operand:DI 1 "register_operand")
4678 (match_operand 2 "")]
4679 "TARGET_ARM"
4680{
4681 emit_insn (gen_negdi2_compare (operands[0], operands[1]));
4682 arm_gen_unlikely_cbranch (NE, CC_Vmode, operands[2]);
4683
4684 DONE;
4685})
4686
4687
4688(define_insn_and_split "negdi2_compare"
4689 [(set (reg:CC CC_REGNUM)
4690 (compare:CC
4691 (const_int 0)
4692 (match_operand:DI 1 "register_operand" "0,r")))
4693 (set (match_operand:DI 0 "register_operand" "=r,&r")
4694 (minus:DI (const_int 0) (match_dup 1)))]
4695 "TARGET_ARM"
4696 "#"
4697 "&& reload_completed"
4698 [(parallel [(set (reg:CC CC_REGNUM)
4699 (compare:CC (const_int 0) (match_dup 1)))
4700 (set (match_dup 0) (minus:SI (const_int 0)
4701 (match_dup 1)))])
4702 (parallel [(set (reg:CC CC_REGNUM)
4703 (compare:CC (const_int 0) (match_dup 3)))
4704 (set (match_dup 2)
4705 (minus:SI
4706 (minus:SI (const_int 0) (match_dup 3))
4707 (ltu:SI (reg:CC_C CC_REGNUM)
4708 (const_int 0))))])]
4709 {
4710 operands[2] = gen_highpart (SImode, operands[0]);
4711 operands[0] = gen_lowpart (SImode, operands[0]);
4712 operands[3] = gen_highpart (SImode, operands[1]);
4713 operands[1] = gen_lowpart (SImode, operands[1]);
4714 }
4715 [(set_attr "conds" "set")
4716 (set_attr "length" "8")
4717 (set_attr "type" "multiple")]
4718)
4719
cffb2a26 4720(define_expand "negdi2"
4721 [(parallel
8135a42b 4722 [(set (match_operand:DI 0 "s_register_operand" "")
4723 (neg:DI (match_operand:DI 1 "s_register_operand" "")))
bd5b4116 4724 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 4725 "TARGET_EITHER"
774d2fbb 4726 {
4727 if (TARGET_NEON)
4728 {
4729 emit_insn (gen_negdi2_neon (operands[0], operands[1]));
4730 DONE;
4731 }
4732 }
cffb2a26 4733)
4734
4735;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
e5fea38e 4736;; The first alternative allows the common case of a *full* overlap.
d5bf2b53 4737(define_insn_and_split "*negdi2_insn"
458a8706 4738 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 4739 (neg:DI (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 4740 (clobber (reg:CC CC_REGNUM))]
d5bf2b53 4741 "TARGET_32BIT"
4742 "#" ; rsbs %Q0, %Q1, #0; rsc %R0, %R1, #0 (ARM)
4743 ; negs %Q0, %Q1 ; sbc %R0, %R1, %R1, lsl #1 (Thumb-2)
ba6a3b2f 4744 "&& reload_completed"
4745 [(parallel [(set (reg:CC CC_REGNUM)
4746 (compare:CC (const_int 0) (match_dup 1)))
4747 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 1)))])
4748 (set (match_dup 2) (minus:SI (minus:SI (const_int 0) (match_dup 3))
4749 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
4750 {
4751 operands[2] = gen_highpart (SImode, operands[0]);
4752 operands[0] = gen_lowpart (SImode, operands[0]);
4753 operands[3] = gen_highpart (SImode, operands[1]);
4754 operands[1] = gen_lowpart (SImode, operands[1]);
4755 }
cffb2a26 4756 [(set_attr "conds" "clob")
1b7da4ac 4757 (set_attr "length" "8")
4758 (set_attr "type" "multiple")]
cffb2a26 4759)
b11cae9e 4760
f6c98a9a 4761(define_insn "*negsi2_carryin_compare"
4762 [(set (reg:CC CC_REGNUM)
4763 (compare:CC (const_int 0)
4764 (match_operand:SI 1 "s_register_operand" "r")))
4765 (set (match_operand:SI 0 "s_register_operand" "=r")
4766 (minus:SI (minus:SI (const_int 0)
4767 (match_dup 1))
4768 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
4769 "TARGET_ARM"
4770 "rscs\\t%0, %1, #0"
4771 [(set_attr "conds" "set")
4772 (set_attr "type" "alus_imm")]
4773)
4774
cffb2a26 4775(define_expand "negsi2"
4776 [(set (match_operand:SI 0 "s_register_operand" "")
4777 (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
4778 "TARGET_EITHER"
b11cae9e 4779 ""
cffb2a26 4780)
4781
4782(define_insn "*arm_negsi2"
d952d547 4783 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4784 (neg:SI (match_operand:SI 1 "s_register_operand" "l,r")))]
25f905c2 4785 "TARGET_32BIT"
cffb2a26 4786 "rsb%?\\t%0, %1, #0"
d952d547 4787 [(set_attr "predicable" "yes")
4788 (set_attr "predicable_short_it" "yes,no")
4789 (set_attr "arch" "t2,*")
1b7da4ac 4790 (set_attr "length" "4")
112eda6f 4791 (set_attr "type" "alu_sreg")]
cffb2a26 4792)
4793
604f3a0a 4794(define_expand "negsf2"
4795 [(set (match_operand:SF 0 "s_register_operand" "")
4796 (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
d7216193 4797 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 4798 ""
4799)
4800
4801(define_expand "negdf2"
4802 [(set (match_operand:DF 0 "s_register_operand" "")
4803 (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
994606f8 4804 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
604f3a0a 4805 "")
4806
7eaf2be0 4807(define_insn_and_split "*zextendsidi_negsi"
4808 [(set (match_operand:DI 0 "s_register_operand" "=r")
4809 (zero_extend:DI (neg:SI (match_operand:SI 1 "s_register_operand" "r"))))]
4810 "TARGET_32BIT"
4811 "#"
4812 ""
4813 [(set (match_dup 2)
4814 (neg:SI (match_dup 1)))
4815 (set (match_dup 3)
4816 (const_int 0))]
4817 {
4818 operands[2] = gen_lowpart (SImode, operands[0]);
4819 operands[3] = gen_highpart (SImode, operands[0]);
4820 }
4821 [(set_attr "length" "8")
4822 (set_attr "type" "multiple")]
4823)
4824
83e2b922 4825;; Negate an extended 32-bit value.
4826(define_insn_and_split "*negdi_extendsidi"
61fa8ff2 4827 [(set (match_operand:DI 0 "s_register_operand" "=l,r")
4828 (neg:DI (sign_extend:DI
4829 (match_operand:SI 1 "s_register_operand" "l,r"))))
83e2b922 4830 (clobber (reg:CC CC_REGNUM))]
4831 "TARGET_32BIT"
61fa8ff2 4832 "#"
83e2b922 4833 "&& reload_completed"
4834 [(const_int 0)]
4835 {
61fa8ff2 4836 rtx low = gen_lowpart (SImode, operands[0]);
4837 rtx high = gen_highpart (SImode, operands[0]);
4838
4839 if (reg_overlap_mentioned_p (low, operands[1]))
4840 {
4841 /* Input overlaps the low word of the output. Use:
4842 asr Rhi, Rin, #31
4843 rsbs Rlo, Rin, #0
4844 rsc Rhi, Rhi, #0 (thumb2: sbc Rhi, Rhi, Rhi, lsl #1). */
4845 rtx cc_reg = gen_rtx_REG (CC_Cmode, CC_REGNUM);
4846
d1f9b275 4847 emit_insn (gen_rtx_SET (high,
61fa8ff2 4848 gen_rtx_ASHIFTRT (SImode, operands[1],
4849 GEN_INT (31))));
4850
4851 emit_insn (gen_subsi3_compare (low, const0_rtx, operands[1]));
4852 if (TARGET_ARM)
d1f9b275 4853 emit_insn (gen_rtx_SET (high,
61fa8ff2 4854 gen_rtx_MINUS (SImode,
4855 gen_rtx_MINUS (SImode,
4856 const0_rtx,
4857 high),
4858 gen_rtx_LTU (SImode,
4859 cc_reg,
4860 const0_rtx))));
4861 else
4862 {
4863 rtx two_x = gen_rtx_ASHIFT (SImode, high, GEN_INT (1));
d1f9b275 4864 emit_insn (gen_rtx_SET (high,
61fa8ff2 4865 gen_rtx_MINUS (SImode,
4866 gen_rtx_MINUS (SImode,
4867 high,
4868 two_x),
4869 gen_rtx_LTU (SImode,
4870 cc_reg,
4871 const0_rtx))));
4872 }
4873 }
4874 else
4875 {
4876 /* No overlap, or overlap on high word. Use:
4877 rsb Rlo, Rin, #0
4878 bic Rhi, Rlo, Rin
4879 asr Rhi, Rhi, #31
4880 Flags not needed for this sequence. */
d1f9b275 4881 emit_insn (gen_rtx_SET (low, gen_rtx_NEG (SImode, operands[1])));
4882 emit_insn (gen_rtx_SET (high,
61fa8ff2 4883 gen_rtx_AND (SImode,
4884 gen_rtx_NOT (SImode, operands[1]),
4885 low)));
d1f9b275 4886 emit_insn (gen_rtx_SET (high,
61fa8ff2 4887 gen_rtx_ASHIFTRT (SImode, high,
4888 GEN_INT (31))));
4889 }
4890 DONE;
83e2b922 4891 }
61fa8ff2 4892 [(set_attr "length" "12")
4893 (set_attr "arch" "t2,*")
1b7da4ac 4894 (set_attr "type" "multiple")]
83e2b922 4895)
4896
4897(define_insn_and_split "*negdi_zero_extendsidi"
4898 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
4899 (neg:DI (zero_extend:DI (match_operand:SI 1 "s_register_operand" "0,r"))))
4900 (clobber (reg:CC CC_REGNUM))]
4901 "TARGET_32BIT"
4902 "#" ; "rsbs\\t%Q0, %1, #0\;sbc\\t%R0,%R0,%R0"
4903 ;; Don't care what register is input to sbc,
47ae02b7 4904 ;; since we just need to propagate the carry.
83e2b922 4905 "&& reload_completed"
4906 [(parallel [(set (reg:CC CC_REGNUM)
4907 (compare:CC (const_int 0) (match_dup 1)))
4908 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 1)))])
4909 (set (match_dup 2) (minus:SI (minus:SI (match_dup 2) (match_dup 2))
4910 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
4911 {
4912 operands[2] = gen_highpart (SImode, operands[0]);
4913 operands[0] = gen_lowpart (SImode, operands[0]);
4914 }
4915 [(set_attr "conds" "clob")
1b7da4ac 4916 (set_attr "length" "8")
4917 (set_attr "type" "multiple")] ;; length in thumb is 4
83e2b922 4918)
4919
9c08d1fa 4920;; abssi2 doesn't really clobber the condition codes if a different register
4921;; is being set. To keep things simple, assume during rtl manipulations that
4922;; it does, but tell the final scan operator the truth. Similarly for
4923;; (neg (abs...))
4924
604f3a0a 4925(define_expand "abssi2"
4926 [(parallel
4927 [(set (match_operand:SI 0 "s_register_operand" "")
4928 (abs:SI (match_operand:SI 1 "s_register_operand" "")))
ba156559 4929 (clobber (match_dup 2))])]
4930 "TARGET_EITHER"
4931 "
25f905c2 4932 if (TARGET_THUMB1)
ba156559 4933 operands[2] = gen_rtx_SCRATCH (SImode);
4934 else
4935 operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
4936")
604f3a0a 4937
ba6a3b2f 4938(define_insn_and_split "*arm_abssi2"
ba156559 4939 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
9c08d1fa 4940 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
bd5b4116 4941 (clobber (reg:CC CC_REGNUM))]
cffb2a26 4942 "TARGET_ARM"
ba6a3b2f 4943 "#"
4944 "&& reload_completed"
4945 [(const_int 0)]
4946 {
4947 /* if (which_alternative == 0) */
4948 if (REGNO(operands[0]) == REGNO(operands[1]))
4949 {
4950 /* Emit the pattern:
4951 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
4952 [(set (reg:CC CC_REGNUM)
4953 (compare:CC (match_dup 0) (const_int 0)))
4954 (cond_exec (lt:CC (reg:CC CC_REGNUM) (const_int 0))
4955 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 1))))]
4956 */
d1f9b275 4957 emit_insn (gen_rtx_SET (gen_rtx_REG (CCmode, CC_REGNUM),
ba6a3b2f 4958 gen_rtx_COMPARE (CCmode, operands[0], const0_rtx)));
4959 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
4960 (gen_rtx_LT (SImode,
4961 gen_rtx_REG (CCmode, CC_REGNUM),
4962 const0_rtx)),
d1f9b275 4963 (gen_rtx_SET (operands[0],
ba6a3b2f 4964 (gen_rtx_MINUS (SImode,
4965 const0_rtx,
4966 operands[1]))))));
4967 DONE;
4968 }
4969 else
4970 {
4971 /* Emit the pattern:
4972 alt1: eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31
4973 [(set (match_dup 0)
4974 (xor:SI (match_dup 1)
4975 (ashiftrt:SI (match_dup 1) (const_int 31))))
4976 (set (match_dup 0)
4977 (minus:SI (match_dup 0)
4978 (ashiftrt:SI (match_dup 1) (const_int 31))))]
4979 */
d1f9b275 4980 emit_insn (gen_rtx_SET (operands[0],
ba6a3b2f 4981 gen_rtx_XOR (SImode,
4982 gen_rtx_ASHIFTRT (SImode,
4983 operands[1],
4984 GEN_INT (31)),
4985 operands[1])));
d1f9b275 4986 emit_insn (gen_rtx_SET (operands[0],
ba6a3b2f 4987 gen_rtx_MINUS (SImode,
4988 operands[0],
4989 gen_rtx_ASHIFTRT (SImode,
4990 operands[1],
4991 GEN_INT (31)))));
4992 DONE;
4993 }
4994 }
cffb2a26 4995 [(set_attr "conds" "clob,*")
331beb1a 4996 (set_attr "shift" "1")
2ad08b65 4997 (set_attr "predicable" "no, yes")
1b7da4ac 4998 (set_attr "length" "8")
4999 (set_attr "type" "multiple")]
cffb2a26 5000)
9c08d1fa 5001
ba6a3b2f 5002(define_insn_and_split "*arm_neg_abssi2"
9c08d1fa 5003 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
5004 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
bd5b4116 5005 (clobber (reg:CC CC_REGNUM))]
cffb2a26 5006 "TARGET_ARM"
ba6a3b2f 5007 "#"
5008 "&& reload_completed"
5009 [(const_int 0)]
5010 {
5011 /* if (which_alternative == 0) */
5012 if (REGNO (operands[0]) == REGNO (operands[1]))
5013 {
5014 /* Emit the pattern:
5015 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
5016 */
d1f9b275 5017 emit_insn (gen_rtx_SET (gen_rtx_REG (CCmode, CC_REGNUM),
ba6a3b2f 5018 gen_rtx_COMPARE (CCmode, operands[0], const0_rtx)));
5019 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
5020 gen_rtx_GT (SImode,
5021 gen_rtx_REG (CCmode, CC_REGNUM),
5022 const0_rtx),
d1f9b275 5023 gen_rtx_SET (operands[0],
ba6a3b2f 5024 (gen_rtx_MINUS (SImode,
5025 const0_rtx,
5026 operands[1])))));
5027 }
5028 else
5029 {
5030 /* Emit the pattern:
5031 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31
5032 */
d1f9b275 5033 emit_insn (gen_rtx_SET (operands[0],
ba6a3b2f 5034 gen_rtx_XOR (SImode,
5035 gen_rtx_ASHIFTRT (SImode,
5036 operands[1],
5037 GEN_INT (31)),
5038 operands[1])));
d1f9b275 5039 emit_insn (gen_rtx_SET (operands[0],
ba6a3b2f 5040 gen_rtx_MINUS (SImode,
5041 gen_rtx_ASHIFTRT (SImode,
5042 operands[1],
5043 GEN_INT (31)),
5044 operands[0])));
5045 }
5046 DONE;
5047 }
cffb2a26 5048 [(set_attr "conds" "clob,*")
331beb1a 5049 (set_attr "shift" "1")
2ad08b65 5050 (set_attr "predicable" "no, yes")
1b7da4ac 5051 (set_attr "length" "8")
5052 (set_attr "type" "multiple")]
cffb2a26 5053)
b11cae9e 5054
604f3a0a 5055(define_expand "abssf2"
5056 [(set (match_operand:SF 0 "s_register_operand" "")
5057 (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
25f905c2 5058 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 5059 "")
5060
604f3a0a 5061(define_expand "absdf2"
5062 [(set (match_operand:DF 0 "s_register_operand" "")
5063 (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 5064 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 5065 "")
5066
7db9af5d 5067(define_expand "sqrtsf2"
5068 [(set (match_operand:SF 0 "s_register_operand" "")
5069 (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
d7216193 5070 "TARGET_32BIT && TARGET_HARD_FLOAT"
7db9af5d 5071 "")
9c08d1fa 5072
7db9af5d 5073(define_expand "sqrtdf2"
5074 [(set (match_operand:DF 0 "s_register_operand" "")
5075 (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
994606f8 5076 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
7db9af5d 5077 "")
9c08d1fa 5078
0d84c6e5 5079(define_expand "one_cmpldi2"
5080 [(set (match_operand:DI 0 "s_register_operand" "")
5081 (not:DI (match_operand:DI 1 "s_register_operand" "")))]
5082 "TARGET_32BIT"
5083 "
5084 if (!TARGET_NEON && !TARGET_IWMMXT)
5085 {
5086 rtx low = simplify_gen_unary (NOT, SImode,
5087 gen_lowpart (SImode, operands[1]),
5088 SImode);
5089 rtx high = simplify_gen_unary (NOT, SImode,
5090 gen_highpart_mode (SImode, DImode,
5091 operands[1]),
5092 SImode);
5093
5094 emit_insn (gen_rtx_SET (gen_lowpart (SImode, operands[0]), low));
5095 emit_insn (gen_rtx_SET (gen_highpart (SImode, operands[0]), high));
5096
5097 DONE;
5098 }
5099 /* Otherwise expand pattern as above. */
5100 "
5101)
5102
5103(define_insn_and_split "*one_cmpldi2_insn"
10efb95f 5104 [(set (match_operand:DI 0 "s_register_operand" "=w,&r,&r,?w")
5105 (not:DI (match_operand:DI 1 "s_register_operand" " w, 0, r, w")))]
25f905c2 5106 "TARGET_32BIT"
10efb95f 5107 "@
5108 vmvn\t%P0, %P1
5109 #
5110 #
5111 vmvn\t%P0, %P1"
5112 "TARGET_32BIT && reload_completed
5113 && arm_general_register_operand (operands[0], DImode)"
a0f94409 5114 [(set (match_dup 0) (not:SI (match_dup 1)))
5115 (set (match_dup 2) (not:SI (match_dup 3)))]
5116 "
5117 {
5118 operands[2] = gen_highpart (SImode, operands[0]);
5119 operands[0] = gen_lowpart (SImode, operands[0]);
5120 operands[3] = gen_highpart (SImode, operands[1]);
5121 operands[1] = gen_lowpart (SImode, operands[1]);
5122 }"
10efb95f 5123 [(set_attr "length" "*,8,8,*")
5124 (set_attr "predicable" "no,yes,yes,no")
32093010 5125 (set_attr "type" "neon_move,multiple,multiple,neon_move")
b6779ddc 5126 (set_attr "arch" "neon_for_64bits,*,*,avoid_neon_for_64bits")]
cffb2a26 5127)
b11cae9e 5128
cffb2a26 5129(define_expand "one_cmplsi2"
5130 [(set (match_operand:SI 0 "s_register_operand" "")
5131 (not:SI (match_operand:SI 1 "s_register_operand" "")))]
5132 "TARGET_EITHER"
b11cae9e 5133 ""
cffb2a26 5134)
5135
5136(define_insn "*arm_one_cmplsi2"
d952d547 5137 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
5138 (not:SI (match_operand:SI 1 "s_register_operand" "l,r")))]
25f905c2 5139 "TARGET_32BIT"
cffb2a26 5140 "mvn%?\\t%0, %1"
d2a518d1 5141 [(set_attr "predicable" "yes")
d952d547 5142 (set_attr "predicable_short_it" "yes,no")
5143 (set_attr "arch" "t2,*")
5144 (set_attr "length" "4")
1aed5204 5145 (set_attr "type" "mvn_reg")]
cffb2a26 5146)
5147
f7fbdd4a 5148(define_insn "*notsi_compare0"
bd5b4116 5149 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 5150 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5151 (const_int 0)))
5152 (set (match_operand:SI 0 "s_register_operand" "=r")
5153 (not:SI (match_dup 1)))]
25f905c2 5154 "TARGET_32BIT"
3ef90e77 5155 "mvns%?\\t%0, %1"
d2a518d1 5156 [(set_attr "conds" "set")
1aed5204 5157 (set_attr "type" "mvn_reg")]
cffb2a26 5158)
9c08d1fa 5159
f7fbdd4a 5160(define_insn "*notsi_compare0_scratch"
bd5b4116 5161 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 5162 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5163 (const_int 0)))
5164 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 5165 "TARGET_32BIT"
3ef90e77 5166 "mvns%?\\t%0, %1"
d2a518d1 5167 [(set_attr "conds" "set")
1aed5204 5168 (set_attr "type" "mvn_reg")]
cffb2a26 5169)
b11cae9e 5170\f
5171;; Fixed <--> Floating conversion insns
5172
9b8516be 5173(define_expand "floatsihf2"
5174 [(set (match_operand:HF 0 "general_operand" "")
5175 (float:HF (match_operand:SI 1 "general_operand" "")))]
5176 "TARGET_EITHER"
5177 "
5178 {
5179 rtx op1 = gen_reg_rtx (SFmode);
5180 expand_float (op1, operands[1], 0);
5181 op1 = convert_to_mode (HFmode, op1, 0);
5182 emit_move_insn (operands[0], op1);
5183 DONE;
5184 }"
5185)
5186
5187(define_expand "floatdihf2"
5188 [(set (match_operand:HF 0 "general_operand" "")
5189 (float:HF (match_operand:DI 1 "general_operand" "")))]
5190 "TARGET_EITHER"
5191 "
5192 {
5193 rtx op1 = gen_reg_rtx (SFmode);
5194 expand_float (op1, operands[1], 0);
5195 op1 = convert_to_mode (HFmode, op1, 0);
5196 emit_move_insn (operands[0], op1);
5197 DONE;
5198 }"
5199)
5200
604f3a0a 5201(define_expand "floatsisf2"
5202 [(set (match_operand:SF 0 "s_register_operand" "")
5203 (float:SF (match_operand:SI 1 "s_register_operand" "")))]
25f905c2 5204 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 5205 "
604f3a0a 5206")
5207
604f3a0a 5208(define_expand "floatsidf2"
5209 [(set (match_operand:DF 0 "s_register_operand" "")
5210 (float:DF (match_operand:SI 1 "s_register_operand" "")))]
a50d7267 5211 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 5212 "
604f3a0a 5213")
5214
9b8516be 5215(define_expand "fix_trunchfsi2"
5216 [(set (match_operand:SI 0 "general_operand" "")
5217 (fix:SI (fix:HF (match_operand:HF 1 "general_operand" ""))))]
5218 "TARGET_EITHER"
5219 "
5220 {
5221 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
5222 expand_fix (operands[0], op1, 0);
5223 DONE;
5224 }"
5225)
5226
5227(define_expand "fix_trunchfdi2"
5228 [(set (match_operand:DI 0 "general_operand" "")
5229 (fix:DI (fix:HF (match_operand:HF 1 "general_operand" ""))))]
5230 "TARGET_EITHER"
5231 "
5232 {
5233 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
5234 expand_fix (operands[0], op1, 0);
5235 DONE;
5236 }"
5237)
5238
604f3a0a 5239(define_expand "fix_truncsfsi2"
5240 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 5241 (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" ""))))]
25f905c2 5242 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 5243 "
604f3a0a 5244")
5245
604f3a0a 5246(define_expand "fix_truncdfsi2"
5247 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 5248 (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" ""))))]
a50d7267 5249 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 5250 "
604f3a0a 5251")
5252
f544c6d2 5253;; Truncation insns
b11cae9e 5254
604f3a0a 5255(define_expand "truncdfsf2"
5256 [(set (match_operand:SF 0 "s_register_operand" "")
5257 (float_truncate:SF
5258 (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 5259 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 5260 ""
5261)
9b8516be 5262
539b44ee 5263;; DFmode to HFmode conversions on targets without a single-step hardware
5264;; instruction for it would have to go through SFmode. This is dangerous
5265;; as it introduces double rounding.
5266;;
5267;; Disable this pattern unless we are in an unsafe math mode, or we have
5268;; a single-step instruction.
5269
9b8516be 5270(define_expand "truncdfhf2"
539b44ee 5271 [(set (match_operand:HF 0 "s_register_operand" "")
9b8516be 5272 (float_truncate:HF
539b44ee 5273 (match_operand:DF 1 "s_register_operand" "")))]
5274 "(TARGET_EITHER && flag_unsafe_math_optimizations)
5275 || (TARGET_32BIT && TARGET_FP16_TO_DOUBLE)"
5276{
5277 /* We don't have a direct instruction for this, so we must be in
5278 an unsafe math mode, and going via SFmode. */
5279
5280 if (!(TARGET_32BIT && TARGET_FP16_TO_DOUBLE))
5281 {
5282 rtx op1;
5283 op1 = convert_to_mode (SFmode, operands[1], 0);
5284 op1 = convert_to_mode (HFmode, op1, 0);
5285 emit_move_insn (operands[0], op1);
5286 DONE;
5287 }
5288 /* Otherwise, we will pick this up as a single instruction with
5289 no intermediary rounding. */
5290}
9b8516be 5291)
b11cae9e 5292\f
9c08d1fa 5293;; Zero and sign extension instructions.
b11cae9e 5294
848e66ac 5295(define_insn "zero_extend<mode>di2"
6aa689e8 5296 [(set (match_operand:DI 0 "s_register_operand" "=w,r,?r,w")
6d97728e 5297 (zero_extend:DI (match_operand:QHSI 1 "<qhs_zextenddi_op>"
5298 "<qhs_zextenddi_cstr>")))]
848e66ac 5299 "TARGET_32BIT <qhs_zextenddi_cond>"
5300 "#"
6aa689e8 5301 [(set_attr "length" "8,4,8,8")
b6779ddc 5302 (set_attr "arch" "neon_for_64bits,*,*,avoid_neon_for_64bits")
848e66ac 5303 (set_attr "ce_count" "2")
efbb5e19 5304 (set_attr "predicable" "yes")
5305 (set_attr "type" "multiple,mov_reg,multiple,multiple")]
25f905c2 5306)
5307
848e66ac 5308(define_insn "extend<mode>di2"
6aa689e8 5309 [(set (match_operand:DI 0 "s_register_operand" "=w,r,?r,?r,w")
63d204a8 5310 (sign_extend:DI (match_operand:QHSI 1 "<qhs_extenddi_op>"
5311 "<qhs_extenddi_cstr>")))]
848e66ac 5312 "TARGET_32BIT <qhs_sextenddi_cond>"
5313 "#"
6aa689e8 5314 [(set_attr "length" "8,4,8,8,8")
848e66ac 5315 (set_attr "ce_count" "2")
5316 (set_attr "shift" "1")
8012d2c2 5317 (set_attr "predicable" "yes")
1b7da4ac 5318 (set_attr "arch" "neon_for_64bits,*,a,t,avoid_neon_for_64bits")
5319 (set_attr "type" "multiple,mov_reg,multiple,multiple,multiple")]
0d66636f 5320)
9c08d1fa 5321
848e66ac 5322;; Splits for all extensions to DImode
5323(define_split
5324 [(set (match_operand:DI 0 "s_register_operand" "")
5325 (zero_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
6aa689e8 5326 "TARGET_32BIT && reload_completed && !IS_VFP_REGNUM (REGNO (operands[0]))"
848e66ac 5327 [(set (match_dup 0) (match_dup 1))]
5328{
848e66ac 5329 rtx lo_part = gen_lowpart (SImode, operands[0]);
3754d046 5330 machine_mode src_mode = GET_MODE (operands[1]);
848e66ac 5331
5332 if (REG_P (operands[0])
5333 && !reg_overlap_mentioned_p (operands[0], operands[1]))
5334 emit_clobber (operands[0]);
5335 if (!REG_P (lo_part) || src_mode != SImode
5336 || !rtx_equal_p (lo_part, operands[1]))
5337 {
5338 if (src_mode == SImode)
5339 emit_move_insn (lo_part, operands[1]);
5340 else
d1f9b275 5341 emit_insn (gen_rtx_SET (lo_part,
848e66ac 5342 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
5343 operands[1] = lo_part;
5344 }
5345 operands[0] = gen_highpart (SImode, operands[0]);
5346 operands[1] = const0_rtx;
5347})
9c08d1fa 5348
848e66ac 5349(define_split
25f905c2 5350 [(set (match_operand:DI 0 "s_register_operand" "")
848e66ac 5351 (sign_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
6aa689e8 5352 "TARGET_32BIT && reload_completed && !IS_VFP_REGNUM (REGNO (operands[0]))"
848e66ac 5353 [(set (match_dup 0) (ashiftrt:SI (match_dup 1) (const_int 31)))]
5354{
5355 rtx lo_part = gen_lowpart (SImode, operands[0]);
3754d046 5356 machine_mode src_mode = GET_MODE (operands[1]);
25f905c2 5357
848e66ac 5358 if (REG_P (operands[0])
5359 && !reg_overlap_mentioned_p (operands[0], operands[1]))
5360 emit_clobber (operands[0]);
5361
5362 if (!REG_P (lo_part) || src_mode != SImode
5363 || !rtx_equal_p (lo_part, operands[1]))
5364 {
5365 if (src_mode == SImode)
5366 emit_move_insn (lo_part, operands[1]);
5367 else
d1f9b275 5368 emit_insn (gen_rtx_SET (lo_part,
848e66ac 5369 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
5370 operands[1] = lo_part;
5371 }
5372 operands[0] = gen_highpart (SImode, operands[0]);
5373})
9c08d1fa 5374
5375(define_expand "zero_extendhisi2"
ef51b8e1 5376 [(set (match_operand:SI 0 "s_register_operand" "")
5377 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
cffb2a26 5378 "TARGET_EITHER"
ef51b8e1 5379{
5380 if (TARGET_ARM && !arm_arch4 && MEM_P (operands[1]))
f7fbdd4a 5381 {
ef51b8e1 5382 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
5383 DONE;
25f7a26e 5384 }
ef51b8e1 5385 if (!arm_arch6 && !MEM_P (operands[1]))
5386 {
5387 rtx t = gen_lowpart (SImode, operands[1]);
5388 rtx tmp = gen_reg_rtx (SImode);
5389 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
5390 emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (16)));
5391 DONE;
5392 }
5393})
9c08d1fa 5394
ef51b8e1 5395(define_split
b146458f 5396 [(set (match_operand:SI 0 "s_register_operand" "")
5397 (zero_extend:SI (match_operand:HI 1 "s_register_operand" "")))]
ef51b8e1 5398 "!TARGET_THUMB2 && !arm_arch6"
5399 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
5400 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 16)))]
5401{
5402 operands[2] = gen_lowpart (SImode, operands[1]);
5403})
5404
cffb2a26 5405(define_insn "*arm_zero_extendhisi2"
ef51b8e1 5406 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5407 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 5408 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 5409 "@
5410 #
3ef90e77 5411 ldrh%?\\t%0, %1"
d82e788e 5412 [(set_attr "type" "alu_shift_reg,load_byte")
848e66ac 5413 (set_attr "predicable" "yes")]
cffb2a26 5414)
f7fbdd4a 5415
a2cd141b 5416(define_insn "*arm_zero_extendhisi2_v6"
5417 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
e3f4ccee 5418 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,Uh")))]
a2cd141b 5419 "TARGET_ARM && arm_arch6"
5420 "@
5421 uxth%?\\t%0, %1
3ef90e77 5422 ldrh%?\\t%0, %1"
65f68e55 5423 [(set_attr "predicable" "yes")
6b6abc9c 5424 (set_attr "type" "extend,load_byte")]
a2cd141b 5425)
5426
5427(define_insn "*arm_zero_extendhisi2addsi"
5428 [(set (match_operand:SI 0 "s_register_operand" "=r")
5429 (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
5430 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 5431 "TARGET_INT_SIMD"
a2cd141b 5432 "uxtah%?\\t%0, %2, %1"
d82e788e 5433 [(set_attr "type" "alu_shift_reg")
d952d547 5434 (set_attr "predicable" "yes")
5435 (set_attr "predicable_short_it" "no")]
a2cd141b 5436)
5437
87b22bf7 5438(define_expand "zero_extendqisi2"
cffb2a26 5439 [(set (match_operand:SI 0 "s_register_operand" "")
5440 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
5441 "TARGET_EITHER"
ef51b8e1 5442{
0438d37f 5443 if (TARGET_ARM && !arm_arch6 && !MEM_P (operands[1]))
87b22bf7 5444 {
ef51b8e1 5445 emit_insn (gen_andsi3 (operands[0],
5446 gen_lowpart (SImode, operands[1]),
5447 GEN_INT (255)));
5448 DONE;
5449 }
5450 if (!arm_arch6 && !MEM_P (operands[1]))
5451 {
5452 rtx t = gen_lowpart (SImode, operands[1]);
5453 rtx tmp = gen_reg_rtx (SImode);
5454 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
5455 emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (24)));
5456 DONE;
5457 }
5458})
cffb2a26 5459
ef51b8e1 5460(define_split
b146458f 5461 [(set (match_operand:SI 0 "s_register_operand" "")
5462 (zero_extend:SI (match_operand:QI 1 "s_register_operand" "")))]
ef51b8e1 5463 "!arm_arch6"
5464 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
5465 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 24)))]
5466{
5467 operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
5468 if (TARGET_ARM)
5469 {
5470 emit_insn (gen_andsi3 (operands[0], operands[2], GEN_INT (255)));
87b22bf7 5471 DONE;
5472 }
ef51b8e1 5473})
9c08d1fa 5474
cffb2a26 5475(define_insn "*arm_zero_extendqisi2"
ef51b8e1 5476 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5477 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 5478 "TARGET_ARM && !arm_arch6"
ef51b8e1 5479 "@
5480 #
3ef90e77 5481 ldrb%?\\t%0, %1\\t%@ zero_extendqisi2"
ef51b8e1 5482 [(set_attr "length" "8,4")
d82e788e 5483 (set_attr "type" "alu_shift_reg,load_byte")
848e66ac 5484 (set_attr "predicable" "yes")]
cffb2a26 5485)
87b22bf7 5486
a2cd141b 5487(define_insn "*arm_zero_extendqisi2_v6"
5488 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
e3f4ccee 5489 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,Uh")))]
a2cd141b 5490 "TARGET_ARM && arm_arch6"
5491 "@
3ef90e77 5492 uxtb%?\\t%0, %1
5493 ldrb%?\\t%0, %1\\t%@ zero_extendqisi2"
6b6abc9c 5494 [(set_attr "type" "extend,load_byte")
848e66ac 5495 (set_attr "predicable" "yes")]
a2cd141b 5496)
5497
5498(define_insn "*arm_zero_extendqisi2addsi"
5499 [(set (match_operand:SI 0 "s_register_operand" "=r")
5500 (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
5501 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 5502 "TARGET_INT_SIMD"
a2cd141b 5503 "uxtab%?\\t%0, %2, %1"
5504 [(set_attr "predicable" "yes")
d952d547 5505 (set_attr "predicable_short_it" "no")
d82e788e 5506 (set_attr "type" "alu_shift_reg")]
a2cd141b 5507)
5508
87b22bf7 5509(define_split
5510 [(set (match_operand:SI 0 "s_register_operand" "")
5511 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
5512 (clobber (match_operand:SI 2 "s_register_operand" ""))]
0438d37f 5513 "TARGET_32BIT && (!MEM_P (operands[1])) && ! BYTES_BIG_ENDIAN"
87b22bf7 5514 [(set (match_dup 2) (match_dup 1))
5515 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
cffb2a26 5516 ""
5517)
9c08d1fa 5518
8a4d25d6 5519(define_split
5520 [(set (match_operand:SI 0 "s_register_operand" "")
5521 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 3)))
5522 (clobber (match_operand:SI 2 "s_register_operand" ""))]
0438d37f 5523 "TARGET_32BIT && (!MEM_P (operands[1])) && BYTES_BIG_ENDIAN"
8a4d25d6 5524 [(set (match_dup 2) (match_dup 1))
5525 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
5526 ""
5527)
5528
1c274529 5529
5530(define_split
5531 [(set (match_operand:SI 0 "s_register_operand" "")
9b23f0a7 5532 (IOR_XOR:SI (and:SI (ashift:SI
1c274529 5533 (match_operand:SI 1 "s_register_operand" "")
5534 (match_operand:SI 2 "const_int_operand" ""))
5535 (match_operand:SI 3 "const_int_operand" ""))
5536 (zero_extend:SI
5537 (match_operator 5 "subreg_lowpart_operator"
5538 [(match_operand:SI 4 "s_register_operand" "")]))))]
5539 "TARGET_32BIT
8c4e8755 5540 && (UINTVAL (operands[3])
1c274529 5541 == (GET_MODE_MASK (GET_MODE (operands[5]))
5542 & (GET_MODE_MASK (GET_MODE (operands[5]))
5543 << (INTVAL (operands[2])))))"
9b23f0a7 5544 [(set (match_dup 0) (IOR_XOR:SI (ashift:SI (match_dup 1) (match_dup 2))
1c274529 5545 (match_dup 4)))
5546 (set (match_dup 0) (zero_extend:SI (match_dup 5)))]
5547 "operands[5] = gen_lowpart (GET_MODE (operands[5]), operands[0]);"
5548)
5549
f7fbdd4a 5550(define_insn "*compareqi_eq0"
bd5b4116 5551 [(set (reg:CC_Z CC_REGNUM)
206ee9a2 5552 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
87b22bf7 5553 (const_int 0)))]
25f905c2 5554 "TARGET_32BIT"
596e5e8f 5555 "tst%?\\t%0, #255"
5556 [(set_attr "conds" "set")
d952d547 5557 (set_attr "predicable" "yes")
1b7da4ac 5558 (set_attr "predicable_short_it" "no")
5559 (set_attr "type" "logic_imm")]
cffb2a26 5560)
b11cae9e 5561
b11cae9e 5562(define_expand "extendhisi2"
ef51b8e1 5563 [(set (match_operand:SI 0 "s_register_operand" "")
5564 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
cffb2a26 5565 "TARGET_EITHER"
ef51b8e1 5566{
5567 if (TARGET_THUMB1)
5568 {
5569 emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1]));
5570 DONE;
5571 }
5572 if (MEM_P (operands[1]) && TARGET_ARM && !arm_arch4)
5573 {
5574 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
5575 DONE;
5576 }
ed29c566 5577
ef51b8e1 5578 if (!arm_arch6 && !MEM_P (operands[1]))
5579 {
5580 rtx t = gen_lowpart (SImode, operands[1]);
5581 rtx tmp = gen_reg_rtx (SImode);
5582 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
5583 emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (16)));
5584 DONE;
5585 }
5586})
cffb2a26 5587
ef51b8e1 5588(define_split
5589 [(parallel
5590 [(set (match_operand:SI 0 "register_operand" "")
5591 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))
5592 (clobber (match_scratch:SI 2 ""))])]
5593 "!arm_arch6"
5594 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
5595 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
5596{
5597 operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
5598})
25f7a26e 5599
25f905c2 5600;; This pattern will only be used when ldsh is not available
25f7a26e 5601(define_expand "extendhisi2_mem"
eab14235 5602 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 5603 (set (match_dup 3)
eab14235 5604 (zero_extend:SI (match_dup 7)))
25f7a26e 5605 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
5606 (set (match_operand:SI 0 "" "")
5607 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
cffb2a26 5608 "TARGET_ARM"
25f7a26e 5609 "
215b30b3 5610 {
5611 rtx mem1, mem2;
5612 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
5613
788fcce0 5614 mem1 = change_address (operands[1], QImode, addr);
29c05e22 5615 mem2 = change_address (operands[1], QImode,
5616 plus_constant (Pmode, addr, 1));
215b30b3 5617 operands[0] = gen_lowpart (SImode, operands[0]);
5618 operands[1] = mem1;
5619 operands[2] = gen_reg_rtx (SImode);
5620 operands[3] = gen_reg_rtx (SImode);
5621 operands[6] = gen_reg_rtx (SImode);
5622 operands[7] = mem2;
25f7a26e 5623
215b30b3 5624 if (BYTES_BIG_ENDIAN)
5625 {
5626 operands[4] = operands[2];
5627 operands[5] = operands[3];
5628 }
5629 else
5630 {
5631 operands[4] = operands[3];
5632 operands[5] = operands[2];
5633 }
5634 }"
5635)
b11cae9e 5636
ef51b8e1 5637(define_split
5638 [(set (match_operand:SI 0 "register_operand" "")
5639 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
5640 "!arm_arch6"
5641 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
5642 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
5643{
5644 operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
5645})
5646
a2cd141b 5647(define_insn "*arm_extendhisi2"
ef51b8e1 5648 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
e3f4ccee 5649 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,Uh")))]
a2cd141b 5650 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 5651 "@
5652 #
3ef90e77 5653 ldrsh%?\\t%0, %1"
ef51b8e1 5654 [(set_attr "length" "8,4")
d82e788e 5655 (set_attr "type" "alu_shift_reg,load_byte")
e3f4ccee 5656 (set_attr "predicable" "yes")]
cffb2a26 5657)
f7fbdd4a 5658
25f905c2 5659;; ??? Check Thumb-2 pool range
a2cd141b 5660(define_insn "*arm_extendhisi2_v6"
5661 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
e3f4ccee 5662 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,Uh")))]
25f905c2 5663 "TARGET_32BIT && arm_arch6"
a2cd141b 5664 "@
5665 sxth%?\\t%0, %1
3ef90e77 5666 ldrsh%?\\t%0, %1"
6b6abc9c 5667 [(set_attr "type" "extend,load_byte")
a2cd141b 5668 (set_attr "predicable" "yes")
e3f4ccee 5669 (set_attr "predicable_short_it" "no")]
a2cd141b 5670)
5671
5672(define_insn "*arm_extendhisi2addsi"
5673 [(set (match_operand:SI 0 "s_register_operand" "=r")
5674 (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
5675 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 5676 "TARGET_INT_SIMD"
a2cd141b 5677 "sxtah%?\\t%0, %2, %1"
1b7da4ac 5678 [(set_attr "type" "alu_shift_reg")]
a2cd141b 5679)
5680
c8f69309 5681(define_expand "extendqihi2"
5682 [(set (match_dup 2)
bed7d9a5 5683 (ashift:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")
c8f69309 5684 (const_int 24)))
9c08d1fa 5685 (set (match_operand:HI 0 "s_register_operand" "")
c8f69309 5686 (ashiftrt:SI (match_dup 2)
5687 (const_int 24)))]
cffb2a26 5688 "TARGET_ARM"
c8f69309 5689 "
215b30b3 5690 {
0438d37f 5691 if (arm_arch4 && MEM_P (operands[1]))
215b30b3 5692 {
d1f9b275 5693 emit_insn (gen_rtx_SET (operands[0],
215b30b3 5694 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
5695 DONE;
5696 }
5697 if (!s_register_operand (operands[1], QImode))
5698 operands[1] = copy_to_mode_reg (QImode, operands[1]);
5699 operands[0] = gen_lowpart (SImode, operands[0]);
5700 operands[1] = gen_lowpart (SImode, operands[1]);
5701 operands[2] = gen_reg_rtx (SImode);
5702 }"
5703)
f7fbdd4a 5704
25f905c2 5705(define_insn "*arm_extendqihi_insn"
b4e8a300 5706 [(set (match_operand:HI 0 "s_register_operand" "=r")
bed7d9a5 5707 (sign_extend:HI (match_operand:QI 1 "arm_extendqisi_mem_op" "Uq")))]
cffb2a26 5708 "TARGET_ARM && arm_arch4"
3ef90e77 5709 "ldrsb%?\\t%0, %1"
a2cd141b 5710 [(set_attr "type" "load_byte")
e3f4ccee 5711 (set_attr "predicable" "yes")]
cffb2a26 5712)
3fc2009e 5713
b11cae9e 5714(define_expand "extendqisi2"
ef51b8e1 5715 [(set (match_operand:SI 0 "s_register_operand" "")
5716 (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")))]
cffb2a26 5717 "TARGET_EITHER"
ef51b8e1 5718{
5719 if (!arm_arch4 && MEM_P (operands[1]))
5720 operands[1] = copy_to_mode_reg (QImode, operands[1]);
a2cd141b 5721
ef51b8e1 5722 if (!arm_arch6 && !MEM_P (operands[1]))
5723 {
5724 rtx t = gen_lowpart (SImode, operands[1]);
5725 rtx tmp = gen_reg_rtx (SImode);
5726 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
5727 emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (24)));
5728 DONE;
5729 }
5730})
a2cd141b 5731
ef51b8e1 5732(define_split
5733 [(set (match_operand:SI 0 "register_operand" "")
5734 (sign_extend:SI (match_operand:QI 1 "register_operand" "")))]
5735 "!arm_arch6"
5736 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
5737 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))]
5738{
5739 operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
5740})
f7fbdd4a 5741
a2cd141b 5742(define_insn "*arm_extendqisi"
ef51b8e1 5743 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5744 (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
a2cd141b 5745 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 5746 "@
5747 #
3ef90e77 5748 ldrsb%?\\t%0, %1"
ef51b8e1 5749 [(set_attr "length" "8,4")
d82e788e 5750 (set_attr "type" "alu_shift_reg,load_byte")
e3f4ccee 5751 (set_attr "predicable" "yes")]
cffb2a26 5752)
3fc2009e 5753
a2cd141b 5754(define_insn "*arm_extendqisi_v6"
5755 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
bed7d9a5 5756 (sign_extend:SI
5757 (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
a2cd141b 5758 "TARGET_ARM && arm_arch6"
b4e8a300 5759 "@
5760 sxtb%?\\t%0, %1
3ef90e77 5761 ldrsb%?\\t%0, %1"
6b6abc9c 5762 [(set_attr "type" "extend,load_byte")
e3f4ccee 5763 (set_attr "predicable" "yes")]
a2cd141b 5764)
5765
5766(define_insn "*arm_extendqisi2addsi"
5767 [(set (match_operand:SI 0 "s_register_operand" "=r")
5768 (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
5769 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 5770 "TARGET_INT_SIMD"
a2cd141b 5771 "sxtab%?\\t%0, %2, %1"
d82e788e 5772 [(set_attr "type" "alu_shift_reg")
d952d547 5773 (set_attr "predicable" "yes")
5774 (set_attr "predicable_short_it" "no")]
a2cd141b 5775)
5776
caedf871 5777(define_expand "extendsfdf2"
5778 [(set (match_operand:DF 0 "s_register_operand" "")
5779 (float_extend:DF (match_operand:SF 1 "s_register_operand" "")))]
a50d7267 5780 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
caedf871 5781 ""
5782)
9b8516be 5783
539b44ee 5784;; HFmode -> DFmode conversions where we don't have an instruction for it
5785;; must go through SFmode.
5786;;
5787;; This is always safe for an extend.
5788
9b8516be 5789(define_expand "extendhfdf2"
539b44ee 5790 [(set (match_operand:DF 0 "s_register_operand" "")
5791 (float_extend:DF (match_operand:HF 1 "s_register_operand" "")))]
9b8516be 5792 "TARGET_EITHER"
539b44ee 5793{
5794 /* We don't have a direct instruction for this, so go via SFmode. */
5795 if (!(TARGET_32BIT && TARGET_FP16_TO_DOUBLE))
5796 {
5797 rtx op1;
5798 op1 = convert_to_mode (SFmode, operands[1], 0);
5799 op1 = convert_to_mode (DFmode, op1, 0);
5800 emit_insn (gen_movdf (operands[0], op1));
5801 DONE;
5802 }
5803 /* Otherwise, we're done producing RTL and will pick up the correct
5804 pattern to do this with one rounding-step in a single instruction. */
5805}
9b8516be 5806)
b11cae9e 5807\f
5808;; Move insns (including loads and stores)
5809
5810;; XXX Just some ideas about movti.
9c08d1fa 5811;; I don't think these are a good idea on the arm, there just aren't enough
5812;; registers
b11cae9e 5813;;(define_expand "loadti"
9c08d1fa 5814;; [(set (match_operand:TI 0 "s_register_operand" "")
b11cae9e 5815;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
5816;; "" "")
5817
5818;;(define_expand "storeti"
5819;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
9c08d1fa 5820;; (match_operand:TI 1 "s_register_operand" ""))]
b11cae9e 5821;; "" "")
5822
5823;;(define_expand "movti"
5824;; [(set (match_operand:TI 0 "general_operand" "")
5825;; (match_operand:TI 1 "general_operand" ""))]
5826;; ""
5827;; "
5828;;{
5829;; rtx insn;
5830;;
0438d37f 5831;; if (MEM_P (operands[0]) && MEM_P (operands[1]))
b11cae9e 5832;; operands[1] = copy_to_reg (operands[1]);
0438d37f 5833;; if (MEM_P (operands[0]))
b11cae9e 5834;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
0438d37f 5835;; else if (MEM_P (operands[1]))
b11cae9e 5836;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
5837;; else
5838;; FAIL;
5839;;
5840;; emit_insn (insn);
5841;; DONE;
5842;;}")
5843
a2f10574 5844;; Recognize garbage generated above.
b11cae9e 5845
5846;;(define_insn ""
5847;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
5848;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
5849;; ""
5850;; "*
5851;; {
5852;; register mem = (which_alternative < 3);
0d66636f 5853;; register const char *template;
b11cae9e 5854;;
5855;; operands[mem] = XEXP (operands[mem], 0);
5856;; switch (which_alternative)
5857;; {
5858;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
5859;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
5860;; case 2: template = \"ldmia\\t%1, %M0\"; break;
5861;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
5862;; case 4: template = \"stmia\\t%0!, %M1\"; break;
5863;; case 5: template = \"stmia\\t%0, %M1\"; break;
5864;; }
e2348bcb 5865;; output_asm_insn (template, operands);
5866;; return \"\";
b11cae9e 5867;; }")
5868
cffb2a26 5869(define_expand "movdi"
5870 [(set (match_operand:DI 0 "general_operand" "")
5871 (match_operand:DI 1 "general_operand" ""))]
5872 "TARGET_EITHER"
5873 "
e1ba4a27 5874 if (can_create_pseudo_p ())
cffb2a26 5875 {
0438d37f 5876 if (!REG_P (operands[0]))
b2778788 5877 operands[1] = force_reg (DImode, operands[1]);
cffb2a26 5878 }
6b97fdcc 5879 if (REG_P (operands[0]) && REGNO (operands[0]) <= LAST_ARM_REGNUM
b395382f 5880 && !targetm.hard_regno_mode_ok (REGNO (operands[0]), DImode))
4f0e25ca 5881 {
5882 /* Avoid LDRD's into an odd-numbered register pair in ARM state
5883 when expanding function calls. */
5884 gcc_assert (can_create_pseudo_p ());
5885 if (MEM_P (operands[1]) && MEM_VOLATILE_P (operands[1]))
5886 {
5887 /* Perform load into legal reg pair first, then move. */
5888 rtx reg = gen_reg_rtx (DImode);
5889 emit_insn (gen_movdi (reg, operands[1]));
5890 operands[1] = reg;
5891 }
5892 emit_move_insn (gen_lowpart (SImode, operands[0]),
5893 gen_lowpart (SImode, operands[1]));
5894 emit_move_insn (gen_highpart (SImode, operands[0]),
5895 gen_highpart (SImode, operands[1]));
5896 DONE;
5897 }
6b97fdcc 5898 else if (REG_P (operands[1]) && REGNO (operands[1]) <= LAST_ARM_REGNUM
b395382f 5899 && !targetm.hard_regno_mode_ok (REGNO (operands[1]), DImode))
4f0e25ca 5900 {
5901 /* Avoid STRD's from an odd-numbered register pair in ARM state
5902 when expanding function prologue. */
5903 gcc_assert (can_create_pseudo_p ());
5904 rtx split_dest = (MEM_P (operands[0]) && MEM_VOLATILE_P (operands[0]))
5905 ? gen_reg_rtx (DImode)
5906 : operands[0];
5907 emit_move_insn (gen_lowpart (SImode, split_dest),
5908 gen_lowpart (SImode, operands[1]));
5909 emit_move_insn (gen_highpart (SImode, split_dest),
5910 gen_highpart (SImode, operands[1]));
5911 if (split_dest != operands[0])
5912 emit_insn (gen_movdi (operands[0], split_dest));
5913 DONE;
5914 }
cffb2a26 5915 "
5916)
b11cae9e 5917
cffb2a26 5918(define_insn "*arm_movdi"
353cf59a 5919 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, q, m")
5920 (match_operand:DI 1 "di_operand" "rDa,Db,Dc,mi,q"))]
cde1623a 5921 "TARGET_32BIT
d7216193 5922 && !(TARGET_HARD_FLOAT)
b2778788 5923 && !TARGET_IWMMXT
5924 && ( register_operand (operands[0], DImode)
5925 || register_operand (operands[1], DImode))"
b11cae9e 5926 "*
d51f92df 5927 switch (which_alternative)
5928 {
5929 case 0:
5930 case 1:
5931 case 2:
5932 return \"#\";
5933 default:
26ff80c0 5934 return output_move_double (operands, true, NULL);
d51f92df 5935 }
cffb2a26 5936 "
359a6e9f 5937 [(set_attr "length" "8,12,16,8,8")
9f2c2a36 5938 (set_attr "type" "multiple,multiple,multiple,load_8,store_8")
cde1623a 5939 (set_attr "arm_pool_range" "*,*,*,1020,*")
8848d797 5940 (set_attr "arm_neg_pool_range" "*,*,*,1004,*")
42e1de19 5941 (set_attr "thumb2_pool_range" "*,*,*,4094,*")
cde1623a 5942 (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
cffb2a26 5943)
5944
d51f92df 5945(define_split
5946 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
e6dd3afa 5947 (match_operand:ANY64 1 "immediate_operand" ""))]
25f905c2 5948 "TARGET_32BIT
d51f92df 5949 && reload_completed
a869c476 5950 && (arm_disable_literal_pool
5951 || (arm_const_double_inline_cost (operands[1])
5952 <= arm_max_const_double_inline_cost ()))"
d51f92df 5953 [(const_int 0)]
5954 "
5955 arm_split_constant (SET, SImode, curr_insn,
5956 INTVAL (gen_lowpart (SImode, operands[1])),
5957 gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
5958 arm_split_constant (SET, SImode, curr_insn,
5959 INTVAL (gen_highpart_mode (SImode,
5960 GET_MODE (operands[0]),
5961 operands[1])),
5962 gen_highpart (SImode, operands[0]), NULL_RTX, 0);
5963 DONE;
5964 "
5965)
5966
e5ba9289 5967; If optimizing for size, or if we have load delay slots, then
5968; we want to split the constant into two separate operations.
5969; In both cases this may split a trivial part into a single data op
5970; leaving a single complex constant to load. We can also get longer
5971; offsets in a LDR which means we get better chances of sharing the pool
5972; entries. Finally, we can normally do a better job of scheduling
5973; LDR instructions than we can with LDM.
5974; This pattern will only match if the one above did not.
5975(define_split
5976 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
5977 (match_operand:ANY64 1 "const_double_operand" ""))]
5978 "TARGET_ARM && reload_completed
5979 && arm_const_double_by_parts (operands[1])"
5980 [(set (match_dup 0) (match_dup 1))
5981 (set (match_dup 2) (match_dup 3))]
5982 "
5983 operands[2] = gen_highpart (SImode, operands[0]);
5984 operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
5985 operands[1]);
5986 operands[0] = gen_lowpart (SImode, operands[0]);
5987 operands[1] = gen_lowpart (SImode, operands[1]);
5988 "
5989)
5990
d51f92df 5991(define_split
5992 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
5993 (match_operand:ANY64 1 "arm_general_register_operand" ""))]
5994 "TARGET_EITHER && reload_completed"
5995 [(set (match_dup 0) (match_dup 1))
5996 (set (match_dup 2) (match_dup 3))]
5997 "
5998 operands[2] = gen_highpart (SImode, operands[0]);
5999 operands[3] = gen_highpart (SImode, operands[1]);
6000 operands[0] = gen_lowpart (SImode, operands[0]);
6001 operands[1] = gen_lowpart (SImode, operands[1]);
6002
6003 /* Handle a partial overlap. */
6004 if (rtx_equal_p (operands[0], operands[3]))
6005 {
6006 rtx tmp0 = operands[0];
6007 rtx tmp1 = operands[1];
6008
6009 operands[0] = operands[2];
6010 operands[1] = operands[3];
6011 operands[2] = tmp0;
6012 operands[3] = tmp1;
6013 }
6014 "
6015)
6016
a8a3b539 6017;; We can't actually do base+index doubleword loads if the index and
6018;; destination overlap. Split here so that we at least have chance to
6019;; schedule.
6020(define_split
6021 [(set (match_operand:DI 0 "s_register_operand" "")
6022 (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
6023 (match_operand:SI 2 "s_register_operand" ""))))]
6024 "TARGET_LDRD
6025 && reg_overlap_mentioned_p (operands[0], operands[1])
6026 && reg_overlap_mentioned_p (operands[0], operands[2])"
6027 [(set (match_dup 4)
6028 (plus:SI (match_dup 1)
6029 (match_dup 2)))
6030 (set (match_dup 0)
6031 (mem:DI (match_dup 4)))]
6032 "
6033 operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
6034 "
6035)
6036
9c08d1fa 6037(define_expand "movsi"
6038 [(set (match_operand:SI 0 "general_operand" "")
6039 (match_operand:SI 1 "general_operand" ""))]
cffb2a26 6040 "TARGET_EITHER"
9c08d1fa 6041 "
befb0bac 6042 {
e348ff3e 6043 rtx base, offset, tmp;
6044
6e291830 6045 if (TARGET_32BIT || TARGET_HAVE_MOVT)
9c08d1fa 6046 {
674a8f0b 6047 /* Everything except mem = const or mem = mem can be done easily. */
0438d37f 6048 if (MEM_P (operands[0]))
cffb2a26 6049 operands[1] = force_reg (SImode, operands[1]);
a2cd141b 6050 if (arm_general_register_operand (operands[0], SImode)
0438d37f 6051 && CONST_INT_P (operands[1])
cffb2a26 6052 && !(const_ok_for_arm (INTVAL (operands[1]))
6053 || const_ok_for_arm (~INTVAL (operands[1]))))
6054 {
17202aa5 6055 if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[1]), SET))
6056 {
6057 emit_insn (gen_rtx_SET (operands[0], operands[1]));
6058 DONE;
6059 }
6060 else
6061 {
6062 arm_split_constant (SET, SImode, NULL_RTX,
6063 INTVAL (operands[1]), operands[0], NULL_RTX,
6064 optimize && can_create_pseudo_p ());
6065 DONE;
6066 }
cffb2a26 6067 }
6068 }
75612252 6069 else /* Target doesn't have MOVT... */
cffb2a26 6070 {
e1ba4a27 6071 if (can_create_pseudo_p ())
cffb2a26 6072 {
0438d37f 6073 if (!REG_P (operands[0]))
cffb2a26 6074 operands[1] = force_reg (SImode, operands[1]);
6075 }
9c08d1fa 6076 }
f655717d 6077
e348ff3e 6078 if (ARM_OFFSETS_MUST_BE_WITHIN_SECTIONS_P)
6079 {
6080 split_const (operands[1], &base, &offset);
6081 if (GET_CODE (base) == SYMBOL_REF
6082 && !offset_within_block_p (base, INTVAL (offset)))
6083 {
b308ddcf 6084 tmp = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
e348ff3e 6085 emit_move_insn (tmp, base);
6086 emit_insn (gen_addsi3 (operands[0], tmp, offset));
6087 DONE;
6088 }
6089 }
6090
f655717d 6091 /* Recognize the case where operand[1] is a reference to thread-local
6092 data and load its address to a register. */
6093 if (arm_tls_referenced_p (operands[1]))
6094 {
6095 rtx tmp = operands[1];
6096 rtx addend = NULL;
6097
6098 if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
6099 {
6100 addend = XEXP (XEXP (tmp, 0), 1);
6101 tmp = XEXP (XEXP (tmp, 0), 0);
6102 }
6103
6104 gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
6105 gcc_assert (SYMBOL_REF_TLS_MODEL (tmp) != 0);
6106
e1ba4a27 6107 tmp = legitimize_tls_address (tmp,
6108 !can_create_pseudo_p () ? operands[0] : 0);
f655717d 6109 if (addend)
6110 {
6111 tmp = gen_rtx_PLUS (SImode, tmp, addend);
6112 tmp = force_operand (tmp, operands[0]);
6113 }
6114 operands[1] = tmp;
6115 }
6116 else if (flag_pic
6117 && (CONSTANT_P (operands[1])
6118 || symbol_mentioned_p (operands[1])
6119 || label_mentioned_p (operands[1])))
6120 operands[1] = legitimize_pic_address (operands[1], SImode,
e1ba4a27 6121 (!can_create_pseudo_p ()
6122 ? operands[0]
6123 : 0));
befb0bac 6124 }
215b30b3 6125 "
6126)
9c08d1fa 6127
d0e6a121 6128;; The ARM LO_SUM and HIGH are backwards - HIGH sets the low bits, and
6129;; LO_SUM adds in the high bits. Fortunately these are opaque operations
6130;; so this does not matter.
6131(define_insn "*arm_movt"
417e5cc5 6132 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r")
6133 (lo_sum:SI (match_operand:SI 1 "nonimmediate_operand" "0,0")
6134 (match_operand:SI 2 "general_operand" "i,i")))]
60a48e7d 6135 "TARGET_HAVE_MOVT && arm_valid_symbolic_address_p (operands[2])"
417e5cc5 6136 "@
6137 movt%?\t%0, #:upper16:%c2
6138 movt\t%0, #:upper16:%c2"
6139 [(set_attr "arch" "32,v8mb")
6140 (set_attr "predicable" "yes")
d952d547 6141 (set_attr "predicable_short_it" "no")
1b7da4ac 6142 (set_attr "length" "4")
282b4c75 6143 (set_attr "type" "alu_sreg")]
d0e6a121 6144)
6145
cffb2a26 6146(define_insn "*arm_movsi_insn"
aaa37ad6 6147 [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,rk,m")
110eae03 6148 (match_operand:SI 1 "general_operand" "rk, I,K,j,mi,rk"))]
d7216193 6149 "TARGET_ARM && !TARGET_IWMMXT && !TARGET_HARD_FLOAT
cffb2a26 6150 && ( register_operand (operands[0], SImode)
6151 || register_operand (operands[1], SImode))"
f7fbdd4a 6152 "@
aaa37ad6 6153 mov%?\\t%0, %1
f7fbdd4a 6154 mov%?\\t%0, %1
6155 mvn%?\\t%0, #%B1
25f905c2 6156 movw%?\\t%0, %1
f7fbdd4a 6157 ldr%?\\t%0, %1
6158 str%?\\t%1, %0"
9f2c2a36 6159 [(set_attr "type" "mov_reg,mov_imm,mvn_imm,mov_imm,load_4,store_4")
0d66636f 6160 (set_attr "predicable" "yes")
100cd063 6161 (set_attr "arch" "*,*,*,v6t2,*,*")
aaa37ad6 6162 (set_attr "pool_range" "*,*,*,*,4096,*")
6163 (set_attr "neg_pool_range" "*,*,*,*,4084,*")]
cffb2a26 6164)
87b22bf7 6165
6166(define_split
a2cd141b 6167 [(set (match_operand:SI 0 "arm_general_register_operand" "")
87b22bf7 6168 (match_operand:SI 1 "const_int_operand" ""))]
6e291830 6169 "(TARGET_32BIT || TARGET_HAVE_MOVT)
215b30b3 6170 && (!(const_ok_for_arm (INTVAL (operands[1]))
6171 || const_ok_for_arm (~INTVAL (operands[1]))))"
87b22bf7 6172 [(clobber (const_int 0))]
6173 "
96f57e36 6174 arm_split_constant (SET, SImode, NULL_RTX,
6175 INTVAL (operands[1]), operands[0], NULL_RTX, 0);
87b22bf7 6176 DONE;
215b30b3 6177 "
6178)
9c08d1fa 6179
861033d5 6180;; A normal way to do (symbol + offset) requires three instructions at least
6181;; (depends on how big the offset is) as below:
6182;; movw r0, #:lower16:g
6183;; movw r0, #:upper16:g
6184;; adds r0, #4
6185;;
6186;; A better way would be:
6187;; movw r0, #:lower16:g+4
6188;; movw r0, #:upper16:g+4
6189;;
6190;; The limitation of this way is that the length of offset should be a 16-bit
6191;; signed value, because current assembler only supports REL type relocation for
6192;; such case. If the more powerful RELA type is supported in future, we should
6193;; update this pattern to go with better way.
6194(define_split
6195 [(set (match_operand:SI 0 "arm_general_register_operand" "")
6196 (const:SI (plus:SI (match_operand:SI 1 "general_operand" "")
6197 (match_operand:SI 2 "const_int_operand" ""))))]
60a48e7d 6198 "TARGET_THUMB
6199 && TARGET_HAVE_MOVT
861033d5 6200 && arm_disable_literal_pool
6201 && reload_completed
6202 && GET_CODE (operands[1]) == SYMBOL_REF"
6203 [(clobber (const_int 0))]
6204 "
6205 int offset = INTVAL (operands[2]);
6206
6207 if (offset < -0x8000 || offset > 0x7fff)
6208 {
6209 arm_emit_movpair (operands[0], operands[1]);
d1f9b275 6210 emit_insn (gen_rtx_SET (operands[0],
861033d5 6211 gen_rtx_PLUS (SImode, operands[0], operands[2])));
6212 }
6213 else
6214 {
6215 rtx op = gen_rtx_CONST (SImode,
6216 gen_rtx_PLUS (SImode, operands[1], operands[2]));
6217 arm_emit_movpair (operands[0], op);
6218 }
6219 "
6220)
6221
b8d5d078 6222;; Split symbol_refs at the later stage (after cprop), instead of generating
6223;; movt/movw pair directly at expand. Otherwise corresponding high_sum
6224;; and lo_sum would be merged back into memory load at cprop. However,
6225;; if the default is to prefer movt/movw rather than a load from the constant
6226;; pool, the performance is better.
6227(define_split
6228 [(set (match_operand:SI 0 "arm_general_register_operand" "")
6229 (match_operand:SI 1 "general_operand" ""))]
60a48e7d 6230 "TARGET_USE_MOVT && GET_CODE (operands[1]) == SYMBOL_REF
b8d5d078 6231 && !flag_pic && !target_word_relocations
6232 && !arm_tls_referenced_p (operands[1])"
6233 [(clobber (const_int 0))]
6234{
6235 arm_emit_movpair (operands[0], operands[1]);
6236 DONE;
6237})
6238
bc360af8 6239;; When generating pic, we need to load the symbol offset into a register.
6240;; So that the optimizer does not confuse this with a normal symbol load
6241;; we use an unspec. The offset will be loaded from a constant pool entry,
6242;; since that is the only type of relocation we can use.
cffb2a26 6243
bc360af8 6244;; Wrap calculation of the whole PIC address in a single pattern for the
6245;; benefit of optimizers, particularly, PRE and HOIST. Calculation of
6246;; a PIC address involves two loads from memory, so we want to CSE it
6247;; as often as possible.
6248;; This pattern will be split into one of the pic_load_addr_* patterns
6249;; and a move after GCSE optimizations.
6250;;
6251;; Note: Update arm.c: legitimize_pic_address() when changing this pattern.
6252(define_expand "calculate_pic_address"
94f8caca 6253 [(set (match_operand:SI 0 "register_operand" "")
6254 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "")
6255 (unspec:SI [(match_operand:SI 2 "" "")]
6256 UNSPEC_PIC_SYM))))]
6257 "flag_pic"
6258)
6259
6260;; Split calculate_pic_address into pic_load_addr_* and a move.
6261(define_split
6262 [(set (match_operand:SI 0 "register_operand" "")
6263 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "")
6264 (unspec:SI [(match_operand:SI 2 "" "")]
6265 UNSPEC_PIC_SYM))))]
6266 "flag_pic"
6267 [(set (match_dup 3) (unspec:SI [(match_dup 2)] UNSPEC_PIC_SYM))
6268 (set (match_dup 0) (mem:SI (plus:SI (match_dup 1) (match_dup 3))))]
6269 "operands[3] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];"
6270)
6271
350ccca5 6272;; operand1 is the memory address to go into
6273;; pic_load_addr_32bit.
6274;; operand2 is the PIC label to be emitted
6275;; from pic_add_dot_plus_eight.
6276;; We do this to allow hoisting of the entire insn.
6277(define_insn_and_split "pic_load_addr_unified"
6278 [(set (match_operand:SI 0 "s_register_operand" "=r,r,l")
6279 (unspec:SI [(match_operand:SI 1 "" "mX,mX,mX")
6280 (match_operand:SI 2 "" "")]
6281 UNSPEC_PIC_UNIFIED))]
6282 "flag_pic"
6283 "#"
6284 "&& reload_completed"
6285 [(set (match_dup 0) (unspec:SI [(match_dup 1)] UNSPEC_PIC_SYM))
6286 (set (match_dup 0) (unspec:SI [(match_dup 0) (match_dup 3)
6287 (match_dup 2)] UNSPEC_PIC_BASE))]
6288 "operands[3] = TARGET_THUMB ? GEN_INT (4) : GEN_INT (8);"
9f2c2a36 6289 [(set_attr "type" "load_4,load_4,load_4")
42e1de19 6290 (set_attr "pool_range" "4096,4094,1022")
350ccca5 6291 (set_attr "neg_pool_range" "4084,0,0")
6292 (set_attr "arch" "a,t2,t1")
6293 (set_attr "length" "8,6,4")]
6294)
6295
67336bcf 6296;; The rather odd constraints on the following are to force reload to leave
6297;; the insn alone, and to force the minipool generation pass to then move
6298;; the GOT symbol to memory.
849170fd 6299
b3cd5f55 6300(define_insn "pic_load_addr_32bit"
849170fd 6301 [(set (match_operand:SI 0 "s_register_operand" "=r")
e1159bbe 6302 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
b3cd5f55 6303 "TARGET_32BIT && flag_pic"
67336bcf 6304 "ldr%?\\t%0, %1"
9f2c2a36 6305 [(set_attr "type" "load_4")
42e1de19 6306 (set (attr "pool_range")
6307 (if_then_else (eq_attr "is_thumb" "no")
6308 (const_int 4096)
6309 (const_int 4094)))
b3cd5f55 6310 (set (attr "neg_pool_range")
6311 (if_then_else (eq_attr "is_thumb" "no")
6312 (const_int 4084)
6313 (const_int 0)))]
8c4d8060 6314)
6315
25f905c2 6316(define_insn "pic_load_addr_thumb1"
8c4d8060 6317 [(set (match_operand:SI 0 "s_register_operand" "=l")
e1159bbe 6318 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
25f905c2 6319 "TARGET_THUMB1 && flag_pic"
8c4d8060 6320 "ldr\\t%0, %1"
9f2c2a36 6321 [(set_attr "type" "load_4")
42e1de19 6322 (set (attr "pool_range") (const_int 1018))]
cffb2a26 6323)
849170fd 6324
cffb2a26 6325(define_insn "pic_add_dot_plus_four"
15d5d060 6326 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 6327 (unspec:SI [(match_operand:SI 1 "register_operand" "0")
6328 (const_int 4)
beef0fb5 6329 (match_operand 2 "" "")]
6330 UNSPEC_PIC_BASE))]
b3cd5f55 6331 "TARGET_THUMB"
cffb2a26 6332 "*
6cdcb15c 6333 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
6334 INTVAL (operands[2]));
cffb2a26 6335 return \"add\\t%0, %|pc\";
6336 "
1b7da4ac 6337 [(set_attr "length" "2")
112eda6f 6338 (set_attr "type" "alu_sreg")]
cffb2a26 6339)
849170fd 6340
6341(define_insn "pic_add_dot_plus_eight"
15d5d060 6342 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 6343 (unspec:SI [(match_operand:SI 1 "register_operand" "r")
6344 (const_int 8)
beef0fb5 6345 (match_operand 2 "" "")]
6346 UNSPEC_PIC_BASE))]
f655717d 6347 "TARGET_ARM"
c4034607 6348 "*
6cdcb15c 6349 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
6350 INTVAL (operands[2]));
15d5d060 6351 return \"add%?\\t%0, %|pc, %1\";
cffb2a26 6352 "
1b7da4ac 6353 [(set_attr "predicable" "yes")
112eda6f 6354 (set_attr "type" "alu_sreg")]
cffb2a26 6355)
849170fd 6356
f655717d 6357(define_insn "tls_load_dot_plus_eight"
cc071db6 6358 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 6359 (mem:SI (unspec:SI [(match_operand:SI 1 "register_operand" "r")
6360 (const_int 8)
beef0fb5 6361 (match_operand 2 "" "")]
6362 UNSPEC_PIC_BASE)))]
f655717d 6363 "TARGET_ARM"
6364 "*
6cdcb15c 6365 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
6366 INTVAL (operands[2]));
f655717d 6367 return \"ldr%?\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_eight\";
6368 "
1b7da4ac 6369 [(set_attr "predicable" "yes")
9f2c2a36 6370 (set_attr "type" "load_4")]
f655717d 6371)
6372
6373;; PIC references to local variables can generate pic_add_dot_plus_eight
6374;; followed by a load. These sequences can be crunched down to
6375;; tls_load_dot_plus_eight by a peephole.
6376
6377(define_peephole2
c0c1fba5 6378 [(set (match_operand:SI 0 "register_operand" "")
6379 (unspec:SI [(match_operand:SI 3 "register_operand" "")
6380 (const_int 8)
6381 (match_operand 1 "" "")]
6382 UNSPEC_PIC_BASE))
2d05dfad 6383 (set (match_operand:SI 2 "arm_general_register_operand" "")
6384 (mem:SI (match_dup 0)))]
f655717d 6385 "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
c0c1fba5 6386 [(set (match_dup 2)
6387 (mem:SI (unspec:SI [(match_dup 3)
6388 (const_int 8)
6389 (match_dup 1)]
6390 UNSPEC_PIC_BASE)))]
f655717d 6391 ""
6392)
6393
bac7fc85 6394(define_insn "pic_offset_arm"
6395 [(set (match_operand:SI 0 "register_operand" "=r")
6396 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
6397 (unspec:SI [(match_operand:SI 2 "" "X")]
6398 UNSPEC_PIC_OFFSET))))]
6399 "TARGET_VXWORKS_RTP && TARGET_ARM && flag_pic"
6400 "ldr%?\\t%0, [%1,%2]"
9f2c2a36 6401 [(set_attr "type" "load_4")]
bac7fc85 6402)
6403
95373f08 6404(define_expand "builtin_setjmp_receiver"
6405 [(label_ref (match_operand 0 "" ""))]
6406 "flag_pic"
6407 "
6408{
b935b306 6409 /* r3 is clobbered by set/longjmp, so we can use it as a scratch
6410 register. */
2cb7d577 6411 if (arm_pic_register != INVALID_REGNUM)
6412 arm_load_pic_register (1UL << 3);
95373f08 6413 DONE;
6414}")
6415
9c08d1fa 6416;; If copying one reg to another we can set the condition codes according to
6417;; its value. Such a move is common after a return from subroutine and the
6418;; result is being tested against zero.
6419
f7fbdd4a 6420(define_insn "*movsi_compare0"
bd5b4116 6421 [(set (reg:CC CC_REGNUM)
cffb2a26 6422 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
6423 (const_int 0)))
6424 (set (match_operand:SI 0 "s_register_operand" "=r,r")
6425 (match_dup 1))]
25f905c2 6426 "TARGET_32BIT"
e2348bcb 6427 "@
40dbec34 6428 cmp%?\\t%0, #0
3ef90e77 6429 subs%?\\t%0, %1, #0"
65f68e55 6430 [(set_attr "conds" "set")
d82e788e 6431 (set_attr "type" "alus_imm,alus_imm")]
cffb2a26 6432)
b11cae9e 6433
b11cae9e 6434;; Subroutine to store a half word from a register into memory.
6435;; Operand 0 is the source register (HImode)
c8f69309 6436;; Operand 1 is the destination address in a register (SImode)
b11cae9e 6437
9c08d1fa 6438;; In both this routine and the next, we must be careful not to spill
01cc3b75 6439;; a memory address of reg+large_const into a separate PLUS insn, since this
9c08d1fa 6440;; can generate unrecognizable rtl.
6441
b11cae9e 6442(define_expand "storehi"
c8f69309 6443 [;; store the low byte
f082f1c4 6444 (set (match_operand 1 "" "") (match_dup 3))
b11cae9e 6445 ;; extract the high byte
c8f69309 6446 (set (match_dup 2)
6447 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
b11cae9e 6448 ;; store the high byte
787f8210 6449 (set (match_dup 4) (match_dup 5))]
cffb2a26 6450 "TARGET_ARM"
b11cae9e 6451 "
215b30b3 6452 {
537ffcfc 6453 rtx op1 = operands[1];
6454 rtx addr = XEXP (op1, 0);
215b30b3 6455 enum rtx_code code = GET_CODE (addr);
6456
0438d37f 6457 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
215b30b3 6458 || code == MINUS)
537ffcfc 6459 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
215b30b3 6460
537ffcfc 6461 operands[4] = adjust_address (op1, QImode, 1);
e513d163 6462 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 6463 operands[3] = gen_lowpart (QImode, operands[0]);
6464 operands[0] = gen_lowpart (SImode, operands[0]);
787f8210 6465 operands[2] = gen_reg_rtx (SImode);
6466 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 6467 }"
6468)
b11cae9e 6469
c7597b5d 6470(define_expand "storehi_bigend"
f082f1c4 6471 [(set (match_dup 4) (match_dup 3))
c7597b5d 6472 (set (match_dup 2)
6473 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
787f8210 6474 (set (match_operand 1 "" "") (match_dup 5))]
cffb2a26 6475 "TARGET_ARM"
b11cae9e 6476 "
215b30b3 6477 {
537ffcfc 6478 rtx op1 = operands[1];
6479 rtx addr = XEXP (op1, 0);
215b30b3 6480 enum rtx_code code = GET_CODE (addr);
6481
0438d37f 6482 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
215b30b3 6483 || code == MINUS)
537ffcfc 6484 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
215b30b3 6485
537ffcfc 6486 operands[4] = adjust_address (op1, QImode, 1);
e513d163 6487 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 6488 operands[3] = gen_lowpart (QImode, operands[0]);
6489 operands[0] = gen_lowpart (SImode, operands[0]);
6490 operands[2] = gen_reg_rtx (SImode);
787f8210 6491 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 6492 }"
6493)
c7597b5d 6494
6495;; Subroutine to store a half word integer constant into memory.
6496(define_expand "storeinthi"
f082f1c4 6497 [(set (match_operand 0 "" "")
787f8210 6498 (match_operand 1 "" ""))
9e8503e6 6499 (set (match_dup 3) (match_dup 2))]
cffb2a26 6500 "TARGET_ARM"
c7597b5d 6501 "
215b30b3 6502 {
6503 HOST_WIDE_INT value = INTVAL (operands[1]);
6504 rtx addr = XEXP (operands[0], 0);
537ffcfc 6505 rtx op0 = operands[0];
215b30b3 6506 enum rtx_code code = GET_CODE (addr);
c7597b5d 6507
0438d37f 6508 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
215b30b3 6509 || code == MINUS)
537ffcfc 6510 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
c7597b5d 6511
215b30b3 6512 operands[1] = gen_reg_rtx (SImode);
6513 if (BYTES_BIG_ENDIAN)
6514 {
6515 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
6516 if ((value & 255) == ((value >> 8) & 255))
6517 operands[2] = operands[1];
6518 else
6519 {
6520 operands[2] = gen_reg_rtx (SImode);
6521 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
6522 }
6523 }
6524 else
6525 {
6526 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
6527 if ((value & 255) == ((value >> 8) & 255))
6528 operands[2] = operands[1];
6529 else
6530 {
6531 operands[2] = gen_reg_rtx (SImode);
6532 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
6533 }
6534 }
c7597b5d 6535
537ffcfc 6536 operands[3] = adjust_address (op0, QImode, 1);
e513d163 6537 operands[0] = adjust_address (operands[0], QImode, 0);
9e8503e6 6538 operands[2] = gen_lowpart (QImode, operands[2]);
787f8210 6539 operands[1] = gen_lowpart (QImode, operands[1]);
215b30b3 6540 }"
6541)
b11cae9e 6542
f7fbdd4a 6543(define_expand "storehi_single_op"
6544 [(set (match_operand:HI 0 "memory_operand" "")
6545 (match_operand:HI 1 "general_operand" ""))]
25f905c2 6546 "TARGET_32BIT && arm_arch4"
f7fbdd4a 6547 "
215b30b3 6548 if (!s_register_operand (operands[1], HImode))
f7fbdd4a 6549 operands[1] = copy_to_mode_reg (HImode, operands[1]);
215b30b3 6550 "
6551)
f7fbdd4a 6552
b11cae9e 6553(define_expand "movhi"
6554 [(set (match_operand:HI 0 "general_operand" "")
c8f69309 6555 (match_operand:HI 1 "general_operand" ""))]
cffb2a26 6556 "TARGET_EITHER"
b11cae9e 6557 "
cffb2a26 6558 if (TARGET_ARM)
b11cae9e 6559 {
e1ba4a27 6560 if (can_create_pseudo_p ())
cffb2a26 6561 {
0438d37f 6562 if (MEM_P (operands[0]))
b11cae9e 6563 {
cffb2a26 6564 if (arm_arch4)
6565 {
6566 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
6567 DONE;
6568 }
0438d37f 6569 if (CONST_INT_P (operands[1]))
cffb2a26 6570 emit_insn (gen_storeinthi (operands[0], operands[1]));
c7597b5d 6571 else
cffb2a26 6572 {
0438d37f 6573 if (MEM_P (operands[1]))
cffb2a26 6574 operands[1] = force_reg (HImode, operands[1]);
6575 if (BYTES_BIG_ENDIAN)
6576 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
6577 else
6578 emit_insn (gen_storehi (operands[1], operands[0]));
6579 }
6580 DONE;
b11cae9e 6581 }
cffb2a26 6582 /* Sign extend a constant, and keep it in an SImode reg. */
0438d37f 6583 else if (CONST_INT_P (operands[1]))
9c08d1fa 6584 {
cffb2a26 6585 rtx reg = gen_reg_rtx (SImode);
6586 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
6587
6588 /* If the constant is already valid, leave it alone. */
215b30b3 6589 if (!const_ok_for_arm (val))
cffb2a26 6590 {
6591 /* If setting all the top bits will make the constant
6592 loadable in a single instruction, then set them.
6593 Otherwise, sign extend the number. */
6594
215b30b3 6595 if (const_ok_for_arm (~(val | ~0xffff)))
cffb2a26 6596 val |= ~0xffff;
6597 else if (val & 0x8000)
6598 val |= ~0xffff;
6599 }
6600
6601 emit_insn (gen_movsi (reg, GEN_INT (val)));
9e8503e6 6602 operands[1] = gen_lowpart (HImode, reg);
9c08d1fa 6603 }
e1ba4a27 6604 else if (arm_arch4 && optimize && can_create_pseudo_p ()
0438d37f 6605 && MEM_P (operands[1]))
0045890a 6606 {
6607 rtx reg = gen_reg_rtx (SImode);
6608
6609 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
6610 operands[1] = gen_lowpart (HImode, reg);
6611 }
215b30b3 6612 else if (!arm_arch4)
f7fbdd4a 6613 {
0438d37f 6614 if (MEM_P (operands[1]))
cffb2a26 6615 {
c1a66faf 6616 rtx base;
6617 rtx offset = const0_rtx;
6618 rtx reg = gen_reg_rtx (SImode);
6619
0438d37f 6620 if ((REG_P (base = XEXP (operands[1], 0))
c1a66faf 6621 || (GET_CODE (base) == PLUS
0438d37f 6622 && (CONST_INT_P (offset = XEXP (base, 1)))
c1a66faf 6623 && ((INTVAL(offset) & 1) != 1)
0438d37f 6624 && REG_P (base = XEXP (base, 0))))
c1a66faf 6625 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
206ee9a2 6626 {
8deb3959 6627 rtx new_rtx;
c1a66faf 6628
8deb3959 6629 new_rtx = widen_memory_access (operands[1], SImode,
6630 ((INTVAL (offset) & ~3)
6631 - INTVAL (offset)));
6632 emit_insn (gen_movsi (reg, new_rtx));
c1a66faf 6633 if (((INTVAL (offset) & 2) != 0)
6634 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
6635 {
6636 rtx reg2 = gen_reg_rtx (SImode);
6637
6638 emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
6639 reg = reg2;
6640 }
206ee9a2 6641 }
c1a66faf 6642 else
6643 emit_insn (gen_movhi_bytes (reg, operands[1]));
6644
6645 operands[1] = gen_lowpart (HImode, reg);
cffb2a26 6646 }
6647 }
6648 }
674a8f0b 6649 /* Handle loading a large integer during reload. */
0438d37f 6650 else if (CONST_INT_P (operands[1])
215b30b3 6651 && !const_ok_for_arm (INTVAL (operands[1]))
6652 && !const_ok_for_arm (~INTVAL (operands[1])))
cffb2a26 6653 {
6654 /* Writing a constant to memory needs a scratch, which should
6655 be handled with SECONDARY_RELOADs. */
0438d37f 6656 gcc_assert (REG_P (operands[0]));
cffb2a26 6657
6658 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
6659 emit_insn (gen_movsi (operands[0], operands[1]));
6660 DONE;
6661 }
6662 }
25f905c2 6663 else if (TARGET_THUMB2)
6664 {
6665 /* Thumb-2 can do everything except mem=mem and mem=const easily. */
e1ba4a27 6666 if (can_create_pseudo_p ())
25f905c2 6667 {
0438d37f 6668 if (!REG_P (operands[0]))
25f905c2 6669 operands[1] = force_reg (HImode, operands[1]);
6670 /* Zero extend a constant, and keep it in an SImode reg. */
0438d37f 6671 else if (CONST_INT_P (operands[1]))
25f905c2 6672 {
6673 rtx reg = gen_reg_rtx (SImode);
6674 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
6675
6676 emit_insn (gen_movsi (reg, GEN_INT (val)));
6677 operands[1] = gen_lowpart (HImode, reg);
6678 }
6679 }
6680 }
6681 else /* TARGET_THUMB1 */
cffb2a26 6682 {
e1ba4a27 6683 if (can_create_pseudo_p ())
cffb2a26 6684 {
0438d37f 6685 if (CONST_INT_P (operands[1]))
6cffc037 6686 {
6687 rtx reg = gen_reg_rtx (SImode);
6688
6689 emit_insn (gen_movsi (reg, operands[1]));
6690 operands[1] = gen_lowpart (HImode, reg);
6691 }
cffb2a26 6692
6693 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 6694 happen if we are passed a SP (never OK for HImode/QImode) or
bc409cb4 6695 virtual register (also rejected as illegitimate for HImode/QImode)
6696 relative address. */
cffb2a26 6697 /* ??? This should perhaps be fixed elsewhere, for instance, in
6698 fixup_stack_1, by checking for other kinds of invalid addresses,
6699 e.g. a bare reference to a virtual register. This may confuse the
6700 alpha though, which must handle this case differently. */
0438d37f 6701 if (MEM_P (operands[0])
215b30b3 6702 && !memory_address_p (GET_MODE (operands[0]),
6703 XEXP (operands[0], 0)))
537ffcfc 6704 operands[0]
6705 = replace_equiv_address (operands[0],
6706 copy_to_reg (XEXP (operands[0], 0)));
cffb2a26 6707
0438d37f 6708 if (MEM_P (operands[1])
215b30b3 6709 && !memory_address_p (GET_MODE (operands[1]),
6710 XEXP (operands[1], 0)))
537ffcfc 6711 operands[1]
6712 = replace_equiv_address (operands[1],
6713 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 6714
0438d37f 6715 if (MEM_P (operands[1]) && optimize > 0)
6cffc037 6716 {
6717 rtx reg = gen_reg_rtx (SImode);
6718
6719 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
6720 operands[1] = gen_lowpart (HImode, reg);
6721 }
6722
0438d37f 6723 if (MEM_P (operands[0]))
6cffc037 6724 operands[1] = force_reg (HImode, operands[1]);
cffb2a26 6725 }
0438d37f 6726 else if (CONST_INT_P (operands[1])
234f6557 6727 && !satisfies_constraint_I (operands[1]))
cffb2a26 6728 {
6cffc037 6729 /* Handle loading a large integer during reload. */
6730
cffb2a26 6731 /* Writing a constant to memory needs a scratch, which should
6732 be handled with SECONDARY_RELOADs. */
0438d37f 6733 gcc_assert (REG_P (operands[0]));
cffb2a26 6734
1a83b3ff 6735 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
cffb2a26 6736 emit_insn (gen_movsi (operands[0], operands[1]));
6737 DONE;
6738 }
b11cae9e 6739 }
cffb2a26 6740 "
6741)
6742
25f7a26e 6743(define_expand "movhi_bytes"
eab14235 6744 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 6745 (set (match_dup 3)
eab14235 6746 (zero_extend:SI (match_dup 6)))
25f7a26e 6747 (set (match_operand:SI 0 "" "")
6748 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
cffb2a26 6749 "TARGET_ARM"
25f7a26e 6750 "
215b30b3 6751 {
6752 rtx mem1, mem2;
6753 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
6754
788fcce0 6755 mem1 = change_address (operands[1], QImode, addr);
29c05e22 6756 mem2 = change_address (operands[1], QImode,
6757 plus_constant (Pmode, addr, 1));
215b30b3 6758 operands[0] = gen_lowpart (SImode, operands[0]);
6759 operands[1] = mem1;
6760 operands[2] = gen_reg_rtx (SImode);
6761 operands[3] = gen_reg_rtx (SImode);
6762 operands[6] = mem2;
25f7a26e 6763
215b30b3 6764 if (BYTES_BIG_ENDIAN)
6765 {
6766 operands[4] = operands[2];
6767 operands[5] = operands[3];
6768 }
6769 else
6770 {
6771 operands[4] = operands[3];
6772 operands[5] = operands[2];
6773 }
6774 }"
6775)
25f7a26e 6776
c7597b5d 6777(define_expand "movhi_bigend"
6778 [(set (match_dup 2)
6779 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
6780 (const_int 16)))
6781 (set (match_dup 3)
6782 (ashiftrt:SI (match_dup 2) (const_int 16)))
6783 (set (match_operand:HI 0 "s_register_operand" "")
787f8210 6784 (match_dup 4))]
cffb2a26 6785 "TARGET_ARM"
c7597b5d 6786 "
6787 operands[2] = gen_reg_rtx (SImode);
6788 operands[3] = gen_reg_rtx (SImode);
787f8210 6789 operands[4] = gen_lowpart (HImode, operands[3]);
215b30b3 6790 "
6791)
b11cae9e 6792
a2f10574 6793;; Pattern to recognize insn generated default case above
f7fbdd4a 6794(define_insn "*movhi_insn_arch4"
e4585731 6795 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r,m,r")
6796 (match_operand:HI 1 "general_operand" "rIk,K,n,r,mi"))]
cffb2a26 6797 "TARGET_ARM
d7216193 6798 && arm_arch4 && !TARGET_HARD_FLOAT
85e02ccb 6799 && (register_operand (operands[0], HImode)
6800 || register_operand (operands[1], HImode))"
f7fbdd4a 6801 "@
6802 mov%?\\t%0, %1\\t%@ movhi
6803 mvn%?\\t%0, #%B1\\t%@ movhi
b1c1a101 6804 movw%?\\t%0, %L1\\t%@ movhi
3ef90e77 6805 strh%?\\t%1, %0\\t%@ movhi
6806 ldrh%?\\t%0, %1\\t%@ movhi"
65f68e55 6807 [(set_attr "predicable" "yes")
e4585731 6808 (set_attr "pool_range" "*,*,*,*,256")
6809 (set_attr "neg_pool_range" "*,*,*,*,244")
6810 (set_attr "arch" "*,*,v6t2,*,*")
65f68e55 6811 (set_attr_alternative "type"
6812 [(if_then_else (match_operand 1 "const_int_operand" "")
1aed5204 6813 (const_string "mov_imm" )
6814 (const_string "mov_reg"))
6815 (const_string "mvn_imm")
e4585731 6816 (const_string "mov_imm")
9f2c2a36 6817 (const_string "store_4")
6818 (const_string "load_4")])]
cffb2a26 6819)
f7fbdd4a 6820
f7fbdd4a 6821(define_insn "*movhi_bytes"
65f68e55 6822 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
5fd254ed 6823 (match_operand:HI 1 "arm_rhs_operand" "I,rk,K"))]
d7216193 6824 "TARGET_ARM && !TARGET_HARD_FLOAT"
25f7a26e 6825 "@
65f68e55 6826 mov%?\\t%0, %1\\t%@ movhi
25f7a26e 6827 mov%?\\t%0, %1\\t%@ movhi
0d66636f 6828 mvn%?\\t%0, #%B1\\t%@ movhi"
d2a518d1 6829 [(set_attr "predicable" "yes")
1aed5204 6830 (set_attr "type" "mov_imm,mov_reg,mvn_imm")]
0d66636f 6831)
837bb76e 6832
bc5c7e08 6833;; We use a DImode scratch because we may occasionally need an additional
6834;; temporary if the address isn't offsettable -- push_reload doesn't seem
6835;; to take any notice of the "o" constraints on reload_memory_operand operand.
d3373b54 6836(define_expand "reload_outhi"
cffb2a26 6837 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
215b30b3 6838 (match_operand:HI 1 "s_register_operand" "r")
6839 (match_operand:DI 2 "s_register_operand" "=&l")])]
cffb2a26 6840 "TARGET_EITHER"
6841 "if (TARGET_ARM)
6842 arm_reload_out_hi (operands);
6843 else
6844 thumb_reload_out_hi (operands);
d3373b54 6845 DONE;
cffb2a26 6846 "
6847)
d3373b54 6848
25f7a26e 6849(define_expand "reload_inhi"
6850 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
cffb2a26 6851 (match_operand:HI 1 "arm_reload_memory_operand" "o")
bc5c7e08 6852 (match_operand:DI 2 "s_register_operand" "=&r")])]
c1a66faf 6853 "TARGET_EITHER"
25f7a26e 6854 "
cffb2a26 6855 if (TARGET_ARM)
6856 arm_reload_in_hi (operands);
6857 else
6858 thumb_reload_out_hi (operands);
25f7a26e 6859 DONE;
6860")
6861
9c08d1fa 6862(define_expand "movqi"
6863 [(set (match_operand:QI 0 "general_operand" "")
6864 (match_operand:QI 1 "general_operand" ""))]
cffb2a26 6865 "TARGET_EITHER"
9c08d1fa 6866 "
6cffc037 6867 /* Everything except mem = const or mem = mem can be done easily */
0045890a 6868
e1ba4a27 6869 if (can_create_pseudo_p ())
cffb2a26 6870 {
0438d37f 6871 if (CONST_INT_P (operands[1]))
6cffc037 6872 {
6873 rtx reg = gen_reg_rtx (SImode);
6874
03770691 6875 /* For thumb we want an unsigned immediate, then we are more likely
6876 to be able to use a movs insn. */
6877 if (TARGET_THUMB)
6878 operands[1] = GEN_INT (INTVAL (operands[1]) & 255);
6879
6cffc037 6880 emit_insn (gen_movsi (reg, operands[1]));
6881 operands[1] = gen_lowpart (QImode, reg);
6882 }
cffb2a26 6883
6cffc037 6884 if (TARGET_THUMB)
6885 {
cffb2a26 6886 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 6887 happen if we are passed a SP (never OK for HImode/QImode) or
bc409cb4 6888 virtual register (also rejected as illegitimate for HImode/QImode)
6889 relative address. */
cffb2a26 6890 /* ??? This should perhaps be fixed elsewhere, for instance, in
6891 fixup_stack_1, by checking for other kinds of invalid addresses,
6892 e.g. a bare reference to a virtual register. This may confuse the
6893 alpha though, which must handle this case differently. */
0438d37f 6894 if (MEM_P (operands[0])
215b30b3 6895 && !memory_address_p (GET_MODE (operands[0]),
cffb2a26 6896 XEXP (operands[0], 0)))
537ffcfc 6897 operands[0]
6898 = replace_equiv_address (operands[0],
6899 copy_to_reg (XEXP (operands[0], 0)));
0438d37f 6900 if (MEM_P (operands[1])
215b30b3 6901 && !memory_address_p (GET_MODE (operands[1]),
cffb2a26 6902 XEXP (operands[1], 0)))
537ffcfc 6903 operands[1]
6904 = replace_equiv_address (operands[1],
6905 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 6906 }
6907
0438d37f 6908 if (MEM_P (operands[1]) && optimize > 0)
6cffc037 6909 {
6910 rtx reg = gen_reg_rtx (SImode);
6911
6912 emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
6913 operands[1] = gen_lowpart (QImode, reg);
6914 }
6915
0438d37f 6916 if (MEM_P (operands[0]))
6cffc037 6917 operands[1] = force_reg (QImode, operands[1]);
6918 }
6919 else if (TARGET_THUMB
0438d37f 6920 && CONST_INT_P (operands[1])
234f6557 6921 && !satisfies_constraint_I (operands[1]))
6cffc037 6922 {
674a8f0b 6923 /* Handle loading a large integer during reload. */
cffb2a26 6924
6cffc037 6925 /* Writing a constant to memory needs a scratch, which should
6926 be handled with SECONDARY_RELOADs. */
0438d37f 6927 gcc_assert (REG_P (operands[0]));
6cffc037 6928
6929 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
6930 emit_insn (gen_movsi (operands[0], operands[1]));
6931 DONE;
cffb2a26 6932 }
6933 "
6934)
b11cae9e 6935
cffb2a26 6936(define_insn "*arm_movqi_insn"
fd711051 6937 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,l,r,l,Uu,r,m")
490f62ca 6938 (match_operand:QI 1 "general_operand" "rk,rk,I,Py,K,Uu,l,Uh,r"))]
25f905c2 6939 "TARGET_32BIT
cffb2a26 6940 && ( register_operand (operands[0], QImode)
6941 || register_operand (operands[1], QImode))"
5565501b 6942 "@
fd711051 6943 mov%?\\t%0, %1
6944 mov%?\\t%0, %1
65f68e55 6945 mov%?\\t%0, %1
5565501b 6946 mov%?\\t%0, %1
6947 mvn%?\\t%0, #%B1
3ef90e77 6948 ldrb%?\\t%0, %1
6949 strb%?\\t%1, %0
6950 ldrb%?\\t%0, %1
6951 strb%?\\t%1, %0"
9f2c2a36 6952 [(set_attr "type" "mov_reg,mov_reg,mov_imm,mov_imm,mvn_imm,load_4,store_4,load_4,store_4")
a54e3e7b 6953 (set_attr "predicable" "yes")
5233bf6a 6954 (set_attr "predicable_short_it" "yes,yes,no,yes,no,no,no,no,no")
fd711051 6955 (set_attr "arch" "t2,any,any,t2,any,t2,t2,any,any")
6956 (set_attr "length" "2,4,4,2,4,2,2,4,4")]
cffb2a26 6957)
6958
9b8516be 6959;; HFmode moves
6960(define_expand "movhf"
6961 [(set (match_operand:HF 0 "general_operand" "")
6962 (match_operand:HF 1 "general_operand" ""))]
6963 "TARGET_EITHER"
6964 "
6965 if (TARGET_32BIT)
6966 {
0438d37f 6967 if (MEM_P (operands[0]))
9b8516be 6968 operands[1] = force_reg (HFmode, operands[1]);
6969 }
6970 else /* TARGET_THUMB1 */
6971 {
6972 if (can_create_pseudo_p ())
6973 {
0438d37f 6974 if (!REG_P (operands[0]))
9b8516be 6975 operands[1] = force_reg (HFmode, operands[1]);
6976 }
6977 }
6978 "
6979)
6980
6981(define_insn "*arm32_movhf"
6982 [(set (match_operand:HF 0 "nonimmediate_operand" "=r,m,r,r")
6983 (match_operand:HF 1 "general_operand" " m,r,r,F"))]
d7216193 6984 "TARGET_32BIT && !TARGET_HARD_FLOAT
9b8516be 6985 && ( s_register_operand (operands[0], HFmode)
6986 || s_register_operand (operands[1], HFmode))"
6987 "*
6988 switch (which_alternative)
6989 {
6990 case 0: /* ARM register from memory */
3ef90e77 6991 return \"ldrh%?\\t%0, %1\\t%@ __fp16\";
9b8516be 6992 case 1: /* memory from ARM register */
3ef90e77 6993 return \"strh%?\\t%1, %0\\t%@ __fp16\";
9b8516be 6994 case 2: /* ARM register from ARM register */
6995 return \"mov%?\\t%0, %1\\t%@ __fp16\";
6996 case 3: /* ARM register from constant */
6997 {
9b8516be 6998 long bits;
6999 rtx ops[4];
7000
945f7b03 7001 bits = real_to_target (NULL, CONST_DOUBLE_REAL_VALUE (operands[1]),
7002 HFmode);
9b8516be 7003 ops[0] = operands[0];
7004 ops[1] = GEN_INT (bits);
7005 ops[2] = GEN_INT (bits & 0xff00);
7006 ops[3] = GEN_INT (bits & 0x00ff);
7007
7008 if (arm_arch_thumb2)
7009 output_asm_insn (\"movw%?\\t%0, %1\", ops);
7010 else
7011 output_asm_insn (\"mov%?\\t%0, %2\;orr%?\\t%0, %0, %3\", ops);
7012 return \"\";
7013 }
7014 default:
7015 gcc_unreachable ();
7016 }
7017 "
7018 [(set_attr "conds" "unconditional")
9f2c2a36 7019 (set_attr "type" "load_4,store_4,mov_reg,multiple")
9b8516be 7020 (set_attr "length" "4,4,4,8")
ea501323 7021 (set_attr "predicable" "yes")
7022 (set_attr "predicable_short_it" "no")]
9b8516be 7023)
7024
87b22bf7 7025(define_expand "movsf"
7026 [(set (match_operand:SF 0 "general_operand" "")
7027 (match_operand:SF 1 "general_operand" ""))]
cffb2a26 7028 "TARGET_EITHER"
87b22bf7 7029 "
25f905c2 7030 if (TARGET_32BIT)
cffb2a26 7031 {
0438d37f 7032 if (MEM_P (operands[0]))
cffb2a26 7033 operands[1] = force_reg (SFmode, operands[1]);
7034 }
25f905c2 7035 else /* TARGET_THUMB1 */
cffb2a26 7036 {
e1ba4a27 7037 if (can_create_pseudo_p ())
cffb2a26 7038 {
0438d37f 7039 if (!REG_P (operands[0]))
cffb2a26 7040 operands[1] = force_reg (SFmode, operands[1]);
7041 }
7042 }
7043 "
7044)
7045
03d440a6 7046;; Transform a floating-point move of a constant into a core register into
7047;; an SImode operation.
cffb2a26 7048(define_split
03d440a6 7049 [(set (match_operand:SF 0 "arm_general_register_operand" "")
cffb2a26 7050 (match_operand:SF 1 "immediate_operand" ""))]
339034d0 7051 "TARGET_EITHER
cffb2a26 7052 && reload_completed
0438d37f 7053 && CONST_DOUBLE_P (operands[1])"
cffb2a26 7054 [(set (match_dup 2) (match_dup 3))]
7055 "
7056 operands[2] = gen_lowpart (SImode, operands[0]);
7057 operands[3] = gen_lowpart (SImode, operands[1]);
7058 if (operands[2] == 0 || operands[3] == 0)
7059 FAIL;
215b30b3 7060 "
7061)
87b22bf7 7062
cffb2a26 7063(define_insn "*arm_movsf_soft_insn"
7064 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
7065 (match_operand:SF 1 "general_operand" "r,mE,r"))]
cde1623a 7066 "TARGET_32BIT
cffb2a26 7067 && TARGET_SOFT_FLOAT
0438d37f 7068 && (!MEM_P (operands[0])
215b30b3 7069 || register_operand (operands[1], SFmode))"
9a1112d7 7070 "@
7071 mov%?\\t%0, %1
7072 ldr%?\\t%0, %1\\t%@ float
7073 str%?\\t%1, %0\\t%@ float"
cde1623a 7074 [(set_attr "predicable" "yes")
7c36fe71 7075 (set_attr "predicable_short_it" "no")
9f2c2a36 7076 (set_attr "type" "mov_reg,load_4,store_4")
42e1de19 7077 (set_attr "arm_pool_range" "*,4096,*")
7078 (set_attr "thumb2_pool_range" "*,4094,*")
cde1623a 7079 (set_attr "arm_neg_pool_range" "*,4084,*")
7080 (set_attr "thumb2_neg_pool_range" "*,0,*")]
cffb2a26 7081)
7082
9c08d1fa 7083(define_expand "movdf"
87b22bf7 7084 [(set (match_operand:DF 0 "general_operand" "")
7085 (match_operand:DF 1 "general_operand" ""))]
cffb2a26 7086 "TARGET_EITHER"
9c08d1fa 7087 "
25f905c2 7088 if (TARGET_32BIT)
cffb2a26 7089 {
0438d37f 7090 if (MEM_P (operands[0]))
cffb2a26 7091 operands[1] = force_reg (DFmode, operands[1]);
7092 }
7093 else /* TARGET_THUMB */
7094 {
e1ba4a27 7095 if (can_create_pseudo_p ())
cffb2a26 7096 {
0438d37f 7097 if (!REG_P (operands[0]))
cffb2a26 7098 operands[1] = force_reg (DFmode, operands[1]);
7099 }
7100 }
7101 "
7102)
b11cae9e 7103
9c08d1fa 7104;; Reloading a df mode value stored in integer regs to memory can require a
7105;; scratch reg.
7106(define_expand "reload_outdf"
cffb2a26 7107 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
87b22bf7 7108 (match_operand:DF 1 "s_register_operand" "r")
7109 (match_operand:SI 2 "s_register_operand" "=&r")]
06adefdc 7110 "TARGET_THUMB2"
87b22bf7 7111 "
215b30b3 7112 {
7113 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
f7fbdd4a 7114
215b30b3 7115 if (code == REG)
7116 operands[2] = XEXP (operands[0], 0);
7117 else if (code == POST_INC || code == PRE_DEC)
7118 {
7119 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
7120 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
7121 emit_insn (gen_movdi (operands[0], operands[1]));
7122 DONE;
7123 }
7124 else if (code == PRE_INC)
7125 {
7126 rtx reg = XEXP (XEXP (operands[0], 0), 0);
f7fbdd4a 7127
215b30b3 7128 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
7129 operands[2] = reg;
7130 }
7131 else if (code == POST_DEC)
7132 operands[2] = XEXP (XEXP (operands[0], 0), 0);
7133 else
7134 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
7135 XEXP (XEXP (operands[0], 0), 1)));
f7fbdd4a 7136
d1f9b275 7137 emit_insn (gen_rtx_SET (replace_equiv_address (operands[0], operands[2]),
215b30b3 7138 operands[1]));
f7fbdd4a 7139
215b30b3 7140 if (code == POST_DEC)
7141 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
7142
7143 DONE;
7144 }"
7145)
9c08d1fa 7146
9a1112d7 7147(define_insn "*movdf_soft_insn"
353cf59a 7148 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,q,m")
7149 (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,q"))]
cde1623a 7150 "TARGET_32BIT && TARGET_SOFT_FLOAT
b2778788 7151 && ( register_operand (operands[0], DFmode)
7152 || register_operand (operands[1], DFmode))"
d51f92df 7153 "*
7154 switch (which_alternative)
7155 {
7156 case 0:
7157 case 1:
7158 case 2:
7159 return \"#\";
7160 default:
26ff80c0 7161 return output_move_double (operands, true, NULL);
d51f92df 7162 }
7163 "
359a6e9f 7164 [(set_attr "length" "8,12,16,8,8")
9f2c2a36 7165 (set_attr "type" "multiple,multiple,multiple,load_8,store_8")
42e1de19 7166 (set_attr "arm_pool_range" "*,*,*,1020,*")
7167 (set_attr "thumb2_pool_range" "*,*,*,1018,*")
8848d797 7168 (set_attr "arm_neg_pool_range" "*,*,*,1004,*")
cde1623a 7169 (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
cffb2a26 7170)
b11cae9e 7171\f
b11cae9e 7172
9c08d1fa 7173;; load- and store-multiple insns
7174;; The arm can load/store any set of registers, provided that they are in
320ea44d 7175;; ascending order, but these expanders assume a contiguous set.
b11cae9e 7176
9c08d1fa 7177(define_expand "load_multiple"
7178 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
7179 (match_operand:SI 1 "" ""))
7180 (use (match_operand:SI 2 "" ""))])]
25f905c2 7181 "TARGET_32BIT"
9580c25f 7182{
7183 HOST_WIDE_INT offset = 0;
7184
bd5b4116 7185 /* Support only fixed point registers. */
0438d37f 7186 if (!CONST_INT_P (operands[2])
6e628811 7187 || INTVAL (operands[2]) > MAX_LDM_STM_OPS
9c08d1fa 7188 || INTVAL (operands[2]) < 2
0438d37f 7189 || !MEM_P (operands[1])
7190 || !REG_P (operands[0])
bd5b4116 7191 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
7192 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 7193 FAIL;
7194
7195 operands[3]
320ea44d 7196 = arm_gen_load_multiple (arm_regs_in_sequence + REGNO (operands[0]),
7197 INTVAL (operands[2]),
f082f1c4 7198 force_reg (SImode, XEXP (operands[1], 0)),
320ea44d 7199 FALSE, operands[1], &offset);
9580c25f 7200})
b11cae9e 7201
9c08d1fa 7202(define_expand "store_multiple"
7203 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
7204 (match_operand:SI 1 "" ""))
7205 (use (match_operand:SI 2 "" ""))])]
25f905c2 7206 "TARGET_32BIT"
9580c25f 7207{
7208 HOST_WIDE_INT offset = 0;
7209
674a8f0b 7210 /* Support only fixed point registers. */
0438d37f 7211 if (!CONST_INT_P (operands[2])
6e628811 7212 || INTVAL (operands[2]) > MAX_LDM_STM_OPS
9c08d1fa 7213 || INTVAL (operands[2]) < 2
0438d37f 7214 || !REG_P (operands[1])
7215 || !MEM_P (operands[0])
bd5b4116 7216 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
7217 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 7218 FAIL;
7219
7220 operands[3]
320ea44d 7221 = arm_gen_store_multiple (arm_regs_in_sequence + REGNO (operands[1]),
7222 INTVAL (operands[2]),
f082f1c4 7223 force_reg (SImode, XEXP (operands[0], 0)),
320ea44d 7224 FALSE, operands[0], &offset);
9580c25f 7225})
b11cae9e 7226
9c08d1fa 7227
e34ebfca 7228(define_expand "setmemsi"
7229 [(match_operand:BLK 0 "general_operand" "")
7230 (match_operand:SI 1 "const_int_operand" "")
7231 (match_operand:SI 2 "const_int_operand" "")
7232 (match_operand:SI 3 "const_int_operand" "")]
7233 "TARGET_32BIT"
7234{
7235 if (arm_gen_setmem (operands))
7236 DONE;
7237
7238 FAIL;
7239})
7240
7241
9c08d1fa 7242;; Move a block of memory if it is word aligned and MORE than 2 words long.
7243;; We could let this apply for blocks of less than this, but it clobbers so
7244;; many registers that there is then probably a better way.
7245
008c057d 7246(define_expand "movmemqi"
34191dd1 7247 [(match_operand:BLK 0 "general_operand" "")
7248 (match_operand:BLK 1 "general_operand" "")
7249 (match_operand:SI 2 "const_int_operand" "")
7250 (match_operand:SI 3 "const_int_operand" "")]
ae51a965 7251 ""
9c08d1fa 7252 "
25f905c2 7253 if (TARGET_32BIT)
cffb2a26 7254 {
ae51a965 7255 if (TARGET_LDRD && current_tune->prefer_ldrd_strd
7256 && !optimize_function_for_size_p (cfun))
7257 {
7258 if (gen_movmem_ldrd_strd (operands))
7259 DONE;
7260 FAIL;
7261 }
7262
008c057d 7263 if (arm_gen_movmemqi (operands))
cffb2a26 7264 DONE;
7265 FAIL;
7266 }
25f905c2 7267 else /* TARGET_THUMB1 */
cffb2a26 7268 {
7269 if ( INTVAL (operands[3]) != 4
7270 || INTVAL (operands[2]) > 48)
7271 FAIL;
7272
008c057d 7273 thumb_expand_movmemqi (operands);
cffb2a26 7274 DONE;
7275 }
7276 "
7277)
9c08d1fa 7278\f
b11cae9e 7279
341940e8 7280;; Compare & branch insns
8d232dc7 7281;; The range calculations are based as follows:
341940e8 7282;; For forward branches, the address calculation returns the address of
7283;; the next instruction. This is 2 beyond the branch instruction.
7284;; For backward branches, the address calculation returns the address of
7285;; the first instruction in this pattern (cmp). This is 2 before the branch
7286;; instruction for the shortest sequence, and 4 before the branch instruction
7287;; if we have to jump around an unconditional branch.
7288;; To the basic branch range the PC offset must be added (this is +4).
7289;; So for forward branches we have
7290;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
7291;; And for backward branches we have
7292;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
7293;;
7294;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
7295;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
cffb2a26 7296
aeac46d4 7297(define_expand "cbranchsi4"
7298 [(set (pc) (if_then_else
aa06947a 7299 (match_operator 0 "expandable_comparison_operator"
aeac46d4 7300 [(match_operand:SI 1 "s_register_operand" "")
7301 (match_operand:SI 2 "nonmemory_operand" "")])
7302 (label_ref (match_operand 3 "" ""))
7303 (pc)))]
f9aa4160 7304 "TARGET_EITHER"
aeac46d4 7305 "
74f4459c 7306 if (!TARGET_THUMB1)
7307 {
f9aa4160 7308 if (!arm_validize_comparison (&operands[0], &operands[1], &operands[2]))
7309 FAIL;
74f4459c 7310 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
7311 operands[3]));
7312 DONE;
7313 }
25f905c2 7314 if (thumb1_cmpneg_operand (operands[2], SImode))
aeac46d4 7315 {
7316 emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
7317 operands[3], operands[0]));
7318 DONE;
7319 }
25f905c2 7320 if (!thumb1_cmp_operand (operands[2], SImode))
aeac46d4 7321 operands[2] = force_reg (SImode, operands[2]);
7322 ")
7323
74f4459c 7324(define_expand "cbranchsf4"
7325 [(set (pc) (if_then_else
aa06947a 7326 (match_operator 0 "expandable_comparison_operator"
74f4459c 7327 [(match_operand:SF 1 "s_register_operand" "")
d7216193 7328 (match_operand:SF 2 "vfp_compare_operand" "")])
74f4459c 7329 (label_ref (match_operand 3 "" ""))
7330 (pc)))]
7331 "TARGET_32BIT && TARGET_HARD_FLOAT"
7332 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
7333 operands[3])); DONE;"
7334)
7335
7336(define_expand "cbranchdf4"
7337 [(set (pc) (if_then_else
aa06947a 7338 (match_operator 0 "expandable_comparison_operator"
74f4459c 7339 [(match_operand:DF 1 "s_register_operand" "")
d7216193 7340 (match_operand:DF 2 "vfp_compare_operand" "")])
74f4459c 7341 (label_ref (match_operand 3 "" ""))
7342 (pc)))]
a50d7267 7343 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
74f4459c 7344 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
7345 operands[3])); DONE;"
7346)
7347
74f4459c 7348(define_expand "cbranchdi4"
7349 [(set (pc) (if_then_else
aa06947a 7350 (match_operator 0 "expandable_comparison_operator"
b8eae306 7351 [(match_operand:DI 1 "s_register_operand" "")
a8045a4f 7352 (match_operand:DI 2 "cmpdi_operand" "")])
74f4459c 7353 (label_ref (match_operand 3 "" ""))
7354 (pc)))]
a8045a4f 7355 "TARGET_32BIT"
7356 "{
0438d37f 7357 if (!arm_validize_comparison (&operands[0], &operands[1], &operands[2]))
f9aa4160 7358 FAIL;
7359 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
a8045a4f 7360 operands[3]));
7361 DONE;
7362 }"
74f4459c 7363)
7364
9c08d1fa 7365;; Comparison and test insns
7366
cffb2a26 7367(define_insn "*arm_cmpsi_insn"
bd5b4116 7368 [(set (reg:CC CC_REGNUM)
f9f234ec 7369 (compare:CC (match_operand:SI 0 "s_register_operand" "l,r,r,r,r")
7370 (match_operand:SI 1 "arm_add_operand" "Py,r,r,I,L")))]
25f905c2 7371 "TARGET_32BIT"
5565501b 7372 "@
a6864a24 7373 cmp%?\\t%0, %1
7374 cmp%?\\t%0, %1
aea4c774 7375 cmp%?\\t%0, %1
f9f234ec 7376 cmp%?\\t%0, %1
aea4c774 7377 cmn%?\\t%0, #%n1"
a6864a24 7378 [(set_attr "conds" "set")
f9f234ec 7379 (set_attr "arch" "t2,t2,any,any,any")
7380 (set_attr "length" "2,2,4,4,4")
65f68e55 7381 (set_attr "predicable" "yes")
f9f234ec 7382 (set_attr "predicable_short_it" "yes,yes,yes,no,no")
112eda6f 7383 (set_attr "type" "alus_imm,alus_sreg,alus_sreg,alus_imm,alus_imm")]
cffb2a26 7384)
b11cae9e 7385
d5d4dc8d 7386(define_insn "*cmpsi_shiftsi"
bd5b4116 7387 [(set (reg:CC CC_REGNUM)
d82e788e 7388 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r,r")
cffb2a26 7389 (match_operator:SI 3 "shift_operator"
d82e788e 7390 [(match_operand:SI 1 "s_register_operand" "r,r,r")
7391 (match_operand:SI 2 "shift_amount_operand" "M,r,M")])))]
d5d4dc8d 7392 "TARGET_32BIT"
f9f234ec 7393 "cmp\\t%0, %1%S3"
344495ea 7394 [(set_attr "conds" "set")
331beb1a 7395 (set_attr "shift" "1")
d82e788e 7396 (set_attr "arch" "32,a,a")
282b4c75 7397 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
b11cae9e 7398
d5d4dc8d 7399(define_insn "*cmpsi_shiftsi_swp"
bd5b4116 7400 [(set (reg:CC_SWP CC_REGNUM)
aea4c774 7401 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
d82e788e 7402 [(match_operand:SI 1 "s_register_operand" "r,r,r")
7403 (match_operand:SI 2 "shift_amount_operand" "M,r,M")])
7404 (match_operand:SI 0 "s_register_operand" "r,r,r")))]
d5d4dc8d 7405 "TARGET_32BIT"
aea4c774 7406 "cmp%?\\t%0, %1%S3"
344495ea 7407 [(set_attr "conds" "set")
331beb1a 7408 (set_attr "shift" "1")
d82e788e 7409 (set_attr "arch" "32,a,a")
282b4c75 7410 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
b11cae9e 7411
25f905c2 7412(define_insn "*arm_cmpsi_negshiftsi_si"
aed179ae 7413 [(set (reg:CC_Z CC_REGNUM)
7414 (compare:CC_Z
7415 (neg:SI (match_operator:SI 1 "shift_operator"
7416 [(match_operand:SI 2 "s_register_operand" "r")
7417 (match_operand:SI 3 "reg_or_int_operand" "rM")]))
7418 (match_operand:SI 0 "s_register_operand" "r")))]
cffb2a26 7419 "TARGET_ARM"
aed179ae 7420 "cmn%?\\t%0, %2%S1"
344495ea 7421 [(set_attr "conds" "set")
aed179ae 7422 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
d82e788e 7423 (const_string "alus_shift_imm")
7424 (const_string "alus_shift_reg")))
596e5e8f 7425 (set_attr "predicable" "yes")]
0d66636f 7426)
b11cae9e 7427
a8045a4f 7428;; DImode comparisons. The generic code generates branches that
7429;; if-conversion can not reduce to a conditional compare, so we do
7430;; that directly.
7431
ba6a3b2f 7432(define_insn_and_split "*arm_cmpdi_insn"
a8045a4f 7433 [(set (reg:CC_NCV CC_REGNUM)
7434 (compare:CC_NCV (match_operand:DI 0 "s_register_operand" "r")
7435 (match_operand:DI 1 "arm_di_operand" "rDi")))
7436 (clobber (match_scratch:SI 2 "=r"))]
b805622c 7437 "TARGET_32BIT"
ba6a3b2f 7438 "#" ; "cmp\\t%Q0, %Q1\;sbcs\\t%2, %R0, %R1"
7439 "&& reload_completed"
7440 [(set (reg:CC CC_REGNUM)
7441 (compare:CC (match_dup 0) (match_dup 1)))
7442 (parallel [(set (reg:CC CC_REGNUM)
7443 (compare:CC (match_dup 3) (match_dup 4)))
7444 (set (match_dup 2)
7445 (minus:SI (match_dup 5)
7446 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))])]
7447 {
7448 operands[3] = gen_highpart (SImode, operands[0]);
7449 operands[0] = gen_lowpart (SImode, operands[0]);
7450 if (CONST_INT_P (operands[1]))
7451 {
7452 operands[4] = GEN_INT (~INTVAL (gen_highpart_mode (SImode,
7453 DImode,
7454 operands[1])));
7455 operands[5] = gen_rtx_PLUS (SImode, operands[3], operands[4]);
7456 }
7457 else
7458 {
7459 operands[4] = gen_highpart (SImode, operands[1]);
7460 operands[5] = gen_rtx_MINUS (SImode, operands[3], operands[4]);
7461 }
7462 operands[1] = gen_lowpart (SImode, operands[1]);
7463 operands[2] = gen_lowpart (SImode, operands[2]);
7464 }
a8045a4f 7465 [(set_attr "conds" "set")
1b7da4ac 7466 (set_attr "length" "8")
7467 (set_attr "type" "multiple")]
a8045a4f 7468)
7469
ba6a3b2f 7470(define_insn_and_split "*arm_cmpdi_unsigned"
a8045a4f 7471 [(set (reg:CC_CZ CC_REGNUM)
1a86364b 7472 (compare:CC_CZ (match_operand:DI 0 "s_register_operand" "l,r,r,r")
7473 (match_operand:DI 1 "arm_di_operand" "Py,r,Di,rDi")))]
7c36fe71 7474
48a98053 7475 "TARGET_32BIT"
ba6a3b2f 7476 "#" ; "cmp\\t%R0, %R1\;it eq\;cmpeq\\t%Q0, %Q1"
7477 "&& reload_completed"
7478 [(set (reg:CC CC_REGNUM)
7479 (compare:CC (match_dup 2) (match_dup 3)))
7480 (cond_exec (eq:SI (reg:CC CC_REGNUM) (const_int 0))
7481 (set (reg:CC CC_REGNUM)
7482 (compare:CC (match_dup 0) (match_dup 1))))]
7483 {
7484 operands[2] = gen_highpart (SImode, operands[0]);
7485 operands[0] = gen_lowpart (SImode, operands[0]);
7486 if (CONST_INT_P (operands[1]))
7487 operands[3] = gen_highpart_mode (SImode, DImode, operands[1]);
7488 else
7489 operands[3] = gen_highpart (SImode, operands[1]);
7490 operands[1] = gen_lowpart (SImode, operands[1]);
7491 }
a8045a4f 7492 [(set_attr "conds" "set")
1a86364b 7493 (set_attr "enabled_for_depr_it" "yes,yes,no,*")
7494 (set_attr "arch" "t2,t2,t2,a")
7495 (set_attr "length" "6,6,10,8")
1b7da4ac 7496 (set_attr "type" "multiple")]
a8045a4f 7497)
7498
7499(define_insn "*arm_cmpdi_zero"
7500 [(set (reg:CC_Z CC_REGNUM)
7501 (compare:CC_Z (match_operand:DI 0 "s_register_operand" "r")
7502 (const_int 0)))
7503 (clobber (match_scratch:SI 1 "=r"))]
7504 "TARGET_32BIT"
3ef90e77 7505 "orrs%?\\t%1, %Q0, %R0"
1b7da4ac 7506 [(set_attr "conds" "set")
7507 (set_attr "type" "logics_reg")]
a8045a4f 7508)
7509
9c08d1fa 7510; This insn allows redundant compares to be removed by cse, nothing should
7511; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
7512; is deleted later on. The match_dup will match the mode here, so that
7513; mode changes of the condition codes aren't lost by this even though we don't
7514; specify what they are.
7515
8a18b90c 7516(define_insn "*deleted_compare"
9c08d1fa 7517 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
25f905c2 7518 "TARGET_32BIT"
40dbec34 7519 "\\t%@ deleted compare"
cffb2a26 7520 [(set_attr "conds" "set")
1b7da4ac 7521 (set_attr "length" "0")
7522 (set_attr "type" "no_insn")]
cffb2a26 7523)
9c08d1fa 7524
7525\f
7526;; Conditional branch insns
7527
74f4459c 7528(define_expand "cbranch_cc"
9c08d1fa 7529 [(set (pc)
74f4459c 7530 (if_then_else (match_operator 0 "" [(match_operand 1 "" "")
7531 (match_operand 2 "" "")])
7532 (label_ref (match_operand 3 "" ""))
9c08d1fa 7533 (pc)))]
25f905c2 7534 "TARGET_32BIT"
74f4459c 7535 "operands[1] = arm_gen_compare_reg (GET_CODE (operands[0]),
e1b93706 7536 operands[1], operands[2], NULL_RTX);
74f4459c 7537 operands[2] = const0_rtx;"
8fa3ba89 7538)
7539
7540;;
7541;; Patterns to match conditional branch insns.
7542;;
7543
ffcc986d 7544(define_insn "arm_cond_branch"
9c08d1fa 7545 [(set (pc)
8fa3ba89 7546 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 7547 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 7548 (label_ref (match_operand 0 "" ""))
7549 (pc)))]
25f905c2 7550 "TARGET_32BIT"
d75350ce 7551 "*
9c08d1fa 7552 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 7553 {
7554 arm_ccfsm_state += 2;
7555 return \"\";
7556 }
e2348bcb 7557 return \"b%d1\\t%l0\";
cffb2a26 7558 "
a2cd141b 7559 [(set_attr "conds" "use")
a6864a24 7560 (set_attr "type" "branch")
7561 (set (attr "length")
7562 (if_then_else
0bf497f5 7563 (and (match_test "TARGET_THUMB2")
a6864a24 7564 (and (ge (minus (match_dup 0) (pc)) (const_int -250))
7565 (le (minus (match_dup 0) (pc)) (const_int 256))))
7566 (const_int 2)
7567 (const_int 4)))]
cffb2a26 7568)
d75350ce 7569
cffb2a26 7570(define_insn "*arm_cond_branch_reversed"
9c08d1fa 7571 [(set (pc)
8fa3ba89 7572 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 7573 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 7574 (pc)
7575 (label_ref (match_operand 0 "" ""))))]
25f905c2 7576 "TARGET_32BIT"
d75350ce 7577 "*
9c08d1fa 7578 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 7579 {
7580 arm_ccfsm_state += 2;
7581 return \"\";
7582 }
e2348bcb 7583 return \"b%D1\\t%l0\";
cffb2a26 7584 "
a2cd141b 7585 [(set_attr "conds" "use")
a6864a24 7586 (set_attr "type" "branch")
7587 (set (attr "length")
7588 (if_then_else
0bf497f5 7589 (and (match_test "TARGET_THUMB2")
a6864a24 7590 (and (ge (minus (match_dup 0) (pc)) (const_int -250))
7591 (le (minus (match_dup 0) (pc)) (const_int 256))))
7592 (const_int 2)
7593 (const_int 4)))]
cffb2a26 7594)
7595
b11cae9e 7596\f
9c08d1fa 7597
7598; scc insns
7599
74f4459c 7600(define_expand "cstore_cc"
7db9af5d 7601 [(set (match_operand:SI 0 "s_register_operand" "")
74f4459c 7602 (match_operator:SI 1 "" [(match_operand 2 "" "")
7603 (match_operand 3 "" "")]))]
25f905c2 7604 "TARGET_32BIT"
74f4459c 7605 "operands[2] = arm_gen_compare_reg (GET_CODE (operands[1]),
e1b93706 7606 operands[2], operands[3], NULL_RTX);
74f4459c 7607 operands[3] = const0_rtx;"
8fa3ba89 7608)
7609
a3b84066 7610(define_insn_and_split "*mov_scc"
9c08d1fa 7611 [(set (match_operand:SI 0 "s_register_operand" "=r")
ff74dd54 7612 (match_operator:SI 1 "arm_comparison_operator_mode"
8a18b90c 7613 [(match_operand 2 "cc_register" "") (const_int 0)]))]
cffb2a26 7614 "TARGET_ARM"
a3b84066 7615 "#" ; "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
7616 "TARGET_ARM"
7617 [(set (match_dup 0)
7618 (if_then_else:SI (match_dup 1)
7619 (const_int 1)
7620 (const_int 0)))]
7621 ""
cffb2a26 7622 [(set_attr "conds" "use")
1b7da4ac 7623 (set_attr "length" "8")
7624 (set_attr "type" "multiple")]
cffb2a26 7625)
9c08d1fa 7626
a3b84066 7627(define_insn_and_split "*mov_negscc"
9c08d1fa 7628 [(set (match_operand:SI 0 "s_register_operand" "=r")
ff74dd54 7629 (neg:SI (match_operator:SI 1 "arm_comparison_operator_mode"
8a18b90c 7630 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 7631 "TARGET_ARM"
a3b84066 7632 "#" ; "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
7633 "TARGET_ARM"
7634 [(set (match_dup 0)
7635 (if_then_else:SI (match_dup 1)
7636 (match_dup 3)
7637 (const_int 0)))]
7638 {
7639 operands[3] = GEN_INT (~0);
7640 }
cffb2a26 7641 [(set_attr "conds" "use")
1b7da4ac 7642 (set_attr "length" "8")
7643 (set_attr "type" "multiple")]
cffb2a26 7644)
9c08d1fa 7645
a3b84066 7646(define_insn_and_split "*mov_notscc"
9c08d1fa 7647 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7648 (not:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7649 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 7650 "TARGET_ARM"
a3b84066 7651 "#" ; "mvn%D1\\t%0, #0\;mvn%d1\\t%0, #1"
7652 "TARGET_ARM"
7653 [(set (match_dup 0)
7654 (if_then_else:SI (match_dup 1)
7655 (match_dup 3)
7656 (match_dup 4)))]
7657 {
7658 operands[3] = GEN_INT (~1);
7659 operands[4] = GEN_INT (~0);
7660 }
cffb2a26 7661 [(set_attr "conds" "use")
1b7da4ac 7662 (set_attr "length" "8")
7663 (set_attr "type" "multiple")]
cffb2a26 7664)
9c08d1fa 7665
595d88b5 7666(define_expand "cstoresi4"
7667 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 7668 (match_operator:SI 1 "expandable_comparison_operator"
595d88b5 7669 [(match_operand:SI 2 "s_register_operand" "")
7670 (match_operand:SI 3 "reg_or_int_operand" "")]))]
74f4459c 7671 "TARGET_32BIT || TARGET_THUMB1"
595d88b5 7672 "{
7673 rtx op3, scratch, scratch2;
7674
74f4459c 7675 if (!TARGET_THUMB1)
7676 {
7677 if (!arm_add_operand (operands[3], SImode))
7678 operands[3] = force_reg (SImode, operands[3]);
7679 emit_insn (gen_cstore_cc (operands[0], operands[1],
7680 operands[2], operands[3]));
7681 DONE;
7682 }
7683
595d88b5 7684 if (operands[3] == const0_rtx)
7685 {
7686 switch (GET_CODE (operands[1]))
7687 {
7688 case EQ:
25f905c2 7689 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], operands[2]));
595d88b5 7690 break;
7691
7692 case NE:
25f905c2 7693 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], operands[2]));
595d88b5 7694 break;
7695
7696 case LE:
7697 scratch = expand_binop (SImode, add_optab, operands[2], constm1_rtx,
7698 NULL_RTX, 0, OPTAB_WIDEN);
7699 scratch = expand_binop (SImode, ior_optab, operands[2], scratch,
7700 NULL_RTX, 0, OPTAB_WIDEN);
7701 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7702 operands[0], 1, OPTAB_WIDEN);
7703 break;
7704
7705 case GE:
7706 scratch = expand_unop (SImode, one_cmpl_optab, operands[2],
7707 NULL_RTX, 1);
7708 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7709 NULL_RTX, 1, OPTAB_WIDEN);
7710 break;
7711
7712 case GT:
7713 scratch = expand_binop (SImode, ashr_optab, operands[2],
7714 GEN_INT (31), NULL_RTX, 0, OPTAB_WIDEN);
7715 scratch = expand_binop (SImode, sub_optab, scratch, operands[2],
7716 NULL_RTX, 0, OPTAB_WIDEN);
7717 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31), operands[0],
7718 0, OPTAB_WIDEN);
7719 break;
7720
7721 /* LT is handled by generic code. No need for unsigned with 0. */
7722 default:
7723 FAIL;
7724 }
7725 DONE;
7726 }
7727
7728 switch (GET_CODE (operands[1]))
7729 {
7730 case EQ:
7731 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7732 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7733 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], scratch));
595d88b5 7734 break;
7735
7736 case NE:
7737 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7738 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7739 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], scratch));
595d88b5 7740 break;
7741
7742 case LE:
7743 op3 = force_reg (SImode, operands[3]);
7744
7745 scratch = expand_binop (SImode, lshr_optab, operands[2], GEN_INT (31),
7746 NULL_RTX, 1, OPTAB_WIDEN);
7747 scratch2 = expand_binop (SImode, ashr_optab, op3, GEN_INT (31),
7748 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7749 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
595d88b5 7750 op3, operands[2]));
7751 break;
7752
7753 case GE:
7754 op3 = operands[3];
25f905c2 7755 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7756 op3 = force_reg (SImode, op3);
7757 scratch = expand_binop (SImode, ashr_optab, operands[2], GEN_INT (31),
7758 NULL_RTX, 0, OPTAB_WIDEN);
7759 scratch2 = expand_binop (SImode, lshr_optab, op3, GEN_INT (31),
7760 NULL_RTX, 1, OPTAB_WIDEN);
25f905c2 7761 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
595d88b5 7762 operands[2], op3));
7763 break;
7764
7765 case LEU:
7766 op3 = force_reg (SImode, operands[3]);
7767 scratch = force_reg (SImode, const0_rtx);
25f905c2 7768 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
595d88b5 7769 op3, operands[2]));
7770 break;
7771
7772 case GEU:
7773 op3 = operands[3];
25f905c2 7774 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7775 op3 = force_reg (SImode, op3);
7776 scratch = force_reg (SImode, const0_rtx);
25f905c2 7777 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
595d88b5 7778 operands[2], op3));
7779 break;
7780
7781 case LTU:
7782 op3 = operands[3];
25f905c2 7783 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7784 op3 = force_reg (SImode, op3);
7785 scratch = gen_reg_rtx (SImode);
408b7ae5 7786 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], operands[2], op3));
595d88b5 7787 break;
7788
7789 case GTU:
7790 op3 = force_reg (SImode, operands[3]);
7791 scratch = gen_reg_rtx (SImode);
408b7ae5 7792 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], op3, operands[2]));
595d88b5 7793 break;
7794
7795 /* No good sequences for GT, LT. */
7796 default:
7797 FAIL;
7798 }
7799 DONE;
7800}")
7801
9854d864 7802(define_expand "cstorehf4"
7803 [(set (match_operand:SI 0 "s_register_operand")
7804 (match_operator:SI 1 "expandable_comparison_operator"
7805 [(match_operand:HF 2 "s_register_operand")
d7216193 7806 (match_operand:HF 3 "vfp_compare_operand")]))]
9854d864 7807 "TARGET_VFP_FP16INST"
7808 {
7809 if (!arm_validize_comparison (&operands[1],
7810 &operands[2],
7811 &operands[3]))
7812 FAIL;
7813
7814 emit_insn (gen_cstore_cc (operands[0], operands[1],
7815 operands[2], operands[3]));
7816 DONE;
7817 }
7818)
7819
74f4459c 7820(define_expand "cstoresf4"
7821 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 7822 (match_operator:SI 1 "expandable_comparison_operator"
74f4459c 7823 [(match_operand:SF 2 "s_register_operand" "")
d7216193 7824 (match_operand:SF 3 "vfp_compare_operand" "")]))]
74f4459c 7825 "TARGET_32BIT && TARGET_HARD_FLOAT"
7826 "emit_insn (gen_cstore_cc (operands[0], operands[1],
7827 operands[2], operands[3])); DONE;"
7828)
7829
7830(define_expand "cstoredf4"
7831 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 7832 (match_operator:SI 1 "expandable_comparison_operator"
74f4459c 7833 [(match_operand:DF 2 "s_register_operand" "")
d7216193 7834 (match_operand:DF 3 "vfp_compare_operand" "")]))]
d63ed457 7835 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
74f4459c 7836 "emit_insn (gen_cstore_cc (operands[0], operands[1],
7837 operands[2], operands[3])); DONE;"
7838)
7839
74f4459c 7840(define_expand "cstoredi4"
7841 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 7842 (match_operator:SI 1 "expandable_comparison_operator"
b8eae306 7843 [(match_operand:DI 2 "s_register_operand" "")
a8045a4f 7844 (match_operand:DI 3 "cmpdi_operand" "")]))]
7845 "TARGET_32BIT"
7846 "{
f9aa4160 7847 if (!arm_validize_comparison (&operands[1],
7848 &operands[2],
7849 &operands[3]))
7850 FAIL;
7851 emit_insn (gen_cstore_cc (operands[0], operands[1], operands[2],
a8045a4f 7852 operands[3]));
7853 DONE;
7854 }"
74f4459c 7855)
7856
9c08d1fa 7857\f
39b5e676 7858;; Conditional move insns
7859
7860(define_expand "movsicc"
8a18b90c 7861 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 7862 (if_then_else:SI (match_operand 1 "expandable_comparison_operator" "")
aea4c774 7863 (match_operand:SI 2 "arm_not_operand" "")
8a18b90c 7864 (match_operand:SI 3 "arm_not_operand" "")))]
25f905c2 7865 "TARGET_32BIT"
39b5e676 7866 "
215b30b3 7867 {
f9aa4160 7868 enum rtx_code code;
278b301d 7869 rtx ccreg;
7870
f9aa4160 7871 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
9854d864 7872 &XEXP (operands[1], 1)))
278b301d 7873 FAIL;
9854d864 7874
7875 code = GET_CODE (operands[1]);
7876 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
7877 XEXP (operands[1], 1), NULL_RTX);
7878 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7879 }"
7880)
7881
7882(define_expand "movhfcc"
7883 [(set (match_operand:HF 0 "s_register_operand")
7884 (if_then_else:HF (match_operand 1 "arm_cond_move_operator")
7885 (match_operand:HF 2 "s_register_operand")
7886 (match_operand:HF 3 "s_register_operand")))]
7887 "TARGET_VFP_FP16INST"
7888 "
7889 {
7890 enum rtx_code code = GET_CODE (operands[1]);
7891 rtx ccreg;
7892
7893 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
7894 &XEXP (operands[1], 1)))
7895 FAIL;
7896
f9aa4160 7897 code = GET_CODE (operands[1]);
74f4459c 7898 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
e1b93706 7899 XEXP (operands[1], 1), NULL_RTX);
29bb088d 7900 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7901 }"
7902)
39b5e676 7903
7904(define_expand "movsfcc"
8a18b90c 7905 [(set (match_operand:SF 0 "s_register_operand" "")
4df97ffc 7906 (if_then_else:SF (match_operand 1 "arm_cond_move_operator" "")
8a18b90c 7907 (match_operand:SF 2 "s_register_operand" "")
d86c91f6 7908 (match_operand:SF 3 "s_register_operand" "")))]
19f6bf8d 7909 "TARGET_32BIT && TARGET_HARD_FLOAT"
39b5e676 7910 "
215b30b3 7911 {
7912 enum rtx_code code = GET_CODE (operands[1]);
7913 rtx ccreg;
f082f1c4 7914
9854d864 7915 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
f9aa4160 7916 &XEXP (operands[1], 1)))
7917 FAIL;
39b5e676 7918
f9aa4160 7919 code = GET_CODE (operands[1]);
74f4459c 7920 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
e1b93706 7921 XEXP (operands[1], 1), NULL_RTX);
29bb088d 7922 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7923 }"
7924)
39b5e676 7925
7926(define_expand "movdfcc"
8a18b90c 7927 [(set (match_operand:DF 0 "s_register_operand" "")
4df97ffc 7928 (if_then_else:DF (match_operand 1 "arm_cond_move_operator" "")
8a18b90c 7929 (match_operand:DF 2 "s_register_operand" "")
d86c91f6 7930 (match_operand:DF 3 "s_register_operand" "")))]
994606f8 7931 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
39b5e676 7932 "
215b30b3 7933 {
7934 enum rtx_code code = GET_CODE (operands[1]);
278b301d 7935 rtx ccreg;
39b5e676 7936
f9aa4160 7937 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
7938 &XEXP (operands[1], 1)))
7939 FAIL;
7940 code = GET_CODE (operands[1]);
74f4459c 7941 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
e1b93706 7942 XEXP (operands[1], 1), NULL_RTX);
29bb088d 7943 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7944 }"
7945)
39b5e676 7946
91cb50d2 7947(define_insn "*cmov<mode>"
7948 [(set (match_operand:SDF 0 "s_register_operand" "=<F_constraint>")
7949 (if_then_else:SDF (match_operator 1 "arm_vsel_comparison_operator"
7950 [(match_operand 2 "cc_register" "") (const_int 0)])
7951 (match_operand:SDF 3 "s_register_operand"
7952 "<F_constraint>")
7953 (match_operand:SDF 4 "s_register_operand"
7954 "<F_constraint>")))]
c79c1b1b 7955 "TARGET_HARD_FLOAT && TARGET_VFP5 <vfp_double_cond>"
91cb50d2 7956 "*
7957 {
7958 enum arm_cond_code code = maybe_get_arm_condition_code (operands[1]);
7959 switch (code)
7960 {
7961 case ARM_GE:
7962 case ARM_GT:
7963 case ARM_EQ:
7964 case ARM_VS:
7965 return \"vsel%d1.<V_if_elem>\\t%<V_reg>0, %<V_reg>3, %<V_reg>4\";
7966 case ARM_LT:
7967 case ARM_LE:
7968 case ARM_NE:
7969 case ARM_VC:
7970 return \"vsel%D1.<V_if_elem>\\t%<V_reg>0, %<V_reg>4, %<V_reg>3\";
7971 default:
7972 gcc_unreachable ();
7973 }
7974 return \"\";
7975 }"
7976 [(set_attr "conds" "use")
6664d308 7977 (set_attr "type" "fcsel")]
91cb50d2 7978)
7979
9854d864 7980(define_insn "*cmovhf"
7981 [(set (match_operand:HF 0 "s_register_operand" "=t")
7982 (if_then_else:HF (match_operator 1 "arm_vsel_comparison_operator"
7983 [(match_operand 2 "cc_register" "") (const_int 0)])
7984 (match_operand:HF 3 "s_register_operand" "t")
7985 (match_operand:HF 4 "s_register_operand" "t")))]
7986 "TARGET_VFP_FP16INST"
7987 "*
7988 {
7989 enum arm_cond_code code = maybe_get_arm_condition_code (operands[1]);
7990 switch (code)
7991 {
7992 case ARM_GE:
7993 case ARM_GT:
7994 case ARM_EQ:
7995 case ARM_VS:
7996 return \"vsel%d1.f16\\t%0, %3, %4\";
7997 case ARM_LT:
7998 case ARM_LE:
7999 case ARM_NE:
8000 case ARM_VC:
8001 return \"vsel%D1.f16\\t%0, %4, %3\";
8002 default:
8003 gcc_unreachable ();
8004 }
8005 return \"\";
8006 }"
8007 [(set_attr "conds" "use")
8008 (set_attr "type" "fcsel")]
8009)
8010
190efb17 8011(define_insn_and_split "*movsicc_insn"
f082f1c4 8012 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
8a18b90c 8013 (if_then_else:SI
8fa3ba89 8014 (match_operator 3 "arm_comparison_operator"
8a18b90c 8015 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 8016 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
8017 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
cffb2a26 8018 "TARGET_ARM"
39b5e676 8019 "@
8a18b90c 8020 mov%D3\\t%0, %2
8021 mvn%D3\\t%0, #%B2
f082f1c4 8022 mov%d3\\t%0, %1
8023 mvn%d3\\t%0, #%B1
190efb17 8024 #
8025 #
8026 #
8027 #"
8028 ; alt4: mov%d3\\t%0, %1\;mov%D3\\t%0, %2
8029 ; alt5: mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
8030 ; alt6: mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
8031 ; alt7: mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
8032 "&& reload_completed"
8033 [(const_int 0)]
8034 {
8035 enum rtx_code rev_code;
3754d046 8036 machine_mode mode;
190efb17 8037 rtx rev_cond;
8038
8039 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
8040 operands[3],
d1f9b275 8041 gen_rtx_SET (operands[0], operands[1])));
190efb17 8042
8043 rev_code = GET_CODE (operands[3]);
8044 mode = GET_MODE (operands[4]);
8045 if (mode == CCFPmode || mode == CCFPEmode)
8046 rev_code = reverse_condition_maybe_unordered (rev_code);
8047 else
8048 rev_code = reverse_condition (rev_code);
8049
8050 rev_cond = gen_rtx_fmt_ee (rev_code,
8051 VOIDmode,
8052 operands[4],
8053 const0_rtx);
8054 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
8055 rev_cond,
d1f9b275 8056 gen_rtx_SET (operands[0], operands[2])));
190efb17 8057 DONE;
8058 }
f082f1c4 8059 [(set_attr "length" "4,4,4,4,8,8,8,8")
d2a518d1 8060 (set_attr "conds" "use")
65f68e55 8061 (set_attr_alternative "type"
8062 [(if_then_else (match_operand 2 "const_int_operand" "")
1aed5204 8063 (const_string "mov_imm")
8064 (const_string "mov_reg"))
8065 (const_string "mvn_imm")
65f68e55 8066 (if_then_else (match_operand 1 "const_int_operand" "")
1aed5204 8067 (const_string "mov_imm")
8068 (const_string "mov_reg"))
8069 (const_string "mvn_imm")
282b4c75 8070 (const_string "multiple")
8071 (const_string "multiple")
8072 (const_string "multiple")
8073 (const_string "multiple")])]
215b30b3 8074)
39b5e676 8075
39b5e676 8076(define_insn "*movsfcc_soft_insn"
f082f1c4 8077 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
8fa3ba89 8078 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
8a18b90c 8079 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 8080 (match_operand:SF 1 "s_register_operand" "0,r")
8081 (match_operand:SF 2 "s_register_operand" "r,0")))]
cffb2a26 8082 "TARGET_ARM && TARGET_SOFT_FLOAT"
f082f1c4 8083 "@
8084 mov%D3\\t%0, %2
8085 mov%d3\\t%0, %1"
d2a518d1 8086 [(set_attr "conds" "use")
1aed5204 8087 (set_attr "type" "mov_reg")]
8fa3ba89 8088)
39b5e676 8089
39b5e676 8090\f
9c08d1fa 8091;; Jump and linkage insns
8092
cffb2a26 8093(define_expand "jump"
9c08d1fa 8094 [(set (pc)
8095 (label_ref (match_operand 0 "" "")))]
cffb2a26 8096 "TARGET_EITHER"
9c08d1fa 8097 ""
cffb2a26 8098)
8099
8100(define_insn "*arm_jump"
8101 [(set (pc)
8102 (label_ref (match_operand 0 "" "")))]
25f905c2 8103 "TARGET_32BIT"
9c08d1fa 8104 "*
0d66636f 8105 {
8106 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
8107 {
8108 arm_ccfsm_state += 2;
8109 return \"\";
8110 }
8111 return \"b%?\\t%l0\";
8112 }
8113 "
a6864a24 8114 [(set_attr "predicable" "yes")
8115 (set (attr "length")
8116 (if_then_else
0bf497f5 8117 (and (match_test "TARGET_THUMB2")
a6864a24 8118 (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
8119 (le (minus (match_dup 0) (pc)) (const_int 2048))))
8120 (const_int 2)
1b7da4ac 8121 (const_int 4)))
8122 (set_attr "type" "branch")]
0d66636f 8123)
9c08d1fa 8124
d3373b54 8125(define_expand "call"
8126 [(parallel [(call (match_operand 0 "memory_operand" "")
8127 (match_operand 1 "general_operand" ""))
cffb2a26 8128 (use (match_operand 2 "" ""))
bd5b4116 8129 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 8130 "TARGET_EITHER"
6c4c2133 8131 "
8132 {
bac7fc85 8133 rtx callee, pat;
2d3a01a7 8134 tree addr = MEM_EXPR (operands[0]);
bbe777ea 8135
bbe777ea 8136 /* In an untyped call, we can get NULL for operand 2. */
8137 if (operands[2] == NULL_RTX)
8138 operands[2] = const0_rtx;
8139
de55252a 8140 /* Decide if we should generate indirect calls by loading the
85c36fd1 8141 32-bit address of the callee into a register before performing the
de55252a 8142 branch and link. */
8143 callee = XEXP (operands[0], 0);
8144 if (GET_CODE (callee) == SYMBOL_REF
8145 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
8146 : !REG_P (callee))
bbe777ea 8147 XEXP (operands[0], 0) = force_reg (Pmode, callee);
bac7fc85 8148
2d3a01a7 8149 if (detect_cmse_nonsecure_call (addr))
8150 {
8151 pat = gen_nonsecure_call_internal (operands[0], operands[1],
8152 operands[2]);
8153 emit_call_insn (pat);
8154 }
8155 else
8156 {
8157 pat = gen_call_internal (operands[0], operands[1], operands[2]);
8158 arm_emit_call_insn (pat, XEXP (operands[0], 0), false);
8159 }
bac7fc85 8160 DONE;
6c4c2133 8161 }"
8162)
d3373b54 8163
bac7fc85 8164(define_expand "call_internal"
8165 [(parallel [(call (match_operand 0 "memory_operand" "")
8166 (match_operand 1 "general_operand" ""))
8167 (use (match_operand 2 "" ""))
8168 (clobber (reg:SI LR_REGNUM))])])
8169
2d3a01a7 8170(define_expand "nonsecure_call_internal"
8171 [(parallel [(call (unspec:SI [(match_operand 0 "memory_operand" "")]
8172 UNSPEC_NONSECURE_MEM)
8173 (match_operand 1 "general_operand" ""))
8174 (use (match_operand 2 "" ""))
8175 (clobber (reg:SI LR_REGNUM))
8176 (clobber (reg:SI 4))])]
8177 "use_cmse"
8178 "
8179 {
8180 rtx tmp;
8181 tmp = copy_to_suggested_reg (XEXP (operands[0], 0),
8182 gen_rtx_REG (SImode, 4),
8183 SImode);
8184
8185 operands[0] = replace_equiv_address (operands[0], tmp);
8186 }")
8187
f1039640 8188(define_insn "*call_reg_armv5"
d3373b54 8189 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
cffb2a26 8190 (match_operand 1 "" ""))
8191 (use (match_operand 2 "" ""))
bd5b4116 8192 (clobber (reg:SI LR_REGNUM))]
33ae7c4b 8193 "TARGET_ARM && arm_arch5 && !SIBLING_CALL_P (insn)"
f1039640 8194 "blx%?\\t%0"
8195 [(set_attr "type" "call")]
8196)
8197
8198(define_insn "*call_reg_arm"
8199 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
8200 (match_operand 1 "" ""))
8201 (use (match_operand 2 "" ""))
8202 (clobber (reg:SI LR_REGNUM))]
33ae7c4b 8203 "TARGET_ARM && !arm_arch5 && !SIBLING_CALL_P (insn)"
9c08d1fa 8204 "*
5565501b 8205 return output_call (operands);
cffb2a26 8206 "
8207 ;; length is worst case, normally it is only two
8208 [(set_attr "length" "12")
8209 (set_attr "type" "call")]
8210)
9c08d1fa 8211
89504fc1 8212
d3373b54 8213(define_expand "call_value"
e0698af7 8214 [(parallel [(set (match_operand 0 "" "")
8215 (call (match_operand 1 "memory_operand" "")
8216 (match_operand 2 "general_operand" "")))
cffb2a26 8217 (use (match_operand 3 "" ""))
bd5b4116 8218 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 8219 "TARGET_EITHER"
6c4c2133 8220 "
8221 {
bac7fc85 8222 rtx pat, callee;
2d3a01a7 8223 tree addr = MEM_EXPR (operands[1]);
bbe777ea 8224
8225 /* In an untyped call, we can get NULL for operand 2. */
8226 if (operands[3] == 0)
8227 operands[3] = const0_rtx;
8228
de55252a 8229 /* Decide if we should generate indirect calls by loading the
8230 32-bit address of the callee into a register before performing the
8231 branch and link. */
8232 callee = XEXP (operands[1], 0);
8233 if (GET_CODE (callee) == SYMBOL_REF
8234 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
8235 : !REG_P (callee))
78fe751b 8236 XEXP (operands[1], 0) = force_reg (Pmode, callee);
bac7fc85 8237
2d3a01a7 8238 if (detect_cmse_nonsecure_call (addr))
8239 {
8240 pat = gen_nonsecure_call_value_internal (operands[0], operands[1],
8241 operands[2], operands[3]);
8242 emit_call_insn (pat);
8243 }
8244 else
8245 {
8246 pat = gen_call_value_internal (operands[0], operands[1],
8247 operands[2], operands[3]);
8248 arm_emit_call_insn (pat, XEXP (operands[1], 0), false);
8249 }
bac7fc85 8250 DONE;
6c4c2133 8251 }"
8252)
d3373b54 8253
bac7fc85 8254(define_expand "call_value_internal"
8255 [(parallel [(set (match_operand 0 "" "")
8256 (call (match_operand 1 "memory_operand" "")
8257 (match_operand 2 "general_operand" "")))
8258 (use (match_operand 3 "" ""))
8259 (clobber (reg:SI LR_REGNUM))])])
8260
2d3a01a7 8261(define_expand "nonsecure_call_value_internal"
8262 [(parallel [(set (match_operand 0 "" "")
8263 (call (unspec:SI [(match_operand 1 "memory_operand" "")]
8264 UNSPEC_NONSECURE_MEM)
8265 (match_operand 2 "general_operand" "")))
8266 (use (match_operand 3 "" ""))
8267 (clobber (reg:SI LR_REGNUM))
8268 (clobber (reg:SI 4))])]
8269 "use_cmse"
8270 "
8271 {
8272 rtx tmp;
8273 tmp = copy_to_suggested_reg (XEXP (operands[1], 0),
8274 gen_rtx_REG (SImode, 4),
8275 SImode);
8276
8277 operands[1] = replace_equiv_address (operands[1], tmp);
8278 }")
8279
f1039640 8280(define_insn "*call_value_reg_armv5"
27ed6835 8281 [(set (match_operand 0 "" "")
755eb2b4 8282 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
cffb2a26 8283 (match_operand 2 "" "")))
bbe777ea 8284 (use (match_operand 3 "" ""))
bd5b4116 8285 (clobber (reg:SI LR_REGNUM))]
33ae7c4b 8286 "TARGET_ARM && arm_arch5 && !SIBLING_CALL_P (insn)"
f1039640 8287 "blx%?\\t%1"
8288 [(set_attr "type" "call")]
8289)
8290
8291(define_insn "*call_value_reg_arm"
8292 [(set (match_operand 0 "" "")
8293 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
8294 (match_operand 2 "" "")))
8295 (use (match_operand 3 "" ""))
8296 (clobber (reg:SI LR_REGNUM))]
33ae7c4b 8297 "TARGET_ARM && !arm_arch5 && !SIBLING_CALL_P (insn)"
9c08d1fa 8298 "*
215b30b3 8299 return output_call (&operands[1]);
cffb2a26 8300 "
8301 [(set_attr "length" "12")
8302 (set_attr "type" "call")]
8303)
9c08d1fa 8304
9c08d1fa 8305;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
8306;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
8307
f7fbdd4a 8308(define_insn "*call_symbol"
27ed6835 8309 [(call (mem:SI (match_operand:SI 0 "" ""))
cffb2a26 8310 (match_operand 1 "" ""))
bbe777ea 8311 (use (match_operand 2 "" ""))
bd5b4116 8312 (clobber (reg:SI LR_REGNUM))]
d68c2c10 8313 "TARGET_32BIT
33ae7c4b 8314 && !SIBLING_CALL_P (insn)
cffb2a26 8315 && (GET_CODE (operands[0]) == SYMBOL_REF)
de55252a 8316 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
6ebaa29d 8317 "*
8318 {
95f1e0d1 8319 rtx op = operands[0];
8320
8321 /* Switch mode now when possible. */
8322 if (SYMBOL_REF_DECL (op) && !TREE_PUBLIC (SYMBOL_REF_DECL (op))
8323 && arm_arch5 && arm_change_mode_p (SYMBOL_REF_DECL (op)))
8324 return NEED_PLT_RELOC ? \"blx%?\\t%a0(PLT)\" : \"blx%?\\t(%a0)\";
8325
55c1e470 8326 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
6ebaa29d 8327 }"
cffb2a26 8328 [(set_attr "type" "call")]
8329)
9c08d1fa 8330
f7fbdd4a 8331(define_insn "*call_value_symbol"
ccd90aaa 8332 [(set (match_operand 0 "" "")
27ed6835 8333 (call (mem:SI (match_operand:SI 1 "" ""))
dd6d7504 8334 (match_operand:SI 2 "" "")))
bbe777ea 8335 (use (match_operand 3 "" ""))
bd5b4116 8336 (clobber (reg:SI LR_REGNUM))]
d68c2c10 8337 "TARGET_32BIT
33ae7c4b 8338 && !SIBLING_CALL_P (insn)
cffb2a26 8339 && (GET_CODE (operands[1]) == SYMBOL_REF)
de55252a 8340 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
6ebaa29d 8341 "*
8342 {
95f1e0d1 8343 rtx op = operands[1];
8344
8345 /* Switch mode now when possible. */
8346 if (SYMBOL_REF_DECL (op) && !TREE_PUBLIC (SYMBOL_REF_DECL (op))
8347 && arm_arch5 && arm_change_mode_p (SYMBOL_REF_DECL (op)))
3f6b66fa 8348 return NEED_PLT_RELOC ? \"blx%?\\t%a1(PLT)\" : \"blx%?\\t(%a1)\";
95f1e0d1 8349
55c1e470 8350 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
6ebaa29d 8351 }"
cffb2a26 8352 [(set_attr "type" "call")]
8353)
8354
ca373797 8355(define_expand "sibcall_internal"
8356 [(parallel [(call (match_operand 0 "memory_operand" "")
8357 (match_operand 1 "general_operand" ""))
8358 (return)
8359 (use (match_operand 2 "" ""))])])
8360
1c494086 8361;; We may also be able to do sibcalls for Thumb, but it's much harder...
8362(define_expand "sibcall"
8363 [(parallel [(call (match_operand 0 "memory_operand" "")
8364 (match_operand 1 "general_operand" ""))
2ba80634 8365 (return)
8366 (use (match_operand 2 "" ""))])]
d68c2c10 8367 "TARGET_32BIT"
1c494086 8368 "
8369 {
ca373797 8370 rtx pat;
8371
3112c3f7 8372 if ((!REG_P (XEXP (operands[0], 0))
8373 && GET_CODE (XEXP (operands[0], 0)) != SYMBOL_REF)
8374 || (GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
8375 && arm_is_long_call_p (SYMBOL_REF_DECL (XEXP (operands[0], 0)))))
33ae7c4b 8376 XEXP (operands[0], 0) = force_reg (SImode, XEXP (operands[0], 0));
8377
1c494086 8378 if (operands[2] == NULL_RTX)
8379 operands[2] = const0_rtx;
ca373797 8380
8381 pat = gen_sibcall_internal (operands[0], operands[1], operands[2]);
8382 arm_emit_call_insn (pat, operands[0], true);
8383 DONE;
1c494086 8384 }"
8385)
8386
ca373797 8387(define_expand "sibcall_value_internal"
8388 [(parallel [(set (match_operand 0 "" "")
8389 (call (match_operand 1 "memory_operand" "")
8390 (match_operand 2 "general_operand" "")))
8391 (return)
8392 (use (match_operand 3 "" ""))])])
8393
1c494086 8394(define_expand "sibcall_value"
ccd90aaa 8395 [(parallel [(set (match_operand 0 "" "")
1c494086 8396 (call (match_operand 1 "memory_operand" "")
8397 (match_operand 2 "general_operand" "")))
2ba80634 8398 (return)
8399 (use (match_operand 3 "" ""))])]
d68c2c10 8400 "TARGET_32BIT"
1c494086 8401 "
8402 {
ca373797 8403 rtx pat;
8404
3112c3f7 8405 if ((!REG_P (XEXP (operands[1], 0))
8406 && GET_CODE (XEXP (operands[1], 0)) != SYMBOL_REF)
8407 || (GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
8408 && arm_is_long_call_p (SYMBOL_REF_DECL (XEXP (operands[1], 0)))))
33ae7c4b 8409 XEXP (operands[1], 0) = force_reg (SImode, XEXP (operands[1], 0));
8410
1c494086 8411 if (operands[3] == NULL_RTX)
8412 operands[3] = const0_rtx;
ca373797 8413
8414 pat = gen_sibcall_value_internal (operands[0], operands[1],
8415 operands[2], operands[3]);
8416 arm_emit_call_insn (pat, operands[1], true);
8417 DONE;
1c494086 8418 }"
8419)
8420
8421(define_insn "*sibcall_insn"
84ce8e5c 8422 [(call (mem:SI (match_operand:SI 0 "call_insn_operand" "Cs, US"))
1c494086 8423 (match_operand 1 "" ""))
2ba80634 8424 (return)
8425 (use (match_operand 2 "" ""))]
33ae7c4b 8426 "TARGET_32BIT && SIBLING_CALL_P (insn)"
1c494086 8427 "*
33ae7c4b 8428 if (which_alternative == 1)
8429 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
8430 else
8431 {
8432 if (arm_arch5 || arm_arch4t)
947d113e 8433 return \"bx%?\\t%0\\t%@ indirect register sibling call\";
33ae7c4b 8434 else
8435 return \"mov%?\\t%|pc, %0\\t%@ indirect register sibling call\";
8436 }
1c494086 8437 "
8438 [(set_attr "type" "call")]
8439)
8440
8441(define_insn "*sibcall_value_insn"
84ce8e5c 8442 [(set (match_operand 0 "" "")
8443 (call (mem:SI (match_operand:SI 1 "call_insn_operand" "Cs,US"))
1c494086 8444 (match_operand 2 "" "")))
2ba80634 8445 (return)
8446 (use (match_operand 3 "" ""))]
33ae7c4b 8447 "TARGET_32BIT && SIBLING_CALL_P (insn)"
1c494086 8448 "*
33ae7c4b 8449 if (which_alternative == 1)
8450 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
8451 else
8452 {
8453 if (arm_arch5 || arm_arch4t)
84ce8e5c 8454 return \"bx%?\\t%1\";
33ae7c4b 8455 else
8456 return \"mov%?\\t%|pc, %1\\t@ indirect sibling call \";
8457 }
1c494086 8458 "
8459 [(set_attr "type" "call")]
8460)
8461
0686440e 8462(define_expand "<return_str>return"
9b23f0a7 8463 [(RETURNS)]
8cba51a5 8464 "(TARGET_ARM || (TARGET_THUMB2
8465 && ARM_FUNC_TYPE (arm_current_func_type ()) == ARM_FT_NORMAL
8466 && !IS_STACKALIGN (arm_current_func_type ())))
0686440e 8467 <return_cond_false>"
8cba51a5 8468 "
8469 {
8470 if (TARGET_THUMB2)
8471 {
0686440e 8472 thumb2_expand_return (<return_simple_p>);
8cba51a5 8473 DONE;
8474 }
8475 }
8476 "
8477)
d68c2c10 8478
9c08d1fa 8479;; Often the return insn will be the same as loading from memory, so set attr
d68c2c10 8480(define_insn "*arm_return"
9c08d1fa 8481 [(return)]
cffb2a26 8482 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
9c08d1fa 8483 "*
9c08d1fa 8484 {
cffb2a26 8485 if (arm_ccfsm_state == 2)
8486 {
8487 arm_ccfsm_state += 2;
8488 return \"\";
8489 }
e2549f81 8490 return output_return_instruction (const_true_rtx, true, false, false);
cffb2a26 8491 }"
9f2c2a36 8492 [(set_attr "type" "load_4")
755eb2b4 8493 (set_attr "length" "12")
0d66636f 8494 (set_attr "predicable" "yes")]
cffb2a26 8495)
9c08d1fa 8496
0686440e 8497(define_insn "*cond_<return_str>return"
9c08d1fa 8498 [(set (pc)
8fa3ba89 8499 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 8500 [(match_operand 1 "cc_register" "") (const_int 0)])
9b23f0a7 8501 (RETURNS)
9c08d1fa 8502 (pc)))]
0686440e 8503 "TARGET_ARM <return_cond_true>"
9c08d1fa 8504 "*
8fa3ba89 8505 {
8506 if (arm_ccfsm_state == 2)
8507 {
8508 arm_ccfsm_state += 2;
8509 return \"\";
8510 }
0686440e 8511 return output_return_instruction (operands[0], true, false,
8512 <return_simple_p>);
8fa3ba89 8513 }"
8514 [(set_attr "conds" "use")
755eb2b4 8515 (set_attr "length" "12")
9f2c2a36 8516 (set_attr "type" "load_4")]
8fa3ba89 8517)
9c08d1fa 8518
0686440e 8519(define_insn "*cond_<return_str>return_inverted"
9c08d1fa 8520 [(set (pc)
8fa3ba89 8521 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 8522 [(match_operand 1 "cc_register" "") (const_int 0)])
9c08d1fa 8523 (pc)
9b23f0a7 8524 (RETURNS)))]
0686440e 8525 "TARGET_ARM <return_cond_true>"
9c08d1fa 8526 "*
8fa3ba89 8527 {
8528 if (arm_ccfsm_state == 2)
8529 {
8530 arm_ccfsm_state += 2;
8531 return \"\";
8532 }
0686440e 8533 return output_return_instruction (operands[0], true, true,
8534 <return_simple_p>);
8fa3ba89 8535 }"
8536 [(set_attr "conds" "use")
37a1317b 8537 (set_attr "length" "12")
9f2c2a36 8538 (set_attr "type" "load_4")]
8fa3ba89 8539)
9c08d1fa 8540
e2549f81 8541(define_insn "*arm_simple_return"
8542 [(simple_return)]
8543 "TARGET_ARM"
8544 "*
8545 {
8546 if (arm_ccfsm_state == 2)
8547 {
8548 arm_ccfsm_state += 2;
8549 return \"\";
8550 }
8551 return output_return_instruction (const_true_rtx, true, false, true);
8552 }"
8553 [(set_attr "type" "branch")
8554 (set_attr "length" "4")
8555 (set_attr "predicable" "yes")]
8556)
8557
68121397 8558;; Generate a sequence of instructions to determine if the processor is
8559;; in 26-bit or 32-bit mode, and return the appropriate return address
8560;; mask.
8561
8562(define_expand "return_addr_mask"
8563 [(set (match_dup 1)
8564 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8565 (const_int 0)))
8566 (set (match_operand:SI 0 "s_register_operand" "")
8567 (if_then_else:SI (eq (match_dup 1) (const_int 0))
8568 (const_int -1)
8569 (const_int 67108860)))] ; 0x03fffffc
8570 "TARGET_ARM"
8571 "
62eddbd4 8572 operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
68121397 8573 ")
8574
8575(define_insn "*check_arch2"
8576 [(set (match_operand:CC_NOOV 0 "cc_register" "")
8577 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8578 (const_int 0)))]
8579 "TARGET_ARM"
8580 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
8581 [(set_attr "length" "8")
1b7da4ac 8582 (set_attr "conds" "set")
8583 (set_attr "type" "multiple")]
68121397 8584)
8585
9c08d1fa 8586;; Call subroutine returning any type.
8587
8588(define_expand "untyped_call"
8589 [(parallel [(call (match_operand 0 "" "")
8590 (const_int 0))
8591 (match_operand 1 "" "")
8592 (match_operand 2 "" "")])]
ccd90aaa 8593 "TARGET_EITHER"
9c08d1fa 8594 "
215b30b3 8595 {
8596 int i;
ccd90aaa 8597 rtx par = gen_rtx_PARALLEL (VOIDmode,
8598 rtvec_alloc (XVECLEN (operands[2], 0)));
8599 rtx addr = gen_reg_rtx (Pmode);
8600 rtx mem;
8601 int size = 0;
9c08d1fa 8602
ccd90aaa 8603 emit_move_insn (addr, XEXP (operands[1], 0));
8604 mem = change_address (operands[1], BLKmode, addr);
9c08d1fa 8605
215b30b3 8606 for (i = 0; i < XVECLEN (operands[2], 0); i++)
8607 {
ccd90aaa 8608 rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
9c08d1fa 8609
ccd90aaa 8610 /* Default code only uses r0 as a return value, but we could
8611 be using anything up to 4 registers. */
8612 if (REGNO (src) == R0_REGNUM)
8613 src = gen_rtx_REG (TImode, R0_REGNUM);
8614
8615 XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
8616 GEN_INT (size));
8617 size += GET_MODE_SIZE (GET_MODE (src));
8618 }
8619
7f265a08 8620 emit_call_insn (gen_call_value (par, operands[0], const0_rtx, NULL));
ccd90aaa 8621
8622 size = 0;
8623
8624 for (i = 0; i < XVECLEN (par, 0); i++)
8625 {
8626 HOST_WIDE_INT offset = 0;
8627 rtx reg = XEXP (XVECEXP (par, 0, i), 0);
8628
8629 if (size != 0)
29c05e22 8630 emit_move_insn (addr, plus_constant (Pmode, addr, size));
ccd90aaa 8631
8632 mem = change_address (mem, GET_MODE (reg), NULL);
8633 if (REGNO (reg) == R0_REGNUM)
8634 {
8635 /* On thumb we have to use a write-back instruction. */
320ea44d 8636 emit_insn (arm_gen_store_multiple (arm_regs_in_sequence, 4, addr,
8637 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
ccd90aaa 8638 size = TARGET_ARM ? 16 : 0;
8639 }
8640 else
8641 {
8642 emit_move_insn (mem, reg);
8643 size = GET_MODE_SIZE (GET_MODE (reg));
8644 }
215b30b3 8645 }
9c08d1fa 8646
215b30b3 8647 /* The optimizer does not know that the call sets the function value
8648 registers we stored in the result block. We avoid problems by
8649 claiming that all hard registers are used and clobbered at this
8650 point. */
8651 emit_insn (gen_blockage ());
8652
8653 DONE;
8654 }"
8655)
9c08d1fa 8656
ccd90aaa 8657(define_expand "untyped_return"
8658 [(match_operand:BLK 0 "memory_operand" "")
8659 (match_operand 1 "" "")]
8660 "TARGET_EITHER"
8661 "
8662 {
8663 int i;
8664 rtx addr = gen_reg_rtx (Pmode);
8665 rtx mem;
8666 int size = 0;
8667
8668 emit_move_insn (addr, XEXP (operands[0], 0));
8669 mem = change_address (operands[0], BLKmode, addr);
8670
8671 for (i = 0; i < XVECLEN (operands[1], 0); i++)
8672 {
8673 HOST_WIDE_INT offset = 0;
8674 rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
8675
8676 if (size != 0)
29c05e22 8677 emit_move_insn (addr, plus_constant (Pmode, addr, size));
ccd90aaa 8678
8679 mem = change_address (mem, GET_MODE (reg), NULL);
8680 if (REGNO (reg) == R0_REGNUM)
8681 {
8682 /* On thumb we have to use a write-back instruction. */
320ea44d 8683 emit_insn (arm_gen_load_multiple (arm_regs_in_sequence, 4, addr,
8684 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
ccd90aaa 8685 size = TARGET_ARM ? 16 : 0;
8686 }
8687 else
8688 {
8689 emit_move_insn (reg, mem);
8690 size = GET_MODE_SIZE (GET_MODE (reg));
8691 }
8692 }
8693
8694 /* Emit USE insns before the return. */
8695 for (i = 0; i < XVECLEN (operands[1], 0); i++)
18b42941 8696 emit_use (SET_DEST (XVECEXP (operands[1], 0, i)));
ccd90aaa 8697
8698 /* Construct the return. */
8699 expand_naked_return ();
8700
8701 DONE;
8702 }"
8703)
8704
9c08d1fa 8705;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
8706;; all of memory. This blocks insns from being moved across this point.
8707
8708(define_insn "blockage"
e1159bbe 8709 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
cffb2a26 8710 "TARGET_EITHER"
9c08d1fa 8711 ""
cffb2a26 8712 [(set_attr "length" "0")
8713 (set_attr "type" "block")]
8714)
9c08d1fa 8715
706dca65 8716(define_insn "probe_stack"
f8570abe 8717 [(set (match_operand:SI 0 "memory_operand" "=m")
8718 (unspec:SI [(const_int 0)] UNSPEC_PROBE_STACK))]
706dca65 8719 "TARGET_32BIT"
154ae8e6 8720 "str%?\\tr0, %0"
9f2c2a36 8721 [(set_attr "type" "store_4")
706dca65 8722 (set_attr "predicable" "yes")]
8723)
8724
8725(define_insn "probe_stack_range"
8726 [(set (match_operand:SI 0 "register_operand" "=r")
8727 (unspec_volatile:SI [(match_operand:SI 1 "register_operand" "0")
8728 (match_operand:SI 2 "register_operand" "r")]
dd8aabc9 8729 VUNSPEC_PROBE_STACK_RANGE))]
706dca65 8730 "TARGET_32BIT"
8731{
8732 return output_probe_stack_range (operands[0], operands[2]);
8733}
8734 [(set_attr "type" "multiple")
8735 (set_attr "conds" "clob")]
8736)
8737
f7fbdd4a 8738(define_expand "casesi"
8739 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
aea4c774 8740 (match_operand:SI 1 "const_int_operand" "") ; lower bound
8741 (match_operand:SI 2 "const_int_operand" "") ; total range
f7fbdd4a 8742 (match_operand:SI 3 "" "") ; table label
8743 (match_operand:SI 4 "" "")] ; Out of range label
9753b549 8744 "(TARGET_32BIT || optimize_size || flag_pic) && !target_pure_code"
f7fbdd4a 8745 "
215b30b3 8746 {
e6ac8414 8747 enum insn_code code;
215b30b3 8748 if (operands[1] != const0_rtx)
8749 {
e6ac8414 8750 rtx reg = gen_reg_rtx (SImode);
f7fbdd4a 8751
215b30b3 8752 emit_insn (gen_addsi3 (reg, operands[0],
d022fa24 8753 gen_int_mode (-INTVAL (operands[1]),
8754 SImode)));
215b30b3 8755 operands[0] = reg;
8756 }
9c08d1fa 8757
25f905c2 8758 if (TARGET_ARM)
e6ac8414 8759 code = CODE_FOR_arm_casesi_internal;
3db2019b 8760 else if (TARGET_THUMB1)
e6ac8414 8761 code = CODE_FOR_thumb1_casesi_internal_pic;
25f905c2 8762 else if (flag_pic)
e6ac8414 8763 code = CODE_FOR_thumb2_casesi_internal_pic;
25f905c2 8764 else
e6ac8414 8765 code = CODE_FOR_thumb2_casesi_internal;
8766
8767 if (!insn_data[(int) code].operand[1].predicate(operands[2], SImode))
8768 operands[2] = force_reg (SImode, operands[2]);
8769
8770 emit_jump_insn (GEN_FCN ((int) code) (operands[0], operands[2],
8771 operands[3], operands[4]));
215b30b3 8772 DONE;
8773 }"
8774)
f7fbdd4a 8775
f082f1c4 8776;; The USE in this pattern is needed to tell flow analysis that this is
8777;; a CASESI insn. It has no other purpose.
25f905c2 8778(define_insn "arm_casesi_internal"
f082f1c4 8779 [(parallel [(set (pc)
8780 (if_then_else
8781 (leu (match_operand:SI 0 "s_register_operand" "r")
8782 (match_operand:SI 1 "arm_rhs_operand" "rI"))
8783 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
8784 (label_ref (match_operand 2 "" ""))))
8785 (label_ref (match_operand 3 "" ""))))
bd5b4116 8786 (clobber (reg:CC CC_REGNUM))
f082f1c4 8787 (use (label_ref (match_dup 2)))])]
cffb2a26 8788 "TARGET_ARM"
f7fbdd4a 8789 "*
0d66636f 8790 if (flag_pic)
8791 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
8792 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
8793 "
8794 [(set_attr "conds" "clob")
1b7da4ac 8795 (set_attr "length" "12")
8796 (set_attr "type" "multiple")]
0d66636f 8797)
9c08d1fa 8798
cffb2a26 8799(define_expand "indirect_jump"
9c08d1fa 8800 [(set (pc)
cffb2a26 8801 (match_operand:SI 0 "s_register_operand" ""))]
8802 "TARGET_EITHER"
25f905c2 8803 "
8804 /* Thumb-2 doesn't have mov pc, reg. Explicitly set the low bit of the
8805 address and use bx. */
8806 if (TARGET_THUMB2)
8807 {
8808 rtx tmp;
8809 tmp = gen_reg_rtx (SImode);
8810 emit_insn (gen_iorsi3 (tmp, operands[0], GEN_INT(1)));
8811 operands[0] = tmp;
8812 }
8813 "
cffb2a26 8814)
8815
f1039640 8816;; NB Never uses BX.
cffb2a26 8817(define_insn "*arm_indirect_jump"
8818 [(set (pc)
8819 (match_operand:SI 0 "s_register_operand" "r"))]
8820 "TARGET_ARM"
8821 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
1b7da4ac 8822 [(set_attr "predicable" "yes")
8823 (set_attr "type" "branch")]
cffb2a26 8824)
9c08d1fa 8825
f7fbdd4a 8826(define_insn "*load_indirect_jump"
9c08d1fa 8827 [(set (pc)
8828 (match_operand:SI 0 "memory_operand" "m"))]
cffb2a26 8829 "TARGET_ARM"
8830 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
9f2c2a36 8831 [(set_attr "type" "load_4")
61a2d04c 8832 (set_attr "pool_range" "4096")
8833 (set_attr "neg_pool_range" "4084")
0d66636f 8834 (set_attr "predicable" "yes")]
cffb2a26 8835)
8836
9c08d1fa 8837\f
8838;; Misc insns
8839
8840(define_insn "nop"
8841 [(const_int 0)]
cffb2a26 8842 "TARGET_EITHER"
3ef90e77 8843 "nop"
cffb2a26 8844 [(set (attr "length")
8845 (if_then_else (eq_attr "is_thumb" "yes")
8846 (const_int 2)
1b7da4ac 8847 (const_int 4)))
8848 (set_attr "type" "mov_reg")]
cffb2a26 8849)
8850
ad9d4399 8851(define_insn "trap"
8852 [(trap_if (const_int 1) (const_int 0))]
8853 ""
8854 "*
8855 if (TARGET_ARM)
8856 return \".inst\\t0xe7f000f0\";
8857 else
8858 return \".inst\\t0xdeff\";
8859 "
8860 [(set (attr "length")
8861 (if_then_else (eq_attr "is_thumb" "yes")
8862 (const_int 2)
8863 (const_int 4)))
8864 (set_attr "type" "trap")
8865 (set_attr "conds" "unconditional")]
8866)
8867
9c08d1fa 8868\f
8869;; Patterns to allow combination of arithmetic, cond code and shifts
8870
0abea32c 8871(define_insn "*<arith_shift_insn>_multsi"
8872 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9b23f0a7 8873 (SHIFTABLE_OPS:SI
0abea32c 8874 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
8875 (match_operand:SI 3 "power_of_two_operand" ""))
8876 (match_operand:SI 1 "s_register_operand" "rk,<t2_binop0>")))]
d5d4dc8d 8877 "TARGET_32BIT"
0abea32c 8878 "<arith_shift_insn>%?\\t%0, %1, %2, lsl %b3"
8879 [(set_attr "predicable" "yes")
8880 (set_attr "predicable_short_it" "no")
753d9835 8881 (set_attr "shift" "2")
0abea32c 8882 (set_attr "arch" "a,t2")
8883 (set_attr "type" "alu_shift_imm")])
8884
8885(define_insn "*<arith_shift_insn>_shiftsi"
8886 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9b23f0a7 8887 (SHIFTABLE_OPS:SI
0abea32c 8888 (match_operator:SI 2 "shift_nomul_operator"
8889 [(match_operand:SI 3 "s_register_operand" "r,r,r")
8890 (match_operand:SI 4 "shift_amount_operand" "M,M,r")])
8891 (match_operand:SI 1 "s_register_operand" "rk,<t2_binop0>,rk")))]
a021b821 8892 "TARGET_32BIT && GET_CODE (operands[2]) != MULT"
0abea32c 8893 "<arith_shift_insn>%?\\t%0, %1, %3%S2"
344495ea 8894 [(set_attr "predicable" "yes")
74ef923b 8895 (set_attr "predicable_short_it" "no")
753d9835 8896 (set_attr "shift" "3")
0abea32c 8897 (set_attr "arch" "a,t2,a")
8898 (set_attr "type" "alu_shift_imm,alu_shift_imm,alu_shift_reg")])
9c08d1fa 8899
d7863cfe 8900(define_split
8901 [(set (match_operand:SI 0 "s_register_operand" "")
8902 (match_operator:SI 1 "shiftable_operator"
8903 [(match_operator:SI 2 "shiftable_operator"
8904 [(match_operator:SI 3 "shift_operator"
8905 [(match_operand:SI 4 "s_register_operand" "")
8906 (match_operand:SI 5 "reg_or_int_operand" "")])
8907 (match_operand:SI 6 "s_register_operand" "")])
8908 (match_operand:SI 7 "arm_rhs_operand" "")]))
8909 (clobber (match_operand:SI 8 "s_register_operand" ""))]
d5d4dc8d 8910 "TARGET_32BIT"
d7863cfe 8911 [(set (match_dup 8)
8912 (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8913 (match_dup 6)]))
8914 (set (match_dup 0)
8915 (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
8916 "")
8917
f7fbdd4a 8918(define_insn "*arith_shiftsi_compare0"
bd5b4116 8919 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 8920 (compare:CC_NOOV
8921 (match_operator:SI 1 "shiftable_operator"
8922 [(match_operator:SI 3 "shift_operator"
8923 [(match_operand:SI 4 "s_register_operand" "r,r")
8924 (match_operand:SI 5 "shift_amount_operand" "M,r")])
8925 (match_operand:SI 2 "s_register_operand" "r,r")])
8926 (const_int 0)))
8927 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 8928 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8929 (match_dup 2)]))]
d5d4dc8d 8930 "TARGET_32BIT"
3ef90e77 8931 "%i1s%?\\t%0, %2, %4%S3"
344495ea 8932 [(set_attr "conds" "set")
331beb1a 8933 (set_attr "shift" "4")
d5d4dc8d 8934 (set_attr "arch" "32,a")
d82e788e 8935 (set_attr "type" "alus_shift_imm,alus_shift_reg")])
9c08d1fa 8936
f7fbdd4a 8937(define_insn "*arith_shiftsi_compare0_scratch"
bd5b4116 8938 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 8939 (compare:CC_NOOV
8940 (match_operator:SI 1 "shiftable_operator"
8941 [(match_operator:SI 3 "shift_operator"
8942 [(match_operand:SI 4 "s_register_operand" "r,r")
8943 (match_operand:SI 5 "shift_amount_operand" "M,r")])
8944 (match_operand:SI 2 "s_register_operand" "r,r")])
8945 (const_int 0)))
8946 (clobber (match_scratch:SI 0 "=r,r"))]
8947 "TARGET_32BIT"
3ef90e77 8948 "%i1s%?\\t%0, %2, %4%S3"
344495ea 8949 [(set_attr "conds" "set")
331beb1a 8950 (set_attr "shift" "4")
d5d4dc8d 8951 (set_attr "arch" "32,a")
d82e788e 8952 (set_attr "type" "alus_shift_imm,alus_shift_reg")])
9c08d1fa 8953
f7fbdd4a 8954(define_insn "*sub_shiftsi"
d5d4dc8d 8955 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8956 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
9c08d1fa 8957 (match_operator:SI 2 "shift_operator"
d5d4dc8d 8958 [(match_operand:SI 3 "s_register_operand" "r,r")
8959 (match_operand:SI 4 "shift_amount_operand" "M,r")])))]
8960 "TARGET_32BIT"
6c4c2133 8961 "sub%?\\t%0, %1, %3%S2"
344495ea 8962 [(set_attr "predicable" "yes")
331beb1a 8963 (set_attr "shift" "3")
d5d4dc8d 8964 (set_attr "arch" "32,a")
d82e788e 8965 (set_attr "type" "alus_shift_imm,alus_shift_reg")])
9c08d1fa 8966
f7fbdd4a 8967(define_insn "*sub_shiftsi_compare0"
bd5b4116 8968 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 8969 (compare:CC_NOOV
d82e788e 8970 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
40dbec34 8971 (match_operator:SI 2 "shift_operator"
d82e788e 8972 [(match_operand:SI 3 "s_register_operand" "r,r,r")
8973 (match_operand:SI 4 "shift_amount_operand" "M,r,M")]))
40dbec34 8974 (const_int 0)))
d82e788e 8975 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
d5d4dc8d 8976 (minus:SI (match_dup 1)
8977 (match_op_dup 2 [(match_dup 3) (match_dup 4)])))]
8978 "TARGET_32BIT"
3ef90e77 8979 "subs%?\\t%0, %1, %3%S2"
344495ea 8980 [(set_attr "conds" "set")
a2cd141b 8981 (set_attr "shift" "3")
d82e788e 8982 (set_attr "arch" "32,a,a")
8983 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
9c08d1fa 8984
f7fbdd4a 8985(define_insn "*sub_shiftsi_compare0_scratch"
bd5b4116 8986 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 8987 (compare:CC_NOOV
d82e788e 8988 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
40dbec34 8989 (match_operator:SI 2 "shift_operator"
d82e788e 8990 [(match_operand:SI 3 "s_register_operand" "r,r,r")
8991 (match_operand:SI 4 "shift_amount_operand" "M,r,M")]))
40dbec34 8992 (const_int 0)))
d82e788e 8993 (clobber (match_scratch:SI 0 "=r,r,r"))]
d5d4dc8d 8994 "TARGET_32BIT"
3ef90e77 8995 "subs%?\\t%0, %1, %3%S2"
344495ea 8996 [(set_attr "conds" "set")
a2cd141b 8997 (set_attr "shift" "3")
d82e788e 8998 (set_attr "arch" "32,a,a")
8999 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
9c08d1fa 9000\f
9001
190efb17 9002(define_insn_and_split "*and_scc"
9c08d1fa 9003 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9004 (and:SI (match_operator:SI 1 "arm_comparison_operator"
190efb17 9005 [(match_operand 2 "cc_register" "") (const_int 0)])
9006 (match_operand:SI 3 "s_register_operand" "r")))]
cffb2a26 9007 "TARGET_ARM"
190efb17 9008 "#" ; "mov%D1\\t%0, #0\;and%d1\\t%0, %3, #1"
9009 "&& reload_completed"
9010 [(cond_exec (match_dup 5) (set (match_dup 0) (const_int 0)))
9011 (cond_exec (match_dup 4) (set (match_dup 0)
9012 (and:SI (match_dup 3) (const_int 1))))]
9013 {
3754d046 9014 machine_mode mode = GET_MODE (operands[2]);
190efb17 9015 enum rtx_code rc = GET_CODE (operands[1]);
9016
9017 /* Note that operands[4] is the same as operands[1],
9018 but with VOIDmode as the result. */
9019 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
9020 if (mode == CCFPmode || mode == CCFPEmode)
9021 rc = reverse_condition_maybe_unordered (rc);
9022 else
9023 rc = reverse_condition (rc);
9024 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
9025 }
8fa3ba89 9026 [(set_attr "conds" "use")
1b7da4ac 9027 (set_attr "type" "multiple")
8fa3ba89 9028 (set_attr "length" "8")]
9029)
9c08d1fa 9030
190efb17 9031(define_insn_and_split "*ior_scc"
9c08d1fa 9032 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
190efb17 9033 (ior:SI (match_operator:SI 1 "arm_comparison_operator"
9034 [(match_operand 2 "cc_register" "") (const_int 0)])
9035 (match_operand:SI 3 "s_register_operand" "0,?r")))]
cffb2a26 9036 "TARGET_ARM"
e2348bcb 9037 "@
190efb17 9038 orr%d1\\t%0, %3, #1
9039 #"
9040 "&& reload_completed
9041 && REGNO (operands [0]) != REGNO (operands[3])"
9042 ;; && which_alternative == 1
9043 ; mov%D1\\t%0, %3\;orr%d1\\t%0, %3, #1
9044 [(cond_exec (match_dup 5) (set (match_dup 0) (match_dup 3)))
9045 (cond_exec (match_dup 4) (set (match_dup 0)
9046 (ior:SI (match_dup 3) (const_int 1))))]
9047 {
3754d046 9048 machine_mode mode = GET_MODE (operands[2]);
190efb17 9049 enum rtx_code rc = GET_CODE (operands[1]);
9050
9051 /* Note that operands[4] is the same as operands[1],
9052 but with VOIDmode as the result. */
9053 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
9054 if (mode == CCFPmode || mode == CCFPEmode)
9055 rc = reverse_condition_maybe_unordered (rc);
9056 else
9057 rc = reverse_condition (rc);
9058 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
9059 }
8fa3ba89 9060 [(set_attr "conds" "use")
1b7da4ac 9061 (set_attr "length" "4,8")
9062 (set_attr "type" "logic_imm,multiple")]
8fa3ba89 9063)
9c08d1fa 9064
2df9477b 9065; A series of splitters for the compare_scc pattern below. Note that
9066; order is important.
9067(define_split
9068 [(set (match_operand:SI 0 "s_register_operand" "")
9069 (lt:SI (match_operand:SI 1 "s_register_operand" "")
9070 (const_int 0)))
9071 (clobber (reg:CC CC_REGNUM))]
9072 "TARGET_32BIT && reload_completed"
9073 [(set (match_dup 0) (lshiftrt:SI (match_dup 1) (const_int 31)))])
9074
9075(define_split
9076 [(set (match_operand:SI 0 "s_register_operand" "")
9077 (ge:SI (match_operand:SI 1 "s_register_operand" "")
9078 (const_int 0)))
9079 (clobber (reg:CC CC_REGNUM))]
9080 "TARGET_32BIT && reload_completed"
9081 [(set (match_dup 0) (not:SI (match_dup 1)))
9082 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 31)))])
9083
98562479 9084(define_split
9085 [(set (match_operand:SI 0 "s_register_operand" "")
9086 (eq:SI (match_operand:SI 1 "s_register_operand" "")
9087 (const_int 0)))
9088 (clobber (reg:CC CC_REGNUM))]
9089 "arm_arch5 && TARGET_32BIT"
9090 [(set (match_dup 0) (clz:SI (match_dup 1)))
9091 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 5)))]
9092)
9093
2df9477b 9094(define_split
9095 [(set (match_operand:SI 0 "s_register_operand" "")
9096 (eq:SI (match_operand:SI 1 "s_register_operand" "")
9097 (const_int 0)))
9098 (clobber (reg:CC CC_REGNUM))]
9099 "TARGET_32BIT && reload_completed"
9100 [(parallel
080c0b9a 9101 [(set (reg:CC CC_REGNUM)
9102 (compare:CC (const_int 1) (match_dup 1)))
2df9477b 9103 (set (match_dup 0)
9104 (minus:SI (const_int 1) (match_dup 1)))])
080c0b9a 9105 (cond_exec (ltu:CC (reg:CC CC_REGNUM) (const_int 0))
2df9477b 9106 (set (match_dup 0) (const_int 0)))])
9107
9108(define_split
9109 [(set (match_operand:SI 0 "s_register_operand" "")
9110 (ne:SI (match_operand:SI 1 "s_register_operand" "")
9111 (match_operand:SI 2 "const_int_operand" "")))
9112 (clobber (reg:CC CC_REGNUM))]
9113 "TARGET_32BIT && reload_completed"
9114 [(parallel
9115 [(set (reg:CC CC_REGNUM)
9116 (compare:CC (match_dup 1) (match_dup 2)))
9117 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))])
9118 (cond_exec (ne:CC (reg:CC CC_REGNUM) (const_int 0))
9119 (set (match_dup 0) (const_int 1)))]
9120{
9121 operands[3] = GEN_INT (-INTVAL (operands[2]));
9122})
9123
9124(define_split
9125 [(set (match_operand:SI 0 "s_register_operand" "")
9126 (ne:SI (match_operand:SI 1 "s_register_operand" "")
9127 (match_operand:SI 2 "arm_add_operand" "")))
9128 (clobber (reg:CC CC_REGNUM))]
9129 "TARGET_32BIT && reload_completed"
9130 [(parallel
9131 [(set (reg:CC_NOOV CC_REGNUM)
9132 (compare:CC_NOOV (minus:SI (match_dup 1) (match_dup 2))
9133 (const_int 0)))
9134 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
9135 (cond_exec (ne:CC_NOOV (reg:CC_NOOV CC_REGNUM) (const_int 0))
9136 (set (match_dup 0) (const_int 1)))])
9137
9138(define_insn_and_split "*compare_scc"
fd711051 9139 [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts")
8fa3ba89 9140 (match_operator:SI 1 "arm_comparison_operator"
5565501b 9141 [(match_operand:SI 2 "s_register_operand" "r,r")
9142 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
bd5b4116 9143 (clobber (reg:CC CC_REGNUM))]
2df9477b 9144 "TARGET_32BIT"
9145 "#"
9146 "&& reload_completed"
9147 [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 3)))
9148 (cond_exec (match_dup 4) (set (match_dup 0) (const_int 0)))
9149 (cond_exec (match_dup 5) (set (match_dup 0) (const_int 1)))]
9150{
9151 rtx tmp1;
3754d046 9152 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
2df9477b 9153 operands[2], operands[3]);
9154 enum rtx_code rc = GET_CODE (operands[1]);
e2348bcb 9155
2df9477b 9156 tmp1 = gen_rtx_REG (mode, CC_REGNUM);
080c0b9a 9157
2df9477b 9158 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
9159 if (mode == CCFPmode || mode == CCFPEmode)
9160 rc = reverse_condition_maybe_unordered (rc);
9161 else
9162 rc = reverse_condition (rc);
9163 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
1b7da4ac 9164}
9165 [(set_attr "type" "multiple")]
9166)
9c08d1fa 9167
080c0b9a 9168;; Attempt to improve the sequence generated by the compare_scc splitters
9169;; not to use conditional execution.
98562479 9170
9171;; Rd = (eq (reg1) (const_int0)) // ARMv5
9172;; clz Rd, reg1
9173;; lsr Rd, Rd, #5
080c0b9a 9174(define_peephole2
9175 [(set (reg:CC CC_REGNUM)
9176 (compare:CC (match_operand:SI 1 "register_operand" "")
98562479 9177 (const_int 0)))
9178 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
9179 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
9180 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
9181 (set (match_dup 0) (const_int 1)))]
9182 "arm_arch5 && TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)"
9183 [(set (match_dup 0) (clz:SI (match_dup 1)))
9184 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 5)))]
9185)
9186
9187;; Rd = (eq (reg1) (const_int0)) // !ARMv5
9188;; negs Rd, reg1
9189;; adc Rd, Rd, reg1
9190(define_peephole2
9191 [(set (reg:CC CC_REGNUM)
9192 (compare:CC (match_operand:SI 1 "register_operand" "")
9193 (const_int 0)))
080c0b9a 9194 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
9195 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
9196 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
9197 (set (match_dup 0) (const_int 1)))
98562479 9198 (match_scratch:SI 2 "r")]
9199 "TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)"
922b6913 9200 [(parallel
9201 [(set (reg:CC CC_REGNUM)
98562479 9202 (compare:CC (const_int 0) (match_dup 1)))
9203 (set (match_dup 2) (minus:SI (const_int 0) (match_dup 1)))])
9204 (set (match_dup 0)
9205 (plus:SI (plus:SI (match_dup 1) (match_dup 2))
9206 (geu:SI (reg:CC CC_REGNUM) (const_int 0))))]
9207)
9208
31991287 9209;; Rd = (eq (reg1) (reg2/imm)) // ARMv5 and optimising for speed.
98562479 9210;; sub Rd, Reg1, reg2
9211;; clz Rd, Rd
9212;; lsr Rd, Rd, #5
9213(define_peephole2
9214 [(set (reg:CC CC_REGNUM)
9215 (compare:CC (match_operand:SI 1 "register_operand" "")
9216 (match_operand:SI 2 "arm_rhs_operand" "")))
9217 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
9218 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
9219 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
9220 (set (match_dup 0) (const_int 1)))]
31991287 9221 "arm_arch5 && TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)
9222 && !(TARGET_THUMB2 && optimize_insn_for_size_p ())"
98562479 9223 [(set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))
9224 (set (match_dup 0) (clz:SI (match_dup 0)))
9225 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 5)))]
9226)
9227
9228
31991287 9229;; Rd = (eq (reg1) (reg2)) // ! ARMv5 or optimising for size.
98562479 9230;; sub T1, Reg1, reg2
9231;; negs Rd, T1
9232;; adc Rd, Rd, T1
9233(define_peephole2
9234 [(set (reg:CC CC_REGNUM)
9235 (compare:CC (match_operand:SI 1 "register_operand" "")
9236 (match_operand:SI 2 "arm_rhs_operand" "")))
9237 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
9238 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
9239 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
9240 (set (match_dup 0) (const_int 1)))
9241 (match_scratch:SI 3 "r")]
9242 "TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)"
31991287 9243 [(set (match_dup 3) (match_dup 4))
080c0b9a 9244 (parallel
9245 [(set (reg:CC CC_REGNUM)
9246 (compare:CC (const_int 0) (match_dup 3)))
9247 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 3)))])
98562479 9248 (set (match_dup 0)
9249 (plus:SI (plus:SI (match_dup 0) (match_dup 3))
9250 (geu:SI (reg:CC CC_REGNUM) (const_int 0))))]
31991287 9251 "
9252 if (CONST_INT_P (operands[2]))
9253 operands[4] = plus_constant (SImode, operands[1], -INTVAL (operands[2]));
9254 else
9255 operands[4] = gen_rtx_MINUS (SImode, operands[1], operands[2]);
9256 ")
080c0b9a 9257
f7fbdd4a 9258(define_insn "*cond_move"
9c08d1fa 9259 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
aea4c774 9260 (if_then_else:SI (match_operator 3 "equality_operator"
8fa3ba89 9261 [(match_operator 4 "arm_comparison_operator"
8a18b90c 9262 [(match_operand 5 "cc_register" "") (const_int 0)])
aea4c774 9263 (const_int 0)])
9264 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9265 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
cffb2a26 9266 "TARGET_ARM"
9c08d1fa 9267 "*
8fa3ba89 9268 if (GET_CODE (operands[3]) == NE)
9269 {
9270 if (which_alternative != 1)
9271 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
9272 if (which_alternative != 0)
9273 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
9274 return \"\";
9275 }
9276 if (which_alternative != 0)
9277 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9278 if (which_alternative != 1)
9279 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
9280 return \"\";
9281 "
9282 [(set_attr "conds" "use")
282b4c75 9283 (set_attr_alternative "type"
9284 [(if_then_else (match_operand 2 "const_int_operand" "")
9285 (const_string "mov_imm")
9286 (const_string "mov_reg"))
9287 (if_then_else (match_operand 1 "const_int_operand" "")
9288 (const_string "mov_imm")
9289 (const_string "mov_reg"))
9290 (const_string "multiple")])
8fa3ba89 9291 (set_attr "length" "4,4,8")]
9292)
9c08d1fa 9293
f7fbdd4a 9294(define_insn "*cond_arith"
9c08d1fa 9295 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9296 (match_operator:SI 5 "shiftable_operator"
8fa3ba89 9297 [(match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 9298 [(match_operand:SI 2 "s_register_operand" "r,r")
9299 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
9300 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 9301 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9302 "TARGET_ARM"
9c08d1fa 9303 "*
8fa3ba89 9304 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
9305 return \"%i5\\t%0, %1, %2, lsr #31\";
40dbec34 9306
8fa3ba89 9307 output_asm_insn (\"cmp\\t%2, %3\", operands);
9308 if (GET_CODE (operands[5]) == AND)
9309 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
9310 else if (GET_CODE (operands[5]) == MINUS)
9311 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
9312 else if (which_alternative != 0)
9313 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9314 return \"%i5%d4\\t%0, %1, #1\";
9315 "
9316 [(set_attr "conds" "clob")
1b7da4ac 9317 (set_attr "length" "12")
9318 (set_attr "type" "multiple")]
8fa3ba89 9319)
9c08d1fa 9320
f7fbdd4a 9321(define_insn "*cond_sub"
9c08d1fa 9322 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9323 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8fa3ba89 9324 (match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 9325 [(match_operand:SI 2 "s_register_operand" "r,r")
9326 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 9327 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9328 "TARGET_ARM"
9c08d1fa 9329 "*
8fa3ba89 9330 output_asm_insn (\"cmp\\t%2, %3\", operands);
9331 if (which_alternative != 0)
9332 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9333 return \"sub%d4\\t%0, %1, #1\";
9334 "
9335 [(set_attr "conds" "clob")
1b7da4ac 9336 (set_attr "length" "8,12")
9337 (set_attr "type" "multiple")]
8fa3ba89 9338)
9c08d1fa 9339
aea4c774 9340(define_insn "*cmp_ite0"
cffb2a26 9341 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 9342 (compare
9343 (if_then_else:SI
8fa3ba89 9344 (match_operator 4 "arm_comparison_operator"
2ff91fec 9345 [(match_operand:SI 0 "s_register_operand"
9346 "l,l,l,r,r,r,r,r,r")
9347 (match_operand:SI 1 "arm_add_operand"
9348 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
8fa3ba89 9349 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 9350 [(match_operand:SI 2 "s_register_operand"
9351 "l,r,r,l,l,r,r,r,r")
9352 (match_operand:SI 3 "arm_add_operand"
9353 "lPy,rI,L,lPy,lPy,rI,rI,L,L")])
aea4c774 9354 (const_int 0))
9355 (const_int 0)))]
2ff91fec 9356 "TARGET_32BIT"
9c08d1fa 9357 "*
aea4c774 9358 {
2ff91fec 9359 static const char * const cmp1[NUM_OF_COND_CMP][2] =
9360 {
9361 {\"cmp%d5\\t%0, %1\",
9362 \"cmp%d4\\t%2, %3\"},
9363 {\"cmn%d5\\t%0, #%n1\",
9364 \"cmp%d4\\t%2, %3\"},
9365 {\"cmp%d5\\t%0, %1\",
9366 \"cmn%d4\\t%2, #%n3\"},
9367 {\"cmn%d5\\t%0, #%n1\",
9368 \"cmn%d4\\t%2, #%n3\"}
9369 };
9370 static const char * const cmp2[NUM_OF_COND_CMP][2] =
9371 {
9372 {\"cmp\\t%2, %3\",
9373 \"cmp\\t%0, %1\"},
9374 {\"cmp\\t%2, %3\",
9375 \"cmn\\t%0, #%n1\"},
9376 {\"cmn\\t%2, #%n3\",
9377 \"cmp\\t%0, %1\"},
9378 {\"cmn\\t%2, #%n3\",
9379 \"cmn\\t%0, #%n1\"}
9380 };
9381 static const char * const ite[2] =
8fa3ba89 9382 {
2ff91fec 9383 \"it\\t%d5\",
9384 \"it\\t%d4\"
8fa3ba89 9385 };
2ff91fec 9386 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
9387 CMP_CMP, CMN_CMP, CMP_CMP,
9388 CMN_CMP, CMP_CMN, CMN_CMN};
8fa3ba89 9389 int swap =
9390 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9391
2ff91fec 9392 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9393 if (TARGET_THUMB2) {
9394 output_asm_insn (ite[swap], operands);
9395 }
9396 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9397 return \"\";
8fa3ba89 9398 }"
9399 [(set_attr "conds" "set")
2ff91fec 9400 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
1b7da4ac 9401 (set_attr "type" "multiple")
2ff91fec 9402 (set_attr_alternative "length"
9403 [(const_int 6)
9404 (const_int 8)
9405 (const_int 8)
9406 (const_int 8)
9407 (const_int 8)
9408 (if_then_else (eq_attr "is_thumb" "no")
9409 (const_int 8)
9410 (const_int 10))
9411 (if_then_else (eq_attr "is_thumb" "no")
9412 (const_int 8)
9413 (const_int 10))
9414 (if_then_else (eq_attr "is_thumb" "no")
9415 (const_int 8)
9416 (const_int 10))
9417 (if_then_else (eq_attr "is_thumb" "no")
9418 (const_int 8)
9419 (const_int 10))])]
8fa3ba89 9420)
9c08d1fa 9421
aea4c774 9422(define_insn "*cmp_ite1"
cffb2a26 9423 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 9424 (compare
9425 (if_then_else:SI
8fa3ba89 9426 (match_operator 4 "arm_comparison_operator"
2ff91fec 9427 [(match_operand:SI 0 "s_register_operand"
9428 "l,l,l,r,r,r,r,r,r")
9429 (match_operand:SI 1 "arm_add_operand"
9430 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
8fa3ba89 9431 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 9432 [(match_operand:SI 2 "s_register_operand"
9433 "l,r,r,l,l,r,r,r,r")
9434 (match_operand:SI 3 "arm_add_operand"
9435 "lPy,rI,L,lPy,lPy,rI,rI,L,L")])
aea4c774 9436 (const_int 1))
9437 (const_int 0)))]
2ff91fec 9438 "TARGET_32BIT"
9c08d1fa 9439 "*
9c08d1fa 9440 {
2ff91fec 9441 static const char * const cmp1[NUM_OF_COND_CMP][2] =
9442 {
9443 {\"cmp\\t%0, %1\",
9444 \"cmp\\t%2, %3\"},
9445 {\"cmn\\t%0, #%n1\",
9446 \"cmp\\t%2, %3\"},
9447 {\"cmp\\t%0, %1\",
9448 \"cmn\\t%2, #%n3\"},
9449 {\"cmn\\t%0, #%n1\",
9450 \"cmn\\t%2, #%n3\"}
9451 };
9452 static const char * const cmp2[NUM_OF_COND_CMP][2] =
215b30b3 9453 {
2ff91fec 9454 {\"cmp%d4\\t%2, %3\",
9455 \"cmp%D5\\t%0, %1\"},
9456 {\"cmp%d4\\t%2, %3\",
9457 \"cmn%D5\\t%0, #%n1\"},
9458 {\"cmn%d4\\t%2, #%n3\",
9459 \"cmp%D5\\t%0, %1\"},
9460 {\"cmn%d4\\t%2, #%n3\",
9461 \"cmn%D5\\t%0, #%n1\"}
215b30b3 9462 };
2ff91fec 9463 static const char * const ite[2] =
9464 {
9465 \"it\\t%d4\",
9466 \"it\\t%D5\"
9467 };
9468 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
9469 CMP_CMP, CMN_CMP, CMP_CMP,
9470 CMN_CMP, CMP_CMN, CMN_CMN};
215b30b3 9471 int swap =
9472 comparison_dominates_p (GET_CODE (operands[5]),
9473 reverse_condition (GET_CODE (operands[4])));
9474
2ff91fec 9475 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9476 if (TARGET_THUMB2) {
9477 output_asm_insn (ite[swap], operands);
9478 }
9479 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9480 return \"\";
215b30b3 9481 }"
8fa3ba89 9482 [(set_attr "conds" "set")
2ff91fec 9483 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
9484 (set_attr_alternative "length"
9485 [(const_int 6)
9486 (const_int 8)
9487 (const_int 8)
9488 (const_int 8)
9489 (const_int 8)
9490 (if_then_else (eq_attr "is_thumb" "no")
9491 (const_int 8)
9492 (const_int 10))
9493 (if_then_else (eq_attr "is_thumb" "no")
9494 (const_int 8)
9495 (const_int 10))
9496 (if_then_else (eq_attr "is_thumb" "no")
9497 (const_int 8)
9498 (const_int 10))
9499 (if_then_else (eq_attr "is_thumb" "no")
9500 (const_int 8)
1b7da4ac 9501 (const_int 10))])
9502 (set_attr "type" "multiple")]
8fa3ba89 9503)
9c08d1fa 9504
f6c53574 9505(define_insn "*cmp_and"
9506 [(set (match_operand 6 "dominant_cc_register" "")
9507 (compare
9508 (and:SI
9509 (match_operator 4 "arm_comparison_operator"
2ff91fec 9510 [(match_operand:SI 0 "s_register_operand"
9511 "l,l,l,r,r,r,r,r,r")
9512 (match_operand:SI 1 "arm_add_operand"
9513 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
f6c53574 9514 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 9515 [(match_operand:SI 2 "s_register_operand"
9516 "l,r,r,l,l,r,r,r,r")
9517 (match_operand:SI 3 "arm_add_operand"
9518 "lPy,rI,L,lPy,lPy,rI,rI,L,L")]))
f6c53574 9519 (const_int 0)))]
2ff91fec 9520 "TARGET_32BIT"
f6c53574 9521 "*
9522 {
2ff91fec 9523 static const char *const cmp1[NUM_OF_COND_CMP][2] =
f6c53574 9524 {
2ff91fec 9525 {\"cmp%d5\\t%0, %1\",
9526 \"cmp%d4\\t%2, %3\"},
9527 {\"cmn%d5\\t%0, #%n1\",
9528 \"cmp%d4\\t%2, %3\"},
9529 {\"cmp%d5\\t%0, %1\",
9530 \"cmn%d4\\t%2, #%n3\"},
9531 {\"cmn%d5\\t%0, #%n1\",
9532 \"cmn%d4\\t%2, #%n3\"}
f6c53574 9533 };
2ff91fec 9534 static const char *const cmp2[NUM_OF_COND_CMP][2] =
9535 {
9536 {\"cmp\\t%2, %3\",
9537 \"cmp\\t%0, %1\"},
9538 {\"cmp\\t%2, %3\",
9539 \"cmn\\t%0, #%n1\"},
9540 {\"cmn\\t%2, #%n3\",
9541 \"cmp\\t%0, %1\"},
9542 {\"cmn\\t%2, #%n3\",
9543 \"cmn\\t%0, #%n1\"}
9544 };
9545 static const char *const ite[2] =
9546 {
9547 \"it\\t%d5\",
9548 \"it\\t%d4\"
9549 };
9550 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
9551 CMP_CMP, CMN_CMP, CMP_CMP,
9552 CMN_CMP, CMP_CMN, CMN_CMN};
f6c53574 9553 int swap =
9554 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9555
2ff91fec 9556 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9557 if (TARGET_THUMB2) {
9558 output_asm_insn (ite[swap], operands);
9559 }
9560 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9561 return \"\";
f6c53574 9562 }"
9563 [(set_attr "conds" "set")
9564 (set_attr "predicable" "no")
2ff91fec 9565 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
9566 (set_attr_alternative "length"
9567 [(const_int 6)
9568 (const_int 8)
9569 (const_int 8)
9570 (const_int 8)
9571 (const_int 8)
9572 (if_then_else (eq_attr "is_thumb" "no")
9573 (const_int 8)
9574 (const_int 10))
9575 (if_then_else (eq_attr "is_thumb" "no")
9576 (const_int 8)
9577 (const_int 10))
9578 (if_then_else (eq_attr "is_thumb" "no")
9579 (const_int 8)
9580 (const_int 10))
9581 (if_then_else (eq_attr "is_thumb" "no")
9582 (const_int 8)
1b7da4ac 9583 (const_int 10))])
9584 (set_attr "type" "multiple")]
f6c53574 9585)
9586
9587(define_insn "*cmp_ior"
9588 [(set (match_operand 6 "dominant_cc_register" "")
9589 (compare
9590 (ior:SI
9591 (match_operator 4 "arm_comparison_operator"
2ff91fec 9592 [(match_operand:SI 0 "s_register_operand"
9593 "l,l,l,r,r,r,r,r,r")
9594 (match_operand:SI 1 "arm_add_operand"
9595 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
f6c53574 9596 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 9597 [(match_operand:SI 2 "s_register_operand"
9598 "l,r,r,l,l,r,r,r,r")
9599 (match_operand:SI 3 "arm_add_operand"
9600 "lPy,rI,L,lPy,lPy,rI,rI,L,L")]))
f6c53574 9601 (const_int 0)))]
2ff91fec 9602 "TARGET_32BIT"
f6c53574 9603 "*
f6c53574 9604 {
2ff91fec 9605 static const char *const cmp1[NUM_OF_COND_CMP][2] =
9606 {
9607 {\"cmp\\t%0, %1\",
9608 \"cmp\\t%2, %3\"},
9609 {\"cmn\\t%0, #%n1\",
9610 \"cmp\\t%2, %3\"},
9611 {\"cmp\\t%0, %1\",
9612 \"cmn\\t%2, #%n3\"},
9613 {\"cmn\\t%0, #%n1\",
9614 \"cmn\\t%2, #%n3\"}
9615 };
9616 static const char *const cmp2[NUM_OF_COND_CMP][2] =
9617 {
9618 {\"cmp%D4\\t%2, %3\",
9619 \"cmp%D5\\t%0, %1\"},
9620 {\"cmp%D4\\t%2, %3\",
9621 \"cmn%D5\\t%0, #%n1\"},
9622 {\"cmn%D4\\t%2, #%n3\",
9623 \"cmp%D5\\t%0, %1\"},
9624 {\"cmn%D4\\t%2, #%n3\",
9625 \"cmn%D5\\t%0, #%n1\"}
9626 };
9627 static const char *const ite[2] =
9628 {
9629 \"it\\t%D4\",
9630 \"it\\t%D5\"
9631 };
9632 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
9633 CMP_CMP, CMN_CMP, CMP_CMP,
9634 CMN_CMP, CMP_CMN, CMN_CMN};
9635 int swap =
9636 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9637
9638 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9639 if (TARGET_THUMB2) {
9640 output_asm_insn (ite[swap], operands);
9641 }
9642 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9643 return \"\";
9644 }
9645 "
f6c53574 9646 [(set_attr "conds" "set")
2ff91fec 9647 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
9648 (set_attr_alternative "length"
9649 [(const_int 6)
9650 (const_int 8)
9651 (const_int 8)
9652 (const_int 8)
9653 (const_int 8)
9654 (if_then_else (eq_attr "is_thumb" "no")
9655 (const_int 8)
9656 (const_int 10))
9657 (if_then_else (eq_attr "is_thumb" "no")
9658 (const_int 8)
9659 (const_int 10))
9660 (if_then_else (eq_attr "is_thumb" "no")
9661 (const_int 8)
9662 (const_int 10))
9663 (if_then_else (eq_attr "is_thumb" "no")
9664 (const_int 8)
1b7da4ac 9665 (const_int 10))])
9666 (set_attr "type" "multiple")]
f6c53574 9667)
9668
3c5afce6 9669(define_insn_and_split "*ior_scc_scc"
fd711051 9670 [(set (match_operand:SI 0 "s_register_operand" "=Ts")
3c5afce6 9671 (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9672 [(match_operand:SI 1 "s_register_operand" "r")
9673 (match_operand:SI 2 "arm_add_operand" "rIL")])
9674 (match_operator:SI 6 "arm_comparison_operator"
9675 [(match_operand:SI 4 "s_register_operand" "r")
9676 (match_operand:SI 5 "arm_add_operand" "rIL")])))
9677 (clobber (reg:CC CC_REGNUM))]
2ff91fec 9678 "TARGET_32BIT
3c5afce6 9679 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
9680 != CCmode)"
9681 "#"
2ff91fec 9682 "TARGET_32BIT && reload_completed"
3c5afce6 9683 [(set (match_dup 7)
9684 (compare
9685 (ior:SI
9686 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9687 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9688 (const_int 0)))
9689 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9690 "operands[7]
9691 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9692 DOM_CC_X_OR_Y),
601f584c 9693 CC_REGNUM);"
9694 [(set_attr "conds" "clob")
1b7da4ac 9695 (set_attr "length" "16")
9696 (set_attr "type" "multiple")]
9697)
601f584c 9698
9699; If the above pattern is followed by a CMP insn, then the compare is
9700; redundant, since we can rework the conditional instruction that follows.
9701(define_insn_and_split "*ior_scc_scc_cmp"
9702 [(set (match_operand 0 "dominant_cc_register" "")
9703 (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9704 [(match_operand:SI 1 "s_register_operand" "r")
9705 (match_operand:SI 2 "arm_add_operand" "rIL")])
9706 (match_operator:SI 6 "arm_comparison_operator"
9707 [(match_operand:SI 4 "s_register_operand" "r")
9708 (match_operand:SI 5 "arm_add_operand" "rIL")]))
9709 (const_int 0)))
fd711051 9710 (set (match_operand:SI 7 "s_register_operand" "=Ts")
601f584c 9711 (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9712 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
2ff91fec 9713 "TARGET_32BIT"
601f584c 9714 "#"
2ff91fec 9715 "TARGET_32BIT && reload_completed"
601f584c 9716 [(set (match_dup 0)
9717 (compare
9718 (ior:SI
9719 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9720 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9721 (const_int 0)))
9722 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9723 ""
9724 [(set_attr "conds" "set")
1b7da4ac 9725 (set_attr "length" "16")
9726 (set_attr "type" "multiple")]
9727)
3c5afce6 9728
9729(define_insn_and_split "*and_scc_scc"
fd711051 9730 [(set (match_operand:SI 0 "s_register_operand" "=Ts")
3c5afce6 9731 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9732 [(match_operand:SI 1 "s_register_operand" "r")
9733 (match_operand:SI 2 "arm_add_operand" "rIL")])
9734 (match_operator:SI 6 "arm_comparison_operator"
9735 [(match_operand:SI 4 "s_register_operand" "r")
9736 (match_operand:SI 5 "arm_add_operand" "rIL")])))
9737 (clobber (reg:CC CC_REGNUM))]
2ff91fec 9738 "TARGET_32BIT
3c5afce6 9739 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9740 != CCmode)"
9741 "#"
2ff91fec 9742 "TARGET_32BIT && reload_completed
601f584c 9743 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9744 != CCmode)"
3c5afce6 9745 [(set (match_dup 7)
9746 (compare
9747 (and:SI
9748 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9749 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9750 (const_int 0)))
9751 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9752 "operands[7]
9753 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9754 DOM_CC_X_AND_Y),
601f584c 9755 CC_REGNUM);"
9756 [(set_attr "conds" "clob")
1b7da4ac 9757 (set_attr "length" "16")
9758 (set_attr "type" "multiple")]
9759)
601f584c 9760
9761; If the above pattern is followed by a CMP insn, then the compare is
9762; redundant, since we can rework the conditional instruction that follows.
9763(define_insn_and_split "*and_scc_scc_cmp"
9764 [(set (match_operand 0 "dominant_cc_register" "")
9765 (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
9766 [(match_operand:SI 1 "s_register_operand" "r")
9767 (match_operand:SI 2 "arm_add_operand" "rIL")])
9768 (match_operator:SI 6 "arm_comparison_operator"
9769 [(match_operand:SI 4 "s_register_operand" "r")
9770 (match_operand:SI 5 "arm_add_operand" "rIL")]))
9771 (const_int 0)))
fd711051 9772 (set (match_operand:SI 7 "s_register_operand" "=Ts")
601f584c 9773 (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9774 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
2ff91fec 9775 "TARGET_32BIT"
601f584c 9776 "#"
2ff91fec 9777 "TARGET_32BIT && reload_completed"
601f584c 9778 [(set (match_dup 0)
9779 (compare
9780 (and:SI
9781 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9782 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9783 (const_int 0)))
9784 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9785 ""
9786 [(set_attr "conds" "set")
1b7da4ac 9787 (set_attr "length" "16")
9788 (set_attr "type" "multiple")]
9789)
601f584c 9790
9791;; If there is no dominance in the comparison, then we can still save an
9792;; instruction in the AND case, since we can know that the second compare
9793;; need only zero the value if false (if true, then the value is already
9794;; correct).
9795(define_insn_and_split "*and_scc_scc_nodom"
fd711051 9796 [(set (match_operand:SI 0 "s_register_operand" "=&Ts,&Ts,&Ts")
601f584c 9797 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9798 [(match_operand:SI 1 "s_register_operand" "r,r,0")
9799 (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
9800 (match_operator:SI 6 "arm_comparison_operator"
9801 [(match_operand:SI 4 "s_register_operand" "r,r,r")
9802 (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
9803 (clobber (reg:CC CC_REGNUM))]
2ff91fec 9804 "TARGET_32BIT
601f584c 9805 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9806 == CCmode)"
9807 "#"
2ff91fec 9808 "TARGET_32BIT && reload_completed"
601f584c 9809 [(parallel [(set (match_dup 0)
9810 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
9811 (clobber (reg:CC CC_REGNUM))])
9812 (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
9813 (set (match_dup 0)
9814 (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
9815 (match_dup 0)
9816 (const_int 0)))]
9817 "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
9818 operands[4], operands[5]),
9819 CC_REGNUM);
9820 operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
9821 operands[5]);"
9822 [(set_attr "conds" "clob")
1b7da4ac 9823 (set_attr "length" "20")
9824 (set_attr "type" "multiple")]
9825)
3c5afce6 9826
3a0bdee0 9827(define_split
9828 [(set (reg:CC_NOOV CC_REGNUM)
9829 (compare:CC_NOOV (ior:SI
9830 (and:SI (match_operand:SI 0 "s_register_operand" "")
9831 (const_int 1))
b0694be0 9832 (match_operator:SI 1 "arm_comparison_operator"
3a0bdee0 9833 [(match_operand:SI 2 "s_register_operand" "")
9834 (match_operand:SI 3 "arm_add_operand" "")]))
9835 (const_int 0)))
9836 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9837 "TARGET_ARM"
9838 [(set (match_dup 4)
9839 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9840 (match_dup 0)))
9841 (set (reg:CC_NOOV CC_REGNUM)
9842 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9843 (const_int 0)))]
9844 "")
9845
9846(define_split
9847 [(set (reg:CC_NOOV CC_REGNUM)
9848 (compare:CC_NOOV (ior:SI
b0694be0 9849 (match_operator:SI 1 "arm_comparison_operator"
3a0bdee0 9850 [(match_operand:SI 2 "s_register_operand" "")
9851 (match_operand:SI 3 "arm_add_operand" "")])
9852 (and:SI (match_operand:SI 0 "s_register_operand" "")
9853 (const_int 1)))
9854 (const_int 0)))
9855 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9856 "TARGET_ARM"
9857 [(set (match_dup 4)
9858 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9859 (match_dup 0)))
9860 (set (reg:CC_NOOV CC_REGNUM)
9861 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9862 (const_int 0)))]
9863 "")
25f905c2 9864;; ??? The conditional patterns above need checking for Thumb-2 usefulness
3a0bdee0 9865
190efb17 9866(define_insn_and_split "*negscc"
9c08d1fa 9867 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9868 (neg:SI (match_operator 3 "arm_comparison_operator"
9c08d1fa 9869 [(match_operand:SI 1 "s_register_operand" "r")
9870 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
bd5b4116 9871 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9872 "TARGET_ARM"
190efb17 9873 "#"
9874 "&& reload_completed"
9875 [(const_int 0)]
9876 {
9877 rtx cc_reg = gen_rtx_REG (CCmode, CC_REGNUM);
e2348bcb 9878
190efb17 9879 if (GET_CODE (operands[3]) == LT && operands[2] == const0_rtx)
9880 {
9881 /* Emit mov\\t%0, %1, asr #31 */
d1f9b275 9882 emit_insn (gen_rtx_SET (operands[0],
190efb17 9883 gen_rtx_ASHIFTRT (SImode,
9884 operands[1],
9885 GEN_INT (31))));
9886 DONE;
9887 }
9888 else if (GET_CODE (operands[3]) == NE)
9889 {
9890 /* Emit subs\\t%0, %1, %2\;mvnne\\t%0, #0 */
9891 if (CONST_INT_P (operands[2]))
9892 emit_insn (gen_cmpsi2_addneg (operands[0], operands[1], operands[2],
9893 GEN_INT (- INTVAL (operands[2]))));
9894 else
9895 emit_insn (gen_subsi3_compare (operands[0], operands[1], operands[2]));
9896
9897 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
9898 gen_rtx_NE (SImode,
9899 cc_reg,
9900 const0_rtx),
d1f9b275 9901 gen_rtx_SET (operands[0],
190efb17 9902 GEN_INT (~0))));
9903 DONE;
9904 }
9905 else
9906 {
9907 /* Emit: cmp\\t%1, %2\;mov%D3\\t%0, #0\;mvn%d3\\t%0, #0 */
d1f9b275 9908 emit_insn (gen_rtx_SET (cc_reg,
190efb17 9909 gen_rtx_COMPARE (CCmode, operands[1], operands[2])));
9910 enum rtx_code rc = GET_CODE (operands[3]);
9911
9912 rc = reverse_condition (rc);
9913 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
9914 gen_rtx_fmt_ee (rc,
9915 VOIDmode,
9916 cc_reg,
9917 const0_rtx),
d1f9b275 9918 gen_rtx_SET (operands[0], const0_rtx)));
190efb17 9919 rc = GET_CODE (operands[3]);
9920 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
9921 gen_rtx_fmt_ee (rc,
9922 VOIDmode,
9923 cc_reg,
9924 const0_rtx),
d1f9b275 9925 gen_rtx_SET (operands[0],
190efb17 9926 GEN_INT (~0))));
9927 DONE;
9928 }
9929 FAIL;
9930 }
8fa3ba89 9931 [(set_attr "conds" "clob")
1b7da4ac 9932 (set_attr "length" "12")
9933 (set_attr "type" "multiple")]
8fa3ba89 9934)
9c08d1fa 9935
90404b57 9936(define_insn_and_split "movcond_addsi"
9937 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r")
9938 (if_then_else:SI
9939 (match_operator 5 "comparison_operator"
9940 [(plus:SI (match_operand:SI 3 "s_register_operand" "r,r,r")
9941 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL"))
9942 (const_int 0)])
9943 (match_operand:SI 1 "arm_rhs_operand" "rI,rPy,r")
9944 (match_operand:SI 2 "arm_rhs_operand" "rI,rPy,r")))
9945 (clobber (reg:CC CC_REGNUM))]
9946 "TARGET_32BIT"
9947 "#"
9948 "&& reload_completed"
9949 [(set (reg:CC_NOOV CC_REGNUM)
9950 (compare:CC_NOOV
9951 (plus:SI (match_dup 3)
9952 (match_dup 4))
9953 (const_int 0)))
9954 (set (match_dup 0) (match_dup 1))
9955 (cond_exec (match_dup 6)
9956 (set (match_dup 0) (match_dup 2)))]
9957 "
9958 {
3754d046 9959 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[5]),
90404b57 9960 operands[3], operands[4]);
9961 enum rtx_code rc = GET_CODE (operands[5]);
90404b57 9962 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9963 gcc_assert (!(mode == CCFPmode || mode == CCFPEmode));
22440aeb 9964 if (!REG_P (operands[2]) || REGNO (operands[2]) != REGNO (operands[0]))
4d01ce2f 9965 rc = reverse_condition (rc);
f145bcba 9966 else
9967 std::swap (operands[1], operands[2]);
90404b57 9968
9969 operands[6] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9970 }
9971 "
9972 [(set_attr "conds" "clob")
1b7da4ac 9973 (set_attr "enabled_for_depr_it" "no,yes,yes")
9974 (set_attr "type" "multiple")]
90404b57 9975)
9976
9c08d1fa 9977(define_insn "movcond"
9978 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 9979 (if_then_else:SI
8fa3ba89 9980 (match_operator 5 "arm_comparison_operator"
5565501b 9981 [(match_operand:SI 3 "s_register_operand" "r,r,r")
9982 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
9983 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9984 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 9985 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9986 "TARGET_ARM"
9c08d1fa 9987 "*
9988 if (GET_CODE (operands[5]) == LT
9989 && (operands[4] == const0_rtx))
9990 {
0438d37f 9991 if (which_alternative != 1 && REG_P (operands[1]))
9c08d1fa 9992 {
9c08d1fa 9993 if (operands[2] == const0_rtx)
e2348bcb 9994 return \"and\\t%0, %1, %3, asr #31\";
9995 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
9c08d1fa 9996 }
0438d37f 9997 else if (which_alternative != 0 && REG_P (operands[2]))
9c08d1fa 9998 {
9c08d1fa 9999 if (operands[1] == const0_rtx)
e2348bcb 10000 return \"bic\\t%0, %2, %3, asr #31\";
10001 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
9c08d1fa 10002 }
10003 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 10004 are constants. */
9c08d1fa 10005 }
e2348bcb 10006
9c08d1fa 10007 if (GET_CODE (operands[5]) == GE
10008 && (operands[4] == const0_rtx))
10009 {
0438d37f 10010 if (which_alternative != 1 && REG_P (operands[1]))
9c08d1fa 10011 {
9c08d1fa 10012 if (operands[2] == const0_rtx)
e2348bcb 10013 return \"bic\\t%0, %1, %3, asr #31\";
10014 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
9c08d1fa 10015 }
0438d37f 10016 else if (which_alternative != 0 && REG_P (operands[2]))
9c08d1fa 10017 {
9c08d1fa 10018 if (operands[1] == const0_rtx)
e2348bcb 10019 return \"and\\t%0, %2, %3, asr #31\";
10020 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
9c08d1fa 10021 }
10022 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 10023 are constants. */
9c08d1fa 10024 }
0438d37f 10025 if (CONST_INT_P (operands[4])
9c08d1fa 10026 && !const_ok_for_arm (INTVAL (operands[4])))
e2348bcb 10027 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
9c08d1fa 10028 else
e2348bcb 10029 output_asm_insn (\"cmp\\t%3, %4\", operands);
9c08d1fa 10030 if (which_alternative != 0)
e2348bcb 10031 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
9c08d1fa 10032 if (which_alternative != 1)
e2348bcb 10033 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
9c08d1fa 10034 return \"\";
215b30b3 10035 "
8fa3ba89 10036 [(set_attr "conds" "clob")
1b7da4ac 10037 (set_attr "length" "8,8,12")
10038 (set_attr "type" "multiple")]
8fa3ba89 10039)
9c08d1fa 10040
25f905c2 10041;; ??? The patterns below need checking for Thumb-2 usefulness.
10042
8a18b90c 10043(define_insn "*ifcompare_plus_move"
10044 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10045 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 10046 [(match_operand:SI 4 "s_register_operand" "r,r")
10047 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
10048 (plus:SI
10049 (match_operand:SI 2 "s_register_operand" "r,r")
10050 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
129a2fe4 10051 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 10052 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10053 "TARGET_ARM"
8a18b90c 10054 "#"
8fa3ba89 10055 [(set_attr "conds" "clob")
1b7da4ac 10056 (set_attr "length" "8,12")
10057 (set_attr "type" "multiple")]
8fa3ba89 10058)
8a18b90c 10059
10060(define_insn "*if_plus_move"
129a2fe4 10061 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 10062 (if_then_else:SI
8fa3ba89 10063 (match_operator 4 "arm_comparison_operator"
8a18b90c 10064 [(match_operand 5 "cc_register" "") (const_int 0)])
10065 (plus:SI
129a2fe4 10066 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
10067 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
10068 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
cffb2a26 10069 "TARGET_ARM"
8a18b90c 10070 "@
10071 add%d4\\t%0, %2, %3
10072 sub%d4\\t%0, %2, #%n3
10073 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
129a2fe4 10074 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8fa3ba89 10075 [(set_attr "conds" "use")
10076 (set_attr "length" "4,4,8,8")
65f68e55 10077 (set_attr_alternative "type"
10078 [(if_then_else (match_operand 3 "const_int_operand" "")
d82e788e 10079 (const_string "alu_imm" )
112eda6f 10080 (const_string "alu_sreg"))
d82e788e 10081 (const_string "alu_imm")
282b4c75 10082 (const_string "multiple")
10083 (const_string "multiple")])]
8fa3ba89 10084)
8a18b90c 10085
10086(define_insn "*ifcompare_move_plus"
5565501b 10087 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10088 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 10089 [(match_operand:SI 4 "s_register_operand" "r,r")
10090 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 10091 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 10092 (plus:SI
10093 (match_operand:SI 2 "s_register_operand" "r,r")
10094 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
bd5b4116 10095 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10096 "TARGET_ARM"
8a18b90c 10097 "#"
8fa3ba89 10098 [(set_attr "conds" "clob")
1b7da4ac 10099 (set_attr "length" "8,12")
10100 (set_attr "type" "multiple")]
8fa3ba89 10101)
8a18b90c 10102
10103(define_insn "*if_move_plus"
129a2fe4 10104 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 10105 (if_then_else:SI
8fa3ba89 10106 (match_operator 4 "arm_comparison_operator"
8a18b90c 10107 [(match_operand 5 "cc_register" "") (const_int 0)])
129a2fe4 10108 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8a18b90c 10109 (plus:SI
129a2fe4 10110 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
10111 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
cffb2a26 10112 "TARGET_ARM"
8a18b90c 10113 "@
10114 add%D4\\t%0, %2, %3
10115 sub%D4\\t%0, %2, #%n3
10116 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
129a2fe4 10117 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8fa3ba89 10118 [(set_attr "conds" "use")
10119 (set_attr "length" "4,4,8,8")
282b4c75 10120 (set_attr_alternative "type"
10121 [(if_then_else (match_operand 3 "const_int_operand" "")
10122 (const_string "alu_imm" )
10123 (const_string "alu_sreg"))
10124 (const_string "alu_imm")
10125 (const_string "multiple")
10126 (const_string "multiple")])]
8fa3ba89 10127)
8a18b90c 10128
10129(define_insn "*ifcompare_arith_arith"
10130 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 10131 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8a18b90c 10132 [(match_operand:SI 5 "s_register_operand" "r")
10133 (match_operand:SI 6 "arm_add_operand" "rIL")])
9c08d1fa 10134 (match_operator:SI 8 "shiftable_operator"
8a18b90c 10135 [(match_operand:SI 1 "s_register_operand" "r")
10136 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9c08d1fa 10137 (match_operator:SI 7 "shiftable_operator"
8a18b90c 10138 [(match_operand:SI 3 "s_register_operand" "r")
10139 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
bd5b4116 10140 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10141 "TARGET_ARM"
8a18b90c 10142 "#"
8fa3ba89 10143 [(set_attr "conds" "clob")
1b7da4ac 10144 (set_attr "length" "12")
10145 (set_attr "type" "multiple")]
8fa3ba89 10146)
9c08d1fa 10147
8a18b90c 10148(define_insn "*if_arith_arith"
10149 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 10150 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8a18b90c 10151 [(match_operand 8 "cc_register" "") (const_int 0)])
10152 (match_operator:SI 6 "shiftable_operator"
10153 [(match_operand:SI 1 "s_register_operand" "r")
10154 (match_operand:SI 2 "arm_rhs_operand" "rI")])
10155 (match_operator:SI 7 "shiftable_operator"
10156 [(match_operand:SI 3 "s_register_operand" "r")
10157 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
cffb2a26 10158 "TARGET_ARM"
8a18b90c 10159 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8fa3ba89 10160 [(set_attr "conds" "use")
1b7da4ac 10161 (set_attr "length" "8")
10162 (set_attr "type" "multiple")]
8fa3ba89 10163)
8a18b90c 10164
f7fbdd4a 10165(define_insn "*ifcompare_arith_move"
9c08d1fa 10166 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10167 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 10168 [(match_operand:SI 2 "s_register_operand" "r,r")
5565501b 10169 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
9c08d1fa 10170 (match_operator:SI 7 "shiftable_operator"
10171 [(match_operand:SI 4 "s_register_operand" "r,r")
10172 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
129a2fe4 10173 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 10174 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10175 "TARGET_ARM"
9c08d1fa 10176 "*
9c08d1fa 10177 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 10178 the conditional operator is LT or GE and we are comparing against zero and
674a8f0b 10179 everything is in registers then we can do this in two instructions. */
9c08d1fa 10180 if (operands[3] == const0_rtx
10181 && GET_CODE (operands[7]) != AND
0438d37f 10182 && REG_P (operands[5])
10183 && REG_P (operands[1])
9c08d1fa 10184 && REGNO (operands[1]) == REGNO (operands[4])
10185 && REGNO (operands[4]) != REGNO (operands[0]))
10186 {
10187 if (GET_CODE (operands[6]) == LT)
40dbec34 10188 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 10189 else if (GET_CODE (operands[6]) == GE)
40dbec34 10190 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 10191 }
0438d37f 10192 if (CONST_INT_P (operands[3])
9c08d1fa 10193 && !const_ok_for_arm (INTVAL (operands[3])))
e2348bcb 10194 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
9c08d1fa 10195 else
e2348bcb 10196 output_asm_insn (\"cmp\\t%2, %3\", operands);
40dbec34 10197 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
9c08d1fa 10198 if (which_alternative != 0)
129a2fe4 10199 return \"mov%D6\\t%0, %1\";
9c08d1fa 10200 return \"\";
215b30b3 10201 "
8fa3ba89 10202 [(set_attr "conds" "clob")
1b7da4ac 10203 (set_attr "length" "8,12")
10204 (set_attr "type" "multiple")]
8fa3ba89 10205)
9c08d1fa 10206
8a18b90c 10207(define_insn "*if_arith_move"
129a2fe4 10208 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10209 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8a18b90c 10210 [(match_operand 6 "cc_register" "") (const_int 0)])
10211 (match_operator:SI 5 "shiftable_operator"
129a2fe4 10212 [(match_operand:SI 2 "s_register_operand" "r,r")
10213 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
10214 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
cffb2a26 10215 "TARGET_ARM"
8a18b90c 10216 "@
10217 %I5%d4\\t%0, %2, %3
129a2fe4 10218 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8fa3ba89 10219 [(set_attr "conds" "use")
10220 (set_attr "length" "4,8")
282b4c75 10221 (set_attr_alternative "type"
10222 [(if_then_else (match_operand 3 "const_int_operand" "")
10223 (const_string "alu_shift_imm" )
10224 (const_string "alu_shift_reg"))
10225 (const_string "multiple")])]
8fa3ba89 10226)
8a18b90c 10227
f7fbdd4a 10228(define_insn "*ifcompare_move_arith"
9c08d1fa 10229 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10230 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 10231 [(match_operand:SI 4 "s_register_operand" "r,r")
5565501b 10232 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 10233 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9c08d1fa 10234 (match_operator:SI 7 "shiftable_operator"
10235 [(match_operand:SI 2 "s_register_operand" "r,r")
10236 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 10237 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10238 "TARGET_ARM"
9c08d1fa 10239 "*
9c08d1fa 10240 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 10241 the conditional operator is LT or GE and we are comparing against zero and
9c08d1fa 10242 everything is in registers then we can do this in two instructions */
10243 if (operands[5] == const0_rtx
10244 && GET_CODE (operands[7]) != AND
0438d37f 10245 && REG_P (operands[3])
10246 && REG_P (operands[1])
9c08d1fa 10247 && REGNO (operands[1]) == REGNO (operands[2])
10248 && REGNO (operands[2]) != REGNO (operands[0]))
10249 {
10250 if (GET_CODE (operands[6]) == GE)
40dbec34 10251 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 10252 else if (GET_CODE (operands[6]) == LT)
40dbec34 10253 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 10254 }
40dbec34 10255
0438d37f 10256 if (CONST_INT_P (operands[5])
9c08d1fa 10257 && !const_ok_for_arm (INTVAL (operands[5])))
e2348bcb 10258 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
9c08d1fa 10259 else
e2348bcb 10260 output_asm_insn (\"cmp\\t%4, %5\", operands);
40dbec34 10261
9c08d1fa 10262 if (which_alternative != 0)
129a2fe4 10263 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
40dbec34 10264 return \"%I7%D6\\t%0, %2, %3\";
215b30b3 10265 "
8fa3ba89 10266 [(set_attr "conds" "clob")
1b7da4ac 10267 (set_attr "length" "8,12")
10268 (set_attr "type" "multiple")]
8fa3ba89 10269)
9c08d1fa 10270
8a18b90c 10271(define_insn "*if_move_arith"
129a2fe4 10272 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 10273 (if_then_else:SI
8fa3ba89 10274 (match_operator 4 "arm_comparison_operator"
8a18b90c 10275 [(match_operand 6 "cc_register" "") (const_int 0)])
129a2fe4 10276 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 10277 (match_operator:SI 5 "shiftable_operator"
129a2fe4 10278 [(match_operand:SI 2 "s_register_operand" "r,r")
10279 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
cffb2a26 10280 "TARGET_ARM"
8a18b90c 10281 "@
10282 %I5%D4\\t%0, %2, %3
129a2fe4 10283 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
8fa3ba89 10284 [(set_attr "conds" "use")
10285 (set_attr "length" "4,8")
282b4c75 10286 (set_attr_alternative "type"
10287 [(if_then_else (match_operand 3 "const_int_operand" "")
10288 (const_string "alu_shift_imm" )
10289 (const_string "alu_shift_reg"))
10290 (const_string "multiple")])]
8fa3ba89 10291)
8a18b90c 10292
10293(define_insn "*ifcompare_move_not"
9c08d1fa 10294 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 10295 (if_then_else:SI
8fa3ba89 10296 (match_operator 5 "arm_comparison_operator"
8a18b90c 10297 [(match_operand:SI 3 "s_register_operand" "r,r")
10298 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10299 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
10300 (not:SI
10301 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 10302 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10303 "TARGET_ARM"
8a18b90c 10304 "#"
8fa3ba89 10305 [(set_attr "conds" "clob")
1b7da4ac 10306 (set_attr "length" "8,12")
10307 (set_attr "type" "multiple")]
8fa3ba89 10308)
9c08d1fa 10309
8a18b90c 10310(define_insn "*if_move_not"
10311 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10312 (if_then_else:SI
8fa3ba89 10313 (match_operator 4 "arm_comparison_operator"
8a18b90c 10314 [(match_operand 3 "cc_register" "") (const_int 0)])
10315 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
10316 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
cffb2a26 10317 "TARGET_ARM"
8a18b90c 10318 "@
10319 mvn%D4\\t%0, %2
10320 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
10321 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
8fa3ba89 10322 [(set_attr "conds" "use")
1aed5204 10323 (set_attr "type" "mvn_reg")
1b7da4ac 10324 (set_attr "length" "4,8,8")
10325 (set_attr "type" "mvn_reg,multiple,multiple")]
8fa3ba89 10326)
8a18b90c 10327
10328(define_insn "*ifcompare_not_move"
9c08d1fa 10329 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 10330 (if_then_else:SI
8fa3ba89 10331 (match_operator 5 "arm_comparison_operator"
8a18b90c 10332 [(match_operand:SI 3 "s_register_operand" "r,r")
10333 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10334 (not:SI
10335 (match_operand:SI 2 "s_register_operand" "r,r"))
10336 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 10337 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10338 "TARGET_ARM"
8a18b90c 10339 "#"
8fa3ba89 10340 [(set_attr "conds" "clob")
1b7da4ac 10341 (set_attr "length" "8,12")
10342 (set_attr "type" "multiple")]
8fa3ba89 10343)
9c08d1fa 10344
8a18b90c 10345(define_insn "*if_not_move"
10346 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10347 (if_then_else:SI
8fa3ba89 10348 (match_operator 4 "arm_comparison_operator"
8a18b90c 10349 [(match_operand 3 "cc_register" "") (const_int 0)])
10350 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
10351 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 10352 "TARGET_ARM"
8a18b90c 10353 "@
10354 mvn%d4\\t%0, %2
10355 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
10356 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
8fa3ba89 10357 [(set_attr "conds" "use")
1b7da4ac 10358 (set_attr "type" "mvn_reg,multiple,multiple")
8fa3ba89 10359 (set_attr "length" "4,8,8")]
10360)
8a18b90c 10361
10362(define_insn "*ifcompare_shift_move"
9c08d1fa 10363 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 10364 (if_then_else:SI
8fa3ba89 10365 (match_operator 6 "arm_comparison_operator"
8a18b90c 10366 [(match_operand:SI 4 "s_register_operand" "r,r")
10367 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
10368 (match_operator:SI 7 "shift_operator"
10369 [(match_operand:SI 2 "s_register_operand" "r,r")
10370 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
10371 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 10372 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10373 "TARGET_ARM"
9c08d1fa 10374 "#"
8fa3ba89 10375 [(set_attr "conds" "clob")
1b7da4ac 10376 (set_attr "length" "8,12")
10377 (set_attr "type" "multiple")]
8fa3ba89 10378)
9c08d1fa 10379
8a18b90c 10380(define_insn "*if_shift_move"
10381 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10382 (if_then_else:SI
8fa3ba89 10383 (match_operator 5 "arm_comparison_operator"
8a18b90c 10384 [(match_operand 6 "cc_register" "") (const_int 0)])
10385 (match_operator:SI 4 "shift_operator"
10386 [(match_operand:SI 2 "s_register_operand" "r,r,r")
10387 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
10388 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 10389 "TARGET_ARM"
5565501b 10390 "@
8a18b90c 10391 mov%d5\\t%0, %2%S4
10392 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
10393 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
8fa3ba89 10394 [(set_attr "conds" "use")
331beb1a 10395 (set_attr "shift" "2")
a2cd141b 10396 (set_attr "length" "4,8,8")
282b4c75 10397 (set_attr_alternative "type"
10398 [(if_then_else (match_operand 3 "const_int_operand" "")
10399 (const_string "mov_shift" )
10400 (const_string "mov_shift_reg"))
10401 (const_string "multiple")
10402 (const_string "multiple")])]
8fa3ba89 10403)
5565501b 10404
8a18b90c 10405(define_insn "*ifcompare_move_shift"
10406 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 10407 (if_then_else:SI
8fa3ba89 10408 (match_operator 6 "arm_comparison_operator"
8a18b90c 10409 [(match_operand:SI 4 "s_register_operand" "r,r")
10410 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
10411 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
5565501b 10412 (match_operator:SI 7 "shift_operator"
8a18b90c 10413 [(match_operand:SI 2 "s_register_operand" "r,r")
10414 (match_operand:SI 3 "arm_rhs_operand" "rM,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" "8,12")
10420 (set_attr "type" "multiple")]
8fa3ba89 10421)
5565501b 10422
8a18b90c 10423(define_insn "*if_move_shift"
10424 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 10425 (if_then_else:SI
8fa3ba89 10426 (match_operator 5 "arm_comparison_operator"
8a18b90c 10427 [(match_operand 6 "cc_register" "") (const_int 0)])
10428 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
10429 (match_operator:SI 4 "shift_operator"
10430 [(match_operand:SI 2 "s_register_operand" "r,r,r")
10431 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
cffb2a26 10432 "TARGET_ARM"
5565501b 10433 "@
8a18b90c 10434 mov%D5\\t%0, %2%S4
10435 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
10436 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
8fa3ba89 10437 [(set_attr "conds" "use")
331beb1a 10438 (set_attr "shift" "2")
a2cd141b 10439 (set_attr "length" "4,8,8")
282b4c75 10440 (set_attr_alternative "type"
10441 [(if_then_else (match_operand 3 "const_int_operand" "")
10442 (const_string "mov_shift" )
10443 (const_string "mov_shift_reg"))
10444 (const_string "multiple")
10445 (const_string "multiple")])]
8fa3ba89 10446)
9c08d1fa 10447
f7fbdd4a 10448(define_insn "*ifcompare_shift_shift"
8a18b90c 10449 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 10450 (if_then_else:SI
8fa3ba89 10451 (match_operator 7 "arm_comparison_operator"
8a18b90c 10452 [(match_operand:SI 5 "s_register_operand" "r")
10453 (match_operand:SI 6 "arm_add_operand" "rIL")])
5565501b 10454 (match_operator:SI 8 "shift_operator"
8a18b90c 10455 [(match_operand:SI 1 "s_register_operand" "r")
10456 (match_operand:SI 2 "arm_rhs_operand" "rM")])
5565501b 10457 (match_operator:SI 9 "shift_operator"
8a18b90c 10458 [(match_operand:SI 3 "s_register_operand" "r")
10459 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
bd5b4116 10460 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10461 "TARGET_ARM"
8a18b90c 10462 "#"
8fa3ba89 10463 [(set_attr "conds" "clob")
1b7da4ac 10464 (set_attr "length" "12")
10465 (set_attr "type" "multiple")]
8fa3ba89 10466)
9c08d1fa 10467
8a18b90c 10468(define_insn "*if_shift_shift"
10469 [(set (match_operand:SI 0 "s_register_operand" "=r")
10470 (if_then_else:SI
8fa3ba89 10471 (match_operator 5 "arm_comparison_operator"
8a18b90c 10472 [(match_operand 8 "cc_register" "") (const_int 0)])
10473 (match_operator:SI 6 "shift_operator"
10474 [(match_operand:SI 1 "s_register_operand" "r")
10475 (match_operand:SI 2 "arm_rhs_operand" "rM")])
10476 (match_operator:SI 7 "shift_operator"
10477 [(match_operand:SI 3 "s_register_operand" "r")
10478 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
cffb2a26 10479 "TARGET_ARM"
8a18b90c 10480 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
8fa3ba89 10481 [(set_attr "conds" "use")
331beb1a 10482 (set_attr "shift" "1")
a2cd141b 10483 (set_attr "length" "8")
10484 (set (attr "type") (if_then_else
10485 (and (match_operand 2 "const_int_operand" "")
10486 (match_operand 4 "const_int_operand" ""))
1aed5204 10487 (const_string "mov_shift")
10488 (const_string "mov_shift_reg")))]
8fa3ba89 10489)
8a18b90c 10490
f7fbdd4a 10491(define_insn "*ifcompare_not_arith"
8a18b90c 10492 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 10493 (if_then_else:SI
8fa3ba89 10494 (match_operator 6 "arm_comparison_operator"
8a18b90c 10495 [(match_operand:SI 4 "s_register_operand" "r")
10496 (match_operand:SI 5 "arm_add_operand" "rIL")])
10497 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5565501b 10498 (match_operator:SI 7 "shiftable_operator"
8a18b90c 10499 [(match_operand:SI 2 "s_register_operand" "r")
10500 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
bd5b4116 10501 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10502 "TARGET_ARM"
8a18b90c 10503 "#"
8fa3ba89 10504 [(set_attr "conds" "clob")
1b7da4ac 10505 (set_attr "length" "12")
10506 (set_attr "type" "multiple")]
8fa3ba89 10507)
9c08d1fa 10508
8a18b90c 10509(define_insn "*if_not_arith"
10510 [(set (match_operand:SI 0 "s_register_operand" "=r")
10511 (if_then_else:SI
8fa3ba89 10512 (match_operator 5 "arm_comparison_operator"
8a18b90c 10513 [(match_operand 4 "cc_register" "") (const_int 0)])
10514 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
10515 (match_operator:SI 6 "shiftable_operator"
10516 [(match_operand:SI 2 "s_register_operand" "r")
10517 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
cffb2a26 10518 "TARGET_ARM"
8a18b90c 10519 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
8fa3ba89 10520 [(set_attr "conds" "use")
1aed5204 10521 (set_attr "type" "mvn_reg")
8fa3ba89 10522 (set_attr "length" "8")]
10523)
8a18b90c 10524
10525(define_insn "*ifcompare_arith_not"
10526 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 10527 (if_then_else:SI
8fa3ba89 10528 (match_operator 6 "arm_comparison_operator"
8a18b90c 10529 [(match_operand:SI 4 "s_register_operand" "r")
10530 (match_operand:SI 5 "arm_add_operand" "rIL")])
5565501b 10531 (match_operator:SI 7 "shiftable_operator"
8a18b90c 10532 [(match_operand:SI 2 "s_register_operand" "r")
10533 (match_operand:SI 3 "arm_rhs_operand" "rI")])
10534 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
bd5b4116 10535 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10536 "TARGET_ARM"
8a18b90c 10537 "#"
8fa3ba89 10538 [(set_attr "conds" "clob")
1b7da4ac 10539 (set_attr "length" "12")
10540 (set_attr "type" "multiple")]
8fa3ba89 10541)
9c08d1fa 10542
8a18b90c 10543(define_insn "*if_arith_not"
10544 [(set (match_operand:SI 0 "s_register_operand" "=r")
10545 (if_then_else:SI
8fa3ba89 10546 (match_operator 5 "arm_comparison_operator"
8a18b90c 10547 [(match_operand 4 "cc_register" "") (const_int 0)])
10548 (match_operator:SI 6 "shiftable_operator"
10549 [(match_operand:SI 2 "s_register_operand" "r")
10550 (match_operand:SI 3 "arm_rhs_operand" "rI")])
10551 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
cffb2a26 10552 "TARGET_ARM"
8a18b90c 10553 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
8fa3ba89 10554 [(set_attr "conds" "use")
1b7da4ac 10555 (set_attr "type" "multiple")
8fa3ba89 10556 (set_attr "length" "8")]
10557)
8a18b90c 10558
f7fbdd4a 10559(define_insn "*ifcompare_neg_move"
8a18b90c 10560 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 10561 (if_then_else:SI
8fa3ba89 10562 (match_operator 5 "arm_comparison_operator"
8a18b90c 10563 [(match_operand:SI 3 "s_register_operand" "r,r")
10564 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10565 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
10566 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 10567 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10568 "TARGET_ARM"
8a18b90c 10569 "#"
8fa3ba89 10570 [(set_attr "conds" "clob")
1b7da4ac 10571 (set_attr "length" "8,12")
10572 (set_attr "type" "multiple")]
8fa3ba89 10573)
8a18b90c 10574
530bb693 10575(define_insn_and_split "*if_neg_move"
10576 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
8a18b90c 10577 (if_then_else:SI
8fa3ba89 10578 (match_operator 4 "arm_comparison_operator"
8a18b90c 10579 [(match_operand 3 "cc_register" "") (const_int 0)])
530bb693 10580 (neg:SI (match_operand:SI 2 "s_register_operand" "l,r"))
10581 (match_operand:SI 1 "s_register_operand" "0,0")))]
10582 "TARGET_32BIT"
10583 "#"
10584 "&& reload_completed"
10585 [(cond_exec (match_op_dup 4 [(match_dup 3) (const_int 0)])
10586 (set (match_dup 0) (neg:SI (match_dup 2))))]
10587 ""
8fa3ba89 10588 [(set_attr "conds" "use")
530bb693 10589 (set_attr "length" "4")
10590 (set_attr "arch" "t2,32")
10591 (set_attr "enabled_for_depr_it" "yes,no")
10592 (set_attr "type" "logic_shift_imm")]
8fa3ba89 10593)
9c08d1fa 10594
f7fbdd4a 10595(define_insn "*ifcompare_move_neg"
8a18b90c 10596 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 10597 (if_then_else:SI
8fa3ba89 10598 (match_operator 5 "arm_comparison_operator"
8a18b90c 10599 [(match_operand:SI 3 "s_register_operand" "r,r")
10600 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10601 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
10602 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 10603 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10604 "TARGET_ARM"
8a18b90c 10605 "#"
8fa3ba89 10606 [(set_attr "conds" "clob")
1b7da4ac 10607 (set_attr "length" "8,12")
10608 (set_attr "type" "multiple")]
8fa3ba89 10609)
8a18b90c 10610
530bb693 10611(define_insn_and_split "*if_move_neg"
10612 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
8a18b90c 10613 (if_then_else:SI
8fa3ba89 10614 (match_operator 4 "arm_comparison_operator"
8a18b90c 10615 [(match_operand 3 "cc_register" "") (const_int 0)])
530bb693 10616 (match_operand:SI 1 "s_register_operand" "0,0")
10617 (neg:SI (match_operand:SI 2 "s_register_operand" "l,r"))))]
10618 "TARGET_32BIT"
10619 "#"
10620 "&& reload_completed"
10621 [(cond_exec (match_dup 5)
10622 (set (match_dup 0) (neg:SI (match_dup 2))))]
10623 {
10624 machine_mode mode = GET_MODE (operands[3]);
10625 rtx_code rc = GET_CODE (operands[4]);
10626
10627 if (mode == CCFPmode || mode == CCFPEmode)
10628 rc = reverse_condition_maybe_unordered (rc);
10629 else
10630 rc = reverse_condition (rc);
10631
10632 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[3], const0_rtx);
10633 }
0d66636f 10634 [(set_attr "conds" "use")
530bb693 10635 (set_attr "length" "4")
10636 (set_attr "arch" "t2,32")
10637 (set_attr "enabled_for_depr_it" "yes,no")
10638 (set_attr "type" "logic_shift_imm")]
0d66636f 10639)
9c08d1fa 10640
f7fbdd4a 10641(define_insn "*arith_adjacentmem"
9c08d1fa 10642 [(set (match_operand:SI 0 "s_register_operand" "=r")
10643 (match_operator:SI 1 "shiftable_operator"
10644 [(match_operand:SI 2 "memory_operand" "m")
10645 (match_operand:SI 3 "memory_operand" "m")]))
10646 (clobber (match_scratch:SI 4 "=r"))]
cffb2a26 10647 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9c08d1fa 10648 "*
215b30b3 10649 {
10650 rtx ldm[3];
10651 rtx arith[4];
94dee231 10652 rtx base_reg;
10653 HOST_WIDE_INT val1 = 0, val2 = 0;
9c08d1fa 10654
215b30b3 10655 if (REGNO (operands[0]) > REGNO (operands[4]))
10656 {
10657 ldm[1] = operands[4];
10658 ldm[2] = operands[0];
10659 }
10660 else
10661 {
10662 ldm[1] = operands[0];
10663 ldm[2] = operands[4];
10664 }
94dee231 10665
10666 base_reg = XEXP (operands[2], 0);
10667
10668 if (!REG_P (base_reg))
10669 {
10670 val1 = INTVAL (XEXP (base_reg, 1));
10671 base_reg = XEXP (base_reg, 0);
10672 }
10673
10674 if (!REG_P (XEXP (operands[3], 0)))
215b30b3 10675 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
94dee231 10676
215b30b3 10677 arith[0] = operands[0];
10678 arith[3] = operands[1];
94dee231 10679
215b30b3 10680 if (val1 < val2)
10681 {
10682 arith[1] = ldm[1];
10683 arith[2] = ldm[2];
10684 }
10685 else
10686 {
10687 arith[1] = ldm[2];
10688 arith[2] = ldm[1];
10689 }
94dee231 10690
10691 ldm[0] = base_reg;
10692 if (val1 !=0 && val2 != 0)
215b30b3 10693 {
cdb1295a 10694 rtx ops[3];
10695
94dee231 10696 if (val1 == 4 || val2 == 4)
10697 /* Other val must be 8, since we know they are adjacent and neither
10698 is zero. */
3ef90e77 10699 output_asm_insn (\"ldmib%?\\t%0, {%1, %2}\", ldm);
cdb1295a 10700 else if (const_ok_for_arm (val1) || const_ok_for_arm (-val1))
94dee231 10701 {
94dee231 10702 ldm[0] = ops[0] = operands[4];
10703 ops[1] = base_reg;
10704 ops[2] = GEN_INT (val1);
10705 output_add_immediate (ops);
10706 if (val1 < val2)
3ef90e77 10707 output_asm_insn (\"ldmia%?\\t%0, {%1, %2}\", ldm);
94dee231 10708 else
3ef90e77 10709 output_asm_insn (\"ldmda%?\\t%0, {%1, %2}\", ldm);
94dee231 10710 }
cdb1295a 10711 else
10712 {
10713 /* Offset is out of range for a single add, so use two ldr. */
10714 ops[0] = ldm[1];
10715 ops[1] = base_reg;
10716 ops[2] = GEN_INT (val1);
10717 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10718 ops[0] = ldm[2];
10719 ops[2] = GEN_INT (val2);
10720 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10721 }
215b30b3 10722 }
94dee231 10723 else if (val1 != 0)
215b30b3 10724 {
215b30b3 10725 if (val1 < val2)
3ef90e77 10726 output_asm_insn (\"ldmda%?\\t%0, {%1, %2}\", ldm);
215b30b3 10727 else
3ef90e77 10728 output_asm_insn (\"ldmia%?\\t%0, {%1, %2}\", ldm);
215b30b3 10729 }
10730 else
10731 {
215b30b3 10732 if (val1 < val2)
3ef90e77 10733 output_asm_insn (\"ldmia%?\\t%0, {%1, %2}\", ldm);
215b30b3 10734 else
3ef90e77 10735 output_asm_insn (\"ldmda%?\\t%0, {%1, %2}\", ldm);
215b30b3 10736 }
10737 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
10738 return \"\";
10739 }"
10740 [(set_attr "length" "12")
10741 (set_attr "predicable" "yes")
9f2c2a36 10742 (set_attr "type" "load_4")]
215b30b3 10743)
9c08d1fa 10744
9c08d1fa 10745; This pattern is never tried by combine, so do it as a peephole
10746
a0f94409 10747(define_peephole2
372575c7 10748 [(set (match_operand:SI 0 "arm_general_register_operand" "")
10749 (match_operand:SI 1 "arm_general_register_operand" ""))
bd5b4116 10750 (set (reg:CC CC_REGNUM)
aea4c774 10751 (compare:CC (match_dup 1) (const_int 0)))]
372575c7 10752 "TARGET_ARM"
a0f94409 10753 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
10754 (set (match_dup 0) (match_dup 1))])]
10755 ""
0d66636f 10756)
9c08d1fa 10757
9c08d1fa 10758(define_split
10759 [(set (match_operand:SI 0 "s_register_operand" "")
10760 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
10761 (const_int 0))
8fa3ba89 10762 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9c08d1fa 10763 [(match_operand:SI 3 "s_register_operand" "")
10764 (match_operand:SI 4 "arm_rhs_operand" "")]))))
10765 (clobber (match_operand:SI 5 "s_register_operand" ""))]
cffb2a26 10766 "TARGET_ARM"
9c08d1fa 10767 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
10768 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
10769 (match_dup 5)))]
215b30b3 10770 ""
10771)
9c08d1fa 10772
aea4c774 10773;; This split can be used because CC_Z mode implies that the following
10774;; branch will be an equality, or an unsigned inequality, so the sign
10775;; extension is not needed.
9c08d1fa 10776
aea4c774 10777(define_split
bd5b4116 10778 [(set (reg:CC_Z CC_REGNUM)
aea4c774 10779 (compare:CC_Z
10780 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9c08d1fa 10781 (const_int 24))
aea4c774 10782 (match_operand 1 "const_int_operand" "")))
10783 (clobber (match_scratch:SI 2 ""))]
cffb2a26 10784 "TARGET_ARM
8c4e8755 10785 && ((UINTVAL (operands[1]))
10786 == ((UINTVAL (operands[1])) >> 24) << 24)"
aea4c774 10787 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
bd5b4116 10788 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
aea4c774 10789 "
9c08d1fa 10790 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
215b30b3 10791 "
10792)
25f905c2 10793;; ??? Check the patterns above for Thumb-2 usefulness
9c08d1fa 10794
87b22bf7 10795(define_expand "prologue"
10796 [(clobber (const_int 0))]
cffb2a26 10797 "TARGET_EITHER"
25f905c2 10798 "if (TARGET_32BIT)
cffb2a26 10799 arm_expand_prologue ();
10800 else
25f905c2 10801 thumb1_expand_prologue ();
87b22bf7 10802 DONE;
cffb2a26 10803 "
10804)
87b22bf7 10805
56d27660 10806(define_expand "epilogue"
4c44712e 10807 [(clobber (const_int 0))]
cffb2a26 10808 "TARGET_EITHER"
56d27660 10809 "
18d50ae6 10810 if (crtl->calls_eh_return)
fb94f18b 10811 emit_insn (gen_force_register_use (gen_rtx_REG (Pmode, 2)));
25f905c2 10812 if (TARGET_THUMB1)
c3635784 10813 {
10814 thumb1_expand_epilogue ();
10815 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
10816 gen_rtvec (1, ret_rtx), VUNSPEC_EPILOGUE));
10817 }
10818 else if (HAVE_return)
10819 {
10820 /* HAVE_return is testing for USE_RETURN_INSN (FALSE). Hence,
10821 no need for explicit testing again. */
10822 emit_jump_insn (gen_return ());
10823 }
10824 else if (TARGET_32BIT)
10825 {
10826 arm_expand_epilogue (true);
10827 }
cffb2a26 10828 DONE;
10829 "
10830)
56d27660 10831
ef5651d0 10832;; Note - although unspec_volatile's USE all hard registers,
10833;; USEs are ignored after relaod has completed. Thus we need
10834;; to add an unspec of the link register to ensure that flow
10835;; does not think that it is unused by the sibcall branch that
10836;; will replace the standard function epilogue.
c3635784 10837(define_expand "sibcall_epilogue"
fb94f18b 10838 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_REGISTER_USE)
c3635784 10839 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
10840 "TARGET_32BIT"
10841 "
10842 arm_expand_epilogue (false);
10843 DONE;
10844 "
1c494086 10845)
10846
cffb2a26 10847(define_expand "eh_epilogue"
7db9af5d 10848 [(use (match_operand:SI 0 "register_operand" ""))
10849 (use (match_operand:SI 1 "register_operand" ""))
10850 (use (match_operand:SI 2 "register_operand" ""))]
cffb2a26 10851 "TARGET_EITHER"
10852 "
215b30b3 10853 {
10854 cfun->machine->eh_epilogue_sp_ofs = operands[1];
0438d37f 10855 if (!REG_P (operands[2]) || REGNO (operands[2]) != 2)
215b30b3 10856 {
10857 rtx ra = gen_rtx_REG (Pmode, 2);
10858
10859 emit_move_insn (ra, operands[2]);
10860 operands[2] = ra;
10861 }
5cf3595a 10862 /* This is a hack -- we may have crystalized the function type too
10863 early. */
10864 cfun->machine->func_type = 0;
215b30b3 10865 }"
10866)
56d27660 10867
9c08d1fa 10868;; This split is only used during output to reduce the number of patterns
10869;; that need assembler instructions adding to them. We allowed the setting
10870;; of the conditions to be implicit during rtl generation so that
10871;; the conditional compare patterns would work. However this conflicts to
8a18b90c 10872;; some extent with the conditional data operations, so we have to split them
9c08d1fa 10873;; up again here.
10874
25f905c2 10875;; ??? Need to audit these splitters for Thumb-2. Why isn't normal
10876;; conditional execution sufficient?
10877
9c08d1fa 10878(define_split
10879 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 10880 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10881 [(match_operand 2 "" "") (match_operand 3 "" "")])
10882 (match_dup 0)
10883 (match_operand 4 "" "")))
bd5b4116 10884 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10885 "TARGET_ARM && reload_completed"
8fa3ba89 10886 [(set (match_dup 5) (match_dup 6))
10887 (cond_exec (match_dup 7)
10888 (set (match_dup 0) (match_dup 4)))]
10889 "
10890 {
3754d046 10891 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8fa3ba89 10892 operands[2], operands[3]);
10893 enum rtx_code rc = GET_CODE (operands[1]);
10894
bd5b4116 10895 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10896 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10897 if (mode == CCFPmode || mode == CCFPEmode)
10898 rc = reverse_condition_maybe_unordered (rc);
10899 else
10900 rc = reverse_condition (rc);
10901
10902 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
10903 }"
10904)
10905
10906(define_split
10907 [(set (match_operand:SI 0 "s_register_operand" "")
10908 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10909 [(match_operand 2 "" "") (match_operand 3 "" "")])
10910 (match_operand 4 "" "")
10911 (match_dup 0)))
bd5b4116 10912 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10913 "TARGET_ARM && reload_completed"
8fa3ba89 10914 [(set (match_dup 5) (match_dup 6))
10915 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
10916 (set (match_dup 0) (match_dup 4)))]
10917 "
10918 {
3754d046 10919 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8fa3ba89 10920 operands[2], operands[3]);
10921
bd5b4116 10922 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10923 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10924 }"
10925)
10926
10927(define_split
10928 [(set (match_operand:SI 0 "s_register_operand" "")
10929 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9c08d1fa 10930 [(match_operand 2 "" "") (match_operand 3 "" "")])
10931 (match_operand 4 "" "")
10932 (match_operand 5 "" "")))
bd5b4116 10933 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10934 "TARGET_ARM && reload_completed"
8fa3ba89 10935 [(set (match_dup 6) (match_dup 7))
10936 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10937 (set (match_dup 0) (match_dup 4)))
10938 (cond_exec (match_dup 8)
10939 (set (match_dup 0) (match_dup 5)))]
10940 "
10941 {
3754d046 10942 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8fa3ba89 10943 operands[2], operands[3]);
10944 enum rtx_code rc = GET_CODE (operands[1]);
10945
bd5b4116 10946 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10947 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10948 if (mode == CCFPmode || mode == CCFPEmode)
10949 rc = reverse_condition_maybe_unordered (rc);
10950 else
10951 rc = reverse_condition (rc);
10952
10953 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10954 }"
10955)
10956
cffb2a26 10957(define_split
10958 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 10959 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
cffb2a26 10960 [(match_operand:SI 2 "s_register_operand" "")
10961 (match_operand:SI 3 "arm_add_operand" "")])
10962 (match_operand:SI 4 "arm_rhs_operand" "")
10963 (not:SI
10964 (match_operand:SI 5 "s_register_operand" ""))))
bd5b4116 10965 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10966 "TARGET_ARM && reload_completed"
cffb2a26 10967 [(set (match_dup 6) (match_dup 7))
f6c53574 10968 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10969 (set (match_dup 0) (match_dup 4)))
10970 (cond_exec (match_dup 8)
10971 (set (match_dup 0) (not:SI (match_dup 5))))]
cffb2a26 10972 "
215b30b3 10973 {
3754d046 10974 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
215b30b3 10975 operands[2], operands[3]);
f6c53574 10976 enum rtx_code rc = GET_CODE (operands[1]);
cffb2a26 10977
bd5b4116 10978 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
1a83b3ff 10979 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
f6c53574 10980 if (mode == CCFPmode || mode == CCFPEmode)
10981 rc = reverse_condition_maybe_unordered (rc);
10982 else
10983 rc = reverse_condition (rc);
10984
10985 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
215b30b3 10986 }"
10987)
cffb2a26 10988
10989(define_insn "*cond_move_not"
10990 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10991 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
cffb2a26 10992 [(match_operand 3 "cc_register" "") (const_int 0)])
10993 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10994 (not:SI
10995 (match_operand:SI 2 "s_register_operand" "r,r"))))]
10996 "TARGET_ARM"
10997 "@
10998 mvn%D4\\t%0, %2
10999 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
0d66636f 11000 [(set_attr "conds" "use")
1b7da4ac 11001 (set_attr "type" "mvn_reg,multiple")
0d66636f 11002 (set_attr "length" "4,8")]
11003)
cffb2a26 11004
9c08d1fa 11005;; The next two patterns occur when an AND operation is followed by a
11006;; scc insn sequence
11007
f7fbdd4a 11008(define_insn "*sign_extract_onebit"
9c08d1fa 11009 [(set (match_operand:SI 0 "s_register_operand" "=r")
11010 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
11011 (const_int 1)
ed750274 11012 (match_operand:SI 2 "const_int_operand" "n")))
11013 (clobber (reg:CC CC_REGNUM))]
cffb2a26 11014 "TARGET_ARM"
9c08d1fa 11015 "*
0d66636f 11016 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
11017 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
11018 return \"mvnne\\t%0, #0\";
11019 "
11020 [(set_attr "conds" "clob")
1b7da4ac 11021 (set_attr "length" "8")
11022 (set_attr "type" "multiple")]
0d66636f 11023)
9c08d1fa 11024
f7fbdd4a 11025(define_insn "*not_signextract_onebit"
9c08d1fa 11026 [(set (match_operand:SI 0 "s_register_operand" "=r")
11027 (not:SI
11028 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
11029 (const_int 1)
ed750274 11030 (match_operand:SI 2 "const_int_operand" "n"))))
11031 (clobber (reg:CC CC_REGNUM))]
cffb2a26 11032 "TARGET_ARM"
9c08d1fa 11033 "*
0d66636f 11034 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
11035 output_asm_insn (\"tst\\t%1, %2\", operands);
11036 output_asm_insn (\"mvneq\\t%0, #0\", operands);
11037 return \"movne\\t%0, #0\";
11038 "
11039 [(set_attr "conds" "clob")
1b7da4ac 11040 (set_attr "length" "12")
11041 (set_attr "type" "multiple")]
0d66636f 11042)
25f905c2 11043;; ??? The above patterns need auditing for Thumb-2
87b22bf7 11044
0d66636f 11045;; Push multiple registers to the stack. Registers are in parallel (use ...)
11046;; expressions. For simplicity, the first register is also in the unspec
11047;; part.
08508cbf 11048;; To avoid the usage of GNU extension, the length attribute is computed
11049;; in a C function arm_attr_length_push_multi.
f7fbdd4a 11050(define_insn "*push_multi"
87b22bf7 11051 [(match_parallel 2 "multi_register_push"
7571d3f7 11052 [(set (match_operand:BLK 0 "push_mult_memory_operand" "")
3cc80a30 11053 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "")]
e1159bbe 11054 UNSPEC_PUSH_MULT))])]
7571d3f7 11055 ""
87b22bf7 11056 "*
215b30b3 11057 {
11058 int num_saves = XVECLEN (operands[2], 0);
ed593f11 11059
215b30b3 11060 /* For the StrongARM at least it is faster to
25f905c2 11061 use STR to store only a single register.
542d5028 11062 In Thumb mode always use push, and the assembler will pick
11063 something appropriate. */
25f905c2 11064 if (num_saves == 1 && TARGET_ARM)
61309563 11065 output_asm_insn (\"str%?\\t%1, [%m0, #-4]!\", operands);
215b30b3 11066 else
11067 {
11068 int i;
11069 char pattern[100];
ed593f11 11070
3ef90e77 11071 if (TARGET_32BIT)
61309563 11072 strcpy (pattern, \"push%?\\t{%1\");
25f905c2 11073 else
11074 strcpy (pattern, \"push\\t{%1\");
215b30b3 11075
6079f055 11076 for (i = 1; i < num_saves; i++)
215b30b3 11077 {
11078 strcat (pattern, \", %|\");
11079 strcat (pattern,
11080 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
11081 }
11082
11083 strcat (pattern, \"}\");
11084 output_asm_insn (pattern, operands);
11085 }
11086
11087 return \"\";
11088 }"
9f2c2a36 11089 [(set_attr "type" "store_16")
a6864a24 11090 (set (attr "length")
08508cbf 11091 (symbol_ref "arm_attr_length_push_multi (operands[2], operands[1])"))]
215b30b3 11092)
f7fbdd4a 11093
4c58c898 11094(define_insn "stack_tie"
11095 [(set (mem:BLK (scratch))
aaa37ad6 11096 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "rk")
11097 (match_operand:SI 1 "s_register_operand" "rk")]
4c58c898 11098 UNSPEC_PRLG_STK))]
11099 ""
11100 ""
1b7da4ac 11101 [(set_attr "length" "0")
11102 (set_attr "type" "block")]
4c58c898 11103)
11104
426be8c5 11105;; Pop (as used in epilogue RTL)
11106;;
11107(define_insn "*load_multiple_with_writeback"
11108 [(match_parallel 0 "load_multiple_operation"
11109 [(set (match_operand:SI 1 "s_register_operand" "+rk")
11110 (plus:SI (match_dup 1)
809003b3 11111 (match_operand:SI 2 "const_int_I_operand" "I")))
426be8c5 11112 (set (match_operand:SI 3 "s_register_operand" "=rk")
11113 (mem:SI (match_dup 1)))
11114 ])]
11115 "TARGET_32BIT && (reload_in_progress || reload_completed)"
11116 "*
11117 {
11118 arm_output_multireg_pop (operands, /*return_pc=*/false,
11119 /*cond=*/const_true_rtx,
11120 /*reverse=*/false,
11121 /*update=*/true);
11122 return \"\";
11123 }
11124 "
9f2c2a36 11125 [(set_attr "type" "load_16")
5431c9c9 11126 (set_attr "predicable" "yes")
11127 (set (attr "length")
11128 (symbol_ref "arm_attr_length_pop_multi (operands,
11129 /*return_pc=*/false,
11130 /*write_back_p=*/true)"))]
426be8c5 11131)
11132
11133;; Pop with return (as used in epilogue RTL)
11134;;
11135;; This instruction is generated when the registers are popped at the end of
11136;; epilogue. Here, instead of popping the value into LR and then generating
11137;; jump to LR, value is popped into PC directly. Hence, the pattern is combined
11138;; with (return).
11139(define_insn "*pop_multiple_with_writeback_and_return"
11140 [(match_parallel 0 "pop_multiple_return"
11141 [(return)
11142 (set (match_operand:SI 1 "s_register_operand" "+rk")
11143 (plus:SI (match_dup 1)
809003b3 11144 (match_operand:SI 2 "const_int_I_operand" "I")))
426be8c5 11145 (set (match_operand:SI 3 "s_register_operand" "=rk")
11146 (mem:SI (match_dup 1)))
11147 ])]
11148 "TARGET_32BIT && (reload_in_progress || reload_completed)"
11149 "*
11150 {
11151 arm_output_multireg_pop (operands, /*return_pc=*/true,
11152 /*cond=*/const_true_rtx,
11153 /*reverse=*/false,
11154 /*update=*/true);
11155 return \"\";
11156 }
11157 "
9f2c2a36 11158 [(set_attr "type" "load_16")
5431c9c9 11159 (set_attr "predicable" "yes")
11160 (set (attr "length")
11161 (symbol_ref "arm_attr_length_pop_multi (operands, /*return_pc=*/true,
11162 /*write_back_p=*/true)"))]
426be8c5 11163)
11164
11165(define_insn "*pop_multiple_with_return"
11166 [(match_parallel 0 "pop_multiple_return"
11167 [(return)
11168 (set (match_operand:SI 2 "s_register_operand" "=rk")
11169 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
11170 ])]
11171 "TARGET_32BIT && (reload_in_progress || reload_completed)"
11172 "*
11173 {
11174 arm_output_multireg_pop (operands, /*return_pc=*/true,
11175 /*cond=*/const_true_rtx,
11176 /*reverse=*/false,
11177 /*update=*/false);
11178 return \"\";
11179 }
11180 "
9f2c2a36 11181 [(set_attr "type" "load_16")
5431c9c9 11182 (set_attr "predicable" "yes")
11183 (set (attr "length")
11184 (symbol_ref "arm_attr_length_pop_multi (operands, /*return_pc=*/true,
11185 /*write_back_p=*/false)"))]
426be8c5 11186)
11187
11188;; Load into PC and return
11189(define_insn "*ldr_with_return"
11190 [(return)
11191 (set (reg:SI PC_REGNUM)
11192 (mem:SI (post_inc:SI (match_operand:SI 0 "s_register_operand" "+rk"))))]
11193 "TARGET_32BIT && (reload_in_progress || reload_completed)"
11194 "ldr%?\t%|pc, [%0], #4"
9f2c2a36 11195 [(set_attr "type" "load_4")
426be8c5 11196 (set_attr "predicable" "yes")]
11197)
1a0b0f12 11198;; Pop for floating point registers (as used in epilogue RTL)
11199(define_insn "*vfp_pop_multiple_with_writeback"
11200 [(match_parallel 0 "pop_multiple_fp"
11201 [(set (match_operand:SI 1 "s_register_operand" "+rk")
11202 (plus:SI (match_dup 1)
809003b3 11203 (match_operand:SI 2 "const_int_I_operand" "I")))
2f2163a4 11204 (set (match_operand:DF 3 "vfp_hard_register_operand" "")
1a0b0f12 11205 (mem:DF (match_dup 1)))])]
d7216193 11206 "TARGET_32BIT && TARGET_HARD_FLOAT"
1a0b0f12 11207 "*
11208 {
11209 int num_regs = XVECLEN (operands[0], 0);
11210 char pattern[100];
11211 rtx op_list[2];
b34d8dac 11212 strcpy (pattern, \"vldm\\t\");
1a0b0f12 11213 strcat (pattern, reg_names[REGNO (SET_DEST (XVECEXP (operands[0], 0, 0)))]);
11214 strcat (pattern, \"!, {\");
11215 op_list[0] = XEXP (XVECEXP (operands[0], 0, 1), 0);
11216 strcat (pattern, \"%P0\");
11217 if ((num_regs - 1) > 1)
11218 {
11219 strcat (pattern, \"-%P1\");
11220 op_list [1] = XEXP (XVECEXP (operands[0], 0, num_regs - 1), 0);
11221 }
11222
11223 strcat (pattern, \"}\");
11224 output_asm_insn (pattern, op_list);
11225 return \"\";
11226 }
11227 "
9f2c2a36 11228 [(set_attr "type" "load_16")
1a0b0f12 11229 (set_attr "conds" "unconditional")
11230 (set_attr "predicable" "no")]
11231)
11232
f7fbdd4a 11233;; Special patterns for dealing with the constant pool
11234
cffb2a26 11235(define_insn "align_4"
e1159bbe 11236 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
cffb2a26 11237 "TARGET_EITHER"
f7fbdd4a 11238 "*
cffb2a26 11239 assemble_align (32);
f7fbdd4a 11240 return \"\";
cffb2a26 11241 "
1b7da4ac 11242 [(set_attr "type" "no_insn")]
cffb2a26 11243)
f7fbdd4a 11244
755eb2b4 11245(define_insn "align_8"
11246 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
f9273c43 11247 "TARGET_EITHER"
755eb2b4 11248 "*
11249 assemble_align (64);
11250 return \"\";
11251 "
1b7da4ac 11252 [(set_attr "type" "no_insn")]
755eb2b4 11253)
11254
cffb2a26 11255(define_insn "consttable_end"
e1159bbe 11256 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
cffb2a26 11257 "TARGET_EITHER"
f7fbdd4a 11258 "*
cffb2a26 11259 making_const_table = FALSE;
f7fbdd4a 11260 return \"\";
cffb2a26 11261 "
1b7da4ac 11262 [(set_attr "type" "no_insn")]
cffb2a26 11263)
f7fbdd4a 11264
0e207eb8 11265(define_insn "consttable_1"
11266 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
11267 "TARGET_EITHER"
11268 "*
11269 making_const_table = TRUE;
11270 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
11271 assemble_zeros (3);
11272 return \"\";
11273 "
11274 [(set_attr "length" "4")
11275 (set_attr "type" "no_insn")]
11276)
11277
11278(define_insn "consttable_2"
11279 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
11280 "TARGET_EITHER"
11281 "*
11282 {
11283 rtx x = operands[0];
11284 making_const_table = TRUE;
11285 switch (GET_MODE_CLASS (GET_MODE (x)))
11286 {
11287 case MODE_FLOAT:
11288 arm_emit_fp16_const (x);
11289 break;
11290 default:
11291 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
11292 assemble_zeros (2);
11293 break;
11294 }
11295 return \"\";
11296 }"
11297 [(set_attr "length" "4")
11298 (set_attr "type" "no_insn")]
11299)
11300
cffb2a26 11301(define_insn "consttable_4"
e1159bbe 11302 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
cffb2a26 11303 "TARGET_EITHER"
11304 "*
11305 {
9b8516be 11306 rtx x = operands[0];
cffb2a26 11307 making_const_table = TRUE;
0f97e0f5 11308 scalar_float_mode float_mode;
11309 if (is_a <scalar_float_mode> (GET_MODE (x), &float_mode))
11310 assemble_real (*CONST_DOUBLE_REAL_VALUE (x), float_mode, BITS_PER_WORD);
11311 else
cffb2a26 11312 {
7b04c5d5 11313 /* XXX: Sometimes gcc does something really dumb and ends up with
11314 a HIGH in a constant pool entry, usually because it's trying to
11315 load into a VFP register. We know this will always be used in
11316 combination with a LO_SUM which ignores the high bits, so just
11317 strip off the HIGH. */
11318 if (GET_CODE (x) == HIGH)
11319 x = XEXP (x, 0);
9b8516be 11320 assemble_integer (x, 4, BITS_PER_WORD, 1);
11321 mark_symbol_refs_as_used (x);
cffb2a26 11322 }
11323 return \"\";
11324 }"
1b7da4ac 11325 [(set_attr "length" "4")
11326 (set_attr "type" "no_insn")]
cffb2a26 11327)
11328
11329(define_insn "consttable_8"
e1159bbe 11330 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
cffb2a26 11331 "TARGET_EITHER"
11332 "*
11333 {
11334 making_const_table = TRUE;
0f97e0f5 11335 scalar_float_mode float_mode;
11336 if (is_a <scalar_float_mode> (GET_MODE (operands[0]), &float_mode))
11337 assemble_real (*CONST_DOUBLE_REAL_VALUE (operands[0]),
11338 float_mode, BITS_PER_WORD);
11339 else
11340 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
cffb2a26 11341 return \"\";
11342 }"
1b7da4ac 11343 [(set_attr "length" "8")
11344 (set_attr "type" "no_insn")]
cffb2a26 11345)
11346
d98a3884 11347(define_insn "consttable_16"
11348 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_16)]
11349 "TARGET_EITHER"
11350 "*
11351 {
11352 making_const_table = TRUE;
0f97e0f5 11353 scalar_float_mode float_mode;
11354 if (is_a <scalar_float_mode> (GET_MODE (operands[0]), &float_mode))
11355 assemble_real (*CONST_DOUBLE_REAL_VALUE (operands[0]),
11356 float_mode, BITS_PER_WORD);
11357 else
11358 assemble_integer (operands[0], 16, BITS_PER_WORD, 1);
d98a3884 11359 return \"\";
11360 }"
1b7da4ac 11361 [(set_attr "length" "16")
11362 (set_attr "type" "no_insn")]
d98a3884 11363)
11364
331beb1a 11365;; V5 Instructions,
11366
8f4be2be 11367(define_insn "clzsi2"
11368 [(set (match_operand:SI 0 "s_register_operand" "=r")
11369 (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 11370 "TARGET_32BIT && arm_arch5"
ee7cbe0e 11371 "clz%?\\t%0, %1"
bcaec148 11372 [(set_attr "predicable" "yes")
4a510717 11373 (set_attr "predicable_short_it" "no")
bebe9bbb 11374 (set_attr "type" "clz")])
331beb1a 11375
099ad98b 11376(define_insn "rbitsi2"
11377 [(set (match_operand:SI 0 "s_register_operand" "=r")
11378 (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")] UNSPEC_RBIT))]
11379 "TARGET_32BIT && arm_arch_thumb2"
11380 "rbit%?\\t%0, %1"
11381 [(set_attr "predicable" "yes")
4a510717 11382 (set_attr "predicable_short_it" "no")
bebe9bbb 11383 (set_attr "type" "clz")])
099ad98b 11384
99ffa689 11385;; Keep this as a CTZ expression until after reload and then split
11386;; into RBIT + CLZ. Since RBIT is represented as an UNSPEC it is unlikely
11387;; to fold with any other expression.
11388
11389(define_insn_and_split "ctzsi2"
11390 [(set (match_operand:SI 0 "s_register_operand" "=r")
11391 (ctz:SI (match_operand:SI 1 "s_register_operand" "r")))]
099ad98b 11392 "TARGET_32BIT && arm_arch_thumb2"
99ffa689 11393 "#"
11394 "&& reload_completed"
11395 [(const_int 0)]
099ad98b 11396 "
99ffa689 11397 emit_insn (gen_rbitsi2 (operands[0], operands[1]));
11398 emit_insn (gen_clzsi2 (operands[0], operands[0]));
11399 DONE;
11400")
099ad98b 11401
e1159bbe 11402;; V5E instructions.
331beb1a 11403
11404(define_insn "prefetch"
f4e79814 11405 [(prefetch (match_operand:SI 0 "address_operand" "p")
11406 (match_operand:SI 1 "" "")
11407 (match_operand:SI 2 "" ""))]
25f905c2 11408 "TARGET_32BIT && arm_arch5e"
1b7da4ac 11409 "pld\\t%a0"
9f2c2a36 11410 [(set_attr "type" "load_4")]
1b7da4ac 11411)
331beb1a 11412
0d66636f 11413;; General predication pattern
11414
11415(define_cond_exec
11416 [(match_operator 0 "arm_comparison_operator"
11417 [(match_operand 1 "cc_register" "")
11418 (const_int 0)])]
580f4c48 11419 "TARGET_32BIT
11420 && (!TARGET_NO_VOLATILE_CE || !volatile_refs_p (PATTERN (insn)))"
0d66636f 11421 ""
c7a58118 11422[(set_attr "predicated" "yes")]
0d66636f 11423)
11424
fb94f18b 11425(define_insn "force_register_use"
11426 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_REGISTER_USE)]
063a05c7 11427 ""
fb94f18b 11428 "%@ %0 needed"
1b7da4ac 11429 [(set_attr "length" "0")
11430 (set_attr "type" "no_insn")]
063a05c7 11431)
7db9af5d 11432
4c44712e 11433
11434;; Patterns for exception handling
11435
11436(define_expand "eh_return"
11437 [(use (match_operand 0 "general_operand" ""))]
11438 "TARGET_EITHER"
11439 "
11440 {
25f905c2 11441 if (TARGET_32BIT)
4c44712e 11442 emit_insn (gen_arm_eh_return (operands[0]));
11443 else
11444 emit_insn (gen_thumb_eh_return (operands[0]));
11445 DONE;
11446 }"
11447)
11448
11449;; We can't expand this before we know where the link register is stored.
11450(define_insn_and_split "arm_eh_return"
11451 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
11452 VUNSPEC_EH_RETURN)
11453 (clobber (match_scratch:SI 1 "=&r"))]
11454 "TARGET_ARM"
11455 "#"
11456 "&& reload_completed"
11457 [(const_int 0)]
11458 "
11459 {
11460 arm_set_return_address (operands[0], operands[1]);
11461 DONE;
11462 }"
11463)
11464
f655717d 11465\f
11466;; TLS support
11467
11468(define_insn "load_tp_hard"
11469 [(set (match_operand:SI 0 "register_operand" "=r")
11470 (unspec:SI [(const_int 0)] UNSPEC_TLS))]
11471 "TARGET_HARD_TP"
11472 "mrc%?\\tp15, 0, %0, c13, c0, 3\\t@ load_tp_hard"
1b7da4ac 11473 [(set_attr "predicable" "yes")
4b5d7374 11474 (set_attr "type" "mrs")]
f655717d 11475)
11476
11477;; Doesn't clobber R1-R3. Must use r0 for the first operand.
11478(define_insn "load_tp_soft"
11479 [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
11480 (clobber (reg:SI LR_REGNUM))
11481 (clobber (reg:SI IP_REGNUM))
11482 (clobber (reg:CC CC_REGNUM))]
11483 "TARGET_SOFT_TP"
11484 "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
1b7da4ac 11485 [(set_attr "conds" "clob")
11486 (set_attr "type" "branch")]
f655717d 11487)
11488
f41e4452 11489;; tls descriptor call
11490(define_insn "tlscall"
11491 [(set (reg:SI R0_REGNUM)
11492 (unspec:SI [(reg:SI R0_REGNUM)
11493 (match_operand:SI 0 "" "X")
11494 (match_operand 1 "" "")] UNSPEC_TLS))
11495 (clobber (reg:SI R1_REGNUM))
11496 (clobber (reg:SI LR_REGNUM))
11497 (clobber (reg:SI CC_REGNUM))]
11498 "TARGET_GNU2_TLS"
11499 {
11500 targetm.asm_out.internal_label (asm_out_file, "LPIC",
11501 INTVAL (operands[1]));
11502 return "bl\\t%c0(tlscall)";
11503 }
11504 [(set_attr "conds" "clob")
1b7da4ac 11505 (set_attr "length" "4")
11506 (set_attr "type" "branch")]
f41e4452 11507)
11508
1fe0edab 11509;; For thread pointer builtin
11510(define_expand "get_thread_pointersi"
11511 [(match_operand:SI 0 "s_register_operand" "=r")]
11512 ""
11513 "
11514 {
11515 arm_load_tp (operands[0]);
11516 DONE;
11517 }")
11518
f41e4452 11519;;
11520
aabe09ac 11521;; We only care about the lower 16 bits of the constant
11522;; being inserted into the upper 16 bits of the register.
eca5c984 11523(define_insn "*arm_movtas_ze"
417e5cc5 11524 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r,r")
eca5c984 11525 (const_int 16)
11526 (const_int 16))
11527 (match_operand:SI 1 "const_int_operand" ""))]
60a48e7d 11528 "TARGET_HAVE_MOVT"
417e5cc5 11529 "@
11530 movt%?\t%0, %L1
11531 movt\t%0, %L1"
11532 [(set_attr "arch" "32,v8mb")
11533 (set_attr "predicable" "yes")
7c36fe71 11534 (set_attr "predicable_short_it" "no")
1b7da4ac 11535 (set_attr "length" "4")
282b4c75 11536 (set_attr "type" "alu_sreg")]
eca5c984 11537)
11538
c0fc3696 11539(define_insn "*arm_rev"
a486b499 11540 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
11541 (bswap:SI (match_operand:SI 1 "s_register_operand" "l,l,r")))]
11542 "arm_arch6"
11543 "@
11544 rev\t%0, %1
11545 rev%?\t%0, %1
11546 rev%?\t%0, %1"
11547 [(set_attr "arch" "t1,t2,32")
1b7da4ac 11548 (set_attr "length" "2,2,4")
4a510717 11549 (set_attr "predicable" "no,yes,yes")
11550 (set_attr "predicable_short_it" "no")
1b7da4ac 11551 (set_attr "type" "rev")]
ff82f757 11552)
11553
11554(define_expand "arm_legacy_rev"
11555 [(set (match_operand:SI 2 "s_register_operand" "")
11556 (xor:SI (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
11557 (const_int 16))
11558 (match_dup 1)))
11559 (set (match_dup 2)
11560 (lshiftrt:SI (match_dup 2)
11561 (const_int 8)))
11562 (set (match_operand:SI 3 "s_register_operand" "")
11563 (rotatert:SI (match_dup 1)
11564 (const_int 8)))
11565 (set (match_dup 2)
11566 (and:SI (match_dup 2)
11567 (const_int -65281)))
11568 (set (match_operand:SI 0 "s_register_operand" "")
11569 (xor:SI (match_dup 3)
11570 (match_dup 2)))]
11571 "TARGET_32BIT"
11572 ""
11573)
11574
11575;; Reuse temporaries to keep register pressure down.
11576(define_expand "thumb_legacy_rev"
11577 [(set (match_operand:SI 2 "s_register_operand" "")
11578 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
11579 (const_int 24)))
11580 (set (match_operand:SI 3 "s_register_operand" "")
11581 (lshiftrt:SI (match_dup 1)
11582 (const_int 24)))
11583 (set (match_dup 3)
11584 (ior:SI (match_dup 3)
11585 (match_dup 2)))
11586 (set (match_operand:SI 4 "s_register_operand" "")
11587 (const_int 16))
11588 (set (match_operand:SI 5 "s_register_operand" "")
11589 (rotatert:SI (match_dup 1)
11590 (match_dup 4)))
11591 (set (match_dup 2)
11592 (ashift:SI (match_dup 5)
11593 (const_int 24)))
11594 (set (match_dup 5)
11595 (lshiftrt:SI (match_dup 5)
11596 (const_int 24)))
11597 (set (match_dup 5)
11598 (ior:SI (match_dup 5)
11599 (match_dup 2)))
11600 (set (match_dup 5)
11601 (rotatert:SI (match_dup 5)
11602 (match_dup 4)))
11603 (set (match_operand:SI 0 "s_register_operand" "")
11604 (ior:SI (match_dup 5)
11605 (match_dup 3)))]
11606 "TARGET_THUMB"
11607 ""
11608)
11609
62e39b06 11610;; ARM-specific expansion of signed mod by power of 2
11611;; using conditional negate.
11612;; For r0 % n where n is a power of 2 produce:
11613;; rsbs r1, r0, #0
11614;; and r0, r0, #(n - 1)
11615;; and r1, r1, #(n - 1)
11616;; rsbpl r0, r1, #0
11617
11618(define_expand "modsi3"
11619 [(match_operand:SI 0 "register_operand" "")
11620 (match_operand:SI 1 "register_operand" "")
11621 (match_operand:SI 2 "const_int_operand" "")]
11622 "TARGET_32BIT"
11623 {
11624 HOST_WIDE_INT val = INTVAL (operands[2]);
11625
11626 if (val <= 0
11627 || exact_log2 (val) <= 0)
11628 FAIL;
11629
11630 rtx mask = GEN_INT (val - 1);
11631
11632 /* In the special case of x0 % 2 we can do the even shorter:
11633 cmp r0, #0
11634 and r0, r0, #1
11635 rsblt r0, r0, #0. */
11636
11637 if (val == 2)
11638 {
11639 rtx cc_reg = arm_gen_compare_reg (LT,
11640 operands[1], const0_rtx, NULL_RTX);
11641 rtx cond = gen_rtx_LT (SImode, cc_reg, const0_rtx);
11642 rtx masked = gen_reg_rtx (SImode);
11643
11644 emit_insn (gen_andsi3 (masked, operands[1], mask));
11645 emit_move_insn (operands[0],
11646 gen_rtx_IF_THEN_ELSE (SImode, cond,
11647 gen_rtx_NEG (SImode,
11648 masked),
11649 masked));
11650 DONE;
11651 }
11652
11653 rtx neg_op = gen_reg_rtx (SImode);
11654 rtx_insn *insn = emit_insn (gen_subsi3_compare0 (neg_op, const0_rtx,
11655 operands[1]));
11656
11657 /* Extract the condition register and mode. */
11658 rtx cmp = XVECEXP (PATTERN (insn), 0, 0);
11659 rtx cc_reg = SET_DEST (cmp);
11660 rtx cond = gen_rtx_GE (SImode, cc_reg, const0_rtx);
11661
11662 emit_insn (gen_andsi3 (operands[0], operands[1], mask));
11663
11664 rtx masked_neg = gen_reg_rtx (SImode);
11665 emit_insn (gen_andsi3 (masked_neg, neg_op, mask));
11666
11667 /* We want a conditional negate here, but emitting COND_EXEC rtxes
11668 during expand does not always work. Do an IF_THEN_ELSE instead. */
11669 emit_move_insn (operands[0],
11670 gen_rtx_IF_THEN_ELSE (SImode, cond,
11671 gen_rtx_NEG (SImode, masked_neg),
11672 operands[0]));
11673
11674
11675 DONE;
11676 }
11677)
11678
ff82f757 11679(define_expand "bswapsi2"
11680 [(set (match_operand:SI 0 "s_register_operand" "=r")
11681 (bswap:SI (match_operand:SI 1 "s_register_operand" "r")))]
8d1af482 11682"TARGET_EITHER && (arm_arch6 || !optimize_size)"
ff82f757 11683"
8d1af482 11684 if (!arm_arch6)
11685 {
11686 rtx op2 = gen_reg_rtx (SImode);
11687 rtx op3 = gen_reg_rtx (SImode);
ff82f757 11688
8d1af482 11689 if (TARGET_THUMB)
11690 {
11691 rtx op4 = gen_reg_rtx (SImode);
11692 rtx op5 = gen_reg_rtx (SImode);
ff82f757 11693
8d1af482 11694 emit_insn (gen_thumb_legacy_rev (operands[0], operands[1],
11695 op2, op3, op4, op5));
11696 }
11697 else
11698 {
11699 emit_insn (gen_arm_legacy_rev (operands[0], operands[1],
11700 op2, op3));
11701 }
ff82f757 11702
8d1af482 11703 DONE;
11704 }
ff82f757 11705 "
11706)
11707
a486b499 11708;; bswap16 patterns: use revsh and rev16 instructions for the signed
11709;; and unsigned variants, respectively. For rev16, expose
11710;; byte-swapping in the lower 16 bits only.
11711(define_insn "*arm_revsh"
11712 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
11713 (sign_extend:SI (bswap:HI (match_operand:HI 1 "s_register_operand" "l,l,r"))))]
11714 "arm_arch6"
11715 "@
11716 revsh\t%0, %1
11717 revsh%?\t%0, %1
11718 revsh%?\t%0, %1"
11719 [(set_attr "arch" "t1,t2,32")
1b7da4ac 11720 (set_attr "length" "2,2,4")
11721 (set_attr "type" "rev")]
a486b499 11722)
11723
11724(define_insn "*arm_rev16"
11725 [(set (match_operand:HI 0 "s_register_operand" "=l,l,r")
11726 (bswap:HI (match_operand:HI 1 "s_register_operand" "l,l,r")))]
11727 "arm_arch6"
11728 "@
11729 rev16\t%0, %1
11730 rev16%?\t%0, %1
11731 rev16%?\t%0, %1"
11732 [(set_attr "arch" "t1,t2,32")
1b7da4ac 11733 (set_attr "length" "2,2,4")
11734 (set_attr "type" "rev")]
09f69e55 11735)
11736
11737;; There are no canonicalisation rules for the position of the lshiftrt, ashift
11738;; operations within an IOR/AND RTX, therefore we have two patterns matching
11739;; each valid permutation.
11740
11741(define_insn "arm_rev16si2"
11742 [(set (match_operand:SI 0 "register_operand" "=l,l,r")
11743 (ior:SI (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "l,l,r")
11744 (const_int 8))
11745 (match_operand:SI 3 "const_int_operand" "n,n,n"))
11746 (and:SI (lshiftrt:SI (match_dup 1)
11747 (const_int 8))
11748 (match_operand:SI 2 "const_int_operand" "n,n,n"))))]
11749 "arm_arch6
11750 && aarch_rev16_shleft_mask_imm_p (operands[3], SImode)
11751 && aarch_rev16_shright_mask_imm_p (operands[2], SImode)"
11752 "rev16\\t%0, %1"
11753 [(set_attr "arch" "t1,t2,32")
11754 (set_attr "length" "2,2,4")
11755 (set_attr "type" "rev")]
11756)
11757
11758(define_insn "arm_rev16si2_alt"
11759 [(set (match_operand:SI 0 "register_operand" "=l,l,r")
11760 (ior:SI (and:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,l,r")
11761 (const_int 8))
11762 (match_operand:SI 2 "const_int_operand" "n,n,n"))
11763 (and:SI (ashift:SI (match_dup 1)
11764 (const_int 8))
11765 (match_operand:SI 3 "const_int_operand" "n,n,n"))))]
11766 "arm_arch6
11767 && aarch_rev16_shleft_mask_imm_p (operands[3], SImode)
11768 && aarch_rev16_shright_mask_imm_p (operands[2], SImode)"
11769 "rev16\\t%0, %1"
11770 [(set_attr "arch" "t1,t2,32")
11771 (set_attr "length" "2,2,4")
11772 (set_attr "type" "rev")]
a486b499 11773)
11774
11775(define_expand "bswaphi2"
11776 [(set (match_operand:HI 0 "s_register_operand" "=r")
11777 (bswap:HI (match_operand:HI 1 "s_register_operand" "r")))]
11778"arm_arch6"
11779""
11780)
11781
1653cf17 11782;; Patterns for LDRD/STRD in Thumb2 mode
11783
11784(define_insn "*thumb2_ldrd"
11785 [(set (match_operand:SI 0 "s_register_operand" "=r")
11786 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
11787 (match_operand:SI 2 "ldrd_strd_offset_operand" "Do"))))
11788 (set (match_operand:SI 3 "s_register_operand" "=r")
11789 (mem:SI (plus:SI (match_dup 1)
11790 (match_operand:SI 4 "const_int_operand" ""))))]
11791 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
1653cf17 11792 && ((INTVAL (operands[2]) + 4) == INTVAL (operands[4]))
11793 && (operands_ok_ldrd_strd (operands[0], operands[3],
11794 operands[1], INTVAL (operands[2]),
11795 false, true))"
11796 "ldrd%?\t%0, %3, [%1, %2]"
9f2c2a36 11797 [(set_attr "type" "load_8")
d952d547 11798 (set_attr "predicable" "yes")
11799 (set_attr "predicable_short_it" "no")])
1653cf17 11800
11801(define_insn "*thumb2_ldrd_base"
11802 [(set (match_operand:SI 0 "s_register_operand" "=r")
11803 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
11804 (set (match_operand:SI 2 "s_register_operand" "=r")
11805 (mem:SI (plus:SI (match_dup 1)
11806 (const_int 4))))]
11807 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
1653cf17 11808 && (operands_ok_ldrd_strd (operands[0], operands[2],
11809 operands[1], 0, false, true))"
11810 "ldrd%?\t%0, %2, [%1]"
9f2c2a36 11811 [(set_attr "type" "load_8")
d952d547 11812 (set_attr "predicable" "yes")
11813 (set_attr "predicable_short_it" "no")])
1653cf17 11814
11815(define_insn "*thumb2_ldrd_base_neg"
11816 [(set (match_operand:SI 0 "s_register_operand" "=r")
11817 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
11818 (const_int -4))))
11819 (set (match_operand:SI 2 "s_register_operand" "=r")
11820 (mem:SI (match_dup 1)))]
11821 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
1653cf17 11822 && (operands_ok_ldrd_strd (operands[0], operands[2],
11823 operands[1], -4, false, true))"
11824 "ldrd%?\t%0, %2, [%1, #-4]"
9f2c2a36 11825 [(set_attr "type" "load_8")
d952d547 11826 (set_attr "predicable" "yes")
11827 (set_attr "predicable_short_it" "no")])
1653cf17 11828
11829(define_insn "*thumb2_strd"
11830 [(set (mem:SI (plus:SI (match_operand:SI 0 "s_register_operand" "rk")
11831 (match_operand:SI 1 "ldrd_strd_offset_operand" "Do")))
11832 (match_operand:SI 2 "s_register_operand" "r"))
11833 (set (mem:SI (plus:SI (match_dup 0)
11834 (match_operand:SI 3 "const_int_operand" "")))
11835 (match_operand:SI 4 "s_register_operand" "r"))]
11836 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
1653cf17 11837 && ((INTVAL (operands[1]) + 4) == INTVAL (operands[3]))
11838 && (operands_ok_ldrd_strd (operands[2], operands[4],
11839 operands[0], INTVAL (operands[1]),
11840 false, false))"
11841 "strd%?\t%2, %4, [%0, %1]"
9f2c2a36 11842 [(set_attr "type" "store_8")
d952d547 11843 (set_attr "predicable" "yes")
11844 (set_attr "predicable_short_it" "no")])
1653cf17 11845
11846(define_insn "*thumb2_strd_base"
11847 [(set (mem:SI (match_operand:SI 0 "s_register_operand" "rk"))
11848 (match_operand:SI 1 "s_register_operand" "r"))
11849 (set (mem:SI (plus:SI (match_dup 0)
11850 (const_int 4)))
11851 (match_operand:SI 2 "s_register_operand" "r"))]
11852 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
1653cf17 11853 && (operands_ok_ldrd_strd (operands[1], operands[2],
11854 operands[0], 0, false, false))"
11855 "strd%?\t%1, %2, [%0]"
9f2c2a36 11856 [(set_attr "type" "store_8")
d952d547 11857 (set_attr "predicable" "yes")
11858 (set_attr "predicable_short_it" "no")])
1653cf17 11859
11860(define_insn "*thumb2_strd_base_neg"
11861 [(set (mem:SI (plus:SI (match_operand:SI 0 "s_register_operand" "rk")
11862 (const_int -4)))
11863 (match_operand:SI 1 "s_register_operand" "r"))
11864 (set (mem:SI (match_dup 0))
11865 (match_operand:SI 2 "s_register_operand" "r"))]
11866 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
1653cf17 11867 && (operands_ok_ldrd_strd (operands[1], operands[2],
11868 operands[0], -4, false, false))"
11869 "strd%?\t%1, %2, [%0, #-4]"
9f2c2a36 11870 [(set_attr "type" "store_8")
d952d547 11871 (set_attr "predicable" "yes")
11872 (set_attr "predicable_short_it" "no")])
1653cf17 11873
2a0c73f2 11874;; ARMv8 CRC32 instructions.
11875(define_insn "<crc_variant>"
11876 [(set (match_operand:SI 0 "s_register_operand" "=r")
11877 (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")
11878 (match_operand:<crc_mode> 2 "s_register_operand" "r")]
11879 CRC))]
11880 "TARGET_CRC32"
11881 "<crc_variant>\\t%0, %1, %2"
11882 [(set_attr "type" "crc")
11883 (set_attr "conds" "unconditional")]
11884)
1653cf17 11885
353cf59a 11886;; Load the load/store double peephole optimizations.
11887(include "ldrdstrd.md")
11888
320ea44d 11889;; Load the load/store multiple patterns
11890(include "ldmstm.md")
426be8c5 11891
11892;; Patterns in ldmstm.md don't cover more than 4 registers. This pattern covers
11893;; large lists without explicit writeback generated for APCS_FRAME epilogue.
3873efff 11894;; The operands are validated through the load_multiple_operation
11895;; match_parallel predicate rather than through constraints so enable it only
11896;; after reload.
426be8c5 11897(define_insn "*load_multiple"
11898 [(match_parallel 0 "load_multiple_operation"
11899 [(set (match_operand:SI 2 "s_register_operand" "=rk")
11900 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
11901 ])]
3873efff 11902 "TARGET_32BIT && reload_completed"
426be8c5 11903 "*
11904 {
11905 arm_output_multireg_pop (operands, /*return_pc=*/false,
11906 /*cond=*/const_true_rtx,
11907 /*reverse=*/false,
11908 /*update=*/false);
11909 return \"\";
11910 }
11911 "
11912 [(set_attr "predicable" "yes")]
11913)
11914
84450ddc 11915(define_expand "copysignsf3"
11916 [(match_operand:SF 0 "register_operand")
11917 (match_operand:SF 1 "register_operand")
11918 (match_operand:SF 2 "register_operand")]
11919 "TARGET_SOFT_FLOAT && arm_arch_thumb2"
11920 "{
11921 emit_move_insn (operands[0], operands[2]);
11922 emit_insn (gen_insv_t2 (simplify_gen_subreg (SImode, operands[0], SFmode, 0),
11923 GEN_INT (31), GEN_INT (0),
11924 simplify_gen_subreg (SImode, operands[1], SFmode, 0)));
11925 DONE;
11926 }"
11927)
11928
11929(define_expand "copysigndf3"
11930 [(match_operand:DF 0 "register_operand")
11931 (match_operand:DF 1 "register_operand")
11932 (match_operand:DF 2 "register_operand")]
11933 "TARGET_SOFT_FLOAT && arm_arch_thumb2"
11934 "{
11935 rtx op0_low = gen_lowpart (SImode, operands[0]);
11936 rtx op0_high = gen_highpart (SImode, operands[0]);
11937 rtx op1_low = gen_lowpart (SImode, operands[1]);
11938 rtx op1_high = gen_highpart (SImode, operands[1]);
11939 rtx op2_high = gen_highpart (SImode, operands[2]);
11940
11941 rtx scratch1 = gen_reg_rtx (SImode);
11942 rtx scratch2 = gen_reg_rtx (SImode);
11943 emit_move_insn (scratch1, op2_high);
11944 emit_move_insn (scratch2, op1_high);
11945
d1f9b275 11946 emit_insn(gen_rtx_SET(scratch1,
84450ddc 11947 gen_rtx_LSHIFTRT (SImode, op2_high, GEN_INT(31))));
11948 emit_insn(gen_insv_t2(scratch2, GEN_INT(1), GEN_INT(31), scratch1));
11949 emit_move_insn (op0_low, op1_low);
11950 emit_move_insn (op0_high, scratch2);
11951
11952 DONE;
11953 }"
11954)
11955
115857ef 11956;; movmisalign patterns for HImode and SImode.
11957(define_expand "movmisalign<mode>"
11958 [(match_operand:HSI 0 "general_operand")
11959 (match_operand:HSI 1 "general_operand")]
11960 "unaligned_access"
11961{
11962 /* This pattern is not permitted to fail during expansion: if both arguments
11963 are non-registers (e.g. memory := constant), force operand 1 into a
11964 register. */
11965 rtx (* gen_unaligned_load)(rtx, rtx);
11966 rtx tmp_dest = operands[0];
11967 if (!s_register_operand (operands[0], <MODE>mode)
11968 && !s_register_operand (operands[1], <MODE>mode))
11969 operands[1] = force_reg (<MODE>mode, operands[1]);
11970
11971 if (<MODE>mode == HImode)
11972 {
11973 gen_unaligned_load = gen_unaligned_loadhiu;
11974 tmp_dest = gen_reg_rtx (SImode);
11975 }
11976 else
11977 gen_unaligned_load = gen_unaligned_loadsi;
11978
11979 if (MEM_P (operands[1]))
11980 {
11981 emit_insn (gen_unaligned_load (tmp_dest, operands[1]));
11982 if (<MODE>mode == HImode)
11983 emit_move_insn (operands[0], gen_lowpart (HImode, tmp_dest));
11984 }
11985 else
11986 emit_insn (gen_unaligned_store<mode> (operands[0], operands[1]));
11987
11988 DONE;
11989})
11990
1be6395a 11991(define_insn "<cdp>"
11992 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "n")
11993 (match_operand:SI 1 "immediate_operand" "n")
11994 (match_operand:SI 2 "immediate_operand" "n")
11995 (match_operand:SI 3 "immediate_operand" "n")
11996 (match_operand:SI 4 "immediate_operand" "n")
11997 (match_operand:SI 5 "immediate_operand" "n")] CDPI)]
11998 "arm_coproc_builtin_available (VUNSPEC_<CDP>)"
11999{
12000 arm_const_bounds (operands[0], 0, 16);
12001 arm_const_bounds (operands[1], 0, 16);
12002 arm_const_bounds (operands[2], 0, (1 << 5));
12003 arm_const_bounds (operands[3], 0, (1 << 5));
12004 arm_const_bounds (operands[4], 0, (1 << 5));
12005 arm_const_bounds (operands[5], 0, 8);
12006 return "<cdp>\\tp%c0, %1, CR%c2, CR%c3, CR%c4, %5";
12007}
12008 [(set_attr "length" "4")
12009 (set_attr "type" "coproc")])
12010
638b44bd 12011(define_insn "*ldc"
12012 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "n")
12013 (match_operand:SI 1 "immediate_operand" "n")
12014 (match_operand:SI 2 "memory_operand" "Uz")] LDCI)]
12015 "arm_coproc_builtin_available (VUNSPEC_<LDC>)"
12016{
12017 arm_const_bounds (operands[0], 0, 16);
12018 arm_const_bounds (operands[1], 0, (1 << 5));
12019 return "<ldc>\\tp%c0, CR%c1, %2";
12020}
12021 [(set_attr "length" "4")
12022 (set_attr "type" "coproc")])
12023
12024(define_insn "*stc"
12025 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "n")
12026 (match_operand:SI 1 "immediate_operand" "n")
12027 (match_operand:SI 2 "memory_operand" "=Uz")] STCI)]
12028 "arm_coproc_builtin_available (VUNSPEC_<STC>)"
12029{
12030 arm_const_bounds (operands[0], 0, 16);
12031 arm_const_bounds (operands[1], 0, (1 << 5));
12032 return "<stc>\\tp%c0, CR%c1, %2";
12033}
12034 [(set_attr "length" "4")
12035 (set_attr "type" "coproc")])
12036
12037(define_expand "<ldc>"
12038 [(unspec_volatile [(match_operand:SI 0 "immediate_operand")
12039 (match_operand:SI 1 "immediate_operand")
12040 (mem:SI (match_operand:SI 2 "s_register_operand"))] LDCI)]
12041 "arm_coproc_builtin_available (VUNSPEC_<LDC>)")
12042
12043(define_expand "<stc>"
12044 [(unspec_volatile [(match_operand:SI 0 "immediate_operand")
12045 (match_operand:SI 1 "immediate_operand")
12046 (mem:SI (match_operand:SI 2 "s_register_operand"))] STCI)]
12047 "arm_coproc_builtin_available (VUNSPEC_<STC>)")
12048
415e9b1f 12049(define_insn "<mcr>"
12050 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "n")
12051 (match_operand:SI 1 "immediate_operand" "n")
12052 (match_operand:SI 2 "s_register_operand" "r")
12053 (match_operand:SI 3 "immediate_operand" "n")
12054 (match_operand:SI 4 "immediate_operand" "n")
12055 (match_operand:SI 5 "immediate_operand" "n")] MCRI)
12056 (use (match_dup 2))]
12057 "arm_coproc_builtin_available (VUNSPEC_<MCR>)"
12058{
12059 arm_const_bounds (operands[0], 0, 16);
12060 arm_const_bounds (operands[1], 0, 8);
12061 arm_const_bounds (operands[3], 0, (1 << 5));
12062 arm_const_bounds (operands[4], 0, (1 << 5));
12063 arm_const_bounds (operands[5], 0, 8);
12064 return "<mcr>\\tp%c0, %1, %2, CR%c3, CR%c4, %5";
12065}
12066 [(set_attr "length" "4")
12067 (set_attr "type" "coproc")])
12068
12069(define_insn "<mrc>"
12070 [(set (match_operand:SI 0 "s_register_operand" "=r")
6f8d7784 12071 (unspec_volatile:SI [(match_operand:SI 1 "immediate_operand" "n")
415e9b1f 12072 (match_operand:SI 2 "immediate_operand" "n")
12073 (match_operand:SI 3 "immediate_operand" "n")
12074 (match_operand:SI 4 "immediate_operand" "n")
12075 (match_operand:SI 5 "immediate_operand" "n")] MRCI))]
12076 "arm_coproc_builtin_available (VUNSPEC_<MRC>)"
12077{
12078 arm_const_bounds (operands[1], 0, 16);
12079 arm_const_bounds (operands[2], 0, 8);
12080 arm_const_bounds (operands[3], 0, (1 << 5));
12081 arm_const_bounds (operands[4], 0, (1 << 5));
12082 arm_const_bounds (operands[5], 0, 8);
12083 return "<mrc>\\tp%c1, %2, %0, CR%c3, CR%c4, %5";
12084}
12085 [(set_attr "length" "4")
12086 (set_attr "type" "coproc")])
12087
cabfd710 12088(define_insn "<mcrr>"
12089 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "n")
12090 (match_operand:SI 1 "immediate_operand" "n")
12091 (match_operand:DI 2 "s_register_operand" "r")
12092 (match_operand:SI 3 "immediate_operand" "n")] MCRRI)
12093 (use (match_dup 2))]
12094 "arm_coproc_builtin_available (VUNSPEC_<MCRR>)"
12095{
12096 arm_const_bounds (operands[0], 0, 16);
12097 arm_const_bounds (operands[1], 0, 8);
12098 arm_const_bounds (operands[3], 0, (1 << 5));
12099 return "<mcrr>\\tp%c0, %1, %Q2, %R2, CR%c3";
12100}
12101 [(set_attr "length" "4")
12102 (set_attr "type" "coproc")])
12103
12104(define_insn "<mrrc>"
12105 [(set (match_operand:DI 0 "s_register_operand" "=r")
6f8d7784 12106 (unspec_volatile:DI [(match_operand:SI 1 "immediate_operand" "n")
cabfd710 12107 (match_operand:SI 2 "immediate_operand" "n")
12108 (match_operand:SI 3 "immediate_operand" "n")] MRRCI))]
12109 "arm_coproc_builtin_available (VUNSPEC_<MRRC>)"
12110{
12111 arm_const_bounds (operands[1], 0, 16);
12112 arm_const_bounds (operands[2], 0, 8);
12113 arm_const_bounds (operands[3], 0, (1 << 5));
12114 return "<mrrc>\\tp%c1, %2, %Q0, %R0, CR%c3";
12115}
12116 [(set_attr "length" "4")
12117 (set_attr "type" "coproc")])
12118
d98a3884 12119;; Vector bits common to IWMMXT and Neon
12120(include "vec-common.md")
755eb2b4 12121;; Load the Intel Wireless Multimedia Extension patterns
12122(include "iwmmxt.md")
a2cd141b 12123;; Load the VFP co-processor patterns
12124(include "vfp.md")
bc360af8 12125;; Thumb-1 patterns
12126(include "thumb1.md")
25f905c2 12127;; Thumb-2 patterns
12128(include "thumb2.md")
d98a3884 12129;; Neon patterns
12130(include "neon.md")
e84fdf6e 12131;; Crypto patterns
12132(include "crypto.md")
06df6b17 12133;; Synchronization Primitives
12134(include "sync.md")
bbbe4599 12135;; Fixed-point patterns
12136(include "arm-fixed.md")