]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/arm/arm.md
Add -march=iamcu to optimize for IA MCU
[thirdparty/gcc.git] / gcc / config / arm / arm.md
CommitLineData
129a2fe4 1;;- Machine description for ARM for GNU compiler
d353bf18 2;; Copyright (C) 1991-2015 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
c7a58118 108(define_attr "predicated" "yes,no" (const_string "no"))
109
094e994f 110; LENGTH of an instruction (in bytes)
06df6b17 111(define_attr "length" ""
e1b93706 112 (const_int 4))
9c08d1fa 113
d5d4dc8d 114; The architecture which supports the instruction (or alternative).
115; This can be "a" for ARM, "t" for either of the Thumbs, "32" for
116; TARGET_32BIT, "t1" or "t2" to specify a specific Thumb mode. "v6"
117; for ARM or Thumb-2 with arm_arch6, and nov6 for ARM without
e4585731 118; arm_arch6. "v6t2" for Thumb-2 with arm_arch6. This attribute is
119; used to compute attribute "enabled", use type "any" to enable an
120; alternative in all cases.
121(define_attr "arch" "any,a,t,32,t1,t2,v6,nov6,v6t2,neon_for_64bits,avoid_neon_for_64bits,iwmmxt,iwmmxt2,armv6_or_vfpv3"
d5d4dc8d 122 (const_string "any"))
123
124(define_attr "arch_enabled" "no,yes"
125 (cond [(eq_attr "arch" "any")
126 (const_string "yes")
127
128 (and (eq_attr "arch" "a")
0bf497f5 129 (match_test "TARGET_ARM"))
d5d4dc8d 130 (const_string "yes")
131
132 (and (eq_attr "arch" "t")
0bf497f5 133 (match_test "TARGET_THUMB"))
d5d4dc8d 134 (const_string "yes")
135
136 (and (eq_attr "arch" "t1")
0bf497f5 137 (match_test "TARGET_THUMB1"))
d5d4dc8d 138 (const_string "yes")
139
140 (and (eq_attr "arch" "t2")
0bf497f5 141 (match_test "TARGET_THUMB2"))
d5d4dc8d 142 (const_string "yes")
143
144 (and (eq_attr "arch" "32")
0bf497f5 145 (match_test "TARGET_32BIT"))
d5d4dc8d 146 (const_string "yes")
147
148 (and (eq_attr "arch" "v6")
0bf497f5 149 (match_test "TARGET_32BIT && arm_arch6"))
d5d4dc8d 150 (const_string "yes")
151
152 (and (eq_attr "arch" "nov6")
0bf497f5 153 (match_test "TARGET_32BIT && !arm_arch6"))
a651f34d 154 (const_string "yes")
155
e4585731 156 (and (eq_attr "arch" "v6t2")
157 (match_test "TARGET_32BIT && arm_arch6 && arm_arch_thumb2"))
158 (const_string "yes")
159
b6779ddc 160 (and (eq_attr "arch" "avoid_neon_for_64bits")
161 (match_test "TARGET_NEON")
162 (not (match_test "TARGET_PREFER_NEON_64BITS")))
a651f34d 163 (const_string "yes")
164
b6779ddc 165 (and (eq_attr "arch" "neon_for_64bits")
166 (match_test "TARGET_NEON")
167 (match_test "TARGET_PREFER_NEON_64BITS"))
6b8f7c28 168 (const_string "yes")
169
170 (and (eq_attr "arch" "iwmmxt2")
171 (match_test "TARGET_REALLY_IWMMXT2"))
21cc9773 172 (const_string "yes")
173
174 (and (eq_attr "arch" "armv6_or_vfpv3")
175 (match_test "arm_arch6 || TARGET_VFP3"))
176 (const_string "yes")
177 ]
6b8f7c28 178
d5d4dc8d 179 (const_string "no")))
180
aa06c51c 181(define_attr "opt" "any,speed,size"
182 (const_string "any"))
183
184(define_attr "opt_enabled" "no,yes"
185 (cond [(eq_attr "opt" "any")
186 (const_string "yes")
187
188 (and (eq_attr "opt" "speed")
189 (match_test "optimize_function_for_speed_p (cfun)"))
190 (const_string "yes")
191
192 (and (eq_attr "opt" "size")
193 (match_test "optimize_function_for_size_p (cfun)"))
194 (const_string "yes")]
195 (const_string "no")))
196
861033d5 197(define_attr "use_literal_pool" "no,yes"
198 (cond [(and (eq_attr "type" "f_loads,f_loadd")
199 (match_test "CONSTANT_P (operands[1])"))
200 (const_string "yes")]
201 (const_string "no")))
202
d5d4dc8d 203; Enable all alternatives that are both arch_enabled and insn_enabled.
951a3f72 204; FIXME:: opt_enabled has been temporarily removed till the time we have
205; an attribute that allows the use of such alternatives.
206; This depends on caching of speed_p, size_p on a per
207; alternative basis. The problem is that the enabled attribute
208; cannot depend on any state that is not cached or is not constant
209; for a compilation unit. We probably need a generic "hot/cold"
210; alternative which if implemented can help with this. We disable this
211; until such a time as this is implemented and / or the improvements or
212; regressions with removing this attribute are double checked.
213; See ashldi3_neon and <shift>di3_neon in neon.md.
214
93b431d9 215 (define_attr "enabled" "no,yes"
0abea32c 216 (cond [(and (eq_attr "predicable_short_it" "no")
c7a58118 217 (and (eq_attr "predicated" "yes")
218 (match_test "arm_restrict_it")))
219 (const_string "no")
220
221 (and (eq_attr "enabled_for_depr_it" "no")
222 (match_test "arm_restrict_it"))
223 (const_string "no")
224
861033d5 225 (and (eq_attr "use_literal_pool" "yes")
226 (match_test "arm_disable_literal_pool"))
227 (const_string "no")
228
aa06c51c 229 (eq_attr "arch_enabled" "no")
aa06c51c 230 (const_string "no")]
231 (const_string "yes")))
d5d4dc8d 232
56d27660 233; POOL_RANGE is how far away from a constant pool entry that this insn
234; can be placed. If the distance is zero, then this insn will never
235; reference the pool.
42e1de19 236; Note that for Thumb constant pools the PC value is rounded down to the
237; nearest multiple of four. Therefore, THUMB2_POOL_RANGE (and POOL_RANGE for
238; Thumb insns) should be set to <max_range> - 2.
cffb2a26 239; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
8848d797 240; before its address. It is set to <max_range> - (8 + <data_size>).
cde1623a 241(define_attr "arm_pool_range" "" (const_int 0))
242(define_attr "thumb2_pool_range" "" (const_int 0))
243(define_attr "arm_neg_pool_range" "" (const_int 0))
244(define_attr "thumb2_neg_pool_range" "" (const_int 0))
245
246(define_attr "pool_range" ""
247 (cond [(eq_attr "is_thumb" "yes") (attr "thumb2_pool_range")]
248 (attr "arm_pool_range")))
249(define_attr "neg_pool_range" ""
250 (cond [(eq_attr "is_thumb" "yes") (attr "thumb2_neg_pool_range")]
251 (attr "arm_neg_pool_range")))
56d27660 252
215b30b3 253; An assembler sequence may clobber the condition codes without us knowing.
4d7a8451 254; If such an insn references the pool, then we have no way of knowing how,
255; so use the most conservative value for pool_range.
9c08d1fa 256(define_asm_attributes
4d7a8451 257 [(set_attr "conds" "clob")
258 (set_attr "length" "4")
259 (set_attr "pool_range" "250")])
9c08d1fa 260
9888ad6d 261; Load scheduling, set from the arm_ld_sched variable
4c834714 262; initialized by arm_option_override()
9888ad6d 263(define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
849170fd 264
f7fbdd4a 265; condition codes: this one is used by final_prescan_insn to speed up
266; conditionalizing instructions. It saves having to scan the rtl to see if
267; it uses or alters the condition codes.
215b30b3 268;
f7fbdd4a 269; USE means that the condition codes are used by the insn in the process of
215b30b3 270; outputting code, this means (at present) that we can't use the insn in
271; inlined branches
272;
f7fbdd4a 273; SET means that the purpose of the insn is to set the condition codes in a
215b30b3 274; well defined manner.
275;
f7fbdd4a 276; CLOB means that the condition codes are altered in an undefined manner, if
215b30b3 277; they are altered at all
278;
ad6d3e2a 279; UNCONDITIONAL means the instruction can not be conditionally executed and
280; that the instruction does not use or alter the condition codes.
c52acdd2 281;
ad6d3e2a 282; NOCOND means that the instruction does not use or alter the condition
283; codes but can be converted into a conditionally exectuted instruction.
f7fbdd4a 284
b0694be0 285(define_attr "conds" "use,set,clob,unconditional,nocond"
747b7458 286 (if_then_else
287 (ior (eq_attr "is_thumb1" "yes")
288 (eq_attr "type" "call"))
c1a66faf 289 (const_string "clob")
32093010 290 (if_then_else (eq_attr "is_neon_type" "no")
52432540 291 (const_string "nocond")
292 (const_string "unconditional"))))
f7fbdd4a 293
215b30b3 294; Predicable means that the insn can be conditionally executed based on
295; an automatically added predicate (additional patterns are generated by
296; gen...). We default to 'no' because no Thumb patterns match this rule
297; and not all ARM patterns do.
0d66636f 298(define_attr "predicable" "no,yes" (const_string "no"))
299
129a2fe4 300; Only model the write buffer for ARM6 and ARM7. Earlier processors don't
301; have one. Later ones, such as StrongARM, have write-back caches, so don't
8d232dc7 302; suffer blockages enough to warrant modelling this (and it can adversely
129a2fe4 303; affect the schedule).
74a71f7d 304(define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_tune_wbuf")))
129a2fe4 305
215b30b3 306; WRITE_CONFLICT implies that a read following an unrelated write is likely
307; to stall the processor. Used with model_wbuf above.
9c08d1fa 308(define_attr "write_conflict" "no,yes"
309 (if_then_else (eq_attr "type"
96854199 310 "block,call,load1")
9c08d1fa 311 (const_string "yes")
312 (const_string "no")))
313
215b30b3 314; Classify the insns into those that take one cycle and those that take more
315; than one on the main cpu execution unit.
f7fbdd4a 316(define_attr "core_cycles" "single,multi"
317 (if_then_else (eq_attr "type"
112eda6f 318 "adc_imm, adc_reg, adcs_imm, adcs_reg, adr, alu_ext, alu_imm, alu_sreg,\
319 alu_shift_imm, alu_shift_reg, alu_dsp_reg, alus_ext, alus_imm, alus_sreg,\
d82e788e 320 alus_shift_imm, alus_shift_reg, bfm, csel, rev, logic_imm, logic_reg,\
321 logic_shift_imm, logic_shift_reg, logics_imm, logics_reg,\
322 logics_shift_imm, logics_shift_reg, extend, shift_imm, float, fcsel,\
7cb6c048 323 wmmx_wor, wmmx_wxor, wmmx_wand, wmmx_wandn, wmmx_wmov, wmmx_tmcrr,\
324 wmmx_tmrrc, wmmx_wldr, wmmx_wstr, wmmx_tmcr, wmmx_tmrc, wmmx_wadd,\
325 wmmx_wsub, wmmx_wmul, wmmx_wmac, wmmx_wavg2, wmmx_tinsr, wmmx_textrm,\
326 wmmx_wshufh, wmmx_wcmpeq, wmmx_wcmpgt, wmmx_wmax, wmmx_wmin, wmmx_wpack,\
327 wmmx_wunpckih, wmmx_wunpckil, wmmx_wunpckeh, wmmx_wunpckel, wmmx_wror,\
328 wmmx_wsra, wmmx_wsrl, wmmx_wsll, wmmx_wmadd, wmmx_tmia, wmmx_tmiaph,\
329 wmmx_tmiaxy, wmmx_tbcst, wmmx_tmovmsk, wmmx_wacc, wmmx_waligni,\
330 wmmx_walignr, wmmx_tandc, wmmx_textrc, wmmx_torc, wmmx_torvsc, wmmx_wsad,\
331 wmmx_wabs, wmmx_wabsdiff, wmmx_waddsubhx, wmmx_wsubaddhx, wmmx_wavg4,\
332 wmmx_wmulw, wmmx_wqmulm, wmmx_wqmulwm, wmmx_waddbhus, wmmx_wqmiaxy,\
333 wmmx_wmiaxy, wmmx_wmiawxy, wmmx_wmerge")
f7fbdd4a 334 (const_string "single")
335 (const_string "multi")))
336
cffb2a26 337;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
215b30b3 338;; distant label. Only applicable to Thumb code.
cffb2a26 339(define_attr "far_jump" "yes,no" (const_string "no"))
340
d51f92df 341
25f905c2 342;; The number of machine instructions this pattern expands to.
343;; Used for Thumb-2 conditional execution.
344(define_attr "ce_count" "" (const_int 1))
345
4182b724 346;;---------------------------------------------------------------------------
347;; Unspecs
348
349(include "unspecs.md")
350
d51f92df 351;;---------------------------------------------------------------------------
fd781bb2 352;; Mode iterators
d51f92df 353
3de0dec6 354(include "iterators.md")
03770691 355
d51f92df 356;;---------------------------------------------------------------------------
357;; Predicates
358
9c9db025 359(include "predicates.md")
234f6557 360(include "constraints.md")
9c9db025 361
a2cd141b 362;;---------------------------------------------------------------------------
363;; Pipeline descriptions
215b30b3 364
e3879fd0 365(define_attr "tune_cortexr4" "yes,no"
366 (const (if_then_else
7d3cda8c 367 (eq_attr "tune" "cortexr4,cortexr4f,cortexr5")
e3879fd0 368 (const_string "yes")
369 (const_string "no"))))
370
a2cd141b 371;; True if the generic scheduling description should be used.
372
373(define_attr "generic_sched" "yes,no"
2546d93a 374 (const (if_then_else
e18862f3 375 (ior (eq_attr "tune" "fa526,fa626,fa606te,fa626te,fmp626,fa726te,\
376 arm926ejs,arm1020e,arm1026ejs,arm1136js,\
377 arm1136jfs,cortexa5,cortexa7,cortexa8,\
42e7b263 378 cortexa9,cortexa12,cortexa15,cortexa17,\
b1099bfd 379 cortexa53,cortexa57,cortexm4,cortexm7,\
380 marvell_pj4,xgene1")
2546d93a 381 (eq_attr "tune_cortexr4" "yes"))
4d5cb40d 382 (const_string "no")
383 (const_string "yes"))))
384
c0e1af52 385(define_attr "generic_vfp" "yes,no"
386 (const (if_then_else
387 (and (eq_attr "fpu" "vfp")
e18862f3 388 (eq_attr "tune" "!arm1020e,arm1022e,cortexa5,cortexa7,\
389 cortexa8,cortexa9,cortexa53,cortexm4,\
55a94dda 390 cortexm7,marvell_pj4,xgene1")
e3879fd0 391 (eq_attr "tune_cortexr4" "no"))
c0e1af52 392 (const_string "yes")
393 (const_string "no"))))
394
6b8f7c28 395(include "marvell-f-iwmmxt.md")
a2cd141b 396(include "arm-generic.md")
397(include "arm926ejs.md")
c0e1af52 398(include "arm1020e.md")
a2cd141b 399(include "arm1026ejs.md")
400(include "arm1136jfs.md")
0e266d06 401(include "fa526.md")
402(include "fa606te.md")
403(include "fa626te.md")
404(include "fmp626.md")
405(include "fa726te.md")
3f1e069f 406(include "cortex-a5.md")
d6b7f019 407(include "cortex-a7.md")
bcaec148 408(include "cortex-a8.md")
036068af 409(include "cortex-a9.md")
65f2f758 410(include "cortex-a15.md")
42e7b263 411(include "cortex-a17.md")
da10bc87 412(include "cortex-a53.md")
b1099bfd 413(include "cortex-a57.md")
934a1e72 414(include "cortex-r4.md")
e3879fd0 415(include "cortex-r4f.md")
e18862f3 416(include "cortex-m7.md")
2546d93a 417(include "cortex-m4.md")
418(include "cortex-m4-fpu.md")
55e3ada8 419(include "vfp11.md")
ea7d210b 420(include "marvell-pj4.md")
55a94dda 421(include "xgene1.md")
3586df96 422
9c08d1fa 423\f
215b30b3 424;;---------------------------------------------------------------------------
e1159bbe 425;; Insn patterns
426;;
a0f94409 427;; Addition insns.
215b30b3 428
9c08d1fa 429;; Note: For DImode insns, there is normally no reason why operands should
430;; not be in the same register, what we don't want is for something being
431;; written to partially overlap something that is an input.
432
cffb2a26 433(define_expand "adddi3"
434 [(parallel
215b30b3 435 [(set (match_operand:DI 0 "s_register_operand" "")
cffb2a26 436 (plus:DI (match_operand:DI 1 "s_register_operand" "")
10e5ccd5 437 (match_operand:DI 2 "arm_adddi_operand" "")))
bd5b4116 438 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 439 "TARGET_EITHER"
440 "
25f905c2 441 if (TARGET_THUMB1)
cffb2a26 442 {
0438d37f 443 if (!REG_P (operands[1]))
bc5a93af 444 operands[1] = force_reg (DImode, operands[1]);
0438d37f 445 if (!REG_P (operands[2]))
bc5a93af 446 operands[2] = force_reg (DImode, operands[2]);
cffb2a26 447 }
448 "
449)
450
a0f94409 451(define_insn_and_split "*arm_adddi3"
10e5ccd5 452 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r,&r,&r")
453 (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0, r, 0, r")
454 (match_operand:DI 2 "arm_adddi_operand" "r, 0, r, Dd, Dd")))
bd5b4116 455 (clobber (reg:CC CC_REGNUM))]
b805622c 456 "TARGET_32BIT && !TARGET_NEON"
33782ec7 457 "#"
94829feb 458 "TARGET_32BIT && reload_completed
459 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))"
a0f94409 460 [(parallel [(set (reg:CC_C CC_REGNUM)
461 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
462 (match_dup 1)))
463 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 464 (set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (match_dup 5))
465 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
a0f94409 466 "
467 {
468 operands[3] = gen_highpart (SImode, operands[0]);
469 operands[0] = gen_lowpart (SImode, operands[0]);
470 operands[4] = gen_highpart (SImode, operands[1]);
471 operands[1] = gen_lowpart (SImode, operands[1]);
10e5ccd5 472 operands[5] = gen_highpart_mode (SImode, DImode, operands[2]);
a0f94409 473 operands[2] = gen_lowpart (SImode, operands[2]);
474 }"
cffb2a26 475 [(set_attr "conds" "clob")
1b7da4ac 476 (set_attr "length" "8")
477 (set_attr "type" "multiple")]
cffb2a26 478)
9c08d1fa 479
a0f94409 480(define_insn_and_split "*adddi_sesidi_di"
9c08d1fa 481 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
482 (plus:DI (sign_extend:DI
97499065 483 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 484 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 485 (clobber (reg:CC CC_REGNUM))]
b805622c 486 "TARGET_32BIT"
33782ec7 487 "#"
25f905c2 488 "TARGET_32BIT && reload_completed"
a0f94409 489 [(parallel [(set (reg:CC_C CC_REGNUM)
490 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
491 (match_dup 1)))
492 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 493 (set (match_dup 3) (plus:SI (plus:SI (ashiftrt:SI (match_dup 2)
a0f94409 494 (const_int 31))
080c0b9a 495 (match_dup 4))
496 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
a0f94409 497 "
498 {
499 operands[3] = gen_highpart (SImode, operands[0]);
500 operands[0] = gen_lowpart (SImode, operands[0]);
501 operands[4] = gen_highpart (SImode, operands[1]);
502 operands[1] = gen_lowpart (SImode, operands[1]);
503 operands[2] = gen_lowpart (SImode, operands[2]);
504 }"
215b30b3 505 [(set_attr "conds" "clob")
1b7da4ac 506 (set_attr "length" "8")
507 (set_attr "type" "multiple")]
215b30b3 508)
9c08d1fa 509
a0f94409 510(define_insn_and_split "*adddi_zesidi_di"
9c08d1fa 511 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
512 (plus:DI (zero_extend:DI
97499065 513 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 514 (match_operand:DI 1 "s_register_operand" "0,r")))
a0f94409 515 (clobber (reg:CC CC_REGNUM))]
b805622c 516 "TARGET_32BIT"
33782ec7 517 "#"
25f905c2 518 "TARGET_32BIT && reload_completed"
a0f94409 519 [(parallel [(set (reg:CC_C CC_REGNUM)
520 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
521 (match_dup 1)))
522 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 523 (set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (const_int 0))
524 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
a0f94409 525 "
526 {
527 operands[3] = gen_highpart (SImode, operands[0]);
528 operands[0] = gen_lowpart (SImode, operands[0]);
529 operands[4] = gen_highpart (SImode, operands[1]);
530 operands[1] = gen_lowpart (SImode, operands[1]);
531 operands[2] = gen_lowpart (SImode, operands[2]);
532 }"
cffb2a26 533 [(set_attr "conds" "clob")
1b7da4ac 534 (set_attr "length" "8")
535 (set_attr "type" "multiple")]
cffb2a26 536)
b11cae9e 537
87b22bf7 538(define_expand "addsi3"
cffb2a26 539 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 540 (plus:SI (match_operand:SI 1 "s_register_operand" "")
541 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 542 "TARGET_EITHER"
87b22bf7 543 "
0438d37f 544 if (TARGET_32BIT && CONST_INT_P (operands[2]))
87b22bf7 545 {
96f57e36 546 arm_split_constant (PLUS, SImode, NULL_RTX,
547 INTVAL (operands[2]), operands[0], operands[1],
e1ba4a27 548 optimize && can_create_pseudo_p ());
87b22bf7 549 DONE;
550 }
cffb2a26 551 "
552)
87b22bf7 553
5bd751ff 554; If there is a scratch available, this will be faster than synthesizing the
a0f94409 555; addition.
556(define_peephole2
557 [(match_scratch:SI 3 "r")
372575c7 558 (set (match_operand:SI 0 "arm_general_register_operand" "")
559 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
cffb2a26 560 (match_operand:SI 2 "const_int_operand" "")))]
25f905c2 561 "TARGET_32BIT &&
a0f94409 562 !(const_ok_for_arm (INTVAL (operands[2]))
563 || const_ok_for_arm (-INTVAL (operands[2])))
564 && const_ok_for_arm (~INTVAL (operands[2]))"
565 [(set (match_dup 3) (match_dup 2))
566 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
567 ""
568)
87b22bf7 569
2f02c19f 570;; The r/r/k alternative is required when reloading the address
571;; (plus (reg rN) (reg sp)) into (reg rN). In this case reload will
572;; put the duplicated register first, and not try the commutative version.
a0f94409 573(define_insn_and_split "*arm_addsi3"
7c36fe71 574 [(set (match_operand:SI 0 "s_register_operand" "=rk,l,l ,l ,r ,k ,r,r ,k ,r ,k,k,r ,k ,r")
575 (plus:SI (match_operand:SI 1 "s_register_operand" "%0 ,l,0 ,l ,rk,k ,r,rk,k ,rk,k,r,rk,k ,rk")
576 (match_operand:SI 2 "reg_or_int_operand" "rk ,l,Py,Pd,rI,rI,k,Pj,Pj,L ,L,L,PJ,PJ,?n")))]
25f905c2 577 "TARGET_32BIT"
5565501b 578 "@
c24d855d 579 add%?\\t%0, %0, %2
5565501b 580 add%?\\t%0, %1, %2
a0b3420a 581 add%?\\t%0, %1, %2
7c36fe71 582 add%?\\t%0, %1, %2
583 add%?\\t%0, %1, %2
aaa37ad6 584 add%?\\t%0, %1, %2
2f02c19f 585 add%?\\t%0, %2, %1
d5cbae34 586 addw%?\\t%0, %1, %2
587 addw%?\\t%0, %1, %2
aaa37ad6 588 sub%?\\t%0, %1, #%n2
87b22bf7 589 sub%?\\t%0, %1, #%n2
d7757711 590 sub%?\\t%0, %1, #%n2
d5cbae34 591 subw%?\\t%0, %1, #%n2
592 subw%?\\t%0, %1, #%n2
87b22bf7 593 #"
a3ffc315 594 "TARGET_32BIT
0438d37f 595 && CONST_INT_P (operands[2])
d5cbae34 596 && !const_ok_for_op (INTVAL (operands[2]), PLUS)
a3ffc315 597 && (reload_completed || !arm_eliminable_register (operands[1]))"
a0f94409 598 [(clobber (const_int 0))]
599 "
96f57e36 600 arm_split_constant (PLUS, SImode, curr_insn,
601 INTVAL (operands[2]), operands[0],
a0f94409 602 operands[1], 0);
603 DONE;
604 "
7c36fe71 605 [(set_attr "length" "2,4,4,4,4,4,4,4,4,4,4,4,4,4,16")
d5cbae34 606 (set_attr "predicable" "yes")
7c36fe71 607 (set_attr "predicable_short_it" "yes,yes,yes,yes,no,no,no,no,no,no,no,no,no,no,no")
608 (set_attr "arch" "t2,t2,t2,t2,*,*,*,t2,t2,*,*,a,t2,t2,*")
65f68e55 609 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
d82e788e 610 (const_string "alu_imm")
112eda6f 611 (const_string "alu_sreg")))
65f68e55 612 ]
cffb2a26 613)
614
90c2bcf0 615(define_insn "addsi3_compare0"
bd5b4116 616 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 617 (compare:CC_NOOV
65f68e55 618 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r,r")
619 (match_operand:SI 2 "arm_add_operand" "I,L,r"))
5565501b 620 (const_int 0)))
65f68e55 621 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9c08d1fa 622 (plus:SI (match_dup 1) (match_dup 2)))]
ec792a7b 623 "TARGET_ARM"
5565501b 624 "@
25f905c2 625 add%.\\t%0, %1, %2
65f68e55 626 sub%.\\t%0, %1, #%n2
627 add%.\\t%0, %1, %2"
628 [(set_attr "conds" "set")
112eda6f 629 (set_attr "type" "alus_imm,alus_imm,alus_sreg")]
cffb2a26 630)
9c08d1fa 631
aea4c774 632(define_insn "*addsi3_compare0_scratch"
bd5b4116 633 [(set (reg:CC_NOOV CC_REGNUM)
aea4c774 634 (compare:CC_NOOV
65f68e55 635 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r, r")
636 (match_operand:SI 1 "arm_add_operand" "I,L, r"))
aea4c774 637 (const_int 0)))]
ec792a7b 638 "TARGET_ARM"
cffb2a26 639 "@
640 cmn%?\\t%0, %1
65f68e55 641 cmp%?\\t%0, #%n1
642 cmn%?\\t%0, %1"
596e5e8f 643 [(set_attr "conds" "set")
65f68e55 644 (set_attr "predicable" "yes")
112eda6f 645 (set_attr "type" "alus_imm,alus_imm,alus_sreg")]
0d66636f 646)
cffb2a26 647
aed179ae 648(define_insn "*compare_negsi_si"
649 [(set (reg:CC_Z CC_REGNUM)
650 (compare:CC_Z
7c36fe71 651 (neg:SI (match_operand:SI 0 "s_register_operand" "l,r"))
652 (match_operand:SI 1 "s_register_operand" "l,r")))]
25f905c2 653 "TARGET_32BIT"
aed179ae 654 "cmn%?\\t%1, %0"
596e5e8f 655 [(set_attr "conds" "set")
7c36fe71 656 (set_attr "predicable" "yes")
657 (set_attr "arch" "t2,*")
658 (set_attr "length" "2,4")
1b7da4ac 659 (set_attr "predicable_short_it" "yes,no")
112eda6f 660 (set_attr "type" "alus_sreg")]
0d66636f 661)
aea4c774 662
203c488f 663;; This is the canonicalization of addsi3_compare0_for_combiner when the
664;; addend is a constant.
190efb17 665(define_insn "cmpsi2_addneg"
203c488f 666 [(set (reg:CC CC_REGNUM)
667 (compare:CC
668 (match_operand:SI 1 "s_register_operand" "r,r")
2a977b78 669 (match_operand:SI 2 "arm_addimm_operand" "L,I")))
203c488f 670 (set (match_operand:SI 0 "s_register_operand" "=r,r")
671 (plus:SI (match_dup 1)
2a977b78 672 (match_operand:SI 3 "arm_addimm_operand" "I,L")))]
25f905c2 673 "TARGET_32BIT && INTVAL (operands[2]) == -INTVAL (operands[3])"
203c488f 674 "@
2a977b78 675 add%.\\t%0, %1, %3
676 sub%.\\t%0, %1, #%n3"
1b7da4ac 677 [(set_attr "conds" "set")
112eda6f 678 (set_attr "type" "alus_sreg")]
203c488f 679)
680
681;; Convert the sequence
682;; sub rd, rn, #1
683;; cmn rd, #1 (equivalent to cmp rd, #-1)
684;; bne dest
685;; into
686;; subs rd, rn, #1
687;; bcs dest ((unsigned)rn >= 1)
688;; similarly for the beq variant using bcc.
689;; This is a common looping idiom (while (n--))
690(define_peephole2
372575c7 691 [(set (match_operand:SI 0 "arm_general_register_operand" "")
692 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
203c488f 693 (const_int -1)))
694 (set (match_operand 2 "cc_register" "")
695 (compare (match_dup 0) (const_int -1)))
696 (set (pc)
697 (if_then_else (match_operator 3 "equality_operator"
698 [(match_dup 2) (const_int 0)])
699 (match_operand 4 "" "")
700 (match_operand 5 "" "")))]
25f905c2 701 "TARGET_32BIT && peep2_reg_dead_p (3, operands[2])"
203c488f 702 [(parallel[
703 (set (match_dup 2)
704 (compare:CC
705 (match_dup 1) (const_int 1)))
706 (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
707 (set (pc)
708 (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
709 (match_dup 4)
710 (match_dup 5)))]
711 "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
712 operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
713 ? GEU : LTU),
714 VOIDmode,
715 operands[2], const0_rtx);"
716)
717
ebcc79bc 718;; The next four insns work because they compare the result with one of
719;; the operands, and we know that the use of the condition code is
720;; either GEU or LTU, so we can use the carry flag from the addition
721;; instead of doing the compare a second time.
722(define_insn "*addsi3_compare_op1"
bd5b4116 723 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 724 (compare:CC_C
65f68e55 725 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
726 (match_operand:SI 2 "arm_add_operand" "I,L,r"))
ebcc79bc 727 (match_dup 1)))
65f68e55 728 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
ebcc79bc 729 (plus:SI (match_dup 1) (match_dup 2)))]
25f905c2 730 "TARGET_32BIT"
ebcc79bc 731 "@
25f905c2 732 add%.\\t%0, %1, %2
65f68e55 733 sub%.\\t%0, %1, #%n2
734 add%.\\t%0, %1, %2"
735 [(set_attr "conds" "set")
112eda6f 736 (set_attr "type" "alus_imm,alus_imm,alus_sreg")]
0d66636f 737)
ebcc79bc 738
739(define_insn "*addsi3_compare_op2"
bd5b4116 740 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 741 (compare:CC_C
65f68e55 742 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
743 (match_operand:SI 2 "arm_add_operand" "I,L,r"))
ebcc79bc 744 (match_dup 2)))
65f68e55 745 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9c08d1fa 746 (plus:SI (match_dup 1) (match_dup 2)))]
25f905c2 747 "TARGET_32BIT"
5565501b 748 "@
65f68e55 749 add%.\\t%0, %1, %2
25f905c2 750 add%.\\t%0, %1, %2
751 sub%.\\t%0, %1, #%n2"
65f68e55 752 [(set_attr "conds" "set")
112eda6f 753 (set_attr "type" "alus_imm,alus_imm,alus_sreg")]
0d66636f 754)
9c08d1fa 755
ebcc79bc 756(define_insn "*compare_addsi2_op0"
bd5b4116 757 [(set (reg:CC_C CC_REGNUM)
7c36fe71 758 (compare:CC_C
759 (plus:SI (match_operand:SI 0 "s_register_operand" "l,l,r,r,r")
760 (match_operand:SI 1 "arm_add_operand" "Pv,l,I,L,r"))
761 (match_dup 0)))]
25f905c2 762 "TARGET_32BIT"
ebcc79bc 763 "@
7c36fe71 764 cmp%?\\t%0, #%n1
765 cmn%?\\t%0, %1
ebcc79bc 766 cmn%?\\t%0, %1
65f68e55 767 cmp%?\\t%0, #%n1
768 cmn%?\\t%0, %1"
596e5e8f 769 [(set_attr "conds" "set")
65f68e55 770 (set_attr "predicable" "yes")
7c36fe71 771 (set_attr "arch" "t2,t2,*,*,*")
772 (set_attr "predicable_short_it" "yes,yes,no,no,no")
773 (set_attr "length" "2,2,4,4,4")
112eda6f 774 (set_attr "type" "alus_imm,alus_sreg,alus_imm,alus_imm,alus_sreg")]
0d66636f 775)
ebcc79bc 776
777(define_insn "*compare_addsi2_op1"
bd5b4116 778 [(set (reg:CC_C CC_REGNUM)
7c36fe71 779 (compare:CC_C
780 (plus:SI (match_operand:SI 0 "s_register_operand" "l,l,r,r,r")
781 (match_operand:SI 1 "arm_add_operand" "Pv,l,I,L,r"))
782 (match_dup 1)))]
25f905c2 783 "TARGET_32BIT"
ebcc79bc 784 "@
7c36fe71 785 cmp%?\\t%0, #%n1
786 cmn%?\\t%0, %1
ebcc79bc 787 cmn%?\\t%0, %1
65f68e55 788 cmp%?\\t%0, #%n1
789 cmn%?\\t%0, %1"
596e5e8f 790 [(set_attr "conds" "set")
65f68e55 791 (set_attr "predicable" "yes")
7c36fe71 792 (set_attr "arch" "t2,t2,*,*,*")
793 (set_attr "predicable_short_it" "yes,yes,no,no,no")
794 (set_attr "length" "2,2,4,4,4")
112eda6f 795 (set_attr "type" "alus_imm,alus_sreg,alus_imm,alus_imm,alus_sreg")]
7c36fe71 796 )
ebcc79bc 797
080c0b9a 798(define_insn "*addsi3_carryin_<optab>"
7c36fe71 799 [(set (match_operand:SI 0 "s_register_operand" "=l,r,r")
800 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%l,r,r")
801 (match_operand:SI 2 "arm_not_operand" "0,rI,K"))
802 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))]
25f905c2 803 "TARGET_32BIT"
10e5ccd5 804 "@
a0b3420a 805 adc%?\\t%0, %1, %2
10e5ccd5 806 adc%?\\t%0, %1, %2
807 sbc%?\\t%0, %1, #%B2"
a7de272d 808 [(set_attr "conds" "use")
7c36fe71 809 (set_attr "predicable" "yes")
810 (set_attr "arch" "t2,*,*")
811 (set_attr "length" "4")
1b7da4ac 812 (set_attr "predicable_short_it" "yes,no,no")
813 (set_attr "type" "adc_reg,adc_reg,adc_imm")]
cffb2a26 814)
ebcc79bc 815
080c0b9a 816(define_insn "*addsi3_carryin_alt2_<optab>"
7c36fe71 817 [(set (match_operand:SI 0 "s_register_operand" "=l,r,r")
818 (plus:SI (plus:SI (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))
819 (match_operand:SI 1 "s_register_operand" "%l,r,r"))
820 (match_operand:SI 2 "arm_rhs_operand" "l,rI,K")))]
25f905c2 821 "TARGET_32BIT"
10e5ccd5 822 "@
a0b3420a 823 adc%?\\t%0, %1, %2
10e5ccd5 824 adc%?\\t%0, %1, %2
825 sbc%?\\t%0, %1, #%B2"
a7de272d 826 [(set_attr "conds" "use")
7c36fe71 827 (set_attr "predicable" "yes")
828 (set_attr "arch" "t2,*,*")
829 (set_attr "length" "4")
1b7da4ac 830 (set_attr "predicable_short_it" "yes,no,no")
831 (set_attr "type" "adc_reg,adc_reg,adc_imm")]
0d66636f 832)
ebcc79bc 833
080c0b9a 834(define_insn "*addsi3_carryin_shift_<optab>"
ebcc79bc 835 [(set (match_operand:SI 0 "s_register_operand" "=r")
080c0b9a 836 (plus:SI (plus:SI
837 (match_operator:SI 2 "shift_operator"
838 [(match_operand:SI 3 "s_register_operand" "r")
839 (match_operand:SI 4 "reg_or_int_operand" "rM")])
840 (match_operand:SI 1 "s_register_operand" "r"))
841 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))]
25f905c2 842 "TARGET_32BIT"
080c0b9a 843 "adc%?\\t%0, %1, %3%S2"
844 [(set_attr "conds" "use")
a7de272d 845 (set_attr "predicable" "yes")
7c36fe71 846 (set_attr "predicable_short_it" "no")
080c0b9a 847 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
d82e788e 848 (const_string "alu_shift_imm")
849 (const_string "alu_shift_reg")))]
cffb2a26 850)
ebcc79bc 851
922b6913 852(define_insn "*addsi3_carryin_clobercc_<optab>"
853 [(set (match_operand:SI 0 "s_register_operand" "=r")
854 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%r")
855 (match_operand:SI 2 "arm_rhs_operand" "rI"))
856 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))
857 (clobber (reg:CC CC_REGNUM))]
858 "TARGET_32BIT"
859 "adc%.\\t%0, %1, %2"
1b7da4ac 860 [(set_attr "conds" "set")
861 (set_attr "type" "adcs_reg")]
922b6913 862)
863
9154bd82 864(define_insn "*subsi3_carryin"
865 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
866 (minus:SI (minus:SI (match_operand:SI 1 "reg_or_int_operand" "r,I")
867 (match_operand:SI 2 "s_register_operand" "r,r"))
868 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
869 "TARGET_32BIT"
870 "@
871 sbc%?\\t%0, %1, %2
872 rsc%?\\t%0, %2, %1"
873 [(set_attr "conds" "use")
874 (set_attr "arch" "*,a")
7c36fe71 875 (set_attr "predicable" "yes")
1b7da4ac 876 (set_attr "predicable_short_it" "no")
877 (set_attr "type" "adc_reg,adc_imm")]
9154bd82 878)
879
880(define_insn "*subsi3_carryin_const"
881 [(set (match_operand:SI 0 "s_register_operand" "=r")
882 (minus:SI (plus:SI (match_operand:SI 1 "reg_or_int_operand" "r")
883 (match_operand:SI 2 "arm_not_operand" "K"))
884 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
885 "TARGET_32BIT"
886 "sbc\\t%0, %1, #%B2"
1b7da4ac 887 [(set_attr "conds" "use")
888 (set_attr "type" "adc_imm")]
9154bd82 889)
890
891(define_insn "*subsi3_carryin_compare"
892 [(set (reg:CC CC_REGNUM)
893 (compare:CC (match_operand:SI 1 "s_register_operand" "r")
894 (match_operand:SI 2 "s_register_operand" "r")))
895 (set (match_operand:SI 0 "s_register_operand" "=r")
896 (minus:SI (minus:SI (match_dup 1)
897 (match_dup 2))
898 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
899 "TARGET_32BIT"
900 "sbcs\\t%0, %1, %2"
1b7da4ac 901 [(set_attr "conds" "set")
902 (set_attr "type" "adcs_reg")]
9154bd82 903)
904
905(define_insn "*subsi3_carryin_compare_const"
906 [(set (reg:CC CC_REGNUM)
907 (compare:CC (match_operand:SI 1 "reg_or_int_operand" "r")
908 (match_operand:SI 2 "arm_not_operand" "K")))
909 (set (match_operand:SI 0 "s_register_operand" "=r")
910 (minus:SI (plus:SI (match_dup 1)
911 (match_dup 2))
912 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
913 "TARGET_32BIT"
914 "sbcs\\t%0, %1, #%B2"
1b7da4ac 915 [(set_attr "conds" "set")
916 (set_attr "type" "adcs_imm")]
9154bd82 917)
918
919(define_insn "*subsi3_carryin_shift"
920 [(set (match_operand:SI 0 "s_register_operand" "=r")
921 (minus:SI (minus:SI
922 (match_operand:SI 1 "s_register_operand" "r")
923 (match_operator:SI 2 "shift_operator"
924 [(match_operand:SI 3 "s_register_operand" "r")
925 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
926 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
927 "TARGET_32BIT"
928 "sbc%?\\t%0, %1, %3%S2"
929 [(set_attr "conds" "use")
930 (set_attr "predicable" "yes")
931 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
d82e788e 932 (const_string "alu_shift_imm")
933 (const_string "alu_shift_reg")))]
9154bd82 934)
935
936(define_insn "*rsbsi3_carryin_shift"
937 [(set (match_operand:SI 0 "s_register_operand" "=r")
938 (minus:SI (minus:SI
939 (match_operator:SI 2 "shift_operator"
940 [(match_operand:SI 3 "s_register_operand" "r")
941 (match_operand:SI 4 "reg_or_int_operand" "rM")])
942 (match_operand:SI 1 "s_register_operand" "r"))
943 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
944 "TARGET_ARM"
945 "rsc%?\\t%0, %1, %3%S2"
946 [(set_attr "conds" "use")
947 (set_attr "predicable" "yes")
948 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
d82e788e 949 (const_string "alu_shift_imm")
950 (const_string "alu_shift_reg")))]
9154bd82 951)
952
d795fb69 953; transform ((x << y) - 1) to ~(~(x-1) << y) Where X is a constant.
954(define_split
955 [(set (match_operand:SI 0 "s_register_operand" "")
956 (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
957 (match_operand:SI 2 "s_register_operand" ""))
958 (const_int -1)))
959 (clobber (match_operand:SI 3 "s_register_operand" ""))]
25f905c2 960 "TARGET_32BIT"
d795fb69 961 [(set (match_dup 3) (match_dup 1))
962 (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
963 "
964 operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
965")
966
604f3a0a 967(define_expand "addsf3"
968 [(set (match_operand:SF 0 "s_register_operand" "")
969 (plus:SF (match_operand:SF 1 "s_register_operand" "")
d86c91f6 970 (match_operand:SF 2 "s_register_operand" "")))]
25f905c2 971 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 972 "
604f3a0a 973")
974
604f3a0a 975(define_expand "adddf3"
976 [(set (match_operand:DF 0 "s_register_operand" "")
977 (plus:DF (match_operand:DF 1 "s_register_operand" "")
d86c91f6 978 (match_operand:DF 2 "s_register_operand" "")))]
a50d7267 979 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 980 "
604f3a0a 981")
982
cffb2a26 983(define_expand "subdi3"
984 [(parallel
985 [(set (match_operand:DI 0 "s_register_operand" "")
986 (minus:DI (match_operand:DI 1 "s_register_operand" "")
987 (match_operand:DI 2 "s_register_operand" "")))
bd5b4116 988 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 989 "TARGET_EITHER"
990 "
25f905c2 991 if (TARGET_THUMB1)
cffb2a26 992 {
0438d37f 993 if (!REG_P (operands[1]))
5aa8c5f0 994 operands[1] = force_reg (DImode, operands[1]);
0438d37f 995 if (!REG_P (operands[2]))
5aa8c5f0 996 operands[2] = force_reg (DImode, operands[2]);
cffb2a26 997 }
998 "
999)
1000
2f9b23e3 1001(define_insn_and_split "*arm_subdi3"
cffb2a26 1002 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
9c08d1fa 1003 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
1004 (match_operand:DI 2 "s_register_operand" "r,0,0")))
bd5b4116 1005 (clobber (reg:CC CC_REGNUM))]
94829feb 1006 "TARGET_32BIT && !TARGET_NEON"
2f9b23e3 1007 "#" ; "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
1008 "&& reload_completed"
1009 [(parallel [(set (reg:CC CC_REGNUM)
1010 (compare:CC (match_dup 1) (match_dup 2)))
1011 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1012 (set (match_dup 3) (minus:SI (minus:SI (match_dup 4) (match_dup 5))
1013 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1014 {
1015 operands[3] = gen_highpart (SImode, operands[0]);
1016 operands[0] = gen_lowpart (SImode, operands[0]);
1017 operands[4] = gen_highpart (SImode, operands[1]);
1018 operands[1] = gen_lowpart (SImode, operands[1]);
1019 operands[5] = gen_highpart (SImode, operands[2]);
1020 operands[2] = gen_lowpart (SImode, operands[2]);
1021 }
cffb2a26 1022 [(set_attr "conds" "clob")
1b7da4ac 1023 (set_attr "length" "8")
1024 (set_attr "type" "multiple")]
cffb2a26 1025)
1026
2f9b23e3 1027(define_insn_and_split "*subdi_di_zesidi"
cffb2a26 1028 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 1029 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r")
9c08d1fa 1030 (zero_extend:DI
cffb2a26 1031 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 1032 (clobber (reg:CC CC_REGNUM))]
25f905c2 1033 "TARGET_32BIT"
2f9b23e3 1034 "#" ; "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
1035 "&& reload_completed"
1036 [(parallel [(set (reg:CC CC_REGNUM)
1037 (compare:CC (match_dup 1) (match_dup 2)))
1038 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1039 (set (match_dup 3) (minus:SI (plus:SI (match_dup 4) (match_dup 5))
1040 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1041 {
1042 operands[3] = gen_highpart (SImode, operands[0]);
1043 operands[0] = gen_lowpart (SImode, operands[0]);
1044 operands[4] = gen_highpart (SImode, operands[1]);
1045 operands[1] = gen_lowpart (SImode, operands[1]);
1046 operands[5] = GEN_INT (~0);
1047 }
cffb2a26 1048 [(set_attr "conds" "clob")
1b7da4ac 1049 (set_attr "length" "8")
1050 (set_attr "type" "multiple")]
cffb2a26 1051)
9c08d1fa 1052
2f9b23e3 1053(define_insn_and_split "*subdi_di_sesidi"
cffb2a26 1054 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 1055 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r")
9c08d1fa 1056 (sign_extend:DI
cffb2a26 1057 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 1058 (clobber (reg:CC CC_REGNUM))]
25f905c2 1059 "TARGET_32BIT"
2f9b23e3 1060 "#" ; "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
1061 "&& reload_completed"
1062 [(parallel [(set (reg:CC CC_REGNUM)
1063 (compare:CC (match_dup 1) (match_dup 2)))
1064 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1065 (set (match_dup 3) (minus:SI (minus:SI (match_dup 4)
1066 (ashiftrt:SI (match_dup 2)
1067 (const_int 31)))
1068 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1069 {
1070 operands[3] = gen_highpart (SImode, operands[0]);
1071 operands[0] = gen_lowpart (SImode, operands[0]);
1072 operands[4] = gen_highpart (SImode, operands[1]);
1073 operands[1] = gen_lowpart (SImode, operands[1]);
1074 }
cffb2a26 1075 [(set_attr "conds" "clob")
1b7da4ac 1076 (set_attr "length" "8")
1077 (set_attr "type" "multiple")]
cffb2a26 1078)
9c08d1fa 1079
2f9b23e3 1080(define_insn_and_split "*subdi_zesidi_di"
cffb2a26 1081 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1082 (minus:DI (zero_extend:DI
cffb2a26 1083 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 1084 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 1085 (clobber (reg:CC CC_REGNUM))]
cffb2a26 1086 "TARGET_ARM"
2f9b23e3 1087 "#" ; "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
1088 ; is equivalent to:
1089 ; "subs\\t%Q0, %2, %Q1\;rsc\\t%R0, %R1, #0"
1090 "&& reload_completed"
1091 [(parallel [(set (reg:CC CC_REGNUM)
1092 (compare:CC (match_dup 2) (match_dup 1)))
1093 (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))])
1094 (set (match_dup 3) (minus:SI (minus:SI (const_int 0) (match_dup 4))
1095 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1096 {
1097 operands[3] = gen_highpart (SImode, operands[0]);
1098 operands[0] = gen_lowpart (SImode, operands[0]);
1099 operands[4] = gen_highpart (SImode, operands[1]);
1100 operands[1] = gen_lowpart (SImode, operands[1]);
1101 }
cffb2a26 1102 [(set_attr "conds" "clob")
1b7da4ac 1103 (set_attr "length" "8")
1104 (set_attr "type" "multiple")]
cffb2a26 1105)
9c08d1fa 1106
2f9b23e3 1107(define_insn_and_split "*subdi_sesidi_di"
cffb2a26 1108 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1109 (minus:DI (sign_extend:DI
cffb2a26 1110 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 1111 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 1112 (clobber (reg:CC CC_REGNUM))]
cffb2a26 1113 "TARGET_ARM"
2f9b23e3 1114 "#" ; "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
1115 ; is equivalent to:
1116 ; "subs\\t%Q0, %2, %Q1\;rsc\\t%R0, %R1, %2, asr #31"
1117 "&& reload_completed"
1118 [(parallel [(set (reg:CC CC_REGNUM)
1119 (compare:CC (match_dup 2) (match_dup 1)))
1120 (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))])
1121 (set (match_dup 3) (minus:SI (minus:SI
1122 (ashiftrt:SI (match_dup 2)
1123 (const_int 31))
1124 (match_dup 4))
1125 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1126 {
1127 operands[3] = gen_highpart (SImode, operands[0]);
1128 operands[0] = gen_lowpart (SImode, operands[0]);
1129 operands[4] = gen_highpart (SImode, operands[1]);
1130 operands[1] = gen_lowpart (SImode, operands[1]);
1131 }
cffb2a26 1132 [(set_attr "conds" "clob")
1b7da4ac 1133 (set_attr "length" "8")
1134 (set_attr "type" "multiple")]
cffb2a26 1135)
9c08d1fa 1136
2f9b23e3 1137(define_insn_and_split "*subdi_zesidi_zesidi"
cffb2a26 1138 [(set (match_operand:DI 0 "s_register_operand" "=r")
9c08d1fa 1139 (minus:DI (zero_extend:DI
cffb2a26 1140 (match_operand:SI 1 "s_register_operand" "r"))
9c08d1fa 1141 (zero_extend:DI
cffb2a26 1142 (match_operand:SI 2 "s_register_operand" "r"))))
bd5b4116 1143 (clobber (reg:CC CC_REGNUM))]
25f905c2 1144 "TARGET_32BIT"
2f9b23e3 1145 "#" ; "subs\\t%Q0, %1, %2\;sbc\\t%R0, %1, %1"
1146 "&& reload_completed"
1147 [(parallel [(set (reg:CC CC_REGNUM)
1148 (compare:CC (match_dup 1) (match_dup 2)))
1149 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1150 (set (match_dup 3) (minus:SI (minus:SI (match_dup 1) (match_dup 1))
1151 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1152 {
1153 operands[3] = gen_highpart (SImode, operands[0]);
1154 operands[0] = gen_lowpart (SImode, operands[0]);
1155 }
cffb2a26 1156 [(set_attr "conds" "clob")
1b7da4ac 1157 (set_attr "length" "8")
1158 (set_attr "type" "multiple")]
cffb2a26 1159)
b11cae9e 1160
87b22bf7 1161(define_expand "subsi3"
cffb2a26 1162 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 1163 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
1164 (match_operand:SI 2 "s_register_operand" "")))]
cffb2a26 1165 "TARGET_EITHER"
87b22bf7 1166 "
0438d37f 1167 if (CONST_INT_P (operands[1]))
87b22bf7 1168 {
25f905c2 1169 if (TARGET_32BIT)
cffb2a26 1170 {
17202aa5 1171 if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[1]), MINUS))
1172 operands[1] = force_reg (SImode, operands[1]);
1173 else
1174 {
1175 arm_split_constant (MINUS, SImode, NULL_RTX,
1176 INTVAL (operands[1]), operands[0],
1177 operands[2],
1178 optimize && can_create_pseudo_p ());
1179 DONE;
1180 }
cffb2a26 1181 }
25f905c2 1182 else /* TARGET_THUMB1 */
cffb2a26 1183 operands[1] = force_reg (SImode, operands[1]);
87b22bf7 1184 }
cffb2a26 1185 "
1186)
87b22bf7 1187
25f905c2 1188; ??? Check Thumb-2 split length
a0f94409 1189(define_insn_and_split "*arm_subsi3_insn"
3a44c5a9 1190 [(set (match_operand:SI 0 "s_register_operand" "=l,l ,l ,l ,r,r,r,rk,r")
1191 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "l ,0 ,l ,Pz,I,r,r,k ,?n")
1192 (match_operand:SI 2 "reg_or_int_operand" "l ,Py,Pd,l ,r,I,r,r ,r")))]
25f905c2 1193 "TARGET_32BIT"
e2348bcb 1194 "@
7c36fe71 1195 sub%?\\t%0, %1, %2
1196 sub%?\\t%0, %2
1197 sub%?\\t%0, %1, %2
1198 rsb%?\\t%0, %2, %1
87b22bf7 1199 rsb%?\\t%0, %2, %1
aaa37ad6 1200 sub%?\\t%0, %1, %2
080c0b9a 1201 sub%?\\t%0, %1, %2
65f68e55 1202 sub%?\\t%0, %1, %2
87b22bf7 1203 #"
0438d37f 1204 "&& (CONST_INT_P (operands[1])
91a5e339 1205 && !const_ok_for_arm (INTVAL (operands[1])))"
87b22bf7 1206 [(clobber (const_int 0))]
1207 "
96f57e36 1208 arm_split_constant (MINUS, SImode, curr_insn,
1209 INTVAL (operands[1]), operands[0], operands[2], 0);
87b22bf7 1210 DONE;
cffb2a26 1211 "
7c36fe71 1212 [(set_attr "length" "4,4,4,4,4,4,4,4,16")
1213 (set_attr "arch" "t2,t2,t2,t2,*,*,*,*,*")
65f68e55 1214 (set_attr "predicable" "yes")
7c36fe71 1215 (set_attr "predicable_short_it" "yes,yes,yes,yes,no,no,no,no,no")
112eda6f 1216 (set_attr "type" "alu_sreg,alu_sreg,alu_sreg,alu_sreg,alu_imm,alu_imm,alu_sreg,alu_sreg,multiple")]
a0f94409 1217)
1218
1219(define_peephole2
1220 [(match_scratch:SI 3 "r")
372575c7 1221 (set (match_operand:SI 0 "arm_general_register_operand" "")
a0f94409 1222 (minus:SI (match_operand:SI 1 "const_int_operand" "")
372575c7 1223 (match_operand:SI 2 "arm_general_register_operand" "")))]
25f905c2 1224 "TARGET_32BIT
a0f94409 1225 && !const_ok_for_arm (INTVAL (operands[1]))
1226 && const_ok_for_arm (~INTVAL (operands[1]))"
1227 [(set (match_dup 3) (match_dup 1))
1228 (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1229 ""
cffb2a26 1230)
b11cae9e 1231
f7fbdd4a 1232(define_insn "*subsi3_compare0"
bd5b4116 1233 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1234 (compare:CC_NOOV
65f68e55 1235 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,r,I")
1236 (match_operand:SI 2 "arm_rhs_operand" "I,r,r"))
215b30b3 1237 (const_int 0)))
65f68e55 1238 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9c08d1fa 1239 (minus:SI (match_dup 1) (match_dup 2)))]
25f905c2 1240 "TARGET_32BIT"
e2348bcb 1241 "@
65f68e55 1242 sub%.\\t%0, %1, %2
25f905c2 1243 sub%.\\t%0, %1, %2
1244 rsb%.\\t%0, %2, %1"
65f68e55 1245 [(set_attr "conds" "set")
112eda6f 1246 (set_attr "type" "alus_imm,alus_sreg,alus_sreg")]
cffb2a26 1247)
9c08d1fa 1248
190efb17 1249(define_insn "subsi3_compare"
080c0b9a 1250 [(set (reg:CC CC_REGNUM)
65f68e55 1251 (compare:CC (match_operand:SI 1 "arm_rhs_operand" "r,r,I")
1252 (match_operand:SI 2 "arm_rhs_operand" "I,r,r")))
1253 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2df9477b 1254 (minus:SI (match_dup 1) (match_dup 2)))]
1255 "TARGET_32BIT"
1256 "@
65f68e55 1257 sub%.\\t%0, %1, %2
2df9477b 1258 sub%.\\t%0, %1, %2
1259 rsb%.\\t%0, %2, %1"
65f68e55 1260 [(set_attr "conds" "set")
112eda6f 1261 (set_attr "type" "alus_imm,alus_sreg,alus_sreg")]
2df9477b 1262)
1263
604f3a0a 1264(define_expand "subsf3"
1265 [(set (match_operand:SF 0 "s_register_operand" "")
d86c91f6 1266 (minus:SF (match_operand:SF 1 "s_register_operand" "")
1267 (match_operand:SF 2 "s_register_operand" "")))]
25f905c2 1268 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1269 "
604f3a0a 1270")
1271
604f3a0a 1272(define_expand "subdf3"
1273 [(set (match_operand:DF 0 "s_register_operand" "")
d86c91f6 1274 (minus:DF (match_operand:DF 1 "s_register_operand" "")
1275 (match_operand:DF 2 "s_register_operand" "")))]
a50d7267 1276 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 1277 "
604f3a0a 1278")
1279
b11cae9e 1280\f
1281;; Multiplication insns
1282
4422d91f 1283(define_expand "mulhi3"
1284 [(set (match_operand:HI 0 "s_register_operand" "")
1285 (mult:HI (match_operand:HI 1 "s_register_operand" "")
1286 (match_operand:HI 2 "s_register_operand" "")))]
1287 "TARGET_DSP_MULTIPLY"
1288 "
1289 {
1290 rtx result = gen_reg_rtx (SImode);
1291 emit_insn (gen_mulhisi3 (result, operands[1], operands[2]));
1292 emit_move_insn (operands[0], gen_lowpart (HImode, result));
1293 DONE;
1294 }"
1295)
1296
cffb2a26 1297(define_expand "mulsi3"
1298 [(set (match_operand:SI 0 "s_register_operand" "")
1299 (mult:SI (match_operand:SI 2 "s_register_operand" "")
1300 (match_operand:SI 1 "s_register_operand" "")))]
1301 "TARGET_EITHER"
1302 ""
1303)
1304
9c08d1fa 1305;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
cffb2a26 1306(define_insn "*arm_mulsi3"
1307 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1308 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1309 (match_operand:SI 1 "s_register_operand" "%0,r")))]
58d7d654 1310 "TARGET_32BIT && !arm_arch6"
f7fbdd4a 1311 "mul%?\\t%0, %2, %1"
9da0ec36 1312 [(set_attr "type" "mul")
0d66636f 1313 (set_attr "predicable" "yes")]
cffb2a26 1314)
1315
58d7d654 1316(define_insn "*arm_mulsi3_v6"
d952d547 1317 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
1318 (mult:SI (match_operand:SI 1 "s_register_operand" "0,l,r")
1319 (match_operand:SI 2 "s_register_operand" "l,0,r")))]
58d7d654 1320 "TARGET_32BIT && arm_arch6"
1321 "mul%?\\t%0, %1, %2"
9da0ec36 1322 [(set_attr "type" "mul")
d952d547 1323 (set_attr "predicable" "yes")
1324 (set_attr "arch" "t2,t2,*")
1325 (set_attr "length" "4")
1326 (set_attr "predicable_short_it" "yes,yes,no")]
58d7d654 1327)
1328
f7fbdd4a 1329(define_insn "*mulsi3_compare0"
bd5b4116 1330 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1331 (compare:CC_NOOV (mult:SI
1332 (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1333 (match_operand:SI 1 "s_register_operand" "%0,r"))
9c08d1fa 1334 (const_int 0)))
1335 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1336 (mult:SI (match_dup 2) (match_dup 1)))]
58d7d654 1337 "TARGET_ARM && !arm_arch6"
1338 "mul%.\\t%0, %2, %1"
1339 [(set_attr "conds" "set")
9da0ec36 1340 (set_attr "type" "muls")]
58d7d654 1341)
1342
1343(define_insn "*mulsi3_compare0_v6"
1344 [(set (reg:CC_NOOV CC_REGNUM)
1345 (compare:CC_NOOV (mult:SI
1346 (match_operand:SI 2 "s_register_operand" "r")
1347 (match_operand:SI 1 "s_register_operand" "r"))
1348 (const_int 0)))
1349 (set (match_operand:SI 0 "s_register_operand" "=r")
1350 (mult:SI (match_dup 2) (match_dup 1)))]
1351 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1352 "mul%.\\t%0, %2, %1"
cffb2a26 1353 [(set_attr "conds" "set")
9da0ec36 1354 (set_attr "type" "muls")]
cffb2a26 1355)
9c08d1fa 1356
f7fbdd4a 1357(define_insn "*mulsi_compare0_scratch"
bd5b4116 1358 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1359 (compare:CC_NOOV (mult:SI
1360 (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1361 (match_operand:SI 1 "s_register_operand" "%0,r"))
9c08d1fa 1362 (const_int 0)))
1363 (clobber (match_scratch:SI 0 "=&r,&r"))]
58d7d654 1364 "TARGET_ARM && !arm_arch6"
1365 "mul%.\\t%0, %2, %1"
1366 [(set_attr "conds" "set")
9da0ec36 1367 (set_attr "type" "muls")]
58d7d654 1368)
1369
1370(define_insn "*mulsi_compare0_scratch_v6"
1371 [(set (reg:CC_NOOV CC_REGNUM)
1372 (compare:CC_NOOV (mult:SI
1373 (match_operand:SI 2 "s_register_operand" "r")
1374 (match_operand:SI 1 "s_register_operand" "r"))
1375 (const_int 0)))
1376 (clobber (match_scratch:SI 0 "=r"))]
1377 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1378 "mul%.\\t%0, %2, %1"
cffb2a26 1379 [(set_attr "conds" "set")
9da0ec36 1380 (set_attr "type" "muls")]
cffb2a26 1381)
9c08d1fa 1382
b11cae9e 1383;; Unnamed templates to match MLA instruction.
1384
f7fbdd4a 1385(define_insn "*mulsi3addsi"
9c08d1fa 1386 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
c8f69309 1387 (plus:SI
9c08d1fa 1388 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1389 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1390 (match_operand:SI 3 "s_register_operand" "r,r,0,0")))]
58d7d654 1391 "TARGET_32BIT && !arm_arch6"
1392 "mla%?\\t%0, %2, %1, %3"
9da0ec36 1393 [(set_attr "type" "mla")
58d7d654 1394 (set_attr "predicable" "yes")]
1395)
1396
1397(define_insn "*mulsi3addsi_v6"
1398 [(set (match_operand:SI 0 "s_register_operand" "=r")
1399 (plus:SI
1400 (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1401 (match_operand:SI 1 "s_register_operand" "r"))
1402 (match_operand:SI 3 "s_register_operand" "r")))]
1403 "TARGET_32BIT && arm_arch6"
f7fbdd4a 1404 "mla%?\\t%0, %2, %1, %3"
9da0ec36 1405 [(set_attr "type" "mla")
d952d547 1406 (set_attr "predicable" "yes")
1407 (set_attr "predicable_short_it" "no")]
0d66636f 1408)
b11cae9e 1409
f7fbdd4a 1410(define_insn "*mulsi3addsi_compare0"
bd5b4116 1411 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1412 (compare:CC_NOOV
1413 (plus:SI (mult:SI
1414 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1415 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1416 (match_operand:SI 3 "s_register_operand" "r,r,0,0"))
215b30b3 1417 (const_int 0)))
9c08d1fa 1418 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1419 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1420 (match_dup 3)))]
58d7d654 1421 "TARGET_ARM && arm_arch6"
1422 "mla%.\\t%0, %2, %1, %3"
1423 [(set_attr "conds" "set")
9da0ec36 1424 (set_attr "type" "mlas")]
58d7d654 1425)
1426
1427(define_insn "*mulsi3addsi_compare0_v6"
1428 [(set (reg:CC_NOOV CC_REGNUM)
1429 (compare:CC_NOOV
1430 (plus:SI (mult:SI
1431 (match_operand:SI 2 "s_register_operand" "r")
1432 (match_operand:SI 1 "s_register_operand" "r"))
1433 (match_operand:SI 3 "s_register_operand" "r"))
1434 (const_int 0)))
1435 (set (match_operand:SI 0 "s_register_operand" "=r")
1436 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1437 (match_dup 3)))]
1438 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1439 "mla%.\\t%0, %2, %1, %3"
0d66636f 1440 [(set_attr "conds" "set")
9da0ec36 1441 (set_attr "type" "mlas")]
0d66636f 1442)
9c08d1fa 1443
f7fbdd4a 1444(define_insn "*mulsi3addsi_compare0_scratch"
bd5b4116 1445 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1446 (compare:CC_NOOV
1447 (plus:SI (mult:SI
1448 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1449 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
215b30b3 1450 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1451 (const_int 0)))
9c08d1fa 1452 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
58d7d654 1453 "TARGET_ARM && !arm_arch6"
1454 "mla%.\\t%0, %2, %1, %3"
1455 [(set_attr "conds" "set")
9da0ec36 1456 (set_attr "type" "mlas")]
58d7d654 1457)
1458
1459(define_insn "*mulsi3addsi_compare0_scratch_v6"
1460 [(set (reg:CC_NOOV CC_REGNUM)
1461 (compare:CC_NOOV
1462 (plus:SI (mult:SI
1463 (match_operand:SI 2 "s_register_operand" "r")
1464 (match_operand:SI 1 "s_register_operand" "r"))
1465 (match_operand:SI 3 "s_register_operand" "r"))
1466 (const_int 0)))
1467 (clobber (match_scratch:SI 0 "=r"))]
1468 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1469 "mla%.\\t%0, %2, %1, %3"
cffb2a26 1470 [(set_attr "conds" "set")
9da0ec36 1471 (set_attr "type" "mlas")]
cffb2a26 1472)
f7fbdd4a 1473
89545238 1474(define_insn "*mulsi3subsi"
1475 [(set (match_operand:SI 0 "s_register_operand" "=r")
1476 (minus:SI
1477 (match_operand:SI 3 "s_register_operand" "r")
1478 (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1479 (match_operand:SI 1 "s_register_operand" "r"))))]
1480 "TARGET_32BIT && arm_arch_thumb2"
1481 "mls%?\\t%0, %2, %1, %3"
9da0ec36 1482 [(set_attr "type" "mla")
d952d547 1483 (set_attr "predicable" "yes")
1484 (set_attr "predicable_short_it" "no")]
89545238 1485)
1486
5cdca009 1487(define_expand "maddsidi4"
1488 [(set (match_operand:DI 0 "s_register_operand" "")
1489 (plus:DI
1490 (mult:DI
1491 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1492 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1493 (match_operand:DI 3 "s_register_operand" "")))]
1494 "TARGET_32BIT && arm_arch3m"
1495 "")
82b85d08 1496
1497(define_insn "*mulsidi3adddi"
fe8dbf85 1498 [(set (match_operand:DI 0 "s_register_operand" "=&r")
82b85d08 1499 (plus:DI
215b30b3 1500 (mult:DI
fe8dbf85 1501 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1502 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1503 (match_operand:DI 1 "s_register_operand" "0")))]
58d7d654 1504 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1505 "smlal%?\\t%Q0, %R0, %3, %2"
9da0ec36 1506 [(set_attr "type" "smlal")
58d7d654 1507 (set_attr "predicable" "yes")]
1508)
1509
1510(define_insn "*mulsidi3adddi_v6"
1511 [(set (match_operand:DI 0 "s_register_operand" "=r")
1512 (plus:DI
1513 (mult:DI
1514 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1515 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1516 (match_operand:DI 1 "s_register_operand" "0")))]
1517 "TARGET_32BIT && arm_arch6"
fe8dbf85 1518 "smlal%?\\t%Q0, %R0, %3, %2"
9da0ec36 1519 [(set_attr "type" "smlal")
d952d547 1520 (set_attr "predicable" "yes")
1521 (set_attr "predicable_short_it" "no")]
0d66636f 1522)
82b85d08 1523
957788b0 1524;; 32x32->64 widening multiply.
1525;; As with mulsi3, the only difference between the v3-5 and v6+
1526;; versions of these patterns is the requirement that the output not
1527;; overlap the inputs, but that still means we have to have a named
1528;; expander and two different starred insns.
1529
1530(define_expand "mulsidi3"
1531 [(set (match_operand:DI 0 "s_register_operand" "")
1532 (mult:DI
1533 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1534 (sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1535 "TARGET_32BIT && arm_arch3m"
1536 ""
1537)
1538
1539(define_insn "*mulsidi3_nov6"
f7fbdd4a 1540 [(set (match_operand:DI 0 "s_register_operand" "=&r")
215b30b3 1541 (mult:DI
1542 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1543 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
58d7d654 1544 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1545 "smull%?\\t%Q0, %R0, %1, %2"
9da0ec36 1546 [(set_attr "type" "smull")
58d7d654 1547 (set_attr "predicable" "yes")]
1548)
1549
957788b0 1550(define_insn "*mulsidi3_v6"
58d7d654 1551 [(set (match_operand:DI 0 "s_register_operand" "=r")
1552 (mult:DI
1553 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1554 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1555 "TARGET_32BIT && arm_arch6"
97499065 1556 "smull%?\\t%Q0, %R0, %1, %2"
9da0ec36 1557 [(set_attr "type" "smull")
d952d547 1558 (set_attr "predicable" "yes")
1559 (set_attr "predicable_short_it" "no")]
0d66636f 1560)
f7fbdd4a 1561
957788b0 1562(define_expand "umulsidi3"
1563 [(set (match_operand:DI 0 "s_register_operand" "")
1564 (mult:DI
1565 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1566 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1567 "TARGET_32BIT && arm_arch3m"
1568 ""
1569)
1570
1571(define_insn "*umulsidi3_nov6"
f7fbdd4a 1572 [(set (match_operand:DI 0 "s_register_operand" "=&r")
215b30b3 1573 (mult:DI
1574 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1575 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
58d7d654 1576 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1577 "umull%?\\t%Q0, %R0, %1, %2"
9da0ec36 1578 [(set_attr "type" "umull")
58d7d654 1579 (set_attr "predicable" "yes")]
1580)
1581
957788b0 1582(define_insn "*umulsidi3_v6"
58d7d654 1583 [(set (match_operand:DI 0 "s_register_operand" "=r")
1584 (mult:DI
1585 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1586 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1587 "TARGET_32BIT && arm_arch6"
97499065 1588 "umull%?\\t%Q0, %R0, %1, %2"
9da0ec36 1589 [(set_attr "type" "umull")
d952d547 1590 (set_attr "predicable" "yes")
1591 (set_attr "predicable_short_it" "no")]
0d66636f 1592)
b11cae9e 1593
5cdca009 1594(define_expand "umaddsidi4"
1595 [(set (match_operand:DI 0 "s_register_operand" "")
1596 (plus:DI
1597 (mult:DI
1598 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1599 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1600 (match_operand:DI 3 "s_register_operand" "")))]
1601 "TARGET_32BIT && arm_arch3m"
1602 "")
82b85d08 1603
1604(define_insn "*umulsidi3adddi"
8ead09f9 1605 [(set (match_operand:DI 0 "s_register_operand" "=&r")
82b85d08 1606 (plus:DI
215b30b3 1607 (mult:DI
fe8dbf85 1608 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1609 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1610 (match_operand:DI 1 "s_register_operand" "0")))]
58d7d654 1611 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1612 "umlal%?\\t%Q0, %R0, %3, %2"
9da0ec36 1613 [(set_attr "type" "umlal")
58d7d654 1614 (set_attr "predicable" "yes")]
1615)
1616
1617(define_insn "*umulsidi3adddi_v6"
1618 [(set (match_operand:DI 0 "s_register_operand" "=r")
1619 (plus:DI
1620 (mult:DI
1621 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1622 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1623 (match_operand:DI 1 "s_register_operand" "0")))]
1624 "TARGET_32BIT && arm_arch6"
fe8dbf85 1625 "umlal%?\\t%Q0, %R0, %3, %2"
9da0ec36 1626 [(set_attr "type" "umlal")
d952d547 1627 (set_attr "predicable" "yes")
1628 (set_attr "predicable_short_it" "no")]
0d66636f 1629)
82b85d08 1630
957788b0 1631(define_expand "smulsi3_highpart"
1632 [(parallel
1633 [(set (match_operand:SI 0 "s_register_operand" "")
1634 (truncate:SI
1635 (lshiftrt:DI
1636 (mult:DI
1637 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1638 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1639 (const_int 32))))
1640 (clobber (match_scratch:SI 3 ""))])]
1641 "TARGET_32BIT && arm_arch3m"
1642 ""
1643)
1644
1645(define_insn "*smulsi3_highpart_nov6"
f082f1c4 1646 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1647 (truncate:SI
1648 (lshiftrt:DI
215b30b3 1649 (mult:DI
e5fea38e 1650 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
215b30b3 1651 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
f082f1c4 1652 (const_int 32))))
1653 (clobber (match_scratch:SI 3 "=&r,&r"))]
58d7d654 1654 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1655 "smull%?\\t%3, %0, %2, %1"
9da0ec36 1656 [(set_attr "type" "smull")
58d7d654 1657 (set_attr "predicable" "yes")]
1658)
1659
957788b0 1660(define_insn "*smulsi3_highpart_v6"
58d7d654 1661 [(set (match_operand:SI 0 "s_register_operand" "=r")
1662 (truncate:SI
1663 (lshiftrt:DI
1664 (mult:DI
1665 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1666 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1667 (const_int 32))))
1668 (clobber (match_scratch:SI 3 "=r"))]
1669 "TARGET_32BIT && arm_arch6"
f082f1c4 1670 "smull%?\\t%3, %0, %2, %1"
9da0ec36 1671 [(set_attr "type" "smull")
d952d547 1672 (set_attr "predicable" "yes")
1673 (set_attr "predicable_short_it" "no")]
cffb2a26 1674)
f082f1c4 1675
957788b0 1676(define_expand "umulsi3_highpart"
1677 [(parallel
1678 [(set (match_operand:SI 0 "s_register_operand" "")
1679 (truncate:SI
1680 (lshiftrt:DI
1681 (mult:DI
1682 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1683 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1684 (const_int 32))))
1685 (clobber (match_scratch:SI 3 ""))])]
1686 "TARGET_32BIT && arm_arch3m"
1687 ""
1688)
1689
1690(define_insn "*umulsi3_highpart_nov6"
f082f1c4 1691 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1692 (truncate:SI
1693 (lshiftrt:DI
215b30b3 1694 (mult:DI
e5fea38e 1695 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
215b30b3 1696 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
f082f1c4 1697 (const_int 32))))
1698 (clobber (match_scratch:SI 3 "=&r,&r"))]
58d7d654 1699 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1700 "umull%?\\t%3, %0, %2, %1"
9da0ec36 1701 [(set_attr "type" "umull")
58d7d654 1702 (set_attr "predicable" "yes")]
1703)
1704
957788b0 1705(define_insn "*umulsi3_highpart_v6"
58d7d654 1706 [(set (match_operand:SI 0 "s_register_operand" "=r")
1707 (truncate:SI
1708 (lshiftrt:DI
1709 (mult:DI
1710 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1711 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1712 (const_int 32))))
1713 (clobber (match_scratch:SI 3 "=r"))]
1714 "TARGET_32BIT && arm_arch6"
f082f1c4 1715 "umull%?\\t%3, %0, %2, %1"
9da0ec36 1716 [(set_attr "type" "umull")
d952d547 1717 (set_attr "predicable" "yes")
1718 (set_attr "predicable_short_it" "no")]
cffb2a26 1719)
f082f1c4 1720
331beb1a 1721(define_insn "mulhisi3"
1722 [(set (match_operand:SI 0 "s_register_operand" "=r")
1723 (mult:SI (sign_extend:SI
1724 (match_operand:HI 1 "s_register_operand" "%r"))
1725 (sign_extend:SI
1726 (match_operand:HI 2 "s_register_operand" "r"))))]
25f905c2 1727 "TARGET_DSP_MULTIPLY"
61a2d04c 1728 "smulbb%?\\t%0, %1, %2"
9da0ec36 1729 [(set_attr "type" "smulxy")
fec538d9 1730 (set_attr "predicable" "yes")]
1731)
1732
1733(define_insn "*mulhisi3tb"
1734 [(set (match_operand:SI 0 "s_register_operand" "=r")
1735 (mult:SI (ashiftrt:SI
1736 (match_operand:SI 1 "s_register_operand" "r")
1737 (const_int 16))
1738 (sign_extend:SI
1739 (match_operand:HI 2 "s_register_operand" "r"))))]
25f905c2 1740 "TARGET_DSP_MULTIPLY"
fec538d9 1741 "smultb%?\\t%0, %1, %2"
9da0ec36 1742 [(set_attr "type" "smulxy")
d952d547 1743 (set_attr "predicable" "yes")
1744 (set_attr "predicable_short_it" "no")]
fec538d9 1745)
1746
1747(define_insn "*mulhisi3bt"
1748 [(set (match_operand:SI 0 "s_register_operand" "=r")
1749 (mult:SI (sign_extend:SI
1750 (match_operand:HI 1 "s_register_operand" "r"))
1751 (ashiftrt:SI
1752 (match_operand:SI 2 "s_register_operand" "r")
1753 (const_int 16))))]
25f905c2 1754 "TARGET_DSP_MULTIPLY"
fec538d9 1755 "smulbt%?\\t%0, %1, %2"
9da0ec36 1756 [(set_attr "type" "smulxy")
d952d547 1757 (set_attr "predicable" "yes")
1758 (set_attr "predicable_short_it" "no")]
fec538d9 1759)
1760
1761(define_insn "*mulhisi3tt"
1762 [(set (match_operand:SI 0 "s_register_operand" "=r")
1763 (mult:SI (ashiftrt:SI
1764 (match_operand:SI 1 "s_register_operand" "r")
1765 (const_int 16))
1766 (ashiftrt:SI
1767 (match_operand:SI 2 "s_register_operand" "r")
1768 (const_int 16))))]
25f905c2 1769 "TARGET_DSP_MULTIPLY"
fec538d9 1770 "smultt%?\\t%0, %1, %2"
9da0ec36 1771 [(set_attr "type" "smulxy")
d952d547 1772 (set_attr "predicable" "yes")
1773 (set_attr "predicable_short_it" "no")]
331beb1a 1774)
1775
5cdca009 1776(define_insn "maddhisi4"
331beb1a 1777 [(set (match_operand:SI 0 "s_register_operand" "=r")
cfa6c608 1778 (plus:SI (mult:SI (sign_extend:SI
1779 (match_operand:HI 1 "s_register_operand" "r"))
331beb1a 1780 (sign_extend:SI
cfa6c608 1781 (match_operand:HI 2 "s_register_operand" "r")))
1782 (match_operand:SI 3 "s_register_operand" "r")))]
25f905c2 1783 "TARGET_DSP_MULTIPLY"
5cdca009 1784 "smlabb%?\\t%0, %1, %2, %3"
9da0ec36 1785 [(set_attr "type" "smlaxy")
d952d547 1786 (set_attr "predicable" "yes")
1787 (set_attr "predicable_short_it" "no")]
331beb1a 1788)
1789
9a92f368 1790;; Note: there is no maddhisi4ibt because this one is canonical form
1791(define_insn "*maddhisi4tb"
1792 [(set (match_operand:SI 0 "s_register_operand" "=r")
1793 (plus:SI (mult:SI (ashiftrt:SI
1794 (match_operand:SI 1 "s_register_operand" "r")
1795 (const_int 16))
1796 (sign_extend:SI
1797 (match_operand:HI 2 "s_register_operand" "r")))
1798 (match_operand:SI 3 "s_register_operand" "r")))]
1799 "TARGET_DSP_MULTIPLY"
1800 "smlatb%?\\t%0, %1, %2, %3"
9da0ec36 1801 [(set_attr "type" "smlaxy")
d952d547 1802 (set_attr "predicable" "yes")
1803 (set_attr "predicable_short_it" "no")]
9a92f368 1804)
1805
1806(define_insn "*maddhisi4tt"
1807 [(set (match_operand:SI 0 "s_register_operand" "=r")
1808 (plus:SI (mult:SI (ashiftrt:SI
1809 (match_operand:SI 1 "s_register_operand" "r")
1810 (const_int 16))
1811 (ashiftrt:SI
1812 (match_operand:SI 2 "s_register_operand" "r")
1813 (const_int 16)))
1814 (match_operand:SI 3 "s_register_operand" "r")))]
1815 "TARGET_DSP_MULTIPLY"
1816 "smlatt%?\\t%0, %1, %2, %3"
9da0ec36 1817 [(set_attr "type" "smlaxy")
d952d547 1818 (set_attr "predicable" "yes")
1819 (set_attr "predicable_short_it" "no")]
9a92f368 1820)
1821
aff5fb4d 1822(define_insn "maddhidi4"
331beb1a 1823 [(set (match_operand:DI 0 "s_register_operand" "=r")
1824 (plus:DI
331beb1a 1825 (mult:DI (sign_extend:DI
d952d547 1826 (match_operand:HI 1 "s_register_operand" "r"))
331beb1a 1827 (sign_extend:DI
cfa6c608 1828 (match_operand:HI 2 "s_register_operand" "r")))
1829 (match_operand:DI 3 "s_register_operand" "0")))]
25f905c2 1830 "TARGET_DSP_MULTIPLY"
5cdca009 1831 "smlalbb%?\\t%Q0, %R0, %1, %2"
9da0ec36 1832 [(set_attr "type" "smlalxy")
d952d547 1833 (set_attr "predicable" "yes")
1834 (set_attr "predicable_short_it" "no")])
331beb1a 1835
9a92f368 1836;; Note: there is no maddhidi4ibt because this one is canonical form
1837(define_insn "*maddhidi4tb"
1838 [(set (match_operand:DI 0 "s_register_operand" "=r")
1839 (plus:DI
1840 (mult:DI (sign_extend:DI
1841 (ashiftrt:SI
1842 (match_operand:SI 1 "s_register_operand" "r")
1843 (const_int 16)))
1844 (sign_extend:DI
1845 (match_operand:HI 2 "s_register_operand" "r")))
1846 (match_operand:DI 3 "s_register_operand" "0")))]
1847 "TARGET_DSP_MULTIPLY"
1848 "smlaltb%?\\t%Q0, %R0, %1, %2"
9da0ec36 1849 [(set_attr "type" "smlalxy")
d952d547 1850 (set_attr "predicable" "yes")
1851 (set_attr "predicable_short_it" "no")])
9a92f368 1852
1853(define_insn "*maddhidi4tt"
1854 [(set (match_operand:DI 0 "s_register_operand" "=r")
1855 (plus:DI
1856 (mult:DI (sign_extend:DI
1857 (ashiftrt:SI
1858 (match_operand:SI 1 "s_register_operand" "r")
1859 (const_int 16)))
1860 (sign_extend:DI
1861 (ashiftrt:SI
1862 (match_operand:SI 2 "s_register_operand" "r")
1863 (const_int 16))))
1864 (match_operand:DI 3 "s_register_operand" "0")))]
1865 "TARGET_DSP_MULTIPLY"
1866 "smlaltt%?\\t%Q0, %R0, %1, %2"
9da0ec36 1867 [(set_attr "type" "smlalxy")
d952d547 1868 (set_attr "predicable" "yes")
1869 (set_attr "predicable_short_it" "no")])
9a92f368 1870
604f3a0a 1871(define_expand "mulsf3"
1872 [(set (match_operand:SF 0 "s_register_operand" "")
1873 (mult:SF (match_operand:SF 1 "s_register_operand" "")
d86c91f6 1874 (match_operand:SF 2 "s_register_operand" "")))]
25f905c2 1875 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1876 "
604f3a0a 1877")
1878
604f3a0a 1879(define_expand "muldf3"
1880 [(set (match_operand:DF 0 "s_register_operand" "")
1881 (mult:DF (match_operand:DF 1 "s_register_operand" "")
d86c91f6 1882 (match_operand:DF 2 "s_register_operand" "")))]
a50d7267 1883 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 1884 "
604f3a0a 1885")
b11cae9e 1886\f
1887;; Division insns
1888
7db9af5d 1889(define_expand "divsf3"
1890 [(set (match_operand:SF 0 "s_register_operand" "")
d86c91f6 1891 (div:SF (match_operand:SF 1 "s_register_operand" "")
1892 (match_operand:SF 2 "s_register_operand" "")))]
994606f8 1893 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
7db9af5d 1894 "")
9c08d1fa 1895
7db9af5d 1896(define_expand "divdf3"
1897 [(set (match_operand:DF 0 "s_register_operand" "")
d86c91f6 1898 (div:DF (match_operand:DF 1 "s_register_operand" "")
1899 (match_operand:DF 2 "s_register_operand" "")))]
994606f8 1900 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
7db9af5d 1901 "")
b11cae9e 1902\f
1903;; Boolean and,ior,xor insns
1904
f6ebffac 1905;; Split up double word logical operations
1906
1907;; Split up simple DImode logical operations. Simply perform the logical
1908;; operation on the upper and lower halves of the registers.
1909(define_split
1910 [(set (match_operand:DI 0 "s_register_operand" "")
1911 (match_operator:DI 6 "logical_binary_operator"
1912 [(match_operand:DI 1 "s_register_operand" "")
1913 (match_operand:DI 2 "s_register_operand" "")]))]
25f905c2 1914 "TARGET_32BIT && reload_completed
e2669ea7 1915 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))
25f905c2 1916 && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
f6ebffac 1917 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1918 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1919 "
215b30b3 1920 {
1921 operands[3] = gen_highpart (SImode, operands[0]);
1922 operands[0] = gen_lowpart (SImode, operands[0]);
1923 operands[4] = gen_highpart (SImode, operands[1]);
1924 operands[1] = gen_lowpart (SImode, operands[1]);
1925 operands[5] = gen_highpart (SImode, operands[2]);
1926 operands[2] = gen_lowpart (SImode, operands[2]);
1927 }"
1928)
f6ebffac 1929
f6ebffac 1930(define_split
1931 [(set (match_operand:DI 0 "s_register_operand" "")
1932 (match_operator:DI 6 "logical_binary_operator"
1933 [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1934 (match_operand:DI 1 "s_register_operand" "")]))]
25f905c2 1935 "TARGET_32BIT && reload_completed"
f6ebffac 1936 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1937 (set (match_dup 3) (match_op_dup:SI 6
1938 [(ashiftrt:SI (match_dup 2) (const_int 31))
1939 (match_dup 4)]))]
1940 "
215b30b3 1941 {
1942 operands[3] = gen_highpart (SImode, operands[0]);
1943 operands[0] = gen_lowpart (SImode, operands[0]);
1944 operands[4] = gen_highpart (SImode, operands[1]);
1945 operands[1] = gen_lowpart (SImode, operands[1]);
1946 operands[5] = gen_highpart (SImode, operands[2]);
1947 operands[2] = gen_lowpart (SImode, operands[2]);
1948 }"
1949)
f6ebffac 1950
f6ebffac 1951;; The zero extend of operand 2 means we can just copy the high part of
1952;; operand1 into operand0.
1953(define_split
1954 [(set (match_operand:DI 0 "s_register_operand" "")
1955 (ior:DI
1956 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1957 (match_operand:DI 1 "s_register_operand" "")))]
25f905c2 1958 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
f6ebffac 1959 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1960 (set (match_dup 3) (match_dup 4))]
1961 "
215b30b3 1962 {
1963 operands[4] = gen_highpart (SImode, operands[1]);
1964 operands[3] = gen_highpart (SImode, operands[0]);
1965 operands[0] = gen_lowpart (SImode, operands[0]);
1966 operands[1] = gen_lowpart (SImode, operands[1]);
1967 }"
1968)
f6ebffac 1969
1970;; The zero extend of operand 2 means we can just copy the high part of
1971;; operand1 into operand0.
1972(define_split
1973 [(set (match_operand:DI 0 "s_register_operand" "")
1974 (xor:DI
1975 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1976 (match_operand:DI 1 "s_register_operand" "")))]
25f905c2 1977 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
f6ebffac 1978 [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1979 (set (match_dup 3) (match_dup 4))]
1980 "
215b30b3 1981 {
1982 operands[4] = gen_highpart (SImode, operands[1]);
1983 operands[3] = gen_highpart (SImode, operands[0]);
1984 operands[0] = gen_lowpart (SImode, operands[0]);
1985 operands[1] = gen_lowpart (SImode, operands[1]);
1986 }"
1987)
f6ebffac 1988
e2669ea7 1989(define_expand "anddi3"
1990 [(set (match_operand:DI 0 "s_register_operand" "")
1991 (and:DI (match_operand:DI 1 "s_register_operand" "")
1992 (match_operand:DI 2 "neon_inv_logic_op2" "")))]
1993 "TARGET_32BIT"
1994 ""
1995)
1996
f6bbdcf6 1997(define_insn_and_split "*anddi3_insn"
0a314dcd 1998 [(set (match_operand:DI 0 "s_register_operand" "=w,w ,&r,&r,&r,&r,?w,?w")
1999 (and:DI (match_operand:DI 1 "s_register_operand" "%w,0 ,0 ,r ,0 ,r ,w ,0")
2000 (match_operand:DI 2 "arm_anddi_operand_neon" "w ,DL,r ,r ,De,De,w ,DL")))]
f6bbdcf6 2001 "TARGET_32BIT && !TARGET_IWMMXT"
2002{
2003 switch (which_alternative)
2004 {
0a314dcd 2005 case 0: /* fall through */
2006 case 6: return "vand\t%P0, %P1, %P2";
2007 case 1: /* fall through */
2008 case 7: return neon_output_logic_immediate ("vand", &operands[2],
2009 DImode, 1, VALID_NEON_QREG_MODE (DImode));
f6bbdcf6 2010 case 2:
0a314dcd 2011 case 3:
2012 case 4:
f6bbdcf6 2013 case 5: /* fall through */
0a314dcd 2014 return "#";
f6bbdcf6 2015 default: gcc_unreachable ();
2016 }
2017}
0a314dcd 2018 "TARGET_32BIT && !TARGET_IWMMXT && reload_completed
2019 && !(IS_VFP_REGNUM (REGNO (operands[0])))"
f6bbdcf6 2020 [(set (match_dup 3) (match_dup 4))
2021 (set (match_dup 5) (match_dup 6))]
2022 "
2023 {
2024 operands[3] = gen_lowpart (SImode, operands[0]);
2025 operands[5] = gen_highpart (SImode, operands[0]);
2026
2027 operands[4] = simplify_gen_binary (AND, SImode,
2028 gen_lowpart (SImode, operands[1]),
2029 gen_lowpart (SImode, operands[2]));
2030 operands[6] = simplify_gen_binary (AND, SImode,
2031 gen_highpart (SImode, operands[1]),
2032 gen_highpart_mode (SImode, DImode, operands[2]));
2033
2034 }"
32093010 2035 [(set_attr "type" "neon_logic,neon_logic,multiple,multiple,\
2036 multiple,multiple,neon_logic,neon_logic")
0a314dcd 2037 (set_attr "arch" "neon_for_64bits,neon_for_64bits,*,*,*,*,
f6bbdcf6 2038 avoid_neon_for_64bits,avoid_neon_for_64bits")
0a314dcd 2039 (set_attr "length" "*,*,8,8,8,8,*,*")
2040 ]
215b30b3 2041)
b11cae9e 2042
a0f94409 2043(define_insn_and_split "*anddi_zesidi_di"
9c08d1fa 2044 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2045 (and:DI (zero_extend:DI
2046 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 2047 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2048 "TARGET_32BIT"
f6ebffac 2049 "#"
25f905c2 2050 "TARGET_32BIT && reload_completed"
a0f94409 2051 ; The zero extend of operand 2 clears the high word of the output
2052 ; operand.
2053 [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
2054 (set (match_dup 3) (const_int 0))]
2055 "
2056 {
2057 operands[3] = gen_highpart (SImode, operands[0]);
2058 operands[0] = gen_lowpart (SImode, operands[0]);
2059 operands[1] = gen_lowpart (SImode, operands[1]);
2060 }"
1b7da4ac 2061 [(set_attr "length" "8")
2062 (set_attr "type" "multiple")]
215b30b3 2063)
b11cae9e 2064
f7fbdd4a 2065(define_insn "*anddi_sesdi_di"
cffb2a26 2066 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 2067 (and:DI (sign_extend:DI
2068 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 2069 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2070 "TARGET_32BIT"
f6ebffac 2071 "#"
1b7da4ac 2072 [(set_attr "length" "8")
2073 (set_attr "type" "multiple")]
cffb2a26 2074)
b11cae9e 2075
87b22bf7 2076(define_expand "andsi3"
cffb2a26 2077 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2078 (and:SI (match_operand:SI 1 "s_register_operand" "")
2079 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 2080 "TARGET_EITHER"
87b22bf7 2081 "
25f905c2 2082 if (TARGET_32BIT)
87b22bf7 2083 {
0438d37f 2084 if (CONST_INT_P (operands[2]))
cffb2a26 2085 {
47b5b27b 2086 if (INTVAL (operands[2]) == 255 && arm_arch6)
2087 {
2088 operands[1] = convert_to_mode (QImode, operands[1], 1);
2089 emit_insn (gen_thumb2_zero_extendqisi2_v6 (operands[0],
2090 operands[1]));
17202aa5 2091 DONE;
47b5b27b 2092 }
17202aa5 2093 else if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[2]), AND))
2094 operands[2] = force_reg (SImode, operands[2]);
47b5b27b 2095 else
17202aa5 2096 {
2097 arm_split_constant (AND, SImode, NULL_RTX,
2098 INTVAL (operands[2]), operands[0],
2099 operands[1],
2100 optimize && can_create_pseudo_p ());
615caa51 2101
17202aa5 2102 DONE;
2103 }
cffb2a26 2104 }
87b22bf7 2105 }
25f905c2 2106 else /* TARGET_THUMB1 */
cffb2a26 2107 {
0438d37f 2108 if (!CONST_INT_P (operands[2]))
923ffadb 2109 {
2110 rtx tmp = force_reg (SImode, operands[2]);
2111 if (rtx_equal_p (operands[0], operands[1]))
2112 operands[2] = tmp;
2113 else
2114 {
2115 operands[2] = operands[1];
2116 operands[1] = tmp;
2117 }
2118 }
cffb2a26 2119 else
2120 {
2121 int i;
2122
215b30b3 2123 if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
cffb2a26 2124 {
215b30b3 2125 operands[2] = force_reg (SImode,
2126 GEN_INT (~INTVAL (operands[2])));
cffb2a26 2127
747b7458 2128 emit_insn (gen_thumb1_bicsi3 (operands[0], operands[2], operands[1]));
cffb2a26 2129
2130 DONE;
2131 }
87b22bf7 2132
cffb2a26 2133 for (i = 9; i <= 31; i++)
2134 {
2135 if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
2136 {
2137 emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
2138 const0_rtx));
2139 DONE;
2140 }
215b30b3 2141 else if ((((HOST_WIDE_INT) 1) << i) - 1
2142 == ~INTVAL (operands[2]))
cffb2a26 2143 {
2144 rtx shift = GEN_INT (i);
2145 rtx reg = gen_reg_rtx (SImode);
2146
2147 emit_insn (gen_lshrsi3 (reg, operands[1], shift));
2148 emit_insn (gen_ashlsi3 (operands[0], reg, shift));
2149
2150 DONE;
2151 }
2152 }
2153
2154 operands[2] = force_reg (SImode, operands[2]);
2155 }
215b30b3 2156 }
2157 "
cffb2a26 2158)
2159
25f905c2 2160; ??? Check split length for Thumb-2
a0f94409 2161(define_insn_and_split "*arm_andsi3_insn"
29e234a3 2162 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r,r,r")
2163 (and:SI (match_operand:SI 1 "s_register_operand" "%r,0,r,r,r")
2164 (match_operand:SI 2 "reg_or_int_operand" "I,l,K,r,?n")))]
25f905c2 2165 "TARGET_32BIT"
5565501b 2166 "@
29e234a3 2167 and%?\\t%0, %1, %2
5565501b 2168 and%?\\t%0, %1, %2
87b22bf7 2169 bic%?\\t%0, %1, #%B2
65f68e55 2170 and%?\\t%0, %1, %2
87b22bf7 2171 #"
25f905c2 2172 "TARGET_32BIT
0438d37f 2173 && CONST_INT_P (operands[2])
a0f94409 2174 && !(const_ok_for_arm (INTVAL (operands[2]))
2175 || const_ok_for_arm (~INTVAL (operands[2])))"
2176 [(clobber (const_int 0))]
2177 "
96f57e36 2178 arm_split_constant (AND, SImode, curr_insn,
2179 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 2180 DONE;
2181 "
29e234a3 2182 [(set_attr "length" "4,4,4,4,16")
65f68e55 2183 (set_attr "predicable" "yes")
29e234a3 2184 (set_attr "predicable_short_it" "no,yes,no,no,no")
d82e788e 2185 (set_attr "type" "logic_imm,logic_imm,logic_reg,logic_reg,logic_imm")]
cffb2a26 2186)
2187
f7fbdd4a 2188(define_insn "*andsi3_compare0"
bd5b4116 2189 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 2190 (compare:CC_NOOV
65f68e55 2191 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
2192 (match_operand:SI 2 "arm_not_operand" "I,K,r"))
5565501b 2193 (const_int 0)))
65f68e55 2194 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9c08d1fa 2195 (and:SI (match_dup 1) (match_dup 2)))]
25f905c2 2196 "TARGET_32BIT"
5565501b 2197 "@
25f905c2 2198 and%.\\t%0, %1, %2
65f68e55 2199 bic%.\\t%0, %1, #%B2
2200 and%.\\t%0, %1, %2"
2201 [(set_attr "conds" "set")
d82e788e 2202 (set_attr "type" "logics_imm,logics_imm,logics_reg")]
cffb2a26 2203)
9c08d1fa 2204
f7fbdd4a 2205(define_insn "*andsi3_compare0_scratch"
bd5b4116 2206 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 2207 (compare:CC_NOOV
65f68e55 2208 (and:SI (match_operand:SI 0 "s_register_operand" "r,r,r")
2209 (match_operand:SI 1 "arm_not_operand" "I,K,r"))
5565501b 2210 (const_int 0)))
65f68e55 2211 (clobber (match_scratch:SI 2 "=X,r,X"))]
25f905c2 2212 "TARGET_32BIT"
5565501b 2213 "@
2214 tst%?\\t%0, %1
65f68e55 2215 bic%.\\t%2, %0, #%B1
2216 tst%?\\t%0, %1"
2217 [(set_attr "conds" "set")
d82e788e 2218 (set_attr "type" "logics_imm,logics_imm,logics_reg")]
0d66636f 2219)
9c08d1fa 2220
f7fbdd4a 2221(define_insn "*zeroextractsi_compare0_scratch"
bd5b4116 2222 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2223 (compare:CC_NOOV (zero_extract:SI
2224 (match_operand:SI 0 "s_register_operand" "r")
d952d547 2225 (match_operand 1 "const_int_operand" "n")
206ee9a2 2226 (match_operand 2 "const_int_operand" "n"))
9c08d1fa 2227 (const_int 0)))]
25f905c2 2228 "TARGET_32BIT
cffb2a26 2229 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
2230 && INTVAL (operands[1]) > 0
2231 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
2232 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
9c08d1fa 2233 "*
5c49a439 2234 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
2235 << INTVAL (operands[2]));
40dbec34 2236 output_asm_insn (\"tst%?\\t%0, %1\", operands);
e2348bcb 2237 return \"\";
0d66636f 2238 "
596e5e8f 2239 [(set_attr "conds" "set")
65f68e55 2240 (set_attr "predicable" "yes")
d952d547 2241 (set_attr "predicable_short_it" "no")
d82e788e 2242 (set_attr "type" "logics_imm")]
0d66636f 2243)
9c08d1fa 2244
f4462328 2245(define_insn_and_split "*ne_zeroextractsi"
c4034607 2246 [(set (match_operand:SI 0 "s_register_operand" "=r")
2247 (ne:SI (zero_extract:SI
2248 (match_operand:SI 1 "s_register_operand" "r")
2249 (match_operand:SI 2 "const_int_operand" "n")
2250 (match_operand:SI 3 "const_int_operand" "n"))
3b8c7f7a 2251 (const_int 0)))
2252 (clobber (reg:CC CC_REGNUM))]
25f905c2 2253 "TARGET_32BIT
cffb2a26 2254 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2255 && INTVAL (operands[2]) > 0
2256 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2257 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
f4462328 2258 "#"
25f905c2 2259 "TARGET_32BIT
f4462328 2260 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2261 && INTVAL (operands[2]) > 0
2262 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2263 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
2264 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2265 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2266 (const_int 0)))
2267 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2268 (set (match_dup 0)
2269 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2270 (match_dup 0) (const_int 1)))]
2271 "
2272 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
2273 << INTVAL (operands[3]));
2274 "
2275 [(set_attr "conds" "clob")
25f905c2 2276 (set (attr "length")
2277 (if_then_else (eq_attr "is_thumb" "yes")
2278 (const_int 12)
1b7da4ac 2279 (const_int 8)))
2280 (set_attr "type" "multiple")]
f4462328 2281)
2282
2283(define_insn_and_split "*ne_zeroextractsi_shifted"
2284 [(set (match_operand:SI 0 "s_register_operand" "=r")
2285 (ne:SI (zero_extract:SI
2286 (match_operand:SI 1 "s_register_operand" "r")
2287 (match_operand:SI 2 "const_int_operand" "n")
2288 (const_int 0))
2289 (const_int 0)))
2290 (clobber (reg:CC CC_REGNUM))]
2291 "TARGET_ARM"
2292 "#"
2293 "TARGET_ARM"
2294 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2295 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2296 (const_int 0)))
2297 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2298 (set (match_dup 0)
2299 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2300 (match_dup 0) (const_int 1)))]
2301 "
2302 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
2303 "
2304 [(set_attr "conds" "clob")
1b7da4ac 2305 (set_attr "length" "8")
2306 (set_attr "type" "multiple")]
f4462328 2307)
2308
2309(define_insn_and_split "*ite_ne_zeroextractsi"
2310 [(set (match_operand:SI 0 "s_register_operand" "=r")
2311 (if_then_else:SI (ne (zero_extract:SI
2312 (match_operand:SI 1 "s_register_operand" "r")
2313 (match_operand:SI 2 "const_int_operand" "n")
2314 (match_operand:SI 3 "const_int_operand" "n"))
2315 (const_int 0))
2316 (match_operand:SI 4 "arm_not_operand" "rIK")
2317 (const_int 0)))
2318 (clobber (reg:CC CC_REGNUM))]
2319 "TARGET_ARM
2320 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2321 && INTVAL (operands[2]) > 0
2322 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 2323 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2324 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 2325 "#"
2326 "TARGET_ARM
2327 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2328 && INTVAL (operands[2]) > 0
2329 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 2330 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2331 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 2332 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2333 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2334 (const_int 0)))
2335 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2336 (set (match_dup 0)
2337 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2338 (match_dup 0) (match_dup 4)))]
2339 "
c4034607 2340 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
f4462328 2341 << INTVAL (operands[3]));
2342 "
2343 [(set_attr "conds" "clob")
1b7da4ac 2344 (set_attr "length" "8")
2345 (set_attr "type" "multiple")]
f4462328 2346)
2347
2348(define_insn_and_split "*ite_ne_zeroextractsi_shifted"
2349 [(set (match_operand:SI 0 "s_register_operand" "=r")
2350 (if_then_else:SI (ne (zero_extract:SI
2351 (match_operand:SI 1 "s_register_operand" "r")
2352 (match_operand:SI 2 "const_int_operand" "n")
2353 (const_int 0))
2354 (const_int 0))
2355 (match_operand:SI 3 "arm_not_operand" "rIK")
2356 (const_int 0)))
2357 (clobber (reg:CC CC_REGNUM))]
f8d7bf2f 2358 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 2359 "#"
f8d7bf2f 2360 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 2361 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2362 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2363 (const_int 0)))
2364 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2365 (set (match_dup 0)
2366 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2367 (match_dup 0) (match_dup 3)))]
2368 "
2369 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
0d66636f 2370 "
2371 [(set_attr "conds" "clob")
1b7da4ac 2372 (set_attr "length" "8")
2373 (set_attr "type" "multiple")]
215b30b3 2374)
9c08d1fa 2375
25f905c2 2376;; ??? Use Thumb-2 has bitfield insert/extract instructions.
d7863cfe 2377(define_split
2378 [(set (match_operand:SI 0 "s_register_operand" "")
2379 (match_operator:SI 1 "shiftable_operator"
2380 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2381 (match_operand:SI 3 "const_int_operand" "")
2382 (match_operand:SI 4 "const_int_operand" ""))
2383 (match_operand:SI 5 "s_register_operand" "")]))
2384 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2385 "TARGET_ARM"
2386 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2387 (set (match_dup 0)
2388 (match_op_dup 1
2389 [(lshiftrt:SI (match_dup 6) (match_dup 4))
2390 (match_dup 5)]))]
2391 "{
2392 HOST_WIDE_INT temp = INTVAL (operands[3]);
2393
2394 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2395 operands[4] = GEN_INT (32 - temp);
2396 }"
2397)
2398
d7863cfe 2399(define_split
2400 [(set (match_operand:SI 0 "s_register_operand" "")
2401 (match_operator:SI 1 "shiftable_operator"
2402 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2403 (match_operand:SI 3 "const_int_operand" "")
2404 (match_operand:SI 4 "const_int_operand" ""))
2405 (match_operand:SI 5 "s_register_operand" "")]))
2406 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2407 "TARGET_ARM"
2408 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2409 (set (match_dup 0)
2410 (match_op_dup 1
2411 [(ashiftrt:SI (match_dup 6) (match_dup 4))
2412 (match_dup 5)]))]
2413 "{
2414 HOST_WIDE_INT temp = INTVAL (operands[3]);
2415
2416 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2417 operands[4] = GEN_INT (32 - temp);
2418 }"
2419)
2420
a42059fd 2421;;; ??? This pattern is bogus. If operand3 has bits outside the range
2422;;; represented by the bitfield, then this will produce incorrect results.
2423;;; Somewhere, the value needs to be truncated. On targets like the m68k,
ceb2fe0f 2424;;; which have a real bit-field insert instruction, the truncation happens
2425;;; in the bit-field insert instruction itself. Since arm does not have a
2426;;; bit-field insert instruction, we would have to emit code here to truncate
a42059fd 2427;;; the value before we insert. This loses some of the advantage of having
2428;;; this insv pattern, so this pattern needs to be reevalutated.
2429
8a18b90c 2430(define_expand "insv"
eb04cafb 2431 [(set (zero_extract (match_operand 0 "nonimmediate_operand" "")
2432 (match_operand 1 "general_operand" "")
2433 (match_operand 2 "general_operand" ""))
2434 (match_operand 3 "reg_or_int_operand" ""))]
8b054d5a 2435 "TARGET_ARM || arm_arch_thumb2"
8a18b90c 2436 "
215b30b3 2437 {
2438 int start_bit = INTVAL (operands[2]);
2439 int width = INTVAL (operands[1]);
2440 HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
2441 rtx target, subtarget;
2442
8b054d5a 2443 if (arm_arch_thumb2)
2444 {
eb04cafb 2445 if (unaligned_access && MEM_P (operands[0])
2446 && s_register_operand (operands[3], GET_MODE (operands[3]))
2447 && (width == 16 || width == 32) && (start_bit % BITS_PER_UNIT) == 0)
8b054d5a 2448 {
eb04cafb 2449 rtx base_addr;
2450
2451 if (BYTES_BIG_ENDIAN)
2452 start_bit = GET_MODE_BITSIZE (GET_MODE (operands[3])) - width
2453 - start_bit;
8b054d5a 2454
eb04cafb 2455 if (width == 32)
8b054d5a 2456 {
eb04cafb 2457 base_addr = adjust_address (operands[0], SImode,
2458 start_bit / BITS_PER_UNIT);
2459 emit_insn (gen_unaligned_storesi (base_addr, operands[3]));
8b054d5a 2460 }
eb04cafb 2461 else
2462 {
2463 rtx tmp = gen_reg_rtx (HImode);
8b054d5a 2464
eb04cafb 2465 base_addr = adjust_address (operands[0], HImode,
2466 start_bit / BITS_PER_UNIT);
2467 emit_move_insn (tmp, gen_lowpart (HImode, operands[3]));
2468 emit_insn (gen_unaligned_storehi (base_addr, tmp));
2469 }
2470 DONE;
8b054d5a 2471 }
eb04cafb 2472 else if (s_register_operand (operands[0], GET_MODE (operands[0])))
8b054d5a 2473 {
eb04cafb 2474 bool use_bfi = TRUE;
8b054d5a 2475
0438d37f 2476 if (CONST_INT_P (operands[3]))
eb04cafb 2477 {
2478 HOST_WIDE_INT val = INTVAL (operands[3]) & mask;
2479
2480 if (val == 0)
2481 {
2482 emit_insn (gen_insv_zero (operands[0], operands[1],
2483 operands[2]));
2484 DONE;
2485 }
2486
2487 /* See if the set can be done with a single orr instruction. */
2488 if (val == mask && const_ok_for_arm (val << start_bit))
2489 use_bfi = FALSE;
2490 }
2491
2492 if (use_bfi)
2493 {
0438d37f 2494 if (!REG_P (operands[3]))
eb04cafb 2495 operands[3] = force_reg (SImode, operands[3]);
2496
2497 emit_insn (gen_insv_t2 (operands[0], operands[1], operands[2],
2498 operands[3]));
2499 DONE;
2500 }
8b054d5a 2501 }
eb04cafb 2502 else
2503 FAIL;
8b054d5a 2504 }
2505
eb04cafb 2506 if (!s_register_operand (operands[0], GET_MODE (operands[0])))
2507 FAIL;
2508
3f8fde42 2509 target = copy_rtx (operands[0]);
215b30b3 2510 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
2511 subreg as the final target. */
2512 if (GET_CODE (target) == SUBREG)
2513 {
2514 subtarget = gen_reg_rtx (SImode);
2515 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
2516 < GET_MODE_SIZE (SImode))
2517 target = SUBREG_REG (target);
2518 }
2519 else
2520 subtarget = target;
8a18b90c 2521
0438d37f 2522 if (CONST_INT_P (operands[3]))
215b30b3 2523 {
2524 /* Since we are inserting a known constant, we may be able to
2525 reduce the number of bits that we have to clear so that
2526 the mask becomes simple. */
2527 /* ??? This code does not check to see if the new mask is actually
2528 simpler. It may not be. */
2529 rtx op1 = gen_reg_rtx (SImode);
2530 /* ??? Truncate operand3 to fit in the bitfield. See comment before
2531 start of this pattern. */
2532 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
2533 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
2534
c5b3a71b 2535 emit_insn (gen_andsi3 (op1, operands[0],
2536 gen_int_mode (~mask2, SImode)));
215b30b3 2537 emit_insn (gen_iorsi3 (subtarget, op1,
4292ca6b 2538 gen_int_mode (op3_value << start_bit, SImode)));
215b30b3 2539 }
2540 else if (start_bit == 0
2541 && !(const_ok_for_arm (mask)
2542 || const_ok_for_arm (~mask)))
2543 {
2544 /* A Trick, since we are setting the bottom bits in the word,
2545 we can shift operand[3] up, operand[0] down, OR them together
2546 and rotate the result back again. This takes 3 insns, and
5910bb95 2547 the third might be mergeable into another op. */
215b30b3 2548 /* The shift up copes with the possibility that operand[3] is
2549 wider than the bitfield. */
2550 rtx op0 = gen_reg_rtx (SImode);
2551 rtx op1 = gen_reg_rtx (SImode);
2552
2553 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2554 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
2555 emit_insn (gen_iorsi3 (op1, op1, op0));
2556 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
2557 }
2558 else if ((width + start_bit == 32)
2559 && !(const_ok_for_arm (mask)
2560 || const_ok_for_arm (~mask)))
2561 {
2562 /* Similar trick, but slightly less efficient. */
8a18b90c 2563
215b30b3 2564 rtx op0 = gen_reg_rtx (SImode);
2565 rtx op1 = gen_reg_rtx (SImode);
8a18b90c 2566
215b30b3 2567 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2568 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
2569 emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
2570 emit_insn (gen_iorsi3 (subtarget, op1, op0));
2571 }
2572 else
2573 {
c5b3a71b 2574 rtx op0 = gen_int_mode (mask, SImode);
215b30b3 2575 rtx op1 = gen_reg_rtx (SImode);
2576 rtx op2 = gen_reg_rtx (SImode);
8a18b90c 2577
215b30b3 2578 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
2579 {
2580 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 2581
215b30b3 2582 emit_insn (gen_movsi (tmp, op0));
2583 op0 = tmp;
2584 }
8a18b90c 2585
215b30b3 2586 /* Mask out any bits in operand[3] that are not needed. */
2587 emit_insn (gen_andsi3 (op1, operands[3], op0));
8a18b90c 2588
0438d37f 2589 if (CONST_INT_P (op0)
215b30b3 2590 && (const_ok_for_arm (mask << start_bit)
2591 || const_ok_for_arm (~(mask << start_bit))))
2592 {
c5b3a71b 2593 op0 = gen_int_mode (~(mask << start_bit), SImode);
215b30b3 2594 emit_insn (gen_andsi3 (op2, operands[0], op0));
2595 }
2596 else
2597 {
0438d37f 2598 if (CONST_INT_P (op0))
215b30b3 2599 {
2600 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 2601
215b30b3 2602 emit_insn (gen_movsi (tmp, op0));
2603 op0 = tmp;
2604 }
2605
2606 if (start_bit != 0)
2607 emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
a42059fd 2608
215b30b3 2609 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
2610 }
8a18b90c 2611
215b30b3 2612 if (start_bit != 0)
2613 emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
8a18b90c 2614
215b30b3 2615 emit_insn (gen_iorsi3 (subtarget, op1, op2));
2616 }
f082f1c4 2617
215b30b3 2618 if (subtarget != target)
2619 {
2620 /* If TARGET is still a SUBREG, then it must be wider than a word,
2621 so we must be careful only to set the subword we were asked to. */
2622 if (GET_CODE (target) == SUBREG)
2623 emit_move_insn (target, subtarget);
2624 else
2625 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
2626 }
8a18b90c 2627
215b30b3 2628 DONE;
2629 }"
2630)
8a18b90c 2631
8b054d5a 2632(define_insn "insv_zero"
2633 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
809003b3 2634 (match_operand:SI 1 "const_int_M_operand" "M")
2635 (match_operand:SI 2 "const_int_M_operand" "M"))
8b054d5a 2636 (const_int 0))]
2637 "arm_arch_thumb2"
2638 "bfc%?\t%0, %2, %1"
2639 [(set_attr "length" "4")
d952d547 2640 (set_attr "predicable" "yes")
d82e788e 2641 (set_attr "predicable_short_it" "no")
2642 (set_attr "type" "bfm")]
8b054d5a 2643)
2644
2645(define_insn "insv_t2"
2646 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
809003b3 2647 (match_operand:SI 1 "const_int_M_operand" "M")
2648 (match_operand:SI 2 "const_int_M_operand" "M"))
8b054d5a 2649 (match_operand:SI 3 "s_register_operand" "r"))]
2650 "arm_arch_thumb2"
2651 "bfi%?\t%0, %3, %2, %1"
2652 [(set_attr "length" "4")
d952d547 2653 (set_attr "predicable" "yes")
d82e788e 2654 (set_attr "predicable_short_it" "no")
2655 (set_attr "type" "bfm")]
8b054d5a 2656)
2657
215b30b3 2658; constants for op 2 will never be given to these patterns.
a0f94409 2659(define_insn_and_split "*anddi_notdi_di"
9c08d1fa 2660 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 2661 (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "0,r"))
2662 (match_operand:DI 2 "s_register_operand" "r,0")))]
25f905c2 2663 "TARGET_32BIT"
f6ebffac 2664 "#"
e2669ea7 2665 "TARGET_32BIT && reload_completed
2666 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))
2667 && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
a0f94409 2668 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2669 (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2670 "
2671 {
2672 operands[3] = gen_highpart (SImode, operands[0]);
2673 operands[0] = gen_lowpart (SImode, operands[0]);
2674 operands[4] = gen_highpart (SImode, operands[1]);
2675 operands[1] = gen_lowpart (SImode, operands[1]);
2676 operands[5] = gen_highpart (SImode, operands[2]);
2677 operands[2] = gen_lowpart (SImode, operands[2]);
2678 }"
0d66636f 2679 [(set_attr "length" "8")
1b7da4ac 2680 (set_attr "predicable" "yes")
2681 (set_attr "type" "multiple")]
0d66636f 2682)
d952d547 2683
a0f94409 2684(define_insn_and_split "*anddi_notzesidi_di"
9c08d1fa 2685 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2686 (and:DI (not:DI (zero_extend:DI
2687 (match_operand:SI 2 "s_register_operand" "r,r")))
e2348bcb 2688 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 2689 "TARGET_32BIT"
e2348bcb 2690 "@
97499065 2691 bic%?\\t%Q0, %Q1, %2
f6ebffac 2692 #"
a0f94409 2693 ; (not (zero_extend ...)) allows us to just copy the high word from
2694 ; operand1 to operand0.
25f905c2 2695 "TARGET_32BIT
a0f94409 2696 && reload_completed
2697 && operands[0] != operands[1]"
5a097f7d 2698 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
a0f94409 2699 (set (match_dup 3) (match_dup 4))]
2700 "
2701 {
2702 operands[3] = gen_highpart (SImode, operands[0]);
2703 operands[0] = gen_lowpart (SImode, operands[0]);
2704 operands[4] = gen_highpart (SImode, operands[1]);
2705 operands[1] = gen_lowpart (SImode, operands[1]);
2706 }"
0d66636f 2707 [(set_attr "length" "4,8")
d952d547 2708 (set_attr "predicable" "yes")
1b7da4ac 2709 (set_attr "predicable_short_it" "no")
2710 (set_attr "type" "multiple")]
0d66636f 2711)
d952d547 2712
d8cd5fa0 2713(define_insn_and_split "*anddi_notdi_zesidi"
2714 [(set (match_operand:DI 0 "s_register_operand" "=r")
2715 (and:DI (not:DI (match_operand:DI 2 "s_register_operand" "r"))
2716 (zero_extend:DI
2717 (match_operand:SI 1 "s_register_operand" "r"))))]
2718 "TARGET_32BIT"
2719 "#"
2720 "TARGET_32BIT && reload_completed"
2721 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2722 (set (match_dup 3) (const_int 0))]
2723 "
2724 {
2725 operands[3] = gen_highpart (SImode, operands[0]);
2726 operands[0] = gen_lowpart (SImode, operands[0]);
2727 operands[2] = gen_lowpart (SImode, operands[2]);
2728 }"
2729 [(set_attr "length" "8")
2730 (set_attr "predicable" "yes")
2731 (set_attr "predicable_short_it" "no")
2732 (set_attr "type" "multiple")]
2733)
2734
a0f94409 2735(define_insn_and_split "*anddi_notsesidi_di"
9c08d1fa 2736 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2737 (and:DI (not:DI (sign_extend:DI
2738 (match_operand:SI 2 "s_register_operand" "r,r")))
5a097f7d 2739 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2740 "TARGET_32BIT"
f6ebffac 2741 "#"
25f905c2 2742 "TARGET_32BIT && reload_completed"
5a097f7d 2743 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
a0f94409 2744 (set (match_dup 3) (and:SI (not:SI
2745 (ashiftrt:SI (match_dup 2) (const_int 31)))
2746 (match_dup 4)))]
2747 "
2748 {
2749 operands[3] = gen_highpart (SImode, operands[0]);
2750 operands[0] = gen_lowpart (SImode, operands[0]);
2751 operands[4] = gen_highpart (SImode, operands[1]);
2752 operands[1] = gen_lowpart (SImode, operands[1]);
2753 }"
0d66636f 2754 [(set_attr "length" "8")
d952d547 2755 (set_attr "predicable" "yes")
1b7da4ac 2756 (set_attr "predicable_short_it" "no")
2757 (set_attr "type" "multiple")]
0d66636f 2758)
d952d547 2759
8a18b90c 2760(define_insn "andsi_notsi_si"
9c08d1fa 2761 [(set (match_operand:SI 0 "s_register_operand" "=r")
2762 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2763 (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 2764 "TARGET_32BIT"
0d66636f 2765 "bic%?\\t%0, %1, %2"
d952d547 2766 [(set_attr "predicable" "yes")
1b7da4ac 2767 (set_attr "predicable_short_it" "no")
2768 (set_attr "type" "logic_reg")]
0d66636f 2769)
b11cae9e 2770
8a18b90c 2771(define_insn "andsi_not_shiftsi_si"
a2cd141b 2772 [(set (match_operand:SI 0 "s_register_operand" "=r")
2773 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2774 [(match_operand:SI 2 "s_register_operand" "r")
2775 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2776 (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 2777 "TARGET_ARM"
6c4c2133 2778 "bic%?\\t%0, %1, %2%S4"
344495ea 2779 [(set_attr "predicable" "yes")
331beb1a 2780 (set_attr "shift" "2")
a2cd141b 2781 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
d82e788e 2782 (const_string "logic_shift_imm")
2783 (const_string "logic_shift_reg")))]
6c4c2133 2784)
8a18b90c 2785
9ed784d8 2786;; Shifted bics pattern used to set up CC status register and not reusing
2787;; bics output. Pattern restricts Thumb2 shift operand as bics for Thumb2
2788;; does not support shift by register.
2789(define_insn "andsi_not_shiftsi_si_scc_no_reuse"
2790 [(set (reg:CC_NOOV CC_REGNUM)
2791 (compare:CC_NOOV
2792 (and:SI (not:SI (match_operator:SI 0 "shift_operator"
2793 [(match_operand:SI 1 "s_register_operand" "r")
2794 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2795 (match_operand:SI 3 "s_register_operand" "r"))
2796 (const_int 0)))
2797 (clobber (match_scratch:SI 4 "=r"))]
2798 "TARGET_ARM || (TARGET_THUMB2 && CONST_INT_P (operands[2]))"
2799 "bic%.%?\\t%4, %3, %1%S0"
2800 [(set_attr "predicable" "yes")
2801 (set_attr "predicable_short_it" "no")
2802 (set_attr "conds" "set")
2803 (set_attr "shift" "1")
2804 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2805 (const_string "logic_shift_imm")
2806 (const_string "logic_shift_reg")))]
2807)
2808
2809;; Same as andsi_not_shiftsi_si_scc_no_reuse, but the bics result is also
2810;; getting reused later.
2811(define_insn "andsi_not_shiftsi_si_scc"
2812 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2813 (compare:CC_NOOV
2814 (and:SI (not:SI (match_operator:SI 0 "shift_operator"
2815 [(match_operand:SI 1 "s_register_operand" "r")
2816 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2817 (match_operand:SI 3 "s_register_operand" "r"))
2818 (const_int 0)))
2819 (set (match_operand:SI 4 "s_register_operand" "=r")
2820 (and:SI (not:SI (match_op_dup 0
2821 [(match_dup 1)
2822 (match_dup 2)]))
2823 (match_dup 3)))])]
2824 "TARGET_ARM || (TARGET_THUMB2 && CONST_INT_P (operands[2]))"
2825 "bic%.%?\\t%4, %3, %1%S0"
2826 [(set_attr "predicable" "yes")
2827 (set_attr "predicable_short_it" "no")
2828 (set_attr "conds" "set")
2829 (set_attr "shift" "1")
2830 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2831 (const_string "logic_shift_imm")
2832 (const_string "logic_shift_reg")))]
2833)
2834
f7fbdd4a 2835(define_insn "*andsi_notsi_si_compare0"
bd5b4116 2836 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 2837 (compare:CC_NOOV
2838 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2839 (match_operand:SI 1 "s_register_operand" "r"))
2840 (const_int 0)))
9c08d1fa 2841 (set (match_operand:SI 0 "s_register_operand" "=r")
2842 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
25f905c2 2843 "TARGET_32BIT"
2844 "bic%.\\t%0, %1, %2"
d82e788e 2845 [(set_attr "conds" "set")
2846 (set_attr "type" "logics_shift_reg")]
0d66636f 2847)
9c08d1fa 2848
f7fbdd4a 2849(define_insn "*andsi_notsi_si_compare0_scratch"
bd5b4116 2850 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 2851 (compare:CC_NOOV
2852 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2853 (match_operand:SI 1 "s_register_operand" "r"))
2854 (const_int 0)))
9c08d1fa 2855 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 2856 "TARGET_32BIT"
2857 "bic%.\\t%0, %1, %2"
d82e788e 2858 [(set_attr "conds" "set")
2859 (set_attr "type" "logics_shift_reg")]
0d66636f 2860)
9c08d1fa 2861
e2669ea7 2862(define_expand "iordi3"
2863 [(set (match_operand:DI 0 "s_register_operand" "")
2864 (ior:DI (match_operand:DI 1 "s_register_operand" "")
2865 (match_operand:DI 2 "neon_logic_op2" "")))]
2866 "TARGET_32BIT"
2867 ""
2868)
2869
74d6113f 2870(define_insn_and_split "*iordi3_insn"
2871 [(set (match_operand:DI 0 "s_register_operand" "=w,w ,&r,&r,&r,&r,?w,?w")
2872 (ior:DI (match_operand:DI 1 "s_register_operand" "%w,0 ,0 ,r ,0 ,r ,w ,0")
e0fe6977 2873 (match_operand:DI 2 "arm_iordi_operand_neon" "w ,Dl,r ,r ,Df,Df,w ,Dl")))]
74d6113f 2874 "TARGET_32BIT && !TARGET_IWMMXT"
2875 {
2876 switch (which_alternative)
2877 {
2878 case 0: /* fall through */
2879 case 6: return "vorr\t%P0, %P1, %P2";
2880 case 1: /* fall through */
2881 case 7: return neon_output_logic_immediate ("vorr", &operands[2],
2882 DImode, 0, VALID_NEON_QREG_MODE (DImode));
2883 case 2:
2884 case 3:
2885 case 4:
2886 case 5:
2887 return "#";
2888 default: gcc_unreachable ();
2889 }
2890 }
2891 "TARGET_32BIT && !TARGET_IWMMXT && reload_completed
2892 && !(IS_VFP_REGNUM (REGNO (operands[0])))"
2893 [(set (match_dup 3) (match_dup 4))
2894 (set (match_dup 5) (match_dup 6))]
2895 "
2896 {
2897 operands[3] = gen_lowpart (SImode, operands[0]);
2898 operands[5] = gen_highpart (SImode, operands[0]);
2899
2900 operands[4] = simplify_gen_binary (IOR, SImode,
2901 gen_lowpart (SImode, operands[1]),
2902 gen_lowpart (SImode, operands[2]));
2903 operands[6] = simplify_gen_binary (IOR, SImode,
2904 gen_highpart (SImode, operands[1]),
2905 gen_highpart_mode (SImode, DImode, operands[2]));
2906
2907 }"
32093010 2908 [(set_attr "type" "neon_logic,neon_logic,multiple,multiple,multiple,\
2909 multiple,neon_logic,neon_logic")
e0fe6977 2910 (set_attr "length" "*,*,8,8,8,8,*,*")
74d6113f 2911 (set_attr "arch" "neon_for_64bits,neon_for_64bits,*,*,*,*,avoid_neon_for_64bits,avoid_neon_for_64bits")]
cffb2a26 2912)
9c08d1fa 2913
f7fbdd4a 2914(define_insn "*iordi_zesidi_di"
9c08d1fa 2915 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2916 (ior:DI (zero_extend:DI
2917 (match_operand:SI 2 "s_register_operand" "r,r"))
e2348bcb 2918 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 2919 "TARGET_32BIT"
e2348bcb 2920 "@
97499065 2921 orr%?\\t%Q0, %Q1, %2
f6ebffac 2922 #"
0d66636f 2923 [(set_attr "length" "4,8")
d952d547 2924 (set_attr "predicable" "yes")
1b7da4ac 2925 (set_attr "predicable_short_it" "no")
2926 (set_attr "type" "logic_reg,multiple")]
cffb2a26 2927)
9c08d1fa 2928
f7fbdd4a 2929(define_insn "*iordi_sesidi_di"
9c08d1fa 2930 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2931 (ior:DI (sign_extend:DI
2932 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 2933 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2934 "TARGET_32BIT"
f6ebffac 2935 "#"
0d66636f 2936 [(set_attr "length" "8")
1b7da4ac 2937 (set_attr "predicable" "yes")
2938 (set_attr "type" "multiple")]
cffb2a26 2939)
9c08d1fa 2940
87b22bf7 2941(define_expand "iorsi3"
cffb2a26 2942 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2943 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2944 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 2945 "TARGET_EITHER"
87b22bf7 2946 "
0438d37f 2947 if (CONST_INT_P (operands[2]))
87b22bf7 2948 {
25f905c2 2949 if (TARGET_32BIT)
cffb2a26 2950 {
17202aa5 2951 if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[2]), IOR))
2952 operands[2] = force_reg (SImode, operands[2]);
2953 else
2954 {
2955 arm_split_constant (IOR, SImode, NULL_RTX,
2956 INTVAL (operands[2]), operands[0],
2957 operands[1],
2958 optimize && can_create_pseudo_p ());
2959 DONE;
2960 }
cffb2a26 2961 }
25f905c2 2962 else /* TARGET_THUMB1 */
923ffadb 2963 {
2964 rtx tmp = force_reg (SImode, operands[2]);
2965 if (rtx_equal_p (operands[0], operands[1]))
2966 operands[2] = tmp;
2967 else
2968 {
2969 operands[2] = operands[1];
2970 operands[1] = tmp;
2971 }
2972 }
87b22bf7 2973 }
cffb2a26 2974 "
2975)
87b22bf7 2976
d5d4dc8d 2977(define_insn_and_split "*iorsi3_insn"
29e234a3 2978 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r,r,r")
2979 (ior:SI (match_operand:SI 1 "s_register_operand" "%r,0,r,r,r")
2980 (match_operand:SI 2 "reg_or_int_operand" "I,l,K,r,?n")))]
d5d4dc8d 2981 "TARGET_32BIT"
87b22bf7 2982 "@
29e234a3 2983 orr%?\\t%0, %1, %2
87b22bf7 2984 orr%?\\t%0, %1, %2
d5d4dc8d 2985 orn%?\\t%0, %1, #%B2
65f68e55 2986 orr%?\\t%0, %1, %2
87b22bf7 2987 #"
d5d4dc8d 2988 "TARGET_32BIT
0438d37f 2989 && CONST_INT_P (operands[2])
d5d4dc8d 2990 && !(const_ok_for_arm (INTVAL (operands[2]))
2991 || (TARGET_THUMB2 && const_ok_for_arm (~INTVAL (operands[2]))))"
a0f94409 2992 [(clobber (const_int 0))]
d5d4dc8d 2993{
29e234a3 2994 arm_split_constant (IOR, SImode, curr_insn,
96f57e36 2995 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 2996 DONE;
d5d4dc8d 2997}
29e234a3 2998 [(set_attr "length" "4,4,4,4,16")
2999 (set_attr "arch" "32,t2,t2,32,32")
65f68e55 3000 (set_attr "predicable" "yes")
29e234a3 3001 (set_attr "predicable_short_it" "no,yes,no,no,no")
d82e788e 3002 (set_attr "type" "logic_imm,logic_reg,logic_imm,logic_reg,logic_reg")]
65f68e55 3003)
cffb2a26 3004
a0f94409 3005(define_peephole2
3006 [(match_scratch:SI 3 "r")
372575c7 3007 (set (match_operand:SI 0 "arm_general_register_operand" "")
3008 (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
87b22bf7 3009 (match_operand:SI 2 "const_int_operand" "")))]
90560cad 3010 "TARGET_ARM
a0f94409 3011 && !const_ok_for_arm (INTVAL (operands[2]))
3012 && const_ok_for_arm (~INTVAL (operands[2]))"
3013 [(set (match_dup 3) (match_dup 2))
3014 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
3015 ""
215b30b3 3016)
a0f94409 3017
f7fbdd4a 3018(define_insn "*iorsi3_compare0"
bd5b4116 3019 [(set (reg:CC_NOOV CC_REGNUM)
65f68e55 3020 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r,r")
3021 (match_operand:SI 2 "arm_rhs_operand" "I,r"))
9c08d1fa 3022 (const_int 0)))
65f68e55 3023 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 3024 (ior:SI (match_dup 1) (match_dup 2)))]
25f905c2 3025 "TARGET_32BIT"
3026 "orr%.\\t%0, %1, %2"
65f68e55 3027 [(set_attr "conds" "set")
d82e788e 3028 (set_attr "type" "logics_imm,logics_reg")]
cffb2a26 3029)
9c08d1fa 3030
f7fbdd4a 3031(define_insn "*iorsi3_compare0_scratch"
bd5b4116 3032 [(set (reg:CC_NOOV CC_REGNUM)
65f68e55 3033 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r,r")
3034 (match_operand:SI 2 "arm_rhs_operand" "I,r"))
9c08d1fa 3035 (const_int 0)))
65f68e55 3036 (clobber (match_scratch:SI 0 "=r,r"))]
25f905c2 3037 "TARGET_32BIT"
3038 "orr%.\\t%0, %1, %2"
65f68e55 3039 [(set_attr "conds" "set")
d82e788e 3040 (set_attr "type" "logics_imm,logics_reg")]
0d66636f 3041)
9c08d1fa 3042
e2669ea7 3043(define_expand "xordi3"
3044 [(set (match_operand:DI 0 "s_register_operand" "")
3045 (xor:DI (match_operand:DI 1 "s_register_operand" "")
8ee7dc6f 3046 (match_operand:DI 2 "arm_xordi_operand" "")))]
e2669ea7 3047 "TARGET_32BIT"
3048 ""
3049)
3050
8ee7dc6f 3051(define_insn_and_split "*xordi3_insn"
3052 [(set (match_operand:DI 0 "s_register_operand" "=w,&r,&r,&r,&r,?w")
205c3b0a 3053 (xor:DI (match_operand:DI 1 "s_register_operand" "%w ,0,r ,0 ,r ,w")
8ee7dc6f 3054 (match_operand:DI 2 "arm_xordi_operand" "w ,r ,r ,Dg,Dg,w")))]
3055 "TARGET_32BIT && !TARGET_IWMMXT"
3056{
3057 switch (which_alternative)
3058 {
3059 case 1:
3060 case 2:
3061 case 3:
3062 case 4: /* fall through */
3063 return "#";
3064 case 0: /* fall through */
3065 case 5: return "veor\t%P0, %P1, %P2";
3066 default: gcc_unreachable ();
3067 }
3068}
3069 "TARGET_32BIT && !TARGET_IWMMXT && reload_completed
3070 && !(IS_VFP_REGNUM (REGNO (operands[0])))"
3071 [(set (match_dup 3) (match_dup 4))
3072 (set (match_dup 5) (match_dup 6))]
3073 "
3074 {
3075 operands[3] = gen_lowpart (SImode, operands[0]);
3076 operands[5] = gen_highpart (SImode, operands[0]);
3077
3078 operands[4] = simplify_gen_binary (XOR, SImode,
3079 gen_lowpart (SImode, operands[1]),
3080 gen_lowpart (SImode, operands[2]));
3081 operands[6] = simplify_gen_binary (XOR, SImode,
3082 gen_highpart (SImode, operands[1]),
3083 gen_highpart_mode (SImode, DImode, operands[2]));
3084
3085 }"
3086 [(set_attr "length" "*,8,8,8,8,*")
32093010 3087 (set_attr "type" "neon_logic,multiple,multiple,multiple,multiple,neon_logic")
8ee7dc6f 3088 (set_attr "arch" "neon_for_64bits,*,*,*,*,avoid_neon_for_64bits")]
cffb2a26 3089)
9c08d1fa 3090
f7fbdd4a 3091(define_insn "*xordi_zesidi_di"
9c08d1fa 3092 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3093 (xor:DI (zero_extend:DI
3094 (match_operand:SI 2 "s_register_operand" "r,r"))
e2348bcb 3095 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 3096 "TARGET_32BIT"
e2348bcb 3097 "@
97499065 3098 eor%?\\t%Q0, %Q1, %2
f6ebffac 3099 #"
0d66636f 3100 [(set_attr "length" "4,8")
d952d547 3101 (set_attr "predicable" "yes")
1b7da4ac 3102 (set_attr "predicable_short_it" "no")
3103 (set_attr "type" "logic_reg")]
cffb2a26 3104)
9c08d1fa 3105
f7fbdd4a 3106(define_insn "*xordi_sesidi_di"
9c08d1fa 3107 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3108 (xor:DI (sign_extend:DI
3109 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 3110 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 3111 "TARGET_32BIT"
f6ebffac 3112 "#"
0d66636f 3113 [(set_attr "length" "8")
1b7da4ac 3114 (set_attr "predicable" "yes")
3115 (set_attr "type" "multiple")]
cffb2a26 3116)
9c08d1fa 3117
cffb2a26 3118(define_expand "xorsi3"
3119 [(set (match_operand:SI 0 "s_register_operand" "")
3120 (xor:SI (match_operand:SI 1 "s_register_operand" "")
923ffadb 3121 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 3122 "TARGET_EITHER"
0438d37f 3123 "if (CONST_INT_P (operands[2]))
923ffadb 3124 {
3125 if (TARGET_32BIT)
3126 {
17202aa5 3127 if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[2]), XOR))
3128 operands[2] = force_reg (SImode, operands[2]);
3129 else
3130 {
3131 arm_split_constant (XOR, SImode, NULL_RTX,
3132 INTVAL (operands[2]), operands[0],
3133 operands[1],
3134 optimize && can_create_pseudo_p ());
3135 DONE;
3136 }
923ffadb 3137 }
3138 else /* TARGET_THUMB1 */
3139 {
3140 rtx tmp = force_reg (SImode, operands[2]);
3141 if (rtx_equal_p (operands[0], operands[1]))
3142 operands[2] = tmp;
3143 else
3144 {
3145 operands[2] = operands[1];
3146 operands[1] = tmp;
3147 }
3148 }
3149 }"
cffb2a26 3150)
3151
5dcb35d9 3152(define_insn_and_split "*arm_xorsi3"
29e234a3 3153 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r,r")
3154 (xor:SI (match_operand:SI 1 "s_register_operand" "%r,0,r,r")
3155 (match_operand:SI 2 "reg_or_int_operand" "I,l,r,?n")))]
25f905c2 3156 "TARGET_32BIT"
5dcb35d9 3157 "@
29e234a3 3158 eor%?\\t%0, %1, %2
65f68e55 3159 eor%?\\t%0, %1, %2
5dcb35d9 3160 eor%?\\t%0, %1, %2
3161 #"
3162 "TARGET_32BIT
0438d37f 3163 && CONST_INT_P (operands[2])
5dcb35d9 3164 && !const_ok_for_arm (INTVAL (operands[2]))"
3165 [(clobber (const_int 0))]
3166{
3167 arm_split_constant (XOR, SImode, curr_insn,
3168 INTVAL (operands[2]), operands[0], operands[1], 0);
3169 DONE;
3170}
29e234a3 3171 [(set_attr "length" "4,4,4,16")
65f68e55 3172 (set_attr "predicable" "yes")
29e234a3 3173 (set_attr "predicable_short_it" "no,yes,no,no")
1b7da4ac 3174 (set_attr "type" "logic_imm,logic_reg,logic_reg,multiple")]
cffb2a26 3175)
3176
f7fbdd4a 3177(define_insn "*xorsi3_compare0"
bd5b4116 3178 [(set (reg:CC_NOOV CC_REGNUM)
65f68e55 3179 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r,r")
3180 (match_operand:SI 2 "arm_rhs_operand" "I,r"))
9c08d1fa 3181 (const_int 0)))
65f68e55 3182 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 3183 (xor:SI (match_dup 1) (match_dup 2)))]
25f905c2 3184 "TARGET_32BIT"
3185 "eor%.\\t%0, %1, %2"
65f68e55 3186 [(set_attr "conds" "set")
d82e788e 3187 (set_attr "type" "logics_imm,logics_reg")]
0d66636f 3188)
9c08d1fa 3189
f7fbdd4a 3190(define_insn "*xorsi3_compare0_scratch"
bd5b4116 3191 [(set (reg:CC_NOOV CC_REGNUM)
65f68e55 3192 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r,r")
3193 (match_operand:SI 1 "arm_rhs_operand" "I,r"))
9c08d1fa 3194 (const_int 0)))]
25f905c2 3195 "TARGET_32BIT"
40dbec34 3196 "teq%?\\t%0, %1"
65f68e55 3197 [(set_attr "conds" "set")
d82e788e 3198 (set_attr "type" "logics_imm,logics_reg")]
cffb2a26 3199)
9c08d1fa 3200
215b30b3 3201; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
3202; (NOT D) we can sometimes merge the final NOT into one of the following
3203; insns.
9c08d1fa 3204
3205(define_split
a058e94a 3206 [(set (match_operand:SI 0 "s_register_operand" "")
3207 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
3208 (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
3209 (match_operand:SI 3 "arm_rhs_operand" "")))
3210 (clobber (match_operand:SI 4 "s_register_operand" ""))]
25f905c2 3211 "TARGET_32BIT"
9c08d1fa 3212 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
3213 (not:SI (match_dup 3))))
3214 (set (match_dup 0) (not:SI (match_dup 4)))]
3215 ""
3216)
3217
ba6a3b2f 3218(define_insn_and_split "*andsi_iorsi3_notsi"
9c08d1fa 3219 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
e5fea38e 3220 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "%0,r,r")
9c08d1fa 3221 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
3222 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
25f905c2 3223 "TARGET_32BIT"
ba6a3b2f 3224 "#" ; "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
3225 "&& reload_completed"
3226 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
3227 (set (match_dup 0) (and:SI (not:SI (match_dup 3)) (match_dup 0)))]
3228 ""
0d66636f 3229 [(set_attr "length" "8")
25f905c2 3230 (set_attr "ce_count" "2")
d952d547 3231 (set_attr "predicable" "yes")
1b7da4ac 3232 (set_attr "predicable_short_it" "no")
3233 (set_attr "type" "multiple")]
cffb2a26 3234)
9c08d1fa 3235
25f905c2 3236; ??? Are these four splitters still beneficial when the Thumb-2 bitfield
3237; insns are available?
d7863cfe 3238(define_split
3239 [(set (match_operand:SI 0 "s_register_operand" "")
3240 (match_operator:SI 1 "logical_binary_operator"
3241 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
3242 (match_operand:SI 3 "const_int_operand" "")
3243 (match_operand:SI 4 "const_int_operand" ""))
3244 (match_operator:SI 9 "logical_binary_operator"
3245 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3246 (match_operand:SI 6 "const_int_operand" ""))
3247 (match_operand:SI 7 "s_register_operand" "")])]))
3248 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3249 "TARGET_32BIT
d7863cfe 3250 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3251 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3252 [(set (match_dup 8)
3253 (match_op_dup 1
3254 [(ashift:SI (match_dup 2) (match_dup 4))
3255 (match_dup 5)]))
3256 (set (match_dup 0)
3257 (match_op_dup 1
3258 [(lshiftrt:SI (match_dup 8) (match_dup 6))
3259 (match_dup 7)]))]
3260 "
3261 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3262")
3263
3264(define_split
3265 [(set (match_operand:SI 0 "s_register_operand" "")
3266 (match_operator:SI 1 "logical_binary_operator"
3267 [(match_operator:SI 9 "logical_binary_operator"
3268 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3269 (match_operand:SI 6 "const_int_operand" ""))
3270 (match_operand:SI 7 "s_register_operand" "")])
3271 (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
3272 (match_operand:SI 3 "const_int_operand" "")
3273 (match_operand:SI 4 "const_int_operand" ""))]))
3274 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3275 "TARGET_32BIT
d7863cfe 3276 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3277 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3278 [(set (match_dup 8)
3279 (match_op_dup 1
3280 [(ashift:SI (match_dup 2) (match_dup 4))
3281 (match_dup 5)]))
3282 (set (match_dup 0)
3283 (match_op_dup 1
3284 [(lshiftrt:SI (match_dup 8) (match_dup 6))
3285 (match_dup 7)]))]
3286 "
3287 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3288")
3289
3290(define_split
3291 [(set (match_operand:SI 0 "s_register_operand" "")
3292 (match_operator:SI 1 "logical_binary_operator"
3293 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
3294 (match_operand:SI 3 "const_int_operand" "")
3295 (match_operand:SI 4 "const_int_operand" ""))
3296 (match_operator:SI 9 "logical_binary_operator"
3297 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3298 (match_operand:SI 6 "const_int_operand" ""))
3299 (match_operand:SI 7 "s_register_operand" "")])]))
3300 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3301 "TARGET_32BIT
d7863cfe 3302 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3303 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3304 [(set (match_dup 8)
3305 (match_op_dup 1
3306 [(ashift:SI (match_dup 2) (match_dup 4))
3307 (match_dup 5)]))
3308 (set (match_dup 0)
3309 (match_op_dup 1
3310 [(ashiftrt:SI (match_dup 8) (match_dup 6))
3311 (match_dup 7)]))]
3312 "
3313 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3314")
3315
3316(define_split
3317 [(set (match_operand:SI 0 "s_register_operand" "")
3318 (match_operator:SI 1 "logical_binary_operator"
3319 [(match_operator:SI 9 "logical_binary_operator"
3320 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3321 (match_operand:SI 6 "const_int_operand" ""))
3322 (match_operand:SI 7 "s_register_operand" "")])
3323 (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
3324 (match_operand:SI 3 "const_int_operand" "")
3325 (match_operand:SI 4 "const_int_operand" ""))]))
3326 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3327 "TARGET_32BIT
d7863cfe 3328 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3329 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3330 [(set (match_dup 8)
3331 (match_op_dup 1
3332 [(ashift:SI (match_dup 2) (match_dup 4))
3333 (match_dup 5)]))
3334 (set (match_dup 0)
3335 (match_op_dup 1
3336 [(ashiftrt:SI (match_dup 8) (match_dup 6))
3337 (match_dup 7)]))]
3338 "
3339 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3340")
9c08d1fa 3341\f
3342
3343;; Minimum and maximum insns
3344
8b9dc177 3345(define_expand "smaxsi3"
3346 [(parallel [
3347 (set (match_operand:SI 0 "s_register_operand" "")
3348 (smax:SI (match_operand:SI 1 "s_register_operand" "")
3349 (match_operand:SI 2 "arm_rhs_operand" "")))
3350 (clobber (reg:CC CC_REGNUM))])]
25f905c2 3351 "TARGET_32BIT"
8b9dc177 3352 "
8774928b 3353 if (operands[2] == const0_rtx || operands[2] == constm1_rtx)
8b9dc177 3354 {
3355 /* No need for a clobber of the condition code register here. */
d1f9b275 3356 emit_insn (gen_rtx_SET (operands[0],
8b9dc177 3357 gen_rtx_SMAX (SImode, operands[1],
3358 operands[2])));
3359 DONE;
3360 }
3361")
3362
3363(define_insn "*smax_0"
3364 [(set (match_operand:SI 0 "s_register_operand" "=r")
3365 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3366 (const_int 0)))]
25f905c2 3367 "TARGET_32BIT"
8b9dc177 3368 "bic%?\\t%0, %1, %1, asr #31"
d952d547 3369 [(set_attr "predicable" "yes")
1b7da4ac 3370 (set_attr "predicable_short_it" "no")
3371 (set_attr "type" "logic_shift_reg")]
8b9dc177 3372)
3373
8774928b 3374(define_insn "*smax_m1"
3375 [(set (match_operand:SI 0 "s_register_operand" "=r")
3376 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3377 (const_int -1)))]
25f905c2 3378 "TARGET_32BIT"
8774928b 3379 "orr%?\\t%0, %1, %1, asr #31"
d952d547 3380 [(set_attr "predicable" "yes")
1b7da4ac 3381 (set_attr "predicable_short_it" "no")
3382 (set_attr "type" "logic_shift_reg")]
8774928b 3383)
3384
3dc953f2 3385(define_insn_and_split "*arm_smax_insn"
8b9dc177 3386 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3387 (smax:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3388 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
bd5b4116 3389 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3390 "TARGET_ARM"
3dc953f2 3391 "#"
3392 ; cmp\\t%1, %2\;movlt\\t%0, %2
3393 ; cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
3394 "TARGET_ARM"
3395 [(set (reg:CC CC_REGNUM)
3396 (compare:CC (match_dup 1) (match_dup 2)))
3397 (set (match_dup 0)
3398 (if_then_else:SI (ge:SI (reg:CC CC_REGNUM) (const_int 0))
3399 (match_dup 1)
3400 (match_dup 2)))]
3401 ""
cffb2a26 3402 [(set_attr "conds" "clob")
1b7da4ac 3403 (set_attr "length" "8,12")
3404 (set_attr "type" "multiple")]
cffb2a26 3405)
9c08d1fa 3406
8b9dc177 3407(define_expand "sminsi3"
3408 [(parallel [
3409 (set (match_operand:SI 0 "s_register_operand" "")
3410 (smin:SI (match_operand:SI 1 "s_register_operand" "")
3411 (match_operand:SI 2 "arm_rhs_operand" "")))
3412 (clobber (reg:CC CC_REGNUM))])]
25f905c2 3413 "TARGET_32BIT"
8b9dc177 3414 "
3415 if (operands[2] == const0_rtx)
3416 {
3417 /* No need for a clobber of the condition code register here. */
d1f9b275 3418 emit_insn (gen_rtx_SET (operands[0],
8b9dc177 3419 gen_rtx_SMIN (SImode, operands[1],
3420 operands[2])));
3421 DONE;
3422 }
3423")
3424
3425(define_insn "*smin_0"
3426 [(set (match_operand:SI 0 "s_register_operand" "=r")
3427 (smin:SI (match_operand:SI 1 "s_register_operand" "r")
3428 (const_int 0)))]
25f905c2 3429 "TARGET_32BIT"
8b9dc177 3430 "and%?\\t%0, %1, %1, asr #31"
d952d547 3431 [(set_attr "predicable" "yes")
1b7da4ac 3432 (set_attr "predicable_short_it" "no")
3433 (set_attr "type" "logic_shift_reg")]
8b9dc177 3434)
3435
3dc953f2 3436(define_insn_and_split "*arm_smin_insn"
8b9dc177 3437 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3438 (smin:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3439 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
bd5b4116 3440 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3441 "TARGET_ARM"
3dc953f2 3442 "#"
3443 ; cmp\\t%1, %2\;movge\\t%0, %2
3444 ; cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
3445 "TARGET_ARM"
3446 [(set (reg:CC CC_REGNUM)
3447 (compare:CC (match_dup 1) (match_dup 2)))
3448 (set (match_dup 0)
3449 (if_then_else:SI (lt:SI (reg:CC CC_REGNUM) (const_int 0))
3450 (match_dup 1)
3451 (match_dup 2)))]
3452 ""
0d66636f 3453 [(set_attr "conds" "clob")
1b7da4ac 3454 (set_attr "length" "8,12")
3455 (set_attr "type" "multiple,multiple")]
0d66636f 3456)
9c08d1fa 3457
25f905c2 3458(define_expand "umaxsi3"
3459 [(parallel [
3460 (set (match_operand:SI 0 "s_register_operand" "")
3461 (umax:SI (match_operand:SI 1 "s_register_operand" "")
3462 (match_operand:SI 2 "arm_rhs_operand" "")))
3463 (clobber (reg:CC CC_REGNUM))])]
3464 "TARGET_32BIT"
3465 ""
3466)
3467
3dc953f2 3468(define_insn_and_split "*arm_umaxsi3"
9c08d1fa 3469 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3470 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3471 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 3472 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3473 "TARGET_ARM"
3dc953f2 3474 "#"
3475 ; cmp\\t%1, %2\;movcc\\t%0, %2
3476 ; cmp\\t%1, %2\;movcs\\t%0, %1
3477 ; cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
3478 "TARGET_ARM"
3479 [(set (reg:CC CC_REGNUM)
3480 (compare:CC (match_dup 1) (match_dup 2)))
3481 (set (match_dup 0)
3482 (if_then_else:SI (geu:SI (reg:CC CC_REGNUM) (const_int 0))
3483 (match_dup 1)
3484 (match_dup 2)))]
3485 ""
0d66636f 3486 [(set_attr "conds" "clob")
1b7da4ac 3487 (set_attr "length" "8,8,12")
3488 (set_attr "type" "store1")]
0d66636f 3489)
9c08d1fa 3490
25f905c2 3491(define_expand "uminsi3"
3492 [(parallel [
3493 (set (match_operand:SI 0 "s_register_operand" "")
3494 (umin:SI (match_operand:SI 1 "s_register_operand" "")
3495 (match_operand:SI 2 "arm_rhs_operand" "")))
3496 (clobber (reg:CC CC_REGNUM))])]
3497 "TARGET_32BIT"
3498 ""
3499)
3500
3dc953f2 3501(define_insn_and_split "*arm_uminsi3"
9c08d1fa 3502 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3503 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3504 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 3505 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3506 "TARGET_ARM"
3dc953f2 3507 "#"
3508 ; cmp\\t%1, %2\;movcs\\t%0, %2
3509 ; cmp\\t%1, %2\;movcc\\t%0, %1
3510 ; cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
3511 "TARGET_ARM"
3512 [(set (reg:CC CC_REGNUM)
3513 (compare:CC (match_dup 1) (match_dup 2)))
3514 (set (match_dup 0)
3515 (if_then_else:SI (ltu:SI (reg:CC CC_REGNUM) (const_int 0))
3516 (match_dup 1)
3517 (match_dup 2)))]
3518 ""
0d66636f 3519 [(set_attr "conds" "clob")
1b7da4ac 3520 (set_attr "length" "8,8,12")
3521 (set_attr "type" "store1")]
0d66636f 3522)
9c08d1fa 3523
8a18b90c 3524(define_insn "*store_minmaxsi"
9c08d1fa 3525 [(set (match_operand:SI 0 "memory_operand" "=m")
3526 (match_operator:SI 3 "minmax_operator"
3527 [(match_operand:SI 1 "s_register_operand" "r")
3528 (match_operand:SI 2 "s_register_operand" "r")]))
bd5b4116 3529 (clobber (reg:CC CC_REGNUM))]
b207d152 3530 "TARGET_32BIT && optimize_function_for_size_p (cfun) && !arm_restrict_it"
9c08d1fa 3531 "*
dc55b8a9 3532 operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
3533 operands[1], operands[2]);
e2348bcb 3534 output_asm_insn (\"cmp\\t%1, %2\", operands);
25f905c2 3535 if (TARGET_THUMB2)
3536 output_asm_insn (\"ite\t%d3\", operands);
e2348bcb 3537 output_asm_insn (\"str%d3\\t%1, %0\", operands);
3538 output_asm_insn (\"str%D3\\t%2, %0\", operands);
3539 return \"\";
0d66636f 3540 "
3541 [(set_attr "conds" "clob")
25f905c2 3542 (set (attr "length")
3543 (if_then_else (eq_attr "is_thumb" "yes")
3544 (const_int 14)
3545 (const_int 12)))
0d66636f 3546 (set_attr "type" "store1")]
3547)
9c08d1fa 3548
8a18b90c 3549; Reject the frame pointer in operand[1], since reloading this after
3550; it has been eliminated can cause carnage.
f7fbdd4a 3551(define_insn "*minmax_arithsi"
9c08d1fa 3552 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3553 (match_operator:SI 4 "shiftable_operator"
3554 [(match_operator:SI 5 "minmax_operator"
3555 [(match_operand:SI 2 "s_register_operand" "r,r")
3556 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
3557 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 3558 (clobber (reg:CC CC_REGNUM))]
7c36fe71 3559 "TARGET_32BIT && !arm_eliminable_register (operands[1]) && !arm_restrict_it"
9c08d1fa 3560 "*
0d66636f 3561 {
3562 enum rtx_code code = GET_CODE (operands[4]);
25f905c2 3563 bool need_else;
3564
3565 if (which_alternative != 0 || operands[3] != const0_rtx
ca0fc5a2 3566 || (code != PLUS && code != IOR && code != XOR))
25f905c2 3567 need_else = true;
3568 else
3569 need_else = false;
0d66636f 3570
dc55b8a9 3571 operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
3572 operands[2], operands[3]);
0d66636f 3573 output_asm_insn (\"cmp\\t%2, %3\", operands);
25f905c2 3574 if (TARGET_THUMB2)
3575 {
3576 if (need_else)
3577 output_asm_insn (\"ite\\t%d5\", operands);
3578 else
3579 output_asm_insn (\"it\\t%d5\", operands);
3580 }
0d66636f 3581 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
25f905c2 3582 if (need_else)
0d66636f 3583 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
3584 return \"\";
215b30b3 3585 }"
0d66636f 3586 [(set_attr "conds" "clob")
25f905c2 3587 (set (attr "length")
3588 (if_then_else (eq_attr "is_thumb" "yes")
3589 (const_int 14)
1b7da4ac 3590 (const_int 12)))
3591 (set_attr "type" "multiple")]
0d66636f 3592)
9c08d1fa 3593
4164bca1 3594; Reject the frame pointer in operand[1], since reloading this after
3595; it has been eliminated can cause carnage.
3596(define_insn_and_split "*minmax_arithsi_non_canon"
7c36fe71 3597 [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts")
4164bca1 3598 (minus:SI
7c36fe71 3599 (match_operand:SI 1 "s_register_operand" "0,?Ts")
4164bca1 3600 (match_operator:SI 4 "minmax_operator"
7c36fe71 3601 [(match_operand:SI 2 "s_register_operand" "Ts,Ts")
3602 (match_operand:SI 3 "arm_rhs_operand" "TsI,TsI")])))
4164bca1 3603 (clobber (reg:CC CC_REGNUM))]
7c36fe71 3604 "TARGET_32BIT && !arm_eliminable_register (operands[1])
3605 && !(arm_restrict_it && CONST_INT_P (operands[3]))"
4164bca1 3606 "#"
3607 "TARGET_32BIT && !arm_eliminable_register (operands[1]) && reload_completed"
3608 [(set (reg:CC CC_REGNUM)
3609 (compare:CC (match_dup 2) (match_dup 3)))
3610
3611 (cond_exec (match_op_dup 4 [(reg:CC CC_REGNUM) (const_int 0)])
3612 (set (match_dup 0)
3613 (minus:SI (match_dup 1)
3614 (match_dup 2))))
3615 (cond_exec (match_op_dup 5 [(reg:CC CC_REGNUM) (const_int 0)])
3616 (set (match_dup 0)
36ee0cde 3617 (match_dup 6)))]
4164bca1 3618 {
3754d046 3619 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
4164bca1 3620 operands[2], operands[3]);
3621 enum rtx_code rc = minmax_code (operands[4]);
3622 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode,
3623 operands[2], operands[3]);
3624
3625 if (mode == CCFPmode || mode == CCFPEmode)
3626 rc = reverse_condition_maybe_unordered (rc);
3627 else
3628 rc = reverse_condition (rc);
3629 operands[5] = gen_rtx_fmt_ee (rc, SImode, operands[2], operands[3]);
36ee0cde 3630 if (CONST_INT_P (operands[3]))
3631 operands[6] = plus_constant (SImode, operands[1], -INTVAL (operands[3]));
3632 else
3633 operands[6] = gen_rtx_MINUS (SImode, operands[1], operands[3]);
4164bca1 3634 }
3635 [(set_attr "conds" "clob")
3636 (set (attr "length")
3637 (if_then_else (eq_attr "is_thumb" "yes")
3638 (const_int 14)
1b7da4ac 3639 (const_int 12)))
3640 (set_attr "type" "multiple")]
4164bca1 3641)
3642
b49e3742 3643(define_code_iterator SAT [smin smax])
3644(define_code_iterator SATrev [smin smax])
3645(define_code_attr SATlo [(smin "1") (smax "2")])
3646(define_code_attr SAThi [(smin "2") (smax "1")])
3647
3648(define_insn "*satsi_<SAT:code>"
3649 [(set (match_operand:SI 0 "s_register_operand" "=r")
3650 (SAT:SI (SATrev:SI (match_operand:SI 3 "s_register_operand" "r")
3651 (match_operand:SI 1 "const_int_operand" "i"))
3652 (match_operand:SI 2 "const_int_operand" "i")))]
3653 "TARGET_32BIT && arm_arch6 && <SAT:CODE> != <SATrev:CODE>
3654 && arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>], NULL, NULL)"
3655{
3656 int mask;
3657 bool signed_sat;
3658 if (!arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>],
3659 &mask, &signed_sat))
3660 gcc_unreachable ();
3661
3662 operands[1] = GEN_INT (mask);
3663 if (signed_sat)
3664 return "ssat%?\t%0, %1, %3";
3665 else
3666 return "usat%?\t%0, %1, %3";
3667}
7c36fe71 3668 [(set_attr "predicable" "yes")
1b7da4ac 3669 (set_attr "predicable_short_it" "no")
3670 (set_attr "type" "alus_imm")]
bebe9bbb 3671)
b49e3742 3672
3673(define_insn "*satsi_<SAT:code>_shift"
3674 [(set (match_operand:SI 0 "s_register_operand" "=r")
3675 (SAT:SI (SATrev:SI (match_operator:SI 3 "sat_shift_operator"
3676 [(match_operand:SI 4 "s_register_operand" "r")
3677 (match_operand:SI 5 "const_int_operand" "i")])
3678 (match_operand:SI 1 "const_int_operand" "i"))
3679 (match_operand:SI 2 "const_int_operand" "i")))]
3680 "TARGET_32BIT && arm_arch6 && <SAT:CODE> != <SATrev:CODE>
3681 && arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>], NULL, NULL)"
3682{
3683 int mask;
3684 bool signed_sat;
3685 if (!arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>],
3686 &mask, &signed_sat))
3687 gcc_unreachable ();
3688
3689 operands[1] = GEN_INT (mask);
3690 if (signed_sat)
3691 return "ssat%?\t%0, %1, %4%S3";
3692 else
3693 return "usat%?\t%0, %1, %4%S3";
3694}
3695 [(set_attr "predicable" "yes")
7c36fe71 3696 (set_attr "predicable_short_it" "no")
b49e3742 3697 (set_attr "shift" "3")
d82e788e 3698 (set_attr "type" "logic_shift_reg")])
b11cae9e 3699\f
3700;; Shift and rotation insns
3701
a2cd141b 3702(define_expand "ashldi3"
3703 [(set (match_operand:DI 0 "s_register_operand" "")
3704 (ashift:DI (match_operand:DI 1 "s_register_operand" "")
aa06c51c 3705 (match_operand:SI 2 "general_operand" "")))]
25f905c2 3706 "TARGET_32BIT"
a2cd141b 3707 "
aa06c51c 3708 if (TARGET_NEON)
3709 {
3710 /* Delay the decision whether to use NEON or core-regs until
3711 register allocation. */
3712 emit_insn (gen_ashldi3_neon (operands[0], operands[1], operands[2]));
3713 DONE;
3714 }
3715 else
3716 {
3717 /* Only the NEON case can handle in-memory shift counts. */
3718 if (!reg_or_int_operand (operands[2], SImode))
3719 operands[2] = force_reg (SImode, operands[2]);
3720 }
3721
b805622c 3722 if (!CONST_INT_P (operands[2]) && TARGET_REALLY_IWMMXT)
ffcc986d 3723 ; /* No special preparation statements; expand pattern as above. */
3724 else
a2cd141b 3725 {
ffcc986d 3726 rtx scratch1, scratch2;
3727
3728 if (CONST_INT_P (operands[2])
3729 && (HOST_WIDE_INT) INTVAL (operands[2]) == 1)
a2cd141b 3730 {
3731 emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
3732 DONE;
3733 }
ffcc986d 3734
3735 /* Ideally we should use iwmmxt here if we could know that operands[1]
3736 ends up already living in an iwmmxt register. Otherwise it's
3737 cheaper to have the alternate code being generated than moving
3738 values to iwmmxt regs and back. */
3739
3740 /* If we're optimizing for size, we prefer the libgcc calls. */
3741 if (optimize_function_for_size_p (cfun))
3742 FAIL;
3743
3744 /* Expand operation using core-registers.
3745 'FAIL' would achieve the same thing, but this is a bit smarter. */
3746 scratch1 = gen_reg_rtx (SImode);
3747 scratch2 = gen_reg_rtx (SImode);
3748 arm_emit_coreregs_64bit_shift (ASHIFT, operands[0], operands[1],
3749 operands[2], scratch1, scratch2);
3750 DONE;
a2cd141b 3751 }
a2cd141b 3752 "
3753)
3754
2837e3fb 3755(define_insn "arm_ashldi3_1bit"
50ad1bf9 3756 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 3757 (ashift:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 3758 (const_int 1)))
3759 (clobber (reg:CC CC_REGNUM))]
25f905c2 3760 "TARGET_32BIT"
2837e3fb 3761 "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
a2cd141b 3762 [(set_attr "conds" "clob")
1b7da4ac 3763 (set_attr "length" "8")
3764 (set_attr "type" "multiple")]
a2cd141b 3765)
3766
87b22bf7 3767(define_expand "ashlsi3"
cffb2a26 3768 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3769 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
3770 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3771 "TARGET_EITHER"
87b22bf7 3772 "
0438d37f 3773 if (CONST_INT_P (operands[2])
87b22bf7 3774 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3775 {
3776 emit_insn (gen_movsi (operands[0], const0_rtx));
3777 DONE;
3778 }
cffb2a26 3779 "
3780)
3781
a2cd141b 3782(define_expand "ashrdi3"
3783 [(set (match_operand:DI 0 "s_register_operand" "")
3784 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
3785 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3786 "TARGET_32BIT"
a2cd141b 3787 "
aa06c51c 3788 if (TARGET_NEON)
3789 {
3790 /* Delay the decision whether to use NEON or core-regs until
3791 register allocation. */
3792 emit_insn (gen_ashrdi3_neon (operands[0], operands[1], operands[2]));
3793 DONE;
3794 }
3795
b805622c 3796 if (!CONST_INT_P (operands[2]) && TARGET_REALLY_IWMMXT)
ffcc986d 3797 ; /* No special preparation statements; expand pattern as above. */
3798 else
a2cd141b 3799 {
ffcc986d 3800 rtx scratch1, scratch2;
3801
3802 if (CONST_INT_P (operands[2])
3803 && (HOST_WIDE_INT) INTVAL (operands[2]) == 1)
a2cd141b 3804 {
3805 emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
3806 DONE;
3807 }
ffcc986d 3808
3809 /* Ideally we should use iwmmxt here if we could know that operands[1]
3810 ends up already living in an iwmmxt register. Otherwise it's
3811 cheaper to have the alternate code being generated than moving
3812 values to iwmmxt regs and back. */
3813
3814 /* If we're optimizing for size, we prefer the libgcc calls. */
3815 if (optimize_function_for_size_p (cfun))
3816 FAIL;
3817
3818 /* Expand operation using core-registers.
3819 'FAIL' would achieve the same thing, but this is a bit smarter. */
3820 scratch1 = gen_reg_rtx (SImode);
3821 scratch2 = gen_reg_rtx (SImode);
3822 arm_emit_coreregs_64bit_shift (ASHIFTRT, operands[0], operands[1],
3823 operands[2], scratch1, scratch2);
3824 DONE;
a2cd141b 3825 }
a2cd141b 3826 "
3827)
3828
2837e3fb 3829(define_insn "arm_ashrdi3_1bit"
50ad1bf9 3830 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 3831 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 3832 (const_int 1)))
3833 (clobber (reg:CC CC_REGNUM))]
25f905c2 3834 "TARGET_32BIT"
2837e3fb 3835 "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
a2cd141b 3836 [(set_attr "conds" "clob")
1b7da4ac 3837 (set_attr "length" "8")
3838 (set_attr "type" "multiple")]
a2cd141b 3839)
3840
87b22bf7 3841(define_expand "ashrsi3"
cffb2a26 3842 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3843 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
3844 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3845 "TARGET_EITHER"
87b22bf7 3846 "
0438d37f 3847 if (CONST_INT_P (operands[2])
87b22bf7 3848 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3849 operands[2] = GEN_INT (31);
cffb2a26 3850 "
3851)
3852
a2cd141b 3853(define_expand "lshrdi3"
3854 [(set (match_operand:DI 0 "s_register_operand" "")
3855 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
3856 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3857 "TARGET_32BIT"
a2cd141b 3858 "
aa06c51c 3859 if (TARGET_NEON)
3860 {
3861 /* Delay the decision whether to use NEON or core-regs until
3862 register allocation. */
3863 emit_insn (gen_lshrdi3_neon (operands[0], operands[1], operands[2]));
3864 DONE;
3865 }
3866
b805622c 3867 if (!CONST_INT_P (operands[2]) && TARGET_REALLY_IWMMXT)
ffcc986d 3868 ; /* No special preparation statements; expand pattern as above. */
3869 else
a2cd141b 3870 {
ffcc986d 3871 rtx scratch1, scratch2;
3872
3873 if (CONST_INT_P (operands[2])
3874 && (HOST_WIDE_INT) INTVAL (operands[2]) == 1)
a2cd141b 3875 {
3876 emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
3877 DONE;
3878 }
ffcc986d 3879
3880 /* Ideally we should use iwmmxt here if we could know that operands[1]
3881 ends up already living in an iwmmxt register. Otherwise it's
3882 cheaper to have the alternate code being generated than moving
3883 values to iwmmxt regs and back. */
3884
3885 /* If we're optimizing for size, we prefer the libgcc calls. */
3886 if (optimize_function_for_size_p (cfun))
3887 FAIL;
3888
3889 /* Expand operation using core-registers.
3890 'FAIL' would achieve the same thing, but this is a bit smarter. */
3891 scratch1 = gen_reg_rtx (SImode);
3892 scratch2 = gen_reg_rtx (SImode);
3893 arm_emit_coreregs_64bit_shift (LSHIFTRT, operands[0], operands[1],
3894 operands[2], scratch1, scratch2);
3895 DONE;
a2cd141b 3896 }
a2cd141b 3897 "
3898)
3899
2837e3fb 3900(define_insn "arm_lshrdi3_1bit"
50ad1bf9 3901 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 3902 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 3903 (const_int 1)))
3904 (clobber (reg:CC CC_REGNUM))]
25f905c2 3905 "TARGET_32BIT"
2837e3fb 3906 "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
a2cd141b 3907 [(set_attr "conds" "clob")
1b7da4ac 3908 (set_attr "length" "8")
3909 (set_attr "type" "multiple")]
a2cd141b 3910)
3911
87b22bf7 3912(define_expand "lshrsi3"
cffb2a26 3913 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3914 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
3915 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3916 "TARGET_EITHER"
87b22bf7 3917 "
0438d37f 3918 if (CONST_INT_P (operands[2])
87b22bf7 3919 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3920 {
3921 emit_insn (gen_movsi (operands[0], const0_rtx));
3922 DONE;
3923 }
cffb2a26 3924 "
3925)
3926
87b22bf7 3927(define_expand "rotlsi3"
cffb2a26 3928 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3929 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
3930 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3931 "TARGET_32BIT"
87b22bf7 3932 "
0438d37f 3933 if (CONST_INT_P (operands[2]))
87b22bf7 3934 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
3935 else
b11cae9e 3936 {
87b22bf7 3937 rtx reg = gen_reg_rtx (SImode);
3938 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
3939 operands[2] = reg;
b11cae9e 3940 }
cffb2a26 3941 "
3942)
9c08d1fa 3943
87b22bf7 3944(define_expand "rotrsi3"
cffb2a26 3945 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3946 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
3947 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3948 "TARGET_EITHER"
87b22bf7 3949 "
25f905c2 3950 if (TARGET_32BIT)
cffb2a26 3951 {
0438d37f 3952 if (CONST_INT_P (operands[2])
cffb2a26 3953 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3954 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
3955 }
25f905c2 3956 else /* TARGET_THUMB1 */
cffb2a26 3957 {
0438d37f 3958 if (CONST_INT_P (operands [2]))
cffb2a26 3959 operands [2] = force_reg (SImode, operands[2]);
3960 }
3961 "
3962)
87b22bf7 3963
cffb2a26 3964(define_insn "*arm_shiftsi3"
88c29385 3965 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r,r")
cffb2a26 3966 (match_operator:SI 3 "shift_operator"
88c29385 3967 [(match_operand:SI 1 "s_register_operand" "0,l,r,r")
3968 (match_operand:SI 2 "reg_or_int_operand" "l,M,M,r")]))]
25f905c2 3969 "TARGET_32BIT"
3970 "* return arm_output_shift(operands, 0);"
344495ea 3971 [(set_attr "predicable" "yes")
88c29385 3972 (set_attr "arch" "t2,t2,*,*")
3973 (set_attr "predicable_short_it" "yes,yes,no,no")
7c36fe71 3974 (set_attr "length" "4")
331beb1a 3975 (set_attr "shift" "1")
88c29385 3976 (set_attr "type" "alu_shift_reg,alu_shift_imm,alu_shift_imm,alu_shift_reg")]
6c4c2133 3977)
87b22bf7 3978
f7fbdd4a 3979(define_insn "*shiftsi3_compare0"
bd5b4116 3980 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 3981 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
6b6abc9c 3982 [(match_operand:SI 1 "s_register_operand" "r,r")
3983 (match_operand:SI 2 "arm_rhs_operand" "M,r")])
9c08d1fa 3984 (const_int 0)))
6b6abc9c 3985 (set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 3986 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
25f905c2 3987 "TARGET_32BIT"
3988 "* return arm_output_shift(operands, 1);"
344495ea 3989 [(set_attr "conds" "set")
331beb1a 3990 (set_attr "shift" "1")
d82e788e 3991 (set_attr "type" "alus_shift_imm,alus_shift_reg")]
0d66636f 3992)
9c08d1fa 3993
f7fbdd4a 3994(define_insn "*shiftsi3_compare0_scratch"
bd5b4116 3995 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 3996 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
6b6abc9c 3997 [(match_operand:SI 1 "s_register_operand" "r,r")
3998 (match_operand:SI 2 "arm_rhs_operand" "M,r")])
9c08d1fa 3999 (const_int 0)))
6b6abc9c 4000 (clobber (match_scratch:SI 0 "=r,r"))]
25f905c2 4001 "TARGET_32BIT"
4002 "* return arm_output_shift(operands, 1);"
344495ea 4003 [(set_attr "conds" "set")
6b6abc9c 4004 (set_attr "shift" "1")
d82e788e 4005 (set_attr "type" "shift_imm,shift_reg")]
0d66636f 4006)
9c08d1fa 4007
d5d4dc8d 4008(define_insn "*not_shiftsi"
4009 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 4010 (not:SI (match_operator:SI 3 "shift_operator"
d5d4dc8d 4011 [(match_operand:SI 1 "s_register_operand" "r,r")
4012 (match_operand:SI 2 "shift_amount_operand" "M,rM")])))]
4013 "TARGET_32BIT"
6c4c2133 4014 "mvn%?\\t%0, %1%S3"
344495ea 4015 [(set_attr "predicable" "yes")
d952d547 4016 (set_attr "predicable_short_it" "no")
331beb1a 4017 (set_attr "shift" "1")
d5d4dc8d 4018 (set_attr "arch" "32,a")
1aed5204 4019 (set_attr "type" "mvn_shift,mvn_shift_reg")])
9c08d1fa 4020
d5d4dc8d 4021(define_insn "*not_shiftsi_compare0"
bd5b4116 4022 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 4023 (compare:CC_NOOV
4024 (not:SI (match_operator:SI 3 "shift_operator"
4025 [(match_operand:SI 1 "s_register_operand" "r,r")
4026 (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
4027 (const_int 0)))
4028 (set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 4029 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
d5d4dc8d 4030 "TARGET_32BIT"
25f905c2 4031 "mvn%.\\t%0, %1%S3"
344495ea 4032 [(set_attr "conds" "set")
331beb1a 4033 (set_attr "shift" "1")
d5d4dc8d 4034 (set_attr "arch" "32,a")
1aed5204 4035 (set_attr "type" "mvn_shift,mvn_shift_reg")])
9c08d1fa 4036
d5d4dc8d 4037(define_insn "*not_shiftsi_compare0_scratch"
bd5b4116 4038 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 4039 (compare:CC_NOOV
4040 (not:SI (match_operator:SI 3 "shift_operator"
4041 [(match_operand:SI 1 "s_register_operand" "r,r")
4042 (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
4043 (const_int 0)))
4044 (clobber (match_scratch:SI 0 "=r,r"))]
4045 "TARGET_32BIT"
25f905c2 4046 "mvn%.\\t%0, %1%S3"
344495ea 4047 [(set_attr "conds" "set")
331beb1a 4048 (set_attr "shift" "1")
d5d4dc8d 4049 (set_attr "arch" "32,a")
1aed5204 4050 (set_attr "type" "mvn_shift,mvn_shift_reg")])
9c08d1fa 4051
cffb2a26 4052;; We don't really have extzv, but defining this using shifts helps
4053;; to reduce register pressure later on.
4054
4055(define_expand "extzv"
eb04cafb 4056 [(set (match_operand 0 "s_register_operand" "")
4057 (zero_extract (match_operand 1 "nonimmediate_operand" "")
4058 (match_operand 2 "const_int_operand" "")
4059 (match_operand 3 "const_int_operand" "")))]
8b054d5a 4060 "TARGET_THUMB1 || arm_arch_thumb2"
cffb2a26 4061 "
4062 {
4063 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
4064 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
4065
8b054d5a 4066 if (arm_arch_thumb2)
4067 {
eb04cafb 4068 HOST_WIDE_INT width = INTVAL (operands[2]);
4069 HOST_WIDE_INT bitpos = INTVAL (operands[3]);
4070
4071 if (unaligned_access && MEM_P (operands[1])
4072 && (width == 16 || width == 32) && (bitpos % BITS_PER_UNIT) == 0)
4073 {
4074 rtx base_addr;
4075
4076 if (BYTES_BIG_ENDIAN)
4077 bitpos = GET_MODE_BITSIZE (GET_MODE (operands[0])) - width
4078 - bitpos;
4079
4080 if (width == 32)
4081 {
4082 base_addr = adjust_address (operands[1], SImode,
4083 bitpos / BITS_PER_UNIT);
4084 emit_insn (gen_unaligned_loadsi (operands[0], base_addr));
4085 }
4086 else
4087 {
4088 rtx dest = operands[0];
4089 rtx tmp = gen_reg_rtx (SImode);
4090
4091 /* We may get a paradoxical subreg here. Strip it off. */
4092 if (GET_CODE (dest) == SUBREG
4093 && GET_MODE (dest) == SImode
4094 && GET_MODE (SUBREG_REG (dest)) == HImode)
4095 dest = SUBREG_REG (dest);
4096
4097 if (GET_MODE_BITSIZE (GET_MODE (dest)) != width)
4098 FAIL;
4099
4100 base_addr = adjust_address (operands[1], HImode,
4101 bitpos / BITS_PER_UNIT);
4102 emit_insn (gen_unaligned_loadhiu (tmp, base_addr));
4103 emit_move_insn (gen_lowpart (SImode, dest), tmp);
4104 }
4105 DONE;
4106 }
4107 else if (s_register_operand (operands[1], GET_MODE (operands[1])))
4108 {
4109 emit_insn (gen_extzv_t2 (operands[0], operands[1], operands[2],
4110 operands[3]));
4111 DONE;
4112 }
4113 else
4114 FAIL;
8b054d5a 4115 }
eb04cafb 4116
4117 if (!s_register_operand (operands[1], GET_MODE (operands[1])))
4118 FAIL;
8b054d5a 4119
cffb2a26 4120 operands[3] = GEN_INT (rshift);
4121
4122 if (lshift == 0)
4123 {
4124 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
4125 DONE;
4126 }
4127
eb04cafb 4128 emit_insn (gen_extzv_t1 (operands[0], operands[1], GEN_INT (lshift),
4129 operands[3], gen_reg_rtx (SImode)));
4130 DONE;
215b30b3 4131 }"
cffb2a26 4132)
4133
eb04cafb 4134;; Helper for extzv, for the Thumb-1 register-shifts case.
4135
4136(define_expand "extzv_t1"
4137 [(set (match_operand:SI 4 "s_register_operand" "")
4138 (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "")
4139 (match_operand:SI 2 "const_int_operand" "")))
4140 (set (match_operand:SI 0 "s_register_operand" "")
4141 (lshiftrt:SI (match_dup 4)
4142 (match_operand:SI 3 "const_int_operand" "")))]
4143 "TARGET_THUMB1"
4144 "")
4145
4146(define_expand "extv"
4147 [(set (match_operand 0 "s_register_operand" "")
4148 (sign_extract (match_operand 1 "nonimmediate_operand" "")
4149 (match_operand 2 "const_int_operand" "")
4150 (match_operand 3 "const_int_operand" "")))]
4151 "arm_arch_thumb2"
4152{
4153 HOST_WIDE_INT width = INTVAL (operands[2]);
4154 HOST_WIDE_INT bitpos = INTVAL (operands[3]);
4155
4156 if (unaligned_access && MEM_P (operands[1]) && (width == 16 || width == 32)
4157 && (bitpos % BITS_PER_UNIT) == 0)
4158 {
4159 rtx base_addr;
4160
4161 if (BYTES_BIG_ENDIAN)
4162 bitpos = GET_MODE_BITSIZE (GET_MODE (operands[0])) - width - bitpos;
4163
4164 if (width == 32)
4165 {
4166 base_addr = adjust_address (operands[1], SImode,
4167 bitpos / BITS_PER_UNIT);
4168 emit_insn (gen_unaligned_loadsi (operands[0], base_addr));
4169 }
4170 else
4171 {
4172 rtx dest = operands[0];
4173 rtx tmp = gen_reg_rtx (SImode);
4174
4175 /* We may get a paradoxical subreg here. Strip it off. */
4176 if (GET_CODE (dest) == SUBREG
4177 && GET_MODE (dest) == SImode
4178 && GET_MODE (SUBREG_REG (dest)) == HImode)
4179 dest = SUBREG_REG (dest);
4180
4181 if (GET_MODE_BITSIZE (GET_MODE (dest)) != width)
4182 FAIL;
4183
4184 base_addr = adjust_address (operands[1], HImode,
4185 bitpos / BITS_PER_UNIT);
4186 emit_insn (gen_unaligned_loadhis (tmp, base_addr));
4187 emit_move_insn (gen_lowpart (SImode, dest), tmp);
4188 }
4189
4190 DONE;
4191 }
4192 else if (!s_register_operand (operands[1], GET_MODE (operands[1])))
4193 FAIL;
4194 else if (GET_MODE (operands[0]) == SImode
4195 && GET_MODE (operands[1]) == SImode)
4196 {
4197 emit_insn (gen_extv_regsi (operands[0], operands[1], operands[2],
4198 operands[3]));
4199 DONE;
4200 }
4201
4202 FAIL;
4203})
4204
4205; Helper to expand register forms of extv with the proper modes.
4206
4207(define_expand "extv_regsi"
4208 [(set (match_operand:SI 0 "s_register_operand" "")
4209 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
4210 (match_operand 2 "const_int_operand" "")
4211 (match_operand 3 "const_int_operand" "")))]
4212 ""
4213{
4214})
4215
4216; ARMv6+ unaligned load/store instructions (used for packed structure accesses).
4217
4218(define_insn "unaligned_loadsi"
4219 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4220 (unspec:SI [(match_operand:SI 1 "memory_operand" "Uw,m")]
4221 UNSPEC_UNALIGNED_LOAD))]
4222 "unaligned_access && TARGET_32BIT"
4223 "ldr%?\t%0, %1\t@ unaligned"
4224 [(set_attr "arch" "t2,any")
4225 (set_attr "length" "2,4")
4226 (set_attr "predicable" "yes")
d952d547 4227 (set_attr "predicable_short_it" "yes,no")
eb04cafb 4228 (set_attr "type" "load1")])
4229
4230(define_insn "unaligned_loadhis"
4231 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4232 (sign_extend:SI
e3f4ccee 4233 (unspec:HI [(match_operand:HI 1 "memory_operand" "Uw,Uh")]
eb04cafb 4234 UNSPEC_UNALIGNED_LOAD)))]
4235 "unaligned_access && TARGET_32BIT"
4236 "ldr%(sh%)\t%0, %1\t@ unaligned"
4237 [(set_attr "arch" "t2,any")
4238 (set_attr "length" "2,4")
4239 (set_attr "predicable" "yes")
d952d547 4240 (set_attr "predicable_short_it" "yes,no")
eb04cafb 4241 (set_attr "type" "load_byte")])
4242
4243(define_insn "unaligned_loadhiu"
4244 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4245 (zero_extend:SI
4246 (unspec:HI [(match_operand:HI 1 "memory_operand" "Uw,m")]
4247 UNSPEC_UNALIGNED_LOAD)))]
4248 "unaligned_access && TARGET_32BIT"
4249 "ldr%(h%)\t%0, %1\t@ unaligned"
4250 [(set_attr "arch" "t2,any")
4251 (set_attr "length" "2,4")
4252 (set_attr "predicable" "yes")
d952d547 4253 (set_attr "predicable_short_it" "yes,no")
eb04cafb 4254 (set_attr "type" "load_byte")])
4255
4256(define_insn "unaligned_storesi"
4257 [(set (match_operand:SI 0 "memory_operand" "=Uw,m")
4258 (unspec:SI [(match_operand:SI 1 "s_register_operand" "l,r")]
4259 UNSPEC_UNALIGNED_STORE))]
4260 "unaligned_access && TARGET_32BIT"
4261 "str%?\t%1, %0\t@ unaligned"
4262 [(set_attr "arch" "t2,any")
4263 (set_attr "length" "2,4")
4264 (set_attr "predicable" "yes")
d952d547 4265 (set_attr "predicable_short_it" "yes,no")
eb04cafb 4266 (set_attr "type" "store1")])
4267
4268(define_insn "unaligned_storehi"
4269 [(set (match_operand:HI 0 "memory_operand" "=Uw,m")
4270 (unspec:HI [(match_operand:HI 1 "s_register_operand" "l,r")]
4271 UNSPEC_UNALIGNED_STORE))]
4272 "unaligned_access && TARGET_32BIT"
4273 "str%(h%)\t%1, %0\t@ unaligned"
4274 [(set_attr "arch" "t2,any")
4275 (set_attr "length" "2,4")
4276 (set_attr "predicable" "yes")
d952d547 4277 (set_attr "predicable_short_it" "yes,no")
eb04cafb 4278 (set_attr "type" "store1")])
4279
ae51a965 4280;; Unaligned double-word load and store.
4281;; Split after reload into two unaligned single-word accesses.
4282;; It prevents lower_subreg from splitting some other aligned
4283;; double-word accesses too early. Used for internal memcpy.
4284
4285(define_insn_and_split "unaligned_loaddi"
4286 [(set (match_operand:DI 0 "s_register_operand" "=l,r")
4287 (unspec:DI [(match_operand:DI 1 "memory_operand" "o,o")]
4288 UNSPEC_UNALIGNED_LOAD))]
4289 "unaligned_access && TARGET_32BIT"
4290 "#"
4291 "&& reload_completed"
4292 [(set (match_dup 0) (unspec:SI [(match_dup 1)] UNSPEC_UNALIGNED_LOAD))
4293 (set (match_dup 2) (unspec:SI [(match_dup 3)] UNSPEC_UNALIGNED_LOAD))]
4294 {
4295 operands[2] = gen_highpart (SImode, operands[0]);
4296 operands[0] = gen_lowpart (SImode, operands[0]);
4297 operands[3] = gen_highpart (SImode, operands[1]);
4298 operands[1] = gen_lowpart (SImode, operands[1]);
4299
4300 /* If the first destination register overlaps with the base address,
4301 swap the order in which the loads are emitted. */
4302 if (reg_overlap_mentioned_p (operands[0], operands[1]))
4303 {
f145bcba 4304 std::swap (operands[1], operands[3]);
4305 std::swap (operands[0], operands[2]);
ae51a965 4306 }
4307 }
4308 [(set_attr "arch" "t2,any")
4309 (set_attr "length" "4,8")
4310 (set_attr "predicable" "yes")
4311 (set_attr "type" "load2")])
4312
4313(define_insn_and_split "unaligned_storedi"
4314 [(set (match_operand:DI 0 "memory_operand" "=o,o")
4315 (unspec:DI [(match_operand:DI 1 "s_register_operand" "l,r")]
4316 UNSPEC_UNALIGNED_STORE))]
4317 "unaligned_access && TARGET_32BIT"
4318 "#"
4319 "&& reload_completed"
4320 [(set (match_dup 0) (unspec:SI [(match_dup 1)] UNSPEC_UNALIGNED_STORE))
4321 (set (match_dup 2) (unspec:SI [(match_dup 3)] UNSPEC_UNALIGNED_STORE))]
4322 {
4323 operands[2] = gen_highpart (SImode, operands[0]);
4324 operands[0] = gen_lowpart (SImode, operands[0]);
4325 operands[3] = gen_highpart (SImode, operands[1]);
4326 operands[1] = gen_lowpart (SImode, operands[1]);
4327 }
4328 [(set_attr "arch" "t2,any")
4329 (set_attr "length" "4,8")
4330 (set_attr "predicable" "yes")
4331 (set_attr "type" "store2")])
4332
4333
eb04cafb 4334(define_insn "*extv_reg"
8b054d5a 4335 [(set (match_operand:SI 0 "s_register_operand" "=r")
4336 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
809003b3 4337 (match_operand:SI 2 "const_int_M_operand" "M")
4338 (match_operand:SI 3 "const_int_M_operand" "M")))]
8b054d5a 4339 "arm_arch_thumb2"
4340 "sbfx%?\t%0, %1, %3, %2"
4341 [(set_attr "length" "4")
d952d547 4342 (set_attr "predicable" "yes")
d82e788e 4343 (set_attr "predicable_short_it" "no")
4344 (set_attr "type" "bfm")]
8b054d5a 4345)
4346
4347(define_insn "extzv_t2"
4348 [(set (match_operand:SI 0 "s_register_operand" "=r")
4349 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "r")
809003b3 4350 (match_operand:SI 2 "const_int_M_operand" "M")
4351 (match_operand:SI 3 "const_int_M_operand" "M")))]
8b054d5a 4352 "arm_arch_thumb2"
4353 "ubfx%?\t%0, %1, %3, %2"
4354 [(set_attr "length" "4")
d952d547 4355 (set_attr "predicable" "yes")
d82e788e 4356 (set_attr "predicable_short_it" "no")
4357 (set_attr "type" "bfm")]
8b054d5a 4358)
4359
7d3cda8c 4360
4361;; Division instructions
4362(define_insn "divsi3"
4363 [(set (match_operand:SI 0 "s_register_operand" "=r")
4364 (div:SI (match_operand:SI 1 "s_register_operand" "r")
4365 (match_operand:SI 2 "s_register_operand" "r")))]
4366 "TARGET_IDIV"
4367 "sdiv%?\t%0, %1, %2"
4368 [(set_attr "predicable" "yes")
d952d547 4369 (set_attr "predicable_short_it" "no")
9da0ec36 4370 (set_attr "type" "sdiv")]
7d3cda8c 4371)
4372
4373(define_insn "udivsi3"
4374 [(set (match_operand:SI 0 "s_register_operand" "=r")
4375 (udiv:SI (match_operand:SI 1 "s_register_operand" "r")
4376 (match_operand:SI 2 "s_register_operand" "r")))]
4377 "TARGET_IDIV"
4378 "udiv%?\t%0, %1, %2"
4379 [(set_attr "predicable" "yes")
d952d547 4380 (set_attr "predicable_short_it" "no")
9da0ec36 4381 (set_attr "type" "udiv")]
7d3cda8c 4382)
4383
b11cae9e 4384\f
4385;; Unary arithmetic insns
4386
cffb2a26 4387(define_expand "negdi2"
4388 [(parallel
8135a42b 4389 [(set (match_operand:DI 0 "s_register_operand" "")
4390 (neg:DI (match_operand:DI 1 "s_register_operand" "")))
bd5b4116 4391 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 4392 "TARGET_EITHER"
774d2fbb 4393 {
4394 if (TARGET_NEON)
4395 {
4396 emit_insn (gen_negdi2_neon (operands[0], operands[1]));
4397 DONE;
4398 }
4399 }
cffb2a26 4400)
4401
4402;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
e5fea38e 4403;; The first alternative allows the common case of a *full* overlap.
ba6a3b2f 4404(define_insn_and_split "*arm_negdi2"
458a8706 4405 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 4406 (neg:DI (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 4407 (clobber (reg:CC CC_REGNUM))]
cffb2a26 4408 "TARGET_ARM"
ba6a3b2f 4409 "#" ; "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
4410 "&& reload_completed"
4411 [(parallel [(set (reg:CC CC_REGNUM)
4412 (compare:CC (const_int 0) (match_dup 1)))
4413 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 1)))])
4414 (set (match_dup 2) (minus:SI (minus:SI (const_int 0) (match_dup 3))
4415 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
4416 {
4417 operands[2] = gen_highpart (SImode, operands[0]);
4418 operands[0] = gen_lowpart (SImode, operands[0]);
4419 operands[3] = gen_highpart (SImode, operands[1]);
4420 operands[1] = gen_lowpart (SImode, operands[1]);
4421 }
cffb2a26 4422 [(set_attr "conds" "clob")
1b7da4ac 4423 (set_attr "length" "8")
4424 (set_attr "type" "multiple")]
cffb2a26 4425)
b11cae9e 4426
cffb2a26 4427(define_expand "negsi2"
4428 [(set (match_operand:SI 0 "s_register_operand" "")
4429 (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
4430 "TARGET_EITHER"
b11cae9e 4431 ""
cffb2a26 4432)
4433
4434(define_insn "*arm_negsi2"
d952d547 4435 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4436 (neg:SI (match_operand:SI 1 "s_register_operand" "l,r")))]
25f905c2 4437 "TARGET_32BIT"
cffb2a26 4438 "rsb%?\\t%0, %1, #0"
d952d547 4439 [(set_attr "predicable" "yes")
4440 (set_attr "predicable_short_it" "yes,no")
4441 (set_attr "arch" "t2,*")
1b7da4ac 4442 (set_attr "length" "4")
112eda6f 4443 (set_attr "type" "alu_sreg")]
cffb2a26 4444)
4445
604f3a0a 4446(define_expand "negsf2"
4447 [(set (match_operand:SF 0 "s_register_operand" "")
4448 (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
994606f8 4449 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
604f3a0a 4450 ""
4451)
4452
4453(define_expand "negdf2"
4454 [(set (match_operand:DF 0 "s_register_operand" "")
4455 (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
994606f8 4456 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
604f3a0a 4457 "")
4458
7eaf2be0 4459(define_insn_and_split "*zextendsidi_negsi"
4460 [(set (match_operand:DI 0 "s_register_operand" "=r")
4461 (zero_extend:DI (neg:SI (match_operand:SI 1 "s_register_operand" "r"))))]
4462 "TARGET_32BIT"
4463 "#"
4464 ""
4465 [(set (match_dup 2)
4466 (neg:SI (match_dup 1)))
4467 (set (match_dup 3)
4468 (const_int 0))]
4469 {
4470 operands[2] = gen_lowpart (SImode, operands[0]);
4471 operands[3] = gen_highpart (SImode, operands[0]);
4472 }
4473 [(set_attr "length" "8")
4474 (set_attr "type" "multiple")]
4475)
4476
83e2b922 4477;; Negate an extended 32-bit value.
4478(define_insn_and_split "*negdi_extendsidi"
61fa8ff2 4479 [(set (match_operand:DI 0 "s_register_operand" "=l,r")
4480 (neg:DI (sign_extend:DI
4481 (match_operand:SI 1 "s_register_operand" "l,r"))))
83e2b922 4482 (clobber (reg:CC CC_REGNUM))]
4483 "TARGET_32BIT"
61fa8ff2 4484 "#"
83e2b922 4485 "&& reload_completed"
4486 [(const_int 0)]
4487 {
61fa8ff2 4488 rtx low = gen_lowpart (SImode, operands[0]);
4489 rtx high = gen_highpart (SImode, operands[0]);
4490
4491 if (reg_overlap_mentioned_p (low, operands[1]))
4492 {
4493 /* Input overlaps the low word of the output. Use:
4494 asr Rhi, Rin, #31
4495 rsbs Rlo, Rin, #0
4496 rsc Rhi, Rhi, #0 (thumb2: sbc Rhi, Rhi, Rhi, lsl #1). */
4497 rtx cc_reg = gen_rtx_REG (CC_Cmode, CC_REGNUM);
4498
d1f9b275 4499 emit_insn (gen_rtx_SET (high,
61fa8ff2 4500 gen_rtx_ASHIFTRT (SImode, operands[1],
4501 GEN_INT (31))));
4502
4503 emit_insn (gen_subsi3_compare (low, const0_rtx, operands[1]));
4504 if (TARGET_ARM)
d1f9b275 4505 emit_insn (gen_rtx_SET (high,
61fa8ff2 4506 gen_rtx_MINUS (SImode,
4507 gen_rtx_MINUS (SImode,
4508 const0_rtx,
4509 high),
4510 gen_rtx_LTU (SImode,
4511 cc_reg,
4512 const0_rtx))));
4513 else
4514 {
4515 rtx two_x = gen_rtx_ASHIFT (SImode, high, GEN_INT (1));
d1f9b275 4516 emit_insn (gen_rtx_SET (high,
61fa8ff2 4517 gen_rtx_MINUS (SImode,
4518 gen_rtx_MINUS (SImode,
4519 high,
4520 two_x),
4521 gen_rtx_LTU (SImode,
4522 cc_reg,
4523 const0_rtx))));
4524 }
4525 }
4526 else
4527 {
4528 /* No overlap, or overlap on high word. Use:
4529 rsb Rlo, Rin, #0
4530 bic Rhi, Rlo, Rin
4531 asr Rhi, Rhi, #31
4532 Flags not needed for this sequence. */
d1f9b275 4533 emit_insn (gen_rtx_SET (low, gen_rtx_NEG (SImode, operands[1])));
4534 emit_insn (gen_rtx_SET (high,
61fa8ff2 4535 gen_rtx_AND (SImode,
4536 gen_rtx_NOT (SImode, operands[1]),
4537 low)));
d1f9b275 4538 emit_insn (gen_rtx_SET (high,
61fa8ff2 4539 gen_rtx_ASHIFTRT (SImode, high,
4540 GEN_INT (31))));
4541 }
4542 DONE;
83e2b922 4543 }
61fa8ff2 4544 [(set_attr "length" "12")
4545 (set_attr "arch" "t2,*")
1b7da4ac 4546 (set_attr "type" "multiple")]
83e2b922 4547)
4548
4549(define_insn_and_split "*negdi_zero_extendsidi"
4550 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
4551 (neg:DI (zero_extend:DI (match_operand:SI 1 "s_register_operand" "0,r"))))
4552 (clobber (reg:CC CC_REGNUM))]
4553 "TARGET_32BIT"
4554 "#" ; "rsbs\\t%Q0, %1, #0\;sbc\\t%R0,%R0,%R0"
4555 ;; Don't care what register is input to sbc,
4556 ;; since we just just need to propagate the carry.
4557 "&& reload_completed"
4558 [(parallel [(set (reg:CC CC_REGNUM)
4559 (compare:CC (const_int 0) (match_dup 1)))
4560 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 1)))])
4561 (set (match_dup 2) (minus:SI (minus:SI (match_dup 2) (match_dup 2))
4562 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
4563 {
4564 operands[2] = gen_highpart (SImode, operands[0]);
4565 operands[0] = gen_lowpart (SImode, operands[0]);
4566 }
4567 [(set_attr "conds" "clob")
1b7da4ac 4568 (set_attr "length" "8")
4569 (set_attr "type" "multiple")] ;; length in thumb is 4
83e2b922 4570)
4571
9c08d1fa 4572;; abssi2 doesn't really clobber the condition codes if a different register
4573;; is being set. To keep things simple, assume during rtl manipulations that
4574;; it does, but tell the final scan operator the truth. Similarly for
4575;; (neg (abs...))
4576
604f3a0a 4577(define_expand "abssi2"
4578 [(parallel
4579 [(set (match_operand:SI 0 "s_register_operand" "")
4580 (abs:SI (match_operand:SI 1 "s_register_operand" "")))
ba156559 4581 (clobber (match_dup 2))])]
4582 "TARGET_EITHER"
4583 "
25f905c2 4584 if (TARGET_THUMB1)
ba156559 4585 operands[2] = gen_rtx_SCRATCH (SImode);
4586 else
4587 operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
4588")
604f3a0a 4589
ba6a3b2f 4590(define_insn_and_split "*arm_abssi2"
ba156559 4591 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
9c08d1fa 4592 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
bd5b4116 4593 (clobber (reg:CC CC_REGNUM))]
cffb2a26 4594 "TARGET_ARM"
ba6a3b2f 4595 "#"
4596 "&& reload_completed"
4597 [(const_int 0)]
4598 {
4599 /* if (which_alternative == 0) */
4600 if (REGNO(operands[0]) == REGNO(operands[1]))
4601 {
4602 /* Emit the pattern:
4603 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
4604 [(set (reg:CC CC_REGNUM)
4605 (compare:CC (match_dup 0) (const_int 0)))
4606 (cond_exec (lt:CC (reg:CC CC_REGNUM) (const_int 0))
4607 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 1))))]
4608 */
d1f9b275 4609 emit_insn (gen_rtx_SET (gen_rtx_REG (CCmode, CC_REGNUM),
ba6a3b2f 4610 gen_rtx_COMPARE (CCmode, operands[0], const0_rtx)));
4611 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
4612 (gen_rtx_LT (SImode,
4613 gen_rtx_REG (CCmode, CC_REGNUM),
4614 const0_rtx)),
d1f9b275 4615 (gen_rtx_SET (operands[0],
ba6a3b2f 4616 (gen_rtx_MINUS (SImode,
4617 const0_rtx,
4618 operands[1]))))));
4619 DONE;
4620 }
4621 else
4622 {
4623 /* Emit the pattern:
4624 alt1: eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31
4625 [(set (match_dup 0)
4626 (xor:SI (match_dup 1)
4627 (ashiftrt:SI (match_dup 1) (const_int 31))))
4628 (set (match_dup 0)
4629 (minus:SI (match_dup 0)
4630 (ashiftrt:SI (match_dup 1) (const_int 31))))]
4631 */
d1f9b275 4632 emit_insn (gen_rtx_SET (operands[0],
ba6a3b2f 4633 gen_rtx_XOR (SImode,
4634 gen_rtx_ASHIFTRT (SImode,
4635 operands[1],
4636 GEN_INT (31)),
4637 operands[1])));
d1f9b275 4638 emit_insn (gen_rtx_SET (operands[0],
ba6a3b2f 4639 gen_rtx_MINUS (SImode,
4640 operands[0],
4641 gen_rtx_ASHIFTRT (SImode,
4642 operands[1],
4643 GEN_INT (31)))));
4644 DONE;
4645 }
4646 }
cffb2a26 4647 [(set_attr "conds" "clob,*")
331beb1a 4648 (set_attr "shift" "1")
2ad08b65 4649 (set_attr "predicable" "no, yes")
1b7da4ac 4650 (set_attr "length" "8")
4651 (set_attr "type" "multiple")]
cffb2a26 4652)
9c08d1fa 4653
ba6a3b2f 4654(define_insn_and_split "*arm_neg_abssi2"
9c08d1fa 4655 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
4656 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
bd5b4116 4657 (clobber (reg:CC CC_REGNUM))]
cffb2a26 4658 "TARGET_ARM"
ba6a3b2f 4659 "#"
4660 "&& reload_completed"
4661 [(const_int 0)]
4662 {
4663 /* if (which_alternative == 0) */
4664 if (REGNO (operands[0]) == REGNO (operands[1]))
4665 {
4666 /* Emit the pattern:
4667 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
4668 */
d1f9b275 4669 emit_insn (gen_rtx_SET (gen_rtx_REG (CCmode, CC_REGNUM),
ba6a3b2f 4670 gen_rtx_COMPARE (CCmode, operands[0], const0_rtx)));
4671 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
4672 gen_rtx_GT (SImode,
4673 gen_rtx_REG (CCmode, CC_REGNUM),
4674 const0_rtx),
d1f9b275 4675 gen_rtx_SET (operands[0],
ba6a3b2f 4676 (gen_rtx_MINUS (SImode,
4677 const0_rtx,
4678 operands[1])))));
4679 }
4680 else
4681 {
4682 /* Emit the pattern:
4683 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31
4684 */
d1f9b275 4685 emit_insn (gen_rtx_SET (operands[0],
ba6a3b2f 4686 gen_rtx_XOR (SImode,
4687 gen_rtx_ASHIFTRT (SImode,
4688 operands[1],
4689 GEN_INT (31)),
4690 operands[1])));
d1f9b275 4691 emit_insn (gen_rtx_SET (operands[0],
ba6a3b2f 4692 gen_rtx_MINUS (SImode,
4693 gen_rtx_ASHIFTRT (SImode,
4694 operands[1],
4695 GEN_INT (31)),
4696 operands[0])));
4697 }
4698 DONE;
4699 }
cffb2a26 4700 [(set_attr "conds" "clob,*")
331beb1a 4701 (set_attr "shift" "1")
2ad08b65 4702 (set_attr "predicable" "no, yes")
1b7da4ac 4703 (set_attr "length" "8")
4704 (set_attr "type" "multiple")]
cffb2a26 4705)
b11cae9e 4706
604f3a0a 4707(define_expand "abssf2"
4708 [(set (match_operand:SF 0 "s_register_operand" "")
4709 (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
25f905c2 4710 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 4711 "")
4712
604f3a0a 4713(define_expand "absdf2"
4714 [(set (match_operand:DF 0 "s_register_operand" "")
4715 (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 4716 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 4717 "")
4718
7db9af5d 4719(define_expand "sqrtsf2"
4720 [(set (match_operand:SF 0 "s_register_operand" "")
4721 (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
994606f8 4722 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
7db9af5d 4723 "")
9c08d1fa 4724
7db9af5d 4725(define_expand "sqrtdf2"
4726 [(set (match_operand:DF 0 "s_register_operand" "")
4727 (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
994606f8 4728 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
7db9af5d 4729 "")
9c08d1fa 4730
a0f94409 4731(define_insn_and_split "one_cmpldi2"
10efb95f 4732 [(set (match_operand:DI 0 "s_register_operand" "=w,&r,&r,?w")
4733 (not:DI (match_operand:DI 1 "s_register_operand" " w, 0, r, w")))]
25f905c2 4734 "TARGET_32BIT"
10efb95f 4735 "@
4736 vmvn\t%P0, %P1
4737 #
4738 #
4739 vmvn\t%P0, %P1"
4740 "TARGET_32BIT && reload_completed
4741 && arm_general_register_operand (operands[0], DImode)"
a0f94409 4742 [(set (match_dup 0) (not:SI (match_dup 1)))
4743 (set (match_dup 2) (not:SI (match_dup 3)))]
4744 "
4745 {
4746 operands[2] = gen_highpart (SImode, operands[0]);
4747 operands[0] = gen_lowpart (SImode, operands[0]);
4748 operands[3] = gen_highpart (SImode, operands[1]);
4749 operands[1] = gen_lowpart (SImode, operands[1]);
4750 }"
10efb95f 4751 [(set_attr "length" "*,8,8,*")
4752 (set_attr "predicable" "no,yes,yes,no")
32093010 4753 (set_attr "type" "neon_move,multiple,multiple,neon_move")
b6779ddc 4754 (set_attr "arch" "neon_for_64bits,*,*,avoid_neon_for_64bits")]
cffb2a26 4755)
b11cae9e 4756
cffb2a26 4757(define_expand "one_cmplsi2"
4758 [(set (match_operand:SI 0 "s_register_operand" "")
4759 (not:SI (match_operand:SI 1 "s_register_operand" "")))]
4760 "TARGET_EITHER"
b11cae9e 4761 ""
cffb2a26 4762)
4763
4764(define_insn "*arm_one_cmplsi2"
d952d547 4765 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4766 (not:SI (match_operand:SI 1 "s_register_operand" "l,r")))]
25f905c2 4767 "TARGET_32BIT"
cffb2a26 4768 "mvn%?\\t%0, %1"
d2a518d1 4769 [(set_attr "predicable" "yes")
d952d547 4770 (set_attr "predicable_short_it" "yes,no")
4771 (set_attr "arch" "t2,*")
4772 (set_attr "length" "4")
1aed5204 4773 (set_attr "type" "mvn_reg")]
cffb2a26 4774)
4775
f7fbdd4a 4776(define_insn "*notsi_compare0"
bd5b4116 4777 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 4778 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
4779 (const_int 0)))
4780 (set (match_operand:SI 0 "s_register_operand" "=r")
4781 (not:SI (match_dup 1)))]
25f905c2 4782 "TARGET_32BIT"
4783 "mvn%.\\t%0, %1"
d2a518d1 4784 [(set_attr "conds" "set")
1aed5204 4785 (set_attr "type" "mvn_reg")]
cffb2a26 4786)
9c08d1fa 4787
f7fbdd4a 4788(define_insn "*notsi_compare0_scratch"
bd5b4116 4789 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 4790 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
4791 (const_int 0)))
4792 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 4793 "TARGET_32BIT"
4794 "mvn%.\\t%0, %1"
d2a518d1 4795 [(set_attr "conds" "set")
1aed5204 4796 (set_attr "type" "mvn_reg")]
cffb2a26 4797)
b11cae9e 4798\f
4799;; Fixed <--> Floating conversion insns
4800
9b8516be 4801(define_expand "floatsihf2"
4802 [(set (match_operand:HF 0 "general_operand" "")
4803 (float:HF (match_operand:SI 1 "general_operand" "")))]
4804 "TARGET_EITHER"
4805 "
4806 {
4807 rtx op1 = gen_reg_rtx (SFmode);
4808 expand_float (op1, operands[1], 0);
4809 op1 = convert_to_mode (HFmode, op1, 0);
4810 emit_move_insn (operands[0], op1);
4811 DONE;
4812 }"
4813)
4814
4815(define_expand "floatdihf2"
4816 [(set (match_operand:HF 0 "general_operand" "")
4817 (float:HF (match_operand:DI 1 "general_operand" "")))]
4818 "TARGET_EITHER"
4819 "
4820 {
4821 rtx op1 = gen_reg_rtx (SFmode);
4822 expand_float (op1, operands[1], 0);
4823 op1 = convert_to_mode (HFmode, op1, 0);
4824 emit_move_insn (operands[0], op1);
4825 DONE;
4826 }"
4827)
4828
604f3a0a 4829(define_expand "floatsisf2"
4830 [(set (match_operand:SF 0 "s_register_operand" "")
4831 (float:SF (match_operand:SI 1 "s_register_operand" "")))]
25f905c2 4832 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 4833 "
604f3a0a 4834")
4835
604f3a0a 4836(define_expand "floatsidf2"
4837 [(set (match_operand:DF 0 "s_register_operand" "")
4838 (float:DF (match_operand:SI 1 "s_register_operand" "")))]
a50d7267 4839 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 4840 "
604f3a0a 4841")
4842
9b8516be 4843(define_expand "fix_trunchfsi2"
4844 [(set (match_operand:SI 0 "general_operand" "")
4845 (fix:SI (fix:HF (match_operand:HF 1 "general_operand" ""))))]
4846 "TARGET_EITHER"
4847 "
4848 {
4849 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
4850 expand_fix (operands[0], op1, 0);
4851 DONE;
4852 }"
4853)
4854
4855(define_expand "fix_trunchfdi2"
4856 [(set (match_operand:DI 0 "general_operand" "")
4857 (fix:DI (fix:HF (match_operand:HF 1 "general_operand" ""))))]
4858 "TARGET_EITHER"
4859 "
4860 {
4861 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
4862 expand_fix (operands[0], op1, 0);
4863 DONE;
4864 }"
4865)
4866
604f3a0a 4867(define_expand "fix_truncsfsi2"
4868 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 4869 (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" ""))))]
25f905c2 4870 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 4871 "
604f3a0a 4872")
4873
604f3a0a 4874(define_expand "fix_truncdfsi2"
4875 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 4876 (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" ""))))]
a50d7267 4877 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 4878 "
604f3a0a 4879")
4880
f544c6d2 4881;; Truncation insns
b11cae9e 4882
604f3a0a 4883(define_expand "truncdfsf2"
4884 [(set (match_operand:SF 0 "s_register_operand" "")
4885 (float_truncate:SF
4886 (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 4887 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 4888 ""
4889)
9b8516be 4890
4891/* DFmode -> HFmode conversions have to go through SFmode. */
4892(define_expand "truncdfhf2"
4893 [(set (match_operand:HF 0 "general_operand" "")
4894 (float_truncate:HF
4895 (match_operand:DF 1 "general_operand" "")))]
4896 "TARGET_EITHER"
4897 "
4898 {
4899 rtx op1;
4900 op1 = convert_to_mode (SFmode, operands[1], 0);
4901 op1 = convert_to_mode (HFmode, op1, 0);
4902 emit_move_insn (operands[0], op1);
4903 DONE;
4904 }"
4905)
b11cae9e 4906\f
9c08d1fa 4907;; Zero and sign extension instructions.
b11cae9e 4908
848e66ac 4909(define_insn "zero_extend<mode>di2"
6aa689e8 4910 [(set (match_operand:DI 0 "s_register_operand" "=w,r,?r,w")
6d97728e 4911 (zero_extend:DI (match_operand:QHSI 1 "<qhs_zextenddi_op>"
4912 "<qhs_zextenddi_cstr>")))]
848e66ac 4913 "TARGET_32BIT <qhs_zextenddi_cond>"
4914 "#"
6aa689e8 4915 [(set_attr "length" "8,4,8,8")
b6779ddc 4916 (set_attr "arch" "neon_for_64bits,*,*,avoid_neon_for_64bits")
848e66ac 4917 (set_attr "ce_count" "2")
efbb5e19 4918 (set_attr "predicable" "yes")
4919 (set_attr "type" "multiple,mov_reg,multiple,multiple")]
25f905c2 4920)
4921
848e66ac 4922(define_insn "extend<mode>di2"
6aa689e8 4923 [(set (match_operand:DI 0 "s_register_operand" "=w,r,?r,?r,w")
63d204a8 4924 (sign_extend:DI (match_operand:QHSI 1 "<qhs_extenddi_op>"
4925 "<qhs_extenddi_cstr>")))]
848e66ac 4926 "TARGET_32BIT <qhs_sextenddi_cond>"
4927 "#"
6aa689e8 4928 [(set_attr "length" "8,4,8,8,8")
848e66ac 4929 (set_attr "ce_count" "2")
4930 (set_attr "shift" "1")
8012d2c2 4931 (set_attr "predicable" "yes")
1b7da4ac 4932 (set_attr "arch" "neon_for_64bits,*,a,t,avoid_neon_for_64bits")
4933 (set_attr "type" "multiple,mov_reg,multiple,multiple,multiple")]
0d66636f 4934)
9c08d1fa 4935
848e66ac 4936;; Splits for all extensions to DImode
4937(define_split
4938 [(set (match_operand:DI 0 "s_register_operand" "")
4939 (zero_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
6aa689e8 4940 "TARGET_32BIT && reload_completed && !IS_VFP_REGNUM (REGNO (operands[0]))"
848e66ac 4941 [(set (match_dup 0) (match_dup 1))]
4942{
848e66ac 4943 rtx lo_part = gen_lowpart (SImode, operands[0]);
3754d046 4944 machine_mode src_mode = GET_MODE (operands[1]);
848e66ac 4945
4946 if (REG_P (operands[0])
4947 && !reg_overlap_mentioned_p (operands[0], operands[1]))
4948 emit_clobber (operands[0]);
4949 if (!REG_P (lo_part) || src_mode != SImode
4950 || !rtx_equal_p (lo_part, operands[1]))
4951 {
4952 if (src_mode == SImode)
4953 emit_move_insn (lo_part, operands[1]);
4954 else
d1f9b275 4955 emit_insn (gen_rtx_SET (lo_part,
848e66ac 4956 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
4957 operands[1] = lo_part;
4958 }
4959 operands[0] = gen_highpart (SImode, operands[0]);
4960 operands[1] = const0_rtx;
4961})
9c08d1fa 4962
848e66ac 4963(define_split
25f905c2 4964 [(set (match_operand:DI 0 "s_register_operand" "")
848e66ac 4965 (sign_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
6aa689e8 4966 "TARGET_32BIT && reload_completed && !IS_VFP_REGNUM (REGNO (operands[0]))"
848e66ac 4967 [(set (match_dup 0) (ashiftrt:SI (match_dup 1) (const_int 31)))]
4968{
4969 rtx lo_part = gen_lowpart (SImode, operands[0]);
3754d046 4970 machine_mode src_mode = GET_MODE (operands[1]);
25f905c2 4971
848e66ac 4972 if (REG_P (operands[0])
4973 && !reg_overlap_mentioned_p (operands[0], operands[1]))
4974 emit_clobber (operands[0]);
4975
4976 if (!REG_P (lo_part) || src_mode != SImode
4977 || !rtx_equal_p (lo_part, operands[1]))
4978 {
4979 if (src_mode == SImode)
4980 emit_move_insn (lo_part, operands[1]);
4981 else
d1f9b275 4982 emit_insn (gen_rtx_SET (lo_part,
848e66ac 4983 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
4984 operands[1] = lo_part;
4985 }
4986 operands[0] = gen_highpart (SImode, operands[0]);
4987})
9c08d1fa 4988
4989(define_expand "zero_extendhisi2"
ef51b8e1 4990 [(set (match_operand:SI 0 "s_register_operand" "")
4991 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
cffb2a26 4992 "TARGET_EITHER"
ef51b8e1 4993{
4994 if (TARGET_ARM && !arm_arch4 && MEM_P (operands[1]))
f7fbdd4a 4995 {
ef51b8e1 4996 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
4997 DONE;
25f7a26e 4998 }
ef51b8e1 4999 if (!arm_arch6 && !MEM_P (operands[1]))
5000 {
5001 rtx t = gen_lowpart (SImode, operands[1]);
5002 rtx tmp = gen_reg_rtx (SImode);
5003 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
5004 emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (16)));
5005 DONE;
5006 }
5007})
9c08d1fa 5008
ef51b8e1 5009(define_split
b146458f 5010 [(set (match_operand:SI 0 "s_register_operand" "")
5011 (zero_extend:SI (match_operand:HI 1 "s_register_operand" "")))]
ef51b8e1 5012 "!TARGET_THUMB2 && !arm_arch6"
5013 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
5014 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 16)))]
5015{
5016 operands[2] = gen_lowpart (SImode, operands[1]);
5017})
5018
cffb2a26 5019(define_insn "*arm_zero_extendhisi2"
ef51b8e1 5020 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5021 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 5022 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 5023 "@
5024 #
5025 ldr%(h%)\\t%0, %1"
d82e788e 5026 [(set_attr "type" "alu_shift_reg,load_byte")
848e66ac 5027 (set_attr "predicable" "yes")]
cffb2a26 5028)
f7fbdd4a 5029
a2cd141b 5030(define_insn "*arm_zero_extendhisi2_v6"
5031 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
e3f4ccee 5032 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,Uh")))]
a2cd141b 5033 "TARGET_ARM && arm_arch6"
5034 "@
5035 uxth%?\\t%0, %1
25f905c2 5036 ldr%(h%)\\t%0, %1"
65f68e55 5037 [(set_attr "predicable" "yes")
6b6abc9c 5038 (set_attr "type" "extend,load_byte")]
a2cd141b 5039)
5040
5041(define_insn "*arm_zero_extendhisi2addsi"
5042 [(set (match_operand:SI 0 "s_register_operand" "=r")
5043 (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
5044 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 5045 "TARGET_INT_SIMD"
a2cd141b 5046 "uxtah%?\\t%0, %2, %1"
d82e788e 5047 [(set_attr "type" "alu_shift_reg")
d952d547 5048 (set_attr "predicable" "yes")
5049 (set_attr "predicable_short_it" "no")]
a2cd141b 5050)
5051
87b22bf7 5052(define_expand "zero_extendqisi2"
cffb2a26 5053 [(set (match_operand:SI 0 "s_register_operand" "")
5054 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
5055 "TARGET_EITHER"
ef51b8e1 5056{
0438d37f 5057 if (TARGET_ARM && !arm_arch6 && !MEM_P (operands[1]))
87b22bf7 5058 {
ef51b8e1 5059 emit_insn (gen_andsi3 (operands[0],
5060 gen_lowpart (SImode, operands[1]),
5061 GEN_INT (255)));
5062 DONE;
5063 }
5064 if (!arm_arch6 && !MEM_P (operands[1]))
5065 {
5066 rtx t = gen_lowpart (SImode, operands[1]);
5067 rtx tmp = gen_reg_rtx (SImode);
5068 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
5069 emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (24)));
5070 DONE;
5071 }
5072})
cffb2a26 5073
ef51b8e1 5074(define_split
b146458f 5075 [(set (match_operand:SI 0 "s_register_operand" "")
5076 (zero_extend:SI (match_operand:QI 1 "s_register_operand" "")))]
ef51b8e1 5077 "!arm_arch6"
5078 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
5079 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 24)))]
5080{
5081 operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
5082 if (TARGET_ARM)
5083 {
5084 emit_insn (gen_andsi3 (operands[0], operands[2], GEN_INT (255)));
87b22bf7 5085 DONE;
5086 }
ef51b8e1 5087})
9c08d1fa 5088
cffb2a26 5089(define_insn "*arm_zero_extendqisi2"
ef51b8e1 5090 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5091 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 5092 "TARGET_ARM && !arm_arch6"
ef51b8e1 5093 "@
5094 #
5095 ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
5096 [(set_attr "length" "8,4")
d82e788e 5097 (set_attr "type" "alu_shift_reg,load_byte")
848e66ac 5098 (set_attr "predicable" "yes")]
cffb2a26 5099)
87b22bf7 5100
a2cd141b 5101(define_insn "*arm_zero_extendqisi2_v6"
5102 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
e3f4ccee 5103 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,Uh")))]
a2cd141b 5104 "TARGET_ARM && arm_arch6"
5105 "@
25f905c2 5106 uxtb%(%)\\t%0, %1
5107 ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
6b6abc9c 5108 [(set_attr "type" "extend,load_byte")
848e66ac 5109 (set_attr "predicable" "yes")]
a2cd141b 5110)
5111
5112(define_insn "*arm_zero_extendqisi2addsi"
5113 [(set (match_operand:SI 0 "s_register_operand" "=r")
5114 (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
5115 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 5116 "TARGET_INT_SIMD"
a2cd141b 5117 "uxtab%?\\t%0, %2, %1"
5118 [(set_attr "predicable" "yes")
d952d547 5119 (set_attr "predicable_short_it" "no")
d82e788e 5120 (set_attr "type" "alu_shift_reg")]
a2cd141b 5121)
5122
87b22bf7 5123(define_split
5124 [(set (match_operand:SI 0 "s_register_operand" "")
5125 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
5126 (clobber (match_operand:SI 2 "s_register_operand" ""))]
0438d37f 5127 "TARGET_32BIT && (!MEM_P (operands[1])) && ! BYTES_BIG_ENDIAN"
87b22bf7 5128 [(set (match_dup 2) (match_dup 1))
5129 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
cffb2a26 5130 ""
5131)
9c08d1fa 5132
8a4d25d6 5133(define_split
5134 [(set (match_operand:SI 0 "s_register_operand" "")
5135 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 3)))
5136 (clobber (match_operand:SI 2 "s_register_operand" ""))]
0438d37f 5137 "TARGET_32BIT && (!MEM_P (operands[1])) && BYTES_BIG_ENDIAN"
8a4d25d6 5138 [(set (match_dup 2) (match_dup 1))
5139 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
5140 ""
5141)
5142
1c274529 5143
5144(define_split
5145 [(set (match_operand:SI 0 "s_register_operand" "")
9b23f0a7 5146 (IOR_XOR:SI (and:SI (ashift:SI
1c274529 5147 (match_operand:SI 1 "s_register_operand" "")
5148 (match_operand:SI 2 "const_int_operand" ""))
5149 (match_operand:SI 3 "const_int_operand" ""))
5150 (zero_extend:SI
5151 (match_operator 5 "subreg_lowpart_operator"
5152 [(match_operand:SI 4 "s_register_operand" "")]))))]
5153 "TARGET_32BIT
63787642 5154 && ((unsigned HOST_WIDE_INT) INTVAL (operands[3])
1c274529 5155 == (GET_MODE_MASK (GET_MODE (operands[5]))
5156 & (GET_MODE_MASK (GET_MODE (operands[5]))
5157 << (INTVAL (operands[2])))))"
9b23f0a7 5158 [(set (match_dup 0) (IOR_XOR:SI (ashift:SI (match_dup 1) (match_dup 2))
1c274529 5159 (match_dup 4)))
5160 (set (match_dup 0) (zero_extend:SI (match_dup 5)))]
5161 "operands[5] = gen_lowpart (GET_MODE (operands[5]), operands[0]);"
5162)
5163
f7fbdd4a 5164(define_insn "*compareqi_eq0"
bd5b4116 5165 [(set (reg:CC_Z CC_REGNUM)
206ee9a2 5166 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
87b22bf7 5167 (const_int 0)))]
25f905c2 5168 "TARGET_32BIT"
596e5e8f 5169 "tst%?\\t%0, #255"
5170 [(set_attr "conds" "set")
d952d547 5171 (set_attr "predicable" "yes")
1b7da4ac 5172 (set_attr "predicable_short_it" "no")
5173 (set_attr "type" "logic_imm")]
cffb2a26 5174)
b11cae9e 5175
b11cae9e 5176(define_expand "extendhisi2"
ef51b8e1 5177 [(set (match_operand:SI 0 "s_register_operand" "")
5178 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
cffb2a26 5179 "TARGET_EITHER"
ef51b8e1 5180{
5181 if (TARGET_THUMB1)
5182 {
5183 emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1]));
5184 DONE;
5185 }
5186 if (MEM_P (operands[1]) && TARGET_ARM && !arm_arch4)
5187 {
5188 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
5189 DONE;
5190 }
ed29c566 5191
ef51b8e1 5192 if (!arm_arch6 && !MEM_P (operands[1]))
5193 {
5194 rtx t = gen_lowpart (SImode, operands[1]);
5195 rtx tmp = gen_reg_rtx (SImode);
5196 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
5197 emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (16)));
5198 DONE;
5199 }
5200})
cffb2a26 5201
ef51b8e1 5202(define_split
5203 [(parallel
5204 [(set (match_operand:SI 0 "register_operand" "")
5205 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))
5206 (clobber (match_scratch:SI 2 ""))])]
5207 "!arm_arch6"
5208 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
5209 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
5210{
5211 operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
5212})
25f7a26e 5213
25f905c2 5214;; This pattern will only be used when ldsh is not available
25f7a26e 5215(define_expand "extendhisi2_mem"
eab14235 5216 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 5217 (set (match_dup 3)
eab14235 5218 (zero_extend:SI (match_dup 7)))
25f7a26e 5219 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
5220 (set (match_operand:SI 0 "" "")
5221 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
cffb2a26 5222 "TARGET_ARM"
25f7a26e 5223 "
215b30b3 5224 {
5225 rtx mem1, mem2;
5226 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
5227
788fcce0 5228 mem1 = change_address (operands[1], QImode, addr);
29c05e22 5229 mem2 = change_address (operands[1], QImode,
5230 plus_constant (Pmode, addr, 1));
215b30b3 5231 operands[0] = gen_lowpart (SImode, operands[0]);
5232 operands[1] = mem1;
5233 operands[2] = gen_reg_rtx (SImode);
5234 operands[3] = gen_reg_rtx (SImode);
5235 operands[6] = gen_reg_rtx (SImode);
5236 operands[7] = mem2;
25f7a26e 5237
215b30b3 5238 if (BYTES_BIG_ENDIAN)
5239 {
5240 operands[4] = operands[2];
5241 operands[5] = operands[3];
5242 }
5243 else
5244 {
5245 operands[4] = operands[3];
5246 operands[5] = operands[2];
5247 }
5248 }"
5249)
b11cae9e 5250
ef51b8e1 5251(define_split
5252 [(set (match_operand:SI 0 "register_operand" "")
5253 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
5254 "!arm_arch6"
5255 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
5256 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
5257{
5258 operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
5259})
5260
a2cd141b 5261(define_insn "*arm_extendhisi2"
ef51b8e1 5262 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
e3f4ccee 5263 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,Uh")))]
a2cd141b 5264 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 5265 "@
5266 #
5267 ldr%(sh%)\\t%0, %1"
5268 [(set_attr "length" "8,4")
d82e788e 5269 (set_attr "type" "alu_shift_reg,load_byte")
e3f4ccee 5270 (set_attr "predicable" "yes")]
cffb2a26 5271)
f7fbdd4a 5272
25f905c2 5273;; ??? Check Thumb-2 pool range
a2cd141b 5274(define_insn "*arm_extendhisi2_v6"
5275 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
e3f4ccee 5276 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,Uh")))]
25f905c2 5277 "TARGET_32BIT && arm_arch6"
a2cd141b 5278 "@
5279 sxth%?\\t%0, %1
25f905c2 5280 ldr%(sh%)\\t%0, %1"
6b6abc9c 5281 [(set_attr "type" "extend,load_byte")
a2cd141b 5282 (set_attr "predicable" "yes")
e3f4ccee 5283 (set_attr "predicable_short_it" "no")]
a2cd141b 5284)
5285
5286(define_insn "*arm_extendhisi2addsi"
5287 [(set (match_operand:SI 0 "s_register_operand" "=r")
5288 (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
5289 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 5290 "TARGET_INT_SIMD"
a2cd141b 5291 "sxtah%?\\t%0, %2, %1"
1b7da4ac 5292 [(set_attr "type" "alu_shift_reg")]
a2cd141b 5293)
5294
c8f69309 5295(define_expand "extendqihi2"
5296 [(set (match_dup 2)
bed7d9a5 5297 (ashift:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")
c8f69309 5298 (const_int 24)))
9c08d1fa 5299 (set (match_operand:HI 0 "s_register_operand" "")
c8f69309 5300 (ashiftrt:SI (match_dup 2)
5301 (const_int 24)))]
cffb2a26 5302 "TARGET_ARM"
c8f69309 5303 "
215b30b3 5304 {
0438d37f 5305 if (arm_arch4 && MEM_P (operands[1]))
215b30b3 5306 {
d1f9b275 5307 emit_insn (gen_rtx_SET (operands[0],
215b30b3 5308 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
5309 DONE;
5310 }
5311 if (!s_register_operand (operands[1], QImode))
5312 operands[1] = copy_to_mode_reg (QImode, operands[1]);
5313 operands[0] = gen_lowpart (SImode, operands[0]);
5314 operands[1] = gen_lowpart (SImode, operands[1]);
5315 operands[2] = gen_reg_rtx (SImode);
5316 }"
5317)
f7fbdd4a 5318
25f905c2 5319(define_insn "*arm_extendqihi_insn"
b4e8a300 5320 [(set (match_operand:HI 0 "s_register_operand" "=r")
bed7d9a5 5321 (sign_extend:HI (match_operand:QI 1 "arm_extendqisi_mem_op" "Uq")))]
cffb2a26 5322 "TARGET_ARM && arm_arch4"
25f905c2 5323 "ldr%(sb%)\\t%0, %1"
a2cd141b 5324 [(set_attr "type" "load_byte")
e3f4ccee 5325 (set_attr "predicable" "yes")]
cffb2a26 5326)
3fc2009e 5327
b11cae9e 5328(define_expand "extendqisi2"
ef51b8e1 5329 [(set (match_operand:SI 0 "s_register_operand" "")
5330 (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")))]
cffb2a26 5331 "TARGET_EITHER"
ef51b8e1 5332{
5333 if (!arm_arch4 && MEM_P (operands[1]))
5334 operands[1] = copy_to_mode_reg (QImode, operands[1]);
a2cd141b 5335
ef51b8e1 5336 if (!arm_arch6 && !MEM_P (operands[1]))
5337 {
5338 rtx t = gen_lowpart (SImode, operands[1]);
5339 rtx tmp = gen_reg_rtx (SImode);
5340 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
5341 emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (24)));
5342 DONE;
5343 }
5344})
a2cd141b 5345
ef51b8e1 5346(define_split
5347 [(set (match_operand:SI 0 "register_operand" "")
5348 (sign_extend:SI (match_operand:QI 1 "register_operand" "")))]
5349 "!arm_arch6"
5350 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
5351 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))]
5352{
5353 operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
5354})
f7fbdd4a 5355
a2cd141b 5356(define_insn "*arm_extendqisi"
ef51b8e1 5357 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5358 (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
a2cd141b 5359 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 5360 "@
5361 #
5362 ldr%(sb%)\\t%0, %1"
5363 [(set_attr "length" "8,4")
d82e788e 5364 (set_attr "type" "alu_shift_reg,load_byte")
e3f4ccee 5365 (set_attr "predicable" "yes")]
cffb2a26 5366)
3fc2009e 5367
a2cd141b 5368(define_insn "*arm_extendqisi_v6"
5369 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
bed7d9a5 5370 (sign_extend:SI
5371 (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
a2cd141b 5372 "TARGET_ARM && arm_arch6"
b4e8a300 5373 "@
5374 sxtb%?\\t%0, %1
25f905c2 5375 ldr%(sb%)\\t%0, %1"
6b6abc9c 5376 [(set_attr "type" "extend,load_byte")
e3f4ccee 5377 (set_attr "predicable" "yes")]
a2cd141b 5378)
5379
5380(define_insn "*arm_extendqisi2addsi"
5381 [(set (match_operand:SI 0 "s_register_operand" "=r")
5382 (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
5383 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 5384 "TARGET_INT_SIMD"
a2cd141b 5385 "sxtab%?\\t%0, %2, %1"
d82e788e 5386 [(set_attr "type" "alu_shift_reg")
d952d547 5387 (set_attr "predicable" "yes")
5388 (set_attr "predicable_short_it" "no")]
a2cd141b 5389)
5390
caedf871 5391(define_expand "extendsfdf2"
5392 [(set (match_operand:DF 0 "s_register_operand" "")
5393 (float_extend:DF (match_operand:SF 1 "s_register_operand" "")))]
a50d7267 5394 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
caedf871 5395 ""
5396)
9b8516be 5397
5398/* HFmode -> DFmode conversions have to go through SFmode. */
5399(define_expand "extendhfdf2"
5400 [(set (match_operand:DF 0 "general_operand" "")
5401 (float_extend:DF (match_operand:HF 1 "general_operand" "")))]
5402 "TARGET_EITHER"
5403 "
5404 {
5405 rtx op1;
5406 op1 = convert_to_mode (SFmode, operands[1], 0);
5407 op1 = convert_to_mode (DFmode, op1, 0);
5408 emit_insn (gen_movdf (operands[0], op1));
5409 DONE;
5410 }"
5411)
b11cae9e 5412\f
5413;; Move insns (including loads and stores)
5414
5415;; XXX Just some ideas about movti.
9c08d1fa 5416;; I don't think these are a good idea on the arm, there just aren't enough
5417;; registers
b11cae9e 5418;;(define_expand "loadti"
9c08d1fa 5419;; [(set (match_operand:TI 0 "s_register_operand" "")
b11cae9e 5420;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
5421;; "" "")
5422
5423;;(define_expand "storeti"
5424;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
9c08d1fa 5425;; (match_operand:TI 1 "s_register_operand" ""))]
b11cae9e 5426;; "" "")
5427
5428;;(define_expand "movti"
5429;; [(set (match_operand:TI 0 "general_operand" "")
5430;; (match_operand:TI 1 "general_operand" ""))]
5431;; ""
5432;; "
5433;;{
5434;; rtx insn;
5435;;
0438d37f 5436;; if (MEM_P (operands[0]) && MEM_P (operands[1]))
b11cae9e 5437;; operands[1] = copy_to_reg (operands[1]);
0438d37f 5438;; if (MEM_P (operands[0]))
b11cae9e 5439;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
0438d37f 5440;; else if (MEM_P (operands[1]))
b11cae9e 5441;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
5442;; else
5443;; FAIL;
5444;;
5445;; emit_insn (insn);
5446;; DONE;
5447;;}")
5448
a2f10574 5449;; Recognize garbage generated above.
b11cae9e 5450
5451;;(define_insn ""
5452;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
5453;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
5454;; ""
5455;; "*
5456;; {
5457;; register mem = (which_alternative < 3);
0d66636f 5458;; register const char *template;
b11cae9e 5459;;
5460;; operands[mem] = XEXP (operands[mem], 0);
5461;; switch (which_alternative)
5462;; {
5463;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
5464;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
5465;; case 2: template = \"ldmia\\t%1, %M0\"; break;
5466;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
5467;; case 4: template = \"stmia\\t%0!, %M1\"; break;
5468;; case 5: template = \"stmia\\t%0, %M1\"; break;
5469;; }
e2348bcb 5470;; output_asm_insn (template, operands);
5471;; return \"\";
b11cae9e 5472;; }")
5473
cffb2a26 5474(define_expand "movdi"
5475 [(set (match_operand:DI 0 "general_operand" "")
5476 (match_operand:DI 1 "general_operand" ""))]
5477 "TARGET_EITHER"
5478 "
e1ba4a27 5479 if (can_create_pseudo_p ())
cffb2a26 5480 {
0438d37f 5481 if (!REG_P (operands[0]))
b2778788 5482 operands[1] = force_reg (DImode, operands[1]);
cffb2a26 5483 }
5484 "
5485)
b11cae9e 5486
cffb2a26 5487(define_insn "*arm_movdi"
353cf59a 5488 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, q, m")
5489 (match_operand:DI 1 "di_operand" "rDa,Db,Dc,mi,q"))]
cde1623a 5490 "TARGET_32BIT
b805622c 5491 && !(TARGET_HARD_FLOAT && TARGET_VFP)
b2778788 5492 && !TARGET_IWMMXT
5493 && ( register_operand (operands[0], DImode)
5494 || register_operand (operands[1], DImode))"
b11cae9e 5495 "*
d51f92df 5496 switch (which_alternative)
5497 {
5498 case 0:
5499 case 1:
5500 case 2:
5501 return \"#\";
5502 default:
26ff80c0 5503 return output_move_double (operands, true, NULL);
d51f92df 5504 }
cffb2a26 5505 "
359a6e9f 5506 [(set_attr "length" "8,12,16,8,8")
1b7da4ac 5507 (set_attr "type" "multiple,multiple,multiple,load2,store2")
cde1623a 5508 (set_attr "arm_pool_range" "*,*,*,1020,*")
8848d797 5509 (set_attr "arm_neg_pool_range" "*,*,*,1004,*")
42e1de19 5510 (set_attr "thumb2_pool_range" "*,*,*,4094,*")
cde1623a 5511 (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
cffb2a26 5512)
5513
d51f92df 5514(define_split
5515 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
e6dd3afa 5516 (match_operand:ANY64 1 "immediate_operand" ""))]
25f905c2 5517 "TARGET_32BIT
d51f92df 5518 && reload_completed
5519 && (arm_const_double_inline_cost (operands[1])
861033d5 5520 <= arm_max_const_double_inline_cost ())"
d51f92df 5521 [(const_int 0)]
5522 "
5523 arm_split_constant (SET, SImode, curr_insn,
5524 INTVAL (gen_lowpart (SImode, operands[1])),
5525 gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
5526 arm_split_constant (SET, SImode, curr_insn,
5527 INTVAL (gen_highpart_mode (SImode,
5528 GET_MODE (operands[0]),
5529 operands[1])),
5530 gen_highpart (SImode, operands[0]), NULL_RTX, 0);
5531 DONE;
5532 "
5533)
5534
e5ba9289 5535; If optimizing for size, or if we have load delay slots, then
5536; we want to split the constant into two separate operations.
5537; In both cases this may split a trivial part into a single data op
5538; leaving a single complex constant to load. We can also get longer
5539; offsets in a LDR which means we get better chances of sharing the pool
5540; entries. Finally, we can normally do a better job of scheduling
5541; LDR instructions than we can with LDM.
5542; This pattern will only match if the one above did not.
5543(define_split
5544 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
5545 (match_operand:ANY64 1 "const_double_operand" ""))]
5546 "TARGET_ARM && reload_completed
5547 && arm_const_double_by_parts (operands[1])"
5548 [(set (match_dup 0) (match_dup 1))
5549 (set (match_dup 2) (match_dup 3))]
5550 "
5551 operands[2] = gen_highpart (SImode, operands[0]);
5552 operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
5553 operands[1]);
5554 operands[0] = gen_lowpart (SImode, operands[0]);
5555 operands[1] = gen_lowpart (SImode, operands[1]);
5556 "
5557)
5558
d51f92df 5559(define_split
5560 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
5561 (match_operand:ANY64 1 "arm_general_register_operand" ""))]
5562 "TARGET_EITHER && reload_completed"
5563 [(set (match_dup 0) (match_dup 1))
5564 (set (match_dup 2) (match_dup 3))]
5565 "
5566 operands[2] = gen_highpart (SImode, operands[0]);
5567 operands[3] = gen_highpart (SImode, operands[1]);
5568 operands[0] = gen_lowpart (SImode, operands[0]);
5569 operands[1] = gen_lowpart (SImode, operands[1]);
5570
5571 /* Handle a partial overlap. */
5572 if (rtx_equal_p (operands[0], operands[3]))
5573 {
5574 rtx tmp0 = operands[0];
5575 rtx tmp1 = operands[1];
5576
5577 operands[0] = operands[2];
5578 operands[1] = operands[3];
5579 operands[2] = tmp0;
5580 operands[3] = tmp1;
5581 }
5582 "
5583)
5584
a8a3b539 5585;; We can't actually do base+index doubleword loads if the index and
5586;; destination overlap. Split here so that we at least have chance to
5587;; schedule.
5588(define_split
5589 [(set (match_operand:DI 0 "s_register_operand" "")
5590 (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
5591 (match_operand:SI 2 "s_register_operand" ""))))]
5592 "TARGET_LDRD
5593 && reg_overlap_mentioned_p (operands[0], operands[1])
5594 && reg_overlap_mentioned_p (operands[0], operands[2])"
5595 [(set (match_dup 4)
5596 (plus:SI (match_dup 1)
5597 (match_dup 2)))
5598 (set (match_dup 0)
5599 (mem:DI (match_dup 4)))]
5600 "
5601 operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
5602 "
5603)
5604
9c08d1fa 5605(define_expand "movsi"
5606 [(set (match_operand:SI 0 "general_operand" "")
5607 (match_operand:SI 1 "general_operand" ""))]
cffb2a26 5608 "TARGET_EITHER"
9c08d1fa 5609 "
befb0bac 5610 {
e348ff3e 5611 rtx base, offset, tmp;
5612
25f905c2 5613 if (TARGET_32BIT)
9c08d1fa 5614 {
674a8f0b 5615 /* Everything except mem = const or mem = mem can be done easily. */
0438d37f 5616 if (MEM_P (operands[0]))
cffb2a26 5617 operands[1] = force_reg (SImode, operands[1]);
a2cd141b 5618 if (arm_general_register_operand (operands[0], SImode)
0438d37f 5619 && CONST_INT_P (operands[1])
cffb2a26 5620 && !(const_ok_for_arm (INTVAL (operands[1]))
5621 || const_ok_for_arm (~INTVAL (operands[1]))))
5622 {
17202aa5 5623 if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[1]), SET))
5624 {
5625 emit_insn (gen_rtx_SET (operands[0], operands[1]));
5626 DONE;
5627 }
5628 else
5629 {
5630 arm_split_constant (SET, SImode, NULL_RTX,
5631 INTVAL (operands[1]), operands[0], NULL_RTX,
5632 optimize && can_create_pseudo_p ());
5633 DONE;
5634 }
cffb2a26 5635 }
5636 }
25f905c2 5637 else /* TARGET_THUMB1... */
cffb2a26 5638 {
e1ba4a27 5639 if (can_create_pseudo_p ())
cffb2a26 5640 {
0438d37f 5641 if (!REG_P (operands[0]))
cffb2a26 5642 operands[1] = force_reg (SImode, operands[1]);
5643 }
9c08d1fa 5644 }
f655717d 5645
e348ff3e 5646 if (ARM_OFFSETS_MUST_BE_WITHIN_SECTIONS_P)
5647 {
5648 split_const (operands[1], &base, &offset);
5649 if (GET_CODE (base) == SYMBOL_REF
5650 && !offset_within_block_p (base, INTVAL (offset)))
5651 {
b308ddcf 5652 tmp = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
e348ff3e 5653 emit_move_insn (tmp, base);
5654 emit_insn (gen_addsi3 (operands[0], tmp, offset));
5655 DONE;
5656 }
5657 }
5658
f655717d 5659 /* Recognize the case where operand[1] is a reference to thread-local
5660 data and load its address to a register. */
5661 if (arm_tls_referenced_p (operands[1]))
5662 {
5663 rtx tmp = operands[1];
5664 rtx addend = NULL;
5665
5666 if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
5667 {
5668 addend = XEXP (XEXP (tmp, 0), 1);
5669 tmp = XEXP (XEXP (tmp, 0), 0);
5670 }
5671
5672 gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
5673 gcc_assert (SYMBOL_REF_TLS_MODEL (tmp) != 0);
5674
e1ba4a27 5675 tmp = legitimize_tls_address (tmp,
5676 !can_create_pseudo_p () ? operands[0] : 0);
f655717d 5677 if (addend)
5678 {
5679 tmp = gen_rtx_PLUS (SImode, tmp, addend);
5680 tmp = force_operand (tmp, operands[0]);
5681 }
5682 operands[1] = tmp;
5683 }
5684 else if (flag_pic
5685 && (CONSTANT_P (operands[1])
5686 || symbol_mentioned_p (operands[1])
5687 || label_mentioned_p (operands[1])))
5688 operands[1] = legitimize_pic_address (operands[1], SImode,
e1ba4a27 5689 (!can_create_pseudo_p ()
5690 ? operands[0]
5691 : 0));
befb0bac 5692 }
215b30b3 5693 "
5694)
9c08d1fa 5695
d0e6a121 5696;; The ARM LO_SUM and HIGH are backwards - HIGH sets the low bits, and
5697;; LO_SUM adds in the high bits. Fortunately these are opaque operations
5698;; so this does not matter.
5699(define_insn "*arm_movt"
5700 [(set (match_operand:SI 0 "nonimmediate_operand" "=r")
5701 (lo_sum:SI (match_operand:SI 1 "nonimmediate_operand" "0")
5702 (match_operand:SI 2 "general_operand" "i")))]
c9b2ce40 5703 "arm_arch_thumb2"
d0e6a121 5704 "movt%?\t%0, #:upper16:%c2"
5705 [(set_attr "predicable" "yes")
d952d547 5706 (set_attr "predicable_short_it" "no")
1b7da4ac 5707 (set_attr "length" "4")
282b4c75 5708 (set_attr "type" "alu_sreg")]
d0e6a121 5709)
5710
cffb2a26 5711(define_insn "*arm_movsi_insn"
aaa37ad6 5712 [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,rk,m")
110eae03 5713 (match_operand:SI 1 "general_operand" "rk, I,K,j,mi,rk"))]
755eb2b4 5714 "TARGET_ARM && ! TARGET_IWMMXT
a2cd141b 5715 && !(TARGET_HARD_FLOAT && TARGET_VFP)
cffb2a26 5716 && ( register_operand (operands[0], SImode)
5717 || register_operand (operands[1], SImode))"
f7fbdd4a 5718 "@
aaa37ad6 5719 mov%?\\t%0, %1
f7fbdd4a 5720 mov%?\\t%0, %1
5721 mvn%?\\t%0, #%B1
25f905c2 5722 movw%?\\t%0, %1
f7fbdd4a 5723 ldr%?\\t%0, %1
5724 str%?\\t%1, %0"
1aed5204 5725 [(set_attr "type" "mov_reg,mov_imm,mvn_imm,mov_imm,load1,store1")
0d66636f 5726 (set_attr "predicable" "yes")
aaa37ad6 5727 (set_attr "pool_range" "*,*,*,*,4096,*")
5728 (set_attr "neg_pool_range" "*,*,*,*,4084,*")]
cffb2a26 5729)
87b22bf7 5730
5731(define_split
a2cd141b 5732 [(set (match_operand:SI 0 "arm_general_register_operand" "")
87b22bf7 5733 (match_operand:SI 1 "const_int_operand" ""))]
25f905c2 5734 "TARGET_32BIT
215b30b3 5735 && (!(const_ok_for_arm (INTVAL (operands[1]))
5736 || const_ok_for_arm (~INTVAL (operands[1]))))"
87b22bf7 5737 [(clobber (const_int 0))]
5738 "
96f57e36 5739 arm_split_constant (SET, SImode, NULL_RTX,
5740 INTVAL (operands[1]), operands[0], NULL_RTX, 0);
87b22bf7 5741 DONE;
215b30b3 5742 "
5743)
9c08d1fa 5744
861033d5 5745;; A normal way to do (symbol + offset) requires three instructions at least
5746;; (depends on how big the offset is) as below:
5747;; movw r0, #:lower16:g
5748;; movw r0, #:upper16:g
5749;; adds r0, #4
5750;;
5751;; A better way would be:
5752;; movw r0, #:lower16:g+4
5753;; movw r0, #:upper16:g+4
5754;;
5755;; The limitation of this way is that the length of offset should be a 16-bit
5756;; signed value, because current assembler only supports REL type relocation for
5757;; such case. If the more powerful RELA type is supported in future, we should
5758;; update this pattern to go with better way.
5759(define_split
5760 [(set (match_operand:SI 0 "arm_general_register_operand" "")
5761 (const:SI (plus:SI (match_operand:SI 1 "general_operand" "")
5762 (match_operand:SI 2 "const_int_operand" ""))))]
5763 "TARGET_THUMB2
5764 && arm_disable_literal_pool
5765 && reload_completed
5766 && GET_CODE (operands[1]) == SYMBOL_REF"
5767 [(clobber (const_int 0))]
5768 "
5769 int offset = INTVAL (operands[2]);
5770
5771 if (offset < -0x8000 || offset > 0x7fff)
5772 {
5773 arm_emit_movpair (operands[0], operands[1]);
d1f9b275 5774 emit_insn (gen_rtx_SET (operands[0],
861033d5 5775 gen_rtx_PLUS (SImode, operands[0], operands[2])));
5776 }
5777 else
5778 {
5779 rtx op = gen_rtx_CONST (SImode,
5780 gen_rtx_PLUS (SImode, operands[1], operands[2]));
5781 arm_emit_movpair (operands[0], op);
5782 }
5783 "
5784)
5785
b8d5d078 5786;; Split symbol_refs at the later stage (after cprop), instead of generating
5787;; movt/movw pair directly at expand. Otherwise corresponding high_sum
5788;; and lo_sum would be merged back into memory load at cprop. However,
5789;; if the default is to prefer movt/movw rather than a load from the constant
5790;; pool, the performance is better.
5791(define_split
5792 [(set (match_operand:SI 0 "arm_general_register_operand" "")
5793 (match_operand:SI 1 "general_operand" ""))]
5794 "TARGET_32BIT
5795 && TARGET_USE_MOVT && GET_CODE (operands[1]) == SYMBOL_REF
5796 && !flag_pic && !target_word_relocations
5797 && !arm_tls_referenced_p (operands[1])"
5798 [(clobber (const_int 0))]
5799{
5800 arm_emit_movpair (operands[0], operands[1]);
5801 DONE;
5802})
5803
bc360af8 5804;; When generating pic, we need to load the symbol offset into a register.
5805;; So that the optimizer does not confuse this with a normal symbol load
5806;; we use an unspec. The offset will be loaded from a constant pool entry,
5807;; since that is the only type of relocation we can use.
cffb2a26 5808
bc360af8 5809;; Wrap calculation of the whole PIC address in a single pattern for the
5810;; benefit of optimizers, particularly, PRE and HOIST. Calculation of
5811;; a PIC address involves two loads from memory, so we want to CSE it
5812;; as often as possible.
5813;; This pattern will be split into one of the pic_load_addr_* patterns
5814;; and a move after GCSE optimizations.
5815;;
5816;; Note: Update arm.c: legitimize_pic_address() when changing this pattern.
5817(define_expand "calculate_pic_address"
94f8caca 5818 [(set (match_operand:SI 0 "register_operand" "")
5819 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "")
5820 (unspec:SI [(match_operand:SI 2 "" "")]
5821 UNSPEC_PIC_SYM))))]
5822 "flag_pic"
5823)
5824
5825;; Split calculate_pic_address into pic_load_addr_* and a move.
5826(define_split
5827 [(set (match_operand:SI 0 "register_operand" "")
5828 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "")
5829 (unspec:SI [(match_operand:SI 2 "" "")]
5830 UNSPEC_PIC_SYM))))]
5831 "flag_pic"
5832 [(set (match_dup 3) (unspec:SI [(match_dup 2)] UNSPEC_PIC_SYM))
5833 (set (match_dup 0) (mem:SI (plus:SI (match_dup 1) (match_dup 3))))]
5834 "operands[3] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];"
5835)
5836
350ccca5 5837;; operand1 is the memory address to go into
5838;; pic_load_addr_32bit.
5839;; operand2 is the PIC label to be emitted
5840;; from pic_add_dot_plus_eight.
5841;; We do this to allow hoisting of the entire insn.
5842(define_insn_and_split "pic_load_addr_unified"
5843 [(set (match_operand:SI 0 "s_register_operand" "=r,r,l")
5844 (unspec:SI [(match_operand:SI 1 "" "mX,mX,mX")
5845 (match_operand:SI 2 "" "")]
5846 UNSPEC_PIC_UNIFIED))]
5847 "flag_pic"
5848 "#"
5849 "&& reload_completed"
5850 [(set (match_dup 0) (unspec:SI [(match_dup 1)] UNSPEC_PIC_SYM))
5851 (set (match_dup 0) (unspec:SI [(match_dup 0) (match_dup 3)
5852 (match_dup 2)] UNSPEC_PIC_BASE))]
5853 "operands[3] = TARGET_THUMB ? GEN_INT (4) : GEN_INT (8);"
5854 [(set_attr "type" "load1,load1,load1")
42e1de19 5855 (set_attr "pool_range" "4096,4094,1022")
350ccca5 5856 (set_attr "neg_pool_range" "4084,0,0")
5857 (set_attr "arch" "a,t2,t1")
5858 (set_attr "length" "8,6,4")]
5859)
5860
67336bcf 5861;; The rather odd constraints on the following are to force reload to leave
5862;; the insn alone, and to force the minipool generation pass to then move
5863;; the GOT symbol to memory.
849170fd 5864
b3cd5f55 5865(define_insn "pic_load_addr_32bit"
849170fd 5866 [(set (match_operand:SI 0 "s_register_operand" "=r")
e1159bbe 5867 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
b3cd5f55 5868 "TARGET_32BIT && flag_pic"
67336bcf 5869 "ldr%?\\t%0, %1"
a2cd141b 5870 [(set_attr "type" "load1")
42e1de19 5871 (set (attr "pool_range")
5872 (if_then_else (eq_attr "is_thumb" "no")
5873 (const_int 4096)
5874 (const_int 4094)))
b3cd5f55 5875 (set (attr "neg_pool_range")
5876 (if_then_else (eq_attr "is_thumb" "no")
5877 (const_int 4084)
5878 (const_int 0)))]
8c4d8060 5879)
5880
25f905c2 5881(define_insn "pic_load_addr_thumb1"
8c4d8060 5882 [(set (match_operand:SI 0 "s_register_operand" "=l")
e1159bbe 5883 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
25f905c2 5884 "TARGET_THUMB1 && flag_pic"
8c4d8060 5885 "ldr\\t%0, %1"
a2cd141b 5886 [(set_attr "type" "load1")
42e1de19 5887 (set (attr "pool_range") (const_int 1018))]
cffb2a26 5888)
849170fd 5889
cffb2a26 5890(define_insn "pic_add_dot_plus_four"
15d5d060 5891 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5892 (unspec:SI [(match_operand:SI 1 "register_operand" "0")
5893 (const_int 4)
beef0fb5 5894 (match_operand 2 "" "")]
5895 UNSPEC_PIC_BASE))]
b3cd5f55 5896 "TARGET_THUMB"
cffb2a26 5897 "*
6cdcb15c 5898 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5899 INTVAL (operands[2]));
cffb2a26 5900 return \"add\\t%0, %|pc\";
5901 "
1b7da4ac 5902 [(set_attr "length" "2")
112eda6f 5903 (set_attr "type" "alu_sreg")]
cffb2a26 5904)
849170fd 5905
5906(define_insn "pic_add_dot_plus_eight"
15d5d060 5907 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5908 (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5909 (const_int 8)
beef0fb5 5910 (match_operand 2 "" "")]
5911 UNSPEC_PIC_BASE))]
f655717d 5912 "TARGET_ARM"
c4034607 5913 "*
6cdcb15c 5914 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5915 INTVAL (operands[2]));
15d5d060 5916 return \"add%?\\t%0, %|pc, %1\";
cffb2a26 5917 "
1b7da4ac 5918 [(set_attr "predicable" "yes")
112eda6f 5919 (set_attr "type" "alu_sreg")]
cffb2a26 5920)
849170fd 5921
f655717d 5922(define_insn "tls_load_dot_plus_eight"
cc071db6 5923 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5924 (mem:SI (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5925 (const_int 8)
beef0fb5 5926 (match_operand 2 "" "")]
5927 UNSPEC_PIC_BASE)))]
f655717d 5928 "TARGET_ARM"
5929 "*
6cdcb15c 5930 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5931 INTVAL (operands[2]));
f655717d 5932 return \"ldr%?\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_eight\";
5933 "
1b7da4ac 5934 [(set_attr "predicable" "yes")
5935 (set_attr "type" "load1")]
f655717d 5936)
5937
5938;; PIC references to local variables can generate pic_add_dot_plus_eight
5939;; followed by a load. These sequences can be crunched down to
5940;; tls_load_dot_plus_eight by a peephole.
5941
5942(define_peephole2
c0c1fba5 5943 [(set (match_operand:SI 0 "register_operand" "")
5944 (unspec:SI [(match_operand:SI 3 "register_operand" "")
5945 (const_int 8)
5946 (match_operand 1 "" "")]
5947 UNSPEC_PIC_BASE))
2d05dfad 5948 (set (match_operand:SI 2 "arm_general_register_operand" "")
5949 (mem:SI (match_dup 0)))]
f655717d 5950 "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
c0c1fba5 5951 [(set (match_dup 2)
5952 (mem:SI (unspec:SI [(match_dup 3)
5953 (const_int 8)
5954 (match_dup 1)]
5955 UNSPEC_PIC_BASE)))]
f655717d 5956 ""
5957)
5958
bac7fc85 5959(define_insn "pic_offset_arm"
5960 [(set (match_operand:SI 0 "register_operand" "=r")
5961 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
5962 (unspec:SI [(match_operand:SI 2 "" "X")]
5963 UNSPEC_PIC_OFFSET))))]
5964 "TARGET_VXWORKS_RTP && TARGET_ARM && flag_pic"
5965 "ldr%?\\t%0, [%1,%2]"
5966 [(set_attr "type" "load1")]
5967)
5968
95373f08 5969(define_expand "builtin_setjmp_receiver"
5970 [(label_ref (match_operand 0 "" ""))]
5971 "flag_pic"
5972 "
5973{
b935b306 5974 /* r3 is clobbered by set/longjmp, so we can use it as a scratch
5975 register. */
2cb7d577 5976 if (arm_pic_register != INVALID_REGNUM)
5977 arm_load_pic_register (1UL << 3);
95373f08 5978 DONE;
5979}")
5980
9c08d1fa 5981;; If copying one reg to another we can set the condition codes according to
5982;; its value. Such a move is common after a return from subroutine and the
5983;; result is being tested against zero.
5984
f7fbdd4a 5985(define_insn "*movsi_compare0"
bd5b4116 5986 [(set (reg:CC CC_REGNUM)
cffb2a26 5987 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
5988 (const_int 0)))
5989 (set (match_operand:SI 0 "s_register_operand" "=r,r")
5990 (match_dup 1))]
25f905c2 5991 "TARGET_32BIT"
e2348bcb 5992 "@
40dbec34 5993 cmp%?\\t%0, #0
25f905c2 5994 sub%.\\t%0, %1, #0"
65f68e55 5995 [(set_attr "conds" "set")
d82e788e 5996 (set_attr "type" "alus_imm,alus_imm")]
cffb2a26 5997)
b11cae9e 5998
b11cae9e 5999;; Subroutine to store a half word from a register into memory.
6000;; Operand 0 is the source register (HImode)
c8f69309 6001;; Operand 1 is the destination address in a register (SImode)
b11cae9e 6002
9c08d1fa 6003;; In both this routine and the next, we must be careful not to spill
01cc3b75 6004;; a memory address of reg+large_const into a separate PLUS insn, since this
9c08d1fa 6005;; can generate unrecognizable rtl.
6006
b11cae9e 6007(define_expand "storehi"
c8f69309 6008 [;; store the low byte
f082f1c4 6009 (set (match_operand 1 "" "") (match_dup 3))
b11cae9e 6010 ;; extract the high byte
c8f69309 6011 (set (match_dup 2)
6012 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
b11cae9e 6013 ;; store the high byte
787f8210 6014 (set (match_dup 4) (match_dup 5))]
cffb2a26 6015 "TARGET_ARM"
b11cae9e 6016 "
215b30b3 6017 {
537ffcfc 6018 rtx op1 = operands[1];
6019 rtx addr = XEXP (op1, 0);
215b30b3 6020 enum rtx_code code = GET_CODE (addr);
6021
0438d37f 6022 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
215b30b3 6023 || code == MINUS)
537ffcfc 6024 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
215b30b3 6025
537ffcfc 6026 operands[4] = adjust_address (op1, QImode, 1);
e513d163 6027 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 6028 operands[3] = gen_lowpart (QImode, operands[0]);
6029 operands[0] = gen_lowpart (SImode, operands[0]);
787f8210 6030 operands[2] = gen_reg_rtx (SImode);
6031 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 6032 }"
6033)
b11cae9e 6034
c7597b5d 6035(define_expand "storehi_bigend"
f082f1c4 6036 [(set (match_dup 4) (match_dup 3))
c7597b5d 6037 (set (match_dup 2)
6038 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
787f8210 6039 (set (match_operand 1 "" "") (match_dup 5))]
cffb2a26 6040 "TARGET_ARM"
b11cae9e 6041 "
215b30b3 6042 {
537ffcfc 6043 rtx op1 = operands[1];
6044 rtx addr = XEXP (op1, 0);
215b30b3 6045 enum rtx_code code = GET_CODE (addr);
6046
0438d37f 6047 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
215b30b3 6048 || code == MINUS)
537ffcfc 6049 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
215b30b3 6050
537ffcfc 6051 operands[4] = adjust_address (op1, QImode, 1);
e513d163 6052 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 6053 operands[3] = gen_lowpart (QImode, operands[0]);
6054 operands[0] = gen_lowpart (SImode, operands[0]);
6055 operands[2] = gen_reg_rtx (SImode);
787f8210 6056 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 6057 }"
6058)
c7597b5d 6059
6060;; Subroutine to store a half word integer constant into memory.
6061(define_expand "storeinthi"
f082f1c4 6062 [(set (match_operand 0 "" "")
787f8210 6063 (match_operand 1 "" ""))
9e8503e6 6064 (set (match_dup 3) (match_dup 2))]
cffb2a26 6065 "TARGET_ARM"
c7597b5d 6066 "
215b30b3 6067 {
6068 HOST_WIDE_INT value = INTVAL (operands[1]);
6069 rtx addr = XEXP (operands[0], 0);
537ffcfc 6070 rtx op0 = operands[0];
215b30b3 6071 enum rtx_code code = GET_CODE (addr);
c7597b5d 6072
0438d37f 6073 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
215b30b3 6074 || code == MINUS)
537ffcfc 6075 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
c7597b5d 6076
215b30b3 6077 operands[1] = gen_reg_rtx (SImode);
6078 if (BYTES_BIG_ENDIAN)
6079 {
6080 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
6081 if ((value & 255) == ((value >> 8) & 255))
6082 operands[2] = operands[1];
6083 else
6084 {
6085 operands[2] = gen_reg_rtx (SImode);
6086 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
6087 }
6088 }
6089 else
6090 {
6091 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
6092 if ((value & 255) == ((value >> 8) & 255))
6093 operands[2] = operands[1];
6094 else
6095 {
6096 operands[2] = gen_reg_rtx (SImode);
6097 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
6098 }
6099 }
c7597b5d 6100
537ffcfc 6101 operands[3] = adjust_address (op0, QImode, 1);
e513d163 6102 operands[0] = adjust_address (operands[0], QImode, 0);
9e8503e6 6103 operands[2] = gen_lowpart (QImode, operands[2]);
787f8210 6104 operands[1] = gen_lowpart (QImode, operands[1]);
215b30b3 6105 }"
6106)
b11cae9e 6107
f7fbdd4a 6108(define_expand "storehi_single_op"
6109 [(set (match_operand:HI 0 "memory_operand" "")
6110 (match_operand:HI 1 "general_operand" ""))]
25f905c2 6111 "TARGET_32BIT && arm_arch4"
f7fbdd4a 6112 "
215b30b3 6113 if (!s_register_operand (operands[1], HImode))
f7fbdd4a 6114 operands[1] = copy_to_mode_reg (HImode, operands[1]);
215b30b3 6115 "
6116)
f7fbdd4a 6117
b11cae9e 6118(define_expand "movhi"
6119 [(set (match_operand:HI 0 "general_operand" "")
c8f69309 6120 (match_operand:HI 1 "general_operand" ""))]
cffb2a26 6121 "TARGET_EITHER"
b11cae9e 6122 "
cffb2a26 6123 if (TARGET_ARM)
b11cae9e 6124 {
e1ba4a27 6125 if (can_create_pseudo_p ())
cffb2a26 6126 {
0438d37f 6127 if (MEM_P (operands[0]))
b11cae9e 6128 {
cffb2a26 6129 if (arm_arch4)
6130 {
6131 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
6132 DONE;
6133 }
0438d37f 6134 if (CONST_INT_P (operands[1]))
cffb2a26 6135 emit_insn (gen_storeinthi (operands[0], operands[1]));
c7597b5d 6136 else
cffb2a26 6137 {
0438d37f 6138 if (MEM_P (operands[1]))
cffb2a26 6139 operands[1] = force_reg (HImode, operands[1]);
6140 if (BYTES_BIG_ENDIAN)
6141 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
6142 else
6143 emit_insn (gen_storehi (operands[1], operands[0]));
6144 }
6145 DONE;
b11cae9e 6146 }
cffb2a26 6147 /* Sign extend a constant, and keep it in an SImode reg. */
0438d37f 6148 else if (CONST_INT_P (operands[1]))
9c08d1fa 6149 {
cffb2a26 6150 rtx reg = gen_reg_rtx (SImode);
6151 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
6152
6153 /* If the constant is already valid, leave it alone. */
215b30b3 6154 if (!const_ok_for_arm (val))
cffb2a26 6155 {
6156 /* If setting all the top bits will make the constant
6157 loadable in a single instruction, then set them.
6158 Otherwise, sign extend the number. */
6159
215b30b3 6160 if (const_ok_for_arm (~(val | ~0xffff)))
cffb2a26 6161 val |= ~0xffff;
6162 else if (val & 0x8000)
6163 val |= ~0xffff;
6164 }
6165
6166 emit_insn (gen_movsi (reg, GEN_INT (val)));
9e8503e6 6167 operands[1] = gen_lowpart (HImode, reg);
9c08d1fa 6168 }
e1ba4a27 6169 else if (arm_arch4 && optimize && can_create_pseudo_p ()
0438d37f 6170 && MEM_P (operands[1]))
0045890a 6171 {
6172 rtx reg = gen_reg_rtx (SImode);
6173
6174 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
6175 operands[1] = gen_lowpart (HImode, reg);
6176 }
215b30b3 6177 else if (!arm_arch4)
f7fbdd4a 6178 {
0438d37f 6179 if (MEM_P (operands[1]))
cffb2a26 6180 {
c1a66faf 6181 rtx base;
6182 rtx offset = const0_rtx;
6183 rtx reg = gen_reg_rtx (SImode);
6184
0438d37f 6185 if ((REG_P (base = XEXP (operands[1], 0))
c1a66faf 6186 || (GET_CODE (base) == PLUS
0438d37f 6187 && (CONST_INT_P (offset = XEXP (base, 1)))
c1a66faf 6188 && ((INTVAL(offset) & 1) != 1)
0438d37f 6189 && REG_P (base = XEXP (base, 0))))
c1a66faf 6190 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
206ee9a2 6191 {
8deb3959 6192 rtx new_rtx;
c1a66faf 6193
8deb3959 6194 new_rtx = widen_memory_access (operands[1], SImode,
6195 ((INTVAL (offset) & ~3)
6196 - INTVAL (offset)));
6197 emit_insn (gen_movsi (reg, new_rtx));
c1a66faf 6198 if (((INTVAL (offset) & 2) != 0)
6199 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
6200 {
6201 rtx reg2 = gen_reg_rtx (SImode);
6202
6203 emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
6204 reg = reg2;
6205 }
206ee9a2 6206 }
c1a66faf 6207 else
6208 emit_insn (gen_movhi_bytes (reg, operands[1]));
6209
6210 operands[1] = gen_lowpart (HImode, reg);
cffb2a26 6211 }
6212 }
6213 }
674a8f0b 6214 /* Handle loading a large integer during reload. */
0438d37f 6215 else if (CONST_INT_P (operands[1])
215b30b3 6216 && !const_ok_for_arm (INTVAL (operands[1]))
6217 && !const_ok_for_arm (~INTVAL (operands[1])))
cffb2a26 6218 {
6219 /* Writing a constant to memory needs a scratch, which should
6220 be handled with SECONDARY_RELOADs. */
0438d37f 6221 gcc_assert (REG_P (operands[0]));
cffb2a26 6222
6223 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
6224 emit_insn (gen_movsi (operands[0], operands[1]));
6225 DONE;
6226 }
6227 }
25f905c2 6228 else if (TARGET_THUMB2)
6229 {
6230 /* Thumb-2 can do everything except mem=mem and mem=const easily. */
e1ba4a27 6231 if (can_create_pseudo_p ())
25f905c2 6232 {
0438d37f 6233 if (!REG_P (operands[0]))
25f905c2 6234 operands[1] = force_reg (HImode, operands[1]);
6235 /* Zero extend a constant, and keep it in an SImode reg. */
0438d37f 6236 else if (CONST_INT_P (operands[1]))
25f905c2 6237 {
6238 rtx reg = gen_reg_rtx (SImode);
6239 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
6240
6241 emit_insn (gen_movsi (reg, GEN_INT (val)));
6242 operands[1] = gen_lowpart (HImode, reg);
6243 }
6244 }
6245 }
6246 else /* TARGET_THUMB1 */
cffb2a26 6247 {
e1ba4a27 6248 if (can_create_pseudo_p ())
cffb2a26 6249 {
0438d37f 6250 if (CONST_INT_P (operands[1]))
6cffc037 6251 {
6252 rtx reg = gen_reg_rtx (SImode);
6253
6254 emit_insn (gen_movsi (reg, operands[1]));
6255 operands[1] = gen_lowpart (HImode, reg);
6256 }
cffb2a26 6257
6258 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 6259 happen if we are passed a SP (never OK for HImode/QImode) or
bc409cb4 6260 virtual register (also rejected as illegitimate for HImode/QImode)
6261 relative address. */
cffb2a26 6262 /* ??? This should perhaps be fixed elsewhere, for instance, in
6263 fixup_stack_1, by checking for other kinds of invalid addresses,
6264 e.g. a bare reference to a virtual register. This may confuse the
6265 alpha though, which must handle this case differently. */
0438d37f 6266 if (MEM_P (operands[0])
215b30b3 6267 && !memory_address_p (GET_MODE (operands[0]),
6268 XEXP (operands[0], 0)))
537ffcfc 6269 operands[0]
6270 = replace_equiv_address (operands[0],
6271 copy_to_reg (XEXP (operands[0], 0)));
cffb2a26 6272
0438d37f 6273 if (MEM_P (operands[1])
215b30b3 6274 && !memory_address_p (GET_MODE (operands[1]),
6275 XEXP (operands[1], 0)))
537ffcfc 6276 operands[1]
6277 = replace_equiv_address (operands[1],
6278 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 6279
0438d37f 6280 if (MEM_P (operands[1]) && optimize > 0)
6cffc037 6281 {
6282 rtx reg = gen_reg_rtx (SImode);
6283
6284 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
6285 operands[1] = gen_lowpart (HImode, reg);
6286 }
6287
0438d37f 6288 if (MEM_P (operands[0]))
6cffc037 6289 operands[1] = force_reg (HImode, operands[1]);
cffb2a26 6290 }
0438d37f 6291 else if (CONST_INT_P (operands[1])
234f6557 6292 && !satisfies_constraint_I (operands[1]))
cffb2a26 6293 {
6cffc037 6294 /* Handle loading a large integer during reload. */
6295
cffb2a26 6296 /* Writing a constant to memory needs a scratch, which should
6297 be handled with SECONDARY_RELOADs. */
0438d37f 6298 gcc_assert (REG_P (operands[0]));
cffb2a26 6299
1a83b3ff 6300 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
cffb2a26 6301 emit_insn (gen_movsi (operands[0], operands[1]));
6302 DONE;
6303 }
b11cae9e 6304 }
cffb2a26 6305 "
6306)
6307
25f7a26e 6308(define_expand "movhi_bytes"
eab14235 6309 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 6310 (set (match_dup 3)
eab14235 6311 (zero_extend:SI (match_dup 6)))
25f7a26e 6312 (set (match_operand:SI 0 "" "")
6313 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
cffb2a26 6314 "TARGET_ARM"
25f7a26e 6315 "
215b30b3 6316 {
6317 rtx mem1, mem2;
6318 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
6319
788fcce0 6320 mem1 = change_address (operands[1], QImode, addr);
29c05e22 6321 mem2 = change_address (operands[1], QImode,
6322 plus_constant (Pmode, addr, 1));
215b30b3 6323 operands[0] = gen_lowpart (SImode, operands[0]);
6324 operands[1] = mem1;
6325 operands[2] = gen_reg_rtx (SImode);
6326 operands[3] = gen_reg_rtx (SImode);
6327 operands[6] = mem2;
25f7a26e 6328
215b30b3 6329 if (BYTES_BIG_ENDIAN)
6330 {
6331 operands[4] = operands[2];
6332 operands[5] = operands[3];
6333 }
6334 else
6335 {
6336 operands[4] = operands[3];
6337 operands[5] = operands[2];
6338 }
6339 }"
6340)
25f7a26e 6341
c7597b5d 6342(define_expand "movhi_bigend"
6343 [(set (match_dup 2)
6344 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
6345 (const_int 16)))
6346 (set (match_dup 3)
6347 (ashiftrt:SI (match_dup 2) (const_int 16)))
6348 (set (match_operand:HI 0 "s_register_operand" "")
787f8210 6349 (match_dup 4))]
cffb2a26 6350 "TARGET_ARM"
c7597b5d 6351 "
6352 operands[2] = gen_reg_rtx (SImode);
6353 operands[3] = gen_reg_rtx (SImode);
787f8210 6354 operands[4] = gen_lowpart (HImode, operands[3]);
215b30b3 6355 "
6356)
b11cae9e 6357
a2f10574 6358;; Pattern to recognize insn generated default case above
f7fbdd4a 6359(define_insn "*movhi_insn_arch4"
e4585731 6360 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r,m,r")
6361 (match_operand:HI 1 "general_operand" "rIk,K,n,r,mi"))]
cffb2a26 6362 "TARGET_ARM
6363 && arm_arch4
85e02ccb 6364 && (register_operand (operands[0], HImode)
6365 || register_operand (operands[1], HImode))"
f7fbdd4a 6366 "@
6367 mov%?\\t%0, %1\\t%@ movhi
6368 mvn%?\\t%0, #%B1\\t%@ movhi
b1c1a101 6369 movw%?\\t%0, %L1\\t%@ movhi
25f905c2 6370 str%(h%)\\t%1, %0\\t%@ movhi
6371 ldr%(h%)\\t%0, %1\\t%@ movhi"
65f68e55 6372 [(set_attr "predicable" "yes")
e4585731 6373 (set_attr "pool_range" "*,*,*,*,256")
6374 (set_attr "neg_pool_range" "*,*,*,*,244")
6375 (set_attr "arch" "*,*,v6t2,*,*")
65f68e55 6376 (set_attr_alternative "type"
6377 [(if_then_else (match_operand 1 "const_int_operand" "")
1aed5204 6378 (const_string "mov_imm" )
6379 (const_string "mov_reg"))
6380 (const_string "mvn_imm")
e4585731 6381 (const_string "mov_imm")
65f68e55 6382 (const_string "store1")
6383 (const_string "load1")])]
cffb2a26 6384)
f7fbdd4a 6385
f7fbdd4a 6386(define_insn "*movhi_bytes"
65f68e55 6387 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
5fd254ed 6388 (match_operand:HI 1 "arm_rhs_operand" "I,rk,K"))]
c1a66faf 6389 "TARGET_ARM"
25f7a26e 6390 "@
65f68e55 6391 mov%?\\t%0, %1\\t%@ movhi
25f7a26e 6392 mov%?\\t%0, %1\\t%@ movhi
0d66636f 6393 mvn%?\\t%0, #%B1\\t%@ movhi"
d2a518d1 6394 [(set_attr "predicable" "yes")
1aed5204 6395 (set_attr "type" "mov_imm,mov_reg,mvn_imm")]
0d66636f 6396)
cffb2a26 6397
bc5c7e08 6398;; We use a DImode scratch because we may occasionally need an additional
6399;; temporary if the address isn't offsettable -- push_reload doesn't seem
6400;; to take any notice of the "o" constraints on reload_memory_operand operand.
d3373b54 6401(define_expand "reload_outhi"
cffb2a26 6402 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
215b30b3 6403 (match_operand:HI 1 "s_register_operand" "r")
6404 (match_operand:DI 2 "s_register_operand" "=&l")])]
cffb2a26 6405 "TARGET_EITHER"
6406 "if (TARGET_ARM)
6407 arm_reload_out_hi (operands);
6408 else
6409 thumb_reload_out_hi (operands);
d3373b54 6410 DONE;
cffb2a26 6411 "
6412)
d3373b54 6413
25f7a26e 6414(define_expand "reload_inhi"
6415 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
cffb2a26 6416 (match_operand:HI 1 "arm_reload_memory_operand" "o")
bc5c7e08 6417 (match_operand:DI 2 "s_register_operand" "=&r")])]
c1a66faf 6418 "TARGET_EITHER"
25f7a26e 6419 "
cffb2a26 6420 if (TARGET_ARM)
6421 arm_reload_in_hi (operands);
6422 else
6423 thumb_reload_out_hi (operands);
25f7a26e 6424 DONE;
6425")
6426
9c08d1fa 6427(define_expand "movqi"
6428 [(set (match_operand:QI 0 "general_operand" "")
6429 (match_operand:QI 1 "general_operand" ""))]
cffb2a26 6430 "TARGET_EITHER"
9c08d1fa 6431 "
6cffc037 6432 /* Everything except mem = const or mem = mem can be done easily */
0045890a 6433
e1ba4a27 6434 if (can_create_pseudo_p ())
cffb2a26 6435 {
0438d37f 6436 if (CONST_INT_P (operands[1]))
6cffc037 6437 {
6438 rtx reg = gen_reg_rtx (SImode);
6439
03770691 6440 /* For thumb we want an unsigned immediate, then we are more likely
6441 to be able to use a movs insn. */
6442 if (TARGET_THUMB)
6443 operands[1] = GEN_INT (INTVAL (operands[1]) & 255);
6444
6cffc037 6445 emit_insn (gen_movsi (reg, operands[1]));
6446 operands[1] = gen_lowpart (QImode, reg);
6447 }
cffb2a26 6448
6cffc037 6449 if (TARGET_THUMB)
6450 {
cffb2a26 6451 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 6452 happen if we are passed a SP (never OK for HImode/QImode) or
bc409cb4 6453 virtual register (also rejected as illegitimate for HImode/QImode)
6454 relative address. */
cffb2a26 6455 /* ??? This should perhaps be fixed elsewhere, for instance, in
6456 fixup_stack_1, by checking for other kinds of invalid addresses,
6457 e.g. a bare reference to a virtual register. This may confuse the
6458 alpha though, which must handle this case differently. */
0438d37f 6459 if (MEM_P (operands[0])
215b30b3 6460 && !memory_address_p (GET_MODE (operands[0]),
cffb2a26 6461 XEXP (operands[0], 0)))
537ffcfc 6462 operands[0]
6463 = replace_equiv_address (operands[0],
6464 copy_to_reg (XEXP (operands[0], 0)));
0438d37f 6465 if (MEM_P (operands[1])
215b30b3 6466 && !memory_address_p (GET_MODE (operands[1]),
cffb2a26 6467 XEXP (operands[1], 0)))
537ffcfc 6468 operands[1]
6469 = replace_equiv_address (operands[1],
6470 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 6471 }
6472
0438d37f 6473 if (MEM_P (operands[1]) && optimize > 0)
6cffc037 6474 {
6475 rtx reg = gen_reg_rtx (SImode);
6476
6477 emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
6478 operands[1] = gen_lowpart (QImode, reg);
6479 }
6480
0438d37f 6481 if (MEM_P (operands[0]))
6cffc037 6482 operands[1] = force_reg (QImode, operands[1]);
6483 }
6484 else if (TARGET_THUMB
0438d37f 6485 && CONST_INT_P (operands[1])
234f6557 6486 && !satisfies_constraint_I (operands[1]))
6cffc037 6487 {
674a8f0b 6488 /* Handle loading a large integer during reload. */
cffb2a26 6489
6cffc037 6490 /* Writing a constant to memory needs a scratch, which should
6491 be handled with SECONDARY_RELOADs. */
0438d37f 6492 gcc_assert (REG_P (operands[0]));
6cffc037 6493
6494 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
6495 emit_insn (gen_movsi (operands[0], operands[1]));
6496 DONE;
cffb2a26 6497 }
6498 "
6499)
b11cae9e 6500
cffb2a26 6501(define_insn "*arm_movqi_insn"
fd711051 6502 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,l,r,l,Uu,r,m")
490f62ca 6503 (match_operand:QI 1 "general_operand" "rk,rk,I,Py,K,Uu,l,Uh,r"))]
25f905c2 6504 "TARGET_32BIT
cffb2a26 6505 && ( register_operand (operands[0], QImode)
6506 || register_operand (operands[1], QImode))"
5565501b 6507 "@
fd711051 6508 mov%?\\t%0, %1
6509 mov%?\\t%0, %1
65f68e55 6510 mov%?\\t%0, %1
5565501b 6511 mov%?\\t%0, %1
6512 mvn%?\\t%0, #%B1
25f905c2 6513 ldr%(b%)\\t%0, %1
a54e3e7b 6514 str%(b%)\\t%1, %0
6515 ldr%(b%)\\t%0, %1
25f905c2 6516 str%(b%)\\t%1, %0"
1aed5204 6517 [(set_attr "type" "mov_reg,mov_reg,mov_imm,mov_imm,mvn_imm,load1,store1,load1,store1")
a54e3e7b 6518 (set_attr "predicable" "yes")
fd711051 6519 (set_attr "predicable_short_it" "yes,yes,yes,no,no,no,no,no,no")
6520 (set_attr "arch" "t2,any,any,t2,any,t2,t2,any,any")
6521 (set_attr "length" "2,4,4,2,4,2,2,4,4")]
cffb2a26 6522)
6523
9b8516be 6524;; HFmode moves
6525(define_expand "movhf"
6526 [(set (match_operand:HF 0 "general_operand" "")
6527 (match_operand:HF 1 "general_operand" ""))]
6528 "TARGET_EITHER"
6529 "
6530 if (TARGET_32BIT)
6531 {
0438d37f 6532 if (MEM_P (operands[0]))
9b8516be 6533 operands[1] = force_reg (HFmode, operands[1]);
6534 }
6535 else /* TARGET_THUMB1 */
6536 {
6537 if (can_create_pseudo_p ())
6538 {
0438d37f 6539 if (!REG_P (operands[0]))
9b8516be 6540 operands[1] = force_reg (HFmode, operands[1]);
6541 }
6542 }
6543 "
6544)
6545
6546(define_insn "*arm32_movhf"
6547 [(set (match_operand:HF 0 "nonimmediate_operand" "=r,m,r,r")
6548 (match_operand:HF 1 "general_operand" " m,r,r,F"))]
7c36fe71 6549 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_FP16) && !arm_restrict_it
9b8516be 6550 && ( s_register_operand (operands[0], HFmode)
6551 || s_register_operand (operands[1], HFmode))"
6552 "*
6553 switch (which_alternative)
6554 {
6555 case 0: /* ARM register from memory */
6556 return \"ldr%(h%)\\t%0, %1\\t%@ __fp16\";
6557 case 1: /* memory from ARM register */
6558 return \"str%(h%)\\t%1, %0\\t%@ __fp16\";
6559 case 2: /* ARM register from ARM register */
6560 return \"mov%?\\t%0, %1\\t%@ __fp16\";
6561 case 3: /* ARM register from constant */
6562 {
6563 REAL_VALUE_TYPE r;
6564 long bits;
6565 rtx ops[4];
6566
6567 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
6568 bits = real_to_target (NULL, &r, HFmode);
6569 ops[0] = operands[0];
6570 ops[1] = GEN_INT (bits);
6571 ops[2] = GEN_INT (bits & 0xff00);
6572 ops[3] = GEN_INT (bits & 0x00ff);
6573
6574 if (arm_arch_thumb2)
6575 output_asm_insn (\"movw%?\\t%0, %1\", ops);
6576 else
6577 output_asm_insn (\"mov%?\\t%0, %2\;orr%?\\t%0, %0, %3\", ops);
6578 return \"\";
6579 }
6580 default:
6581 gcc_unreachable ();
6582 }
6583 "
6584 [(set_attr "conds" "unconditional")
ad4fc3c0 6585 (set_attr "type" "load1,store1,mov_reg,multiple")
9b8516be 6586 (set_attr "length" "4,4,4,8")
d2a518d1 6587 (set_attr "predicable" "yes")]
9b8516be 6588)
6589
87b22bf7 6590(define_expand "movsf"
6591 [(set (match_operand:SF 0 "general_operand" "")
6592 (match_operand:SF 1 "general_operand" ""))]
cffb2a26 6593 "TARGET_EITHER"
87b22bf7 6594 "
25f905c2 6595 if (TARGET_32BIT)
cffb2a26 6596 {
0438d37f 6597 if (MEM_P (operands[0]))
cffb2a26 6598 operands[1] = force_reg (SFmode, operands[1]);
6599 }
25f905c2 6600 else /* TARGET_THUMB1 */
cffb2a26 6601 {
e1ba4a27 6602 if (can_create_pseudo_p ())
cffb2a26 6603 {
0438d37f 6604 if (!REG_P (operands[0]))
cffb2a26 6605 operands[1] = force_reg (SFmode, operands[1]);
6606 }
6607 }
6608 "
6609)
6610
03d440a6 6611;; Transform a floating-point move of a constant into a core register into
6612;; an SImode operation.
cffb2a26 6613(define_split
03d440a6 6614 [(set (match_operand:SF 0 "arm_general_register_operand" "")
cffb2a26 6615 (match_operand:SF 1 "immediate_operand" ""))]
339034d0 6616 "TARGET_EITHER
cffb2a26 6617 && reload_completed
0438d37f 6618 && CONST_DOUBLE_P (operands[1])"
cffb2a26 6619 [(set (match_dup 2) (match_dup 3))]
6620 "
6621 operands[2] = gen_lowpart (SImode, operands[0]);
6622 operands[3] = gen_lowpart (SImode, operands[1]);
6623 if (operands[2] == 0 || operands[3] == 0)
6624 FAIL;
215b30b3 6625 "
6626)
87b22bf7 6627
cffb2a26 6628(define_insn "*arm_movsf_soft_insn"
6629 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
6630 (match_operand:SF 1 "general_operand" "r,mE,r"))]
cde1623a 6631 "TARGET_32BIT
cffb2a26 6632 && TARGET_SOFT_FLOAT
0438d37f 6633 && (!MEM_P (operands[0])
215b30b3 6634 || register_operand (operands[1], SFmode))"
9a1112d7 6635 "@
6636 mov%?\\t%0, %1
6637 ldr%?\\t%0, %1\\t%@ float
6638 str%?\\t%1, %0\\t%@ float"
cde1623a 6639 [(set_attr "predicable" "yes")
7c36fe71 6640 (set_attr "predicable_short_it" "no")
1aed5204 6641 (set_attr "type" "mov_reg,load1,store1")
42e1de19 6642 (set_attr "arm_pool_range" "*,4096,*")
6643 (set_attr "thumb2_pool_range" "*,4094,*")
cde1623a 6644 (set_attr "arm_neg_pool_range" "*,4084,*")
6645 (set_attr "thumb2_neg_pool_range" "*,0,*")]
cffb2a26 6646)
6647
9c08d1fa 6648(define_expand "movdf"
87b22bf7 6649 [(set (match_operand:DF 0 "general_operand" "")
6650 (match_operand:DF 1 "general_operand" ""))]
cffb2a26 6651 "TARGET_EITHER"
9c08d1fa 6652 "
25f905c2 6653 if (TARGET_32BIT)
cffb2a26 6654 {
0438d37f 6655 if (MEM_P (operands[0]))
cffb2a26 6656 operands[1] = force_reg (DFmode, operands[1]);
6657 }
6658 else /* TARGET_THUMB */
6659 {
e1ba4a27 6660 if (can_create_pseudo_p ())
cffb2a26 6661 {
0438d37f 6662 if (!REG_P (operands[0]))
cffb2a26 6663 operands[1] = force_reg (DFmode, operands[1]);
6664 }
6665 }
6666 "
6667)
b11cae9e 6668
9c08d1fa 6669;; Reloading a df mode value stored in integer regs to memory can require a
6670;; scratch reg.
6671(define_expand "reload_outdf"
cffb2a26 6672 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
87b22bf7 6673 (match_operand:DF 1 "s_register_operand" "r")
6674 (match_operand:SI 2 "s_register_operand" "=&r")]
06adefdc 6675 "TARGET_THUMB2"
87b22bf7 6676 "
215b30b3 6677 {
6678 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
f7fbdd4a 6679
215b30b3 6680 if (code == REG)
6681 operands[2] = XEXP (operands[0], 0);
6682 else if (code == POST_INC || code == PRE_DEC)
6683 {
6684 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
6685 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
6686 emit_insn (gen_movdi (operands[0], operands[1]));
6687 DONE;
6688 }
6689 else if (code == PRE_INC)
6690 {
6691 rtx reg = XEXP (XEXP (operands[0], 0), 0);
f7fbdd4a 6692
215b30b3 6693 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
6694 operands[2] = reg;
6695 }
6696 else if (code == POST_DEC)
6697 operands[2] = XEXP (XEXP (operands[0], 0), 0);
6698 else
6699 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
6700 XEXP (XEXP (operands[0], 0), 1)));
f7fbdd4a 6701
d1f9b275 6702 emit_insn (gen_rtx_SET (replace_equiv_address (operands[0], operands[2]),
215b30b3 6703 operands[1]));
f7fbdd4a 6704
215b30b3 6705 if (code == POST_DEC)
6706 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
6707
6708 DONE;
6709 }"
6710)
9c08d1fa 6711
9a1112d7 6712(define_insn "*movdf_soft_insn"
353cf59a 6713 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,q,m")
6714 (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,q"))]
cde1623a 6715 "TARGET_32BIT && TARGET_SOFT_FLOAT
b2778788 6716 && ( register_operand (operands[0], DFmode)
6717 || register_operand (operands[1], DFmode))"
d51f92df 6718 "*
6719 switch (which_alternative)
6720 {
6721 case 0:
6722 case 1:
6723 case 2:
6724 return \"#\";
6725 default:
26ff80c0 6726 return output_move_double (operands, true, NULL);
d51f92df 6727 }
6728 "
359a6e9f 6729 [(set_attr "length" "8,12,16,8,8")
1b7da4ac 6730 (set_attr "type" "multiple,multiple,multiple,load2,store2")
42e1de19 6731 (set_attr "arm_pool_range" "*,*,*,1020,*")
6732 (set_attr "thumb2_pool_range" "*,*,*,1018,*")
8848d797 6733 (set_attr "arm_neg_pool_range" "*,*,*,1004,*")
cde1623a 6734 (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
cffb2a26 6735)
b11cae9e 6736\f
b11cae9e 6737
9c08d1fa 6738;; load- and store-multiple insns
6739;; The arm can load/store any set of registers, provided that they are in
320ea44d 6740;; ascending order, but these expanders assume a contiguous set.
b11cae9e 6741
9c08d1fa 6742(define_expand "load_multiple"
6743 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6744 (match_operand:SI 1 "" ""))
6745 (use (match_operand:SI 2 "" ""))])]
25f905c2 6746 "TARGET_32BIT"
9580c25f 6747{
6748 HOST_WIDE_INT offset = 0;
6749
bd5b4116 6750 /* Support only fixed point registers. */
0438d37f 6751 if (!CONST_INT_P (operands[2])
6e628811 6752 || INTVAL (operands[2]) > MAX_LDM_STM_OPS
9c08d1fa 6753 || INTVAL (operands[2]) < 2
0438d37f 6754 || !MEM_P (operands[1])
6755 || !REG_P (operands[0])
bd5b4116 6756 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
6757 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 6758 FAIL;
6759
6760 operands[3]
320ea44d 6761 = arm_gen_load_multiple (arm_regs_in_sequence + REGNO (operands[0]),
6762 INTVAL (operands[2]),
f082f1c4 6763 force_reg (SImode, XEXP (operands[1], 0)),
320ea44d 6764 FALSE, operands[1], &offset);
9580c25f 6765})
b11cae9e 6766
9c08d1fa 6767(define_expand "store_multiple"
6768 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6769 (match_operand:SI 1 "" ""))
6770 (use (match_operand:SI 2 "" ""))])]
25f905c2 6771 "TARGET_32BIT"
9580c25f 6772{
6773 HOST_WIDE_INT offset = 0;
6774
674a8f0b 6775 /* Support only fixed point registers. */
0438d37f 6776 if (!CONST_INT_P (operands[2])
6e628811 6777 || INTVAL (operands[2]) > MAX_LDM_STM_OPS
9c08d1fa 6778 || INTVAL (operands[2]) < 2
0438d37f 6779 || !REG_P (operands[1])
6780 || !MEM_P (operands[0])
bd5b4116 6781 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
6782 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 6783 FAIL;
6784
6785 operands[3]
320ea44d 6786 = arm_gen_store_multiple (arm_regs_in_sequence + REGNO (operands[1]),
6787 INTVAL (operands[2]),
f082f1c4 6788 force_reg (SImode, XEXP (operands[0], 0)),
320ea44d 6789 FALSE, operands[0], &offset);
9580c25f 6790})
b11cae9e 6791
9c08d1fa 6792
e34ebfca 6793(define_expand "setmemsi"
6794 [(match_operand:BLK 0 "general_operand" "")
6795 (match_operand:SI 1 "const_int_operand" "")
6796 (match_operand:SI 2 "const_int_operand" "")
6797 (match_operand:SI 3 "const_int_operand" "")]
6798 "TARGET_32BIT"
6799{
6800 if (arm_gen_setmem (operands))
6801 DONE;
6802
6803 FAIL;
6804})
6805
6806
9c08d1fa 6807;; Move a block of memory if it is word aligned and MORE than 2 words long.
6808;; We could let this apply for blocks of less than this, but it clobbers so
6809;; many registers that there is then probably a better way.
6810
008c057d 6811(define_expand "movmemqi"
34191dd1 6812 [(match_operand:BLK 0 "general_operand" "")
6813 (match_operand:BLK 1 "general_operand" "")
6814 (match_operand:SI 2 "const_int_operand" "")
6815 (match_operand:SI 3 "const_int_operand" "")]
ae51a965 6816 ""
9c08d1fa 6817 "
25f905c2 6818 if (TARGET_32BIT)
cffb2a26 6819 {
ae51a965 6820 if (TARGET_LDRD && current_tune->prefer_ldrd_strd
6821 && !optimize_function_for_size_p (cfun))
6822 {
6823 if (gen_movmem_ldrd_strd (operands))
6824 DONE;
6825 FAIL;
6826 }
6827
008c057d 6828 if (arm_gen_movmemqi (operands))
cffb2a26 6829 DONE;
6830 FAIL;
6831 }
25f905c2 6832 else /* TARGET_THUMB1 */
cffb2a26 6833 {
6834 if ( INTVAL (operands[3]) != 4
6835 || INTVAL (operands[2]) > 48)
6836 FAIL;
6837
008c057d 6838 thumb_expand_movmemqi (operands);
cffb2a26 6839 DONE;
6840 }
6841 "
6842)
9c08d1fa 6843\f
b11cae9e 6844
341940e8 6845;; Compare & branch insns
8d232dc7 6846;; The range calculations are based as follows:
341940e8 6847;; For forward branches, the address calculation returns the address of
6848;; the next instruction. This is 2 beyond the branch instruction.
6849;; For backward branches, the address calculation returns the address of
6850;; the first instruction in this pattern (cmp). This is 2 before the branch
6851;; instruction for the shortest sequence, and 4 before the branch instruction
6852;; if we have to jump around an unconditional branch.
6853;; To the basic branch range the PC offset must be added (this is +4).
6854;; So for forward branches we have
6855;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
6856;; And for backward branches we have
6857;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
6858;;
6859;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
6860;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
cffb2a26 6861
aeac46d4 6862(define_expand "cbranchsi4"
6863 [(set (pc) (if_then_else
aa06947a 6864 (match_operator 0 "expandable_comparison_operator"
aeac46d4 6865 [(match_operand:SI 1 "s_register_operand" "")
6866 (match_operand:SI 2 "nonmemory_operand" "")])
6867 (label_ref (match_operand 3 "" ""))
6868 (pc)))]
f9aa4160 6869 "TARGET_EITHER"
aeac46d4 6870 "
74f4459c 6871 if (!TARGET_THUMB1)
6872 {
f9aa4160 6873 if (!arm_validize_comparison (&operands[0], &operands[1], &operands[2]))
6874 FAIL;
74f4459c 6875 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6876 operands[3]));
6877 DONE;
6878 }
25f905c2 6879 if (thumb1_cmpneg_operand (operands[2], SImode))
aeac46d4 6880 {
6881 emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
6882 operands[3], operands[0]));
6883 DONE;
6884 }
25f905c2 6885 if (!thumb1_cmp_operand (operands[2], SImode))
aeac46d4 6886 operands[2] = force_reg (SImode, operands[2]);
6887 ")
6888
74f4459c 6889(define_expand "cbranchsf4"
6890 [(set (pc) (if_then_else
aa06947a 6891 (match_operator 0 "expandable_comparison_operator"
74f4459c 6892 [(match_operand:SF 1 "s_register_operand" "")
6893 (match_operand:SF 2 "arm_float_compare_operand" "")])
6894 (label_ref (match_operand 3 "" ""))
6895 (pc)))]
6896 "TARGET_32BIT && TARGET_HARD_FLOAT"
6897 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6898 operands[3])); DONE;"
6899)
6900
6901(define_expand "cbranchdf4"
6902 [(set (pc) (if_then_else
aa06947a 6903 (match_operator 0 "expandable_comparison_operator"
74f4459c 6904 [(match_operand:DF 1 "s_register_operand" "")
6905 (match_operand:DF 2 "arm_float_compare_operand" "")])
6906 (label_ref (match_operand 3 "" ""))
6907 (pc)))]
a50d7267 6908 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
74f4459c 6909 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6910 operands[3])); DONE;"
6911)
6912
74f4459c 6913(define_expand "cbranchdi4"
6914 [(set (pc) (if_then_else
aa06947a 6915 (match_operator 0 "expandable_comparison_operator"
b8eae306 6916 [(match_operand:DI 1 "s_register_operand" "")
a8045a4f 6917 (match_operand:DI 2 "cmpdi_operand" "")])
74f4459c 6918 (label_ref (match_operand 3 "" ""))
6919 (pc)))]
a8045a4f 6920 "TARGET_32BIT"
6921 "{
0438d37f 6922 if (!arm_validize_comparison (&operands[0], &operands[1], &operands[2]))
f9aa4160 6923 FAIL;
6924 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
a8045a4f 6925 operands[3]));
6926 DONE;
6927 }"
74f4459c 6928)
6929
9c08d1fa 6930;; Comparison and test insns
6931
cffb2a26 6932(define_insn "*arm_cmpsi_insn"
bd5b4116 6933 [(set (reg:CC CC_REGNUM)
f9f234ec 6934 (compare:CC (match_operand:SI 0 "s_register_operand" "l,r,r,r,r")
6935 (match_operand:SI 1 "arm_add_operand" "Py,r,r,I,L")))]
25f905c2 6936 "TARGET_32BIT"
5565501b 6937 "@
a6864a24 6938 cmp%?\\t%0, %1
6939 cmp%?\\t%0, %1
aea4c774 6940 cmp%?\\t%0, %1
f9f234ec 6941 cmp%?\\t%0, %1
aea4c774 6942 cmn%?\\t%0, #%n1"
a6864a24 6943 [(set_attr "conds" "set")
f9f234ec 6944 (set_attr "arch" "t2,t2,any,any,any")
6945 (set_attr "length" "2,2,4,4,4")
65f68e55 6946 (set_attr "predicable" "yes")
f9f234ec 6947 (set_attr "predicable_short_it" "yes,yes,yes,no,no")
112eda6f 6948 (set_attr "type" "alus_imm,alus_sreg,alus_sreg,alus_imm,alus_imm")]
cffb2a26 6949)
b11cae9e 6950
d5d4dc8d 6951(define_insn "*cmpsi_shiftsi"
bd5b4116 6952 [(set (reg:CC CC_REGNUM)
d82e788e 6953 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r,r")
cffb2a26 6954 (match_operator:SI 3 "shift_operator"
d82e788e 6955 [(match_operand:SI 1 "s_register_operand" "r,r,r")
6956 (match_operand:SI 2 "shift_amount_operand" "M,r,M")])))]
d5d4dc8d 6957 "TARGET_32BIT"
f9f234ec 6958 "cmp\\t%0, %1%S3"
344495ea 6959 [(set_attr "conds" "set")
331beb1a 6960 (set_attr "shift" "1")
d82e788e 6961 (set_attr "arch" "32,a,a")
282b4c75 6962 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
b11cae9e 6963
d5d4dc8d 6964(define_insn "*cmpsi_shiftsi_swp"
bd5b4116 6965 [(set (reg:CC_SWP CC_REGNUM)
aea4c774 6966 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
d82e788e 6967 [(match_operand:SI 1 "s_register_operand" "r,r,r")
6968 (match_operand:SI 2 "shift_amount_operand" "M,r,M")])
6969 (match_operand:SI 0 "s_register_operand" "r,r,r")))]
d5d4dc8d 6970 "TARGET_32BIT"
aea4c774 6971 "cmp%?\\t%0, %1%S3"
344495ea 6972 [(set_attr "conds" "set")
331beb1a 6973 (set_attr "shift" "1")
d82e788e 6974 (set_attr "arch" "32,a,a")
282b4c75 6975 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
b11cae9e 6976
25f905c2 6977(define_insn "*arm_cmpsi_negshiftsi_si"
aed179ae 6978 [(set (reg:CC_Z CC_REGNUM)
6979 (compare:CC_Z
6980 (neg:SI (match_operator:SI 1 "shift_operator"
6981 [(match_operand:SI 2 "s_register_operand" "r")
6982 (match_operand:SI 3 "reg_or_int_operand" "rM")]))
6983 (match_operand:SI 0 "s_register_operand" "r")))]
cffb2a26 6984 "TARGET_ARM"
aed179ae 6985 "cmn%?\\t%0, %2%S1"
344495ea 6986 [(set_attr "conds" "set")
aed179ae 6987 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
d82e788e 6988 (const_string "alus_shift_imm")
6989 (const_string "alus_shift_reg")))
596e5e8f 6990 (set_attr "predicable" "yes")]
0d66636f 6991)
b11cae9e 6992
a8045a4f 6993;; DImode comparisons. The generic code generates branches that
6994;; if-conversion can not reduce to a conditional compare, so we do
6995;; that directly.
6996
ba6a3b2f 6997(define_insn_and_split "*arm_cmpdi_insn"
a8045a4f 6998 [(set (reg:CC_NCV CC_REGNUM)
6999 (compare:CC_NCV (match_operand:DI 0 "s_register_operand" "r")
7000 (match_operand:DI 1 "arm_di_operand" "rDi")))
7001 (clobber (match_scratch:SI 2 "=r"))]
b805622c 7002 "TARGET_32BIT"
ba6a3b2f 7003 "#" ; "cmp\\t%Q0, %Q1\;sbcs\\t%2, %R0, %R1"
7004 "&& reload_completed"
7005 [(set (reg:CC CC_REGNUM)
7006 (compare:CC (match_dup 0) (match_dup 1)))
7007 (parallel [(set (reg:CC CC_REGNUM)
7008 (compare:CC (match_dup 3) (match_dup 4)))
7009 (set (match_dup 2)
7010 (minus:SI (match_dup 5)
7011 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))])]
7012 {
7013 operands[3] = gen_highpart (SImode, operands[0]);
7014 operands[0] = gen_lowpart (SImode, operands[0]);
7015 if (CONST_INT_P (operands[1]))
7016 {
7017 operands[4] = GEN_INT (~INTVAL (gen_highpart_mode (SImode,
7018 DImode,
7019 operands[1])));
7020 operands[5] = gen_rtx_PLUS (SImode, operands[3], operands[4]);
7021 }
7022 else
7023 {
7024 operands[4] = gen_highpart (SImode, operands[1]);
7025 operands[5] = gen_rtx_MINUS (SImode, operands[3], operands[4]);
7026 }
7027 operands[1] = gen_lowpart (SImode, operands[1]);
7028 operands[2] = gen_lowpart (SImode, operands[2]);
7029 }
a8045a4f 7030 [(set_attr "conds" "set")
1b7da4ac 7031 (set_attr "length" "8")
7032 (set_attr "type" "multiple")]
a8045a4f 7033)
7034
ba6a3b2f 7035(define_insn_and_split "*arm_cmpdi_unsigned"
a8045a4f 7036 [(set (reg:CC_CZ CC_REGNUM)
1a86364b 7037 (compare:CC_CZ (match_operand:DI 0 "s_register_operand" "l,r,r,r")
7038 (match_operand:DI 1 "arm_di_operand" "Py,r,Di,rDi")))]
7c36fe71 7039
48a98053 7040 "TARGET_32BIT"
ba6a3b2f 7041 "#" ; "cmp\\t%R0, %R1\;it eq\;cmpeq\\t%Q0, %Q1"
7042 "&& reload_completed"
7043 [(set (reg:CC CC_REGNUM)
7044 (compare:CC (match_dup 2) (match_dup 3)))
7045 (cond_exec (eq:SI (reg:CC CC_REGNUM) (const_int 0))
7046 (set (reg:CC CC_REGNUM)
7047 (compare:CC (match_dup 0) (match_dup 1))))]
7048 {
7049 operands[2] = gen_highpart (SImode, operands[0]);
7050 operands[0] = gen_lowpart (SImode, operands[0]);
7051 if (CONST_INT_P (operands[1]))
7052 operands[3] = gen_highpart_mode (SImode, DImode, operands[1]);
7053 else
7054 operands[3] = gen_highpart (SImode, operands[1]);
7055 operands[1] = gen_lowpart (SImode, operands[1]);
7056 }
a8045a4f 7057 [(set_attr "conds" "set")
1a86364b 7058 (set_attr "enabled_for_depr_it" "yes,yes,no,*")
7059 (set_attr "arch" "t2,t2,t2,a")
7060 (set_attr "length" "6,6,10,8")
1b7da4ac 7061 (set_attr "type" "multiple")]
a8045a4f 7062)
7063
7064(define_insn "*arm_cmpdi_zero"
7065 [(set (reg:CC_Z CC_REGNUM)
7066 (compare:CC_Z (match_operand:DI 0 "s_register_operand" "r")
7067 (const_int 0)))
7068 (clobber (match_scratch:SI 1 "=r"))]
7069 "TARGET_32BIT"
7070 "orr%.\\t%1, %Q0, %R0"
1b7da4ac 7071 [(set_attr "conds" "set")
7072 (set_attr "type" "logics_reg")]
a8045a4f 7073)
7074
9c08d1fa 7075; This insn allows redundant compares to be removed by cse, nothing should
7076; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
7077; is deleted later on. The match_dup will match the mode here, so that
7078; mode changes of the condition codes aren't lost by this even though we don't
7079; specify what they are.
7080
8a18b90c 7081(define_insn "*deleted_compare"
9c08d1fa 7082 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
25f905c2 7083 "TARGET_32BIT"
40dbec34 7084 "\\t%@ deleted compare"
cffb2a26 7085 [(set_attr "conds" "set")
1b7da4ac 7086 (set_attr "length" "0")
7087 (set_attr "type" "no_insn")]
cffb2a26 7088)
9c08d1fa 7089
7090\f
7091;; Conditional branch insns
7092
74f4459c 7093(define_expand "cbranch_cc"
9c08d1fa 7094 [(set (pc)
74f4459c 7095 (if_then_else (match_operator 0 "" [(match_operand 1 "" "")
7096 (match_operand 2 "" "")])
7097 (label_ref (match_operand 3 "" ""))
9c08d1fa 7098 (pc)))]
25f905c2 7099 "TARGET_32BIT"
74f4459c 7100 "operands[1] = arm_gen_compare_reg (GET_CODE (operands[0]),
e1b93706 7101 operands[1], operands[2], NULL_RTX);
74f4459c 7102 operands[2] = const0_rtx;"
8fa3ba89 7103)
7104
7105;;
7106;; Patterns to match conditional branch insns.
7107;;
7108
ffcc986d 7109(define_insn "arm_cond_branch"
9c08d1fa 7110 [(set (pc)
8fa3ba89 7111 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 7112 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 7113 (label_ref (match_operand 0 "" ""))
7114 (pc)))]
25f905c2 7115 "TARGET_32BIT"
d75350ce 7116 "*
9c08d1fa 7117 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 7118 {
7119 arm_ccfsm_state += 2;
7120 return \"\";
7121 }
e2348bcb 7122 return \"b%d1\\t%l0\";
cffb2a26 7123 "
a2cd141b 7124 [(set_attr "conds" "use")
a6864a24 7125 (set_attr "type" "branch")
7126 (set (attr "length")
7127 (if_then_else
0bf497f5 7128 (and (match_test "TARGET_THUMB2")
a6864a24 7129 (and (ge (minus (match_dup 0) (pc)) (const_int -250))
7130 (le (minus (match_dup 0) (pc)) (const_int 256))))
7131 (const_int 2)
7132 (const_int 4)))]
cffb2a26 7133)
d75350ce 7134
cffb2a26 7135(define_insn "*arm_cond_branch_reversed"
9c08d1fa 7136 [(set (pc)
8fa3ba89 7137 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 7138 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 7139 (pc)
7140 (label_ref (match_operand 0 "" ""))))]
25f905c2 7141 "TARGET_32BIT"
d75350ce 7142 "*
9c08d1fa 7143 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 7144 {
7145 arm_ccfsm_state += 2;
7146 return \"\";
7147 }
e2348bcb 7148 return \"b%D1\\t%l0\";
cffb2a26 7149 "
a2cd141b 7150 [(set_attr "conds" "use")
a6864a24 7151 (set_attr "type" "branch")
7152 (set (attr "length")
7153 (if_then_else
0bf497f5 7154 (and (match_test "TARGET_THUMB2")
a6864a24 7155 (and (ge (minus (match_dup 0) (pc)) (const_int -250))
7156 (le (minus (match_dup 0) (pc)) (const_int 256))))
7157 (const_int 2)
7158 (const_int 4)))]
cffb2a26 7159)
7160
b11cae9e 7161\f
9c08d1fa 7162
7163; scc insns
7164
74f4459c 7165(define_expand "cstore_cc"
7db9af5d 7166 [(set (match_operand:SI 0 "s_register_operand" "")
74f4459c 7167 (match_operator:SI 1 "" [(match_operand 2 "" "")
7168 (match_operand 3 "" "")]))]
25f905c2 7169 "TARGET_32BIT"
74f4459c 7170 "operands[2] = arm_gen_compare_reg (GET_CODE (operands[1]),
e1b93706 7171 operands[2], operands[3], NULL_RTX);
74f4459c 7172 operands[3] = const0_rtx;"
8fa3ba89 7173)
7174
a3b84066 7175(define_insn_and_split "*mov_scc"
9c08d1fa 7176 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7177 (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7178 [(match_operand 2 "cc_register" "") (const_int 0)]))]
cffb2a26 7179 "TARGET_ARM"
a3b84066 7180 "#" ; "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
7181 "TARGET_ARM"
7182 [(set (match_dup 0)
7183 (if_then_else:SI (match_dup 1)
7184 (const_int 1)
7185 (const_int 0)))]
7186 ""
cffb2a26 7187 [(set_attr "conds" "use")
1b7da4ac 7188 (set_attr "length" "8")
7189 (set_attr "type" "multiple")]
cffb2a26 7190)
9c08d1fa 7191
a3b84066 7192(define_insn_and_split "*mov_negscc"
9c08d1fa 7193 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7194 (neg:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7195 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 7196 "TARGET_ARM"
a3b84066 7197 "#" ; "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
7198 "TARGET_ARM"
7199 [(set (match_dup 0)
7200 (if_then_else:SI (match_dup 1)
7201 (match_dup 3)
7202 (const_int 0)))]
7203 {
7204 operands[3] = GEN_INT (~0);
7205 }
cffb2a26 7206 [(set_attr "conds" "use")
1b7da4ac 7207 (set_attr "length" "8")
7208 (set_attr "type" "multiple")]
cffb2a26 7209)
9c08d1fa 7210
a3b84066 7211(define_insn_and_split "*mov_notscc"
9c08d1fa 7212 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7213 (not:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7214 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 7215 "TARGET_ARM"
a3b84066 7216 "#" ; "mvn%D1\\t%0, #0\;mvn%d1\\t%0, #1"
7217 "TARGET_ARM"
7218 [(set (match_dup 0)
7219 (if_then_else:SI (match_dup 1)
7220 (match_dup 3)
7221 (match_dup 4)))]
7222 {
7223 operands[3] = GEN_INT (~1);
7224 operands[4] = GEN_INT (~0);
7225 }
cffb2a26 7226 [(set_attr "conds" "use")
1b7da4ac 7227 (set_attr "length" "8")
7228 (set_attr "type" "multiple")]
cffb2a26 7229)
9c08d1fa 7230
595d88b5 7231(define_expand "cstoresi4"
7232 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 7233 (match_operator:SI 1 "expandable_comparison_operator"
595d88b5 7234 [(match_operand:SI 2 "s_register_operand" "")
7235 (match_operand:SI 3 "reg_or_int_operand" "")]))]
74f4459c 7236 "TARGET_32BIT || TARGET_THUMB1"
595d88b5 7237 "{
7238 rtx op3, scratch, scratch2;
7239
74f4459c 7240 if (!TARGET_THUMB1)
7241 {
7242 if (!arm_add_operand (operands[3], SImode))
7243 operands[3] = force_reg (SImode, operands[3]);
7244 emit_insn (gen_cstore_cc (operands[0], operands[1],
7245 operands[2], operands[3]));
7246 DONE;
7247 }
7248
595d88b5 7249 if (operands[3] == const0_rtx)
7250 {
7251 switch (GET_CODE (operands[1]))
7252 {
7253 case EQ:
25f905c2 7254 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], operands[2]));
595d88b5 7255 break;
7256
7257 case NE:
25f905c2 7258 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], operands[2]));
595d88b5 7259 break;
7260
7261 case LE:
7262 scratch = expand_binop (SImode, add_optab, operands[2], constm1_rtx,
7263 NULL_RTX, 0, OPTAB_WIDEN);
7264 scratch = expand_binop (SImode, ior_optab, operands[2], scratch,
7265 NULL_RTX, 0, OPTAB_WIDEN);
7266 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7267 operands[0], 1, OPTAB_WIDEN);
7268 break;
7269
7270 case GE:
7271 scratch = expand_unop (SImode, one_cmpl_optab, operands[2],
7272 NULL_RTX, 1);
7273 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7274 NULL_RTX, 1, OPTAB_WIDEN);
7275 break;
7276
7277 case GT:
7278 scratch = expand_binop (SImode, ashr_optab, operands[2],
7279 GEN_INT (31), NULL_RTX, 0, OPTAB_WIDEN);
7280 scratch = expand_binop (SImode, sub_optab, scratch, operands[2],
7281 NULL_RTX, 0, OPTAB_WIDEN);
7282 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31), operands[0],
7283 0, OPTAB_WIDEN);
7284 break;
7285
7286 /* LT is handled by generic code. No need for unsigned with 0. */
7287 default:
7288 FAIL;
7289 }
7290 DONE;
7291 }
7292
7293 switch (GET_CODE (operands[1]))
7294 {
7295 case EQ:
7296 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7297 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7298 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], scratch));
595d88b5 7299 break;
7300
7301 case NE:
7302 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7303 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7304 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], scratch));
595d88b5 7305 break;
7306
7307 case LE:
7308 op3 = force_reg (SImode, operands[3]);
7309
7310 scratch = expand_binop (SImode, lshr_optab, operands[2], GEN_INT (31),
7311 NULL_RTX, 1, OPTAB_WIDEN);
7312 scratch2 = expand_binop (SImode, ashr_optab, op3, GEN_INT (31),
7313 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7314 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
595d88b5 7315 op3, operands[2]));
7316 break;
7317
7318 case GE:
7319 op3 = operands[3];
25f905c2 7320 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7321 op3 = force_reg (SImode, op3);
7322 scratch = expand_binop (SImode, ashr_optab, operands[2], GEN_INT (31),
7323 NULL_RTX, 0, OPTAB_WIDEN);
7324 scratch2 = expand_binop (SImode, lshr_optab, op3, GEN_INT (31),
7325 NULL_RTX, 1, OPTAB_WIDEN);
25f905c2 7326 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
595d88b5 7327 operands[2], op3));
7328 break;
7329
7330 case LEU:
7331 op3 = force_reg (SImode, operands[3]);
7332 scratch = force_reg (SImode, const0_rtx);
25f905c2 7333 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
595d88b5 7334 op3, operands[2]));
7335 break;
7336
7337 case GEU:
7338 op3 = operands[3];
25f905c2 7339 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7340 op3 = force_reg (SImode, op3);
7341 scratch = force_reg (SImode, const0_rtx);
25f905c2 7342 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
595d88b5 7343 operands[2], op3));
7344 break;
7345
7346 case LTU:
7347 op3 = operands[3];
25f905c2 7348 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7349 op3 = force_reg (SImode, op3);
7350 scratch = gen_reg_rtx (SImode);
408b7ae5 7351 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], operands[2], op3));
595d88b5 7352 break;
7353
7354 case GTU:
7355 op3 = force_reg (SImode, operands[3]);
7356 scratch = gen_reg_rtx (SImode);
408b7ae5 7357 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], op3, operands[2]));
595d88b5 7358 break;
7359
7360 /* No good sequences for GT, LT. */
7361 default:
7362 FAIL;
7363 }
7364 DONE;
7365}")
7366
74f4459c 7367(define_expand "cstoresf4"
7368 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 7369 (match_operator:SI 1 "expandable_comparison_operator"
74f4459c 7370 [(match_operand:SF 2 "s_register_operand" "")
7371 (match_operand:SF 3 "arm_float_compare_operand" "")]))]
7372 "TARGET_32BIT && TARGET_HARD_FLOAT"
7373 "emit_insn (gen_cstore_cc (operands[0], operands[1],
7374 operands[2], operands[3])); DONE;"
7375)
7376
7377(define_expand "cstoredf4"
7378 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 7379 (match_operator:SI 1 "expandable_comparison_operator"
74f4459c 7380 [(match_operand:DF 2 "s_register_operand" "")
7381 (match_operand:DF 3 "arm_float_compare_operand" "")]))]
d63ed457 7382 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
74f4459c 7383 "emit_insn (gen_cstore_cc (operands[0], operands[1],
7384 operands[2], operands[3])); DONE;"
7385)
7386
74f4459c 7387(define_expand "cstoredi4"
7388 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 7389 (match_operator:SI 1 "expandable_comparison_operator"
b8eae306 7390 [(match_operand:DI 2 "s_register_operand" "")
a8045a4f 7391 (match_operand:DI 3 "cmpdi_operand" "")]))]
7392 "TARGET_32BIT"
7393 "{
f9aa4160 7394 if (!arm_validize_comparison (&operands[1],
7395 &operands[2],
7396 &operands[3]))
7397 FAIL;
7398 emit_insn (gen_cstore_cc (operands[0], operands[1], operands[2],
a8045a4f 7399 operands[3]));
7400 DONE;
7401 }"
74f4459c 7402)
7403
9c08d1fa 7404\f
39b5e676 7405;; Conditional move insns
7406
7407(define_expand "movsicc"
8a18b90c 7408 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 7409 (if_then_else:SI (match_operand 1 "expandable_comparison_operator" "")
aea4c774 7410 (match_operand:SI 2 "arm_not_operand" "")
8a18b90c 7411 (match_operand:SI 3 "arm_not_operand" "")))]
25f905c2 7412 "TARGET_32BIT"
39b5e676 7413 "
215b30b3 7414 {
f9aa4160 7415 enum rtx_code code;
278b301d 7416 rtx ccreg;
7417
f9aa4160 7418 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
7419 &XEXP (operands[1], 1)))
278b301d 7420 FAIL;
f9aa4160 7421
7422 code = GET_CODE (operands[1]);
74f4459c 7423 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
e1b93706 7424 XEXP (operands[1], 1), NULL_RTX);
29bb088d 7425 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7426 }"
7427)
39b5e676 7428
7429(define_expand "movsfcc"
8a18b90c 7430 [(set (match_operand:SF 0 "s_register_operand" "")
4df97ffc 7431 (if_then_else:SF (match_operand 1 "arm_cond_move_operator" "")
8a18b90c 7432 (match_operand:SF 2 "s_register_operand" "")
d86c91f6 7433 (match_operand:SF 3 "s_register_operand" "")))]
19f6bf8d 7434 "TARGET_32BIT && TARGET_HARD_FLOAT"
39b5e676 7435 "
215b30b3 7436 {
7437 enum rtx_code code = GET_CODE (operands[1]);
7438 rtx ccreg;
f082f1c4 7439
f9aa4160 7440 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
7441 &XEXP (operands[1], 1)))
7442 FAIL;
39b5e676 7443
f9aa4160 7444 code = GET_CODE (operands[1]);
74f4459c 7445 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
e1b93706 7446 XEXP (operands[1], 1), NULL_RTX);
29bb088d 7447 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7448 }"
7449)
39b5e676 7450
7451(define_expand "movdfcc"
8a18b90c 7452 [(set (match_operand:DF 0 "s_register_operand" "")
4df97ffc 7453 (if_then_else:DF (match_operand 1 "arm_cond_move_operator" "")
8a18b90c 7454 (match_operand:DF 2 "s_register_operand" "")
d86c91f6 7455 (match_operand:DF 3 "s_register_operand" "")))]
994606f8 7456 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
39b5e676 7457 "
215b30b3 7458 {
7459 enum rtx_code code = GET_CODE (operands[1]);
278b301d 7460 rtx ccreg;
39b5e676 7461
f9aa4160 7462 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
7463 &XEXP (operands[1], 1)))
7464 FAIL;
7465 code = GET_CODE (operands[1]);
74f4459c 7466 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
e1b93706 7467 XEXP (operands[1], 1), NULL_RTX);
29bb088d 7468 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7469 }"
7470)
39b5e676 7471
91cb50d2 7472(define_insn "*cmov<mode>"
7473 [(set (match_operand:SDF 0 "s_register_operand" "=<F_constraint>")
7474 (if_then_else:SDF (match_operator 1 "arm_vsel_comparison_operator"
7475 [(match_operand 2 "cc_register" "") (const_int 0)])
7476 (match_operand:SDF 3 "s_register_operand"
7477 "<F_constraint>")
7478 (match_operand:SDF 4 "s_register_operand"
7479 "<F_constraint>")))]
7480 "TARGET_HARD_FLOAT && TARGET_FPU_ARMV8 <vfp_double_cond>"
7481 "*
7482 {
7483 enum arm_cond_code code = maybe_get_arm_condition_code (operands[1]);
7484 switch (code)
7485 {
7486 case ARM_GE:
7487 case ARM_GT:
7488 case ARM_EQ:
7489 case ARM_VS:
7490 return \"vsel%d1.<V_if_elem>\\t%<V_reg>0, %<V_reg>3, %<V_reg>4\";
7491 case ARM_LT:
7492 case ARM_LE:
7493 case ARM_NE:
7494 case ARM_VC:
7495 return \"vsel%D1.<V_if_elem>\\t%<V_reg>0, %<V_reg>4, %<V_reg>3\";
7496 default:
7497 gcc_unreachable ();
7498 }
7499 return \"\";
7500 }"
7501 [(set_attr "conds" "use")
6664d308 7502 (set_attr "type" "fcsel")]
91cb50d2 7503)
7504
190efb17 7505(define_insn_and_split "*movsicc_insn"
f082f1c4 7506 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
8a18b90c 7507 (if_then_else:SI
8fa3ba89 7508 (match_operator 3 "arm_comparison_operator"
8a18b90c 7509 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 7510 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
7511 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
cffb2a26 7512 "TARGET_ARM"
39b5e676 7513 "@
8a18b90c 7514 mov%D3\\t%0, %2
7515 mvn%D3\\t%0, #%B2
f082f1c4 7516 mov%d3\\t%0, %1
7517 mvn%d3\\t%0, #%B1
190efb17 7518 #
7519 #
7520 #
7521 #"
7522 ; alt4: mov%d3\\t%0, %1\;mov%D3\\t%0, %2
7523 ; alt5: mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
7524 ; alt6: mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
7525 ; alt7: mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
7526 "&& reload_completed"
7527 [(const_int 0)]
7528 {
7529 enum rtx_code rev_code;
3754d046 7530 machine_mode mode;
190efb17 7531 rtx rev_cond;
7532
7533 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
7534 operands[3],
d1f9b275 7535 gen_rtx_SET (operands[0], operands[1])));
190efb17 7536
7537 rev_code = GET_CODE (operands[3]);
7538 mode = GET_MODE (operands[4]);
7539 if (mode == CCFPmode || mode == CCFPEmode)
7540 rev_code = reverse_condition_maybe_unordered (rev_code);
7541 else
7542 rev_code = reverse_condition (rev_code);
7543
7544 rev_cond = gen_rtx_fmt_ee (rev_code,
7545 VOIDmode,
7546 operands[4],
7547 const0_rtx);
7548 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
7549 rev_cond,
d1f9b275 7550 gen_rtx_SET (operands[0], operands[2])));
190efb17 7551 DONE;
7552 }
f082f1c4 7553 [(set_attr "length" "4,4,4,4,8,8,8,8")
d2a518d1 7554 (set_attr "conds" "use")
65f68e55 7555 (set_attr_alternative "type"
7556 [(if_then_else (match_operand 2 "const_int_operand" "")
1aed5204 7557 (const_string "mov_imm")
7558 (const_string "mov_reg"))
7559 (const_string "mvn_imm")
65f68e55 7560 (if_then_else (match_operand 1 "const_int_operand" "")
1aed5204 7561 (const_string "mov_imm")
7562 (const_string "mov_reg"))
7563 (const_string "mvn_imm")
282b4c75 7564 (const_string "multiple")
7565 (const_string "multiple")
7566 (const_string "multiple")
7567 (const_string "multiple")])]
215b30b3 7568)
39b5e676 7569
39b5e676 7570(define_insn "*movsfcc_soft_insn"
f082f1c4 7571 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
8fa3ba89 7572 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
8a18b90c 7573 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 7574 (match_operand:SF 1 "s_register_operand" "0,r")
7575 (match_operand:SF 2 "s_register_operand" "r,0")))]
cffb2a26 7576 "TARGET_ARM && TARGET_SOFT_FLOAT"
f082f1c4 7577 "@
7578 mov%D3\\t%0, %2
7579 mov%d3\\t%0, %1"
d2a518d1 7580 [(set_attr "conds" "use")
1aed5204 7581 (set_attr "type" "mov_reg")]
8fa3ba89 7582)
39b5e676 7583
39b5e676 7584\f
9c08d1fa 7585;; Jump and linkage insns
7586
cffb2a26 7587(define_expand "jump"
9c08d1fa 7588 [(set (pc)
7589 (label_ref (match_operand 0 "" "")))]
cffb2a26 7590 "TARGET_EITHER"
9c08d1fa 7591 ""
cffb2a26 7592)
7593
7594(define_insn "*arm_jump"
7595 [(set (pc)
7596 (label_ref (match_operand 0 "" "")))]
25f905c2 7597 "TARGET_32BIT"
9c08d1fa 7598 "*
0d66636f 7599 {
7600 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7601 {
7602 arm_ccfsm_state += 2;
7603 return \"\";
7604 }
7605 return \"b%?\\t%l0\";
7606 }
7607 "
a6864a24 7608 [(set_attr "predicable" "yes")
7609 (set (attr "length")
7610 (if_then_else
0bf497f5 7611 (and (match_test "TARGET_THUMB2")
a6864a24 7612 (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
7613 (le (minus (match_dup 0) (pc)) (const_int 2048))))
7614 (const_int 2)
1b7da4ac 7615 (const_int 4)))
7616 (set_attr "type" "branch")]
0d66636f 7617)
9c08d1fa 7618
d3373b54 7619(define_expand "call"
7620 [(parallel [(call (match_operand 0 "memory_operand" "")
7621 (match_operand 1 "general_operand" ""))
cffb2a26 7622 (use (match_operand 2 "" ""))
bd5b4116 7623 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 7624 "TARGET_EITHER"
6c4c2133 7625 "
7626 {
bac7fc85 7627 rtx callee, pat;
bbe777ea 7628
bbe777ea 7629 /* In an untyped call, we can get NULL for operand 2. */
7630 if (operands[2] == NULL_RTX)
7631 operands[2] = const0_rtx;
7632
de55252a 7633 /* Decide if we should generate indirect calls by loading the
85c36fd1 7634 32-bit address of the callee into a register before performing the
de55252a 7635 branch and link. */
7636 callee = XEXP (operands[0], 0);
7637 if (GET_CODE (callee) == SYMBOL_REF
7638 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
7639 : !REG_P (callee))
bbe777ea 7640 XEXP (operands[0], 0) = force_reg (Pmode, callee);
bac7fc85 7641
7642 pat = gen_call_internal (operands[0], operands[1], operands[2]);
ca373797 7643 arm_emit_call_insn (pat, XEXP (operands[0], 0), false);
bac7fc85 7644 DONE;
6c4c2133 7645 }"
7646)
d3373b54 7647
bac7fc85 7648(define_expand "call_internal"
7649 [(parallel [(call (match_operand 0 "memory_operand" "")
7650 (match_operand 1 "general_operand" ""))
7651 (use (match_operand 2 "" ""))
7652 (clobber (reg:SI LR_REGNUM))])])
7653
f1039640 7654(define_insn "*call_reg_armv5"
d3373b54 7655 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
cffb2a26 7656 (match_operand 1 "" ""))
7657 (use (match_operand 2 "" ""))
bd5b4116 7658 (clobber (reg:SI LR_REGNUM))]
33ae7c4b 7659 "TARGET_ARM && arm_arch5 && !SIBLING_CALL_P (insn)"
f1039640 7660 "blx%?\\t%0"
7661 [(set_attr "type" "call")]
7662)
7663
7664(define_insn "*call_reg_arm"
7665 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7666 (match_operand 1 "" ""))
7667 (use (match_operand 2 "" ""))
7668 (clobber (reg:SI LR_REGNUM))]
33ae7c4b 7669 "TARGET_ARM && !arm_arch5 && !SIBLING_CALL_P (insn)"
9c08d1fa 7670 "*
5565501b 7671 return output_call (operands);
cffb2a26 7672 "
7673 ;; length is worst case, normally it is only two
7674 [(set_attr "length" "12")
7675 (set_attr "type" "call")]
7676)
9c08d1fa 7677
89504fc1 7678
7679;; Note: not used for armv5+ because the sequence used (ldr pc, ...) is not
7680;; considered a function call by the branch predictor of some cores (PR40887).
7681;; Falls back to blx rN (*call_reg_armv5).
7682
f7fbdd4a 7683(define_insn "*call_mem"
a3c63a9d 7684 [(call (mem:SI (match_operand:SI 0 "call_memory_operand" "m"))
cffb2a26 7685 (match_operand 1 "" ""))
7686 (use (match_operand 2 "" ""))
bd5b4116 7687 (clobber (reg:SI LR_REGNUM))]
33ae7c4b 7688 "TARGET_ARM && !arm_arch5 && !SIBLING_CALL_P (insn)"
9c08d1fa 7689 "*
5565501b 7690 return output_call_mem (operands);
cffb2a26 7691 "
7692 [(set_attr "length" "12")
7693 (set_attr "type" "call")]
7694)
7695
d3373b54 7696(define_expand "call_value"
e0698af7 7697 [(parallel [(set (match_operand 0 "" "")
7698 (call (match_operand 1 "memory_operand" "")
7699 (match_operand 2 "general_operand" "")))
cffb2a26 7700 (use (match_operand 3 "" ""))
bd5b4116 7701 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 7702 "TARGET_EITHER"
6c4c2133 7703 "
7704 {
bac7fc85 7705 rtx pat, callee;
bbe777ea 7706
7707 /* In an untyped call, we can get NULL for operand 2. */
7708 if (operands[3] == 0)
7709 operands[3] = const0_rtx;
7710
de55252a 7711 /* Decide if we should generate indirect calls by loading the
7712 32-bit address of the callee into a register before performing the
7713 branch and link. */
7714 callee = XEXP (operands[1], 0);
7715 if (GET_CODE (callee) == SYMBOL_REF
7716 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
7717 : !REG_P (callee))
78fe751b 7718 XEXP (operands[1], 0) = force_reg (Pmode, callee);
bac7fc85 7719
7720 pat = gen_call_value_internal (operands[0], operands[1],
7721 operands[2], operands[3]);
ca373797 7722 arm_emit_call_insn (pat, XEXP (operands[1], 0), false);
bac7fc85 7723 DONE;
6c4c2133 7724 }"
7725)
d3373b54 7726
bac7fc85 7727(define_expand "call_value_internal"
7728 [(parallel [(set (match_operand 0 "" "")
7729 (call (match_operand 1 "memory_operand" "")
7730 (match_operand 2 "general_operand" "")))
7731 (use (match_operand 3 "" ""))
7732 (clobber (reg:SI LR_REGNUM))])])
7733
f1039640 7734(define_insn "*call_value_reg_armv5"
27ed6835 7735 [(set (match_operand 0 "" "")
755eb2b4 7736 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
cffb2a26 7737 (match_operand 2 "" "")))
bbe777ea 7738 (use (match_operand 3 "" ""))
bd5b4116 7739 (clobber (reg:SI LR_REGNUM))]
33ae7c4b 7740 "TARGET_ARM && arm_arch5 && !SIBLING_CALL_P (insn)"
f1039640 7741 "blx%?\\t%1"
7742 [(set_attr "type" "call")]
7743)
7744
7745(define_insn "*call_value_reg_arm"
7746 [(set (match_operand 0 "" "")
7747 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7748 (match_operand 2 "" "")))
7749 (use (match_operand 3 "" ""))
7750 (clobber (reg:SI LR_REGNUM))]
33ae7c4b 7751 "TARGET_ARM && !arm_arch5 && !SIBLING_CALL_P (insn)"
9c08d1fa 7752 "*
215b30b3 7753 return output_call (&operands[1]);
cffb2a26 7754 "
7755 [(set_attr "length" "12")
7756 (set_attr "type" "call")]
7757)
9c08d1fa 7758
89504fc1 7759;; Note: see *call_mem
7760
f7fbdd4a 7761(define_insn "*call_value_mem"
27ed6835 7762 [(set (match_operand 0 "" "")
a3c63a9d 7763 (call (mem:SI (match_operand:SI 1 "call_memory_operand" "m"))
cffb2a26 7764 (match_operand 2 "" "")))
bbe777ea 7765 (use (match_operand 3 "" ""))
bd5b4116 7766 (clobber (reg:SI LR_REGNUM))]
33ae7c4b 7767 "TARGET_ARM && !arm_arch5 && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
7768 && !SIBLING_CALL_P (insn)"
9c08d1fa 7769 "*
215b30b3 7770 return output_call_mem (&operands[1]);
cffb2a26 7771 "
7772 [(set_attr "length" "12")
7773 (set_attr "type" "call")]
7774)
9c08d1fa 7775
7776;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
7777;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
7778
f7fbdd4a 7779(define_insn "*call_symbol"
27ed6835 7780 [(call (mem:SI (match_operand:SI 0 "" ""))
cffb2a26 7781 (match_operand 1 "" ""))
bbe777ea 7782 (use (match_operand 2 "" ""))
bd5b4116 7783 (clobber (reg:SI LR_REGNUM))]
d68c2c10 7784 "TARGET_32BIT
33ae7c4b 7785 && !SIBLING_CALL_P (insn)
cffb2a26 7786 && (GET_CODE (operands[0]) == SYMBOL_REF)
de55252a 7787 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
6ebaa29d 7788 "*
7789 {
95f1e0d1 7790 rtx op = operands[0];
7791
7792 /* Switch mode now when possible. */
7793 if (SYMBOL_REF_DECL (op) && !TREE_PUBLIC (SYMBOL_REF_DECL (op))
7794 && arm_arch5 && arm_change_mode_p (SYMBOL_REF_DECL (op)))
7795 return NEED_PLT_RELOC ? \"blx%?\\t%a0(PLT)\" : \"blx%?\\t(%a0)\";
7796
55c1e470 7797 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
6ebaa29d 7798 }"
cffb2a26 7799 [(set_attr "type" "call")]
7800)
9c08d1fa 7801
f7fbdd4a 7802(define_insn "*call_value_symbol"
ccd90aaa 7803 [(set (match_operand 0 "" "")
27ed6835 7804 (call (mem:SI (match_operand:SI 1 "" ""))
dd6d7504 7805 (match_operand:SI 2 "" "")))
bbe777ea 7806 (use (match_operand 3 "" ""))
bd5b4116 7807 (clobber (reg:SI LR_REGNUM))]
d68c2c10 7808 "TARGET_32BIT
33ae7c4b 7809 && !SIBLING_CALL_P (insn)
cffb2a26 7810 && (GET_CODE (operands[1]) == SYMBOL_REF)
de55252a 7811 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
6ebaa29d 7812 "*
7813 {
95f1e0d1 7814 rtx op = operands[1];
7815
7816 /* Switch mode now when possible. */
7817 if (SYMBOL_REF_DECL (op) && !TREE_PUBLIC (SYMBOL_REF_DECL (op))
7818 && arm_arch5 && arm_change_mode_p (SYMBOL_REF_DECL (op)))
7819 return NEED_PLT_RELOC ? \"blx%?\\t%a0(PLT)\" : \"blx%?\\t(%a0)\";
7820
55c1e470 7821 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
6ebaa29d 7822 }"
cffb2a26 7823 [(set_attr "type" "call")]
7824)
7825
ca373797 7826(define_expand "sibcall_internal"
7827 [(parallel [(call (match_operand 0 "memory_operand" "")
7828 (match_operand 1 "general_operand" ""))
7829 (return)
7830 (use (match_operand 2 "" ""))])])
7831
1c494086 7832;; We may also be able to do sibcalls for Thumb, but it's much harder...
7833(define_expand "sibcall"
7834 [(parallel [(call (match_operand 0 "memory_operand" "")
7835 (match_operand 1 "general_operand" ""))
2ba80634 7836 (return)
7837 (use (match_operand 2 "" ""))])]
d68c2c10 7838 "TARGET_32BIT"
1c494086 7839 "
7840 {
ca373797 7841 rtx pat;
7842
3112c3f7 7843 if ((!REG_P (XEXP (operands[0], 0))
7844 && GET_CODE (XEXP (operands[0], 0)) != SYMBOL_REF)
7845 || (GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
7846 && arm_is_long_call_p (SYMBOL_REF_DECL (XEXP (operands[0], 0)))))
33ae7c4b 7847 XEXP (operands[0], 0) = force_reg (SImode, XEXP (operands[0], 0));
7848
1c494086 7849 if (operands[2] == NULL_RTX)
7850 operands[2] = const0_rtx;
ca373797 7851
7852 pat = gen_sibcall_internal (operands[0], operands[1], operands[2]);
7853 arm_emit_call_insn (pat, operands[0], true);
7854 DONE;
1c494086 7855 }"
7856)
7857
ca373797 7858(define_expand "sibcall_value_internal"
7859 [(parallel [(set (match_operand 0 "" "")
7860 (call (match_operand 1 "memory_operand" "")
7861 (match_operand 2 "general_operand" "")))
7862 (return)
7863 (use (match_operand 3 "" ""))])])
7864
1c494086 7865(define_expand "sibcall_value"
ccd90aaa 7866 [(parallel [(set (match_operand 0 "" "")
1c494086 7867 (call (match_operand 1 "memory_operand" "")
7868 (match_operand 2 "general_operand" "")))
2ba80634 7869 (return)
7870 (use (match_operand 3 "" ""))])]
d68c2c10 7871 "TARGET_32BIT"
1c494086 7872 "
7873 {
ca373797 7874 rtx pat;
7875
3112c3f7 7876 if ((!REG_P (XEXP (operands[1], 0))
7877 && GET_CODE (XEXP (operands[1], 0)) != SYMBOL_REF)
7878 || (GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
7879 && arm_is_long_call_p (SYMBOL_REF_DECL (XEXP (operands[1], 0)))))
33ae7c4b 7880 XEXP (operands[1], 0) = force_reg (SImode, XEXP (operands[1], 0));
7881
1c494086 7882 if (operands[3] == NULL_RTX)
7883 operands[3] = const0_rtx;
ca373797 7884
7885 pat = gen_sibcall_value_internal (operands[0], operands[1],
7886 operands[2], operands[3]);
7887 arm_emit_call_insn (pat, operands[1], true);
7888 DONE;
1c494086 7889 }"
7890)
7891
7892(define_insn "*sibcall_insn"
84ce8e5c 7893 [(call (mem:SI (match_operand:SI 0 "call_insn_operand" "Cs, US"))
1c494086 7894 (match_operand 1 "" ""))
2ba80634 7895 (return)
7896 (use (match_operand 2 "" ""))]
33ae7c4b 7897 "TARGET_32BIT && SIBLING_CALL_P (insn)"
1c494086 7898 "*
33ae7c4b 7899 if (which_alternative == 1)
7900 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
7901 else
7902 {
7903 if (arm_arch5 || arm_arch4t)
947d113e 7904 return \"bx%?\\t%0\\t%@ indirect register sibling call\";
33ae7c4b 7905 else
7906 return \"mov%?\\t%|pc, %0\\t%@ indirect register sibling call\";
7907 }
1c494086 7908 "
7909 [(set_attr "type" "call")]
7910)
7911
7912(define_insn "*sibcall_value_insn"
84ce8e5c 7913 [(set (match_operand 0 "" "")
7914 (call (mem:SI (match_operand:SI 1 "call_insn_operand" "Cs,US"))
1c494086 7915 (match_operand 2 "" "")))
2ba80634 7916 (return)
7917 (use (match_operand 3 "" ""))]
33ae7c4b 7918 "TARGET_32BIT && SIBLING_CALL_P (insn)"
1c494086 7919 "*
33ae7c4b 7920 if (which_alternative == 1)
7921 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
7922 else
7923 {
7924 if (arm_arch5 || arm_arch4t)
84ce8e5c 7925 return \"bx%?\\t%1\";
33ae7c4b 7926 else
7927 return \"mov%?\\t%|pc, %1\\t@ indirect sibling call \";
7928 }
1c494086 7929 "
7930 [(set_attr "type" "call")]
7931)
7932
0686440e 7933(define_expand "<return_str>return"
9b23f0a7 7934 [(RETURNS)]
8cba51a5 7935 "(TARGET_ARM || (TARGET_THUMB2
7936 && ARM_FUNC_TYPE (arm_current_func_type ()) == ARM_FT_NORMAL
7937 && !IS_STACKALIGN (arm_current_func_type ())))
0686440e 7938 <return_cond_false>"
8cba51a5 7939 "
7940 {
7941 if (TARGET_THUMB2)
7942 {
0686440e 7943 thumb2_expand_return (<return_simple_p>);
8cba51a5 7944 DONE;
7945 }
7946 }
7947 "
7948)
d68c2c10 7949
9c08d1fa 7950;; Often the return insn will be the same as loading from memory, so set attr
d68c2c10 7951(define_insn "*arm_return"
9c08d1fa 7952 [(return)]
cffb2a26 7953 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
9c08d1fa 7954 "*
9c08d1fa 7955 {
cffb2a26 7956 if (arm_ccfsm_state == 2)
7957 {
7958 arm_ccfsm_state += 2;
7959 return \"\";
7960 }
e2549f81 7961 return output_return_instruction (const_true_rtx, true, false, false);
cffb2a26 7962 }"
a2cd141b 7963 [(set_attr "type" "load1")
755eb2b4 7964 (set_attr "length" "12")
0d66636f 7965 (set_attr "predicable" "yes")]
cffb2a26 7966)
9c08d1fa 7967
0686440e 7968(define_insn "*cond_<return_str>return"
9c08d1fa 7969 [(set (pc)
8fa3ba89 7970 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 7971 [(match_operand 1 "cc_register" "") (const_int 0)])
9b23f0a7 7972 (RETURNS)
9c08d1fa 7973 (pc)))]
0686440e 7974 "TARGET_ARM <return_cond_true>"
9c08d1fa 7975 "*
8fa3ba89 7976 {
7977 if (arm_ccfsm_state == 2)
7978 {
7979 arm_ccfsm_state += 2;
7980 return \"\";
7981 }
0686440e 7982 return output_return_instruction (operands[0], true, false,
7983 <return_simple_p>);
8fa3ba89 7984 }"
7985 [(set_attr "conds" "use")
755eb2b4 7986 (set_attr "length" "12")
a2cd141b 7987 (set_attr "type" "load1")]
8fa3ba89 7988)
9c08d1fa 7989
0686440e 7990(define_insn "*cond_<return_str>return_inverted"
9c08d1fa 7991 [(set (pc)
8fa3ba89 7992 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 7993 [(match_operand 1 "cc_register" "") (const_int 0)])
9c08d1fa 7994 (pc)
9b23f0a7 7995 (RETURNS)))]
0686440e 7996 "TARGET_ARM <return_cond_true>"
9c08d1fa 7997 "*
8fa3ba89 7998 {
7999 if (arm_ccfsm_state == 2)
8000 {
8001 arm_ccfsm_state += 2;
8002 return \"\";
8003 }
0686440e 8004 return output_return_instruction (operands[0], true, true,
8005 <return_simple_p>);
8fa3ba89 8006 }"
8007 [(set_attr "conds" "use")
37a1317b 8008 (set_attr "length" "12")
a2cd141b 8009 (set_attr "type" "load1")]
8fa3ba89 8010)
9c08d1fa 8011
e2549f81 8012(define_insn "*arm_simple_return"
8013 [(simple_return)]
8014 "TARGET_ARM"
8015 "*
8016 {
8017 if (arm_ccfsm_state == 2)
8018 {
8019 arm_ccfsm_state += 2;
8020 return \"\";
8021 }
8022 return output_return_instruction (const_true_rtx, true, false, true);
8023 }"
8024 [(set_attr "type" "branch")
8025 (set_attr "length" "4")
8026 (set_attr "predicable" "yes")]
8027)
8028
68121397 8029;; Generate a sequence of instructions to determine if the processor is
8030;; in 26-bit or 32-bit mode, and return the appropriate return address
8031;; mask.
8032
8033(define_expand "return_addr_mask"
8034 [(set (match_dup 1)
8035 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8036 (const_int 0)))
8037 (set (match_operand:SI 0 "s_register_operand" "")
8038 (if_then_else:SI (eq (match_dup 1) (const_int 0))
8039 (const_int -1)
8040 (const_int 67108860)))] ; 0x03fffffc
8041 "TARGET_ARM"
8042 "
62eddbd4 8043 operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
68121397 8044 ")
8045
8046(define_insn "*check_arch2"
8047 [(set (match_operand:CC_NOOV 0 "cc_register" "")
8048 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8049 (const_int 0)))]
8050 "TARGET_ARM"
8051 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
8052 [(set_attr "length" "8")
1b7da4ac 8053 (set_attr "conds" "set")
8054 (set_attr "type" "multiple")]
68121397 8055)
8056
9c08d1fa 8057;; Call subroutine returning any type.
8058
8059(define_expand "untyped_call"
8060 [(parallel [(call (match_operand 0 "" "")
8061 (const_int 0))
8062 (match_operand 1 "" "")
8063 (match_operand 2 "" "")])]
ccd90aaa 8064 "TARGET_EITHER"
9c08d1fa 8065 "
215b30b3 8066 {
8067 int i;
ccd90aaa 8068 rtx par = gen_rtx_PARALLEL (VOIDmode,
8069 rtvec_alloc (XVECLEN (operands[2], 0)));
8070 rtx addr = gen_reg_rtx (Pmode);
8071 rtx mem;
8072 int size = 0;
9c08d1fa 8073
ccd90aaa 8074 emit_move_insn (addr, XEXP (operands[1], 0));
8075 mem = change_address (operands[1], BLKmode, addr);
9c08d1fa 8076
215b30b3 8077 for (i = 0; i < XVECLEN (operands[2], 0); i++)
8078 {
ccd90aaa 8079 rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
9c08d1fa 8080
ccd90aaa 8081 /* Default code only uses r0 as a return value, but we could
8082 be using anything up to 4 registers. */
8083 if (REGNO (src) == R0_REGNUM)
8084 src = gen_rtx_REG (TImode, R0_REGNUM);
8085
8086 XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
8087 GEN_INT (size));
8088 size += GET_MODE_SIZE (GET_MODE (src));
8089 }
8090
8091 emit_call_insn (GEN_CALL_VALUE (par, operands[0], const0_rtx, NULL,
8092 const0_rtx));
8093
8094 size = 0;
8095
8096 for (i = 0; i < XVECLEN (par, 0); i++)
8097 {
8098 HOST_WIDE_INT offset = 0;
8099 rtx reg = XEXP (XVECEXP (par, 0, i), 0);
8100
8101 if (size != 0)
29c05e22 8102 emit_move_insn (addr, plus_constant (Pmode, addr, size));
ccd90aaa 8103
8104 mem = change_address (mem, GET_MODE (reg), NULL);
8105 if (REGNO (reg) == R0_REGNUM)
8106 {
8107 /* On thumb we have to use a write-back instruction. */
320ea44d 8108 emit_insn (arm_gen_store_multiple (arm_regs_in_sequence, 4, addr,
8109 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
ccd90aaa 8110 size = TARGET_ARM ? 16 : 0;
8111 }
8112 else
8113 {
8114 emit_move_insn (mem, reg);
8115 size = GET_MODE_SIZE (GET_MODE (reg));
8116 }
215b30b3 8117 }
9c08d1fa 8118
215b30b3 8119 /* The optimizer does not know that the call sets the function value
8120 registers we stored in the result block. We avoid problems by
8121 claiming that all hard registers are used and clobbered at this
8122 point. */
8123 emit_insn (gen_blockage ());
8124
8125 DONE;
8126 }"
8127)
9c08d1fa 8128
ccd90aaa 8129(define_expand "untyped_return"
8130 [(match_operand:BLK 0 "memory_operand" "")
8131 (match_operand 1 "" "")]
8132 "TARGET_EITHER"
8133 "
8134 {
8135 int i;
8136 rtx addr = gen_reg_rtx (Pmode);
8137 rtx mem;
8138 int size = 0;
8139
8140 emit_move_insn (addr, XEXP (operands[0], 0));
8141 mem = change_address (operands[0], BLKmode, addr);
8142
8143 for (i = 0; i < XVECLEN (operands[1], 0); i++)
8144 {
8145 HOST_WIDE_INT offset = 0;
8146 rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
8147
8148 if (size != 0)
29c05e22 8149 emit_move_insn (addr, plus_constant (Pmode, addr, size));
ccd90aaa 8150
8151 mem = change_address (mem, GET_MODE (reg), NULL);
8152 if (REGNO (reg) == R0_REGNUM)
8153 {
8154 /* On thumb we have to use a write-back instruction. */
320ea44d 8155 emit_insn (arm_gen_load_multiple (arm_regs_in_sequence, 4, addr,
8156 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
ccd90aaa 8157 size = TARGET_ARM ? 16 : 0;
8158 }
8159 else
8160 {
8161 emit_move_insn (reg, mem);
8162 size = GET_MODE_SIZE (GET_MODE (reg));
8163 }
8164 }
8165
8166 /* Emit USE insns before the return. */
8167 for (i = 0; i < XVECLEN (operands[1], 0); i++)
18b42941 8168 emit_use (SET_DEST (XVECEXP (operands[1], 0, i)));
ccd90aaa 8169
8170 /* Construct the return. */
8171 expand_naked_return ();
8172
8173 DONE;
8174 }"
8175)
8176
9c08d1fa 8177;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
8178;; all of memory. This blocks insns from being moved across this point.
8179
8180(define_insn "blockage"
e1159bbe 8181 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
cffb2a26 8182 "TARGET_EITHER"
9c08d1fa 8183 ""
cffb2a26 8184 [(set_attr "length" "0")
8185 (set_attr "type" "block")]
8186)
9c08d1fa 8187
f7fbdd4a 8188(define_expand "casesi"
8189 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
aea4c774 8190 (match_operand:SI 1 "const_int_operand" "") ; lower bound
8191 (match_operand:SI 2 "const_int_operand" "") ; total range
f7fbdd4a 8192 (match_operand:SI 3 "" "") ; table label
8193 (match_operand:SI 4 "" "")] ; Out of range label
e6ac8414 8194 "TARGET_32BIT || optimize_size || flag_pic"
f7fbdd4a 8195 "
215b30b3 8196 {
e6ac8414 8197 enum insn_code code;
215b30b3 8198 if (operands[1] != const0_rtx)
8199 {
e6ac8414 8200 rtx reg = gen_reg_rtx (SImode);
f7fbdd4a 8201
215b30b3 8202 emit_insn (gen_addsi3 (reg, operands[0],
d022fa24 8203 gen_int_mode (-INTVAL (operands[1]),
8204 SImode)));
215b30b3 8205 operands[0] = reg;
8206 }
9c08d1fa 8207
25f905c2 8208 if (TARGET_ARM)
e6ac8414 8209 code = CODE_FOR_arm_casesi_internal;
3db2019b 8210 else if (TARGET_THUMB1)
e6ac8414 8211 code = CODE_FOR_thumb1_casesi_internal_pic;
25f905c2 8212 else if (flag_pic)
e6ac8414 8213 code = CODE_FOR_thumb2_casesi_internal_pic;
25f905c2 8214 else
e6ac8414 8215 code = CODE_FOR_thumb2_casesi_internal;
8216
8217 if (!insn_data[(int) code].operand[1].predicate(operands[2], SImode))
8218 operands[2] = force_reg (SImode, operands[2]);
8219
8220 emit_jump_insn (GEN_FCN ((int) code) (operands[0], operands[2],
8221 operands[3], operands[4]));
215b30b3 8222 DONE;
8223 }"
8224)
f7fbdd4a 8225
f082f1c4 8226;; The USE in this pattern is needed to tell flow analysis that this is
8227;; a CASESI insn. It has no other purpose.
25f905c2 8228(define_insn "arm_casesi_internal"
f082f1c4 8229 [(parallel [(set (pc)
8230 (if_then_else
8231 (leu (match_operand:SI 0 "s_register_operand" "r")
8232 (match_operand:SI 1 "arm_rhs_operand" "rI"))
8233 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
8234 (label_ref (match_operand 2 "" ""))))
8235 (label_ref (match_operand 3 "" ""))))
bd5b4116 8236 (clobber (reg:CC CC_REGNUM))
f082f1c4 8237 (use (label_ref (match_dup 2)))])]
cffb2a26 8238 "TARGET_ARM"
f7fbdd4a 8239 "*
0d66636f 8240 if (flag_pic)
8241 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
8242 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
8243 "
8244 [(set_attr "conds" "clob")
1b7da4ac 8245 (set_attr "length" "12")
8246 (set_attr "type" "multiple")]
0d66636f 8247)
9c08d1fa 8248
cffb2a26 8249(define_expand "indirect_jump"
9c08d1fa 8250 [(set (pc)
cffb2a26 8251 (match_operand:SI 0 "s_register_operand" ""))]
8252 "TARGET_EITHER"
25f905c2 8253 "
8254 /* Thumb-2 doesn't have mov pc, reg. Explicitly set the low bit of the
8255 address and use bx. */
8256 if (TARGET_THUMB2)
8257 {
8258 rtx tmp;
8259 tmp = gen_reg_rtx (SImode);
8260 emit_insn (gen_iorsi3 (tmp, operands[0], GEN_INT(1)));
8261 operands[0] = tmp;
8262 }
8263 "
cffb2a26 8264)
8265
f1039640 8266;; NB Never uses BX.
cffb2a26 8267(define_insn "*arm_indirect_jump"
8268 [(set (pc)
8269 (match_operand:SI 0 "s_register_operand" "r"))]
8270 "TARGET_ARM"
8271 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
1b7da4ac 8272 [(set_attr "predicable" "yes")
8273 (set_attr "type" "branch")]
cffb2a26 8274)
9c08d1fa 8275
f7fbdd4a 8276(define_insn "*load_indirect_jump"
9c08d1fa 8277 [(set (pc)
8278 (match_operand:SI 0 "memory_operand" "m"))]
cffb2a26 8279 "TARGET_ARM"
8280 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
a2cd141b 8281 [(set_attr "type" "load1")
61a2d04c 8282 (set_attr "pool_range" "4096")
8283 (set_attr "neg_pool_range" "4084")
0d66636f 8284 (set_attr "predicable" "yes")]
cffb2a26 8285)
8286
9c08d1fa 8287\f
8288;; Misc insns
8289
8290(define_insn "nop"
8291 [(const_int 0)]
cffb2a26 8292 "TARGET_EITHER"
8293 "*
25f905c2 8294 if (TARGET_UNIFIED_ASM)
8295 return \"nop\";
cffb2a26 8296 if (TARGET_ARM)
8297 return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
8298 return \"mov\\tr8, r8\";
8299 "
8300 [(set (attr "length")
8301 (if_then_else (eq_attr "is_thumb" "yes")
8302 (const_int 2)
1b7da4ac 8303 (const_int 4)))
8304 (set_attr "type" "mov_reg")]
cffb2a26 8305)
8306
ad9d4399 8307(define_insn "trap"
8308 [(trap_if (const_int 1) (const_int 0))]
8309 ""
8310 "*
8311 if (TARGET_ARM)
8312 return \".inst\\t0xe7f000f0\";
8313 else
8314 return \".inst\\t0xdeff\";
8315 "
8316 [(set (attr "length")
8317 (if_then_else (eq_attr "is_thumb" "yes")
8318 (const_int 2)
8319 (const_int 4)))
8320 (set_attr "type" "trap")
8321 (set_attr "conds" "unconditional")]
8322)
8323
9c08d1fa 8324\f
8325;; Patterns to allow combination of arithmetic, cond code and shifts
8326
0abea32c 8327(define_insn "*<arith_shift_insn>_multsi"
8328 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9b23f0a7 8329 (SHIFTABLE_OPS:SI
0abea32c 8330 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
8331 (match_operand:SI 3 "power_of_two_operand" ""))
8332 (match_operand:SI 1 "s_register_operand" "rk,<t2_binop0>")))]
d5d4dc8d 8333 "TARGET_32BIT"
0abea32c 8334 "<arith_shift_insn>%?\\t%0, %1, %2, lsl %b3"
8335 [(set_attr "predicable" "yes")
8336 (set_attr "predicable_short_it" "no")
753d9835 8337 (set_attr "shift" "2")
0abea32c 8338 (set_attr "arch" "a,t2")
8339 (set_attr "type" "alu_shift_imm")])
8340
8341(define_insn "*<arith_shift_insn>_shiftsi"
8342 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9b23f0a7 8343 (SHIFTABLE_OPS:SI
0abea32c 8344 (match_operator:SI 2 "shift_nomul_operator"
8345 [(match_operand:SI 3 "s_register_operand" "r,r,r")
8346 (match_operand:SI 4 "shift_amount_operand" "M,M,r")])
8347 (match_operand:SI 1 "s_register_operand" "rk,<t2_binop0>,rk")))]
a021b821 8348 "TARGET_32BIT && GET_CODE (operands[2]) != MULT"
0abea32c 8349 "<arith_shift_insn>%?\\t%0, %1, %3%S2"
344495ea 8350 [(set_attr "predicable" "yes")
74ef923b 8351 (set_attr "predicable_short_it" "no")
753d9835 8352 (set_attr "shift" "3")
0abea32c 8353 (set_attr "arch" "a,t2,a")
8354 (set_attr "type" "alu_shift_imm,alu_shift_imm,alu_shift_reg")])
9c08d1fa 8355
d7863cfe 8356(define_split
8357 [(set (match_operand:SI 0 "s_register_operand" "")
8358 (match_operator:SI 1 "shiftable_operator"
8359 [(match_operator:SI 2 "shiftable_operator"
8360 [(match_operator:SI 3 "shift_operator"
8361 [(match_operand:SI 4 "s_register_operand" "")
8362 (match_operand:SI 5 "reg_or_int_operand" "")])
8363 (match_operand:SI 6 "s_register_operand" "")])
8364 (match_operand:SI 7 "arm_rhs_operand" "")]))
8365 (clobber (match_operand:SI 8 "s_register_operand" ""))]
d5d4dc8d 8366 "TARGET_32BIT"
d7863cfe 8367 [(set (match_dup 8)
8368 (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8369 (match_dup 6)]))
8370 (set (match_dup 0)
8371 (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
8372 "")
8373
f7fbdd4a 8374(define_insn "*arith_shiftsi_compare0"
bd5b4116 8375 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 8376 (compare:CC_NOOV
8377 (match_operator:SI 1 "shiftable_operator"
8378 [(match_operator:SI 3 "shift_operator"
8379 [(match_operand:SI 4 "s_register_operand" "r,r")
8380 (match_operand:SI 5 "shift_amount_operand" "M,r")])
8381 (match_operand:SI 2 "s_register_operand" "r,r")])
8382 (const_int 0)))
8383 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 8384 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8385 (match_dup 2)]))]
d5d4dc8d 8386 "TARGET_32BIT"
25f905c2 8387 "%i1%.\\t%0, %2, %4%S3"
344495ea 8388 [(set_attr "conds" "set")
331beb1a 8389 (set_attr "shift" "4")
d5d4dc8d 8390 (set_attr "arch" "32,a")
d82e788e 8391 (set_attr "type" "alus_shift_imm,alus_shift_reg")])
9c08d1fa 8392
f7fbdd4a 8393(define_insn "*arith_shiftsi_compare0_scratch"
bd5b4116 8394 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 8395 (compare:CC_NOOV
8396 (match_operator:SI 1 "shiftable_operator"
8397 [(match_operator:SI 3 "shift_operator"
8398 [(match_operand:SI 4 "s_register_operand" "r,r")
8399 (match_operand:SI 5 "shift_amount_operand" "M,r")])
8400 (match_operand:SI 2 "s_register_operand" "r,r")])
8401 (const_int 0)))
8402 (clobber (match_scratch:SI 0 "=r,r"))]
8403 "TARGET_32BIT"
25f905c2 8404 "%i1%.\\t%0, %2, %4%S3"
344495ea 8405 [(set_attr "conds" "set")
331beb1a 8406 (set_attr "shift" "4")
d5d4dc8d 8407 (set_attr "arch" "32,a")
d82e788e 8408 (set_attr "type" "alus_shift_imm,alus_shift_reg")])
9c08d1fa 8409
f7fbdd4a 8410(define_insn "*sub_shiftsi"
d5d4dc8d 8411 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8412 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
9c08d1fa 8413 (match_operator:SI 2 "shift_operator"
d5d4dc8d 8414 [(match_operand:SI 3 "s_register_operand" "r,r")
8415 (match_operand:SI 4 "shift_amount_operand" "M,r")])))]
8416 "TARGET_32BIT"
6c4c2133 8417 "sub%?\\t%0, %1, %3%S2"
344495ea 8418 [(set_attr "predicable" "yes")
331beb1a 8419 (set_attr "shift" "3")
d5d4dc8d 8420 (set_attr "arch" "32,a")
d82e788e 8421 (set_attr "type" "alus_shift_imm,alus_shift_reg")])
9c08d1fa 8422
f7fbdd4a 8423(define_insn "*sub_shiftsi_compare0"
bd5b4116 8424 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 8425 (compare:CC_NOOV
d82e788e 8426 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
40dbec34 8427 (match_operator:SI 2 "shift_operator"
d82e788e 8428 [(match_operand:SI 3 "s_register_operand" "r,r,r")
8429 (match_operand:SI 4 "shift_amount_operand" "M,r,M")]))
40dbec34 8430 (const_int 0)))
d82e788e 8431 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
d5d4dc8d 8432 (minus:SI (match_dup 1)
8433 (match_op_dup 2 [(match_dup 3) (match_dup 4)])))]
8434 "TARGET_32BIT"
25f905c2 8435 "sub%.\\t%0, %1, %3%S2"
344495ea 8436 [(set_attr "conds" "set")
a2cd141b 8437 (set_attr "shift" "3")
d82e788e 8438 (set_attr "arch" "32,a,a")
8439 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
9c08d1fa 8440
f7fbdd4a 8441(define_insn "*sub_shiftsi_compare0_scratch"
bd5b4116 8442 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 8443 (compare:CC_NOOV
d82e788e 8444 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
40dbec34 8445 (match_operator:SI 2 "shift_operator"
d82e788e 8446 [(match_operand:SI 3 "s_register_operand" "r,r,r")
8447 (match_operand:SI 4 "shift_amount_operand" "M,r,M")]))
40dbec34 8448 (const_int 0)))
d82e788e 8449 (clobber (match_scratch:SI 0 "=r,r,r"))]
d5d4dc8d 8450 "TARGET_32BIT"
25f905c2 8451 "sub%.\\t%0, %1, %3%S2"
344495ea 8452 [(set_attr "conds" "set")
a2cd141b 8453 (set_attr "shift" "3")
d82e788e 8454 (set_attr "arch" "32,a,a")
8455 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
9c08d1fa 8456\f
8457
190efb17 8458(define_insn_and_split "*and_scc"
9c08d1fa 8459 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 8460 (and:SI (match_operator:SI 1 "arm_comparison_operator"
190efb17 8461 [(match_operand 2 "cc_register" "") (const_int 0)])
8462 (match_operand:SI 3 "s_register_operand" "r")))]
cffb2a26 8463 "TARGET_ARM"
190efb17 8464 "#" ; "mov%D1\\t%0, #0\;and%d1\\t%0, %3, #1"
8465 "&& reload_completed"
8466 [(cond_exec (match_dup 5) (set (match_dup 0) (const_int 0)))
8467 (cond_exec (match_dup 4) (set (match_dup 0)
8468 (and:SI (match_dup 3) (const_int 1))))]
8469 {
3754d046 8470 machine_mode mode = GET_MODE (operands[2]);
190efb17 8471 enum rtx_code rc = GET_CODE (operands[1]);
8472
8473 /* Note that operands[4] is the same as operands[1],
8474 but with VOIDmode as the result. */
8475 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
8476 if (mode == CCFPmode || mode == CCFPEmode)
8477 rc = reverse_condition_maybe_unordered (rc);
8478 else
8479 rc = reverse_condition (rc);
8480 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
8481 }
8fa3ba89 8482 [(set_attr "conds" "use")
1b7da4ac 8483 (set_attr "type" "multiple")
8fa3ba89 8484 (set_attr "length" "8")]
8485)
9c08d1fa 8486
190efb17 8487(define_insn_and_split "*ior_scc"
9c08d1fa 8488 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
190efb17 8489 (ior:SI (match_operator:SI 1 "arm_comparison_operator"
8490 [(match_operand 2 "cc_register" "") (const_int 0)])
8491 (match_operand:SI 3 "s_register_operand" "0,?r")))]
cffb2a26 8492 "TARGET_ARM"
e2348bcb 8493 "@
190efb17 8494 orr%d1\\t%0, %3, #1
8495 #"
8496 "&& reload_completed
8497 && REGNO (operands [0]) != REGNO (operands[3])"
8498 ;; && which_alternative == 1
8499 ; mov%D1\\t%0, %3\;orr%d1\\t%0, %3, #1
8500 [(cond_exec (match_dup 5) (set (match_dup 0) (match_dup 3)))
8501 (cond_exec (match_dup 4) (set (match_dup 0)
8502 (ior:SI (match_dup 3) (const_int 1))))]
8503 {
3754d046 8504 machine_mode mode = GET_MODE (operands[2]);
190efb17 8505 enum rtx_code rc = GET_CODE (operands[1]);
8506
8507 /* Note that operands[4] is the same as operands[1],
8508 but with VOIDmode as the result. */
8509 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
8510 if (mode == CCFPmode || mode == CCFPEmode)
8511 rc = reverse_condition_maybe_unordered (rc);
8512 else
8513 rc = reverse_condition (rc);
8514 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
8515 }
8fa3ba89 8516 [(set_attr "conds" "use")
1b7da4ac 8517 (set_attr "length" "4,8")
8518 (set_attr "type" "logic_imm,multiple")]
8fa3ba89 8519)
9c08d1fa 8520
2df9477b 8521; A series of splitters for the compare_scc pattern below. Note that
8522; order is important.
8523(define_split
8524 [(set (match_operand:SI 0 "s_register_operand" "")
8525 (lt:SI (match_operand:SI 1 "s_register_operand" "")
8526 (const_int 0)))
8527 (clobber (reg:CC CC_REGNUM))]
8528 "TARGET_32BIT && reload_completed"
8529 [(set (match_dup 0) (lshiftrt:SI (match_dup 1) (const_int 31)))])
8530
8531(define_split
8532 [(set (match_operand:SI 0 "s_register_operand" "")
8533 (ge:SI (match_operand:SI 1 "s_register_operand" "")
8534 (const_int 0)))
8535 (clobber (reg:CC CC_REGNUM))]
8536 "TARGET_32BIT && reload_completed"
8537 [(set (match_dup 0) (not:SI (match_dup 1)))
8538 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 31)))])
8539
98562479 8540(define_split
8541 [(set (match_operand:SI 0 "s_register_operand" "")
8542 (eq:SI (match_operand:SI 1 "s_register_operand" "")
8543 (const_int 0)))
8544 (clobber (reg:CC CC_REGNUM))]
8545 "arm_arch5 && TARGET_32BIT"
8546 [(set (match_dup 0) (clz:SI (match_dup 1)))
8547 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 5)))]
8548)
8549
2df9477b 8550(define_split
8551 [(set (match_operand:SI 0 "s_register_operand" "")
8552 (eq:SI (match_operand:SI 1 "s_register_operand" "")
8553 (const_int 0)))
8554 (clobber (reg:CC CC_REGNUM))]
8555 "TARGET_32BIT && reload_completed"
8556 [(parallel
080c0b9a 8557 [(set (reg:CC CC_REGNUM)
8558 (compare:CC (const_int 1) (match_dup 1)))
2df9477b 8559 (set (match_dup 0)
8560 (minus:SI (const_int 1) (match_dup 1)))])
080c0b9a 8561 (cond_exec (ltu:CC (reg:CC CC_REGNUM) (const_int 0))
2df9477b 8562 (set (match_dup 0) (const_int 0)))])
8563
8564(define_split
8565 [(set (match_operand:SI 0 "s_register_operand" "")
8566 (ne:SI (match_operand:SI 1 "s_register_operand" "")
8567 (match_operand:SI 2 "const_int_operand" "")))
8568 (clobber (reg:CC CC_REGNUM))]
8569 "TARGET_32BIT && reload_completed"
8570 [(parallel
8571 [(set (reg:CC CC_REGNUM)
8572 (compare:CC (match_dup 1) (match_dup 2)))
8573 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))])
8574 (cond_exec (ne:CC (reg:CC CC_REGNUM) (const_int 0))
8575 (set (match_dup 0) (const_int 1)))]
8576{
8577 operands[3] = GEN_INT (-INTVAL (operands[2]));
8578})
8579
8580(define_split
8581 [(set (match_operand:SI 0 "s_register_operand" "")
8582 (ne:SI (match_operand:SI 1 "s_register_operand" "")
8583 (match_operand:SI 2 "arm_add_operand" "")))
8584 (clobber (reg:CC CC_REGNUM))]
8585 "TARGET_32BIT && reload_completed"
8586 [(parallel
8587 [(set (reg:CC_NOOV CC_REGNUM)
8588 (compare:CC_NOOV (minus:SI (match_dup 1) (match_dup 2))
8589 (const_int 0)))
8590 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
8591 (cond_exec (ne:CC_NOOV (reg:CC_NOOV CC_REGNUM) (const_int 0))
8592 (set (match_dup 0) (const_int 1)))])
8593
8594(define_insn_and_split "*compare_scc"
fd711051 8595 [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts")
8fa3ba89 8596 (match_operator:SI 1 "arm_comparison_operator"
5565501b 8597 [(match_operand:SI 2 "s_register_operand" "r,r")
8598 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
bd5b4116 8599 (clobber (reg:CC CC_REGNUM))]
2df9477b 8600 "TARGET_32BIT"
8601 "#"
8602 "&& reload_completed"
8603 [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 3)))
8604 (cond_exec (match_dup 4) (set (match_dup 0) (const_int 0)))
8605 (cond_exec (match_dup 5) (set (match_dup 0) (const_int 1)))]
8606{
8607 rtx tmp1;
3754d046 8608 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
2df9477b 8609 operands[2], operands[3]);
8610 enum rtx_code rc = GET_CODE (operands[1]);
e2348bcb 8611
2df9477b 8612 tmp1 = gen_rtx_REG (mode, CC_REGNUM);
080c0b9a 8613
2df9477b 8614 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
8615 if (mode == CCFPmode || mode == CCFPEmode)
8616 rc = reverse_condition_maybe_unordered (rc);
8617 else
8618 rc = reverse_condition (rc);
8619 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
1b7da4ac 8620}
8621 [(set_attr "type" "multiple")]
8622)
9c08d1fa 8623
080c0b9a 8624;; Attempt to improve the sequence generated by the compare_scc splitters
8625;; not to use conditional execution.
98562479 8626
8627;; Rd = (eq (reg1) (const_int0)) // ARMv5
8628;; clz Rd, reg1
8629;; lsr Rd, Rd, #5
080c0b9a 8630(define_peephole2
8631 [(set (reg:CC CC_REGNUM)
8632 (compare:CC (match_operand:SI 1 "register_operand" "")
98562479 8633 (const_int 0)))
8634 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
8635 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
8636 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
8637 (set (match_dup 0) (const_int 1)))]
8638 "arm_arch5 && TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)"
8639 [(set (match_dup 0) (clz:SI (match_dup 1)))
8640 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 5)))]
8641)
8642
8643;; Rd = (eq (reg1) (const_int0)) // !ARMv5
8644;; negs Rd, reg1
8645;; adc Rd, Rd, reg1
8646(define_peephole2
8647 [(set (reg:CC CC_REGNUM)
8648 (compare:CC (match_operand:SI 1 "register_operand" "")
8649 (const_int 0)))
080c0b9a 8650 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
8651 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
8652 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
8653 (set (match_dup 0) (const_int 1)))
98562479 8654 (match_scratch:SI 2 "r")]
8655 "TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)"
922b6913 8656 [(parallel
8657 [(set (reg:CC CC_REGNUM)
98562479 8658 (compare:CC (const_int 0) (match_dup 1)))
8659 (set (match_dup 2) (minus:SI (const_int 0) (match_dup 1)))])
8660 (set (match_dup 0)
8661 (plus:SI (plus:SI (match_dup 1) (match_dup 2))
8662 (geu:SI (reg:CC CC_REGNUM) (const_int 0))))]
8663)
8664
31991287 8665;; Rd = (eq (reg1) (reg2/imm)) // ARMv5 and optimising for speed.
98562479 8666;; sub Rd, Reg1, reg2
8667;; clz Rd, Rd
8668;; lsr Rd, Rd, #5
8669(define_peephole2
8670 [(set (reg:CC CC_REGNUM)
8671 (compare:CC (match_operand:SI 1 "register_operand" "")
8672 (match_operand:SI 2 "arm_rhs_operand" "")))
8673 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
8674 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
8675 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
8676 (set (match_dup 0) (const_int 1)))]
31991287 8677 "arm_arch5 && TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)
8678 && !(TARGET_THUMB2 && optimize_insn_for_size_p ())"
98562479 8679 [(set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))
8680 (set (match_dup 0) (clz:SI (match_dup 0)))
8681 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 5)))]
8682)
8683
8684
31991287 8685;; Rd = (eq (reg1) (reg2)) // ! ARMv5 or optimising for size.
98562479 8686;; sub T1, Reg1, reg2
8687;; negs Rd, T1
8688;; adc Rd, Rd, T1
8689(define_peephole2
8690 [(set (reg:CC CC_REGNUM)
8691 (compare:CC (match_operand:SI 1 "register_operand" "")
8692 (match_operand:SI 2 "arm_rhs_operand" "")))
8693 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
8694 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
8695 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
8696 (set (match_dup 0) (const_int 1)))
8697 (match_scratch:SI 3 "r")]
8698 "TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)"
31991287 8699 [(set (match_dup 3) (match_dup 4))
080c0b9a 8700 (parallel
8701 [(set (reg:CC CC_REGNUM)
8702 (compare:CC (const_int 0) (match_dup 3)))
8703 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 3)))])
98562479 8704 (set (match_dup 0)
8705 (plus:SI (plus:SI (match_dup 0) (match_dup 3))
8706 (geu:SI (reg:CC CC_REGNUM) (const_int 0))))]
31991287 8707 "
8708 if (CONST_INT_P (operands[2]))
8709 operands[4] = plus_constant (SImode, operands[1], -INTVAL (operands[2]));
8710 else
8711 operands[4] = gen_rtx_MINUS (SImode, operands[1], operands[2]);
8712 ")
080c0b9a 8713
f7fbdd4a 8714(define_insn "*cond_move"
9c08d1fa 8715 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
aea4c774 8716 (if_then_else:SI (match_operator 3 "equality_operator"
8fa3ba89 8717 [(match_operator 4 "arm_comparison_operator"
8a18b90c 8718 [(match_operand 5 "cc_register" "") (const_int 0)])
aea4c774 8719 (const_int 0)])
8720 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8721 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
cffb2a26 8722 "TARGET_ARM"
9c08d1fa 8723 "*
8fa3ba89 8724 if (GET_CODE (operands[3]) == NE)
8725 {
8726 if (which_alternative != 1)
8727 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
8728 if (which_alternative != 0)
8729 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
8730 return \"\";
8731 }
8732 if (which_alternative != 0)
8733 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8734 if (which_alternative != 1)
8735 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
8736 return \"\";
8737 "
8738 [(set_attr "conds" "use")
282b4c75 8739 (set_attr_alternative "type"
8740 [(if_then_else (match_operand 2 "const_int_operand" "")
8741 (const_string "mov_imm")
8742 (const_string "mov_reg"))
8743 (if_then_else (match_operand 1 "const_int_operand" "")
8744 (const_string "mov_imm")
8745 (const_string "mov_reg"))
8746 (const_string "multiple")])
8fa3ba89 8747 (set_attr "length" "4,4,8")]
8748)
9c08d1fa 8749
f7fbdd4a 8750(define_insn "*cond_arith"
9c08d1fa 8751 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8752 (match_operator:SI 5 "shiftable_operator"
8fa3ba89 8753 [(match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 8754 [(match_operand:SI 2 "s_register_operand" "r,r")
8755 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8756 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 8757 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8758 "TARGET_ARM"
9c08d1fa 8759 "*
8fa3ba89 8760 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
8761 return \"%i5\\t%0, %1, %2, lsr #31\";
40dbec34 8762
8fa3ba89 8763 output_asm_insn (\"cmp\\t%2, %3\", operands);
8764 if (GET_CODE (operands[5]) == AND)
8765 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
8766 else if (GET_CODE (operands[5]) == MINUS)
8767 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
8768 else if (which_alternative != 0)
8769 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8770 return \"%i5%d4\\t%0, %1, #1\";
8771 "
8772 [(set_attr "conds" "clob")
1b7da4ac 8773 (set_attr "length" "12")
8774 (set_attr "type" "multiple")]
8fa3ba89 8775)
9c08d1fa 8776
f7fbdd4a 8777(define_insn "*cond_sub"
9c08d1fa 8778 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8779 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8fa3ba89 8780 (match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 8781 [(match_operand:SI 2 "s_register_operand" "r,r")
8782 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 8783 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8784 "TARGET_ARM"
9c08d1fa 8785 "*
8fa3ba89 8786 output_asm_insn (\"cmp\\t%2, %3\", operands);
8787 if (which_alternative != 0)
8788 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8789 return \"sub%d4\\t%0, %1, #1\";
8790 "
8791 [(set_attr "conds" "clob")
1b7da4ac 8792 (set_attr "length" "8,12")
8793 (set_attr "type" "multiple")]
8fa3ba89 8794)
9c08d1fa 8795
aea4c774 8796(define_insn "*cmp_ite0"
cffb2a26 8797 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 8798 (compare
8799 (if_then_else:SI
8fa3ba89 8800 (match_operator 4 "arm_comparison_operator"
2ff91fec 8801 [(match_operand:SI 0 "s_register_operand"
8802 "l,l,l,r,r,r,r,r,r")
8803 (match_operand:SI 1 "arm_add_operand"
8804 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
8fa3ba89 8805 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 8806 [(match_operand:SI 2 "s_register_operand"
8807 "l,r,r,l,l,r,r,r,r")
8808 (match_operand:SI 3 "arm_add_operand"
8809 "lPy,rI,L,lPy,lPy,rI,rI,L,L")])
aea4c774 8810 (const_int 0))
8811 (const_int 0)))]
2ff91fec 8812 "TARGET_32BIT"
9c08d1fa 8813 "*
aea4c774 8814 {
2ff91fec 8815 static const char * const cmp1[NUM_OF_COND_CMP][2] =
8816 {
8817 {\"cmp%d5\\t%0, %1\",
8818 \"cmp%d4\\t%2, %3\"},
8819 {\"cmn%d5\\t%0, #%n1\",
8820 \"cmp%d4\\t%2, %3\"},
8821 {\"cmp%d5\\t%0, %1\",
8822 \"cmn%d4\\t%2, #%n3\"},
8823 {\"cmn%d5\\t%0, #%n1\",
8824 \"cmn%d4\\t%2, #%n3\"}
8825 };
8826 static const char * const cmp2[NUM_OF_COND_CMP][2] =
8827 {
8828 {\"cmp\\t%2, %3\",
8829 \"cmp\\t%0, %1\"},
8830 {\"cmp\\t%2, %3\",
8831 \"cmn\\t%0, #%n1\"},
8832 {\"cmn\\t%2, #%n3\",
8833 \"cmp\\t%0, %1\"},
8834 {\"cmn\\t%2, #%n3\",
8835 \"cmn\\t%0, #%n1\"}
8836 };
8837 static const char * const ite[2] =
8fa3ba89 8838 {
2ff91fec 8839 \"it\\t%d5\",
8840 \"it\\t%d4\"
8fa3ba89 8841 };
2ff91fec 8842 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
8843 CMP_CMP, CMN_CMP, CMP_CMP,
8844 CMN_CMP, CMP_CMN, CMN_CMN};
8fa3ba89 8845 int swap =
8846 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8847
2ff91fec 8848 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
8849 if (TARGET_THUMB2) {
8850 output_asm_insn (ite[swap], operands);
8851 }
8852 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
8853 return \"\";
8fa3ba89 8854 }"
8855 [(set_attr "conds" "set")
2ff91fec 8856 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
1b7da4ac 8857 (set_attr "type" "multiple")
2ff91fec 8858 (set_attr_alternative "length"
8859 [(const_int 6)
8860 (const_int 8)
8861 (const_int 8)
8862 (const_int 8)
8863 (const_int 8)
8864 (if_then_else (eq_attr "is_thumb" "no")
8865 (const_int 8)
8866 (const_int 10))
8867 (if_then_else (eq_attr "is_thumb" "no")
8868 (const_int 8)
8869 (const_int 10))
8870 (if_then_else (eq_attr "is_thumb" "no")
8871 (const_int 8)
8872 (const_int 10))
8873 (if_then_else (eq_attr "is_thumb" "no")
8874 (const_int 8)
8875 (const_int 10))])]
8fa3ba89 8876)
9c08d1fa 8877
aea4c774 8878(define_insn "*cmp_ite1"
cffb2a26 8879 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 8880 (compare
8881 (if_then_else:SI
8fa3ba89 8882 (match_operator 4 "arm_comparison_operator"
2ff91fec 8883 [(match_operand:SI 0 "s_register_operand"
8884 "l,l,l,r,r,r,r,r,r")
8885 (match_operand:SI 1 "arm_add_operand"
8886 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
8fa3ba89 8887 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 8888 [(match_operand:SI 2 "s_register_operand"
8889 "l,r,r,l,l,r,r,r,r")
8890 (match_operand:SI 3 "arm_add_operand"
8891 "lPy,rI,L,lPy,lPy,rI,rI,L,L")])
aea4c774 8892 (const_int 1))
8893 (const_int 0)))]
2ff91fec 8894 "TARGET_32BIT"
9c08d1fa 8895 "*
9c08d1fa 8896 {
2ff91fec 8897 static const char * const cmp1[NUM_OF_COND_CMP][2] =
8898 {
8899 {\"cmp\\t%0, %1\",
8900 \"cmp\\t%2, %3\"},
8901 {\"cmn\\t%0, #%n1\",
8902 \"cmp\\t%2, %3\"},
8903 {\"cmp\\t%0, %1\",
8904 \"cmn\\t%2, #%n3\"},
8905 {\"cmn\\t%0, #%n1\",
8906 \"cmn\\t%2, #%n3\"}
8907 };
8908 static const char * const cmp2[NUM_OF_COND_CMP][2] =
215b30b3 8909 {
2ff91fec 8910 {\"cmp%d4\\t%2, %3\",
8911 \"cmp%D5\\t%0, %1\"},
8912 {\"cmp%d4\\t%2, %3\",
8913 \"cmn%D5\\t%0, #%n1\"},
8914 {\"cmn%d4\\t%2, #%n3\",
8915 \"cmp%D5\\t%0, %1\"},
8916 {\"cmn%d4\\t%2, #%n3\",
8917 \"cmn%D5\\t%0, #%n1\"}
215b30b3 8918 };
2ff91fec 8919 static const char * const ite[2] =
8920 {
8921 \"it\\t%d4\",
8922 \"it\\t%D5\"
8923 };
8924 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
8925 CMP_CMP, CMN_CMP, CMP_CMP,
8926 CMN_CMP, CMP_CMN, CMN_CMN};
215b30b3 8927 int swap =
8928 comparison_dominates_p (GET_CODE (operands[5]),
8929 reverse_condition (GET_CODE (operands[4])));
8930
2ff91fec 8931 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
8932 if (TARGET_THUMB2) {
8933 output_asm_insn (ite[swap], operands);
8934 }
8935 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
8936 return \"\";
215b30b3 8937 }"
8fa3ba89 8938 [(set_attr "conds" "set")
2ff91fec 8939 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
8940 (set_attr_alternative "length"
8941 [(const_int 6)
8942 (const_int 8)
8943 (const_int 8)
8944 (const_int 8)
8945 (const_int 8)
8946 (if_then_else (eq_attr "is_thumb" "no")
8947 (const_int 8)
8948 (const_int 10))
8949 (if_then_else (eq_attr "is_thumb" "no")
8950 (const_int 8)
8951 (const_int 10))
8952 (if_then_else (eq_attr "is_thumb" "no")
8953 (const_int 8)
8954 (const_int 10))
8955 (if_then_else (eq_attr "is_thumb" "no")
8956 (const_int 8)
1b7da4ac 8957 (const_int 10))])
8958 (set_attr "type" "multiple")]
8fa3ba89 8959)
9c08d1fa 8960
f6c53574 8961(define_insn "*cmp_and"
8962 [(set (match_operand 6 "dominant_cc_register" "")
8963 (compare
8964 (and:SI
8965 (match_operator 4 "arm_comparison_operator"
2ff91fec 8966 [(match_operand:SI 0 "s_register_operand"
8967 "l,l,l,r,r,r,r,r,r")
8968 (match_operand:SI 1 "arm_add_operand"
8969 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
f6c53574 8970 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 8971 [(match_operand:SI 2 "s_register_operand"
8972 "l,r,r,l,l,r,r,r,r")
8973 (match_operand:SI 3 "arm_add_operand"
8974 "lPy,rI,L,lPy,lPy,rI,rI,L,L")]))
f6c53574 8975 (const_int 0)))]
2ff91fec 8976 "TARGET_32BIT"
f6c53574 8977 "*
8978 {
2ff91fec 8979 static const char *const cmp1[NUM_OF_COND_CMP][2] =
f6c53574 8980 {
2ff91fec 8981 {\"cmp%d5\\t%0, %1\",
8982 \"cmp%d4\\t%2, %3\"},
8983 {\"cmn%d5\\t%0, #%n1\",
8984 \"cmp%d4\\t%2, %3\"},
8985 {\"cmp%d5\\t%0, %1\",
8986 \"cmn%d4\\t%2, #%n3\"},
8987 {\"cmn%d5\\t%0, #%n1\",
8988 \"cmn%d4\\t%2, #%n3\"}
f6c53574 8989 };
2ff91fec 8990 static const char *const cmp2[NUM_OF_COND_CMP][2] =
8991 {
8992 {\"cmp\\t%2, %3\",
8993 \"cmp\\t%0, %1\"},
8994 {\"cmp\\t%2, %3\",
8995 \"cmn\\t%0, #%n1\"},
8996 {\"cmn\\t%2, #%n3\",
8997 \"cmp\\t%0, %1\"},
8998 {\"cmn\\t%2, #%n3\",
8999 \"cmn\\t%0, #%n1\"}
9000 };
9001 static const char *const ite[2] =
9002 {
9003 \"it\\t%d5\",
9004 \"it\\t%d4\"
9005 };
9006 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
9007 CMP_CMP, CMN_CMP, CMP_CMP,
9008 CMN_CMP, CMP_CMN, CMN_CMN};
f6c53574 9009 int swap =
9010 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9011
2ff91fec 9012 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9013 if (TARGET_THUMB2) {
9014 output_asm_insn (ite[swap], operands);
9015 }
9016 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9017 return \"\";
f6c53574 9018 }"
9019 [(set_attr "conds" "set")
9020 (set_attr "predicable" "no")
2ff91fec 9021 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
9022 (set_attr_alternative "length"
9023 [(const_int 6)
9024 (const_int 8)
9025 (const_int 8)
9026 (const_int 8)
9027 (const_int 8)
9028 (if_then_else (eq_attr "is_thumb" "no")
9029 (const_int 8)
9030 (const_int 10))
9031 (if_then_else (eq_attr "is_thumb" "no")
9032 (const_int 8)
9033 (const_int 10))
9034 (if_then_else (eq_attr "is_thumb" "no")
9035 (const_int 8)
9036 (const_int 10))
9037 (if_then_else (eq_attr "is_thumb" "no")
9038 (const_int 8)
1b7da4ac 9039 (const_int 10))])
9040 (set_attr "type" "multiple")]
f6c53574 9041)
9042
9043(define_insn "*cmp_ior"
9044 [(set (match_operand 6 "dominant_cc_register" "")
9045 (compare
9046 (ior:SI
9047 (match_operator 4 "arm_comparison_operator"
2ff91fec 9048 [(match_operand:SI 0 "s_register_operand"
9049 "l,l,l,r,r,r,r,r,r")
9050 (match_operand:SI 1 "arm_add_operand"
9051 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
f6c53574 9052 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 9053 [(match_operand:SI 2 "s_register_operand"
9054 "l,r,r,l,l,r,r,r,r")
9055 (match_operand:SI 3 "arm_add_operand"
9056 "lPy,rI,L,lPy,lPy,rI,rI,L,L")]))
f6c53574 9057 (const_int 0)))]
2ff91fec 9058 "TARGET_32BIT"
f6c53574 9059 "*
f6c53574 9060 {
2ff91fec 9061 static const char *const cmp1[NUM_OF_COND_CMP][2] =
9062 {
9063 {\"cmp\\t%0, %1\",
9064 \"cmp\\t%2, %3\"},
9065 {\"cmn\\t%0, #%n1\",
9066 \"cmp\\t%2, %3\"},
9067 {\"cmp\\t%0, %1\",
9068 \"cmn\\t%2, #%n3\"},
9069 {\"cmn\\t%0, #%n1\",
9070 \"cmn\\t%2, #%n3\"}
9071 };
9072 static const char *const cmp2[NUM_OF_COND_CMP][2] =
9073 {
9074 {\"cmp%D4\\t%2, %3\",
9075 \"cmp%D5\\t%0, %1\"},
9076 {\"cmp%D4\\t%2, %3\",
9077 \"cmn%D5\\t%0, #%n1\"},
9078 {\"cmn%D4\\t%2, #%n3\",
9079 \"cmp%D5\\t%0, %1\"},
9080 {\"cmn%D4\\t%2, #%n3\",
9081 \"cmn%D5\\t%0, #%n1\"}
9082 };
9083 static const char *const ite[2] =
9084 {
9085 \"it\\t%D4\",
9086 \"it\\t%D5\"
9087 };
9088 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
9089 CMP_CMP, CMN_CMP, CMP_CMP,
9090 CMN_CMP, CMP_CMN, CMN_CMN};
9091 int swap =
9092 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9093
9094 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9095 if (TARGET_THUMB2) {
9096 output_asm_insn (ite[swap], operands);
9097 }
9098 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9099 return \"\";
9100 }
9101 "
f6c53574 9102 [(set_attr "conds" "set")
2ff91fec 9103 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
9104 (set_attr_alternative "length"
9105 [(const_int 6)
9106 (const_int 8)
9107 (const_int 8)
9108 (const_int 8)
9109 (const_int 8)
9110 (if_then_else (eq_attr "is_thumb" "no")
9111 (const_int 8)
9112 (const_int 10))
9113 (if_then_else (eq_attr "is_thumb" "no")
9114 (const_int 8)
9115 (const_int 10))
9116 (if_then_else (eq_attr "is_thumb" "no")
9117 (const_int 8)
9118 (const_int 10))
9119 (if_then_else (eq_attr "is_thumb" "no")
9120 (const_int 8)
1b7da4ac 9121 (const_int 10))])
9122 (set_attr "type" "multiple")]
f6c53574 9123)
9124
3c5afce6 9125(define_insn_and_split "*ior_scc_scc"
fd711051 9126 [(set (match_operand:SI 0 "s_register_operand" "=Ts")
3c5afce6 9127 (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9128 [(match_operand:SI 1 "s_register_operand" "r")
9129 (match_operand:SI 2 "arm_add_operand" "rIL")])
9130 (match_operator:SI 6 "arm_comparison_operator"
9131 [(match_operand:SI 4 "s_register_operand" "r")
9132 (match_operand:SI 5 "arm_add_operand" "rIL")])))
9133 (clobber (reg:CC CC_REGNUM))]
2ff91fec 9134 "TARGET_32BIT
3c5afce6 9135 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
9136 != CCmode)"
9137 "#"
2ff91fec 9138 "TARGET_32BIT && reload_completed"
3c5afce6 9139 [(set (match_dup 7)
9140 (compare
9141 (ior:SI
9142 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9143 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9144 (const_int 0)))
9145 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9146 "operands[7]
9147 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9148 DOM_CC_X_OR_Y),
601f584c 9149 CC_REGNUM);"
9150 [(set_attr "conds" "clob")
1b7da4ac 9151 (set_attr "length" "16")
9152 (set_attr "type" "multiple")]
9153)
601f584c 9154
9155; If the above pattern is followed by a CMP insn, then the compare is
9156; redundant, since we can rework the conditional instruction that follows.
9157(define_insn_and_split "*ior_scc_scc_cmp"
9158 [(set (match_operand 0 "dominant_cc_register" "")
9159 (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9160 [(match_operand:SI 1 "s_register_operand" "r")
9161 (match_operand:SI 2 "arm_add_operand" "rIL")])
9162 (match_operator:SI 6 "arm_comparison_operator"
9163 [(match_operand:SI 4 "s_register_operand" "r")
9164 (match_operand:SI 5 "arm_add_operand" "rIL")]))
9165 (const_int 0)))
fd711051 9166 (set (match_operand:SI 7 "s_register_operand" "=Ts")
601f584c 9167 (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9168 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
2ff91fec 9169 "TARGET_32BIT"
601f584c 9170 "#"
2ff91fec 9171 "TARGET_32BIT && reload_completed"
601f584c 9172 [(set (match_dup 0)
9173 (compare
9174 (ior:SI
9175 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9176 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9177 (const_int 0)))
9178 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9179 ""
9180 [(set_attr "conds" "set")
1b7da4ac 9181 (set_attr "length" "16")
9182 (set_attr "type" "multiple")]
9183)
3c5afce6 9184
9185(define_insn_and_split "*and_scc_scc"
fd711051 9186 [(set (match_operand:SI 0 "s_register_operand" "=Ts")
3c5afce6 9187 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9188 [(match_operand:SI 1 "s_register_operand" "r")
9189 (match_operand:SI 2 "arm_add_operand" "rIL")])
9190 (match_operator:SI 6 "arm_comparison_operator"
9191 [(match_operand:SI 4 "s_register_operand" "r")
9192 (match_operand:SI 5 "arm_add_operand" "rIL")])))
9193 (clobber (reg:CC CC_REGNUM))]
2ff91fec 9194 "TARGET_32BIT
3c5afce6 9195 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9196 != CCmode)"
9197 "#"
2ff91fec 9198 "TARGET_32BIT && reload_completed
601f584c 9199 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9200 != CCmode)"
3c5afce6 9201 [(set (match_dup 7)
9202 (compare
9203 (and:SI
9204 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9205 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9206 (const_int 0)))
9207 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9208 "operands[7]
9209 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9210 DOM_CC_X_AND_Y),
601f584c 9211 CC_REGNUM);"
9212 [(set_attr "conds" "clob")
1b7da4ac 9213 (set_attr "length" "16")
9214 (set_attr "type" "multiple")]
9215)
601f584c 9216
9217; If the above pattern is followed by a CMP insn, then the compare is
9218; redundant, since we can rework the conditional instruction that follows.
9219(define_insn_and_split "*and_scc_scc_cmp"
9220 [(set (match_operand 0 "dominant_cc_register" "")
9221 (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
9222 [(match_operand:SI 1 "s_register_operand" "r")
9223 (match_operand:SI 2 "arm_add_operand" "rIL")])
9224 (match_operator:SI 6 "arm_comparison_operator"
9225 [(match_operand:SI 4 "s_register_operand" "r")
9226 (match_operand:SI 5 "arm_add_operand" "rIL")]))
9227 (const_int 0)))
fd711051 9228 (set (match_operand:SI 7 "s_register_operand" "=Ts")
601f584c 9229 (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9230 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
2ff91fec 9231 "TARGET_32BIT"
601f584c 9232 "#"
2ff91fec 9233 "TARGET_32BIT && reload_completed"
601f584c 9234 [(set (match_dup 0)
9235 (compare
9236 (and:SI
9237 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9238 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9239 (const_int 0)))
9240 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9241 ""
9242 [(set_attr "conds" "set")
1b7da4ac 9243 (set_attr "length" "16")
9244 (set_attr "type" "multiple")]
9245)
601f584c 9246
9247;; If there is no dominance in the comparison, then we can still save an
9248;; instruction in the AND case, since we can know that the second compare
9249;; need only zero the value if false (if true, then the value is already
9250;; correct).
9251(define_insn_and_split "*and_scc_scc_nodom"
fd711051 9252 [(set (match_operand:SI 0 "s_register_operand" "=&Ts,&Ts,&Ts")
601f584c 9253 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9254 [(match_operand:SI 1 "s_register_operand" "r,r,0")
9255 (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
9256 (match_operator:SI 6 "arm_comparison_operator"
9257 [(match_operand:SI 4 "s_register_operand" "r,r,r")
9258 (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
9259 (clobber (reg:CC CC_REGNUM))]
2ff91fec 9260 "TARGET_32BIT
601f584c 9261 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9262 == CCmode)"
9263 "#"
2ff91fec 9264 "TARGET_32BIT && reload_completed"
601f584c 9265 [(parallel [(set (match_dup 0)
9266 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
9267 (clobber (reg:CC CC_REGNUM))])
9268 (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
9269 (set (match_dup 0)
9270 (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
9271 (match_dup 0)
9272 (const_int 0)))]
9273 "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
9274 operands[4], operands[5]),
9275 CC_REGNUM);
9276 operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
9277 operands[5]);"
9278 [(set_attr "conds" "clob")
1b7da4ac 9279 (set_attr "length" "20")
9280 (set_attr "type" "multiple")]
9281)
3c5afce6 9282
3a0bdee0 9283(define_split
9284 [(set (reg:CC_NOOV CC_REGNUM)
9285 (compare:CC_NOOV (ior:SI
9286 (and:SI (match_operand:SI 0 "s_register_operand" "")
9287 (const_int 1))
b0694be0 9288 (match_operator:SI 1 "arm_comparison_operator"
3a0bdee0 9289 [(match_operand:SI 2 "s_register_operand" "")
9290 (match_operand:SI 3 "arm_add_operand" "")]))
9291 (const_int 0)))
9292 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9293 "TARGET_ARM"
9294 [(set (match_dup 4)
9295 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9296 (match_dup 0)))
9297 (set (reg:CC_NOOV CC_REGNUM)
9298 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9299 (const_int 0)))]
9300 "")
9301
9302(define_split
9303 [(set (reg:CC_NOOV CC_REGNUM)
9304 (compare:CC_NOOV (ior:SI
b0694be0 9305 (match_operator:SI 1 "arm_comparison_operator"
3a0bdee0 9306 [(match_operand:SI 2 "s_register_operand" "")
9307 (match_operand:SI 3 "arm_add_operand" "")])
9308 (and:SI (match_operand:SI 0 "s_register_operand" "")
9309 (const_int 1)))
9310 (const_int 0)))
9311 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9312 "TARGET_ARM"
9313 [(set (match_dup 4)
9314 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9315 (match_dup 0)))
9316 (set (reg:CC_NOOV CC_REGNUM)
9317 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9318 (const_int 0)))]
9319 "")
25f905c2 9320;; ??? The conditional patterns above need checking for Thumb-2 usefulness
3a0bdee0 9321
190efb17 9322(define_insn_and_split "*negscc"
9c08d1fa 9323 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9324 (neg:SI (match_operator 3 "arm_comparison_operator"
9c08d1fa 9325 [(match_operand:SI 1 "s_register_operand" "r")
9326 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
bd5b4116 9327 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9328 "TARGET_ARM"
190efb17 9329 "#"
9330 "&& reload_completed"
9331 [(const_int 0)]
9332 {
9333 rtx cc_reg = gen_rtx_REG (CCmode, CC_REGNUM);
e2348bcb 9334
190efb17 9335 if (GET_CODE (operands[3]) == LT && operands[2] == const0_rtx)
9336 {
9337 /* Emit mov\\t%0, %1, asr #31 */
d1f9b275 9338 emit_insn (gen_rtx_SET (operands[0],
190efb17 9339 gen_rtx_ASHIFTRT (SImode,
9340 operands[1],
9341 GEN_INT (31))));
9342 DONE;
9343 }
9344 else if (GET_CODE (operands[3]) == NE)
9345 {
9346 /* Emit subs\\t%0, %1, %2\;mvnne\\t%0, #0 */
9347 if (CONST_INT_P (operands[2]))
9348 emit_insn (gen_cmpsi2_addneg (operands[0], operands[1], operands[2],
9349 GEN_INT (- INTVAL (operands[2]))));
9350 else
9351 emit_insn (gen_subsi3_compare (operands[0], operands[1], operands[2]));
9352
9353 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
9354 gen_rtx_NE (SImode,
9355 cc_reg,
9356 const0_rtx),
d1f9b275 9357 gen_rtx_SET (operands[0],
190efb17 9358 GEN_INT (~0))));
9359 DONE;
9360 }
9361 else
9362 {
9363 /* Emit: cmp\\t%1, %2\;mov%D3\\t%0, #0\;mvn%d3\\t%0, #0 */
d1f9b275 9364 emit_insn (gen_rtx_SET (cc_reg,
190efb17 9365 gen_rtx_COMPARE (CCmode, operands[1], operands[2])));
9366 enum rtx_code rc = GET_CODE (operands[3]);
9367
9368 rc = reverse_condition (rc);
9369 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
9370 gen_rtx_fmt_ee (rc,
9371 VOIDmode,
9372 cc_reg,
9373 const0_rtx),
d1f9b275 9374 gen_rtx_SET (operands[0], const0_rtx)));
190efb17 9375 rc = GET_CODE (operands[3]);
9376 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
9377 gen_rtx_fmt_ee (rc,
9378 VOIDmode,
9379 cc_reg,
9380 const0_rtx),
d1f9b275 9381 gen_rtx_SET (operands[0],
190efb17 9382 GEN_INT (~0))));
9383 DONE;
9384 }
9385 FAIL;
9386 }
8fa3ba89 9387 [(set_attr "conds" "clob")
1b7da4ac 9388 (set_attr "length" "12")
9389 (set_attr "type" "multiple")]
8fa3ba89 9390)
9c08d1fa 9391
90404b57 9392(define_insn_and_split "movcond_addsi"
9393 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r")
9394 (if_then_else:SI
9395 (match_operator 5 "comparison_operator"
9396 [(plus:SI (match_operand:SI 3 "s_register_operand" "r,r,r")
9397 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL"))
9398 (const_int 0)])
9399 (match_operand:SI 1 "arm_rhs_operand" "rI,rPy,r")
9400 (match_operand:SI 2 "arm_rhs_operand" "rI,rPy,r")))
9401 (clobber (reg:CC CC_REGNUM))]
9402 "TARGET_32BIT"
9403 "#"
9404 "&& reload_completed"
9405 [(set (reg:CC_NOOV CC_REGNUM)
9406 (compare:CC_NOOV
9407 (plus:SI (match_dup 3)
9408 (match_dup 4))
9409 (const_int 0)))
9410 (set (match_dup 0) (match_dup 1))
9411 (cond_exec (match_dup 6)
9412 (set (match_dup 0) (match_dup 2)))]
9413 "
9414 {
3754d046 9415 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[5]),
90404b57 9416 operands[3], operands[4]);
9417 enum rtx_code rc = GET_CODE (operands[5]);
90404b57 9418 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9419 gcc_assert (!(mode == CCFPmode || mode == CCFPEmode));
22440aeb 9420 if (!REG_P (operands[2]) || REGNO (operands[2]) != REGNO (operands[0]))
4d01ce2f 9421 rc = reverse_condition (rc);
f145bcba 9422 else
9423 std::swap (operands[1], operands[2]);
90404b57 9424
9425 operands[6] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9426 }
9427 "
9428 [(set_attr "conds" "clob")
1b7da4ac 9429 (set_attr "enabled_for_depr_it" "no,yes,yes")
9430 (set_attr "type" "multiple")]
90404b57 9431)
9432
9c08d1fa 9433(define_insn "movcond"
9434 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 9435 (if_then_else:SI
8fa3ba89 9436 (match_operator 5 "arm_comparison_operator"
5565501b 9437 [(match_operand:SI 3 "s_register_operand" "r,r,r")
9438 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
9439 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9440 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 9441 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9442 "TARGET_ARM"
9c08d1fa 9443 "*
9444 if (GET_CODE (operands[5]) == LT
9445 && (operands[4] == const0_rtx))
9446 {
0438d37f 9447 if (which_alternative != 1 && REG_P (operands[1]))
9c08d1fa 9448 {
9c08d1fa 9449 if (operands[2] == const0_rtx)
e2348bcb 9450 return \"and\\t%0, %1, %3, asr #31\";
9451 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
9c08d1fa 9452 }
0438d37f 9453 else if (which_alternative != 0 && REG_P (operands[2]))
9c08d1fa 9454 {
9c08d1fa 9455 if (operands[1] == const0_rtx)
e2348bcb 9456 return \"bic\\t%0, %2, %3, asr #31\";
9457 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
9c08d1fa 9458 }
9459 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 9460 are constants. */
9c08d1fa 9461 }
e2348bcb 9462
9c08d1fa 9463 if (GET_CODE (operands[5]) == GE
9464 && (operands[4] == const0_rtx))
9465 {
0438d37f 9466 if (which_alternative != 1 && REG_P (operands[1]))
9c08d1fa 9467 {
9c08d1fa 9468 if (operands[2] == const0_rtx)
e2348bcb 9469 return \"bic\\t%0, %1, %3, asr #31\";
9470 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
9c08d1fa 9471 }
0438d37f 9472 else if (which_alternative != 0 && REG_P (operands[2]))
9c08d1fa 9473 {
9c08d1fa 9474 if (operands[1] == const0_rtx)
e2348bcb 9475 return \"and\\t%0, %2, %3, asr #31\";
9476 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
9c08d1fa 9477 }
9478 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 9479 are constants. */
9c08d1fa 9480 }
0438d37f 9481 if (CONST_INT_P (operands[4])
9c08d1fa 9482 && !const_ok_for_arm (INTVAL (operands[4])))
e2348bcb 9483 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
9c08d1fa 9484 else
e2348bcb 9485 output_asm_insn (\"cmp\\t%3, %4\", operands);
9c08d1fa 9486 if (which_alternative != 0)
e2348bcb 9487 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
9c08d1fa 9488 if (which_alternative != 1)
e2348bcb 9489 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
9c08d1fa 9490 return \"\";
215b30b3 9491 "
8fa3ba89 9492 [(set_attr "conds" "clob")
1b7da4ac 9493 (set_attr "length" "8,8,12")
9494 (set_attr "type" "multiple")]
8fa3ba89 9495)
9c08d1fa 9496
25f905c2 9497;; ??? The patterns below need checking for Thumb-2 usefulness.
9498
8a18b90c 9499(define_insn "*ifcompare_plus_move"
9500 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9501 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 9502 [(match_operand:SI 4 "s_register_operand" "r,r")
9503 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9504 (plus:SI
9505 (match_operand:SI 2 "s_register_operand" "r,r")
9506 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
129a2fe4 9507 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 9508 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9509 "TARGET_ARM"
8a18b90c 9510 "#"
8fa3ba89 9511 [(set_attr "conds" "clob")
1b7da4ac 9512 (set_attr "length" "8,12")
9513 (set_attr "type" "multiple")]
8fa3ba89 9514)
8a18b90c 9515
9516(define_insn "*if_plus_move"
129a2fe4 9517 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 9518 (if_then_else:SI
8fa3ba89 9519 (match_operator 4 "arm_comparison_operator"
8a18b90c 9520 [(match_operand 5 "cc_register" "") (const_int 0)])
9521 (plus:SI
129a2fe4 9522 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9523 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
9524 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
cffb2a26 9525 "TARGET_ARM"
8a18b90c 9526 "@
9527 add%d4\\t%0, %2, %3
9528 sub%d4\\t%0, %2, #%n3
9529 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
129a2fe4 9530 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8fa3ba89 9531 [(set_attr "conds" "use")
9532 (set_attr "length" "4,4,8,8")
65f68e55 9533 (set_attr_alternative "type"
9534 [(if_then_else (match_operand 3 "const_int_operand" "")
d82e788e 9535 (const_string "alu_imm" )
112eda6f 9536 (const_string "alu_sreg"))
d82e788e 9537 (const_string "alu_imm")
282b4c75 9538 (const_string "multiple")
9539 (const_string "multiple")])]
8fa3ba89 9540)
8a18b90c 9541
9542(define_insn "*ifcompare_move_plus"
5565501b 9543 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9544 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 9545 [(match_operand:SI 4 "s_register_operand" "r,r")
9546 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 9547 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 9548 (plus:SI
9549 (match_operand:SI 2 "s_register_operand" "r,r")
9550 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
bd5b4116 9551 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9552 "TARGET_ARM"
8a18b90c 9553 "#"
8fa3ba89 9554 [(set_attr "conds" "clob")
1b7da4ac 9555 (set_attr "length" "8,12")
9556 (set_attr "type" "multiple")]
8fa3ba89 9557)
8a18b90c 9558
9559(define_insn "*if_move_plus"
129a2fe4 9560 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 9561 (if_then_else:SI
8fa3ba89 9562 (match_operator 4 "arm_comparison_operator"
8a18b90c 9563 [(match_operand 5 "cc_register" "") (const_int 0)])
129a2fe4 9564 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8a18b90c 9565 (plus:SI
129a2fe4 9566 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9567 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
cffb2a26 9568 "TARGET_ARM"
8a18b90c 9569 "@
9570 add%D4\\t%0, %2, %3
9571 sub%D4\\t%0, %2, #%n3
9572 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
129a2fe4 9573 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8fa3ba89 9574 [(set_attr "conds" "use")
9575 (set_attr "length" "4,4,8,8")
282b4c75 9576 (set_attr_alternative "type"
9577 [(if_then_else (match_operand 3 "const_int_operand" "")
9578 (const_string "alu_imm" )
9579 (const_string "alu_sreg"))
9580 (const_string "alu_imm")
9581 (const_string "multiple")
9582 (const_string "multiple")])]
8fa3ba89 9583)
8a18b90c 9584
9585(define_insn "*ifcompare_arith_arith"
9586 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9587 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8a18b90c 9588 [(match_operand:SI 5 "s_register_operand" "r")
9589 (match_operand:SI 6 "arm_add_operand" "rIL")])
9c08d1fa 9590 (match_operator:SI 8 "shiftable_operator"
8a18b90c 9591 [(match_operand:SI 1 "s_register_operand" "r")
9592 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9c08d1fa 9593 (match_operator:SI 7 "shiftable_operator"
8a18b90c 9594 [(match_operand:SI 3 "s_register_operand" "r")
9595 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
bd5b4116 9596 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9597 "TARGET_ARM"
8a18b90c 9598 "#"
8fa3ba89 9599 [(set_attr "conds" "clob")
1b7da4ac 9600 (set_attr "length" "12")
9601 (set_attr "type" "multiple")]
8fa3ba89 9602)
9c08d1fa 9603
8a18b90c 9604(define_insn "*if_arith_arith"
9605 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9606 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8a18b90c 9607 [(match_operand 8 "cc_register" "") (const_int 0)])
9608 (match_operator:SI 6 "shiftable_operator"
9609 [(match_operand:SI 1 "s_register_operand" "r")
9610 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9611 (match_operator:SI 7 "shiftable_operator"
9612 [(match_operand:SI 3 "s_register_operand" "r")
9613 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
cffb2a26 9614 "TARGET_ARM"
8a18b90c 9615 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8fa3ba89 9616 [(set_attr "conds" "use")
1b7da4ac 9617 (set_attr "length" "8")
9618 (set_attr "type" "multiple")]
8fa3ba89 9619)
8a18b90c 9620
f7fbdd4a 9621(define_insn "*ifcompare_arith_move"
9c08d1fa 9622 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9623 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 9624 [(match_operand:SI 2 "s_register_operand" "r,r")
5565501b 9625 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
9c08d1fa 9626 (match_operator:SI 7 "shiftable_operator"
9627 [(match_operand:SI 4 "s_register_operand" "r,r")
9628 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
129a2fe4 9629 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 9630 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9631 "TARGET_ARM"
9c08d1fa 9632 "*
9c08d1fa 9633 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 9634 the conditional operator is LT or GE and we are comparing against zero and
674a8f0b 9635 everything is in registers then we can do this in two instructions. */
9c08d1fa 9636 if (operands[3] == const0_rtx
9637 && GET_CODE (operands[7]) != AND
0438d37f 9638 && REG_P (operands[5])
9639 && REG_P (operands[1])
9c08d1fa 9640 && REGNO (operands[1]) == REGNO (operands[4])
9641 && REGNO (operands[4]) != REGNO (operands[0]))
9642 {
9643 if (GET_CODE (operands[6]) == LT)
40dbec34 9644 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 9645 else if (GET_CODE (operands[6]) == GE)
40dbec34 9646 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 9647 }
0438d37f 9648 if (CONST_INT_P (operands[3])
9c08d1fa 9649 && !const_ok_for_arm (INTVAL (operands[3])))
e2348bcb 9650 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
9c08d1fa 9651 else
e2348bcb 9652 output_asm_insn (\"cmp\\t%2, %3\", operands);
40dbec34 9653 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
9c08d1fa 9654 if (which_alternative != 0)
129a2fe4 9655 return \"mov%D6\\t%0, %1\";
9c08d1fa 9656 return \"\";
215b30b3 9657 "
8fa3ba89 9658 [(set_attr "conds" "clob")
1b7da4ac 9659 (set_attr "length" "8,12")
9660 (set_attr "type" "multiple")]
8fa3ba89 9661)
9c08d1fa 9662
8a18b90c 9663(define_insn "*if_arith_move"
129a2fe4 9664 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9665 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8a18b90c 9666 [(match_operand 6 "cc_register" "") (const_int 0)])
9667 (match_operator:SI 5 "shiftable_operator"
129a2fe4 9668 [(match_operand:SI 2 "s_register_operand" "r,r")
9669 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
9670 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
cffb2a26 9671 "TARGET_ARM"
8a18b90c 9672 "@
9673 %I5%d4\\t%0, %2, %3
129a2fe4 9674 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8fa3ba89 9675 [(set_attr "conds" "use")
9676 (set_attr "length" "4,8")
282b4c75 9677 (set_attr_alternative "type"
9678 [(if_then_else (match_operand 3 "const_int_operand" "")
9679 (const_string "alu_shift_imm" )
9680 (const_string "alu_shift_reg"))
9681 (const_string "multiple")])]
8fa3ba89 9682)
8a18b90c 9683
f7fbdd4a 9684(define_insn "*ifcompare_move_arith"
9c08d1fa 9685 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9686 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 9687 [(match_operand:SI 4 "s_register_operand" "r,r")
5565501b 9688 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 9689 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9c08d1fa 9690 (match_operator:SI 7 "shiftable_operator"
9691 [(match_operand:SI 2 "s_register_operand" "r,r")
9692 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 9693 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9694 "TARGET_ARM"
9c08d1fa 9695 "*
9c08d1fa 9696 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 9697 the conditional operator is LT or GE and we are comparing against zero and
9c08d1fa 9698 everything is in registers then we can do this in two instructions */
9699 if (operands[5] == const0_rtx
9700 && GET_CODE (operands[7]) != AND
0438d37f 9701 && REG_P (operands[3])
9702 && REG_P (operands[1])
9c08d1fa 9703 && REGNO (operands[1]) == REGNO (operands[2])
9704 && REGNO (operands[2]) != REGNO (operands[0]))
9705 {
9706 if (GET_CODE (operands[6]) == GE)
40dbec34 9707 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 9708 else if (GET_CODE (operands[6]) == LT)
40dbec34 9709 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 9710 }
40dbec34 9711
0438d37f 9712 if (CONST_INT_P (operands[5])
9c08d1fa 9713 && !const_ok_for_arm (INTVAL (operands[5])))
e2348bcb 9714 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
9c08d1fa 9715 else
e2348bcb 9716 output_asm_insn (\"cmp\\t%4, %5\", operands);
40dbec34 9717
9c08d1fa 9718 if (which_alternative != 0)
129a2fe4 9719 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
40dbec34 9720 return \"%I7%D6\\t%0, %2, %3\";
215b30b3 9721 "
8fa3ba89 9722 [(set_attr "conds" "clob")
1b7da4ac 9723 (set_attr "length" "8,12")
9724 (set_attr "type" "multiple")]
8fa3ba89 9725)
9c08d1fa 9726
8a18b90c 9727(define_insn "*if_move_arith"
129a2fe4 9728 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9729 (if_then_else:SI
8fa3ba89 9730 (match_operator 4 "arm_comparison_operator"
8a18b90c 9731 [(match_operand 6 "cc_register" "") (const_int 0)])
129a2fe4 9732 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 9733 (match_operator:SI 5 "shiftable_operator"
129a2fe4 9734 [(match_operand:SI 2 "s_register_operand" "r,r")
9735 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
cffb2a26 9736 "TARGET_ARM"
8a18b90c 9737 "@
9738 %I5%D4\\t%0, %2, %3
129a2fe4 9739 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
8fa3ba89 9740 [(set_attr "conds" "use")
9741 (set_attr "length" "4,8")
282b4c75 9742 (set_attr_alternative "type"
9743 [(if_then_else (match_operand 3 "const_int_operand" "")
9744 (const_string "alu_shift_imm" )
9745 (const_string "alu_shift_reg"))
9746 (const_string "multiple")])]
8fa3ba89 9747)
8a18b90c 9748
9749(define_insn "*ifcompare_move_not"
9c08d1fa 9750 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9751 (if_then_else:SI
8fa3ba89 9752 (match_operator 5 "arm_comparison_operator"
8a18b90c 9753 [(match_operand:SI 3 "s_register_operand" "r,r")
9754 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9755 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9756 (not:SI
9757 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 9758 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9759 "TARGET_ARM"
8a18b90c 9760 "#"
8fa3ba89 9761 [(set_attr "conds" "clob")
1b7da4ac 9762 (set_attr "length" "8,12")
9763 (set_attr "type" "multiple")]
8fa3ba89 9764)
9c08d1fa 9765
8a18b90c 9766(define_insn "*if_move_not"
9767 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9768 (if_then_else:SI
8fa3ba89 9769 (match_operator 4 "arm_comparison_operator"
8a18b90c 9770 [(match_operand 3 "cc_register" "") (const_int 0)])
9771 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9772 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
cffb2a26 9773 "TARGET_ARM"
8a18b90c 9774 "@
9775 mvn%D4\\t%0, %2
9776 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
9777 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
8fa3ba89 9778 [(set_attr "conds" "use")
1aed5204 9779 (set_attr "type" "mvn_reg")
1b7da4ac 9780 (set_attr "length" "4,8,8")
9781 (set_attr "type" "mvn_reg,multiple,multiple")]
8fa3ba89 9782)
8a18b90c 9783
9784(define_insn "*ifcompare_not_move"
9c08d1fa 9785 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9786 (if_then_else:SI
8fa3ba89 9787 (match_operator 5 "arm_comparison_operator"
8a18b90c 9788 [(match_operand:SI 3 "s_register_operand" "r,r")
9789 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9790 (not:SI
9791 (match_operand:SI 2 "s_register_operand" "r,r"))
9792 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 9793 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9794 "TARGET_ARM"
8a18b90c 9795 "#"
8fa3ba89 9796 [(set_attr "conds" "clob")
1b7da4ac 9797 (set_attr "length" "8,12")
9798 (set_attr "type" "multiple")]
8fa3ba89 9799)
9c08d1fa 9800
8a18b90c 9801(define_insn "*if_not_move"
9802 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9803 (if_then_else:SI
8fa3ba89 9804 (match_operator 4 "arm_comparison_operator"
8a18b90c 9805 [(match_operand 3 "cc_register" "") (const_int 0)])
9806 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9807 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 9808 "TARGET_ARM"
8a18b90c 9809 "@
9810 mvn%d4\\t%0, %2
9811 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
9812 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
8fa3ba89 9813 [(set_attr "conds" "use")
1b7da4ac 9814 (set_attr "type" "mvn_reg,multiple,multiple")
8fa3ba89 9815 (set_attr "length" "4,8,8")]
9816)
8a18b90c 9817
9818(define_insn "*ifcompare_shift_move"
9c08d1fa 9819 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9820 (if_then_else:SI
8fa3ba89 9821 (match_operator 6 "arm_comparison_operator"
8a18b90c 9822 [(match_operand:SI 4 "s_register_operand" "r,r")
9823 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9824 (match_operator:SI 7 "shift_operator"
9825 [(match_operand:SI 2 "s_register_operand" "r,r")
9826 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
9827 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 9828 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9829 "TARGET_ARM"
9c08d1fa 9830 "#"
8fa3ba89 9831 [(set_attr "conds" "clob")
1b7da4ac 9832 (set_attr "length" "8,12")
9833 (set_attr "type" "multiple")]
8fa3ba89 9834)
9c08d1fa 9835
8a18b90c 9836(define_insn "*if_shift_move"
9837 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9838 (if_then_else:SI
8fa3ba89 9839 (match_operator 5 "arm_comparison_operator"
8a18b90c 9840 [(match_operand 6 "cc_register" "") (const_int 0)])
9841 (match_operator:SI 4 "shift_operator"
9842 [(match_operand:SI 2 "s_register_operand" "r,r,r")
9843 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
9844 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 9845 "TARGET_ARM"
5565501b 9846 "@
8a18b90c 9847 mov%d5\\t%0, %2%S4
9848 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
9849 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
8fa3ba89 9850 [(set_attr "conds" "use")
331beb1a 9851 (set_attr "shift" "2")
a2cd141b 9852 (set_attr "length" "4,8,8")
282b4c75 9853 (set_attr_alternative "type"
9854 [(if_then_else (match_operand 3 "const_int_operand" "")
9855 (const_string "mov_shift" )
9856 (const_string "mov_shift_reg"))
9857 (const_string "multiple")
9858 (const_string "multiple")])]
8fa3ba89 9859)
5565501b 9860
8a18b90c 9861(define_insn "*ifcompare_move_shift"
9862 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 9863 (if_then_else:SI
8fa3ba89 9864 (match_operator 6 "arm_comparison_operator"
8a18b90c 9865 [(match_operand:SI 4 "s_register_operand" "r,r")
9866 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9867 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
5565501b 9868 (match_operator:SI 7 "shift_operator"
8a18b90c 9869 [(match_operand:SI 2 "s_register_operand" "r,r")
9870 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
bd5b4116 9871 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9872 "TARGET_ARM"
8a18b90c 9873 "#"
8fa3ba89 9874 [(set_attr "conds" "clob")
1b7da4ac 9875 (set_attr "length" "8,12")
9876 (set_attr "type" "multiple")]
8fa3ba89 9877)
5565501b 9878
8a18b90c 9879(define_insn "*if_move_shift"
9880 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 9881 (if_then_else:SI
8fa3ba89 9882 (match_operator 5 "arm_comparison_operator"
8a18b90c 9883 [(match_operand 6 "cc_register" "") (const_int 0)])
9884 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9885 (match_operator:SI 4 "shift_operator"
9886 [(match_operand:SI 2 "s_register_operand" "r,r,r")
9887 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
cffb2a26 9888 "TARGET_ARM"
5565501b 9889 "@
8a18b90c 9890 mov%D5\\t%0, %2%S4
9891 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
9892 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
8fa3ba89 9893 [(set_attr "conds" "use")
331beb1a 9894 (set_attr "shift" "2")
a2cd141b 9895 (set_attr "length" "4,8,8")
282b4c75 9896 (set_attr_alternative "type"
9897 [(if_then_else (match_operand 3 "const_int_operand" "")
9898 (const_string "mov_shift" )
9899 (const_string "mov_shift_reg"))
9900 (const_string "multiple")
9901 (const_string "multiple")])]
8fa3ba89 9902)
9c08d1fa 9903
f7fbdd4a 9904(define_insn "*ifcompare_shift_shift"
8a18b90c 9905 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 9906 (if_then_else:SI
8fa3ba89 9907 (match_operator 7 "arm_comparison_operator"
8a18b90c 9908 [(match_operand:SI 5 "s_register_operand" "r")
9909 (match_operand:SI 6 "arm_add_operand" "rIL")])
5565501b 9910 (match_operator:SI 8 "shift_operator"
8a18b90c 9911 [(match_operand:SI 1 "s_register_operand" "r")
9912 (match_operand:SI 2 "arm_rhs_operand" "rM")])
5565501b 9913 (match_operator:SI 9 "shift_operator"
8a18b90c 9914 [(match_operand:SI 3 "s_register_operand" "r")
9915 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
bd5b4116 9916 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9917 "TARGET_ARM"
8a18b90c 9918 "#"
8fa3ba89 9919 [(set_attr "conds" "clob")
1b7da4ac 9920 (set_attr "length" "12")
9921 (set_attr "type" "multiple")]
8fa3ba89 9922)
9c08d1fa 9923
8a18b90c 9924(define_insn "*if_shift_shift"
9925 [(set (match_operand:SI 0 "s_register_operand" "=r")
9926 (if_then_else:SI
8fa3ba89 9927 (match_operator 5 "arm_comparison_operator"
8a18b90c 9928 [(match_operand 8 "cc_register" "") (const_int 0)])
9929 (match_operator:SI 6 "shift_operator"
9930 [(match_operand:SI 1 "s_register_operand" "r")
9931 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9932 (match_operator:SI 7 "shift_operator"
9933 [(match_operand:SI 3 "s_register_operand" "r")
9934 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
cffb2a26 9935 "TARGET_ARM"
8a18b90c 9936 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
8fa3ba89 9937 [(set_attr "conds" "use")
331beb1a 9938 (set_attr "shift" "1")
a2cd141b 9939 (set_attr "length" "8")
9940 (set (attr "type") (if_then_else
9941 (and (match_operand 2 "const_int_operand" "")
9942 (match_operand 4 "const_int_operand" ""))
1aed5204 9943 (const_string "mov_shift")
9944 (const_string "mov_shift_reg")))]
8fa3ba89 9945)
8a18b90c 9946
f7fbdd4a 9947(define_insn "*ifcompare_not_arith"
8a18b90c 9948 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 9949 (if_then_else:SI
8fa3ba89 9950 (match_operator 6 "arm_comparison_operator"
8a18b90c 9951 [(match_operand:SI 4 "s_register_operand" "r")
9952 (match_operand:SI 5 "arm_add_operand" "rIL")])
9953 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5565501b 9954 (match_operator:SI 7 "shiftable_operator"
8a18b90c 9955 [(match_operand:SI 2 "s_register_operand" "r")
9956 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
bd5b4116 9957 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9958 "TARGET_ARM"
8a18b90c 9959 "#"
8fa3ba89 9960 [(set_attr "conds" "clob")
1b7da4ac 9961 (set_attr "length" "12")
9962 (set_attr "type" "multiple")]
8fa3ba89 9963)
9c08d1fa 9964
8a18b90c 9965(define_insn "*if_not_arith"
9966 [(set (match_operand:SI 0 "s_register_operand" "=r")
9967 (if_then_else:SI
8fa3ba89 9968 (match_operator 5 "arm_comparison_operator"
8a18b90c 9969 [(match_operand 4 "cc_register" "") (const_int 0)])
9970 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9971 (match_operator:SI 6 "shiftable_operator"
9972 [(match_operand:SI 2 "s_register_operand" "r")
9973 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
cffb2a26 9974 "TARGET_ARM"
8a18b90c 9975 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
8fa3ba89 9976 [(set_attr "conds" "use")
1aed5204 9977 (set_attr "type" "mvn_reg")
8fa3ba89 9978 (set_attr "length" "8")]
9979)
8a18b90c 9980
9981(define_insn "*ifcompare_arith_not"
9982 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 9983 (if_then_else:SI
8fa3ba89 9984 (match_operator 6 "arm_comparison_operator"
8a18b90c 9985 [(match_operand:SI 4 "s_register_operand" "r")
9986 (match_operand:SI 5 "arm_add_operand" "rIL")])
5565501b 9987 (match_operator:SI 7 "shiftable_operator"
8a18b90c 9988 [(match_operand:SI 2 "s_register_operand" "r")
9989 (match_operand:SI 3 "arm_rhs_operand" "rI")])
9990 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
bd5b4116 9991 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9992 "TARGET_ARM"
8a18b90c 9993 "#"
8fa3ba89 9994 [(set_attr "conds" "clob")
1b7da4ac 9995 (set_attr "length" "12")
9996 (set_attr "type" "multiple")]
8fa3ba89 9997)
9c08d1fa 9998
8a18b90c 9999(define_insn "*if_arith_not"
10000 [(set (match_operand:SI 0 "s_register_operand" "=r")
10001 (if_then_else:SI
8fa3ba89 10002 (match_operator 5 "arm_comparison_operator"
8a18b90c 10003 [(match_operand 4 "cc_register" "") (const_int 0)])
10004 (match_operator:SI 6 "shiftable_operator"
10005 [(match_operand:SI 2 "s_register_operand" "r")
10006 (match_operand:SI 3 "arm_rhs_operand" "rI")])
10007 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
cffb2a26 10008 "TARGET_ARM"
8a18b90c 10009 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
8fa3ba89 10010 [(set_attr "conds" "use")
1b7da4ac 10011 (set_attr "type" "multiple")
8fa3ba89 10012 (set_attr "length" "8")]
10013)
8a18b90c 10014
f7fbdd4a 10015(define_insn "*ifcompare_neg_move"
8a18b90c 10016 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 10017 (if_then_else:SI
8fa3ba89 10018 (match_operator 5 "arm_comparison_operator"
8a18b90c 10019 [(match_operand:SI 3 "s_register_operand" "r,r")
10020 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10021 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
10022 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 10023 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10024 "TARGET_ARM"
8a18b90c 10025 "#"
8fa3ba89 10026 [(set_attr "conds" "clob")
1b7da4ac 10027 (set_attr "length" "8,12")
10028 (set_attr "type" "multiple")]
8fa3ba89 10029)
8a18b90c 10030
10031(define_insn "*if_neg_move"
10032 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10033 (if_then_else:SI
8fa3ba89 10034 (match_operator 4 "arm_comparison_operator"
8a18b90c 10035 [(match_operand 3 "cc_register" "") (const_int 0)])
10036 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
10037 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 10038 "TARGET_ARM"
8a18b90c 10039 "@
10040 rsb%d4\\t%0, %2, #0
10041 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
10042 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
8fa3ba89 10043 [(set_attr "conds" "use")
1b7da4ac 10044 (set_attr "length" "4,8,8")
10045 (set_attr "type" "logic_shift_imm,multiple,multiple")]
8fa3ba89 10046)
9c08d1fa 10047
f7fbdd4a 10048(define_insn "*ifcompare_move_neg"
8a18b90c 10049 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 10050 (if_then_else:SI
8fa3ba89 10051 (match_operator 5 "arm_comparison_operator"
8a18b90c 10052 [(match_operand:SI 3 "s_register_operand" "r,r")
10053 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10054 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
10055 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 10056 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10057 "TARGET_ARM"
8a18b90c 10058 "#"
8fa3ba89 10059 [(set_attr "conds" "clob")
1b7da4ac 10060 (set_attr "length" "8,12")
10061 (set_attr "type" "multiple")]
8fa3ba89 10062)
8a18b90c 10063
10064(define_insn "*if_move_neg"
10065 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10066 (if_then_else:SI
8fa3ba89 10067 (match_operator 4 "arm_comparison_operator"
8a18b90c 10068 [(match_operand 3 "cc_register" "") (const_int 0)])
10069 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
10070 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
cffb2a26 10071 "TARGET_ARM"
8a18b90c 10072 "@
10073 rsb%D4\\t%0, %2, #0
10074 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
10075 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
0d66636f 10076 [(set_attr "conds" "use")
1b7da4ac 10077 (set_attr "length" "4,8,8")
10078 (set_attr "type" "logic_shift_imm,multiple,multiple")]
0d66636f 10079)
9c08d1fa 10080
f7fbdd4a 10081(define_insn "*arith_adjacentmem"
9c08d1fa 10082 [(set (match_operand:SI 0 "s_register_operand" "=r")
10083 (match_operator:SI 1 "shiftable_operator"
10084 [(match_operand:SI 2 "memory_operand" "m")
10085 (match_operand:SI 3 "memory_operand" "m")]))
10086 (clobber (match_scratch:SI 4 "=r"))]
cffb2a26 10087 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9c08d1fa 10088 "*
215b30b3 10089 {
10090 rtx ldm[3];
10091 rtx arith[4];
94dee231 10092 rtx base_reg;
10093 HOST_WIDE_INT val1 = 0, val2 = 0;
9c08d1fa 10094
215b30b3 10095 if (REGNO (operands[0]) > REGNO (operands[4]))
10096 {
10097 ldm[1] = operands[4];
10098 ldm[2] = operands[0];
10099 }
10100 else
10101 {
10102 ldm[1] = operands[0];
10103 ldm[2] = operands[4];
10104 }
94dee231 10105
10106 base_reg = XEXP (operands[2], 0);
10107
10108 if (!REG_P (base_reg))
10109 {
10110 val1 = INTVAL (XEXP (base_reg, 1));
10111 base_reg = XEXP (base_reg, 0);
10112 }
10113
10114 if (!REG_P (XEXP (operands[3], 0)))
215b30b3 10115 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
94dee231 10116
215b30b3 10117 arith[0] = operands[0];
10118 arith[3] = operands[1];
94dee231 10119
215b30b3 10120 if (val1 < val2)
10121 {
10122 arith[1] = ldm[1];
10123 arith[2] = ldm[2];
10124 }
10125 else
10126 {
10127 arith[1] = ldm[2];
10128 arith[2] = ldm[1];
10129 }
94dee231 10130
10131 ldm[0] = base_reg;
10132 if (val1 !=0 && val2 != 0)
215b30b3 10133 {
cdb1295a 10134 rtx ops[3];
10135
94dee231 10136 if (val1 == 4 || val2 == 4)
10137 /* Other val must be 8, since we know they are adjacent and neither
10138 is zero. */
25f905c2 10139 output_asm_insn (\"ldm%(ib%)\\t%0, {%1, %2}\", ldm);
cdb1295a 10140 else if (const_ok_for_arm (val1) || const_ok_for_arm (-val1))
94dee231 10141 {
94dee231 10142 ldm[0] = ops[0] = operands[4];
10143 ops[1] = base_reg;
10144 ops[2] = GEN_INT (val1);
10145 output_add_immediate (ops);
10146 if (val1 < val2)
25f905c2 10147 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
94dee231 10148 else
25f905c2 10149 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
94dee231 10150 }
cdb1295a 10151 else
10152 {
10153 /* Offset is out of range for a single add, so use two ldr. */
10154 ops[0] = ldm[1];
10155 ops[1] = base_reg;
10156 ops[2] = GEN_INT (val1);
10157 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10158 ops[0] = ldm[2];
10159 ops[2] = GEN_INT (val2);
10160 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10161 }
215b30b3 10162 }
94dee231 10163 else if (val1 != 0)
215b30b3 10164 {
215b30b3 10165 if (val1 < val2)
25f905c2 10166 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
215b30b3 10167 else
25f905c2 10168 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
215b30b3 10169 }
10170 else
10171 {
215b30b3 10172 if (val1 < val2)
25f905c2 10173 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
215b30b3 10174 else
25f905c2 10175 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
215b30b3 10176 }
10177 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
10178 return \"\";
10179 }"
10180 [(set_attr "length" "12")
10181 (set_attr "predicable" "yes")
a2cd141b 10182 (set_attr "type" "load1")]
215b30b3 10183)
9c08d1fa 10184
9c08d1fa 10185; This pattern is never tried by combine, so do it as a peephole
10186
a0f94409 10187(define_peephole2
372575c7 10188 [(set (match_operand:SI 0 "arm_general_register_operand" "")
10189 (match_operand:SI 1 "arm_general_register_operand" ""))
bd5b4116 10190 (set (reg:CC CC_REGNUM)
aea4c774 10191 (compare:CC (match_dup 1) (const_int 0)))]
372575c7 10192 "TARGET_ARM"
a0f94409 10193 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
10194 (set (match_dup 0) (match_dup 1))])]
10195 ""
0d66636f 10196)
9c08d1fa 10197
9c08d1fa 10198(define_split
10199 [(set (match_operand:SI 0 "s_register_operand" "")
10200 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
10201 (const_int 0))
8fa3ba89 10202 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9c08d1fa 10203 [(match_operand:SI 3 "s_register_operand" "")
10204 (match_operand:SI 4 "arm_rhs_operand" "")]))))
10205 (clobber (match_operand:SI 5 "s_register_operand" ""))]
cffb2a26 10206 "TARGET_ARM"
9c08d1fa 10207 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
10208 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
10209 (match_dup 5)))]
215b30b3 10210 ""
10211)
9c08d1fa 10212
aea4c774 10213;; This split can be used because CC_Z mode implies that the following
10214;; branch will be an equality, or an unsigned inequality, so the sign
10215;; extension is not needed.
9c08d1fa 10216
aea4c774 10217(define_split
bd5b4116 10218 [(set (reg:CC_Z CC_REGNUM)
aea4c774 10219 (compare:CC_Z
10220 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9c08d1fa 10221 (const_int 24))
aea4c774 10222 (match_operand 1 "const_int_operand" "")))
10223 (clobber (match_scratch:SI 2 ""))]
cffb2a26 10224 "TARGET_ARM
10225 && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
10226 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
aea4c774 10227 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
bd5b4116 10228 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
aea4c774 10229 "
9c08d1fa 10230 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
215b30b3 10231 "
10232)
25f905c2 10233;; ??? Check the patterns above for Thumb-2 usefulness
9c08d1fa 10234
87b22bf7 10235(define_expand "prologue"
10236 [(clobber (const_int 0))]
cffb2a26 10237 "TARGET_EITHER"
25f905c2 10238 "if (TARGET_32BIT)
cffb2a26 10239 arm_expand_prologue ();
10240 else
25f905c2 10241 thumb1_expand_prologue ();
87b22bf7 10242 DONE;
cffb2a26 10243 "
10244)
87b22bf7 10245
56d27660 10246(define_expand "epilogue"
4c44712e 10247 [(clobber (const_int 0))]
cffb2a26 10248 "TARGET_EITHER"
56d27660 10249 "
18d50ae6 10250 if (crtl->calls_eh_return)
fb94f18b 10251 emit_insn (gen_force_register_use (gen_rtx_REG (Pmode, 2)));
25f905c2 10252 if (TARGET_THUMB1)
c3635784 10253 {
10254 thumb1_expand_epilogue ();
10255 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
10256 gen_rtvec (1, ret_rtx), VUNSPEC_EPILOGUE));
10257 }
10258 else if (HAVE_return)
10259 {
10260 /* HAVE_return is testing for USE_RETURN_INSN (FALSE). Hence,
10261 no need for explicit testing again. */
10262 emit_jump_insn (gen_return ());
10263 }
10264 else if (TARGET_32BIT)
10265 {
10266 arm_expand_epilogue (true);
10267 }
cffb2a26 10268 DONE;
10269 "
10270)
56d27660 10271
ef5651d0 10272;; Note - although unspec_volatile's USE all hard registers,
10273;; USEs are ignored after relaod has completed. Thus we need
10274;; to add an unspec of the link register to ensure that flow
10275;; does not think that it is unused by the sibcall branch that
10276;; will replace the standard function epilogue.
c3635784 10277(define_expand "sibcall_epilogue"
fb94f18b 10278 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_REGISTER_USE)
c3635784 10279 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
10280 "TARGET_32BIT"
10281 "
10282 arm_expand_epilogue (false);
10283 DONE;
10284 "
1c494086 10285)
10286
cffb2a26 10287(define_expand "eh_epilogue"
7db9af5d 10288 [(use (match_operand:SI 0 "register_operand" ""))
10289 (use (match_operand:SI 1 "register_operand" ""))
10290 (use (match_operand:SI 2 "register_operand" ""))]
cffb2a26 10291 "TARGET_EITHER"
10292 "
215b30b3 10293 {
10294 cfun->machine->eh_epilogue_sp_ofs = operands[1];
0438d37f 10295 if (!REG_P (operands[2]) || REGNO (operands[2]) != 2)
215b30b3 10296 {
10297 rtx ra = gen_rtx_REG (Pmode, 2);
10298
10299 emit_move_insn (ra, operands[2]);
10300 operands[2] = ra;
10301 }
5cf3595a 10302 /* This is a hack -- we may have crystalized the function type too
10303 early. */
10304 cfun->machine->func_type = 0;
215b30b3 10305 }"
10306)
56d27660 10307
9c08d1fa 10308;; This split is only used during output to reduce the number of patterns
10309;; that need assembler instructions adding to them. We allowed the setting
10310;; of the conditions to be implicit during rtl generation so that
10311;; the conditional compare patterns would work. However this conflicts to
8a18b90c 10312;; some extent with the conditional data operations, so we have to split them
9c08d1fa 10313;; up again here.
10314
25f905c2 10315;; ??? Need to audit these splitters for Thumb-2. Why isn't normal
10316;; conditional execution sufficient?
10317
9c08d1fa 10318(define_split
10319 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 10320 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10321 [(match_operand 2 "" "") (match_operand 3 "" "")])
10322 (match_dup 0)
10323 (match_operand 4 "" "")))
bd5b4116 10324 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10325 "TARGET_ARM && reload_completed"
8fa3ba89 10326 [(set (match_dup 5) (match_dup 6))
10327 (cond_exec (match_dup 7)
10328 (set (match_dup 0) (match_dup 4)))]
10329 "
10330 {
3754d046 10331 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8fa3ba89 10332 operands[2], operands[3]);
10333 enum rtx_code rc = GET_CODE (operands[1]);
10334
bd5b4116 10335 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10336 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10337 if (mode == CCFPmode || mode == CCFPEmode)
10338 rc = reverse_condition_maybe_unordered (rc);
10339 else
10340 rc = reverse_condition (rc);
10341
10342 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
10343 }"
10344)
10345
10346(define_split
10347 [(set (match_operand:SI 0 "s_register_operand" "")
10348 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10349 [(match_operand 2 "" "") (match_operand 3 "" "")])
10350 (match_operand 4 "" "")
10351 (match_dup 0)))
bd5b4116 10352 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10353 "TARGET_ARM && reload_completed"
8fa3ba89 10354 [(set (match_dup 5) (match_dup 6))
10355 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
10356 (set (match_dup 0) (match_dup 4)))]
10357 "
10358 {
3754d046 10359 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8fa3ba89 10360 operands[2], operands[3]);
10361
bd5b4116 10362 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10363 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10364 }"
10365)
10366
10367(define_split
10368 [(set (match_operand:SI 0 "s_register_operand" "")
10369 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9c08d1fa 10370 [(match_operand 2 "" "") (match_operand 3 "" "")])
10371 (match_operand 4 "" "")
10372 (match_operand 5 "" "")))
bd5b4116 10373 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10374 "TARGET_ARM && reload_completed"
8fa3ba89 10375 [(set (match_dup 6) (match_dup 7))
10376 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10377 (set (match_dup 0) (match_dup 4)))
10378 (cond_exec (match_dup 8)
10379 (set (match_dup 0) (match_dup 5)))]
10380 "
10381 {
3754d046 10382 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8fa3ba89 10383 operands[2], operands[3]);
10384 enum rtx_code rc = GET_CODE (operands[1]);
10385
bd5b4116 10386 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10387 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10388 if (mode == CCFPmode || mode == CCFPEmode)
10389 rc = reverse_condition_maybe_unordered (rc);
10390 else
10391 rc = reverse_condition (rc);
10392
10393 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10394 }"
10395)
10396
cffb2a26 10397(define_split
10398 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 10399 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
cffb2a26 10400 [(match_operand:SI 2 "s_register_operand" "")
10401 (match_operand:SI 3 "arm_add_operand" "")])
10402 (match_operand:SI 4 "arm_rhs_operand" "")
10403 (not:SI
10404 (match_operand:SI 5 "s_register_operand" ""))))
bd5b4116 10405 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10406 "TARGET_ARM && reload_completed"
cffb2a26 10407 [(set (match_dup 6) (match_dup 7))
f6c53574 10408 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10409 (set (match_dup 0) (match_dup 4)))
10410 (cond_exec (match_dup 8)
10411 (set (match_dup 0) (not:SI (match_dup 5))))]
cffb2a26 10412 "
215b30b3 10413 {
3754d046 10414 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
215b30b3 10415 operands[2], operands[3]);
f6c53574 10416 enum rtx_code rc = GET_CODE (operands[1]);
cffb2a26 10417
bd5b4116 10418 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
1a83b3ff 10419 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
f6c53574 10420 if (mode == CCFPmode || mode == CCFPEmode)
10421 rc = reverse_condition_maybe_unordered (rc);
10422 else
10423 rc = reverse_condition (rc);
10424
10425 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
215b30b3 10426 }"
10427)
cffb2a26 10428
10429(define_insn "*cond_move_not"
10430 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10431 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
cffb2a26 10432 [(match_operand 3 "cc_register" "") (const_int 0)])
10433 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10434 (not:SI
10435 (match_operand:SI 2 "s_register_operand" "r,r"))))]
10436 "TARGET_ARM"
10437 "@
10438 mvn%D4\\t%0, %2
10439 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
0d66636f 10440 [(set_attr "conds" "use")
1b7da4ac 10441 (set_attr "type" "mvn_reg,multiple")
0d66636f 10442 (set_attr "length" "4,8")]
10443)
cffb2a26 10444
9c08d1fa 10445;; The next two patterns occur when an AND operation is followed by a
10446;; scc insn sequence
10447
f7fbdd4a 10448(define_insn "*sign_extract_onebit"
9c08d1fa 10449 [(set (match_operand:SI 0 "s_register_operand" "=r")
10450 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10451 (const_int 1)
ed750274 10452 (match_operand:SI 2 "const_int_operand" "n")))
10453 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10454 "TARGET_ARM"
9c08d1fa 10455 "*
0d66636f 10456 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10457 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
10458 return \"mvnne\\t%0, #0\";
10459 "
10460 [(set_attr "conds" "clob")
1b7da4ac 10461 (set_attr "length" "8")
10462 (set_attr "type" "multiple")]
0d66636f 10463)
9c08d1fa 10464
f7fbdd4a 10465(define_insn "*not_signextract_onebit"
9c08d1fa 10466 [(set (match_operand:SI 0 "s_register_operand" "=r")
10467 (not:SI
10468 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10469 (const_int 1)
ed750274 10470 (match_operand:SI 2 "const_int_operand" "n"))))
10471 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10472 "TARGET_ARM"
9c08d1fa 10473 "*
0d66636f 10474 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10475 output_asm_insn (\"tst\\t%1, %2\", operands);
10476 output_asm_insn (\"mvneq\\t%0, #0\", operands);
10477 return \"movne\\t%0, #0\";
10478 "
10479 [(set_attr "conds" "clob")
1b7da4ac 10480 (set_attr "length" "12")
10481 (set_attr "type" "multiple")]
0d66636f 10482)
25f905c2 10483;; ??? The above patterns need auditing for Thumb-2
87b22bf7 10484
0d66636f 10485;; Push multiple registers to the stack. Registers are in parallel (use ...)
10486;; expressions. For simplicity, the first register is also in the unspec
10487;; part.
08508cbf 10488;; To avoid the usage of GNU extension, the length attribute is computed
10489;; in a C function arm_attr_length_push_multi.
f7fbdd4a 10490(define_insn "*push_multi"
87b22bf7 10491 [(match_parallel 2 "multi_register_push"
7571d3f7 10492 [(set (match_operand:BLK 0 "push_mult_memory_operand" "")
3cc80a30 10493 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "")]
e1159bbe 10494 UNSPEC_PUSH_MULT))])]
7571d3f7 10495 ""
87b22bf7 10496 "*
215b30b3 10497 {
10498 int num_saves = XVECLEN (operands[2], 0);
ed593f11 10499
215b30b3 10500 /* For the StrongARM at least it is faster to
25f905c2 10501 use STR to store only a single register.
542d5028 10502 In Thumb mode always use push, and the assembler will pick
10503 something appropriate. */
25f905c2 10504 if (num_saves == 1 && TARGET_ARM)
61309563 10505 output_asm_insn (\"str%?\\t%1, [%m0, #-4]!\", operands);
215b30b3 10506 else
10507 {
10508 int i;
10509 char pattern[100];
ed593f11 10510
25f905c2 10511 if (TARGET_ARM)
61309563 10512 strcpy (pattern, \"stm%(fd%)\\t%m0!, {%1\");
10513 else if (TARGET_THUMB2)
10514 strcpy (pattern, \"push%?\\t{%1\");
25f905c2 10515 else
10516 strcpy (pattern, \"push\\t{%1\");
215b30b3 10517
6079f055 10518 for (i = 1; i < num_saves; i++)
215b30b3 10519 {
10520 strcat (pattern, \", %|\");
10521 strcat (pattern,
10522 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
10523 }
10524
10525 strcat (pattern, \"}\");
10526 output_asm_insn (pattern, operands);
10527 }
10528
10529 return \"\";
10530 }"
a6864a24 10531 [(set_attr "type" "store4")
10532 (set (attr "length")
08508cbf 10533 (symbol_ref "arm_attr_length_push_multi (operands[2], operands[1])"))]
215b30b3 10534)
f7fbdd4a 10535
4c58c898 10536(define_insn "stack_tie"
10537 [(set (mem:BLK (scratch))
aaa37ad6 10538 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "rk")
10539 (match_operand:SI 1 "s_register_operand" "rk")]
4c58c898 10540 UNSPEC_PRLG_STK))]
10541 ""
10542 ""
1b7da4ac 10543 [(set_attr "length" "0")
10544 (set_attr "type" "block")]
4c58c898 10545)
10546
426be8c5 10547;; Pop (as used in epilogue RTL)
10548;;
10549(define_insn "*load_multiple_with_writeback"
10550 [(match_parallel 0 "load_multiple_operation"
10551 [(set (match_operand:SI 1 "s_register_operand" "+rk")
10552 (plus:SI (match_dup 1)
809003b3 10553 (match_operand:SI 2 "const_int_I_operand" "I")))
426be8c5 10554 (set (match_operand:SI 3 "s_register_operand" "=rk")
10555 (mem:SI (match_dup 1)))
10556 ])]
10557 "TARGET_32BIT && (reload_in_progress || reload_completed)"
10558 "*
10559 {
10560 arm_output_multireg_pop (operands, /*return_pc=*/false,
10561 /*cond=*/const_true_rtx,
10562 /*reverse=*/false,
10563 /*update=*/true);
10564 return \"\";
10565 }
10566 "
10567 [(set_attr "type" "load4")
10568 (set_attr "predicable" "yes")]
10569)
10570
10571;; Pop with return (as used in epilogue RTL)
10572;;
10573;; This instruction is generated when the registers are popped at the end of
10574;; epilogue. Here, instead of popping the value into LR and then generating
10575;; jump to LR, value is popped into PC directly. Hence, the pattern is combined
10576;; with (return).
10577(define_insn "*pop_multiple_with_writeback_and_return"
10578 [(match_parallel 0 "pop_multiple_return"
10579 [(return)
10580 (set (match_operand:SI 1 "s_register_operand" "+rk")
10581 (plus:SI (match_dup 1)
809003b3 10582 (match_operand:SI 2 "const_int_I_operand" "I")))
426be8c5 10583 (set (match_operand:SI 3 "s_register_operand" "=rk")
10584 (mem:SI (match_dup 1)))
10585 ])]
10586 "TARGET_32BIT && (reload_in_progress || reload_completed)"
10587 "*
10588 {
10589 arm_output_multireg_pop (operands, /*return_pc=*/true,
10590 /*cond=*/const_true_rtx,
10591 /*reverse=*/false,
10592 /*update=*/true);
10593 return \"\";
10594 }
10595 "
10596 [(set_attr "type" "load4")
10597 (set_attr "predicable" "yes")]
10598)
10599
10600(define_insn "*pop_multiple_with_return"
10601 [(match_parallel 0 "pop_multiple_return"
10602 [(return)
10603 (set (match_operand:SI 2 "s_register_operand" "=rk")
10604 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
10605 ])]
10606 "TARGET_32BIT && (reload_in_progress || reload_completed)"
10607 "*
10608 {
10609 arm_output_multireg_pop (operands, /*return_pc=*/true,
10610 /*cond=*/const_true_rtx,
10611 /*reverse=*/false,
10612 /*update=*/false);
10613 return \"\";
10614 }
10615 "
10616 [(set_attr "type" "load4")
10617 (set_attr "predicable" "yes")]
10618)
10619
10620;; Load into PC and return
10621(define_insn "*ldr_with_return"
10622 [(return)
10623 (set (reg:SI PC_REGNUM)
10624 (mem:SI (post_inc:SI (match_operand:SI 0 "s_register_operand" "+rk"))))]
10625 "TARGET_32BIT && (reload_in_progress || reload_completed)"
10626 "ldr%?\t%|pc, [%0], #4"
10627 [(set_attr "type" "load1")
10628 (set_attr "predicable" "yes")]
10629)
1a0b0f12 10630;; Pop for floating point registers (as used in epilogue RTL)
10631(define_insn "*vfp_pop_multiple_with_writeback"
10632 [(match_parallel 0 "pop_multiple_fp"
10633 [(set (match_operand:SI 1 "s_register_operand" "+rk")
10634 (plus:SI (match_dup 1)
809003b3 10635 (match_operand:SI 2 "const_int_I_operand" "I")))
2f2163a4 10636 (set (match_operand:DF 3 "vfp_hard_register_operand" "")
1a0b0f12 10637 (mem:DF (match_dup 1)))])]
10638 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
10639 "*
10640 {
10641 int num_regs = XVECLEN (operands[0], 0);
10642 char pattern[100];
10643 rtx op_list[2];
b34d8dac 10644 strcpy (pattern, \"vldm\\t\");
1a0b0f12 10645 strcat (pattern, reg_names[REGNO (SET_DEST (XVECEXP (operands[0], 0, 0)))]);
10646 strcat (pattern, \"!, {\");
10647 op_list[0] = XEXP (XVECEXP (operands[0], 0, 1), 0);
10648 strcat (pattern, \"%P0\");
10649 if ((num_regs - 1) > 1)
10650 {
10651 strcat (pattern, \"-%P1\");
10652 op_list [1] = XEXP (XVECEXP (operands[0], 0, num_regs - 1), 0);
10653 }
10654
10655 strcat (pattern, \"}\");
10656 output_asm_insn (pattern, op_list);
10657 return \"\";
10658 }
10659 "
10660 [(set_attr "type" "load4")
10661 (set_attr "conds" "unconditional")
10662 (set_attr "predicable" "no")]
10663)
10664
f7fbdd4a 10665;; Special patterns for dealing with the constant pool
10666
cffb2a26 10667(define_insn "align_4"
e1159bbe 10668 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
cffb2a26 10669 "TARGET_EITHER"
f7fbdd4a 10670 "*
cffb2a26 10671 assemble_align (32);
f7fbdd4a 10672 return \"\";
cffb2a26 10673 "
1b7da4ac 10674 [(set_attr "type" "no_insn")]
cffb2a26 10675)
f7fbdd4a 10676
755eb2b4 10677(define_insn "align_8"
10678 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
f9273c43 10679 "TARGET_EITHER"
755eb2b4 10680 "*
10681 assemble_align (64);
10682 return \"\";
10683 "
1b7da4ac 10684 [(set_attr "type" "no_insn")]
755eb2b4 10685)
10686
cffb2a26 10687(define_insn "consttable_end"
e1159bbe 10688 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
cffb2a26 10689 "TARGET_EITHER"
f7fbdd4a 10690 "*
cffb2a26 10691 making_const_table = FALSE;
f7fbdd4a 10692 return \"\";
cffb2a26 10693 "
1b7da4ac 10694 [(set_attr "type" "no_insn")]
cffb2a26 10695)
f7fbdd4a 10696
0e207eb8 10697(define_insn "consttable_1"
10698 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
10699 "TARGET_EITHER"
10700 "*
10701 making_const_table = TRUE;
10702 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
10703 assemble_zeros (3);
10704 return \"\";
10705 "
10706 [(set_attr "length" "4")
10707 (set_attr "type" "no_insn")]
10708)
10709
10710(define_insn "consttable_2"
10711 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
10712 "TARGET_EITHER"
10713 "*
10714 {
10715 rtx x = operands[0];
10716 making_const_table = TRUE;
10717 switch (GET_MODE_CLASS (GET_MODE (x)))
10718 {
10719 case MODE_FLOAT:
10720 arm_emit_fp16_const (x);
10721 break;
10722 default:
10723 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
10724 assemble_zeros (2);
10725 break;
10726 }
10727 return \"\";
10728 }"
10729 [(set_attr "length" "4")
10730 (set_attr "type" "no_insn")]
10731)
10732
cffb2a26 10733(define_insn "consttable_4"
e1159bbe 10734 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
cffb2a26 10735 "TARGET_EITHER"
10736 "*
10737 {
9b8516be 10738 rtx x = operands[0];
cffb2a26 10739 making_const_table = TRUE;
9b8516be 10740 switch (GET_MODE_CLASS (GET_MODE (x)))
cffb2a26 10741 {
10742 case MODE_FLOAT:
0e207eb8 10743 {
10744 REAL_VALUE_TYPE r;
10745 REAL_VALUE_FROM_CONST_DOUBLE (r, x);
10746 assemble_real (r, GET_MODE (x), BITS_PER_WORD);
10747 break;
10748 }
cffb2a26 10749 default:
7b04c5d5 10750 /* XXX: Sometimes gcc does something really dumb and ends up with
10751 a HIGH in a constant pool entry, usually because it's trying to
10752 load into a VFP register. We know this will always be used in
10753 combination with a LO_SUM which ignores the high bits, so just
10754 strip off the HIGH. */
10755 if (GET_CODE (x) == HIGH)
10756 x = XEXP (x, 0);
9b8516be 10757 assemble_integer (x, 4, BITS_PER_WORD, 1);
10758 mark_symbol_refs_as_used (x);
cffb2a26 10759 break;
10760 }
10761 return \"\";
10762 }"
1b7da4ac 10763 [(set_attr "length" "4")
10764 (set_attr "type" "no_insn")]
cffb2a26 10765)
10766
10767(define_insn "consttable_8"
e1159bbe 10768 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
cffb2a26 10769 "TARGET_EITHER"
10770 "*
10771 {
10772 making_const_table = TRUE;
10773 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10774 {
10775 case MODE_FLOAT:
10776 {
badfe841 10777 REAL_VALUE_TYPE r;
10778 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10779 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
cffb2a26 10780 break;
10781 }
10782 default:
09d688ff 10783 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
cffb2a26 10784 break;
10785 }
10786 return \"\";
10787 }"
1b7da4ac 10788 [(set_attr "length" "8")
10789 (set_attr "type" "no_insn")]
cffb2a26 10790)
10791
d98a3884 10792(define_insn "consttable_16"
10793 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_16)]
10794 "TARGET_EITHER"
10795 "*
10796 {
10797 making_const_table = TRUE;
10798 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10799 {
10800 case MODE_FLOAT:
10801 {
10802 REAL_VALUE_TYPE r;
10803 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10804 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10805 break;
10806 }
10807 default:
10808 assemble_integer (operands[0], 16, BITS_PER_WORD, 1);
10809 break;
10810 }
10811 return \"\";
10812 }"
1b7da4ac 10813 [(set_attr "length" "16")
10814 (set_attr "type" "no_insn")]
d98a3884 10815)
10816
331beb1a 10817;; V5 Instructions,
10818
8f4be2be 10819(define_insn "clzsi2"
10820 [(set (match_operand:SI 0 "s_register_operand" "=r")
10821 (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 10822 "TARGET_32BIT && arm_arch5"
ee7cbe0e 10823 "clz%?\\t%0, %1"
bcaec148 10824 [(set_attr "predicable" "yes")
4a510717 10825 (set_attr "predicable_short_it" "no")
bebe9bbb 10826 (set_attr "type" "clz")])
331beb1a 10827
099ad98b 10828(define_insn "rbitsi2"
10829 [(set (match_operand:SI 0 "s_register_operand" "=r")
10830 (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")] UNSPEC_RBIT))]
10831 "TARGET_32BIT && arm_arch_thumb2"
10832 "rbit%?\\t%0, %1"
10833 [(set_attr "predicable" "yes")
4a510717 10834 (set_attr "predicable_short_it" "no")
bebe9bbb 10835 (set_attr "type" "clz")])
099ad98b 10836
10837(define_expand "ctzsi2"
10838 [(set (match_operand:SI 0 "s_register_operand" "")
10839 (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
10840 "TARGET_32BIT && arm_arch_thumb2"
10841 "
30191172 10842 {
10843 rtx tmp = gen_reg_rtx (SImode);
10844 emit_insn (gen_rbitsi2 (tmp, operands[1]));
10845 emit_insn (gen_clzsi2 (operands[0], tmp));
10846 }
099ad98b 10847 DONE;
10848 "
10849)
10850
e1159bbe 10851;; V5E instructions.
331beb1a 10852
10853(define_insn "prefetch"
f4e79814 10854 [(prefetch (match_operand:SI 0 "address_operand" "p")
10855 (match_operand:SI 1 "" "")
10856 (match_operand:SI 2 "" ""))]
25f905c2 10857 "TARGET_32BIT && arm_arch5e"
1b7da4ac 10858 "pld\\t%a0"
10859 [(set_attr "type" "load1")]
10860)
331beb1a 10861
0d66636f 10862;; General predication pattern
10863
10864(define_cond_exec
10865 [(match_operator 0 "arm_comparison_operator"
10866 [(match_operand 1 "cc_register" "")
10867 (const_int 0)])]
580f4c48 10868 "TARGET_32BIT
10869 && (!TARGET_NO_VOLATILE_CE || !volatile_refs_p (PATTERN (insn)))"
0d66636f 10870 ""
c7a58118 10871[(set_attr "predicated" "yes")]
0d66636f 10872)
10873
fb94f18b 10874(define_insn "force_register_use"
10875 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_REGISTER_USE)]
063a05c7 10876 ""
fb94f18b 10877 "%@ %0 needed"
1b7da4ac 10878 [(set_attr "length" "0")
10879 (set_attr "type" "no_insn")]
063a05c7 10880)
7db9af5d 10881
4c44712e 10882
10883;; Patterns for exception handling
10884
10885(define_expand "eh_return"
10886 [(use (match_operand 0 "general_operand" ""))]
10887 "TARGET_EITHER"
10888 "
10889 {
25f905c2 10890 if (TARGET_32BIT)
4c44712e 10891 emit_insn (gen_arm_eh_return (operands[0]));
10892 else
10893 emit_insn (gen_thumb_eh_return (operands[0]));
10894 DONE;
10895 }"
10896)
10897
10898;; We can't expand this before we know where the link register is stored.
10899(define_insn_and_split "arm_eh_return"
10900 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
10901 VUNSPEC_EH_RETURN)
10902 (clobber (match_scratch:SI 1 "=&r"))]
10903 "TARGET_ARM"
10904 "#"
10905 "&& reload_completed"
10906 [(const_int 0)]
10907 "
10908 {
10909 arm_set_return_address (operands[0], operands[1]);
10910 DONE;
10911 }"
10912)
10913
f655717d 10914\f
10915;; TLS support
10916
10917(define_insn "load_tp_hard"
10918 [(set (match_operand:SI 0 "register_operand" "=r")
10919 (unspec:SI [(const_int 0)] UNSPEC_TLS))]
10920 "TARGET_HARD_TP"
10921 "mrc%?\\tp15, 0, %0, c13, c0, 3\\t@ load_tp_hard"
1b7da4ac 10922 [(set_attr "predicable" "yes")
4b5d7374 10923 (set_attr "type" "mrs")]
f655717d 10924)
10925
10926;; Doesn't clobber R1-R3. Must use r0 for the first operand.
10927(define_insn "load_tp_soft"
10928 [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
10929 (clobber (reg:SI LR_REGNUM))
10930 (clobber (reg:SI IP_REGNUM))
10931 (clobber (reg:CC CC_REGNUM))]
10932 "TARGET_SOFT_TP"
10933 "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
1b7da4ac 10934 [(set_attr "conds" "clob")
10935 (set_attr "type" "branch")]
f655717d 10936)
10937
f41e4452 10938;; tls descriptor call
10939(define_insn "tlscall"
10940 [(set (reg:SI R0_REGNUM)
10941 (unspec:SI [(reg:SI R0_REGNUM)
10942 (match_operand:SI 0 "" "X")
10943 (match_operand 1 "" "")] UNSPEC_TLS))
10944 (clobber (reg:SI R1_REGNUM))
10945 (clobber (reg:SI LR_REGNUM))
10946 (clobber (reg:SI CC_REGNUM))]
10947 "TARGET_GNU2_TLS"
10948 {
10949 targetm.asm_out.internal_label (asm_out_file, "LPIC",
10950 INTVAL (operands[1]));
10951 return "bl\\t%c0(tlscall)";
10952 }
10953 [(set_attr "conds" "clob")
1b7da4ac 10954 (set_attr "length" "4")
10955 (set_attr "type" "branch")]
f41e4452 10956)
10957
1fe0edab 10958;; For thread pointer builtin
10959(define_expand "get_thread_pointersi"
10960 [(match_operand:SI 0 "s_register_operand" "=r")]
10961 ""
10962 "
10963 {
10964 arm_load_tp (operands[0]);
10965 DONE;
10966 }")
10967
f41e4452 10968;;
10969
aabe09ac 10970;; We only care about the lower 16 bits of the constant
10971;; being inserted into the upper 16 bits of the register.
eca5c984 10972(define_insn "*arm_movtas_ze"
10973 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
10974 (const_int 16)
10975 (const_int 16))
10976 (match_operand:SI 1 "const_int_operand" ""))]
181ab277 10977 "arm_arch_thumb2"
aabe09ac 10978 "movt%?\t%0, %L1"
eca5c984 10979 [(set_attr "predicable" "yes")
7c36fe71 10980 (set_attr "predicable_short_it" "no")
1b7da4ac 10981 (set_attr "length" "4")
282b4c75 10982 (set_attr "type" "alu_sreg")]
eca5c984 10983)
10984
c0fc3696 10985(define_insn "*arm_rev"
a486b499 10986 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
10987 (bswap:SI (match_operand:SI 1 "s_register_operand" "l,l,r")))]
10988 "arm_arch6"
10989 "@
10990 rev\t%0, %1
10991 rev%?\t%0, %1
10992 rev%?\t%0, %1"
10993 [(set_attr "arch" "t1,t2,32")
1b7da4ac 10994 (set_attr "length" "2,2,4")
4a510717 10995 (set_attr "predicable" "no,yes,yes")
10996 (set_attr "predicable_short_it" "no")
1b7da4ac 10997 (set_attr "type" "rev")]
ff82f757 10998)
10999
11000(define_expand "arm_legacy_rev"
11001 [(set (match_operand:SI 2 "s_register_operand" "")
11002 (xor:SI (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
11003 (const_int 16))
11004 (match_dup 1)))
11005 (set (match_dup 2)
11006 (lshiftrt:SI (match_dup 2)
11007 (const_int 8)))
11008 (set (match_operand:SI 3 "s_register_operand" "")
11009 (rotatert:SI (match_dup 1)
11010 (const_int 8)))
11011 (set (match_dup 2)
11012 (and:SI (match_dup 2)
11013 (const_int -65281)))
11014 (set (match_operand:SI 0 "s_register_operand" "")
11015 (xor:SI (match_dup 3)
11016 (match_dup 2)))]
11017 "TARGET_32BIT"
11018 ""
11019)
11020
11021;; Reuse temporaries to keep register pressure down.
11022(define_expand "thumb_legacy_rev"
11023 [(set (match_operand:SI 2 "s_register_operand" "")
11024 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
11025 (const_int 24)))
11026 (set (match_operand:SI 3 "s_register_operand" "")
11027 (lshiftrt:SI (match_dup 1)
11028 (const_int 24)))
11029 (set (match_dup 3)
11030 (ior:SI (match_dup 3)
11031 (match_dup 2)))
11032 (set (match_operand:SI 4 "s_register_operand" "")
11033 (const_int 16))
11034 (set (match_operand:SI 5 "s_register_operand" "")
11035 (rotatert:SI (match_dup 1)
11036 (match_dup 4)))
11037 (set (match_dup 2)
11038 (ashift:SI (match_dup 5)
11039 (const_int 24)))
11040 (set (match_dup 5)
11041 (lshiftrt:SI (match_dup 5)
11042 (const_int 24)))
11043 (set (match_dup 5)
11044 (ior:SI (match_dup 5)
11045 (match_dup 2)))
11046 (set (match_dup 5)
11047 (rotatert:SI (match_dup 5)
11048 (match_dup 4)))
11049 (set (match_operand:SI 0 "s_register_operand" "")
11050 (ior:SI (match_dup 5)
11051 (match_dup 3)))]
11052 "TARGET_THUMB"
11053 ""
11054)
11055
11056(define_expand "bswapsi2"
11057 [(set (match_operand:SI 0 "s_register_operand" "=r")
11058 (bswap:SI (match_operand:SI 1 "s_register_operand" "r")))]
8d1af482 11059"TARGET_EITHER && (arm_arch6 || !optimize_size)"
ff82f757 11060"
8d1af482 11061 if (!arm_arch6)
11062 {
11063 rtx op2 = gen_reg_rtx (SImode);
11064 rtx op3 = gen_reg_rtx (SImode);
ff82f757 11065
8d1af482 11066 if (TARGET_THUMB)
11067 {
11068 rtx op4 = gen_reg_rtx (SImode);
11069 rtx op5 = gen_reg_rtx (SImode);
ff82f757 11070
8d1af482 11071 emit_insn (gen_thumb_legacy_rev (operands[0], operands[1],
11072 op2, op3, op4, op5));
11073 }
11074 else
11075 {
11076 emit_insn (gen_arm_legacy_rev (operands[0], operands[1],
11077 op2, op3));
11078 }
ff82f757 11079
8d1af482 11080 DONE;
11081 }
ff82f757 11082 "
11083)
11084
a486b499 11085;; bswap16 patterns: use revsh and rev16 instructions for the signed
11086;; and unsigned variants, respectively. For rev16, expose
11087;; byte-swapping in the lower 16 bits only.
11088(define_insn "*arm_revsh"
11089 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
11090 (sign_extend:SI (bswap:HI (match_operand:HI 1 "s_register_operand" "l,l,r"))))]
11091 "arm_arch6"
11092 "@
11093 revsh\t%0, %1
11094 revsh%?\t%0, %1
11095 revsh%?\t%0, %1"
11096 [(set_attr "arch" "t1,t2,32")
1b7da4ac 11097 (set_attr "length" "2,2,4")
11098 (set_attr "type" "rev")]
a486b499 11099)
11100
11101(define_insn "*arm_rev16"
11102 [(set (match_operand:HI 0 "s_register_operand" "=l,l,r")
11103 (bswap:HI (match_operand:HI 1 "s_register_operand" "l,l,r")))]
11104 "arm_arch6"
11105 "@
11106 rev16\t%0, %1
11107 rev16%?\t%0, %1
11108 rev16%?\t%0, %1"
11109 [(set_attr "arch" "t1,t2,32")
1b7da4ac 11110 (set_attr "length" "2,2,4")
11111 (set_attr "type" "rev")]
09f69e55 11112)
11113
11114;; There are no canonicalisation rules for the position of the lshiftrt, ashift
11115;; operations within an IOR/AND RTX, therefore we have two patterns matching
11116;; each valid permutation.
11117
11118(define_insn "arm_rev16si2"
11119 [(set (match_operand:SI 0 "register_operand" "=l,l,r")
11120 (ior:SI (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "l,l,r")
11121 (const_int 8))
11122 (match_operand:SI 3 "const_int_operand" "n,n,n"))
11123 (and:SI (lshiftrt:SI (match_dup 1)
11124 (const_int 8))
11125 (match_operand:SI 2 "const_int_operand" "n,n,n"))))]
11126 "arm_arch6
11127 && aarch_rev16_shleft_mask_imm_p (operands[3], SImode)
11128 && aarch_rev16_shright_mask_imm_p (operands[2], SImode)"
11129 "rev16\\t%0, %1"
11130 [(set_attr "arch" "t1,t2,32")
11131 (set_attr "length" "2,2,4")
11132 (set_attr "type" "rev")]
11133)
11134
11135(define_insn "arm_rev16si2_alt"
11136 [(set (match_operand:SI 0 "register_operand" "=l,l,r")
11137 (ior:SI (and:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,l,r")
11138 (const_int 8))
11139 (match_operand:SI 2 "const_int_operand" "n,n,n"))
11140 (and:SI (ashift:SI (match_dup 1)
11141 (const_int 8))
11142 (match_operand:SI 3 "const_int_operand" "n,n,n"))))]
11143 "arm_arch6
11144 && aarch_rev16_shleft_mask_imm_p (operands[3], SImode)
11145 && aarch_rev16_shright_mask_imm_p (operands[2], SImode)"
11146 "rev16\\t%0, %1"
11147 [(set_attr "arch" "t1,t2,32")
11148 (set_attr "length" "2,2,4")
11149 (set_attr "type" "rev")]
a486b499 11150)
11151
11152(define_expand "bswaphi2"
11153 [(set (match_operand:HI 0 "s_register_operand" "=r")
11154 (bswap:HI (match_operand:HI 1 "s_register_operand" "r")))]
11155"arm_arch6"
11156""
11157)
11158
1653cf17 11159;; Patterns for LDRD/STRD in Thumb2 mode
11160
11161(define_insn "*thumb2_ldrd"
11162 [(set (match_operand:SI 0 "s_register_operand" "=r")
11163 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
11164 (match_operand:SI 2 "ldrd_strd_offset_operand" "Do"))))
11165 (set (match_operand:SI 3 "s_register_operand" "=r")
11166 (mem:SI (plus:SI (match_dup 1)
11167 (match_operand:SI 4 "const_int_operand" ""))))]
11168 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11169 && current_tune->prefer_ldrd_strd
11170 && ((INTVAL (operands[2]) + 4) == INTVAL (operands[4]))
11171 && (operands_ok_ldrd_strd (operands[0], operands[3],
11172 operands[1], INTVAL (operands[2]),
11173 false, true))"
11174 "ldrd%?\t%0, %3, [%1, %2]"
11175 [(set_attr "type" "load2")
d952d547 11176 (set_attr "predicable" "yes")
11177 (set_attr "predicable_short_it" "no")])
1653cf17 11178
11179(define_insn "*thumb2_ldrd_base"
11180 [(set (match_operand:SI 0 "s_register_operand" "=r")
11181 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
11182 (set (match_operand:SI 2 "s_register_operand" "=r")
11183 (mem:SI (plus:SI (match_dup 1)
11184 (const_int 4))))]
11185 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11186 && current_tune->prefer_ldrd_strd
11187 && (operands_ok_ldrd_strd (operands[0], operands[2],
11188 operands[1], 0, false, true))"
11189 "ldrd%?\t%0, %2, [%1]"
11190 [(set_attr "type" "load2")
d952d547 11191 (set_attr "predicable" "yes")
11192 (set_attr "predicable_short_it" "no")])
1653cf17 11193
11194(define_insn "*thumb2_ldrd_base_neg"
11195 [(set (match_operand:SI 0 "s_register_operand" "=r")
11196 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
11197 (const_int -4))))
11198 (set (match_operand:SI 2 "s_register_operand" "=r")
11199 (mem:SI (match_dup 1)))]
11200 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11201 && current_tune->prefer_ldrd_strd
11202 && (operands_ok_ldrd_strd (operands[0], operands[2],
11203 operands[1], -4, false, true))"
11204 "ldrd%?\t%0, %2, [%1, #-4]"
11205 [(set_attr "type" "load2")
d952d547 11206 (set_attr "predicable" "yes")
11207 (set_attr "predicable_short_it" "no")])
1653cf17 11208
11209(define_insn "*thumb2_strd"
11210 [(set (mem:SI (plus:SI (match_operand:SI 0 "s_register_operand" "rk")
11211 (match_operand:SI 1 "ldrd_strd_offset_operand" "Do")))
11212 (match_operand:SI 2 "s_register_operand" "r"))
11213 (set (mem:SI (plus:SI (match_dup 0)
11214 (match_operand:SI 3 "const_int_operand" "")))
11215 (match_operand:SI 4 "s_register_operand" "r"))]
11216 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11217 && current_tune->prefer_ldrd_strd
11218 && ((INTVAL (operands[1]) + 4) == INTVAL (operands[3]))
11219 && (operands_ok_ldrd_strd (operands[2], operands[4],
11220 operands[0], INTVAL (operands[1]),
11221 false, false))"
11222 "strd%?\t%2, %4, [%0, %1]"
11223 [(set_attr "type" "store2")
d952d547 11224 (set_attr "predicable" "yes")
11225 (set_attr "predicable_short_it" "no")])
1653cf17 11226
11227(define_insn "*thumb2_strd_base"
11228 [(set (mem:SI (match_operand:SI 0 "s_register_operand" "rk"))
11229 (match_operand:SI 1 "s_register_operand" "r"))
11230 (set (mem:SI (plus:SI (match_dup 0)
11231 (const_int 4)))
11232 (match_operand:SI 2 "s_register_operand" "r"))]
11233 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11234 && current_tune->prefer_ldrd_strd
11235 && (operands_ok_ldrd_strd (operands[1], operands[2],
11236 operands[0], 0, false, false))"
11237 "strd%?\t%1, %2, [%0]"
11238 [(set_attr "type" "store2")
d952d547 11239 (set_attr "predicable" "yes")
11240 (set_attr "predicable_short_it" "no")])
1653cf17 11241
11242(define_insn "*thumb2_strd_base_neg"
11243 [(set (mem:SI (plus:SI (match_operand:SI 0 "s_register_operand" "rk")
11244 (const_int -4)))
11245 (match_operand:SI 1 "s_register_operand" "r"))
11246 (set (mem:SI (match_dup 0))
11247 (match_operand:SI 2 "s_register_operand" "r"))]
11248 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11249 && current_tune->prefer_ldrd_strd
11250 && (operands_ok_ldrd_strd (operands[1], operands[2],
11251 operands[0], -4, false, false))"
11252 "strd%?\t%1, %2, [%0, #-4]"
11253 [(set_attr "type" "store2")
d952d547 11254 (set_attr "predicable" "yes")
11255 (set_attr "predicable_short_it" "no")])
1653cf17 11256
2a0c73f2 11257;; ARMv8 CRC32 instructions.
11258(define_insn "<crc_variant>"
11259 [(set (match_operand:SI 0 "s_register_operand" "=r")
11260 (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")
11261 (match_operand:<crc_mode> 2 "s_register_operand" "r")]
11262 CRC))]
11263 "TARGET_CRC32"
11264 "<crc_variant>\\t%0, %1, %2"
11265 [(set_attr "type" "crc")
11266 (set_attr "conds" "unconditional")]
11267)
1653cf17 11268
353cf59a 11269;; Load the load/store double peephole optimizations.
11270(include "ldrdstrd.md")
11271
320ea44d 11272;; Load the load/store multiple patterns
11273(include "ldmstm.md")
426be8c5 11274
11275;; Patterns in ldmstm.md don't cover more than 4 registers. This pattern covers
11276;; large lists without explicit writeback generated for APCS_FRAME epilogue.
11277(define_insn "*load_multiple"
11278 [(match_parallel 0 "load_multiple_operation"
11279 [(set (match_operand:SI 2 "s_register_operand" "=rk")
11280 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
11281 ])]
11282 "TARGET_32BIT"
11283 "*
11284 {
11285 arm_output_multireg_pop (operands, /*return_pc=*/false,
11286 /*cond=*/const_true_rtx,
11287 /*reverse=*/false,
11288 /*update=*/false);
11289 return \"\";
11290 }
11291 "
11292 [(set_attr "predicable" "yes")]
11293)
11294
84450ddc 11295(define_expand "copysignsf3"
11296 [(match_operand:SF 0 "register_operand")
11297 (match_operand:SF 1 "register_operand")
11298 (match_operand:SF 2 "register_operand")]
11299 "TARGET_SOFT_FLOAT && arm_arch_thumb2"
11300 "{
11301 emit_move_insn (operands[0], operands[2]);
11302 emit_insn (gen_insv_t2 (simplify_gen_subreg (SImode, operands[0], SFmode, 0),
11303 GEN_INT (31), GEN_INT (0),
11304 simplify_gen_subreg (SImode, operands[1], SFmode, 0)));
11305 DONE;
11306 }"
11307)
11308
11309(define_expand "copysigndf3"
11310 [(match_operand:DF 0 "register_operand")
11311 (match_operand:DF 1 "register_operand")
11312 (match_operand:DF 2 "register_operand")]
11313 "TARGET_SOFT_FLOAT && arm_arch_thumb2"
11314 "{
11315 rtx op0_low = gen_lowpart (SImode, operands[0]);
11316 rtx op0_high = gen_highpart (SImode, operands[0]);
11317 rtx op1_low = gen_lowpart (SImode, operands[1]);
11318 rtx op1_high = gen_highpart (SImode, operands[1]);
11319 rtx op2_high = gen_highpart (SImode, operands[2]);
11320
11321 rtx scratch1 = gen_reg_rtx (SImode);
11322 rtx scratch2 = gen_reg_rtx (SImode);
11323 emit_move_insn (scratch1, op2_high);
11324 emit_move_insn (scratch2, op1_high);
11325
d1f9b275 11326 emit_insn(gen_rtx_SET(scratch1,
84450ddc 11327 gen_rtx_LSHIFTRT (SImode, op2_high, GEN_INT(31))));
11328 emit_insn(gen_insv_t2(scratch2, GEN_INT(1), GEN_INT(31), scratch1));
11329 emit_move_insn (op0_low, op1_low);
11330 emit_move_insn (op0_high, scratch2);
11331
11332 DONE;
11333 }"
11334)
11335
d98a3884 11336;; Vector bits common to IWMMXT and Neon
11337(include "vec-common.md")
755eb2b4 11338;; Load the Intel Wireless Multimedia Extension patterns
11339(include "iwmmxt.md")
a2cd141b 11340;; Load the VFP co-processor patterns
11341(include "vfp.md")
bc360af8 11342;; Thumb-1 patterns
11343(include "thumb1.md")
25f905c2 11344;; Thumb-2 patterns
11345(include "thumb2.md")
d98a3884 11346;; Neon patterns
11347(include "neon.md")
e84fdf6e 11348;; Crypto patterns
11349(include "crypto.md")
06df6b17 11350;; Synchronization Primitives
11351(include "sync.md")
bbbe4599 11352;; Fixed-point patterns
11353(include "arm-fixed.md")