]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/arm/arm.md
2015-01-26 Tony Liu <tony.liu@arm.com>
[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.
1c494086 72(define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
cffb2a26 73
ef51b8e1 74; IS_ARCH6 is set to 'yes' when we are generating code form ARMv6.
75(define_attr "is_arch6" "no,yes" (const (symbol_ref "arm_arch6")))
76
747b7458 77; IS_THUMB1 is set to 'yes' iff we are generating Thumb-1 code.
78(define_attr "is_thumb1" "no,yes" (const (symbol_ref "thumb1_code")))
79
c7a58118 80; We use this attribute to disable alternatives that can produce 32-bit
81; instructions inside an IT-block in Thumb2 state. ARMv8 deprecates IT blocks
82; that contain 32-bit instructions.
83(define_attr "enabled_for_depr_it" "no,yes" (const_string "yes"))
84
85; This attribute is used to disable a predicated alternative when we have
86; arm_restrict_it.
87(define_attr "predicable_short_it" "no,yes" (const_string "yes"))
88
331beb1a 89;; Operand number of an input operand that is shifted. Zero if the
90;; given instruction does not shift one of its input operands.
331beb1a 91(define_attr "shift" "" (const_int 0))
92
55a94dda 93;; [For compatibility with AArch64 in pipeline models]
94;; Attribute that specifies whether or not the instruction touches fp
95;; registers.
96(define_attr "fp" "no,yes" (const_string "no"))
97
3d91c5d6 98; Floating Point Unit. If we only have floating point emulation, then there
99; is no point in scheduling the floating point insns. (Well, for best
100; performance we should try and group them together).
bffbb863 101(define_attr "fpu" "none,vfp"
c7f506fd 102 (const (symbol_ref "arm_fpu_attr")))
3d91c5d6 103
c7a58118 104(define_attr "predicated" "yes,no" (const_string "no"))
105
094e994f 106; LENGTH of an instruction (in bytes)
06df6b17 107(define_attr "length" ""
e1b93706 108 (const_int 4))
9c08d1fa 109
d5d4dc8d 110; The architecture which supports the instruction (or alternative).
111; This can be "a" for ARM, "t" for either of the Thumbs, "32" for
112; TARGET_32BIT, "t1" or "t2" to specify a specific Thumb mode. "v6"
113; for ARM or Thumb-2 with arm_arch6, and nov6 for ARM without
e4585731 114; arm_arch6. "v6t2" for Thumb-2 with arm_arch6. This attribute is
115; used to compute attribute "enabled", use type "any" to enable an
116; alternative in all cases.
117(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 118 (const_string "any"))
119
120(define_attr "arch_enabled" "no,yes"
121 (cond [(eq_attr "arch" "any")
122 (const_string "yes")
123
124 (and (eq_attr "arch" "a")
0bf497f5 125 (match_test "TARGET_ARM"))
d5d4dc8d 126 (const_string "yes")
127
128 (and (eq_attr "arch" "t")
0bf497f5 129 (match_test "TARGET_THUMB"))
d5d4dc8d 130 (const_string "yes")
131
132 (and (eq_attr "arch" "t1")
0bf497f5 133 (match_test "TARGET_THUMB1"))
d5d4dc8d 134 (const_string "yes")
135
136 (and (eq_attr "arch" "t2")
0bf497f5 137 (match_test "TARGET_THUMB2"))
d5d4dc8d 138 (const_string "yes")
139
140 (and (eq_attr "arch" "32")
0bf497f5 141 (match_test "TARGET_32BIT"))
d5d4dc8d 142 (const_string "yes")
143
144 (and (eq_attr "arch" "v6")
0bf497f5 145 (match_test "TARGET_32BIT && arm_arch6"))
d5d4dc8d 146 (const_string "yes")
147
148 (and (eq_attr "arch" "nov6")
0bf497f5 149 (match_test "TARGET_32BIT && !arm_arch6"))
a651f34d 150 (const_string "yes")
151
e4585731 152 (and (eq_attr "arch" "v6t2")
153 (match_test "TARGET_32BIT && arm_arch6 && arm_arch_thumb2"))
154 (const_string "yes")
155
b6779ddc 156 (and (eq_attr "arch" "avoid_neon_for_64bits")
157 (match_test "TARGET_NEON")
158 (not (match_test "TARGET_PREFER_NEON_64BITS")))
a651f34d 159 (const_string "yes")
160
b6779ddc 161 (and (eq_attr "arch" "neon_for_64bits")
162 (match_test "TARGET_NEON")
163 (match_test "TARGET_PREFER_NEON_64BITS"))
6b8f7c28 164 (const_string "yes")
165
166 (and (eq_attr "arch" "iwmmxt2")
167 (match_test "TARGET_REALLY_IWMMXT2"))
21cc9773 168 (const_string "yes")
169
170 (and (eq_attr "arch" "armv6_or_vfpv3")
171 (match_test "arm_arch6 || TARGET_VFP3"))
172 (const_string "yes")
173 ]
6b8f7c28 174
d5d4dc8d 175 (const_string "no")))
176
aa06c51c 177(define_attr "opt" "any,speed,size"
178 (const_string "any"))
179
180(define_attr "opt_enabled" "no,yes"
181 (cond [(eq_attr "opt" "any")
182 (const_string "yes")
183
184 (and (eq_attr "opt" "speed")
185 (match_test "optimize_function_for_speed_p (cfun)"))
186 (const_string "yes")
187
188 (and (eq_attr "opt" "size")
189 (match_test "optimize_function_for_size_p (cfun)"))
190 (const_string "yes")]
191 (const_string "no")))
192
861033d5 193(define_attr "use_literal_pool" "no,yes"
194 (cond [(and (eq_attr "type" "f_loads,f_loadd")
195 (match_test "CONSTANT_P (operands[1])"))
196 (const_string "yes")]
197 (const_string "no")))
198
d5d4dc8d 199; Enable all alternatives that are both arch_enabled and insn_enabled.
951a3f72 200; FIXME:: opt_enabled has been temporarily removed till the time we have
201; an attribute that allows the use of such alternatives.
202; This depends on caching of speed_p, size_p on a per
203; alternative basis. The problem is that the enabled attribute
204; cannot depend on any state that is not cached or is not constant
205; for a compilation unit. We probably need a generic "hot/cold"
206; alternative which if implemented can help with this. We disable this
207; until such a time as this is implemented and / or the improvements or
208; regressions with removing this attribute are double checked.
209; See ashldi3_neon and <shift>di3_neon in neon.md.
210
93b431d9 211 (define_attr "enabled" "no,yes"
0abea32c 212 (cond [(and (eq_attr "predicable_short_it" "no")
c7a58118 213 (and (eq_attr "predicated" "yes")
214 (match_test "arm_restrict_it")))
215 (const_string "no")
216
217 (and (eq_attr "enabled_for_depr_it" "no")
218 (match_test "arm_restrict_it"))
219 (const_string "no")
220
861033d5 221 (and (eq_attr "use_literal_pool" "yes")
222 (match_test "arm_disable_literal_pool"))
223 (const_string "no")
224
aa06c51c 225 (eq_attr "arch_enabled" "no")
aa06c51c 226 (const_string "no")]
227 (const_string "yes")))
d5d4dc8d 228
56d27660 229; POOL_RANGE is how far away from a constant pool entry that this insn
230; can be placed. If the distance is zero, then this insn will never
231; reference the pool.
42e1de19 232; Note that for Thumb constant pools the PC value is rounded down to the
233; nearest multiple of four. Therefore, THUMB2_POOL_RANGE (and POOL_RANGE for
234; Thumb insns) should be set to <max_range> - 2.
cffb2a26 235; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
8848d797 236; before its address. It is set to <max_range> - (8 + <data_size>).
cde1623a 237(define_attr "arm_pool_range" "" (const_int 0))
238(define_attr "thumb2_pool_range" "" (const_int 0))
239(define_attr "arm_neg_pool_range" "" (const_int 0))
240(define_attr "thumb2_neg_pool_range" "" (const_int 0))
241
242(define_attr "pool_range" ""
243 (cond [(eq_attr "is_thumb" "yes") (attr "thumb2_pool_range")]
244 (attr "arm_pool_range")))
245(define_attr "neg_pool_range" ""
246 (cond [(eq_attr "is_thumb" "yes") (attr "thumb2_neg_pool_range")]
247 (attr "arm_neg_pool_range")))
56d27660 248
215b30b3 249; An assembler sequence may clobber the condition codes without us knowing.
4d7a8451 250; If such an insn references the pool, then we have no way of knowing how,
251; so use the most conservative value for pool_range.
9c08d1fa 252(define_asm_attributes
4d7a8451 253 [(set_attr "conds" "clob")
254 (set_attr "length" "4")
255 (set_attr "pool_range" "250")])
9c08d1fa 256
9888ad6d 257; Load scheduling, set from the arm_ld_sched variable
4c834714 258; initialized by arm_option_override()
9888ad6d 259(define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
849170fd 260
f7fbdd4a 261; condition codes: this one is used by final_prescan_insn to speed up
262; conditionalizing instructions. It saves having to scan the rtl to see if
263; it uses or alters the condition codes.
215b30b3 264;
f7fbdd4a 265; USE means that the condition codes are used by the insn in the process of
215b30b3 266; outputting code, this means (at present) that we can't use the insn in
267; inlined branches
268;
f7fbdd4a 269; SET means that the purpose of the insn is to set the condition codes in a
215b30b3 270; well defined manner.
271;
f7fbdd4a 272; CLOB means that the condition codes are altered in an undefined manner, if
215b30b3 273; they are altered at all
274;
ad6d3e2a 275; UNCONDITIONAL means the instruction can not be conditionally executed and
276; that the instruction does not use or alter the condition codes.
c52acdd2 277;
ad6d3e2a 278; NOCOND means that the instruction does not use or alter the condition
279; codes but can be converted into a conditionally exectuted instruction.
f7fbdd4a 280
b0694be0 281(define_attr "conds" "use,set,clob,unconditional,nocond"
747b7458 282 (if_then_else
283 (ior (eq_attr "is_thumb1" "yes")
284 (eq_attr "type" "call"))
c1a66faf 285 (const_string "clob")
32093010 286 (if_then_else (eq_attr "is_neon_type" "no")
52432540 287 (const_string "nocond")
288 (const_string "unconditional"))))
f7fbdd4a 289
215b30b3 290; Predicable means that the insn can be conditionally executed based on
291; an automatically added predicate (additional patterns are generated by
292; gen...). We default to 'no' because no Thumb patterns match this rule
293; and not all ARM patterns do.
0d66636f 294(define_attr "predicable" "no,yes" (const_string "no"))
295
129a2fe4 296; Only model the write buffer for ARM6 and ARM7. Earlier processors don't
297; have one. Later ones, such as StrongARM, have write-back caches, so don't
8d232dc7 298; suffer blockages enough to warrant modelling this (and it can adversely
129a2fe4 299; affect the schedule).
74a71f7d 300(define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_tune_wbuf")))
129a2fe4 301
215b30b3 302; WRITE_CONFLICT implies that a read following an unrelated write is likely
303; to stall the processor. Used with model_wbuf above.
9c08d1fa 304(define_attr "write_conflict" "no,yes"
305 (if_then_else (eq_attr "type"
96854199 306 "block,call,load1")
9c08d1fa 307 (const_string "yes")
308 (const_string "no")))
309
215b30b3 310; Classify the insns into those that take one cycle and those that take more
311; than one on the main cpu execution unit.
f7fbdd4a 312(define_attr "core_cycles" "single,multi"
313 (if_then_else (eq_attr "type"
112eda6f 314 "adc_imm, adc_reg, adcs_imm, adcs_reg, adr, alu_ext, alu_imm, alu_sreg,\
315 alu_shift_imm, alu_shift_reg, alu_dsp_reg, alus_ext, alus_imm, alus_sreg,\
d82e788e 316 alus_shift_imm, alus_shift_reg, bfm, csel, rev, logic_imm, logic_reg,\
317 logic_shift_imm, logic_shift_reg, logics_imm, logics_reg,\
318 logics_shift_imm, logics_shift_reg, extend, shift_imm, float, fcsel,\
7cb6c048 319 wmmx_wor, wmmx_wxor, wmmx_wand, wmmx_wandn, wmmx_wmov, wmmx_tmcrr,\
320 wmmx_tmrrc, wmmx_wldr, wmmx_wstr, wmmx_tmcr, wmmx_tmrc, wmmx_wadd,\
321 wmmx_wsub, wmmx_wmul, wmmx_wmac, wmmx_wavg2, wmmx_tinsr, wmmx_textrm,\
322 wmmx_wshufh, wmmx_wcmpeq, wmmx_wcmpgt, wmmx_wmax, wmmx_wmin, wmmx_wpack,\
323 wmmx_wunpckih, wmmx_wunpckil, wmmx_wunpckeh, wmmx_wunpckel, wmmx_wror,\
324 wmmx_wsra, wmmx_wsrl, wmmx_wsll, wmmx_wmadd, wmmx_tmia, wmmx_tmiaph,\
325 wmmx_tmiaxy, wmmx_tbcst, wmmx_tmovmsk, wmmx_wacc, wmmx_waligni,\
326 wmmx_walignr, wmmx_tandc, wmmx_textrc, wmmx_torc, wmmx_torvsc, wmmx_wsad,\
327 wmmx_wabs, wmmx_wabsdiff, wmmx_waddsubhx, wmmx_wsubaddhx, wmmx_wavg4,\
328 wmmx_wmulw, wmmx_wqmulm, wmmx_wqmulwm, wmmx_waddbhus, wmmx_wqmiaxy,\
329 wmmx_wmiaxy, wmmx_wmiawxy, wmmx_wmerge")
f7fbdd4a 330 (const_string "single")
331 (const_string "multi")))
332
cffb2a26 333;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
215b30b3 334;; distant label. Only applicable to Thumb code.
cffb2a26 335(define_attr "far_jump" "yes,no" (const_string "no"))
336
d51f92df 337
25f905c2 338;; The number of machine instructions this pattern expands to.
339;; Used for Thumb-2 conditional execution.
340(define_attr "ce_count" "" (const_int 1))
341
4182b724 342;;---------------------------------------------------------------------------
343;; Unspecs
344
345(include "unspecs.md")
346
d51f92df 347;;---------------------------------------------------------------------------
fd781bb2 348;; Mode iterators
d51f92df 349
3de0dec6 350(include "iterators.md")
03770691 351
d51f92df 352;;---------------------------------------------------------------------------
353;; Predicates
354
9c9db025 355(include "predicates.md")
234f6557 356(include "constraints.md")
9c9db025 357
a2cd141b 358;;---------------------------------------------------------------------------
359;; Pipeline descriptions
215b30b3 360
e3879fd0 361(define_attr "tune_cortexr4" "yes,no"
362 (const (if_then_else
7d3cda8c 363 (eq_attr "tune" "cortexr4,cortexr4f,cortexr5")
e3879fd0 364 (const_string "yes")
365 (const_string "no"))))
366
a2cd141b 367;; True if the generic scheduling description should be used.
368
369(define_attr "generic_sched" "yes,no"
2546d93a 370 (const (if_then_else
e18862f3 371 (ior (eq_attr "tune" "fa526,fa626,fa606te,fa626te,fmp626,fa726te,\
372 arm926ejs,arm1020e,arm1026ejs,arm1136js,\
373 arm1136jfs,cortexa5,cortexa7,cortexa8,\
42e7b263 374 cortexa9,cortexa12,cortexa15,cortexa17,\
55a94dda 375 cortexa53,cortexm4,cortexm7,marvell_pj4,\
376 xgene1")
2546d93a 377 (eq_attr "tune_cortexr4" "yes"))
4d5cb40d 378 (const_string "no")
379 (const_string "yes"))))
380
c0e1af52 381(define_attr "generic_vfp" "yes,no"
382 (const (if_then_else
383 (and (eq_attr "fpu" "vfp")
e18862f3 384 (eq_attr "tune" "!arm1020e,arm1022e,cortexa5,cortexa7,\
385 cortexa8,cortexa9,cortexa53,cortexm4,\
55a94dda 386 cortexm7,marvell_pj4,xgene1")
e3879fd0 387 (eq_attr "tune_cortexr4" "no"))
c0e1af52 388 (const_string "yes")
389 (const_string "no"))))
390
6b8f7c28 391(include "marvell-f-iwmmxt.md")
a2cd141b 392(include "arm-generic.md")
393(include "arm926ejs.md")
c0e1af52 394(include "arm1020e.md")
a2cd141b 395(include "arm1026ejs.md")
396(include "arm1136jfs.md")
0e266d06 397(include "fa526.md")
398(include "fa606te.md")
399(include "fa626te.md")
400(include "fmp626.md")
401(include "fa726te.md")
3f1e069f 402(include "cortex-a5.md")
d6b7f019 403(include "cortex-a7.md")
bcaec148 404(include "cortex-a8.md")
036068af 405(include "cortex-a9.md")
65f2f758 406(include "cortex-a15.md")
42e7b263 407(include "cortex-a17.md")
da10bc87 408(include "cortex-a53.md")
934a1e72 409(include "cortex-r4.md")
e3879fd0 410(include "cortex-r4f.md")
e18862f3 411(include "cortex-m7.md")
2546d93a 412(include "cortex-m4.md")
413(include "cortex-m4-fpu.md")
55e3ada8 414(include "vfp11.md")
ea7d210b 415(include "marvell-pj4.md")
55a94dda 416(include "xgene1.md")
3586df96 417
9c08d1fa 418\f
215b30b3 419;;---------------------------------------------------------------------------
e1159bbe 420;; Insn patterns
421;;
a0f94409 422;; Addition insns.
215b30b3 423
9c08d1fa 424;; Note: For DImode insns, there is normally no reason why operands should
425;; not be in the same register, what we don't want is for something being
426;; written to partially overlap something that is an input.
427
cffb2a26 428(define_expand "adddi3"
429 [(parallel
215b30b3 430 [(set (match_operand:DI 0 "s_register_operand" "")
cffb2a26 431 (plus:DI (match_operand:DI 1 "s_register_operand" "")
10e5ccd5 432 (match_operand:DI 2 "arm_adddi_operand" "")))
bd5b4116 433 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 434 "TARGET_EITHER"
435 "
25f905c2 436 if (TARGET_THUMB1)
cffb2a26 437 {
0438d37f 438 if (!REG_P (operands[1]))
bc5a93af 439 operands[1] = force_reg (DImode, operands[1]);
0438d37f 440 if (!REG_P (operands[2]))
bc5a93af 441 operands[2] = force_reg (DImode, operands[2]);
cffb2a26 442 }
443 "
444)
445
a0f94409 446(define_insn_and_split "*arm_adddi3"
10e5ccd5 447 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r,&r,&r")
448 (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0, r, 0, r")
449 (match_operand:DI 2 "arm_adddi_operand" "r, 0, r, Dd, Dd")))
bd5b4116 450 (clobber (reg:CC CC_REGNUM))]
b805622c 451 "TARGET_32BIT && !TARGET_NEON"
33782ec7 452 "#"
94829feb 453 "TARGET_32BIT && reload_completed
454 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))"
a0f94409 455 [(parallel [(set (reg:CC_C CC_REGNUM)
456 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
457 (match_dup 1)))
458 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 459 (set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (match_dup 5))
460 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
a0f94409 461 "
462 {
463 operands[3] = gen_highpart (SImode, operands[0]);
464 operands[0] = gen_lowpart (SImode, operands[0]);
465 operands[4] = gen_highpart (SImode, operands[1]);
466 operands[1] = gen_lowpart (SImode, operands[1]);
10e5ccd5 467 operands[5] = gen_highpart_mode (SImode, DImode, operands[2]);
a0f94409 468 operands[2] = gen_lowpart (SImode, operands[2]);
469 }"
cffb2a26 470 [(set_attr "conds" "clob")
1b7da4ac 471 (set_attr "length" "8")
472 (set_attr "type" "multiple")]
cffb2a26 473)
9c08d1fa 474
a0f94409 475(define_insn_and_split "*adddi_sesidi_di"
9c08d1fa 476 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
477 (plus:DI (sign_extend:DI
97499065 478 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 479 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 480 (clobber (reg:CC CC_REGNUM))]
b805622c 481 "TARGET_32BIT"
33782ec7 482 "#"
25f905c2 483 "TARGET_32BIT && reload_completed"
a0f94409 484 [(parallel [(set (reg:CC_C CC_REGNUM)
485 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
486 (match_dup 1)))
487 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 488 (set (match_dup 3) (plus:SI (plus:SI (ashiftrt:SI (match_dup 2)
a0f94409 489 (const_int 31))
080c0b9a 490 (match_dup 4))
491 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
a0f94409 492 "
493 {
494 operands[3] = gen_highpart (SImode, operands[0]);
495 operands[0] = gen_lowpart (SImode, operands[0]);
496 operands[4] = gen_highpart (SImode, operands[1]);
497 operands[1] = gen_lowpart (SImode, operands[1]);
498 operands[2] = gen_lowpart (SImode, operands[2]);
499 }"
215b30b3 500 [(set_attr "conds" "clob")
1b7da4ac 501 (set_attr "length" "8")
502 (set_attr "type" "multiple")]
215b30b3 503)
9c08d1fa 504
a0f94409 505(define_insn_and_split "*adddi_zesidi_di"
9c08d1fa 506 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
507 (plus:DI (zero_extend:DI
97499065 508 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 509 (match_operand:DI 1 "s_register_operand" "0,r")))
a0f94409 510 (clobber (reg:CC CC_REGNUM))]
b805622c 511 "TARGET_32BIT"
33782ec7 512 "#"
25f905c2 513 "TARGET_32BIT && reload_completed"
a0f94409 514 [(parallel [(set (reg:CC_C CC_REGNUM)
515 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
516 (match_dup 1)))
517 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 518 (set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (const_int 0))
519 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
a0f94409 520 "
521 {
522 operands[3] = gen_highpart (SImode, operands[0]);
523 operands[0] = gen_lowpart (SImode, operands[0]);
524 operands[4] = gen_highpart (SImode, operands[1]);
525 operands[1] = gen_lowpart (SImode, operands[1]);
526 operands[2] = gen_lowpart (SImode, operands[2]);
527 }"
cffb2a26 528 [(set_attr "conds" "clob")
1b7da4ac 529 (set_attr "length" "8")
530 (set_attr "type" "multiple")]
cffb2a26 531)
b11cae9e 532
87b22bf7 533(define_expand "addsi3"
cffb2a26 534 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 535 (plus:SI (match_operand:SI 1 "s_register_operand" "")
536 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 537 "TARGET_EITHER"
87b22bf7 538 "
0438d37f 539 if (TARGET_32BIT && CONST_INT_P (operands[2]))
87b22bf7 540 {
96f57e36 541 arm_split_constant (PLUS, SImode, NULL_RTX,
542 INTVAL (operands[2]), operands[0], operands[1],
e1ba4a27 543 optimize && can_create_pseudo_p ());
87b22bf7 544 DONE;
545 }
cffb2a26 546 "
547)
87b22bf7 548
5bd751ff 549; If there is a scratch available, this will be faster than synthesizing the
a0f94409 550; addition.
551(define_peephole2
552 [(match_scratch:SI 3 "r")
372575c7 553 (set (match_operand:SI 0 "arm_general_register_operand" "")
554 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
cffb2a26 555 (match_operand:SI 2 "const_int_operand" "")))]
25f905c2 556 "TARGET_32BIT &&
a0f94409 557 !(const_ok_for_arm (INTVAL (operands[2]))
558 || const_ok_for_arm (-INTVAL (operands[2])))
559 && const_ok_for_arm (~INTVAL (operands[2]))"
560 [(set (match_dup 3) (match_dup 2))
561 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
562 ""
563)
87b22bf7 564
2f02c19f 565;; The r/r/k alternative is required when reloading the address
566;; (plus (reg rN) (reg sp)) into (reg rN). In this case reload will
567;; put the duplicated register first, and not try the commutative version.
a0f94409 568(define_insn_and_split "*arm_addsi3"
7c36fe71 569 [(set (match_operand:SI 0 "s_register_operand" "=rk,l,l ,l ,r ,k ,r,r ,k ,r ,k,k,r ,k ,r")
570 (plus:SI (match_operand:SI 1 "s_register_operand" "%0 ,l,0 ,l ,rk,k ,r,rk,k ,rk,k,r,rk,k ,rk")
571 (match_operand:SI 2 "reg_or_int_operand" "rk ,l,Py,Pd,rI,rI,k,Pj,Pj,L ,L,L,PJ,PJ,?n")))]
25f905c2 572 "TARGET_32BIT"
5565501b 573 "@
c24d855d 574 add%?\\t%0, %0, %2
5565501b 575 add%?\\t%0, %1, %2
a0b3420a 576 add%?\\t%0, %1, %2
7c36fe71 577 add%?\\t%0, %1, %2
578 add%?\\t%0, %1, %2
aaa37ad6 579 add%?\\t%0, %1, %2
2f02c19f 580 add%?\\t%0, %2, %1
d5cbae34 581 addw%?\\t%0, %1, %2
582 addw%?\\t%0, %1, %2
aaa37ad6 583 sub%?\\t%0, %1, #%n2
87b22bf7 584 sub%?\\t%0, %1, #%n2
d7757711 585 sub%?\\t%0, %1, #%n2
d5cbae34 586 subw%?\\t%0, %1, #%n2
587 subw%?\\t%0, %1, #%n2
87b22bf7 588 #"
a3ffc315 589 "TARGET_32BIT
0438d37f 590 && CONST_INT_P (operands[2])
d5cbae34 591 && !const_ok_for_op (INTVAL (operands[2]), PLUS)
a3ffc315 592 && (reload_completed || !arm_eliminable_register (operands[1]))"
a0f94409 593 [(clobber (const_int 0))]
594 "
96f57e36 595 arm_split_constant (PLUS, SImode, curr_insn,
596 INTVAL (operands[2]), operands[0],
a0f94409 597 operands[1], 0);
598 DONE;
599 "
7c36fe71 600 [(set_attr "length" "2,4,4,4,4,4,4,4,4,4,4,4,4,4,16")
d5cbae34 601 (set_attr "predicable" "yes")
7c36fe71 602 (set_attr "predicable_short_it" "yes,yes,yes,yes,no,no,no,no,no,no,no,no,no,no,no")
603 (set_attr "arch" "t2,t2,t2,t2,*,*,*,t2,t2,*,*,a,t2,t2,*")
65f68e55 604 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
d82e788e 605 (const_string "alu_imm")
112eda6f 606 (const_string "alu_sreg")))
65f68e55 607 ]
cffb2a26 608)
609
90c2bcf0 610(define_insn "addsi3_compare0"
bd5b4116 611 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 612 (compare:CC_NOOV
65f68e55 613 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r,r")
614 (match_operand:SI 2 "arm_add_operand" "I,L,r"))
5565501b 615 (const_int 0)))
65f68e55 616 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9c08d1fa 617 (plus:SI (match_dup 1) (match_dup 2)))]
ec792a7b 618 "TARGET_ARM"
5565501b 619 "@
25f905c2 620 add%.\\t%0, %1, %2
65f68e55 621 sub%.\\t%0, %1, #%n2
622 add%.\\t%0, %1, %2"
623 [(set_attr "conds" "set")
112eda6f 624 (set_attr "type" "alus_imm,alus_imm,alus_sreg")]
cffb2a26 625)
9c08d1fa 626
aea4c774 627(define_insn "*addsi3_compare0_scratch"
bd5b4116 628 [(set (reg:CC_NOOV CC_REGNUM)
aea4c774 629 (compare:CC_NOOV
65f68e55 630 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r, r")
631 (match_operand:SI 1 "arm_add_operand" "I,L, r"))
aea4c774 632 (const_int 0)))]
ec792a7b 633 "TARGET_ARM"
cffb2a26 634 "@
635 cmn%?\\t%0, %1
65f68e55 636 cmp%?\\t%0, #%n1
637 cmn%?\\t%0, %1"
596e5e8f 638 [(set_attr "conds" "set")
65f68e55 639 (set_attr "predicable" "yes")
112eda6f 640 (set_attr "type" "alus_imm,alus_imm,alus_sreg")]
0d66636f 641)
cffb2a26 642
aed179ae 643(define_insn "*compare_negsi_si"
644 [(set (reg:CC_Z CC_REGNUM)
645 (compare:CC_Z
7c36fe71 646 (neg:SI (match_operand:SI 0 "s_register_operand" "l,r"))
647 (match_operand:SI 1 "s_register_operand" "l,r")))]
25f905c2 648 "TARGET_32BIT"
aed179ae 649 "cmn%?\\t%1, %0"
596e5e8f 650 [(set_attr "conds" "set")
7c36fe71 651 (set_attr "predicable" "yes")
652 (set_attr "arch" "t2,*")
653 (set_attr "length" "2,4")
1b7da4ac 654 (set_attr "predicable_short_it" "yes,no")
112eda6f 655 (set_attr "type" "alus_sreg")]
0d66636f 656)
aea4c774 657
203c488f 658;; This is the canonicalization of addsi3_compare0_for_combiner when the
659;; addend is a constant.
190efb17 660(define_insn "cmpsi2_addneg"
203c488f 661 [(set (reg:CC CC_REGNUM)
662 (compare:CC
663 (match_operand:SI 1 "s_register_operand" "r,r")
2a977b78 664 (match_operand:SI 2 "arm_addimm_operand" "L,I")))
203c488f 665 (set (match_operand:SI 0 "s_register_operand" "=r,r")
666 (plus:SI (match_dup 1)
2a977b78 667 (match_operand:SI 3 "arm_addimm_operand" "I,L")))]
25f905c2 668 "TARGET_32BIT && INTVAL (operands[2]) == -INTVAL (operands[3])"
203c488f 669 "@
2a977b78 670 add%.\\t%0, %1, %3
671 sub%.\\t%0, %1, #%n3"
1b7da4ac 672 [(set_attr "conds" "set")
112eda6f 673 (set_attr "type" "alus_sreg")]
203c488f 674)
675
676;; Convert the sequence
677;; sub rd, rn, #1
678;; cmn rd, #1 (equivalent to cmp rd, #-1)
679;; bne dest
680;; into
681;; subs rd, rn, #1
682;; bcs dest ((unsigned)rn >= 1)
683;; similarly for the beq variant using bcc.
684;; This is a common looping idiom (while (n--))
685(define_peephole2
372575c7 686 [(set (match_operand:SI 0 "arm_general_register_operand" "")
687 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
203c488f 688 (const_int -1)))
689 (set (match_operand 2 "cc_register" "")
690 (compare (match_dup 0) (const_int -1)))
691 (set (pc)
692 (if_then_else (match_operator 3 "equality_operator"
693 [(match_dup 2) (const_int 0)])
694 (match_operand 4 "" "")
695 (match_operand 5 "" "")))]
25f905c2 696 "TARGET_32BIT && peep2_reg_dead_p (3, operands[2])"
203c488f 697 [(parallel[
698 (set (match_dup 2)
699 (compare:CC
700 (match_dup 1) (const_int 1)))
701 (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
702 (set (pc)
703 (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
704 (match_dup 4)
705 (match_dup 5)))]
706 "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
707 operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
708 ? GEU : LTU),
709 VOIDmode,
710 operands[2], const0_rtx);"
711)
712
ebcc79bc 713;; The next four insns work because they compare the result with one of
714;; the operands, and we know that the use of the condition code is
715;; either GEU or LTU, so we can use the carry flag from the addition
716;; instead of doing the compare a second time.
717(define_insn "*addsi3_compare_op1"
bd5b4116 718 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 719 (compare:CC_C
65f68e55 720 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
721 (match_operand:SI 2 "arm_add_operand" "I,L,r"))
ebcc79bc 722 (match_dup 1)))
65f68e55 723 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
ebcc79bc 724 (plus:SI (match_dup 1) (match_dup 2)))]
25f905c2 725 "TARGET_32BIT"
ebcc79bc 726 "@
25f905c2 727 add%.\\t%0, %1, %2
65f68e55 728 sub%.\\t%0, %1, #%n2
729 add%.\\t%0, %1, %2"
730 [(set_attr "conds" "set")
112eda6f 731 (set_attr "type" "alus_imm,alus_imm,alus_sreg")]
0d66636f 732)
ebcc79bc 733
734(define_insn "*addsi3_compare_op2"
bd5b4116 735 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 736 (compare:CC_C
65f68e55 737 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
738 (match_operand:SI 2 "arm_add_operand" "I,L,r"))
ebcc79bc 739 (match_dup 2)))
65f68e55 740 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9c08d1fa 741 (plus:SI (match_dup 1) (match_dup 2)))]
25f905c2 742 "TARGET_32BIT"
5565501b 743 "@
65f68e55 744 add%.\\t%0, %1, %2
25f905c2 745 add%.\\t%0, %1, %2
746 sub%.\\t%0, %1, #%n2"
65f68e55 747 [(set_attr "conds" "set")
112eda6f 748 (set_attr "type" "alus_imm,alus_imm,alus_sreg")]
0d66636f 749)
9c08d1fa 750
ebcc79bc 751(define_insn "*compare_addsi2_op0"
bd5b4116 752 [(set (reg:CC_C CC_REGNUM)
7c36fe71 753 (compare:CC_C
754 (plus:SI (match_operand:SI 0 "s_register_operand" "l,l,r,r,r")
755 (match_operand:SI 1 "arm_add_operand" "Pv,l,I,L,r"))
756 (match_dup 0)))]
25f905c2 757 "TARGET_32BIT"
ebcc79bc 758 "@
7c36fe71 759 cmp%?\\t%0, #%n1
760 cmn%?\\t%0, %1
ebcc79bc 761 cmn%?\\t%0, %1
65f68e55 762 cmp%?\\t%0, #%n1
763 cmn%?\\t%0, %1"
596e5e8f 764 [(set_attr "conds" "set")
65f68e55 765 (set_attr "predicable" "yes")
7c36fe71 766 (set_attr "arch" "t2,t2,*,*,*")
767 (set_attr "predicable_short_it" "yes,yes,no,no,no")
768 (set_attr "length" "2,2,4,4,4")
112eda6f 769 (set_attr "type" "alus_imm,alus_sreg,alus_imm,alus_imm,alus_sreg")]
0d66636f 770)
ebcc79bc 771
772(define_insn "*compare_addsi2_op1"
bd5b4116 773 [(set (reg:CC_C CC_REGNUM)
7c36fe71 774 (compare:CC_C
775 (plus:SI (match_operand:SI 0 "s_register_operand" "l,l,r,r,r")
776 (match_operand:SI 1 "arm_add_operand" "Pv,l,I,L,r"))
777 (match_dup 1)))]
25f905c2 778 "TARGET_32BIT"
ebcc79bc 779 "@
7c36fe71 780 cmp%?\\t%0, #%n1
781 cmn%?\\t%0, %1
ebcc79bc 782 cmn%?\\t%0, %1
65f68e55 783 cmp%?\\t%0, #%n1
784 cmn%?\\t%0, %1"
596e5e8f 785 [(set_attr "conds" "set")
65f68e55 786 (set_attr "predicable" "yes")
7c36fe71 787 (set_attr "arch" "t2,t2,*,*,*")
788 (set_attr "predicable_short_it" "yes,yes,no,no,no")
789 (set_attr "length" "2,2,4,4,4")
112eda6f 790 (set_attr "type" "alus_imm,alus_sreg,alus_imm,alus_imm,alus_sreg")]
7c36fe71 791 )
ebcc79bc 792
080c0b9a 793(define_insn "*addsi3_carryin_<optab>"
7c36fe71 794 [(set (match_operand:SI 0 "s_register_operand" "=l,r,r")
795 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%l,r,r")
796 (match_operand:SI 2 "arm_not_operand" "0,rI,K"))
797 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))]
25f905c2 798 "TARGET_32BIT"
10e5ccd5 799 "@
a0b3420a 800 adc%?\\t%0, %1, %2
10e5ccd5 801 adc%?\\t%0, %1, %2
802 sbc%?\\t%0, %1, #%B2"
a7de272d 803 [(set_attr "conds" "use")
7c36fe71 804 (set_attr "predicable" "yes")
805 (set_attr "arch" "t2,*,*")
806 (set_attr "length" "4")
1b7da4ac 807 (set_attr "predicable_short_it" "yes,no,no")
808 (set_attr "type" "adc_reg,adc_reg,adc_imm")]
cffb2a26 809)
ebcc79bc 810
080c0b9a 811(define_insn "*addsi3_carryin_alt2_<optab>"
7c36fe71 812 [(set (match_operand:SI 0 "s_register_operand" "=l,r,r")
813 (plus:SI (plus:SI (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))
814 (match_operand:SI 1 "s_register_operand" "%l,r,r"))
815 (match_operand:SI 2 "arm_rhs_operand" "l,rI,K")))]
25f905c2 816 "TARGET_32BIT"
10e5ccd5 817 "@
a0b3420a 818 adc%?\\t%0, %1, %2
10e5ccd5 819 adc%?\\t%0, %1, %2
820 sbc%?\\t%0, %1, #%B2"
a7de272d 821 [(set_attr "conds" "use")
7c36fe71 822 (set_attr "predicable" "yes")
823 (set_attr "arch" "t2,*,*")
824 (set_attr "length" "4")
1b7da4ac 825 (set_attr "predicable_short_it" "yes,no,no")
826 (set_attr "type" "adc_reg,adc_reg,adc_imm")]
0d66636f 827)
ebcc79bc 828
080c0b9a 829(define_insn "*addsi3_carryin_shift_<optab>"
ebcc79bc 830 [(set (match_operand:SI 0 "s_register_operand" "=r")
080c0b9a 831 (plus:SI (plus:SI
832 (match_operator:SI 2 "shift_operator"
833 [(match_operand:SI 3 "s_register_operand" "r")
834 (match_operand:SI 4 "reg_or_int_operand" "rM")])
835 (match_operand:SI 1 "s_register_operand" "r"))
836 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))]
25f905c2 837 "TARGET_32BIT"
080c0b9a 838 "adc%?\\t%0, %1, %3%S2"
839 [(set_attr "conds" "use")
a7de272d 840 (set_attr "predicable" "yes")
7c36fe71 841 (set_attr "predicable_short_it" "no")
080c0b9a 842 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
d82e788e 843 (const_string "alu_shift_imm")
844 (const_string "alu_shift_reg")))]
cffb2a26 845)
ebcc79bc 846
922b6913 847(define_insn "*addsi3_carryin_clobercc_<optab>"
848 [(set (match_operand:SI 0 "s_register_operand" "=r")
849 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%r")
850 (match_operand:SI 2 "arm_rhs_operand" "rI"))
851 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))
852 (clobber (reg:CC CC_REGNUM))]
853 "TARGET_32BIT"
854 "adc%.\\t%0, %1, %2"
1b7da4ac 855 [(set_attr "conds" "set")
856 (set_attr "type" "adcs_reg")]
922b6913 857)
858
9154bd82 859(define_insn "*subsi3_carryin"
860 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
861 (minus:SI (minus:SI (match_operand:SI 1 "reg_or_int_operand" "r,I")
862 (match_operand:SI 2 "s_register_operand" "r,r"))
863 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
864 "TARGET_32BIT"
865 "@
866 sbc%?\\t%0, %1, %2
867 rsc%?\\t%0, %2, %1"
868 [(set_attr "conds" "use")
869 (set_attr "arch" "*,a")
7c36fe71 870 (set_attr "predicable" "yes")
1b7da4ac 871 (set_attr "predicable_short_it" "no")
872 (set_attr "type" "adc_reg,adc_imm")]
9154bd82 873)
874
875(define_insn "*subsi3_carryin_const"
876 [(set (match_operand:SI 0 "s_register_operand" "=r")
877 (minus:SI (plus:SI (match_operand:SI 1 "reg_or_int_operand" "r")
878 (match_operand:SI 2 "arm_not_operand" "K"))
879 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
880 "TARGET_32BIT"
881 "sbc\\t%0, %1, #%B2"
1b7da4ac 882 [(set_attr "conds" "use")
883 (set_attr "type" "adc_imm")]
9154bd82 884)
885
886(define_insn "*subsi3_carryin_compare"
887 [(set (reg:CC CC_REGNUM)
888 (compare:CC (match_operand:SI 1 "s_register_operand" "r")
889 (match_operand:SI 2 "s_register_operand" "r")))
890 (set (match_operand:SI 0 "s_register_operand" "=r")
891 (minus:SI (minus:SI (match_dup 1)
892 (match_dup 2))
893 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
894 "TARGET_32BIT"
895 "sbcs\\t%0, %1, %2"
1b7da4ac 896 [(set_attr "conds" "set")
897 (set_attr "type" "adcs_reg")]
9154bd82 898)
899
900(define_insn "*subsi3_carryin_compare_const"
901 [(set (reg:CC CC_REGNUM)
902 (compare:CC (match_operand:SI 1 "reg_or_int_operand" "r")
903 (match_operand:SI 2 "arm_not_operand" "K")))
904 (set (match_operand:SI 0 "s_register_operand" "=r")
905 (minus:SI (plus:SI (match_dup 1)
906 (match_dup 2))
907 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
908 "TARGET_32BIT"
909 "sbcs\\t%0, %1, #%B2"
1b7da4ac 910 [(set_attr "conds" "set")
911 (set_attr "type" "adcs_imm")]
9154bd82 912)
913
914(define_insn "*subsi3_carryin_shift"
915 [(set (match_operand:SI 0 "s_register_operand" "=r")
916 (minus:SI (minus:SI
917 (match_operand:SI 1 "s_register_operand" "r")
918 (match_operator:SI 2 "shift_operator"
919 [(match_operand:SI 3 "s_register_operand" "r")
920 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
921 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
922 "TARGET_32BIT"
923 "sbc%?\\t%0, %1, %3%S2"
924 [(set_attr "conds" "use")
925 (set_attr "predicable" "yes")
926 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
d82e788e 927 (const_string "alu_shift_imm")
928 (const_string "alu_shift_reg")))]
9154bd82 929)
930
931(define_insn "*rsbsi3_carryin_shift"
932 [(set (match_operand:SI 0 "s_register_operand" "=r")
933 (minus:SI (minus:SI
934 (match_operator:SI 2 "shift_operator"
935 [(match_operand:SI 3 "s_register_operand" "r")
936 (match_operand:SI 4 "reg_or_int_operand" "rM")])
937 (match_operand:SI 1 "s_register_operand" "r"))
938 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
939 "TARGET_ARM"
940 "rsc%?\\t%0, %1, %3%S2"
941 [(set_attr "conds" "use")
942 (set_attr "predicable" "yes")
943 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
d82e788e 944 (const_string "alu_shift_imm")
945 (const_string "alu_shift_reg")))]
9154bd82 946)
947
d795fb69 948; transform ((x << y) - 1) to ~(~(x-1) << y) Where X is a constant.
949(define_split
950 [(set (match_operand:SI 0 "s_register_operand" "")
951 (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
952 (match_operand:SI 2 "s_register_operand" ""))
953 (const_int -1)))
954 (clobber (match_operand:SI 3 "s_register_operand" ""))]
25f905c2 955 "TARGET_32BIT"
d795fb69 956 [(set (match_dup 3) (match_dup 1))
957 (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
958 "
959 operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
960")
961
604f3a0a 962(define_expand "addsf3"
963 [(set (match_operand:SF 0 "s_register_operand" "")
964 (plus:SF (match_operand:SF 1 "s_register_operand" "")
d86c91f6 965 (match_operand:SF 2 "s_register_operand" "")))]
25f905c2 966 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 967 "
604f3a0a 968")
969
604f3a0a 970(define_expand "adddf3"
971 [(set (match_operand:DF 0 "s_register_operand" "")
972 (plus:DF (match_operand:DF 1 "s_register_operand" "")
d86c91f6 973 (match_operand:DF 2 "s_register_operand" "")))]
a50d7267 974 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 975 "
604f3a0a 976")
977
cffb2a26 978(define_expand "subdi3"
979 [(parallel
980 [(set (match_operand:DI 0 "s_register_operand" "")
981 (minus:DI (match_operand:DI 1 "s_register_operand" "")
982 (match_operand:DI 2 "s_register_operand" "")))
bd5b4116 983 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 984 "TARGET_EITHER"
985 "
25f905c2 986 if (TARGET_THUMB1)
cffb2a26 987 {
0438d37f 988 if (!REG_P (operands[1]))
5aa8c5f0 989 operands[1] = force_reg (DImode, operands[1]);
0438d37f 990 if (!REG_P (operands[2]))
5aa8c5f0 991 operands[2] = force_reg (DImode, operands[2]);
cffb2a26 992 }
993 "
994)
995
2f9b23e3 996(define_insn_and_split "*arm_subdi3"
cffb2a26 997 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
9c08d1fa 998 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
999 (match_operand:DI 2 "s_register_operand" "r,0,0")))
bd5b4116 1000 (clobber (reg:CC CC_REGNUM))]
94829feb 1001 "TARGET_32BIT && !TARGET_NEON"
2f9b23e3 1002 "#" ; "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
1003 "&& reload_completed"
1004 [(parallel [(set (reg:CC CC_REGNUM)
1005 (compare:CC (match_dup 1) (match_dup 2)))
1006 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1007 (set (match_dup 3) (minus:SI (minus:SI (match_dup 4) (match_dup 5))
1008 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1009 {
1010 operands[3] = gen_highpart (SImode, operands[0]);
1011 operands[0] = gen_lowpart (SImode, operands[0]);
1012 operands[4] = gen_highpart (SImode, operands[1]);
1013 operands[1] = gen_lowpart (SImode, operands[1]);
1014 operands[5] = gen_highpart (SImode, operands[2]);
1015 operands[2] = gen_lowpart (SImode, operands[2]);
1016 }
cffb2a26 1017 [(set_attr "conds" "clob")
1b7da4ac 1018 (set_attr "length" "8")
1019 (set_attr "type" "multiple")]
cffb2a26 1020)
1021
2f9b23e3 1022(define_insn_and_split "*subdi_di_zesidi"
cffb2a26 1023 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 1024 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r")
9c08d1fa 1025 (zero_extend:DI
cffb2a26 1026 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 1027 (clobber (reg:CC CC_REGNUM))]
25f905c2 1028 "TARGET_32BIT"
2f9b23e3 1029 "#" ; "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
1030 "&& reload_completed"
1031 [(parallel [(set (reg:CC CC_REGNUM)
1032 (compare:CC (match_dup 1) (match_dup 2)))
1033 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1034 (set (match_dup 3) (minus:SI (plus:SI (match_dup 4) (match_dup 5))
1035 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1036 {
1037 operands[3] = gen_highpart (SImode, operands[0]);
1038 operands[0] = gen_lowpart (SImode, operands[0]);
1039 operands[4] = gen_highpart (SImode, operands[1]);
1040 operands[1] = gen_lowpart (SImode, operands[1]);
1041 operands[5] = GEN_INT (~0);
1042 }
cffb2a26 1043 [(set_attr "conds" "clob")
1b7da4ac 1044 (set_attr "length" "8")
1045 (set_attr "type" "multiple")]
cffb2a26 1046)
9c08d1fa 1047
2f9b23e3 1048(define_insn_and_split "*subdi_di_sesidi"
cffb2a26 1049 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 1050 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r")
9c08d1fa 1051 (sign_extend:DI
cffb2a26 1052 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 1053 (clobber (reg:CC CC_REGNUM))]
25f905c2 1054 "TARGET_32BIT"
2f9b23e3 1055 "#" ; "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
1056 "&& reload_completed"
1057 [(parallel [(set (reg:CC CC_REGNUM)
1058 (compare:CC (match_dup 1) (match_dup 2)))
1059 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1060 (set (match_dup 3) (minus:SI (minus:SI (match_dup 4)
1061 (ashiftrt:SI (match_dup 2)
1062 (const_int 31)))
1063 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1064 {
1065 operands[3] = gen_highpart (SImode, operands[0]);
1066 operands[0] = gen_lowpart (SImode, operands[0]);
1067 operands[4] = gen_highpart (SImode, operands[1]);
1068 operands[1] = gen_lowpart (SImode, operands[1]);
1069 }
cffb2a26 1070 [(set_attr "conds" "clob")
1b7da4ac 1071 (set_attr "length" "8")
1072 (set_attr "type" "multiple")]
cffb2a26 1073)
9c08d1fa 1074
2f9b23e3 1075(define_insn_and_split "*subdi_zesidi_di"
cffb2a26 1076 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1077 (minus:DI (zero_extend:DI
cffb2a26 1078 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 1079 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 1080 (clobber (reg:CC CC_REGNUM))]
cffb2a26 1081 "TARGET_ARM"
2f9b23e3 1082 "#" ; "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
1083 ; is equivalent to:
1084 ; "subs\\t%Q0, %2, %Q1\;rsc\\t%R0, %R1, #0"
1085 "&& reload_completed"
1086 [(parallel [(set (reg:CC CC_REGNUM)
1087 (compare:CC (match_dup 2) (match_dup 1)))
1088 (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))])
1089 (set (match_dup 3) (minus:SI (minus:SI (const_int 0) (match_dup 4))
1090 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1091 {
1092 operands[3] = gen_highpart (SImode, operands[0]);
1093 operands[0] = gen_lowpart (SImode, operands[0]);
1094 operands[4] = gen_highpart (SImode, operands[1]);
1095 operands[1] = gen_lowpart (SImode, operands[1]);
1096 }
cffb2a26 1097 [(set_attr "conds" "clob")
1b7da4ac 1098 (set_attr "length" "8")
1099 (set_attr "type" "multiple")]
cffb2a26 1100)
9c08d1fa 1101
2f9b23e3 1102(define_insn_and_split "*subdi_sesidi_di"
cffb2a26 1103 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1104 (minus:DI (sign_extend:DI
cffb2a26 1105 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 1106 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 1107 (clobber (reg:CC CC_REGNUM))]
cffb2a26 1108 "TARGET_ARM"
2f9b23e3 1109 "#" ; "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
1110 ; is equivalent to:
1111 ; "subs\\t%Q0, %2, %Q1\;rsc\\t%R0, %R1, %2, asr #31"
1112 "&& reload_completed"
1113 [(parallel [(set (reg:CC CC_REGNUM)
1114 (compare:CC (match_dup 2) (match_dup 1)))
1115 (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))])
1116 (set (match_dup 3) (minus:SI (minus:SI
1117 (ashiftrt:SI (match_dup 2)
1118 (const_int 31))
1119 (match_dup 4))
1120 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1121 {
1122 operands[3] = gen_highpart (SImode, operands[0]);
1123 operands[0] = gen_lowpart (SImode, operands[0]);
1124 operands[4] = gen_highpart (SImode, operands[1]);
1125 operands[1] = gen_lowpart (SImode, operands[1]);
1126 }
cffb2a26 1127 [(set_attr "conds" "clob")
1b7da4ac 1128 (set_attr "length" "8")
1129 (set_attr "type" "multiple")]
cffb2a26 1130)
9c08d1fa 1131
2f9b23e3 1132(define_insn_and_split "*subdi_zesidi_zesidi"
cffb2a26 1133 [(set (match_operand:DI 0 "s_register_operand" "=r")
9c08d1fa 1134 (minus:DI (zero_extend:DI
cffb2a26 1135 (match_operand:SI 1 "s_register_operand" "r"))
9c08d1fa 1136 (zero_extend:DI
cffb2a26 1137 (match_operand:SI 2 "s_register_operand" "r"))))
bd5b4116 1138 (clobber (reg:CC CC_REGNUM))]
25f905c2 1139 "TARGET_32BIT"
2f9b23e3 1140 "#" ; "subs\\t%Q0, %1, %2\;sbc\\t%R0, %1, %1"
1141 "&& reload_completed"
1142 [(parallel [(set (reg:CC CC_REGNUM)
1143 (compare:CC (match_dup 1) (match_dup 2)))
1144 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1145 (set (match_dup 3) (minus:SI (minus:SI (match_dup 1) (match_dup 1))
1146 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1147 {
1148 operands[3] = gen_highpart (SImode, operands[0]);
1149 operands[0] = gen_lowpart (SImode, operands[0]);
1150 }
cffb2a26 1151 [(set_attr "conds" "clob")
1b7da4ac 1152 (set_attr "length" "8")
1153 (set_attr "type" "multiple")]
cffb2a26 1154)
b11cae9e 1155
87b22bf7 1156(define_expand "subsi3"
cffb2a26 1157 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 1158 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
1159 (match_operand:SI 2 "s_register_operand" "")))]
cffb2a26 1160 "TARGET_EITHER"
87b22bf7 1161 "
0438d37f 1162 if (CONST_INT_P (operands[1]))
87b22bf7 1163 {
25f905c2 1164 if (TARGET_32BIT)
cffb2a26 1165 {
96f57e36 1166 arm_split_constant (MINUS, SImode, NULL_RTX,
1167 INTVAL (operands[1]), operands[0],
e1ba4a27 1168 operands[2], optimize && can_create_pseudo_p ());
cffb2a26 1169 DONE;
1170 }
25f905c2 1171 else /* TARGET_THUMB1 */
cffb2a26 1172 operands[1] = force_reg (SImode, operands[1]);
87b22bf7 1173 }
cffb2a26 1174 "
1175)
87b22bf7 1176
25f905c2 1177; ??? Check Thumb-2 split length
a0f94409 1178(define_insn_and_split "*arm_subsi3_insn"
7c36fe71 1179 [(set (match_operand:SI 0 "s_register_operand" "=l,l ,l ,l ,r ,r,r,rk,r")
1180 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "l ,0 ,l ,Pz,rI,r,r,k ,?n")
1181 (match_operand:SI 2 "reg_or_int_operand" "l ,Py,Pd,l ,r ,I,r,r ,r")))]
25f905c2 1182 "TARGET_32BIT"
e2348bcb 1183 "@
7c36fe71 1184 sub%?\\t%0, %1, %2
1185 sub%?\\t%0, %2
1186 sub%?\\t%0, %1, %2
1187 rsb%?\\t%0, %2, %1
87b22bf7 1188 rsb%?\\t%0, %2, %1
aaa37ad6 1189 sub%?\\t%0, %1, %2
080c0b9a 1190 sub%?\\t%0, %1, %2
65f68e55 1191 sub%?\\t%0, %1, %2
87b22bf7 1192 #"
0438d37f 1193 "&& (CONST_INT_P (operands[1])
91a5e339 1194 && !const_ok_for_arm (INTVAL (operands[1])))"
87b22bf7 1195 [(clobber (const_int 0))]
1196 "
96f57e36 1197 arm_split_constant (MINUS, SImode, curr_insn,
1198 INTVAL (operands[1]), operands[0], operands[2], 0);
87b22bf7 1199 DONE;
cffb2a26 1200 "
7c36fe71 1201 [(set_attr "length" "4,4,4,4,4,4,4,4,16")
1202 (set_attr "arch" "t2,t2,t2,t2,*,*,*,*,*")
65f68e55 1203 (set_attr "predicable" "yes")
7c36fe71 1204 (set_attr "predicable_short_it" "yes,yes,yes,yes,no,no,no,no,no")
112eda6f 1205 (set_attr "type" "alu_sreg,alu_sreg,alu_sreg,alu_sreg,alu_imm,alu_imm,alu_sreg,alu_sreg,multiple")]
a0f94409 1206)
1207
1208(define_peephole2
1209 [(match_scratch:SI 3 "r")
372575c7 1210 (set (match_operand:SI 0 "arm_general_register_operand" "")
a0f94409 1211 (minus:SI (match_operand:SI 1 "const_int_operand" "")
372575c7 1212 (match_operand:SI 2 "arm_general_register_operand" "")))]
25f905c2 1213 "TARGET_32BIT
a0f94409 1214 && !const_ok_for_arm (INTVAL (operands[1]))
1215 && const_ok_for_arm (~INTVAL (operands[1]))"
1216 [(set (match_dup 3) (match_dup 1))
1217 (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1218 ""
cffb2a26 1219)
b11cae9e 1220
f7fbdd4a 1221(define_insn "*subsi3_compare0"
bd5b4116 1222 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1223 (compare:CC_NOOV
65f68e55 1224 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,r,I")
1225 (match_operand:SI 2 "arm_rhs_operand" "I,r,r"))
215b30b3 1226 (const_int 0)))
65f68e55 1227 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9c08d1fa 1228 (minus:SI (match_dup 1) (match_dup 2)))]
25f905c2 1229 "TARGET_32BIT"
e2348bcb 1230 "@
65f68e55 1231 sub%.\\t%0, %1, %2
25f905c2 1232 sub%.\\t%0, %1, %2
1233 rsb%.\\t%0, %2, %1"
65f68e55 1234 [(set_attr "conds" "set")
112eda6f 1235 (set_attr "type" "alus_imm,alus_sreg,alus_sreg")]
cffb2a26 1236)
9c08d1fa 1237
190efb17 1238(define_insn "subsi3_compare"
080c0b9a 1239 [(set (reg:CC CC_REGNUM)
65f68e55 1240 (compare:CC (match_operand:SI 1 "arm_rhs_operand" "r,r,I")
1241 (match_operand:SI 2 "arm_rhs_operand" "I,r,r")))
1242 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2df9477b 1243 (minus:SI (match_dup 1) (match_dup 2)))]
1244 "TARGET_32BIT"
1245 "@
65f68e55 1246 sub%.\\t%0, %1, %2
2df9477b 1247 sub%.\\t%0, %1, %2
1248 rsb%.\\t%0, %2, %1"
65f68e55 1249 [(set_attr "conds" "set")
112eda6f 1250 (set_attr "type" "alus_imm,alus_sreg,alus_sreg")]
2df9477b 1251)
1252
604f3a0a 1253(define_expand "subsf3"
1254 [(set (match_operand:SF 0 "s_register_operand" "")
d86c91f6 1255 (minus:SF (match_operand:SF 1 "s_register_operand" "")
1256 (match_operand:SF 2 "s_register_operand" "")))]
25f905c2 1257 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1258 "
604f3a0a 1259")
1260
604f3a0a 1261(define_expand "subdf3"
1262 [(set (match_operand:DF 0 "s_register_operand" "")
d86c91f6 1263 (minus:DF (match_operand:DF 1 "s_register_operand" "")
1264 (match_operand:DF 2 "s_register_operand" "")))]
a50d7267 1265 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 1266 "
604f3a0a 1267")
1268
b11cae9e 1269\f
1270;; Multiplication insns
1271
4422d91f 1272(define_expand "mulhi3"
1273 [(set (match_operand:HI 0 "s_register_operand" "")
1274 (mult:HI (match_operand:HI 1 "s_register_operand" "")
1275 (match_operand:HI 2 "s_register_operand" "")))]
1276 "TARGET_DSP_MULTIPLY"
1277 "
1278 {
1279 rtx result = gen_reg_rtx (SImode);
1280 emit_insn (gen_mulhisi3 (result, operands[1], operands[2]));
1281 emit_move_insn (operands[0], gen_lowpart (HImode, result));
1282 DONE;
1283 }"
1284)
1285
cffb2a26 1286(define_expand "mulsi3"
1287 [(set (match_operand:SI 0 "s_register_operand" "")
1288 (mult:SI (match_operand:SI 2 "s_register_operand" "")
1289 (match_operand:SI 1 "s_register_operand" "")))]
1290 "TARGET_EITHER"
1291 ""
1292)
1293
9c08d1fa 1294;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
cffb2a26 1295(define_insn "*arm_mulsi3"
1296 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1297 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1298 (match_operand:SI 1 "s_register_operand" "%0,r")))]
58d7d654 1299 "TARGET_32BIT && !arm_arch6"
f7fbdd4a 1300 "mul%?\\t%0, %2, %1"
9da0ec36 1301 [(set_attr "type" "mul")
0d66636f 1302 (set_attr "predicable" "yes")]
cffb2a26 1303)
1304
58d7d654 1305(define_insn "*arm_mulsi3_v6"
d952d547 1306 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
1307 (mult:SI (match_operand:SI 1 "s_register_operand" "0,l,r")
1308 (match_operand:SI 2 "s_register_operand" "l,0,r")))]
58d7d654 1309 "TARGET_32BIT && arm_arch6"
1310 "mul%?\\t%0, %1, %2"
9da0ec36 1311 [(set_attr "type" "mul")
d952d547 1312 (set_attr "predicable" "yes")
1313 (set_attr "arch" "t2,t2,*")
1314 (set_attr "length" "4")
1315 (set_attr "predicable_short_it" "yes,yes,no")]
58d7d654 1316)
1317
f7fbdd4a 1318(define_insn "*mulsi3_compare0"
bd5b4116 1319 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1320 (compare:CC_NOOV (mult:SI
1321 (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1322 (match_operand:SI 1 "s_register_operand" "%0,r"))
9c08d1fa 1323 (const_int 0)))
1324 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1325 (mult:SI (match_dup 2) (match_dup 1)))]
58d7d654 1326 "TARGET_ARM && !arm_arch6"
1327 "mul%.\\t%0, %2, %1"
1328 [(set_attr "conds" "set")
9da0ec36 1329 (set_attr "type" "muls")]
58d7d654 1330)
1331
1332(define_insn "*mulsi3_compare0_v6"
1333 [(set (reg:CC_NOOV CC_REGNUM)
1334 (compare:CC_NOOV (mult:SI
1335 (match_operand:SI 2 "s_register_operand" "r")
1336 (match_operand:SI 1 "s_register_operand" "r"))
1337 (const_int 0)))
1338 (set (match_operand:SI 0 "s_register_operand" "=r")
1339 (mult:SI (match_dup 2) (match_dup 1)))]
1340 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1341 "mul%.\\t%0, %2, %1"
cffb2a26 1342 [(set_attr "conds" "set")
9da0ec36 1343 (set_attr "type" "muls")]
cffb2a26 1344)
9c08d1fa 1345
f7fbdd4a 1346(define_insn "*mulsi_compare0_scratch"
bd5b4116 1347 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1348 (compare:CC_NOOV (mult:SI
1349 (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1350 (match_operand:SI 1 "s_register_operand" "%0,r"))
9c08d1fa 1351 (const_int 0)))
1352 (clobber (match_scratch:SI 0 "=&r,&r"))]
58d7d654 1353 "TARGET_ARM && !arm_arch6"
1354 "mul%.\\t%0, %2, %1"
1355 [(set_attr "conds" "set")
9da0ec36 1356 (set_attr "type" "muls")]
58d7d654 1357)
1358
1359(define_insn "*mulsi_compare0_scratch_v6"
1360 [(set (reg:CC_NOOV CC_REGNUM)
1361 (compare:CC_NOOV (mult:SI
1362 (match_operand:SI 2 "s_register_operand" "r")
1363 (match_operand:SI 1 "s_register_operand" "r"))
1364 (const_int 0)))
1365 (clobber (match_scratch:SI 0 "=r"))]
1366 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1367 "mul%.\\t%0, %2, %1"
cffb2a26 1368 [(set_attr "conds" "set")
9da0ec36 1369 (set_attr "type" "muls")]
cffb2a26 1370)
9c08d1fa 1371
b11cae9e 1372;; Unnamed templates to match MLA instruction.
1373
f7fbdd4a 1374(define_insn "*mulsi3addsi"
9c08d1fa 1375 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
c8f69309 1376 (plus:SI
9c08d1fa 1377 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1378 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1379 (match_operand:SI 3 "s_register_operand" "r,r,0,0")))]
58d7d654 1380 "TARGET_32BIT && !arm_arch6"
1381 "mla%?\\t%0, %2, %1, %3"
9da0ec36 1382 [(set_attr "type" "mla")
58d7d654 1383 (set_attr "predicable" "yes")]
1384)
1385
1386(define_insn "*mulsi3addsi_v6"
1387 [(set (match_operand:SI 0 "s_register_operand" "=r")
1388 (plus:SI
1389 (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1390 (match_operand:SI 1 "s_register_operand" "r"))
1391 (match_operand:SI 3 "s_register_operand" "r")))]
1392 "TARGET_32BIT && arm_arch6"
f7fbdd4a 1393 "mla%?\\t%0, %2, %1, %3"
9da0ec36 1394 [(set_attr "type" "mla")
d952d547 1395 (set_attr "predicable" "yes")
1396 (set_attr "predicable_short_it" "no")]
0d66636f 1397)
b11cae9e 1398
f7fbdd4a 1399(define_insn "*mulsi3addsi_compare0"
bd5b4116 1400 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1401 (compare:CC_NOOV
1402 (plus:SI (mult:SI
1403 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1404 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1405 (match_operand:SI 3 "s_register_operand" "r,r,0,0"))
215b30b3 1406 (const_int 0)))
9c08d1fa 1407 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1408 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1409 (match_dup 3)))]
58d7d654 1410 "TARGET_ARM && arm_arch6"
1411 "mla%.\\t%0, %2, %1, %3"
1412 [(set_attr "conds" "set")
9da0ec36 1413 (set_attr "type" "mlas")]
58d7d654 1414)
1415
1416(define_insn "*mulsi3addsi_compare0_v6"
1417 [(set (reg:CC_NOOV CC_REGNUM)
1418 (compare:CC_NOOV
1419 (plus:SI (mult:SI
1420 (match_operand:SI 2 "s_register_operand" "r")
1421 (match_operand:SI 1 "s_register_operand" "r"))
1422 (match_operand:SI 3 "s_register_operand" "r"))
1423 (const_int 0)))
1424 (set (match_operand:SI 0 "s_register_operand" "=r")
1425 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1426 (match_dup 3)))]
1427 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1428 "mla%.\\t%0, %2, %1, %3"
0d66636f 1429 [(set_attr "conds" "set")
9da0ec36 1430 (set_attr "type" "mlas")]
0d66636f 1431)
9c08d1fa 1432
f7fbdd4a 1433(define_insn "*mulsi3addsi_compare0_scratch"
bd5b4116 1434 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1435 (compare:CC_NOOV
1436 (plus:SI (mult:SI
1437 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1438 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
215b30b3 1439 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1440 (const_int 0)))
9c08d1fa 1441 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
58d7d654 1442 "TARGET_ARM && !arm_arch6"
1443 "mla%.\\t%0, %2, %1, %3"
1444 [(set_attr "conds" "set")
9da0ec36 1445 (set_attr "type" "mlas")]
58d7d654 1446)
1447
1448(define_insn "*mulsi3addsi_compare0_scratch_v6"
1449 [(set (reg:CC_NOOV CC_REGNUM)
1450 (compare:CC_NOOV
1451 (plus:SI (mult:SI
1452 (match_operand:SI 2 "s_register_operand" "r")
1453 (match_operand:SI 1 "s_register_operand" "r"))
1454 (match_operand:SI 3 "s_register_operand" "r"))
1455 (const_int 0)))
1456 (clobber (match_scratch:SI 0 "=r"))]
1457 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1458 "mla%.\\t%0, %2, %1, %3"
cffb2a26 1459 [(set_attr "conds" "set")
9da0ec36 1460 (set_attr "type" "mlas")]
cffb2a26 1461)
f7fbdd4a 1462
89545238 1463(define_insn "*mulsi3subsi"
1464 [(set (match_operand:SI 0 "s_register_operand" "=r")
1465 (minus:SI
1466 (match_operand:SI 3 "s_register_operand" "r")
1467 (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1468 (match_operand:SI 1 "s_register_operand" "r"))))]
1469 "TARGET_32BIT && arm_arch_thumb2"
1470 "mls%?\\t%0, %2, %1, %3"
9da0ec36 1471 [(set_attr "type" "mla")
d952d547 1472 (set_attr "predicable" "yes")
1473 (set_attr "predicable_short_it" "no")]
89545238 1474)
1475
5cdca009 1476(define_expand "maddsidi4"
1477 [(set (match_operand:DI 0 "s_register_operand" "")
1478 (plus:DI
1479 (mult:DI
1480 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1481 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1482 (match_operand:DI 3 "s_register_operand" "")))]
1483 "TARGET_32BIT && arm_arch3m"
1484 "")
82b85d08 1485
1486(define_insn "*mulsidi3adddi"
fe8dbf85 1487 [(set (match_operand:DI 0 "s_register_operand" "=&r")
82b85d08 1488 (plus:DI
215b30b3 1489 (mult:DI
fe8dbf85 1490 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1491 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1492 (match_operand:DI 1 "s_register_operand" "0")))]
58d7d654 1493 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1494 "smlal%?\\t%Q0, %R0, %3, %2"
9da0ec36 1495 [(set_attr "type" "smlal")
58d7d654 1496 (set_attr "predicable" "yes")]
1497)
1498
1499(define_insn "*mulsidi3adddi_v6"
1500 [(set (match_operand:DI 0 "s_register_operand" "=r")
1501 (plus:DI
1502 (mult:DI
1503 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1504 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1505 (match_operand:DI 1 "s_register_operand" "0")))]
1506 "TARGET_32BIT && arm_arch6"
fe8dbf85 1507 "smlal%?\\t%Q0, %R0, %3, %2"
9da0ec36 1508 [(set_attr "type" "smlal")
d952d547 1509 (set_attr "predicable" "yes")
1510 (set_attr "predicable_short_it" "no")]
0d66636f 1511)
82b85d08 1512
957788b0 1513;; 32x32->64 widening multiply.
1514;; As with mulsi3, the only difference between the v3-5 and v6+
1515;; versions of these patterns is the requirement that the output not
1516;; overlap the inputs, but that still means we have to have a named
1517;; expander and two different starred insns.
1518
1519(define_expand "mulsidi3"
1520 [(set (match_operand:DI 0 "s_register_operand" "")
1521 (mult:DI
1522 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1523 (sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1524 "TARGET_32BIT && arm_arch3m"
1525 ""
1526)
1527
1528(define_insn "*mulsidi3_nov6"
f7fbdd4a 1529 [(set (match_operand:DI 0 "s_register_operand" "=&r")
215b30b3 1530 (mult:DI
1531 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1532 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
58d7d654 1533 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1534 "smull%?\\t%Q0, %R0, %1, %2"
9da0ec36 1535 [(set_attr "type" "smull")
58d7d654 1536 (set_attr "predicable" "yes")]
1537)
1538
957788b0 1539(define_insn "*mulsidi3_v6"
58d7d654 1540 [(set (match_operand:DI 0 "s_register_operand" "=r")
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"))))]
1544 "TARGET_32BIT && arm_arch6"
97499065 1545 "smull%?\\t%Q0, %R0, %1, %2"
9da0ec36 1546 [(set_attr "type" "smull")
d952d547 1547 (set_attr "predicable" "yes")
1548 (set_attr "predicable_short_it" "no")]
0d66636f 1549)
f7fbdd4a 1550
957788b0 1551(define_expand "umulsidi3"
1552 [(set (match_operand:DI 0 "s_register_operand" "")
1553 (mult:DI
1554 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1555 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1556 "TARGET_32BIT && arm_arch3m"
1557 ""
1558)
1559
1560(define_insn "*umulsidi3_nov6"
f7fbdd4a 1561 [(set (match_operand:DI 0 "s_register_operand" "=&r")
215b30b3 1562 (mult:DI
1563 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1564 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
58d7d654 1565 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1566 "umull%?\\t%Q0, %R0, %1, %2"
9da0ec36 1567 [(set_attr "type" "umull")
58d7d654 1568 (set_attr "predicable" "yes")]
1569)
1570
957788b0 1571(define_insn "*umulsidi3_v6"
58d7d654 1572 [(set (match_operand:DI 0 "s_register_operand" "=r")
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"))))]
1576 "TARGET_32BIT && arm_arch6"
97499065 1577 "umull%?\\t%Q0, %R0, %1, %2"
9da0ec36 1578 [(set_attr "type" "umull")
d952d547 1579 (set_attr "predicable" "yes")
1580 (set_attr "predicable_short_it" "no")]
0d66636f 1581)
b11cae9e 1582
5cdca009 1583(define_expand "umaddsidi4"
1584 [(set (match_operand:DI 0 "s_register_operand" "")
1585 (plus:DI
1586 (mult:DI
1587 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1588 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1589 (match_operand:DI 3 "s_register_operand" "")))]
1590 "TARGET_32BIT && arm_arch3m"
1591 "")
82b85d08 1592
1593(define_insn "*umulsidi3adddi"
8ead09f9 1594 [(set (match_operand:DI 0 "s_register_operand" "=&r")
82b85d08 1595 (plus:DI
215b30b3 1596 (mult:DI
fe8dbf85 1597 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1598 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1599 (match_operand:DI 1 "s_register_operand" "0")))]
58d7d654 1600 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1601 "umlal%?\\t%Q0, %R0, %3, %2"
9da0ec36 1602 [(set_attr "type" "umlal")
58d7d654 1603 (set_attr "predicable" "yes")]
1604)
1605
1606(define_insn "*umulsidi3adddi_v6"
1607 [(set (match_operand:DI 0 "s_register_operand" "=r")
1608 (plus:DI
1609 (mult:DI
1610 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1611 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1612 (match_operand:DI 1 "s_register_operand" "0")))]
1613 "TARGET_32BIT && arm_arch6"
fe8dbf85 1614 "umlal%?\\t%Q0, %R0, %3, %2"
9da0ec36 1615 [(set_attr "type" "umlal")
d952d547 1616 (set_attr "predicable" "yes")
1617 (set_attr "predicable_short_it" "no")]
0d66636f 1618)
82b85d08 1619
957788b0 1620(define_expand "smulsi3_highpart"
1621 [(parallel
1622 [(set (match_operand:SI 0 "s_register_operand" "")
1623 (truncate:SI
1624 (lshiftrt:DI
1625 (mult:DI
1626 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1627 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1628 (const_int 32))))
1629 (clobber (match_scratch:SI 3 ""))])]
1630 "TARGET_32BIT && arm_arch3m"
1631 ""
1632)
1633
1634(define_insn "*smulsi3_highpart_nov6"
f082f1c4 1635 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1636 (truncate:SI
1637 (lshiftrt:DI
215b30b3 1638 (mult:DI
e5fea38e 1639 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
215b30b3 1640 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
f082f1c4 1641 (const_int 32))))
1642 (clobber (match_scratch:SI 3 "=&r,&r"))]
58d7d654 1643 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1644 "smull%?\\t%3, %0, %2, %1"
9da0ec36 1645 [(set_attr "type" "smull")
58d7d654 1646 (set_attr "predicable" "yes")]
1647)
1648
957788b0 1649(define_insn "*smulsi3_highpart_v6"
58d7d654 1650 [(set (match_operand:SI 0 "s_register_operand" "=r")
1651 (truncate:SI
1652 (lshiftrt:DI
1653 (mult:DI
1654 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1655 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1656 (const_int 32))))
1657 (clobber (match_scratch:SI 3 "=r"))]
1658 "TARGET_32BIT && arm_arch6"
f082f1c4 1659 "smull%?\\t%3, %0, %2, %1"
9da0ec36 1660 [(set_attr "type" "smull")
d952d547 1661 (set_attr "predicable" "yes")
1662 (set_attr "predicable_short_it" "no")]
cffb2a26 1663)
f082f1c4 1664
957788b0 1665(define_expand "umulsi3_highpart"
1666 [(parallel
1667 [(set (match_operand:SI 0 "s_register_operand" "")
1668 (truncate:SI
1669 (lshiftrt:DI
1670 (mult:DI
1671 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1672 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1673 (const_int 32))))
1674 (clobber (match_scratch:SI 3 ""))])]
1675 "TARGET_32BIT && arm_arch3m"
1676 ""
1677)
1678
1679(define_insn "*umulsi3_highpart_nov6"
f082f1c4 1680 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1681 (truncate:SI
1682 (lshiftrt:DI
215b30b3 1683 (mult:DI
e5fea38e 1684 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
215b30b3 1685 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
f082f1c4 1686 (const_int 32))))
1687 (clobber (match_scratch:SI 3 "=&r,&r"))]
58d7d654 1688 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1689 "umull%?\\t%3, %0, %2, %1"
9da0ec36 1690 [(set_attr "type" "umull")
58d7d654 1691 (set_attr "predicable" "yes")]
1692)
1693
957788b0 1694(define_insn "*umulsi3_highpart_v6"
58d7d654 1695 [(set (match_operand:SI 0 "s_register_operand" "=r")
1696 (truncate:SI
1697 (lshiftrt:DI
1698 (mult:DI
1699 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1700 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1701 (const_int 32))))
1702 (clobber (match_scratch:SI 3 "=r"))]
1703 "TARGET_32BIT && arm_arch6"
f082f1c4 1704 "umull%?\\t%3, %0, %2, %1"
9da0ec36 1705 [(set_attr "type" "umull")
d952d547 1706 (set_attr "predicable" "yes")
1707 (set_attr "predicable_short_it" "no")]
cffb2a26 1708)
f082f1c4 1709
331beb1a 1710(define_insn "mulhisi3"
1711 [(set (match_operand:SI 0 "s_register_operand" "=r")
1712 (mult:SI (sign_extend:SI
1713 (match_operand:HI 1 "s_register_operand" "%r"))
1714 (sign_extend:SI
1715 (match_operand:HI 2 "s_register_operand" "r"))))]
25f905c2 1716 "TARGET_DSP_MULTIPLY"
61a2d04c 1717 "smulbb%?\\t%0, %1, %2"
9da0ec36 1718 [(set_attr "type" "smulxy")
fec538d9 1719 (set_attr "predicable" "yes")]
1720)
1721
1722(define_insn "*mulhisi3tb"
1723 [(set (match_operand:SI 0 "s_register_operand" "=r")
1724 (mult:SI (ashiftrt:SI
1725 (match_operand:SI 1 "s_register_operand" "r")
1726 (const_int 16))
1727 (sign_extend:SI
1728 (match_operand:HI 2 "s_register_operand" "r"))))]
25f905c2 1729 "TARGET_DSP_MULTIPLY"
fec538d9 1730 "smultb%?\\t%0, %1, %2"
9da0ec36 1731 [(set_attr "type" "smulxy")
d952d547 1732 (set_attr "predicable" "yes")
1733 (set_attr "predicable_short_it" "no")]
fec538d9 1734)
1735
1736(define_insn "*mulhisi3bt"
1737 [(set (match_operand:SI 0 "s_register_operand" "=r")
1738 (mult:SI (sign_extend:SI
1739 (match_operand:HI 1 "s_register_operand" "r"))
1740 (ashiftrt:SI
1741 (match_operand:SI 2 "s_register_operand" "r")
1742 (const_int 16))))]
25f905c2 1743 "TARGET_DSP_MULTIPLY"
fec538d9 1744 "smulbt%?\\t%0, %1, %2"
9da0ec36 1745 [(set_attr "type" "smulxy")
d952d547 1746 (set_attr "predicable" "yes")
1747 (set_attr "predicable_short_it" "no")]
fec538d9 1748)
1749
1750(define_insn "*mulhisi3tt"
1751 [(set (match_operand:SI 0 "s_register_operand" "=r")
1752 (mult:SI (ashiftrt:SI
1753 (match_operand:SI 1 "s_register_operand" "r")
1754 (const_int 16))
1755 (ashiftrt:SI
1756 (match_operand:SI 2 "s_register_operand" "r")
1757 (const_int 16))))]
25f905c2 1758 "TARGET_DSP_MULTIPLY"
fec538d9 1759 "smultt%?\\t%0, %1, %2"
9da0ec36 1760 [(set_attr "type" "smulxy")
d952d547 1761 (set_attr "predicable" "yes")
1762 (set_attr "predicable_short_it" "no")]
331beb1a 1763)
1764
5cdca009 1765(define_insn "maddhisi4"
331beb1a 1766 [(set (match_operand:SI 0 "s_register_operand" "=r")
cfa6c608 1767 (plus:SI (mult:SI (sign_extend:SI
1768 (match_operand:HI 1 "s_register_operand" "r"))
331beb1a 1769 (sign_extend:SI
cfa6c608 1770 (match_operand:HI 2 "s_register_operand" "r")))
1771 (match_operand:SI 3 "s_register_operand" "r")))]
25f905c2 1772 "TARGET_DSP_MULTIPLY"
5cdca009 1773 "smlabb%?\\t%0, %1, %2, %3"
9da0ec36 1774 [(set_attr "type" "smlaxy")
d952d547 1775 (set_attr "predicable" "yes")
1776 (set_attr "predicable_short_it" "no")]
331beb1a 1777)
1778
9a92f368 1779;; Note: there is no maddhisi4ibt because this one is canonical form
1780(define_insn "*maddhisi4tb"
1781 [(set (match_operand:SI 0 "s_register_operand" "=r")
1782 (plus:SI (mult:SI (ashiftrt:SI
1783 (match_operand:SI 1 "s_register_operand" "r")
1784 (const_int 16))
1785 (sign_extend:SI
1786 (match_operand:HI 2 "s_register_operand" "r")))
1787 (match_operand:SI 3 "s_register_operand" "r")))]
1788 "TARGET_DSP_MULTIPLY"
1789 "smlatb%?\\t%0, %1, %2, %3"
9da0ec36 1790 [(set_attr "type" "smlaxy")
d952d547 1791 (set_attr "predicable" "yes")
1792 (set_attr "predicable_short_it" "no")]
9a92f368 1793)
1794
1795(define_insn "*maddhisi4tt"
1796 [(set (match_operand:SI 0 "s_register_operand" "=r")
1797 (plus:SI (mult:SI (ashiftrt:SI
1798 (match_operand:SI 1 "s_register_operand" "r")
1799 (const_int 16))
1800 (ashiftrt:SI
1801 (match_operand:SI 2 "s_register_operand" "r")
1802 (const_int 16)))
1803 (match_operand:SI 3 "s_register_operand" "r")))]
1804 "TARGET_DSP_MULTIPLY"
1805 "smlatt%?\\t%0, %1, %2, %3"
9da0ec36 1806 [(set_attr "type" "smlaxy")
d952d547 1807 (set_attr "predicable" "yes")
1808 (set_attr "predicable_short_it" "no")]
9a92f368 1809)
1810
aff5fb4d 1811(define_insn "maddhidi4"
331beb1a 1812 [(set (match_operand:DI 0 "s_register_operand" "=r")
1813 (plus:DI
331beb1a 1814 (mult:DI (sign_extend:DI
d952d547 1815 (match_operand:HI 1 "s_register_operand" "r"))
331beb1a 1816 (sign_extend:DI
cfa6c608 1817 (match_operand:HI 2 "s_register_operand" "r")))
1818 (match_operand:DI 3 "s_register_operand" "0")))]
25f905c2 1819 "TARGET_DSP_MULTIPLY"
5cdca009 1820 "smlalbb%?\\t%Q0, %R0, %1, %2"
9da0ec36 1821 [(set_attr "type" "smlalxy")
d952d547 1822 (set_attr "predicable" "yes")
1823 (set_attr "predicable_short_it" "no")])
331beb1a 1824
9a92f368 1825;; Note: there is no maddhidi4ibt because this one is canonical form
1826(define_insn "*maddhidi4tb"
1827 [(set (match_operand:DI 0 "s_register_operand" "=r")
1828 (plus:DI
1829 (mult:DI (sign_extend:DI
1830 (ashiftrt:SI
1831 (match_operand:SI 1 "s_register_operand" "r")
1832 (const_int 16)))
1833 (sign_extend:DI
1834 (match_operand:HI 2 "s_register_operand" "r")))
1835 (match_operand:DI 3 "s_register_operand" "0")))]
1836 "TARGET_DSP_MULTIPLY"
1837 "smlaltb%?\\t%Q0, %R0, %1, %2"
9da0ec36 1838 [(set_attr "type" "smlalxy")
d952d547 1839 (set_attr "predicable" "yes")
1840 (set_attr "predicable_short_it" "no")])
9a92f368 1841
1842(define_insn "*maddhidi4tt"
1843 [(set (match_operand:DI 0 "s_register_operand" "=r")
1844 (plus:DI
1845 (mult:DI (sign_extend:DI
1846 (ashiftrt:SI
1847 (match_operand:SI 1 "s_register_operand" "r")
1848 (const_int 16)))
1849 (sign_extend:DI
1850 (ashiftrt:SI
1851 (match_operand:SI 2 "s_register_operand" "r")
1852 (const_int 16))))
1853 (match_operand:DI 3 "s_register_operand" "0")))]
1854 "TARGET_DSP_MULTIPLY"
1855 "smlaltt%?\\t%Q0, %R0, %1, %2"
9da0ec36 1856 [(set_attr "type" "smlalxy")
d952d547 1857 (set_attr "predicable" "yes")
1858 (set_attr "predicable_short_it" "no")])
9a92f368 1859
604f3a0a 1860(define_expand "mulsf3"
1861 [(set (match_operand:SF 0 "s_register_operand" "")
1862 (mult:SF (match_operand:SF 1 "s_register_operand" "")
d86c91f6 1863 (match_operand:SF 2 "s_register_operand" "")))]
25f905c2 1864 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1865 "
604f3a0a 1866")
1867
604f3a0a 1868(define_expand "muldf3"
1869 [(set (match_operand:DF 0 "s_register_operand" "")
1870 (mult:DF (match_operand:DF 1 "s_register_operand" "")
d86c91f6 1871 (match_operand:DF 2 "s_register_operand" "")))]
a50d7267 1872 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 1873 "
604f3a0a 1874")
b11cae9e 1875\f
1876;; Division insns
1877
7db9af5d 1878(define_expand "divsf3"
1879 [(set (match_operand:SF 0 "s_register_operand" "")
d86c91f6 1880 (div:SF (match_operand:SF 1 "s_register_operand" "")
1881 (match_operand:SF 2 "s_register_operand" "")))]
994606f8 1882 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
7db9af5d 1883 "")
9c08d1fa 1884
7db9af5d 1885(define_expand "divdf3"
1886 [(set (match_operand:DF 0 "s_register_operand" "")
d86c91f6 1887 (div:DF (match_operand:DF 1 "s_register_operand" "")
1888 (match_operand:DF 2 "s_register_operand" "")))]
994606f8 1889 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
7db9af5d 1890 "")
b11cae9e 1891\f
1892;; Boolean and,ior,xor insns
1893
f6ebffac 1894;; Split up double word logical operations
1895
1896;; Split up simple DImode logical operations. Simply perform the logical
1897;; operation on the upper and lower halves of the registers.
1898(define_split
1899 [(set (match_operand:DI 0 "s_register_operand" "")
1900 (match_operator:DI 6 "logical_binary_operator"
1901 [(match_operand:DI 1 "s_register_operand" "")
1902 (match_operand:DI 2 "s_register_operand" "")]))]
25f905c2 1903 "TARGET_32BIT && reload_completed
e2669ea7 1904 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))
25f905c2 1905 && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
f6ebffac 1906 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1907 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1908 "
215b30b3 1909 {
1910 operands[3] = gen_highpart (SImode, operands[0]);
1911 operands[0] = gen_lowpart (SImode, operands[0]);
1912 operands[4] = gen_highpart (SImode, operands[1]);
1913 operands[1] = gen_lowpart (SImode, operands[1]);
1914 operands[5] = gen_highpart (SImode, operands[2]);
1915 operands[2] = gen_lowpart (SImode, operands[2]);
1916 }"
1917)
f6ebffac 1918
f6ebffac 1919(define_split
1920 [(set (match_operand:DI 0 "s_register_operand" "")
1921 (match_operator:DI 6 "logical_binary_operator"
1922 [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1923 (match_operand:DI 1 "s_register_operand" "")]))]
25f905c2 1924 "TARGET_32BIT && reload_completed"
f6ebffac 1925 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1926 (set (match_dup 3) (match_op_dup:SI 6
1927 [(ashiftrt:SI (match_dup 2) (const_int 31))
1928 (match_dup 4)]))]
1929 "
215b30b3 1930 {
1931 operands[3] = gen_highpart (SImode, operands[0]);
1932 operands[0] = gen_lowpart (SImode, operands[0]);
1933 operands[4] = gen_highpart (SImode, operands[1]);
1934 operands[1] = gen_lowpart (SImode, operands[1]);
1935 operands[5] = gen_highpart (SImode, operands[2]);
1936 operands[2] = gen_lowpart (SImode, operands[2]);
1937 }"
1938)
f6ebffac 1939
f6ebffac 1940;; The zero extend of operand 2 means we can just copy the high part of
1941;; operand1 into operand0.
1942(define_split
1943 [(set (match_operand:DI 0 "s_register_operand" "")
1944 (ior:DI
1945 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1946 (match_operand:DI 1 "s_register_operand" "")))]
25f905c2 1947 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
f6ebffac 1948 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1949 (set (match_dup 3) (match_dup 4))]
1950 "
215b30b3 1951 {
1952 operands[4] = gen_highpart (SImode, operands[1]);
1953 operands[3] = gen_highpart (SImode, operands[0]);
1954 operands[0] = gen_lowpart (SImode, operands[0]);
1955 operands[1] = gen_lowpart (SImode, operands[1]);
1956 }"
1957)
f6ebffac 1958
1959;; The zero extend of operand 2 means we can just copy the high part of
1960;; operand1 into operand0.
1961(define_split
1962 [(set (match_operand:DI 0 "s_register_operand" "")
1963 (xor:DI
1964 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1965 (match_operand:DI 1 "s_register_operand" "")))]
25f905c2 1966 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
f6ebffac 1967 [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1968 (set (match_dup 3) (match_dup 4))]
1969 "
215b30b3 1970 {
1971 operands[4] = gen_highpart (SImode, operands[1]);
1972 operands[3] = gen_highpart (SImode, operands[0]);
1973 operands[0] = gen_lowpart (SImode, operands[0]);
1974 operands[1] = gen_lowpart (SImode, operands[1]);
1975 }"
1976)
f6ebffac 1977
e2669ea7 1978(define_expand "anddi3"
1979 [(set (match_operand:DI 0 "s_register_operand" "")
1980 (and:DI (match_operand:DI 1 "s_register_operand" "")
1981 (match_operand:DI 2 "neon_inv_logic_op2" "")))]
1982 "TARGET_32BIT"
1983 ""
1984)
1985
f6bbdcf6 1986(define_insn_and_split "*anddi3_insn"
0a314dcd 1987 [(set (match_operand:DI 0 "s_register_operand" "=w,w ,&r,&r,&r,&r,?w,?w")
1988 (and:DI (match_operand:DI 1 "s_register_operand" "%w,0 ,0 ,r ,0 ,r ,w ,0")
1989 (match_operand:DI 2 "arm_anddi_operand_neon" "w ,DL,r ,r ,De,De,w ,DL")))]
f6bbdcf6 1990 "TARGET_32BIT && !TARGET_IWMMXT"
1991{
1992 switch (which_alternative)
1993 {
0a314dcd 1994 case 0: /* fall through */
1995 case 6: return "vand\t%P0, %P1, %P2";
1996 case 1: /* fall through */
1997 case 7: return neon_output_logic_immediate ("vand", &operands[2],
1998 DImode, 1, VALID_NEON_QREG_MODE (DImode));
f6bbdcf6 1999 case 2:
0a314dcd 2000 case 3:
2001 case 4:
f6bbdcf6 2002 case 5: /* fall through */
0a314dcd 2003 return "#";
f6bbdcf6 2004 default: gcc_unreachable ();
2005 }
2006}
0a314dcd 2007 "TARGET_32BIT && !TARGET_IWMMXT && reload_completed
2008 && !(IS_VFP_REGNUM (REGNO (operands[0])))"
f6bbdcf6 2009 [(set (match_dup 3) (match_dup 4))
2010 (set (match_dup 5) (match_dup 6))]
2011 "
2012 {
2013 operands[3] = gen_lowpart (SImode, operands[0]);
2014 operands[5] = gen_highpart (SImode, operands[0]);
2015
2016 operands[4] = simplify_gen_binary (AND, SImode,
2017 gen_lowpart (SImode, operands[1]),
2018 gen_lowpart (SImode, operands[2]));
2019 operands[6] = simplify_gen_binary (AND, SImode,
2020 gen_highpart (SImode, operands[1]),
2021 gen_highpart_mode (SImode, DImode, operands[2]));
2022
2023 }"
32093010 2024 [(set_attr "type" "neon_logic,neon_logic,multiple,multiple,\
2025 multiple,multiple,neon_logic,neon_logic")
0a314dcd 2026 (set_attr "arch" "neon_for_64bits,neon_for_64bits,*,*,*,*,
f6bbdcf6 2027 avoid_neon_for_64bits,avoid_neon_for_64bits")
0a314dcd 2028 (set_attr "length" "*,*,8,8,8,8,*,*")
2029 ]
215b30b3 2030)
b11cae9e 2031
a0f94409 2032(define_insn_and_split "*anddi_zesidi_di"
9c08d1fa 2033 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2034 (and:DI (zero_extend:DI
2035 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 2036 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2037 "TARGET_32BIT"
f6ebffac 2038 "#"
25f905c2 2039 "TARGET_32BIT && reload_completed"
a0f94409 2040 ; The zero extend of operand 2 clears the high word of the output
2041 ; operand.
2042 [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
2043 (set (match_dup 3) (const_int 0))]
2044 "
2045 {
2046 operands[3] = gen_highpart (SImode, operands[0]);
2047 operands[0] = gen_lowpart (SImode, operands[0]);
2048 operands[1] = gen_lowpart (SImode, operands[1]);
2049 }"
1b7da4ac 2050 [(set_attr "length" "8")
2051 (set_attr "type" "multiple")]
215b30b3 2052)
b11cae9e 2053
f7fbdd4a 2054(define_insn "*anddi_sesdi_di"
cffb2a26 2055 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 2056 (and:DI (sign_extend:DI
2057 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 2058 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2059 "TARGET_32BIT"
f6ebffac 2060 "#"
1b7da4ac 2061 [(set_attr "length" "8")
2062 (set_attr "type" "multiple")]
cffb2a26 2063)
b11cae9e 2064
87b22bf7 2065(define_expand "andsi3"
cffb2a26 2066 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2067 (and:SI (match_operand:SI 1 "s_register_operand" "")
2068 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 2069 "TARGET_EITHER"
87b22bf7 2070 "
25f905c2 2071 if (TARGET_32BIT)
87b22bf7 2072 {
0438d37f 2073 if (CONST_INT_P (operands[2]))
cffb2a26 2074 {
47b5b27b 2075 if (INTVAL (operands[2]) == 255 && arm_arch6)
2076 {
2077 operands[1] = convert_to_mode (QImode, operands[1], 1);
2078 emit_insn (gen_thumb2_zero_extendqisi2_v6 (operands[0],
2079 operands[1]));
2080 }
2081 else
2082 arm_split_constant (AND, SImode, NULL_RTX,
2083 INTVAL (operands[2]), operands[0],
2084 operands[1],
2085 optimize && can_create_pseudo_p ());
615caa51 2086
cffb2a26 2087 DONE;
2088 }
87b22bf7 2089 }
25f905c2 2090 else /* TARGET_THUMB1 */
cffb2a26 2091 {
0438d37f 2092 if (!CONST_INT_P (operands[2]))
923ffadb 2093 {
2094 rtx tmp = force_reg (SImode, operands[2]);
2095 if (rtx_equal_p (operands[0], operands[1]))
2096 operands[2] = tmp;
2097 else
2098 {
2099 operands[2] = operands[1];
2100 operands[1] = tmp;
2101 }
2102 }
cffb2a26 2103 else
2104 {
2105 int i;
2106
215b30b3 2107 if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
cffb2a26 2108 {
215b30b3 2109 operands[2] = force_reg (SImode,
2110 GEN_INT (~INTVAL (operands[2])));
cffb2a26 2111
747b7458 2112 emit_insn (gen_thumb1_bicsi3 (operands[0], operands[2], operands[1]));
cffb2a26 2113
2114 DONE;
2115 }
87b22bf7 2116
cffb2a26 2117 for (i = 9; i <= 31; i++)
2118 {
2119 if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
2120 {
2121 emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
2122 const0_rtx));
2123 DONE;
2124 }
215b30b3 2125 else if ((((HOST_WIDE_INT) 1) << i) - 1
2126 == ~INTVAL (operands[2]))
cffb2a26 2127 {
2128 rtx shift = GEN_INT (i);
2129 rtx reg = gen_reg_rtx (SImode);
2130
2131 emit_insn (gen_lshrsi3 (reg, operands[1], shift));
2132 emit_insn (gen_ashlsi3 (operands[0], reg, shift));
2133
2134 DONE;
2135 }
2136 }
2137
2138 operands[2] = force_reg (SImode, operands[2]);
2139 }
215b30b3 2140 }
2141 "
cffb2a26 2142)
2143
25f905c2 2144; ??? Check split length for Thumb-2
a0f94409 2145(define_insn_and_split "*arm_andsi3_insn"
29e234a3 2146 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r,r,r")
2147 (and:SI (match_operand:SI 1 "s_register_operand" "%r,0,r,r,r")
2148 (match_operand:SI 2 "reg_or_int_operand" "I,l,K,r,?n")))]
25f905c2 2149 "TARGET_32BIT"
5565501b 2150 "@
29e234a3 2151 and%?\\t%0, %1, %2
5565501b 2152 and%?\\t%0, %1, %2
87b22bf7 2153 bic%?\\t%0, %1, #%B2
65f68e55 2154 and%?\\t%0, %1, %2
87b22bf7 2155 #"
25f905c2 2156 "TARGET_32BIT
0438d37f 2157 && CONST_INT_P (operands[2])
a0f94409 2158 && !(const_ok_for_arm (INTVAL (operands[2]))
2159 || const_ok_for_arm (~INTVAL (operands[2])))"
2160 [(clobber (const_int 0))]
2161 "
96f57e36 2162 arm_split_constant (AND, SImode, curr_insn,
2163 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 2164 DONE;
2165 "
29e234a3 2166 [(set_attr "length" "4,4,4,4,16")
65f68e55 2167 (set_attr "predicable" "yes")
29e234a3 2168 (set_attr "predicable_short_it" "no,yes,no,no,no")
d82e788e 2169 (set_attr "type" "logic_imm,logic_imm,logic_reg,logic_reg,logic_imm")]
cffb2a26 2170)
2171
f7fbdd4a 2172(define_insn "*andsi3_compare0"
bd5b4116 2173 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 2174 (compare:CC_NOOV
65f68e55 2175 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
2176 (match_operand:SI 2 "arm_not_operand" "I,K,r"))
5565501b 2177 (const_int 0)))
65f68e55 2178 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9c08d1fa 2179 (and:SI (match_dup 1) (match_dup 2)))]
25f905c2 2180 "TARGET_32BIT"
5565501b 2181 "@
25f905c2 2182 and%.\\t%0, %1, %2
65f68e55 2183 bic%.\\t%0, %1, #%B2
2184 and%.\\t%0, %1, %2"
2185 [(set_attr "conds" "set")
d82e788e 2186 (set_attr "type" "logics_imm,logics_imm,logics_reg")]
cffb2a26 2187)
9c08d1fa 2188
f7fbdd4a 2189(define_insn "*andsi3_compare0_scratch"
bd5b4116 2190 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 2191 (compare:CC_NOOV
65f68e55 2192 (and:SI (match_operand:SI 0 "s_register_operand" "r,r,r")
2193 (match_operand:SI 1 "arm_not_operand" "I,K,r"))
5565501b 2194 (const_int 0)))
65f68e55 2195 (clobber (match_scratch:SI 2 "=X,r,X"))]
25f905c2 2196 "TARGET_32BIT"
5565501b 2197 "@
2198 tst%?\\t%0, %1
65f68e55 2199 bic%.\\t%2, %0, #%B1
2200 tst%?\\t%0, %1"
2201 [(set_attr "conds" "set")
d82e788e 2202 (set_attr "type" "logics_imm,logics_imm,logics_reg")]
0d66636f 2203)
9c08d1fa 2204
f7fbdd4a 2205(define_insn "*zeroextractsi_compare0_scratch"
bd5b4116 2206 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2207 (compare:CC_NOOV (zero_extract:SI
2208 (match_operand:SI 0 "s_register_operand" "r")
d952d547 2209 (match_operand 1 "const_int_operand" "n")
206ee9a2 2210 (match_operand 2 "const_int_operand" "n"))
9c08d1fa 2211 (const_int 0)))]
25f905c2 2212 "TARGET_32BIT
cffb2a26 2213 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
2214 && INTVAL (operands[1]) > 0
2215 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
2216 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
9c08d1fa 2217 "*
5c49a439 2218 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
2219 << INTVAL (operands[2]));
40dbec34 2220 output_asm_insn (\"tst%?\\t%0, %1\", operands);
e2348bcb 2221 return \"\";
0d66636f 2222 "
596e5e8f 2223 [(set_attr "conds" "set")
65f68e55 2224 (set_attr "predicable" "yes")
d952d547 2225 (set_attr "predicable_short_it" "no")
d82e788e 2226 (set_attr "type" "logics_imm")]
0d66636f 2227)
9c08d1fa 2228
f4462328 2229(define_insn_and_split "*ne_zeroextractsi"
c4034607 2230 [(set (match_operand:SI 0 "s_register_operand" "=r")
2231 (ne:SI (zero_extract:SI
2232 (match_operand:SI 1 "s_register_operand" "r")
2233 (match_operand:SI 2 "const_int_operand" "n")
2234 (match_operand:SI 3 "const_int_operand" "n"))
3b8c7f7a 2235 (const_int 0)))
2236 (clobber (reg:CC CC_REGNUM))]
25f905c2 2237 "TARGET_32BIT
cffb2a26 2238 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2239 && INTVAL (operands[2]) > 0
2240 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2241 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
f4462328 2242 "#"
25f905c2 2243 "TARGET_32BIT
f4462328 2244 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2245 && INTVAL (operands[2]) > 0
2246 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2247 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
2248 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2249 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2250 (const_int 0)))
2251 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2252 (set (match_dup 0)
2253 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2254 (match_dup 0) (const_int 1)))]
2255 "
2256 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
2257 << INTVAL (operands[3]));
2258 "
2259 [(set_attr "conds" "clob")
25f905c2 2260 (set (attr "length")
2261 (if_then_else (eq_attr "is_thumb" "yes")
2262 (const_int 12)
1b7da4ac 2263 (const_int 8)))
2264 (set_attr "type" "multiple")]
f4462328 2265)
2266
2267(define_insn_and_split "*ne_zeroextractsi_shifted"
2268 [(set (match_operand:SI 0 "s_register_operand" "=r")
2269 (ne:SI (zero_extract:SI
2270 (match_operand:SI 1 "s_register_operand" "r")
2271 (match_operand:SI 2 "const_int_operand" "n")
2272 (const_int 0))
2273 (const_int 0)))
2274 (clobber (reg:CC CC_REGNUM))]
2275 "TARGET_ARM"
2276 "#"
2277 "TARGET_ARM"
2278 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2279 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2280 (const_int 0)))
2281 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2282 (set (match_dup 0)
2283 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2284 (match_dup 0) (const_int 1)))]
2285 "
2286 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
2287 "
2288 [(set_attr "conds" "clob")
1b7da4ac 2289 (set_attr "length" "8")
2290 (set_attr "type" "multiple")]
f4462328 2291)
2292
2293(define_insn_and_split "*ite_ne_zeroextractsi"
2294 [(set (match_operand:SI 0 "s_register_operand" "=r")
2295 (if_then_else:SI (ne (zero_extract:SI
2296 (match_operand:SI 1 "s_register_operand" "r")
2297 (match_operand:SI 2 "const_int_operand" "n")
2298 (match_operand:SI 3 "const_int_operand" "n"))
2299 (const_int 0))
2300 (match_operand:SI 4 "arm_not_operand" "rIK")
2301 (const_int 0)))
2302 (clobber (reg:CC CC_REGNUM))]
2303 "TARGET_ARM
2304 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2305 && INTVAL (operands[2]) > 0
2306 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 2307 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2308 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 2309 "#"
2310 "TARGET_ARM
2311 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2312 && INTVAL (operands[2]) > 0
2313 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 2314 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2315 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 2316 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2317 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2318 (const_int 0)))
2319 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2320 (set (match_dup 0)
2321 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2322 (match_dup 0) (match_dup 4)))]
2323 "
c4034607 2324 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
f4462328 2325 << INTVAL (operands[3]));
2326 "
2327 [(set_attr "conds" "clob")
1b7da4ac 2328 (set_attr "length" "8")
2329 (set_attr "type" "multiple")]
f4462328 2330)
2331
2332(define_insn_and_split "*ite_ne_zeroextractsi_shifted"
2333 [(set (match_operand:SI 0 "s_register_operand" "=r")
2334 (if_then_else:SI (ne (zero_extract:SI
2335 (match_operand:SI 1 "s_register_operand" "r")
2336 (match_operand:SI 2 "const_int_operand" "n")
2337 (const_int 0))
2338 (const_int 0))
2339 (match_operand:SI 3 "arm_not_operand" "rIK")
2340 (const_int 0)))
2341 (clobber (reg:CC CC_REGNUM))]
f8d7bf2f 2342 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 2343 "#"
f8d7bf2f 2344 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 2345 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2346 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2347 (const_int 0)))
2348 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2349 (set (match_dup 0)
2350 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2351 (match_dup 0) (match_dup 3)))]
2352 "
2353 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
0d66636f 2354 "
2355 [(set_attr "conds" "clob")
1b7da4ac 2356 (set_attr "length" "8")
2357 (set_attr "type" "multiple")]
215b30b3 2358)
9c08d1fa 2359
25f905c2 2360;; ??? Use Thumb-2 has bitfield insert/extract instructions.
d7863cfe 2361(define_split
2362 [(set (match_operand:SI 0 "s_register_operand" "")
2363 (match_operator:SI 1 "shiftable_operator"
2364 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2365 (match_operand:SI 3 "const_int_operand" "")
2366 (match_operand:SI 4 "const_int_operand" ""))
2367 (match_operand:SI 5 "s_register_operand" "")]))
2368 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2369 "TARGET_ARM"
2370 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2371 (set (match_dup 0)
2372 (match_op_dup 1
2373 [(lshiftrt:SI (match_dup 6) (match_dup 4))
2374 (match_dup 5)]))]
2375 "{
2376 HOST_WIDE_INT temp = INTVAL (operands[3]);
2377
2378 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2379 operands[4] = GEN_INT (32 - temp);
2380 }"
2381)
2382
d7863cfe 2383(define_split
2384 [(set (match_operand:SI 0 "s_register_operand" "")
2385 (match_operator:SI 1 "shiftable_operator"
2386 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2387 (match_operand:SI 3 "const_int_operand" "")
2388 (match_operand:SI 4 "const_int_operand" ""))
2389 (match_operand:SI 5 "s_register_operand" "")]))
2390 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2391 "TARGET_ARM"
2392 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2393 (set (match_dup 0)
2394 (match_op_dup 1
2395 [(ashiftrt:SI (match_dup 6) (match_dup 4))
2396 (match_dup 5)]))]
2397 "{
2398 HOST_WIDE_INT temp = INTVAL (operands[3]);
2399
2400 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2401 operands[4] = GEN_INT (32 - temp);
2402 }"
2403)
2404
a42059fd 2405;;; ??? This pattern is bogus. If operand3 has bits outside the range
2406;;; represented by the bitfield, then this will produce incorrect results.
2407;;; Somewhere, the value needs to be truncated. On targets like the m68k,
ceb2fe0f 2408;;; which have a real bit-field insert instruction, the truncation happens
2409;;; in the bit-field insert instruction itself. Since arm does not have a
2410;;; bit-field insert instruction, we would have to emit code here to truncate
a42059fd 2411;;; the value before we insert. This loses some of the advantage of having
2412;;; this insv pattern, so this pattern needs to be reevalutated.
2413
8a18b90c 2414(define_expand "insv"
eb04cafb 2415 [(set (zero_extract (match_operand 0 "nonimmediate_operand" "")
2416 (match_operand 1 "general_operand" "")
2417 (match_operand 2 "general_operand" ""))
2418 (match_operand 3 "reg_or_int_operand" ""))]
8b054d5a 2419 "TARGET_ARM || arm_arch_thumb2"
8a18b90c 2420 "
215b30b3 2421 {
2422 int start_bit = INTVAL (operands[2]);
2423 int width = INTVAL (operands[1]);
2424 HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
2425 rtx target, subtarget;
2426
8b054d5a 2427 if (arm_arch_thumb2)
2428 {
eb04cafb 2429 if (unaligned_access && MEM_P (operands[0])
2430 && s_register_operand (operands[3], GET_MODE (operands[3]))
2431 && (width == 16 || width == 32) && (start_bit % BITS_PER_UNIT) == 0)
8b054d5a 2432 {
eb04cafb 2433 rtx base_addr;
2434
2435 if (BYTES_BIG_ENDIAN)
2436 start_bit = GET_MODE_BITSIZE (GET_MODE (operands[3])) - width
2437 - start_bit;
8b054d5a 2438
eb04cafb 2439 if (width == 32)
8b054d5a 2440 {
eb04cafb 2441 base_addr = adjust_address (operands[0], SImode,
2442 start_bit / BITS_PER_UNIT);
2443 emit_insn (gen_unaligned_storesi (base_addr, operands[3]));
8b054d5a 2444 }
eb04cafb 2445 else
2446 {
2447 rtx tmp = gen_reg_rtx (HImode);
8b054d5a 2448
eb04cafb 2449 base_addr = adjust_address (operands[0], HImode,
2450 start_bit / BITS_PER_UNIT);
2451 emit_move_insn (tmp, gen_lowpart (HImode, operands[3]));
2452 emit_insn (gen_unaligned_storehi (base_addr, tmp));
2453 }
2454 DONE;
8b054d5a 2455 }
eb04cafb 2456 else if (s_register_operand (operands[0], GET_MODE (operands[0])))
8b054d5a 2457 {
eb04cafb 2458 bool use_bfi = TRUE;
8b054d5a 2459
0438d37f 2460 if (CONST_INT_P (operands[3]))
eb04cafb 2461 {
2462 HOST_WIDE_INT val = INTVAL (operands[3]) & mask;
2463
2464 if (val == 0)
2465 {
2466 emit_insn (gen_insv_zero (operands[0], operands[1],
2467 operands[2]));
2468 DONE;
2469 }
2470
2471 /* See if the set can be done with a single orr instruction. */
2472 if (val == mask && const_ok_for_arm (val << start_bit))
2473 use_bfi = FALSE;
2474 }
2475
2476 if (use_bfi)
2477 {
0438d37f 2478 if (!REG_P (operands[3]))
eb04cafb 2479 operands[3] = force_reg (SImode, operands[3]);
2480
2481 emit_insn (gen_insv_t2 (operands[0], operands[1], operands[2],
2482 operands[3]));
2483 DONE;
2484 }
8b054d5a 2485 }
eb04cafb 2486 else
2487 FAIL;
8b054d5a 2488 }
2489
eb04cafb 2490 if (!s_register_operand (operands[0], GET_MODE (operands[0])))
2491 FAIL;
2492
3f8fde42 2493 target = copy_rtx (operands[0]);
215b30b3 2494 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
2495 subreg as the final target. */
2496 if (GET_CODE (target) == SUBREG)
2497 {
2498 subtarget = gen_reg_rtx (SImode);
2499 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
2500 < GET_MODE_SIZE (SImode))
2501 target = SUBREG_REG (target);
2502 }
2503 else
2504 subtarget = target;
8a18b90c 2505
0438d37f 2506 if (CONST_INT_P (operands[3]))
215b30b3 2507 {
2508 /* Since we are inserting a known constant, we may be able to
2509 reduce the number of bits that we have to clear so that
2510 the mask becomes simple. */
2511 /* ??? This code does not check to see if the new mask is actually
2512 simpler. It may not be. */
2513 rtx op1 = gen_reg_rtx (SImode);
2514 /* ??? Truncate operand3 to fit in the bitfield. See comment before
2515 start of this pattern. */
2516 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
2517 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
2518
c5b3a71b 2519 emit_insn (gen_andsi3 (op1, operands[0],
2520 gen_int_mode (~mask2, SImode)));
215b30b3 2521 emit_insn (gen_iorsi3 (subtarget, op1,
4292ca6b 2522 gen_int_mode (op3_value << start_bit, SImode)));
215b30b3 2523 }
2524 else if (start_bit == 0
2525 && !(const_ok_for_arm (mask)
2526 || const_ok_for_arm (~mask)))
2527 {
2528 /* A Trick, since we are setting the bottom bits in the word,
2529 we can shift operand[3] up, operand[0] down, OR them together
2530 and rotate the result back again. This takes 3 insns, and
5910bb95 2531 the third might be mergeable into another op. */
215b30b3 2532 /* The shift up copes with the possibility that operand[3] is
2533 wider than the bitfield. */
2534 rtx op0 = gen_reg_rtx (SImode);
2535 rtx op1 = gen_reg_rtx (SImode);
2536
2537 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2538 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
2539 emit_insn (gen_iorsi3 (op1, op1, op0));
2540 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
2541 }
2542 else if ((width + start_bit == 32)
2543 && !(const_ok_for_arm (mask)
2544 || const_ok_for_arm (~mask)))
2545 {
2546 /* Similar trick, but slightly less efficient. */
8a18b90c 2547
215b30b3 2548 rtx op0 = gen_reg_rtx (SImode);
2549 rtx op1 = gen_reg_rtx (SImode);
8a18b90c 2550
215b30b3 2551 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2552 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
2553 emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
2554 emit_insn (gen_iorsi3 (subtarget, op1, op0));
2555 }
2556 else
2557 {
c5b3a71b 2558 rtx op0 = gen_int_mode (mask, SImode);
215b30b3 2559 rtx op1 = gen_reg_rtx (SImode);
2560 rtx op2 = gen_reg_rtx (SImode);
8a18b90c 2561
215b30b3 2562 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
2563 {
2564 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 2565
215b30b3 2566 emit_insn (gen_movsi (tmp, op0));
2567 op0 = tmp;
2568 }
8a18b90c 2569
215b30b3 2570 /* Mask out any bits in operand[3] that are not needed. */
2571 emit_insn (gen_andsi3 (op1, operands[3], op0));
8a18b90c 2572
0438d37f 2573 if (CONST_INT_P (op0)
215b30b3 2574 && (const_ok_for_arm (mask << start_bit)
2575 || const_ok_for_arm (~(mask << start_bit))))
2576 {
c5b3a71b 2577 op0 = gen_int_mode (~(mask << start_bit), SImode);
215b30b3 2578 emit_insn (gen_andsi3 (op2, operands[0], op0));
2579 }
2580 else
2581 {
0438d37f 2582 if (CONST_INT_P (op0))
215b30b3 2583 {
2584 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 2585
215b30b3 2586 emit_insn (gen_movsi (tmp, op0));
2587 op0 = tmp;
2588 }
2589
2590 if (start_bit != 0)
2591 emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
a42059fd 2592
215b30b3 2593 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
2594 }
8a18b90c 2595
215b30b3 2596 if (start_bit != 0)
2597 emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
8a18b90c 2598
215b30b3 2599 emit_insn (gen_iorsi3 (subtarget, op1, op2));
2600 }
f082f1c4 2601
215b30b3 2602 if (subtarget != target)
2603 {
2604 /* If TARGET is still a SUBREG, then it must be wider than a word,
2605 so we must be careful only to set the subword we were asked to. */
2606 if (GET_CODE (target) == SUBREG)
2607 emit_move_insn (target, subtarget);
2608 else
2609 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
2610 }
8a18b90c 2611
215b30b3 2612 DONE;
2613 }"
2614)
8a18b90c 2615
8b054d5a 2616(define_insn "insv_zero"
2617 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
809003b3 2618 (match_operand:SI 1 "const_int_M_operand" "M")
2619 (match_operand:SI 2 "const_int_M_operand" "M"))
8b054d5a 2620 (const_int 0))]
2621 "arm_arch_thumb2"
2622 "bfc%?\t%0, %2, %1"
2623 [(set_attr "length" "4")
d952d547 2624 (set_attr "predicable" "yes")
d82e788e 2625 (set_attr "predicable_short_it" "no")
2626 (set_attr "type" "bfm")]
8b054d5a 2627)
2628
2629(define_insn "insv_t2"
2630 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
809003b3 2631 (match_operand:SI 1 "const_int_M_operand" "M")
2632 (match_operand:SI 2 "const_int_M_operand" "M"))
8b054d5a 2633 (match_operand:SI 3 "s_register_operand" "r"))]
2634 "arm_arch_thumb2"
2635 "bfi%?\t%0, %3, %2, %1"
2636 [(set_attr "length" "4")
d952d547 2637 (set_attr "predicable" "yes")
d82e788e 2638 (set_attr "predicable_short_it" "no")
2639 (set_attr "type" "bfm")]
8b054d5a 2640)
2641
215b30b3 2642; constants for op 2 will never be given to these patterns.
a0f94409 2643(define_insn_and_split "*anddi_notdi_di"
9c08d1fa 2644 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 2645 (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "0,r"))
2646 (match_operand:DI 2 "s_register_operand" "r,0")))]
25f905c2 2647 "TARGET_32BIT"
f6ebffac 2648 "#"
e2669ea7 2649 "TARGET_32BIT && reload_completed
2650 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))
2651 && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
a0f94409 2652 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2653 (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2654 "
2655 {
2656 operands[3] = gen_highpart (SImode, operands[0]);
2657 operands[0] = gen_lowpart (SImode, operands[0]);
2658 operands[4] = gen_highpart (SImode, operands[1]);
2659 operands[1] = gen_lowpart (SImode, operands[1]);
2660 operands[5] = gen_highpart (SImode, operands[2]);
2661 operands[2] = gen_lowpart (SImode, operands[2]);
2662 }"
0d66636f 2663 [(set_attr "length" "8")
1b7da4ac 2664 (set_attr "predicable" "yes")
2665 (set_attr "type" "multiple")]
0d66636f 2666)
d952d547 2667
a0f94409 2668(define_insn_and_split "*anddi_notzesidi_di"
9c08d1fa 2669 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2670 (and:DI (not:DI (zero_extend:DI
2671 (match_operand:SI 2 "s_register_operand" "r,r")))
e2348bcb 2672 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 2673 "TARGET_32BIT"
e2348bcb 2674 "@
97499065 2675 bic%?\\t%Q0, %Q1, %2
f6ebffac 2676 #"
a0f94409 2677 ; (not (zero_extend ...)) allows us to just copy the high word from
2678 ; operand1 to operand0.
25f905c2 2679 "TARGET_32BIT
a0f94409 2680 && reload_completed
2681 && operands[0] != operands[1]"
5a097f7d 2682 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
a0f94409 2683 (set (match_dup 3) (match_dup 4))]
2684 "
2685 {
2686 operands[3] = gen_highpart (SImode, operands[0]);
2687 operands[0] = gen_lowpart (SImode, operands[0]);
2688 operands[4] = gen_highpart (SImode, operands[1]);
2689 operands[1] = gen_lowpart (SImode, operands[1]);
2690 }"
0d66636f 2691 [(set_attr "length" "4,8")
d952d547 2692 (set_attr "predicable" "yes")
1b7da4ac 2693 (set_attr "predicable_short_it" "no")
2694 (set_attr "type" "multiple")]
0d66636f 2695)
d952d547 2696
d8cd5fa0 2697(define_insn_and_split "*anddi_notdi_zesidi"
2698 [(set (match_operand:DI 0 "s_register_operand" "=r")
2699 (and:DI (not:DI (match_operand:DI 2 "s_register_operand" "r"))
2700 (zero_extend:DI
2701 (match_operand:SI 1 "s_register_operand" "r"))))]
2702 "TARGET_32BIT"
2703 "#"
2704 "TARGET_32BIT && reload_completed"
2705 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2706 (set (match_dup 3) (const_int 0))]
2707 "
2708 {
2709 operands[3] = gen_highpart (SImode, operands[0]);
2710 operands[0] = gen_lowpart (SImode, operands[0]);
2711 operands[2] = gen_lowpart (SImode, operands[2]);
2712 }"
2713 [(set_attr "length" "8")
2714 (set_attr "predicable" "yes")
2715 (set_attr "predicable_short_it" "no")
2716 (set_attr "type" "multiple")]
2717)
2718
a0f94409 2719(define_insn_and_split "*anddi_notsesidi_di"
9c08d1fa 2720 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2721 (and:DI (not:DI (sign_extend:DI
2722 (match_operand:SI 2 "s_register_operand" "r,r")))
5a097f7d 2723 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2724 "TARGET_32BIT"
f6ebffac 2725 "#"
25f905c2 2726 "TARGET_32BIT && reload_completed"
5a097f7d 2727 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
a0f94409 2728 (set (match_dup 3) (and:SI (not:SI
2729 (ashiftrt:SI (match_dup 2) (const_int 31)))
2730 (match_dup 4)))]
2731 "
2732 {
2733 operands[3] = gen_highpart (SImode, operands[0]);
2734 operands[0] = gen_lowpart (SImode, operands[0]);
2735 operands[4] = gen_highpart (SImode, operands[1]);
2736 operands[1] = gen_lowpart (SImode, operands[1]);
2737 }"
0d66636f 2738 [(set_attr "length" "8")
d952d547 2739 (set_attr "predicable" "yes")
1b7da4ac 2740 (set_attr "predicable_short_it" "no")
2741 (set_attr "type" "multiple")]
0d66636f 2742)
d952d547 2743
8a18b90c 2744(define_insn "andsi_notsi_si"
9c08d1fa 2745 [(set (match_operand:SI 0 "s_register_operand" "=r")
2746 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2747 (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 2748 "TARGET_32BIT"
0d66636f 2749 "bic%?\\t%0, %1, %2"
d952d547 2750 [(set_attr "predicable" "yes")
1b7da4ac 2751 (set_attr "predicable_short_it" "no")
2752 (set_attr "type" "logic_reg")]
0d66636f 2753)
b11cae9e 2754
8a18b90c 2755(define_insn "andsi_not_shiftsi_si"
a2cd141b 2756 [(set (match_operand:SI 0 "s_register_operand" "=r")
2757 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2758 [(match_operand:SI 2 "s_register_operand" "r")
2759 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2760 (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 2761 "TARGET_ARM"
6c4c2133 2762 "bic%?\\t%0, %1, %2%S4"
344495ea 2763 [(set_attr "predicable" "yes")
331beb1a 2764 (set_attr "shift" "2")
a2cd141b 2765 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
d82e788e 2766 (const_string "logic_shift_imm")
2767 (const_string "logic_shift_reg")))]
6c4c2133 2768)
8a18b90c 2769
f7fbdd4a 2770(define_insn "*andsi_notsi_si_compare0"
bd5b4116 2771 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 2772 (compare:CC_NOOV
2773 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2774 (match_operand:SI 1 "s_register_operand" "r"))
2775 (const_int 0)))
9c08d1fa 2776 (set (match_operand:SI 0 "s_register_operand" "=r")
2777 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
25f905c2 2778 "TARGET_32BIT"
2779 "bic%.\\t%0, %1, %2"
d82e788e 2780 [(set_attr "conds" "set")
2781 (set_attr "type" "logics_shift_reg")]
0d66636f 2782)
9c08d1fa 2783
f7fbdd4a 2784(define_insn "*andsi_notsi_si_compare0_scratch"
bd5b4116 2785 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 2786 (compare:CC_NOOV
2787 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2788 (match_operand:SI 1 "s_register_operand" "r"))
2789 (const_int 0)))
9c08d1fa 2790 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 2791 "TARGET_32BIT"
2792 "bic%.\\t%0, %1, %2"
d82e788e 2793 [(set_attr "conds" "set")
2794 (set_attr "type" "logics_shift_reg")]
0d66636f 2795)
9c08d1fa 2796
e2669ea7 2797(define_expand "iordi3"
2798 [(set (match_operand:DI 0 "s_register_operand" "")
2799 (ior:DI (match_operand:DI 1 "s_register_operand" "")
2800 (match_operand:DI 2 "neon_logic_op2" "")))]
2801 "TARGET_32BIT"
2802 ""
2803)
2804
74d6113f 2805(define_insn_and_split "*iordi3_insn"
2806 [(set (match_operand:DI 0 "s_register_operand" "=w,w ,&r,&r,&r,&r,?w,?w")
2807 (ior:DI (match_operand:DI 1 "s_register_operand" "%w,0 ,0 ,r ,0 ,r ,w ,0")
e0fe6977 2808 (match_operand:DI 2 "arm_iordi_operand_neon" "w ,Dl,r ,r ,Df,Df,w ,Dl")))]
74d6113f 2809 "TARGET_32BIT && !TARGET_IWMMXT"
2810 {
2811 switch (which_alternative)
2812 {
2813 case 0: /* fall through */
2814 case 6: return "vorr\t%P0, %P1, %P2";
2815 case 1: /* fall through */
2816 case 7: return neon_output_logic_immediate ("vorr", &operands[2],
2817 DImode, 0, VALID_NEON_QREG_MODE (DImode));
2818 case 2:
2819 case 3:
2820 case 4:
2821 case 5:
2822 return "#";
2823 default: gcc_unreachable ();
2824 }
2825 }
2826 "TARGET_32BIT && !TARGET_IWMMXT && reload_completed
2827 && !(IS_VFP_REGNUM (REGNO (operands[0])))"
2828 [(set (match_dup 3) (match_dup 4))
2829 (set (match_dup 5) (match_dup 6))]
2830 "
2831 {
2832 operands[3] = gen_lowpart (SImode, operands[0]);
2833 operands[5] = gen_highpart (SImode, operands[0]);
2834
2835 operands[4] = simplify_gen_binary (IOR, SImode,
2836 gen_lowpart (SImode, operands[1]),
2837 gen_lowpart (SImode, operands[2]));
2838 operands[6] = simplify_gen_binary (IOR, SImode,
2839 gen_highpart (SImode, operands[1]),
2840 gen_highpart_mode (SImode, DImode, operands[2]));
2841
2842 }"
32093010 2843 [(set_attr "type" "neon_logic,neon_logic,multiple,multiple,multiple,\
2844 multiple,neon_logic,neon_logic")
e0fe6977 2845 (set_attr "length" "*,*,8,8,8,8,*,*")
74d6113f 2846 (set_attr "arch" "neon_for_64bits,neon_for_64bits,*,*,*,*,avoid_neon_for_64bits,avoid_neon_for_64bits")]
cffb2a26 2847)
9c08d1fa 2848
f7fbdd4a 2849(define_insn "*iordi_zesidi_di"
9c08d1fa 2850 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2851 (ior:DI (zero_extend:DI
2852 (match_operand:SI 2 "s_register_operand" "r,r"))
e2348bcb 2853 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 2854 "TARGET_32BIT"
e2348bcb 2855 "@
97499065 2856 orr%?\\t%Q0, %Q1, %2
f6ebffac 2857 #"
0d66636f 2858 [(set_attr "length" "4,8")
d952d547 2859 (set_attr "predicable" "yes")
1b7da4ac 2860 (set_attr "predicable_short_it" "no")
2861 (set_attr "type" "logic_reg,multiple")]
cffb2a26 2862)
9c08d1fa 2863
f7fbdd4a 2864(define_insn "*iordi_sesidi_di"
9c08d1fa 2865 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2866 (ior:DI (sign_extend:DI
2867 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 2868 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2869 "TARGET_32BIT"
f6ebffac 2870 "#"
0d66636f 2871 [(set_attr "length" "8")
1b7da4ac 2872 (set_attr "predicable" "yes")
2873 (set_attr "type" "multiple")]
cffb2a26 2874)
9c08d1fa 2875
87b22bf7 2876(define_expand "iorsi3"
cffb2a26 2877 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2878 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2879 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 2880 "TARGET_EITHER"
87b22bf7 2881 "
0438d37f 2882 if (CONST_INT_P (operands[2]))
87b22bf7 2883 {
25f905c2 2884 if (TARGET_32BIT)
cffb2a26 2885 {
96f57e36 2886 arm_split_constant (IOR, SImode, NULL_RTX,
2887 INTVAL (operands[2]), operands[0], operands[1],
e1ba4a27 2888 optimize && can_create_pseudo_p ());
cffb2a26 2889 DONE;
2890 }
25f905c2 2891 else /* TARGET_THUMB1 */
923ffadb 2892 {
2893 rtx tmp = force_reg (SImode, operands[2]);
2894 if (rtx_equal_p (operands[0], operands[1]))
2895 operands[2] = tmp;
2896 else
2897 {
2898 operands[2] = operands[1];
2899 operands[1] = tmp;
2900 }
2901 }
87b22bf7 2902 }
cffb2a26 2903 "
2904)
87b22bf7 2905
d5d4dc8d 2906(define_insn_and_split "*iorsi3_insn"
29e234a3 2907 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r,r,r")
2908 (ior:SI (match_operand:SI 1 "s_register_operand" "%r,0,r,r,r")
2909 (match_operand:SI 2 "reg_or_int_operand" "I,l,K,r,?n")))]
d5d4dc8d 2910 "TARGET_32BIT"
87b22bf7 2911 "@
29e234a3 2912 orr%?\\t%0, %1, %2
87b22bf7 2913 orr%?\\t%0, %1, %2
d5d4dc8d 2914 orn%?\\t%0, %1, #%B2
65f68e55 2915 orr%?\\t%0, %1, %2
87b22bf7 2916 #"
d5d4dc8d 2917 "TARGET_32BIT
0438d37f 2918 && CONST_INT_P (operands[2])
d5d4dc8d 2919 && !(const_ok_for_arm (INTVAL (operands[2]))
2920 || (TARGET_THUMB2 && const_ok_for_arm (~INTVAL (operands[2]))))"
a0f94409 2921 [(clobber (const_int 0))]
d5d4dc8d 2922{
29e234a3 2923 arm_split_constant (IOR, SImode, curr_insn,
96f57e36 2924 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 2925 DONE;
d5d4dc8d 2926}
29e234a3 2927 [(set_attr "length" "4,4,4,4,16")
2928 (set_attr "arch" "32,t2,t2,32,32")
65f68e55 2929 (set_attr "predicable" "yes")
29e234a3 2930 (set_attr "predicable_short_it" "no,yes,no,no,no")
d82e788e 2931 (set_attr "type" "logic_imm,logic_reg,logic_imm,logic_reg,logic_reg")]
65f68e55 2932)
cffb2a26 2933
a0f94409 2934(define_peephole2
2935 [(match_scratch:SI 3 "r")
372575c7 2936 (set (match_operand:SI 0 "arm_general_register_operand" "")
2937 (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
87b22bf7 2938 (match_operand:SI 2 "const_int_operand" "")))]
90560cad 2939 "TARGET_ARM
a0f94409 2940 && !const_ok_for_arm (INTVAL (operands[2]))
2941 && const_ok_for_arm (~INTVAL (operands[2]))"
2942 [(set (match_dup 3) (match_dup 2))
2943 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2944 ""
215b30b3 2945)
a0f94409 2946
f7fbdd4a 2947(define_insn "*iorsi3_compare0"
bd5b4116 2948 [(set (reg:CC_NOOV CC_REGNUM)
65f68e55 2949 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r,r")
2950 (match_operand:SI 2 "arm_rhs_operand" "I,r"))
9c08d1fa 2951 (const_int 0)))
65f68e55 2952 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 2953 (ior:SI (match_dup 1) (match_dup 2)))]
25f905c2 2954 "TARGET_32BIT"
2955 "orr%.\\t%0, %1, %2"
65f68e55 2956 [(set_attr "conds" "set")
d82e788e 2957 (set_attr "type" "logics_imm,logics_reg")]
cffb2a26 2958)
9c08d1fa 2959
f7fbdd4a 2960(define_insn "*iorsi3_compare0_scratch"
bd5b4116 2961 [(set (reg:CC_NOOV CC_REGNUM)
65f68e55 2962 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r,r")
2963 (match_operand:SI 2 "arm_rhs_operand" "I,r"))
9c08d1fa 2964 (const_int 0)))
65f68e55 2965 (clobber (match_scratch:SI 0 "=r,r"))]
25f905c2 2966 "TARGET_32BIT"
2967 "orr%.\\t%0, %1, %2"
65f68e55 2968 [(set_attr "conds" "set")
d82e788e 2969 (set_attr "type" "logics_imm,logics_reg")]
0d66636f 2970)
9c08d1fa 2971
e2669ea7 2972(define_expand "xordi3"
2973 [(set (match_operand:DI 0 "s_register_operand" "")
2974 (xor:DI (match_operand:DI 1 "s_register_operand" "")
8ee7dc6f 2975 (match_operand:DI 2 "arm_xordi_operand" "")))]
e2669ea7 2976 "TARGET_32BIT"
2977 ""
2978)
2979
8ee7dc6f 2980(define_insn_and_split "*xordi3_insn"
2981 [(set (match_operand:DI 0 "s_register_operand" "=w,&r,&r,&r,&r,?w")
205c3b0a 2982 (xor:DI (match_operand:DI 1 "s_register_operand" "%w ,0,r ,0 ,r ,w")
8ee7dc6f 2983 (match_operand:DI 2 "arm_xordi_operand" "w ,r ,r ,Dg,Dg,w")))]
2984 "TARGET_32BIT && !TARGET_IWMMXT"
2985{
2986 switch (which_alternative)
2987 {
2988 case 1:
2989 case 2:
2990 case 3:
2991 case 4: /* fall through */
2992 return "#";
2993 case 0: /* fall through */
2994 case 5: return "veor\t%P0, %P1, %P2";
2995 default: gcc_unreachable ();
2996 }
2997}
2998 "TARGET_32BIT && !TARGET_IWMMXT && reload_completed
2999 && !(IS_VFP_REGNUM (REGNO (operands[0])))"
3000 [(set (match_dup 3) (match_dup 4))
3001 (set (match_dup 5) (match_dup 6))]
3002 "
3003 {
3004 operands[3] = gen_lowpart (SImode, operands[0]);
3005 operands[5] = gen_highpart (SImode, operands[0]);
3006
3007 operands[4] = simplify_gen_binary (XOR, SImode,
3008 gen_lowpart (SImode, operands[1]),
3009 gen_lowpart (SImode, operands[2]));
3010 operands[6] = simplify_gen_binary (XOR, SImode,
3011 gen_highpart (SImode, operands[1]),
3012 gen_highpart_mode (SImode, DImode, operands[2]));
3013
3014 }"
3015 [(set_attr "length" "*,8,8,8,8,*")
32093010 3016 (set_attr "type" "neon_logic,multiple,multiple,multiple,multiple,neon_logic")
8ee7dc6f 3017 (set_attr "arch" "neon_for_64bits,*,*,*,*,avoid_neon_for_64bits")]
cffb2a26 3018)
9c08d1fa 3019
f7fbdd4a 3020(define_insn "*xordi_zesidi_di"
9c08d1fa 3021 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3022 (xor:DI (zero_extend:DI
3023 (match_operand:SI 2 "s_register_operand" "r,r"))
e2348bcb 3024 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 3025 "TARGET_32BIT"
e2348bcb 3026 "@
97499065 3027 eor%?\\t%Q0, %Q1, %2
f6ebffac 3028 #"
0d66636f 3029 [(set_attr "length" "4,8")
d952d547 3030 (set_attr "predicable" "yes")
1b7da4ac 3031 (set_attr "predicable_short_it" "no")
3032 (set_attr "type" "logic_reg")]
cffb2a26 3033)
9c08d1fa 3034
f7fbdd4a 3035(define_insn "*xordi_sesidi_di"
9c08d1fa 3036 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3037 (xor:DI (sign_extend:DI
3038 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 3039 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 3040 "TARGET_32BIT"
f6ebffac 3041 "#"
0d66636f 3042 [(set_attr "length" "8")
1b7da4ac 3043 (set_attr "predicable" "yes")
3044 (set_attr "type" "multiple")]
cffb2a26 3045)
9c08d1fa 3046
cffb2a26 3047(define_expand "xorsi3"
3048 [(set (match_operand:SI 0 "s_register_operand" "")
3049 (xor:SI (match_operand:SI 1 "s_register_operand" "")
923ffadb 3050 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 3051 "TARGET_EITHER"
0438d37f 3052 "if (CONST_INT_P (operands[2]))
923ffadb 3053 {
3054 if (TARGET_32BIT)
3055 {
3056 arm_split_constant (XOR, SImode, NULL_RTX,
3057 INTVAL (operands[2]), operands[0], operands[1],
3058 optimize && can_create_pseudo_p ());
3059 DONE;
3060 }
3061 else /* TARGET_THUMB1 */
3062 {
3063 rtx tmp = force_reg (SImode, operands[2]);
3064 if (rtx_equal_p (operands[0], operands[1]))
3065 operands[2] = tmp;
3066 else
3067 {
3068 operands[2] = operands[1];
3069 operands[1] = tmp;
3070 }
3071 }
3072 }"
cffb2a26 3073)
3074
5dcb35d9 3075(define_insn_and_split "*arm_xorsi3"
29e234a3 3076 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r,r")
3077 (xor:SI (match_operand:SI 1 "s_register_operand" "%r,0,r,r")
3078 (match_operand:SI 2 "reg_or_int_operand" "I,l,r,?n")))]
25f905c2 3079 "TARGET_32BIT"
5dcb35d9 3080 "@
29e234a3 3081 eor%?\\t%0, %1, %2
65f68e55 3082 eor%?\\t%0, %1, %2
5dcb35d9 3083 eor%?\\t%0, %1, %2
3084 #"
3085 "TARGET_32BIT
0438d37f 3086 && CONST_INT_P (operands[2])
5dcb35d9 3087 && !const_ok_for_arm (INTVAL (operands[2]))"
3088 [(clobber (const_int 0))]
3089{
3090 arm_split_constant (XOR, SImode, curr_insn,
3091 INTVAL (operands[2]), operands[0], operands[1], 0);
3092 DONE;
3093}
29e234a3 3094 [(set_attr "length" "4,4,4,16")
65f68e55 3095 (set_attr "predicable" "yes")
29e234a3 3096 (set_attr "predicable_short_it" "no,yes,no,no")
1b7da4ac 3097 (set_attr "type" "logic_imm,logic_reg,logic_reg,multiple")]
cffb2a26 3098)
3099
f7fbdd4a 3100(define_insn "*xorsi3_compare0"
bd5b4116 3101 [(set (reg:CC_NOOV CC_REGNUM)
65f68e55 3102 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r,r")
3103 (match_operand:SI 2 "arm_rhs_operand" "I,r"))
9c08d1fa 3104 (const_int 0)))
65f68e55 3105 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 3106 (xor:SI (match_dup 1) (match_dup 2)))]
25f905c2 3107 "TARGET_32BIT"
3108 "eor%.\\t%0, %1, %2"
65f68e55 3109 [(set_attr "conds" "set")
d82e788e 3110 (set_attr "type" "logics_imm,logics_reg")]
0d66636f 3111)
9c08d1fa 3112
f7fbdd4a 3113(define_insn "*xorsi3_compare0_scratch"
bd5b4116 3114 [(set (reg:CC_NOOV CC_REGNUM)
65f68e55 3115 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r,r")
3116 (match_operand:SI 1 "arm_rhs_operand" "I,r"))
9c08d1fa 3117 (const_int 0)))]
25f905c2 3118 "TARGET_32BIT"
40dbec34 3119 "teq%?\\t%0, %1"
65f68e55 3120 [(set_attr "conds" "set")
d82e788e 3121 (set_attr "type" "logics_imm,logics_reg")]
cffb2a26 3122)
9c08d1fa 3123
215b30b3 3124; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
3125; (NOT D) we can sometimes merge the final NOT into one of the following
3126; insns.
9c08d1fa 3127
3128(define_split
a058e94a 3129 [(set (match_operand:SI 0 "s_register_operand" "")
3130 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
3131 (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
3132 (match_operand:SI 3 "arm_rhs_operand" "")))
3133 (clobber (match_operand:SI 4 "s_register_operand" ""))]
25f905c2 3134 "TARGET_32BIT"
9c08d1fa 3135 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
3136 (not:SI (match_dup 3))))
3137 (set (match_dup 0) (not:SI (match_dup 4)))]
3138 ""
3139)
3140
ba6a3b2f 3141(define_insn_and_split "*andsi_iorsi3_notsi"
9c08d1fa 3142 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
e5fea38e 3143 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "%0,r,r")
9c08d1fa 3144 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
3145 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
25f905c2 3146 "TARGET_32BIT"
ba6a3b2f 3147 "#" ; "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
3148 "&& reload_completed"
3149 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
3150 (set (match_dup 0) (and:SI (not:SI (match_dup 3)) (match_dup 0)))]
3151 ""
0d66636f 3152 [(set_attr "length" "8")
25f905c2 3153 (set_attr "ce_count" "2")
d952d547 3154 (set_attr "predicable" "yes")
1b7da4ac 3155 (set_attr "predicable_short_it" "no")
3156 (set_attr "type" "multiple")]
cffb2a26 3157)
9c08d1fa 3158
25f905c2 3159; ??? Are these four splitters still beneficial when the Thumb-2 bitfield
3160; insns are available?
d7863cfe 3161(define_split
3162 [(set (match_operand:SI 0 "s_register_operand" "")
3163 (match_operator:SI 1 "logical_binary_operator"
3164 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
3165 (match_operand:SI 3 "const_int_operand" "")
3166 (match_operand:SI 4 "const_int_operand" ""))
3167 (match_operator:SI 9 "logical_binary_operator"
3168 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3169 (match_operand:SI 6 "const_int_operand" ""))
3170 (match_operand:SI 7 "s_register_operand" "")])]))
3171 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3172 "TARGET_32BIT
d7863cfe 3173 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3174 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3175 [(set (match_dup 8)
3176 (match_op_dup 1
3177 [(ashift:SI (match_dup 2) (match_dup 4))
3178 (match_dup 5)]))
3179 (set (match_dup 0)
3180 (match_op_dup 1
3181 [(lshiftrt:SI (match_dup 8) (match_dup 6))
3182 (match_dup 7)]))]
3183 "
3184 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3185")
3186
3187(define_split
3188 [(set (match_operand:SI 0 "s_register_operand" "")
3189 (match_operator:SI 1 "logical_binary_operator"
3190 [(match_operator:SI 9 "logical_binary_operator"
3191 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3192 (match_operand:SI 6 "const_int_operand" ""))
3193 (match_operand:SI 7 "s_register_operand" "")])
3194 (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
3195 (match_operand:SI 3 "const_int_operand" "")
3196 (match_operand:SI 4 "const_int_operand" ""))]))
3197 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3198 "TARGET_32BIT
d7863cfe 3199 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3200 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3201 [(set (match_dup 8)
3202 (match_op_dup 1
3203 [(ashift:SI (match_dup 2) (match_dup 4))
3204 (match_dup 5)]))
3205 (set (match_dup 0)
3206 (match_op_dup 1
3207 [(lshiftrt:SI (match_dup 8) (match_dup 6))
3208 (match_dup 7)]))]
3209 "
3210 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3211")
3212
3213(define_split
3214 [(set (match_operand:SI 0 "s_register_operand" "")
3215 (match_operator:SI 1 "logical_binary_operator"
3216 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
3217 (match_operand:SI 3 "const_int_operand" "")
3218 (match_operand:SI 4 "const_int_operand" ""))
3219 (match_operator:SI 9 "logical_binary_operator"
3220 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3221 (match_operand:SI 6 "const_int_operand" ""))
3222 (match_operand:SI 7 "s_register_operand" "")])]))
3223 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3224 "TARGET_32BIT
d7863cfe 3225 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3226 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3227 [(set (match_dup 8)
3228 (match_op_dup 1
3229 [(ashift:SI (match_dup 2) (match_dup 4))
3230 (match_dup 5)]))
3231 (set (match_dup 0)
3232 (match_op_dup 1
3233 [(ashiftrt:SI (match_dup 8) (match_dup 6))
3234 (match_dup 7)]))]
3235 "
3236 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3237")
3238
3239(define_split
3240 [(set (match_operand:SI 0 "s_register_operand" "")
3241 (match_operator:SI 1 "logical_binary_operator"
3242 [(match_operator:SI 9 "logical_binary_operator"
3243 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3244 (match_operand:SI 6 "const_int_operand" ""))
3245 (match_operand:SI 7 "s_register_operand" "")])
3246 (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
3247 (match_operand:SI 3 "const_int_operand" "")
3248 (match_operand:SI 4 "const_int_operand" ""))]))
3249 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3250 "TARGET_32BIT
d7863cfe 3251 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3252 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3253 [(set (match_dup 8)
3254 (match_op_dup 1
3255 [(ashift:SI (match_dup 2) (match_dup 4))
3256 (match_dup 5)]))
3257 (set (match_dup 0)
3258 (match_op_dup 1
3259 [(ashiftrt:SI (match_dup 8) (match_dup 6))
3260 (match_dup 7)]))]
3261 "
3262 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3263")
9c08d1fa 3264\f
3265
3266;; Minimum and maximum insns
3267
8b9dc177 3268(define_expand "smaxsi3"
3269 [(parallel [
3270 (set (match_operand:SI 0 "s_register_operand" "")
3271 (smax:SI (match_operand:SI 1 "s_register_operand" "")
3272 (match_operand:SI 2 "arm_rhs_operand" "")))
3273 (clobber (reg:CC CC_REGNUM))])]
25f905c2 3274 "TARGET_32BIT"
8b9dc177 3275 "
8774928b 3276 if (operands[2] == const0_rtx || operands[2] == constm1_rtx)
8b9dc177 3277 {
3278 /* No need for a clobber of the condition code register here. */
3279 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3280 gen_rtx_SMAX (SImode, operands[1],
3281 operands[2])));
3282 DONE;
3283 }
3284")
3285
3286(define_insn "*smax_0"
3287 [(set (match_operand:SI 0 "s_register_operand" "=r")
3288 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3289 (const_int 0)))]
25f905c2 3290 "TARGET_32BIT"
8b9dc177 3291 "bic%?\\t%0, %1, %1, asr #31"
d952d547 3292 [(set_attr "predicable" "yes")
1b7da4ac 3293 (set_attr "predicable_short_it" "no")
3294 (set_attr "type" "logic_shift_reg")]
8b9dc177 3295)
3296
8774928b 3297(define_insn "*smax_m1"
3298 [(set (match_operand:SI 0 "s_register_operand" "=r")
3299 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3300 (const_int -1)))]
25f905c2 3301 "TARGET_32BIT"
8774928b 3302 "orr%?\\t%0, %1, %1, asr #31"
d952d547 3303 [(set_attr "predicable" "yes")
1b7da4ac 3304 (set_attr "predicable_short_it" "no")
3305 (set_attr "type" "logic_shift_reg")]
8774928b 3306)
3307
3dc953f2 3308(define_insn_and_split "*arm_smax_insn"
8b9dc177 3309 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3310 (smax:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3311 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
bd5b4116 3312 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3313 "TARGET_ARM"
3dc953f2 3314 "#"
3315 ; cmp\\t%1, %2\;movlt\\t%0, %2
3316 ; cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
3317 "TARGET_ARM"
3318 [(set (reg:CC CC_REGNUM)
3319 (compare:CC (match_dup 1) (match_dup 2)))
3320 (set (match_dup 0)
3321 (if_then_else:SI (ge:SI (reg:CC CC_REGNUM) (const_int 0))
3322 (match_dup 1)
3323 (match_dup 2)))]
3324 ""
cffb2a26 3325 [(set_attr "conds" "clob")
1b7da4ac 3326 (set_attr "length" "8,12")
3327 (set_attr "type" "multiple")]
cffb2a26 3328)
9c08d1fa 3329
8b9dc177 3330(define_expand "sminsi3"
3331 [(parallel [
3332 (set (match_operand:SI 0 "s_register_operand" "")
3333 (smin:SI (match_operand:SI 1 "s_register_operand" "")
3334 (match_operand:SI 2 "arm_rhs_operand" "")))
3335 (clobber (reg:CC CC_REGNUM))])]
25f905c2 3336 "TARGET_32BIT"
8b9dc177 3337 "
3338 if (operands[2] == const0_rtx)
3339 {
3340 /* No need for a clobber of the condition code register here. */
3341 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3342 gen_rtx_SMIN (SImode, operands[1],
3343 operands[2])));
3344 DONE;
3345 }
3346")
3347
3348(define_insn "*smin_0"
3349 [(set (match_operand:SI 0 "s_register_operand" "=r")
3350 (smin:SI (match_operand:SI 1 "s_register_operand" "r")
3351 (const_int 0)))]
25f905c2 3352 "TARGET_32BIT"
8b9dc177 3353 "and%?\\t%0, %1, %1, asr #31"
d952d547 3354 [(set_attr "predicable" "yes")
1b7da4ac 3355 (set_attr "predicable_short_it" "no")
3356 (set_attr "type" "logic_shift_reg")]
8b9dc177 3357)
3358
3dc953f2 3359(define_insn_and_split "*arm_smin_insn"
8b9dc177 3360 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3361 (smin:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3362 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
bd5b4116 3363 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3364 "TARGET_ARM"
3dc953f2 3365 "#"
3366 ; cmp\\t%1, %2\;movge\\t%0, %2
3367 ; cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
3368 "TARGET_ARM"
3369 [(set (reg:CC CC_REGNUM)
3370 (compare:CC (match_dup 1) (match_dup 2)))
3371 (set (match_dup 0)
3372 (if_then_else:SI (lt:SI (reg:CC CC_REGNUM) (const_int 0))
3373 (match_dup 1)
3374 (match_dup 2)))]
3375 ""
0d66636f 3376 [(set_attr "conds" "clob")
1b7da4ac 3377 (set_attr "length" "8,12")
3378 (set_attr "type" "multiple,multiple")]
0d66636f 3379)
9c08d1fa 3380
25f905c2 3381(define_expand "umaxsi3"
3382 [(parallel [
3383 (set (match_operand:SI 0 "s_register_operand" "")
3384 (umax:SI (match_operand:SI 1 "s_register_operand" "")
3385 (match_operand:SI 2 "arm_rhs_operand" "")))
3386 (clobber (reg:CC CC_REGNUM))])]
3387 "TARGET_32BIT"
3388 ""
3389)
3390
3dc953f2 3391(define_insn_and_split "*arm_umaxsi3"
9c08d1fa 3392 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3393 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3394 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 3395 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3396 "TARGET_ARM"
3dc953f2 3397 "#"
3398 ; cmp\\t%1, %2\;movcc\\t%0, %2
3399 ; cmp\\t%1, %2\;movcs\\t%0, %1
3400 ; cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
3401 "TARGET_ARM"
3402 [(set (reg:CC CC_REGNUM)
3403 (compare:CC (match_dup 1) (match_dup 2)))
3404 (set (match_dup 0)
3405 (if_then_else:SI (geu:SI (reg:CC CC_REGNUM) (const_int 0))
3406 (match_dup 1)
3407 (match_dup 2)))]
3408 ""
0d66636f 3409 [(set_attr "conds" "clob")
1b7da4ac 3410 (set_attr "length" "8,8,12")
3411 (set_attr "type" "store1")]
0d66636f 3412)
9c08d1fa 3413
25f905c2 3414(define_expand "uminsi3"
3415 [(parallel [
3416 (set (match_operand:SI 0 "s_register_operand" "")
3417 (umin:SI (match_operand:SI 1 "s_register_operand" "")
3418 (match_operand:SI 2 "arm_rhs_operand" "")))
3419 (clobber (reg:CC CC_REGNUM))])]
3420 "TARGET_32BIT"
3421 ""
3422)
3423
3dc953f2 3424(define_insn_and_split "*arm_uminsi3"
9c08d1fa 3425 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3426 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3427 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 3428 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3429 "TARGET_ARM"
3dc953f2 3430 "#"
3431 ; cmp\\t%1, %2\;movcs\\t%0, %2
3432 ; cmp\\t%1, %2\;movcc\\t%0, %1
3433 ; cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
3434 "TARGET_ARM"
3435 [(set (reg:CC CC_REGNUM)
3436 (compare:CC (match_dup 1) (match_dup 2)))
3437 (set (match_dup 0)
3438 (if_then_else:SI (ltu:SI (reg:CC CC_REGNUM) (const_int 0))
3439 (match_dup 1)
3440 (match_dup 2)))]
3441 ""
0d66636f 3442 [(set_attr "conds" "clob")
1b7da4ac 3443 (set_attr "length" "8,8,12")
3444 (set_attr "type" "store1")]
0d66636f 3445)
9c08d1fa 3446
8a18b90c 3447(define_insn "*store_minmaxsi"
9c08d1fa 3448 [(set (match_operand:SI 0 "memory_operand" "=m")
3449 (match_operator:SI 3 "minmax_operator"
3450 [(match_operand:SI 1 "s_register_operand" "r")
3451 (match_operand:SI 2 "s_register_operand" "r")]))
bd5b4116 3452 (clobber (reg:CC CC_REGNUM))]
b207d152 3453 "TARGET_32BIT && optimize_function_for_size_p (cfun) && !arm_restrict_it"
9c08d1fa 3454 "*
dc55b8a9 3455 operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
3456 operands[1], operands[2]);
e2348bcb 3457 output_asm_insn (\"cmp\\t%1, %2\", operands);
25f905c2 3458 if (TARGET_THUMB2)
3459 output_asm_insn (\"ite\t%d3\", operands);
e2348bcb 3460 output_asm_insn (\"str%d3\\t%1, %0\", operands);
3461 output_asm_insn (\"str%D3\\t%2, %0\", operands);
3462 return \"\";
0d66636f 3463 "
3464 [(set_attr "conds" "clob")
25f905c2 3465 (set (attr "length")
3466 (if_then_else (eq_attr "is_thumb" "yes")
3467 (const_int 14)
3468 (const_int 12)))
0d66636f 3469 (set_attr "type" "store1")]
3470)
9c08d1fa 3471
8a18b90c 3472; Reject the frame pointer in operand[1], since reloading this after
3473; it has been eliminated can cause carnage.
f7fbdd4a 3474(define_insn "*minmax_arithsi"
9c08d1fa 3475 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3476 (match_operator:SI 4 "shiftable_operator"
3477 [(match_operator:SI 5 "minmax_operator"
3478 [(match_operand:SI 2 "s_register_operand" "r,r")
3479 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
3480 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 3481 (clobber (reg:CC CC_REGNUM))]
7c36fe71 3482 "TARGET_32BIT && !arm_eliminable_register (operands[1]) && !arm_restrict_it"
9c08d1fa 3483 "*
0d66636f 3484 {
3485 enum rtx_code code = GET_CODE (operands[4]);
25f905c2 3486 bool need_else;
3487
3488 if (which_alternative != 0 || operands[3] != const0_rtx
ca0fc5a2 3489 || (code != PLUS && code != IOR && code != XOR))
25f905c2 3490 need_else = true;
3491 else
3492 need_else = false;
0d66636f 3493
dc55b8a9 3494 operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
3495 operands[2], operands[3]);
0d66636f 3496 output_asm_insn (\"cmp\\t%2, %3\", operands);
25f905c2 3497 if (TARGET_THUMB2)
3498 {
3499 if (need_else)
3500 output_asm_insn (\"ite\\t%d5\", operands);
3501 else
3502 output_asm_insn (\"it\\t%d5\", operands);
3503 }
0d66636f 3504 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
25f905c2 3505 if (need_else)
0d66636f 3506 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
3507 return \"\";
215b30b3 3508 }"
0d66636f 3509 [(set_attr "conds" "clob")
25f905c2 3510 (set (attr "length")
3511 (if_then_else (eq_attr "is_thumb" "yes")
3512 (const_int 14)
1b7da4ac 3513 (const_int 12)))
3514 (set_attr "type" "multiple")]
0d66636f 3515)
9c08d1fa 3516
4164bca1 3517; Reject the frame pointer in operand[1], since reloading this after
3518; it has been eliminated can cause carnage.
3519(define_insn_and_split "*minmax_arithsi_non_canon"
7c36fe71 3520 [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts")
4164bca1 3521 (minus:SI
7c36fe71 3522 (match_operand:SI 1 "s_register_operand" "0,?Ts")
4164bca1 3523 (match_operator:SI 4 "minmax_operator"
7c36fe71 3524 [(match_operand:SI 2 "s_register_operand" "Ts,Ts")
3525 (match_operand:SI 3 "arm_rhs_operand" "TsI,TsI")])))
4164bca1 3526 (clobber (reg:CC CC_REGNUM))]
7c36fe71 3527 "TARGET_32BIT && !arm_eliminable_register (operands[1])
3528 && !(arm_restrict_it && CONST_INT_P (operands[3]))"
4164bca1 3529 "#"
3530 "TARGET_32BIT && !arm_eliminable_register (operands[1]) && reload_completed"
3531 [(set (reg:CC CC_REGNUM)
3532 (compare:CC (match_dup 2) (match_dup 3)))
3533
3534 (cond_exec (match_op_dup 4 [(reg:CC CC_REGNUM) (const_int 0)])
3535 (set (match_dup 0)
3536 (minus:SI (match_dup 1)
3537 (match_dup 2))))
3538 (cond_exec (match_op_dup 5 [(reg:CC CC_REGNUM) (const_int 0)])
3539 (set (match_dup 0)
36ee0cde 3540 (match_dup 6)))]
4164bca1 3541 {
3754d046 3542 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
4164bca1 3543 operands[2], operands[3]);
3544 enum rtx_code rc = minmax_code (operands[4]);
3545 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode,
3546 operands[2], operands[3]);
3547
3548 if (mode == CCFPmode || mode == CCFPEmode)
3549 rc = reverse_condition_maybe_unordered (rc);
3550 else
3551 rc = reverse_condition (rc);
3552 operands[5] = gen_rtx_fmt_ee (rc, SImode, operands[2], operands[3]);
36ee0cde 3553 if (CONST_INT_P (operands[3]))
3554 operands[6] = plus_constant (SImode, operands[1], -INTVAL (operands[3]));
3555 else
3556 operands[6] = gen_rtx_MINUS (SImode, operands[1], operands[3]);
4164bca1 3557 }
3558 [(set_attr "conds" "clob")
3559 (set (attr "length")
3560 (if_then_else (eq_attr "is_thumb" "yes")
3561 (const_int 14)
1b7da4ac 3562 (const_int 12)))
3563 (set_attr "type" "multiple")]
4164bca1 3564)
3565
b49e3742 3566(define_code_iterator SAT [smin smax])
3567(define_code_iterator SATrev [smin smax])
3568(define_code_attr SATlo [(smin "1") (smax "2")])
3569(define_code_attr SAThi [(smin "2") (smax "1")])
3570
3571(define_insn "*satsi_<SAT:code>"
3572 [(set (match_operand:SI 0 "s_register_operand" "=r")
3573 (SAT:SI (SATrev:SI (match_operand:SI 3 "s_register_operand" "r")
3574 (match_operand:SI 1 "const_int_operand" "i"))
3575 (match_operand:SI 2 "const_int_operand" "i")))]
3576 "TARGET_32BIT && arm_arch6 && <SAT:CODE> != <SATrev:CODE>
3577 && arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>], NULL, NULL)"
3578{
3579 int mask;
3580 bool signed_sat;
3581 if (!arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>],
3582 &mask, &signed_sat))
3583 gcc_unreachable ();
3584
3585 operands[1] = GEN_INT (mask);
3586 if (signed_sat)
3587 return "ssat%?\t%0, %1, %3";
3588 else
3589 return "usat%?\t%0, %1, %3";
3590}
7c36fe71 3591 [(set_attr "predicable" "yes")
1b7da4ac 3592 (set_attr "predicable_short_it" "no")
3593 (set_attr "type" "alus_imm")]
bebe9bbb 3594)
b49e3742 3595
3596(define_insn "*satsi_<SAT:code>_shift"
3597 [(set (match_operand:SI 0 "s_register_operand" "=r")
3598 (SAT:SI (SATrev:SI (match_operator:SI 3 "sat_shift_operator"
3599 [(match_operand:SI 4 "s_register_operand" "r")
3600 (match_operand:SI 5 "const_int_operand" "i")])
3601 (match_operand:SI 1 "const_int_operand" "i"))
3602 (match_operand:SI 2 "const_int_operand" "i")))]
3603 "TARGET_32BIT && arm_arch6 && <SAT:CODE> != <SATrev:CODE>
3604 && arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>], NULL, NULL)"
3605{
3606 int mask;
3607 bool signed_sat;
3608 if (!arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>],
3609 &mask, &signed_sat))
3610 gcc_unreachable ();
3611
3612 operands[1] = GEN_INT (mask);
3613 if (signed_sat)
3614 return "ssat%?\t%0, %1, %4%S3";
3615 else
3616 return "usat%?\t%0, %1, %4%S3";
3617}
3618 [(set_attr "predicable" "yes")
7c36fe71 3619 (set_attr "predicable_short_it" "no")
b49e3742 3620 (set_attr "shift" "3")
d82e788e 3621 (set_attr "type" "logic_shift_reg")])
b11cae9e 3622\f
3623;; Shift and rotation insns
3624
a2cd141b 3625(define_expand "ashldi3"
3626 [(set (match_operand:DI 0 "s_register_operand" "")
3627 (ashift:DI (match_operand:DI 1 "s_register_operand" "")
aa06c51c 3628 (match_operand:SI 2 "general_operand" "")))]
25f905c2 3629 "TARGET_32BIT"
a2cd141b 3630 "
aa06c51c 3631 if (TARGET_NEON)
3632 {
3633 /* Delay the decision whether to use NEON or core-regs until
3634 register allocation. */
3635 emit_insn (gen_ashldi3_neon (operands[0], operands[1], operands[2]));
3636 DONE;
3637 }
3638 else
3639 {
3640 /* Only the NEON case can handle in-memory shift counts. */
3641 if (!reg_or_int_operand (operands[2], SImode))
3642 operands[2] = force_reg (SImode, operands[2]);
3643 }
3644
b805622c 3645 if (!CONST_INT_P (operands[2]) && TARGET_REALLY_IWMMXT)
ffcc986d 3646 ; /* No special preparation statements; expand pattern as above. */
3647 else
a2cd141b 3648 {
ffcc986d 3649 rtx scratch1, scratch2;
3650
3651 if (CONST_INT_P (operands[2])
3652 && (HOST_WIDE_INT) INTVAL (operands[2]) == 1)
a2cd141b 3653 {
3654 emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
3655 DONE;
3656 }
ffcc986d 3657
3658 /* Ideally we should use iwmmxt here if we could know that operands[1]
3659 ends up already living in an iwmmxt register. Otherwise it's
3660 cheaper to have the alternate code being generated than moving
3661 values to iwmmxt regs and back. */
3662
3663 /* If we're optimizing for size, we prefer the libgcc calls. */
3664 if (optimize_function_for_size_p (cfun))
3665 FAIL;
3666
3667 /* Expand operation using core-registers.
3668 'FAIL' would achieve the same thing, but this is a bit smarter. */
3669 scratch1 = gen_reg_rtx (SImode);
3670 scratch2 = gen_reg_rtx (SImode);
3671 arm_emit_coreregs_64bit_shift (ASHIFT, operands[0], operands[1],
3672 operands[2], scratch1, scratch2);
3673 DONE;
a2cd141b 3674 }
a2cd141b 3675 "
3676)
3677
2837e3fb 3678(define_insn "arm_ashldi3_1bit"
50ad1bf9 3679 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 3680 (ashift:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 3681 (const_int 1)))
3682 (clobber (reg:CC CC_REGNUM))]
25f905c2 3683 "TARGET_32BIT"
2837e3fb 3684 "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
a2cd141b 3685 [(set_attr "conds" "clob")
1b7da4ac 3686 (set_attr "length" "8")
3687 (set_attr "type" "multiple")]
a2cd141b 3688)
3689
87b22bf7 3690(define_expand "ashlsi3"
cffb2a26 3691 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3692 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
3693 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3694 "TARGET_EITHER"
87b22bf7 3695 "
0438d37f 3696 if (CONST_INT_P (operands[2])
87b22bf7 3697 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3698 {
3699 emit_insn (gen_movsi (operands[0], const0_rtx));
3700 DONE;
3701 }
cffb2a26 3702 "
3703)
3704
a2cd141b 3705(define_expand "ashrdi3"
3706 [(set (match_operand:DI 0 "s_register_operand" "")
3707 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
3708 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3709 "TARGET_32BIT"
a2cd141b 3710 "
aa06c51c 3711 if (TARGET_NEON)
3712 {
3713 /* Delay the decision whether to use NEON or core-regs until
3714 register allocation. */
3715 emit_insn (gen_ashrdi3_neon (operands[0], operands[1], operands[2]));
3716 DONE;
3717 }
3718
b805622c 3719 if (!CONST_INT_P (operands[2]) && TARGET_REALLY_IWMMXT)
ffcc986d 3720 ; /* No special preparation statements; expand pattern as above. */
3721 else
a2cd141b 3722 {
ffcc986d 3723 rtx scratch1, scratch2;
3724
3725 if (CONST_INT_P (operands[2])
3726 && (HOST_WIDE_INT) INTVAL (operands[2]) == 1)
a2cd141b 3727 {
3728 emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
3729 DONE;
3730 }
ffcc986d 3731
3732 /* Ideally we should use iwmmxt here if we could know that operands[1]
3733 ends up already living in an iwmmxt register. Otherwise it's
3734 cheaper to have the alternate code being generated than moving
3735 values to iwmmxt regs and back. */
3736
3737 /* If we're optimizing for size, we prefer the libgcc calls. */
3738 if (optimize_function_for_size_p (cfun))
3739 FAIL;
3740
3741 /* Expand operation using core-registers.
3742 'FAIL' would achieve the same thing, but this is a bit smarter. */
3743 scratch1 = gen_reg_rtx (SImode);
3744 scratch2 = gen_reg_rtx (SImode);
3745 arm_emit_coreregs_64bit_shift (ASHIFTRT, operands[0], operands[1],
3746 operands[2], scratch1, scratch2);
3747 DONE;
a2cd141b 3748 }
a2cd141b 3749 "
3750)
3751
2837e3fb 3752(define_insn "arm_ashrdi3_1bit"
50ad1bf9 3753 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 3754 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 3755 (const_int 1)))
3756 (clobber (reg:CC CC_REGNUM))]
25f905c2 3757 "TARGET_32BIT"
2837e3fb 3758 "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
a2cd141b 3759 [(set_attr "conds" "clob")
1b7da4ac 3760 (set_attr "length" "8")
3761 (set_attr "type" "multiple")]
a2cd141b 3762)
3763
87b22bf7 3764(define_expand "ashrsi3"
cffb2a26 3765 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3766 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
3767 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3768 "TARGET_EITHER"
87b22bf7 3769 "
0438d37f 3770 if (CONST_INT_P (operands[2])
87b22bf7 3771 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3772 operands[2] = GEN_INT (31);
cffb2a26 3773 "
3774)
3775
a2cd141b 3776(define_expand "lshrdi3"
3777 [(set (match_operand:DI 0 "s_register_operand" "")
3778 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
3779 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3780 "TARGET_32BIT"
a2cd141b 3781 "
aa06c51c 3782 if (TARGET_NEON)
3783 {
3784 /* Delay the decision whether to use NEON or core-regs until
3785 register allocation. */
3786 emit_insn (gen_lshrdi3_neon (operands[0], operands[1], operands[2]));
3787 DONE;
3788 }
3789
b805622c 3790 if (!CONST_INT_P (operands[2]) && TARGET_REALLY_IWMMXT)
ffcc986d 3791 ; /* No special preparation statements; expand pattern as above. */
3792 else
a2cd141b 3793 {
ffcc986d 3794 rtx scratch1, scratch2;
3795
3796 if (CONST_INT_P (operands[2])
3797 && (HOST_WIDE_INT) INTVAL (operands[2]) == 1)
a2cd141b 3798 {
3799 emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
3800 DONE;
3801 }
ffcc986d 3802
3803 /* Ideally we should use iwmmxt here if we could know that operands[1]
3804 ends up already living in an iwmmxt register. Otherwise it's
3805 cheaper to have the alternate code being generated than moving
3806 values to iwmmxt regs and back. */
3807
3808 /* If we're optimizing for size, we prefer the libgcc calls. */
3809 if (optimize_function_for_size_p (cfun))
3810 FAIL;
3811
3812 /* Expand operation using core-registers.
3813 'FAIL' would achieve the same thing, but this is a bit smarter. */
3814 scratch1 = gen_reg_rtx (SImode);
3815 scratch2 = gen_reg_rtx (SImode);
3816 arm_emit_coreregs_64bit_shift (LSHIFTRT, operands[0], operands[1],
3817 operands[2], scratch1, scratch2);
3818 DONE;
a2cd141b 3819 }
a2cd141b 3820 "
3821)
3822
2837e3fb 3823(define_insn "arm_lshrdi3_1bit"
50ad1bf9 3824 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 3825 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 3826 (const_int 1)))
3827 (clobber (reg:CC CC_REGNUM))]
25f905c2 3828 "TARGET_32BIT"
2837e3fb 3829 "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
a2cd141b 3830 [(set_attr "conds" "clob")
1b7da4ac 3831 (set_attr "length" "8")
3832 (set_attr "type" "multiple")]
a2cd141b 3833)
3834
87b22bf7 3835(define_expand "lshrsi3"
cffb2a26 3836 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3837 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
3838 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3839 "TARGET_EITHER"
87b22bf7 3840 "
0438d37f 3841 if (CONST_INT_P (operands[2])
87b22bf7 3842 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3843 {
3844 emit_insn (gen_movsi (operands[0], const0_rtx));
3845 DONE;
3846 }
cffb2a26 3847 "
3848)
3849
87b22bf7 3850(define_expand "rotlsi3"
cffb2a26 3851 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3852 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
3853 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3854 "TARGET_32BIT"
87b22bf7 3855 "
0438d37f 3856 if (CONST_INT_P (operands[2]))
87b22bf7 3857 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
3858 else
b11cae9e 3859 {
87b22bf7 3860 rtx reg = gen_reg_rtx (SImode);
3861 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
3862 operands[2] = reg;
b11cae9e 3863 }
cffb2a26 3864 "
3865)
9c08d1fa 3866
87b22bf7 3867(define_expand "rotrsi3"
cffb2a26 3868 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3869 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
3870 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3871 "TARGET_EITHER"
87b22bf7 3872 "
25f905c2 3873 if (TARGET_32BIT)
cffb2a26 3874 {
0438d37f 3875 if (CONST_INT_P (operands[2])
cffb2a26 3876 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3877 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
3878 }
25f905c2 3879 else /* TARGET_THUMB1 */
cffb2a26 3880 {
0438d37f 3881 if (CONST_INT_P (operands [2]))
cffb2a26 3882 operands [2] = force_reg (SImode, operands[2]);
3883 }
3884 "
3885)
87b22bf7 3886
cffb2a26 3887(define_insn "*arm_shiftsi3"
88c29385 3888 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r,r")
cffb2a26 3889 (match_operator:SI 3 "shift_operator"
88c29385 3890 [(match_operand:SI 1 "s_register_operand" "0,l,r,r")
3891 (match_operand:SI 2 "reg_or_int_operand" "l,M,M,r")]))]
25f905c2 3892 "TARGET_32BIT"
3893 "* return arm_output_shift(operands, 0);"
344495ea 3894 [(set_attr "predicable" "yes")
88c29385 3895 (set_attr "arch" "t2,t2,*,*")
3896 (set_attr "predicable_short_it" "yes,yes,no,no")
7c36fe71 3897 (set_attr "length" "4")
331beb1a 3898 (set_attr "shift" "1")
88c29385 3899 (set_attr "type" "alu_shift_reg,alu_shift_imm,alu_shift_imm,alu_shift_reg")]
6c4c2133 3900)
87b22bf7 3901
f7fbdd4a 3902(define_insn "*shiftsi3_compare0"
bd5b4116 3903 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 3904 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
6b6abc9c 3905 [(match_operand:SI 1 "s_register_operand" "r,r")
3906 (match_operand:SI 2 "arm_rhs_operand" "M,r")])
9c08d1fa 3907 (const_int 0)))
6b6abc9c 3908 (set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 3909 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
25f905c2 3910 "TARGET_32BIT"
3911 "* return arm_output_shift(operands, 1);"
344495ea 3912 [(set_attr "conds" "set")
331beb1a 3913 (set_attr "shift" "1")
d82e788e 3914 (set_attr "type" "alus_shift_imm,alus_shift_reg")]
0d66636f 3915)
9c08d1fa 3916
f7fbdd4a 3917(define_insn "*shiftsi3_compare0_scratch"
bd5b4116 3918 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 3919 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
6b6abc9c 3920 [(match_operand:SI 1 "s_register_operand" "r,r")
3921 (match_operand:SI 2 "arm_rhs_operand" "M,r")])
9c08d1fa 3922 (const_int 0)))
6b6abc9c 3923 (clobber (match_scratch:SI 0 "=r,r"))]
25f905c2 3924 "TARGET_32BIT"
3925 "* return arm_output_shift(operands, 1);"
344495ea 3926 [(set_attr "conds" "set")
6b6abc9c 3927 (set_attr "shift" "1")
d82e788e 3928 (set_attr "type" "shift_imm,shift_reg")]
0d66636f 3929)
9c08d1fa 3930
d5d4dc8d 3931(define_insn "*not_shiftsi"
3932 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 3933 (not:SI (match_operator:SI 3 "shift_operator"
d5d4dc8d 3934 [(match_operand:SI 1 "s_register_operand" "r,r")
3935 (match_operand:SI 2 "shift_amount_operand" "M,rM")])))]
3936 "TARGET_32BIT"
6c4c2133 3937 "mvn%?\\t%0, %1%S3"
344495ea 3938 [(set_attr "predicable" "yes")
d952d547 3939 (set_attr "predicable_short_it" "no")
331beb1a 3940 (set_attr "shift" "1")
d5d4dc8d 3941 (set_attr "arch" "32,a")
1aed5204 3942 (set_attr "type" "mvn_shift,mvn_shift_reg")])
9c08d1fa 3943
d5d4dc8d 3944(define_insn "*not_shiftsi_compare0"
bd5b4116 3945 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 3946 (compare:CC_NOOV
3947 (not:SI (match_operator:SI 3 "shift_operator"
3948 [(match_operand:SI 1 "s_register_operand" "r,r")
3949 (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
3950 (const_int 0)))
3951 (set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 3952 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
d5d4dc8d 3953 "TARGET_32BIT"
25f905c2 3954 "mvn%.\\t%0, %1%S3"
344495ea 3955 [(set_attr "conds" "set")
331beb1a 3956 (set_attr "shift" "1")
d5d4dc8d 3957 (set_attr "arch" "32,a")
1aed5204 3958 (set_attr "type" "mvn_shift,mvn_shift_reg")])
9c08d1fa 3959
d5d4dc8d 3960(define_insn "*not_shiftsi_compare0_scratch"
bd5b4116 3961 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 3962 (compare:CC_NOOV
3963 (not:SI (match_operator:SI 3 "shift_operator"
3964 [(match_operand:SI 1 "s_register_operand" "r,r")
3965 (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
3966 (const_int 0)))
3967 (clobber (match_scratch:SI 0 "=r,r"))]
3968 "TARGET_32BIT"
25f905c2 3969 "mvn%.\\t%0, %1%S3"
344495ea 3970 [(set_attr "conds" "set")
331beb1a 3971 (set_attr "shift" "1")
d5d4dc8d 3972 (set_attr "arch" "32,a")
1aed5204 3973 (set_attr "type" "mvn_shift,mvn_shift_reg")])
9c08d1fa 3974
cffb2a26 3975;; We don't really have extzv, but defining this using shifts helps
3976;; to reduce register pressure later on.
3977
3978(define_expand "extzv"
eb04cafb 3979 [(set (match_operand 0 "s_register_operand" "")
3980 (zero_extract (match_operand 1 "nonimmediate_operand" "")
3981 (match_operand 2 "const_int_operand" "")
3982 (match_operand 3 "const_int_operand" "")))]
8b054d5a 3983 "TARGET_THUMB1 || arm_arch_thumb2"
cffb2a26 3984 "
3985 {
3986 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
3987 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
3988
8b054d5a 3989 if (arm_arch_thumb2)
3990 {
eb04cafb 3991 HOST_WIDE_INT width = INTVAL (operands[2]);
3992 HOST_WIDE_INT bitpos = INTVAL (operands[3]);
3993
3994 if (unaligned_access && MEM_P (operands[1])
3995 && (width == 16 || width == 32) && (bitpos % BITS_PER_UNIT) == 0)
3996 {
3997 rtx base_addr;
3998
3999 if (BYTES_BIG_ENDIAN)
4000 bitpos = GET_MODE_BITSIZE (GET_MODE (operands[0])) - width
4001 - bitpos;
4002
4003 if (width == 32)
4004 {
4005 base_addr = adjust_address (operands[1], SImode,
4006 bitpos / BITS_PER_UNIT);
4007 emit_insn (gen_unaligned_loadsi (operands[0], base_addr));
4008 }
4009 else
4010 {
4011 rtx dest = operands[0];
4012 rtx tmp = gen_reg_rtx (SImode);
4013
4014 /* We may get a paradoxical subreg here. Strip it off. */
4015 if (GET_CODE (dest) == SUBREG
4016 && GET_MODE (dest) == SImode
4017 && GET_MODE (SUBREG_REG (dest)) == HImode)
4018 dest = SUBREG_REG (dest);
4019
4020 if (GET_MODE_BITSIZE (GET_MODE (dest)) != width)
4021 FAIL;
4022
4023 base_addr = adjust_address (operands[1], HImode,
4024 bitpos / BITS_PER_UNIT);
4025 emit_insn (gen_unaligned_loadhiu (tmp, base_addr));
4026 emit_move_insn (gen_lowpart (SImode, dest), tmp);
4027 }
4028 DONE;
4029 }
4030 else if (s_register_operand (operands[1], GET_MODE (operands[1])))
4031 {
4032 emit_insn (gen_extzv_t2 (operands[0], operands[1], operands[2],
4033 operands[3]));
4034 DONE;
4035 }
4036 else
4037 FAIL;
8b054d5a 4038 }
eb04cafb 4039
4040 if (!s_register_operand (operands[1], GET_MODE (operands[1])))
4041 FAIL;
8b054d5a 4042
cffb2a26 4043 operands[3] = GEN_INT (rshift);
4044
4045 if (lshift == 0)
4046 {
4047 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
4048 DONE;
4049 }
4050
eb04cafb 4051 emit_insn (gen_extzv_t1 (operands[0], operands[1], GEN_INT (lshift),
4052 operands[3], gen_reg_rtx (SImode)));
4053 DONE;
215b30b3 4054 }"
cffb2a26 4055)
4056
eb04cafb 4057;; Helper for extzv, for the Thumb-1 register-shifts case.
4058
4059(define_expand "extzv_t1"
4060 [(set (match_operand:SI 4 "s_register_operand" "")
4061 (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "")
4062 (match_operand:SI 2 "const_int_operand" "")))
4063 (set (match_operand:SI 0 "s_register_operand" "")
4064 (lshiftrt:SI (match_dup 4)
4065 (match_operand:SI 3 "const_int_operand" "")))]
4066 "TARGET_THUMB1"
4067 "")
4068
4069(define_expand "extv"
4070 [(set (match_operand 0 "s_register_operand" "")
4071 (sign_extract (match_operand 1 "nonimmediate_operand" "")
4072 (match_operand 2 "const_int_operand" "")
4073 (match_operand 3 "const_int_operand" "")))]
4074 "arm_arch_thumb2"
4075{
4076 HOST_WIDE_INT width = INTVAL (operands[2]);
4077 HOST_WIDE_INT bitpos = INTVAL (operands[3]);
4078
4079 if (unaligned_access && MEM_P (operands[1]) && (width == 16 || width == 32)
4080 && (bitpos % BITS_PER_UNIT) == 0)
4081 {
4082 rtx base_addr;
4083
4084 if (BYTES_BIG_ENDIAN)
4085 bitpos = GET_MODE_BITSIZE (GET_MODE (operands[0])) - width - bitpos;
4086
4087 if (width == 32)
4088 {
4089 base_addr = adjust_address (operands[1], SImode,
4090 bitpos / BITS_PER_UNIT);
4091 emit_insn (gen_unaligned_loadsi (operands[0], base_addr));
4092 }
4093 else
4094 {
4095 rtx dest = operands[0];
4096 rtx tmp = gen_reg_rtx (SImode);
4097
4098 /* We may get a paradoxical subreg here. Strip it off. */
4099 if (GET_CODE (dest) == SUBREG
4100 && GET_MODE (dest) == SImode
4101 && GET_MODE (SUBREG_REG (dest)) == HImode)
4102 dest = SUBREG_REG (dest);
4103
4104 if (GET_MODE_BITSIZE (GET_MODE (dest)) != width)
4105 FAIL;
4106
4107 base_addr = adjust_address (operands[1], HImode,
4108 bitpos / BITS_PER_UNIT);
4109 emit_insn (gen_unaligned_loadhis (tmp, base_addr));
4110 emit_move_insn (gen_lowpart (SImode, dest), tmp);
4111 }
4112
4113 DONE;
4114 }
4115 else if (!s_register_operand (operands[1], GET_MODE (operands[1])))
4116 FAIL;
4117 else if (GET_MODE (operands[0]) == SImode
4118 && GET_MODE (operands[1]) == SImode)
4119 {
4120 emit_insn (gen_extv_regsi (operands[0], operands[1], operands[2],
4121 operands[3]));
4122 DONE;
4123 }
4124
4125 FAIL;
4126})
4127
4128; Helper to expand register forms of extv with the proper modes.
4129
4130(define_expand "extv_regsi"
4131 [(set (match_operand:SI 0 "s_register_operand" "")
4132 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
4133 (match_operand 2 "const_int_operand" "")
4134 (match_operand 3 "const_int_operand" "")))]
4135 ""
4136{
4137})
4138
4139; ARMv6+ unaligned load/store instructions (used for packed structure accesses).
4140
4141(define_insn "unaligned_loadsi"
4142 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4143 (unspec:SI [(match_operand:SI 1 "memory_operand" "Uw,m")]
4144 UNSPEC_UNALIGNED_LOAD))]
4145 "unaligned_access && TARGET_32BIT"
4146 "ldr%?\t%0, %1\t@ unaligned"
4147 [(set_attr "arch" "t2,any")
4148 (set_attr "length" "2,4")
4149 (set_attr "predicable" "yes")
d952d547 4150 (set_attr "predicable_short_it" "yes,no")
eb04cafb 4151 (set_attr "type" "load1")])
4152
4153(define_insn "unaligned_loadhis"
4154 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4155 (sign_extend:SI
e3f4ccee 4156 (unspec:HI [(match_operand:HI 1 "memory_operand" "Uw,Uh")]
eb04cafb 4157 UNSPEC_UNALIGNED_LOAD)))]
4158 "unaligned_access && TARGET_32BIT"
4159 "ldr%(sh%)\t%0, %1\t@ unaligned"
4160 [(set_attr "arch" "t2,any")
4161 (set_attr "length" "2,4")
4162 (set_attr "predicable" "yes")
d952d547 4163 (set_attr "predicable_short_it" "yes,no")
eb04cafb 4164 (set_attr "type" "load_byte")])
4165
4166(define_insn "unaligned_loadhiu"
4167 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4168 (zero_extend:SI
4169 (unspec:HI [(match_operand:HI 1 "memory_operand" "Uw,m")]
4170 UNSPEC_UNALIGNED_LOAD)))]
4171 "unaligned_access && TARGET_32BIT"
4172 "ldr%(h%)\t%0, %1\t@ unaligned"
4173 [(set_attr "arch" "t2,any")
4174 (set_attr "length" "2,4")
4175 (set_attr "predicable" "yes")
d952d547 4176 (set_attr "predicable_short_it" "yes,no")
eb04cafb 4177 (set_attr "type" "load_byte")])
4178
4179(define_insn "unaligned_storesi"
4180 [(set (match_operand:SI 0 "memory_operand" "=Uw,m")
4181 (unspec:SI [(match_operand:SI 1 "s_register_operand" "l,r")]
4182 UNSPEC_UNALIGNED_STORE))]
4183 "unaligned_access && TARGET_32BIT"
4184 "str%?\t%1, %0\t@ unaligned"
4185 [(set_attr "arch" "t2,any")
4186 (set_attr "length" "2,4")
4187 (set_attr "predicable" "yes")
d952d547 4188 (set_attr "predicable_short_it" "yes,no")
eb04cafb 4189 (set_attr "type" "store1")])
4190
4191(define_insn "unaligned_storehi"
4192 [(set (match_operand:HI 0 "memory_operand" "=Uw,m")
4193 (unspec:HI [(match_operand:HI 1 "s_register_operand" "l,r")]
4194 UNSPEC_UNALIGNED_STORE))]
4195 "unaligned_access && TARGET_32BIT"
4196 "str%(h%)\t%1, %0\t@ unaligned"
4197 [(set_attr "arch" "t2,any")
4198 (set_attr "length" "2,4")
4199 (set_attr "predicable" "yes")
d952d547 4200 (set_attr "predicable_short_it" "yes,no")
eb04cafb 4201 (set_attr "type" "store1")])
4202
ae51a965 4203;; Unaligned double-word load and store.
4204;; Split after reload into two unaligned single-word accesses.
4205;; It prevents lower_subreg from splitting some other aligned
4206;; double-word accesses too early. Used for internal memcpy.
4207
4208(define_insn_and_split "unaligned_loaddi"
4209 [(set (match_operand:DI 0 "s_register_operand" "=l,r")
4210 (unspec:DI [(match_operand:DI 1 "memory_operand" "o,o")]
4211 UNSPEC_UNALIGNED_LOAD))]
4212 "unaligned_access && TARGET_32BIT"
4213 "#"
4214 "&& reload_completed"
4215 [(set (match_dup 0) (unspec:SI [(match_dup 1)] UNSPEC_UNALIGNED_LOAD))
4216 (set (match_dup 2) (unspec:SI [(match_dup 3)] UNSPEC_UNALIGNED_LOAD))]
4217 {
4218 operands[2] = gen_highpart (SImode, operands[0]);
4219 operands[0] = gen_lowpart (SImode, operands[0]);
4220 operands[3] = gen_highpart (SImode, operands[1]);
4221 operands[1] = gen_lowpart (SImode, operands[1]);
4222
4223 /* If the first destination register overlaps with the base address,
4224 swap the order in which the loads are emitted. */
4225 if (reg_overlap_mentioned_p (operands[0], operands[1]))
4226 {
f145bcba 4227 std::swap (operands[1], operands[3]);
4228 std::swap (operands[0], operands[2]);
ae51a965 4229 }
4230 }
4231 [(set_attr "arch" "t2,any")
4232 (set_attr "length" "4,8")
4233 (set_attr "predicable" "yes")
4234 (set_attr "type" "load2")])
4235
4236(define_insn_and_split "unaligned_storedi"
4237 [(set (match_operand:DI 0 "memory_operand" "=o,o")
4238 (unspec:DI [(match_operand:DI 1 "s_register_operand" "l,r")]
4239 UNSPEC_UNALIGNED_STORE))]
4240 "unaligned_access && TARGET_32BIT"
4241 "#"
4242 "&& reload_completed"
4243 [(set (match_dup 0) (unspec:SI [(match_dup 1)] UNSPEC_UNALIGNED_STORE))
4244 (set (match_dup 2) (unspec:SI [(match_dup 3)] UNSPEC_UNALIGNED_STORE))]
4245 {
4246 operands[2] = gen_highpart (SImode, operands[0]);
4247 operands[0] = gen_lowpart (SImode, operands[0]);
4248 operands[3] = gen_highpart (SImode, operands[1]);
4249 operands[1] = gen_lowpart (SImode, operands[1]);
4250 }
4251 [(set_attr "arch" "t2,any")
4252 (set_attr "length" "4,8")
4253 (set_attr "predicable" "yes")
4254 (set_attr "type" "store2")])
4255
4256
eb04cafb 4257(define_insn "*extv_reg"
8b054d5a 4258 [(set (match_operand:SI 0 "s_register_operand" "=r")
4259 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
809003b3 4260 (match_operand:SI 2 "const_int_M_operand" "M")
4261 (match_operand:SI 3 "const_int_M_operand" "M")))]
8b054d5a 4262 "arm_arch_thumb2"
4263 "sbfx%?\t%0, %1, %3, %2"
4264 [(set_attr "length" "4")
d952d547 4265 (set_attr "predicable" "yes")
d82e788e 4266 (set_attr "predicable_short_it" "no")
4267 (set_attr "type" "bfm")]
8b054d5a 4268)
4269
4270(define_insn "extzv_t2"
4271 [(set (match_operand:SI 0 "s_register_operand" "=r")
4272 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "r")
809003b3 4273 (match_operand:SI 2 "const_int_M_operand" "M")
4274 (match_operand:SI 3 "const_int_M_operand" "M")))]
8b054d5a 4275 "arm_arch_thumb2"
4276 "ubfx%?\t%0, %1, %3, %2"
4277 [(set_attr "length" "4")
d952d547 4278 (set_attr "predicable" "yes")
d82e788e 4279 (set_attr "predicable_short_it" "no")
4280 (set_attr "type" "bfm")]
8b054d5a 4281)
4282
7d3cda8c 4283
4284;; Division instructions
4285(define_insn "divsi3"
4286 [(set (match_operand:SI 0 "s_register_operand" "=r")
4287 (div:SI (match_operand:SI 1 "s_register_operand" "r")
4288 (match_operand:SI 2 "s_register_operand" "r")))]
4289 "TARGET_IDIV"
4290 "sdiv%?\t%0, %1, %2"
4291 [(set_attr "predicable" "yes")
d952d547 4292 (set_attr "predicable_short_it" "no")
9da0ec36 4293 (set_attr "type" "sdiv")]
7d3cda8c 4294)
4295
4296(define_insn "udivsi3"
4297 [(set (match_operand:SI 0 "s_register_operand" "=r")
4298 (udiv:SI (match_operand:SI 1 "s_register_operand" "r")
4299 (match_operand:SI 2 "s_register_operand" "r")))]
4300 "TARGET_IDIV"
4301 "udiv%?\t%0, %1, %2"
4302 [(set_attr "predicable" "yes")
d952d547 4303 (set_attr "predicable_short_it" "no")
9da0ec36 4304 (set_attr "type" "udiv")]
7d3cda8c 4305)
4306
b11cae9e 4307\f
4308;; Unary arithmetic insns
4309
cffb2a26 4310(define_expand "negdi2"
4311 [(parallel
8135a42b 4312 [(set (match_operand:DI 0 "s_register_operand" "")
4313 (neg:DI (match_operand:DI 1 "s_register_operand" "")))
bd5b4116 4314 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 4315 "TARGET_EITHER"
774d2fbb 4316 {
4317 if (TARGET_NEON)
4318 {
4319 emit_insn (gen_negdi2_neon (operands[0], operands[1]));
4320 DONE;
4321 }
4322 }
cffb2a26 4323)
4324
4325;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
e5fea38e 4326;; The first alternative allows the common case of a *full* overlap.
ba6a3b2f 4327(define_insn_and_split "*arm_negdi2"
458a8706 4328 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 4329 (neg:DI (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 4330 (clobber (reg:CC CC_REGNUM))]
cffb2a26 4331 "TARGET_ARM"
ba6a3b2f 4332 "#" ; "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
4333 "&& reload_completed"
4334 [(parallel [(set (reg:CC CC_REGNUM)
4335 (compare:CC (const_int 0) (match_dup 1)))
4336 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 1)))])
4337 (set (match_dup 2) (minus:SI (minus:SI (const_int 0) (match_dup 3))
4338 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
4339 {
4340 operands[2] = gen_highpart (SImode, operands[0]);
4341 operands[0] = gen_lowpart (SImode, operands[0]);
4342 operands[3] = gen_highpart (SImode, operands[1]);
4343 operands[1] = gen_lowpart (SImode, operands[1]);
4344 }
cffb2a26 4345 [(set_attr "conds" "clob")
1b7da4ac 4346 (set_attr "length" "8")
4347 (set_attr "type" "multiple")]
cffb2a26 4348)
b11cae9e 4349
cffb2a26 4350(define_expand "negsi2"
4351 [(set (match_operand:SI 0 "s_register_operand" "")
4352 (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
4353 "TARGET_EITHER"
b11cae9e 4354 ""
cffb2a26 4355)
4356
4357(define_insn "*arm_negsi2"
d952d547 4358 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4359 (neg:SI (match_operand:SI 1 "s_register_operand" "l,r")))]
25f905c2 4360 "TARGET_32BIT"
cffb2a26 4361 "rsb%?\\t%0, %1, #0"
d952d547 4362 [(set_attr "predicable" "yes")
4363 (set_attr "predicable_short_it" "yes,no")
4364 (set_attr "arch" "t2,*")
1b7da4ac 4365 (set_attr "length" "4")
112eda6f 4366 (set_attr "type" "alu_sreg")]
cffb2a26 4367)
4368
604f3a0a 4369(define_expand "negsf2"
4370 [(set (match_operand:SF 0 "s_register_operand" "")
4371 (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
994606f8 4372 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
604f3a0a 4373 ""
4374)
4375
4376(define_expand "negdf2"
4377 [(set (match_operand:DF 0 "s_register_operand" "")
4378 (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
994606f8 4379 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
604f3a0a 4380 "")
4381
7eaf2be0 4382(define_insn_and_split "*zextendsidi_negsi"
4383 [(set (match_operand:DI 0 "s_register_operand" "=r")
4384 (zero_extend:DI (neg:SI (match_operand:SI 1 "s_register_operand" "r"))))]
4385 "TARGET_32BIT"
4386 "#"
4387 ""
4388 [(set (match_dup 2)
4389 (neg:SI (match_dup 1)))
4390 (set (match_dup 3)
4391 (const_int 0))]
4392 {
4393 operands[2] = gen_lowpart (SImode, operands[0]);
4394 operands[3] = gen_highpart (SImode, operands[0]);
4395 }
4396 [(set_attr "length" "8")
4397 (set_attr "type" "multiple")]
4398)
4399
83e2b922 4400;; Negate an extended 32-bit value.
4401(define_insn_and_split "*negdi_extendsidi"
61fa8ff2 4402 [(set (match_operand:DI 0 "s_register_operand" "=l,r")
4403 (neg:DI (sign_extend:DI
4404 (match_operand:SI 1 "s_register_operand" "l,r"))))
83e2b922 4405 (clobber (reg:CC CC_REGNUM))]
4406 "TARGET_32BIT"
61fa8ff2 4407 "#"
83e2b922 4408 "&& reload_completed"
4409 [(const_int 0)]
4410 {
61fa8ff2 4411 rtx low = gen_lowpart (SImode, operands[0]);
4412 rtx high = gen_highpart (SImode, operands[0]);
4413
4414 if (reg_overlap_mentioned_p (low, operands[1]))
4415 {
4416 /* Input overlaps the low word of the output. Use:
4417 asr Rhi, Rin, #31
4418 rsbs Rlo, Rin, #0
4419 rsc Rhi, Rhi, #0 (thumb2: sbc Rhi, Rhi, Rhi, lsl #1). */
4420 rtx cc_reg = gen_rtx_REG (CC_Cmode, CC_REGNUM);
4421
4422 emit_insn (gen_rtx_SET (VOIDmode, high,
4423 gen_rtx_ASHIFTRT (SImode, operands[1],
4424 GEN_INT (31))));
4425
4426 emit_insn (gen_subsi3_compare (low, const0_rtx, operands[1]));
4427 if (TARGET_ARM)
4428 emit_insn (gen_rtx_SET (VOIDmode, high,
4429 gen_rtx_MINUS (SImode,
4430 gen_rtx_MINUS (SImode,
4431 const0_rtx,
4432 high),
4433 gen_rtx_LTU (SImode,
4434 cc_reg,
4435 const0_rtx))));
4436 else
4437 {
4438 rtx two_x = gen_rtx_ASHIFT (SImode, high, GEN_INT (1));
4439 emit_insn (gen_rtx_SET (VOIDmode, high,
4440 gen_rtx_MINUS (SImode,
4441 gen_rtx_MINUS (SImode,
4442 high,
4443 two_x),
4444 gen_rtx_LTU (SImode,
4445 cc_reg,
4446 const0_rtx))));
4447 }
4448 }
4449 else
4450 {
4451 /* No overlap, or overlap on high word. Use:
4452 rsb Rlo, Rin, #0
4453 bic Rhi, Rlo, Rin
4454 asr Rhi, Rhi, #31
4455 Flags not needed for this sequence. */
4456 emit_insn (gen_rtx_SET (VOIDmode, low,
4457 gen_rtx_NEG (SImode, operands[1])));
4458 emit_insn (gen_rtx_SET (VOIDmode, high,
4459 gen_rtx_AND (SImode,
4460 gen_rtx_NOT (SImode, operands[1]),
4461 low)));
4462 emit_insn (gen_rtx_SET (VOIDmode, high,
4463 gen_rtx_ASHIFTRT (SImode, high,
4464 GEN_INT (31))));
4465 }
4466 DONE;
83e2b922 4467 }
61fa8ff2 4468 [(set_attr "length" "12")
4469 (set_attr "arch" "t2,*")
1b7da4ac 4470 (set_attr "type" "multiple")]
83e2b922 4471)
4472
4473(define_insn_and_split "*negdi_zero_extendsidi"
4474 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
4475 (neg:DI (zero_extend:DI (match_operand:SI 1 "s_register_operand" "0,r"))))
4476 (clobber (reg:CC CC_REGNUM))]
4477 "TARGET_32BIT"
4478 "#" ; "rsbs\\t%Q0, %1, #0\;sbc\\t%R0,%R0,%R0"
4479 ;; Don't care what register is input to sbc,
4480 ;; since we just just need to propagate the carry.
4481 "&& reload_completed"
4482 [(parallel [(set (reg:CC CC_REGNUM)
4483 (compare:CC (const_int 0) (match_dup 1)))
4484 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 1)))])
4485 (set (match_dup 2) (minus:SI (minus:SI (match_dup 2) (match_dup 2))
4486 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
4487 {
4488 operands[2] = gen_highpart (SImode, operands[0]);
4489 operands[0] = gen_lowpart (SImode, operands[0]);
4490 }
4491 [(set_attr "conds" "clob")
1b7da4ac 4492 (set_attr "length" "8")
4493 (set_attr "type" "multiple")] ;; length in thumb is 4
83e2b922 4494)
4495
9c08d1fa 4496;; abssi2 doesn't really clobber the condition codes if a different register
4497;; is being set. To keep things simple, assume during rtl manipulations that
4498;; it does, but tell the final scan operator the truth. Similarly for
4499;; (neg (abs...))
4500
604f3a0a 4501(define_expand "abssi2"
4502 [(parallel
4503 [(set (match_operand:SI 0 "s_register_operand" "")
4504 (abs:SI (match_operand:SI 1 "s_register_operand" "")))
ba156559 4505 (clobber (match_dup 2))])]
4506 "TARGET_EITHER"
4507 "
25f905c2 4508 if (TARGET_THUMB1)
ba156559 4509 operands[2] = gen_rtx_SCRATCH (SImode);
4510 else
4511 operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
4512")
604f3a0a 4513
ba6a3b2f 4514(define_insn_and_split "*arm_abssi2"
ba156559 4515 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
9c08d1fa 4516 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
bd5b4116 4517 (clobber (reg:CC CC_REGNUM))]
cffb2a26 4518 "TARGET_ARM"
ba6a3b2f 4519 "#"
4520 "&& reload_completed"
4521 [(const_int 0)]
4522 {
4523 /* if (which_alternative == 0) */
4524 if (REGNO(operands[0]) == REGNO(operands[1]))
4525 {
4526 /* Emit the pattern:
4527 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
4528 [(set (reg:CC CC_REGNUM)
4529 (compare:CC (match_dup 0) (const_int 0)))
4530 (cond_exec (lt:CC (reg:CC CC_REGNUM) (const_int 0))
4531 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 1))))]
4532 */
4533 emit_insn (gen_rtx_SET (VOIDmode,
4534 gen_rtx_REG (CCmode, CC_REGNUM),
4535 gen_rtx_COMPARE (CCmode, operands[0], const0_rtx)));
4536 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
4537 (gen_rtx_LT (SImode,
4538 gen_rtx_REG (CCmode, CC_REGNUM),
4539 const0_rtx)),
4540 (gen_rtx_SET (VOIDmode,
4541 operands[0],
4542 (gen_rtx_MINUS (SImode,
4543 const0_rtx,
4544 operands[1]))))));
4545 DONE;
4546 }
4547 else
4548 {
4549 /* Emit the pattern:
4550 alt1: eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31
4551 [(set (match_dup 0)
4552 (xor:SI (match_dup 1)
4553 (ashiftrt:SI (match_dup 1) (const_int 31))))
4554 (set (match_dup 0)
4555 (minus:SI (match_dup 0)
4556 (ashiftrt:SI (match_dup 1) (const_int 31))))]
4557 */
4558 emit_insn (gen_rtx_SET (VOIDmode,
4559 operands[0],
4560 gen_rtx_XOR (SImode,
4561 gen_rtx_ASHIFTRT (SImode,
4562 operands[1],
4563 GEN_INT (31)),
4564 operands[1])));
4565 emit_insn (gen_rtx_SET (VOIDmode,
4566 operands[0],
4567 gen_rtx_MINUS (SImode,
4568 operands[0],
4569 gen_rtx_ASHIFTRT (SImode,
4570 operands[1],
4571 GEN_INT (31)))));
4572 DONE;
4573 }
4574 }
cffb2a26 4575 [(set_attr "conds" "clob,*")
331beb1a 4576 (set_attr "shift" "1")
2ad08b65 4577 (set_attr "predicable" "no, yes")
1b7da4ac 4578 (set_attr "length" "8")
4579 (set_attr "type" "multiple")]
cffb2a26 4580)
9c08d1fa 4581
ba6a3b2f 4582(define_insn_and_split "*arm_neg_abssi2"
9c08d1fa 4583 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
4584 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
bd5b4116 4585 (clobber (reg:CC CC_REGNUM))]
cffb2a26 4586 "TARGET_ARM"
ba6a3b2f 4587 "#"
4588 "&& reload_completed"
4589 [(const_int 0)]
4590 {
4591 /* if (which_alternative == 0) */
4592 if (REGNO (operands[0]) == REGNO (operands[1]))
4593 {
4594 /* Emit the pattern:
4595 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
4596 */
4597 emit_insn (gen_rtx_SET (VOIDmode,
4598 gen_rtx_REG (CCmode, CC_REGNUM),
4599 gen_rtx_COMPARE (CCmode, operands[0], const0_rtx)));
4600 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
4601 gen_rtx_GT (SImode,
4602 gen_rtx_REG (CCmode, CC_REGNUM),
4603 const0_rtx),
4604 gen_rtx_SET (VOIDmode,
4605 operands[0],
4606 (gen_rtx_MINUS (SImode,
4607 const0_rtx,
4608 operands[1])))));
4609 }
4610 else
4611 {
4612 /* Emit the pattern:
4613 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31
4614 */
4615 emit_insn (gen_rtx_SET (VOIDmode,
4616 operands[0],
4617 gen_rtx_XOR (SImode,
4618 gen_rtx_ASHIFTRT (SImode,
4619 operands[1],
4620 GEN_INT (31)),
4621 operands[1])));
4622 emit_insn (gen_rtx_SET (VOIDmode,
4623 operands[0],
4624 gen_rtx_MINUS (SImode,
4625 gen_rtx_ASHIFTRT (SImode,
4626 operands[1],
4627 GEN_INT (31)),
4628 operands[0])));
4629 }
4630 DONE;
4631 }
cffb2a26 4632 [(set_attr "conds" "clob,*")
331beb1a 4633 (set_attr "shift" "1")
2ad08b65 4634 (set_attr "predicable" "no, yes")
1b7da4ac 4635 (set_attr "length" "8")
4636 (set_attr "type" "multiple")]
cffb2a26 4637)
b11cae9e 4638
604f3a0a 4639(define_expand "abssf2"
4640 [(set (match_operand:SF 0 "s_register_operand" "")
4641 (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
25f905c2 4642 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 4643 "")
4644
604f3a0a 4645(define_expand "absdf2"
4646 [(set (match_operand:DF 0 "s_register_operand" "")
4647 (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 4648 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 4649 "")
4650
7db9af5d 4651(define_expand "sqrtsf2"
4652 [(set (match_operand:SF 0 "s_register_operand" "")
4653 (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
994606f8 4654 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
7db9af5d 4655 "")
9c08d1fa 4656
7db9af5d 4657(define_expand "sqrtdf2"
4658 [(set (match_operand:DF 0 "s_register_operand" "")
4659 (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
994606f8 4660 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
7db9af5d 4661 "")
9c08d1fa 4662
a0f94409 4663(define_insn_and_split "one_cmpldi2"
10efb95f 4664 [(set (match_operand:DI 0 "s_register_operand" "=w,&r,&r,?w")
4665 (not:DI (match_operand:DI 1 "s_register_operand" " w, 0, r, w")))]
25f905c2 4666 "TARGET_32BIT"
10efb95f 4667 "@
4668 vmvn\t%P0, %P1
4669 #
4670 #
4671 vmvn\t%P0, %P1"
4672 "TARGET_32BIT && reload_completed
4673 && arm_general_register_operand (operands[0], DImode)"
a0f94409 4674 [(set (match_dup 0) (not:SI (match_dup 1)))
4675 (set (match_dup 2) (not:SI (match_dup 3)))]
4676 "
4677 {
4678 operands[2] = gen_highpart (SImode, operands[0]);
4679 operands[0] = gen_lowpart (SImode, operands[0]);
4680 operands[3] = gen_highpart (SImode, operands[1]);
4681 operands[1] = gen_lowpart (SImode, operands[1]);
4682 }"
10efb95f 4683 [(set_attr "length" "*,8,8,*")
4684 (set_attr "predicable" "no,yes,yes,no")
32093010 4685 (set_attr "type" "neon_move,multiple,multiple,neon_move")
b6779ddc 4686 (set_attr "arch" "neon_for_64bits,*,*,avoid_neon_for_64bits")]
cffb2a26 4687)
b11cae9e 4688
cffb2a26 4689(define_expand "one_cmplsi2"
4690 [(set (match_operand:SI 0 "s_register_operand" "")
4691 (not:SI (match_operand:SI 1 "s_register_operand" "")))]
4692 "TARGET_EITHER"
b11cae9e 4693 ""
cffb2a26 4694)
4695
4696(define_insn "*arm_one_cmplsi2"
d952d547 4697 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4698 (not:SI (match_operand:SI 1 "s_register_operand" "l,r")))]
25f905c2 4699 "TARGET_32BIT"
cffb2a26 4700 "mvn%?\\t%0, %1"
d2a518d1 4701 [(set_attr "predicable" "yes")
d952d547 4702 (set_attr "predicable_short_it" "yes,no")
4703 (set_attr "arch" "t2,*")
4704 (set_attr "length" "4")
1aed5204 4705 (set_attr "type" "mvn_reg")]
cffb2a26 4706)
4707
f7fbdd4a 4708(define_insn "*notsi_compare0"
bd5b4116 4709 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 4710 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
4711 (const_int 0)))
4712 (set (match_operand:SI 0 "s_register_operand" "=r")
4713 (not:SI (match_dup 1)))]
25f905c2 4714 "TARGET_32BIT"
4715 "mvn%.\\t%0, %1"
d2a518d1 4716 [(set_attr "conds" "set")
1aed5204 4717 (set_attr "type" "mvn_reg")]
cffb2a26 4718)
9c08d1fa 4719
f7fbdd4a 4720(define_insn "*notsi_compare0_scratch"
bd5b4116 4721 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 4722 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
4723 (const_int 0)))
4724 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 4725 "TARGET_32BIT"
4726 "mvn%.\\t%0, %1"
d2a518d1 4727 [(set_attr "conds" "set")
1aed5204 4728 (set_attr "type" "mvn_reg")]
cffb2a26 4729)
b11cae9e 4730\f
4731;; Fixed <--> Floating conversion insns
4732
9b8516be 4733(define_expand "floatsihf2"
4734 [(set (match_operand:HF 0 "general_operand" "")
4735 (float:HF (match_operand:SI 1 "general_operand" "")))]
4736 "TARGET_EITHER"
4737 "
4738 {
4739 rtx op1 = gen_reg_rtx (SFmode);
4740 expand_float (op1, operands[1], 0);
4741 op1 = convert_to_mode (HFmode, op1, 0);
4742 emit_move_insn (operands[0], op1);
4743 DONE;
4744 }"
4745)
4746
4747(define_expand "floatdihf2"
4748 [(set (match_operand:HF 0 "general_operand" "")
4749 (float:HF (match_operand:DI 1 "general_operand" "")))]
4750 "TARGET_EITHER"
4751 "
4752 {
4753 rtx op1 = gen_reg_rtx (SFmode);
4754 expand_float (op1, operands[1], 0);
4755 op1 = convert_to_mode (HFmode, op1, 0);
4756 emit_move_insn (operands[0], op1);
4757 DONE;
4758 }"
4759)
4760
604f3a0a 4761(define_expand "floatsisf2"
4762 [(set (match_operand:SF 0 "s_register_operand" "")
4763 (float:SF (match_operand:SI 1 "s_register_operand" "")))]
25f905c2 4764 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 4765 "
604f3a0a 4766")
4767
604f3a0a 4768(define_expand "floatsidf2"
4769 [(set (match_operand:DF 0 "s_register_operand" "")
4770 (float:DF (match_operand:SI 1 "s_register_operand" "")))]
a50d7267 4771 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 4772 "
604f3a0a 4773")
4774
9b8516be 4775(define_expand "fix_trunchfsi2"
4776 [(set (match_operand:SI 0 "general_operand" "")
4777 (fix:SI (fix:HF (match_operand:HF 1 "general_operand" ""))))]
4778 "TARGET_EITHER"
4779 "
4780 {
4781 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
4782 expand_fix (operands[0], op1, 0);
4783 DONE;
4784 }"
4785)
4786
4787(define_expand "fix_trunchfdi2"
4788 [(set (match_operand:DI 0 "general_operand" "")
4789 (fix:DI (fix:HF (match_operand:HF 1 "general_operand" ""))))]
4790 "TARGET_EITHER"
4791 "
4792 {
4793 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
4794 expand_fix (operands[0], op1, 0);
4795 DONE;
4796 }"
4797)
4798
604f3a0a 4799(define_expand "fix_truncsfsi2"
4800 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 4801 (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" ""))))]
25f905c2 4802 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 4803 "
604f3a0a 4804")
4805
604f3a0a 4806(define_expand "fix_truncdfsi2"
4807 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 4808 (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" ""))))]
a50d7267 4809 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 4810 "
604f3a0a 4811")
4812
f544c6d2 4813;; Truncation insns
b11cae9e 4814
604f3a0a 4815(define_expand "truncdfsf2"
4816 [(set (match_operand:SF 0 "s_register_operand" "")
4817 (float_truncate:SF
4818 (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 4819 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 4820 ""
4821)
9b8516be 4822
4823/* DFmode -> HFmode conversions have to go through SFmode. */
4824(define_expand "truncdfhf2"
4825 [(set (match_operand:HF 0 "general_operand" "")
4826 (float_truncate:HF
4827 (match_operand:DF 1 "general_operand" "")))]
4828 "TARGET_EITHER"
4829 "
4830 {
4831 rtx op1;
4832 op1 = convert_to_mode (SFmode, operands[1], 0);
4833 op1 = convert_to_mode (HFmode, op1, 0);
4834 emit_move_insn (operands[0], op1);
4835 DONE;
4836 }"
4837)
b11cae9e 4838\f
9c08d1fa 4839;; Zero and sign extension instructions.
b11cae9e 4840
848e66ac 4841(define_insn "zero_extend<mode>di2"
6aa689e8 4842 [(set (match_operand:DI 0 "s_register_operand" "=w,r,?r,w")
6d97728e 4843 (zero_extend:DI (match_operand:QHSI 1 "<qhs_zextenddi_op>"
4844 "<qhs_zextenddi_cstr>")))]
848e66ac 4845 "TARGET_32BIT <qhs_zextenddi_cond>"
4846 "#"
6aa689e8 4847 [(set_attr "length" "8,4,8,8")
b6779ddc 4848 (set_attr "arch" "neon_for_64bits,*,*,avoid_neon_for_64bits")
848e66ac 4849 (set_attr "ce_count" "2")
efbb5e19 4850 (set_attr "predicable" "yes")
4851 (set_attr "type" "multiple,mov_reg,multiple,multiple")]
25f905c2 4852)
4853
848e66ac 4854(define_insn "extend<mode>di2"
6aa689e8 4855 [(set (match_operand:DI 0 "s_register_operand" "=w,r,?r,?r,w")
63d204a8 4856 (sign_extend:DI (match_operand:QHSI 1 "<qhs_extenddi_op>"
4857 "<qhs_extenddi_cstr>")))]
848e66ac 4858 "TARGET_32BIT <qhs_sextenddi_cond>"
4859 "#"
6aa689e8 4860 [(set_attr "length" "8,4,8,8,8")
848e66ac 4861 (set_attr "ce_count" "2")
4862 (set_attr "shift" "1")
8012d2c2 4863 (set_attr "predicable" "yes")
1b7da4ac 4864 (set_attr "arch" "neon_for_64bits,*,a,t,avoid_neon_for_64bits")
4865 (set_attr "type" "multiple,mov_reg,multiple,multiple,multiple")]
0d66636f 4866)
9c08d1fa 4867
848e66ac 4868;; Splits for all extensions to DImode
4869(define_split
4870 [(set (match_operand:DI 0 "s_register_operand" "")
4871 (zero_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
6aa689e8 4872 "TARGET_32BIT && reload_completed && !IS_VFP_REGNUM (REGNO (operands[0]))"
848e66ac 4873 [(set (match_dup 0) (match_dup 1))]
4874{
848e66ac 4875 rtx lo_part = gen_lowpart (SImode, operands[0]);
3754d046 4876 machine_mode src_mode = GET_MODE (operands[1]);
848e66ac 4877
4878 if (REG_P (operands[0])
4879 && !reg_overlap_mentioned_p (operands[0], operands[1]))
4880 emit_clobber (operands[0]);
4881 if (!REG_P (lo_part) || src_mode != SImode
4882 || !rtx_equal_p (lo_part, operands[1]))
4883 {
4884 if (src_mode == SImode)
4885 emit_move_insn (lo_part, operands[1]);
4886 else
4887 emit_insn (gen_rtx_SET (VOIDmode, lo_part,
4888 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
4889 operands[1] = lo_part;
4890 }
4891 operands[0] = gen_highpart (SImode, operands[0]);
4892 operands[1] = const0_rtx;
4893})
9c08d1fa 4894
848e66ac 4895(define_split
25f905c2 4896 [(set (match_operand:DI 0 "s_register_operand" "")
848e66ac 4897 (sign_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
6aa689e8 4898 "TARGET_32BIT && reload_completed && !IS_VFP_REGNUM (REGNO (operands[0]))"
848e66ac 4899 [(set (match_dup 0) (ashiftrt:SI (match_dup 1) (const_int 31)))]
4900{
4901 rtx lo_part = gen_lowpart (SImode, operands[0]);
3754d046 4902 machine_mode src_mode = GET_MODE (operands[1]);
25f905c2 4903
848e66ac 4904 if (REG_P (operands[0])
4905 && !reg_overlap_mentioned_p (operands[0], operands[1]))
4906 emit_clobber (operands[0]);
4907
4908 if (!REG_P (lo_part) || src_mode != SImode
4909 || !rtx_equal_p (lo_part, operands[1]))
4910 {
4911 if (src_mode == SImode)
4912 emit_move_insn (lo_part, operands[1]);
4913 else
4914 emit_insn (gen_rtx_SET (VOIDmode, lo_part,
4915 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
4916 operands[1] = lo_part;
4917 }
4918 operands[0] = gen_highpart (SImode, operands[0]);
4919})
9c08d1fa 4920
4921(define_expand "zero_extendhisi2"
ef51b8e1 4922 [(set (match_operand:SI 0 "s_register_operand" "")
4923 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
cffb2a26 4924 "TARGET_EITHER"
ef51b8e1 4925{
4926 if (TARGET_ARM && !arm_arch4 && MEM_P (operands[1]))
f7fbdd4a 4927 {
ef51b8e1 4928 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
4929 DONE;
25f7a26e 4930 }
ef51b8e1 4931 if (!arm_arch6 && !MEM_P (operands[1]))
4932 {
4933 rtx t = gen_lowpart (SImode, operands[1]);
4934 rtx tmp = gen_reg_rtx (SImode);
4935 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
4936 emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (16)));
4937 DONE;
4938 }
4939})
9c08d1fa 4940
ef51b8e1 4941(define_split
b146458f 4942 [(set (match_operand:SI 0 "s_register_operand" "")
4943 (zero_extend:SI (match_operand:HI 1 "s_register_operand" "")))]
ef51b8e1 4944 "!TARGET_THUMB2 && !arm_arch6"
4945 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4946 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 16)))]
4947{
4948 operands[2] = gen_lowpart (SImode, operands[1]);
4949})
4950
cffb2a26 4951(define_insn "*arm_zero_extendhisi2"
ef51b8e1 4952 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4953 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 4954 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 4955 "@
4956 #
4957 ldr%(h%)\\t%0, %1"
d82e788e 4958 [(set_attr "type" "alu_shift_reg,load_byte")
848e66ac 4959 (set_attr "predicable" "yes")]
cffb2a26 4960)
f7fbdd4a 4961
a2cd141b 4962(define_insn "*arm_zero_extendhisi2_v6"
4963 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
e3f4ccee 4964 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,Uh")))]
a2cd141b 4965 "TARGET_ARM && arm_arch6"
4966 "@
4967 uxth%?\\t%0, %1
25f905c2 4968 ldr%(h%)\\t%0, %1"
65f68e55 4969 [(set_attr "predicable" "yes")
6b6abc9c 4970 (set_attr "type" "extend,load_byte")]
a2cd141b 4971)
4972
4973(define_insn "*arm_zero_extendhisi2addsi"
4974 [(set (match_operand:SI 0 "s_register_operand" "=r")
4975 (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
4976 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4977 "TARGET_INT_SIMD"
a2cd141b 4978 "uxtah%?\\t%0, %2, %1"
d82e788e 4979 [(set_attr "type" "alu_shift_reg")
d952d547 4980 (set_attr "predicable" "yes")
4981 (set_attr "predicable_short_it" "no")]
a2cd141b 4982)
4983
87b22bf7 4984(define_expand "zero_extendqisi2"
cffb2a26 4985 [(set (match_operand:SI 0 "s_register_operand" "")
4986 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
4987 "TARGET_EITHER"
ef51b8e1 4988{
0438d37f 4989 if (TARGET_ARM && !arm_arch6 && !MEM_P (operands[1]))
87b22bf7 4990 {
ef51b8e1 4991 emit_insn (gen_andsi3 (operands[0],
4992 gen_lowpart (SImode, operands[1]),
4993 GEN_INT (255)));
4994 DONE;
4995 }
4996 if (!arm_arch6 && !MEM_P (operands[1]))
4997 {
4998 rtx t = gen_lowpart (SImode, operands[1]);
4999 rtx tmp = gen_reg_rtx (SImode);
5000 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
5001 emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (24)));
5002 DONE;
5003 }
5004})
cffb2a26 5005
ef51b8e1 5006(define_split
b146458f 5007 [(set (match_operand:SI 0 "s_register_operand" "")
5008 (zero_extend:SI (match_operand:QI 1 "s_register_operand" "")))]
ef51b8e1 5009 "!arm_arch6"
5010 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
5011 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 24)))]
5012{
5013 operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
5014 if (TARGET_ARM)
5015 {
5016 emit_insn (gen_andsi3 (operands[0], operands[2], GEN_INT (255)));
87b22bf7 5017 DONE;
5018 }
ef51b8e1 5019})
9c08d1fa 5020
cffb2a26 5021(define_insn "*arm_zero_extendqisi2"
ef51b8e1 5022 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5023 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 5024 "TARGET_ARM && !arm_arch6"
ef51b8e1 5025 "@
5026 #
5027 ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
5028 [(set_attr "length" "8,4")
d82e788e 5029 (set_attr "type" "alu_shift_reg,load_byte")
848e66ac 5030 (set_attr "predicable" "yes")]
cffb2a26 5031)
87b22bf7 5032
a2cd141b 5033(define_insn "*arm_zero_extendqisi2_v6"
5034 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
e3f4ccee 5035 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,Uh")))]
a2cd141b 5036 "TARGET_ARM && arm_arch6"
5037 "@
25f905c2 5038 uxtb%(%)\\t%0, %1
5039 ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
6b6abc9c 5040 [(set_attr "type" "extend,load_byte")
848e66ac 5041 (set_attr "predicable" "yes")]
a2cd141b 5042)
5043
5044(define_insn "*arm_zero_extendqisi2addsi"
5045 [(set (match_operand:SI 0 "s_register_operand" "=r")
5046 (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
5047 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 5048 "TARGET_INT_SIMD"
a2cd141b 5049 "uxtab%?\\t%0, %2, %1"
5050 [(set_attr "predicable" "yes")
d952d547 5051 (set_attr "predicable_short_it" "no")
d82e788e 5052 (set_attr "type" "alu_shift_reg")]
a2cd141b 5053)
5054
87b22bf7 5055(define_split
5056 [(set (match_operand:SI 0 "s_register_operand" "")
5057 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
5058 (clobber (match_operand:SI 2 "s_register_operand" ""))]
0438d37f 5059 "TARGET_32BIT && (!MEM_P (operands[1])) && ! BYTES_BIG_ENDIAN"
87b22bf7 5060 [(set (match_dup 2) (match_dup 1))
5061 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
cffb2a26 5062 ""
5063)
9c08d1fa 5064
8a4d25d6 5065(define_split
5066 [(set (match_operand:SI 0 "s_register_operand" "")
5067 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 3)))
5068 (clobber (match_operand:SI 2 "s_register_operand" ""))]
0438d37f 5069 "TARGET_32BIT && (!MEM_P (operands[1])) && BYTES_BIG_ENDIAN"
8a4d25d6 5070 [(set (match_dup 2) (match_dup 1))
5071 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
5072 ""
5073)
5074
1c274529 5075
5076(define_split
5077 [(set (match_operand:SI 0 "s_register_operand" "")
5078 (ior_xor:SI (and:SI (ashift:SI
5079 (match_operand:SI 1 "s_register_operand" "")
5080 (match_operand:SI 2 "const_int_operand" ""))
5081 (match_operand:SI 3 "const_int_operand" ""))
5082 (zero_extend:SI
5083 (match_operator 5 "subreg_lowpart_operator"
5084 [(match_operand:SI 4 "s_register_operand" "")]))))]
5085 "TARGET_32BIT
63787642 5086 && ((unsigned HOST_WIDE_INT) INTVAL (operands[3])
1c274529 5087 == (GET_MODE_MASK (GET_MODE (operands[5]))
5088 & (GET_MODE_MASK (GET_MODE (operands[5]))
5089 << (INTVAL (operands[2])))))"
5090 [(set (match_dup 0) (ior_xor:SI (ashift:SI (match_dup 1) (match_dup 2))
5091 (match_dup 4)))
5092 (set (match_dup 0) (zero_extend:SI (match_dup 5)))]
5093 "operands[5] = gen_lowpart (GET_MODE (operands[5]), operands[0]);"
5094)
5095
f7fbdd4a 5096(define_insn "*compareqi_eq0"
bd5b4116 5097 [(set (reg:CC_Z CC_REGNUM)
206ee9a2 5098 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
87b22bf7 5099 (const_int 0)))]
25f905c2 5100 "TARGET_32BIT"
596e5e8f 5101 "tst%?\\t%0, #255"
5102 [(set_attr "conds" "set")
d952d547 5103 (set_attr "predicable" "yes")
1b7da4ac 5104 (set_attr "predicable_short_it" "no")
5105 (set_attr "type" "logic_imm")]
cffb2a26 5106)
b11cae9e 5107
b11cae9e 5108(define_expand "extendhisi2"
ef51b8e1 5109 [(set (match_operand:SI 0 "s_register_operand" "")
5110 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
cffb2a26 5111 "TARGET_EITHER"
ef51b8e1 5112{
5113 if (TARGET_THUMB1)
5114 {
5115 emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1]));
5116 DONE;
5117 }
5118 if (MEM_P (operands[1]) && TARGET_ARM && !arm_arch4)
5119 {
5120 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
5121 DONE;
5122 }
ed29c566 5123
ef51b8e1 5124 if (!arm_arch6 && !MEM_P (operands[1]))
5125 {
5126 rtx t = gen_lowpart (SImode, operands[1]);
5127 rtx tmp = gen_reg_rtx (SImode);
5128 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
5129 emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (16)));
5130 DONE;
5131 }
5132})
cffb2a26 5133
ef51b8e1 5134(define_split
5135 [(parallel
5136 [(set (match_operand:SI 0 "register_operand" "")
5137 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))
5138 (clobber (match_scratch:SI 2 ""))])]
5139 "!arm_arch6"
5140 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
5141 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
5142{
5143 operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
5144})
25f7a26e 5145
25f905c2 5146;; This pattern will only be used when ldsh is not available
25f7a26e 5147(define_expand "extendhisi2_mem"
eab14235 5148 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 5149 (set (match_dup 3)
eab14235 5150 (zero_extend:SI (match_dup 7)))
25f7a26e 5151 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
5152 (set (match_operand:SI 0 "" "")
5153 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
cffb2a26 5154 "TARGET_ARM"
25f7a26e 5155 "
215b30b3 5156 {
5157 rtx mem1, mem2;
5158 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
5159
788fcce0 5160 mem1 = change_address (operands[1], QImode, addr);
29c05e22 5161 mem2 = change_address (operands[1], QImode,
5162 plus_constant (Pmode, addr, 1));
215b30b3 5163 operands[0] = gen_lowpart (SImode, operands[0]);
5164 operands[1] = mem1;
5165 operands[2] = gen_reg_rtx (SImode);
5166 operands[3] = gen_reg_rtx (SImode);
5167 operands[6] = gen_reg_rtx (SImode);
5168 operands[7] = mem2;
25f7a26e 5169
215b30b3 5170 if (BYTES_BIG_ENDIAN)
5171 {
5172 operands[4] = operands[2];
5173 operands[5] = operands[3];
5174 }
5175 else
5176 {
5177 operands[4] = operands[3];
5178 operands[5] = operands[2];
5179 }
5180 }"
5181)
b11cae9e 5182
ef51b8e1 5183(define_split
5184 [(set (match_operand:SI 0 "register_operand" "")
5185 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
5186 "!arm_arch6"
5187 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
5188 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
5189{
5190 operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
5191})
5192
a2cd141b 5193(define_insn "*arm_extendhisi2"
ef51b8e1 5194 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
e3f4ccee 5195 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,Uh")))]
a2cd141b 5196 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 5197 "@
5198 #
5199 ldr%(sh%)\\t%0, %1"
5200 [(set_attr "length" "8,4")
d82e788e 5201 (set_attr "type" "alu_shift_reg,load_byte")
e3f4ccee 5202 (set_attr "predicable" "yes")]
cffb2a26 5203)
f7fbdd4a 5204
25f905c2 5205;; ??? Check Thumb-2 pool range
a2cd141b 5206(define_insn "*arm_extendhisi2_v6"
5207 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
e3f4ccee 5208 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,Uh")))]
25f905c2 5209 "TARGET_32BIT && arm_arch6"
a2cd141b 5210 "@
5211 sxth%?\\t%0, %1
25f905c2 5212 ldr%(sh%)\\t%0, %1"
6b6abc9c 5213 [(set_attr "type" "extend,load_byte")
a2cd141b 5214 (set_attr "predicable" "yes")
e3f4ccee 5215 (set_attr "predicable_short_it" "no")]
a2cd141b 5216)
5217
5218(define_insn "*arm_extendhisi2addsi"
5219 [(set (match_operand:SI 0 "s_register_operand" "=r")
5220 (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
5221 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 5222 "TARGET_INT_SIMD"
a2cd141b 5223 "sxtah%?\\t%0, %2, %1"
1b7da4ac 5224 [(set_attr "type" "alu_shift_reg")]
a2cd141b 5225)
5226
c8f69309 5227(define_expand "extendqihi2"
5228 [(set (match_dup 2)
bed7d9a5 5229 (ashift:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")
c8f69309 5230 (const_int 24)))
9c08d1fa 5231 (set (match_operand:HI 0 "s_register_operand" "")
c8f69309 5232 (ashiftrt:SI (match_dup 2)
5233 (const_int 24)))]
cffb2a26 5234 "TARGET_ARM"
c8f69309 5235 "
215b30b3 5236 {
0438d37f 5237 if (arm_arch4 && MEM_P (operands[1]))
215b30b3 5238 {
5239 emit_insn (gen_rtx_SET (VOIDmode,
5240 operands[0],
5241 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
5242 DONE;
5243 }
5244 if (!s_register_operand (operands[1], QImode))
5245 operands[1] = copy_to_mode_reg (QImode, operands[1]);
5246 operands[0] = gen_lowpart (SImode, operands[0]);
5247 operands[1] = gen_lowpart (SImode, operands[1]);
5248 operands[2] = gen_reg_rtx (SImode);
5249 }"
5250)
f7fbdd4a 5251
25f905c2 5252(define_insn "*arm_extendqihi_insn"
b4e8a300 5253 [(set (match_operand:HI 0 "s_register_operand" "=r")
bed7d9a5 5254 (sign_extend:HI (match_operand:QI 1 "arm_extendqisi_mem_op" "Uq")))]
cffb2a26 5255 "TARGET_ARM && arm_arch4"
25f905c2 5256 "ldr%(sb%)\\t%0, %1"
a2cd141b 5257 [(set_attr "type" "load_byte")
e3f4ccee 5258 (set_attr "predicable" "yes")]
cffb2a26 5259)
3fc2009e 5260
b11cae9e 5261(define_expand "extendqisi2"
ef51b8e1 5262 [(set (match_operand:SI 0 "s_register_operand" "")
5263 (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")))]
cffb2a26 5264 "TARGET_EITHER"
ef51b8e1 5265{
5266 if (!arm_arch4 && MEM_P (operands[1]))
5267 operands[1] = copy_to_mode_reg (QImode, operands[1]);
a2cd141b 5268
ef51b8e1 5269 if (!arm_arch6 && !MEM_P (operands[1]))
5270 {
5271 rtx t = gen_lowpart (SImode, operands[1]);
5272 rtx tmp = gen_reg_rtx (SImode);
5273 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
5274 emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (24)));
5275 DONE;
5276 }
5277})
a2cd141b 5278
ef51b8e1 5279(define_split
5280 [(set (match_operand:SI 0 "register_operand" "")
5281 (sign_extend:SI (match_operand:QI 1 "register_operand" "")))]
5282 "!arm_arch6"
5283 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
5284 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))]
5285{
5286 operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
5287})
f7fbdd4a 5288
a2cd141b 5289(define_insn "*arm_extendqisi"
ef51b8e1 5290 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5291 (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
a2cd141b 5292 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 5293 "@
5294 #
5295 ldr%(sb%)\\t%0, %1"
5296 [(set_attr "length" "8,4")
d82e788e 5297 (set_attr "type" "alu_shift_reg,load_byte")
e3f4ccee 5298 (set_attr "predicable" "yes")]
cffb2a26 5299)
3fc2009e 5300
a2cd141b 5301(define_insn "*arm_extendqisi_v6"
5302 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
bed7d9a5 5303 (sign_extend:SI
5304 (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
a2cd141b 5305 "TARGET_ARM && arm_arch6"
b4e8a300 5306 "@
5307 sxtb%?\\t%0, %1
25f905c2 5308 ldr%(sb%)\\t%0, %1"
6b6abc9c 5309 [(set_attr "type" "extend,load_byte")
e3f4ccee 5310 (set_attr "predicable" "yes")]
a2cd141b 5311)
5312
5313(define_insn "*arm_extendqisi2addsi"
5314 [(set (match_operand:SI 0 "s_register_operand" "=r")
5315 (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
5316 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 5317 "TARGET_INT_SIMD"
a2cd141b 5318 "sxtab%?\\t%0, %2, %1"
d82e788e 5319 [(set_attr "type" "alu_shift_reg")
d952d547 5320 (set_attr "predicable" "yes")
5321 (set_attr "predicable_short_it" "no")]
a2cd141b 5322)
5323
caedf871 5324(define_expand "extendsfdf2"
5325 [(set (match_operand:DF 0 "s_register_operand" "")
5326 (float_extend:DF (match_operand:SF 1 "s_register_operand" "")))]
a50d7267 5327 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
caedf871 5328 ""
5329)
9b8516be 5330
5331/* HFmode -> DFmode conversions have to go through SFmode. */
5332(define_expand "extendhfdf2"
5333 [(set (match_operand:DF 0 "general_operand" "")
5334 (float_extend:DF (match_operand:HF 1 "general_operand" "")))]
5335 "TARGET_EITHER"
5336 "
5337 {
5338 rtx op1;
5339 op1 = convert_to_mode (SFmode, operands[1], 0);
5340 op1 = convert_to_mode (DFmode, op1, 0);
5341 emit_insn (gen_movdf (operands[0], op1));
5342 DONE;
5343 }"
5344)
b11cae9e 5345\f
5346;; Move insns (including loads and stores)
5347
5348;; XXX Just some ideas about movti.
9c08d1fa 5349;; I don't think these are a good idea on the arm, there just aren't enough
5350;; registers
b11cae9e 5351;;(define_expand "loadti"
9c08d1fa 5352;; [(set (match_operand:TI 0 "s_register_operand" "")
b11cae9e 5353;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
5354;; "" "")
5355
5356;;(define_expand "storeti"
5357;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
9c08d1fa 5358;; (match_operand:TI 1 "s_register_operand" ""))]
b11cae9e 5359;; "" "")
5360
5361;;(define_expand "movti"
5362;; [(set (match_operand:TI 0 "general_operand" "")
5363;; (match_operand:TI 1 "general_operand" ""))]
5364;; ""
5365;; "
5366;;{
5367;; rtx insn;
5368;;
0438d37f 5369;; if (MEM_P (operands[0]) && MEM_P (operands[1]))
b11cae9e 5370;; operands[1] = copy_to_reg (operands[1]);
0438d37f 5371;; if (MEM_P (operands[0]))
b11cae9e 5372;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
0438d37f 5373;; else if (MEM_P (operands[1]))
b11cae9e 5374;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
5375;; else
5376;; FAIL;
5377;;
5378;; emit_insn (insn);
5379;; DONE;
5380;;}")
5381
a2f10574 5382;; Recognize garbage generated above.
b11cae9e 5383
5384;;(define_insn ""
5385;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
5386;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
5387;; ""
5388;; "*
5389;; {
5390;; register mem = (which_alternative < 3);
0d66636f 5391;; register const char *template;
b11cae9e 5392;;
5393;; operands[mem] = XEXP (operands[mem], 0);
5394;; switch (which_alternative)
5395;; {
5396;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
5397;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
5398;; case 2: template = \"ldmia\\t%1, %M0\"; break;
5399;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
5400;; case 4: template = \"stmia\\t%0!, %M1\"; break;
5401;; case 5: template = \"stmia\\t%0, %M1\"; break;
5402;; }
e2348bcb 5403;; output_asm_insn (template, operands);
5404;; return \"\";
b11cae9e 5405;; }")
5406
cffb2a26 5407(define_expand "movdi"
5408 [(set (match_operand:DI 0 "general_operand" "")
5409 (match_operand:DI 1 "general_operand" ""))]
5410 "TARGET_EITHER"
5411 "
e1ba4a27 5412 if (can_create_pseudo_p ())
cffb2a26 5413 {
0438d37f 5414 if (!REG_P (operands[0]))
b2778788 5415 operands[1] = force_reg (DImode, operands[1]);
cffb2a26 5416 }
5417 "
5418)
b11cae9e 5419
cffb2a26 5420(define_insn "*arm_movdi"
353cf59a 5421 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, q, m")
5422 (match_operand:DI 1 "di_operand" "rDa,Db,Dc,mi,q"))]
cde1623a 5423 "TARGET_32BIT
b805622c 5424 && !(TARGET_HARD_FLOAT && TARGET_VFP)
b2778788 5425 && !TARGET_IWMMXT
5426 && ( register_operand (operands[0], DImode)
5427 || register_operand (operands[1], DImode))"
b11cae9e 5428 "*
d51f92df 5429 switch (which_alternative)
5430 {
5431 case 0:
5432 case 1:
5433 case 2:
5434 return \"#\";
5435 default:
26ff80c0 5436 return output_move_double (operands, true, NULL);
d51f92df 5437 }
cffb2a26 5438 "
359a6e9f 5439 [(set_attr "length" "8,12,16,8,8")
1b7da4ac 5440 (set_attr "type" "multiple,multiple,multiple,load2,store2")
cde1623a 5441 (set_attr "arm_pool_range" "*,*,*,1020,*")
8848d797 5442 (set_attr "arm_neg_pool_range" "*,*,*,1004,*")
42e1de19 5443 (set_attr "thumb2_pool_range" "*,*,*,4094,*")
cde1623a 5444 (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
cffb2a26 5445)
5446
d51f92df 5447(define_split
5448 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
e6dd3afa 5449 (match_operand:ANY64 1 "immediate_operand" ""))]
25f905c2 5450 "TARGET_32BIT
d51f92df 5451 && reload_completed
5452 && (arm_const_double_inline_cost (operands[1])
861033d5 5453 <= arm_max_const_double_inline_cost ())"
d51f92df 5454 [(const_int 0)]
5455 "
5456 arm_split_constant (SET, SImode, curr_insn,
5457 INTVAL (gen_lowpart (SImode, operands[1])),
5458 gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
5459 arm_split_constant (SET, SImode, curr_insn,
5460 INTVAL (gen_highpart_mode (SImode,
5461 GET_MODE (operands[0]),
5462 operands[1])),
5463 gen_highpart (SImode, operands[0]), NULL_RTX, 0);
5464 DONE;
5465 "
5466)
5467
e5ba9289 5468; If optimizing for size, or if we have load delay slots, then
5469; we want to split the constant into two separate operations.
5470; In both cases this may split a trivial part into a single data op
5471; leaving a single complex constant to load. We can also get longer
5472; offsets in a LDR which means we get better chances of sharing the pool
5473; entries. Finally, we can normally do a better job of scheduling
5474; LDR instructions than we can with LDM.
5475; This pattern will only match if the one above did not.
5476(define_split
5477 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
5478 (match_operand:ANY64 1 "const_double_operand" ""))]
5479 "TARGET_ARM && reload_completed
5480 && arm_const_double_by_parts (operands[1])"
5481 [(set (match_dup 0) (match_dup 1))
5482 (set (match_dup 2) (match_dup 3))]
5483 "
5484 operands[2] = gen_highpart (SImode, operands[0]);
5485 operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
5486 operands[1]);
5487 operands[0] = gen_lowpart (SImode, operands[0]);
5488 operands[1] = gen_lowpart (SImode, operands[1]);
5489 "
5490)
5491
d51f92df 5492(define_split
5493 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
5494 (match_operand:ANY64 1 "arm_general_register_operand" ""))]
5495 "TARGET_EITHER && reload_completed"
5496 [(set (match_dup 0) (match_dup 1))
5497 (set (match_dup 2) (match_dup 3))]
5498 "
5499 operands[2] = gen_highpart (SImode, operands[0]);
5500 operands[3] = gen_highpart (SImode, operands[1]);
5501 operands[0] = gen_lowpart (SImode, operands[0]);
5502 operands[1] = gen_lowpart (SImode, operands[1]);
5503
5504 /* Handle a partial overlap. */
5505 if (rtx_equal_p (operands[0], operands[3]))
5506 {
5507 rtx tmp0 = operands[0];
5508 rtx tmp1 = operands[1];
5509
5510 operands[0] = operands[2];
5511 operands[1] = operands[3];
5512 operands[2] = tmp0;
5513 operands[3] = tmp1;
5514 }
5515 "
5516)
5517
a8a3b539 5518;; We can't actually do base+index doubleword loads if the index and
5519;; destination overlap. Split here so that we at least have chance to
5520;; schedule.
5521(define_split
5522 [(set (match_operand:DI 0 "s_register_operand" "")
5523 (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
5524 (match_operand:SI 2 "s_register_operand" ""))))]
5525 "TARGET_LDRD
5526 && reg_overlap_mentioned_p (operands[0], operands[1])
5527 && reg_overlap_mentioned_p (operands[0], operands[2])"
5528 [(set (match_dup 4)
5529 (plus:SI (match_dup 1)
5530 (match_dup 2)))
5531 (set (match_dup 0)
5532 (mem:DI (match_dup 4)))]
5533 "
5534 operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
5535 "
5536)
5537
9c08d1fa 5538(define_expand "movsi"
5539 [(set (match_operand:SI 0 "general_operand" "")
5540 (match_operand:SI 1 "general_operand" ""))]
cffb2a26 5541 "TARGET_EITHER"
9c08d1fa 5542 "
befb0bac 5543 {
e348ff3e 5544 rtx base, offset, tmp;
5545
25f905c2 5546 if (TARGET_32BIT)
9c08d1fa 5547 {
674a8f0b 5548 /* Everything except mem = const or mem = mem can be done easily. */
0438d37f 5549 if (MEM_P (operands[0]))
cffb2a26 5550 operands[1] = force_reg (SImode, operands[1]);
a2cd141b 5551 if (arm_general_register_operand (operands[0], SImode)
0438d37f 5552 && CONST_INT_P (operands[1])
cffb2a26 5553 && !(const_ok_for_arm (INTVAL (operands[1]))
5554 || const_ok_for_arm (~INTVAL (operands[1]))))
5555 {
96f57e36 5556 arm_split_constant (SET, SImode, NULL_RTX,
5557 INTVAL (operands[1]), operands[0], NULL_RTX,
e1ba4a27 5558 optimize && can_create_pseudo_p ());
cffb2a26 5559 DONE;
5560 }
5561 }
25f905c2 5562 else /* TARGET_THUMB1... */
cffb2a26 5563 {
e1ba4a27 5564 if (can_create_pseudo_p ())
cffb2a26 5565 {
0438d37f 5566 if (!REG_P (operands[0]))
cffb2a26 5567 operands[1] = force_reg (SImode, operands[1]);
5568 }
9c08d1fa 5569 }
f655717d 5570
e348ff3e 5571 if (ARM_OFFSETS_MUST_BE_WITHIN_SECTIONS_P)
5572 {
5573 split_const (operands[1], &base, &offset);
5574 if (GET_CODE (base) == SYMBOL_REF
5575 && !offset_within_block_p (base, INTVAL (offset)))
5576 {
b308ddcf 5577 tmp = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
e348ff3e 5578 emit_move_insn (tmp, base);
5579 emit_insn (gen_addsi3 (operands[0], tmp, offset));
5580 DONE;
5581 }
5582 }
5583
f655717d 5584 /* Recognize the case where operand[1] is a reference to thread-local
5585 data and load its address to a register. */
5586 if (arm_tls_referenced_p (operands[1]))
5587 {
5588 rtx tmp = operands[1];
5589 rtx addend = NULL;
5590
5591 if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
5592 {
5593 addend = XEXP (XEXP (tmp, 0), 1);
5594 tmp = XEXP (XEXP (tmp, 0), 0);
5595 }
5596
5597 gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
5598 gcc_assert (SYMBOL_REF_TLS_MODEL (tmp) != 0);
5599
e1ba4a27 5600 tmp = legitimize_tls_address (tmp,
5601 !can_create_pseudo_p () ? operands[0] : 0);
f655717d 5602 if (addend)
5603 {
5604 tmp = gen_rtx_PLUS (SImode, tmp, addend);
5605 tmp = force_operand (tmp, operands[0]);
5606 }
5607 operands[1] = tmp;
5608 }
5609 else if (flag_pic
5610 && (CONSTANT_P (operands[1])
5611 || symbol_mentioned_p (operands[1])
5612 || label_mentioned_p (operands[1])))
5613 operands[1] = legitimize_pic_address (operands[1], SImode,
e1ba4a27 5614 (!can_create_pseudo_p ()
5615 ? operands[0]
5616 : 0));
befb0bac 5617 }
215b30b3 5618 "
5619)
9c08d1fa 5620
d0e6a121 5621;; The ARM LO_SUM and HIGH are backwards - HIGH sets the low bits, and
5622;; LO_SUM adds in the high bits. Fortunately these are opaque operations
5623;; so this does not matter.
5624(define_insn "*arm_movt"
5625 [(set (match_operand:SI 0 "nonimmediate_operand" "=r")
5626 (lo_sum:SI (match_operand:SI 1 "nonimmediate_operand" "0")
5627 (match_operand:SI 2 "general_operand" "i")))]
c9b2ce40 5628 "arm_arch_thumb2"
d0e6a121 5629 "movt%?\t%0, #:upper16:%c2"
5630 [(set_attr "predicable" "yes")
d952d547 5631 (set_attr "predicable_short_it" "no")
1b7da4ac 5632 (set_attr "length" "4")
5633 (set_attr "type" "mov_imm")]
d0e6a121 5634)
5635
cffb2a26 5636(define_insn "*arm_movsi_insn"
aaa37ad6 5637 [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,rk,m")
110eae03 5638 (match_operand:SI 1 "general_operand" "rk, I,K,j,mi,rk"))]
755eb2b4 5639 "TARGET_ARM && ! TARGET_IWMMXT
a2cd141b 5640 && !(TARGET_HARD_FLOAT && TARGET_VFP)
cffb2a26 5641 && ( register_operand (operands[0], SImode)
5642 || register_operand (operands[1], SImode))"
f7fbdd4a 5643 "@
aaa37ad6 5644 mov%?\\t%0, %1
f7fbdd4a 5645 mov%?\\t%0, %1
5646 mvn%?\\t%0, #%B1
25f905c2 5647 movw%?\\t%0, %1
f7fbdd4a 5648 ldr%?\\t%0, %1
5649 str%?\\t%1, %0"
1aed5204 5650 [(set_attr "type" "mov_reg,mov_imm,mvn_imm,mov_imm,load1,store1")
0d66636f 5651 (set_attr "predicable" "yes")
aaa37ad6 5652 (set_attr "pool_range" "*,*,*,*,4096,*")
5653 (set_attr "neg_pool_range" "*,*,*,*,4084,*")]
cffb2a26 5654)
87b22bf7 5655
5656(define_split
a2cd141b 5657 [(set (match_operand:SI 0 "arm_general_register_operand" "")
87b22bf7 5658 (match_operand:SI 1 "const_int_operand" ""))]
25f905c2 5659 "TARGET_32BIT
215b30b3 5660 && (!(const_ok_for_arm (INTVAL (operands[1]))
5661 || const_ok_for_arm (~INTVAL (operands[1]))))"
87b22bf7 5662 [(clobber (const_int 0))]
5663 "
96f57e36 5664 arm_split_constant (SET, SImode, NULL_RTX,
5665 INTVAL (operands[1]), operands[0], NULL_RTX, 0);
87b22bf7 5666 DONE;
215b30b3 5667 "
5668)
9c08d1fa 5669
861033d5 5670;; A normal way to do (symbol + offset) requires three instructions at least
5671;; (depends on how big the offset is) as below:
5672;; movw r0, #:lower16:g
5673;; movw r0, #:upper16:g
5674;; adds r0, #4
5675;;
5676;; A better way would be:
5677;; movw r0, #:lower16:g+4
5678;; movw r0, #:upper16:g+4
5679;;
5680;; The limitation of this way is that the length of offset should be a 16-bit
5681;; signed value, because current assembler only supports REL type relocation for
5682;; such case. If the more powerful RELA type is supported in future, we should
5683;; update this pattern to go with better way.
5684(define_split
5685 [(set (match_operand:SI 0 "arm_general_register_operand" "")
5686 (const:SI (plus:SI (match_operand:SI 1 "general_operand" "")
5687 (match_operand:SI 2 "const_int_operand" ""))))]
5688 "TARGET_THUMB2
5689 && arm_disable_literal_pool
5690 && reload_completed
5691 && GET_CODE (operands[1]) == SYMBOL_REF"
5692 [(clobber (const_int 0))]
5693 "
5694 int offset = INTVAL (operands[2]);
5695
5696 if (offset < -0x8000 || offset > 0x7fff)
5697 {
5698 arm_emit_movpair (operands[0], operands[1]);
5699 emit_insn (gen_rtx_SET (SImode, operands[0],
5700 gen_rtx_PLUS (SImode, operands[0], operands[2])));
5701 }
5702 else
5703 {
5704 rtx op = gen_rtx_CONST (SImode,
5705 gen_rtx_PLUS (SImode, operands[1], operands[2]));
5706 arm_emit_movpair (operands[0], op);
5707 }
5708 "
5709)
5710
b8d5d078 5711;; Split symbol_refs at the later stage (after cprop), instead of generating
5712;; movt/movw pair directly at expand. Otherwise corresponding high_sum
5713;; and lo_sum would be merged back into memory load at cprop. However,
5714;; if the default is to prefer movt/movw rather than a load from the constant
5715;; pool, the performance is better.
5716(define_split
5717 [(set (match_operand:SI 0 "arm_general_register_operand" "")
5718 (match_operand:SI 1 "general_operand" ""))]
5719 "TARGET_32BIT
5720 && TARGET_USE_MOVT && GET_CODE (operands[1]) == SYMBOL_REF
5721 && !flag_pic && !target_word_relocations
5722 && !arm_tls_referenced_p (operands[1])"
5723 [(clobber (const_int 0))]
5724{
5725 arm_emit_movpair (operands[0], operands[1]);
5726 DONE;
5727})
5728
bc360af8 5729;; When generating pic, we need to load the symbol offset into a register.
5730;; So that the optimizer does not confuse this with a normal symbol load
5731;; we use an unspec. The offset will be loaded from a constant pool entry,
5732;; since that is the only type of relocation we can use.
cffb2a26 5733
bc360af8 5734;; Wrap calculation of the whole PIC address in a single pattern for the
5735;; benefit of optimizers, particularly, PRE and HOIST. Calculation of
5736;; a PIC address involves two loads from memory, so we want to CSE it
5737;; as often as possible.
5738;; This pattern will be split into one of the pic_load_addr_* patterns
5739;; and a move after GCSE optimizations.
5740;;
5741;; Note: Update arm.c: legitimize_pic_address() when changing this pattern.
5742(define_expand "calculate_pic_address"
94f8caca 5743 [(set (match_operand:SI 0 "register_operand" "")
5744 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "")
5745 (unspec:SI [(match_operand:SI 2 "" "")]
5746 UNSPEC_PIC_SYM))))]
5747 "flag_pic"
5748)
5749
5750;; Split calculate_pic_address into pic_load_addr_* and a move.
5751(define_split
5752 [(set (match_operand:SI 0 "register_operand" "")
5753 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "")
5754 (unspec:SI [(match_operand:SI 2 "" "")]
5755 UNSPEC_PIC_SYM))))]
5756 "flag_pic"
5757 [(set (match_dup 3) (unspec:SI [(match_dup 2)] UNSPEC_PIC_SYM))
5758 (set (match_dup 0) (mem:SI (plus:SI (match_dup 1) (match_dup 3))))]
5759 "operands[3] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];"
5760)
5761
350ccca5 5762;; operand1 is the memory address to go into
5763;; pic_load_addr_32bit.
5764;; operand2 is the PIC label to be emitted
5765;; from pic_add_dot_plus_eight.
5766;; We do this to allow hoisting of the entire insn.
5767(define_insn_and_split "pic_load_addr_unified"
5768 [(set (match_operand:SI 0 "s_register_operand" "=r,r,l")
5769 (unspec:SI [(match_operand:SI 1 "" "mX,mX,mX")
5770 (match_operand:SI 2 "" "")]
5771 UNSPEC_PIC_UNIFIED))]
5772 "flag_pic"
5773 "#"
5774 "&& reload_completed"
5775 [(set (match_dup 0) (unspec:SI [(match_dup 1)] UNSPEC_PIC_SYM))
5776 (set (match_dup 0) (unspec:SI [(match_dup 0) (match_dup 3)
5777 (match_dup 2)] UNSPEC_PIC_BASE))]
5778 "operands[3] = TARGET_THUMB ? GEN_INT (4) : GEN_INT (8);"
5779 [(set_attr "type" "load1,load1,load1")
42e1de19 5780 (set_attr "pool_range" "4096,4094,1022")
350ccca5 5781 (set_attr "neg_pool_range" "4084,0,0")
5782 (set_attr "arch" "a,t2,t1")
5783 (set_attr "length" "8,6,4")]
5784)
5785
67336bcf 5786;; The rather odd constraints on the following are to force reload to leave
5787;; the insn alone, and to force the minipool generation pass to then move
5788;; the GOT symbol to memory.
849170fd 5789
b3cd5f55 5790(define_insn "pic_load_addr_32bit"
849170fd 5791 [(set (match_operand:SI 0 "s_register_operand" "=r")
e1159bbe 5792 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
b3cd5f55 5793 "TARGET_32BIT && flag_pic"
67336bcf 5794 "ldr%?\\t%0, %1"
a2cd141b 5795 [(set_attr "type" "load1")
42e1de19 5796 (set (attr "pool_range")
5797 (if_then_else (eq_attr "is_thumb" "no")
5798 (const_int 4096)
5799 (const_int 4094)))
b3cd5f55 5800 (set (attr "neg_pool_range")
5801 (if_then_else (eq_attr "is_thumb" "no")
5802 (const_int 4084)
5803 (const_int 0)))]
8c4d8060 5804)
5805
25f905c2 5806(define_insn "pic_load_addr_thumb1"
8c4d8060 5807 [(set (match_operand:SI 0 "s_register_operand" "=l")
e1159bbe 5808 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
25f905c2 5809 "TARGET_THUMB1 && flag_pic"
8c4d8060 5810 "ldr\\t%0, %1"
a2cd141b 5811 [(set_attr "type" "load1")
42e1de19 5812 (set (attr "pool_range") (const_int 1018))]
cffb2a26 5813)
849170fd 5814
cffb2a26 5815(define_insn "pic_add_dot_plus_four"
15d5d060 5816 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5817 (unspec:SI [(match_operand:SI 1 "register_operand" "0")
5818 (const_int 4)
beef0fb5 5819 (match_operand 2 "" "")]
5820 UNSPEC_PIC_BASE))]
b3cd5f55 5821 "TARGET_THUMB"
cffb2a26 5822 "*
6cdcb15c 5823 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5824 INTVAL (operands[2]));
cffb2a26 5825 return \"add\\t%0, %|pc\";
5826 "
1b7da4ac 5827 [(set_attr "length" "2")
112eda6f 5828 (set_attr "type" "alu_sreg")]
cffb2a26 5829)
849170fd 5830
5831(define_insn "pic_add_dot_plus_eight"
15d5d060 5832 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5833 (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5834 (const_int 8)
beef0fb5 5835 (match_operand 2 "" "")]
5836 UNSPEC_PIC_BASE))]
f655717d 5837 "TARGET_ARM"
c4034607 5838 "*
6cdcb15c 5839 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5840 INTVAL (operands[2]));
15d5d060 5841 return \"add%?\\t%0, %|pc, %1\";
cffb2a26 5842 "
1b7da4ac 5843 [(set_attr "predicable" "yes")
112eda6f 5844 (set_attr "type" "alu_sreg")]
cffb2a26 5845)
849170fd 5846
f655717d 5847(define_insn "tls_load_dot_plus_eight"
cc071db6 5848 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5849 (mem:SI (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5850 (const_int 8)
beef0fb5 5851 (match_operand 2 "" "")]
5852 UNSPEC_PIC_BASE)))]
f655717d 5853 "TARGET_ARM"
5854 "*
6cdcb15c 5855 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5856 INTVAL (operands[2]));
f655717d 5857 return \"ldr%?\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_eight\";
5858 "
1b7da4ac 5859 [(set_attr "predicable" "yes")
5860 (set_attr "type" "load1")]
f655717d 5861)
5862
5863;; PIC references to local variables can generate pic_add_dot_plus_eight
5864;; followed by a load. These sequences can be crunched down to
5865;; tls_load_dot_plus_eight by a peephole.
5866
5867(define_peephole2
c0c1fba5 5868 [(set (match_operand:SI 0 "register_operand" "")
5869 (unspec:SI [(match_operand:SI 3 "register_operand" "")
5870 (const_int 8)
5871 (match_operand 1 "" "")]
5872 UNSPEC_PIC_BASE))
2d05dfad 5873 (set (match_operand:SI 2 "arm_general_register_operand" "")
5874 (mem:SI (match_dup 0)))]
f655717d 5875 "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
c0c1fba5 5876 [(set (match_dup 2)
5877 (mem:SI (unspec:SI [(match_dup 3)
5878 (const_int 8)
5879 (match_dup 1)]
5880 UNSPEC_PIC_BASE)))]
f655717d 5881 ""
5882)
5883
bac7fc85 5884(define_insn "pic_offset_arm"
5885 [(set (match_operand:SI 0 "register_operand" "=r")
5886 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
5887 (unspec:SI [(match_operand:SI 2 "" "X")]
5888 UNSPEC_PIC_OFFSET))))]
5889 "TARGET_VXWORKS_RTP && TARGET_ARM && flag_pic"
5890 "ldr%?\\t%0, [%1,%2]"
5891 [(set_attr "type" "load1")]
5892)
5893
95373f08 5894(define_expand "builtin_setjmp_receiver"
5895 [(label_ref (match_operand 0 "" ""))]
5896 "flag_pic"
5897 "
5898{
b935b306 5899 /* r3 is clobbered by set/longjmp, so we can use it as a scratch
5900 register. */
2cb7d577 5901 if (arm_pic_register != INVALID_REGNUM)
5902 arm_load_pic_register (1UL << 3);
95373f08 5903 DONE;
5904}")
5905
9c08d1fa 5906;; If copying one reg to another we can set the condition codes according to
5907;; its value. Such a move is common after a return from subroutine and the
5908;; result is being tested against zero.
5909
f7fbdd4a 5910(define_insn "*movsi_compare0"
bd5b4116 5911 [(set (reg:CC CC_REGNUM)
cffb2a26 5912 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
5913 (const_int 0)))
5914 (set (match_operand:SI 0 "s_register_operand" "=r,r")
5915 (match_dup 1))]
25f905c2 5916 "TARGET_32BIT"
e2348bcb 5917 "@
40dbec34 5918 cmp%?\\t%0, #0
25f905c2 5919 sub%.\\t%0, %1, #0"
65f68e55 5920 [(set_attr "conds" "set")
d82e788e 5921 (set_attr "type" "alus_imm,alus_imm")]
cffb2a26 5922)
b11cae9e 5923
b11cae9e 5924;; Subroutine to store a half word from a register into memory.
5925;; Operand 0 is the source register (HImode)
c8f69309 5926;; Operand 1 is the destination address in a register (SImode)
b11cae9e 5927
9c08d1fa 5928;; In both this routine and the next, we must be careful not to spill
01cc3b75 5929;; a memory address of reg+large_const into a separate PLUS insn, since this
9c08d1fa 5930;; can generate unrecognizable rtl.
5931
b11cae9e 5932(define_expand "storehi"
c8f69309 5933 [;; store the low byte
f082f1c4 5934 (set (match_operand 1 "" "") (match_dup 3))
b11cae9e 5935 ;; extract the high byte
c8f69309 5936 (set (match_dup 2)
5937 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
b11cae9e 5938 ;; store the high byte
787f8210 5939 (set (match_dup 4) (match_dup 5))]
cffb2a26 5940 "TARGET_ARM"
b11cae9e 5941 "
215b30b3 5942 {
537ffcfc 5943 rtx op1 = operands[1];
5944 rtx addr = XEXP (op1, 0);
215b30b3 5945 enum rtx_code code = GET_CODE (addr);
5946
0438d37f 5947 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
215b30b3 5948 || code == MINUS)
537ffcfc 5949 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
215b30b3 5950
537ffcfc 5951 operands[4] = adjust_address (op1, QImode, 1);
e513d163 5952 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 5953 operands[3] = gen_lowpart (QImode, operands[0]);
5954 operands[0] = gen_lowpart (SImode, operands[0]);
787f8210 5955 operands[2] = gen_reg_rtx (SImode);
5956 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 5957 }"
5958)
b11cae9e 5959
c7597b5d 5960(define_expand "storehi_bigend"
f082f1c4 5961 [(set (match_dup 4) (match_dup 3))
c7597b5d 5962 (set (match_dup 2)
5963 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
787f8210 5964 (set (match_operand 1 "" "") (match_dup 5))]
cffb2a26 5965 "TARGET_ARM"
b11cae9e 5966 "
215b30b3 5967 {
537ffcfc 5968 rtx op1 = operands[1];
5969 rtx addr = XEXP (op1, 0);
215b30b3 5970 enum rtx_code code = GET_CODE (addr);
5971
0438d37f 5972 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
215b30b3 5973 || code == MINUS)
537ffcfc 5974 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
215b30b3 5975
537ffcfc 5976 operands[4] = adjust_address (op1, QImode, 1);
e513d163 5977 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 5978 operands[3] = gen_lowpart (QImode, operands[0]);
5979 operands[0] = gen_lowpart (SImode, operands[0]);
5980 operands[2] = gen_reg_rtx (SImode);
787f8210 5981 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 5982 }"
5983)
c7597b5d 5984
5985;; Subroutine to store a half word integer constant into memory.
5986(define_expand "storeinthi"
f082f1c4 5987 [(set (match_operand 0 "" "")
787f8210 5988 (match_operand 1 "" ""))
9e8503e6 5989 (set (match_dup 3) (match_dup 2))]
cffb2a26 5990 "TARGET_ARM"
c7597b5d 5991 "
215b30b3 5992 {
5993 HOST_WIDE_INT value = INTVAL (operands[1]);
5994 rtx addr = XEXP (operands[0], 0);
537ffcfc 5995 rtx op0 = operands[0];
215b30b3 5996 enum rtx_code code = GET_CODE (addr);
c7597b5d 5997
0438d37f 5998 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
215b30b3 5999 || code == MINUS)
537ffcfc 6000 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
c7597b5d 6001
215b30b3 6002 operands[1] = gen_reg_rtx (SImode);
6003 if (BYTES_BIG_ENDIAN)
6004 {
6005 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
6006 if ((value & 255) == ((value >> 8) & 255))
6007 operands[2] = operands[1];
6008 else
6009 {
6010 operands[2] = gen_reg_rtx (SImode);
6011 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
6012 }
6013 }
6014 else
6015 {
6016 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
6017 if ((value & 255) == ((value >> 8) & 255))
6018 operands[2] = operands[1];
6019 else
6020 {
6021 operands[2] = gen_reg_rtx (SImode);
6022 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
6023 }
6024 }
c7597b5d 6025
537ffcfc 6026 operands[3] = adjust_address (op0, QImode, 1);
e513d163 6027 operands[0] = adjust_address (operands[0], QImode, 0);
9e8503e6 6028 operands[2] = gen_lowpart (QImode, operands[2]);
787f8210 6029 operands[1] = gen_lowpart (QImode, operands[1]);
215b30b3 6030 }"
6031)
b11cae9e 6032
f7fbdd4a 6033(define_expand "storehi_single_op"
6034 [(set (match_operand:HI 0 "memory_operand" "")
6035 (match_operand:HI 1 "general_operand" ""))]
25f905c2 6036 "TARGET_32BIT && arm_arch4"
f7fbdd4a 6037 "
215b30b3 6038 if (!s_register_operand (operands[1], HImode))
f7fbdd4a 6039 operands[1] = copy_to_mode_reg (HImode, operands[1]);
215b30b3 6040 "
6041)
f7fbdd4a 6042
b11cae9e 6043(define_expand "movhi"
6044 [(set (match_operand:HI 0 "general_operand" "")
c8f69309 6045 (match_operand:HI 1 "general_operand" ""))]
cffb2a26 6046 "TARGET_EITHER"
b11cae9e 6047 "
cffb2a26 6048 if (TARGET_ARM)
b11cae9e 6049 {
e1ba4a27 6050 if (can_create_pseudo_p ())
cffb2a26 6051 {
0438d37f 6052 if (MEM_P (operands[0]))
b11cae9e 6053 {
cffb2a26 6054 if (arm_arch4)
6055 {
6056 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
6057 DONE;
6058 }
0438d37f 6059 if (CONST_INT_P (operands[1]))
cffb2a26 6060 emit_insn (gen_storeinthi (operands[0], operands[1]));
c7597b5d 6061 else
cffb2a26 6062 {
0438d37f 6063 if (MEM_P (operands[1]))
cffb2a26 6064 operands[1] = force_reg (HImode, operands[1]);
6065 if (BYTES_BIG_ENDIAN)
6066 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
6067 else
6068 emit_insn (gen_storehi (operands[1], operands[0]));
6069 }
6070 DONE;
b11cae9e 6071 }
cffb2a26 6072 /* Sign extend a constant, and keep it in an SImode reg. */
0438d37f 6073 else if (CONST_INT_P (operands[1]))
9c08d1fa 6074 {
cffb2a26 6075 rtx reg = gen_reg_rtx (SImode);
6076 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
6077
6078 /* If the constant is already valid, leave it alone. */
215b30b3 6079 if (!const_ok_for_arm (val))
cffb2a26 6080 {
6081 /* If setting all the top bits will make the constant
6082 loadable in a single instruction, then set them.
6083 Otherwise, sign extend the number. */
6084
215b30b3 6085 if (const_ok_for_arm (~(val | ~0xffff)))
cffb2a26 6086 val |= ~0xffff;
6087 else if (val & 0x8000)
6088 val |= ~0xffff;
6089 }
6090
6091 emit_insn (gen_movsi (reg, GEN_INT (val)));
9e8503e6 6092 operands[1] = gen_lowpart (HImode, reg);
9c08d1fa 6093 }
e1ba4a27 6094 else if (arm_arch4 && optimize && can_create_pseudo_p ()
0438d37f 6095 && MEM_P (operands[1]))
0045890a 6096 {
6097 rtx reg = gen_reg_rtx (SImode);
6098
6099 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
6100 operands[1] = gen_lowpart (HImode, reg);
6101 }
215b30b3 6102 else if (!arm_arch4)
f7fbdd4a 6103 {
0438d37f 6104 if (MEM_P (operands[1]))
cffb2a26 6105 {
c1a66faf 6106 rtx base;
6107 rtx offset = const0_rtx;
6108 rtx reg = gen_reg_rtx (SImode);
6109
0438d37f 6110 if ((REG_P (base = XEXP (operands[1], 0))
c1a66faf 6111 || (GET_CODE (base) == PLUS
0438d37f 6112 && (CONST_INT_P (offset = XEXP (base, 1)))
c1a66faf 6113 && ((INTVAL(offset) & 1) != 1)
0438d37f 6114 && REG_P (base = XEXP (base, 0))))
c1a66faf 6115 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
206ee9a2 6116 {
8deb3959 6117 rtx new_rtx;
c1a66faf 6118
8deb3959 6119 new_rtx = widen_memory_access (operands[1], SImode,
6120 ((INTVAL (offset) & ~3)
6121 - INTVAL (offset)));
6122 emit_insn (gen_movsi (reg, new_rtx));
c1a66faf 6123 if (((INTVAL (offset) & 2) != 0)
6124 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
6125 {
6126 rtx reg2 = gen_reg_rtx (SImode);
6127
6128 emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
6129 reg = reg2;
6130 }
206ee9a2 6131 }
c1a66faf 6132 else
6133 emit_insn (gen_movhi_bytes (reg, operands[1]));
6134
6135 operands[1] = gen_lowpart (HImode, reg);
cffb2a26 6136 }
6137 }
6138 }
674a8f0b 6139 /* Handle loading a large integer during reload. */
0438d37f 6140 else if (CONST_INT_P (operands[1])
215b30b3 6141 && !const_ok_for_arm (INTVAL (operands[1]))
6142 && !const_ok_for_arm (~INTVAL (operands[1])))
cffb2a26 6143 {
6144 /* Writing a constant to memory needs a scratch, which should
6145 be handled with SECONDARY_RELOADs. */
0438d37f 6146 gcc_assert (REG_P (operands[0]));
cffb2a26 6147
6148 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
6149 emit_insn (gen_movsi (operands[0], operands[1]));
6150 DONE;
6151 }
6152 }
25f905c2 6153 else if (TARGET_THUMB2)
6154 {
6155 /* Thumb-2 can do everything except mem=mem and mem=const easily. */
e1ba4a27 6156 if (can_create_pseudo_p ())
25f905c2 6157 {
0438d37f 6158 if (!REG_P (operands[0]))
25f905c2 6159 operands[1] = force_reg (HImode, operands[1]);
6160 /* Zero extend a constant, and keep it in an SImode reg. */
0438d37f 6161 else if (CONST_INT_P (operands[1]))
25f905c2 6162 {
6163 rtx reg = gen_reg_rtx (SImode);
6164 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
6165
6166 emit_insn (gen_movsi (reg, GEN_INT (val)));
6167 operands[1] = gen_lowpart (HImode, reg);
6168 }
6169 }
6170 }
6171 else /* TARGET_THUMB1 */
cffb2a26 6172 {
e1ba4a27 6173 if (can_create_pseudo_p ())
cffb2a26 6174 {
0438d37f 6175 if (CONST_INT_P (operands[1]))
6cffc037 6176 {
6177 rtx reg = gen_reg_rtx (SImode);
6178
6179 emit_insn (gen_movsi (reg, operands[1]));
6180 operands[1] = gen_lowpart (HImode, reg);
6181 }
cffb2a26 6182
6183 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 6184 happen if we are passed a SP (never OK for HImode/QImode) or
bc409cb4 6185 virtual register (also rejected as illegitimate for HImode/QImode)
6186 relative address. */
cffb2a26 6187 /* ??? This should perhaps be fixed elsewhere, for instance, in
6188 fixup_stack_1, by checking for other kinds of invalid addresses,
6189 e.g. a bare reference to a virtual register. This may confuse the
6190 alpha though, which must handle this case differently. */
0438d37f 6191 if (MEM_P (operands[0])
215b30b3 6192 && !memory_address_p (GET_MODE (operands[0]),
6193 XEXP (operands[0], 0)))
537ffcfc 6194 operands[0]
6195 = replace_equiv_address (operands[0],
6196 copy_to_reg (XEXP (operands[0], 0)));
cffb2a26 6197
0438d37f 6198 if (MEM_P (operands[1])
215b30b3 6199 && !memory_address_p (GET_MODE (operands[1]),
6200 XEXP (operands[1], 0)))
537ffcfc 6201 operands[1]
6202 = replace_equiv_address (operands[1],
6203 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 6204
0438d37f 6205 if (MEM_P (operands[1]) && optimize > 0)
6cffc037 6206 {
6207 rtx reg = gen_reg_rtx (SImode);
6208
6209 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
6210 operands[1] = gen_lowpart (HImode, reg);
6211 }
6212
0438d37f 6213 if (MEM_P (operands[0]))
6cffc037 6214 operands[1] = force_reg (HImode, operands[1]);
cffb2a26 6215 }
0438d37f 6216 else if (CONST_INT_P (operands[1])
234f6557 6217 && !satisfies_constraint_I (operands[1]))
cffb2a26 6218 {
6cffc037 6219 /* Handle loading a large integer during reload. */
6220
cffb2a26 6221 /* Writing a constant to memory needs a scratch, which should
6222 be handled with SECONDARY_RELOADs. */
0438d37f 6223 gcc_assert (REG_P (operands[0]));
cffb2a26 6224
1a83b3ff 6225 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
cffb2a26 6226 emit_insn (gen_movsi (operands[0], operands[1]));
6227 DONE;
6228 }
b11cae9e 6229 }
cffb2a26 6230 "
6231)
6232
25f7a26e 6233(define_expand "movhi_bytes"
eab14235 6234 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 6235 (set (match_dup 3)
eab14235 6236 (zero_extend:SI (match_dup 6)))
25f7a26e 6237 (set (match_operand:SI 0 "" "")
6238 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
cffb2a26 6239 "TARGET_ARM"
25f7a26e 6240 "
215b30b3 6241 {
6242 rtx mem1, mem2;
6243 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
6244
788fcce0 6245 mem1 = change_address (operands[1], QImode, addr);
29c05e22 6246 mem2 = change_address (operands[1], QImode,
6247 plus_constant (Pmode, addr, 1));
215b30b3 6248 operands[0] = gen_lowpart (SImode, operands[0]);
6249 operands[1] = mem1;
6250 operands[2] = gen_reg_rtx (SImode);
6251 operands[3] = gen_reg_rtx (SImode);
6252 operands[6] = mem2;
25f7a26e 6253
215b30b3 6254 if (BYTES_BIG_ENDIAN)
6255 {
6256 operands[4] = operands[2];
6257 operands[5] = operands[3];
6258 }
6259 else
6260 {
6261 operands[4] = operands[3];
6262 operands[5] = operands[2];
6263 }
6264 }"
6265)
25f7a26e 6266
c7597b5d 6267(define_expand "movhi_bigend"
6268 [(set (match_dup 2)
6269 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
6270 (const_int 16)))
6271 (set (match_dup 3)
6272 (ashiftrt:SI (match_dup 2) (const_int 16)))
6273 (set (match_operand:HI 0 "s_register_operand" "")
787f8210 6274 (match_dup 4))]
cffb2a26 6275 "TARGET_ARM"
c7597b5d 6276 "
6277 operands[2] = gen_reg_rtx (SImode);
6278 operands[3] = gen_reg_rtx (SImode);
787f8210 6279 operands[4] = gen_lowpart (HImode, operands[3]);
215b30b3 6280 "
6281)
b11cae9e 6282
a2f10574 6283;; Pattern to recognize insn generated default case above
f7fbdd4a 6284(define_insn "*movhi_insn_arch4"
e4585731 6285 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r,m,r")
6286 (match_operand:HI 1 "general_operand" "rIk,K,n,r,mi"))]
cffb2a26 6287 "TARGET_ARM
6288 && arm_arch4
85e02ccb 6289 && (register_operand (operands[0], HImode)
6290 || register_operand (operands[1], HImode))"
f7fbdd4a 6291 "@
6292 mov%?\\t%0, %1\\t%@ movhi
6293 mvn%?\\t%0, #%B1\\t%@ movhi
b1c1a101 6294 movw%?\\t%0, %L1\\t%@ movhi
25f905c2 6295 str%(h%)\\t%1, %0\\t%@ movhi
6296 ldr%(h%)\\t%0, %1\\t%@ movhi"
65f68e55 6297 [(set_attr "predicable" "yes")
e4585731 6298 (set_attr "pool_range" "*,*,*,*,256")
6299 (set_attr "neg_pool_range" "*,*,*,*,244")
6300 (set_attr "arch" "*,*,v6t2,*,*")
65f68e55 6301 (set_attr_alternative "type"
6302 [(if_then_else (match_operand 1 "const_int_operand" "")
1aed5204 6303 (const_string "mov_imm" )
6304 (const_string "mov_reg"))
6305 (const_string "mvn_imm")
e4585731 6306 (const_string "mov_imm")
65f68e55 6307 (const_string "store1")
6308 (const_string "load1")])]
cffb2a26 6309)
f7fbdd4a 6310
f7fbdd4a 6311(define_insn "*movhi_bytes"
65f68e55 6312 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
5fd254ed 6313 (match_operand:HI 1 "arm_rhs_operand" "I,rk,K"))]
c1a66faf 6314 "TARGET_ARM"
25f7a26e 6315 "@
65f68e55 6316 mov%?\\t%0, %1\\t%@ movhi
25f7a26e 6317 mov%?\\t%0, %1\\t%@ movhi
0d66636f 6318 mvn%?\\t%0, #%B1\\t%@ movhi"
d2a518d1 6319 [(set_attr "predicable" "yes")
1aed5204 6320 (set_attr "type" "mov_imm,mov_reg,mvn_imm")]
0d66636f 6321)
cffb2a26 6322
bc5c7e08 6323;; We use a DImode scratch because we may occasionally need an additional
6324;; temporary if the address isn't offsettable -- push_reload doesn't seem
6325;; to take any notice of the "o" constraints on reload_memory_operand operand.
d3373b54 6326(define_expand "reload_outhi"
cffb2a26 6327 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
215b30b3 6328 (match_operand:HI 1 "s_register_operand" "r")
6329 (match_operand:DI 2 "s_register_operand" "=&l")])]
cffb2a26 6330 "TARGET_EITHER"
6331 "if (TARGET_ARM)
6332 arm_reload_out_hi (operands);
6333 else
6334 thumb_reload_out_hi (operands);
d3373b54 6335 DONE;
cffb2a26 6336 "
6337)
d3373b54 6338
25f7a26e 6339(define_expand "reload_inhi"
6340 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
cffb2a26 6341 (match_operand:HI 1 "arm_reload_memory_operand" "o")
bc5c7e08 6342 (match_operand:DI 2 "s_register_operand" "=&r")])]
c1a66faf 6343 "TARGET_EITHER"
25f7a26e 6344 "
cffb2a26 6345 if (TARGET_ARM)
6346 arm_reload_in_hi (operands);
6347 else
6348 thumb_reload_out_hi (operands);
25f7a26e 6349 DONE;
6350")
6351
9c08d1fa 6352(define_expand "movqi"
6353 [(set (match_operand:QI 0 "general_operand" "")
6354 (match_operand:QI 1 "general_operand" ""))]
cffb2a26 6355 "TARGET_EITHER"
9c08d1fa 6356 "
6cffc037 6357 /* Everything except mem = const or mem = mem can be done easily */
0045890a 6358
e1ba4a27 6359 if (can_create_pseudo_p ())
cffb2a26 6360 {
0438d37f 6361 if (CONST_INT_P (operands[1]))
6cffc037 6362 {
6363 rtx reg = gen_reg_rtx (SImode);
6364
03770691 6365 /* For thumb we want an unsigned immediate, then we are more likely
6366 to be able to use a movs insn. */
6367 if (TARGET_THUMB)
6368 operands[1] = GEN_INT (INTVAL (operands[1]) & 255);
6369
6cffc037 6370 emit_insn (gen_movsi (reg, operands[1]));
6371 operands[1] = gen_lowpart (QImode, reg);
6372 }
cffb2a26 6373
6cffc037 6374 if (TARGET_THUMB)
6375 {
cffb2a26 6376 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 6377 happen if we are passed a SP (never OK for HImode/QImode) or
bc409cb4 6378 virtual register (also rejected as illegitimate for HImode/QImode)
6379 relative address. */
cffb2a26 6380 /* ??? This should perhaps be fixed elsewhere, for instance, in
6381 fixup_stack_1, by checking for other kinds of invalid addresses,
6382 e.g. a bare reference to a virtual register. This may confuse the
6383 alpha though, which must handle this case differently. */
0438d37f 6384 if (MEM_P (operands[0])
215b30b3 6385 && !memory_address_p (GET_MODE (operands[0]),
cffb2a26 6386 XEXP (operands[0], 0)))
537ffcfc 6387 operands[0]
6388 = replace_equiv_address (operands[0],
6389 copy_to_reg (XEXP (operands[0], 0)));
0438d37f 6390 if (MEM_P (operands[1])
215b30b3 6391 && !memory_address_p (GET_MODE (operands[1]),
cffb2a26 6392 XEXP (operands[1], 0)))
537ffcfc 6393 operands[1]
6394 = replace_equiv_address (operands[1],
6395 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 6396 }
6397
0438d37f 6398 if (MEM_P (operands[1]) && optimize > 0)
6cffc037 6399 {
6400 rtx reg = gen_reg_rtx (SImode);
6401
6402 emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
6403 operands[1] = gen_lowpart (QImode, reg);
6404 }
6405
0438d37f 6406 if (MEM_P (operands[0]))
6cffc037 6407 operands[1] = force_reg (QImode, operands[1]);
6408 }
6409 else if (TARGET_THUMB
0438d37f 6410 && CONST_INT_P (operands[1])
234f6557 6411 && !satisfies_constraint_I (operands[1]))
6cffc037 6412 {
674a8f0b 6413 /* Handle loading a large integer during reload. */
cffb2a26 6414
6cffc037 6415 /* Writing a constant to memory needs a scratch, which should
6416 be handled with SECONDARY_RELOADs. */
0438d37f 6417 gcc_assert (REG_P (operands[0]));
6cffc037 6418
6419 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
6420 emit_insn (gen_movsi (operands[0], operands[1]));
6421 DONE;
cffb2a26 6422 }
6423 "
6424)
b11cae9e 6425
cffb2a26 6426(define_insn "*arm_movqi_insn"
fd711051 6427 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,l,r,l,Uu,r,m")
490f62ca 6428 (match_operand:QI 1 "general_operand" "rk,rk,I,Py,K,Uu,l,Uh,r"))]
25f905c2 6429 "TARGET_32BIT
cffb2a26 6430 && ( register_operand (operands[0], QImode)
6431 || register_operand (operands[1], QImode))"
5565501b 6432 "@
fd711051 6433 mov%?\\t%0, %1
6434 mov%?\\t%0, %1
65f68e55 6435 mov%?\\t%0, %1
5565501b 6436 mov%?\\t%0, %1
6437 mvn%?\\t%0, #%B1
25f905c2 6438 ldr%(b%)\\t%0, %1
a54e3e7b 6439 str%(b%)\\t%1, %0
6440 ldr%(b%)\\t%0, %1
25f905c2 6441 str%(b%)\\t%1, %0"
1aed5204 6442 [(set_attr "type" "mov_reg,mov_reg,mov_imm,mov_imm,mvn_imm,load1,store1,load1,store1")
a54e3e7b 6443 (set_attr "predicable" "yes")
fd711051 6444 (set_attr "predicable_short_it" "yes,yes,yes,no,no,no,no,no,no")
6445 (set_attr "arch" "t2,any,any,t2,any,t2,t2,any,any")
6446 (set_attr "length" "2,4,4,2,4,2,2,4,4")]
cffb2a26 6447)
6448
9b8516be 6449;; HFmode moves
6450(define_expand "movhf"
6451 [(set (match_operand:HF 0 "general_operand" "")
6452 (match_operand:HF 1 "general_operand" ""))]
6453 "TARGET_EITHER"
6454 "
6455 if (TARGET_32BIT)
6456 {
0438d37f 6457 if (MEM_P (operands[0]))
9b8516be 6458 operands[1] = force_reg (HFmode, operands[1]);
6459 }
6460 else /* TARGET_THUMB1 */
6461 {
6462 if (can_create_pseudo_p ())
6463 {
0438d37f 6464 if (!REG_P (operands[0]))
9b8516be 6465 operands[1] = force_reg (HFmode, operands[1]);
6466 }
6467 }
6468 "
6469)
6470
6471(define_insn "*arm32_movhf"
6472 [(set (match_operand:HF 0 "nonimmediate_operand" "=r,m,r,r")
6473 (match_operand:HF 1 "general_operand" " m,r,r,F"))]
7c36fe71 6474 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_FP16) && !arm_restrict_it
9b8516be 6475 && ( s_register_operand (operands[0], HFmode)
6476 || s_register_operand (operands[1], HFmode))"
6477 "*
6478 switch (which_alternative)
6479 {
6480 case 0: /* ARM register from memory */
6481 return \"ldr%(h%)\\t%0, %1\\t%@ __fp16\";
6482 case 1: /* memory from ARM register */
6483 return \"str%(h%)\\t%1, %0\\t%@ __fp16\";
6484 case 2: /* ARM register from ARM register */
6485 return \"mov%?\\t%0, %1\\t%@ __fp16\";
6486 case 3: /* ARM register from constant */
6487 {
6488 REAL_VALUE_TYPE r;
6489 long bits;
6490 rtx ops[4];
6491
6492 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
6493 bits = real_to_target (NULL, &r, HFmode);
6494 ops[0] = operands[0];
6495 ops[1] = GEN_INT (bits);
6496 ops[2] = GEN_INT (bits & 0xff00);
6497 ops[3] = GEN_INT (bits & 0x00ff);
6498
6499 if (arm_arch_thumb2)
6500 output_asm_insn (\"movw%?\\t%0, %1\", ops);
6501 else
6502 output_asm_insn (\"mov%?\\t%0, %2\;orr%?\\t%0, %0, %3\", ops);
6503 return \"\";
6504 }
6505 default:
6506 gcc_unreachable ();
6507 }
6508 "
6509 [(set_attr "conds" "unconditional")
ad4fc3c0 6510 (set_attr "type" "load1,store1,mov_reg,multiple")
9b8516be 6511 (set_attr "length" "4,4,4,8")
d2a518d1 6512 (set_attr "predicable" "yes")]
9b8516be 6513)
6514
87b22bf7 6515(define_expand "movsf"
6516 [(set (match_operand:SF 0 "general_operand" "")
6517 (match_operand:SF 1 "general_operand" ""))]
cffb2a26 6518 "TARGET_EITHER"
87b22bf7 6519 "
25f905c2 6520 if (TARGET_32BIT)
cffb2a26 6521 {
0438d37f 6522 if (MEM_P (operands[0]))
cffb2a26 6523 operands[1] = force_reg (SFmode, operands[1]);
6524 }
25f905c2 6525 else /* TARGET_THUMB1 */
cffb2a26 6526 {
e1ba4a27 6527 if (can_create_pseudo_p ())
cffb2a26 6528 {
0438d37f 6529 if (!REG_P (operands[0]))
cffb2a26 6530 operands[1] = force_reg (SFmode, operands[1]);
6531 }
6532 }
6533 "
6534)
6535
03d440a6 6536;; Transform a floating-point move of a constant into a core register into
6537;; an SImode operation.
cffb2a26 6538(define_split
03d440a6 6539 [(set (match_operand:SF 0 "arm_general_register_operand" "")
cffb2a26 6540 (match_operand:SF 1 "immediate_operand" ""))]
339034d0 6541 "TARGET_EITHER
cffb2a26 6542 && reload_completed
0438d37f 6543 && CONST_DOUBLE_P (operands[1])"
cffb2a26 6544 [(set (match_dup 2) (match_dup 3))]
6545 "
6546 operands[2] = gen_lowpart (SImode, operands[0]);
6547 operands[3] = gen_lowpart (SImode, operands[1]);
6548 if (operands[2] == 0 || operands[3] == 0)
6549 FAIL;
215b30b3 6550 "
6551)
87b22bf7 6552
cffb2a26 6553(define_insn "*arm_movsf_soft_insn"
6554 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
6555 (match_operand:SF 1 "general_operand" "r,mE,r"))]
cde1623a 6556 "TARGET_32BIT
cffb2a26 6557 && TARGET_SOFT_FLOAT
0438d37f 6558 && (!MEM_P (operands[0])
215b30b3 6559 || register_operand (operands[1], SFmode))"
9a1112d7 6560 "@
6561 mov%?\\t%0, %1
6562 ldr%?\\t%0, %1\\t%@ float
6563 str%?\\t%1, %0\\t%@ float"
cde1623a 6564 [(set_attr "predicable" "yes")
7c36fe71 6565 (set_attr "predicable_short_it" "no")
1aed5204 6566 (set_attr "type" "mov_reg,load1,store1")
42e1de19 6567 (set_attr "arm_pool_range" "*,4096,*")
6568 (set_attr "thumb2_pool_range" "*,4094,*")
cde1623a 6569 (set_attr "arm_neg_pool_range" "*,4084,*")
6570 (set_attr "thumb2_neg_pool_range" "*,0,*")]
cffb2a26 6571)
6572
9c08d1fa 6573(define_expand "movdf"
87b22bf7 6574 [(set (match_operand:DF 0 "general_operand" "")
6575 (match_operand:DF 1 "general_operand" ""))]
cffb2a26 6576 "TARGET_EITHER"
9c08d1fa 6577 "
25f905c2 6578 if (TARGET_32BIT)
cffb2a26 6579 {
0438d37f 6580 if (MEM_P (operands[0]))
cffb2a26 6581 operands[1] = force_reg (DFmode, operands[1]);
6582 }
6583 else /* TARGET_THUMB */
6584 {
e1ba4a27 6585 if (can_create_pseudo_p ())
cffb2a26 6586 {
0438d37f 6587 if (!REG_P (operands[0]))
cffb2a26 6588 operands[1] = force_reg (DFmode, operands[1]);
6589 }
6590 }
6591 "
6592)
b11cae9e 6593
9c08d1fa 6594;; Reloading a df mode value stored in integer regs to memory can require a
6595;; scratch reg.
6596(define_expand "reload_outdf"
cffb2a26 6597 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
87b22bf7 6598 (match_operand:DF 1 "s_register_operand" "r")
6599 (match_operand:SI 2 "s_register_operand" "=&r")]
06adefdc 6600 "TARGET_THUMB2"
87b22bf7 6601 "
215b30b3 6602 {
6603 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
f7fbdd4a 6604
215b30b3 6605 if (code == REG)
6606 operands[2] = XEXP (operands[0], 0);
6607 else if (code == POST_INC || code == PRE_DEC)
6608 {
6609 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
6610 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
6611 emit_insn (gen_movdi (operands[0], operands[1]));
6612 DONE;
6613 }
6614 else if (code == PRE_INC)
6615 {
6616 rtx reg = XEXP (XEXP (operands[0], 0), 0);
f7fbdd4a 6617
215b30b3 6618 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
6619 operands[2] = reg;
6620 }
6621 else if (code == POST_DEC)
6622 operands[2] = XEXP (XEXP (operands[0], 0), 0);
6623 else
6624 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
6625 XEXP (XEXP (operands[0], 0), 1)));
f7fbdd4a 6626
788fcce0 6627 emit_insn (gen_rtx_SET (VOIDmode,
6628 replace_equiv_address (operands[0], operands[2]),
215b30b3 6629 operands[1]));
f7fbdd4a 6630
215b30b3 6631 if (code == POST_DEC)
6632 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
6633
6634 DONE;
6635 }"
6636)
9c08d1fa 6637
9a1112d7 6638(define_insn "*movdf_soft_insn"
353cf59a 6639 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,q,m")
6640 (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,q"))]
cde1623a 6641 "TARGET_32BIT && TARGET_SOFT_FLOAT
b2778788 6642 && ( register_operand (operands[0], DFmode)
6643 || register_operand (operands[1], DFmode))"
d51f92df 6644 "*
6645 switch (which_alternative)
6646 {
6647 case 0:
6648 case 1:
6649 case 2:
6650 return \"#\";
6651 default:
26ff80c0 6652 return output_move_double (operands, true, NULL);
d51f92df 6653 }
6654 "
359a6e9f 6655 [(set_attr "length" "8,12,16,8,8")
1b7da4ac 6656 (set_attr "type" "multiple,multiple,multiple,load2,store2")
42e1de19 6657 (set_attr "arm_pool_range" "*,*,*,1020,*")
6658 (set_attr "thumb2_pool_range" "*,*,*,1018,*")
8848d797 6659 (set_attr "arm_neg_pool_range" "*,*,*,1004,*")
cde1623a 6660 (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
cffb2a26 6661)
b11cae9e 6662\f
b11cae9e 6663
9c08d1fa 6664;; load- and store-multiple insns
6665;; The arm can load/store any set of registers, provided that they are in
320ea44d 6666;; ascending order, but these expanders assume a contiguous set.
b11cae9e 6667
9c08d1fa 6668(define_expand "load_multiple"
6669 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6670 (match_operand:SI 1 "" ""))
6671 (use (match_operand:SI 2 "" ""))])]
25f905c2 6672 "TARGET_32BIT"
9580c25f 6673{
6674 HOST_WIDE_INT offset = 0;
6675
bd5b4116 6676 /* Support only fixed point registers. */
0438d37f 6677 if (!CONST_INT_P (operands[2])
9c08d1fa 6678 || INTVAL (operands[2]) > 14
6679 || INTVAL (operands[2]) < 2
0438d37f 6680 || !MEM_P (operands[1])
6681 || !REG_P (operands[0])
bd5b4116 6682 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
6683 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 6684 FAIL;
6685
6686 operands[3]
320ea44d 6687 = arm_gen_load_multiple (arm_regs_in_sequence + REGNO (operands[0]),
6688 INTVAL (operands[2]),
f082f1c4 6689 force_reg (SImode, XEXP (operands[1], 0)),
320ea44d 6690 FALSE, operands[1], &offset);
9580c25f 6691})
b11cae9e 6692
9c08d1fa 6693(define_expand "store_multiple"
6694 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6695 (match_operand:SI 1 "" ""))
6696 (use (match_operand:SI 2 "" ""))])]
25f905c2 6697 "TARGET_32BIT"
9580c25f 6698{
6699 HOST_WIDE_INT offset = 0;
6700
674a8f0b 6701 /* Support only fixed point registers. */
0438d37f 6702 if (!CONST_INT_P (operands[2])
9c08d1fa 6703 || INTVAL (operands[2]) > 14
6704 || INTVAL (operands[2]) < 2
0438d37f 6705 || !REG_P (operands[1])
6706 || !MEM_P (operands[0])
bd5b4116 6707 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
6708 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 6709 FAIL;
6710
6711 operands[3]
320ea44d 6712 = arm_gen_store_multiple (arm_regs_in_sequence + REGNO (operands[1]),
6713 INTVAL (operands[2]),
f082f1c4 6714 force_reg (SImode, XEXP (operands[0], 0)),
320ea44d 6715 FALSE, operands[0], &offset);
9580c25f 6716})
b11cae9e 6717
9c08d1fa 6718
e34ebfca 6719(define_expand "setmemsi"
6720 [(match_operand:BLK 0 "general_operand" "")
6721 (match_operand:SI 1 "const_int_operand" "")
6722 (match_operand:SI 2 "const_int_operand" "")
6723 (match_operand:SI 3 "const_int_operand" "")]
6724 "TARGET_32BIT"
6725{
6726 if (arm_gen_setmem (operands))
6727 DONE;
6728
6729 FAIL;
6730})
6731
6732
9c08d1fa 6733;; Move a block of memory if it is word aligned and MORE than 2 words long.
6734;; We could let this apply for blocks of less than this, but it clobbers so
6735;; many registers that there is then probably a better way.
6736
008c057d 6737(define_expand "movmemqi"
34191dd1 6738 [(match_operand:BLK 0 "general_operand" "")
6739 (match_operand:BLK 1 "general_operand" "")
6740 (match_operand:SI 2 "const_int_operand" "")
6741 (match_operand:SI 3 "const_int_operand" "")]
ae51a965 6742 ""
9c08d1fa 6743 "
25f905c2 6744 if (TARGET_32BIT)
cffb2a26 6745 {
ae51a965 6746 if (TARGET_LDRD && current_tune->prefer_ldrd_strd
6747 && !optimize_function_for_size_p (cfun))
6748 {
6749 if (gen_movmem_ldrd_strd (operands))
6750 DONE;
6751 FAIL;
6752 }
6753
008c057d 6754 if (arm_gen_movmemqi (operands))
cffb2a26 6755 DONE;
6756 FAIL;
6757 }
25f905c2 6758 else /* TARGET_THUMB1 */
cffb2a26 6759 {
6760 if ( INTVAL (operands[3]) != 4
6761 || INTVAL (operands[2]) > 48)
6762 FAIL;
6763
008c057d 6764 thumb_expand_movmemqi (operands);
cffb2a26 6765 DONE;
6766 }
6767 "
6768)
9c08d1fa 6769\f
b11cae9e 6770
341940e8 6771;; Compare & branch insns
8d232dc7 6772;; The range calculations are based as follows:
341940e8 6773;; For forward branches, the address calculation returns the address of
6774;; the next instruction. This is 2 beyond the branch instruction.
6775;; For backward branches, the address calculation returns the address of
6776;; the first instruction in this pattern (cmp). This is 2 before the branch
6777;; instruction for the shortest sequence, and 4 before the branch instruction
6778;; if we have to jump around an unconditional branch.
6779;; To the basic branch range the PC offset must be added (this is +4).
6780;; So for forward branches we have
6781;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
6782;; And for backward branches we have
6783;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
6784;;
6785;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
6786;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
cffb2a26 6787
aeac46d4 6788(define_expand "cbranchsi4"
6789 [(set (pc) (if_then_else
aa06947a 6790 (match_operator 0 "expandable_comparison_operator"
aeac46d4 6791 [(match_operand:SI 1 "s_register_operand" "")
6792 (match_operand:SI 2 "nonmemory_operand" "")])
6793 (label_ref (match_operand 3 "" ""))
6794 (pc)))]
f9aa4160 6795 "TARGET_EITHER"
aeac46d4 6796 "
74f4459c 6797 if (!TARGET_THUMB1)
6798 {
f9aa4160 6799 if (!arm_validize_comparison (&operands[0], &operands[1], &operands[2]))
6800 FAIL;
74f4459c 6801 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6802 operands[3]));
6803 DONE;
6804 }
25f905c2 6805 if (thumb1_cmpneg_operand (operands[2], SImode))
aeac46d4 6806 {
6807 emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
6808 operands[3], operands[0]));
6809 DONE;
6810 }
25f905c2 6811 if (!thumb1_cmp_operand (operands[2], SImode))
aeac46d4 6812 operands[2] = force_reg (SImode, operands[2]);
6813 ")
6814
74f4459c 6815(define_expand "cbranchsf4"
6816 [(set (pc) (if_then_else
aa06947a 6817 (match_operator 0 "expandable_comparison_operator"
74f4459c 6818 [(match_operand:SF 1 "s_register_operand" "")
6819 (match_operand:SF 2 "arm_float_compare_operand" "")])
6820 (label_ref (match_operand 3 "" ""))
6821 (pc)))]
6822 "TARGET_32BIT && TARGET_HARD_FLOAT"
6823 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6824 operands[3])); DONE;"
6825)
6826
6827(define_expand "cbranchdf4"
6828 [(set (pc) (if_then_else
aa06947a 6829 (match_operator 0 "expandable_comparison_operator"
74f4459c 6830 [(match_operand:DF 1 "s_register_operand" "")
6831 (match_operand:DF 2 "arm_float_compare_operand" "")])
6832 (label_ref (match_operand 3 "" ""))
6833 (pc)))]
a50d7267 6834 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
74f4459c 6835 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6836 operands[3])); DONE;"
6837)
6838
74f4459c 6839(define_expand "cbranchdi4"
6840 [(set (pc) (if_then_else
aa06947a 6841 (match_operator 0 "expandable_comparison_operator"
b8eae306 6842 [(match_operand:DI 1 "s_register_operand" "")
a8045a4f 6843 (match_operand:DI 2 "cmpdi_operand" "")])
74f4459c 6844 (label_ref (match_operand 3 "" ""))
6845 (pc)))]
a8045a4f 6846 "TARGET_32BIT"
6847 "{
0438d37f 6848 if (!arm_validize_comparison (&operands[0], &operands[1], &operands[2]))
f9aa4160 6849 FAIL;
6850 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
a8045a4f 6851 operands[3]));
6852 DONE;
6853 }"
74f4459c 6854)
6855
9c08d1fa 6856;; Comparison and test insns
6857
cffb2a26 6858(define_insn "*arm_cmpsi_insn"
bd5b4116 6859 [(set (reg:CC CC_REGNUM)
f9f234ec 6860 (compare:CC (match_operand:SI 0 "s_register_operand" "l,r,r,r,r")
6861 (match_operand:SI 1 "arm_add_operand" "Py,r,r,I,L")))]
25f905c2 6862 "TARGET_32BIT"
5565501b 6863 "@
a6864a24 6864 cmp%?\\t%0, %1
6865 cmp%?\\t%0, %1
aea4c774 6866 cmp%?\\t%0, %1
f9f234ec 6867 cmp%?\\t%0, %1
aea4c774 6868 cmn%?\\t%0, #%n1"
a6864a24 6869 [(set_attr "conds" "set")
f9f234ec 6870 (set_attr "arch" "t2,t2,any,any,any")
6871 (set_attr "length" "2,2,4,4,4")
65f68e55 6872 (set_attr "predicable" "yes")
f9f234ec 6873 (set_attr "predicable_short_it" "yes,yes,yes,no,no")
112eda6f 6874 (set_attr "type" "alus_imm,alus_sreg,alus_sreg,alus_imm,alus_imm")]
cffb2a26 6875)
b11cae9e 6876
d5d4dc8d 6877(define_insn "*cmpsi_shiftsi"
bd5b4116 6878 [(set (reg:CC CC_REGNUM)
d82e788e 6879 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r,r")
cffb2a26 6880 (match_operator:SI 3 "shift_operator"
d82e788e 6881 [(match_operand:SI 1 "s_register_operand" "r,r,r")
6882 (match_operand:SI 2 "shift_amount_operand" "M,r,M")])))]
d5d4dc8d 6883 "TARGET_32BIT"
f9f234ec 6884 "cmp\\t%0, %1%S3"
344495ea 6885 [(set_attr "conds" "set")
331beb1a 6886 (set_attr "shift" "1")
d82e788e 6887 (set_attr "arch" "32,a,a")
6888 (set_attr "type" "alus_shift_imm,alu_shift_reg,alus_shift_imm")])
b11cae9e 6889
d5d4dc8d 6890(define_insn "*cmpsi_shiftsi_swp"
bd5b4116 6891 [(set (reg:CC_SWP CC_REGNUM)
aea4c774 6892 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
d82e788e 6893 [(match_operand:SI 1 "s_register_operand" "r,r,r")
6894 (match_operand:SI 2 "shift_amount_operand" "M,r,M")])
6895 (match_operand:SI 0 "s_register_operand" "r,r,r")))]
d5d4dc8d 6896 "TARGET_32BIT"
aea4c774 6897 "cmp%?\\t%0, %1%S3"
344495ea 6898 [(set_attr "conds" "set")
331beb1a 6899 (set_attr "shift" "1")
d82e788e 6900 (set_attr "arch" "32,a,a")
6901 (set_attr "type" "alus_shift_imm,alu_shift_reg,alus_shift_imm")])
b11cae9e 6902
25f905c2 6903(define_insn "*arm_cmpsi_negshiftsi_si"
aed179ae 6904 [(set (reg:CC_Z CC_REGNUM)
6905 (compare:CC_Z
6906 (neg:SI (match_operator:SI 1 "shift_operator"
6907 [(match_operand:SI 2 "s_register_operand" "r")
6908 (match_operand:SI 3 "reg_or_int_operand" "rM")]))
6909 (match_operand:SI 0 "s_register_operand" "r")))]
cffb2a26 6910 "TARGET_ARM"
aed179ae 6911 "cmn%?\\t%0, %2%S1"
344495ea 6912 [(set_attr "conds" "set")
aed179ae 6913 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
d82e788e 6914 (const_string "alus_shift_imm")
6915 (const_string "alus_shift_reg")))
596e5e8f 6916 (set_attr "predicable" "yes")]
0d66636f 6917)
b11cae9e 6918
a8045a4f 6919;; DImode comparisons. The generic code generates branches that
6920;; if-conversion can not reduce to a conditional compare, so we do
6921;; that directly.
6922
ba6a3b2f 6923(define_insn_and_split "*arm_cmpdi_insn"
a8045a4f 6924 [(set (reg:CC_NCV CC_REGNUM)
6925 (compare:CC_NCV (match_operand:DI 0 "s_register_operand" "r")
6926 (match_operand:DI 1 "arm_di_operand" "rDi")))
6927 (clobber (match_scratch:SI 2 "=r"))]
b805622c 6928 "TARGET_32BIT"
ba6a3b2f 6929 "#" ; "cmp\\t%Q0, %Q1\;sbcs\\t%2, %R0, %R1"
6930 "&& reload_completed"
6931 [(set (reg:CC CC_REGNUM)
6932 (compare:CC (match_dup 0) (match_dup 1)))
6933 (parallel [(set (reg:CC CC_REGNUM)
6934 (compare:CC (match_dup 3) (match_dup 4)))
6935 (set (match_dup 2)
6936 (minus:SI (match_dup 5)
6937 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))])]
6938 {
6939 operands[3] = gen_highpart (SImode, operands[0]);
6940 operands[0] = gen_lowpart (SImode, operands[0]);
6941 if (CONST_INT_P (operands[1]))
6942 {
6943 operands[4] = GEN_INT (~INTVAL (gen_highpart_mode (SImode,
6944 DImode,
6945 operands[1])));
6946 operands[5] = gen_rtx_PLUS (SImode, operands[3], operands[4]);
6947 }
6948 else
6949 {
6950 operands[4] = gen_highpart (SImode, operands[1]);
6951 operands[5] = gen_rtx_MINUS (SImode, operands[3], operands[4]);
6952 }
6953 operands[1] = gen_lowpart (SImode, operands[1]);
6954 operands[2] = gen_lowpart (SImode, operands[2]);
6955 }
a8045a4f 6956 [(set_attr "conds" "set")
1b7da4ac 6957 (set_attr "length" "8")
6958 (set_attr "type" "multiple")]
a8045a4f 6959)
6960
ba6a3b2f 6961(define_insn_and_split "*arm_cmpdi_unsigned"
a8045a4f 6962 [(set (reg:CC_CZ CC_REGNUM)
1a86364b 6963 (compare:CC_CZ (match_operand:DI 0 "s_register_operand" "l,r,r,r")
6964 (match_operand:DI 1 "arm_di_operand" "Py,r,Di,rDi")))]
7c36fe71 6965
48a98053 6966 "TARGET_32BIT"
ba6a3b2f 6967 "#" ; "cmp\\t%R0, %R1\;it eq\;cmpeq\\t%Q0, %Q1"
6968 "&& reload_completed"
6969 [(set (reg:CC CC_REGNUM)
6970 (compare:CC (match_dup 2) (match_dup 3)))
6971 (cond_exec (eq:SI (reg:CC CC_REGNUM) (const_int 0))
6972 (set (reg:CC CC_REGNUM)
6973 (compare:CC (match_dup 0) (match_dup 1))))]
6974 {
6975 operands[2] = gen_highpart (SImode, operands[0]);
6976 operands[0] = gen_lowpart (SImode, operands[0]);
6977 if (CONST_INT_P (operands[1]))
6978 operands[3] = gen_highpart_mode (SImode, DImode, operands[1]);
6979 else
6980 operands[3] = gen_highpart (SImode, operands[1]);
6981 operands[1] = gen_lowpart (SImode, operands[1]);
6982 }
a8045a4f 6983 [(set_attr "conds" "set")
1a86364b 6984 (set_attr "enabled_for_depr_it" "yes,yes,no,*")
6985 (set_attr "arch" "t2,t2,t2,a")
6986 (set_attr "length" "6,6,10,8")
1b7da4ac 6987 (set_attr "type" "multiple")]
a8045a4f 6988)
6989
6990(define_insn "*arm_cmpdi_zero"
6991 [(set (reg:CC_Z CC_REGNUM)
6992 (compare:CC_Z (match_operand:DI 0 "s_register_operand" "r")
6993 (const_int 0)))
6994 (clobber (match_scratch:SI 1 "=r"))]
6995 "TARGET_32BIT"
6996 "orr%.\\t%1, %Q0, %R0"
1b7da4ac 6997 [(set_attr "conds" "set")
6998 (set_attr "type" "logics_reg")]
a8045a4f 6999)
7000
9c08d1fa 7001; This insn allows redundant compares to be removed by cse, nothing should
7002; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
7003; is deleted later on. The match_dup will match the mode here, so that
7004; mode changes of the condition codes aren't lost by this even though we don't
7005; specify what they are.
7006
8a18b90c 7007(define_insn "*deleted_compare"
9c08d1fa 7008 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
25f905c2 7009 "TARGET_32BIT"
40dbec34 7010 "\\t%@ deleted compare"
cffb2a26 7011 [(set_attr "conds" "set")
1b7da4ac 7012 (set_attr "length" "0")
7013 (set_attr "type" "no_insn")]
cffb2a26 7014)
9c08d1fa 7015
7016\f
7017;; Conditional branch insns
7018
74f4459c 7019(define_expand "cbranch_cc"
9c08d1fa 7020 [(set (pc)
74f4459c 7021 (if_then_else (match_operator 0 "" [(match_operand 1 "" "")
7022 (match_operand 2 "" "")])
7023 (label_ref (match_operand 3 "" ""))
9c08d1fa 7024 (pc)))]
25f905c2 7025 "TARGET_32BIT"
74f4459c 7026 "operands[1] = arm_gen_compare_reg (GET_CODE (operands[0]),
e1b93706 7027 operands[1], operands[2], NULL_RTX);
74f4459c 7028 operands[2] = const0_rtx;"
8fa3ba89 7029)
7030
7031;;
7032;; Patterns to match conditional branch insns.
7033;;
7034
ffcc986d 7035(define_insn "arm_cond_branch"
9c08d1fa 7036 [(set (pc)
8fa3ba89 7037 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 7038 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 7039 (label_ref (match_operand 0 "" ""))
7040 (pc)))]
25f905c2 7041 "TARGET_32BIT"
d75350ce 7042 "*
9c08d1fa 7043 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 7044 {
7045 arm_ccfsm_state += 2;
7046 return \"\";
7047 }
e2348bcb 7048 return \"b%d1\\t%l0\";
cffb2a26 7049 "
a2cd141b 7050 [(set_attr "conds" "use")
a6864a24 7051 (set_attr "type" "branch")
7052 (set (attr "length")
7053 (if_then_else
0bf497f5 7054 (and (match_test "TARGET_THUMB2")
a6864a24 7055 (and (ge (minus (match_dup 0) (pc)) (const_int -250))
7056 (le (minus (match_dup 0) (pc)) (const_int 256))))
7057 (const_int 2)
7058 (const_int 4)))]
cffb2a26 7059)
d75350ce 7060
cffb2a26 7061(define_insn "*arm_cond_branch_reversed"
9c08d1fa 7062 [(set (pc)
8fa3ba89 7063 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 7064 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 7065 (pc)
7066 (label_ref (match_operand 0 "" ""))))]
25f905c2 7067 "TARGET_32BIT"
d75350ce 7068 "*
9c08d1fa 7069 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 7070 {
7071 arm_ccfsm_state += 2;
7072 return \"\";
7073 }
e2348bcb 7074 return \"b%D1\\t%l0\";
cffb2a26 7075 "
a2cd141b 7076 [(set_attr "conds" "use")
a6864a24 7077 (set_attr "type" "branch")
7078 (set (attr "length")
7079 (if_then_else
0bf497f5 7080 (and (match_test "TARGET_THUMB2")
a6864a24 7081 (and (ge (minus (match_dup 0) (pc)) (const_int -250))
7082 (le (minus (match_dup 0) (pc)) (const_int 256))))
7083 (const_int 2)
7084 (const_int 4)))]
cffb2a26 7085)
7086
b11cae9e 7087\f
9c08d1fa 7088
7089; scc insns
7090
74f4459c 7091(define_expand "cstore_cc"
7db9af5d 7092 [(set (match_operand:SI 0 "s_register_operand" "")
74f4459c 7093 (match_operator:SI 1 "" [(match_operand 2 "" "")
7094 (match_operand 3 "" "")]))]
25f905c2 7095 "TARGET_32BIT"
74f4459c 7096 "operands[2] = arm_gen_compare_reg (GET_CODE (operands[1]),
e1b93706 7097 operands[2], operands[3], NULL_RTX);
74f4459c 7098 operands[3] = const0_rtx;"
8fa3ba89 7099)
7100
a3b84066 7101(define_insn_and_split "*mov_scc"
9c08d1fa 7102 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7103 (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7104 [(match_operand 2 "cc_register" "") (const_int 0)]))]
cffb2a26 7105 "TARGET_ARM"
a3b84066 7106 "#" ; "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
7107 "TARGET_ARM"
7108 [(set (match_dup 0)
7109 (if_then_else:SI (match_dup 1)
7110 (const_int 1)
7111 (const_int 0)))]
7112 ""
cffb2a26 7113 [(set_attr "conds" "use")
1b7da4ac 7114 (set_attr "length" "8")
7115 (set_attr "type" "multiple")]
cffb2a26 7116)
9c08d1fa 7117
a3b84066 7118(define_insn_and_split "*mov_negscc"
9c08d1fa 7119 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7120 (neg:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7121 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 7122 "TARGET_ARM"
a3b84066 7123 "#" ; "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
7124 "TARGET_ARM"
7125 [(set (match_dup 0)
7126 (if_then_else:SI (match_dup 1)
7127 (match_dup 3)
7128 (const_int 0)))]
7129 {
7130 operands[3] = GEN_INT (~0);
7131 }
cffb2a26 7132 [(set_attr "conds" "use")
1b7da4ac 7133 (set_attr "length" "8")
7134 (set_attr "type" "multiple")]
cffb2a26 7135)
9c08d1fa 7136
a3b84066 7137(define_insn_and_split "*mov_notscc"
9c08d1fa 7138 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7139 (not:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7140 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 7141 "TARGET_ARM"
a3b84066 7142 "#" ; "mvn%D1\\t%0, #0\;mvn%d1\\t%0, #1"
7143 "TARGET_ARM"
7144 [(set (match_dup 0)
7145 (if_then_else:SI (match_dup 1)
7146 (match_dup 3)
7147 (match_dup 4)))]
7148 {
7149 operands[3] = GEN_INT (~1);
7150 operands[4] = GEN_INT (~0);
7151 }
cffb2a26 7152 [(set_attr "conds" "use")
1b7da4ac 7153 (set_attr "length" "8")
7154 (set_attr "type" "multiple")]
cffb2a26 7155)
9c08d1fa 7156
595d88b5 7157(define_expand "cstoresi4"
7158 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 7159 (match_operator:SI 1 "expandable_comparison_operator"
595d88b5 7160 [(match_operand:SI 2 "s_register_operand" "")
7161 (match_operand:SI 3 "reg_or_int_operand" "")]))]
74f4459c 7162 "TARGET_32BIT || TARGET_THUMB1"
595d88b5 7163 "{
7164 rtx op3, scratch, scratch2;
7165
74f4459c 7166 if (!TARGET_THUMB1)
7167 {
7168 if (!arm_add_operand (operands[3], SImode))
7169 operands[3] = force_reg (SImode, operands[3]);
7170 emit_insn (gen_cstore_cc (operands[0], operands[1],
7171 operands[2], operands[3]));
7172 DONE;
7173 }
7174
595d88b5 7175 if (operands[3] == const0_rtx)
7176 {
7177 switch (GET_CODE (operands[1]))
7178 {
7179 case EQ:
25f905c2 7180 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], operands[2]));
595d88b5 7181 break;
7182
7183 case NE:
25f905c2 7184 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], operands[2]));
595d88b5 7185 break;
7186
7187 case LE:
7188 scratch = expand_binop (SImode, add_optab, operands[2], constm1_rtx,
7189 NULL_RTX, 0, OPTAB_WIDEN);
7190 scratch = expand_binop (SImode, ior_optab, operands[2], scratch,
7191 NULL_RTX, 0, OPTAB_WIDEN);
7192 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7193 operands[0], 1, OPTAB_WIDEN);
7194 break;
7195
7196 case GE:
7197 scratch = expand_unop (SImode, one_cmpl_optab, operands[2],
7198 NULL_RTX, 1);
7199 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7200 NULL_RTX, 1, OPTAB_WIDEN);
7201 break;
7202
7203 case GT:
7204 scratch = expand_binop (SImode, ashr_optab, operands[2],
7205 GEN_INT (31), NULL_RTX, 0, OPTAB_WIDEN);
7206 scratch = expand_binop (SImode, sub_optab, scratch, operands[2],
7207 NULL_RTX, 0, OPTAB_WIDEN);
7208 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31), operands[0],
7209 0, OPTAB_WIDEN);
7210 break;
7211
7212 /* LT is handled by generic code. No need for unsigned with 0. */
7213 default:
7214 FAIL;
7215 }
7216 DONE;
7217 }
7218
7219 switch (GET_CODE (operands[1]))
7220 {
7221 case EQ:
7222 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7223 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7224 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], scratch));
595d88b5 7225 break;
7226
7227 case NE:
7228 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7229 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7230 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], scratch));
595d88b5 7231 break;
7232
7233 case LE:
7234 op3 = force_reg (SImode, operands[3]);
7235
7236 scratch = expand_binop (SImode, lshr_optab, operands[2], GEN_INT (31),
7237 NULL_RTX, 1, OPTAB_WIDEN);
7238 scratch2 = expand_binop (SImode, ashr_optab, op3, GEN_INT (31),
7239 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7240 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
595d88b5 7241 op3, operands[2]));
7242 break;
7243
7244 case GE:
7245 op3 = operands[3];
25f905c2 7246 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7247 op3 = force_reg (SImode, op3);
7248 scratch = expand_binop (SImode, ashr_optab, operands[2], GEN_INT (31),
7249 NULL_RTX, 0, OPTAB_WIDEN);
7250 scratch2 = expand_binop (SImode, lshr_optab, op3, GEN_INT (31),
7251 NULL_RTX, 1, OPTAB_WIDEN);
25f905c2 7252 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
595d88b5 7253 operands[2], op3));
7254 break;
7255
7256 case LEU:
7257 op3 = force_reg (SImode, operands[3]);
7258 scratch = force_reg (SImode, const0_rtx);
25f905c2 7259 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
595d88b5 7260 op3, operands[2]));
7261 break;
7262
7263 case GEU:
7264 op3 = operands[3];
25f905c2 7265 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7266 op3 = force_reg (SImode, op3);
7267 scratch = force_reg (SImode, const0_rtx);
25f905c2 7268 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
595d88b5 7269 operands[2], op3));
7270 break;
7271
7272 case LTU:
7273 op3 = operands[3];
25f905c2 7274 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7275 op3 = force_reg (SImode, op3);
7276 scratch = gen_reg_rtx (SImode);
408b7ae5 7277 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], operands[2], op3));
595d88b5 7278 break;
7279
7280 case GTU:
7281 op3 = force_reg (SImode, operands[3]);
7282 scratch = gen_reg_rtx (SImode);
408b7ae5 7283 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], op3, operands[2]));
595d88b5 7284 break;
7285
7286 /* No good sequences for GT, LT. */
7287 default:
7288 FAIL;
7289 }
7290 DONE;
7291}")
7292
74f4459c 7293(define_expand "cstoresf4"
7294 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 7295 (match_operator:SI 1 "expandable_comparison_operator"
74f4459c 7296 [(match_operand:SF 2 "s_register_operand" "")
7297 (match_operand:SF 3 "arm_float_compare_operand" "")]))]
7298 "TARGET_32BIT && TARGET_HARD_FLOAT"
7299 "emit_insn (gen_cstore_cc (operands[0], operands[1],
7300 operands[2], operands[3])); DONE;"
7301)
7302
7303(define_expand "cstoredf4"
7304 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 7305 (match_operator:SI 1 "expandable_comparison_operator"
74f4459c 7306 [(match_operand:DF 2 "s_register_operand" "")
7307 (match_operand:DF 3 "arm_float_compare_operand" "")]))]
d63ed457 7308 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
74f4459c 7309 "emit_insn (gen_cstore_cc (operands[0], operands[1],
7310 operands[2], operands[3])); DONE;"
7311)
7312
74f4459c 7313(define_expand "cstoredi4"
7314 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 7315 (match_operator:SI 1 "expandable_comparison_operator"
b8eae306 7316 [(match_operand:DI 2 "s_register_operand" "")
a8045a4f 7317 (match_operand:DI 3 "cmpdi_operand" "")]))]
7318 "TARGET_32BIT"
7319 "{
f9aa4160 7320 if (!arm_validize_comparison (&operands[1],
7321 &operands[2],
7322 &operands[3]))
7323 FAIL;
7324 emit_insn (gen_cstore_cc (operands[0], operands[1], operands[2],
a8045a4f 7325 operands[3]));
7326 DONE;
7327 }"
74f4459c 7328)
7329
9c08d1fa 7330\f
39b5e676 7331;; Conditional move insns
7332
7333(define_expand "movsicc"
8a18b90c 7334 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 7335 (if_then_else:SI (match_operand 1 "expandable_comparison_operator" "")
aea4c774 7336 (match_operand:SI 2 "arm_not_operand" "")
8a18b90c 7337 (match_operand:SI 3 "arm_not_operand" "")))]
25f905c2 7338 "TARGET_32BIT"
39b5e676 7339 "
215b30b3 7340 {
f9aa4160 7341 enum rtx_code code;
278b301d 7342 rtx ccreg;
7343
f9aa4160 7344 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
7345 &XEXP (operands[1], 1)))
278b301d 7346 FAIL;
f9aa4160 7347
7348 code = GET_CODE (operands[1]);
74f4459c 7349 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
e1b93706 7350 XEXP (operands[1], 1), NULL_RTX);
29bb088d 7351 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7352 }"
7353)
39b5e676 7354
7355(define_expand "movsfcc"
8a18b90c 7356 [(set (match_operand:SF 0 "s_register_operand" "")
4df97ffc 7357 (if_then_else:SF (match_operand 1 "arm_cond_move_operator" "")
8a18b90c 7358 (match_operand:SF 2 "s_register_operand" "")
d86c91f6 7359 (match_operand:SF 3 "s_register_operand" "")))]
19f6bf8d 7360 "TARGET_32BIT && TARGET_HARD_FLOAT"
39b5e676 7361 "
215b30b3 7362 {
7363 enum rtx_code code = GET_CODE (operands[1]);
7364 rtx ccreg;
f082f1c4 7365
f9aa4160 7366 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
7367 &XEXP (operands[1], 1)))
7368 FAIL;
39b5e676 7369
f9aa4160 7370 code = GET_CODE (operands[1]);
74f4459c 7371 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
e1b93706 7372 XEXP (operands[1], 1), NULL_RTX);
29bb088d 7373 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7374 }"
7375)
39b5e676 7376
7377(define_expand "movdfcc"
8a18b90c 7378 [(set (match_operand:DF 0 "s_register_operand" "")
4df97ffc 7379 (if_then_else:DF (match_operand 1 "arm_cond_move_operator" "")
8a18b90c 7380 (match_operand:DF 2 "s_register_operand" "")
d86c91f6 7381 (match_operand:DF 3 "s_register_operand" "")))]
994606f8 7382 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
39b5e676 7383 "
215b30b3 7384 {
7385 enum rtx_code code = GET_CODE (operands[1]);
278b301d 7386 rtx ccreg;
39b5e676 7387
f9aa4160 7388 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
7389 &XEXP (operands[1], 1)))
7390 FAIL;
7391 code = GET_CODE (operands[1]);
74f4459c 7392 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
e1b93706 7393 XEXP (operands[1], 1), NULL_RTX);
29bb088d 7394 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7395 }"
7396)
39b5e676 7397
91cb50d2 7398(define_insn "*cmov<mode>"
7399 [(set (match_operand:SDF 0 "s_register_operand" "=<F_constraint>")
7400 (if_then_else:SDF (match_operator 1 "arm_vsel_comparison_operator"
7401 [(match_operand 2 "cc_register" "") (const_int 0)])
7402 (match_operand:SDF 3 "s_register_operand"
7403 "<F_constraint>")
7404 (match_operand:SDF 4 "s_register_operand"
7405 "<F_constraint>")))]
7406 "TARGET_HARD_FLOAT && TARGET_FPU_ARMV8 <vfp_double_cond>"
7407 "*
7408 {
7409 enum arm_cond_code code = maybe_get_arm_condition_code (operands[1]);
7410 switch (code)
7411 {
7412 case ARM_GE:
7413 case ARM_GT:
7414 case ARM_EQ:
7415 case ARM_VS:
7416 return \"vsel%d1.<V_if_elem>\\t%<V_reg>0, %<V_reg>3, %<V_reg>4\";
7417 case ARM_LT:
7418 case ARM_LE:
7419 case ARM_NE:
7420 case ARM_VC:
7421 return \"vsel%D1.<V_if_elem>\\t%<V_reg>0, %<V_reg>4, %<V_reg>3\";
7422 default:
7423 gcc_unreachable ();
7424 }
7425 return \"\";
7426 }"
7427 [(set_attr "conds" "use")
6664d308 7428 (set_attr "type" "fcsel")]
91cb50d2 7429)
7430
190efb17 7431(define_insn_and_split "*movsicc_insn"
f082f1c4 7432 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
8a18b90c 7433 (if_then_else:SI
8fa3ba89 7434 (match_operator 3 "arm_comparison_operator"
8a18b90c 7435 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 7436 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
7437 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
cffb2a26 7438 "TARGET_ARM"
39b5e676 7439 "@
8a18b90c 7440 mov%D3\\t%0, %2
7441 mvn%D3\\t%0, #%B2
f082f1c4 7442 mov%d3\\t%0, %1
7443 mvn%d3\\t%0, #%B1
190efb17 7444 #
7445 #
7446 #
7447 #"
7448 ; alt4: mov%d3\\t%0, %1\;mov%D3\\t%0, %2
7449 ; alt5: mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
7450 ; alt6: mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
7451 ; alt7: mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
7452 "&& reload_completed"
7453 [(const_int 0)]
7454 {
7455 enum rtx_code rev_code;
3754d046 7456 machine_mode mode;
190efb17 7457 rtx rev_cond;
7458
7459 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
7460 operands[3],
7461 gen_rtx_SET (VOIDmode,
7462 operands[0],
7463 operands[1])));
7464
7465 rev_code = GET_CODE (operands[3]);
7466 mode = GET_MODE (operands[4]);
7467 if (mode == CCFPmode || mode == CCFPEmode)
7468 rev_code = reverse_condition_maybe_unordered (rev_code);
7469 else
7470 rev_code = reverse_condition (rev_code);
7471
7472 rev_cond = gen_rtx_fmt_ee (rev_code,
7473 VOIDmode,
7474 operands[4],
7475 const0_rtx);
7476 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
7477 rev_cond,
7478 gen_rtx_SET (VOIDmode,
7479 operands[0],
7480 operands[2])));
7481 DONE;
7482 }
f082f1c4 7483 [(set_attr "length" "4,4,4,4,8,8,8,8")
d2a518d1 7484 (set_attr "conds" "use")
65f68e55 7485 (set_attr_alternative "type"
7486 [(if_then_else (match_operand 2 "const_int_operand" "")
1aed5204 7487 (const_string "mov_imm")
7488 (const_string "mov_reg"))
7489 (const_string "mvn_imm")
65f68e55 7490 (if_then_else (match_operand 1 "const_int_operand" "")
1aed5204 7491 (const_string "mov_imm")
7492 (const_string "mov_reg"))
7493 (const_string "mvn_imm")
7494 (const_string "mov_reg")
7495 (const_string "mov_reg")
7496 (const_string "mov_reg")
7497 (const_string "mov_reg")])]
215b30b3 7498)
39b5e676 7499
39b5e676 7500(define_insn "*movsfcc_soft_insn"
f082f1c4 7501 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
8fa3ba89 7502 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
8a18b90c 7503 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 7504 (match_operand:SF 1 "s_register_operand" "0,r")
7505 (match_operand:SF 2 "s_register_operand" "r,0")))]
cffb2a26 7506 "TARGET_ARM && TARGET_SOFT_FLOAT"
f082f1c4 7507 "@
7508 mov%D3\\t%0, %2
7509 mov%d3\\t%0, %1"
d2a518d1 7510 [(set_attr "conds" "use")
1aed5204 7511 (set_attr "type" "mov_reg")]
8fa3ba89 7512)
39b5e676 7513
39b5e676 7514\f
9c08d1fa 7515;; Jump and linkage insns
7516
cffb2a26 7517(define_expand "jump"
9c08d1fa 7518 [(set (pc)
7519 (label_ref (match_operand 0 "" "")))]
cffb2a26 7520 "TARGET_EITHER"
9c08d1fa 7521 ""
cffb2a26 7522)
7523
7524(define_insn "*arm_jump"
7525 [(set (pc)
7526 (label_ref (match_operand 0 "" "")))]
25f905c2 7527 "TARGET_32BIT"
9c08d1fa 7528 "*
0d66636f 7529 {
7530 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7531 {
7532 arm_ccfsm_state += 2;
7533 return \"\";
7534 }
7535 return \"b%?\\t%l0\";
7536 }
7537 "
a6864a24 7538 [(set_attr "predicable" "yes")
7539 (set (attr "length")
7540 (if_then_else
0bf497f5 7541 (and (match_test "TARGET_THUMB2")
a6864a24 7542 (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
7543 (le (minus (match_dup 0) (pc)) (const_int 2048))))
7544 (const_int 2)
1b7da4ac 7545 (const_int 4)))
7546 (set_attr "type" "branch")]
0d66636f 7547)
9c08d1fa 7548
d3373b54 7549(define_expand "call"
7550 [(parallel [(call (match_operand 0 "memory_operand" "")
7551 (match_operand 1 "general_operand" ""))
cffb2a26 7552 (use (match_operand 2 "" ""))
bd5b4116 7553 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 7554 "TARGET_EITHER"
6c4c2133 7555 "
7556 {
bac7fc85 7557 rtx callee, pat;
bbe777ea 7558
bbe777ea 7559 /* In an untyped call, we can get NULL for operand 2. */
7560 if (operands[2] == NULL_RTX)
7561 operands[2] = const0_rtx;
7562
de55252a 7563 /* Decide if we should generate indirect calls by loading the
85c36fd1 7564 32-bit address of the callee into a register before performing the
de55252a 7565 branch and link. */
7566 callee = XEXP (operands[0], 0);
7567 if (GET_CODE (callee) == SYMBOL_REF
7568 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
7569 : !REG_P (callee))
bbe777ea 7570 XEXP (operands[0], 0) = force_reg (Pmode, callee);
bac7fc85 7571
7572 pat = gen_call_internal (operands[0], operands[1], operands[2]);
ca373797 7573 arm_emit_call_insn (pat, XEXP (operands[0], 0), false);
bac7fc85 7574 DONE;
6c4c2133 7575 }"
7576)
d3373b54 7577
bac7fc85 7578(define_expand "call_internal"
7579 [(parallel [(call (match_operand 0 "memory_operand" "")
7580 (match_operand 1 "general_operand" ""))
7581 (use (match_operand 2 "" ""))
7582 (clobber (reg:SI LR_REGNUM))])])
7583
f1039640 7584(define_insn "*call_reg_armv5"
d3373b54 7585 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
cffb2a26 7586 (match_operand 1 "" ""))
7587 (use (match_operand 2 "" ""))
bd5b4116 7588 (clobber (reg:SI LR_REGNUM))]
33ae7c4b 7589 "TARGET_ARM && arm_arch5 && !SIBLING_CALL_P (insn)"
f1039640 7590 "blx%?\\t%0"
7591 [(set_attr "type" "call")]
7592)
7593
7594(define_insn "*call_reg_arm"
7595 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7596 (match_operand 1 "" ""))
7597 (use (match_operand 2 "" ""))
7598 (clobber (reg:SI LR_REGNUM))]
33ae7c4b 7599 "TARGET_ARM && !arm_arch5 && !SIBLING_CALL_P (insn)"
9c08d1fa 7600 "*
5565501b 7601 return output_call (operands);
cffb2a26 7602 "
7603 ;; length is worst case, normally it is only two
7604 [(set_attr "length" "12")
7605 (set_attr "type" "call")]
7606)
9c08d1fa 7607
89504fc1 7608
7609;; Note: not used for armv5+ because the sequence used (ldr pc, ...) is not
7610;; considered a function call by the branch predictor of some cores (PR40887).
7611;; Falls back to blx rN (*call_reg_armv5).
7612
f7fbdd4a 7613(define_insn "*call_mem"
a3c63a9d 7614 [(call (mem:SI (match_operand:SI 0 "call_memory_operand" "m"))
cffb2a26 7615 (match_operand 1 "" ""))
7616 (use (match_operand 2 "" ""))
bd5b4116 7617 (clobber (reg:SI LR_REGNUM))]
33ae7c4b 7618 "TARGET_ARM && !arm_arch5 && !SIBLING_CALL_P (insn)"
9c08d1fa 7619 "*
5565501b 7620 return output_call_mem (operands);
cffb2a26 7621 "
7622 [(set_attr "length" "12")
7623 (set_attr "type" "call")]
7624)
7625
d3373b54 7626(define_expand "call_value"
e0698af7 7627 [(parallel [(set (match_operand 0 "" "")
7628 (call (match_operand 1 "memory_operand" "")
7629 (match_operand 2 "general_operand" "")))
cffb2a26 7630 (use (match_operand 3 "" ""))
bd5b4116 7631 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 7632 "TARGET_EITHER"
6c4c2133 7633 "
7634 {
bac7fc85 7635 rtx pat, callee;
bbe777ea 7636
7637 /* In an untyped call, we can get NULL for operand 2. */
7638 if (operands[3] == 0)
7639 operands[3] = const0_rtx;
7640
de55252a 7641 /* Decide if we should generate indirect calls by loading the
7642 32-bit address of the callee into a register before performing the
7643 branch and link. */
7644 callee = XEXP (operands[1], 0);
7645 if (GET_CODE (callee) == SYMBOL_REF
7646 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
7647 : !REG_P (callee))
78fe751b 7648 XEXP (operands[1], 0) = force_reg (Pmode, callee);
bac7fc85 7649
7650 pat = gen_call_value_internal (operands[0], operands[1],
7651 operands[2], operands[3]);
ca373797 7652 arm_emit_call_insn (pat, XEXP (operands[1], 0), false);
bac7fc85 7653 DONE;
6c4c2133 7654 }"
7655)
d3373b54 7656
bac7fc85 7657(define_expand "call_value_internal"
7658 [(parallel [(set (match_operand 0 "" "")
7659 (call (match_operand 1 "memory_operand" "")
7660 (match_operand 2 "general_operand" "")))
7661 (use (match_operand 3 "" ""))
7662 (clobber (reg:SI LR_REGNUM))])])
7663
f1039640 7664(define_insn "*call_value_reg_armv5"
27ed6835 7665 [(set (match_operand 0 "" "")
755eb2b4 7666 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
cffb2a26 7667 (match_operand 2 "" "")))
bbe777ea 7668 (use (match_operand 3 "" ""))
bd5b4116 7669 (clobber (reg:SI LR_REGNUM))]
33ae7c4b 7670 "TARGET_ARM && arm_arch5 && !SIBLING_CALL_P (insn)"
f1039640 7671 "blx%?\\t%1"
7672 [(set_attr "type" "call")]
7673)
7674
7675(define_insn "*call_value_reg_arm"
7676 [(set (match_operand 0 "" "")
7677 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7678 (match_operand 2 "" "")))
7679 (use (match_operand 3 "" ""))
7680 (clobber (reg:SI LR_REGNUM))]
33ae7c4b 7681 "TARGET_ARM && !arm_arch5 && !SIBLING_CALL_P (insn)"
9c08d1fa 7682 "*
215b30b3 7683 return output_call (&operands[1]);
cffb2a26 7684 "
7685 [(set_attr "length" "12")
7686 (set_attr "type" "call")]
7687)
9c08d1fa 7688
89504fc1 7689;; Note: see *call_mem
7690
f7fbdd4a 7691(define_insn "*call_value_mem"
27ed6835 7692 [(set (match_operand 0 "" "")
a3c63a9d 7693 (call (mem:SI (match_operand:SI 1 "call_memory_operand" "m"))
cffb2a26 7694 (match_operand 2 "" "")))
bbe777ea 7695 (use (match_operand 3 "" ""))
bd5b4116 7696 (clobber (reg:SI LR_REGNUM))]
33ae7c4b 7697 "TARGET_ARM && !arm_arch5 && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
7698 && !SIBLING_CALL_P (insn)"
9c08d1fa 7699 "*
215b30b3 7700 return output_call_mem (&operands[1]);
cffb2a26 7701 "
7702 [(set_attr "length" "12")
7703 (set_attr "type" "call")]
7704)
9c08d1fa 7705
7706;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
7707;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
7708
f7fbdd4a 7709(define_insn "*call_symbol"
27ed6835 7710 [(call (mem:SI (match_operand:SI 0 "" ""))
cffb2a26 7711 (match_operand 1 "" ""))
bbe777ea 7712 (use (match_operand 2 "" ""))
bd5b4116 7713 (clobber (reg:SI LR_REGNUM))]
d68c2c10 7714 "TARGET_32BIT
33ae7c4b 7715 && !SIBLING_CALL_P (insn)
cffb2a26 7716 && (GET_CODE (operands[0]) == SYMBOL_REF)
de55252a 7717 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
6ebaa29d 7718 "*
7719 {
55c1e470 7720 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
6ebaa29d 7721 }"
cffb2a26 7722 [(set_attr "type" "call")]
7723)
9c08d1fa 7724
f7fbdd4a 7725(define_insn "*call_value_symbol"
ccd90aaa 7726 [(set (match_operand 0 "" "")
27ed6835 7727 (call (mem:SI (match_operand:SI 1 "" ""))
dd6d7504 7728 (match_operand:SI 2 "" "")))
bbe777ea 7729 (use (match_operand 3 "" ""))
bd5b4116 7730 (clobber (reg:SI LR_REGNUM))]
d68c2c10 7731 "TARGET_32BIT
33ae7c4b 7732 && !SIBLING_CALL_P (insn)
cffb2a26 7733 && (GET_CODE (operands[1]) == SYMBOL_REF)
de55252a 7734 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
6ebaa29d 7735 "*
7736 {
55c1e470 7737 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
6ebaa29d 7738 }"
cffb2a26 7739 [(set_attr "type" "call")]
7740)
7741
ca373797 7742(define_expand "sibcall_internal"
7743 [(parallel [(call (match_operand 0 "memory_operand" "")
7744 (match_operand 1 "general_operand" ""))
7745 (return)
7746 (use (match_operand 2 "" ""))])])
7747
1c494086 7748;; We may also be able to do sibcalls for Thumb, but it's much harder...
7749(define_expand "sibcall"
7750 [(parallel [(call (match_operand 0 "memory_operand" "")
7751 (match_operand 1 "general_operand" ""))
2ba80634 7752 (return)
7753 (use (match_operand 2 "" ""))])]
d68c2c10 7754 "TARGET_32BIT"
1c494086 7755 "
7756 {
ca373797 7757 rtx pat;
7758
3112c3f7 7759 if ((!REG_P (XEXP (operands[0], 0))
7760 && GET_CODE (XEXP (operands[0], 0)) != SYMBOL_REF)
7761 || (GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
7762 && arm_is_long_call_p (SYMBOL_REF_DECL (XEXP (operands[0], 0)))))
33ae7c4b 7763 XEXP (operands[0], 0) = force_reg (SImode, XEXP (operands[0], 0));
7764
1c494086 7765 if (operands[2] == NULL_RTX)
7766 operands[2] = const0_rtx;
ca373797 7767
7768 pat = gen_sibcall_internal (operands[0], operands[1], operands[2]);
7769 arm_emit_call_insn (pat, operands[0], true);
7770 DONE;
1c494086 7771 }"
7772)
7773
ca373797 7774(define_expand "sibcall_value_internal"
7775 [(parallel [(set (match_operand 0 "" "")
7776 (call (match_operand 1 "memory_operand" "")
7777 (match_operand 2 "general_operand" "")))
7778 (return)
7779 (use (match_operand 3 "" ""))])])
7780
1c494086 7781(define_expand "sibcall_value"
ccd90aaa 7782 [(parallel [(set (match_operand 0 "" "")
1c494086 7783 (call (match_operand 1 "memory_operand" "")
7784 (match_operand 2 "general_operand" "")))
2ba80634 7785 (return)
7786 (use (match_operand 3 "" ""))])]
d68c2c10 7787 "TARGET_32BIT"
1c494086 7788 "
7789 {
ca373797 7790 rtx pat;
7791
3112c3f7 7792 if ((!REG_P (XEXP (operands[1], 0))
7793 && GET_CODE (XEXP (operands[1], 0)) != SYMBOL_REF)
7794 || (GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
7795 && arm_is_long_call_p (SYMBOL_REF_DECL (XEXP (operands[1], 0)))))
33ae7c4b 7796 XEXP (operands[1], 0) = force_reg (SImode, XEXP (operands[1], 0));
7797
1c494086 7798 if (operands[3] == NULL_RTX)
7799 operands[3] = const0_rtx;
ca373797 7800
7801 pat = gen_sibcall_value_internal (operands[0], operands[1],
7802 operands[2], operands[3]);
7803 arm_emit_call_insn (pat, operands[1], true);
7804 DONE;
1c494086 7805 }"
7806)
7807
7808(define_insn "*sibcall_insn"
84ce8e5c 7809 [(call (mem:SI (match_operand:SI 0 "call_insn_operand" "Cs, US"))
1c494086 7810 (match_operand 1 "" ""))
2ba80634 7811 (return)
7812 (use (match_operand 2 "" ""))]
33ae7c4b 7813 "TARGET_32BIT && SIBLING_CALL_P (insn)"
1c494086 7814 "*
33ae7c4b 7815 if (which_alternative == 1)
7816 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
7817 else
7818 {
7819 if (arm_arch5 || arm_arch4t)
947d113e 7820 return \"bx%?\\t%0\\t%@ indirect register sibling call\";
33ae7c4b 7821 else
7822 return \"mov%?\\t%|pc, %0\\t%@ indirect register sibling call\";
7823 }
1c494086 7824 "
7825 [(set_attr "type" "call")]
7826)
7827
7828(define_insn "*sibcall_value_insn"
84ce8e5c 7829 [(set (match_operand 0 "" "")
7830 (call (mem:SI (match_operand:SI 1 "call_insn_operand" "Cs,US"))
1c494086 7831 (match_operand 2 "" "")))
2ba80634 7832 (return)
7833 (use (match_operand 3 "" ""))]
33ae7c4b 7834 "TARGET_32BIT && SIBLING_CALL_P (insn)"
1c494086 7835 "*
33ae7c4b 7836 if (which_alternative == 1)
7837 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
7838 else
7839 {
7840 if (arm_arch5 || arm_arch4t)
84ce8e5c 7841 return \"bx%?\\t%1\";
33ae7c4b 7842 else
7843 return \"mov%?\\t%|pc, %1\\t@ indirect sibling call \";
7844 }
1c494086 7845 "
7846 [(set_attr "type" "call")]
7847)
7848
0686440e 7849(define_expand "<return_str>return"
7850 [(returns)]
8cba51a5 7851 "(TARGET_ARM || (TARGET_THUMB2
7852 && ARM_FUNC_TYPE (arm_current_func_type ()) == ARM_FT_NORMAL
7853 && !IS_STACKALIGN (arm_current_func_type ())))
0686440e 7854 <return_cond_false>"
8cba51a5 7855 "
7856 {
7857 if (TARGET_THUMB2)
7858 {
0686440e 7859 thumb2_expand_return (<return_simple_p>);
8cba51a5 7860 DONE;
7861 }
7862 }
7863 "
7864)
d68c2c10 7865
9c08d1fa 7866;; Often the return insn will be the same as loading from memory, so set attr
d68c2c10 7867(define_insn "*arm_return"
9c08d1fa 7868 [(return)]
cffb2a26 7869 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
9c08d1fa 7870 "*
9c08d1fa 7871 {
cffb2a26 7872 if (arm_ccfsm_state == 2)
7873 {
7874 arm_ccfsm_state += 2;
7875 return \"\";
7876 }
e2549f81 7877 return output_return_instruction (const_true_rtx, true, false, false);
cffb2a26 7878 }"
a2cd141b 7879 [(set_attr "type" "load1")
755eb2b4 7880 (set_attr "length" "12")
0d66636f 7881 (set_attr "predicable" "yes")]
cffb2a26 7882)
9c08d1fa 7883
0686440e 7884(define_insn "*cond_<return_str>return"
9c08d1fa 7885 [(set (pc)
8fa3ba89 7886 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 7887 [(match_operand 1 "cc_register" "") (const_int 0)])
0686440e 7888 (returns)
9c08d1fa 7889 (pc)))]
0686440e 7890 "TARGET_ARM <return_cond_true>"
9c08d1fa 7891 "*
8fa3ba89 7892 {
7893 if (arm_ccfsm_state == 2)
7894 {
7895 arm_ccfsm_state += 2;
7896 return \"\";
7897 }
0686440e 7898 return output_return_instruction (operands[0], true, false,
7899 <return_simple_p>);
8fa3ba89 7900 }"
7901 [(set_attr "conds" "use")
755eb2b4 7902 (set_attr "length" "12")
a2cd141b 7903 (set_attr "type" "load1")]
8fa3ba89 7904)
9c08d1fa 7905
0686440e 7906(define_insn "*cond_<return_str>return_inverted"
9c08d1fa 7907 [(set (pc)
8fa3ba89 7908 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 7909 [(match_operand 1 "cc_register" "") (const_int 0)])
9c08d1fa 7910 (pc)
0686440e 7911 (returns)))]
7912 "TARGET_ARM <return_cond_true>"
9c08d1fa 7913 "*
8fa3ba89 7914 {
7915 if (arm_ccfsm_state == 2)
7916 {
7917 arm_ccfsm_state += 2;
7918 return \"\";
7919 }
0686440e 7920 return output_return_instruction (operands[0], true, true,
7921 <return_simple_p>);
8fa3ba89 7922 }"
7923 [(set_attr "conds" "use")
37a1317b 7924 (set_attr "length" "12")
a2cd141b 7925 (set_attr "type" "load1")]
8fa3ba89 7926)
9c08d1fa 7927
e2549f81 7928(define_insn "*arm_simple_return"
7929 [(simple_return)]
7930 "TARGET_ARM"
7931 "*
7932 {
7933 if (arm_ccfsm_state == 2)
7934 {
7935 arm_ccfsm_state += 2;
7936 return \"\";
7937 }
7938 return output_return_instruction (const_true_rtx, true, false, true);
7939 }"
7940 [(set_attr "type" "branch")
7941 (set_attr "length" "4")
7942 (set_attr "predicable" "yes")]
7943)
7944
68121397 7945;; Generate a sequence of instructions to determine if the processor is
7946;; in 26-bit or 32-bit mode, and return the appropriate return address
7947;; mask.
7948
7949(define_expand "return_addr_mask"
7950 [(set (match_dup 1)
7951 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7952 (const_int 0)))
7953 (set (match_operand:SI 0 "s_register_operand" "")
7954 (if_then_else:SI (eq (match_dup 1) (const_int 0))
7955 (const_int -1)
7956 (const_int 67108860)))] ; 0x03fffffc
7957 "TARGET_ARM"
7958 "
62eddbd4 7959 operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
68121397 7960 ")
7961
7962(define_insn "*check_arch2"
7963 [(set (match_operand:CC_NOOV 0 "cc_register" "")
7964 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7965 (const_int 0)))]
7966 "TARGET_ARM"
7967 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
7968 [(set_attr "length" "8")
1b7da4ac 7969 (set_attr "conds" "set")
7970 (set_attr "type" "multiple")]
68121397 7971)
7972
9c08d1fa 7973;; Call subroutine returning any type.
7974
7975(define_expand "untyped_call"
7976 [(parallel [(call (match_operand 0 "" "")
7977 (const_int 0))
7978 (match_operand 1 "" "")
7979 (match_operand 2 "" "")])]
ccd90aaa 7980 "TARGET_EITHER"
9c08d1fa 7981 "
215b30b3 7982 {
7983 int i;
ccd90aaa 7984 rtx par = gen_rtx_PARALLEL (VOIDmode,
7985 rtvec_alloc (XVECLEN (operands[2], 0)));
7986 rtx addr = gen_reg_rtx (Pmode);
7987 rtx mem;
7988 int size = 0;
9c08d1fa 7989
ccd90aaa 7990 emit_move_insn (addr, XEXP (operands[1], 0));
7991 mem = change_address (operands[1], BLKmode, addr);
9c08d1fa 7992
215b30b3 7993 for (i = 0; i < XVECLEN (operands[2], 0); i++)
7994 {
ccd90aaa 7995 rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
9c08d1fa 7996
ccd90aaa 7997 /* Default code only uses r0 as a return value, but we could
7998 be using anything up to 4 registers. */
7999 if (REGNO (src) == R0_REGNUM)
8000 src = gen_rtx_REG (TImode, R0_REGNUM);
8001
8002 XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
8003 GEN_INT (size));
8004 size += GET_MODE_SIZE (GET_MODE (src));
8005 }
8006
8007 emit_call_insn (GEN_CALL_VALUE (par, operands[0], const0_rtx, NULL,
8008 const0_rtx));
8009
8010 size = 0;
8011
8012 for (i = 0; i < XVECLEN (par, 0); i++)
8013 {
8014 HOST_WIDE_INT offset = 0;
8015 rtx reg = XEXP (XVECEXP (par, 0, i), 0);
8016
8017 if (size != 0)
29c05e22 8018 emit_move_insn (addr, plus_constant (Pmode, addr, size));
ccd90aaa 8019
8020 mem = change_address (mem, GET_MODE (reg), NULL);
8021 if (REGNO (reg) == R0_REGNUM)
8022 {
8023 /* On thumb we have to use a write-back instruction. */
320ea44d 8024 emit_insn (arm_gen_store_multiple (arm_regs_in_sequence, 4, addr,
8025 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
ccd90aaa 8026 size = TARGET_ARM ? 16 : 0;
8027 }
8028 else
8029 {
8030 emit_move_insn (mem, reg);
8031 size = GET_MODE_SIZE (GET_MODE (reg));
8032 }
215b30b3 8033 }
9c08d1fa 8034
215b30b3 8035 /* The optimizer does not know that the call sets the function value
8036 registers we stored in the result block. We avoid problems by
8037 claiming that all hard registers are used and clobbered at this
8038 point. */
8039 emit_insn (gen_blockage ());
8040
8041 DONE;
8042 }"
8043)
9c08d1fa 8044
ccd90aaa 8045(define_expand "untyped_return"
8046 [(match_operand:BLK 0 "memory_operand" "")
8047 (match_operand 1 "" "")]
8048 "TARGET_EITHER"
8049 "
8050 {
8051 int i;
8052 rtx addr = gen_reg_rtx (Pmode);
8053 rtx mem;
8054 int size = 0;
8055
8056 emit_move_insn (addr, XEXP (operands[0], 0));
8057 mem = change_address (operands[0], BLKmode, addr);
8058
8059 for (i = 0; i < XVECLEN (operands[1], 0); i++)
8060 {
8061 HOST_WIDE_INT offset = 0;
8062 rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
8063
8064 if (size != 0)
29c05e22 8065 emit_move_insn (addr, plus_constant (Pmode, addr, size));
ccd90aaa 8066
8067 mem = change_address (mem, GET_MODE (reg), NULL);
8068 if (REGNO (reg) == R0_REGNUM)
8069 {
8070 /* On thumb we have to use a write-back instruction. */
320ea44d 8071 emit_insn (arm_gen_load_multiple (arm_regs_in_sequence, 4, addr,
8072 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
ccd90aaa 8073 size = TARGET_ARM ? 16 : 0;
8074 }
8075 else
8076 {
8077 emit_move_insn (reg, mem);
8078 size = GET_MODE_SIZE (GET_MODE (reg));
8079 }
8080 }
8081
8082 /* Emit USE insns before the return. */
8083 for (i = 0; i < XVECLEN (operands[1], 0); i++)
18b42941 8084 emit_use (SET_DEST (XVECEXP (operands[1], 0, i)));
ccd90aaa 8085
8086 /* Construct the return. */
8087 expand_naked_return ();
8088
8089 DONE;
8090 }"
8091)
8092
9c08d1fa 8093;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
8094;; all of memory. This blocks insns from being moved across this point.
8095
8096(define_insn "blockage"
e1159bbe 8097 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
cffb2a26 8098 "TARGET_EITHER"
9c08d1fa 8099 ""
cffb2a26 8100 [(set_attr "length" "0")
8101 (set_attr "type" "block")]
8102)
9c08d1fa 8103
f7fbdd4a 8104(define_expand "casesi"
8105 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
aea4c774 8106 (match_operand:SI 1 "const_int_operand" "") ; lower bound
8107 (match_operand:SI 2 "const_int_operand" "") ; total range
f7fbdd4a 8108 (match_operand:SI 3 "" "") ; table label
8109 (match_operand:SI 4 "" "")] ; Out of range label
e6ac8414 8110 "TARGET_32BIT || optimize_size || flag_pic"
f7fbdd4a 8111 "
215b30b3 8112 {
e6ac8414 8113 enum insn_code code;
215b30b3 8114 if (operands[1] != const0_rtx)
8115 {
e6ac8414 8116 rtx reg = gen_reg_rtx (SImode);
f7fbdd4a 8117
215b30b3 8118 emit_insn (gen_addsi3 (reg, operands[0],
d022fa24 8119 gen_int_mode (-INTVAL (operands[1]),
8120 SImode)));
215b30b3 8121 operands[0] = reg;
8122 }
9c08d1fa 8123
25f905c2 8124 if (TARGET_ARM)
e6ac8414 8125 code = CODE_FOR_arm_casesi_internal;
3db2019b 8126 else if (TARGET_THUMB1)
e6ac8414 8127 code = CODE_FOR_thumb1_casesi_internal_pic;
25f905c2 8128 else if (flag_pic)
e6ac8414 8129 code = CODE_FOR_thumb2_casesi_internal_pic;
25f905c2 8130 else
e6ac8414 8131 code = CODE_FOR_thumb2_casesi_internal;
8132
8133 if (!insn_data[(int) code].operand[1].predicate(operands[2], SImode))
8134 operands[2] = force_reg (SImode, operands[2]);
8135
8136 emit_jump_insn (GEN_FCN ((int) code) (operands[0], operands[2],
8137 operands[3], operands[4]));
215b30b3 8138 DONE;
8139 }"
8140)
f7fbdd4a 8141
f082f1c4 8142;; The USE in this pattern is needed to tell flow analysis that this is
8143;; a CASESI insn. It has no other purpose.
25f905c2 8144(define_insn "arm_casesi_internal"
f082f1c4 8145 [(parallel [(set (pc)
8146 (if_then_else
8147 (leu (match_operand:SI 0 "s_register_operand" "r")
8148 (match_operand:SI 1 "arm_rhs_operand" "rI"))
8149 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
8150 (label_ref (match_operand 2 "" ""))))
8151 (label_ref (match_operand 3 "" ""))))
bd5b4116 8152 (clobber (reg:CC CC_REGNUM))
f082f1c4 8153 (use (label_ref (match_dup 2)))])]
cffb2a26 8154 "TARGET_ARM"
f7fbdd4a 8155 "*
0d66636f 8156 if (flag_pic)
8157 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
8158 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
8159 "
8160 [(set_attr "conds" "clob")
1b7da4ac 8161 (set_attr "length" "12")
8162 (set_attr "type" "multiple")]
0d66636f 8163)
9c08d1fa 8164
cffb2a26 8165(define_expand "indirect_jump"
9c08d1fa 8166 [(set (pc)
cffb2a26 8167 (match_operand:SI 0 "s_register_operand" ""))]
8168 "TARGET_EITHER"
25f905c2 8169 "
8170 /* Thumb-2 doesn't have mov pc, reg. Explicitly set the low bit of the
8171 address and use bx. */
8172 if (TARGET_THUMB2)
8173 {
8174 rtx tmp;
8175 tmp = gen_reg_rtx (SImode);
8176 emit_insn (gen_iorsi3 (tmp, operands[0], GEN_INT(1)));
8177 operands[0] = tmp;
8178 }
8179 "
cffb2a26 8180)
8181
f1039640 8182;; NB Never uses BX.
cffb2a26 8183(define_insn "*arm_indirect_jump"
8184 [(set (pc)
8185 (match_operand:SI 0 "s_register_operand" "r"))]
8186 "TARGET_ARM"
8187 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
1b7da4ac 8188 [(set_attr "predicable" "yes")
8189 (set_attr "type" "branch")]
cffb2a26 8190)
9c08d1fa 8191
f7fbdd4a 8192(define_insn "*load_indirect_jump"
9c08d1fa 8193 [(set (pc)
8194 (match_operand:SI 0 "memory_operand" "m"))]
cffb2a26 8195 "TARGET_ARM"
8196 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
a2cd141b 8197 [(set_attr "type" "load1")
61a2d04c 8198 (set_attr "pool_range" "4096")
8199 (set_attr "neg_pool_range" "4084")
0d66636f 8200 (set_attr "predicable" "yes")]
cffb2a26 8201)
8202
9c08d1fa 8203\f
8204;; Misc insns
8205
8206(define_insn "nop"
8207 [(const_int 0)]
cffb2a26 8208 "TARGET_EITHER"
8209 "*
25f905c2 8210 if (TARGET_UNIFIED_ASM)
8211 return \"nop\";
cffb2a26 8212 if (TARGET_ARM)
8213 return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
8214 return \"mov\\tr8, r8\";
8215 "
8216 [(set (attr "length")
8217 (if_then_else (eq_attr "is_thumb" "yes")
8218 (const_int 2)
1b7da4ac 8219 (const_int 4)))
8220 (set_attr "type" "mov_reg")]
cffb2a26 8221)
8222
ad9d4399 8223(define_insn "trap"
8224 [(trap_if (const_int 1) (const_int 0))]
8225 ""
8226 "*
8227 if (TARGET_ARM)
8228 return \".inst\\t0xe7f000f0\";
8229 else
8230 return \".inst\\t0xdeff\";
8231 "
8232 [(set (attr "length")
8233 (if_then_else (eq_attr "is_thumb" "yes")
8234 (const_int 2)
8235 (const_int 4)))
8236 (set_attr "type" "trap")
8237 (set_attr "conds" "unconditional")]
8238)
8239
9c08d1fa 8240\f
8241;; Patterns to allow combination of arithmetic, cond code and shifts
8242
0abea32c 8243(define_insn "*<arith_shift_insn>_multsi"
8244 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8245 (shiftable_ops:SI
8246 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
8247 (match_operand:SI 3 "power_of_two_operand" ""))
8248 (match_operand:SI 1 "s_register_operand" "rk,<t2_binop0>")))]
d5d4dc8d 8249 "TARGET_32BIT"
0abea32c 8250 "<arith_shift_insn>%?\\t%0, %1, %2, lsl %b3"
8251 [(set_attr "predicable" "yes")
8252 (set_attr "predicable_short_it" "no")
753d9835 8253 (set_attr "shift" "2")
0abea32c 8254 (set_attr "arch" "a,t2")
8255 (set_attr "type" "alu_shift_imm")])
8256
8257(define_insn "*<arith_shift_insn>_shiftsi"
8258 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8259 (shiftable_ops:SI
8260 (match_operator:SI 2 "shift_nomul_operator"
8261 [(match_operand:SI 3 "s_register_operand" "r,r,r")
8262 (match_operand:SI 4 "shift_amount_operand" "M,M,r")])
8263 (match_operand:SI 1 "s_register_operand" "rk,<t2_binop0>,rk")))]
a021b821 8264 "TARGET_32BIT && GET_CODE (operands[2]) != MULT"
0abea32c 8265 "<arith_shift_insn>%?\\t%0, %1, %3%S2"
344495ea 8266 [(set_attr "predicable" "yes")
74ef923b 8267 (set_attr "predicable_short_it" "no")
753d9835 8268 (set_attr "shift" "3")
0abea32c 8269 (set_attr "arch" "a,t2,a")
8270 (set_attr "type" "alu_shift_imm,alu_shift_imm,alu_shift_reg")])
9c08d1fa 8271
d7863cfe 8272(define_split
8273 [(set (match_operand:SI 0 "s_register_operand" "")
8274 (match_operator:SI 1 "shiftable_operator"
8275 [(match_operator:SI 2 "shiftable_operator"
8276 [(match_operator:SI 3 "shift_operator"
8277 [(match_operand:SI 4 "s_register_operand" "")
8278 (match_operand:SI 5 "reg_or_int_operand" "")])
8279 (match_operand:SI 6 "s_register_operand" "")])
8280 (match_operand:SI 7 "arm_rhs_operand" "")]))
8281 (clobber (match_operand:SI 8 "s_register_operand" ""))]
d5d4dc8d 8282 "TARGET_32BIT"
d7863cfe 8283 [(set (match_dup 8)
8284 (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8285 (match_dup 6)]))
8286 (set (match_dup 0)
8287 (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
8288 "")
8289
f7fbdd4a 8290(define_insn "*arith_shiftsi_compare0"
bd5b4116 8291 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 8292 (compare:CC_NOOV
8293 (match_operator:SI 1 "shiftable_operator"
8294 [(match_operator:SI 3 "shift_operator"
8295 [(match_operand:SI 4 "s_register_operand" "r,r")
8296 (match_operand:SI 5 "shift_amount_operand" "M,r")])
8297 (match_operand:SI 2 "s_register_operand" "r,r")])
8298 (const_int 0)))
8299 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 8300 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8301 (match_dup 2)]))]
d5d4dc8d 8302 "TARGET_32BIT"
25f905c2 8303 "%i1%.\\t%0, %2, %4%S3"
344495ea 8304 [(set_attr "conds" "set")
331beb1a 8305 (set_attr "shift" "4")
d5d4dc8d 8306 (set_attr "arch" "32,a")
d82e788e 8307 (set_attr "type" "alus_shift_imm,alus_shift_reg")])
9c08d1fa 8308
f7fbdd4a 8309(define_insn "*arith_shiftsi_compare0_scratch"
bd5b4116 8310 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 8311 (compare:CC_NOOV
8312 (match_operator:SI 1 "shiftable_operator"
8313 [(match_operator:SI 3 "shift_operator"
8314 [(match_operand:SI 4 "s_register_operand" "r,r")
8315 (match_operand:SI 5 "shift_amount_operand" "M,r")])
8316 (match_operand:SI 2 "s_register_operand" "r,r")])
8317 (const_int 0)))
8318 (clobber (match_scratch:SI 0 "=r,r"))]
8319 "TARGET_32BIT"
25f905c2 8320 "%i1%.\\t%0, %2, %4%S3"
344495ea 8321 [(set_attr "conds" "set")
331beb1a 8322 (set_attr "shift" "4")
d5d4dc8d 8323 (set_attr "arch" "32,a")
d82e788e 8324 (set_attr "type" "alus_shift_imm,alus_shift_reg")])
9c08d1fa 8325
f7fbdd4a 8326(define_insn "*sub_shiftsi"
d5d4dc8d 8327 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8328 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
9c08d1fa 8329 (match_operator:SI 2 "shift_operator"
d5d4dc8d 8330 [(match_operand:SI 3 "s_register_operand" "r,r")
8331 (match_operand:SI 4 "shift_amount_operand" "M,r")])))]
8332 "TARGET_32BIT"
6c4c2133 8333 "sub%?\\t%0, %1, %3%S2"
344495ea 8334 [(set_attr "predicable" "yes")
331beb1a 8335 (set_attr "shift" "3")
d5d4dc8d 8336 (set_attr "arch" "32,a")
d82e788e 8337 (set_attr "type" "alus_shift_imm,alus_shift_reg")])
9c08d1fa 8338
f7fbdd4a 8339(define_insn "*sub_shiftsi_compare0"
bd5b4116 8340 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 8341 (compare:CC_NOOV
d82e788e 8342 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
40dbec34 8343 (match_operator:SI 2 "shift_operator"
d82e788e 8344 [(match_operand:SI 3 "s_register_operand" "r,r,r")
8345 (match_operand:SI 4 "shift_amount_operand" "M,r,M")]))
40dbec34 8346 (const_int 0)))
d82e788e 8347 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
d5d4dc8d 8348 (minus:SI (match_dup 1)
8349 (match_op_dup 2 [(match_dup 3) (match_dup 4)])))]
8350 "TARGET_32BIT"
25f905c2 8351 "sub%.\\t%0, %1, %3%S2"
344495ea 8352 [(set_attr "conds" "set")
a2cd141b 8353 (set_attr "shift" "3")
d82e788e 8354 (set_attr "arch" "32,a,a")
8355 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
9c08d1fa 8356
f7fbdd4a 8357(define_insn "*sub_shiftsi_compare0_scratch"
bd5b4116 8358 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 8359 (compare:CC_NOOV
d82e788e 8360 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
40dbec34 8361 (match_operator:SI 2 "shift_operator"
d82e788e 8362 [(match_operand:SI 3 "s_register_operand" "r,r,r")
8363 (match_operand:SI 4 "shift_amount_operand" "M,r,M")]))
40dbec34 8364 (const_int 0)))
d82e788e 8365 (clobber (match_scratch:SI 0 "=r,r,r"))]
d5d4dc8d 8366 "TARGET_32BIT"
25f905c2 8367 "sub%.\\t%0, %1, %3%S2"
344495ea 8368 [(set_attr "conds" "set")
a2cd141b 8369 (set_attr "shift" "3")
d82e788e 8370 (set_attr "arch" "32,a,a")
8371 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
9c08d1fa 8372\f
8373
190efb17 8374(define_insn_and_split "*and_scc"
9c08d1fa 8375 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 8376 (and:SI (match_operator:SI 1 "arm_comparison_operator"
190efb17 8377 [(match_operand 2 "cc_register" "") (const_int 0)])
8378 (match_operand:SI 3 "s_register_operand" "r")))]
cffb2a26 8379 "TARGET_ARM"
190efb17 8380 "#" ; "mov%D1\\t%0, #0\;and%d1\\t%0, %3, #1"
8381 "&& reload_completed"
8382 [(cond_exec (match_dup 5) (set (match_dup 0) (const_int 0)))
8383 (cond_exec (match_dup 4) (set (match_dup 0)
8384 (and:SI (match_dup 3) (const_int 1))))]
8385 {
3754d046 8386 machine_mode mode = GET_MODE (operands[2]);
190efb17 8387 enum rtx_code rc = GET_CODE (operands[1]);
8388
8389 /* Note that operands[4] is the same as operands[1],
8390 but with VOIDmode as the result. */
8391 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
8392 if (mode == CCFPmode || mode == CCFPEmode)
8393 rc = reverse_condition_maybe_unordered (rc);
8394 else
8395 rc = reverse_condition (rc);
8396 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
8397 }
8fa3ba89 8398 [(set_attr "conds" "use")
1b7da4ac 8399 (set_attr "type" "multiple")
8fa3ba89 8400 (set_attr "length" "8")]
8401)
9c08d1fa 8402
190efb17 8403(define_insn_and_split "*ior_scc"
9c08d1fa 8404 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
190efb17 8405 (ior:SI (match_operator:SI 1 "arm_comparison_operator"
8406 [(match_operand 2 "cc_register" "") (const_int 0)])
8407 (match_operand:SI 3 "s_register_operand" "0,?r")))]
cffb2a26 8408 "TARGET_ARM"
e2348bcb 8409 "@
190efb17 8410 orr%d1\\t%0, %3, #1
8411 #"
8412 "&& reload_completed
8413 && REGNO (operands [0]) != REGNO (operands[3])"
8414 ;; && which_alternative == 1
8415 ; mov%D1\\t%0, %3\;orr%d1\\t%0, %3, #1
8416 [(cond_exec (match_dup 5) (set (match_dup 0) (match_dup 3)))
8417 (cond_exec (match_dup 4) (set (match_dup 0)
8418 (ior:SI (match_dup 3) (const_int 1))))]
8419 {
3754d046 8420 machine_mode mode = GET_MODE (operands[2]);
190efb17 8421 enum rtx_code rc = GET_CODE (operands[1]);
8422
8423 /* Note that operands[4] is the same as operands[1],
8424 but with VOIDmode as the result. */
8425 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
8426 if (mode == CCFPmode || mode == CCFPEmode)
8427 rc = reverse_condition_maybe_unordered (rc);
8428 else
8429 rc = reverse_condition (rc);
8430 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
8431 }
8fa3ba89 8432 [(set_attr "conds" "use")
1b7da4ac 8433 (set_attr "length" "4,8")
8434 (set_attr "type" "logic_imm,multiple")]
8fa3ba89 8435)
9c08d1fa 8436
2df9477b 8437; A series of splitters for the compare_scc pattern below. Note that
8438; order is important.
8439(define_split
8440 [(set (match_operand:SI 0 "s_register_operand" "")
8441 (lt:SI (match_operand:SI 1 "s_register_operand" "")
8442 (const_int 0)))
8443 (clobber (reg:CC CC_REGNUM))]
8444 "TARGET_32BIT && reload_completed"
8445 [(set (match_dup 0) (lshiftrt:SI (match_dup 1) (const_int 31)))])
8446
8447(define_split
8448 [(set (match_operand:SI 0 "s_register_operand" "")
8449 (ge:SI (match_operand:SI 1 "s_register_operand" "")
8450 (const_int 0)))
8451 (clobber (reg:CC CC_REGNUM))]
8452 "TARGET_32BIT && reload_completed"
8453 [(set (match_dup 0) (not:SI (match_dup 1)))
8454 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 31)))])
8455
98562479 8456(define_split
8457 [(set (match_operand:SI 0 "s_register_operand" "")
8458 (eq:SI (match_operand:SI 1 "s_register_operand" "")
8459 (const_int 0)))
8460 (clobber (reg:CC CC_REGNUM))]
8461 "arm_arch5 && TARGET_32BIT"
8462 [(set (match_dup 0) (clz:SI (match_dup 1)))
8463 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 5)))]
8464)
8465
2df9477b 8466(define_split
8467 [(set (match_operand:SI 0 "s_register_operand" "")
8468 (eq:SI (match_operand:SI 1 "s_register_operand" "")
8469 (const_int 0)))
8470 (clobber (reg:CC CC_REGNUM))]
8471 "TARGET_32BIT && reload_completed"
8472 [(parallel
080c0b9a 8473 [(set (reg:CC CC_REGNUM)
8474 (compare:CC (const_int 1) (match_dup 1)))
2df9477b 8475 (set (match_dup 0)
8476 (minus:SI (const_int 1) (match_dup 1)))])
080c0b9a 8477 (cond_exec (ltu:CC (reg:CC CC_REGNUM) (const_int 0))
2df9477b 8478 (set (match_dup 0) (const_int 0)))])
8479
8480(define_split
8481 [(set (match_operand:SI 0 "s_register_operand" "")
8482 (ne:SI (match_operand:SI 1 "s_register_operand" "")
8483 (match_operand:SI 2 "const_int_operand" "")))
8484 (clobber (reg:CC CC_REGNUM))]
8485 "TARGET_32BIT && reload_completed"
8486 [(parallel
8487 [(set (reg:CC CC_REGNUM)
8488 (compare:CC (match_dup 1) (match_dup 2)))
8489 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))])
8490 (cond_exec (ne:CC (reg:CC CC_REGNUM) (const_int 0))
8491 (set (match_dup 0) (const_int 1)))]
8492{
8493 operands[3] = GEN_INT (-INTVAL (operands[2]));
8494})
8495
8496(define_split
8497 [(set (match_operand:SI 0 "s_register_operand" "")
8498 (ne:SI (match_operand:SI 1 "s_register_operand" "")
8499 (match_operand:SI 2 "arm_add_operand" "")))
8500 (clobber (reg:CC CC_REGNUM))]
8501 "TARGET_32BIT && reload_completed"
8502 [(parallel
8503 [(set (reg:CC_NOOV CC_REGNUM)
8504 (compare:CC_NOOV (minus:SI (match_dup 1) (match_dup 2))
8505 (const_int 0)))
8506 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
8507 (cond_exec (ne:CC_NOOV (reg:CC_NOOV CC_REGNUM) (const_int 0))
8508 (set (match_dup 0) (const_int 1)))])
8509
8510(define_insn_and_split "*compare_scc"
fd711051 8511 [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts")
8fa3ba89 8512 (match_operator:SI 1 "arm_comparison_operator"
5565501b 8513 [(match_operand:SI 2 "s_register_operand" "r,r")
8514 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
bd5b4116 8515 (clobber (reg:CC CC_REGNUM))]
2df9477b 8516 "TARGET_32BIT"
8517 "#"
8518 "&& reload_completed"
8519 [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 3)))
8520 (cond_exec (match_dup 4) (set (match_dup 0) (const_int 0)))
8521 (cond_exec (match_dup 5) (set (match_dup 0) (const_int 1)))]
8522{
8523 rtx tmp1;
3754d046 8524 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
2df9477b 8525 operands[2], operands[3]);
8526 enum rtx_code rc = GET_CODE (operands[1]);
e2348bcb 8527
2df9477b 8528 tmp1 = gen_rtx_REG (mode, CC_REGNUM);
080c0b9a 8529
2df9477b 8530 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
8531 if (mode == CCFPmode || mode == CCFPEmode)
8532 rc = reverse_condition_maybe_unordered (rc);
8533 else
8534 rc = reverse_condition (rc);
8535 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
1b7da4ac 8536}
8537 [(set_attr "type" "multiple")]
8538)
9c08d1fa 8539
080c0b9a 8540;; Attempt to improve the sequence generated by the compare_scc splitters
8541;; not to use conditional execution.
98562479 8542
8543;; Rd = (eq (reg1) (const_int0)) // ARMv5
8544;; clz Rd, reg1
8545;; lsr Rd, Rd, #5
080c0b9a 8546(define_peephole2
8547 [(set (reg:CC CC_REGNUM)
8548 (compare:CC (match_operand:SI 1 "register_operand" "")
98562479 8549 (const_int 0)))
8550 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
8551 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
8552 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
8553 (set (match_dup 0) (const_int 1)))]
8554 "arm_arch5 && TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)"
8555 [(set (match_dup 0) (clz:SI (match_dup 1)))
8556 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 5)))]
8557)
8558
8559;; Rd = (eq (reg1) (const_int0)) // !ARMv5
8560;; negs Rd, reg1
8561;; adc Rd, Rd, reg1
8562(define_peephole2
8563 [(set (reg:CC CC_REGNUM)
8564 (compare:CC (match_operand:SI 1 "register_operand" "")
8565 (const_int 0)))
080c0b9a 8566 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
8567 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
8568 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
8569 (set (match_dup 0) (const_int 1)))
98562479 8570 (match_scratch:SI 2 "r")]
8571 "TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)"
922b6913 8572 [(parallel
8573 [(set (reg:CC CC_REGNUM)
98562479 8574 (compare:CC (const_int 0) (match_dup 1)))
8575 (set (match_dup 2) (minus:SI (const_int 0) (match_dup 1)))])
8576 (set (match_dup 0)
8577 (plus:SI (plus:SI (match_dup 1) (match_dup 2))
8578 (geu:SI (reg:CC CC_REGNUM) (const_int 0))))]
8579)
8580
31991287 8581;; Rd = (eq (reg1) (reg2/imm)) // ARMv5 and optimising for speed.
98562479 8582;; sub Rd, Reg1, reg2
8583;; clz Rd, Rd
8584;; lsr Rd, Rd, #5
8585(define_peephole2
8586 [(set (reg:CC CC_REGNUM)
8587 (compare:CC (match_operand:SI 1 "register_operand" "")
8588 (match_operand:SI 2 "arm_rhs_operand" "")))
8589 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
8590 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
8591 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
8592 (set (match_dup 0) (const_int 1)))]
31991287 8593 "arm_arch5 && TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)
8594 && !(TARGET_THUMB2 && optimize_insn_for_size_p ())"
98562479 8595 [(set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))
8596 (set (match_dup 0) (clz:SI (match_dup 0)))
8597 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 5)))]
8598)
8599
8600
31991287 8601;; Rd = (eq (reg1) (reg2)) // ! ARMv5 or optimising for size.
98562479 8602;; sub T1, Reg1, reg2
8603;; negs Rd, T1
8604;; adc Rd, Rd, T1
8605(define_peephole2
8606 [(set (reg:CC CC_REGNUM)
8607 (compare:CC (match_operand:SI 1 "register_operand" "")
8608 (match_operand:SI 2 "arm_rhs_operand" "")))
8609 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
8610 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
8611 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
8612 (set (match_dup 0) (const_int 1)))
8613 (match_scratch:SI 3 "r")]
8614 "TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)"
31991287 8615 [(set (match_dup 3) (match_dup 4))
080c0b9a 8616 (parallel
8617 [(set (reg:CC CC_REGNUM)
8618 (compare:CC (const_int 0) (match_dup 3)))
8619 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 3)))])
98562479 8620 (set (match_dup 0)
8621 (plus:SI (plus:SI (match_dup 0) (match_dup 3))
8622 (geu:SI (reg:CC CC_REGNUM) (const_int 0))))]
31991287 8623 "
8624 if (CONST_INT_P (operands[2]))
8625 operands[4] = plus_constant (SImode, operands[1], -INTVAL (operands[2]));
8626 else
8627 operands[4] = gen_rtx_MINUS (SImode, operands[1], operands[2]);
8628 ")
080c0b9a 8629
f7fbdd4a 8630(define_insn "*cond_move"
9c08d1fa 8631 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
aea4c774 8632 (if_then_else:SI (match_operator 3 "equality_operator"
8fa3ba89 8633 [(match_operator 4 "arm_comparison_operator"
8a18b90c 8634 [(match_operand 5 "cc_register" "") (const_int 0)])
aea4c774 8635 (const_int 0)])
8636 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8637 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
cffb2a26 8638 "TARGET_ARM"
9c08d1fa 8639 "*
8fa3ba89 8640 if (GET_CODE (operands[3]) == NE)
8641 {
8642 if (which_alternative != 1)
8643 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
8644 if (which_alternative != 0)
8645 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
8646 return \"\";
8647 }
8648 if (which_alternative != 0)
8649 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8650 if (which_alternative != 1)
8651 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
8652 return \"\";
8653 "
8654 [(set_attr "conds" "use")
1b7da4ac 8655 (set_attr "type" "mov_reg,mov_reg,multiple")
8fa3ba89 8656 (set_attr "length" "4,4,8")]
8657)
9c08d1fa 8658
f7fbdd4a 8659(define_insn "*cond_arith"
9c08d1fa 8660 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8661 (match_operator:SI 5 "shiftable_operator"
8fa3ba89 8662 [(match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 8663 [(match_operand:SI 2 "s_register_operand" "r,r")
8664 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8665 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 8666 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8667 "TARGET_ARM"
9c08d1fa 8668 "*
8fa3ba89 8669 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
8670 return \"%i5\\t%0, %1, %2, lsr #31\";
40dbec34 8671
8fa3ba89 8672 output_asm_insn (\"cmp\\t%2, %3\", operands);
8673 if (GET_CODE (operands[5]) == AND)
8674 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
8675 else if (GET_CODE (operands[5]) == MINUS)
8676 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
8677 else if (which_alternative != 0)
8678 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8679 return \"%i5%d4\\t%0, %1, #1\";
8680 "
8681 [(set_attr "conds" "clob")
1b7da4ac 8682 (set_attr "length" "12")
8683 (set_attr "type" "multiple")]
8fa3ba89 8684)
9c08d1fa 8685
f7fbdd4a 8686(define_insn "*cond_sub"
9c08d1fa 8687 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8688 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8fa3ba89 8689 (match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 8690 [(match_operand:SI 2 "s_register_operand" "r,r")
8691 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 8692 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8693 "TARGET_ARM"
9c08d1fa 8694 "*
8fa3ba89 8695 output_asm_insn (\"cmp\\t%2, %3\", operands);
8696 if (which_alternative != 0)
8697 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8698 return \"sub%d4\\t%0, %1, #1\";
8699 "
8700 [(set_attr "conds" "clob")
1b7da4ac 8701 (set_attr "length" "8,12")
8702 (set_attr "type" "multiple")]
8fa3ba89 8703)
9c08d1fa 8704
aea4c774 8705(define_insn "*cmp_ite0"
cffb2a26 8706 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 8707 (compare
8708 (if_then_else:SI
8fa3ba89 8709 (match_operator 4 "arm_comparison_operator"
2ff91fec 8710 [(match_operand:SI 0 "s_register_operand"
8711 "l,l,l,r,r,r,r,r,r")
8712 (match_operand:SI 1 "arm_add_operand"
8713 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
8fa3ba89 8714 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 8715 [(match_operand:SI 2 "s_register_operand"
8716 "l,r,r,l,l,r,r,r,r")
8717 (match_operand:SI 3 "arm_add_operand"
8718 "lPy,rI,L,lPy,lPy,rI,rI,L,L")])
aea4c774 8719 (const_int 0))
8720 (const_int 0)))]
2ff91fec 8721 "TARGET_32BIT"
9c08d1fa 8722 "*
aea4c774 8723 {
2ff91fec 8724 static const char * const cmp1[NUM_OF_COND_CMP][2] =
8725 {
8726 {\"cmp%d5\\t%0, %1\",
8727 \"cmp%d4\\t%2, %3\"},
8728 {\"cmn%d5\\t%0, #%n1\",
8729 \"cmp%d4\\t%2, %3\"},
8730 {\"cmp%d5\\t%0, %1\",
8731 \"cmn%d4\\t%2, #%n3\"},
8732 {\"cmn%d5\\t%0, #%n1\",
8733 \"cmn%d4\\t%2, #%n3\"}
8734 };
8735 static const char * const cmp2[NUM_OF_COND_CMP][2] =
8736 {
8737 {\"cmp\\t%2, %3\",
8738 \"cmp\\t%0, %1\"},
8739 {\"cmp\\t%2, %3\",
8740 \"cmn\\t%0, #%n1\"},
8741 {\"cmn\\t%2, #%n3\",
8742 \"cmp\\t%0, %1\"},
8743 {\"cmn\\t%2, #%n3\",
8744 \"cmn\\t%0, #%n1\"}
8745 };
8746 static const char * const ite[2] =
8fa3ba89 8747 {
2ff91fec 8748 \"it\\t%d5\",
8749 \"it\\t%d4\"
8fa3ba89 8750 };
2ff91fec 8751 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
8752 CMP_CMP, CMN_CMP, CMP_CMP,
8753 CMN_CMP, CMP_CMN, CMN_CMN};
8fa3ba89 8754 int swap =
8755 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8756
2ff91fec 8757 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
8758 if (TARGET_THUMB2) {
8759 output_asm_insn (ite[swap], operands);
8760 }
8761 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
8762 return \"\";
8fa3ba89 8763 }"
8764 [(set_attr "conds" "set")
2ff91fec 8765 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
1b7da4ac 8766 (set_attr "type" "multiple")
2ff91fec 8767 (set_attr_alternative "length"
8768 [(const_int 6)
8769 (const_int 8)
8770 (const_int 8)
8771 (const_int 8)
8772 (const_int 8)
8773 (if_then_else (eq_attr "is_thumb" "no")
8774 (const_int 8)
8775 (const_int 10))
8776 (if_then_else (eq_attr "is_thumb" "no")
8777 (const_int 8)
8778 (const_int 10))
8779 (if_then_else (eq_attr "is_thumb" "no")
8780 (const_int 8)
8781 (const_int 10))
8782 (if_then_else (eq_attr "is_thumb" "no")
8783 (const_int 8)
8784 (const_int 10))])]
8fa3ba89 8785)
9c08d1fa 8786
aea4c774 8787(define_insn "*cmp_ite1"
cffb2a26 8788 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 8789 (compare
8790 (if_then_else:SI
8fa3ba89 8791 (match_operator 4 "arm_comparison_operator"
2ff91fec 8792 [(match_operand:SI 0 "s_register_operand"
8793 "l,l,l,r,r,r,r,r,r")
8794 (match_operand:SI 1 "arm_add_operand"
8795 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
8fa3ba89 8796 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 8797 [(match_operand:SI 2 "s_register_operand"
8798 "l,r,r,l,l,r,r,r,r")
8799 (match_operand:SI 3 "arm_add_operand"
8800 "lPy,rI,L,lPy,lPy,rI,rI,L,L")])
aea4c774 8801 (const_int 1))
8802 (const_int 0)))]
2ff91fec 8803 "TARGET_32BIT"
9c08d1fa 8804 "*
9c08d1fa 8805 {
2ff91fec 8806 static const char * const cmp1[NUM_OF_COND_CMP][2] =
8807 {
8808 {\"cmp\\t%0, %1\",
8809 \"cmp\\t%2, %3\"},
8810 {\"cmn\\t%0, #%n1\",
8811 \"cmp\\t%2, %3\"},
8812 {\"cmp\\t%0, %1\",
8813 \"cmn\\t%2, #%n3\"},
8814 {\"cmn\\t%0, #%n1\",
8815 \"cmn\\t%2, #%n3\"}
8816 };
8817 static const char * const cmp2[NUM_OF_COND_CMP][2] =
215b30b3 8818 {
2ff91fec 8819 {\"cmp%d4\\t%2, %3\",
8820 \"cmp%D5\\t%0, %1\"},
8821 {\"cmp%d4\\t%2, %3\",
8822 \"cmn%D5\\t%0, #%n1\"},
8823 {\"cmn%d4\\t%2, #%n3\",
8824 \"cmp%D5\\t%0, %1\"},
8825 {\"cmn%d4\\t%2, #%n3\",
8826 \"cmn%D5\\t%0, #%n1\"}
215b30b3 8827 };
2ff91fec 8828 static const char * const ite[2] =
8829 {
8830 \"it\\t%d4\",
8831 \"it\\t%D5\"
8832 };
8833 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
8834 CMP_CMP, CMN_CMP, CMP_CMP,
8835 CMN_CMP, CMP_CMN, CMN_CMN};
215b30b3 8836 int swap =
8837 comparison_dominates_p (GET_CODE (operands[5]),
8838 reverse_condition (GET_CODE (operands[4])));
8839
2ff91fec 8840 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
8841 if (TARGET_THUMB2) {
8842 output_asm_insn (ite[swap], operands);
8843 }
8844 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
8845 return \"\";
215b30b3 8846 }"
8fa3ba89 8847 [(set_attr "conds" "set")
2ff91fec 8848 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
8849 (set_attr_alternative "length"
8850 [(const_int 6)
8851 (const_int 8)
8852 (const_int 8)
8853 (const_int 8)
8854 (const_int 8)
8855 (if_then_else (eq_attr "is_thumb" "no")
8856 (const_int 8)
8857 (const_int 10))
8858 (if_then_else (eq_attr "is_thumb" "no")
8859 (const_int 8)
8860 (const_int 10))
8861 (if_then_else (eq_attr "is_thumb" "no")
8862 (const_int 8)
8863 (const_int 10))
8864 (if_then_else (eq_attr "is_thumb" "no")
8865 (const_int 8)
1b7da4ac 8866 (const_int 10))])
8867 (set_attr "type" "multiple")]
8fa3ba89 8868)
9c08d1fa 8869
f6c53574 8870(define_insn "*cmp_and"
8871 [(set (match_operand 6 "dominant_cc_register" "")
8872 (compare
8873 (and:SI
8874 (match_operator 4 "arm_comparison_operator"
2ff91fec 8875 [(match_operand:SI 0 "s_register_operand"
8876 "l,l,l,r,r,r,r,r,r")
8877 (match_operand:SI 1 "arm_add_operand"
8878 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
f6c53574 8879 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 8880 [(match_operand:SI 2 "s_register_operand"
8881 "l,r,r,l,l,r,r,r,r")
8882 (match_operand:SI 3 "arm_add_operand"
8883 "lPy,rI,L,lPy,lPy,rI,rI,L,L")]))
f6c53574 8884 (const_int 0)))]
2ff91fec 8885 "TARGET_32BIT"
f6c53574 8886 "*
8887 {
2ff91fec 8888 static const char *const cmp1[NUM_OF_COND_CMP][2] =
f6c53574 8889 {
2ff91fec 8890 {\"cmp%d5\\t%0, %1\",
8891 \"cmp%d4\\t%2, %3\"},
8892 {\"cmn%d5\\t%0, #%n1\",
8893 \"cmp%d4\\t%2, %3\"},
8894 {\"cmp%d5\\t%0, %1\",
8895 \"cmn%d4\\t%2, #%n3\"},
8896 {\"cmn%d5\\t%0, #%n1\",
8897 \"cmn%d4\\t%2, #%n3\"}
f6c53574 8898 };
2ff91fec 8899 static const char *const cmp2[NUM_OF_COND_CMP][2] =
8900 {
8901 {\"cmp\\t%2, %3\",
8902 \"cmp\\t%0, %1\"},
8903 {\"cmp\\t%2, %3\",
8904 \"cmn\\t%0, #%n1\"},
8905 {\"cmn\\t%2, #%n3\",
8906 \"cmp\\t%0, %1\"},
8907 {\"cmn\\t%2, #%n3\",
8908 \"cmn\\t%0, #%n1\"}
8909 };
8910 static const char *const ite[2] =
8911 {
8912 \"it\\t%d5\",
8913 \"it\\t%d4\"
8914 };
8915 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
8916 CMP_CMP, CMN_CMP, CMP_CMP,
8917 CMN_CMP, CMP_CMN, CMN_CMN};
f6c53574 8918 int swap =
8919 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8920
2ff91fec 8921 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
8922 if (TARGET_THUMB2) {
8923 output_asm_insn (ite[swap], operands);
8924 }
8925 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
8926 return \"\";
f6c53574 8927 }"
8928 [(set_attr "conds" "set")
8929 (set_attr "predicable" "no")
2ff91fec 8930 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
8931 (set_attr_alternative "length"
8932 [(const_int 6)
8933 (const_int 8)
8934 (const_int 8)
8935 (const_int 8)
8936 (const_int 8)
8937 (if_then_else (eq_attr "is_thumb" "no")
8938 (const_int 8)
8939 (const_int 10))
8940 (if_then_else (eq_attr "is_thumb" "no")
8941 (const_int 8)
8942 (const_int 10))
8943 (if_then_else (eq_attr "is_thumb" "no")
8944 (const_int 8)
8945 (const_int 10))
8946 (if_then_else (eq_attr "is_thumb" "no")
8947 (const_int 8)
1b7da4ac 8948 (const_int 10))])
8949 (set_attr "type" "multiple")]
f6c53574 8950)
8951
8952(define_insn "*cmp_ior"
8953 [(set (match_operand 6 "dominant_cc_register" "")
8954 (compare
8955 (ior:SI
8956 (match_operator 4 "arm_comparison_operator"
2ff91fec 8957 [(match_operand:SI 0 "s_register_operand"
8958 "l,l,l,r,r,r,r,r,r")
8959 (match_operand:SI 1 "arm_add_operand"
8960 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
f6c53574 8961 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 8962 [(match_operand:SI 2 "s_register_operand"
8963 "l,r,r,l,l,r,r,r,r")
8964 (match_operand:SI 3 "arm_add_operand"
8965 "lPy,rI,L,lPy,lPy,rI,rI,L,L")]))
f6c53574 8966 (const_int 0)))]
2ff91fec 8967 "TARGET_32BIT"
f6c53574 8968 "*
f6c53574 8969 {
2ff91fec 8970 static const char *const cmp1[NUM_OF_COND_CMP][2] =
8971 {
8972 {\"cmp\\t%0, %1\",
8973 \"cmp\\t%2, %3\"},
8974 {\"cmn\\t%0, #%n1\",
8975 \"cmp\\t%2, %3\"},
8976 {\"cmp\\t%0, %1\",
8977 \"cmn\\t%2, #%n3\"},
8978 {\"cmn\\t%0, #%n1\",
8979 \"cmn\\t%2, #%n3\"}
8980 };
8981 static const char *const cmp2[NUM_OF_COND_CMP][2] =
8982 {
8983 {\"cmp%D4\\t%2, %3\",
8984 \"cmp%D5\\t%0, %1\"},
8985 {\"cmp%D4\\t%2, %3\",
8986 \"cmn%D5\\t%0, #%n1\"},
8987 {\"cmn%D4\\t%2, #%n3\",
8988 \"cmp%D5\\t%0, %1\"},
8989 {\"cmn%D4\\t%2, #%n3\",
8990 \"cmn%D5\\t%0, #%n1\"}
8991 };
8992 static const char *const ite[2] =
8993 {
8994 \"it\\t%D4\",
8995 \"it\\t%D5\"
8996 };
8997 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
8998 CMP_CMP, CMN_CMP, CMP_CMP,
8999 CMN_CMP, CMP_CMN, CMN_CMN};
9000 int swap =
9001 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9002
9003 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9004 if (TARGET_THUMB2) {
9005 output_asm_insn (ite[swap], operands);
9006 }
9007 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9008 return \"\";
9009 }
9010 "
f6c53574 9011 [(set_attr "conds" "set")
2ff91fec 9012 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
9013 (set_attr_alternative "length"
9014 [(const_int 6)
9015 (const_int 8)
9016 (const_int 8)
9017 (const_int 8)
9018 (const_int 8)
9019 (if_then_else (eq_attr "is_thumb" "no")
9020 (const_int 8)
9021 (const_int 10))
9022 (if_then_else (eq_attr "is_thumb" "no")
9023 (const_int 8)
9024 (const_int 10))
9025 (if_then_else (eq_attr "is_thumb" "no")
9026 (const_int 8)
9027 (const_int 10))
9028 (if_then_else (eq_attr "is_thumb" "no")
9029 (const_int 8)
1b7da4ac 9030 (const_int 10))])
9031 (set_attr "type" "multiple")]
f6c53574 9032)
9033
3c5afce6 9034(define_insn_and_split "*ior_scc_scc"
fd711051 9035 [(set (match_operand:SI 0 "s_register_operand" "=Ts")
3c5afce6 9036 (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9037 [(match_operand:SI 1 "s_register_operand" "r")
9038 (match_operand:SI 2 "arm_add_operand" "rIL")])
9039 (match_operator:SI 6 "arm_comparison_operator"
9040 [(match_operand:SI 4 "s_register_operand" "r")
9041 (match_operand:SI 5 "arm_add_operand" "rIL")])))
9042 (clobber (reg:CC CC_REGNUM))]
2ff91fec 9043 "TARGET_32BIT
3c5afce6 9044 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
9045 != CCmode)"
9046 "#"
2ff91fec 9047 "TARGET_32BIT && reload_completed"
3c5afce6 9048 [(set (match_dup 7)
9049 (compare
9050 (ior:SI
9051 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9052 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9053 (const_int 0)))
9054 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9055 "operands[7]
9056 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9057 DOM_CC_X_OR_Y),
601f584c 9058 CC_REGNUM);"
9059 [(set_attr "conds" "clob")
1b7da4ac 9060 (set_attr "length" "16")
9061 (set_attr "type" "multiple")]
9062)
601f584c 9063
9064; If the above pattern is followed by a CMP insn, then the compare is
9065; redundant, since we can rework the conditional instruction that follows.
9066(define_insn_and_split "*ior_scc_scc_cmp"
9067 [(set (match_operand 0 "dominant_cc_register" "")
9068 (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9069 [(match_operand:SI 1 "s_register_operand" "r")
9070 (match_operand:SI 2 "arm_add_operand" "rIL")])
9071 (match_operator:SI 6 "arm_comparison_operator"
9072 [(match_operand:SI 4 "s_register_operand" "r")
9073 (match_operand:SI 5 "arm_add_operand" "rIL")]))
9074 (const_int 0)))
fd711051 9075 (set (match_operand:SI 7 "s_register_operand" "=Ts")
601f584c 9076 (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9077 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
2ff91fec 9078 "TARGET_32BIT"
601f584c 9079 "#"
2ff91fec 9080 "TARGET_32BIT && reload_completed"
601f584c 9081 [(set (match_dup 0)
9082 (compare
9083 (ior:SI
9084 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9085 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9086 (const_int 0)))
9087 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9088 ""
9089 [(set_attr "conds" "set")
1b7da4ac 9090 (set_attr "length" "16")
9091 (set_attr "type" "multiple")]
9092)
3c5afce6 9093
9094(define_insn_and_split "*and_scc_scc"
fd711051 9095 [(set (match_operand:SI 0 "s_register_operand" "=Ts")
3c5afce6 9096 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9097 [(match_operand:SI 1 "s_register_operand" "r")
9098 (match_operand:SI 2 "arm_add_operand" "rIL")])
9099 (match_operator:SI 6 "arm_comparison_operator"
9100 [(match_operand:SI 4 "s_register_operand" "r")
9101 (match_operand:SI 5 "arm_add_operand" "rIL")])))
9102 (clobber (reg:CC CC_REGNUM))]
2ff91fec 9103 "TARGET_32BIT
3c5afce6 9104 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9105 != CCmode)"
9106 "#"
2ff91fec 9107 "TARGET_32BIT && reload_completed
601f584c 9108 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9109 != CCmode)"
3c5afce6 9110 [(set (match_dup 7)
9111 (compare
9112 (and:SI
9113 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9114 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9115 (const_int 0)))
9116 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9117 "operands[7]
9118 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9119 DOM_CC_X_AND_Y),
601f584c 9120 CC_REGNUM);"
9121 [(set_attr "conds" "clob")
1b7da4ac 9122 (set_attr "length" "16")
9123 (set_attr "type" "multiple")]
9124)
601f584c 9125
9126; If the above pattern is followed by a CMP insn, then the compare is
9127; redundant, since we can rework the conditional instruction that follows.
9128(define_insn_and_split "*and_scc_scc_cmp"
9129 [(set (match_operand 0 "dominant_cc_register" "")
9130 (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
9131 [(match_operand:SI 1 "s_register_operand" "r")
9132 (match_operand:SI 2 "arm_add_operand" "rIL")])
9133 (match_operator:SI 6 "arm_comparison_operator"
9134 [(match_operand:SI 4 "s_register_operand" "r")
9135 (match_operand:SI 5 "arm_add_operand" "rIL")]))
9136 (const_int 0)))
fd711051 9137 (set (match_operand:SI 7 "s_register_operand" "=Ts")
601f584c 9138 (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9139 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
2ff91fec 9140 "TARGET_32BIT"
601f584c 9141 "#"
2ff91fec 9142 "TARGET_32BIT && reload_completed"
601f584c 9143 [(set (match_dup 0)
9144 (compare
9145 (and:SI
9146 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9147 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9148 (const_int 0)))
9149 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9150 ""
9151 [(set_attr "conds" "set")
1b7da4ac 9152 (set_attr "length" "16")
9153 (set_attr "type" "multiple")]
9154)
601f584c 9155
9156;; If there is no dominance in the comparison, then we can still save an
9157;; instruction in the AND case, since we can know that the second compare
9158;; need only zero the value if false (if true, then the value is already
9159;; correct).
9160(define_insn_and_split "*and_scc_scc_nodom"
fd711051 9161 [(set (match_operand:SI 0 "s_register_operand" "=&Ts,&Ts,&Ts")
601f584c 9162 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9163 [(match_operand:SI 1 "s_register_operand" "r,r,0")
9164 (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
9165 (match_operator:SI 6 "arm_comparison_operator"
9166 [(match_operand:SI 4 "s_register_operand" "r,r,r")
9167 (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
9168 (clobber (reg:CC CC_REGNUM))]
2ff91fec 9169 "TARGET_32BIT
601f584c 9170 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9171 == CCmode)"
9172 "#"
2ff91fec 9173 "TARGET_32BIT && reload_completed"
601f584c 9174 [(parallel [(set (match_dup 0)
9175 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
9176 (clobber (reg:CC CC_REGNUM))])
9177 (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
9178 (set (match_dup 0)
9179 (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
9180 (match_dup 0)
9181 (const_int 0)))]
9182 "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
9183 operands[4], operands[5]),
9184 CC_REGNUM);
9185 operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
9186 operands[5]);"
9187 [(set_attr "conds" "clob")
1b7da4ac 9188 (set_attr "length" "20")
9189 (set_attr "type" "multiple")]
9190)
3c5afce6 9191
3a0bdee0 9192(define_split
9193 [(set (reg:CC_NOOV CC_REGNUM)
9194 (compare:CC_NOOV (ior:SI
9195 (and:SI (match_operand:SI 0 "s_register_operand" "")
9196 (const_int 1))
b0694be0 9197 (match_operator:SI 1 "arm_comparison_operator"
3a0bdee0 9198 [(match_operand:SI 2 "s_register_operand" "")
9199 (match_operand:SI 3 "arm_add_operand" "")]))
9200 (const_int 0)))
9201 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9202 "TARGET_ARM"
9203 [(set (match_dup 4)
9204 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9205 (match_dup 0)))
9206 (set (reg:CC_NOOV CC_REGNUM)
9207 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9208 (const_int 0)))]
9209 "")
9210
9211(define_split
9212 [(set (reg:CC_NOOV CC_REGNUM)
9213 (compare:CC_NOOV (ior:SI
b0694be0 9214 (match_operator:SI 1 "arm_comparison_operator"
3a0bdee0 9215 [(match_operand:SI 2 "s_register_operand" "")
9216 (match_operand:SI 3 "arm_add_operand" "")])
9217 (and:SI (match_operand:SI 0 "s_register_operand" "")
9218 (const_int 1)))
9219 (const_int 0)))
9220 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9221 "TARGET_ARM"
9222 [(set (match_dup 4)
9223 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9224 (match_dup 0)))
9225 (set (reg:CC_NOOV CC_REGNUM)
9226 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9227 (const_int 0)))]
9228 "")
25f905c2 9229;; ??? The conditional patterns above need checking for Thumb-2 usefulness
3a0bdee0 9230
190efb17 9231(define_insn_and_split "*negscc"
9c08d1fa 9232 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9233 (neg:SI (match_operator 3 "arm_comparison_operator"
9c08d1fa 9234 [(match_operand:SI 1 "s_register_operand" "r")
9235 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
bd5b4116 9236 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9237 "TARGET_ARM"
190efb17 9238 "#"
9239 "&& reload_completed"
9240 [(const_int 0)]
9241 {
9242 rtx cc_reg = gen_rtx_REG (CCmode, CC_REGNUM);
e2348bcb 9243
190efb17 9244 if (GET_CODE (operands[3]) == LT && operands[2] == const0_rtx)
9245 {
9246 /* Emit mov\\t%0, %1, asr #31 */
9247 emit_insn (gen_rtx_SET (VOIDmode,
9248 operands[0],
9249 gen_rtx_ASHIFTRT (SImode,
9250 operands[1],
9251 GEN_INT (31))));
9252 DONE;
9253 }
9254 else if (GET_CODE (operands[3]) == NE)
9255 {
9256 /* Emit subs\\t%0, %1, %2\;mvnne\\t%0, #0 */
9257 if (CONST_INT_P (operands[2]))
9258 emit_insn (gen_cmpsi2_addneg (operands[0], operands[1], operands[2],
9259 GEN_INT (- INTVAL (operands[2]))));
9260 else
9261 emit_insn (gen_subsi3_compare (operands[0], operands[1], operands[2]));
9262
9263 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
9264 gen_rtx_NE (SImode,
9265 cc_reg,
9266 const0_rtx),
9267 gen_rtx_SET (SImode,
9268 operands[0],
9269 GEN_INT (~0))));
9270 DONE;
9271 }
9272 else
9273 {
9274 /* Emit: cmp\\t%1, %2\;mov%D3\\t%0, #0\;mvn%d3\\t%0, #0 */
9275 emit_insn (gen_rtx_SET (VOIDmode,
9276 cc_reg,
9277 gen_rtx_COMPARE (CCmode, operands[1], operands[2])));
9278 enum rtx_code rc = GET_CODE (operands[3]);
9279
9280 rc = reverse_condition (rc);
9281 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
9282 gen_rtx_fmt_ee (rc,
9283 VOIDmode,
9284 cc_reg,
9285 const0_rtx),
9286 gen_rtx_SET (VOIDmode, operands[0], const0_rtx)));
9287 rc = GET_CODE (operands[3]);
9288 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
9289 gen_rtx_fmt_ee (rc,
9290 VOIDmode,
9291 cc_reg,
9292 const0_rtx),
9293 gen_rtx_SET (VOIDmode,
9294 operands[0],
9295 GEN_INT (~0))));
9296 DONE;
9297 }
9298 FAIL;
9299 }
8fa3ba89 9300 [(set_attr "conds" "clob")
1b7da4ac 9301 (set_attr "length" "12")
9302 (set_attr "type" "multiple")]
8fa3ba89 9303)
9c08d1fa 9304
90404b57 9305(define_insn_and_split "movcond_addsi"
9306 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r")
9307 (if_then_else:SI
9308 (match_operator 5 "comparison_operator"
9309 [(plus:SI (match_operand:SI 3 "s_register_operand" "r,r,r")
9310 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL"))
9311 (const_int 0)])
9312 (match_operand:SI 1 "arm_rhs_operand" "rI,rPy,r")
9313 (match_operand:SI 2 "arm_rhs_operand" "rI,rPy,r")))
9314 (clobber (reg:CC CC_REGNUM))]
9315 "TARGET_32BIT"
9316 "#"
9317 "&& reload_completed"
9318 [(set (reg:CC_NOOV CC_REGNUM)
9319 (compare:CC_NOOV
9320 (plus:SI (match_dup 3)
9321 (match_dup 4))
9322 (const_int 0)))
9323 (set (match_dup 0) (match_dup 1))
9324 (cond_exec (match_dup 6)
9325 (set (match_dup 0) (match_dup 2)))]
9326 "
9327 {
3754d046 9328 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[5]),
90404b57 9329 operands[3], operands[4]);
9330 enum rtx_code rc = GET_CODE (operands[5]);
90404b57 9331 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9332 gcc_assert (!(mode == CCFPmode || mode == CCFPEmode));
4d01ce2f 9333 if (REGNO (operands[2]) != REGNO (operands[0]))
9334 rc = reverse_condition (rc);
f145bcba 9335 else
9336 std::swap (operands[1], operands[2]);
90404b57 9337
9338 operands[6] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9339 }
9340 "
9341 [(set_attr "conds" "clob")
1b7da4ac 9342 (set_attr "enabled_for_depr_it" "no,yes,yes")
9343 (set_attr "type" "multiple")]
90404b57 9344)
9345
9c08d1fa 9346(define_insn "movcond"
9347 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 9348 (if_then_else:SI
8fa3ba89 9349 (match_operator 5 "arm_comparison_operator"
5565501b 9350 [(match_operand:SI 3 "s_register_operand" "r,r,r")
9351 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
9352 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9353 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 9354 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9355 "TARGET_ARM"
9c08d1fa 9356 "*
9357 if (GET_CODE (operands[5]) == LT
9358 && (operands[4] == const0_rtx))
9359 {
0438d37f 9360 if (which_alternative != 1 && REG_P (operands[1]))
9c08d1fa 9361 {
9c08d1fa 9362 if (operands[2] == const0_rtx)
e2348bcb 9363 return \"and\\t%0, %1, %3, asr #31\";
9364 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
9c08d1fa 9365 }
0438d37f 9366 else if (which_alternative != 0 && REG_P (operands[2]))
9c08d1fa 9367 {
9c08d1fa 9368 if (operands[1] == const0_rtx)
e2348bcb 9369 return \"bic\\t%0, %2, %3, asr #31\";
9370 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
9c08d1fa 9371 }
9372 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 9373 are constants. */
9c08d1fa 9374 }
e2348bcb 9375
9c08d1fa 9376 if (GET_CODE (operands[5]) == GE
9377 && (operands[4] == const0_rtx))
9378 {
0438d37f 9379 if (which_alternative != 1 && REG_P (operands[1]))
9c08d1fa 9380 {
9c08d1fa 9381 if (operands[2] == const0_rtx)
e2348bcb 9382 return \"bic\\t%0, %1, %3, asr #31\";
9383 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
9c08d1fa 9384 }
0438d37f 9385 else if (which_alternative != 0 && REG_P (operands[2]))
9c08d1fa 9386 {
9c08d1fa 9387 if (operands[1] == const0_rtx)
e2348bcb 9388 return \"and\\t%0, %2, %3, asr #31\";
9389 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
9c08d1fa 9390 }
9391 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 9392 are constants. */
9c08d1fa 9393 }
0438d37f 9394 if (CONST_INT_P (operands[4])
9c08d1fa 9395 && !const_ok_for_arm (INTVAL (operands[4])))
e2348bcb 9396 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
9c08d1fa 9397 else
e2348bcb 9398 output_asm_insn (\"cmp\\t%3, %4\", operands);
9c08d1fa 9399 if (which_alternative != 0)
e2348bcb 9400 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
9c08d1fa 9401 if (which_alternative != 1)
e2348bcb 9402 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
9c08d1fa 9403 return \"\";
215b30b3 9404 "
8fa3ba89 9405 [(set_attr "conds" "clob")
1b7da4ac 9406 (set_attr "length" "8,8,12")
9407 (set_attr "type" "multiple")]
8fa3ba89 9408)
9c08d1fa 9409
25f905c2 9410;; ??? The patterns below need checking for Thumb-2 usefulness.
9411
8a18b90c 9412(define_insn "*ifcompare_plus_move"
9413 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9414 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 9415 [(match_operand:SI 4 "s_register_operand" "r,r")
9416 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9417 (plus:SI
9418 (match_operand:SI 2 "s_register_operand" "r,r")
9419 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
129a2fe4 9420 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 9421 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9422 "TARGET_ARM"
8a18b90c 9423 "#"
8fa3ba89 9424 [(set_attr "conds" "clob")
1b7da4ac 9425 (set_attr "length" "8,12")
9426 (set_attr "type" "multiple")]
8fa3ba89 9427)
8a18b90c 9428
9429(define_insn "*if_plus_move"
129a2fe4 9430 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 9431 (if_then_else:SI
8fa3ba89 9432 (match_operator 4 "arm_comparison_operator"
8a18b90c 9433 [(match_operand 5 "cc_register" "") (const_int 0)])
9434 (plus:SI
129a2fe4 9435 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9436 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
9437 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
cffb2a26 9438 "TARGET_ARM"
8a18b90c 9439 "@
9440 add%d4\\t%0, %2, %3
9441 sub%d4\\t%0, %2, #%n3
9442 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
129a2fe4 9443 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8fa3ba89 9444 [(set_attr "conds" "use")
9445 (set_attr "length" "4,4,8,8")
65f68e55 9446 (set_attr_alternative "type"
9447 [(if_then_else (match_operand 3 "const_int_operand" "")
d82e788e 9448 (const_string "alu_imm" )
112eda6f 9449 (const_string "alu_sreg"))
d82e788e 9450 (const_string "alu_imm")
112eda6f 9451 (const_string "alu_sreg")
9452 (const_string "alu_sreg")])]
8fa3ba89 9453)
8a18b90c 9454
9455(define_insn "*ifcompare_move_plus"
5565501b 9456 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9457 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 9458 [(match_operand:SI 4 "s_register_operand" "r,r")
9459 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 9460 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 9461 (plus:SI
9462 (match_operand:SI 2 "s_register_operand" "r,r")
9463 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
bd5b4116 9464 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9465 "TARGET_ARM"
8a18b90c 9466 "#"
8fa3ba89 9467 [(set_attr "conds" "clob")
1b7da4ac 9468 (set_attr "length" "8,12")
9469 (set_attr "type" "multiple")]
8fa3ba89 9470)
8a18b90c 9471
9472(define_insn "*if_move_plus"
129a2fe4 9473 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 9474 (if_then_else:SI
8fa3ba89 9475 (match_operator 4 "arm_comparison_operator"
8a18b90c 9476 [(match_operand 5 "cc_register" "") (const_int 0)])
129a2fe4 9477 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8a18b90c 9478 (plus:SI
129a2fe4 9479 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9480 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
cffb2a26 9481 "TARGET_ARM"
8a18b90c 9482 "@
9483 add%D4\\t%0, %2, %3
9484 sub%D4\\t%0, %2, #%n3
9485 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
129a2fe4 9486 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8fa3ba89 9487 [(set_attr "conds" "use")
9488 (set_attr "length" "4,4,8,8")
112eda6f 9489 (set_attr "type" "alu_sreg,alu_imm,multiple,multiple")]
8fa3ba89 9490)
8a18b90c 9491
9492(define_insn "*ifcompare_arith_arith"
9493 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9494 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8a18b90c 9495 [(match_operand:SI 5 "s_register_operand" "r")
9496 (match_operand:SI 6 "arm_add_operand" "rIL")])
9c08d1fa 9497 (match_operator:SI 8 "shiftable_operator"
8a18b90c 9498 [(match_operand:SI 1 "s_register_operand" "r")
9499 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9c08d1fa 9500 (match_operator:SI 7 "shiftable_operator"
8a18b90c 9501 [(match_operand:SI 3 "s_register_operand" "r")
9502 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
bd5b4116 9503 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9504 "TARGET_ARM"
8a18b90c 9505 "#"
8fa3ba89 9506 [(set_attr "conds" "clob")
1b7da4ac 9507 (set_attr "length" "12")
9508 (set_attr "type" "multiple")]
8fa3ba89 9509)
9c08d1fa 9510
8a18b90c 9511(define_insn "*if_arith_arith"
9512 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9513 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8a18b90c 9514 [(match_operand 8 "cc_register" "") (const_int 0)])
9515 (match_operator:SI 6 "shiftable_operator"
9516 [(match_operand:SI 1 "s_register_operand" "r")
9517 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9518 (match_operator:SI 7 "shiftable_operator"
9519 [(match_operand:SI 3 "s_register_operand" "r")
9520 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
cffb2a26 9521 "TARGET_ARM"
8a18b90c 9522 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8fa3ba89 9523 [(set_attr "conds" "use")
1b7da4ac 9524 (set_attr "length" "8")
9525 (set_attr "type" "multiple")]
8fa3ba89 9526)
8a18b90c 9527
f7fbdd4a 9528(define_insn "*ifcompare_arith_move"
9c08d1fa 9529 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9530 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 9531 [(match_operand:SI 2 "s_register_operand" "r,r")
5565501b 9532 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
9c08d1fa 9533 (match_operator:SI 7 "shiftable_operator"
9534 [(match_operand:SI 4 "s_register_operand" "r,r")
9535 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
129a2fe4 9536 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 9537 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9538 "TARGET_ARM"
9c08d1fa 9539 "*
9c08d1fa 9540 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 9541 the conditional operator is LT or GE and we are comparing against zero and
674a8f0b 9542 everything is in registers then we can do this in two instructions. */
9c08d1fa 9543 if (operands[3] == const0_rtx
9544 && GET_CODE (operands[7]) != AND
0438d37f 9545 && REG_P (operands[5])
9546 && REG_P (operands[1])
9c08d1fa 9547 && REGNO (operands[1]) == REGNO (operands[4])
9548 && REGNO (operands[4]) != REGNO (operands[0]))
9549 {
9550 if (GET_CODE (operands[6]) == LT)
40dbec34 9551 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 9552 else if (GET_CODE (operands[6]) == GE)
40dbec34 9553 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 9554 }
0438d37f 9555 if (CONST_INT_P (operands[3])
9c08d1fa 9556 && !const_ok_for_arm (INTVAL (operands[3])))
e2348bcb 9557 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
9c08d1fa 9558 else
e2348bcb 9559 output_asm_insn (\"cmp\\t%2, %3\", operands);
40dbec34 9560 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
9c08d1fa 9561 if (which_alternative != 0)
129a2fe4 9562 return \"mov%D6\\t%0, %1\";
9c08d1fa 9563 return \"\";
215b30b3 9564 "
8fa3ba89 9565 [(set_attr "conds" "clob")
1b7da4ac 9566 (set_attr "length" "8,12")
9567 (set_attr "type" "multiple")]
8fa3ba89 9568)
9c08d1fa 9569
8a18b90c 9570(define_insn "*if_arith_move"
129a2fe4 9571 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9572 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8a18b90c 9573 [(match_operand 6 "cc_register" "") (const_int 0)])
9574 (match_operator:SI 5 "shiftable_operator"
129a2fe4 9575 [(match_operand:SI 2 "s_register_operand" "r,r")
9576 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
9577 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
cffb2a26 9578 "TARGET_ARM"
8a18b90c 9579 "@
9580 %I5%d4\\t%0, %2, %3
129a2fe4 9581 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8fa3ba89 9582 [(set_attr "conds" "use")
9583 (set_attr "length" "4,8")
1b7da4ac 9584 (set_attr "type" "alu_shift_reg,multiple")]
8fa3ba89 9585)
8a18b90c 9586
f7fbdd4a 9587(define_insn "*ifcompare_move_arith"
9c08d1fa 9588 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9589 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 9590 [(match_operand:SI 4 "s_register_operand" "r,r")
5565501b 9591 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 9592 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9c08d1fa 9593 (match_operator:SI 7 "shiftable_operator"
9594 [(match_operand:SI 2 "s_register_operand" "r,r")
9595 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 9596 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9597 "TARGET_ARM"
9c08d1fa 9598 "*
9c08d1fa 9599 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 9600 the conditional operator is LT or GE and we are comparing against zero and
9c08d1fa 9601 everything is in registers then we can do this in two instructions */
9602 if (operands[5] == const0_rtx
9603 && GET_CODE (operands[7]) != AND
0438d37f 9604 && REG_P (operands[3])
9605 && REG_P (operands[1])
9c08d1fa 9606 && REGNO (operands[1]) == REGNO (operands[2])
9607 && REGNO (operands[2]) != REGNO (operands[0]))
9608 {
9609 if (GET_CODE (operands[6]) == GE)
40dbec34 9610 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 9611 else if (GET_CODE (operands[6]) == LT)
40dbec34 9612 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 9613 }
40dbec34 9614
0438d37f 9615 if (CONST_INT_P (operands[5])
9c08d1fa 9616 && !const_ok_for_arm (INTVAL (operands[5])))
e2348bcb 9617 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
9c08d1fa 9618 else
e2348bcb 9619 output_asm_insn (\"cmp\\t%4, %5\", operands);
40dbec34 9620
9c08d1fa 9621 if (which_alternative != 0)
129a2fe4 9622 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
40dbec34 9623 return \"%I7%D6\\t%0, %2, %3\";
215b30b3 9624 "
8fa3ba89 9625 [(set_attr "conds" "clob")
1b7da4ac 9626 (set_attr "length" "8,12")
9627 (set_attr "type" "multiple")]
8fa3ba89 9628)
9c08d1fa 9629
8a18b90c 9630(define_insn "*if_move_arith"
129a2fe4 9631 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9632 (if_then_else:SI
8fa3ba89 9633 (match_operator 4 "arm_comparison_operator"
8a18b90c 9634 [(match_operand 6 "cc_register" "") (const_int 0)])
129a2fe4 9635 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 9636 (match_operator:SI 5 "shiftable_operator"
129a2fe4 9637 [(match_operand:SI 2 "s_register_operand" "r,r")
9638 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
cffb2a26 9639 "TARGET_ARM"
8a18b90c 9640 "@
9641 %I5%D4\\t%0, %2, %3
129a2fe4 9642 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
8fa3ba89 9643 [(set_attr "conds" "use")
9644 (set_attr "length" "4,8")
1b7da4ac 9645 (set_attr "type" "alu_shift_reg,multiple")]
8fa3ba89 9646)
8a18b90c 9647
9648(define_insn "*ifcompare_move_not"
9c08d1fa 9649 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9650 (if_then_else:SI
8fa3ba89 9651 (match_operator 5 "arm_comparison_operator"
8a18b90c 9652 [(match_operand:SI 3 "s_register_operand" "r,r")
9653 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9654 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9655 (not:SI
9656 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 9657 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9658 "TARGET_ARM"
8a18b90c 9659 "#"
8fa3ba89 9660 [(set_attr "conds" "clob")
1b7da4ac 9661 (set_attr "length" "8,12")
9662 (set_attr "type" "multiple")]
8fa3ba89 9663)
9c08d1fa 9664
8a18b90c 9665(define_insn "*if_move_not"
9666 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9667 (if_then_else:SI
8fa3ba89 9668 (match_operator 4 "arm_comparison_operator"
8a18b90c 9669 [(match_operand 3 "cc_register" "") (const_int 0)])
9670 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9671 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
cffb2a26 9672 "TARGET_ARM"
8a18b90c 9673 "@
9674 mvn%D4\\t%0, %2
9675 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
9676 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
8fa3ba89 9677 [(set_attr "conds" "use")
1aed5204 9678 (set_attr "type" "mvn_reg")
1b7da4ac 9679 (set_attr "length" "4,8,8")
9680 (set_attr "type" "mvn_reg,multiple,multiple")]
8fa3ba89 9681)
8a18b90c 9682
9683(define_insn "*ifcompare_not_move"
9c08d1fa 9684 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9685 (if_then_else:SI
8fa3ba89 9686 (match_operator 5 "arm_comparison_operator"
8a18b90c 9687 [(match_operand:SI 3 "s_register_operand" "r,r")
9688 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9689 (not:SI
9690 (match_operand:SI 2 "s_register_operand" "r,r"))
9691 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 9692 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9693 "TARGET_ARM"
8a18b90c 9694 "#"
8fa3ba89 9695 [(set_attr "conds" "clob")
1b7da4ac 9696 (set_attr "length" "8,12")
9697 (set_attr "type" "multiple")]
8fa3ba89 9698)
9c08d1fa 9699
8a18b90c 9700(define_insn "*if_not_move"
9701 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9702 (if_then_else:SI
8fa3ba89 9703 (match_operator 4 "arm_comparison_operator"
8a18b90c 9704 [(match_operand 3 "cc_register" "") (const_int 0)])
9705 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9706 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 9707 "TARGET_ARM"
8a18b90c 9708 "@
9709 mvn%d4\\t%0, %2
9710 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
9711 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
8fa3ba89 9712 [(set_attr "conds" "use")
1b7da4ac 9713 (set_attr "type" "mvn_reg,multiple,multiple")
8fa3ba89 9714 (set_attr "length" "4,8,8")]
9715)
8a18b90c 9716
9717(define_insn "*ifcompare_shift_move"
9c08d1fa 9718 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9719 (if_then_else:SI
8fa3ba89 9720 (match_operator 6 "arm_comparison_operator"
8a18b90c 9721 [(match_operand:SI 4 "s_register_operand" "r,r")
9722 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9723 (match_operator:SI 7 "shift_operator"
9724 [(match_operand:SI 2 "s_register_operand" "r,r")
9725 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
9726 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 9727 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9728 "TARGET_ARM"
9c08d1fa 9729 "#"
8fa3ba89 9730 [(set_attr "conds" "clob")
1b7da4ac 9731 (set_attr "length" "8,12")
9732 (set_attr "type" "multiple")]
8fa3ba89 9733)
9c08d1fa 9734
8a18b90c 9735(define_insn "*if_shift_move"
9736 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9737 (if_then_else:SI
8fa3ba89 9738 (match_operator 5 "arm_comparison_operator"
8a18b90c 9739 [(match_operand 6 "cc_register" "") (const_int 0)])
9740 (match_operator:SI 4 "shift_operator"
9741 [(match_operand:SI 2 "s_register_operand" "r,r,r")
9742 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
9743 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 9744 "TARGET_ARM"
5565501b 9745 "@
8a18b90c 9746 mov%d5\\t%0, %2%S4
9747 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
9748 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
8fa3ba89 9749 [(set_attr "conds" "use")
331beb1a 9750 (set_attr "shift" "2")
a2cd141b 9751 (set_attr "length" "4,8,8")
1b7da4ac 9752 (set_attr "type" "mov_shift_reg,multiple,multiple")]
8fa3ba89 9753)
5565501b 9754
8a18b90c 9755(define_insn "*ifcompare_move_shift"
9756 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 9757 (if_then_else:SI
8fa3ba89 9758 (match_operator 6 "arm_comparison_operator"
8a18b90c 9759 [(match_operand:SI 4 "s_register_operand" "r,r")
9760 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9761 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
5565501b 9762 (match_operator:SI 7 "shift_operator"
8a18b90c 9763 [(match_operand:SI 2 "s_register_operand" "r,r")
9764 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
bd5b4116 9765 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9766 "TARGET_ARM"
8a18b90c 9767 "#"
8fa3ba89 9768 [(set_attr "conds" "clob")
1b7da4ac 9769 (set_attr "length" "8,12")
9770 (set_attr "type" "multiple")]
8fa3ba89 9771)
5565501b 9772
8a18b90c 9773(define_insn "*if_move_shift"
9774 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 9775 (if_then_else:SI
8fa3ba89 9776 (match_operator 5 "arm_comparison_operator"
8a18b90c 9777 [(match_operand 6 "cc_register" "") (const_int 0)])
9778 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9779 (match_operator:SI 4 "shift_operator"
9780 [(match_operand:SI 2 "s_register_operand" "r,r,r")
9781 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
cffb2a26 9782 "TARGET_ARM"
5565501b 9783 "@
8a18b90c 9784 mov%D5\\t%0, %2%S4
9785 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
9786 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
8fa3ba89 9787 [(set_attr "conds" "use")
331beb1a 9788 (set_attr "shift" "2")
a2cd141b 9789 (set_attr "length" "4,8,8")
1b7da4ac 9790 (set_attr "type" "mov_shift_reg,multiple,multiple")]
8fa3ba89 9791)
9c08d1fa 9792
f7fbdd4a 9793(define_insn "*ifcompare_shift_shift"
8a18b90c 9794 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 9795 (if_then_else:SI
8fa3ba89 9796 (match_operator 7 "arm_comparison_operator"
8a18b90c 9797 [(match_operand:SI 5 "s_register_operand" "r")
9798 (match_operand:SI 6 "arm_add_operand" "rIL")])
5565501b 9799 (match_operator:SI 8 "shift_operator"
8a18b90c 9800 [(match_operand:SI 1 "s_register_operand" "r")
9801 (match_operand:SI 2 "arm_rhs_operand" "rM")])
5565501b 9802 (match_operator:SI 9 "shift_operator"
8a18b90c 9803 [(match_operand:SI 3 "s_register_operand" "r")
9804 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
bd5b4116 9805 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9806 "TARGET_ARM"
8a18b90c 9807 "#"
8fa3ba89 9808 [(set_attr "conds" "clob")
1b7da4ac 9809 (set_attr "length" "12")
9810 (set_attr "type" "multiple")]
8fa3ba89 9811)
9c08d1fa 9812
8a18b90c 9813(define_insn "*if_shift_shift"
9814 [(set (match_operand:SI 0 "s_register_operand" "=r")
9815 (if_then_else:SI
8fa3ba89 9816 (match_operator 5 "arm_comparison_operator"
8a18b90c 9817 [(match_operand 8 "cc_register" "") (const_int 0)])
9818 (match_operator:SI 6 "shift_operator"
9819 [(match_operand:SI 1 "s_register_operand" "r")
9820 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9821 (match_operator:SI 7 "shift_operator"
9822 [(match_operand:SI 3 "s_register_operand" "r")
9823 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
cffb2a26 9824 "TARGET_ARM"
8a18b90c 9825 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
8fa3ba89 9826 [(set_attr "conds" "use")
331beb1a 9827 (set_attr "shift" "1")
a2cd141b 9828 (set_attr "length" "8")
9829 (set (attr "type") (if_then_else
9830 (and (match_operand 2 "const_int_operand" "")
9831 (match_operand 4 "const_int_operand" ""))
1aed5204 9832 (const_string "mov_shift")
9833 (const_string "mov_shift_reg")))]
8fa3ba89 9834)
8a18b90c 9835
f7fbdd4a 9836(define_insn "*ifcompare_not_arith"
8a18b90c 9837 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 9838 (if_then_else:SI
8fa3ba89 9839 (match_operator 6 "arm_comparison_operator"
8a18b90c 9840 [(match_operand:SI 4 "s_register_operand" "r")
9841 (match_operand:SI 5 "arm_add_operand" "rIL")])
9842 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5565501b 9843 (match_operator:SI 7 "shiftable_operator"
8a18b90c 9844 [(match_operand:SI 2 "s_register_operand" "r")
9845 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
bd5b4116 9846 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9847 "TARGET_ARM"
8a18b90c 9848 "#"
8fa3ba89 9849 [(set_attr "conds" "clob")
1b7da4ac 9850 (set_attr "length" "12")
9851 (set_attr "type" "multiple")]
8fa3ba89 9852)
9c08d1fa 9853
8a18b90c 9854(define_insn "*if_not_arith"
9855 [(set (match_operand:SI 0 "s_register_operand" "=r")
9856 (if_then_else:SI
8fa3ba89 9857 (match_operator 5 "arm_comparison_operator"
8a18b90c 9858 [(match_operand 4 "cc_register" "") (const_int 0)])
9859 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9860 (match_operator:SI 6 "shiftable_operator"
9861 [(match_operand:SI 2 "s_register_operand" "r")
9862 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
cffb2a26 9863 "TARGET_ARM"
8a18b90c 9864 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
8fa3ba89 9865 [(set_attr "conds" "use")
1aed5204 9866 (set_attr "type" "mvn_reg")
8fa3ba89 9867 (set_attr "length" "8")]
9868)
8a18b90c 9869
9870(define_insn "*ifcompare_arith_not"
9871 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 9872 (if_then_else:SI
8fa3ba89 9873 (match_operator 6 "arm_comparison_operator"
8a18b90c 9874 [(match_operand:SI 4 "s_register_operand" "r")
9875 (match_operand:SI 5 "arm_add_operand" "rIL")])
5565501b 9876 (match_operator:SI 7 "shiftable_operator"
8a18b90c 9877 [(match_operand:SI 2 "s_register_operand" "r")
9878 (match_operand:SI 3 "arm_rhs_operand" "rI")])
9879 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
bd5b4116 9880 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9881 "TARGET_ARM"
8a18b90c 9882 "#"
8fa3ba89 9883 [(set_attr "conds" "clob")
1b7da4ac 9884 (set_attr "length" "12")
9885 (set_attr "type" "multiple")]
8fa3ba89 9886)
9c08d1fa 9887
8a18b90c 9888(define_insn "*if_arith_not"
9889 [(set (match_operand:SI 0 "s_register_operand" "=r")
9890 (if_then_else:SI
8fa3ba89 9891 (match_operator 5 "arm_comparison_operator"
8a18b90c 9892 [(match_operand 4 "cc_register" "") (const_int 0)])
9893 (match_operator:SI 6 "shiftable_operator"
9894 [(match_operand:SI 2 "s_register_operand" "r")
9895 (match_operand:SI 3 "arm_rhs_operand" "rI")])
9896 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
cffb2a26 9897 "TARGET_ARM"
8a18b90c 9898 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
8fa3ba89 9899 [(set_attr "conds" "use")
1b7da4ac 9900 (set_attr "type" "multiple")
8fa3ba89 9901 (set_attr "length" "8")]
9902)
8a18b90c 9903
f7fbdd4a 9904(define_insn "*ifcompare_neg_move"
8a18b90c 9905 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 9906 (if_then_else:SI
8fa3ba89 9907 (match_operator 5 "arm_comparison_operator"
8a18b90c 9908 [(match_operand:SI 3 "s_register_operand" "r,r")
9909 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9910 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
9911 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 9912 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9913 "TARGET_ARM"
8a18b90c 9914 "#"
8fa3ba89 9915 [(set_attr "conds" "clob")
1b7da4ac 9916 (set_attr "length" "8,12")
9917 (set_attr "type" "multiple")]
8fa3ba89 9918)
8a18b90c 9919
9920(define_insn "*if_neg_move"
9921 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9922 (if_then_else:SI
8fa3ba89 9923 (match_operator 4 "arm_comparison_operator"
8a18b90c 9924 [(match_operand 3 "cc_register" "") (const_int 0)])
9925 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9926 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 9927 "TARGET_ARM"
8a18b90c 9928 "@
9929 rsb%d4\\t%0, %2, #0
9930 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
9931 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
8fa3ba89 9932 [(set_attr "conds" "use")
1b7da4ac 9933 (set_attr "length" "4,8,8")
9934 (set_attr "type" "logic_shift_imm,multiple,multiple")]
8fa3ba89 9935)
9c08d1fa 9936
f7fbdd4a 9937(define_insn "*ifcompare_move_neg"
8a18b90c 9938 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 9939 (if_then_else:SI
8fa3ba89 9940 (match_operator 5 "arm_comparison_operator"
8a18b90c 9941 [(match_operand:SI 3 "s_register_operand" "r,r")
9942 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9943 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9944 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 9945 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9946 "TARGET_ARM"
8a18b90c 9947 "#"
8fa3ba89 9948 [(set_attr "conds" "clob")
1b7da4ac 9949 (set_attr "length" "8,12")
9950 (set_attr "type" "multiple")]
8fa3ba89 9951)
8a18b90c 9952
9953(define_insn "*if_move_neg"
9954 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9955 (if_then_else:SI
8fa3ba89 9956 (match_operator 4 "arm_comparison_operator"
8a18b90c 9957 [(match_operand 3 "cc_register" "") (const_int 0)])
9958 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9959 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
cffb2a26 9960 "TARGET_ARM"
8a18b90c 9961 "@
9962 rsb%D4\\t%0, %2, #0
9963 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
9964 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
0d66636f 9965 [(set_attr "conds" "use")
1b7da4ac 9966 (set_attr "length" "4,8,8")
9967 (set_attr "type" "logic_shift_imm,multiple,multiple")]
0d66636f 9968)
9c08d1fa 9969
f7fbdd4a 9970(define_insn "*arith_adjacentmem"
9c08d1fa 9971 [(set (match_operand:SI 0 "s_register_operand" "=r")
9972 (match_operator:SI 1 "shiftable_operator"
9973 [(match_operand:SI 2 "memory_operand" "m")
9974 (match_operand:SI 3 "memory_operand" "m")]))
9975 (clobber (match_scratch:SI 4 "=r"))]
cffb2a26 9976 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9c08d1fa 9977 "*
215b30b3 9978 {
9979 rtx ldm[3];
9980 rtx arith[4];
94dee231 9981 rtx base_reg;
9982 HOST_WIDE_INT val1 = 0, val2 = 0;
9c08d1fa 9983
215b30b3 9984 if (REGNO (operands[0]) > REGNO (operands[4]))
9985 {
9986 ldm[1] = operands[4];
9987 ldm[2] = operands[0];
9988 }
9989 else
9990 {
9991 ldm[1] = operands[0];
9992 ldm[2] = operands[4];
9993 }
94dee231 9994
9995 base_reg = XEXP (operands[2], 0);
9996
9997 if (!REG_P (base_reg))
9998 {
9999 val1 = INTVAL (XEXP (base_reg, 1));
10000 base_reg = XEXP (base_reg, 0);
10001 }
10002
10003 if (!REG_P (XEXP (operands[3], 0)))
215b30b3 10004 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
94dee231 10005
215b30b3 10006 arith[0] = operands[0];
10007 arith[3] = operands[1];
94dee231 10008
215b30b3 10009 if (val1 < val2)
10010 {
10011 arith[1] = ldm[1];
10012 arith[2] = ldm[2];
10013 }
10014 else
10015 {
10016 arith[1] = ldm[2];
10017 arith[2] = ldm[1];
10018 }
94dee231 10019
10020 ldm[0] = base_reg;
10021 if (val1 !=0 && val2 != 0)
215b30b3 10022 {
cdb1295a 10023 rtx ops[3];
10024
94dee231 10025 if (val1 == 4 || val2 == 4)
10026 /* Other val must be 8, since we know they are adjacent and neither
10027 is zero. */
25f905c2 10028 output_asm_insn (\"ldm%(ib%)\\t%0, {%1, %2}\", ldm);
cdb1295a 10029 else if (const_ok_for_arm (val1) || const_ok_for_arm (-val1))
94dee231 10030 {
94dee231 10031 ldm[0] = ops[0] = operands[4];
10032 ops[1] = base_reg;
10033 ops[2] = GEN_INT (val1);
10034 output_add_immediate (ops);
10035 if (val1 < val2)
25f905c2 10036 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
94dee231 10037 else
25f905c2 10038 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
94dee231 10039 }
cdb1295a 10040 else
10041 {
10042 /* Offset is out of range for a single add, so use two ldr. */
10043 ops[0] = ldm[1];
10044 ops[1] = base_reg;
10045 ops[2] = GEN_INT (val1);
10046 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10047 ops[0] = ldm[2];
10048 ops[2] = GEN_INT (val2);
10049 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10050 }
215b30b3 10051 }
94dee231 10052 else if (val1 != 0)
215b30b3 10053 {
215b30b3 10054 if (val1 < val2)
25f905c2 10055 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
215b30b3 10056 else
25f905c2 10057 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
215b30b3 10058 }
10059 else
10060 {
215b30b3 10061 if (val1 < val2)
25f905c2 10062 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
215b30b3 10063 else
25f905c2 10064 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
215b30b3 10065 }
10066 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
10067 return \"\";
10068 }"
10069 [(set_attr "length" "12")
10070 (set_attr "predicable" "yes")
a2cd141b 10071 (set_attr "type" "load1")]
215b30b3 10072)
9c08d1fa 10073
9c08d1fa 10074; This pattern is never tried by combine, so do it as a peephole
10075
a0f94409 10076(define_peephole2
372575c7 10077 [(set (match_operand:SI 0 "arm_general_register_operand" "")
10078 (match_operand:SI 1 "arm_general_register_operand" ""))
bd5b4116 10079 (set (reg:CC CC_REGNUM)
aea4c774 10080 (compare:CC (match_dup 1) (const_int 0)))]
372575c7 10081 "TARGET_ARM"
a0f94409 10082 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
10083 (set (match_dup 0) (match_dup 1))])]
10084 ""
0d66636f 10085)
9c08d1fa 10086
9c08d1fa 10087(define_split
10088 [(set (match_operand:SI 0 "s_register_operand" "")
10089 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
10090 (const_int 0))
8fa3ba89 10091 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9c08d1fa 10092 [(match_operand:SI 3 "s_register_operand" "")
10093 (match_operand:SI 4 "arm_rhs_operand" "")]))))
10094 (clobber (match_operand:SI 5 "s_register_operand" ""))]
cffb2a26 10095 "TARGET_ARM"
9c08d1fa 10096 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
10097 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
10098 (match_dup 5)))]
215b30b3 10099 ""
10100)
9c08d1fa 10101
aea4c774 10102;; This split can be used because CC_Z mode implies that the following
10103;; branch will be an equality, or an unsigned inequality, so the sign
10104;; extension is not needed.
9c08d1fa 10105
aea4c774 10106(define_split
bd5b4116 10107 [(set (reg:CC_Z CC_REGNUM)
aea4c774 10108 (compare:CC_Z
10109 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9c08d1fa 10110 (const_int 24))
aea4c774 10111 (match_operand 1 "const_int_operand" "")))
10112 (clobber (match_scratch:SI 2 ""))]
cffb2a26 10113 "TARGET_ARM
10114 && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
10115 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
aea4c774 10116 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
bd5b4116 10117 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
aea4c774 10118 "
9c08d1fa 10119 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
215b30b3 10120 "
10121)
25f905c2 10122;; ??? Check the patterns above for Thumb-2 usefulness
9c08d1fa 10123
87b22bf7 10124(define_expand "prologue"
10125 [(clobber (const_int 0))]
cffb2a26 10126 "TARGET_EITHER"
25f905c2 10127 "if (TARGET_32BIT)
cffb2a26 10128 arm_expand_prologue ();
10129 else
25f905c2 10130 thumb1_expand_prologue ();
87b22bf7 10131 DONE;
cffb2a26 10132 "
10133)
87b22bf7 10134
56d27660 10135(define_expand "epilogue"
4c44712e 10136 [(clobber (const_int 0))]
cffb2a26 10137 "TARGET_EITHER"
56d27660 10138 "
18d50ae6 10139 if (crtl->calls_eh_return)
fb94f18b 10140 emit_insn (gen_force_register_use (gen_rtx_REG (Pmode, 2)));
25f905c2 10141 if (TARGET_THUMB1)
c3635784 10142 {
10143 thumb1_expand_epilogue ();
10144 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
10145 gen_rtvec (1, ret_rtx), VUNSPEC_EPILOGUE));
10146 }
10147 else if (HAVE_return)
10148 {
10149 /* HAVE_return is testing for USE_RETURN_INSN (FALSE). Hence,
10150 no need for explicit testing again. */
10151 emit_jump_insn (gen_return ());
10152 }
10153 else if (TARGET_32BIT)
10154 {
10155 arm_expand_epilogue (true);
10156 }
cffb2a26 10157 DONE;
10158 "
10159)
56d27660 10160
ef5651d0 10161;; Note - although unspec_volatile's USE all hard registers,
10162;; USEs are ignored after relaod has completed. Thus we need
10163;; to add an unspec of the link register to ensure that flow
10164;; does not think that it is unused by the sibcall branch that
10165;; will replace the standard function epilogue.
c3635784 10166(define_expand "sibcall_epilogue"
fb94f18b 10167 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_REGISTER_USE)
c3635784 10168 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
10169 "TARGET_32BIT"
10170 "
10171 arm_expand_epilogue (false);
10172 DONE;
10173 "
1c494086 10174)
10175
cffb2a26 10176(define_expand "eh_epilogue"
7db9af5d 10177 [(use (match_operand:SI 0 "register_operand" ""))
10178 (use (match_operand:SI 1 "register_operand" ""))
10179 (use (match_operand:SI 2 "register_operand" ""))]
cffb2a26 10180 "TARGET_EITHER"
10181 "
215b30b3 10182 {
10183 cfun->machine->eh_epilogue_sp_ofs = operands[1];
0438d37f 10184 if (!REG_P (operands[2]) || REGNO (operands[2]) != 2)
215b30b3 10185 {
10186 rtx ra = gen_rtx_REG (Pmode, 2);
10187
10188 emit_move_insn (ra, operands[2]);
10189 operands[2] = ra;
10190 }
5cf3595a 10191 /* This is a hack -- we may have crystalized the function type too
10192 early. */
10193 cfun->machine->func_type = 0;
215b30b3 10194 }"
10195)
56d27660 10196
9c08d1fa 10197;; This split is only used during output to reduce the number of patterns
10198;; that need assembler instructions adding to them. We allowed the setting
10199;; of the conditions to be implicit during rtl generation so that
10200;; the conditional compare patterns would work. However this conflicts to
8a18b90c 10201;; some extent with the conditional data operations, so we have to split them
9c08d1fa 10202;; up again here.
10203
25f905c2 10204;; ??? Need to audit these splitters for Thumb-2. Why isn't normal
10205;; conditional execution sufficient?
10206
9c08d1fa 10207(define_split
10208 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 10209 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10210 [(match_operand 2 "" "") (match_operand 3 "" "")])
10211 (match_dup 0)
10212 (match_operand 4 "" "")))
bd5b4116 10213 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10214 "TARGET_ARM && reload_completed"
8fa3ba89 10215 [(set (match_dup 5) (match_dup 6))
10216 (cond_exec (match_dup 7)
10217 (set (match_dup 0) (match_dup 4)))]
10218 "
10219 {
3754d046 10220 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8fa3ba89 10221 operands[2], operands[3]);
10222 enum rtx_code rc = GET_CODE (operands[1]);
10223
bd5b4116 10224 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10225 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10226 if (mode == CCFPmode || mode == CCFPEmode)
10227 rc = reverse_condition_maybe_unordered (rc);
10228 else
10229 rc = reverse_condition (rc);
10230
10231 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
10232 }"
10233)
10234
10235(define_split
10236 [(set (match_operand:SI 0 "s_register_operand" "")
10237 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10238 [(match_operand 2 "" "") (match_operand 3 "" "")])
10239 (match_operand 4 "" "")
10240 (match_dup 0)))
bd5b4116 10241 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10242 "TARGET_ARM && reload_completed"
8fa3ba89 10243 [(set (match_dup 5) (match_dup 6))
10244 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
10245 (set (match_dup 0) (match_dup 4)))]
10246 "
10247 {
3754d046 10248 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8fa3ba89 10249 operands[2], operands[3]);
10250
bd5b4116 10251 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10252 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10253 }"
10254)
10255
10256(define_split
10257 [(set (match_operand:SI 0 "s_register_operand" "")
10258 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9c08d1fa 10259 [(match_operand 2 "" "") (match_operand 3 "" "")])
10260 (match_operand 4 "" "")
10261 (match_operand 5 "" "")))
bd5b4116 10262 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10263 "TARGET_ARM && reload_completed"
8fa3ba89 10264 [(set (match_dup 6) (match_dup 7))
10265 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10266 (set (match_dup 0) (match_dup 4)))
10267 (cond_exec (match_dup 8)
10268 (set (match_dup 0) (match_dup 5)))]
10269 "
10270 {
3754d046 10271 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8fa3ba89 10272 operands[2], operands[3]);
10273 enum rtx_code rc = GET_CODE (operands[1]);
10274
bd5b4116 10275 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10276 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10277 if (mode == CCFPmode || mode == CCFPEmode)
10278 rc = reverse_condition_maybe_unordered (rc);
10279 else
10280 rc = reverse_condition (rc);
10281
10282 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10283 }"
10284)
10285
cffb2a26 10286(define_split
10287 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 10288 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
cffb2a26 10289 [(match_operand:SI 2 "s_register_operand" "")
10290 (match_operand:SI 3 "arm_add_operand" "")])
10291 (match_operand:SI 4 "arm_rhs_operand" "")
10292 (not:SI
10293 (match_operand:SI 5 "s_register_operand" ""))))
bd5b4116 10294 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10295 "TARGET_ARM && reload_completed"
cffb2a26 10296 [(set (match_dup 6) (match_dup 7))
f6c53574 10297 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10298 (set (match_dup 0) (match_dup 4)))
10299 (cond_exec (match_dup 8)
10300 (set (match_dup 0) (not:SI (match_dup 5))))]
cffb2a26 10301 "
215b30b3 10302 {
3754d046 10303 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
215b30b3 10304 operands[2], operands[3]);
f6c53574 10305 enum rtx_code rc = GET_CODE (operands[1]);
cffb2a26 10306
bd5b4116 10307 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
1a83b3ff 10308 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
f6c53574 10309 if (mode == CCFPmode || mode == CCFPEmode)
10310 rc = reverse_condition_maybe_unordered (rc);
10311 else
10312 rc = reverse_condition (rc);
10313
10314 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
215b30b3 10315 }"
10316)
cffb2a26 10317
10318(define_insn "*cond_move_not"
10319 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10320 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
cffb2a26 10321 [(match_operand 3 "cc_register" "") (const_int 0)])
10322 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10323 (not:SI
10324 (match_operand:SI 2 "s_register_operand" "r,r"))))]
10325 "TARGET_ARM"
10326 "@
10327 mvn%D4\\t%0, %2
10328 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
0d66636f 10329 [(set_attr "conds" "use")
1b7da4ac 10330 (set_attr "type" "mvn_reg,multiple")
0d66636f 10331 (set_attr "length" "4,8")]
10332)
cffb2a26 10333
9c08d1fa 10334;; The next two patterns occur when an AND operation is followed by a
10335;; scc insn sequence
10336
f7fbdd4a 10337(define_insn "*sign_extract_onebit"
9c08d1fa 10338 [(set (match_operand:SI 0 "s_register_operand" "=r")
10339 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10340 (const_int 1)
ed750274 10341 (match_operand:SI 2 "const_int_operand" "n")))
10342 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10343 "TARGET_ARM"
9c08d1fa 10344 "*
0d66636f 10345 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10346 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
10347 return \"mvnne\\t%0, #0\";
10348 "
10349 [(set_attr "conds" "clob")
1b7da4ac 10350 (set_attr "length" "8")
10351 (set_attr "type" "multiple")]
0d66636f 10352)
9c08d1fa 10353
f7fbdd4a 10354(define_insn "*not_signextract_onebit"
9c08d1fa 10355 [(set (match_operand:SI 0 "s_register_operand" "=r")
10356 (not:SI
10357 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10358 (const_int 1)
ed750274 10359 (match_operand:SI 2 "const_int_operand" "n"))))
10360 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10361 "TARGET_ARM"
9c08d1fa 10362 "*
0d66636f 10363 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10364 output_asm_insn (\"tst\\t%1, %2\", operands);
10365 output_asm_insn (\"mvneq\\t%0, #0\", operands);
10366 return \"movne\\t%0, #0\";
10367 "
10368 [(set_attr "conds" "clob")
1b7da4ac 10369 (set_attr "length" "12")
10370 (set_attr "type" "multiple")]
0d66636f 10371)
25f905c2 10372;; ??? The above patterns need auditing for Thumb-2
87b22bf7 10373
0d66636f 10374;; Push multiple registers to the stack. Registers are in parallel (use ...)
10375;; expressions. For simplicity, the first register is also in the unspec
10376;; part.
08508cbf 10377;; To avoid the usage of GNU extension, the length attribute is computed
10378;; in a C function arm_attr_length_push_multi.
f7fbdd4a 10379(define_insn "*push_multi"
87b22bf7 10380 [(match_parallel 2 "multi_register_push"
7571d3f7 10381 [(set (match_operand:BLK 0 "push_mult_memory_operand" "")
3cc80a30 10382 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "")]
e1159bbe 10383 UNSPEC_PUSH_MULT))])]
7571d3f7 10384 ""
87b22bf7 10385 "*
215b30b3 10386 {
10387 int num_saves = XVECLEN (operands[2], 0);
ed593f11 10388
215b30b3 10389 /* For the StrongARM at least it is faster to
25f905c2 10390 use STR to store only a single register.
542d5028 10391 In Thumb mode always use push, and the assembler will pick
10392 something appropriate. */
25f905c2 10393 if (num_saves == 1 && TARGET_ARM)
61309563 10394 output_asm_insn (\"str%?\\t%1, [%m0, #-4]!\", operands);
215b30b3 10395 else
10396 {
10397 int i;
10398 char pattern[100];
ed593f11 10399
25f905c2 10400 if (TARGET_ARM)
61309563 10401 strcpy (pattern, \"stm%(fd%)\\t%m0!, {%1\");
10402 else if (TARGET_THUMB2)
10403 strcpy (pattern, \"push%?\\t{%1\");
25f905c2 10404 else
10405 strcpy (pattern, \"push\\t{%1\");
215b30b3 10406
6079f055 10407 for (i = 1; i < num_saves; i++)
215b30b3 10408 {
10409 strcat (pattern, \", %|\");
10410 strcat (pattern,
10411 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
10412 }
10413
10414 strcat (pattern, \"}\");
10415 output_asm_insn (pattern, operands);
10416 }
10417
10418 return \"\";
10419 }"
a6864a24 10420 [(set_attr "type" "store4")
10421 (set (attr "length")
08508cbf 10422 (symbol_ref "arm_attr_length_push_multi (operands[2], operands[1])"))]
215b30b3 10423)
f7fbdd4a 10424
4c58c898 10425(define_insn "stack_tie"
10426 [(set (mem:BLK (scratch))
aaa37ad6 10427 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "rk")
10428 (match_operand:SI 1 "s_register_operand" "rk")]
4c58c898 10429 UNSPEC_PRLG_STK))]
10430 ""
10431 ""
1b7da4ac 10432 [(set_attr "length" "0")
10433 (set_attr "type" "block")]
4c58c898 10434)
10435
426be8c5 10436;; Pop (as used in epilogue RTL)
10437;;
10438(define_insn "*load_multiple_with_writeback"
10439 [(match_parallel 0 "load_multiple_operation"
10440 [(set (match_operand:SI 1 "s_register_operand" "+rk")
10441 (plus:SI (match_dup 1)
809003b3 10442 (match_operand:SI 2 "const_int_I_operand" "I")))
426be8c5 10443 (set (match_operand:SI 3 "s_register_operand" "=rk")
10444 (mem:SI (match_dup 1)))
10445 ])]
10446 "TARGET_32BIT && (reload_in_progress || reload_completed)"
10447 "*
10448 {
10449 arm_output_multireg_pop (operands, /*return_pc=*/false,
10450 /*cond=*/const_true_rtx,
10451 /*reverse=*/false,
10452 /*update=*/true);
10453 return \"\";
10454 }
10455 "
10456 [(set_attr "type" "load4")
10457 (set_attr "predicable" "yes")]
10458)
10459
10460;; Pop with return (as used in epilogue RTL)
10461;;
10462;; This instruction is generated when the registers are popped at the end of
10463;; epilogue. Here, instead of popping the value into LR and then generating
10464;; jump to LR, value is popped into PC directly. Hence, the pattern is combined
10465;; with (return).
10466(define_insn "*pop_multiple_with_writeback_and_return"
10467 [(match_parallel 0 "pop_multiple_return"
10468 [(return)
10469 (set (match_operand:SI 1 "s_register_operand" "+rk")
10470 (plus:SI (match_dup 1)
809003b3 10471 (match_operand:SI 2 "const_int_I_operand" "I")))
426be8c5 10472 (set (match_operand:SI 3 "s_register_operand" "=rk")
10473 (mem:SI (match_dup 1)))
10474 ])]
10475 "TARGET_32BIT && (reload_in_progress || reload_completed)"
10476 "*
10477 {
10478 arm_output_multireg_pop (operands, /*return_pc=*/true,
10479 /*cond=*/const_true_rtx,
10480 /*reverse=*/false,
10481 /*update=*/true);
10482 return \"\";
10483 }
10484 "
10485 [(set_attr "type" "load4")
10486 (set_attr "predicable" "yes")]
10487)
10488
10489(define_insn "*pop_multiple_with_return"
10490 [(match_parallel 0 "pop_multiple_return"
10491 [(return)
10492 (set (match_operand:SI 2 "s_register_operand" "=rk")
10493 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
10494 ])]
10495 "TARGET_32BIT && (reload_in_progress || reload_completed)"
10496 "*
10497 {
10498 arm_output_multireg_pop (operands, /*return_pc=*/true,
10499 /*cond=*/const_true_rtx,
10500 /*reverse=*/false,
10501 /*update=*/false);
10502 return \"\";
10503 }
10504 "
10505 [(set_attr "type" "load4")
10506 (set_attr "predicable" "yes")]
10507)
10508
10509;; Load into PC and return
10510(define_insn "*ldr_with_return"
10511 [(return)
10512 (set (reg:SI PC_REGNUM)
10513 (mem:SI (post_inc:SI (match_operand:SI 0 "s_register_operand" "+rk"))))]
10514 "TARGET_32BIT && (reload_in_progress || reload_completed)"
10515 "ldr%?\t%|pc, [%0], #4"
10516 [(set_attr "type" "load1")
10517 (set_attr "predicable" "yes")]
10518)
1a0b0f12 10519;; Pop for floating point registers (as used in epilogue RTL)
10520(define_insn "*vfp_pop_multiple_with_writeback"
10521 [(match_parallel 0 "pop_multiple_fp"
10522 [(set (match_operand:SI 1 "s_register_operand" "+rk")
10523 (plus:SI (match_dup 1)
809003b3 10524 (match_operand:SI 2 "const_int_I_operand" "I")))
2f2163a4 10525 (set (match_operand:DF 3 "vfp_hard_register_operand" "")
1a0b0f12 10526 (mem:DF (match_dup 1)))])]
10527 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
10528 "*
10529 {
10530 int num_regs = XVECLEN (operands[0], 0);
10531 char pattern[100];
10532 rtx op_list[2];
b34d8dac 10533 strcpy (pattern, \"vldm\\t\");
1a0b0f12 10534 strcat (pattern, reg_names[REGNO (SET_DEST (XVECEXP (operands[0], 0, 0)))]);
10535 strcat (pattern, \"!, {\");
10536 op_list[0] = XEXP (XVECEXP (operands[0], 0, 1), 0);
10537 strcat (pattern, \"%P0\");
10538 if ((num_regs - 1) > 1)
10539 {
10540 strcat (pattern, \"-%P1\");
10541 op_list [1] = XEXP (XVECEXP (operands[0], 0, num_regs - 1), 0);
10542 }
10543
10544 strcat (pattern, \"}\");
10545 output_asm_insn (pattern, op_list);
10546 return \"\";
10547 }
10548 "
10549 [(set_attr "type" "load4")
10550 (set_attr "conds" "unconditional")
10551 (set_attr "predicable" "no")]
10552)
10553
f7fbdd4a 10554;; Special patterns for dealing with the constant pool
10555
cffb2a26 10556(define_insn "align_4"
e1159bbe 10557 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
cffb2a26 10558 "TARGET_EITHER"
f7fbdd4a 10559 "*
cffb2a26 10560 assemble_align (32);
f7fbdd4a 10561 return \"\";
cffb2a26 10562 "
1b7da4ac 10563 [(set_attr "type" "no_insn")]
cffb2a26 10564)
f7fbdd4a 10565
755eb2b4 10566(define_insn "align_8"
10567 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
f9273c43 10568 "TARGET_EITHER"
755eb2b4 10569 "*
10570 assemble_align (64);
10571 return \"\";
10572 "
1b7da4ac 10573 [(set_attr "type" "no_insn")]
755eb2b4 10574)
10575
cffb2a26 10576(define_insn "consttable_end"
e1159bbe 10577 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
cffb2a26 10578 "TARGET_EITHER"
f7fbdd4a 10579 "*
cffb2a26 10580 making_const_table = FALSE;
f7fbdd4a 10581 return \"\";
cffb2a26 10582 "
1b7da4ac 10583 [(set_attr "type" "no_insn")]
cffb2a26 10584)
f7fbdd4a 10585
0e207eb8 10586(define_insn "consttable_1"
10587 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
10588 "TARGET_EITHER"
10589 "*
10590 making_const_table = TRUE;
10591 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
10592 assemble_zeros (3);
10593 return \"\";
10594 "
10595 [(set_attr "length" "4")
10596 (set_attr "type" "no_insn")]
10597)
10598
10599(define_insn "consttable_2"
10600 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
10601 "TARGET_EITHER"
10602 "*
10603 {
10604 rtx x = operands[0];
10605 making_const_table = TRUE;
10606 switch (GET_MODE_CLASS (GET_MODE (x)))
10607 {
10608 case MODE_FLOAT:
10609 arm_emit_fp16_const (x);
10610 break;
10611 default:
10612 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
10613 assemble_zeros (2);
10614 break;
10615 }
10616 return \"\";
10617 }"
10618 [(set_attr "length" "4")
10619 (set_attr "type" "no_insn")]
10620)
10621
cffb2a26 10622(define_insn "consttable_4"
e1159bbe 10623 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
cffb2a26 10624 "TARGET_EITHER"
10625 "*
10626 {
9b8516be 10627 rtx x = operands[0];
cffb2a26 10628 making_const_table = TRUE;
9b8516be 10629 switch (GET_MODE_CLASS (GET_MODE (x)))
cffb2a26 10630 {
10631 case MODE_FLOAT:
0e207eb8 10632 {
10633 REAL_VALUE_TYPE r;
10634 REAL_VALUE_FROM_CONST_DOUBLE (r, x);
10635 assemble_real (r, GET_MODE (x), BITS_PER_WORD);
10636 break;
10637 }
cffb2a26 10638 default:
7b04c5d5 10639 /* XXX: Sometimes gcc does something really dumb and ends up with
10640 a HIGH in a constant pool entry, usually because it's trying to
10641 load into a VFP register. We know this will always be used in
10642 combination with a LO_SUM which ignores the high bits, so just
10643 strip off the HIGH. */
10644 if (GET_CODE (x) == HIGH)
10645 x = XEXP (x, 0);
9b8516be 10646 assemble_integer (x, 4, BITS_PER_WORD, 1);
10647 mark_symbol_refs_as_used (x);
cffb2a26 10648 break;
10649 }
10650 return \"\";
10651 }"
1b7da4ac 10652 [(set_attr "length" "4")
10653 (set_attr "type" "no_insn")]
cffb2a26 10654)
10655
10656(define_insn "consttable_8"
e1159bbe 10657 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
cffb2a26 10658 "TARGET_EITHER"
10659 "*
10660 {
10661 making_const_table = TRUE;
10662 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10663 {
10664 case MODE_FLOAT:
10665 {
badfe841 10666 REAL_VALUE_TYPE r;
10667 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10668 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
cffb2a26 10669 break;
10670 }
10671 default:
09d688ff 10672 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
cffb2a26 10673 break;
10674 }
10675 return \"\";
10676 }"
1b7da4ac 10677 [(set_attr "length" "8")
10678 (set_attr "type" "no_insn")]
cffb2a26 10679)
10680
d98a3884 10681(define_insn "consttable_16"
10682 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_16)]
10683 "TARGET_EITHER"
10684 "*
10685 {
10686 making_const_table = TRUE;
10687 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10688 {
10689 case MODE_FLOAT:
10690 {
10691 REAL_VALUE_TYPE r;
10692 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10693 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10694 break;
10695 }
10696 default:
10697 assemble_integer (operands[0], 16, BITS_PER_WORD, 1);
10698 break;
10699 }
10700 return \"\";
10701 }"
1b7da4ac 10702 [(set_attr "length" "16")
10703 (set_attr "type" "no_insn")]
d98a3884 10704)
10705
331beb1a 10706;; V5 Instructions,
10707
8f4be2be 10708(define_insn "clzsi2"
10709 [(set (match_operand:SI 0 "s_register_operand" "=r")
10710 (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 10711 "TARGET_32BIT && arm_arch5"
ee7cbe0e 10712 "clz%?\\t%0, %1"
bcaec148 10713 [(set_attr "predicable" "yes")
4a510717 10714 (set_attr "predicable_short_it" "no")
bebe9bbb 10715 (set_attr "type" "clz")])
331beb1a 10716
099ad98b 10717(define_insn "rbitsi2"
10718 [(set (match_operand:SI 0 "s_register_operand" "=r")
10719 (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")] UNSPEC_RBIT))]
10720 "TARGET_32BIT && arm_arch_thumb2"
10721 "rbit%?\\t%0, %1"
10722 [(set_attr "predicable" "yes")
4a510717 10723 (set_attr "predicable_short_it" "no")
bebe9bbb 10724 (set_attr "type" "clz")])
099ad98b 10725
10726(define_expand "ctzsi2"
10727 [(set (match_operand:SI 0 "s_register_operand" "")
10728 (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
10729 "TARGET_32BIT && arm_arch_thumb2"
10730 "
30191172 10731 {
10732 rtx tmp = gen_reg_rtx (SImode);
10733 emit_insn (gen_rbitsi2 (tmp, operands[1]));
10734 emit_insn (gen_clzsi2 (operands[0], tmp));
10735 }
099ad98b 10736 DONE;
10737 "
10738)
10739
e1159bbe 10740;; V5E instructions.
331beb1a 10741
10742(define_insn "prefetch"
f4e79814 10743 [(prefetch (match_operand:SI 0 "address_operand" "p")
10744 (match_operand:SI 1 "" "")
10745 (match_operand:SI 2 "" ""))]
25f905c2 10746 "TARGET_32BIT && arm_arch5e"
1b7da4ac 10747 "pld\\t%a0"
10748 [(set_attr "type" "load1")]
10749)
331beb1a 10750
0d66636f 10751;; General predication pattern
10752
10753(define_cond_exec
10754 [(match_operator 0 "arm_comparison_operator"
10755 [(match_operand 1 "cc_register" "")
10756 (const_int 0)])]
25f905c2 10757 "TARGET_32BIT"
0d66636f 10758 ""
c7a58118 10759[(set_attr "predicated" "yes")]
0d66636f 10760)
10761
fb94f18b 10762(define_insn "force_register_use"
10763 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_REGISTER_USE)]
063a05c7 10764 ""
fb94f18b 10765 "%@ %0 needed"
1b7da4ac 10766 [(set_attr "length" "0")
10767 (set_attr "type" "no_insn")]
063a05c7 10768)
7db9af5d 10769
4c44712e 10770
10771;; Patterns for exception handling
10772
10773(define_expand "eh_return"
10774 [(use (match_operand 0 "general_operand" ""))]
10775 "TARGET_EITHER"
10776 "
10777 {
25f905c2 10778 if (TARGET_32BIT)
4c44712e 10779 emit_insn (gen_arm_eh_return (operands[0]));
10780 else
10781 emit_insn (gen_thumb_eh_return (operands[0]));
10782 DONE;
10783 }"
10784)
10785
10786;; We can't expand this before we know where the link register is stored.
10787(define_insn_and_split "arm_eh_return"
10788 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
10789 VUNSPEC_EH_RETURN)
10790 (clobber (match_scratch:SI 1 "=&r"))]
10791 "TARGET_ARM"
10792 "#"
10793 "&& reload_completed"
10794 [(const_int 0)]
10795 "
10796 {
10797 arm_set_return_address (operands[0], operands[1]);
10798 DONE;
10799 }"
10800)
10801
f655717d 10802\f
10803;; TLS support
10804
10805(define_insn "load_tp_hard"
10806 [(set (match_operand:SI 0 "register_operand" "=r")
10807 (unspec:SI [(const_int 0)] UNSPEC_TLS))]
10808 "TARGET_HARD_TP"
10809 "mrc%?\\tp15, 0, %0, c13, c0, 3\\t@ load_tp_hard"
1b7da4ac 10810 [(set_attr "predicable" "yes")
4b5d7374 10811 (set_attr "type" "mrs")]
f655717d 10812)
10813
10814;; Doesn't clobber R1-R3. Must use r0 for the first operand.
10815(define_insn "load_tp_soft"
10816 [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
10817 (clobber (reg:SI LR_REGNUM))
10818 (clobber (reg:SI IP_REGNUM))
10819 (clobber (reg:CC CC_REGNUM))]
10820 "TARGET_SOFT_TP"
10821 "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
1b7da4ac 10822 [(set_attr "conds" "clob")
10823 (set_attr "type" "branch")]
f655717d 10824)
10825
f41e4452 10826;; tls descriptor call
10827(define_insn "tlscall"
10828 [(set (reg:SI R0_REGNUM)
10829 (unspec:SI [(reg:SI R0_REGNUM)
10830 (match_operand:SI 0 "" "X")
10831 (match_operand 1 "" "")] UNSPEC_TLS))
10832 (clobber (reg:SI R1_REGNUM))
10833 (clobber (reg:SI LR_REGNUM))
10834 (clobber (reg:SI CC_REGNUM))]
10835 "TARGET_GNU2_TLS"
10836 {
10837 targetm.asm_out.internal_label (asm_out_file, "LPIC",
10838 INTVAL (operands[1]));
10839 return "bl\\t%c0(tlscall)";
10840 }
10841 [(set_attr "conds" "clob")
1b7da4ac 10842 (set_attr "length" "4")
10843 (set_attr "type" "branch")]
f41e4452 10844)
10845
1fe0edab 10846;; For thread pointer builtin
10847(define_expand "get_thread_pointersi"
10848 [(match_operand:SI 0 "s_register_operand" "=r")]
10849 ""
10850 "
10851 {
10852 arm_load_tp (operands[0]);
10853 DONE;
10854 }")
10855
f41e4452 10856;;
10857
aabe09ac 10858;; We only care about the lower 16 bits of the constant
10859;; being inserted into the upper 16 bits of the register.
eca5c984 10860(define_insn "*arm_movtas_ze"
10861 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
10862 (const_int 16)
10863 (const_int 16))
10864 (match_operand:SI 1 "const_int_operand" ""))]
181ab277 10865 "arm_arch_thumb2"
aabe09ac 10866 "movt%?\t%0, %L1"
eca5c984 10867 [(set_attr "predicable" "yes")
7c36fe71 10868 (set_attr "predicable_short_it" "no")
1b7da4ac 10869 (set_attr "length" "4")
10870 (set_attr "type" "mov_imm")]
eca5c984 10871)
10872
c0fc3696 10873(define_insn "*arm_rev"
a486b499 10874 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
10875 (bswap:SI (match_operand:SI 1 "s_register_operand" "l,l,r")))]
10876 "arm_arch6"
10877 "@
10878 rev\t%0, %1
10879 rev%?\t%0, %1
10880 rev%?\t%0, %1"
10881 [(set_attr "arch" "t1,t2,32")
1b7da4ac 10882 (set_attr "length" "2,2,4")
4a510717 10883 (set_attr "predicable" "no,yes,yes")
10884 (set_attr "predicable_short_it" "no")
1b7da4ac 10885 (set_attr "type" "rev")]
ff82f757 10886)
10887
10888(define_expand "arm_legacy_rev"
10889 [(set (match_operand:SI 2 "s_register_operand" "")
10890 (xor:SI (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
10891 (const_int 16))
10892 (match_dup 1)))
10893 (set (match_dup 2)
10894 (lshiftrt:SI (match_dup 2)
10895 (const_int 8)))
10896 (set (match_operand:SI 3 "s_register_operand" "")
10897 (rotatert:SI (match_dup 1)
10898 (const_int 8)))
10899 (set (match_dup 2)
10900 (and:SI (match_dup 2)
10901 (const_int -65281)))
10902 (set (match_operand:SI 0 "s_register_operand" "")
10903 (xor:SI (match_dup 3)
10904 (match_dup 2)))]
10905 "TARGET_32BIT"
10906 ""
10907)
10908
10909;; Reuse temporaries to keep register pressure down.
10910(define_expand "thumb_legacy_rev"
10911 [(set (match_operand:SI 2 "s_register_operand" "")
10912 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
10913 (const_int 24)))
10914 (set (match_operand:SI 3 "s_register_operand" "")
10915 (lshiftrt:SI (match_dup 1)
10916 (const_int 24)))
10917 (set (match_dup 3)
10918 (ior:SI (match_dup 3)
10919 (match_dup 2)))
10920 (set (match_operand:SI 4 "s_register_operand" "")
10921 (const_int 16))
10922 (set (match_operand:SI 5 "s_register_operand" "")
10923 (rotatert:SI (match_dup 1)
10924 (match_dup 4)))
10925 (set (match_dup 2)
10926 (ashift:SI (match_dup 5)
10927 (const_int 24)))
10928 (set (match_dup 5)
10929 (lshiftrt:SI (match_dup 5)
10930 (const_int 24)))
10931 (set (match_dup 5)
10932 (ior:SI (match_dup 5)
10933 (match_dup 2)))
10934 (set (match_dup 5)
10935 (rotatert:SI (match_dup 5)
10936 (match_dup 4)))
10937 (set (match_operand:SI 0 "s_register_operand" "")
10938 (ior:SI (match_dup 5)
10939 (match_dup 3)))]
10940 "TARGET_THUMB"
10941 ""
10942)
10943
10944(define_expand "bswapsi2"
10945 [(set (match_operand:SI 0 "s_register_operand" "=r")
10946 (bswap:SI (match_operand:SI 1 "s_register_operand" "r")))]
8d1af482 10947"TARGET_EITHER && (arm_arch6 || !optimize_size)"
ff82f757 10948"
8d1af482 10949 if (!arm_arch6)
10950 {
10951 rtx op2 = gen_reg_rtx (SImode);
10952 rtx op3 = gen_reg_rtx (SImode);
ff82f757 10953
8d1af482 10954 if (TARGET_THUMB)
10955 {
10956 rtx op4 = gen_reg_rtx (SImode);
10957 rtx op5 = gen_reg_rtx (SImode);
ff82f757 10958
8d1af482 10959 emit_insn (gen_thumb_legacy_rev (operands[0], operands[1],
10960 op2, op3, op4, op5));
10961 }
10962 else
10963 {
10964 emit_insn (gen_arm_legacy_rev (operands[0], operands[1],
10965 op2, op3));
10966 }
ff82f757 10967
8d1af482 10968 DONE;
10969 }
ff82f757 10970 "
10971)
10972
a486b499 10973;; bswap16 patterns: use revsh and rev16 instructions for the signed
10974;; and unsigned variants, respectively. For rev16, expose
10975;; byte-swapping in the lower 16 bits only.
10976(define_insn "*arm_revsh"
10977 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
10978 (sign_extend:SI (bswap:HI (match_operand:HI 1 "s_register_operand" "l,l,r"))))]
10979 "arm_arch6"
10980 "@
10981 revsh\t%0, %1
10982 revsh%?\t%0, %1
10983 revsh%?\t%0, %1"
10984 [(set_attr "arch" "t1,t2,32")
1b7da4ac 10985 (set_attr "length" "2,2,4")
10986 (set_attr "type" "rev")]
a486b499 10987)
10988
10989(define_insn "*arm_rev16"
10990 [(set (match_operand:HI 0 "s_register_operand" "=l,l,r")
10991 (bswap:HI (match_operand:HI 1 "s_register_operand" "l,l,r")))]
10992 "arm_arch6"
10993 "@
10994 rev16\t%0, %1
10995 rev16%?\t%0, %1
10996 rev16%?\t%0, %1"
10997 [(set_attr "arch" "t1,t2,32")
1b7da4ac 10998 (set_attr "length" "2,2,4")
10999 (set_attr "type" "rev")]
09f69e55 11000)
11001
11002;; There are no canonicalisation rules for the position of the lshiftrt, ashift
11003;; operations within an IOR/AND RTX, therefore we have two patterns matching
11004;; each valid permutation.
11005
11006(define_insn "arm_rev16si2"
11007 [(set (match_operand:SI 0 "register_operand" "=l,l,r")
11008 (ior:SI (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "l,l,r")
11009 (const_int 8))
11010 (match_operand:SI 3 "const_int_operand" "n,n,n"))
11011 (and:SI (lshiftrt:SI (match_dup 1)
11012 (const_int 8))
11013 (match_operand:SI 2 "const_int_operand" "n,n,n"))))]
11014 "arm_arch6
11015 && aarch_rev16_shleft_mask_imm_p (operands[3], SImode)
11016 && aarch_rev16_shright_mask_imm_p (operands[2], SImode)"
11017 "rev16\\t%0, %1"
11018 [(set_attr "arch" "t1,t2,32")
11019 (set_attr "length" "2,2,4")
11020 (set_attr "type" "rev")]
11021)
11022
11023(define_insn "arm_rev16si2_alt"
11024 [(set (match_operand:SI 0 "register_operand" "=l,l,r")
11025 (ior:SI (and:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,l,r")
11026 (const_int 8))
11027 (match_operand:SI 2 "const_int_operand" "n,n,n"))
11028 (and:SI (ashift:SI (match_dup 1)
11029 (const_int 8))
11030 (match_operand:SI 3 "const_int_operand" "n,n,n"))))]
11031 "arm_arch6
11032 && aarch_rev16_shleft_mask_imm_p (operands[3], SImode)
11033 && aarch_rev16_shright_mask_imm_p (operands[2], SImode)"
11034 "rev16\\t%0, %1"
11035 [(set_attr "arch" "t1,t2,32")
11036 (set_attr "length" "2,2,4")
11037 (set_attr "type" "rev")]
a486b499 11038)
11039
11040(define_expand "bswaphi2"
11041 [(set (match_operand:HI 0 "s_register_operand" "=r")
11042 (bswap:HI (match_operand:HI 1 "s_register_operand" "r")))]
11043"arm_arch6"
11044""
11045)
11046
1653cf17 11047;; Patterns for LDRD/STRD in Thumb2 mode
11048
11049(define_insn "*thumb2_ldrd"
11050 [(set (match_operand:SI 0 "s_register_operand" "=r")
11051 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
11052 (match_operand:SI 2 "ldrd_strd_offset_operand" "Do"))))
11053 (set (match_operand:SI 3 "s_register_operand" "=r")
11054 (mem:SI (plus:SI (match_dup 1)
11055 (match_operand:SI 4 "const_int_operand" ""))))]
11056 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11057 && current_tune->prefer_ldrd_strd
11058 && ((INTVAL (operands[2]) + 4) == INTVAL (operands[4]))
11059 && (operands_ok_ldrd_strd (operands[0], operands[3],
11060 operands[1], INTVAL (operands[2]),
11061 false, true))"
11062 "ldrd%?\t%0, %3, [%1, %2]"
11063 [(set_attr "type" "load2")
d952d547 11064 (set_attr "predicable" "yes")
11065 (set_attr "predicable_short_it" "no")])
1653cf17 11066
11067(define_insn "*thumb2_ldrd_base"
11068 [(set (match_operand:SI 0 "s_register_operand" "=r")
11069 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
11070 (set (match_operand:SI 2 "s_register_operand" "=r")
11071 (mem:SI (plus:SI (match_dup 1)
11072 (const_int 4))))]
11073 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11074 && current_tune->prefer_ldrd_strd
11075 && (operands_ok_ldrd_strd (operands[0], operands[2],
11076 operands[1], 0, false, true))"
11077 "ldrd%?\t%0, %2, [%1]"
11078 [(set_attr "type" "load2")
d952d547 11079 (set_attr "predicable" "yes")
11080 (set_attr "predicable_short_it" "no")])
1653cf17 11081
11082(define_insn "*thumb2_ldrd_base_neg"
11083 [(set (match_operand:SI 0 "s_register_operand" "=r")
11084 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
11085 (const_int -4))))
11086 (set (match_operand:SI 2 "s_register_operand" "=r")
11087 (mem:SI (match_dup 1)))]
11088 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11089 && current_tune->prefer_ldrd_strd
11090 && (operands_ok_ldrd_strd (operands[0], operands[2],
11091 operands[1], -4, false, true))"
11092 "ldrd%?\t%0, %2, [%1, #-4]"
11093 [(set_attr "type" "load2")
d952d547 11094 (set_attr "predicable" "yes")
11095 (set_attr "predicable_short_it" "no")])
1653cf17 11096
11097(define_insn "*thumb2_strd"
11098 [(set (mem:SI (plus:SI (match_operand:SI 0 "s_register_operand" "rk")
11099 (match_operand:SI 1 "ldrd_strd_offset_operand" "Do")))
11100 (match_operand:SI 2 "s_register_operand" "r"))
11101 (set (mem:SI (plus:SI (match_dup 0)
11102 (match_operand:SI 3 "const_int_operand" "")))
11103 (match_operand:SI 4 "s_register_operand" "r"))]
11104 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11105 && current_tune->prefer_ldrd_strd
11106 && ((INTVAL (operands[1]) + 4) == INTVAL (operands[3]))
11107 && (operands_ok_ldrd_strd (operands[2], operands[4],
11108 operands[0], INTVAL (operands[1]),
11109 false, false))"
11110 "strd%?\t%2, %4, [%0, %1]"
11111 [(set_attr "type" "store2")
d952d547 11112 (set_attr "predicable" "yes")
11113 (set_attr "predicable_short_it" "no")])
1653cf17 11114
11115(define_insn "*thumb2_strd_base"
11116 [(set (mem:SI (match_operand:SI 0 "s_register_operand" "rk"))
11117 (match_operand:SI 1 "s_register_operand" "r"))
11118 (set (mem:SI (plus:SI (match_dup 0)
11119 (const_int 4)))
11120 (match_operand:SI 2 "s_register_operand" "r"))]
11121 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11122 && current_tune->prefer_ldrd_strd
11123 && (operands_ok_ldrd_strd (operands[1], operands[2],
11124 operands[0], 0, false, false))"
11125 "strd%?\t%1, %2, [%0]"
11126 [(set_attr "type" "store2")
d952d547 11127 (set_attr "predicable" "yes")
11128 (set_attr "predicable_short_it" "no")])
1653cf17 11129
11130(define_insn "*thumb2_strd_base_neg"
11131 [(set (mem:SI (plus:SI (match_operand:SI 0 "s_register_operand" "rk")
11132 (const_int -4)))
11133 (match_operand:SI 1 "s_register_operand" "r"))
11134 (set (mem:SI (match_dup 0))
11135 (match_operand:SI 2 "s_register_operand" "r"))]
11136 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11137 && current_tune->prefer_ldrd_strd
11138 && (operands_ok_ldrd_strd (operands[1], operands[2],
11139 operands[0], -4, false, false))"
11140 "strd%?\t%1, %2, [%0, #-4]"
11141 [(set_attr "type" "store2")
d952d547 11142 (set_attr "predicable" "yes")
11143 (set_attr "predicable_short_it" "no")])
1653cf17 11144
2a0c73f2 11145;; ARMv8 CRC32 instructions.
11146(define_insn "<crc_variant>"
11147 [(set (match_operand:SI 0 "s_register_operand" "=r")
11148 (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")
11149 (match_operand:<crc_mode> 2 "s_register_operand" "r")]
11150 CRC))]
11151 "TARGET_CRC32"
11152 "<crc_variant>\\t%0, %1, %2"
11153 [(set_attr "type" "crc")
11154 (set_attr "conds" "unconditional")]
11155)
1653cf17 11156
353cf59a 11157;; Load the load/store double peephole optimizations.
11158(include "ldrdstrd.md")
11159
320ea44d 11160;; Load the load/store multiple patterns
11161(include "ldmstm.md")
426be8c5 11162
11163;; Patterns in ldmstm.md don't cover more than 4 registers. This pattern covers
11164;; large lists without explicit writeback generated for APCS_FRAME epilogue.
11165(define_insn "*load_multiple"
11166 [(match_parallel 0 "load_multiple_operation"
11167 [(set (match_operand:SI 2 "s_register_operand" "=rk")
11168 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
11169 ])]
11170 "TARGET_32BIT"
11171 "*
11172 {
11173 arm_output_multireg_pop (operands, /*return_pc=*/false,
11174 /*cond=*/const_true_rtx,
11175 /*reverse=*/false,
11176 /*update=*/false);
11177 return \"\";
11178 }
11179 "
11180 [(set_attr "predicable" "yes")]
11181)
11182
84450ddc 11183(define_expand "copysignsf3"
11184 [(match_operand:SF 0 "register_operand")
11185 (match_operand:SF 1 "register_operand")
11186 (match_operand:SF 2 "register_operand")]
11187 "TARGET_SOFT_FLOAT && arm_arch_thumb2"
11188 "{
11189 emit_move_insn (operands[0], operands[2]);
11190 emit_insn (gen_insv_t2 (simplify_gen_subreg (SImode, operands[0], SFmode, 0),
11191 GEN_INT (31), GEN_INT (0),
11192 simplify_gen_subreg (SImode, operands[1], SFmode, 0)));
11193 DONE;
11194 }"
11195)
11196
11197(define_expand "copysigndf3"
11198 [(match_operand:DF 0 "register_operand")
11199 (match_operand:DF 1 "register_operand")
11200 (match_operand:DF 2 "register_operand")]
11201 "TARGET_SOFT_FLOAT && arm_arch_thumb2"
11202 "{
11203 rtx op0_low = gen_lowpart (SImode, operands[0]);
11204 rtx op0_high = gen_highpart (SImode, operands[0]);
11205 rtx op1_low = gen_lowpart (SImode, operands[1]);
11206 rtx op1_high = gen_highpart (SImode, operands[1]);
11207 rtx op2_high = gen_highpart (SImode, operands[2]);
11208
11209 rtx scratch1 = gen_reg_rtx (SImode);
11210 rtx scratch2 = gen_reg_rtx (SImode);
11211 emit_move_insn (scratch1, op2_high);
11212 emit_move_insn (scratch2, op1_high);
11213
11214 emit_insn(gen_rtx_SET(SImode, scratch1,
11215 gen_rtx_LSHIFTRT (SImode, op2_high, GEN_INT(31))));
11216 emit_insn(gen_insv_t2(scratch2, GEN_INT(1), GEN_INT(31), scratch1));
11217 emit_move_insn (op0_low, op1_low);
11218 emit_move_insn (op0_high, scratch2);
11219
11220 DONE;
11221 }"
11222)
11223
d98a3884 11224;; Vector bits common to IWMMXT and Neon
11225(include "vec-common.md")
755eb2b4 11226;; Load the Intel Wireless Multimedia Extension patterns
11227(include "iwmmxt.md")
a2cd141b 11228;; Load the VFP co-processor patterns
11229(include "vfp.md")
bc360af8 11230;; Thumb-1 patterns
11231(include "thumb1.md")
25f905c2 11232;; Thumb-2 patterns
11233(include "thumb2.md")
d98a3884 11234;; Neon patterns
11235(include "neon.md")
e84fdf6e 11236;; Crypto patterns
11237(include "crypto.md")
06df6b17 11238;; Synchronization Primitives
11239(include "sync.md")
bbbe4599 11240;; Fixed-point patterns
11241(include "arm-fixed.md")