]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/arm/arm.md
Thumb uses a special register allocation order to increase the use of low
[thirdparty/gcc.git] / gcc / config / arm / arm.md
CommitLineData
129a2fe4 1;;- Machine description for ARM for GNU compiler
f1717362 2;; Copyright (C) 1991-2016 Free Software Foundation, Inc.
b11cae9e 3;; Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
f082f1c4 4;; and Martin Simmons (@harleqn.co.uk).
129a2fe4 5;; More major hacks by Richard Earnshaw (rearnsha@arm.com).
b11cae9e 6
acf6ed70 7;; This file is part of GCC.
b11cae9e 8
acf6ed70 9;; GCC is free software; you can redistribute it and/or modify it
10;; under the terms of the GNU General Public License as published
038d1e19 11;; by the Free Software Foundation; either version 3, or (at your
acf6ed70 12;; option) any later version.
b11cae9e 13
acf6ed70 14;; GCC is distributed in the hope that it will be useful, but WITHOUT
15;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
17;; License for more details.
b11cae9e 18
19;; You should have received a copy of the GNU General Public License
038d1e19 20;; along with GCC; see the file COPYING3. If not see
21;; <http://www.gnu.org/licenses/>.
b11cae9e 22
23;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
24
9c08d1fa 25\f
e1159bbe 26;;---------------------------------------------------------------------------
27;; Constants
28
bffbb863 29;; Register numbers -- All machine registers should be defined here
e1159bbe 30(define_constants
bffbb863 31 [(R0_REGNUM 0) ; First CORE register
32 (R1_REGNUM 1) ; Second CORE register
33 (IP_REGNUM 12) ; Scratch register
34 (SP_REGNUM 13) ; Stack pointer
35 (LR_REGNUM 14) ; Return address register
36 (PC_REGNUM 15) ; Program counter
37 (LAST_ARM_REGNUM 15) ;
38 (CC_REGNUM 100) ; Condition code pseudo register
39 (VFPCC_REGNUM 101) ; VFP Condition code pseudo register
e1159bbe 40 ]
41)
3c5afce6 42;; 3rd operand to select_dominance_cc_mode
43(define_constants
44 [(DOM_CC_X_AND_Y 0)
45 (DOM_CC_NX_OR_Y 1)
46 (DOM_CC_X_OR_Y 2)
47 ]
48)
2ff91fec 49;; conditional compare combination
50(define_constants
51 [(CMP_CMP 0)
52 (CMN_CMP 1)
53 (CMP_CMN 2)
54 (CMN_CMN 3)
55 (NUM_OF_COND_CMP 4)
56 ]
57)
e1159bbe 58
b11cae9e 59\f
e1159bbe 60;;---------------------------------------------------------------------------
9c08d1fa 61;; Attributes
62
a651f34d 63;; Processor type. This is created automatically from arm-cores.def.
64(include "arm-tune.md")
65
861033d5 66;; Instruction classification types
67(include "types.md")
68
215b30b3 69; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
70; generating ARM code. This is used to control the length of some insn
71; patterns that share the same RTL in both ARM and Thumb code.
8724f216 72(define_attr "is_thumb" "yes,no"
73 (const (if_then_else (symbol_ref "TARGET_THUMB")
74 (const_string "yes") (const_string "no"))))
cffb2a26 75
ef51b8e1 76; IS_ARCH6 is set to 'yes' when we are generating code form ARMv6.
77(define_attr "is_arch6" "no,yes" (const (symbol_ref "arm_arch6")))
78
747b7458 79; IS_THUMB1 is set to 'yes' iff we are generating Thumb-1 code.
8724f216 80(define_attr "is_thumb1" "yes,no"
81 (const (if_then_else (symbol_ref "TARGET_THUMB1")
82 (const_string "yes") (const_string "no"))))
747b7458 83
c7a58118 84; We use this attribute to disable alternatives that can produce 32-bit
85; instructions inside an IT-block in Thumb2 state. ARMv8 deprecates IT blocks
86; that contain 32-bit instructions.
87(define_attr "enabled_for_depr_it" "no,yes" (const_string "yes"))
88
89; This attribute is used to disable a predicated alternative when we have
90; arm_restrict_it.
91(define_attr "predicable_short_it" "no,yes" (const_string "yes"))
92
331beb1a 93;; Operand number of an input operand that is shifted. Zero if the
94;; given instruction does not shift one of its input operands.
331beb1a 95(define_attr "shift" "" (const_int 0))
96
55a94dda 97;; [For compatibility with AArch64 in pipeline models]
98;; Attribute that specifies whether or not the instruction touches fp
99;; registers.
100(define_attr "fp" "no,yes" (const_string "no"))
101
3d91c5d6 102; Floating Point Unit. If we only have floating point emulation, then there
103; is no point in scheduling the floating point insns. (Well, for best
104; performance we should try and group them together).
bffbb863 105(define_attr "fpu" "none,vfp"
c7f506fd 106 (const (symbol_ref "arm_fpu_attr")))
3d91c5d6 107
b2bcff19 108; Predicated means that the insn form is conditionally executed based on a
109; predicate. We default to 'no' because no Thumb patterns match this rule
110; and not all ARM insns do.
c7a58118 111(define_attr "predicated" "yes,no" (const_string "no"))
112
094e994f 113; LENGTH of an instruction (in bytes)
06df6b17 114(define_attr "length" ""
e1b93706 115 (const_int 4))
9c08d1fa 116
d5d4dc8d 117; The architecture which supports the instruction (or alternative).
118; This can be "a" for ARM, "t" for either of the Thumbs, "32" for
119; TARGET_32BIT, "t1" or "t2" to specify a specific Thumb mode. "v6"
120; for ARM or Thumb-2 with arm_arch6, and nov6 for ARM without
417e5cc5 121; arm_arch6. "v6t2" for Thumb-2 with arm_arch6 and "v8mb" for ARMv8-M
122; Baseline. This attribute is used to compute attribute "enabled",
123; use type "any" to enable an alternative in all cases.
124(define_attr "arch" "any,a,t,32,t1,t2,v6,nov6,v6t2,v8mb,neon_for_64bits,avoid_neon_for_64bits,iwmmxt,iwmmxt2,armv6_or_vfpv3,neon"
d5d4dc8d 125 (const_string "any"))
126
127(define_attr "arch_enabled" "no,yes"
128 (cond [(eq_attr "arch" "any")
129 (const_string "yes")
130
131 (and (eq_attr "arch" "a")
0bf497f5 132 (match_test "TARGET_ARM"))
d5d4dc8d 133 (const_string "yes")
134
135 (and (eq_attr "arch" "t")
0bf497f5 136 (match_test "TARGET_THUMB"))
d5d4dc8d 137 (const_string "yes")
138
139 (and (eq_attr "arch" "t1")
0bf497f5 140 (match_test "TARGET_THUMB1"))
d5d4dc8d 141 (const_string "yes")
142
143 (and (eq_attr "arch" "t2")
0bf497f5 144 (match_test "TARGET_THUMB2"))
d5d4dc8d 145 (const_string "yes")
146
147 (and (eq_attr "arch" "32")
0bf497f5 148 (match_test "TARGET_32BIT"))
d5d4dc8d 149 (const_string "yes")
150
151 (and (eq_attr "arch" "v6")
0bf497f5 152 (match_test "TARGET_32BIT && arm_arch6"))
d5d4dc8d 153 (const_string "yes")
154
155 (and (eq_attr "arch" "nov6")
0bf497f5 156 (match_test "TARGET_32BIT && !arm_arch6"))
a651f34d 157 (const_string "yes")
158
e4585731 159 (and (eq_attr "arch" "v6t2")
160 (match_test "TARGET_32BIT && arm_arch6 && arm_arch_thumb2"))
161 (const_string "yes")
162
417e5cc5 163 (and (eq_attr "arch" "v8mb")
164 (match_test "TARGET_THUMB1 && arm_arch8"))
165 (const_string "yes")
166
b6779ddc 167 (and (eq_attr "arch" "avoid_neon_for_64bits")
168 (match_test "TARGET_NEON")
169 (not (match_test "TARGET_PREFER_NEON_64BITS")))
a651f34d 170 (const_string "yes")
171
b6779ddc 172 (and (eq_attr "arch" "neon_for_64bits")
173 (match_test "TARGET_NEON")
174 (match_test "TARGET_PREFER_NEON_64BITS"))
6b8f7c28 175 (const_string "yes")
176
177 (and (eq_attr "arch" "iwmmxt2")
178 (match_test "TARGET_REALLY_IWMMXT2"))
21cc9773 179 (const_string "yes")
180
181 (and (eq_attr "arch" "armv6_or_vfpv3")
182 (match_test "arm_arch6 || TARGET_VFP3"))
183 (const_string "yes")
ac876af5 184
185 (and (eq_attr "arch" "neon")
186 (match_test "TARGET_NEON"))
187 (const_string "yes")
21cc9773 188 ]
6b8f7c28 189
d5d4dc8d 190 (const_string "no")))
191
aa06c51c 192(define_attr "opt" "any,speed,size"
193 (const_string "any"))
194
195(define_attr "opt_enabled" "no,yes"
196 (cond [(eq_attr "opt" "any")
197 (const_string "yes")
198
199 (and (eq_attr "opt" "speed")
200 (match_test "optimize_function_for_speed_p (cfun)"))
201 (const_string "yes")
202
203 (and (eq_attr "opt" "size")
204 (match_test "optimize_function_for_size_p (cfun)"))
205 (const_string "yes")]
206 (const_string "no")))
207
861033d5 208(define_attr "use_literal_pool" "no,yes"
209 (cond [(and (eq_attr "type" "f_loads,f_loadd")
210 (match_test "CONSTANT_P (operands[1])"))
211 (const_string "yes")]
212 (const_string "no")))
213
d5d4dc8d 214; Enable all alternatives that are both arch_enabled and insn_enabled.
951a3f72 215; FIXME:: opt_enabled has been temporarily removed till the time we have
216; an attribute that allows the use of such alternatives.
217; This depends on caching of speed_p, size_p on a per
218; alternative basis. The problem is that the enabled attribute
219; cannot depend on any state that is not cached or is not constant
220; for a compilation unit. We probably need a generic "hot/cold"
221; alternative which if implemented can help with this. We disable this
222; until such a time as this is implemented and / or the improvements or
223; regressions with removing this attribute are double checked.
224; See ashldi3_neon and <shift>di3_neon in neon.md.
225
93b431d9 226 (define_attr "enabled" "no,yes"
0abea32c 227 (cond [(and (eq_attr "predicable_short_it" "no")
c7a58118 228 (and (eq_attr "predicated" "yes")
229 (match_test "arm_restrict_it")))
230 (const_string "no")
231
232 (and (eq_attr "enabled_for_depr_it" "no")
233 (match_test "arm_restrict_it"))
234 (const_string "no")
235
861033d5 236 (and (eq_attr "use_literal_pool" "yes")
237 (match_test "arm_disable_literal_pool"))
238 (const_string "no")
239
aa06c51c 240 (eq_attr "arch_enabled" "no")
aa06c51c 241 (const_string "no")]
242 (const_string "yes")))
d5d4dc8d 243
56d27660 244; POOL_RANGE is how far away from a constant pool entry that this insn
245; can be placed. If the distance is zero, then this insn will never
246; reference the pool.
42e1de19 247; Note that for Thumb constant pools the PC value is rounded down to the
248; nearest multiple of four. Therefore, THUMB2_POOL_RANGE (and POOL_RANGE for
249; Thumb insns) should be set to <max_range> - 2.
cffb2a26 250; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
8848d797 251; before its address. It is set to <max_range> - (8 + <data_size>).
cde1623a 252(define_attr "arm_pool_range" "" (const_int 0))
253(define_attr "thumb2_pool_range" "" (const_int 0))
254(define_attr "arm_neg_pool_range" "" (const_int 0))
255(define_attr "thumb2_neg_pool_range" "" (const_int 0))
256
257(define_attr "pool_range" ""
258 (cond [(eq_attr "is_thumb" "yes") (attr "thumb2_pool_range")]
259 (attr "arm_pool_range")))
260(define_attr "neg_pool_range" ""
261 (cond [(eq_attr "is_thumb" "yes") (attr "thumb2_neg_pool_range")]
262 (attr "arm_neg_pool_range")))
56d27660 263
215b30b3 264; An assembler sequence may clobber the condition codes without us knowing.
4d7a8451 265; If such an insn references the pool, then we have no way of knowing how,
266; so use the most conservative value for pool_range.
9c08d1fa 267(define_asm_attributes
4d7a8451 268 [(set_attr "conds" "clob")
269 (set_attr "length" "4")
270 (set_attr "pool_range" "250")])
9c08d1fa 271
9888ad6d 272; Load scheduling, set from the arm_ld_sched variable
4c834714 273; initialized by arm_option_override()
9888ad6d 274(define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
849170fd 275
f7fbdd4a 276; condition codes: this one is used by final_prescan_insn to speed up
277; conditionalizing instructions. It saves having to scan the rtl to see if
278; it uses or alters the condition codes.
215b30b3 279;
f7fbdd4a 280; USE means that the condition codes are used by the insn in the process of
215b30b3 281; outputting code, this means (at present) that we can't use the insn in
282; inlined branches
283;
f7fbdd4a 284; SET means that the purpose of the insn is to set the condition codes in a
215b30b3 285; well defined manner.
286;
f7fbdd4a 287; CLOB means that the condition codes are altered in an undefined manner, if
215b30b3 288; they are altered at all
289;
ad6d3e2a 290; UNCONDITIONAL means the instruction can not be conditionally executed and
291; that the instruction does not use or alter the condition codes.
c52acdd2 292;
ad6d3e2a 293; NOCOND means that the instruction does not use or alter the condition
294; codes but can be converted into a conditionally exectuted instruction.
f7fbdd4a 295
b0694be0 296(define_attr "conds" "use,set,clob,unconditional,nocond"
747b7458 297 (if_then_else
298 (ior (eq_attr "is_thumb1" "yes")
299 (eq_attr "type" "call"))
c1a66faf 300 (const_string "clob")
32093010 301 (if_then_else (eq_attr "is_neon_type" "no")
52432540 302 (const_string "nocond")
303 (const_string "unconditional"))))
f7fbdd4a 304
215b30b3 305; Predicable means that the insn can be conditionally executed based on
306; an automatically added predicate (additional patterns are generated by
307; gen...). We default to 'no' because no Thumb patterns match this rule
308; and not all ARM patterns do.
0d66636f 309(define_attr "predicable" "no,yes" (const_string "no"))
310
129a2fe4 311; Only model the write buffer for ARM6 and ARM7. Earlier processors don't
312; have one. Later ones, such as StrongARM, have write-back caches, so don't
8d232dc7 313; suffer blockages enough to warrant modelling this (and it can adversely
129a2fe4 314; affect the schedule).
74a71f7d 315(define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_tune_wbuf")))
129a2fe4 316
215b30b3 317; WRITE_CONFLICT implies that a read following an unrelated write is likely
318; to stall the processor. Used with model_wbuf above.
9c08d1fa 319(define_attr "write_conflict" "no,yes"
320 (if_then_else (eq_attr "type"
96854199 321 "block,call,load1")
9c08d1fa 322 (const_string "yes")
323 (const_string "no")))
324
215b30b3 325; Classify the insns into those that take one cycle and those that take more
326; than one on the main cpu execution unit.
f7fbdd4a 327(define_attr "core_cycles" "single,multi"
328 (if_then_else (eq_attr "type"
112eda6f 329 "adc_imm, adc_reg, adcs_imm, adcs_reg, adr, alu_ext, alu_imm, alu_sreg,\
330 alu_shift_imm, alu_shift_reg, alu_dsp_reg, alus_ext, alus_imm, alus_sreg,\
d82e788e 331 alus_shift_imm, alus_shift_reg, bfm, csel, rev, logic_imm, logic_reg,\
332 logic_shift_imm, logic_shift_reg, logics_imm, logics_reg,\
333 logics_shift_imm, logics_shift_reg, extend, shift_imm, float, fcsel,\
7cb6c048 334 wmmx_wor, wmmx_wxor, wmmx_wand, wmmx_wandn, wmmx_wmov, wmmx_tmcrr,\
335 wmmx_tmrrc, wmmx_wldr, wmmx_wstr, wmmx_tmcr, wmmx_tmrc, wmmx_wadd,\
336 wmmx_wsub, wmmx_wmul, wmmx_wmac, wmmx_wavg2, wmmx_tinsr, wmmx_textrm,\
337 wmmx_wshufh, wmmx_wcmpeq, wmmx_wcmpgt, wmmx_wmax, wmmx_wmin, wmmx_wpack,\
338 wmmx_wunpckih, wmmx_wunpckil, wmmx_wunpckeh, wmmx_wunpckel, wmmx_wror,\
339 wmmx_wsra, wmmx_wsrl, wmmx_wsll, wmmx_wmadd, wmmx_tmia, wmmx_tmiaph,\
340 wmmx_tmiaxy, wmmx_tbcst, wmmx_tmovmsk, wmmx_wacc, wmmx_waligni,\
341 wmmx_walignr, wmmx_tandc, wmmx_textrc, wmmx_torc, wmmx_torvsc, wmmx_wsad,\
342 wmmx_wabs, wmmx_wabsdiff, wmmx_waddsubhx, wmmx_wsubaddhx, wmmx_wavg4,\
343 wmmx_wmulw, wmmx_wqmulm, wmmx_wqmulwm, wmmx_waddbhus, wmmx_wqmiaxy,\
344 wmmx_wmiaxy, wmmx_wmiawxy, wmmx_wmerge")
f7fbdd4a 345 (const_string "single")
346 (const_string "multi")))
347
cffb2a26 348;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
215b30b3 349;; distant label. Only applicable to Thumb code.
cffb2a26 350(define_attr "far_jump" "yes,no" (const_string "no"))
351
d51f92df 352
25f905c2 353;; The number of machine instructions this pattern expands to.
354;; Used for Thumb-2 conditional execution.
355(define_attr "ce_count" "" (const_int 1))
356
4182b724 357;;---------------------------------------------------------------------------
358;; Unspecs
359
360(include "unspecs.md")
361
d51f92df 362;;---------------------------------------------------------------------------
fd781bb2 363;; Mode iterators
d51f92df 364
3de0dec6 365(include "iterators.md")
03770691 366
d51f92df 367;;---------------------------------------------------------------------------
368;; Predicates
369
9c9db025 370(include "predicates.md")
234f6557 371(include "constraints.md")
9c9db025 372
a2cd141b 373;;---------------------------------------------------------------------------
374;; Pipeline descriptions
215b30b3 375
e3879fd0 376(define_attr "tune_cortexr4" "yes,no"
377 (const (if_then_else
7d3cda8c 378 (eq_attr "tune" "cortexr4,cortexr4f,cortexr5")
e3879fd0 379 (const_string "yes")
380 (const_string "no"))))
381
a2cd141b 382;; True if the generic scheduling description should be used.
383
384(define_attr "generic_sched" "yes,no"
2546d93a 385 (const (if_then_else
e18862f3 386 (ior (eq_attr "tune" "fa526,fa626,fa606te,fa626te,fmp626,fa726te,\
387 arm926ejs,arm1020e,arm1026ejs,arm1136js,\
388 arm1136jfs,cortexa5,cortexa7,cortexa8,\
42e7b263 389 cortexa9,cortexa12,cortexa15,cortexa17,\
b1099bfd 390 cortexa53,cortexa57,cortexm4,cortexm7,\
802e6377 391 exynosm1,marvell_pj4,xgene1")
2546d93a 392 (eq_attr "tune_cortexr4" "yes"))
4d5cb40d 393 (const_string "no")
394 (const_string "yes"))))
395
c0e1af52 396(define_attr "generic_vfp" "yes,no"
397 (const (if_then_else
398 (and (eq_attr "fpu" "vfp")
e18862f3 399 (eq_attr "tune" "!arm1020e,arm1022e,cortexa5,cortexa7,\
400 cortexa8,cortexa9,cortexa53,cortexm4,\
55a94dda 401 cortexm7,marvell_pj4,xgene1")
e3879fd0 402 (eq_attr "tune_cortexr4" "no"))
c0e1af52 403 (const_string "yes")
404 (const_string "no"))))
405
6b8f7c28 406(include "marvell-f-iwmmxt.md")
a2cd141b 407(include "arm-generic.md")
408(include "arm926ejs.md")
c0e1af52 409(include "arm1020e.md")
a2cd141b 410(include "arm1026ejs.md")
411(include "arm1136jfs.md")
0e266d06 412(include "fa526.md")
413(include "fa606te.md")
414(include "fa626te.md")
415(include "fmp626.md")
416(include "fa726te.md")
3f1e069f 417(include "cortex-a5.md")
d6b7f019 418(include "cortex-a7.md")
bcaec148 419(include "cortex-a8.md")
036068af 420(include "cortex-a9.md")
65f2f758 421(include "cortex-a15.md")
42e7b263 422(include "cortex-a17.md")
da10bc87 423(include "cortex-a53.md")
b1099bfd 424(include "cortex-a57.md")
934a1e72 425(include "cortex-r4.md")
e3879fd0 426(include "cortex-r4f.md")
e18862f3 427(include "cortex-m7.md")
2546d93a 428(include "cortex-m4.md")
429(include "cortex-m4-fpu.md")
802e6377 430(include "exynos-m1.md")
55e3ada8 431(include "vfp11.md")
ea7d210b 432(include "marvell-pj4.md")
55a94dda 433(include "xgene1.md")
3586df96 434
9c08d1fa 435\f
215b30b3 436;;---------------------------------------------------------------------------
e1159bbe 437;; Insn patterns
438;;
a0f94409 439;; Addition insns.
215b30b3 440
9c08d1fa 441;; Note: For DImode insns, there is normally no reason why operands should
442;; not be in the same register, what we don't want is for something being
443;; written to partially overlap something that is an input.
444
cffb2a26 445(define_expand "adddi3"
446 [(parallel
215b30b3 447 [(set (match_operand:DI 0 "s_register_operand" "")
cffb2a26 448 (plus:DI (match_operand:DI 1 "s_register_operand" "")
10e5ccd5 449 (match_operand:DI 2 "arm_adddi_operand" "")))
bd5b4116 450 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 451 "TARGET_EITHER"
452 "
25f905c2 453 if (TARGET_THUMB1)
cffb2a26 454 {
0438d37f 455 if (!REG_P (operands[1]))
bc5a93af 456 operands[1] = force_reg (DImode, operands[1]);
0438d37f 457 if (!REG_P (operands[2]))
bc5a93af 458 operands[2] = force_reg (DImode, operands[2]);
cffb2a26 459 }
460 "
461)
462
a0f94409 463(define_insn_and_split "*arm_adddi3"
10e5ccd5 464 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r,&r,&r")
465 (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0, r, 0, r")
466 (match_operand:DI 2 "arm_adddi_operand" "r, 0, r, Dd, Dd")))
bd5b4116 467 (clobber (reg:CC CC_REGNUM))]
b805622c 468 "TARGET_32BIT && !TARGET_NEON"
33782ec7 469 "#"
94829feb 470 "TARGET_32BIT && reload_completed
471 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))"
a0f94409 472 [(parallel [(set (reg:CC_C CC_REGNUM)
473 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
474 (match_dup 1)))
475 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 476 (set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (match_dup 5))
477 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
a0f94409 478 "
479 {
480 operands[3] = gen_highpart (SImode, operands[0]);
481 operands[0] = gen_lowpart (SImode, operands[0]);
482 operands[4] = gen_highpart (SImode, operands[1]);
483 operands[1] = gen_lowpart (SImode, operands[1]);
10e5ccd5 484 operands[5] = gen_highpart_mode (SImode, DImode, operands[2]);
a0f94409 485 operands[2] = gen_lowpart (SImode, operands[2]);
486 }"
cffb2a26 487 [(set_attr "conds" "clob")
1b7da4ac 488 (set_attr "length" "8")
489 (set_attr "type" "multiple")]
cffb2a26 490)
9c08d1fa 491
a0f94409 492(define_insn_and_split "*adddi_sesidi_di"
9c08d1fa 493 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
494 (plus:DI (sign_extend:DI
97499065 495 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 496 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 497 (clobber (reg:CC CC_REGNUM))]
b805622c 498 "TARGET_32BIT"
33782ec7 499 "#"
25f905c2 500 "TARGET_32BIT && reload_completed"
a0f94409 501 [(parallel [(set (reg:CC_C CC_REGNUM)
502 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
503 (match_dup 1)))
504 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 505 (set (match_dup 3) (plus:SI (plus:SI (ashiftrt:SI (match_dup 2)
a0f94409 506 (const_int 31))
080c0b9a 507 (match_dup 4))
508 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
a0f94409 509 "
510 {
511 operands[3] = gen_highpart (SImode, operands[0]);
512 operands[0] = gen_lowpart (SImode, operands[0]);
513 operands[4] = gen_highpart (SImode, operands[1]);
514 operands[1] = gen_lowpart (SImode, operands[1]);
515 operands[2] = gen_lowpart (SImode, operands[2]);
516 }"
215b30b3 517 [(set_attr "conds" "clob")
1b7da4ac 518 (set_attr "length" "8")
519 (set_attr "type" "multiple")]
215b30b3 520)
9c08d1fa 521
a0f94409 522(define_insn_and_split "*adddi_zesidi_di"
9c08d1fa 523 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
524 (plus:DI (zero_extend:DI
97499065 525 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 526 (match_operand:DI 1 "s_register_operand" "0,r")))
a0f94409 527 (clobber (reg:CC CC_REGNUM))]
b805622c 528 "TARGET_32BIT"
33782ec7 529 "#"
25f905c2 530 "TARGET_32BIT && reload_completed"
a0f94409 531 [(parallel [(set (reg:CC_C CC_REGNUM)
532 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
533 (match_dup 1)))
534 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 535 (set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (const_int 0))
536 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
a0f94409 537 "
538 {
539 operands[3] = gen_highpart (SImode, operands[0]);
540 operands[0] = gen_lowpart (SImode, operands[0]);
541 operands[4] = gen_highpart (SImode, operands[1]);
542 operands[1] = gen_lowpart (SImode, operands[1]);
543 operands[2] = gen_lowpart (SImode, operands[2]);
544 }"
cffb2a26 545 [(set_attr "conds" "clob")
1b7da4ac 546 (set_attr "length" "8")
547 (set_attr "type" "multiple")]
cffb2a26 548)
b11cae9e 549
f6c98a9a 550(define_expand "addv<mode>4"
551 [(match_operand:SIDI 0 "register_operand")
552 (match_operand:SIDI 1 "register_operand")
553 (match_operand:SIDI 2 "register_operand")
554 (match_operand 3 "")]
555 "TARGET_32BIT"
556{
557 emit_insn (gen_add<mode>3_compareV (operands[0], operands[1], operands[2]));
558 arm_gen_unlikely_cbranch (NE, CC_Vmode, operands[3]);
559
560 DONE;
561})
562
563(define_expand "uaddv<mode>4"
564 [(match_operand:SIDI 0 "register_operand")
565 (match_operand:SIDI 1 "register_operand")
566 (match_operand:SIDI 2 "register_operand")
567 (match_operand 3 "")]
568 "TARGET_32BIT"
569{
570 emit_insn (gen_add<mode>3_compareC (operands[0], operands[1], operands[2]));
571 arm_gen_unlikely_cbranch (NE, CC_Cmode, operands[3]);
572
573 DONE;
574})
575
87b22bf7 576(define_expand "addsi3"
cffb2a26 577 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 578 (plus:SI (match_operand:SI 1 "s_register_operand" "")
579 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 580 "TARGET_EITHER"
87b22bf7 581 "
0438d37f 582 if (TARGET_32BIT && CONST_INT_P (operands[2]))
87b22bf7 583 {
96f57e36 584 arm_split_constant (PLUS, SImode, NULL_RTX,
585 INTVAL (operands[2]), operands[0], operands[1],
e1ba4a27 586 optimize && can_create_pseudo_p ());
87b22bf7 587 DONE;
588 }
cffb2a26 589 "
590)
87b22bf7 591
5bd751ff 592; If there is a scratch available, this will be faster than synthesizing the
a0f94409 593; addition.
594(define_peephole2
595 [(match_scratch:SI 3 "r")
372575c7 596 (set (match_operand:SI 0 "arm_general_register_operand" "")
597 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
cffb2a26 598 (match_operand:SI 2 "const_int_operand" "")))]
25f905c2 599 "TARGET_32BIT &&
a0f94409 600 !(const_ok_for_arm (INTVAL (operands[2]))
601 || const_ok_for_arm (-INTVAL (operands[2])))
602 && const_ok_for_arm (~INTVAL (operands[2]))"
603 [(set (match_dup 3) (match_dup 2))
604 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
605 ""
606)
87b22bf7 607
2f02c19f 608;; The r/r/k alternative is required when reloading the address
609;; (plus (reg rN) (reg sp)) into (reg rN). In this case reload will
610;; put the duplicated register first, and not try the commutative version.
a0f94409 611(define_insn_and_split "*arm_addsi3"
fa1f9c9e 612 [(set (match_operand:SI 0 "s_register_operand" "=rk,l,l ,l ,r ,k ,r,k ,r ,k ,r ,k,k,r ,k ,r")
613 (plus:SI (match_operand:SI 1 "s_register_operand" "%0 ,l,0 ,l ,rk,k ,r,r ,rk,k ,rk,k,r,rk,k ,rk")
614 (match_operand:SI 2 "reg_or_int_operand" "rk ,l,Py,Pd,rI,rI,k,rI,Pj,Pj,L ,L,L,PJ,PJ,?n")))]
25f905c2 615 "TARGET_32BIT"
5565501b 616 "@
c24d855d 617 add%?\\t%0, %0, %2
5565501b 618 add%?\\t%0, %1, %2
a0b3420a 619 add%?\\t%0, %1, %2
7c36fe71 620 add%?\\t%0, %1, %2
621 add%?\\t%0, %1, %2
aaa37ad6 622 add%?\\t%0, %1, %2
2f02c19f 623 add%?\\t%0, %2, %1
fa1f9c9e 624 add%?\\t%0, %1, %2
d5cbae34 625 addw%?\\t%0, %1, %2
626 addw%?\\t%0, %1, %2
aaa37ad6 627 sub%?\\t%0, %1, #%n2
87b22bf7 628 sub%?\\t%0, %1, #%n2
d7757711 629 sub%?\\t%0, %1, #%n2
d5cbae34 630 subw%?\\t%0, %1, #%n2
631 subw%?\\t%0, %1, #%n2
87b22bf7 632 #"
a3ffc315 633 "TARGET_32BIT
0438d37f 634 && CONST_INT_P (operands[2])
d5cbae34 635 && !const_ok_for_op (INTVAL (operands[2]), PLUS)
a3ffc315 636 && (reload_completed || !arm_eliminable_register (operands[1]))"
a0f94409 637 [(clobber (const_int 0))]
638 "
96f57e36 639 arm_split_constant (PLUS, SImode, curr_insn,
640 INTVAL (operands[2]), operands[0],
a0f94409 641 operands[1], 0);
642 DONE;
643 "
fa1f9c9e 644 [(set_attr "length" "2,4,4,4,4,4,4,4,4,4,4,4,4,4,4,16")
d5cbae34 645 (set_attr "predicable" "yes")
fa1f9c9e 646 (set_attr "predicable_short_it" "yes,yes,yes,yes,no,no,no,no,no,no,no,no,no,no,no,no")
647 (set_attr "arch" "t2,t2,t2,t2,*,*,*,a,t2,t2,*,*,a,t2,t2,*")
65f68e55 648 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
d82e788e 649 (const_string "alu_imm")
112eda6f 650 (const_string "alu_sreg")))
65f68e55 651 ]
cffb2a26 652)
653
f6c98a9a 654(define_insn_and_split "adddi3_compareV"
655 [(set (reg:CC_V CC_REGNUM)
656 (ne:CC_V
657 (plus:TI
658 (sign_extend:TI (match_operand:DI 1 "register_operand" "r"))
659 (sign_extend:TI (match_operand:DI 2 "register_operand" "r")))
660 (sign_extend:TI (plus:DI (match_dup 1) (match_dup 2)))))
661 (set (match_operand:DI 0 "register_operand" "=&r")
662 (plus:DI (match_dup 1) (match_dup 2)))]
663 "TARGET_32BIT"
664 "#"
665 "&& reload_completed"
666 [(parallel [(set (reg:CC_C CC_REGNUM)
667 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
668 (match_dup 1)))
669 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
670 (parallel [(set (reg:CC_V CC_REGNUM)
671 (ne:CC_V
672 (plus:DI (plus:DI
673 (sign_extend:DI (match_dup 4))
674 (sign_extend:DI (match_dup 5)))
675 (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0)))
676 (plus:DI (sign_extend:DI
677 (plus:SI (match_dup 4) (match_dup 5)))
678 (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0)))))
679 (set (match_dup 3) (plus:SI (plus:SI
680 (match_dup 4) (match_dup 5))
681 (ltu:SI (reg:CC_C CC_REGNUM)
682 (const_int 0))))])]
683 "
684 {
685 operands[3] = gen_highpart (SImode, operands[0]);
686 operands[0] = gen_lowpart (SImode, operands[0]);
687 operands[4] = gen_highpart (SImode, operands[1]);
688 operands[1] = gen_lowpart (SImode, operands[1]);
689 operands[5] = gen_highpart (SImode, operands[2]);
690 operands[2] = gen_lowpart (SImode, operands[2]);
691 }"
692 [(set_attr "conds" "set")
693 (set_attr "length" "8")
694 (set_attr "type" "multiple")]
695)
696
697(define_insn "addsi3_compareV"
698 [(set (reg:CC_V CC_REGNUM)
699 (ne:CC_V
700 (plus:DI
701 (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
702 (sign_extend:DI (match_operand:SI 2 "register_operand" "r")))
703 (sign_extend:DI (plus:SI (match_dup 1) (match_dup 2)))))
704 (set (match_operand:SI 0 "register_operand" "=r")
705 (plus:SI (match_dup 1) (match_dup 2)))]
706 "TARGET_32BIT"
707 "adds%?\\t%0, %1, %2"
708 [(set_attr "conds" "set")
709 (set_attr "type" "alus_sreg")]
710)
711
712(define_insn "*addsi3_compareV_upper"
713 [(set (reg:CC_V CC_REGNUM)
714 (ne:CC_V
715 (plus:DI
716 (plus:DI
717 (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
718 (sign_extend:DI (match_operand:SI 2 "register_operand" "r")))
719 (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0)))
720 (plus:DI (sign_extend:DI
721 (plus:SI (match_dup 1) (match_dup 2)))
722 (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0)))))
723 (set (match_operand:SI 0 "register_operand" "=r")
724 (plus:SI
725 (plus:SI (match_dup 1) (match_dup 2))
726 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
727 "TARGET_32BIT"
728 "adcs%?\\t%0, %1, %2"
729 [(set_attr "conds" "set")
730 (set_attr "type" "adcs_reg")]
731)
732
733(define_insn_and_split "adddi3_compareC"
734 [(set (reg:CC_C CC_REGNUM)
735 (ne:CC_C
736 (plus:TI
737 (zero_extend:TI (match_operand:DI 1 "register_operand" "r"))
738 (zero_extend:TI (match_operand:DI 2 "register_operand" "r")))
739 (zero_extend:TI (plus:DI (match_dup 1) (match_dup 2)))))
740 (set (match_operand:DI 0 "register_operand" "=&r")
741 (plus:DI (match_dup 1) (match_dup 2)))]
742 "TARGET_32BIT"
743 "#"
744 "&& reload_completed"
745 [(parallel [(set (reg:CC_C CC_REGNUM)
746 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
747 (match_dup 1)))
748 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
749 (parallel [(set (reg:CC_C CC_REGNUM)
750 (ne:CC_C
751 (plus:DI (plus:DI
752 (zero_extend:DI (match_dup 4))
753 (zero_extend:DI (match_dup 5)))
754 (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0)))
755 (plus:DI (zero_extend:DI
756 (plus:SI (match_dup 4) (match_dup 5)))
757 (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0)))))
758 (set (match_dup 3) (plus:SI
759 (plus:SI (match_dup 4) (match_dup 5))
760 (ltu:SI (reg:CC_C CC_REGNUM)
761 (const_int 0))))])]
762 "
763 {
764 operands[3] = gen_highpart (SImode, operands[0]);
765 operands[0] = gen_lowpart (SImode, operands[0]);
766 operands[4] = gen_highpart (SImode, operands[1]);
767 operands[5] = gen_highpart (SImode, operands[2]);
768 operands[1] = gen_lowpart (SImode, operands[1]);
769 operands[2] = gen_lowpart (SImode, operands[2]);
770 }"
771 [(set_attr "conds" "set")
772 (set_attr "length" "8")
773 (set_attr "type" "multiple")]
774)
775
776(define_insn "*addsi3_compareC_upper"
777 [(set (reg:CC_C CC_REGNUM)
778 (ne:CC_C
779 (plus:DI
780 (plus:DI
781 (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
782 (zero_extend:DI (match_operand:SI 2 "register_operand" "r")))
783 (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0)))
784 (plus:DI (zero_extend:DI
785 (plus:SI (match_dup 1) (match_dup 2)))
786 (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0)))))
787 (set (match_operand:SI 0 "register_operand" "=r")
788 (plus:SI
789 (plus:SI (match_dup 1) (match_dup 2))
790 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
791 "TARGET_32BIT"
792 "adcs%?\\t%0, %1, %2"
793 [(set_attr "conds" "set")
794 (set_attr "type" "adcs_reg")]
795)
796
797(define_insn "addsi3_compareC"
798 [(set (reg:CC_C CC_REGNUM)
799 (ne:CC_C
800 (plus:DI
801 (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
802 (zero_extend:DI (match_operand:SI 2 "register_operand" "r")))
803 (zero_extend:DI
804 (plus:SI (match_dup 1) (match_dup 2)))))
805 (set (match_operand:SI 0 "register_operand" "=r")
806 (plus:SI (match_dup 1) (match_dup 2)))]
807 "TARGET_32BIT"
808 "adds%?\\t%0, %1, %2"
809 [(set_attr "conds" "set")
810 (set_attr "type" "alus_sreg")]
811)
812
90c2bcf0 813(define_insn "addsi3_compare0"
bd5b4116 814 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 815 (compare:CC_NOOV
65f68e55 816 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r,r")
817 (match_operand:SI 2 "arm_add_operand" "I,L,r"))
5565501b 818 (const_int 0)))
65f68e55 819 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9c08d1fa 820 (plus:SI (match_dup 1) (match_dup 2)))]
ec792a7b 821 "TARGET_ARM"
5565501b 822 "@
3ef90e77 823 adds%?\\t%0, %1, %2
824 subs%?\\t%0, %1, #%n2
825 adds%?\\t%0, %1, %2"
65f68e55 826 [(set_attr "conds" "set")
112eda6f 827 (set_attr "type" "alus_imm,alus_imm,alus_sreg")]
cffb2a26 828)
9c08d1fa 829
aea4c774 830(define_insn "*addsi3_compare0_scratch"
bd5b4116 831 [(set (reg:CC_NOOV CC_REGNUM)
aea4c774 832 (compare:CC_NOOV
65f68e55 833 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r, r")
834 (match_operand:SI 1 "arm_add_operand" "I,L, r"))
aea4c774 835 (const_int 0)))]
ec792a7b 836 "TARGET_ARM"
cffb2a26 837 "@
838 cmn%?\\t%0, %1
65f68e55 839 cmp%?\\t%0, #%n1
840 cmn%?\\t%0, %1"
596e5e8f 841 [(set_attr "conds" "set")
65f68e55 842 (set_attr "predicable" "yes")
112eda6f 843 (set_attr "type" "alus_imm,alus_imm,alus_sreg")]
0d66636f 844)
cffb2a26 845
aed179ae 846(define_insn "*compare_negsi_si"
847 [(set (reg:CC_Z CC_REGNUM)
848 (compare:CC_Z
7c36fe71 849 (neg:SI (match_operand:SI 0 "s_register_operand" "l,r"))
850 (match_operand:SI 1 "s_register_operand" "l,r")))]
25f905c2 851 "TARGET_32BIT"
aed179ae 852 "cmn%?\\t%1, %0"
596e5e8f 853 [(set_attr "conds" "set")
7c36fe71 854 (set_attr "predicable" "yes")
855 (set_attr "arch" "t2,*")
856 (set_attr "length" "2,4")
1b7da4ac 857 (set_attr "predicable_short_it" "yes,no")
112eda6f 858 (set_attr "type" "alus_sreg")]
0d66636f 859)
aea4c774 860
203c488f 861;; This is the canonicalization of addsi3_compare0_for_combiner when the
862;; addend is a constant.
190efb17 863(define_insn "cmpsi2_addneg"
203c488f 864 [(set (reg:CC CC_REGNUM)
865 (compare:CC
866 (match_operand:SI 1 "s_register_operand" "r,r")
2a977b78 867 (match_operand:SI 2 "arm_addimm_operand" "L,I")))
203c488f 868 (set (match_operand:SI 0 "s_register_operand" "=r,r")
869 (plus:SI (match_dup 1)
2a977b78 870 (match_operand:SI 3 "arm_addimm_operand" "I,L")))]
25f905c2 871 "TARGET_32BIT && INTVAL (operands[2]) == -INTVAL (operands[3])"
203c488f 872 "@
3ef90e77 873 adds%?\\t%0, %1, %3
874 subs%?\\t%0, %1, #%n3"
1b7da4ac 875 [(set_attr "conds" "set")
112eda6f 876 (set_attr "type" "alus_sreg")]
203c488f 877)
878
879;; Convert the sequence
880;; sub rd, rn, #1
881;; cmn rd, #1 (equivalent to cmp rd, #-1)
882;; bne dest
883;; into
884;; subs rd, rn, #1
885;; bcs dest ((unsigned)rn >= 1)
886;; similarly for the beq variant using bcc.
887;; This is a common looping idiom (while (n--))
888(define_peephole2
372575c7 889 [(set (match_operand:SI 0 "arm_general_register_operand" "")
890 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
203c488f 891 (const_int -1)))
892 (set (match_operand 2 "cc_register" "")
893 (compare (match_dup 0) (const_int -1)))
894 (set (pc)
895 (if_then_else (match_operator 3 "equality_operator"
896 [(match_dup 2) (const_int 0)])
897 (match_operand 4 "" "")
898 (match_operand 5 "" "")))]
25f905c2 899 "TARGET_32BIT && peep2_reg_dead_p (3, operands[2])"
203c488f 900 [(parallel[
901 (set (match_dup 2)
902 (compare:CC
903 (match_dup 1) (const_int 1)))
904 (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
905 (set (pc)
906 (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
907 (match_dup 4)
908 (match_dup 5)))]
909 "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
910 operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
911 ? GEU : LTU),
912 VOIDmode,
913 operands[2], const0_rtx);"
914)
915
ebcc79bc 916;; The next four insns work because they compare the result with one of
917;; the operands, and we know that the use of the condition code is
918;; either GEU or LTU, so we can use the carry flag from the addition
919;; instead of doing the compare a second time.
920(define_insn "*addsi3_compare_op1"
bd5b4116 921 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 922 (compare:CC_C
65f68e55 923 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
924 (match_operand:SI 2 "arm_add_operand" "I,L,r"))
ebcc79bc 925 (match_dup 1)))
65f68e55 926 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
ebcc79bc 927 (plus:SI (match_dup 1) (match_dup 2)))]
25f905c2 928 "TARGET_32BIT"
ebcc79bc 929 "@
3ef90e77 930 adds%?\\t%0, %1, %2
931 subs%?\\t%0, %1, #%n2
932 adds%?\\t%0, %1, %2"
65f68e55 933 [(set_attr "conds" "set")
112eda6f 934 (set_attr "type" "alus_imm,alus_imm,alus_sreg")]
0d66636f 935)
ebcc79bc 936
937(define_insn "*addsi3_compare_op2"
bd5b4116 938 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 939 (compare:CC_C
65f68e55 940 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
941 (match_operand:SI 2 "arm_add_operand" "I,L,r"))
ebcc79bc 942 (match_dup 2)))
65f68e55 943 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9c08d1fa 944 (plus:SI (match_dup 1) (match_dup 2)))]
25f905c2 945 "TARGET_32BIT"
5565501b 946 "@
3ef90e77 947 adds%?\\t%0, %1, %2
38128b57 948 subs%?\\t%0, %1, #%n2
949 adds%?\\t%0, %1, %2"
65f68e55 950 [(set_attr "conds" "set")
112eda6f 951 (set_attr "type" "alus_imm,alus_imm,alus_sreg")]
0d66636f 952)
9c08d1fa 953
ebcc79bc 954(define_insn "*compare_addsi2_op0"
bd5b4116 955 [(set (reg:CC_C CC_REGNUM)
7c36fe71 956 (compare:CC_C
957 (plus:SI (match_operand:SI 0 "s_register_operand" "l,l,r,r,r")
958 (match_operand:SI 1 "arm_add_operand" "Pv,l,I,L,r"))
959 (match_dup 0)))]
25f905c2 960 "TARGET_32BIT"
ebcc79bc 961 "@
7c36fe71 962 cmp%?\\t%0, #%n1
963 cmn%?\\t%0, %1
ebcc79bc 964 cmn%?\\t%0, %1
65f68e55 965 cmp%?\\t%0, #%n1
966 cmn%?\\t%0, %1"
596e5e8f 967 [(set_attr "conds" "set")
65f68e55 968 (set_attr "predicable" "yes")
7c36fe71 969 (set_attr "arch" "t2,t2,*,*,*")
970 (set_attr "predicable_short_it" "yes,yes,no,no,no")
971 (set_attr "length" "2,2,4,4,4")
112eda6f 972 (set_attr "type" "alus_imm,alus_sreg,alus_imm,alus_imm,alus_sreg")]
0d66636f 973)
ebcc79bc 974
975(define_insn "*compare_addsi2_op1"
bd5b4116 976 [(set (reg:CC_C CC_REGNUM)
7c36fe71 977 (compare:CC_C
978 (plus:SI (match_operand:SI 0 "s_register_operand" "l,l,r,r,r")
979 (match_operand:SI 1 "arm_add_operand" "Pv,l,I,L,r"))
980 (match_dup 1)))]
25f905c2 981 "TARGET_32BIT"
ebcc79bc 982 "@
7c36fe71 983 cmp%?\\t%0, #%n1
984 cmn%?\\t%0, %1
ebcc79bc 985 cmn%?\\t%0, %1
65f68e55 986 cmp%?\\t%0, #%n1
987 cmn%?\\t%0, %1"
596e5e8f 988 [(set_attr "conds" "set")
65f68e55 989 (set_attr "predicable" "yes")
7c36fe71 990 (set_attr "arch" "t2,t2,*,*,*")
991 (set_attr "predicable_short_it" "yes,yes,no,no,no")
992 (set_attr "length" "2,2,4,4,4")
112eda6f 993 (set_attr "type" "alus_imm,alus_sreg,alus_imm,alus_imm,alus_sreg")]
7c36fe71 994 )
ebcc79bc 995
080c0b9a 996(define_insn "*addsi3_carryin_<optab>"
7c36fe71 997 [(set (match_operand:SI 0 "s_register_operand" "=l,r,r")
998 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%l,r,r")
999 (match_operand:SI 2 "arm_not_operand" "0,rI,K"))
1000 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))]
25f905c2 1001 "TARGET_32BIT"
10e5ccd5 1002 "@
a0b3420a 1003 adc%?\\t%0, %1, %2
10e5ccd5 1004 adc%?\\t%0, %1, %2
1005 sbc%?\\t%0, %1, #%B2"
a7de272d 1006 [(set_attr "conds" "use")
7c36fe71 1007 (set_attr "predicable" "yes")
1008 (set_attr "arch" "t2,*,*")
1009 (set_attr "length" "4")
1b7da4ac 1010 (set_attr "predicable_short_it" "yes,no,no")
1011 (set_attr "type" "adc_reg,adc_reg,adc_imm")]
cffb2a26 1012)
ebcc79bc 1013
080c0b9a 1014(define_insn "*addsi3_carryin_alt2_<optab>"
7c36fe71 1015 [(set (match_operand:SI 0 "s_register_operand" "=l,r,r")
1016 (plus:SI (plus:SI (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))
1017 (match_operand:SI 1 "s_register_operand" "%l,r,r"))
1018 (match_operand:SI 2 "arm_rhs_operand" "l,rI,K")))]
25f905c2 1019 "TARGET_32BIT"
10e5ccd5 1020 "@
a0b3420a 1021 adc%?\\t%0, %1, %2
10e5ccd5 1022 adc%?\\t%0, %1, %2
1023 sbc%?\\t%0, %1, #%B2"
a7de272d 1024 [(set_attr "conds" "use")
7c36fe71 1025 (set_attr "predicable" "yes")
1026 (set_attr "arch" "t2,*,*")
1027 (set_attr "length" "4")
1b7da4ac 1028 (set_attr "predicable_short_it" "yes,no,no")
1029 (set_attr "type" "adc_reg,adc_reg,adc_imm")]
0d66636f 1030)
ebcc79bc 1031
080c0b9a 1032(define_insn "*addsi3_carryin_shift_<optab>"
ebcc79bc 1033 [(set (match_operand:SI 0 "s_register_operand" "=r")
080c0b9a 1034 (plus:SI (plus:SI
1035 (match_operator:SI 2 "shift_operator"
1036 [(match_operand:SI 3 "s_register_operand" "r")
1037 (match_operand:SI 4 "reg_or_int_operand" "rM")])
1038 (match_operand:SI 1 "s_register_operand" "r"))
1039 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))]
25f905c2 1040 "TARGET_32BIT"
080c0b9a 1041 "adc%?\\t%0, %1, %3%S2"
1042 [(set_attr "conds" "use")
a7de272d 1043 (set_attr "predicable" "yes")
7c36fe71 1044 (set_attr "predicable_short_it" "no")
080c0b9a 1045 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
d82e788e 1046 (const_string "alu_shift_imm")
1047 (const_string "alu_shift_reg")))]
cffb2a26 1048)
ebcc79bc 1049
922b6913 1050(define_insn "*addsi3_carryin_clobercc_<optab>"
1051 [(set (match_operand:SI 0 "s_register_operand" "=r")
1052 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%r")
1053 (match_operand:SI 2 "arm_rhs_operand" "rI"))
1054 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))
1055 (clobber (reg:CC CC_REGNUM))]
1056 "TARGET_32BIT"
3ef90e77 1057 "adcs%?\\t%0, %1, %2"
1b7da4ac 1058 [(set_attr "conds" "set")
1059 (set_attr "type" "adcs_reg")]
922b6913 1060)
1061
f6c98a9a 1062(define_expand "subv<mode>4"
1063 [(match_operand:SIDI 0 "register_operand")
1064 (match_operand:SIDI 1 "register_operand")
1065 (match_operand:SIDI 2 "register_operand")
1066 (match_operand 3 "")]
1067 "TARGET_32BIT"
1068{
1069 emit_insn (gen_sub<mode>3_compare1 (operands[0], operands[1], operands[2]));
1070 arm_gen_unlikely_cbranch (NE, CC_Vmode, operands[3]);
1071
1072 DONE;
1073})
1074
1075(define_expand "usubv<mode>4"
1076 [(match_operand:SIDI 0 "register_operand")
1077 (match_operand:SIDI 1 "register_operand")
1078 (match_operand:SIDI 2 "register_operand")
1079 (match_operand 3 "")]
1080 "TARGET_32BIT"
1081{
1082 emit_insn (gen_sub<mode>3_compare1 (operands[0], operands[1], operands[2]));
1083 arm_gen_unlikely_cbranch (LTU, CCmode, operands[3]);
1084
1085 DONE;
1086})
1087
1088(define_insn_and_split "subdi3_compare1"
1089 [(set (reg:CC CC_REGNUM)
1090 (compare:CC
1091 (match_operand:DI 1 "register_operand" "r")
1092 (match_operand:DI 2 "register_operand" "r")))
1093 (set (match_operand:DI 0 "register_operand" "=&r")
1094 (minus:DI (match_dup 1) (match_dup 2)))]
1095 "TARGET_32BIT"
1096 "#"
1097 "&& reload_completed"
1098 [(parallel [(set (reg:CC CC_REGNUM)
1099 (compare:CC (match_dup 1) (match_dup 2)))
1100 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1101 (parallel [(set (reg:CC CC_REGNUM)
1102 (compare:CC (match_dup 4) (match_dup 5)))
1103 (set (match_dup 3) (minus:SI (minus:SI (match_dup 4) (match_dup 5))
1104 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))])]
1105 {
1106 operands[3] = gen_highpart (SImode, operands[0]);
1107 operands[0] = gen_lowpart (SImode, operands[0]);
1108 operands[4] = gen_highpart (SImode, operands[1]);
1109 operands[1] = gen_lowpart (SImode, operands[1]);
1110 operands[5] = gen_highpart (SImode, operands[2]);
1111 operands[2] = gen_lowpart (SImode, operands[2]);
1112 }
1113 [(set_attr "conds" "set")
1114 (set_attr "length" "8")
1115 (set_attr "type" "multiple")]
1116)
1117
1118(define_insn "subsi3_compare1"
1119 [(set (reg:CC CC_REGNUM)
1120 (compare:CC
1121 (match_operand:SI 1 "register_operand" "r")
1122 (match_operand:SI 2 "register_operand" "r")))
1123 (set (match_operand:SI 0 "register_operand" "=r")
1124 (minus:SI (match_dup 1) (match_dup 2)))]
1125 "TARGET_32BIT"
1126 "subs%?\\t%0, %1, %2"
1127 [(set_attr "conds" "set")
1128 (set_attr "type" "alus_sreg")]
1129)
1130
9154bd82 1131(define_insn "*subsi3_carryin"
1132 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1133 (minus:SI (minus:SI (match_operand:SI 1 "reg_or_int_operand" "r,I")
1134 (match_operand:SI 2 "s_register_operand" "r,r"))
1135 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1136 "TARGET_32BIT"
1137 "@
1138 sbc%?\\t%0, %1, %2
1139 rsc%?\\t%0, %2, %1"
1140 [(set_attr "conds" "use")
1141 (set_attr "arch" "*,a")
7c36fe71 1142 (set_attr "predicable" "yes")
1b7da4ac 1143 (set_attr "predicable_short_it" "no")
1144 (set_attr "type" "adc_reg,adc_imm")]
9154bd82 1145)
1146
1147(define_insn "*subsi3_carryin_const"
1148 [(set (match_operand:SI 0 "s_register_operand" "=r")
df46fd5e 1149 (minus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1150 (match_operand:SI 2 "arm_not_immediate_operand" "K"))
9154bd82 1151 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1152 "TARGET_32BIT"
1153 "sbc\\t%0, %1, #%B2"
1b7da4ac 1154 [(set_attr "conds" "use")
1155 (set_attr "type" "adc_imm")]
9154bd82 1156)
1157
1158(define_insn "*subsi3_carryin_compare"
1159 [(set (reg:CC CC_REGNUM)
1160 (compare:CC (match_operand:SI 1 "s_register_operand" "r")
1161 (match_operand:SI 2 "s_register_operand" "r")))
1162 (set (match_operand:SI 0 "s_register_operand" "=r")
1163 (minus:SI (minus:SI (match_dup 1)
1164 (match_dup 2))
1165 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1166 "TARGET_32BIT"
1167 "sbcs\\t%0, %1, %2"
1b7da4ac 1168 [(set_attr "conds" "set")
1169 (set_attr "type" "adcs_reg")]
9154bd82 1170)
1171
1172(define_insn "*subsi3_carryin_compare_const"
1173 [(set (reg:CC CC_REGNUM)
1174 (compare:CC (match_operand:SI 1 "reg_or_int_operand" "r")
1175 (match_operand:SI 2 "arm_not_operand" "K")))
1176 (set (match_operand:SI 0 "s_register_operand" "=r")
1177 (minus:SI (plus:SI (match_dup 1)
1178 (match_dup 2))
1179 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1180 "TARGET_32BIT"
1181 "sbcs\\t%0, %1, #%B2"
1b7da4ac 1182 [(set_attr "conds" "set")
1183 (set_attr "type" "adcs_imm")]
9154bd82 1184)
1185
1186(define_insn "*subsi3_carryin_shift"
1187 [(set (match_operand:SI 0 "s_register_operand" "=r")
1188 (minus:SI (minus:SI
1189 (match_operand:SI 1 "s_register_operand" "r")
1190 (match_operator:SI 2 "shift_operator"
1191 [(match_operand:SI 3 "s_register_operand" "r")
1192 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
1193 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1194 "TARGET_32BIT"
1195 "sbc%?\\t%0, %1, %3%S2"
1196 [(set_attr "conds" "use")
1197 (set_attr "predicable" "yes")
1198 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
d82e788e 1199 (const_string "alu_shift_imm")
1200 (const_string "alu_shift_reg")))]
9154bd82 1201)
1202
1203(define_insn "*rsbsi3_carryin_shift"
1204 [(set (match_operand:SI 0 "s_register_operand" "=r")
1205 (minus:SI (minus:SI
1206 (match_operator:SI 2 "shift_operator"
1207 [(match_operand:SI 3 "s_register_operand" "r")
1208 (match_operand:SI 4 "reg_or_int_operand" "rM")])
1209 (match_operand:SI 1 "s_register_operand" "r"))
1210 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1211 "TARGET_ARM"
1212 "rsc%?\\t%0, %1, %3%S2"
1213 [(set_attr "conds" "use")
1214 (set_attr "predicable" "yes")
1215 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
d82e788e 1216 (const_string "alu_shift_imm")
1217 (const_string "alu_shift_reg")))]
9154bd82 1218)
1219
d795fb69 1220; transform ((x << y) - 1) to ~(~(x-1) << y) Where X is a constant.
1221(define_split
1222 [(set (match_operand:SI 0 "s_register_operand" "")
1223 (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
1224 (match_operand:SI 2 "s_register_operand" ""))
1225 (const_int -1)))
1226 (clobber (match_operand:SI 3 "s_register_operand" ""))]
25f905c2 1227 "TARGET_32BIT"
d795fb69 1228 [(set (match_dup 3) (match_dup 1))
1229 (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
1230 "
1231 operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
1232")
1233
604f3a0a 1234(define_expand "addsf3"
1235 [(set (match_operand:SF 0 "s_register_operand" "")
1236 (plus:SF (match_operand:SF 1 "s_register_operand" "")
d86c91f6 1237 (match_operand:SF 2 "s_register_operand" "")))]
25f905c2 1238 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1239 "
604f3a0a 1240")
1241
604f3a0a 1242(define_expand "adddf3"
1243 [(set (match_operand:DF 0 "s_register_operand" "")
1244 (plus:DF (match_operand:DF 1 "s_register_operand" "")
d86c91f6 1245 (match_operand:DF 2 "s_register_operand" "")))]
a50d7267 1246 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 1247 "
604f3a0a 1248")
1249
cffb2a26 1250(define_expand "subdi3"
1251 [(parallel
1252 [(set (match_operand:DI 0 "s_register_operand" "")
1253 (minus:DI (match_operand:DI 1 "s_register_operand" "")
1254 (match_operand:DI 2 "s_register_operand" "")))
bd5b4116 1255 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 1256 "TARGET_EITHER"
1257 "
25f905c2 1258 if (TARGET_THUMB1)
cffb2a26 1259 {
0438d37f 1260 if (!REG_P (operands[1]))
5aa8c5f0 1261 operands[1] = force_reg (DImode, operands[1]);
0438d37f 1262 if (!REG_P (operands[2]))
5aa8c5f0 1263 operands[2] = force_reg (DImode, operands[2]);
cffb2a26 1264 }
1265 "
1266)
1267
2f9b23e3 1268(define_insn_and_split "*arm_subdi3"
cffb2a26 1269 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
9c08d1fa 1270 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
1271 (match_operand:DI 2 "s_register_operand" "r,0,0")))
bd5b4116 1272 (clobber (reg:CC CC_REGNUM))]
94829feb 1273 "TARGET_32BIT && !TARGET_NEON"
2f9b23e3 1274 "#" ; "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
1275 "&& reload_completed"
1276 [(parallel [(set (reg:CC CC_REGNUM)
1277 (compare:CC (match_dup 1) (match_dup 2)))
1278 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1279 (set (match_dup 3) (minus:SI (minus:SI (match_dup 4) (match_dup 5))
1280 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1281 {
1282 operands[3] = gen_highpart (SImode, operands[0]);
1283 operands[0] = gen_lowpart (SImode, operands[0]);
1284 operands[4] = gen_highpart (SImode, operands[1]);
1285 operands[1] = gen_lowpart (SImode, operands[1]);
1286 operands[5] = gen_highpart (SImode, operands[2]);
1287 operands[2] = gen_lowpart (SImode, operands[2]);
1288 }
cffb2a26 1289 [(set_attr "conds" "clob")
1b7da4ac 1290 (set_attr "length" "8")
1291 (set_attr "type" "multiple")]
cffb2a26 1292)
1293
2f9b23e3 1294(define_insn_and_split "*subdi_di_zesidi"
cffb2a26 1295 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 1296 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r")
9c08d1fa 1297 (zero_extend:DI
cffb2a26 1298 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 1299 (clobber (reg:CC CC_REGNUM))]
25f905c2 1300 "TARGET_32BIT"
2f9b23e3 1301 "#" ; "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
1302 "&& reload_completed"
1303 [(parallel [(set (reg:CC CC_REGNUM)
1304 (compare:CC (match_dup 1) (match_dup 2)))
1305 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1306 (set (match_dup 3) (minus:SI (plus:SI (match_dup 4) (match_dup 5))
1307 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1308 {
1309 operands[3] = gen_highpart (SImode, operands[0]);
1310 operands[0] = gen_lowpart (SImode, operands[0]);
1311 operands[4] = gen_highpart (SImode, operands[1]);
1312 operands[1] = gen_lowpart (SImode, operands[1]);
1313 operands[5] = GEN_INT (~0);
1314 }
cffb2a26 1315 [(set_attr "conds" "clob")
1b7da4ac 1316 (set_attr "length" "8")
1317 (set_attr "type" "multiple")]
cffb2a26 1318)
9c08d1fa 1319
2f9b23e3 1320(define_insn_and_split "*subdi_di_sesidi"
cffb2a26 1321 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 1322 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r")
9c08d1fa 1323 (sign_extend:DI
cffb2a26 1324 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 1325 (clobber (reg:CC CC_REGNUM))]
25f905c2 1326 "TARGET_32BIT"
2f9b23e3 1327 "#" ; "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
1328 "&& reload_completed"
1329 [(parallel [(set (reg:CC CC_REGNUM)
1330 (compare:CC (match_dup 1) (match_dup 2)))
1331 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1332 (set (match_dup 3) (minus:SI (minus:SI (match_dup 4)
1333 (ashiftrt:SI (match_dup 2)
1334 (const_int 31)))
1335 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1336 {
1337 operands[3] = gen_highpart (SImode, operands[0]);
1338 operands[0] = gen_lowpart (SImode, operands[0]);
1339 operands[4] = gen_highpart (SImode, operands[1]);
1340 operands[1] = gen_lowpart (SImode, operands[1]);
1341 }
cffb2a26 1342 [(set_attr "conds" "clob")
1b7da4ac 1343 (set_attr "length" "8")
1344 (set_attr "type" "multiple")]
cffb2a26 1345)
9c08d1fa 1346
2f9b23e3 1347(define_insn_and_split "*subdi_zesidi_di"
cffb2a26 1348 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1349 (minus:DI (zero_extend:DI
cffb2a26 1350 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 1351 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 1352 (clobber (reg:CC CC_REGNUM))]
cffb2a26 1353 "TARGET_ARM"
2f9b23e3 1354 "#" ; "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
1355 ; is equivalent to:
1356 ; "subs\\t%Q0, %2, %Q1\;rsc\\t%R0, %R1, #0"
1357 "&& reload_completed"
1358 [(parallel [(set (reg:CC CC_REGNUM)
1359 (compare:CC (match_dup 2) (match_dup 1)))
1360 (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))])
1361 (set (match_dup 3) (minus:SI (minus:SI (const_int 0) (match_dup 4))
1362 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1363 {
1364 operands[3] = gen_highpart (SImode, operands[0]);
1365 operands[0] = gen_lowpart (SImode, operands[0]);
1366 operands[4] = gen_highpart (SImode, operands[1]);
1367 operands[1] = gen_lowpart (SImode, operands[1]);
1368 }
cffb2a26 1369 [(set_attr "conds" "clob")
1b7da4ac 1370 (set_attr "length" "8")
1371 (set_attr "type" "multiple")]
cffb2a26 1372)
9c08d1fa 1373
2f9b23e3 1374(define_insn_and_split "*subdi_sesidi_di"
cffb2a26 1375 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1376 (minus:DI (sign_extend:DI
cffb2a26 1377 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 1378 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 1379 (clobber (reg:CC CC_REGNUM))]
cffb2a26 1380 "TARGET_ARM"
2f9b23e3 1381 "#" ; "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
1382 ; is equivalent to:
1383 ; "subs\\t%Q0, %2, %Q1\;rsc\\t%R0, %R1, %2, asr #31"
1384 "&& reload_completed"
1385 [(parallel [(set (reg:CC CC_REGNUM)
1386 (compare:CC (match_dup 2) (match_dup 1)))
1387 (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))])
1388 (set (match_dup 3) (minus:SI (minus:SI
1389 (ashiftrt:SI (match_dup 2)
1390 (const_int 31))
1391 (match_dup 4))
1392 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1393 {
1394 operands[3] = gen_highpart (SImode, operands[0]);
1395 operands[0] = gen_lowpart (SImode, operands[0]);
1396 operands[4] = gen_highpart (SImode, operands[1]);
1397 operands[1] = gen_lowpart (SImode, operands[1]);
1398 }
cffb2a26 1399 [(set_attr "conds" "clob")
1b7da4ac 1400 (set_attr "length" "8")
1401 (set_attr "type" "multiple")]
cffb2a26 1402)
9c08d1fa 1403
2f9b23e3 1404(define_insn_and_split "*subdi_zesidi_zesidi"
cffb2a26 1405 [(set (match_operand:DI 0 "s_register_operand" "=r")
9c08d1fa 1406 (minus:DI (zero_extend:DI
cffb2a26 1407 (match_operand:SI 1 "s_register_operand" "r"))
9c08d1fa 1408 (zero_extend:DI
cffb2a26 1409 (match_operand:SI 2 "s_register_operand" "r"))))
bd5b4116 1410 (clobber (reg:CC CC_REGNUM))]
25f905c2 1411 "TARGET_32BIT"
2f9b23e3 1412 "#" ; "subs\\t%Q0, %1, %2\;sbc\\t%R0, %1, %1"
1413 "&& reload_completed"
1414 [(parallel [(set (reg:CC CC_REGNUM)
1415 (compare:CC (match_dup 1) (match_dup 2)))
1416 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1417 (set (match_dup 3) (minus:SI (minus:SI (match_dup 1) (match_dup 1))
1418 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1419 {
1420 operands[3] = gen_highpart (SImode, operands[0]);
1421 operands[0] = gen_lowpart (SImode, operands[0]);
1422 }
cffb2a26 1423 [(set_attr "conds" "clob")
1b7da4ac 1424 (set_attr "length" "8")
1425 (set_attr "type" "multiple")]
cffb2a26 1426)
b11cae9e 1427
87b22bf7 1428(define_expand "subsi3"
cffb2a26 1429 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 1430 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
1431 (match_operand:SI 2 "s_register_operand" "")))]
cffb2a26 1432 "TARGET_EITHER"
87b22bf7 1433 "
0438d37f 1434 if (CONST_INT_P (operands[1]))
87b22bf7 1435 {
25f905c2 1436 if (TARGET_32BIT)
cffb2a26 1437 {
17202aa5 1438 if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[1]), MINUS))
1439 operands[1] = force_reg (SImode, operands[1]);
1440 else
1441 {
1442 arm_split_constant (MINUS, SImode, NULL_RTX,
1443 INTVAL (operands[1]), operands[0],
1444 operands[2],
1445 optimize && can_create_pseudo_p ());
1446 DONE;
1447 }
cffb2a26 1448 }
25f905c2 1449 else /* TARGET_THUMB1 */
cffb2a26 1450 operands[1] = force_reg (SImode, operands[1]);
87b22bf7 1451 }
cffb2a26 1452 "
1453)
87b22bf7 1454
25f905c2 1455; ??? Check Thumb-2 split length
a0f94409 1456(define_insn_and_split "*arm_subsi3_insn"
3a44c5a9 1457 [(set (match_operand:SI 0 "s_register_operand" "=l,l ,l ,l ,r,r,r,rk,r")
1458 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "l ,0 ,l ,Pz,I,r,r,k ,?n")
1459 (match_operand:SI 2 "reg_or_int_operand" "l ,Py,Pd,l ,r,I,r,r ,r")))]
25f905c2 1460 "TARGET_32BIT"
e2348bcb 1461 "@
7c36fe71 1462 sub%?\\t%0, %1, %2
1463 sub%?\\t%0, %2
1464 sub%?\\t%0, %1, %2
1465 rsb%?\\t%0, %2, %1
87b22bf7 1466 rsb%?\\t%0, %2, %1
aaa37ad6 1467 sub%?\\t%0, %1, %2
080c0b9a 1468 sub%?\\t%0, %1, %2
65f68e55 1469 sub%?\\t%0, %1, %2
87b22bf7 1470 #"
0438d37f 1471 "&& (CONST_INT_P (operands[1])
91a5e339 1472 && !const_ok_for_arm (INTVAL (operands[1])))"
87b22bf7 1473 [(clobber (const_int 0))]
1474 "
96f57e36 1475 arm_split_constant (MINUS, SImode, curr_insn,
1476 INTVAL (operands[1]), operands[0], operands[2], 0);
87b22bf7 1477 DONE;
cffb2a26 1478 "
7c36fe71 1479 [(set_attr "length" "4,4,4,4,4,4,4,4,16")
1480 (set_attr "arch" "t2,t2,t2,t2,*,*,*,*,*")
65f68e55 1481 (set_attr "predicable" "yes")
7c36fe71 1482 (set_attr "predicable_short_it" "yes,yes,yes,yes,no,no,no,no,no")
112eda6f 1483 (set_attr "type" "alu_sreg,alu_sreg,alu_sreg,alu_sreg,alu_imm,alu_imm,alu_sreg,alu_sreg,multiple")]
a0f94409 1484)
1485
1486(define_peephole2
1487 [(match_scratch:SI 3 "r")
372575c7 1488 (set (match_operand:SI 0 "arm_general_register_operand" "")
a0f94409 1489 (minus:SI (match_operand:SI 1 "const_int_operand" "")
372575c7 1490 (match_operand:SI 2 "arm_general_register_operand" "")))]
25f905c2 1491 "TARGET_32BIT
a0f94409 1492 && !const_ok_for_arm (INTVAL (operands[1]))
1493 && const_ok_for_arm (~INTVAL (operands[1]))"
1494 [(set (match_dup 3) (match_dup 1))
1495 (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1496 ""
cffb2a26 1497)
b11cae9e 1498
62e39b06 1499(define_insn "subsi3_compare0"
bd5b4116 1500 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1501 (compare:CC_NOOV
65f68e55 1502 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,r,I")
1503 (match_operand:SI 2 "arm_rhs_operand" "I,r,r"))
215b30b3 1504 (const_int 0)))
65f68e55 1505 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9c08d1fa 1506 (minus:SI (match_dup 1) (match_dup 2)))]
25f905c2 1507 "TARGET_32BIT"
e2348bcb 1508 "@
3ef90e77 1509 subs%?\\t%0, %1, %2
1510 subs%?\\t%0, %1, %2
1511 rsbs%?\\t%0, %2, %1"
65f68e55 1512 [(set_attr "conds" "set")
112eda6f 1513 (set_attr "type" "alus_imm,alus_sreg,alus_sreg")]
cffb2a26 1514)
9c08d1fa 1515
190efb17 1516(define_insn "subsi3_compare"
080c0b9a 1517 [(set (reg:CC CC_REGNUM)
65f68e55 1518 (compare:CC (match_operand:SI 1 "arm_rhs_operand" "r,r,I")
1519 (match_operand:SI 2 "arm_rhs_operand" "I,r,r")))
1520 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2df9477b 1521 (minus:SI (match_dup 1) (match_dup 2)))]
1522 "TARGET_32BIT"
1523 "@
3ef90e77 1524 subs%?\\t%0, %1, %2
1525 subs%?\\t%0, %1, %2
1526 rsbs%?\\t%0, %2, %1"
65f68e55 1527 [(set_attr "conds" "set")
112eda6f 1528 (set_attr "type" "alus_imm,alus_sreg,alus_sreg")]
2df9477b 1529)
1530
604f3a0a 1531(define_expand "subsf3"
1532 [(set (match_operand:SF 0 "s_register_operand" "")
d86c91f6 1533 (minus:SF (match_operand:SF 1 "s_register_operand" "")
1534 (match_operand:SF 2 "s_register_operand" "")))]
25f905c2 1535 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1536 "
604f3a0a 1537")
1538
604f3a0a 1539(define_expand "subdf3"
1540 [(set (match_operand:DF 0 "s_register_operand" "")
d86c91f6 1541 (minus:DF (match_operand:DF 1 "s_register_operand" "")
1542 (match_operand:DF 2 "s_register_operand" "")))]
a50d7267 1543 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 1544 "
604f3a0a 1545")
1546
b11cae9e 1547\f
1548;; Multiplication insns
1549
4422d91f 1550(define_expand "mulhi3"
1551 [(set (match_operand:HI 0 "s_register_operand" "")
1552 (mult:HI (match_operand:HI 1 "s_register_operand" "")
1553 (match_operand:HI 2 "s_register_operand" "")))]
1554 "TARGET_DSP_MULTIPLY"
1555 "
1556 {
1557 rtx result = gen_reg_rtx (SImode);
1558 emit_insn (gen_mulhisi3 (result, operands[1], operands[2]));
1559 emit_move_insn (operands[0], gen_lowpart (HImode, result));
1560 DONE;
1561 }"
1562)
1563
cffb2a26 1564(define_expand "mulsi3"
1565 [(set (match_operand:SI 0 "s_register_operand" "")
1566 (mult:SI (match_operand:SI 2 "s_register_operand" "")
1567 (match_operand:SI 1 "s_register_operand" "")))]
1568 "TARGET_EITHER"
1569 ""
1570)
1571
9c08d1fa 1572;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
cffb2a26 1573(define_insn "*arm_mulsi3"
1574 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1575 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1576 (match_operand:SI 1 "s_register_operand" "%0,r")))]
58d7d654 1577 "TARGET_32BIT && !arm_arch6"
f7fbdd4a 1578 "mul%?\\t%0, %2, %1"
9da0ec36 1579 [(set_attr "type" "mul")
0d66636f 1580 (set_attr "predicable" "yes")]
cffb2a26 1581)
1582
58d7d654 1583(define_insn "*arm_mulsi3_v6"
d952d547 1584 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
1585 (mult:SI (match_operand:SI 1 "s_register_operand" "0,l,r")
1586 (match_operand:SI 2 "s_register_operand" "l,0,r")))]
58d7d654 1587 "TARGET_32BIT && arm_arch6"
1588 "mul%?\\t%0, %1, %2"
9da0ec36 1589 [(set_attr "type" "mul")
d952d547 1590 (set_attr "predicable" "yes")
1591 (set_attr "arch" "t2,t2,*")
1592 (set_attr "length" "4")
1593 (set_attr "predicable_short_it" "yes,yes,no")]
58d7d654 1594)
1595
f7fbdd4a 1596(define_insn "*mulsi3_compare0"
bd5b4116 1597 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1598 (compare:CC_NOOV (mult:SI
1599 (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1600 (match_operand:SI 1 "s_register_operand" "%0,r"))
9c08d1fa 1601 (const_int 0)))
1602 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1603 (mult:SI (match_dup 2) (match_dup 1)))]
58d7d654 1604 "TARGET_ARM && !arm_arch6"
3ef90e77 1605 "muls%?\\t%0, %2, %1"
58d7d654 1606 [(set_attr "conds" "set")
9da0ec36 1607 (set_attr "type" "muls")]
58d7d654 1608)
1609
1610(define_insn "*mulsi3_compare0_v6"
1611 [(set (reg:CC_NOOV CC_REGNUM)
1612 (compare:CC_NOOV (mult:SI
1613 (match_operand:SI 2 "s_register_operand" "r")
1614 (match_operand:SI 1 "s_register_operand" "r"))
1615 (const_int 0)))
1616 (set (match_operand:SI 0 "s_register_operand" "=r")
1617 (mult:SI (match_dup 2) (match_dup 1)))]
1618 "TARGET_ARM && arm_arch6 && optimize_size"
3ef90e77 1619 "muls%?\\t%0, %2, %1"
cffb2a26 1620 [(set_attr "conds" "set")
9da0ec36 1621 (set_attr "type" "muls")]
cffb2a26 1622)
9c08d1fa 1623
f7fbdd4a 1624(define_insn "*mulsi_compare0_scratch"
bd5b4116 1625 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1626 (compare:CC_NOOV (mult:SI
1627 (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1628 (match_operand:SI 1 "s_register_operand" "%0,r"))
9c08d1fa 1629 (const_int 0)))
1630 (clobber (match_scratch:SI 0 "=&r,&r"))]
58d7d654 1631 "TARGET_ARM && !arm_arch6"
3ef90e77 1632 "muls%?\\t%0, %2, %1"
58d7d654 1633 [(set_attr "conds" "set")
9da0ec36 1634 (set_attr "type" "muls")]
58d7d654 1635)
1636
1637(define_insn "*mulsi_compare0_scratch_v6"
1638 [(set (reg:CC_NOOV CC_REGNUM)
1639 (compare:CC_NOOV (mult:SI
1640 (match_operand:SI 2 "s_register_operand" "r")
1641 (match_operand:SI 1 "s_register_operand" "r"))
1642 (const_int 0)))
1643 (clobber (match_scratch:SI 0 "=r"))]
1644 "TARGET_ARM && arm_arch6 && optimize_size"
3ef90e77 1645 "muls%?\\t%0, %2, %1"
cffb2a26 1646 [(set_attr "conds" "set")
9da0ec36 1647 (set_attr "type" "muls")]
cffb2a26 1648)
9c08d1fa 1649
b11cae9e 1650;; Unnamed templates to match MLA instruction.
1651
f7fbdd4a 1652(define_insn "*mulsi3addsi"
9c08d1fa 1653 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
c8f69309 1654 (plus:SI
9c08d1fa 1655 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1656 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1657 (match_operand:SI 3 "s_register_operand" "r,r,0,0")))]
58d7d654 1658 "TARGET_32BIT && !arm_arch6"
1659 "mla%?\\t%0, %2, %1, %3"
9da0ec36 1660 [(set_attr "type" "mla")
58d7d654 1661 (set_attr "predicable" "yes")]
1662)
1663
1664(define_insn "*mulsi3addsi_v6"
1665 [(set (match_operand:SI 0 "s_register_operand" "=r")
1666 (plus:SI
1667 (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1668 (match_operand:SI 1 "s_register_operand" "r"))
1669 (match_operand:SI 3 "s_register_operand" "r")))]
1670 "TARGET_32BIT && arm_arch6"
f7fbdd4a 1671 "mla%?\\t%0, %2, %1, %3"
9da0ec36 1672 [(set_attr "type" "mla")
d952d547 1673 (set_attr "predicable" "yes")
1674 (set_attr "predicable_short_it" "no")]
0d66636f 1675)
b11cae9e 1676
f7fbdd4a 1677(define_insn "*mulsi3addsi_compare0"
bd5b4116 1678 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1679 (compare:CC_NOOV
1680 (plus:SI (mult:SI
1681 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1682 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1683 (match_operand:SI 3 "s_register_operand" "r,r,0,0"))
215b30b3 1684 (const_int 0)))
9c08d1fa 1685 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1686 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1687 (match_dup 3)))]
58d7d654 1688 "TARGET_ARM && arm_arch6"
3ef90e77 1689 "mlas%?\\t%0, %2, %1, %3"
58d7d654 1690 [(set_attr "conds" "set")
9da0ec36 1691 (set_attr "type" "mlas")]
58d7d654 1692)
1693
1694(define_insn "*mulsi3addsi_compare0_v6"
1695 [(set (reg:CC_NOOV CC_REGNUM)
1696 (compare:CC_NOOV
1697 (plus:SI (mult:SI
1698 (match_operand:SI 2 "s_register_operand" "r")
1699 (match_operand:SI 1 "s_register_operand" "r"))
1700 (match_operand:SI 3 "s_register_operand" "r"))
1701 (const_int 0)))
1702 (set (match_operand:SI 0 "s_register_operand" "=r")
1703 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1704 (match_dup 3)))]
1705 "TARGET_ARM && arm_arch6 && optimize_size"
3ef90e77 1706 "mlas%?\\t%0, %2, %1, %3"
0d66636f 1707 [(set_attr "conds" "set")
9da0ec36 1708 (set_attr "type" "mlas")]
0d66636f 1709)
9c08d1fa 1710
f7fbdd4a 1711(define_insn "*mulsi3addsi_compare0_scratch"
bd5b4116 1712 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1713 (compare:CC_NOOV
1714 (plus:SI (mult:SI
1715 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1716 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
215b30b3 1717 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1718 (const_int 0)))
9c08d1fa 1719 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
58d7d654 1720 "TARGET_ARM && !arm_arch6"
3ef90e77 1721 "mlas%?\\t%0, %2, %1, %3"
58d7d654 1722 [(set_attr "conds" "set")
9da0ec36 1723 (set_attr "type" "mlas")]
58d7d654 1724)
1725
1726(define_insn "*mulsi3addsi_compare0_scratch_v6"
1727 [(set (reg:CC_NOOV CC_REGNUM)
1728 (compare:CC_NOOV
1729 (plus:SI (mult:SI
1730 (match_operand:SI 2 "s_register_operand" "r")
1731 (match_operand:SI 1 "s_register_operand" "r"))
1732 (match_operand:SI 3 "s_register_operand" "r"))
1733 (const_int 0)))
1734 (clobber (match_scratch:SI 0 "=r"))]
1735 "TARGET_ARM && arm_arch6 && optimize_size"
3ef90e77 1736 "mlas%?\\t%0, %2, %1, %3"
cffb2a26 1737 [(set_attr "conds" "set")
9da0ec36 1738 (set_attr "type" "mlas")]
cffb2a26 1739)
f7fbdd4a 1740
89545238 1741(define_insn "*mulsi3subsi"
1742 [(set (match_operand:SI 0 "s_register_operand" "=r")
1743 (minus:SI
1744 (match_operand:SI 3 "s_register_operand" "r")
1745 (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1746 (match_operand:SI 1 "s_register_operand" "r"))))]
1747 "TARGET_32BIT && arm_arch_thumb2"
1748 "mls%?\\t%0, %2, %1, %3"
9da0ec36 1749 [(set_attr "type" "mla")
d952d547 1750 (set_attr "predicable" "yes")
1751 (set_attr "predicable_short_it" "no")]
89545238 1752)
1753
5cdca009 1754(define_expand "maddsidi4"
1755 [(set (match_operand:DI 0 "s_register_operand" "")
1756 (plus:DI
1757 (mult:DI
1758 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1759 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1760 (match_operand:DI 3 "s_register_operand" "")))]
1761 "TARGET_32BIT && arm_arch3m"
1762 "")
82b85d08 1763
1764(define_insn "*mulsidi3adddi"
fe8dbf85 1765 [(set (match_operand:DI 0 "s_register_operand" "=&r")
82b85d08 1766 (plus:DI
215b30b3 1767 (mult:DI
fe8dbf85 1768 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1769 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1770 (match_operand:DI 1 "s_register_operand" "0")))]
58d7d654 1771 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1772 "smlal%?\\t%Q0, %R0, %3, %2"
9da0ec36 1773 [(set_attr "type" "smlal")
58d7d654 1774 (set_attr "predicable" "yes")]
1775)
1776
1777(define_insn "*mulsidi3adddi_v6"
1778 [(set (match_operand:DI 0 "s_register_operand" "=r")
1779 (plus:DI
1780 (mult:DI
1781 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1782 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1783 (match_operand:DI 1 "s_register_operand" "0")))]
1784 "TARGET_32BIT && arm_arch6"
fe8dbf85 1785 "smlal%?\\t%Q0, %R0, %3, %2"
9da0ec36 1786 [(set_attr "type" "smlal")
d952d547 1787 (set_attr "predicable" "yes")
1788 (set_attr "predicable_short_it" "no")]
0d66636f 1789)
82b85d08 1790
957788b0 1791;; 32x32->64 widening multiply.
1792;; As with mulsi3, the only difference between the v3-5 and v6+
1793;; versions of these patterns is the requirement that the output not
1794;; overlap the inputs, but that still means we have to have a named
1795;; expander and two different starred insns.
1796
1797(define_expand "mulsidi3"
1798 [(set (match_operand:DI 0 "s_register_operand" "")
1799 (mult:DI
1800 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1801 (sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1802 "TARGET_32BIT && arm_arch3m"
1803 ""
1804)
1805
1806(define_insn "*mulsidi3_nov6"
f7fbdd4a 1807 [(set (match_operand:DI 0 "s_register_operand" "=&r")
215b30b3 1808 (mult:DI
1809 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1810 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
58d7d654 1811 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1812 "smull%?\\t%Q0, %R0, %1, %2"
9da0ec36 1813 [(set_attr "type" "smull")
58d7d654 1814 (set_attr "predicable" "yes")]
1815)
1816
957788b0 1817(define_insn "*mulsidi3_v6"
58d7d654 1818 [(set (match_operand:DI 0 "s_register_operand" "=r")
1819 (mult:DI
1820 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1821 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1822 "TARGET_32BIT && arm_arch6"
97499065 1823 "smull%?\\t%Q0, %R0, %1, %2"
9da0ec36 1824 [(set_attr "type" "smull")
d952d547 1825 (set_attr "predicable" "yes")
1826 (set_attr "predicable_short_it" "no")]
0d66636f 1827)
f7fbdd4a 1828
957788b0 1829(define_expand "umulsidi3"
1830 [(set (match_operand:DI 0 "s_register_operand" "")
1831 (mult:DI
1832 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1833 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1834 "TARGET_32BIT && arm_arch3m"
1835 ""
1836)
1837
1838(define_insn "*umulsidi3_nov6"
f7fbdd4a 1839 [(set (match_operand:DI 0 "s_register_operand" "=&r")
215b30b3 1840 (mult:DI
1841 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1842 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
58d7d654 1843 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1844 "umull%?\\t%Q0, %R0, %1, %2"
9da0ec36 1845 [(set_attr "type" "umull")
58d7d654 1846 (set_attr "predicable" "yes")]
1847)
1848
957788b0 1849(define_insn "*umulsidi3_v6"
58d7d654 1850 [(set (match_operand:DI 0 "s_register_operand" "=r")
1851 (mult:DI
1852 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1853 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1854 "TARGET_32BIT && arm_arch6"
97499065 1855 "umull%?\\t%Q0, %R0, %1, %2"
9da0ec36 1856 [(set_attr "type" "umull")
d952d547 1857 (set_attr "predicable" "yes")
1858 (set_attr "predicable_short_it" "no")]
0d66636f 1859)
b11cae9e 1860
5cdca009 1861(define_expand "umaddsidi4"
1862 [(set (match_operand:DI 0 "s_register_operand" "")
1863 (plus:DI
1864 (mult:DI
1865 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1866 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1867 (match_operand:DI 3 "s_register_operand" "")))]
1868 "TARGET_32BIT && arm_arch3m"
1869 "")
82b85d08 1870
1871(define_insn "*umulsidi3adddi"
8ead09f9 1872 [(set (match_operand:DI 0 "s_register_operand" "=&r")
82b85d08 1873 (plus:DI
215b30b3 1874 (mult:DI
fe8dbf85 1875 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1876 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1877 (match_operand:DI 1 "s_register_operand" "0")))]
58d7d654 1878 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1879 "umlal%?\\t%Q0, %R0, %3, %2"
9da0ec36 1880 [(set_attr "type" "umlal")
58d7d654 1881 (set_attr "predicable" "yes")]
1882)
1883
1884(define_insn "*umulsidi3adddi_v6"
1885 [(set (match_operand:DI 0 "s_register_operand" "=r")
1886 (plus:DI
1887 (mult:DI
1888 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1889 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1890 (match_operand:DI 1 "s_register_operand" "0")))]
1891 "TARGET_32BIT && arm_arch6"
fe8dbf85 1892 "umlal%?\\t%Q0, %R0, %3, %2"
9da0ec36 1893 [(set_attr "type" "umlal")
d952d547 1894 (set_attr "predicable" "yes")
1895 (set_attr "predicable_short_it" "no")]
0d66636f 1896)
82b85d08 1897
957788b0 1898(define_expand "smulsi3_highpart"
1899 [(parallel
1900 [(set (match_operand:SI 0 "s_register_operand" "")
1901 (truncate:SI
1902 (lshiftrt:DI
1903 (mult:DI
1904 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1905 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1906 (const_int 32))))
1907 (clobber (match_scratch:SI 3 ""))])]
1908 "TARGET_32BIT && arm_arch3m"
1909 ""
1910)
1911
1912(define_insn "*smulsi3_highpart_nov6"
f082f1c4 1913 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1914 (truncate:SI
1915 (lshiftrt:DI
215b30b3 1916 (mult:DI
e5fea38e 1917 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
215b30b3 1918 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
f082f1c4 1919 (const_int 32))))
1920 (clobber (match_scratch:SI 3 "=&r,&r"))]
58d7d654 1921 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1922 "smull%?\\t%3, %0, %2, %1"
9da0ec36 1923 [(set_attr "type" "smull")
58d7d654 1924 (set_attr "predicable" "yes")]
1925)
1926
957788b0 1927(define_insn "*smulsi3_highpart_v6"
58d7d654 1928 [(set (match_operand:SI 0 "s_register_operand" "=r")
1929 (truncate:SI
1930 (lshiftrt:DI
1931 (mult:DI
1932 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1933 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1934 (const_int 32))))
1935 (clobber (match_scratch:SI 3 "=r"))]
1936 "TARGET_32BIT && arm_arch6"
f082f1c4 1937 "smull%?\\t%3, %0, %2, %1"
9da0ec36 1938 [(set_attr "type" "smull")
d952d547 1939 (set_attr "predicable" "yes")
1940 (set_attr "predicable_short_it" "no")]
cffb2a26 1941)
f082f1c4 1942
957788b0 1943(define_expand "umulsi3_highpart"
1944 [(parallel
1945 [(set (match_operand:SI 0 "s_register_operand" "")
1946 (truncate:SI
1947 (lshiftrt:DI
1948 (mult:DI
1949 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1950 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1951 (const_int 32))))
1952 (clobber (match_scratch:SI 3 ""))])]
1953 "TARGET_32BIT && arm_arch3m"
1954 ""
1955)
1956
1957(define_insn "*umulsi3_highpart_nov6"
f082f1c4 1958 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1959 (truncate:SI
1960 (lshiftrt:DI
215b30b3 1961 (mult:DI
e5fea38e 1962 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
215b30b3 1963 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
f082f1c4 1964 (const_int 32))))
1965 (clobber (match_scratch:SI 3 "=&r,&r"))]
58d7d654 1966 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1967 "umull%?\\t%3, %0, %2, %1"
9da0ec36 1968 [(set_attr "type" "umull")
58d7d654 1969 (set_attr "predicable" "yes")]
1970)
1971
957788b0 1972(define_insn "*umulsi3_highpart_v6"
58d7d654 1973 [(set (match_operand:SI 0 "s_register_operand" "=r")
1974 (truncate:SI
1975 (lshiftrt:DI
1976 (mult:DI
1977 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1978 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1979 (const_int 32))))
1980 (clobber (match_scratch:SI 3 "=r"))]
1981 "TARGET_32BIT && arm_arch6"
f082f1c4 1982 "umull%?\\t%3, %0, %2, %1"
9da0ec36 1983 [(set_attr "type" "umull")
d952d547 1984 (set_attr "predicable" "yes")
1985 (set_attr "predicable_short_it" "no")]
cffb2a26 1986)
f082f1c4 1987
331beb1a 1988(define_insn "mulhisi3"
1989 [(set (match_operand:SI 0 "s_register_operand" "=r")
1990 (mult:SI (sign_extend:SI
1991 (match_operand:HI 1 "s_register_operand" "%r"))
1992 (sign_extend:SI
1993 (match_operand:HI 2 "s_register_operand" "r"))))]
25f905c2 1994 "TARGET_DSP_MULTIPLY"
61a2d04c 1995 "smulbb%?\\t%0, %1, %2"
9da0ec36 1996 [(set_attr "type" "smulxy")
fec538d9 1997 (set_attr "predicable" "yes")]
1998)
1999
2000(define_insn "*mulhisi3tb"
2001 [(set (match_operand:SI 0 "s_register_operand" "=r")
2002 (mult:SI (ashiftrt:SI
2003 (match_operand:SI 1 "s_register_operand" "r")
2004 (const_int 16))
2005 (sign_extend:SI
2006 (match_operand:HI 2 "s_register_operand" "r"))))]
25f905c2 2007 "TARGET_DSP_MULTIPLY"
fec538d9 2008 "smultb%?\\t%0, %1, %2"
9da0ec36 2009 [(set_attr "type" "smulxy")
d952d547 2010 (set_attr "predicable" "yes")
2011 (set_attr "predicable_short_it" "no")]
fec538d9 2012)
2013
2014(define_insn "*mulhisi3bt"
2015 [(set (match_operand:SI 0 "s_register_operand" "=r")
2016 (mult:SI (sign_extend:SI
2017 (match_operand:HI 1 "s_register_operand" "r"))
2018 (ashiftrt:SI
2019 (match_operand:SI 2 "s_register_operand" "r")
2020 (const_int 16))))]
25f905c2 2021 "TARGET_DSP_MULTIPLY"
fec538d9 2022 "smulbt%?\\t%0, %1, %2"
9da0ec36 2023 [(set_attr "type" "smulxy")
d952d547 2024 (set_attr "predicable" "yes")
2025 (set_attr "predicable_short_it" "no")]
fec538d9 2026)
2027
2028(define_insn "*mulhisi3tt"
2029 [(set (match_operand:SI 0 "s_register_operand" "=r")
2030 (mult:SI (ashiftrt:SI
2031 (match_operand:SI 1 "s_register_operand" "r")
2032 (const_int 16))
2033 (ashiftrt:SI
2034 (match_operand:SI 2 "s_register_operand" "r")
2035 (const_int 16))))]
25f905c2 2036 "TARGET_DSP_MULTIPLY"
fec538d9 2037 "smultt%?\\t%0, %1, %2"
9da0ec36 2038 [(set_attr "type" "smulxy")
d952d547 2039 (set_attr "predicable" "yes")
2040 (set_attr "predicable_short_it" "no")]
331beb1a 2041)
2042
5cdca009 2043(define_insn "maddhisi4"
331beb1a 2044 [(set (match_operand:SI 0 "s_register_operand" "=r")
cfa6c608 2045 (plus:SI (mult:SI (sign_extend:SI
2046 (match_operand:HI 1 "s_register_operand" "r"))
331beb1a 2047 (sign_extend:SI
cfa6c608 2048 (match_operand:HI 2 "s_register_operand" "r")))
2049 (match_operand:SI 3 "s_register_operand" "r")))]
25f905c2 2050 "TARGET_DSP_MULTIPLY"
5cdca009 2051 "smlabb%?\\t%0, %1, %2, %3"
9da0ec36 2052 [(set_attr "type" "smlaxy")
d952d547 2053 (set_attr "predicable" "yes")
2054 (set_attr "predicable_short_it" "no")]
331beb1a 2055)
2056
9a92f368 2057;; Note: there is no maddhisi4ibt because this one is canonical form
2058(define_insn "*maddhisi4tb"
2059 [(set (match_operand:SI 0 "s_register_operand" "=r")
2060 (plus:SI (mult:SI (ashiftrt:SI
2061 (match_operand:SI 1 "s_register_operand" "r")
2062 (const_int 16))
2063 (sign_extend:SI
2064 (match_operand:HI 2 "s_register_operand" "r")))
2065 (match_operand:SI 3 "s_register_operand" "r")))]
2066 "TARGET_DSP_MULTIPLY"
2067 "smlatb%?\\t%0, %1, %2, %3"
9da0ec36 2068 [(set_attr "type" "smlaxy")
d952d547 2069 (set_attr "predicable" "yes")
2070 (set_attr "predicable_short_it" "no")]
9a92f368 2071)
2072
2073(define_insn "*maddhisi4tt"
2074 [(set (match_operand:SI 0 "s_register_operand" "=r")
2075 (plus:SI (mult:SI (ashiftrt:SI
2076 (match_operand:SI 1 "s_register_operand" "r")
2077 (const_int 16))
2078 (ashiftrt:SI
2079 (match_operand:SI 2 "s_register_operand" "r")
2080 (const_int 16)))
2081 (match_operand:SI 3 "s_register_operand" "r")))]
2082 "TARGET_DSP_MULTIPLY"
2083 "smlatt%?\\t%0, %1, %2, %3"
9da0ec36 2084 [(set_attr "type" "smlaxy")
d952d547 2085 (set_attr "predicable" "yes")
2086 (set_attr "predicable_short_it" "no")]
9a92f368 2087)
2088
aff5fb4d 2089(define_insn "maddhidi4"
331beb1a 2090 [(set (match_operand:DI 0 "s_register_operand" "=r")
2091 (plus:DI
331beb1a 2092 (mult:DI (sign_extend:DI
d952d547 2093 (match_operand:HI 1 "s_register_operand" "r"))
331beb1a 2094 (sign_extend:DI
cfa6c608 2095 (match_operand:HI 2 "s_register_operand" "r")))
2096 (match_operand:DI 3 "s_register_operand" "0")))]
25f905c2 2097 "TARGET_DSP_MULTIPLY"
5cdca009 2098 "smlalbb%?\\t%Q0, %R0, %1, %2"
9da0ec36 2099 [(set_attr "type" "smlalxy")
d952d547 2100 (set_attr "predicable" "yes")
2101 (set_attr "predicable_short_it" "no")])
331beb1a 2102
9a92f368 2103;; Note: there is no maddhidi4ibt because this one is canonical form
2104(define_insn "*maddhidi4tb"
2105 [(set (match_operand:DI 0 "s_register_operand" "=r")
2106 (plus:DI
2107 (mult:DI (sign_extend:DI
2108 (ashiftrt:SI
2109 (match_operand:SI 1 "s_register_operand" "r")
2110 (const_int 16)))
2111 (sign_extend:DI
2112 (match_operand:HI 2 "s_register_operand" "r")))
2113 (match_operand:DI 3 "s_register_operand" "0")))]
2114 "TARGET_DSP_MULTIPLY"
2115 "smlaltb%?\\t%Q0, %R0, %1, %2"
9da0ec36 2116 [(set_attr "type" "smlalxy")
d952d547 2117 (set_attr "predicable" "yes")
2118 (set_attr "predicable_short_it" "no")])
9a92f368 2119
2120(define_insn "*maddhidi4tt"
2121 [(set (match_operand:DI 0 "s_register_operand" "=r")
2122 (plus:DI
2123 (mult:DI (sign_extend:DI
2124 (ashiftrt:SI
2125 (match_operand:SI 1 "s_register_operand" "r")
2126 (const_int 16)))
2127 (sign_extend:DI
2128 (ashiftrt:SI
2129 (match_operand:SI 2 "s_register_operand" "r")
2130 (const_int 16))))
2131 (match_operand:DI 3 "s_register_operand" "0")))]
2132 "TARGET_DSP_MULTIPLY"
2133 "smlaltt%?\\t%Q0, %R0, %1, %2"
9da0ec36 2134 [(set_attr "type" "smlalxy")
d952d547 2135 (set_attr "predicable" "yes")
2136 (set_attr "predicable_short_it" "no")])
9a92f368 2137
604f3a0a 2138(define_expand "mulsf3"
2139 [(set (match_operand:SF 0 "s_register_operand" "")
2140 (mult:SF (match_operand:SF 1 "s_register_operand" "")
d86c91f6 2141 (match_operand:SF 2 "s_register_operand" "")))]
25f905c2 2142 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 2143 "
604f3a0a 2144")
2145
604f3a0a 2146(define_expand "muldf3"
2147 [(set (match_operand:DF 0 "s_register_operand" "")
2148 (mult:DF (match_operand:DF 1 "s_register_operand" "")
d86c91f6 2149 (match_operand:DF 2 "s_register_operand" "")))]
a50d7267 2150 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 2151 "
604f3a0a 2152")
b11cae9e 2153\f
2154;; Division insns
2155
7db9af5d 2156(define_expand "divsf3"
2157 [(set (match_operand:SF 0 "s_register_operand" "")
d86c91f6 2158 (div:SF (match_operand:SF 1 "s_register_operand" "")
2159 (match_operand:SF 2 "s_register_operand" "")))]
d7216193 2160 "TARGET_32BIT && TARGET_HARD_FLOAT"
7db9af5d 2161 "")
9c08d1fa 2162
7db9af5d 2163(define_expand "divdf3"
2164 [(set (match_operand:DF 0 "s_register_operand" "")
d86c91f6 2165 (div:DF (match_operand:DF 1 "s_register_operand" "")
2166 (match_operand:DF 2 "s_register_operand" "")))]
994606f8 2167 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
7db9af5d 2168 "")
b11cae9e 2169\f
2170;; Boolean and,ior,xor insns
2171
f6ebffac 2172;; Split up double word logical operations
2173
2174;; Split up simple DImode logical operations. Simply perform the logical
2175;; operation on the upper and lower halves of the registers.
2176(define_split
2177 [(set (match_operand:DI 0 "s_register_operand" "")
2178 (match_operator:DI 6 "logical_binary_operator"
2179 [(match_operand:DI 1 "s_register_operand" "")
2180 (match_operand:DI 2 "s_register_operand" "")]))]
25f905c2 2181 "TARGET_32BIT && reload_completed
e2669ea7 2182 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))
25f905c2 2183 && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
f6ebffac 2184 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
2185 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
2186 "
215b30b3 2187 {
2188 operands[3] = gen_highpart (SImode, operands[0]);
2189 operands[0] = gen_lowpart (SImode, operands[0]);
2190 operands[4] = gen_highpart (SImode, operands[1]);
2191 operands[1] = gen_lowpart (SImode, operands[1]);
2192 operands[5] = gen_highpart (SImode, operands[2]);
2193 operands[2] = gen_lowpart (SImode, operands[2]);
2194 }"
2195)
f6ebffac 2196
f6ebffac 2197(define_split
2198 [(set (match_operand:DI 0 "s_register_operand" "")
2199 (match_operator:DI 6 "logical_binary_operator"
2200 [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
2201 (match_operand:DI 1 "s_register_operand" "")]))]
25f905c2 2202 "TARGET_32BIT && reload_completed"
f6ebffac 2203 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
2204 (set (match_dup 3) (match_op_dup:SI 6
2205 [(ashiftrt:SI (match_dup 2) (const_int 31))
2206 (match_dup 4)]))]
2207 "
215b30b3 2208 {
2209 operands[3] = gen_highpart (SImode, operands[0]);
2210 operands[0] = gen_lowpart (SImode, operands[0]);
2211 operands[4] = gen_highpart (SImode, operands[1]);
2212 operands[1] = gen_lowpart (SImode, operands[1]);
2213 operands[5] = gen_highpart (SImode, operands[2]);
2214 operands[2] = gen_lowpart (SImode, operands[2]);
2215 }"
2216)
f6ebffac 2217
f6ebffac 2218;; The zero extend of operand 2 means we can just copy the high part of
2219;; operand1 into operand0.
2220(define_split
2221 [(set (match_operand:DI 0 "s_register_operand" "")
2222 (ior:DI
2223 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
2224 (match_operand:DI 1 "s_register_operand" "")))]
25f905c2 2225 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
f6ebffac 2226 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
2227 (set (match_dup 3) (match_dup 4))]
2228 "
215b30b3 2229 {
2230 operands[4] = gen_highpart (SImode, operands[1]);
2231 operands[3] = gen_highpart (SImode, operands[0]);
2232 operands[0] = gen_lowpart (SImode, operands[0]);
2233 operands[1] = gen_lowpart (SImode, operands[1]);
2234 }"
2235)
f6ebffac 2236
2237;; The zero extend of operand 2 means we can just copy the high part of
2238;; operand1 into operand0.
2239(define_split
2240 [(set (match_operand:DI 0 "s_register_operand" "")
2241 (xor:DI
2242 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
2243 (match_operand:DI 1 "s_register_operand" "")))]
25f905c2 2244 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
f6ebffac 2245 [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
2246 (set (match_dup 3) (match_dup 4))]
2247 "
215b30b3 2248 {
2249 operands[4] = gen_highpart (SImode, operands[1]);
2250 operands[3] = gen_highpart (SImode, operands[0]);
2251 operands[0] = gen_lowpart (SImode, operands[0]);
2252 operands[1] = gen_lowpart (SImode, operands[1]);
2253 }"
2254)
f6ebffac 2255
e2669ea7 2256(define_expand "anddi3"
2257 [(set (match_operand:DI 0 "s_register_operand" "")
2258 (and:DI (match_operand:DI 1 "s_register_operand" "")
2259 (match_operand:DI 2 "neon_inv_logic_op2" "")))]
2260 "TARGET_32BIT"
2261 ""
2262)
2263
f6bbdcf6 2264(define_insn_and_split "*anddi3_insn"
0a314dcd 2265 [(set (match_operand:DI 0 "s_register_operand" "=w,w ,&r,&r,&r,&r,?w,?w")
2266 (and:DI (match_operand:DI 1 "s_register_operand" "%w,0 ,0 ,r ,0 ,r ,w ,0")
2267 (match_operand:DI 2 "arm_anddi_operand_neon" "w ,DL,r ,r ,De,De,w ,DL")))]
f6bbdcf6 2268 "TARGET_32BIT && !TARGET_IWMMXT"
2269{
2270 switch (which_alternative)
2271 {
0a314dcd 2272 case 0: /* fall through */
2273 case 6: return "vand\t%P0, %P1, %P2";
2274 case 1: /* fall through */
2275 case 7: return neon_output_logic_immediate ("vand", &operands[2],
2276 DImode, 1, VALID_NEON_QREG_MODE (DImode));
f6bbdcf6 2277 case 2:
0a314dcd 2278 case 3:
2279 case 4:
f6bbdcf6 2280 case 5: /* fall through */
0a314dcd 2281 return "#";
f6bbdcf6 2282 default: gcc_unreachable ();
2283 }
2284}
0a314dcd 2285 "TARGET_32BIT && !TARGET_IWMMXT && reload_completed
2286 && !(IS_VFP_REGNUM (REGNO (operands[0])))"
f6bbdcf6 2287 [(set (match_dup 3) (match_dup 4))
2288 (set (match_dup 5) (match_dup 6))]
2289 "
2290 {
2291 operands[3] = gen_lowpart (SImode, operands[0]);
2292 operands[5] = gen_highpart (SImode, operands[0]);
2293
2294 operands[4] = simplify_gen_binary (AND, SImode,
2295 gen_lowpart (SImode, operands[1]),
2296 gen_lowpart (SImode, operands[2]));
2297 operands[6] = simplify_gen_binary (AND, SImode,
2298 gen_highpart (SImode, operands[1]),
2299 gen_highpart_mode (SImode, DImode, operands[2]));
2300
2301 }"
32093010 2302 [(set_attr "type" "neon_logic,neon_logic,multiple,multiple,\
2303 multiple,multiple,neon_logic,neon_logic")
0a314dcd 2304 (set_attr "arch" "neon_for_64bits,neon_for_64bits,*,*,*,*,
f6bbdcf6 2305 avoid_neon_for_64bits,avoid_neon_for_64bits")
0a314dcd 2306 (set_attr "length" "*,*,8,8,8,8,*,*")
2307 ]
215b30b3 2308)
b11cae9e 2309
a0f94409 2310(define_insn_and_split "*anddi_zesidi_di"
9c08d1fa 2311 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2312 (and:DI (zero_extend:DI
2313 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 2314 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2315 "TARGET_32BIT"
f6ebffac 2316 "#"
25f905c2 2317 "TARGET_32BIT && reload_completed"
a0f94409 2318 ; The zero extend of operand 2 clears the high word of the output
2319 ; operand.
2320 [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
2321 (set (match_dup 3) (const_int 0))]
2322 "
2323 {
2324 operands[3] = gen_highpart (SImode, operands[0]);
2325 operands[0] = gen_lowpart (SImode, operands[0]);
2326 operands[1] = gen_lowpart (SImode, operands[1]);
2327 }"
1b7da4ac 2328 [(set_attr "length" "8")
2329 (set_attr "type" "multiple")]
215b30b3 2330)
b11cae9e 2331
f7fbdd4a 2332(define_insn "*anddi_sesdi_di"
cffb2a26 2333 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 2334 (and:DI (sign_extend:DI
2335 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 2336 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2337 "TARGET_32BIT"
f6ebffac 2338 "#"
1b7da4ac 2339 [(set_attr "length" "8")
2340 (set_attr "type" "multiple")]
cffb2a26 2341)
b11cae9e 2342
87b22bf7 2343(define_expand "andsi3"
cffb2a26 2344 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2345 (and:SI (match_operand:SI 1 "s_register_operand" "")
2346 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 2347 "TARGET_EITHER"
87b22bf7 2348 "
25f905c2 2349 if (TARGET_32BIT)
87b22bf7 2350 {
0438d37f 2351 if (CONST_INT_P (operands[2]))
cffb2a26 2352 {
47b5b27b 2353 if (INTVAL (operands[2]) == 255 && arm_arch6)
2354 {
2355 operands[1] = convert_to_mode (QImode, operands[1], 1);
2356 emit_insn (gen_thumb2_zero_extendqisi2_v6 (operands[0],
2357 operands[1]));
17202aa5 2358 DONE;
47b5b27b 2359 }
17202aa5 2360 else if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[2]), AND))
2361 operands[2] = force_reg (SImode, operands[2]);
47b5b27b 2362 else
17202aa5 2363 {
2364 arm_split_constant (AND, SImode, NULL_RTX,
2365 INTVAL (operands[2]), operands[0],
2366 operands[1],
2367 optimize && can_create_pseudo_p ());
615caa51 2368
17202aa5 2369 DONE;
2370 }
cffb2a26 2371 }
87b22bf7 2372 }
25f905c2 2373 else /* TARGET_THUMB1 */
cffb2a26 2374 {
0438d37f 2375 if (!CONST_INT_P (operands[2]))
923ffadb 2376 {
2377 rtx tmp = force_reg (SImode, operands[2]);
2378 if (rtx_equal_p (operands[0], operands[1]))
2379 operands[2] = tmp;
2380 else
2381 {
2382 operands[2] = operands[1];
2383 operands[1] = tmp;
2384 }
2385 }
cffb2a26 2386 else
2387 {
2388 int i;
2389
215b30b3 2390 if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
cffb2a26 2391 {
215b30b3 2392 operands[2] = force_reg (SImode,
2393 GEN_INT (~INTVAL (operands[2])));
cffb2a26 2394
747b7458 2395 emit_insn (gen_thumb1_bicsi3 (operands[0], operands[2], operands[1]));
cffb2a26 2396
2397 DONE;
2398 }
87b22bf7 2399
cffb2a26 2400 for (i = 9; i <= 31; i++)
2401 {
db2faf44 2402 if ((HOST_WIDE_INT_1 << i) - 1 == INTVAL (operands[2]))
cffb2a26 2403 {
2404 emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
2405 const0_rtx));
2406 DONE;
2407 }
db2faf44 2408 else if ((HOST_WIDE_INT_1 << i) - 1
215b30b3 2409 == ~INTVAL (operands[2]))
cffb2a26 2410 {
2411 rtx shift = GEN_INT (i);
2412 rtx reg = gen_reg_rtx (SImode);
2413
2414 emit_insn (gen_lshrsi3 (reg, operands[1], shift));
2415 emit_insn (gen_ashlsi3 (operands[0], reg, shift));
2416
2417 DONE;
2418 }
2419 }
2420
2421 operands[2] = force_reg (SImode, operands[2]);
2422 }
215b30b3 2423 }
2424 "
cffb2a26 2425)
2426
25f905c2 2427; ??? Check split length for Thumb-2
a0f94409 2428(define_insn_and_split "*arm_andsi3_insn"
29e234a3 2429 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r,r,r")
2430 (and:SI (match_operand:SI 1 "s_register_operand" "%r,0,r,r,r")
2431 (match_operand:SI 2 "reg_or_int_operand" "I,l,K,r,?n")))]
25f905c2 2432 "TARGET_32BIT"
5565501b 2433 "@
29e234a3 2434 and%?\\t%0, %1, %2
5565501b 2435 and%?\\t%0, %1, %2
87b22bf7 2436 bic%?\\t%0, %1, #%B2
65f68e55 2437 and%?\\t%0, %1, %2
87b22bf7 2438 #"
25f905c2 2439 "TARGET_32BIT
0438d37f 2440 && CONST_INT_P (operands[2])
a0f94409 2441 && !(const_ok_for_arm (INTVAL (operands[2]))
2442 || const_ok_for_arm (~INTVAL (operands[2])))"
2443 [(clobber (const_int 0))]
2444 "
96f57e36 2445 arm_split_constant (AND, SImode, curr_insn,
2446 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 2447 DONE;
2448 "
29e234a3 2449 [(set_attr "length" "4,4,4,4,16")
65f68e55 2450 (set_attr "predicable" "yes")
29e234a3 2451 (set_attr "predicable_short_it" "no,yes,no,no,no")
d82e788e 2452 (set_attr "type" "logic_imm,logic_imm,logic_reg,logic_reg,logic_imm")]
cffb2a26 2453)
2454
f7fbdd4a 2455(define_insn "*andsi3_compare0"
bd5b4116 2456 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 2457 (compare:CC_NOOV
65f68e55 2458 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
2459 (match_operand:SI 2 "arm_not_operand" "I,K,r"))
5565501b 2460 (const_int 0)))
65f68e55 2461 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9c08d1fa 2462 (and:SI (match_dup 1) (match_dup 2)))]
25f905c2 2463 "TARGET_32BIT"
5565501b 2464 "@
3ef90e77 2465 ands%?\\t%0, %1, %2
2466 bics%?\\t%0, %1, #%B2
2467 ands%?\\t%0, %1, %2"
65f68e55 2468 [(set_attr "conds" "set")
d82e788e 2469 (set_attr "type" "logics_imm,logics_imm,logics_reg")]
cffb2a26 2470)
9c08d1fa 2471
f7fbdd4a 2472(define_insn "*andsi3_compare0_scratch"
bd5b4116 2473 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 2474 (compare:CC_NOOV
65f68e55 2475 (and:SI (match_operand:SI 0 "s_register_operand" "r,r,r")
2476 (match_operand:SI 1 "arm_not_operand" "I,K,r"))
5565501b 2477 (const_int 0)))
65f68e55 2478 (clobber (match_scratch:SI 2 "=X,r,X"))]
25f905c2 2479 "TARGET_32BIT"
5565501b 2480 "@
2481 tst%?\\t%0, %1
3ef90e77 2482 bics%?\\t%2, %0, #%B1
65f68e55 2483 tst%?\\t%0, %1"
2484 [(set_attr "conds" "set")
d82e788e 2485 (set_attr "type" "logics_imm,logics_imm,logics_reg")]
0d66636f 2486)
9c08d1fa 2487
f7fbdd4a 2488(define_insn "*zeroextractsi_compare0_scratch"
bd5b4116 2489 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2490 (compare:CC_NOOV (zero_extract:SI
2491 (match_operand:SI 0 "s_register_operand" "r")
d952d547 2492 (match_operand 1 "const_int_operand" "n")
206ee9a2 2493 (match_operand 2 "const_int_operand" "n"))
9c08d1fa 2494 (const_int 0)))]
25f905c2 2495 "TARGET_32BIT
cffb2a26 2496 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
2497 && INTVAL (operands[1]) > 0
2498 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
2499 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
9c08d1fa 2500 "*
5c49a439 2501 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
2502 << INTVAL (operands[2]));
40dbec34 2503 output_asm_insn (\"tst%?\\t%0, %1\", operands);
e2348bcb 2504 return \"\";
0d66636f 2505 "
596e5e8f 2506 [(set_attr "conds" "set")
65f68e55 2507 (set_attr "predicable" "yes")
d952d547 2508 (set_attr "predicable_short_it" "no")
d82e788e 2509 (set_attr "type" "logics_imm")]
0d66636f 2510)
9c08d1fa 2511
f4462328 2512(define_insn_and_split "*ne_zeroextractsi"
c4034607 2513 [(set (match_operand:SI 0 "s_register_operand" "=r")
2514 (ne:SI (zero_extract:SI
2515 (match_operand:SI 1 "s_register_operand" "r")
2516 (match_operand:SI 2 "const_int_operand" "n")
2517 (match_operand:SI 3 "const_int_operand" "n"))
3b8c7f7a 2518 (const_int 0)))
2519 (clobber (reg:CC CC_REGNUM))]
25f905c2 2520 "TARGET_32BIT
cffb2a26 2521 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2522 && INTVAL (operands[2]) > 0
2523 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2524 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
f4462328 2525 "#"
25f905c2 2526 "TARGET_32BIT
f4462328 2527 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2528 && INTVAL (operands[2]) > 0
2529 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2530 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
2531 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2532 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2533 (const_int 0)))
2534 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2535 (set (match_dup 0)
2536 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2537 (match_dup 0) (const_int 1)))]
2538 "
2539 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
2540 << INTVAL (operands[3]));
2541 "
2542 [(set_attr "conds" "clob")
25f905c2 2543 (set (attr "length")
2544 (if_then_else (eq_attr "is_thumb" "yes")
2545 (const_int 12)
1b7da4ac 2546 (const_int 8)))
2547 (set_attr "type" "multiple")]
f4462328 2548)
2549
2550(define_insn_and_split "*ne_zeroextractsi_shifted"
2551 [(set (match_operand:SI 0 "s_register_operand" "=r")
2552 (ne:SI (zero_extract:SI
2553 (match_operand:SI 1 "s_register_operand" "r")
2554 (match_operand:SI 2 "const_int_operand" "n")
2555 (const_int 0))
2556 (const_int 0)))
2557 (clobber (reg:CC CC_REGNUM))]
2558 "TARGET_ARM"
2559 "#"
2560 "TARGET_ARM"
2561 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2562 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2563 (const_int 0)))
2564 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2565 (set (match_dup 0)
2566 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2567 (match_dup 0) (const_int 1)))]
2568 "
2569 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
2570 "
2571 [(set_attr "conds" "clob")
1b7da4ac 2572 (set_attr "length" "8")
2573 (set_attr "type" "multiple")]
f4462328 2574)
2575
2576(define_insn_and_split "*ite_ne_zeroextractsi"
2577 [(set (match_operand:SI 0 "s_register_operand" "=r")
2578 (if_then_else:SI (ne (zero_extract:SI
2579 (match_operand:SI 1 "s_register_operand" "r")
2580 (match_operand:SI 2 "const_int_operand" "n")
2581 (match_operand:SI 3 "const_int_operand" "n"))
2582 (const_int 0))
2583 (match_operand:SI 4 "arm_not_operand" "rIK")
2584 (const_int 0)))
2585 (clobber (reg:CC CC_REGNUM))]
2586 "TARGET_ARM
2587 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2588 && INTVAL (operands[2]) > 0
2589 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 2590 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2591 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 2592 "#"
2593 "TARGET_ARM
2594 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2595 && INTVAL (operands[2]) > 0
2596 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 2597 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2598 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 2599 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2600 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2601 (const_int 0)))
2602 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2603 (set (match_dup 0)
2604 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2605 (match_dup 0) (match_dup 4)))]
2606 "
c4034607 2607 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
f4462328 2608 << INTVAL (operands[3]));
2609 "
2610 [(set_attr "conds" "clob")
1b7da4ac 2611 (set_attr "length" "8")
2612 (set_attr "type" "multiple")]
f4462328 2613)
2614
2615(define_insn_and_split "*ite_ne_zeroextractsi_shifted"
2616 [(set (match_operand:SI 0 "s_register_operand" "=r")
2617 (if_then_else:SI (ne (zero_extract:SI
2618 (match_operand:SI 1 "s_register_operand" "r")
2619 (match_operand:SI 2 "const_int_operand" "n")
2620 (const_int 0))
2621 (const_int 0))
2622 (match_operand:SI 3 "arm_not_operand" "rIK")
2623 (const_int 0)))
2624 (clobber (reg:CC CC_REGNUM))]
f8d7bf2f 2625 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 2626 "#"
f8d7bf2f 2627 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 2628 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2629 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2630 (const_int 0)))
2631 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2632 (set (match_dup 0)
2633 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2634 (match_dup 0) (match_dup 3)))]
2635 "
2636 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
0d66636f 2637 "
2638 [(set_attr "conds" "clob")
1b7da4ac 2639 (set_attr "length" "8")
2640 (set_attr "type" "multiple")]
215b30b3 2641)
9c08d1fa 2642
25f905c2 2643;; ??? Use Thumb-2 has bitfield insert/extract instructions.
d7863cfe 2644(define_split
2645 [(set (match_operand:SI 0 "s_register_operand" "")
2646 (match_operator:SI 1 "shiftable_operator"
2647 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2648 (match_operand:SI 3 "const_int_operand" "")
2649 (match_operand:SI 4 "const_int_operand" ""))
2650 (match_operand:SI 5 "s_register_operand" "")]))
2651 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2652 "TARGET_ARM"
2653 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2654 (set (match_dup 0)
2655 (match_op_dup 1
2656 [(lshiftrt:SI (match_dup 6) (match_dup 4))
2657 (match_dup 5)]))]
2658 "{
2659 HOST_WIDE_INT temp = INTVAL (operands[3]);
2660
2661 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2662 operands[4] = GEN_INT (32 - temp);
2663 }"
2664)
2665
d7863cfe 2666(define_split
2667 [(set (match_operand:SI 0 "s_register_operand" "")
2668 (match_operator:SI 1 "shiftable_operator"
2669 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2670 (match_operand:SI 3 "const_int_operand" "")
2671 (match_operand:SI 4 "const_int_operand" ""))
2672 (match_operand:SI 5 "s_register_operand" "")]))
2673 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2674 "TARGET_ARM"
2675 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2676 (set (match_dup 0)
2677 (match_op_dup 1
2678 [(ashiftrt:SI (match_dup 6) (match_dup 4))
2679 (match_dup 5)]))]
2680 "{
2681 HOST_WIDE_INT temp = INTVAL (operands[3]);
2682
2683 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2684 operands[4] = GEN_INT (32 - temp);
2685 }"
2686)
2687
a42059fd 2688;;; ??? This pattern is bogus. If operand3 has bits outside the range
2689;;; represented by the bitfield, then this will produce incorrect results.
2690;;; Somewhere, the value needs to be truncated. On targets like the m68k,
ceb2fe0f 2691;;; which have a real bit-field insert instruction, the truncation happens
2692;;; in the bit-field insert instruction itself. Since arm does not have a
2693;;; bit-field insert instruction, we would have to emit code here to truncate
a42059fd 2694;;; the value before we insert. This loses some of the advantage of having
2695;;; this insv pattern, so this pattern needs to be reevalutated.
2696
8a18b90c 2697(define_expand "insv"
eb04cafb 2698 [(set (zero_extract (match_operand 0 "nonimmediate_operand" "")
2699 (match_operand 1 "general_operand" "")
2700 (match_operand 2 "general_operand" ""))
2701 (match_operand 3 "reg_or_int_operand" ""))]
8b054d5a 2702 "TARGET_ARM || arm_arch_thumb2"
8a18b90c 2703 "
215b30b3 2704 {
2705 int start_bit = INTVAL (operands[2]);
2706 int width = INTVAL (operands[1]);
db2faf44 2707 HOST_WIDE_INT mask = (HOST_WIDE_INT_1 << width) - 1;
215b30b3 2708 rtx target, subtarget;
2709
8b054d5a 2710 if (arm_arch_thumb2)
2711 {
eb04cafb 2712 if (unaligned_access && MEM_P (operands[0])
2713 && s_register_operand (operands[3], GET_MODE (operands[3]))
2714 && (width == 16 || width == 32) && (start_bit % BITS_PER_UNIT) == 0)
8b054d5a 2715 {
eb04cafb 2716 rtx base_addr;
2717
2718 if (BYTES_BIG_ENDIAN)
2719 start_bit = GET_MODE_BITSIZE (GET_MODE (operands[3])) - width
2720 - start_bit;
8b054d5a 2721
eb04cafb 2722 if (width == 32)
8b054d5a 2723 {
eb04cafb 2724 base_addr = adjust_address (operands[0], SImode,
2725 start_bit / BITS_PER_UNIT);
2726 emit_insn (gen_unaligned_storesi (base_addr, operands[3]));
8b054d5a 2727 }
eb04cafb 2728 else
2729 {
2730 rtx tmp = gen_reg_rtx (HImode);
8b054d5a 2731
eb04cafb 2732 base_addr = adjust_address (operands[0], HImode,
2733 start_bit / BITS_PER_UNIT);
2734 emit_move_insn (tmp, gen_lowpart (HImode, operands[3]));
2735 emit_insn (gen_unaligned_storehi (base_addr, tmp));
2736 }
2737 DONE;
8b054d5a 2738 }
eb04cafb 2739 else if (s_register_operand (operands[0], GET_MODE (operands[0])))
8b054d5a 2740 {
eb04cafb 2741 bool use_bfi = TRUE;
8b054d5a 2742
0438d37f 2743 if (CONST_INT_P (operands[3]))
eb04cafb 2744 {
2745 HOST_WIDE_INT val = INTVAL (operands[3]) & mask;
2746
2747 if (val == 0)
2748 {
2749 emit_insn (gen_insv_zero (operands[0], operands[1],
2750 operands[2]));
2751 DONE;
2752 }
2753
2754 /* See if the set can be done with a single orr instruction. */
2755 if (val == mask && const_ok_for_arm (val << start_bit))
2756 use_bfi = FALSE;
2757 }
2758
2759 if (use_bfi)
2760 {
0438d37f 2761 if (!REG_P (operands[3]))
eb04cafb 2762 operands[3] = force_reg (SImode, operands[3]);
2763
2764 emit_insn (gen_insv_t2 (operands[0], operands[1], operands[2],
2765 operands[3]));
2766 DONE;
2767 }
8b054d5a 2768 }
eb04cafb 2769 else
2770 FAIL;
8b054d5a 2771 }
2772
eb04cafb 2773 if (!s_register_operand (operands[0], GET_MODE (operands[0])))
2774 FAIL;
2775
3f8fde42 2776 target = copy_rtx (operands[0]);
215b30b3 2777 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
2778 subreg as the final target. */
2779 if (GET_CODE (target) == SUBREG)
2780 {
2781 subtarget = gen_reg_rtx (SImode);
2782 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
2783 < GET_MODE_SIZE (SImode))
2784 target = SUBREG_REG (target);
2785 }
2786 else
2787 subtarget = target;
8a18b90c 2788
0438d37f 2789 if (CONST_INT_P (operands[3]))
215b30b3 2790 {
2791 /* Since we are inserting a known constant, we may be able to
2792 reduce the number of bits that we have to clear so that
2793 the mask becomes simple. */
2794 /* ??? This code does not check to see if the new mask is actually
2795 simpler. It may not be. */
2796 rtx op1 = gen_reg_rtx (SImode);
2797 /* ??? Truncate operand3 to fit in the bitfield. See comment before
2798 start of this pattern. */
2799 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
2800 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
2801
c5b3a71b 2802 emit_insn (gen_andsi3 (op1, operands[0],
2803 gen_int_mode (~mask2, SImode)));
215b30b3 2804 emit_insn (gen_iorsi3 (subtarget, op1,
4292ca6b 2805 gen_int_mode (op3_value << start_bit, SImode)));
215b30b3 2806 }
2807 else if (start_bit == 0
2808 && !(const_ok_for_arm (mask)
2809 || const_ok_for_arm (~mask)))
2810 {
2811 /* A Trick, since we are setting the bottom bits in the word,
2812 we can shift operand[3] up, operand[0] down, OR them together
2813 and rotate the result back again. This takes 3 insns, and
5910bb95 2814 the third might be mergeable into another op. */
215b30b3 2815 /* The shift up copes with the possibility that operand[3] is
2816 wider than the bitfield. */
2817 rtx op0 = gen_reg_rtx (SImode);
2818 rtx op1 = gen_reg_rtx (SImode);
2819
2820 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2821 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
2822 emit_insn (gen_iorsi3 (op1, op1, op0));
2823 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
2824 }
2825 else if ((width + start_bit == 32)
2826 && !(const_ok_for_arm (mask)
2827 || const_ok_for_arm (~mask)))
2828 {
2829 /* Similar trick, but slightly less efficient. */
8a18b90c 2830
215b30b3 2831 rtx op0 = gen_reg_rtx (SImode);
2832 rtx op1 = gen_reg_rtx (SImode);
8a18b90c 2833
215b30b3 2834 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2835 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
2836 emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
2837 emit_insn (gen_iorsi3 (subtarget, op1, op0));
2838 }
2839 else
2840 {
c5b3a71b 2841 rtx op0 = gen_int_mode (mask, SImode);
215b30b3 2842 rtx op1 = gen_reg_rtx (SImode);
2843 rtx op2 = gen_reg_rtx (SImode);
8a18b90c 2844
215b30b3 2845 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
2846 {
2847 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 2848
215b30b3 2849 emit_insn (gen_movsi (tmp, op0));
2850 op0 = tmp;
2851 }
8a18b90c 2852
215b30b3 2853 /* Mask out any bits in operand[3] that are not needed. */
2854 emit_insn (gen_andsi3 (op1, operands[3], op0));
8a18b90c 2855
0438d37f 2856 if (CONST_INT_P (op0)
215b30b3 2857 && (const_ok_for_arm (mask << start_bit)
2858 || const_ok_for_arm (~(mask << start_bit))))
2859 {
c5b3a71b 2860 op0 = gen_int_mode (~(mask << start_bit), SImode);
215b30b3 2861 emit_insn (gen_andsi3 (op2, operands[0], op0));
2862 }
2863 else
2864 {
0438d37f 2865 if (CONST_INT_P (op0))
215b30b3 2866 {
2867 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 2868
215b30b3 2869 emit_insn (gen_movsi (tmp, op0));
2870 op0 = tmp;
2871 }
2872
2873 if (start_bit != 0)
2874 emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
a42059fd 2875
215b30b3 2876 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
2877 }
8a18b90c 2878
215b30b3 2879 if (start_bit != 0)
2880 emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
8a18b90c 2881
215b30b3 2882 emit_insn (gen_iorsi3 (subtarget, op1, op2));
2883 }
f082f1c4 2884
215b30b3 2885 if (subtarget != target)
2886 {
2887 /* If TARGET is still a SUBREG, then it must be wider than a word,
2888 so we must be careful only to set the subword we were asked to. */
2889 if (GET_CODE (target) == SUBREG)
2890 emit_move_insn (target, subtarget);
2891 else
2892 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
2893 }
8a18b90c 2894
215b30b3 2895 DONE;
2896 }"
2897)
8a18b90c 2898
8b054d5a 2899(define_insn "insv_zero"
2900 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
809003b3 2901 (match_operand:SI 1 "const_int_M_operand" "M")
2902 (match_operand:SI 2 "const_int_M_operand" "M"))
8b054d5a 2903 (const_int 0))]
2904 "arm_arch_thumb2"
2905 "bfc%?\t%0, %2, %1"
2906 [(set_attr "length" "4")
d952d547 2907 (set_attr "predicable" "yes")
d82e788e 2908 (set_attr "predicable_short_it" "no")
2909 (set_attr "type" "bfm")]
8b054d5a 2910)
2911
2912(define_insn "insv_t2"
2913 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
809003b3 2914 (match_operand:SI 1 "const_int_M_operand" "M")
2915 (match_operand:SI 2 "const_int_M_operand" "M"))
8b054d5a 2916 (match_operand:SI 3 "s_register_operand" "r"))]
2917 "arm_arch_thumb2"
2918 "bfi%?\t%0, %3, %2, %1"
2919 [(set_attr "length" "4")
d952d547 2920 (set_attr "predicable" "yes")
d82e788e 2921 (set_attr "predicable_short_it" "no")
2922 (set_attr "type" "bfm")]
8b054d5a 2923)
2924
215b30b3 2925; constants for op 2 will never be given to these patterns.
a0f94409 2926(define_insn_and_split "*anddi_notdi_di"
9c08d1fa 2927 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 2928 (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "0,r"))
2929 (match_operand:DI 2 "s_register_operand" "r,0")))]
25f905c2 2930 "TARGET_32BIT"
f6ebffac 2931 "#"
e2669ea7 2932 "TARGET_32BIT && reload_completed
2933 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))
2934 && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
a0f94409 2935 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2936 (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2937 "
2938 {
2939 operands[3] = gen_highpart (SImode, operands[0]);
2940 operands[0] = gen_lowpart (SImode, operands[0]);
2941 operands[4] = gen_highpart (SImode, operands[1]);
2942 operands[1] = gen_lowpart (SImode, operands[1]);
2943 operands[5] = gen_highpart (SImode, operands[2]);
2944 operands[2] = gen_lowpart (SImode, operands[2]);
2945 }"
0d66636f 2946 [(set_attr "length" "8")
1b7da4ac 2947 (set_attr "predicable" "yes")
2948 (set_attr "type" "multiple")]
0d66636f 2949)
d952d547 2950
a0f94409 2951(define_insn_and_split "*anddi_notzesidi_di"
9c08d1fa 2952 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2953 (and:DI (not:DI (zero_extend:DI
2954 (match_operand:SI 2 "s_register_operand" "r,r")))
e2348bcb 2955 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 2956 "TARGET_32BIT"
e2348bcb 2957 "@
97499065 2958 bic%?\\t%Q0, %Q1, %2
f6ebffac 2959 #"
a0f94409 2960 ; (not (zero_extend ...)) allows us to just copy the high word from
2961 ; operand1 to operand0.
25f905c2 2962 "TARGET_32BIT
a0f94409 2963 && reload_completed
2964 && operands[0] != operands[1]"
5a097f7d 2965 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
a0f94409 2966 (set (match_dup 3) (match_dup 4))]
2967 "
2968 {
2969 operands[3] = gen_highpart (SImode, operands[0]);
2970 operands[0] = gen_lowpart (SImode, operands[0]);
2971 operands[4] = gen_highpart (SImode, operands[1]);
2972 operands[1] = gen_lowpart (SImode, operands[1]);
2973 }"
0d66636f 2974 [(set_attr "length" "4,8")
d952d547 2975 (set_attr "predicable" "yes")
1b7da4ac 2976 (set_attr "predicable_short_it" "no")
2977 (set_attr "type" "multiple")]
0d66636f 2978)
d952d547 2979
d8cd5fa0 2980(define_insn_and_split "*anddi_notdi_zesidi"
2981 [(set (match_operand:DI 0 "s_register_operand" "=r")
2982 (and:DI (not:DI (match_operand:DI 2 "s_register_operand" "r"))
2983 (zero_extend:DI
2984 (match_operand:SI 1 "s_register_operand" "r"))))]
2985 "TARGET_32BIT"
2986 "#"
2987 "TARGET_32BIT && reload_completed"
2988 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2989 (set (match_dup 3) (const_int 0))]
2990 "
2991 {
2992 operands[3] = gen_highpart (SImode, operands[0]);
2993 operands[0] = gen_lowpart (SImode, operands[0]);
2994 operands[2] = gen_lowpart (SImode, operands[2]);
2995 }"
2996 [(set_attr "length" "8")
2997 (set_attr "predicable" "yes")
2998 (set_attr "predicable_short_it" "no")
2999 (set_attr "type" "multiple")]
3000)
3001
a0f94409 3002(define_insn_and_split "*anddi_notsesidi_di"
9c08d1fa 3003 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3004 (and:DI (not:DI (sign_extend:DI
3005 (match_operand:SI 2 "s_register_operand" "r,r")))
5a097f7d 3006 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 3007 "TARGET_32BIT"
f6ebffac 3008 "#"
25f905c2 3009 "TARGET_32BIT && reload_completed"
5a097f7d 3010 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
a0f94409 3011 (set (match_dup 3) (and:SI (not:SI
3012 (ashiftrt:SI (match_dup 2) (const_int 31)))
3013 (match_dup 4)))]
3014 "
3015 {
3016 operands[3] = gen_highpart (SImode, operands[0]);
3017 operands[0] = gen_lowpart (SImode, operands[0]);
3018 operands[4] = gen_highpart (SImode, operands[1]);
3019 operands[1] = gen_lowpart (SImode, operands[1]);
3020 }"
0d66636f 3021 [(set_attr "length" "8")
d952d547 3022 (set_attr "predicable" "yes")
1b7da4ac 3023 (set_attr "predicable_short_it" "no")
3024 (set_attr "type" "multiple")]
0d66636f 3025)
d952d547 3026
8a18b90c 3027(define_insn "andsi_notsi_si"
9c08d1fa 3028 [(set (match_operand:SI 0 "s_register_operand" "=r")
3029 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
3030 (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 3031 "TARGET_32BIT"
0d66636f 3032 "bic%?\\t%0, %1, %2"
d952d547 3033 [(set_attr "predicable" "yes")
1b7da4ac 3034 (set_attr "predicable_short_it" "no")
3035 (set_attr "type" "logic_reg")]
0d66636f 3036)
b11cae9e 3037
8a18b90c 3038(define_insn "andsi_not_shiftsi_si"
a2cd141b 3039 [(set (match_operand:SI 0 "s_register_operand" "=r")
3040 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
3041 [(match_operand:SI 2 "s_register_operand" "r")
3042 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
3043 (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 3044 "TARGET_ARM"
6c4c2133 3045 "bic%?\\t%0, %1, %2%S4"
344495ea 3046 [(set_attr "predicable" "yes")
331beb1a 3047 (set_attr "shift" "2")
a2cd141b 3048 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
d82e788e 3049 (const_string "logic_shift_imm")
3050 (const_string "logic_shift_reg")))]
6c4c2133 3051)
8a18b90c 3052
9ed784d8 3053;; Shifted bics pattern used to set up CC status register and not reusing
3054;; bics output. Pattern restricts Thumb2 shift operand as bics for Thumb2
3055;; does not support shift by register.
3056(define_insn "andsi_not_shiftsi_si_scc_no_reuse"
3057 [(set (reg:CC_NOOV CC_REGNUM)
3058 (compare:CC_NOOV
3059 (and:SI (not:SI (match_operator:SI 0 "shift_operator"
3060 [(match_operand:SI 1 "s_register_operand" "r")
3061 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
3062 (match_operand:SI 3 "s_register_operand" "r"))
3063 (const_int 0)))
3064 (clobber (match_scratch:SI 4 "=r"))]
3065 "TARGET_ARM || (TARGET_THUMB2 && CONST_INT_P (operands[2]))"
3ef90e77 3066 "bics%?\\t%4, %3, %1%S0"
9ed784d8 3067 [(set_attr "predicable" "yes")
3068 (set_attr "predicable_short_it" "no")
3069 (set_attr "conds" "set")
3070 (set_attr "shift" "1")
3071 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3072 (const_string "logic_shift_imm")
3073 (const_string "logic_shift_reg")))]
3074)
3075
3076;; Same as andsi_not_shiftsi_si_scc_no_reuse, but the bics result is also
3077;; getting reused later.
3078(define_insn "andsi_not_shiftsi_si_scc"
3079 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
3080 (compare:CC_NOOV
3081 (and:SI (not:SI (match_operator:SI 0 "shift_operator"
3082 [(match_operand:SI 1 "s_register_operand" "r")
3083 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
3084 (match_operand:SI 3 "s_register_operand" "r"))
3085 (const_int 0)))
3086 (set (match_operand:SI 4 "s_register_operand" "=r")
3087 (and:SI (not:SI (match_op_dup 0
3088 [(match_dup 1)
3089 (match_dup 2)]))
3090 (match_dup 3)))])]
3091 "TARGET_ARM || (TARGET_THUMB2 && CONST_INT_P (operands[2]))"
3ef90e77 3092 "bics%?\\t%4, %3, %1%S0"
9ed784d8 3093 [(set_attr "predicable" "yes")
3094 (set_attr "predicable_short_it" "no")
3095 (set_attr "conds" "set")
3096 (set_attr "shift" "1")
3097 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3098 (const_string "logic_shift_imm")
3099 (const_string "logic_shift_reg")))]
3100)
3101
f7fbdd4a 3102(define_insn "*andsi_notsi_si_compare0"
bd5b4116 3103 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 3104 (compare:CC_NOOV
3105 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
3106 (match_operand:SI 1 "s_register_operand" "r"))
3107 (const_int 0)))
9c08d1fa 3108 (set (match_operand:SI 0 "s_register_operand" "=r")
3109 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
25f905c2 3110 "TARGET_32BIT"
3ef90e77 3111 "bics\\t%0, %1, %2"
d82e788e 3112 [(set_attr "conds" "set")
3113 (set_attr "type" "logics_shift_reg")]
0d66636f 3114)
9c08d1fa 3115
f7fbdd4a 3116(define_insn "*andsi_notsi_si_compare0_scratch"
bd5b4116 3117 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 3118 (compare:CC_NOOV
3119 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
3120 (match_operand:SI 1 "s_register_operand" "r"))
3121 (const_int 0)))
9c08d1fa 3122 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 3123 "TARGET_32BIT"
3ef90e77 3124 "bics\\t%0, %1, %2"
d82e788e 3125 [(set_attr "conds" "set")
3126 (set_attr "type" "logics_shift_reg")]
0d66636f 3127)
9c08d1fa 3128
e2669ea7 3129(define_expand "iordi3"
3130 [(set (match_operand:DI 0 "s_register_operand" "")
3131 (ior:DI (match_operand:DI 1 "s_register_operand" "")
3132 (match_operand:DI 2 "neon_logic_op2" "")))]
3133 "TARGET_32BIT"
3134 ""
3135)
3136
74d6113f 3137(define_insn_and_split "*iordi3_insn"
3138 [(set (match_operand:DI 0 "s_register_operand" "=w,w ,&r,&r,&r,&r,?w,?w")
3139 (ior:DI (match_operand:DI 1 "s_register_operand" "%w,0 ,0 ,r ,0 ,r ,w ,0")
e0fe6977 3140 (match_operand:DI 2 "arm_iordi_operand_neon" "w ,Dl,r ,r ,Df,Df,w ,Dl")))]
74d6113f 3141 "TARGET_32BIT && !TARGET_IWMMXT"
3142 {
3143 switch (which_alternative)
3144 {
3145 case 0: /* fall through */
3146 case 6: return "vorr\t%P0, %P1, %P2";
3147 case 1: /* fall through */
3148 case 7: return neon_output_logic_immediate ("vorr", &operands[2],
3149 DImode, 0, VALID_NEON_QREG_MODE (DImode));
3150 case 2:
3151 case 3:
3152 case 4:
3153 case 5:
3154 return "#";
3155 default: gcc_unreachable ();
3156 }
3157 }
3158 "TARGET_32BIT && !TARGET_IWMMXT && reload_completed
3159 && !(IS_VFP_REGNUM (REGNO (operands[0])))"
3160 [(set (match_dup 3) (match_dup 4))
3161 (set (match_dup 5) (match_dup 6))]
3162 "
3163 {
3164 operands[3] = gen_lowpart (SImode, operands[0]);
3165 operands[5] = gen_highpart (SImode, operands[0]);
3166
3167 operands[4] = simplify_gen_binary (IOR, SImode,
3168 gen_lowpart (SImode, operands[1]),
3169 gen_lowpart (SImode, operands[2]));
3170 operands[6] = simplify_gen_binary (IOR, SImode,
3171 gen_highpart (SImode, operands[1]),
3172 gen_highpart_mode (SImode, DImode, operands[2]));
3173
3174 }"
32093010 3175 [(set_attr "type" "neon_logic,neon_logic,multiple,multiple,multiple,\
3176 multiple,neon_logic,neon_logic")
e0fe6977 3177 (set_attr "length" "*,*,8,8,8,8,*,*")
74d6113f 3178 (set_attr "arch" "neon_for_64bits,neon_for_64bits,*,*,*,*,avoid_neon_for_64bits,avoid_neon_for_64bits")]
cffb2a26 3179)
9c08d1fa 3180
f7fbdd4a 3181(define_insn "*iordi_zesidi_di"
9c08d1fa 3182 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3183 (ior:DI (zero_extend:DI
3184 (match_operand:SI 2 "s_register_operand" "r,r"))
e2348bcb 3185 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 3186 "TARGET_32BIT"
e2348bcb 3187 "@
97499065 3188 orr%?\\t%Q0, %Q1, %2
f6ebffac 3189 #"
0d66636f 3190 [(set_attr "length" "4,8")
d952d547 3191 (set_attr "predicable" "yes")
1b7da4ac 3192 (set_attr "predicable_short_it" "no")
3193 (set_attr "type" "logic_reg,multiple")]
cffb2a26 3194)
9c08d1fa 3195
f7fbdd4a 3196(define_insn "*iordi_sesidi_di"
9c08d1fa 3197 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3198 (ior:DI (sign_extend:DI
3199 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 3200 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 3201 "TARGET_32BIT"
f6ebffac 3202 "#"
0d66636f 3203 [(set_attr "length" "8")
1b7da4ac 3204 (set_attr "predicable" "yes")
3205 (set_attr "type" "multiple")]
cffb2a26 3206)
9c08d1fa 3207
87b22bf7 3208(define_expand "iorsi3"
cffb2a26 3209 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3210 (ior:SI (match_operand:SI 1 "s_register_operand" "")
3211 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 3212 "TARGET_EITHER"
87b22bf7 3213 "
0438d37f 3214 if (CONST_INT_P (operands[2]))
87b22bf7 3215 {
25f905c2 3216 if (TARGET_32BIT)
cffb2a26 3217 {
17202aa5 3218 if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[2]), IOR))
3219 operands[2] = force_reg (SImode, operands[2]);
3220 else
3221 {
3222 arm_split_constant (IOR, SImode, NULL_RTX,
3223 INTVAL (operands[2]), operands[0],
3224 operands[1],
3225 optimize && can_create_pseudo_p ());
3226 DONE;
3227 }
cffb2a26 3228 }
25f905c2 3229 else /* TARGET_THUMB1 */
923ffadb 3230 {
3231 rtx tmp = force_reg (SImode, operands[2]);
3232 if (rtx_equal_p (operands[0], operands[1]))
3233 operands[2] = tmp;
3234 else
3235 {
3236 operands[2] = operands[1];
3237 operands[1] = tmp;
3238 }
3239 }
87b22bf7 3240 }
cffb2a26 3241 "
3242)
87b22bf7 3243
d5d4dc8d 3244(define_insn_and_split "*iorsi3_insn"
29e234a3 3245 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r,r,r")
3246 (ior:SI (match_operand:SI 1 "s_register_operand" "%r,0,r,r,r")
3247 (match_operand:SI 2 "reg_or_int_operand" "I,l,K,r,?n")))]
d5d4dc8d 3248 "TARGET_32BIT"
87b22bf7 3249 "@
29e234a3 3250 orr%?\\t%0, %1, %2
87b22bf7 3251 orr%?\\t%0, %1, %2
d5d4dc8d 3252 orn%?\\t%0, %1, #%B2
65f68e55 3253 orr%?\\t%0, %1, %2
87b22bf7 3254 #"
d5d4dc8d 3255 "TARGET_32BIT
0438d37f 3256 && CONST_INT_P (operands[2])
d5d4dc8d 3257 && !(const_ok_for_arm (INTVAL (operands[2]))
3258 || (TARGET_THUMB2 && const_ok_for_arm (~INTVAL (operands[2]))))"
a0f94409 3259 [(clobber (const_int 0))]
d5d4dc8d 3260{
29e234a3 3261 arm_split_constant (IOR, SImode, curr_insn,
96f57e36 3262 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 3263 DONE;
d5d4dc8d 3264}
29e234a3 3265 [(set_attr "length" "4,4,4,4,16")
3266 (set_attr "arch" "32,t2,t2,32,32")
65f68e55 3267 (set_attr "predicable" "yes")
29e234a3 3268 (set_attr "predicable_short_it" "no,yes,no,no,no")
d82e788e 3269 (set_attr "type" "logic_imm,logic_reg,logic_imm,logic_reg,logic_reg")]
65f68e55 3270)
cffb2a26 3271
a0f94409 3272(define_peephole2
3273 [(match_scratch:SI 3 "r")
372575c7 3274 (set (match_operand:SI 0 "arm_general_register_operand" "")
3275 (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
87b22bf7 3276 (match_operand:SI 2 "const_int_operand" "")))]
90560cad 3277 "TARGET_ARM
a0f94409 3278 && !const_ok_for_arm (INTVAL (operands[2]))
3279 && const_ok_for_arm (~INTVAL (operands[2]))"
3280 [(set (match_dup 3) (match_dup 2))
3281 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
3282 ""
215b30b3 3283)
a0f94409 3284
f7fbdd4a 3285(define_insn "*iorsi3_compare0"
bd5b4116 3286 [(set (reg:CC_NOOV CC_REGNUM)
65f68e55 3287 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r,r")
3288 (match_operand:SI 2 "arm_rhs_operand" "I,r"))
9c08d1fa 3289 (const_int 0)))
65f68e55 3290 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 3291 (ior:SI (match_dup 1) (match_dup 2)))]
25f905c2 3292 "TARGET_32BIT"
3ef90e77 3293 "orrs%?\\t%0, %1, %2"
65f68e55 3294 [(set_attr "conds" "set")
d82e788e 3295 (set_attr "type" "logics_imm,logics_reg")]
cffb2a26 3296)
9c08d1fa 3297
f7fbdd4a 3298(define_insn "*iorsi3_compare0_scratch"
bd5b4116 3299 [(set (reg:CC_NOOV CC_REGNUM)
65f68e55 3300 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r,r")
3301 (match_operand:SI 2 "arm_rhs_operand" "I,r"))
9c08d1fa 3302 (const_int 0)))
65f68e55 3303 (clobber (match_scratch:SI 0 "=r,r"))]
25f905c2 3304 "TARGET_32BIT"
3ef90e77 3305 "orrs%?\\t%0, %1, %2"
65f68e55 3306 [(set_attr "conds" "set")
d82e788e 3307 (set_attr "type" "logics_imm,logics_reg")]
0d66636f 3308)
9c08d1fa 3309
e2669ea7 3310(define_expand "xordi3"
3311 [(set (match_operand:DI 0 "s_register_operand" "")
3312 (xor:DI (match_operand:DI 1 "s_register_operand" "")
8ee7dc6f 3313 (match_operand:DI 2 "arm_xordi_operand" "")))]
e2669ea7 3314 "TARGET_32BIT"
3315 ""
3316)
3317
8ee7dc6f 3318(define_insn_and_split "*xordi3_insn"
3319 [(set (match_operand:DI 0 "s_register_operand" "=w,&r,&r,&r,&r,?w")
205c3b0a 3320 (xor:DI (match_operand:DI 1 "s_register_operand" "%w ,0,r ,0 ,r ,w")
8ee7dc6f 3321 (match_operand:DI 2 "arm_xordi_operand" "w ,r ,r ,Dg,Dg,w")))]
3322 "TARGET_32BIT && !TARGET_IWMMXT"
3323{
3324 switch (which_alternative)
3325 {
3326 case 1:
3327 case 2:
3328 case 3:
3329 case 4: /* fall through */
3330 return "#";
3331 case 0: /* fall through */
3332 case 5: return "veor\t%P0, %P1, %P2";
3333 default: gcc_unreachable ();
3334 }
3335}
3336 "TARGET_32BIT && !TARGET_IWMMXT && reload_completed
3337 && !(IS_VFP_REGNUM (REGNO (operands[0])))"
3338 [(set (match_dup 3) (match_dup 4))
3339 (set (match_dup 5) (match_dup 6))]
3340 "
3341 {
3342 operands[3] = gen_lowpart (SImode, operands[0]);
3343 operands[5] = gen_highpart (SImode, operands[0]);
3344
3345 operands[4] = simplify_gen_binary (XOR, SImode,
3346 gen_lowpart (SImode, operands[1]),
3347 gen_lowpart (SImode, operands[2]));
3348 operands[6] = simplify_gen_binary (XOR, SImode,
3349 gen_highpart (SImode, operands[1]),
3350 gen_highpart_mode (SImode, DImode, operands[2]));
3351
3352 }"
3353 [(set_attr "length" "*,8,8,8,8,*")
32093010 3354 (set_attr "type" "neon_logic,multiple,multiple,multiple,multiple,neon_logic")
8ee7dc6f 3355 (set_attr "arch" "neon_for_64bits,*,*,*,*,avoid_neon_for_64bits")]
cffb2a26 3356)
9c08d1fa 3357
f7fbdd4a 3358(define_insn "*xordi_zesidi_di"
9c08d1fa 3359 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3360 (xor:DI (zero_extend:DI
3361 (match_operand:SI 2 "s_register_operand" "r,r"))
e2348bcb 3362 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 3363 "TARGET_32BIT"
e2348bcb 3364 "@
97499065 3365 eor%?\\t%Q0, %Q1, %2
f6ebffac 3366 #"
0d66636f 3367 [(set_attr "length" "4,8")
d952d547 3368 (set_attr "predicable" "yes")
1b7da4ac 3369 (set_attr "predicable_short_it" "no")
3370 (set_attr "type" "logic_reg")]
cffb2a26 3371)
9c08d1fa 3372
f7fbdd4a 3373(define_insn "*xordi_sesidi_di"
9c08d1fa 3374 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3375 (xor:DI (sign_extend:DI
3376 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 3377 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 3378 "TARGET_32BIT"
f6ebffac 3379 "#"
0d66636f 3380 [(set_attr "length" "8")
1b7da4ac 3381 (set_attr "predicable" "yes")
3382 (set_attr "type" "multiple")]
cffb2a26 3383)
9c08d1fa 3384
cffb2a26 3385(define_expand "xorsi3"
3386 [(set (match_operand:SI 0 "s_register_operand" "")
3387 (xor:SI (match_operand:SI 1 "s_register_operand" "")
923ffadb 3388 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 3389 "TARGET_EITHER"
0438d37f 3390 "if (CONST_INT_P (operands[2]))
923ffadb 3391 {
3392 if (TARGET_32BIT)
3393 {
17202aa5 3394 if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[2]), XOR))
3395 operands[2] = force_reg (SImode, operands[2]);
3396 else
3397 {
3398 arm_split_constant (XOR, SImode, NULL_RTX,
3399 INTVAL (operands[2]), operands[0],
3400 operands[1],
3401 optimize && can_create_pseudo_p ());
3402 DONE;
3403 }
923ffadb 3404 }
3405 else /* TARGET_THUMB1 */
3406 {
3407 rtx tmp = force_reg (SImode, operands[2]);
3408 if (rtx_equal_p (operands[0], operands[1]))
3409 operands[2] = tmp;
3410 else
3411 {
3412 operands[2] = operands[1];
3413 operands[1] = tmp;
3414 }
3415 }
3416 }"
cffb2a26 3417)
3418
5dcb35d9 3419(define_insn_and_split "*arm_xorsi3"
29e234a3 3420 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r,r")
3421 (xor:SI (match_operand:SI 1 "s_register_operand" "%r,0,r,r")
3422 (match_operand:SI 2 "reg_or_int_operand" "I,l,r,?n")))]
25f905c2 3423 "TARGET_32BIT"
5dcb35d9 3424 "@
29e234a3 3425 eor%?\\t%0, %1, %2
65f68e55 3426 eor%?\\t%0, %1, %2
5dcb35d9 3427 eor%?\\t%0, %1, %2
3428 #"
3429 "TARGET_32BIT
0438d37f 3430 && CONST_INT_P (operands[2])
5dcb35d9 3431 && !const_ok_for_arm (INTVAL (operands[2]))"
3432 [(clobber (const_int 0))]
3433{
3434 arm_split_constant (XOR, SImode, curr_insn,
3435 INTVAL (operands[2]), operands[0], operands[1], 0);
3436 DONE;
3437}
29e234a3 3438 [(set_attr "length" "4,4,4,16")
65f68e55 3439 (set_attr "predicable" "yes")
29e234a3 3440 (set_attr "predicable_short_it" "no,yes,no,no")
1b7da4ac 3441 (set_attr "type" "logic_imm,logic_reg,logic_reg,multiple")]
cffb2a26 3442)
3443
f7fbdd4a 3444(define_insn "*xorsi3_compare0"
bd5b4116 3445 [(set (reg:CC_NOOV CC_REGNUM)
65f68e55 3446 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r,r")
3447 (match_operand:SI 2 "arm_rhs_operand" "I,r"))
9c08d1fa 3448 (const_int 0)))
65f68e55 3449 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 3450 (xor:SI (match_dup 1) (match_dup 2)))]
25f905c2 3451 "TARGET_32BIT"
3ef90e77 3452 "eors%?\\t%0, %1, %2"
65f68e55 3453 [(set_attr "conds" "set")
d82e788e 3454 (set_attr "type" "logics_imm,logics_reg")]
0d66636f 3455)
9c08d1fa 3456
f7fbdd4a 3457(define_insn "*xorsi3_compare0_scratch"
bd5b4116 3458 [(set (reg:CC_NOOV CC_REGNUM)
65f68e55 3459 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r,r")
3460 (match_operand:SI 1 "arm_rhs_operand" "I,r"))
9c08d1fa 3461 (const_int 0)))]
25f905c2 3462 "TARGET_32BIT"
40dbec34 3463 "teq%?\\t%0, %1"
65f68e55 3464 [(set_attr "conds" "set")
d82e788e 3465 (set_attr "type" "logics_imm,logics_reg")]
cffb2a26 3466)
9c08d1fa 3467
215b30b3 3468; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
3469; (NOT D) we can sometimes merge the final NOT into one of the following
3470; insns.
9c08d1fa 3471
3472(define_split
a058e94a 3473 [(set (match_operand:SI 0 "s_register_operand" "")
3474 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
3475 (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
3476 (match_operand:SI 3 "arm_rhs_operand" "")))
3477 (clobber (match_operand:SI 4 "s_register_operand" ""))]
25f905c2 3478 "TARGET_32BIT"
9c08d1fa 3479 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
3480 (not:SI (match_dup 3))))
3481 (set (match_dup 0) (not:SI (match_dup 4)))]
3482 ""
3483)
3484
ba6a3b2f 3485(define_insn_and_split "*andsi_iorsi3_notsi"
9c08d1fa 3486 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
e5fea38e 3487 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "%0,r,r")
9c08d1fa 3488 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
3489 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
25f905c2 3490 "TARGET_32BIT"
ba6a3b2f 3491 "#" ; "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
3492 "&& reload_completed"
3493 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
054fd237 3494 (set (match_dup 0) (and:SI (match_dup 4) (match_dup 5)))]
3495 {
3496 /* If operands[3] is a constant make sure to fold the NOT into it
3497 to avoid creating a NOT of a CONST_INT. */
3498 rtx not_rtx = simplify_gen_unary (NOT, SImode, operands[3], SImode);
3499 if (CONST_INT_P (not_rtx))
3500 {
3501 operands[4] = operands[0];
3502 operands[5] = not_rtx;
3503 }
3504 else
3505 {
3506 operands[5] = operands[0];
3507 operands[4] = not_rtx;
3508 }
3509 }
0d66636f 3510 [(set_attr "length" "8")
25f905c2 3511 (set_attr "ce_count" "2")
d952d547 3512 (set_attr "predicable" "yes")
1b7da4ac 3513 (set_attr "predicable_short_it" "no")
3514 (set_attr "type" "multiple")]
cffb2a26 3515)
9c08d1fa 3516
25f905c2 3517; ??? Are these four splitters still beneficial when the Thumb-2 bitfield
3518; insns are available?
d7863cfe 3519(define_split
3520 [(set (match_operand:SI 0 "s_register_operand" "")
3521 (match_operator:SI 1 "logical_binary_operator"
3522 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
3523 (match_operand:SI 3 "const_int_operand" "")
3524 (match_operand:SI 4 "const_int_operand" ""))
3525 (match_operator:SI 9 "logical_binary_operator"
3526 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3527 (match_operand:SI 6 "const_int_operand" ""))
3528 (match_operand:SI 7 "s_register_operand" "")])]))
3529 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3530 "TARGET_32BIT
d7863cfe 3531 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3532 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3533 [(set (match_dup 8)
3534 (match_op_dup 1
3535 [(ashift:SI (match_dup 2) (match_dup 4))
3536 (match_dup 5)]))
3537 (set (match_dup 0)
3538 (match_op_dup 1
3539 [(lshiftrt:SI (match_dup 8) (match_dup 6))
3540 (match_dup 7)]))]
3541 "
3542 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3543")
3544
3545(define_split
3546 [(set (match_operand:SI 0 "s_register_operand" "")
3547 (match_operator:SI 1 "logical_binary_operator"
3548 [(match_operator:SI 9 "logical_binary_operator"
3549 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3550 (match_operand:SI 6 "const_int_operand" ""))
3551 (match_operand:SI 7 "s_register_operand" "")])
3552 (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
3553 (match_operand:SI 3 "const_int_operand" "")
3554 (match_operand:SI 4 "const_int_operand" ""))]))
3555 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3556 "TARGET_32BIT
d7863cfe 3557 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3558 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3559 [(set (match_dup 8)
3560 (match_op_dup 1
3561 [(ashift:SI (match_dup 2) (match_dup 4))
3562 (match_dup 5)]))
3563 (set (match_dup 0)
3564 (match_op_dup 1
3565 [(lshiftrt:SI (match_dup 8) (match_dup 6))
3566 (match_dup 7)]))]
3567 "
3568 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3569")
3570
3571(define_split
3572 [(set (match_operand:SI 0 "s_register_operand" "")
3573 (match_operator:SI 1 "logical_binary_operator"
3574 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
3575 (match_operand:SI 3 "const_int_operand" "")
3576 (match_operand:SI 4 "const_int_operand" ""))
3577 (match_operator:SI 9 "logical_binary_operator"
3578 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3579 (match_operand:SI 6 "const_int_operand" ""))
3580 (match_operand:SI 7 "s_register_operand" "")])]))
3581 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3582 "TARGET_32BIT
d7863cfe 3583 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3584 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3585 [(set (match_dup 8)
3586 (match_op_dup 1
3587 [(ashift:SI (match_dup 2) (match_dup 4))
3588 (match_dup 5)]))
3589 (set (match_dup 0)
3590 (match_op_dup 1
3591 [(ashiftrt:SI (match_dup 8) (match_dup 6))
3592 (match_dup 7)]))]
3593 "
3594 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3595")
3596
3597(define_split
3598 [(set (match_operand:SI 0 "s_register_operand" "")
3599 (match_operator:SI 1 "logical_binary_operator"
3600 [(match_operator:SI 9 "logical_binary_operator"
3601 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3602 (match_operand:SI 6 "const_int_operand" ""))
3603 (match_operand:SI 7 "s_register_operand" "")])
3604 (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
3605 (match_operand:SI 3 "const_int_operand" "")
3606 (match_operand:SI 4 "const_int_operand" ""))]))
3607 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3608 "TARGET_32BIT
d7863cfe 3609 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3610 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3611 [(set (match_dup 8)
3612 (match_op_dup 1
3613 [(ashift:SI (match_dup 2) (match_dup 4))
3614 (match_dup 5)]))
3615 (set (match_dup 0)
3616 (match_op_dup 1
3617 [(ashiftrt:SI (match_dup 8) (match_dup 6))
3618 (match_dup 7)]))]
3619 "
3620 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3621")
9c08d1fa 3622\f
3623
3624;; Minimum and maximum insns
3625
8b9dc177 3626(define_expand "smaxsi3"
3627 [(parallel [
3628 (set (match_operand:SI 0 "s_register_operand" "")
3629 (smax:SI (match_operand:SI 1 "s_register_operand" "")
3630 (match_operand:SI 2 "arm_rhs_operand" "")))
3631 (clobber (reg:CC CC_REGNUM))])]
25f905c2 3632 "TARGET_32BIT"
8b9dc177 3633 "
8774928b 3634 if (operands[2] == const0_rtx || operands[2] == constm1_rtx)
8b9dc177 3635 {
3636 /* No need for a clobber of the condition code register here. */
d1f9b275 3637 emit_insn (gen_rtx_SET (operands[0],
8b9dc177 3638 gen_rtx_SMAX (SImode, operands[1],
3639 operands[2])));
3640 DONE;
3641 }
3642")
3643
3644(define_insn "*smax_0"
3645 [(set (match_operand:SI 0 "s_register_operand" "=r")
3646 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3647 (const_int 0)))]
25f905c2 3648 "TARGET_32BIT"
8b9dc177 3649 "bic%?\\t%0, %1, %1, asr #31"
d952d547 3650 [(set_attr "predicable" "yes")
1b7da4ac 3651 (set_attr "predicable_short_it" "no")
3652 (set_attr "type" "logic_shift_reg")]
8b9dc177 3653)
3654
8774928b 3655(define_insn "*smax_m1"
3656 [(set (match_operand:SI 0 "s_register_operand" "=r")
3657 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3658 (const_int -1)))]
25f905c2 3659 "TARGET_32BIT"
8774928b 3660 "orr%?\\t%0, %1, %1, asr #31"
d952d547 3661 [(set_attr "predicable" "yes")
1b7da4ac 3662 (set_attr "predicable_short_it" "no")
3663 (set_attr "type" "logic_shift_reg")]
8774928b 3664)
3665
3dc953f2 3666(define_insn_and_split "*arm_smax_insn"
8b9dc177 3667 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3668 (smax:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3669 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
bd5b4116 3670 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3671 "TARGET_ARM"
3dc953f2 3672 "#"
3673 ; cmp\\t%1, %2\;movlt\\t%0, %2
3674 ; cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
3675 "TARGET_ARM"
3676 [(set (reg:CC CC_REGNUM)
3677 (compare:CC (match_dup 1) (match_dup 2)))
3678 (set (match_dup 0)
3679 (if_then_else:SI (ge:SI (reg:CC CC_REGNUM) (const_int 0))
3680 (match_dup 1)
3681 (match_dup 2)))]
3682 ""
cffb2a26 3683 [(set_attr "conds" "clob")
1b7da4ac 3684 (set_attr "length" "8,12")
3685 (set_attr "type" "multiple")]
cffb2a26 3686)
9c08d1fa 3687
8b9dc177 3688(define_expand "sminsi3"
3689 [(parallel [
3690 (set (match_operand:SI 0 "s_register_operand" "")
3691 (smin:SI (match_operand:SI 1 "s_register_operand" "")
3692 (match_operand:SI 2 "arm_rhs_operand" "")))
3693 (clobber (reg:CC CC_REGNUM))])]
25f905c2 3694 "TARGET_32BIT"
8b9dc177 3695 "
3696 if (operands[2] == const0_rtx)
3697 {
3698 /* No need for a clobber of the condition code register here. */
d1f9b275 3699 emit_insn (gen_rtx_SET (operands[0],
8b9dc177 3700 gen_rtx_SMIN (SImode, operands[1],
3701 operands[2])));
3702 DONE;
3703 }
3704")
3705
3706(define_insn "*smin_0"
3707 [(set (match_operand:SI 0 "s_register_operand" "=r")
3708 (smin:SI (match_operand:SI 1 "s_register_operand" "r")
3709 (const_int 0)))]
25f905c2 3710 "TARGET_32BIT"
8b9dc177 3711 "and%?\\t%0, %1, %1, asr #31"
d952d547 3712 [(set_attr "predicable" "yes")
1b7da4ac 3713 (set_attr "predicable_short_it" "no")
3714 (set_attr "type" "logic_shift_reg")]
8b9dc177 3715)
3716
3dc953f2 3717(define_insn_and_split "*arm_smin_insn"
8b9dc177 3718 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3719 (smin:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3720 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
bd5b4116 3721 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3722 "TARGET_ARM"
3dc953f2 3723 "#"
3724 ; cmp\\t%1, %2\;movge\\t%0, %2
3725 ; cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
3726 "TARGET_ARM"
3727 [(set (reg:CC CC_REGNUM)
3728 (compare:CC (match_dup 1) (match_dup 2)))
3729 (set (match_dup 0)
3730 (if_then_else:SI (lt:SI (reg:CC CC_REGNUM) (const_int 0))
3731 (match_dup 1)
3732 (match_dup 2)))]
3733 ""
0d66636f 3734 [(set_attr "conds" "clob")
1b7da4ac 3735 (set_attr "length" "8,12")
3736 (set_attr "type" "multiple,multiple")]
0d66636f 3737)
9c08d1fa 3738
25f905c2 3739(define_expand "umaxsi3"
3740 [(parallel [
3741 (set (match_operand:SI 0 "s_register_operand" "")
3742 (umax:SI (match_operand:SI 1 "s_register_operand" "")
3743 (match_operand:SI 2 "arm_rhs_operand" "")))
3744 (clobber (reg:CC CC_REGNUM))])]
3745 "TARGET_32BIT"
3746 ""
3747)
3748
3dc953f2 3749(define_insn_and_split "*arm_umaxsi3"
9c08d1fa 3750 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3751 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3752 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 3753 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3754 "TARGET_ARM"
3dc953f2 3755 "#"
3756 ; cmp\\t%1, %2\;movcc\\t%0, %2
3757 ; cmp\\t%1, %2\;movcs\\t%0, %1
3758 ; cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
3759 "TARGET_ARM"
3760 [(set (reg:CC CC_REGNUM)
3761 (compare:CC (match_dup 1) (match_dup 2)))
3762 (set (match_dup 0)
3763 (if_then_else:SI (geu:SI (reg:CC CC_REGNUM) (const_int 0))
3764 (match_dup 1)
3765 (match_dup 2)))]
3766 ""
0d66636f 3767 [(set_attr "conds" "clob")
1b7da4ac 3768 (set_attr "length" "8,8,12")
3769 (set_attr "type" "store1")]
0d66636f 3770)
9c08d1fa 3771
25f905c2 3772(define_expand "uminsi3"
3773 [(parallel [
3774 (set (match_operand:SI 0 "s_register_operand" "")
3775 (umin:SI (match_operand:SI 1 "s_register_operand" "")
3776 (match_operand:SI 2 "arm_rhs_operand" "")))
3777 (clobber (reg:CC CC_REGNUM))])]
3778 "TARGET_32BIT"
3779 ""
3780)
3781
3dc953f2 3782(define_insn_and_split "*arm_uminsi3"
9c08d1fa 3783 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3784 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3785 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 3786 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3787 "TARGET_ARM"
3dc953f2 3788 "#"
3789 ; cmp\\t%1, %2\;movcs\\t%0, %2
3790 ; cmp\\t%1, %2\;movcc\\t%0, %1
3791 ; cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
3792 "TARGET_ARM"
3793 [(set (reg:CC CC_REGNUM)
3794 (compare:CC (match_dup 1) (match_dup 2)))
3795 (set (match_dup 0)
3796 (if_then_else:SI (ltu:SI (reg:CC CC_REGNUM) (const_int 0))
3797 (match_dup 1)
3798 (match_dup 2)))]
3799 ""
0d66636f 3800 [(set_attr "conds" "clob")
1b7da4ac 3801 (set_attr "length" "8,8,12")
3802 (set_attr "type" "store1")]
0d66636f 3803)
9c08d1fa 3804
8a18b90c 3805(define_insn "*store_minmaxsi"
9c08d1fa 3806 [(set (match_operand:SI 0 "memory_operand" "=m")
3807 (match_operator:SI 3 "minmax_operator"
3808 [(match_operand:SI 1 "s_register_operand" "r")
3809 (match_operand:SI 2 "s_register_operand" "r")]))
bd5b4116 3810 (clobber (reg:CC CC_REGNUM))]
b207d152 3811 "TARGET_32BIT && optimize_function_for_size_p (cfun) && !arm_restrict_it"
9c08d1fa 3812 "*
dc55b8a9 3813 operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
3814 operands[1], operands[2]);
e2348bcb 3815 output_asm_insn (\"cmp\\t%1, %2\", operands);
25f905c2 3816 if (TARGET_THUMB2)
3817 output_asm_insn (\"ite\t%d3\", operands);
e2348bcb 3818 output_asm_insn (\"str%d3\\t%1, %0\", operands);
3819 output_asm_insn (\"str%D3\\t%2, %0\", operands);
3820 return \"\";
0d66636f 3821 "
3822 [(set_attr "conds" "clob")
25f905c2 3823 (set (attr "length")
3824 (if_then_else (eq_attr "is_thumb" "yes")
3825 (const_int 14)
3826 (const_int 12)))
0d66636f 3827 (set_attr "type" "store1")]
3828)
9c08d1fa 3829
8a18b90c 3830; Reject the frame pointer in operand[1], since reloading this after
3831; it has been eliminated can cause carnage.
f7fbdd4a 3832(define_insn "*minmax_arithsi"
9c08d1fa 3833 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3834 (match_operator:SI 4 "shiftable_operator"
3835 [(match_operator:SI 5 "minmax_operator"
3836 [(match_operand:SI 2 "s_register_operand" "r,r")
3837 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
3838 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 3839 (clobber (reg:CC CC_REGNUM))]
7c36fe71 3840 "TARGET_32BIT && !arm_eliminable_register (operands[1]) && !arm_restrict_it"
9c08d1fa 3841 "*
0d66636f 3842 {
3843 enum rtx_code code = GET_CODE (operands[4]);
25f905c2 3844 bool need_else;
3845
3846 if (which_alternative != 0 || operands[3] != const0_rtx
ca0fc5a2 3847 || (code != PLUS && code != IOR && code != XOR))
25f905c2 3848 need_else = true;
3849 else
3850 need_else = false;
0d66636f 3851
dc55b8a9 3852 operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
3853 operands[2], operands[3]);
0d66636f 3854 output_asm_insn (\"cmp\\t%2, %3\", operands);
25f905c2 3855 if (TARGET_THUMB2)
3856 {
3857 if (need_else)
3858 output_asm_insn (\"ite\\t%d5\", operands);
3859 else
3860 output_asm_insn (\"it\\t%d5\", operands);
3861 }
0d66636f 3862 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
25f905c2 3863 if (need_else)
0d66636f 3864 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
3865 return \"\";
215b30b3 3866 }"
0d66636f 3867 [(set_attr "conds" "clob")
25f905c2 3868 (set (attr "length")
3869 (if_then_else (eq_attr "is_thumb" "yes")
3870 (const_int 14)
1b7da4ac 3871 (const_int 12)))
3872 (set_attr "type" "multiple")]
0d66636f 3873)
9c08d1fa 3874
4164bca1 3875; Reject the frame pointer in operand[1], since reloading this after
3876; it has been eliminated can cause carnage.
3877(define_insn_and_split "*minmax_arithsi_non_canon"
7c36fe71 3878 [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts")
4164bca1 3879 (minus:SI
7c36fe71 3880 (match_operand:SI 1 "s_register_operand" "0,?Ts")
4164bca1 3881 (match_operator:SI 4 "minmax_operator"
7c36fe71 3882 [(match_operand:SI 2 "s_register_operand" "Ts,Ts")
3883 (match_operand:SI 3 "arm_rhs_operand" "TsI,TsI")])))
4164bca1 3884 (clobber (reg:CC CC_REGNUM))]
7c36fe71 3885 "TARGET_32BIT && !arm_eliminable_register (operands[1])
3886 && !(arm_restrict_it && CONST_INT_P (operands[3]))"
4164bca1 3887 "#"
3888 "TARGET_32BIT && !arm_eliminable_register (operands[1]) && reload_completed"
3889 [(set (reg:CC CC_REGNUM)
3890 (compare:CC (match_dup 2) (match_dup 3)))
3891
3892 (cond_exec (match_op_dup 4 [(reg:CC CC_REGNUM) (const_int 0)])
3893 (set (match_dup 0)
3894 (minus:SI (match_dup 1)
3895 (match_dup 2))))
3896 (cond_exec (match_op_dup 5 [(reg:CC CC_REGNUM) (const_int 0)])
3897 (set (match_dup 0)
36ee0cde 3898 (match_dup 6)))]
4164bca1 3899 {
3754d046 3900 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
4164bca1 3901 operands[2], operands[3]);
3902 enum rtx_code rc = minmax_code (operands[4]);
3903 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode,
3904 operands[2], operands[3]);
3905
3906 if (mode == CCFPmode || mode == CCFPEmode)
3907 rc = reverse_condition_maybe_unordered (rc);
3908 else
3909 rc = reverse_condition (rc);
3910 operands[5] = gen_rtx_fmt_ee (rc, SImode, operands[2], operands[3]);
36ee0cde 3911 if (CONST_INT_P (operands[3]))
3912 operands[6] = plus_constant (SImode, operands[1], -INTVAL (operands[3]));
3913 else
3914 operands[6] = gen_rtx_MINUS (SImode, operands[1], operands[3]);
4164bca1 3915 }
3916 [(set_attr "conds" "clob")
3917 (set (attr "length")
3918 (if_then_else (eq_attr "is_thumb" "yes")
3919 (const_int 14)
1b7da4ac 3920 (const_int 12)))
3921 (set_attr "type" "multiple")]
4164bca1 3922)
3923
b49e3742 3924(define_code_iterator SAT [smin smax])
3925(define_code_iterator SATrev [smin smax])
3926(define_code_attr SATlo [(smin "1") (smax "2")])
3927(define_code_attr SAThi [(smin "2") (smax "1")])
3928
3929(define_insn "*satsi_<SAT:code>"
3930 [(set (match_operand:SI 0 "s_register_operand" "=r")
3931 (SAT:SI (SATrev:SI (match_operand:SI 3 "s_register_operand" "r")
3932 (match_operand:SI 1 "const_int_operand" "i"))
3933 (match_operand:SI 2 "const_int_operand" "i")))]
3934 "TARGET_32BIT && arm_arch6 && <SAT:CODE> != <SATrev:CODE>
3935 && arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>], NULL, NULL)"
3936{
3937 int mask;
3938 bool signed_sat;
3939 if (!arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>],
3940 &mask, &signed_sat))
3941 gcc_unreachable ();
3942
3943 operands[1] = GEN_INT (mask);
3944 if (signed_sat)
3945 return "ssat%?\t%0, %1, %3";
3946 else
3947 return "usat%?\t%0, %1, %3";
3948}
7c36fe71 3949 [(set_attr "predicable" "yes")
1b7da4ac 3950 (set_attr "predicable_short_it" "no")
3951 (set_attr "type" "alus_imm")]
bebe9bbb 3952)
b49e3742 3953
3954(define_insn "*satsi_<SAT:code>_shift"
3955 [(set (match_operand:SI 0 "s_register_operand" "=r")
3956 (SAT:SI (SATrev:SI (match_operator:SI 3 "sat_shift_operator"
3957 [(match_operand:SI 4 "s_register_operand" "r")
3958 (match_operand:SI 5 "const_int_operand" "i")])
3959 (match_operand:SI 1 "const_int_operand" "i"))
3960 (match_operand:SI 2 "const_int_operand" "i")))]
3961 "TARGET_32BIT && arm_arch6 && <SAT:CODE> != <SATrev:CODE>
3962 && arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>], NULL, NULL)"
3963{
3964 int mask;
3965 bool signed_sat;
3966 if (!arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>],
3967 &mask, &signed_sat))
3968 gcc_unreachable ();
3969
3970 operands[1] = GEN_INT (mask);
3971 if (signed_sat)
3972 return "ssat%?\t%0, %1, %4%S3";
3973 else
3974 return "usat%?\t%0, %1, %4%S3";
3975}
3976 [(set_attr "predicable" "yes")
7c36fe71 3977 (set_attr "predicable_short_it" "no")
b49e3742 3978 (set_attr "shift" "3")
d82e788e 3979 (set_attr "type" "logic_shift_reg")])
b11cae9e 3980\f
3981;; Shift and rotation insns
3982
a2cd141b 3983(define_expand "ashldi3"
3984 [(set (match_operand:DI 0 "s_register_operand" "")
3985 (ashift:DI (match_operand:DI 1 "s_register_operand" "")
aa06c51c 3986 (match_operand:SI 2 "general_operand" "")))]
25f905c2 3987 "TARGET_32BIT"
a2cd141b 3988 "
aa06c51c 3989 if (TARGET_NEON)
3990 {
3991 /* Delay the decision whether to use NEON or core-regs until
3992 register allocation. */
3993 emit_insn (gen_ashldi3_neon (operands[0], operands[1], operands[2]));
3994 DONE;
3995 }
3996 else
3997 {
3998 /* Only the NEON case can handle in-memory shift counts. */
3999 if (!reg_or_int_operand (operands[2], SImode))
4000 operands[2] = force_reg (SImode, operands[2]);
4001 }
4002
b805622c 4003 if (!CONST_INT_P (operands[2]) && TARGET_REALLY_IWMMXT)
ffcc986d 4004 ; /* No special preparation statements; expand pattern as above. */
4005 else
a2cd141b 4006 {
ffcc986d 4007 rtx scratch1, scratch2;
4008
8c4e8755 4009 if (operands[2] == CONST1_RTX (SImode))
a2cd141b 4010 {
4011 emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
4012 DONE;
4013 }
ffcc986d 4014
4015 /* Ideally we should use iwmmxt here if we could know that operands[1]
4016 ends up already living in an iwmmxt register. Otherwise it's
4017 cheaper to have the alternate code being generated than moving
4018 values to iwmmxt regs and back. */
4019
ffcc986d 4020 /* Expand operation using core-registers.
4021 'FAIL' would achieve the same thing, but this is a bit smarter. */
4022 scratch1 = gen_reg_rtx (SImode);
4023 scratch2 = gen_reg_rtx (SImode);
4024 arm_emit_coreregs_64bit_shift (ASHIFT, operands[0], operands[1],
4025 operands[2], scratch1, scratch2);
4026 DONE;
a2cd141b 4027 }
a2cd141b 4028 "
4029)
4030
2837e3fb 4031(define_insn "arm_ashldi3_1bit"
50ad1bf9 4032 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 4033 (ashift:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 4034 (const_int 1)))
4035 (clobber (reg:CC CC_REGNUM))]
25f905c2 4036 "TARGET_32BIT"
2837e3fb 4037 "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
a2cd141b 4038 [(set_attr "conds" "clob")
1b7da4ac 4039 (set_attr "length" "8")
4040 (set_attr "type" "multiple")]
a2cd141b 4041)
4042
87b22bf7 4043(define_expand "ashlsi3"
cffb2a26 4044 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 4045 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
4046 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 4047 "TARGET_EITHER"
87b22bf7 4048 "
0438d37f 4049 if (CONST_INT_P (operands[2])
8c4e8755 4050 && (UINTVAL (operands[2])) > 31)
87b22bf7 4051 {
4052 emit_insn (gen_movsi (operands[0], const0_rtx));
4053 DONE;
4054 }
cffb2a26 4055 "
4056)
4057
a2cd141b 4058(define_expand "ashrdi3"
4059 [(set (match_operand:DI 0 "s_register_operand" "")
4060 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
4061 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 4062 "TARGET_32BIT"
a2cd141b 4063 "
aa06c51c 4064 if (TARGET_NEON)
4065 {
4066 /* Delay the decision whether to use NEON or core-regs until
4067 register allocation. */
4068 emit_insn (gen_ashrdi3_neon (operands[0], operands[1], operands[2]));
4069 DONE;
4070 }
4071
b805622c 4072 if (!CONST_INT_P (operands[2]) && TARGET_REALLY_IWMMXT)
ffcc986d 4073 ; /* No special preparation statements; expand pattern as above. */
4074 else
a2cd141b 4075 {
ffcc986d 4076 rtx scratch1, scratch2;
4077
8c4e8755 4078 if (operands[2] == CONST1_RTX (SImode))
a2cd141b 4079 {
4080 emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
4081 DONE;
4082 }
ffcc986d 4083
4084 /* Ideally we should use iwmmxt here if we could know that operands[1]
4085 ends up already living in an iwmmxt register. Otherwise it's
4086 cheaper to have the alternate code being generated than moving
4087 values to iwmmxt regs and back. */
4088
ffcc986d 4089 /* Expand operation using core-registers.
4090 'FAIL' would achieve the same thing, but this is a bit smarter. */
4091 scratch1 = gen_reg_rtx (SImode);
4092 scratch2 = gen_reg_rtx (SImode);
4093 arm_emit_coreregs_64bit_shift (ASHIFTRT, operands[0], operands[1],
4094 operands[2], scratch1, scratch2);
4095 DONE;
a2cd141b 4096 }
a2cd141b 4097 "
4098)
4099
2837e3fb 4100(define_insn "arm_ashrdi3_1bit"
50ad1bf9 4101 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 4102 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 4103 (const_int 1)))
4104 (clobber (reg:CC CC_REGNUM))]
25f905c2 4105 "TARGET_32BIT"
2837e3fb 4106 "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
a2cd141b 4107 [(set_attr "conds" "clob")
1b7da4ac 4108 (set_attr "length" "8")
4109 (set_attr "type" "multiple")]
a2cd141b 4110)
4111
87b22bf7 4112(define_expand "ashrsi3"
cffb2a26 4113 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 4114 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
4115 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 4116 "TARGET_EITHER"
87b22bf7 4117 "
0438d37f 4118 if (CONST_INT_P (operands[2])
8c4e8755 4119 && UINTVAL (operands[2]) > 31)
87b22bf7 4120 operands[2] = GEN_INT (31);
cffb2a26 4121 "
4122)
4123
a2cd141b 4124(define_expand "lshrdi3"
4125 [(set (match_operand:DI 0 "s_register_operand" "")
4126 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
4127 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 4128 "TARGET_32BIT"
a2cd141b 4129 "
aa06c51c 4130 if (TARGET_NEON)
4131 {
4132 /* Delay the decision whether to use NEON or core-regs until
4133 register allocation. */
4134 emit_insn (gen_lshrdi3_neon (operands[0], operands[1], operands[2]));
4135 DONE;
4136 }
4137
b805622c 4138 if (!CONST_INT_P (operands[2]) && TARGET_REALLY_IWMMXT)
ffcc986d 4139 ; /* No special preparation statements; expand pattern as above. */
4140 else
a2cd141b 4141 {
ffcc986d 4142 rtx scratch1, scratch2;
4143
8c4e8755 4144 if (operands[2] == CONST1_RTX (SImode))
a2cd141b 4145 {
4146 emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
4147 DONE;
4148 }
ffcc986d 4149
4150 /* Ideally we should use iwmmxt here if we could know that operands[1]
4151 ends up already living in an iwmmxt register. Otherwise it's
4152 cheaper to have the alternate code being generated than moving
4153 values to iwmmxt regs and back. */
4154
ffcc986d 4155 /* Expand operation using core-registers.
4156 'FAIL' would achieve the same thing, but this is a bit smarter. */
4157 scratch1 = gen_reg_rtx (SImode);
4158 scratch2 = gen_reg_rtx (SImode);
4159 arm_emit_coreregs_64bit_shift (LSHIFTRT, operands[0], operands[1],
4160 operands[2], scratch1, scratch2);
4161 DONE;
a2cd141b 4162 }
a2cd141b 4163 "
4164)
4165
2837e3fb 4166(define_insn "arm_lshrdi3_1bit"
50ad1bf9 4167 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 4168 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 4169 (const_int 1)))
4170 (clobber (reg:CC CC_REGNUM))]
25f905c2 4171 "TARGET_32BIT"
2837e3fb 4172 "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
a2cd141b 4173 [(set_attr "conds" "clob")
1b7da4ac 4174 (set_attr "length" "8")
4175 (set_attr "type" "multiple")]
a2cd141b 4176)
4177
87b22bf7 4178(define_expand "lshrsi3"
cffb2a26 4179 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 4180 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
4181 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 4182 "TARGET_EITHER"
87b22bf7 4183 "
0438d37f 4184 if (CONST_INT_P (operands[2])
8c4e8755 4185 && (UINTVAL (operands[2])) > 31)
87b22bf7 4186 {
4187 emit_insn (gen_movsi (operands[0], const0_rtx));
4188 DONE;
4189 }
cffb2a26 4190 "
4191)
4192
87b22bf7 4193(define_expand "rotlsi3"
cffb2a26 4194 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 4195 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
4196 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 4197 "TARGET_32BIT"
87b22bf7 4198 "
0438d37f 4199 if (CONST_INT_P (operands[2]))
87b22bf7 4200 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
4201 else
b11cae9e 4202 {
87b22bf7 4203 rtx reg = gen_reg_rtx (SImode);
4204 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
4205 operands[2] = reg;
b11cae9e 4206 }
cffb2a26 4207 "
4208)
9c08d1fa 4209
87b22bf7 4210(define_expand "rotrsi3"
cffb2a26 4211 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 4212 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
4213 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 4214 "TARGET_EITHER"
87b22bf7 4215 "
25f905c2 4216 if (TARGET_32BIT)
cffb2a26 4217 {
0438d37f 4218 if (CONST_INT_P (operands[2])
8c4e8755 4219 && UINTVAL (operands[2]) > 31)
cffb2a26 4220 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
4221 }
25f905c2 4222 else /* TARGET_THUMB1 */
cffb2a26 4223 {
0438d37f 4224 if (CONST_INT_P (operands [2]))
cffb2a26 4225 operands [2] = force_reg (SImode, operands[2]);
4226 }
4227 "
4228)
87b22bf7 4229
cffb2a26 4230(define_insn "*arm_shiftsi3"
88c29385 4231 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r,r")
cffb2a26 4232 (match_operator:SI 3 "shift_operator"
88c29385 4233 [(match_operand:SI 1 "s_register_operand" "0,l,r,r")
4234 (match_operand:SI 2 "reg_or_int_operand" "l,M,M,r")]))]
25f905c2 4235 "TARGET_32BIT"
4236 "* return arm_output_shift(operands, 0);"
344495ea 4237 [(set_attr "predicable" "yes")
88c29385 4238 (set_attr "arch" "t2,t2,*,*")
4239 (set_attr "predicable_short_it" "yes,yes,no,no")
7c36fe71 4240 (set_attr "length" "4")
331beb1a 4241 (set_attr "shift" "1")
88c29385 4242 (set_attr "type" "alu_shift_reg,alu_shift_imm,alu_shift_imm,alu_shift_reg")]
6c4c2133 4243)
87b22bf7 4244
f7fbdd4a 4245(define_insn "*shiftsi3_compare0"
bd5b4116 4246 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 4247 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
6b6abc9c 4248 [(match_operand:SI 1 "s_register_operand" "r,r")
4249 (match_operand:SI 2 "arm_rhs_operand" "M,r")])
9c08d1fa 4250 (const_int 0)))
6b6abc9c 4251 (set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 4252 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
25f905c2 4253 "TARGET_32BIT"
4254 "* return arm_output_shift(operands, 1);"
344495ea 4255 [(set_attr "conds" "set")
331beb1a 4256 (set_attr "shift" "1")
d82e788e 4257 (set_attr "type" "alus_shift_imm,alus_shift_reg")]
0d66636f 4258)
9c08d1fa 4259
f7fbdd4a 4260(define_insn "*shiftsi3_compare0_scratch"
bd5b4116 4261 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 4262 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
6b6abc9c 4263 [(match_operand:SI 1 "s_register_operand" "r,r")
4264 (match_operand:SI 2 "arm_rhs_operand" "M,r")])
9c08d1fa 4265 (const_int 0)))
6b6abc9c 4266 (clobber (match_scratch:SI 0 "=r,r"))]
25f905c2 4267 "TARGET_32BIT"
4268 "* return arm_output_shift(operands, 1);"
344495ea 4269 [(set_attr "conds" "set")
6b6abc9c 4270 (set_attr "shift" "1")
d82e788e 4271 (set_attr "type" "shift_imm,shift_reg")]
0d66636f 4272)
9c08d1fa 4273
d5d4dc8d 4274(define_insn "*not_shiftsi"
4275 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 4276 (not:SI (match_operator:SI 3 "shift_operator"
d5d4dc8d 4277 [(match_operand:SI 1 "s_register_operand" "r,r")
4278 (match_operand:SI 2 "shift_amount_operand" "M,rM")])))]
4279 "TARGET_32BIT"
6c4c2133 4280 "mvn%?\\t%0, %1%S3"
344495ea 4281 [(set_attr "predicable" "yes")
d952d547 4282 (set_attr "predicable_short_it" "no")
331beb1a 4283 (set_attr "shift" "1")
d5d4dc8d 4284 (set_attr "arch" "32,a")
1aed5204 4285 (set_attr "type" "mvn_shift,mvn_shift_reg")])
9c08d1fa 4286
d5d4dc8d 4287(define_insn "*not_shiftsi_compare0"
bd5b4116 4288 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 4289 (compare:CC_NOOV
4290 (not:SI (match_operator:SI 3 "shift_operator"
4291 [(match_operand:SI 1 "s_register_operand" "r,r")
4292 (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
4293 (const_int 0)))
4294 (set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 4295 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
d5d4dc8d 4296 "TARGET_32BIT"
3ef90e77 4297 "mvns%?\\t%0, %1%S3"
344495ea 4298 [(set_attr "conds" "set")
331beb1a 4299 (set_attr "shift" "1")
d5d4dc8d 4300 (set_attr "arch" "32,a")
1aed5204 4301 (set_attr "type" "mvn_shift,mvn_shift_reg")])
9c08d1fa 4302
d5d4dc8d 4303(define_insn "*not_shiftsi_compare0_scratch"
bd5b4116 4304 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 4305 (compare:CC_NOOV
4306 (not:SI (match_operator:SI 3 "shift_operator"
4307 [(match_operand:SI 1 "s_register_operand" "r,r")
4308 (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
4309 (const_int 0)))
4310 (clobber (match_scratch:SI 0 "=r,r"))]
4311 "TARGET_32BIT"
3ef90e77 4312 "mvns%?\\t%0, %1%S3"
344495ea 4313 [(set_attr "conds" "set")
331beb1a 4314 (set_attr "shift" "1")
d5d4dc8d 4315 (set_attr "arch" "32,a")
1aed5204 4316 (set_attr "type" "mvn_shift,mvn_shift_reg")])
9c08d1fa 4317
cffb2a26 4318;; We don't really have extzv, but defining this using shifts helps
4319;; to reduce register pressure later on.
4320
4321(define_expand "extzv"
eb04cafb 4322 [(set (match_operand 0 "s_register_operand" "")
4323 (zero_extract (match_operand 1 "nonimmediate_operand" "")
4324 (match_operand 2 "const_int_operand" "")
4325 (match_operand 3 "const_int_operand" "")))]
8b054d5a 4326 "TARGET_THUMB1 || arm_arch_thumb2"
cffb2a26 4327 "
4328 {
4329 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
4330 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
4331
8b054d5a 4332 if (arm_arch_thumb2)
4333 {
eb04cafb 4334 HOST_WIDE_INT width = INTVAL (operands[2]);
4335 HOST_WIDE_INT bitpos = INTVAL (operands[3]);
4336
4337 if (unaligned_access && MEM_P (operands[1])
4338 && (width == 16 || width == 32) && (bitpos % BITS_PER_UNIT) == 0)
4339 {
4340 rtx base_addr;
4341
4342 if (BYTES_BIG_ENDIAN)
4343 bitpos = GET_MODE_BITSIZE (GET_MODE (operands[0])) - width
4344 - bitpos;
4345
4346 if (width == 32)
4347 {
4348 base_addr = adjust_address (operands[1], SImode,
4349 bitpos / BITS_PER_UNIT);
4350 emit_insn (gen_unaligned_loadsi (operands[0], base_addr));
4351 }
4352 else
4353 {
4354 rtx dest = operands[0];
4355 rtx tmp = gen_reg_rtx (SImode);
4356
4357 /* We may get a paradoxical subreg here. Strip it off. */
4358 if (GET_CODE (dest) == SUBREG
4359 && GET_MODE (dest) == SImode
4360 && GET_MODE (SUBREG_REG (dest)) == HImode)
4361 dest = SUBREG_REG (dest);
4362
4363 if (GET_MODE_BITSIZE (GET_MODE (dest)) != width)
4364 FAIL;
4365
4366 base_addr = adjust_address (operands[1], HImode,
4367 bitpos / BITS_PER_UNIT);
4368 emit_insn (gen_unaligned_loadhiu (tmp, base_addr));
4369 emit_move_insn (gen_lowpart (SImode, dest), tmp);
4370 }
4371 DONE;
4372 }
4373 else if (s_register_operand (operands[1], GET_MODE (operands[1])))
4374 {
4375 emit_insn (gen_extzv_t2 (operands[0], operands[1], operands[2],
4376 operands[3]));
4377 DONE;
4378 }
4379 else
4380 FAIL;
8b054d5a 4381 }
eb04cafb 4382
4383 if (!s_register_operand (operands[1], GET_MODE (operands[1])))
4384 FAIL;
8b054d5a 4385
cffb2a26 4386 operands[3] = GEN_INT (rshift);
4387
4388 if (lshift == 0)
4389 {
4390 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
4391 DONE;
4392 }
4393
eb04cafb 4394 emit_insn (gen_extzv_t1 (operands[0], operands[1], GEN_INT (lshift),
4395 operands[3], gen_reg_rtx (SImode)));
4396 DONE;
215b30b3 4397 }"
cffb2a26 4398)
4399
eb04cafb 4400;; Helper for extzv, for the Thumb-1 register-shifts case.
4401
4402(define_expand "extzv_t1"
4403 [(set (match_operand:SI 4 "s_register_operand" "")
4404 (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "")
4405 (match_operand:SI 2 "const_int_operand" "")))
4406 (set (match_operand:SI 0 "s_register_operand" "")
4407 (lshiftrt:SI (match_dup 4)
4408 (match_operand:SI 3 "const_int_operand" "")))]
4409 "TARGET_THUMB1"
4410 "")
4411
4412(define_expand "extv"
4413 [(set (match_operand 0 "s_register_operand" "")
4414 (sign_extract (match_operand 1 "nonimmediate_operand" "")
4415 (match_operand 2 "const_int_operand" "")
4416 (match_operand 3 "const_int_operand" "")))]
4417 "arm_arch_thumb2"
4418{
4419 HOST_WIDE_INT width = INTVAL (operands[2]);
4420 HOST_WIDE_INT bitpos = INTVAL (operands[3]);
4421
4422 if (unaligned_access && MEM_P (operands[1]) && (width == 16 || width == 32)
4423 && (bitpos % BITS_PER_UNIT) == 0)
4424 {
4425 rtx base_addr;
4426
4427 if (BYTES_BIG_ENDIAN)
4428 bitpos = GET_MODE_BITSIZE (GET_MODE (operands[0])) - width - bitpos;
4429
4430 if (width == 32)
4431 {
4432 base_addr = adjust_address (operands[1], SImode,
4433 bitpos / BITS_PER_UNIT);
4434 emit_insn (gen_unaligned_loadsi (operands[0], base_addr));
4435 }
4436 else
4437 {
4438 rtx dest = operands[0];
4439 rtx tmp = gen_reg_rtx (SImode);
4440
4441 /* We may get a paradoxical subreg here. Strip it off. */
4442 if (GET_CODE (dest) == SUBREG
4443 && GET_MODE (dest) == SImode
4444 && GET_MODE (SUBREG_REG (dest)) == HImode)
4445 dest = SUBREG_REG (dest);
4446
4447 if (GET_MODE_BITSIZE (GET_MODE (dest)) != width)
4448 FAIL;
4449
4450 base_addr = adjust_address (operands[1], HImode,
4451 bitpos / BITS_PER_UNIT);
4452 emit_insn (gen_unaligned_loadhis (tmp, base_addr));
4453 emit_move_insn (gen_lowpart (SImode, dest), tmp);
4454 }
4455
4456 DONE;
4457 }
4458 else if (!s_register_operand (operands[1], GET_MODE (operands[1])))
4459 FAIL;
4460 else if (GET_MODE (operands[0]) == SImode
4461 && GET_MODE (operands[1]) == SImode)
4462 {
4463 emit_insn (gen_extv_regsi (operands[0], operands[1], operands[2],
4464 operands[3]));
4465 DONE;
4466 }
4467
4468 FAIL;
4469})
4470
4471; Helper to expand register forms of extv with the proper modes.
4472
4473(define_expand "extv_regsi"
4474 [(set (match_operand:SI 0 "s_register_operand" "")
4475 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
4476 (match_operand 2 "const_int_operand" "")
4477 (match_operand 3 "const_int_operand" "")))]
4478 ""
4479{
4480})
4481
4482; ARMv6+ unaligned load/store instructions (used for packed structure accesses).
4483
4484(define_insn "unaligned_loadsi"
4485 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4486 (unspec:SI [(match_operand:SI 1 "memory_operand" "Uw,m")]
4487 UNSPEC_UNALIGNED_LOAD))]
8fe38eb2 4488 "unaligned_access"
eb04cafb 4489 "ldr%?\t%0, %1\t@ unaligned"
4490 [(set_attr "arch" "t2,any")
4491 (set_attr "length" "2,4")
4492 (set_attr "predicable" "yes")
d952d547 4493 (set_attr "predicable_short_it" "yes,no")
eb04cafb 4494 (set_attr "type" "load1")])
4495
4496(define_insn "unaligned_loadhis"
4497 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4498 (sign_extend:SI
e3f4ccee 4499 (unspec:HI [(match_operand:HI 1 "memory_operand" "Uw,Uh")]
eb04cafb 4500 UNSPEC_UNALIGNED_LOAD)))]
8fe38eb2 4501 "unaligned_access"
3ef90e77 4502 "ldrsh%?\t%0, %1\t@ unaligned"
eb04cafb 4503 [(set_attr "arch" "t2,any")
4504 (set_attr "length" "2,4")
4505 (set_attr "predicable" "yes")
d952d547 4506 (set_attr "predicable_short_it" "yes,no")
eb04cafb 4507 (set_attr "type" "load_byte")])
4508
4509(define_insn "unaligned_loadhiu"
4510 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4511 (zero_extend:SI
4512 (unspec:HI [(match_operand:HI 1 "memory_operand" "Uw,m")]
4513 UNSPEC_UNALIGNED_LOAD)))]
8fe38eb2 4514 "unaligned_access"
3ef90e77 4515 "ldrh%?\t%0, %1\t@ unaligned"
eb04cafb 4516 [(set_attr "arch" "t2,any")
4517 (set_attr "length" "2,4")
4518 (set_attr "predicable" "yes")
d952d547 4519 (set_attr "predicable_short_it" "yes,no")
eb04cafb 4520 (set_attr "type" "load_byte")])
4521
4522(define_insn "unaligned_storesi"
4523 [(set (match_operand:SI 0 "memory_operand" "=Uw,m")
4524 (unspec:SI [(match_operand:SI 1 "s_register_operand" "l,r")]
4525 UNSPEC_UNALIGNED_STORE))]
8fe38eb2 4526 "unaligned_access"
eb04cafb 4527 "str%?\t%1, %0\t@ unaligned"
4528 [(set_attr "arch" "t2,any")
4529 (set_attr "length" "2,4")
4530 (set_attr "predicable" "yes")
d952d547 4531 (set_attr "predicable_short_it" "yes,no")
eb04cafb 4532 (set_attr "type" "store1")])
4533
4534(define_insn "unaligned_storehi"
4535 [(set (match_operand:HI 0 "memory_operand" "=Uw,m")
4536 (unspec:HI [(match_operand:HI 1 "s_register_operand" "l,r")]
4537 UNSPEC_UNALIGNED_STORE))]
8fe38eb2 4538 "unaligned_access"
3ef90e77 4539 "strh%?\t%1, %0\t@ unaligned"
eb04cafb 4540 [(set_attr "arch" "t2,any")
4541 (set_attr "length" "2,4")
4542 (set_attr "predicable" "yes")
d952d547 4543 (set_attr "predicable_short_it" "yes,no")
eb04cafb 4544 (set_attr "type" "store1")])
4545
ae51a965 4546
eb04cafb 4547(define_insn "*extv_reg"
8b054d5a 4548 [(set (match_operand:SI 0 "s_register_operand" "=r")
4549 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
13051f13 4550 (match_operand:SI 2 "const_int_operand" "n")
4551 (match_operand:SI 3 "const_int_operand" "n")))]
4552 "arm_arch_thumb2
4553 && IN_RANGE (INTVAL (operands[3]), 0, 31)
4554 && IN_RANGE (INTVAL (operands[2]), 1, 32 - INTVAL (operands[3]))"
8b054d5a 4555 "sbfx%?\t%0, %1, %3, %2"
4556 [(set_attr "length" "4")
d952d547 4557 (set_attr "predicable" "yes")
d82e788e 4558 (set_attr "predicable_short_it" "no")
4559 (set_attr "type" "bfm")]
8b054d5a 4560)
4561
4562(define_insn "extzv_t2"
4563 [(set (match_operand:SI 0 "s_register_operand" "=r")
4564 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "r")
13051f13 4565 (match_operand:SI 2 "const_int_operand" "n")
4566 (match_operand:SI 3 "const_int_operand" "n")))]
4567 "arm_arch_thumb2
4568 && IN_RANGE (INTVAL (operands[3]), 0, 31)
4569 && IN_RANGE (INTVAL (operands[2]), 1, 32 - INTVAL (operands[3]))"
8b054d5a 4570 "ubfx%?\t%0, %1, %3, %2"
4571 [(set_attr "length" "4")
d952d547 4572 (set_attr "predicable" "yes")
d82e788e 4573 (set_attr "predicable_short_it" "no")
4574 (set_attr "type" "bfm")]
8b054d5a 4575)
4576
7d3cda8c 4577
4578;; Division instructions
4579(define_insn "divsi3"
8f5f2788 4580 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4581 (div:SI (match_operand:SI 1 "s_register_operand" "r,r")
4582 (match_operand:SI 2 "s_register_operand" "r,r")))]
7d3cda8c 4583 "TARGET_IDIV"
8f5f2788 4584 "@
4585 sdiv%?\t%0, %1, %2
4586 sdiv\t%0, %1, %2"
4587 [(set_attr "arch" "32,v8mb")
4588 (set_attr "predicable" "yes")
d952d547 4589 (set_attr "predicable_short_it" "no")
9da0ec36 4590 (set_attr "type" "sdiv")]
7d3cda8c 4591)
4592
4593(define_insn "udivsi3"
8f5f2788 4594 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4595 (udiv:SI (match_operand:SI 1 "s_register_operand" "r,r")
4596 (match_operand:SI 2 "s_register_operand" "r,r")))]
7d3cda8c 4597 "TARGET_IDIV"
8f5f2788 4598 "@
4599 udiv%?\t%0, %1, %2
4600 udiv\t%0, %1, %2"
4601 [(set_attr "arch" "32,v8mb")
4602 (set_attr "predicable" "yes")
d952d547 4603 (set_attr "predicable_short_it" "no")
9da0ec36 4604 (set_attr "type" "udiv")]
7d3cda8c 4605)
4606
b11cae9e 4607\f
4608;; Unary arithmetic insns
4609
f6c98a9a 4610(define_expand "negvsi3"
4611 [(match_operand:SI 0 "register_operand")
4612 (match_operand:SI 1 "register_operand")
4613 (match_operand 2 "")]
4614 "TARGET_32BIT"
4615{
4616 emit_insn (gen_subsi3_compare (operands[0], const0_rtx, operands[1]));
4617 arm_gen_unlikely_cbranch (NE, CC_Vmode, operands[2]);
4618
4619 DONE;
4620})
4621
4622(define_expand "negvdi3"
4623 [(match_operand:DI 0 "register_operand")
4624 (match_operand:DI 1 "register_operand")
4625 (match_operand 2 "")]
4626 "TARGET_ARM"
4627{
4628 emit_insn (gen_negdi2_compare (operands[0], operands[1]));
4629 arm_gen_unlikely_cbranch (NE, CC_Vmode, operands[2]);
4630
4631 DONE;
4632})
4633
4634
4635(define_insn_and_split "negdi2_compare"
4636 [(set (reg:CC CC_REGNUM)
4637 (compare:CC
4638 (const_int 0)
4639 (match_operand:DI 1 "register_operand" "0,r")))
4640 (set (match_operand:DI 0 "register_operand" "=r,&r")
4641 (minus:DI (const_int 0) (match_dup 1)))]
4642 "TARGET_ARM"
4643 "#"
4644 "&& reload_completed"
4645 [(parallel [(set (reg:CC CC_REGNUM)
4646 (compare:CC (const_int 0) (match_dup 1)))
4647 (set (match_dup 0) (minus:SI (const_int 0)
4648 (match_dup 1)))])
4649 (parallel [(set (reg:CC CC_REGNUM)
4650 (compare:CC (const_int 0) (match_dup 3)))
4651 (set (match_dup 2)
4652 (minus:SI
4653 (minus:SI (const_int 0) (match_dup 3))
4654 (ltu:SI (reg:CC_C CC_REGNUM)
4655 (const_int 0))))])]
4656 {
4657 operands[2] = gen_highpart (SImode, operands[0]);
4658 operands[0] = gen_lowpart (SImode, operands[0]);
4659 operands[3] = gen_highpart (SImode, operands[1]);
4660 operands[1] = gen_lowpart (SImode, operands[1]);
4661 }
4662 [(set_attr "conds" "set")
4663 (set_attr "length" "8")
4664 (set_attr "type" "multiple")]
4665)
4666
cffb2a26 4667(define_expand "negdi2"
4668 [(parallel
8135a42b 4669 [(set (match_operand:DI 0 "s_register_operand" "")
4670 (neg:DI (match_operand:DI 1 "s_register_operand" "")))
bd5b4116 4671 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 4672 "TARGET_EITHER"
774d2fbb 4673 {
4674 if (TARGET_NEON)
4675 {
4676 emit_insn (gen_negdi2_neon (operands[0], operands[1]));
4677 DONE;
4678 }
4679 }
cffb2a26 4680)
4681
4682;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
e5fea38e 4683;; The first alternative allows the common case of a *full* overlap.
ba6a3b2f 4684(define_insn_and_split "*arm_negdi2"
458a8706 4685 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 4686 (neg:DI (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 4687 (clobber (reg:CC CC_REGNUM))]
cffb2a26 4688 "TARGET_ARM"
ba6a3b2f 4689 "#" ; "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
4690 "&& reload_completed"
4691 [(parallel [(set (reg:CC CC_REGNUM)
4692 (compare:CC (const_int 0) (match_dup 1)))
4693 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 1)))])
4694 (set (match_dup 2) (minus:SI (minus:SI (const_int 0) (match_dup 3))
4695 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
4696 {
4697 operands[2] = gen_highpart (SImode, operands[0]);
4698 operands[0] = gen_lowpart (SImode, operands[0]);
4699 operands[3] = gen_highpart (SImode, operands[1]);
4700 operands[1] = gen_lowpart (SImode, operands[1]);
4701 }
cffb2a26 4702 [(set_attr "conds" "clob")
1b7da4ac 4703 (set_attr "length" "8")
4704 (set_attr "type" "multiple")]
cffb2a26 4705)
b11cae9e 4706
f6c98a9a 4707(define_insn "*negsi2_carryin_compare"
4708 [(set (reg:CC CC_REGNUM)
4709 (compare:CC (const_int 0)
4710 (match_operand:SI 1 "s_register_operand" "r")))
4711 (set (match_operand:SI 0 "s_register_operand" "=r")
4712 (minus:SI (minus:SI (const_int 0)
4713 (match_dup 1))
4714 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
4715 "TARGET_ARM"
4716 "rscs\\t%0, %1, #0"
4717 [(set_attr "conds" "set")
4718 (set_attr "type" "alus_imm")]
4719)
4720
cffb2a26 4721(define_expand "negsi2"
4722 [(set (match_operand:SI 0 "s_register_operand" "")
4723 (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
4724 "TARGET_EITHER"
b11cae9e 4725 ""
cffb2a26 4726)
4727
4728(define_insn "*arm_negsi2"
d952d547 4729 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4730 (neg:SI (match_operand:SI 1 "s_register_operand" "l,r")))]
25f905c2 4731 "TARGET_32BIT"
cffb2a26 4732 "rsb%?\\t%0, %1, #0"
d952d547 4733 [(set_attr "predicable" "yes")
4734 (set_attr "predicable_short_it" "yes,no")
4735 (set_attr "arch" "t2,*")
1b7da4ac 4736 (set_attr "length" "4")
112eda6f 4737 (set_attr "type" "alu_sreg")]
cffb2a26 4738)
4739
604f3a0a 4740(define_expand "negsf2"
4741 [(set (match_operand:SF 0 "s_register_operand" "")
4742 (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
d7216193 4743 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 4744 ""
4745)
4746
4747(define_expand "negdf2"
4748 [(set (match_operand:DF 0 "s_register_operand" "")
4749 (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
994606f8 4750 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
604f3a0a 4751 "")
4752
7eaf2be0 4753(define_insn_and_split "*zextendsidi_negsi"
4754 [(set (match_operand:DI 0 "s_register_operand" "=r")
4755 (zero_extend:DI (neg:SI (match_operand:SI 1 "s_register_operand" "r"))))]
4756 "TARGET_32BIT"
4757 "#"
4758 ""
4759 [(set (match_dup 2)
4760 (neg:SI (match_dup 1)))
4761 (set (match_dup 3)
4762 (const_int 0))]
4763 {
4764 operands[2] = gen_lowpart (SImode, operands[0]);
4765 operands[3] = gen_highpart (SImode, operands[0]);
4766 }
4767 [(set_attr "length" "8")
4768 (set_attr "type" "multiple")]
4769)
4770
83e2b922 4771;; Negate an extended 32-bit value.
4772(define_insn_and_split "*negdi_extendsidi"
61fa8ff2 4773 [(set (match_operand:DI 0 "s_register_operand" "=l,r")
4774 (neg:DI (sign_extend:DI
4775 (match_operand:SI 1 "s_register_operand" "l,r"))))
83e2b922 4776 (clobber (reg:CC CC_REGNUM))]
4777 "TARGET_32BIT"
61fa8ff2 4778 "#"
83e2b922 4779 "&& reload_completed"
4780 [(const_int 0)]
4781 {
61fa8ff2 4782 rtx low = gen_lowpart (SImode, operands[0]);
4783 rtx high = gen_highpart (SImode, operands[0]);
4784
4785 if (reg_overlap_mentioned_p (low, operands[1]))
4786 {
4787 /* Input overlaps the low word of the output. Use:
4788 asr Rhi, Rin, #31
4789 rsbs Rlo, Rin, #0
4790 rsc Rhi, Rhi, #0 (thumb2: sbc Rhi, Rhi, Rhi, lsl #1). */
4791 rtx cc_reg = gen_rtx_REG (CC_Cmode, CC_REGNUM);
4792
d1f9b275 4793 emit_insn (gen_rtx_SET (high,
61fa8ff2 4794 gen_rtx_ASHIFTRT (SImode, operands[1],
4795 GEN_INT (31))));
4796
4797 emit_insn (gen_subsi3_compare (low, const0_rtx, operands[1]));
4798 if (TARGET_ARM)
d1f9b275 4799 emit_insn (gen_rtx_SET (high,
61fa8ff2 4800 gen_rtx_MINUS (SImode,
4801 gen_rtx_MINUS (SImode,
4802 const0_rtx,
4803 high),
4804 gen_rtx_LTU (SImode,
4805 cc_reg,
4806 const0_rtx))));
4807 else
4808 {
4809 rtx two_x = gen_rtx_ASHIFT (SImode, high, GEN_INT (1));
d1f9b275 4810 emit_insn (gen_rtx_SET (high,
61fa8ff2 4811 gen_rtx_MINUS (SImode,
4812 gen_rtx_MINUS (SImode,
4813 high,
4814 two_x),
4815 gen_rtx_LTU (SImode,
4816 cc_reg,
4817 const0_rtx))));
4818 }
4819 }
4820 else
4821 {
4822 /* No overlap, or overlap on high word. Use:
4823 rsb Rlo, Rin, #0
4824 bic Rhi, Rlo, Rin
4825 asr Rhi, Rhi, #31
4826 Flags not needed for this sequence. */
d1f9b275 4827 emit_insn (gen_rtx_SET (low, gen_rtx_NEG (SImode, operands[1])));
4828 emit_insn (gen_rtx_SET (high,
61fa8ff2 4829 gen_rtx_AND (SImode,
4830 gen_rtx_NOT (SImode, operands[1]),
4831 low)));
d1f9b275 4832 emit_insn (gen_rtx_SET (high,
61fa8ff2 4833 gen_rtx_ASHIFTRT (SImode, high,
4834 GEN_INT (31))));
4835 }
4836 DONE;
83e2b922 4837 }
61fa8ff2 4838 [(set_attr "length" "12")
4839 (set_attr "arch" "t2,*")
1b7da4ac 4840 (set_attr "type" "multiple")]
83e2b922 4841)
4842
4843(define_insn_and_split "*negdi_zero_extendsidi"
4844 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
4845 (neg:DI (zero_extend:DI (match_operand:SI 1 "s_register_operand" "0,r"))))
4846 (clobber (reg:CC CC_REGNUM))]
4847 "TARGET_32BIT"
4848 "#" ; "rsbs\\t%Q0, %1, #0\;sbc\\t%R0,%R0,%R0"
4849 ;; Don't care what register is input to sbc,
47ae02b7 4850 ;; since we just need to propagate the carry.
83e2b922 4851 "&& reload_completed"
4852 [(parallel [(set (reg:CC CC_REGNUM)
4853 (compare:CC (const_int 0) (match_dup 1)))
4854 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 1)))])
4855 (set (match_dup 2) (minus:SI (minus:SI (match_dup 2) (match_dup 2))
4856 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
4857 {
4858 operands[2] = gen_highpart (SImode, operands[0]);
4859 operands[0] = gen_lowpart (SImode, operands[0]);
4860 }
4861 [(set_attr "conds" "clob")
1b7da4ac 4862 (set_attr "length" "8")
4863 (set_attr "type" "multiple")] ;; length in thumb is 4
83e2b922 4864)
4865
9c08d1fa 4866;; abssi2 doesn't really clobber the condition codes if a different register
4867;; is being set. To keep things simple, assume during rtl manipulations that
4868;; it does, but tell the final scan operator the truth. Similarly for
4869;; (neg (abs...))
4870
604f3a0a 4871(define_expand "abssi2"
4872 [(parallel
4873 [(set (match_operand:SI 0 "s_register_operand" "")
4874 (abs:SI (match_operand:SI 1 "s_register_operand" "")))
ba156559 4875 (clobber (match_dup 2))])]
4876 "TARGET_EITHER"
4877 "
25f905c2 4878 if (TARGET_THUMB1)
ba156559 4879 operands[2] = gen_rtx_SCRATCH (SImode);
4880 else
4881 operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
4882")
604f3a0a 4883
ba6a3b2f 4884(define_insn_and_split "*arm_abssi2"
ba156559 4885 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
9c08d1fa 4886 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
bd5b4116 4887 (clobber (reg:CC CC_REGNUM))]
cffb2a26 4888 "TARGET_ARM"
ba6a3b2f 4889 "#"
4890 "&& reload_completed"
4891 [(const_int 0)]
4892 {
4893 /* if (which_alternative == 0) */
4894 if (REGNO(operands[0]) == REGNO(operands[1]))
4895 {
4896 /* Emit the pattern:
4897 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
4898 [(set (reg:CC CC_REGNUM)
4899 (compare:CC (match_dup 0) (const_int 0)))
4900 (cond_exec (lt:CC (reg:CC CC_REGNUM) (const_int 0))
4901 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 1))))]
4902 */
d1f9b275 4903 emit_insn (gen_rtx_SET (gen_rtx_REG (CCmode, CC_REGNUM),
ba6a3b2f 4904 gen_rtx_COMPARE (CCmode, operands[0], const0_rtx)));
4905 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
4906 (gen_rtx_LT (SImode,
4907 gen_rtx_REG (CCmode, CC_REGNUM),
4908 const0_rtx)),
d1f9b275 4909 (gen_rtx_SET (operands[0],
ba6a3b2f 4910 (gen_rtx_MINUS (SImode,
4911 const0_rtx,
4912 operands[1]))))));
4913 DONE;
4914 }
4915 else
4916 {
4917 /* Emit the pattern:
4918 alt1: eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31
4919 [(set (match_dup 0)
4920 (xor:SI (match_dup 1)
4921 (ashiftrt:SI (match_dup 1) (const_int 31))))
4922 (set (match_dup 0)
4923 (minus:SI (match_dup 0)
4924 (ashiftrt:SI (match_dup 1) (const_int 31))))]
4925 */
d1f9b275 4926 emit_insn (gen_rtx_SET (operands[0],
ba6a3b2f 4927 gen_rtx_XOR (SImode,
4928 gen_rtx_ASHIFTRT (SImode,
4929 operands[1],
4930 GEN_INT (31)),
4931 operands[1])));
d1f9b275 4932 emit_insn (gen_rtx_SET (operands[0],
ba6a3b2f 4933 gen_rtx_MINUS (SImode,
4934 operands[0],
4935 gen_rtx_ASHIFTRT (SImode,
4936 operands[1],
4937 GEN_INT (31)))));
4938 DONE;
4939 }
4940 }
cffb2a26 4941 [(set_attr "conds" "clob,*")
331beb1a 4942 (set_attr "shift" "1")
2ad08b65 4943 (set_attr "predicable" "no, yes")
1b7da4ac 4944 (set_attr "length" "8")
4945 (set_attr "type" "multiple")]
cffb2a26 4946)
9c08d1fa 4947
ba6a3b2f 4948(define_insn_and_split "*arm_neg_abssi2"
9c08d1fa 4949 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
4950 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
bd5b4116 4951 (clobber (reg:CC CC_REGNUM))]
cffb2a26 4952 "TARGET_ARM"
ba6a3b2f 4953 "#"
4954 "&& reload_completed"
4955 [(const_int 0)]
4956 {
4957 /* if (which_alternative == 0) */
4958 if (REGNO (operands[0]) == REGNO (operands[1]))
4959 {
4960 /* Emit the pattern:
4961 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
4962 */
d1f9b275 4963 emit_insn (gen_rtx_SET (gen_rtx_REG (CCmode, CC_REGNUM),
ba6a3b2f 4964 gen_rtx_COMPARE (CCmode, operands[0], const0_rtx)));
4965 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
4966 gen_rtx_GT (SImode,
4967 gen_rtx_REG (CCmode, CC_REGNUM),
4968 const0_rtx),
d1f9b275 4969 gen_rtx_SET (operands[0],
ba6a3b2f 4970 (gen_rtx_MINUS (SImode,
4971 const0_rtx,
4972 operands[1])))));
4973 }
4974 else
4975 {
4976 /* Emit the pattern:
4977 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31
4978 */
d1f9b275 4979 emit_insn (gen_rtx_SET (operands[0],
ba6a3b2f 4980 gen_rtx_XOR (SImode,
4981 gen_rtx_ASHIFTRT (SImode,
4982 operands[1],
4983 GEN_INT (31)),
4984 operands[1])));
d1f9b275 4985 emit_insn (gen_rtx_SET (operands[0],
ba6a3b2f 4986 gen_rtx_MINUS (SImode,
4987 gen_rtx_ASHIFTRT (SImode,
4988 operands[1],
4989 GEN_INT (31)),
4990 operands[0])));
4991 }
4992 DONE;
4993 }
cffb2a26 4994 [(set_attr "conds" "clob,*")
331beb1a 4995 (set_attr "shift" "1")
2ad08b65 4996 (set_attr "predicable" "no, yes")
1b7da4ac 4997 (set_attr "length" "8")
4998 (set_attr "type" "multiple")]
cffb2a26 4999)
b11cae9e 5000
604f3a0a 5001(define_expand "abssf2"
5002 [(set (match_operand:SF 0 "s_register_operand" "")
5003 (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
25f905c2 5004 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 5005 "")
5006
604f3a0a 5007(define_expand "absdf2"
5008 [(set (match_operand:DF 0 "s_register_operand" "")
5009 (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 5010 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 5011 "")
5012
7db9af5d 5013(define_expand "sqrtsf2"
5014 [(set (match_operand:SF 0 "s_register_operand" "")
5015 (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
d7216193 5016 "TARGET_32BIT && TARGET_HARD_FLOAT"
7db9af5d 5017 "")
9c08d1fa 5018
7db9af5d 5019(define_expand "sqrtdf2"
5020 [(set (match_operand:DF 0 "s_register_operand" "")
5021 (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
994606f8 5022 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
7db9af5d 5023 "")
9c08d1fa 5024
a0f94409 5025(define_insn_and_split "one_cmpldi2"
10efb95f 5026 [(set (match_operand:DI 0 "s_register_operand" "=w,&r,&r,?w")
5027 (not:DI (match_operand:DI 1 "s_register_operand" " w, 0, r, w")))]
25f905c2 5028 "TARGET_32BIT"
10efb95f 5029 "@
5030 vmvn\t%P0, %P1
5031 #
5032 #
5033 vmvn\t%P0, %P1"
5034 "TARGET_32BIT && reload_completed
5035 && arm_general_register_operand (operands[0], DImode)"
a0f94409 5036 [(set (match_dup 0) (not:SI (match_dup 1)))
5037 (set (match_dup 2) (not:SI (match_dup 3)))]
5038 "
5039 {
5040 operands[2] = gen_highpart (SImode, operands[0]);
5041 operands[0] = gen_lowpart (SImode, operands[0]);
5042 operands[3] = gen_highpart (SImode, operands[1]);
5043 operands[1] = gen_lowpart (SImode, operands[1]);
5044 }"
10efb95f 5045 [(set_attr "length" "*,8,8,*")
5046 (set_attr "predicable" "no,yes,yes,no")
32093010 5047 (set_attr "type" "neon_move,multiple,multiple,neon_move")
b6779ddc 5048 (set_attr "arch" "neon_for_64bits,*,*,avoid_neon_for_64bits")]
cffb2a26 5049)
b11cae9e 5050
cffb2a26 5051(define_expand "one_cmplsi2"
5052 [(set (match_operand:SI 0 "s_register_operand" "")
5053 (not:SI (match_operand:SI 1 "s_register_operand" "")))]
5054 "TARGET_EITHER"
b11cae9e 5055 ""
cffb2a26 5056)
5057
5058(define_insn "*arm_one_cmplsi2"
d952d547 5059 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
5060 (not:SI (match_operand:SI 1 "s_register_operand" "l,r")))]
25f905c2 5061 "TARGET_32BIT"
cffb2a26 5062 "mvn%?\\t%0, %1"
d2a518d1 5063 [(set_attr "predicable" "yes")
d952d547 5064 (set_attr "predicable_short_it" "yes,no")
5065 (set_attr "arch" "t2,*")
5066 (set_attr "length" "4")
1aed5204 5067 (set_attr "type" "mvn_reg")]
cffb2a26 5068)
5069
f7fbdd4a 5070(define_insn "*notsi_compare0"
bd5b4116 5071 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 5072 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5073 (const_int 0)))
5074 (set (match_operand:SI 0 "s_register_operand" "=r")
5075 (not:SI (match_dup 1)))]
25f905c2 5076 "TARGET_32BIT"
3ef90e77 5077 "mvns%?\\t%0, %1"
d2a518d1 5078 [(set_attr "conds" "set")
1aed5204 5079 (set_attr "type" "mvn_reg")]
cffb2a26 5080)
9c08d1fa 5081
f7fbdd4a 5082(define_insn "*notsi_compare0_scratch"
bd5b4116 5083 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 5084 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5085 (const_int 0)))
5086 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 5087 "TARGET_32BIT"
3ef90e77 5088 "mvns%?\\t%0, %1"
d2a518d1 5089 [(set_attr "conds" "set")
1aed5204 5090 (set_attr "type" "mvn_reg")]
cffb2a26 5091)
b11cae9e 5092\f
5093;; Fixed <--> Floating conversion insns
5094
9b8516be 5095(define_expand "floatsihf2"
5096 [(set (match_operand:HF 0 "general_operand" "")
5097 (float:HF (match_operand:SI 1 "general_operand" "")))]
5098 "TARGET_EITHER"
5099 "
5100 {
5101 rtx op1 = gen_reg_rtx (SFmode);
5102 expand_float (op1, operands[1], 0);
5103 op1 = convert_to_mode (HFmode, op1, 0);
5104 emit_move_insn (operands[0], op1);
5105 DONE;
5106 }"
5107)
5108
5109(define_expand "floatdihf2"
5110 [(set (match_operand:HF 0 "general_operand" "")
5111 (float:HF (match_operand:DI 1 "general_operand" "")))]
5112 "TARGET_EITHER"
5113 "
5114 {
5115 rtx op1 = gen_reg_rtx (SFmode);
5116 expand_float (op1, operands[1], 0);
5117 op1 = convert_to_mode (HFmode, op1, 0);
5118 emit_move_insn (operands[0], op1);
5119 DONE;
5120 }"
5121)
5122
604f3a0a 5123(define_expand "floatsisf2"
5124 [(set (match_operand:SF 0 "s_register_operand" "")
5125 (float:SF (match_operand:SI 1 "s_register_operand" "")))]
25f905c2 5126 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 5127 "
604f3a0a 5128")
5129
604f3a0a 5130(define_expand "floatsidf2"
5131 [(set (match_operand:DF 0 "s_register_operand" "")
5132 (float:DF (match_operand:SI 1 "s_register_operand" "")))]
a50d7267 5133 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 5134 "
604f3a0a 5135")
5136
9b8516be 5137(define_expand "fix_trunchfsi2"
5138 [(set (match_operand:SI 0 "general_operand" "")
5139 (fix:SI (fix:HF (match_operand:HF 1 "general_operand" ""))))]
5140 "TARGET_EITHER"
5141 "
5142 {
5143 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
5144 expand_fix (operands[0], op1, 0);
5145 DONE;
5146 }"
5147)
5148
5149(define_expand "fix_trunchfdi2"
5150 [(set (match_operand:DI 0 "general_operand" "")
5151 (fix:DI (fix:HF (match_operand:HF 1 "general_operand" ""))))]
5152 "TARGET_EITHER"
5153 "
5154 {
5155 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
5156 expand_fix (operands[0], op1, 0);
5157 DONE;
5158 }"
5159)
5160
604f3a0a 5161(define_expand "fix_truncsfsi2"
5162 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 5163 (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" ""))))]
25f905c2 5164 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 5165 "
604f3a0a 5166")
5167
604f3a0a 5168(define_expand "fix_truncdfsi2"
5169 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 5170 (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" ""))))]
a50d7267 5171 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 5172 "
604f3a0a 5173")
5174
f544c6d2 5175;; Truncation insns
b11cae9e 5176
604f3a0a 5177(define_expand "truncdfsf2"
5178 [(set (match_operand:SF 0 "s_register_operand" "")
5179 (float_truncate:SF
5180 (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 5181 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 5182 ""
5183)
9b8516be 5184
539b44ee 5185;; DFmode to HFmode conversions on targets without a single-step hardware
5186;; instruction for it would have to go through SFmode. This is dangerous
5187;; as it introduces double rounding.
5188;;
5189;; Disable this pattern unless we are in an unsafe math mode, or we have
5190;; a single-step instruction.
5191
9b8516be 5192(define_expand "truncdfhf2"
539b44ee 5193 [(set (match_operand:HF 0 "s_register_operand" "")
9b8516be 5194 (float_truncate:HF
539b44ee 5195 (match_operand:DF 1 "s_register_operand" "")))]
5196 "(TARGET_EITHER && flag_unsafe_math_optimizations)
5197 || (TARGET_32BIT && TARGET_FP16_TO_DOUBLE)"
5198{
5199 /* We don't have a direct instruction for this, so we must be in
5200 an unsafe math mode, and going via SFmode. */
5201
5202 if (!(TARGET_32BIT && TARGET_FP16_TO_DOUBLE))
5203 {
5204 rtx op1;
5205 op1 = convert_to_mode (SFmode, operands[1], 0);
5206 op1 = convert_to_mode (HFmode, op1, 0);
5207 emit_move_insn (operands[0], op1);
5208 DONE;
5209 }
5210 /* Otherwise, we will pick this up as a single instruction with
5211 no intermediary rounding. */
5212}
9b8516be 5213)
b11cae9e 5214\f
9c08d1fa 5215;; Zero and sign extension instructions.
b11cae9e 5216
848e66ac 5217(define_insn "zero_extend<mode>di2"
6aa689e8 5218 [(set (match_operand:DI 0 "s_register_operand" "=w,r,?r,w")
6d97728e 5219 (zero_extend:DI (match_operand:QHSI 1 "<qhs_zextenddi_op>"
5220 "<qhs_zextenddi_cstr>")))]
848e66ac 5221 "TARGET_32BIT <qhs_zextenddi_cond>"
5222 "#"
6aa689e8 5223 [(set_attr "length" "8,4,8,8")
b6779ddc 5224 (set_attr "arch" "neon_for_64bits,*,*,avoid_neon_for_64bits")
848e66ac 5225 (set_attr "ce_count" "2")
efbb5e19 5226 (set_attr "predicable" "yes")
5227 (set_attr "type" "multiple,mov_reg,multiple,multiple")]
25f905c2 5228)
5229
848e66ac 5230(define_insn "extend<mode>di2"
6aa689e8 5231 [(set (match_operand:DI 0 "s_register_operand" "=w,r,?r,?r,w")
63d204a8 5232 (sign_extend:DI (match_operand:QHSI 1 "<qhs_extenddi_op>"
5233 "<qhs_extenddi_cstr>")))]
848e66ac 5234 "TARGET_32BIT <qhs_sextenddi_cond>"
5235 "#"
6aa689e8 5236 [(set_attr "length" "8,4,8,8,8")
848e66ac 5237 (set_attr "ce_count" "2")
5238 (set_attr "shift" "1")
8012d2c2 5239 (set_attr "predicable" "yes")
1b7da4ac 5240 (set_attr "arch" "neon_for_64bits,*,a,t,avoid_neon_for_64bits")
5241 (set_attr "type" "multiple,mov_reg,multiple,multiple,multiple")]
0d66636f 5242)
9c08d1fa 5243
848e66ac 5244;; Splits for all extensions to DImode
5245(define_split
5246 [(set (match_operand:DI 0 "s_register_operand" "")
5247 (zero_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
6aa689e8 5248 "TARGET_32BIT && reload_completed && !IS_VFP_REGNUM (REGNO (operands[0]))"
848e66ac 5249 [(set (match_dup 0) (match_dup 1))]
5250{
848e66ac 5251 rtx lo_part = gen_lowpart (SImode, operands[0]);
3754d046 5252 machine_mode src_mode = GET_MODE (operands[1]);
848e66ac 5253
5254 if (REG_P (operands[0])
5255 && !reg_overlap_mentioned_p (operands[0], operands[1]))
5256 emit_clobber (operands[0]);
5257 if (!REG_P (lo_part) || src_mode != SImode
5258 || !rtx_equal_p (lo_part, operands[1]))
5259 {
5260 if (src_mode == SImode)
5261 emit_move_insn (lo_part, operands[1]);
5262 else
d1f9b275 5263 emit_insn (gen_rtx_SET (lo_part,
848e66ac 5264 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
5265 operands[1] = lo_part;
5266 }
5267 operands[0] = gen_highpart (SImode, operands[0]);
5268 operands[1] = const0_rtx;
5269})
9c08d1fa 5270
848e66ac 5271(define_split
25f905c2 5272 [(set (match_operand:DI 0 "s_register_operand" "")
848e66ac 5273 (sign_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
6aa689e8 5274 "TARGET_32BIT && reload_completed && !IS_VFP_REGNUM (REGNO (operands[0]))"
848e66ac 5275 [(set (match_dup 0) (ashiftrt:SI (match_dup 1) (const_int 31)))]
5276{
5277 rtx lo_part = gen_lowpart (SImode, operands[0]);
3754d046 5278 machine_mode src_mode = GET_MODE (operands[1]);
25f905c2 5279
848e66ac 5280 if (REG_P (operands[0])
5281 && !reg_overlap_mentioned_p (operands[0], operands[1]))
5282 emit_clobber (operands[0]);
5283
5284 if (!REG_P (lo_part) || src_mode != SImode
5285 || !rtx_equal_p (lo_part, operands[1]))
5286 {
5287 if (src_mode == SImode)
5288 emit_move_insn (lo_part, operands[1]);
5289 else
d1f9b275 5290 emit_insn (gen_rtx_SET (lo_part,
848e66ac 5291 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
5292 operands[1] = lo_part;
5293 }
5294 operands[0] = gen_highpart (SImode, operands[0]);
5295})
9c08d1fa 5296
5297(define_expand "zero_extendhisi2"
ef51b8e1 5298 [(set (match_operand:SI 0 "s_register_operand" "")
5299 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
cffb2a26 5300 "TARGET_EITHER"
ef51b8e1 5301{
5302 if (TARGET_ARM && !arm_arch4 && MEM_P (operands[1]))
f7fbdd4a 5303 {
ef51b8e1 5304 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
5305 DONE;
25f7a26e 5306 }
ef51b8e1 5307 if (!arm_arch6 && !MEM_P (operands[1]))
5308 {
5309 rtx t = gen_lowpart (SImode, operands[1]);
5310 rtx tmp = gen_reg_rtx (SImode);
5311 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
5312 emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (16)));
5313 DONE;
5314 }
5315})
9c08d1fa 5316
ef51b8e1 5317(define_split
b146458f 5318 [(set (match_operand:SI 0 "s_register_operand" "")
5319 (zero_extend:SI (match_operand:HI 1 "s_register_operand" "")))]
ef51b8e1 5320 "!TARGET_THUMB2 && !arm_arch6"
5321 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
5322 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 16)))]
5323{
5324 operands[2] = gen_lowpart (SImode, operands[1]);
5325})
5326
cffb2a26 5327(define_insn "*arm_zero_extendhisi2"
ef51b8e1 5328 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5329 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 5330 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 5331 "@
5332 #
3ef90e77 5333 ldrh%?\\t%0, %1"
d82e788e 5334 [(set_attr "type" "alu_shift_reg,load_byte")
848e66ac 5335 (set_attr "predicable" "yes")]
cffb2a26 5336)
f7fbdd4a 5337
a2cd141b 5338(define_insn "*arm_zero_extendhisi2_v6"
5339 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
e3f4ccee 5340 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,Uh")))]
a2cd141b 5341 "TARGET_ARM && arm_arch6"
5342 "@
5343 uxth%?\\t%0, %1
3ef90e77 5344 ldrh%?\\t%0, %1"
65f68e55 5345 [(set_attr "predicable" "yes")
6b6abc9c 5346 (set_attr "type" "extend,load_byte")]
a2cd141b 5347)
5348
5349(define_insn "*arm_zero_extendhisi2addsi"
5350 [(set (match_operand:SI 0 "s_register_operand" "=r")
5351 (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
5352 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 5353 "TARGET_INT_SIMD"
a2cd141b 5354 "uxtah%?\\t%0, %2, %1"
d82e788e 5355 [(set_attr "type" "alu_shift_reg")
d952d547 5356 (set_attr "predicable" "yes")
5357 (set_attr "predicable_short_it" "no")]
a2cd141b 5358)
5359
87b22bf7 5360(define_expand "zero_extendqisi2"
cffb2a26 5361 [(set (match_operand:SI 0 "s_register_operand" "")
5362 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
5363 "TARGET_EITHER"
ef51b8e1 5364{
0438d37f 5365 if (TARGET_ARM && !arm_arch6 && !MEM_P (operands[1]))
87b22bf7 5366 {
ef51b8e1 5367 emit_insn (gen_andsi3 (operands[0],
5368 gen_lowpart (SImode, operands[1]),
5369 GEN_INT (255)));
5370 DONE;
5371 }
5372 if (!arm_arch6 && !MEM_P (operands[1]))
5373 {
5374 rtx t = gen_lowpart (SImode, operands[1]);
5375 rtx tmp = gen_reg_rtx (SImode);
5376 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
5377 emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (24)));
5378 DONE;
5379 }
5380})
cffb2a26 5381
ef51b8e1 5382(define_split
b146458f 5383 [(set (match_operand:SI 0 "s_register_operand" "")
5384 (zero_extend:SI (match_operand:QI 1 "s_register_operand" "")))]
ef51b8e1 5385 "!arm_arch6"
5386 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
5387 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 24)))]
5388{
5389 operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
5390 if (TARGET_ARM)
5391 {
5392 emit_insn (gen_andsi3 (operands[0], operands[2], GEN_INT (255)));
87b22bf7 5393 DONE;
5394 }
ef51b8e1 5395})
9c08d1fa 5396
cffb2a26 5397(define_insn "*arm_zero_extendqisi2"
ef51b8e1 5398 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5399 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 5400 "TARGET_ARM && !arm_arch6"
ef51b8e1 5401 "@
5402 #
3ef90e77 5403 ldrb%?\\t%0, %1\\t%@ zero_extendqisi2"
ef51b8e1 5404 [(set_attr "length" "8,4")
d82e788e 5405 (set_attr "type" "alu_shift_reg,load_byte")
848e66ac 5406 (set_attr "predicable" "yes")]
cffb2a26 5407)
87b22bf7 5408
a2cd141b 5409(define_insn "*arm_zero_extendqisi2_v6"
5410 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
e3f4ccee 5411 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,Uh")))]
a2cd141b 5412 "TARGET_ARM && arm_arch6"
5413 "@
3ef90e77 5414 uxtb%?\\t%0, %1
5415 ldrb%?\\t%0, %1\\t%@ zero_extendqisi2"
6b6abc9c 5416 [(set_attr "type" "extend,load_byte")
848e66ac 5417 (set_attr "predicable" "yes")]
a2cd141b 5418)
5419
5420(define_insn "*arm_zero_extendqisi2addsi"
5421 [(set (match_operand:SI 0 "s_register_operand" "=r")
5422 (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
5423 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 5424 "TARGET_INT_SIMD"
a2cd141b 5425 "uxtab%?\\t%0, %2, %1"
5426 [(set_attr "predicable" "yes")
d952d547 5427 (set_attr "predicable_short_it" "no")
d82e788e 5428 (set_attr "type" "alu_shift_reg")]
a2cd141b 5429)
5430
87b22bf7 5431(define_split
5432 [(set (match_operand:SI 0 "s_register_operand" "")
5433 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
5434 (clobber (match_operand:SI 2 "s_register_operand" ""))]
0438d37f 5435 "TARGET_32BIT && (!MEM_P (operands[1])) && ! BYTES_BIG_ENDIAN"
87b22bf7 5436 [(set (match_dup 2) (match_dup 1))
5437 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
cffb2a26 5438 ""
5439)
9c08d1fa 5440
8a4d25d6 5441(define_split
5442 [(set (match_operand:SI 0 "s_register_operand" "")
5443 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 3)))
5444 (clobber (match_operand:SI 2 "s_register_operand" ""))]
0438d37f 5445 "TARGET_32BIT && (!MEM_P (operands[1])) && BYTES_BIG_ENDIAN"
8a4d25d6 5446 [(set (match_dup 2) (match_dup 1))
5447 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
5448 ""
5449)
5450
1c274529 5451
5452(define_split
5453 [(set (match_operand:SI 0 "s_register_operand" "")
9b23f0a7 5454 (IOR_XOR:SI (and:SI (ashift:SI
1c274529 5455 (match_operand:SI 1 "s_register_operand" "")
5456 (match_operand:SI 2 "const_int_operand" ""))
5457 (match_operand:SI 3 "const_int_operand" ""))
5458 (zero_extend:SI
5459 (match_operator 5 "subreg_lowpart_operator"
5460 [(match_operand:SI 4 "s_register_operand" "")]))))]
5461 "TARGET_32BIT
8c4e8755 5462 && (UINTVAL (operands[3])
1c274529 5463 == (GET_MODE_MASK (GET_MODE (operands[5]))
5464 & (GET_MODE_MASK (GET_MODE (operands[5]))
5465 << (INTVAL (operands[2])))))"
9b23f0a7 5466 [(set (match_dup 0) (IOR_XOR:SI (ashift:SI (match_dup 1) (match_dup 2))
1c274529 5467 (match_dup 4)))
5468 (set (match_dup 0) (zero_extend:SI (match_dup 5)))]
5469 "operands[5] = gen_lowpart (GET_MODE (operands[5]), operands[0]);"
5470)
5471
f7fbdd4a 5472(define_insn "*compareqi_eq0"
bd5b4116 5473 [(set (reg:CC_Z CC_REGNUM)
206ee9a2 5474 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
87b22bf7 5475 (const_int 0)))]
25f905c2 5476 "TARGET_32BIT"
596e5e8f 5477 "tst%?\\t%0, #255"
5478 [(set_attr "conds" "set")
d952d547 5479 (set_attr "predicable" "yes")
1b7da4ac 5480 (set_attr "predicable_short_it" "no")
5481 (set_attr "type" "logic_imm")]
cffb2a26 5482)
b11cae9e 5483
b11cae9e 5484(define_expand "extendhisi2"
ef51b8e1 5485 [(set (match_operand:SI 0 "s_register_operand" "")
5486 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
cffb2a26 5487 "TARGET_EITHER"
ef51b8e1 5488{
5489 if (TARGET_THUMB1)
5490 {
5491 emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1]));
5492 DONE;
5493 }
5494 if (MEM_P (operands[1]) && TARGET_ARM && !arm_arch4)
5495 {
5496 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
5497 DONE;
5498 }
ed29c566 5499
ef51b8e1 5500 if (!arm_arch6 && !MEM_P (operands[1]))
5501 {
5502 rtx t = gen_lowpart (SImode, operands[1]);
5503 rtx tmp = gen_reg_rtx (SImode);
5504 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
5505 emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (16)));
5506 DONE;
5507 }
5508})
cffb2a26 5509
ef51b8e1 5510(define_split
5511 [(parallel
5512 [(set (match_operand:SI 0 "register_operand" "")
5513 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))
5514 (clobber (match_scratch:SI 2 ""))])]
5515 "!arm_arch6"
5516 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
5517 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
5518{
5519 operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
5520})
25f7a26e 5521
25f905c2 5522;; This pattern will only be used when ldsh is not available
25f7a26e 5523(define_expand "extendhisi2_mem"
eab14235 5524 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 5525 (set (match_dup 3)
eab14235 5526 (zero_extend:SI (match_dup 7)))
25f7a26e 5527 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
5528 (set (match_operand:SI 0 "" "")
5529 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
cffb2a26 5530 "TARGET_ARM"
25f7a26e 5531 "
215b30b3 5532 {
5533 rtx mem1, mem2;
5534 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
5535
788fcce0 5536 mem1 = change_address (operands[1], QImode, addr);
29c05e22 5537 mem2 = change_address (operands[1], QImode,
5538 plus_constant (Pmode, addr, 1));
215b30b3 5539 operands[0] = gen_lowpart (SImode, operands[0]);
5540 operands[1] = mem1;
5541 operands[2] = gen_reg_rtx (SImode);
5542 operands[3] = gen_reg_rtx (SImode);
5543 operands[6] = gen_reg_rtx (SImode);
5544 operands[7] = mem2;
25f7a26e 5545
215b30b3 5546 if (BYTES_BIG_ENDIAN)
5547 {
5548 operands[4] = operands[2];
5549 operands[5] = operands[3];
5550 }
5551 else
5552 {
5553 operands[4] = operands[3];
5554 operands[5] = operands[2];
5555 }
5556 }"
5557)
b11cae9e 5558
ef51b8e1 5559(define_split
5560 [(set (match_operand:SI 0 "register_operand" "")
5561 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
5562 "!arm_arch6"
5563 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
5564 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
5565{
5566 operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
5567})
5568
a2cd141b 5569(define_insn "*arm_extendhisi2"
ef51b8e1 5570 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
e3f4ccee 5571 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,Uh")))]
a2cd141b 5572 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 5573 "@
5574 #
3ef90e77 5575 ldrsh%?\\t%0, %1"
ef51b8e1 5576 [(set_attr "length" "8,4")
d82e788e 5577 (set_attr "type" "alu_shift_reg,load_byte")
e3f4ccee 5578 (set_attr "predicable" "yes")]
cffb2a26 5579)
f7fbdd4a 5580
25f905c2 5581;; ??? Check Thumb-2 pool range
a2cd141b 5582(define_insn "*arm_extendhisi2_v6"
5583 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
e3f4ccee 5584 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,Uh")))]
25f905c2 5585 "TARGET_32BIT && arm_arch6"
a2cd141b 5586 "@
5587 sxth%?\\t%0, %1
3ef90e77 5588 ldrsh%?\\t%0, %1"
6b6abc9c 5589 [(set_attr "type" "extend,load_byte")
a2cd141b 5590 (set_attr "predicable" "yes")
e3f4ccee 5591 (set_attr "predicable_short_it" "no")]
a2cd141b 5592)
5593
5594(define_insn "*arm_extendhisi2addsi"
5595 [(set (match_operand:SI 0 "s_register_operand" "=r")
5596 (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
5597 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 5598 "TARGET_INT_SIMD"
a2cd141b 5599 "sxtah%?\\t%0, %2, %1"
1b7da4ac 5600 [(set_attr "type" "alu_shift_reg")]
a2cd141b 5601)
5602
c8f69309 5603(define_expand "extendqihi2"
5604 [(set (match_dup 2)
bed7d9a5 5605 (ashift:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")
c8f69309 5606 (const_int 24)))
9c08d1fa 5607 (set (match_operand:HI 0 "s_register_operand" "")
c8f69309 5608 (ashiftrt:SI (match_dup 2)
5609 (const_int 24)))]
cffb2a26 5610 "TARGET_ARM"
c8f69309 5611 "
215b30b3 5612 {
0438d37f 5613 if (arm_arch4 && MEM_P (operands[1]))
215b30b3 5614 {
d1f9b275 5615 emit_insn (gen_rtx_SET (operands[0],
215b30b3 5616 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
5617 DONE;
5618 }
5619 if (!s_register_operand (operands[1], QImode))
5620 operands[1] = copy_to_mode_reg (QImode, operands[1]);
5621 operands[0] = gen_lowpart (SImode, operands[0]);
5622 operands[1] = gen_lowpart (SImode, operands[1]);
5623 operands[2] = gen_reg_rtx (SImode);
5624 }"
5625)
f7fbdd4a 5626
25f905c2 5627(define_insn "*arm_extendqihi_insn"
b4e8a300 5628 [(set (match_operand:HI 0 "s_register_operand" "=r")
bed7d9a5 5629 (sign_extend:HI (match_operand:QI 1 "arm_extendqisi_mem_op" "Uq")))]
cffb2a26 5630 "TARGET_ARM && arm_arch4"
3ef90e77 5631 "ldrsb%?\\t%0, %1"
a2cd141b 5632 [(set_attr "type" "load_byte")
e3f4ccee 5633 (set_attr "predicable" "yes")]
cffb2a26 5634)
3fc2009e 5635
b11cae9e 5636(define_expand "extendqisi2"
ef51b8e1 5637 [(set (match_operand:SI 0 "s_register_operand" "")
5638 (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")))]
cffb2a26 5639 "TARGET_EITHER"
ef51b8e1 5640{
5641 if (!arm_arch4 && MEM_P (operands[1]))
5642 operands[1] = copy_to_mode_reg (QImode, operands[1]);
a2cd141b 5643
ef51b8e1 5644 if (!arm_arch6 && !MEM_P (operands[1]))
5645 {
5646 rtx t = gen_lowpart (SImode, operands[1]);
5647 rtx tmp = gen_reg_rtx (SImode);
5648 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
5649 emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (24)));
5650 DONE;
5651 }
5652})
a2cd141b 5653
ef51b8e1 5654(define_split
5655 [(set (match_operand:SI 0 "register_operand" "")
5656 (sign_extend:SI (match_operand:QI 1 "register_operand" "")))]
5657 "!arm_arch6"
5658 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
5659 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))]
5660{
5661 operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
5662})
f7fbdd4a 5663
a2cd141b 5664(define_insn "*arm_extendqisi"
ef51b8e1 5665 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5666 (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
a2cd141b 5667 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 5668 "@
5669 #
3ef90e77 5670 ldrsb%?\\t%0, %1"
ef51b8e1 5671 [(set_attr "length" "8,4")
d82e788e 5672 (set_attr "type" "alu_shift_reg,load_byte")
e3f4ccee 5673 (set_attr "predicable" "yes")]
cffb2a26 5674)
3fc2009e 5675
a2cd141b 5676(define_insn "*arm_extendqisi_v6"
5677 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
bed7d9a5 5678 (sign_extend:SI
5679 (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
a2cd141b 5680 "TARGET_ARM && arm_arch6"
b4e8a300 5681 "@
5682 sxtb%?\\t%0, %1
3ef90e77 5683 ldrsb%?\\t%0, %1"
6b6abc9c 5684 [(set_attr "type" "extend,load_byte")
e3f4ccee 5685 (set_attr "predicable" "yes")]
a2cd141b 5686)
5687
5688(define_insn "*arm_extendqisi2addsi"
5689 [(set (match_operand:SI 0 "s_register_operand" "=r")
5690 (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
5691 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 5692 "TARGET_INT_SIMD"
a2cd141b 5693 "sxtab%?\\t%0, %2, %1"
d82e788e 5694 [(set_attr "type" "alu_shift_reg")
d952d547 5695 (set_attr "predicable" "yes")
5696 (set_attr "predicable_short_it" "no")]
a2cd141b 5697)
5698
caedf871 5699(define_expand "extendsfdf2"
5700 [(set (match_operand:DF 0 "s_register_operand" "")
5701 (float_extend:DF (match_operand:SF 1 "s_register_operand" "")))]
a50d7267 5702 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
caedf871 5703 ""
5704)
9b8516be 5705
539b44ee 5706;; HFmode -> DFmode conversions where we don't have an instruction for it
5707;; must go through SFmode.
5708;;
5709;; This is always safe for an extend.
5710
9b8516be 5711(define_expand "extendhfdf2"
539b44ee 5712 [(set (match_operand:DF 0 "s_register_operand" "")
5713 (float_extend:DF (match_operand:HF 1 "s_register_operand" "")))]
9b8516be 5714 "TARGET_EITHER"
539b44ee 5715{
5716 /* We don't have a direct instruction for this, so go via SFmode. */
5717 if (!(TARGET_32BIT && TARGET_FP16_TO_DOUBLE))
5718 {
5719 rtx op1;
5720 op1 = convert_to_mode (SFmode, operands[1], 0);
5721 op1 = convert_to_mode (DFmode, op1, 0);
5722 emit_insn (gen_movdf (operands[0], op1));
5723 DONE;
5724 }
5725 /* Otherwise, we're done producing RTL and will pick up the correct
5726 pattern to do this with one rounding-step in a single instruction. */
5727}
9b8516be 5728)
b11cae9e 5729\f
5730;; Move insns (including loads and stores)
5731
5732;; XXX Just some ideas about movti.
9c08d1fa 5733;; I don't think these are a good idea on the arm, there just aren't enough
5734;; registers
b11cae9e 5735;;(define_expand "loadti"
9c08d1fa 5736;; [(set (match_operand:TI 0 "s_register_operand" "")
b11cae9e 5737;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
5738;; "" "")
5739
5740;;(define_expand "storeti"
5741;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
9c08d1fa 5742;; (match_operand:TI 1 "s_register_operand" ""))]
b11cae9e 5743;; "" "")
5744
5745;;(define_expand "movti"
5746;; [(set (match_operand:TI 0 "general_operand" "")
5747;; (match_operand:TI 1 "general_operand" ""))]
5748;; ""
5749;; "
5750;;{
5751;; rtx insn;
5752;;
0438d37f 5753;; if (MEM_P (operands[0]) && MEM_P (operands[1]))
b11cae9e 5754;; operands[1] = copy_to_reg (operands[1]);
0438d37f 5755;; if (MEM_P (operands[0]))
b11cae9e 5756;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
0438d37f 5757;; else if (MEM_P (operands[1]))
b11cae9e 5758;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
5759;; else
5760;; FAIL;
5761;;
5762;; emit_insn (insn);
5763;; DONE;
5764;;}")
5765
a2f10574 5766;; Recognize garbage generated above.
b11cae9e 5767
5768;;(define_insn ""
5769;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
5770;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
5771;; ""
5772;; "*
5773;; {
5774;; register mem = (which_alternative < 3);
0d66636f 5775;; register const char *template;
b11cae9e 5776;;
5777;; operands[mem] = XEXP (operands[mem], 0);
5778;; switch (which_alternative)
5779;; {
5780;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
5781;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
5782;; case 2: template = \"ldmia\\t%1, %M0\"; break;
5783;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
5784;; case 4: template = \"stmia\\t%0!, %M1\"; break;
5785;; case 5: template = \"stmia\\t%0, %M1\"; break;
5786;; }
e2348bcb 5787;; output_asm_insn (template, operands);
5788;; return \"\";
b11cae9e 5789;; }")
5790
cffb2a26 5791(define_expand "movdi"
5792 [(set (match_operand:DI 0 "general_operand" "")
5793 (match_operand:DI 1 "general_operand" ""))]
5794 "TARGET_EITHER"
5795 "
e1ba4a27 5796 if (can_create_pseudo_p ())
cffb2a26 5797 {
0438d37f 5798 if (!REG_P (operands[0]))
b2778788 5799 operands[1] = force_reg (DImode, operands[1]);
cffb2a26 5800 }
6b97fdcc 5801 if (REG_P (operands[0]) && REGNO (operands[0]) <= LAST_ARM_REGNUM
4f0e25ca 5802 && !HARD_REGNO_MODE_OK (REGNO (operands[0]), DImode))
5803 {
5804 /* Avoid LDRD's into an odd-numbered register pair in ARM state
5805 when expanding function calls. */
5806 gcc_assert (can_create_pseudo_p ());
5807 if (MEM_P (operands[1]) && MEM_VOLATILE_P (operands[1]))
5808 {
5809 /* Perform load into legal reg pair first, then move. */
5810 rtx reg = gen_reg_rtx (DImode);
5811 emit_insn (gen_movdi (reg, operands[1]));
5812 operands[1] = reg;
5813 }
5814 emit_move_insn (gen_lowpart (SImode, operands[0]),
5815 gen_lowpart (SImode, operands[1]));
5816 emit_move_insn (gen_highpart (SImode, operands[0]),
5817 gen_highpart (SImode, operands[1]));
5818 DONE;
5819 }
6b97fdcc 5820 else if (REG_P (operands[1]) && REGNO (operands[1]) <= LAST_ARM_REGNUM
4f0e25ca 5821 && !HARD_REGNO_MODE_OK (REGNO (operands[1]), DImode))
5822 {
5823 /* Avoid STRD's from an odd-numbered register pair in ARM state
5824 when expanding function prologue. */
5825 gcc_assert (can_create_pseudo_p ());
5826 rtx split_dest = (MEM_P (operands[0]) && MEM_VOLATILE_P (operands[0]))
5827 ? gen_reg_rtx (DImode)
5828 : operands[0];
5829 emit_move_insn (gen_lowpart (SImode, split_dest),
5830 gen_lowpart (SImode, operands[1]));
5831 emit_move_insn (gen_highpart (SImode, split_dest),
5832 gen_highpart (SImode, operands[1]));
5833 if (split_dest != operands[0])
5834 emit_insn (gen_movdi (operands[0], split_dest));
5835 DONE;
5836 }
cffb2a26 5837 "
5838)
b11cae9e 5839
cffb2a26 5840(define_insn "*arm_movdi"
353cf59a 5841 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, q, m")
5842 (match_operand:DI 1 "di_operand" "rDa,Db,Dc,mi,q"))]
cde1623a 5843 "TARGET_32BIT
d7216193 5844 && !(TARGET_HARD_FLOAT)
b2778788 5845 && !TARGET_IWMMXT
5846 && ( register_operand (operands[0], DImode)
5847 || register_operand (operands[1], DImode))"
b11cae9e 5848 "*
d51f92df 5849 switch (which_alternative)
5850 {
5851 case 0:
5852 case 1:
5853 case 2:
5854 return \"#\";
5855 default:
26ff80c0 5856 return output_move_double (operands, true, NULL);
d51f92df 5857 }
cffb2a26 5858 "
359a6e9f 5859 [(set_attr "length" "8,12,16,8,8")
1b7da4ac 5860 (set_attr "type" "multiple,multiple,multiple,load2,store2")
cde1623a 5861 (set_attr "arm_pool_range" "*,*,*,1020,*")
8848d797 5862 (set_attr "arm_neg_pool_range" "*,*,*,1004,*")
42e1de19 5863 (set_attr "thumb2_pool_range" "*,*,*,4094,*")
cde1623a 5864 (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
cffb2a26 5865)
5866
d51f92df 5867(define_split
5868 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
e6dd3afa 5869 (match_operand:ANY64 1 "immediate_operand" ""))]
25f905c2 5870 "TARGET_32BIT
d51f92df 5871 && reload_completed
5872 && (arm_const_double_inline_cost (operands[1])
861033d5 5873 <= arm_max_const_double_inline_cost ())"
d51f92df 5874 [(const_int 0)]
5875 "
5876 arm_split_constant (SET, SImode, curr_insn,
5877 INTVAL (gen_lowpart (SImode, operands[1])),
5878 gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
5879 arm_split_constant (SET, SImode, curr_insn,
5880 INTVAL (gen_highpart_mode (SImode,
5881 GET_MODE (operands[0]),
5882 operands[1])),
5883 gen_highpart (SImode, operands[0]), NULL_RTX, 0);
5884 DONE;
5885 "
5886)
5887
e5ba9289 5888; If optimizing for size, or if we have load delay slots, then
5889; we want to split the constant into two separate operations.
5890; In both cases this may split a trivial part into a single data op
5891; leaving a single complex constant to load. We can also get longer
5892; offsets in a LDR which means we get better chances of sharing the pool
5893; entries. Finally, we can normally do a better job of scheduling
5894; LDR instructions than we can with LDM.
5895; This pattern will only match if the one above did not.
5896(define_split
5897 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
5898 (match_operand:ANY64 1 "const_double_operand" ""))]
5899 "TARGET_ARM && reload_completed
5900 && arm_const_double_by_parts (operands[1])"
5901 [(set (match_dup 0) (match_dup 1))
5902 (set (match_dup 2) (match_dup 3))]
5903 "
5904 operands[2] = gen_highpart (SImode, operands[0]);
5905 operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
5906 operands[1]);
5907 operands[0] = gen_lowpart (SImode, operands[0]);
5908 operands[1] = gen_lowpart (SImode, operands[1]);
5909 "
5910)
5911
d51f92df 5912(define_split
5913 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
5914 (match_operand:ANY64 1 "arm_general_register_operand" ""))]
5915 "TARGET_EITHER && reload_completed"
5916 [(set (match_dup 0) (match_dup 1))
5917 (set (match_dup 2) (match_dup 3))]
5918 "
5919 operands[2] = gen_highpart (SImode, operands[0]);
5920 operands[3] = gen_highpart (SImode, operands[1]);
5921 operands[0] = gen_lowpart (SImode, operands[0]);
5922 operands[1] = gen_lowpart (SImode, operands[1]);
5923
5924 /* Handle a partial overlap. */
5925 if (rtx_equal_p (operands[0], operands[3]))
5926 {
5927 rtx tmp0 = operands[0];
5928 rtx tmp1 = operands[1];
5929
5930 operands[0] = operands[2];
5931 operands[1] = operands[3];
5932 operands[2] = tmp0;
5933 operands[3] = tmp1;
5934 }
5935 "
5936)
5937
a8a3b539 5938;; We can't actually do base+index doubleword loads if the index and
5939;; destination overlap. Split here so that we at least have chance to
5940;; schedule.
5941(define_split
5942 [(set (match_operand:DI 0 "s_register_operand" "")
5943 (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
5944 (match_operand:SI 2 "s_register_operand" ""))))]
5945 "TARGET_LDRD
5946 && reg_overlap_mentioned_p (operands[0], operands[1])
5947 && reg_overlap_mentioned_p (operands[0], operands[2])"
5948 [(set (match_dup 4)
5949 (plus:SI (match_dup 1)
5950 (match_dup 2)))
5951 (set (match_dup 0)
5952 (mem:DI (match_dup 4)))]
5953 "
5954 operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
5955 "
5956)
5957
9c08d1fa 5958(define_expand "movsi"
5959 [(set (match_operand:SI 0 "general_operand" "")
5960 (match_operand:SI 1 "general_operand" ""))]
cffb2a26 5961 "TARGET_EITHER"
9c08d1fa 5962 "
befb0bac 5963 {
e348ff3e 5964 rtx base, offset, tmp;
5965
25f905c2 5966 if (TARGET_32BIT)
9c08d1fa 5967 {
674a8f0b 5968 /* Everything except mem = const or mem = mem can be done easily. */
0438d37f 5969 if (MEM_P (operands[0]))
cffb2a26 5970 operands[1] = force_reg (SImode, operands[1]);
a2cd141b 5971 if (arm_general_register_operand (operands[0], SImode)
0438d37f 5972 && CONST_INT_P (operands[1])
cffb2a26 5973 && !(const_ok_for_arm (INTVAL (operands[1]))
5974 || const_ok_for_arm (~INTVAL (operands[1]))))
5975 {
17202aa5 5976 if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[1]), SET))
5977 {
5978 emit_insn (gen_rtx_SET (operands[0], operands[1]));
5979 DONE;
5980 }
5981 else
5982 {
5983 arm_split_constant (SET, SImode, NULL_RTX,
5984 INTVAL (operands[1]), operands[0], NULL_RTX,
5985 optimize && can_create_pseudo_p ());
5986 DONE;
5987 }
cffb2a26 5988 }
5989 }
25f905c2 5990 else /* TARGET_THUMB1... */
cffb2a26 5991 {
e1ba4a27 5992 if (can_create_pseudo_p ())
cffb2a26 5993 {
0438d37f 5994 if (!REG_P (operands[0]))
cffb2a26 5995 operands[1] = force_reg (SImode, operands[1]);
5996 }
9c08d1fa 5997 }
f655717d 5998
e348ff3e 5999 if (ARM_OFFSETS_MUST_BE_WITHIN_SECTIONS_P)
6000 {
6001 split_const (operands[1], &base, &offset);
6002 if (GET_CODE (base) == SYMBOL_REF
6003 && !offset_within_block_p (base, INTVAL (offset)))
6004 {
b308ddcf 6005 tmp = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
e348ff3e 6006 emit_move_insn (tmp, base);
6007 emit_insn (gen_addsi3 (operands[0], tmp, offset));
6008 DONE;
6009 }
6010 }
6011
f655717d 6012 /* Recognize the case where operand[1] is a reference to thread-local
6013 data and load its address to a register. */
6014 if (arm_tls_referenced_p (operands[1]))
6015 {
6016 rtx tmp = operands[1];
6017 rtx addend = NULL;
6018
6019 if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
6020 {
6021 addend = XEXP (XEXP (tmp, 0), 1);
6022 tmp = XEXP (XEXP (tmp, 0), 0);
6023 }
6024
6025 gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
6026 gcc_assert (SYMBOL_REF_TLS_MODEL (tmp) != 0);
6027
e1ba4a27 6028 tmp = legitimize_tls_address (tmp,
6029 !can_create_pseudo_p () ? operands[0] : 0);
f655717d 6030 if (addend)
6031 {
6032 tmp = gen_rtx_PLUS (SImode, tmp, addend);
6033 tmp = force_operand (tmp, operands[0]);
6034 }
6035 operands[1] = tmp;
6036 }
6037 else if (flag_pic
6038 && (CONSTANT_P (operands[1])
6039 || symbol_mentioned_p (operands[1])
6040 || label_mentioned_p (operands[1])))
6041 operands[1] = legitimize_pic_address (operands[1], SImode,
e1ba4a27 6042 (!can_create_pseudo_p ()
6043 ? operands[0]
6044 : 0));
befb0bac 6045 }
215b30b3 6046 "
6047)
9c08d1fa 6048
d0e6a121 6049;; The ARM LO_SUM and HIGH are backwards - HIGH sets the low bits, and
6050;; LO_SUM adds in the high bits. Fortunately these are opaque operations
6051;; so this does not matter.
6052(define_insn "*arm_movt"
417e5cc5 6053 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r")
6054 (lo_sum:SI (match_operand:SI 1 "nonimmediate_operand" "0,0")
6055 (match_operand:SI 2 "general_operand" "i,i")))]
60a48e7d 6056 "TARGET_HAVE_MOVT && arm_valid_symbolic_address_p (operands[2])"
417e5cc5 6057 "@
6058 movt%?\t%0, #:upper16:%c2
6059 movt\t%0, #:upper16:%c2"
6060 [(set_attr "arch" "32,v8mb")
6061 (set_attr "predicable" "yes")
d952d547 6062 (set_attr "predicable_short_it" "no")
1b7da4ac 6063 (set_attr "length" "4")
282b4c75 6064 (set_attr "type" "alu_sreg")]
d0e6a121 6065)
6066
cffb2a26 6067(define_insn "*arm_movsi_insn"
aaa37ad6 6068 [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,rk,m")
110eae03 6069 (match_operand:SI 1 "general_operand" "rk, I,K,j,mi,rk"))]
d7216193 6070 "TARGET_ARM && !TARGET_IWMMXT && !TARGET_HARD_FLOAT
cffb2a26 6071 && ( register_operand (operands[0], SImode)
6072 || register_operand (operands[1], SImode))"
f7fbdd4a 6073 "@
aaa37ad6 6074 mov%?\\t%0, %1
f7fbdd4a 6075 mov%?\\t%0, %1
6076 mvn%?\\t%0, #%B1
25f905c2 6077 movw%?\\t%0, %1
f7fbdd4a 6078 ldr%?\\t%0, %1
6079 str%?\\t%1, %0"
1aed5204 6080 [(set_attr "type" "mov_reg,mov_imm,mvn_imm,mov_imm,load1,store1")
0d66636f 6081 (set_attr "predicable" "yes")
100cd063 6082 (set_attr "arch" "*,*,*,v6t2,*,*")
aaa37ad6 6083 (set_attr "pool_range" "*,*,*,*,4096,*")
6084 (set_attr "neg_pool_range" "*,*,*,*,4084,*")]
cffb2a26 6085)
87b22bf7 6086
6087(define_split
a2cd141b 6088 [(set (match_operand:SI 0 "arm_general_register_operand" "")
87b22bf7 6089 (match_operand:SI 1 "const_int_operand" ""))]
25f905c2 6090 "TARGET_32BIT
215b30b3 6091 && (!(const_ok_for_arm (INTVAL (operands[1]))
6092 || const_ok_for_arm (~INTVAL (operands[1]))))"
87b22bf7 6093 [(clobber (const_int 0))]
6094 "
96f57e36 6095 arm_split_constant (SET, SImode, NULL_RTX,
6096 INTVAL (operands[1]), operands[0], NULL_RTX, 0);
87b22bf7 6097 DONE;
215b30b3 6098 "
6099)
9c08d1fa 6100
861033d5 6101;; A normal way to do (symbol + offset) requires three instructions at least
6102;; (depends on how big the offset is) as below:
6103;; movw r0, #:lower16:g
6104;; movw r0, #:upper16:g
6105;; adds r0, #4
6106;;
6107;; A better way would be:
6108;; movw r0, #:lower16:g+4
6109;; movw r0, #:upper16:g+4
6110;;
6111;; The limitation of this way is that the length of offset should be a 16-bit
6112;; signed value, because current assembler only supports REL type relocation for
6113;; such case. If the more powerful RELA type is supported in future, we should
6114;; update this pattern to go with better way.
6115(define_split
6116 [(set (match_operand:SI 0 "arm_general_register_operand" "")
6117 (const:SI (plus:SI (match_operand:SI 1 "general_operand" "")
6118 (match_operand:SI 2 "const_int_operand" ""))))]
60a48e7d 6119 "TARGET_THUMB
6120 && TARGET_HAVE_MOVT
861033d5 6121 && arm_disable_literal_pool
6122 && reload_completed
6123 && GET_CODE (operands[1]) == SYMBOL_REF"
6124 [(clobber (const_int 0))]
6125 "
6126 int offset = INTVAL (operands[2]);
6127
6128 if (offset < -0x8000 || offset > 0x7fff)
6129 {
6130 arm_emit_movpair (operands[0], operands[1]);
d1f9b275 6131 emit_insn (gen_rtx_SET (operands[0],
861033d5 6132 gen_rtx_PLUS (SImode, operands[0], operands[2])));
6133 }
6134 else
6135 {
6136 rtx op = gen_rtx_CONST (SImode,
6137 gen_rtx_PLUS (SImode, operands[1], operands[2]));
6138 arm_emit_movpair (operands[0], op);
6139 }
6140 "
6141)
6142
b8d5d078 6143;; Split symbol_refs at the later stage (after cprop), instead of generating
6144;; movt/movw pair directly at expand. Otherwise corresponding high_sum
6145;; and lo_sum would be merged back into memory load at cprop. However,
6146;; if the default is to prefer movt/movw rather than a load from the constant
6147;; pool, the performance is better.
6148(define_split
6149 [(set (match_operand:SI 0 "arm_general_register_operand" "")
6150 (match_operand:SI 1 "general_operand" ""))]
60a48e7d 6151 "TARGET_USE_MOVT && GET_CODE (operands[1]) == SYMBOL_REF
b8d5d078 6152 && !flag_pic && !target_word_relocations
6153 && !arm_tls_referenced_p (operands[1])"
6154 [(clobber (const_int 0))]
6155{
6156 arm_emit_movpair (operands[0], operands[1]);
6157 DONE;
6158})
6159
bc360af8 6160;; When generating pic, we need to load the symbol offset into a register.
6161;; So that the optimizer does not confuse this with a normal symbol load
6162;; we use an unspec. The offset will be loaded from a constant pool entry,
6163;; since that is the only type of relocation we can use.
cffb2a26 6164
bc360af8 6165;; Wrap calculation of the whole PIC address in a single pattern for the
6166;; benefit of optimizers, particularly, PRE and HOIST. Calculation of
6167;; a PIC address involves two loads from memory, so we want to CSE it
6168;; as often as possible.
6169;; This pattern will be split into one of the pic_load_addr_* patterns
6170;; and a move after GCSE optimizations.
6171;;
6172;; Note: Update arm.c: legitimize_pic_address() when changing this pattern.
6173(define_expand "calculate_pic_address"
94f8caca 6174 [(set (match_operand:SI 0 "register_operand" "")
6175 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "")
6176 (unspec:SI [(match_operand:SI 2 "" "")]
6177 UNSPEC_PIC_SYM))))]
6178 "flag_pic"
6179)
6180
6181;; Split calculate_pic_address into pic_load_addr_* and a move.
6182(define_split
6183 [(set (match_operand:SI 0 "register_operand" "")
6184 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "")
6185 (unspec:SI [(match_operand:SI 2 "" "")]
6186 UNSPEC_PIC_SYM))))]
6187 "flag_pic"
6188 [(set (match_dup 3) (unspec:SI [(match_dup 2)] UNSPEC_PIC_SYM))
6189 (set (match_dup 0) (mem:SI (plus:SI (match_dup 1) (match_dup 3))))]
6190 "operands[3] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];"
6191)
6192
350ccca5 6193;; operand1 is the memory address to go into
6194;; pic_load_addr_32bit.
6195;; operand2 is the PIC label to be emitted
6196;; from pic_add_dot_plus_eight.
6197;; We do this to allow hoisting of the entire insn.
6198(define_insn_and_split "pic_load_addr_unified"
6199 [(set (match_operand:SI 0 "s_register_operand" "=r,r,l")
6200 (unspec:SI [(match_operand:SI 1 "" "mX,mX,mX")
6201 (match_operand:SI 2 "" "")]
6202 UNSPEC_PIC_UNIFIED))]
6203 "flag_pic"
6204 "#"
6205 "&& reload_completed"
6206 [(set (match_dup 0) (unspec:SI [(match_dup 1)] UNSPEC_PIC_SYM))
6207 (set (match_dup 0) (unspec:SI [(match_dup 0) (match_dup 3)
6208 (match_dup 2)] UNSPEC_PIC_BASE))]
6209 "operands[3] = TARGET_THUMB ? GEN_INT (4) : GEN_INT (8);"
6210 [(set_attr "type" "load1,load1,load1")
42e1de19 6211 (set_attr "pool_range" "4096,4094,1022")
350ccca5 6212 (set_attr "neg_pool_range" "4084,0,0")
6213 (set_attr "arch" "a,t2,t1")
6214 (set_attr "length" "8,6,4")]
6215)
6216
67336bcf 6217;; The rather odd constraints on the following are to force reload to leave
6218;; the insn alone, and to force the minipool generation pass to then move
6219;; the GOT symbol to memory.
849170fd 6220
b3cd5f55 6221(define_insn "pic_load_addr_32bit"
849170fd 6222 [(set (match_operand:SI 0 "s_register_operand" "=r")
e1159bbe 6223 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
b3cd5f55 6224 "TARGET_32BIT && flag_pic"
67336bcf 6225 "ldr%?\\t%0, %1"
a2cd141b 6226 [(set_attr "type" "load1")
42e1de19 6227 (set (attr "pool_range")
6228 (if_then_else (eq_attr "is_thumb" "no")
6229 (const_int 4096)
6230 (const_int 4094)))
b3cd5f55 6231 (set (attr "neg_pool_range")
6232 (if_then_else (eq_attr "is_thumb" "no")
6233 (const_int 4084)
6234 (const_int 0)))]
8c4d8060 6235)
6236
25f905c2 6237(define_insn "pic_load_addr_thumb1"
8c4d8060 6238 [(set (match_operand:SI 0 "s_register_operand" "=l")
e1159bbe 6239 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
25f905c2 6240 "TARGET_THUMB1 && flag_pic"
8c4d8060 6241 "ldr\\t%0, %1"
a2cd141b 6242 [(set_attr "type" "load1")
42e1de19 6243 (set (attr "pool_range") (const_int 1018))]
cffb2a26 6244)
849170fd 6245
cffb2a26 6246(define_insn "pic_add_dot_plus_four"
15d5d060 6247 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 6248 (unspec:SI [(match_operand:SI 1 "register_operand" "0")
6249 (const_int 4)
beef0fb5 6250 (match_operand 2 "" "")]
6251 UNSPEC_PIC_BASE))]
b3cd5f55 6252 "TARGET_THUMB"
cffb2a26 6253 "*
6cdcb15c 6254 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
6255 INTVAL (operands[2]));
cffb2a26 6256 return \"add\\t%0, %|pc\";
6257 "
1b7da4ac 6258 [(set_attr "length" "2")
112eda6f 6259 (set_attr "type" "alu_sreg")]
cffb2a26 6260)
849170fd 6261
6262(define_insn "pic_add_dot_plus_eight"
15d5d060 6263 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 6264 (unspec:SI [(match_operand:SI 1 "register_operand" "r")
6265 (const_int 8)
beef0fb5 6266 (match_operand 2 "" "")]
6267 UNSPEC_PIC_BASE))]
f655717d 6268 "TARGET_ARM"
c4034607 6269 "*
6cdcb15c 6270 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
6271 INTVAL (operands[2]));
15d5d060 6272 return \"add%?\\t%0, %|pc, %1\";
cffb2a26 6273 "
1b7da4ac 6274 [(set_attr "predicable" "yes")
112eda6f 6275 (set_attr "type" "alu_sreg")]
cffb2a26 6276)
849170fd 6277
f655717d 6278(define_insn "tls_load_dot_plus_eight"
cc071db6 6279 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 6280 (mem:SI (unspec:SI [(match_operand:SI 1 "register_operand" "r")
6281 (const_int 8)
beef0fb5 6282 (match_operand 2 "" "")]
6283 UNSPEC_PIC_BASE)))]
f655717d 6284 "TARGET_ARM"
6285 "*
6cdcb15c 6286 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
6287 INTVAL (operands[2]));
f655717d 6288 return \"ldr%?\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_eight\";
6289 "
1b7da4ac 6290 [(set_attr "predicable" "yes")
6291 (set_attr "type" "load1")]
f655717d 6292)
6293
6294;; PIC references to local variables can generate pic_add_dot_plus_eight
6295;; followed by a load. These sequences can be crunched down to
6296;; tls_load_dot_plus_eight by a peephole.
6297
6298(define_peephole2
c0c1fba5 6299 [(set (match_operand:SI 0 "register_operand" "")
6300 (unspec:SI [(match_operand:SI 3 "register_operand" "")
6301 (const_int 8)
6302 (match_operand 1 "" "")]
6303 UNSPEC_PIC_BASE))
2d05dfad 6304 (set (match_operand:SI 2 "arm_general_register_operand" "")
6305 (mem:SI (match_dup 0)))]
f655717d 6306 "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
c0c1fba5 6307 [(set (match_dup 2)
6308 (mem:SI (unspec:SI [(match_dup 3)
6309 (const_int 8)
6310 (match_dup 1)]
6311 UNSPEC_PIC_BASE)))]
f655717d 6312 ""
6313)
6314
bac7fc85 6315(define_insn "pic_offset_arm"
6316 [(set (match_operand:SI 0 "register_operand" "=r")
6317 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
6318 (unspec:SI [(match_operand:SI 2 "" "X")]
6319 UNSPEC_PIC_OFFSET))))]
6320 "TARGET_VXWORKS_RTP && TARGET_ARM && flag_pic"
6321 "ldr%?\\t%0, [%1,%2]"
6322 [(set_attr "type" "load1")]
6323)
6324
95373f08 6325(define_expand "builtin_setjmp_receiver"
6326 [(label_ref (match_operand 0 "" ""))]
6327 "flag_pic"
6328 "
6329{
b935b306 6330 /* r3 is clobbered by set/longjmp, so we can use it as a scratch
6331 register. */
2cb7d577 6332 if (arm_pic_register != INVALID_REGNUM)
6333 arm_load_pic_register (1UL << 3);
95373f08 6334 DONE;
6335}")
6336
9c08d1fa 6337;; If copying one reg to another we can set the condition codes according to
6338;; its value. Such a move is common after a return from subroutine and the
6339;; result is being tested against zero.
6340
f7fbdd4a 6341(define_insn "*movsi_compare0"
bd5b4116 6342 [(set (reg:CC CC_REGNUM)
cffb2a26 6343 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
6344 (const_int 0)))
6345 (set (match_operand:SI 0 "s_register_operand" "=r,r")
6346 (match_dup 1))]
25f905c2 6347 "TARGET_32BIT"
e2348bcb 6348 "@
40dbec34 6349 cmp%?\\t%0, #0
3ef90e77 6350 subs%?\\t%0, %1, #0"
65f68e55 6351 [(set_attr "conds" "set")
d82e788e 6352 (set_attr "type" "alus_imm,alus_imm")]
cffb2a26 6353)
b11cae9e 6354
b11cae9e 6355;; Subroutine to store a half word from a register into memory.
6356;; Operand 0 is the source register (HImode)
c8f69309 6357;; Operand 1 is the destination address in a register (SImode)
b11cae9e 6358
9c08d1fa 6359;; In both this routine and the next, we must be careful not to spill
01cc3b75 6360;; a memory address of reg+large_const into a separate PLUS insn, since this
9c08d1fa 6361;; can generate unrecognizable rtl.
6362
b11cae9e 6363(define_expand "storehi"
c8f69309 6364 [;; store the low byte
f082f1c4 6365 (set (match_operand 1 "" "") (match_dup 3))
b11cae9e 6366 ;; extract the high byte
c8f69309 6367 (set (match_dup 2)
6368 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
b11cae9e 6369 ;; store the high byte
787f8210 6370 (set (match_dup 4) (match_dup 5))]
cffb2a26 6371 "TARGET_ARM"
b11cae9e 6372 "
215b30b3 6373 {
537ffcfc 6374 rtx op1 = operands[1];
6375 rtx addr = XEXP (op1, 0);
215b30b3 6376 enum rtx_code code = GET_CODE (addr);
6377
0438d37f 6378 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
215b30b3 6379 || code == MINUS)
537ffcfc 6380 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
215b30b3 6381
537ffcfc 6382 operands[4] = adjust_address (op1, QImode, 1);
e513d163 6383 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 6384 operands[3] = gen_lowpart (QImode, operands[0]);
6385 operands[0] = gen_lowpart (SImode, operands[0]);
787f8210 6386 operands[2] = gen_reg_rtx (SImode);
6387 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 6388 }"
6389)
b11cae9e 6390
c7597b5d 6391(define_expand "storehi_bigend"
f082f1c4 6392 [(set (match_dup 4) (match_dup 3))
c7597b5d 6393 (set (match_dup 2)
6394 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
787f8210 6395 (set (match_operand 1 "" "") (match_dup 5))]
cffb2a26 6396 "TARGET_ARM"
b11cae9e 6397 "
215b30b3 6398 {
537ffcfc 6399 rtx op1 = operands[1];
6400 rtx addr = XEXP (op1, 0);
215b30b3 6401 enum rtx_code code = GET_CODE (addr);
6402
0438d37f 6403 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
215b30b3 6404 || code == MINUS)
537ffcfc 6405 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
215b30b3 6406
537ffcfc 6407 operands[4] = adjust_address (op1, QImode, 1);
e513d163 6408 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 6409 operands[3] = gen_lowpart (QImode, operands[0]);
6410 operands[0] = gen_lowpart (SImode, operands[0]);
6411 operands[2] = gen_reg_rtx (SImode);
787f8210 6412 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 6413 }"
6414)
c7597b5d 6415
6416;; Subroutine to store a half word integer constant into memory.
6417(define_expand "storeinthi"
f082f1c4 6418 [(set (match_operand 0 "" "")
787f8210 6419 (match_operand 1 "" ""))
9e8503e6 6420 (set (match_dup 3) (match_dup 2))]
cffb2a26 6421 "TARGET_ARM"
c7597b5d 6422 "
215b30b3 6423 {
6424 HOST_WIDE_INT value = INTVAL (operands[1]);
6425 rtx addr = XEXP (operands[0], 0);
537ffcfc 6426 rtx op0 = operands[0];
215b30b3 6427 enum rtx_code code = GET_CODE (addr);
c7597b5d 6428
0438d37f 6429 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
215b30b3 6430 || code == MINUS)
537ffcfc 6431 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
c7597b5d 6432
215b30b3 6433 operands[1] = gen_reg_rtx (SImode);
6434 if (BYTES_BIG_ENDIAN)
6435 {
6436 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
6437 if ((value & 255) == ((value >> 8) & 255))
6438 operands[2] = operands[1];
6439 else
6440 {
6441 operands[2] = gen_reg_rtx (SImode);
6442 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
6443 }
6444 }
6445 else
6446 {
6447 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
6448 if ((value & 255) == ((value >> 8) & 255))
6449 operands[2] = operands[1];
6450 else
6451 {
6452 operands[2] = gen_reg_rtx (SImode);
6453 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
6454 }
6455 }
c7597b5d 6456
537ffcfc 6457 operands[3] = adjust_address (op0, QImode, 1);
e513d163 6458 operands[0] = adjust_address (operands[0], QImode, 0);
9e8503e6 6459 operands[2] = gen_lowpart (QImode, operands[2]);
787f8210 6460 operands[1] = gen_lowpart (QImode, operands[1]);
215b30b3 6461 }"
6462)
b11cae9e 6463
f7fbdd4a 6464(define_expand "storehi_single_op"
6465 [(set (match_operand:HI 0 "memory_operand" "")
6466 (match_operand:HI 1 "general_operand" ""))]
25f905c2 6467 "TARGET_32BIT && arm_arch4"
f7fbdd4a 6468 "
215b30b3 6469 if (!s_register_operand (operands[1], HImode))
f7fbdd4a 6470 operands[1] = copy_to_mode_reg (HImode, operands[1]);
215b30b3 6471 "
6472)
f7fbdd4a 6473
b11cae9e 6474(define_expand "movhi"
6475 [(set (match_operand:HI 0 "general_operand" "")
c8f69309 6476 (match_operand:HI 1 "general_operand" ""))]
cffb2a26 6477 "TARGET_EITHER"
b11cae9e 6478 "
cffb2a26 6479 if (TARGET_ARM)
b11cae9e 6480 {
e1ba4a27 6481 if (can_create_pseudo_p ())
cffb2a26 6482 {
0438d37f 6483 if (MEM_P (operands[0]))
b11cae9e 6484 {
cffb2a26 6485 if (arm_arch4)
6486 {
6487 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
6488 DONE;
6489 }
0438d37f 6490 if (CONST_INT_P (operands[1]))
cffb2a26 6491 emit_insn (gen_storeinthi (operands[0], operands[1]));
c7597b5d 6492 else
cffb2a26 6493 {
0438d37f 6494 if (MEM_P (operands[1]))
cffb2a26 6495 operands[1] = force_reg (HImode, operands[1]);
6496 if (BYTES_BIG_ENDIAN)
6497 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
6498 else
6499 emit_insn (gen_storehi (operands[1], operands[0]));
6500 }
6501 DONE;
b11cae9e 6502 }
cffb2a26 6503 /* Sign extend a constant, and keep it in an SImode reg. */
0438d37f 6504 else if (CONST_INT_P (operands[1]))
9c08d1fa 6505 {
cffb2a26 6506 rtx reg = gen_reg_rtx (SImode);
6507 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
6508
6509 /* If the constant is already valid, leave it alone. */
215b30b3 6510 if (!const_ok_for_arm (val))
cffb2a26 6511 {
6512 /* If setting all the top bits will make the constant
6513 loadable in a single instruction, then set them.
6514 Otherwise, sign extend the number. */
6515
215b30b3 6516 if (const_ok_for_arm (~(val | ~0xffff)))
cffb2a26 6517 val |= ~0xffff;
6518 else if (val & 0x8000)
6519 val |= ~0xffff;
6520 }
6521
6522 emit_insn (gen_movsi (reg, GEN_INT (val)));
9e8503e6 6523 operands[1] = gen_lowpart (HImode, reg);
9c08d1fa 6524 }
e1ba4a27 6525 else if (arm_arch4 && optimize && can_create_pseudo_p ()
0438d37f 6526 && MEM_P (operands[1]))
0045890a 6527 {
6528 rtx reg = gen_reg_rtx (SImode);
6529
6530 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
6531 operands[1] = gen_lowpart (HImode, reg);
6532 }
215b30b3 6533 else if (!arm_arch4)
f7fbdd4a 6534 {
0438d37f 6535 if (MEM_P (operands[1]))
cffb2a26 6536 {
c1a66faf 6537 rtx base;
6538 rtx offset = const0_rtx;
6539 rtx reg = gen_reg_rtx (SImode);
6540
0438d37f 6541 if ((REG_P (base = XEXP (operands[1], 0))
c1a66faf 6542 || (GET_CODE (base) == PLUS
0438d37f 6543 && (CONST_INT_P (offset = XEXP (base, 1)))
c1a66faf 6544 && ((INTVAL(offset) & 1) != 1)
0438d37f 6545 && REG_P (base = XEXP (base, 0))))
c1a66faf 6546 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
206ee9a2 6547 {
8deb3959 6548 rtx new_rtx;
c1a66faf 6549
8deb3959 6550 new_rtx = widen_memory_access (operands[1], SImode,
6551 ((INTVAL (offset) & ~3)
6552 - INTVAL (offset)));
6553 emit_insn (gen_movsi (reg, new_rtx));
c1a66faf 6554 if (((INTVAL (offset) & 2) != 0)
6555 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
6556 {
6557 rtx reg2 = gen_reg_rtx (SImode);
6558
6559 emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
6560 reg = reg2;
6561 }
206ee9a2 6562 }
c1a66faf 6563 else
6564 emit_insn (gen_movhi_bytes (reg, operands[1]));
6565
6566 operands[1] = gen_lowpart (HImode, reg);
cffb2a26 6567 }
6568 }
6569 }
674a8f0b 6570 /* Handle loading a large integer during reload. */
0438d37f 6571 else if (CONST_INT_P (operands[1])
215b30b3 6572 && !const_ok_for_arm (INTVAL (operands[1]))
6573 && !const_ok_for_arm (~INTVAL (operands[1])))
cffb2a26 6574 {
6575 /* Writing a constant to memory needs a scratch, which should
6576 be handled with SECONDARY_RELOADs. */
0438d37f 6577 gcc_assert (REG_P (operands[0]));
cffb2a26 6578
6579 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
6580 emit_insn (gen_movsi (operands[0], operands[1]));
6581 DONE;
6582 }
6583 }
25f905c2 6584 else if (TARGET_THUMB2)
6585 {
6586 /* Thumb-2 can do everything except mem=mem and mem=const easily. */
e1ba4a27 6587 if (can_create_pseudo_p ())
25f905c2 6588 {
0438d37f 6589 if (!REG_P (operands[0]))
25f905c2 6590 operands[1] = force_reg (HImode, operands[1]);
6591 /* Zero extend a constant, and keep it in an SImode reg. */
0438d37f 6592 else if (CONST_INT_P (operands[1]))
25f905c2 6593 {
6594 rtx reg = gen_reg_rtx (SImode);
6595 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
6596
6597 emit_insn (gen_movsi (reg, GEN_INT (val)));
6598 operands[1] = gen_lowpart (HImode, reg);
6599 }
6600 }
6601 }
6602 else /* TARGET_THUMB1 */
cffb2a26 6603 {
e1ba4a27 6604 if (can_create_pseudo_p ())
cffb2a26 6605 {
0438d37f 6606 if (CONST_INT_P (operands[1]))
6cffc037 6607 {
6608 rtx reg = gen_reg_rtx (SImode);
6609
6610 emit_insn (gen_movsi (reg, operands[1]));
6611 operands[1] = gen_lowpart (HImode, reg);
6612 }
cffb2a26 6613
6614 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 6615 happen if we are passed a SP (never OK for HImode/QImode) or
bc409cb4 6616 virtual register (also rejected as illegitimate for HImode/QImode)
6617 relative address. */
cffb2a26 6618 /* ??? This should perhaps be fixed elsewhere, for instance, in
6619 fixup_stack_1, by checking for other kinds of invalid addresses,
6620 e.g. a bare reference to a virtual register. This may confuse the
6621 alpha though, which must handle this case differently. */
0438d37f 6622 if (MEM_P (operands[0])
215b30b3 6623 && !memory_address_p (GET_MODE (operands[0]),
6624 XEXP (operands[0], 0)))
537ffcfc 6625 operands[0]
6626 = replace_equiv_address (operands[0],
6627 copy_to_reg (XEXP (operands[0], 0)));
cffb2a26 6628
0438d37f 6629 if (MEM_P (operands[1])
215b30b3 6630 && !memory_address_p (GET_MODE (operands[1]),
6631 XEXP (operands[1], 0)))
537ffcfc 6632 operands[1]
6633 = replace_equiv_address (operands[1],
6634 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 6635
0438d37f 6636 if (MEM_P (operands[1]) && optimize > 0)
6cffc037 6637 {
6638 rtx reg = gen_reg_rtx (SImode);
6639
6640 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
6641 operands[1] = gen_lowpart (HImode, reg);
6642 }
6643
0438d37f 6644 if (MEM_P (operands[0]))
6cffc037 6645 operands[1] = force_reg (HImode, operands[1]);
cffb2a26 6646 }
0438d37f 6647 else if (CONST_INT_P (operands[1])
234f6557 6648 && !satisfies_constraint_I (operands[1]))
cffb2a26 6649 {
6cffc037 6650 /* Handle loading a large integer during reload. */
6651
cffb2a26 6652 /* Writing a constant to memory needs a scratch, which should
6653 be handled with SECONDARY_RELOADs. */
0438d37f 6654 gcc_assert (REG_P (operands[0]));
cffb2a26 6655
1a83b3ff 6656 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
cffb2a26 6657 emit_insn (gen_movsi (operands[0], operands[1]));
6658 DONE;
6659 }
b11cae9e 6660 }
cffb2a26 6661 "
6662)
6663
25f7a26e 6664(define_expand "movhi_bytes"
eab14235 6665 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 6666 (set (match_dup 3)
eab14235 6667 (zero_extend:SI (match_dup 6)))
25f7a26e 6668 (set (match_operand:SI 0 "" "")
6669 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
cffb2a26 6670 "TARGET_ARM"
25f7a26e 6671 "
215b30b3 6672 {
6673 rtx mem1, mem2;
6674 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
6675
788fcce0 6676 mem1 = change_address (operands[1], QImode, addr);
29c05e22 6677 mem2 = change_address (operands[1], QImode,
6678 plus_constant (Pmode, addr, 1));
215b30b3 6679 operands[0] = gen_lowpart (SImode, operands[0]);
6680 operands[1] = mem1;
6681 operands[2] = gen_reg_rtx (SImode);
6682 operands[3] = gen_reg_rtx (SImode);
6683 operands[6] = mem2;
25f7a26e 6684
215b30b3 6685 if (BYTES_BIG_ENDIAN)
6686 {
6687 operands[4] = operands[2];
6688 operands[5] = operands[3];
6689 }
6690 else
6691 {
6692 operands[4] = operands[3];
6693 operands[5] = operands[2];
6694 }
6695 }"
6696)
25f7a26e 6697
c7597b5d 6698(define_expand "movhi_bigend"
6699 [(set (match_dup 2)
6700 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
6701 (const_int 16)))
6702 (set (match_dup 3)
6703 (ashiftrt:SI (match_dup 2) (const_int 16)))
6704 (set (match_operand:HI 0 "s_register_operand" "")
787f8210 6705 (match_dup 4))]
cffb2a26 6706 "TARGET_ARM"
c7597b5d 6707 "
6708 operands[2] = gen_reg_rtx (SImode);
6709 operands[3] = gen_reg_rtx (SImode);
787f8210 6710 operands[4] = gen_lowpart (HImode, operands[3]);
215b30b3 6711 "
6712)
b11cae9e 6713
a2f10574 6714;; Pattern to recognize insn generated default case above
f7fbdd4a 6715(define_insn "*movhi_insn_arch4"
e4585731 6716 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r,m,r")
6717 (match_operand:HI 1 "general_operand" "rIk,K,n,r,mi"))]
cffb2a26 6718 "TARGET_ARM
d7216193 6719 && arm_arch4 && !TARGET_HARD_FLOAT
85e02ccb 6720 && (register_operand (operands[0], HImode)
6721 || register_operand (operands[1], HImode))"
f7fbdd4a 6722 "@
6723 mov%?\\t%0, %1\\t%@ movhi
6724 mvn%?\\t%0, #%B1\\t%@ movhi
b1c1a101 6725 movw%?\\t%0, %L1\\t%@ movhi
3ef90e77 6726 strh%?\\t%1, %0\\t%@ movhi
6727 ldrh%?\\t%0, %1\\t%@ movhi"
65f68e55 6728 [(set_attr "predicable" "yes")
e4585731 6729 (set_attr "pool_range" "*,*,*,*,256")
6730 (set_attr "neg_pool_range" "*,*,*,*,244")
6731 (set_attr "arch" "*,*,v6t2,*,*")
65f68e55 6732 (set_attr_alternative "type"
6733 [(if_then_else (match_operand 1 "const_int_operand" "")
1aed5204 6734 (const_string "mov_imm" )
6735 (const_string "mov_reg"))
6736 (const_string "mvn_imm")
e4585731 6737 (const_string "mov_imm")
65f68e55 6738 (const_string "store1")
6739 (const_string "load1")])]
cffb2a26 6740)
f7fbdd4a 6741
f7fbdd4a 6742(define_insn "*movhi_bytes"
65f68e55 6743 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
5fd254ed 6744 (match_operand:HI 1 "arm_rhs_operand" "I,rk,K"))]
d7216193 6745 "TARGET_ARM && !TARGET_HARD_FLOAT"
25f7a26e 6746 "@
65f68e55 6747 mov%?\\t%0, %1\\t%@ movhi
25f7a26e 6748 mov%?\\t%0, %1\\t%@ movhi
0d66636f 6749 mvn%?\\t%0, #%B1\\t%@ movhi"
d2a518d1 6750 [(set_attr "predicable" "yes")
1aed5204 6751 (set_attr "type" "mov_imm,mov_reg,mvn_imm")]
0d66636f 6752)
837bb76e 6753
bc5c7e08 6754;; We use a DImode scratch because we may occasionally need an additional
6755;; temporary if the address isn't offsettable -- push_reload doesn't seem
6756;; to take any notice of the "o" constraints on reload_memory_operand operand.
d3373b54 6757(define_expand "reload_outhi"
cffb2a26 6758 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
215b30b3 6759 (match_operand:HI 1 "s_register_operand" "r")
6760 (match_operand:DI 2 "s_register_operand" "=&l")])]
cffb2a26 6761 "TARGET_EITHER"
6762 "if (TARGET_ARM)
6763 arm_reload_out_hi (operands);
6764 else
6765 thumb_reload_out_hi (operands);
d3373b54 6766 DONE;
cffb2a26 6767 "
6768)
d3373b54 6769
25f7a26e 6770(define_expand "reload_inhi"
6771 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
cffb2a26 6772 (match_operand:HI 1 "arm_reload_memory_operand" "o")
bc5c7e08 6773 (match_operand:DI 2 "s_register_operand" "=&r")])]
c1a66faf 6774 "TARGET_EITHER"
25f7a26e 6775 "
cffb2a26 6776 if (TARGET_ARM)
6777 arm_reload_in_hi (operands);
6778 else
6779 thumb_reload_out_hi (operands);
25f7a26e 6780 DONE;
6781")
6782
9c08d1fa 6783(define_expand "movqi"
6784 [(set (match_operand:QI 0 "general_operand" "")
6785 (match_operand:QI 1 "general_operand" ""))]
cffb2a26 6786 "TARGET_EITHER"
9c08d1fa 6787 "
6cffc037 6788 /* Everything except mem = const or mem = mem can be done easily */
0045890a 6789
e1ba4a27 6790 if (can_create_pseudo_p ())
cffb2a26 6791 {
0438d37f 6792 if (CONST_INT_P (operands[1]))
6cffc037 6793 {
6794 rtx reg = gen_reg_rtx (SImode);
6795
03770691 6796 /* For thumb we want an unsigned immediate, then we are more likely
6797 to be able to use a movs insn. */
6798 if (TARGET_THUMB)
6799 operands[1] = GEN_INT (INTVAL (operands[1]) & 255);
6800
6cffc037 6801 emit_insn (gen_movsi (reg, operands[1]));
6802 operands[1] = gen_lowpart (QImode, reg);
6803 }
cffb2a26 6804
6cffc037 6805 if (TARGET_THUMB)
6806 {
cffb2a26 6807 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 6808 happen if we are passed a SP (never OK for HImode/QImode) or
bc409cb4 6809 virtual register (also rejected as illegitimate for HImode/QImode)
6810 relative address. */
cffb2a26 6811 /* ??? This should perhaps be fixed elsewhere, for instance, in
6812 fixup_stack_1, by checking for other kinds of invalid addresses,
6813 e.g. a bare reference to a virtual register. This may confuse the
6814 alpha though, which must handle this case differently. */
0438d37f 6815 if (MEM_P (operands[0])
215b30b3 6816 && !memory_address_p (GET_MODE (operands[0]),
cffb2a26 6817 XEXP (operands[0], 0)))
537ffcfc 6818 operands[0]
6819 = replace_equiv_address (operands[0],
6820 copy_to_reg (XEXP (operands[0], 0)));
0438d37f 6821 if (MEM_P (operands[1])
215b30b3 6822 && !memory_address_p (GET_MODE (operands[1]),
cffb2a26 6823 XEXP (operands[1], 0)))
537ffcfc 6824 operands[1]
6825 = replace_equiv_address (operands[1],
6826 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 6827 }
6828
0438d37f 6829 if (MEM_P (operands[1]) && optimize > 0)
6cffc037 6830 {
6831 rtx reg = gen_reg_rtx (SImode);
6832
6833 emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
6834 operands[1] = gen_lowpart (QImode, reg);
6835 }
6836
0438d37f 6837 if (MEM_P (operands[0]))
6cffc037 6838 operands[1] = force_reg (QImode, operands[1]);
6839 }
6840 else if (TARGET_THUMB
0438d37f 6841 && CONST_INT_P (operands[1])
234f6557 6842 && !satisfies_constraint_I (operands[1]))
6cffc037 6843 {
674a8f0b 6844 /* Handle loading a large integer during reload. */
cffb2a26 6845
6cffc037 6846 /* Writing a constant to memory needs a scratch, which should
6847 be handled with SECONDARY_RELOADs. */
0438d37f 6848 gcc_assert (REG_P (operands[0]));
6cffc037 6849
6850 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
6851 emit_insn (gen_movsi (operands[0], operands[1]));
6852 DONE;
cffb2a26 6853 }
6854 "
6855)
b11cae9e 6856
cffb2a26 6857(define_insn "*arm_movqi_insn"
fd711051 6858 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,l,r,l,Uu,r,m")
490f62ca 6859 (match_operand:QI 1 "general_operand" "rk,rk,I,Py,K,Uu,l,Uh,r"))]
25f905c2 6860 "TARGET_32BIT
cffb2a26 6861 && ( register_operand (operands[0], QImode)
6862 || register_operand (operands[1], QImode))"
5565501b 6863 "@
fd711051 6864 mov%?\\t%0, %1
6865 mov%?\\t%0, %1
65f68e55 6866 mov%?\\t%0, %1
5565501b 6867 mov%?\\t%0, %1
6868 mvn%?\\t%0, #%B1
3ef90e77 6869 ldrb%?\\t%0, %1
6870 strb%?\\t%1, %0
6871 ldrb%?\\t%0, %1
6872 strb%?\\t%1, %0"
1aed5204 6873 [(set_attr "type" "mov_reg,mov_reg,mov_imm,mov_imm,mvn_imm,load1,store1,load1,store1")
a54e3e7b 6874 (set_attr "predicable" "yes")
5233bf6a 6875 (set_attr "predicable_short_it" "yes,yes,no,yes,no,no,no,no,no")
fd711051 6876 (set_attr "arch" "t2,any,any,t2,any,t2,t2,any,any")
6877 (set_attr "length" "2,4,4,2,4,2,2,4,4")]
cffb2a26 6878)
6879
9b8516be 6880;; HFmode moves
6881(define_expand "movhf"
6882 [(set (match_operand:HF 0 "general_operand" "")
6883 (match_operand:HF 1 "general_operand" ""))]
6884 "TARGET_EITHER"
6885 "
6886 if (TARGET_32BIT)
6887 {
0438d37f 6888 if (MEM_P (operands[0]))
9b8516be 6889 operands[1] = force_reg (HFmode, operands[1]);
6890 }
6891 else /* TARGET_THUMB1 */
6892 {
6893 if (can_create_pseudo_p ())
6894 {
0438d37f 6895 if (!REG_P (operands[0]))
9b8516be 6896 operands[1] = force_reg (HFmode, operands[1]);
6897 }
6898 }
6899 "
6900)
6901
6902(define_insn "*arm32_movhf"
6903 [(set (match_operand:HF 0 "nonimmediate_operand" "=r,m,r,r")
6904 (match_operand:HF 1 "general_operand" " m,r,r,F"))]
d7216193 6905 "TARGET_32BIT && !TARGET_HARD_FLOAT
9b8516be 6906 && ( s_register_operand (operands[0], HFmode)
6907 || s_register_operand (operands[1], HFmode))"
6908 "*
6909 switch (which_alternative)
6910 {
6911 case 0: /* ARM register from memory */
3ef90e77 6912 return \"ldrh%?\\t%0, %1\\t%@ __fp16\";
9b8516be 6913 case 1: /* memory from ARM register */
3ef90e77 6914 return \"strh%?\\t%1, %0\\t%@ __fp16\";
9b8516be 6915 case 2: /* ARM register from ARM register */
6916 return \"mov%?\\t%0, %1\\t%@ __fp16\";
6917 case 3: /* ARM register from constant */
6918 {
9b8516be 6919 long bits;
6920 rtx ops[4];
6921
945f7b03 6922 bits = real_to_target (NULL, CONST_DOUBLE_REAL_VALUE (operands[1]),
6923 HFmode);
9b8516be 6924 ops[0] = operands[0];
6925 ops[1] = GEN_INT (bits);
6926 ops[2] = GEN_INT (bits & 0xff00);
6927 ops[3] = GEN_INT (bits & 0x00ff);
6928
6929 if (arm_arch_thumb2)
6930 output_asm_insn (\"movw%?\\t%0, %1\", ops);
6931 else
6932 output_asm_insn (\"mov%?\\t%0, %2\;orr%?\\t%0, %0, %3\", ops);
6933 return \"\";
6934 }
6935 default:
6936 gcc_unreachable ();
6937 }
6938 "
6939 [(set_attr "conds" "unconditional")
ad4fc3c0 6940 (set_attr "type" "load1,store1,mov_reg,multiple")
9b8516be 6941 (set_attr "length" "4,4,4,8")
ea501323 6942 (set_attr "predicable" "yes")
6943 (set_attr "predicable_short_it" "no")]
9b8516be 6944)
6945
87b22bf7 6946(define_expand "movsf"
6947 [(set (match_operand:SF 0 "general_operand" "")
6948 (match_operand:SF 1 "general_operand" ""))]
cffb2a26 6949 "TARGET_EITHER"
87b22bf7 6950 "
25f905c2 6951 if (TARGET_32BIT)
cffb2a26 6952 {
0438d37f 6953 if (MEM_P (operands[0]))
cffb2a26 6954 operands[1] = force_reg (SFmode, operands[1]);
6955 }
25f905c2 6956 else /* TARGET_THUMB1 */
cffb2a26 6957 {
e1ba4a27 6958 if (can_create_pseudo_p ())
cffb2a26 6959 {
0438d37f 6960 if (!REG_P (operands[0]))
cffb2a26 6961 operands[1] = force_reg (SFmode, operands[1]);
6962 }
6963 }
6964 "
6965)
6966
03d440a6 6967;; Transform a floating-point move of a constant into a core register into
6968;; an SImode operation.
cffb2a26 6969(define_split
03d440a6 6970 [(set (match_operand:SF 0 "arm_general_register_operand" "")
cffb2a26 6971 (match_operand:SF 1 "immediate_operand" ""))]
339034d0 6972 "TARGET_EITHER
cffb2a26 6973 && reload_completed
0438d37f 6974 && CONST_DOUBLE_P (operands[1])"
cffb2a26 6975 [(set (match_dup 2) (match_dup 3))]
6976 "
6977 operands[2] = gen_lowpart (SImode, operands[0]);
6978 operands[3] = gen_lowpart (SImode, operands[1]);
6979 if (operands[2] == 0 || operands[3] == 0)
6980 FAIL;
215b30b3 6981 "
6982)
87b22bf7 6983
cffb2a26 6984(define_insn "*arm_movsf_soft_insn"
6985 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
6986 (match_operand:SF 1 "general_operand" "r,mE,r"))]
cde1623a 6987 "TARGET_32BIT
cffb2a26 6988 && TARGET_SOFT_FLOAT
0438d37f 6989 && (!MEM_P (operands[0])
215b30b3 6990 || register_operand (operands[1], SFmode))"
9a1112d7 6991 "@
6992 mov%?\\t%0, %1
6993 ldr%?\\t%0, %1\\t%@ float
6994 str%?\\t%1, %0\\t%@ float"
cde1623a 6995 [(set_attr "predicable" "yes")
7c36fe71 6996 (set_attr "predicable_short_it" "no")
1aed5204 6997 (set_attr "type" "mov_reg,load1,store1")
42e1de19 6998 (set_attr "arm_pool_range" "*,4096,*")
6999 (set_attr "thumb2_pool_range" "*,4094,*")
cde1623a 7000 (set_attr "arm_neg_pool_range" "*,4084,*")
7001 (set_attr "thumb2_neg_pool_range" "*,0,*")]
cffb2a26 7002)
7003
9c08d1fa 7004(define_expand "movdf"
87b22bf7 7005 [(set (match_operand:DF 0 "general_operand" "")
7006 (match_operand:DF 1 "general_operand" ""))]
cffb2a26 7007 "TARGET_EITHER"
9c08d1fa 7008 "
25f905c2 7009 if (TARGET_32BIT)
cffb2a26 7010 {
0438d37f 7011 if (MEM_P (operands[0]))
cffb2a26 7012 operands[1] = force_reg (DFmode, operands[1]);
7013 }
7014 else /* TARGET_THUMB */
7015 {
e1ba4a27 7016 if (can_create_pseudo_p ())
cffb2a26 7017 {
0438d37f 7018 if (!REG_P (operands[0]))
cffb2a26 7019 operands[1] = force_reg (DFmode, operands[1]);
7020 }
7021 }
7022 "
7023)
b11cae9e 7024
9c08d1fa 7025;; Reloading a df mode value stored in integer regs to memory can require a
7026;; scratch reg.
7027(define_expand "reload_outdf"
cffb2a26 7028 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
87b22bf7 7029 (match_operand:DF 1 "s_register_operand" "r")
7030 (match_operand:SI 2 "s_register_operand" "=&r")]
06adefdc 7031 "TARGET_THUMB2"
87b22bf7 7032 "
215b30b3 7033 {
7034 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
f7fbdd4a 7035
215b30b3 7036 if (code == REG)
7037 operands[2] = XEXP (operands[0], 0);
7038 else if (code == POST_INC || code == PRE_DEC)
7039 {
7040 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
7041 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
7042 emit_insn (gen_movdi (operands[0], operands[1]));
7043 DONE;
7044 }
7045 else if (code == PRE_INC)
7046 {
7047 rtx reg = XEXP (XEXP (operands[0], 0), 0);
f7fbdd4a 7048
215b30b3 7049 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
7050 operands[2] = reg;
7051 }
7052 else if (code == POST_DEC)
7053 operands[2] = XEXP (XEXP (operands[0], 0), 0);
7054 else
7055 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
7056 XEXP (XEXP (operands[0], 0), 1)));
f7fbdd4a 7057
d1f9b275 7058 emit_insn (gen_rtx_SET (replace_equiv_address (operands[0], operands[2]),
215b30b3 7059 operands[1]));
f7fbdd4a 7060
215b30b3 7061 if (code == POST_DEC)
7062 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
7063
7064 DONE;
7065 }"
7066)
9c08d1fa 7067
9a1112d7 7068(define_insn "*movdf_soft_insn"
353cf59a 7069 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,q,m")
7070 (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,q"))]
cde1623a 7071 "TARGET_32BIT && TARGET_SOFT_FLOAT
b2778788 7072 && ( register_operand (operands[0], DFmode)
7073 || register_operand (operands[1], DFmode))"
d51f92df 7074 "*
7075 switch (which_alternative)
7076 {
7077 case 0:
7078 case 1:
7079 case 2:
7080 return \"#\";
7081 default:
26ff80c0 7082 return output_move_double (operands, true, NULL);
d51f92df 7083 }
7084 "
359a6e9f 7085 [(set_attr "length" "8,12,16,8,8")
1b7da4ac 7086 (set_attr "type" "multiple,multiple,multiple,load2,store2")
42e1de19 7087 (set_attr "arm_pool_range" "*,*,*,1020,*")
7088 (set_attr "thumb2_pool_range" "*,*,*,1018,*")
8848d797 7089 (set_attr "arm_neg_pool_range" "*,*,*,1004,*")
cde1623a 7090 (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
cffb2a26 7091)
b11cae9e 7092\f
b11cae9e 7093
9c08d1fa 7094;; load- and store-multiple insns
7095;; The arm can load/store any set of registers, provided that they are in
320ea44d 7096;; ascending order, but these expanders assume a contiguous set.
b11cae9e 7097
9c08d1fa 7098(define_expand "load_multiple"
7099 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
7100 (match_operand:SI 1 "" ""))
7101 (use (match_operand:SI 2 "" ""))])]
25f905c2 7102 "TARGET_32BIT"
9580c25f 7103{
7104 HOST_WIDE_INT offset = 0;
7105
bd5b4116 7106 /* Support only fixed point registers. */
0438d37f 7107 if (!CONST_INT_P (operands[2])
6e628811 7108 || INTVAL (operands[2]) > MAX_LDM_STM_OPS
9c08d1fa 7109 || INTVAL (operands[2]) < 2
0438d37f 7110 || !MEM_P (operands[1])
7111 || !REG_P (operands[0])
bd5b4116 7112 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
7113 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 7114 FAIL;
7115
7116 operands[3]
320ea44d 7117 = arm_gen_load_multiple (arm_regs_in_sequence + REGNO (operands[0]),
7118 INTVAL (operands[2]),
f082f1c4 7119 force_reg (SImode, XEXP (operands[1], 0)),
320ea44d 7120 FALSE, operands[1], &offset);
9580c25f 7121})
b11cae9e 7122
9c08d1fa 7123(define_expand "store_multiple"
7124 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
7125 (match_operand:SI 1 "" ""))
7126 (use (match_operand:SI 2 "" ""))])]
25f905c2 7127 "TARGET_32BIT"
9580c25f 7128{
7129 HOST_WIDE_INT offset = 0;
7130
674a8f0b 7131 /* Support only fixed point registers. */
0438d37f 7132 if (!CONST_INT_P (operands[2])
6e628811 7133 || INTVAL (operands[2]) > MAX_LDM_STM_OPS
9c08d1fa 7134 || INTVAL (operands[2]) < 2
0438d37f 7135 || !REG_P (operands[1])
7136 || !MEM_P (operands[0])
bd5b4116 7137 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
7138 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 7139 FAIL;
7140
7141 operands[3]
320ea44d 7142 = arm_gen_store_multiple (arm_regs_in_sequence + REGNO (operands[1]),
7143 INTVAL (operands[2]),
f082f1c4 7144 force_reg (SImode, XEXP (operands[0], 0)),
320ea44d 7145 FALSE, operands[0], &offset);
9580c25f 7146})
b11cae9e 7147
9c08d1fa 7148
e34ebfca 7149(define_expand "setmemsi"
7150 [(match_operand:BLK 0 "general_operand" "")
7151 (match_operand:SI 1 "const_int_operand" "")
7152 (match_operand:SI 2 "const_int_operand" "")
7153 (match_operand:SI 3 "const_int_operand" "")]
7154 "TARGET_32BIT"
7155{
7156 if (arm_gen_setmem (operands))
7157 DONE;
7158
7159 FAIL;
7160})
7161
7162
9c08d1fa 7163;; Move a block of memory if it is word aligned and MORE than 2 words long.
7164;; We could let this apply for blocks of less than this, but it clobbers so
7165;; many registers that there is then probably a better way.
7166
008c057d 7167(define_expand "movmemqi"
34191dd1 7168 [(match_operand:BLK 0 "general_operand" "")
7169 (match_operand:BLK 1 "general_operand" "")
7170 (match_operand:SI 2 "const_int_operand" "")
7171 (match_operand:SI 3 "const_int_operand" "")]
ae51a965 7172 ""
9c08d1fa 7173 "
25f905c2 7174 if (TARGET_32BIT)
cffb2a26 7175 {
ae51a965 7176 if (TARGET_LDRD && current_tune->prefer_ldrd_strd
7177 && !optimize_function_for_size_p (cfun))
7178 {
7179 if (gen_movmem_ldrd_strd (operands))
7180 DONE;
7181 FAIL;
7182 }
7183
008c057d 7184 if (arm_gen_movmemqi (operands))
cffb2a26 7185 DONE;
7186 FAIL;
7187 }
25f905c2 7188 else /* TARGET_THUMB1 */
cffb2a26 7189 {
7190 if ( INTVAL (operands[3]) != 4
7191 || INTVAL (operands[2]) > 48)
7192 FAIL;
7193
008c057d 7194 thumb_expand_movmemqi (operands);
cffb2a26 7195 DONE;
7196 }
7197 "
7198)
9c08d1fa 7199\f
b11cae9e 7200
341940e8 7201;; Compare & branch insns
8d232dc7 7202;; The range calculations are based as follows:
341940e8 7203;; For forward branches, the address calculation returns the address of
7204;; the next instruction. This is 2 beyond the branch instruction.
7205;; For backward branches, the address calculation returns the address of
7206;; the first instruction in this pattern (cmp). This is 2 before the branch
7207;; instruction for the shortest sequence, and 4 before the branch instruction
7208;; if we have to jump around an unconditional branch.
7209;; To the basic branch range the PC offset must be added (this is +4).
7210;; So for forward branches we have
7211;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
7212;; And for backward branches we have
7213;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
7214;;
7215;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
7216;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
cffb2a26 7217
aeac46d4 7218(define_expand "cbranchsi4"
7219 [(set (pc) (if_then_else
aa06947a 7220 (match_operator 0 "expandable_comparison_operator"
aeac46d4 7221 [(match_operand:SI 1 "s_register_operand" "")
7222 (match_operand:SI 2 "nonmemory_operand" "")])
7223 (label_ref (match_operand 3 "" ""))
7224 (pc)))]
f9aa4160 7225 "TARGET_EITHER"
aeac46d4 7226 "
74f4459c 7227 if (!TARGET_THUMB1)
7228 {
f9aa4160 7229 if (!arm_validize_comparison (&operands[0], &operands[1], &operands[2]))
7230 FAIL;
74f4459c 7231 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
7232 operands[3]));
7233 DONE;
7234 }
25f905c2 7235 if (thumb1_cmpneg_operand (operands[2], SImode))
aeac46d4 7236 {
7237 emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
7238 operands[3], operands[0]));
7239 DONE;
7240 }
25f905c2 7241 if (!thumb1_cmp_operand (operands[2], SImode))
aeac46d4 7242 operands[2] = force_reg (SImode, operands[2]);
7243 ")
7244
74f4459c 7245(define_expand "cbranchsf4"
7246 [(set (pc) (if_then_else
aa06947a 7247 (match_operator 0 "expandable_comparison_operator"
74f4459c 7248 [(match_operand:SF 1 "s_register_operand" "")
d7216193 7249 (match_operand:SF 2 "vfp_compare_operand" "")])
74f4459c 7250 (label_ref (match_operand 3 "" ""))
7251 (pc)))]
7252 "TARGET_32BIT && TARGET_HARD_FLOAT"
7253 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
7254 operands[3])); DONE;"
7255)
7256
7257(define_expand "cbranchdf4"
7258 [(set (pc) (if_then_else
aa06947a 7259 (match_operator 0 "expandable_comparison_operator"
74f4459c 7260 [(match_operand:DF 1 "s_register_operand" "")
d7216193 7261 (match_operand:DF 2 "vfp_compare_operand" "")])
74f4459c 7262 (label_ref (match_operand 3 "" ""))
7263 (pc)))]
a50d7267 7264 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
74f4459c 7265 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
7266 operands[3])); DONE;"
7267)
7268
74f4459c 7269(define_expand "cbranchdi4"
7270 [(set (pc) (if_then_else
aa06947a 7271 (match_operator 0 "expandable_comparison_operator"
b8eae306 7272 [(match_operand:DI 1 "s_register_operand" "")
a8045a4f 7273 (match_operand:DI 2 "cmpdi_operand" "")])
74f4459c 7274 (label_ref (match_operand 3 "" ""))
7275 (pc)))]
a8045a4f 7276 "TARGET_32BIT"
7277 "{
0438d37f 7278 if (!arm_validize_comparison (&operands[0], &operands[1], &operands[2]))
f9aa4160 7279 FAIL;
7280 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
a8045a4f 7281 operands[3]));
7282 DONE;
7283 }"
74f4459c 7284)
7285
9c08d1fa 7286;; Comparison and test insns
7287
cffb2a26 7288(define_insn "*arm_cmpsi_insn"
bd5b4116 7289 [(set (reg:CC CC_REGNUM)
f9f234ec 7290 (compare:CC (match_operand:SI 0 "s_register_operand" "l,r,r,r,r")
7291 (match_operand:SI 1 "arm_add_operand" "Py,r,r,I,L")))]
25f905c2 7292 "TARGET_32BIT"
5565501b 7293 "@
a6864a24 7294 cmp%?\\t%0, %1
7295 cmp%?\\t%0, %1
aea4c774 7296 cmp%?\\t%0, %1
f9f234ec 7297 cmp%?\\t%0, %1
aea4c774 7298 cmn%?\\t%0, #%n1"
a6864a24 7299 [(set_attr "conds" "set")
f9f234ec 7300 (set_attr "arch" "t2,t2,any,any,any")
7301 (set_attr "length" "2,2,4,4,4")
65f68e55 7302 (set_attr "predicable" "yes")
f9f234ec 7303 (set_attr "predicable_short_it" "yes,yes,yes,no,no")
112eda6f 7304 (set_attr "type" "alus_imm,alus_sreg,alus_sreg,alus_imm,alus_imm")]
cffb2a26 7305)
b11cae9e 7306
d5d4dc8d 7307(define_insn "*cmpsi_shiftsi"
bd5b4116 7308 [(set (reg:CC CC_REGNUM)
d82e788e 7309 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r,r")
cffb2a26 7310 (match_operator:SI 3 "shift_operator"
d82e788e 7311 [(match_operand:SI 1 "s_register_operand" "r,r,r")
7312 (match_operand:SI 2 "shift_amount_operand" "M,r,M")])))]
d5d4dc8d 7313 "TARGET_32BIT"
f9f234ec 7314 "cmp\\t%0, %1%S3"
344495ea 7315 [(set_attr "conds" "set")
331beb1a 7316 (set_attr "shift" "1")
d82e788e 7317 (set_attr "arch" "32,a,a")
282b4c75 7318 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
b11cae9e 7319
d5d4dc8d 7320(define_insn "*cmpsi_shiftsi_swp"
bd5b4116 7321 [(set (reg:CC_SWP CC_REGNUM)
aea4c774 7322 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
d82e788e 7323 [(match_operand:SI 1 "s_register_operand" "r,r,r")
7324 (match_operand:SI 2 "shift_amount_operand" "M,r,M")])
7325 (match_operand:SI 0 "s_register_operand" "r,r,r")))]
d5d4dc8d 7326 "TARGET_32BIT"
aea4c774 7327 "cmp%?\\t%0, %1%S3"
344495ea 7328 [(set_attr "conds" "set")
331beb1a 7329 (set_attr "shift" "1")
d82e788e 7330 (set_attr "arch" "32,a,a")
282b4c75 7331 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
b11cae9e 7332
25f905c2 7333(define_insn "*arm_cmpsi_negshiftsi_si"
aed179ae 7334 [(set (reg:CC_Z CC_REGNUM)
7335 (compare:CC_Z
7336 (neg:SI (match_operator:SI 1 "shift_operator"
7337 [(match_operand:SI 2 "s_register_operand" "r")
7338 (match_operand:SI 3 "reg_or_int_operand" "rM")]))
7339 (match_operand:SI 0 "s_register_operand" "r")))]
cffb2a26 7340 "TARGET_ARM"
aed179ae 7341 "cmn%?\\t%0, %2%S1"
344495ea 7342 [(set_attr "conds" "set")
aed179ae 7343 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
d82e788e 7344 (const_string "alus_shift_imm")
7345 (const_string "alus_shift_reg")))
596e5e8f 7346 (set_attr "predicable" "yes")]
0d66636f 7347)
b11cae9e 7348
a8045a4f 7349;; DImode comparisons. The generic code generates branches that
7350;; if-conversion can not reduce to a conditional compare, so we do
7351;; that directly.
7352
ba6a3b2f 7353(define_insn_and_split "*arm_cmpdi_insn"
a8045a4f 7354 [(set (reg:CC_NCV CC_REGNUM)
7355 (compare:CC_NCV (match_operand:DI 0 "s_register_operand" "r")
7356 (match_operand:DI 1 "arm_di_operand" "rDi")))
7357 (clobber (match_scratch:SI 2 "=r"))]
b805622c 7358 "TARGET_32BIT"
ba6a3b2f 7359 "#" ; "cmp\\t%Q0, %Q1\;sbcs\\t%2, %R0, %R1"
7360 "&& reload_completed"
7361 [(set (reg:CC CC_REGNUM)
7362 (compare:CC (match_dup 0) (match_dup 1)))
7363 (parallel [(set (reg:CC CC_REGNUM)
7364 (compare:CC (match_dup 3) (match_dup 4)))
7365 (set (match_dup 2)
7366 (minus:SI (match_dup 5)
7367 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))])]
7368 {
7369 operands[3] = gen_highpart (SImode, operands[0]);
7370 operands[0] = gen_lowpart (SImode, operands[0]);
7371 if (CONST_INT_P (operands[1]))
7372 {
7373 operands[4] = GEN_INT (~INTVAL (gen_highpart_mode (SImode,
7374 DImode,
7375 operands[1])));
7376 operands[5] = gen_rtx_PLUS (SImode, operands[3], operands[4]);
7377 }
7378 else
7379 {
7380 operands[4] = gen_highpart (SImode, operands[1]);
7381 operands[5] = gen_rtx_MINUS (SImode, operands[3], operands[4]);
7382 }
7383 operands[1] = gen_lowpart (SImode, operands[1]);
7384 operands[2] = gen_lowpart (SImode, operands[2]);
7385 }
a8045a4f 7386 [(set_attr "conds" "set")
1b7da4ac 7387 (set_attr "length" "8")
7388 (set_attr "type" "multiple")]
a8045a4f 7389)
7390
ba6a3b2f 7391(define_insn_and_split "*arm_cmpdi_unsigned"
a8045a4f 7392 [(set (reg:CC_CZ CC_REGNUM)
1a86364b 7393 (compare:CC_CZ (match_operand:DI 0 "s_register_operand" "l,r,r,r")
7394 (match_operand:DI 1 "arm_di_operand" "Py,r,Di,rDi")))]
7c36fe71 7395
48a98053 7396 "TARGET_32BIT"
ba6a3b2f 7397 "#" ; "cmp\\t%R0, %R1\;it eq\;cmpeq\\t%Q0, %Q1"
7398 "&& reload_completed"
7399 [(set (reg:CC CC_REGNUM)
7400 (compare:CC (match_dup 2) (match_dup 3)))
7401 (cond_exec (eq:SI (reg:CC CC_REGNUM) (const_int 0))
7402 (set (reg:CC CC_REGNUM)
7403 (compare:CC (match_dup 0) (match_dup 1))))]
7404 {
7405 operands[2] = gen_highpart (SImode, operands[0]);
7406 operands[0] = gen_lowpart (SImode, operands[0]);
7407 if (CONST_INT_P (operands[1]))
7408 operands[3] = gen_highpart_mode (SImode, DImode, operands[1]);
7409 else
7410 operands[3] = gen_highpart (SImode, operands[1]);
7411 operands[1] = gen_lowpart (SImode, operands[1]);
7412 }
a8045a4f 7413 [(set_attr "conds" "set")
1a86364b 7414 (set_attr "enabled_for_depr_it" "yes,yes,no,*")
7415 (set_attr "arch" "t2,t2,t2,a")
7416 (set_attr "length" "6,6,10,8")
1b7da4ac 7417 (set_attr "type" "multiple")]
a8045a4f 7418)
7419
7420(define_insn "*arm_cmpdi_zero"
7421 [(set (reg:CC_Z CC_REGNUM)
7422 (compare:CC_Z (match_operand:DI 0 "s_register_operand" "r")
7423 (const_int 0)))
7424 (clobber (match_scratch:SI 1 "=r"))]
7425 "TARGET_32BIT"
3ef90e77 7426 "orrs%?\\t%1, %Q0, %R0"
1b7da4ac 7427 [(set_attr "conds" "set")
7428 (set_attr "type" "logics_reg")]
a8045a4f 7429)
7430
9c08d1fa 7431; This insn allows redundant compares to be removed by cse, nothing should
7432; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
7433; is deleted later on. The match_dup will match the mode here, so that
7434; mode changes of the condition codes aren't lost by this even though we don't
7435; specify what they are.
7436
8a18b90c 7437(define_insn "*deleted_compare"
9c08d1fa 7438 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
25f905c2 7439 "TARGET_32BIT"
40dbec34 7440 "\\t%@ deleted compare"
cffb2a26 7441 [(set_attr "conds" "set")
1b7da4ac 7442 (set_attr "length" "0")
7443 (set_attr "type" "no_insn")]
cffb2a26 7444)
9c08d1fa 7445
7446\f
7447;; Conditional branch insns
7448
74f4459c 7449(define_expand "cbranch_cc"
9c08d1fa 7450 [(set (pc)
74f4459c 7451 (if_then_else (match_operator 0 "" [(match_operand 1 "" "")
7452 (match_operand 2 "" "")])
7453 (label_ref (match_operand 3 "" ""))
9c08d1fa 7454 (pc)))]
25f905c2 7455 "TARGET_32BIT"
74f4459c 7456 "operands[1] = arm_gen_compare_reg (GET_CODE (operands[0]),
e1b93706 7457 operands[1], operands[2], NULL_RTX);
74f4459c 7458 operands[2] = const0_rtx;"
8fa3ba89 7459)
7460
7461;;
7462;; Patterns to match conditional branch insns.
7463;;
7464
ffcc986d 7465(define_insn "arm_cond_branch"
9c08d1fa 7466 [(set (pc)
8fa3ba89 7467 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 7468 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 7469 (label_ref (match_operand 0 "" ""))
7470 (pc)))]
25f905c2 7471 "TARGET_32BIT"
d75350ce 7472 "*
9c08d1fa 7473 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 7474 {
7475 arm_ccfsm_state += 2;
7476 return \"\";
7477 }
e2348bcb 7478 return \"b%d1\\t%l0\";
cffb2a26 7479 "
a2cd141b 7480 [(set_attr "conds" "use")
a6864a24 7481 (set_attr "type" "branch")
7482 (set (attr "length")
7483 (if_then_else
0bf497f5 7484 (and (match_test "TARGET_THUMB2")
a6864a24 7485 (and (ge (minus (match_dup 0) (pc)) (const_int -250))
7486 (le (minus (match_dup 0) (pc)) (const_int 256))))
7487 (const_int 2)
7488 (const_int 4)))]
cffb2a26 7489)
d75350ce 7490
cffb2a26 7491(define_insn "*arm_cond_branch_reversed"
9c08d1fa 7492 [(set (pc)
8fa3ba89 7493 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 7494 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 7495 (pc)
7496 (label_ref (match_operand 0 "" ""))))]
25f905c2 7497 "TARGET_32BIT"
d75350ce 7498 "*
9c08d1fa 7499 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 7500 {
7501 arm_ccfsm_state += 2;
7502 return \"\";
7503 }
e2348bcb 7504 return \"b%D1\\t%l0\";
cffb2a26 7505 "
a2cd141b 7506 [(set_attr "conds" "use")
a6864a24 7507 (set_attr "type" "branch")
7508 (set (attr "length")
7509 (if_then_else
0bf497f5 7510 (and (match_test "TARGET_THUMB2")
a6864a24 7511 (and (ge (minus (match_dup 0) (pc)) (const_int -250))
7512 (le (minus (match_dup 0) (pc)) (const_int 256))))
7513 (const_int 2)
7514 (const_int 4)))]
cffb2a26 7515)
7516
b11cae9e 7517\f
9c08d1fa 7518
7519; scc insns
7520
74f4459c 7521(define_expand "cstore_cc"
7db9af5d 7522 [(set (match_operand:SI 0 "s_register_operand" "")
74f4459c 7523 (match_operator:SI 1 "" [(match_operand 2 "" "")
7524 (match_operand 3 "" "")]))]
25f905c2 7525 "TARGET_32BIT"
74f4459c 7526 "operands[2] = arm_gen_compare_reg (GET_CODE (operands[1]),
e1b93706 7527 operands[2], operands[3], NULL_RTX);
74f4459c 7528 operands[3] = const0_rtx;"
8fa3ba89 7529)
7530
a3b84066 7531(define_insn_and_split "*mov_scc"
9c08d1fa 7532 [(set (match_operand:SI 0 "s_register_operand" "=r")
ff74dd54 7533 (match_operator:SI 1 "arm_comparison_operator_mode"
8a18b90c 7534 [(match_operand 2 "cc_register" "") (const_int 0)]))]
cffb2a26 7535 "TARGET_ARM"
a3b84066 7536 "#" ; "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
7537 "TARGET_ARM"
7538 [(set (match_dup 0)
7539 (if_then_else:SI (match_dup 1)
7540 (const_int 1)
7541 (const_int 0)))]
7542 ""
cffb2a26 7543 [(set_attr "conds" "use")
1b7da4ac 7544 (set_attr "length" "8")
7545 (set_attr "type" "multiple")]
cffb2a26 7546)
9c08d1fa 7547
a3b84066 7548(define_insn_and_split "*mov_negscc"
9c08d1fa 7549 [(set (match_operand:SI 0 "s_register_operand" "=r")
ff74dd54 7550 (neg:SI (match_operator:SI 1 "arm_comparison_operator_mode"
8a18b90c 7551 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 7552 "TARGET_ARM"
a3b84066 7553 "#" ; "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
7554 "TARGET_ARM"
7555 [(set (match_dup 0)
7556 (if_then_else:SI (match_dup 1)
7557 (match_dup 3)
7558 (const_int 0)))]
7559 {
7560 operands[3] = GEN_INT (~0);
7561 }
cffb2a26 7562 [(set_attr "conds" "use")
1b7da4ac 7563 (set_attr "length" "8")
7564 (set_attr "type" "multiple")]
cffb2a26 7565)
9c08d1fa 7566
a3b84066 7567(define_insn_and_split "*mov_notscc"
9c08d1fa 7568 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7569 (not:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7570 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 7571 "TARGET_ARM"
a3b84066 7572 "#" ; "mvn%D1\\t%0, #0\;mvn%d1\\t%0, #1"
7573 "TARGET_ARM"
7574 [(set (match_dup 0)
7575 (if_then_else:SI (match_dup 1)
7576 (match_dup 3)
7577 (match_dup 4)))]
7578 {
7579 operands[3] = GEN_INT (~1);
7580 operands[4] = GEN_INT (~0);
7581 }
cffb2a26 7582 [(set_attr "conds" "use")
1b7da4ac 7583 (set_attr "length" "8")
7584 (set_attr "type" "multiple")]
cffb2a26 7585)
9c08d1fa 7586
595d88b5 7587(define_expand "cstoresi4"
7588 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 7589 (match_operator:SI 1 "expandable_comparison_operator"
595d88b5 7590 [(match_operand:SI 2 "s_register_operand" "")
7591 (match_operand:SI 3 "reg_or_int_operand" "")]))]
74f4459c 7592 "TARGET_32BIT || TARGET_THUMB1"
595d88b5 7593 "{
7594 rtx op3, scratch, scratch2;
7595
74f4459c 7596 if (!TARGET_THUMB1)
7597 {
7598 if (!arm_add_operand (operands[3], SImode))
7599 operands[3] = force_reg (SImode, operands[3]);
7600 emit_insn (gen_cstore_cc (operands[0], operands[1],
7601 operands[2], operands[3]));
7602 DONE;
7603 }
7604
595d88b5 7605 if (operands[3] == const0_rtx)
7606 {
7607 switch (GET_CODE (operands[1]))
7608 {
7609 case EQ:
25f905c2 7610 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], operands[2]));
595d88b5 7611 break;
7612
7613 case NE:
25f905c2 7614 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], operands[2]));
595d88b5 7615 break;
7616
7617 case LE:
7618 scratch = expand_binop (SImode, add_optab, operands[2], constm1_rtx,
7619 NULL_RTX, 0, OPTAB_WIDEN);
7620 scratch = expand_binop (SImode, ior_optab, operands[2], scratch,
7621 NULL_RTX, 0, OPTAB_WIDEN);
7622 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7623 operands[0], 1, OPTAB_WIDEN);
7624 break;
7625
7626 case GE:
7627 scratch = expand_unop (SImode, one_cmpl_optab, operands[2],
7628 NULL_RTX, 1);
7629 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7630 NULL_RTX, 1, OPTAB_WIDEN);
7631 break;
7632
7633 case GT:
7634 scratch = expand_binop (SImode, ashr_optab, operands[2],
7635 GEN_INT (31), NULL_RTX, 0, OPTAB_WIDEN);
7636 scratch = expand_binop (SImode, sub_optab, scratch, operands[2],
7637 NULL_RTX, 0, OPTAB_WIDEN);
7638 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31), operands[0],
7639 0, OPTAB_WIDEN);
7640 break;
7641
7642 /* LT is handled by generic code. No need for unsigned with 0. */
7643 default:
7644 FAIL;
7645 }
7646 DONE;
7647 }
7648
7649 switch (GET_CODE (operands[1]))
7650 {
7651 case EQ:
7652 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7653 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7654 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], scratch));
595d88b5 7655 break;
7656
7657 case NE:
7658 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7659 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7660 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], scratch));
595d88b5 7661 break;
7662
7663 case LE:
7664 op3 = force_reg (SImode, operands[3]);
7665
7666 scratch = expand_binop (SImode, lshr_optab, operands[2], GEN_INT (31),
7667 NULL_RTX, 1, OPTAB_WIDEN);
7668 scratch2 = expand_binop (SImode, ashr_optab, op3, GEN_INT (31),
7669 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7670 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
595d88b5 7671 op3, operands[2]));
7672 break;
7673
7674 case GE:
7675 op3 = operands[3];
25f905c2 7676 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7677 op3 = force_reg (SImode, op3);
7678 scratch = expand_binop (SImode, ashr_optab, operands[2], GEN_INT (31),
7679 NULL_RTX, 0, OPTAB_WIDEN);
7680 scratch2 = expand_binop (SImode, lshr_optab, op3, GEN_INT (31),
7681 NULL_RTX, 1, OPTAB_WIDEN);
25f905c2 7682 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
595d88b5 7683 operands[2], op3));
7684 break;
7685
7686 case LEU:
7687 op3 = force_reg (SImode, operands[3]);
7688 scratch = force_reg (SImode, const0_rtx);
25f905c2 7689 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
595d88b5 7690 op3, operands[2]));
7691 break;
7692
7693 case GEU:
7694 op3 = operands[3];
25f905c2 7695 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7696 op3 = force_reg (SImode, op3);
7697 scratch = force_reg (SImode, const0_rtx);
25f905c2 7698 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
595d88b5 7699 operands[2], op3));
7700 break;
7701
7702 case LTU:
7703 op3 = operands[3];
25f905c2 7704 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7705 op3 = force_reg (SImode, op3);
7706 scratch = gen_reg_rtx (SImode);
408b7ae5 7707 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], operands[2], op3));
595d88b5 7708 break;
7709
7710 case GTU:
7711 op3 = force_reg (SImode, operands[3]);
7712 scratch = gen_reg_rtx (SImode);
408b7ae5 7713 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], op3, operands[2]));
595d88b5 7714 break;
7715
7716 /* No good sequences for GT, LT. */
7717 default:
7718 FAIL;
7719 }
7720 DONE;
7721}")
7722
9854d864 7723(define_expand "cstorehf4"
7724 [(set (match_operand:SI 0 "s_register_operand")
7725 (match_operator:SI 1 "expandable_comparison_operator"
7726 [(match_operand:HF 2 "s_register_operand")
d7216193 7727 (match_operand:HF 3 "vfp_compare_operand")]))]
9854d864 7728 "TARGET_VFP_FP16INST"
7729 {
7730 if (!arm_validize_comparison (&operands[1],
7731 &operands[2],
7732 &operands[3]))
7733 FAIL;
7734
7735 emit_insn (gen_cstore_cc (operands[0], operands[1],
7736 operands[2], operands[3]));
7737 DONE;
7738 }
7739)
7740
74f4459c 7741(define_expand "cstoresf4"
7742 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 7743 (match_operator:SI 1 "expandable_comparison_operator"
74f4459c 7744 [(match_operand:SF 2 "s_register_operand" "")
d7216193 7745 (match_operand:SF 3 "vfp_compare_operand" "")]))]
74f4459c 7746 "TARGET_32BIT && TARGET_HARD_FLOAT"
7747 "emit_insn (gen_cstore_cc (operands[0], operands[1],
7748 operands[2], operands[3])); DONE;"
7749)
7750
7751(define_expand "cstoredf4"
7752 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 7753 (match_operator:SI 1 "expandable_comparison_operator"
74f4459c 7754 [(match_operand:DF 2 "s_register_operand" "")
d7216193 7755 (match_operand:DF 3 "vfp_compare_operand" "")]))]
d63ed457 7756 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
74f4459c 7757 "emit_insn (gen_cstore_cc (operands[0], operands[1],
7758 operands[2], operands[3])); DONE;"
7759)
7760
74f4459c 7761(define_expand "cstoredi4"
7762 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 7763 (match_operator:SI 1 "expandable_comparison_operator"
b8eae306 7764 [(match_operand:DI 2 "s_register_operand" "")
a8045a4f 7765 (match_operand:DI 3 "cmpdi_operand" "")]))]
7766 "TARGET_32BIT"
7767 "{
f9aa4160 7768 if (!arm_validize_comparison (&operands[1],
7769 &operands[2],
7770 &operands[3]))
7771 FAIL;
7772 emit_insn (gen_cstore_cc (operands[0], operands[1], operands[2],
a8045a4f 7773 operands[3]));
7774 DONE;
7775 }"
74f4459c 7776)
7777
9c08d1fa 7778\f
39b5e676 7779;; Conditional move insns
7780
7781(define_expand "movsicc"
8a18b90c 7782 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 7783 (if_then_else:SI (match_operand 1 "expandable_comparison_operator" "")
aea4c774 7784 (match_operand:SI 2 "arm_not_operand" "")
8a18b90c 7785 (match_operand:SI 3 "arm_not_operand" "")))]
25f905c2 7786 "TARGET_32BIT"
39b5e676 7787 "
215b30b3 7788 {
f9aa4160 7789 enum rtx_code code;
278b301d 7790 rtx ccreg;
7791
f9aa4160 7792 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
9854d864 7793 &XEXP (operands[1], 1)))
278b301d 7794 FAIL;
9854d864 7795
7796 code = GET_CODE (operands[1]);
7797 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
7798 XEXP (operands[1], 1), NULL_RTX);
7799 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7800 }"
7801)
7802
7803(define_expand "movhfcc"
7804 [(set (match_operand:HF 0 "s_register_operand")
7805 (if_then_else:HF (match_operand 1 "arm_cond_move_operator")
7806 (match_operand:HF 2 "s_register_operand")
7807 (match_operand:HF 3 "s_register_operand")))]
7808 "TARGET_VFP_FP16INST"
7809 "
7810 {
7811 enum rtx_code code = GET_CODE (operands[1]);
7812 rtx ccreg;
7813
7814 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
7815 &XEXP (operands[1], 1)))
7816 FAIL;
7817
f9aa4160 7818 code = GET_CODE (operands[1]);
74f4459c 7819 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
e1b93706 7820 XEXP (operands[1], 1), NULL_RTX);
29bb088d 7821 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7822 }"
7823)
39b5e676 7824
7825(define_expand "movsfcc"
8a18b90c 7826 [(set (match_operand:SF 0 "s_register_operand" "")
4df97ffc 7827 (if_then_else:SF (match_operand 1 "arm_cond_move_operator" "")
8a18b90c 7828 (match_operand:SF 2 "s_register_operand" "")
d86c91f6 7829 (match_operand:SF 3 "s_register_operand" "")))]
19f6bf8d 7830 "TARGET_32BIT && TARGET_HARD_FLOAT"
39b5e676 7831 "
215b30b3 7832 {
7833 enum rtx_code code = GET_CODE (operands[1]);
7834 rtx ccreg;
f082f1c4 7835
9854d864 7836 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
f9aa4160 7837 &XEXP (operands[1], 1)))
7838 FAIL;
39b5e676 7839
f9aa4160 7840 code = GET_CODE (operands[1]);
74f4459c 7841 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
e1b93706 7842 XEXP (operands[1], 1), NULL_RTX);
29bb088d 7843 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7844 }"
7845)
39b5e676 7846
7847(define_expand "movdfcc"
8a18b90c 7848 [(set (match_operand:DF 0 "s_register_operand" "")
4df97ffc 7849 (if_then_else:DF (match_operand 1 "arm_cond_move_operator" "")
8a18b90c 7850 (match_operand:DF 2 "s_register_operand" "")
d86c91f6 7851 (match_operand:DF 3 "s_register_operand" "")))]
994606f8 7852 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
39b5e676 7853 "
215b30b3 7854 {
7855 enum rtx_code code = GET_CODE (operands[1]);
278b301d 7856 rtx ccreg;
39b5e676 7857
f9aa4160 7858 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
7859 &XEXP (operands[1], 1)))
7860 FAIL;
7861 code = GET_CODE (operands[1]);
74f4459c 7862 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
e1b93706 7863 XEXP (operands[1], 1), NULL_RTX);
29bb088d 7864 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7865 }"
7866)
39b5e676 7867
91cb50d2 7868(define_insn "*cmov<mode>"
7869 [(set (match_operand:SDF 0 "s_register_operand" "=<F_constraint>")
7870 (if_then_else:SDF (match_operator 1 "arm_vsel_comparison_operator"
7871 [(match_operand 2 "cc_register" "") (const_int 0)])
7872 (match_operand:SDF 3 "s_register_operand"
7873 "<F_constraint>")
7874 (match_operand:SDF 4 "s_register_operand"
7875 "<F_constraint>")))]
7876 "TARGET_HARD_FLOAT && TARGET_FPU_ARMV8 <vfp_double_cond>"
7877 "*
7878 {
7879 enum arm_cond_code code = maybe_get_arm_condition_code (operands[1]);
7880 switch (code)
7881 {
7882 case ARM_GE:
7883 case ARM_GT:
7884 case ARM_EQ:
7885 case ARM_VS:
7886 return \"vsel%d1.<V_if_elem>\\t%<V_reg>0, %<V_reg>3, %<V_reg>4\";
7887 case ARM_LT:
7888 case ARM_LE:
7889 case ARM_NE:
7890 case ARM_VC:
7891 return \"vsel%D1.<V_if_elem>\\t%<V_reg>0, %<V_reg>4, %<V_reg>3\";
7892 default:
7893 gcc_unreachable ();
7894 }
7895 return \"\";
7896 }"
7897 [(set_attr "conds" "use")
6664d308 7898 (set_attr "type" "fcsel")]
91cb50d2 7899)
7900
9854d864 7901(define_insn "*cmovhf"
7902 [(set (match_operand:HF 0 "s_register_operand" "=t")
7903 (if_then_else:HF (match_operator 1 "arm_vsel_comparison_operator"
7904 [(match_operand 2 "cc_register" "") (const_int 0)])
7905 (match_operand:HF 3 "s_register_operand" "t")
7906 (match_operand:HF 4 "s_register_operand" "t")))]
7907 "TARGET_VFP_FP16INST"
7908 "*
7909 {
7910 enum arm_cond_code code = maybe_get_arm_condition_code (operands[1]);
7911 switch (code)
7912 {
7913 case ARM_GE:
7914 case ARM_GT:
7915 case ARM_EQ:
7916 case ARM_VS:
7917 return \"vsel%d1.f16\\t%0, %3, %4\";
7918 case ARM_LT:
7919 case ARM_LE:
7920 case ARM_NE:
7921 case ARM_VC:
7922 return \"vsel%D1.f16\\t%0, %4, %3\";
7923 default:
7924 gcc_unreachable ();
7925 }
7926 return \"\";
7927 }"
7928 [(set_attr "conds" "use")
7929 (set_attr "type" "fcsel")]
7930)
7931
190efb17 7932(define_insn_and_split "*movsicc_insn"
f082f1c4 7933 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
8a18b90c 7934 (if_then_else:SI
8fa3ba89 7935 (match_operator 3 "arm_comparison_operator"
8a18b90c 7936 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 7937 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
7938 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
cffb2a26 7939 "TARGET_ARM"
39b5e676 7940 "@
8a18b90c 7941 mov%D3\\t%0, %2
7942 mvn%D3\\t%0, #%B2
f082f1c4 7943 mov%d3\\t%0, %1
7944 mvn%d3\\t%0, #%B1
190efb17 7945 #
7946 #
7947 #
7948 #"
7949 ; alt4: mov%d3\\t%0, %1\;mov%D3\\t%0, %2
7950 ; alt5: mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
7951 ; alt6: mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
7952 ; alt7: mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
7953 "&& reload_completed"
7954 [(const_int 0)]
7955 {
7956 enum rtx_code rev_code;
3754d046 7957 machine_mode mode;
190efb17 7958 rtx rev_cond;
7959
7960 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
7961 operands[3],
d1f9b275 7962 gen_rtx_SET (operands[0], operands[1])));
190efb17 7963
7964 rev_code = GET_CODE (operands[3]);
7965 mode = GET_MODE (operands[4]);
7966 if (mode == CCFPmode || mode == CCFPEmode)
7967 rev_code = reverse_condition_maybe_unordered (rev_code);
7968 else
7969 rev_code = reverse_condition (rev_code);
7970
7971 rev_cond = gen_rtx_fmt_ee (rev_code,
7972 VOIDmode,
7973 operands[4],
7974 const0_rtx);
7975 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
7976 rev_cond,
d1f9b275 7977 gen_rtx_SET (operands[0], operands[2])));
190efb17 7978 DONE;
7979 }
f082f1c4 7980 [(set_attr "length" "4,4,4,4,8,8,8,8")
d2a518d1 7981 (set_attr "conds" "use")
65f68e55 7982 (set_attr_alternative "type"
7983 [(if_then_else (match_operand 2 "const_int_operand" "")
1aed5204 7984 (const_string "mov_imm")
7985 (const_string "mov_reg"))
7986 (const_string "mvn_imm")
65f68e55 7987 (if_then_else (match_operand 1 "const_int_operand" "")
1aed5204 7988 (const_string "mov_imm")
7989 (const_string "mov_reg"))
7990 (const_string "mvn_imm")
282b4c75 7991 (const_string "multiple")
7992 (const_string "multiple")
7993 (const_string "multiple")
7994 (const_string "multiple")])]
215b30b3 7995)
39b5e676 7996
39b5e676 7997(define_insn "*movsfcc_soft_insn"
f082f1c4 7998 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
8fa3ba89 7999 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
8a18b90c 8000 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 8001 (match_operand:SF 1 "s_register_operand" "0,r")
8002 (match_operand:SF 2 "s_register_operand" "r,0")))]
cffb2a26 8003 "TARGET_ARM && TARGET_SOFT_FLOAT"
f082f1c4 8004 "@
8005 mov%D3\\t%0, %2
8006 mov%d3\\t%0, %1"
d2a518d1 8007 [(set_attr "conds" "use")
1aed5204 8008 (set_attr "type" "mov_reg")]
8fa3ba89 8009)
39b5e676 8010
39b5e676 8011\f
9c08d1fa 8012;; Jump and linkage insns
8013
cffb2a26 8014(define_expand "jump"
9c08d1fa 8015 [(set (pc)
8016 (label_ref (match_operand 0 "" "")))]
cffb2a26 8017 "TARGET_EITHER"
9c08d1fa 8018 ""
cffb2a26 8019)
8020
8021(define_insn "*arm_jump"
8022 [(set (pc)
8023 (label_ref (match_operand 0 "" "")))]
25f905c2 8024 "TARGET_32BIT"
9c08d1fa 8025 "*
0d66636f 8026 {
8027 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
8028 {
8029 arm_ccfsm_state += 2;
8030 return \"\";
8031 }
8032 return \"b%?\\t%l0\";
8033 }
8034 "
a6864a24 8035 [(set_attr "predicable" "yes")
8036 (set (attr "length")
8037 (if_then_else
0bf497f5 8038 (and (match_test "TARGET_THUMB2")
a6864a24 8039 (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
8040 (le (minus (match_dup 0) (pc)) (const_int 2048))))
8041 (const_int 2)
1b7da4ac 8042 (const_int 4)))
8043 (set_attr "type" "branch")]
0d66636f 8044)
9c08d1fa 8045
d3373b54 8046(define_expand "call"
8047 [(parallel [(call (match_operand 0 "memory_operand" "")
8048 (match_operand 1 "general_operand" ""))
cffb2a26 8049 (use (match_operand 2 "" ""))
bd5b4116 8050 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 8051 "TARGET_EITHER"
6c4c2133 8052 "
8053 {
bac7fc85 8054 rtx callee, pat;
2d3a01a7 8055 tree addr = MEM_EXPR (operands[0]);
bbe777ea 8056
bbe777ea 8057 /* In an untyped call, we can get NULL for operand 2. */
8058 if (operands[2] == NULL_RTX)
8059 operands[2] = const0_rtx;
8060
de55252a 8061 /* Decide if we should generate indirect calls by loading the
85c36fd1 8062 32-bit address of the callee into a register before performing the
de55252a 8063 branch and link. */
8064 callee = XEXP (operands[0], 0);
8065 if (GET_CODE (callee) == SYMBOL_REF
8066 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
8067 : !REG_P (callee))
bbe777ea 8068 XEXP (operands[0], 0) = force_reg (Pmode, callee);
bac7fc85 8069
2d3a01a7 8070 if (detect_cmse_nonsecure_call (addr))
8071 {
8072 pat = gen_nonsecure_call_internal (operands[0], operands[1],
8073 operands[2]);
8074 emit_call_insn (pat);
8075 }
8076 else
8077 {
8078 pat = gen_call_internal (operands[0], operands[1], operands[2]);
8079 arm_emit_call_insn (pat, XEXP (operands[0], 0), false);
8080 }
bac7fc85 8081 DONE;
6c4c2133 8082 }"
8083)
d3373b54 8084
bac7fc85 8085(define_expand "call_internal"
8086 [(parallel [(call (match_operand 0 "memory_operand" "")
8087 (match_operand 1 "general_operand" ""))
8088 (use (match_operand 2 "" ""))
8089 (clobber (reg:SI LR_REGNUM))])])
8090
2d3a01a7 8091(define_expand "nonsecure_call_internal"
8092 [(parallel [(call (unspec:SI [(match_operand 0 "memory_operand" "")]
8093 UNSPEC_NONSECURE_MEM)
8094 (match_operand 1 "general_operand" ""))
8095 (use (match_operand 2 "" ""))
8096 (clobber (reg:SI LR_REGNUM))
8097 (clobber (reg:SI 4))])]
8098 "use_cmse"
8099 "
8100 {
8101 rtx tmp;
8102 tmp = copy_to_suggested_reg (XEXP (operands[0], 0),
8103 gen_rtx_REG (SImode, 4),
8104 SImode);
8105
8106 operands[0] = replace_equiv_address (operands[0], tmp);
8107 }")
8108
f1039640 8109(define_insn "*call_reg_armv5"
d3373b54 8110 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
cffb2a26 8111 (match_operand 1 "" ""))
8112 (use (match_operand 2 "" ""))
bd5b4116 8113 (clobber (reg:SI LR_REGNUM))]
33ae7c4b 8114 "TARGET_ARM && arm_arch5 && !SIBLING_CALL_P (insn)"
f1039640 8115 "blx%?\\t%0"
8116 [(set_attr "type" "call")]
8117)
8118
8119(define_insn "*call_reg_arm"
8120 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
8121 (match_operand 1 "" ""))
8122 (use (match_operand 2 "" ""))
8123 (clobber (reg:SI LR_REGNUM))]
33ae7c4b 8124 "TARGET_ARM && !arm_arch5 && !SIBLING_CALL_P (insn)"
9c08d1fa 8125 "*
5565501b 8126 return output_call (operands);
cffb2a26 8127 "
8128 ;; length is worst case, normally it is only two
8129 [(set_attr "length" "12")
8130 (set_attr "type" "call")]
8131)
9c08d1fa 8132
89504fc1 8133
d3373b54 8134(define_expand "call_value"
e0698af7 8135 [(parallel [(set (match_operand 0 "" "")
8136 (call (match_operand 1 "memory_operand" "")
8137 (match_operand 2 "general_operand" "")))
cffb2a26 8138 (use (match_operand 3 "" ""))
bd5b4116 8139 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 8140 "TARGET_EITHER"
6c4c2133 8141 "
8142 {
bac7fc85 8143 rtx pat, callee;
2d3a01a7 8144 tree addr = MEM_EXPR (operands[1]);
bbe777ea 8145
8146 /* In an untyped call, we can get NULL for operand 2. */
8147 if (operands[3] == 0)
8148 operands[3] = const0_rtx;
8149
de55252a 8150 /* Decide if we should generate indirect calls by loading the
8151 32-bit address of the callee into a register before performing the
8152 branch and link. */
8153 callee = XEXP (operands[1], 0);
8154 if (GET_CODE (callee) == SYMBOL_REF
8155 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
8156 : !REG_P (callee))
78fe751b 8157 XEXP (operands[1], 0) = force_reg (Pmode, callee);
bac7fc85 8158
2d3a01a7 8159 if (detect_cmse_nonsecure_call (addr))
8160 {
8161 pat = gen_nonsecure_call_value_internal (operands[0], operands[1],
8162 operands[2], operands[3]);
8163 emit_call_insn (pat);
8164 }
8165 else
8166 {
8167 pat = gen_call_value_internal (operands[0], operands[1],
8168 operands[2], operands[3]);
8169 arm_emit_call_insn (pat, XEXP (operands[1], 0), false);
8170 }
bac7fc85 8171 DONE;
6c4c2133 8172 }"
8173)
d3373b54 8174
bac7fc85 8175(define_expand "call_value_internal"
8176 [(parallel [(set (match_operand 0 "" "")
8177 (call (match_operand 1 "memory_operand" "")
8178 (match_operand 2 "general_operand" "")))
8179 (use (match_operand 3 "" ""))
8180 (clobber (reg:SI LR_REGNUM))])])
8181
2d3a01a7 8182(define_expand "nonsecure_call_value_internal"
8183 [(parallel [(set (match_operand 0 "" "")
8184 (call (unspec:SI [(match_operand 1 "memory_operand" "")]
8185 UNSPEC_NONSECURE_MEM)
8186 (match_operand 2 "general_operand" "")))
8187 (use (match_operand 3 "" ""))
8188 (clobber (reg:SI LR_REGNUM))
8189 (clobber (reg:SI 4))])]
8190 "use_cmse"
8191 "
8192 {
8193 rtx tmp;
8194 tmp = copy_to_suggested_reg (XEXP (operands[1], 0),
8195 gen_rtx_REG (SImode, 4),
8196 SImode);
8197
8198 operands[1] = replace_equiv_address (operands[1], tmp);
8199 }")
8200
f1039640 8201(define_insn "*call_value_reg_armv5"
27ed6835 8202 [(set (match_operand 0 "" "")
755eb2b4 8203 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
cffb2a26 8204 (match_operand 2 "" "")))
bbe777ea 8205 (use (match_operand 3 "" ""))
bd5b4116 8206 (clobber (reg:SI LR_REGNUM))]
33ae7c4b 8207 "TARGET_ARM && arm_arch5 && !SIBLING_CALL_P (insn)"
f1039640 8208 "blx%?\\t%1"
8209 [(set_attr "type" "call")]
8210)
8211
8212(define_insn "*call_value_reg_arm"
8213 [(set (match_operand 0 "" "")
8214 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
8215 (match_operand 2 "" "")))
8216 (use (match_operand 3 "" ""))
8217 (clobber (reg:SI LR_REGNUM))]
33ae7c4b 8218 "TARGET_ARM && !arm_arch5 && !SIBLING_CALL_P (insn)"
9c08d1fa 8219 "*
215b30b3 8220 return output_call (&operands[1]);
cffb2a26 8221 "
8222 [(set_attr "length" "12")
8223 (set_attr "type" "call")]
8224)
9c08d1fa 8225
9c08d1fa 8226;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
8227;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
8228
f7fbdd4a 8229(define_insn "*call_symbol"
27ed6835 8230 [(call (mem:SI (match_operand:SI 0 "" ""))
cffb2a26 8231 (match_operand 1 "" ""))
bbe777ea 8232 (use (match_operand 2 "" ""))
bd5b4116 8233 (clobber (reg:SI LR_REGNUM))]
d68c2c10 8234 "TARGET_32BIT
33ae7c4b 8235 && !SIBLING_CALL_P (insn)
cffb2a26 8236 && (GET_CODE (operands[0]) == SYMBOL_REF)
de55252a 8237 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
6ebaa29d 8238 "*
8239 {
95f1e0d1 8240 rtx op = operands[0];
8241
8242 /* Switch mode now when possible. */
8243 if (SYMBOL_REF_DECL (op) && !TREE_PUBLIC (SYMBOL_REF_DECL (op))
8244 && arm_arch5 && arm_change_mode_p (SYMBOL_REF_DECL (op)))
8245 return NEED_PLT_RELOC ? \"blx%?\\t%a0(PLT)\" : \"blx%?\\t(%a0)\";
8246
55c1e470 8247 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
6ebaa29d 8248 }"
cffb2a26 8249 [(set_attr "type" "call")]
8250)
9c08d1fa 8251
f7fbdd4a 8252(define_insn "*call_value_symbol"
ccd90aaa 8253 [(set (match_operand 0 "" "")
27ed6835 8254 (call (mem:SI (match_operand:SI 1 "" ""))
dd6d7504 8255 (match_operand:SI 2 "" "")))
bbe777ea 8256 (use (match_operand 3 "" ""))
bd5b4116 8257 (clobber (reg:SI LR_REGNUM))]
d68c2c10 8258 "TARGET_32BIT
33ae7c4b 8259 && !SIBLING_CALL_P (insn)
cffb2a26 8260 && (GET_CODE (operands[1]) == SYMBOL_REF)
de55252a 8261 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
6ebaa29d 8262 "*
8263 {
95f1e0d1 8264 rtx op = operands[1];
8265
8266 /* Switch mode now when possible. */
8267 if (SYMBOL_REF_DECL (op) && !TREE_PUBLIC (SYMBOL_REF_DECL (op))
8268 && arm_arch5 && arm_change_mode_p (SYMBOL_REF_DECL (op)))
3f6b66fa 8269 return NEED_PLT_RELOC ? \"blx%?\\t%a1(PLT)\" : \"blx%?\\t(%a1)\";
95f1e0d1 8270
55c1e470 8271 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
6ebaa29d 8272 }"
cffb2a26 8273 [(set_attr "type" "call")]
8274)
8275
ca373797 8276(define_expand "sibcall_internal"
8277 [(parallel [(call (match_operand 0 "memory_operand" "")
8278 (match_operand 1 "general_operand" ""))
8279 (return)
8280 (use (match_operand 2 "" ""))])])
8281
1c494086 8282;; We may also be able to do sibcalls for Thumb, but it's much harder...
8283(define_expand "sibcall"
8284 [(parallel [(call (match_operand 0 "memory_operand" "")
8285 (match_operand 1 "general_operand" ""))
2ba80634 8286 (return)
8287 (use (match_operand 2 "" ""))])]
d68c2c10 8288 "TARGET_32BIT"
1c494086 8289 "
8290 {
ca373797 8291 rtx pat;
8292
3112c3f7 8293 if ((!REG_P (XEXP (operands[0], 0))
8294 && GET_CODE (XEXP (operands[0], 0)) != SYMBOL_REF)
8295 || (GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
8296 && arm_is_long_call_p (SYMBOL_REF_DECL (XEXP (operands[0], 0)))))
33ae7c4b 8297 XEXP (operands[0], 0) = force_reg (SImode, XEXP (operands[0], 0));
8298
1c494086 8299 if (operands[2] == NULL_RTX)
8300 operands[2] = const0_rtx;
ca373797 8301
8302 pat = gen_sibcall_internal (operands[0], operands[1], operands[2]);
8303 arm_emit_call_insn (pat, operands[0], true);
8304 DONE;
1c494086 8305 }"
8306)
8307
ca373797 8308(define_expand "sibcall_value_internal"
8309 [(parallel [(set (match_operand 0 "" "")
8310 (call (match_operand 1 "memory_operand" "")
8311 (match_operand 2 "general_operand" "")))
8312 (return)
8313 (use (match_operand 3 "" ""))])])
8314
1c494086 8315(define_expand "sibcall_value"
ccd90aaa 8316 [(parallel [(set (match_operand 0 "" "")
1c494086 8317 (call (match_operand 1 "memory_operand" "")
8318 (match_operand 2 "general_operand" "")))
2ba80634 8319 (return)
8320 (use (match_operand 3 "" ""))])]
d68c2c10 8321 "TARGET_32BIT"
1c494086 8322 "
8323 {
ca373797 8324 rtx pat;
8325
3112c3f7 8326 if ((!REG_P (XEXP (operands[1], 0))
8327 && GET_CODE (XEXP (operands[1], 0)) != SYMBOL_REF)
8328 || (GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
8329 && arm_is_long_call_p (SYMBOL_REF_DECL (XEXP (operands[1], 0)))))
33ae7c4b 8330 XEXP (operands[1], 0) = force_reg (SImode, XEXP (operands[1], 0));
8331
1c494086 8332 if (operands[3] == NULL_RTX)
8333 operands[3] = const0_rtx;
ca373797 8334
8335 pat = gen_sibcall_value_internal (operands[0], operands[1],
8336 operands[2], operands[3]);
8337 arm_emit_call_insn (pat, operands[1], true);
8338 DONE;
1c494086 8339 }"
8340)
8341
8342(define_insn "*sibcall_insn"
84ce8e5c 8343 [(call (mem:SI (match_operand:SI 0 "call_insn_operand" "Cs, US"))
1c494086 8344 (match_operand 1 "" ""))
2ba80634 8345 (return)
8346 (use (match_operand 2 "" ""))]
33ae7c4b 8347 "TARGET_32BIT && SIBLING_CALL_P (insn)"
1c494086 8348 "*
33ae7c4b 8349 if (which_alternative == 1)
8350 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
8351 else
8352 {
8353 if (arm_arch5 || arm_arch4t)
947d113e 8354 return \"bx%?\\t%0\\t%@ indirect register sibling call\";
33ae7c4b 8355 else
8356 return \"mov%?\\t%|pc, %0\\t%@ indirect register sibling call\";
8357 }
1c494086 8358 "
8359 [(set_attr "type" "call")]
8360)
8361
8362(define_insn "*sibcall_value_insn"
84ce8e5c 8363 [(set (match_operand 0 "" "")
8364 (call (mem:SI (match_operand:SI 1 "call_insn_operand" "Cs,US"))
1c494086 8365 (match_operand 2 "" "")))
2ba80634 8366 (return)
8367 (use (match_operand 3 "" ""))]
33ae7c4b 8368 "TARGET_32BIT && SIBLING_CALL_P (insn)"
1c494086 8369 "*
33ae7c4b 8370 if (which_alternative == 1)
8371 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
8372 else
8373 {
8374 if (arm_arch5 || arm_arch4t)
84ce8e5c 8375 return \"bx%?\\t%1\";
33ae7c4b 8376 else
8377 return \"mov%?\\t%|pc, %1\\t@ indirect sibling call \";
8378 }
1c494086 8379 "
8380 [(set_attr "type" "call")]
8381)
8382
0686440e 8383(define_expand "<return_str>return"
9b23f0a7 8384 [(RETURNS)]
8cba51a5 8385 "(TARGET_ARM || (TARGET_THUMB2
8386 && ARM_FUNC_TYPE (arm_current_func_type ()) == ARM_FT_NORMAL
8387 && !IS_STACKALIGN (arm_current_func_type ())))
0686440e 8388 <return_cond_false>"
8cba51a5 8389 "
8390 {
8391 if (TARGET_THUMB2)
8392 {
0686440e 8393 thumb2_expand_return (<return_simple_p>);
8cba51a5 8394 DONE;
8395 }
8396 }
8397 "
8398)
d68c2c10 8399
9c08d1fa 8400;; Often the return insn will be the same as loading from memory, so set attr
d68c2c10 8401(define_insn "*arm_return"
9c08d1fa 8402 [(return)]
cffb2a26 8403 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
9c08d1fa 8404 "*
9c08d1fa 8405 {
cffb2a26 8406 if (arm_ccfsm_state == 2)
8407 {
8408 arm_ccfsm_state += 2;
8409 return \"\";
8410 }
e2549f81 8411 return output_return_instruction (const_true_rtx, true, false, false);
cffb2a26 8412 }"
a2cd141b 8413 [(set_attr "type" "load1")
755eb2b4 8414 (set_attr "length" "12")
0d66636f 8415 (set_attr "predicable" "yes")]
cffb2a26 8416)
9c08d1fa 8417
0686440e 8418(define_insn "*cond_<return_str>return"
9c08d1fa 8419 [(set (pc)
8fa3ba89 8420 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 8421 [(match_operand 1 "cc_register" "") (const_int 0)])
9b23f0a7 8422 (RETURNS)
9c08d1fa 8423 (pc)))]
0686440e 8424 "TARGET_ARM <return_cond_true>"
9c08d1fa 8425 "*
8fa3ba89 8426 {
8427 if (arm_ccfsm_state == 2)
8428 {
8429 arm_ccfsm_state += 2;
8430 return \"\";
8431 }
0686440e 8432 return output_return_instruction (operands[0], true, false,
8433 <return_simple_p>);
8fa3ba89 8434 }"
8435 [(set_attr "conds" "use")
755eb2b4 8436 (set_attr "length" "12")
a2cd141b 8437 (set_attr "type" "load1")]
8fa3ba89 8438)
9c08d1fa 8439
0686440e 8440(define_insn "*cond_<return_str>return_inverted"
9c08d1fa 8441 [(set (pc)
8fa3ba89 8442 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 8443 [(match_operand 1 "cc_register" "") (const_int 0)])
9c08d1fa 8444 (pc)
9b23f0a7 8445 (RETURNS)))]
0686440e 8446 "TARGET_ARM <return_cond_true>"
9c08d1fa 8447 "*
8fa3ba89 8448 {
8449 if (arm_ccfsm_state == 2)
8450 {
8451 arm_ccfsm_state += 2;
8452 return \"\";
8453 }
0686440e 8454 return output_return_instruction (operands[0], true, true,
8455 <return_simple_p>);
8fa3ba89 8456 }"
8457 [(set_attr "conds" "use")
37a1317b 8458 (set_attr "length" "12")
a2cd141b 8459 (set_attr "type" "load1")]
8fa3ba89 8460)
9c08d1fa 8461
e2549f81 8462(define_insn "*arm_simple_return"
8463 [(simple_return)]
8464 "TARGET_ARM"
8465 "*
8466 {
8467 if (arm_ccfsm_state == 2)
8468 {
8469 arm_ccfsm_state += 2;
8470 return \"\";
8471 }
8472 return output_return_instruction (const_true_rtx, true, false, true);
8473 }"
8474 [(set_attr "type" "branch")
8475 (set_attr "length" "4")
8476 (set_attr "predicable" "yes")]
8477)
8478
68121397 8479;; Generate a sequence of instructions to determine if the processor is
8480;; in 26-bit or 32-bit mode, and return the appropriate return address
8481;; mask.
8482
8483(define_expand "return_addr_mask"
8484 [(set (match_dup 1)
8485 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8486 (const_int 0)))
8487 (set (match_operand:SI 0 "s_register_operand" "")
8488 (if_then_else:SI (eq (match_dup 1) (const_int 0))
8489 (const_int -1)
8490 (const_int 67108860)))] ; 0x03fffffc
8491 "TARGET_ARM"
8492 "
62eddbd4 8493 operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
68121397 8494 ")
8495
8496(define_insn "*check_arch2"
8497 [(set (match_operand:CC_NOOV 0 "cc_register" "")
8498 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8499 (const_int 0)))]
8500 "TARGET_ARM"
8501 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
8502 [(set_attr "length" "8")
1b7da4ac 8503 (set_attr "conds" "set")
8504 (set_attr "type" "multiple")]
68121397 8505)
8506
9c08d1fa 8507;; Call subroutine returning any type.
8508
8509(define_expand "untyped_call"
8510 [(parallel [(call (match_operand 0 "" "")
8511 (const_int 0))
8512 (match_operand 1 "" "")
8513 (match_operand 2 "" "")])]
ccd90aaa 8514 "TARGET_EITHER"
9c08d1fa 8515 "
215b30b3 8516 {
8517 int i;
ccd90aaa 8518 rtx par = gen_rtx_PARALLEL (VOIDmode,
8519 rtvec_alloc (XVECLEN (operands[2], 0)));
8520 rtx addr = gen_reg_rtx (Pmode);
8521 rtx mem;
8522 int size = 0;
9c08d1fa 8523
ccd90aaa 8524 emit_move_insn (addr, XEXP (operands[1], 0));
8525 mem = change_address (operands[1], BLKmode, addr);
9c08d1fa 8526
215b30b3 8527 for (i = 0; i < XVECLEN (operands[2], 0); i++)
8528 {
ccd90aaa 8529 rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
9c08d1fa 8530
ccd90aaa 8531 /* Default code only uses r0 as a return value, but we could
8532 be using anything up to 4 registers. */
8533 if (REGNO (src) == R0_REGNUM)
8534 src = gen_rtx_REG (TImode, R0_REGNUM);
8535
8536 XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
8537 GEN_INT (size));
8538 size += GET_MODE_SIZE (GET_MODE (src));
8539 }
8540
7f265a08 8541 emit_call_insn (gen_call_value (par, operands[0], const0_rtx, NULL));
ccd90aaa 8542
8543 size = 0;
8544
8545 for (i = 0; i < XVECLEN (par, 0); i++)
8546 {
8547 HOST_WIDE_INT offset = 0;
8548 rtx reg = XEXP (XVECEXP (par, 0, i), 0);
8549
8550 if (size != 0)
29c05e22 8551 emit_move_insn (addr, plus_constant (Pmode, addr, size));
ccd90aaa 8552
8553 mem = change_address (mem, GET_MODE (reg), NULL);
8554 if (REGNO (reg) == R0_REGNUM)
8555 {
8556 /* On thumb we have to use a write-back instruction. */
320ea44d 8557 emit_insn (arm_gen_store_multiple (arm_regs_in_sequence, 4, addr,
8558 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
ccd90aaa 8559 size = TARGET_ARM ? 16 : 0;
8560 }
8561 else
8562 {
8563 emit_move_insn (mem, reg);
8564 size = GET_MODE_SIZE (GET_MODE (reg));
8565 }
215b30b3 8566 }
9c08d1fa 8567
215b30b3 8568 /* The optimizer does not know that the call sets the function value
8569 registers we stored in the result block. We avoid problems by
8570 claiming that all hard registers are used and clobbered at this
8571 point. */
8572 emit_insn (gen_blockage ());
8573
8574 DONE;
8575 }"
8576)
9c08d1fa 8577
ccd90aaa 8578(define_expand "untyped_return"
8579 [(match_operand:BLK 0 "memory_operand" "")
8580 (match_operand 1 "" "")]
8581 "TARGET_EITHER"
8582 "
8583 {
8584 int i;
8585 rtx addr = gen_reg_rtx (Pmode);
8586 rtx mem;
8587 int size = 0;
8588
8589 emit_move_insn (addr, XEXP (operands[0], 0));
8590 mem = change_address (operands[0], BLKmode, addr);
8591
8592 for (i = 0; i < XVECLEN (operands[1], 0); i++)
8593 {
8594 HOST_WIDE_INT offset = 0;
8595 rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
8596
8597 if (size != 0)
29c05e22 8598 emit_move_insn (addr, plus_constant (Pmode, addr, size));
ccd90aaa 8599
8600 mem = change_address (mem, GET_MODE (reg), NULL);
8601 if (REGNO (reg) == R0_REGNUM)
8602 {
8603 /* On thumb we have to use a write-back instruction. */
320ea44d 8604 emit_insn (arm_gen_load_multiple (arm_regs_in_sequence, 4, addr,
8605 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
ccd90aaa 8606 size = TARGET_ARM ? 16 : 0;
8607 }
8608 else
8609 {
8610 emit_move_insn (reg, mem);
8611 size = GET_MODE_SIZE (GET_MODE (reg));
8612 }
8613 }
8614
8615 /* Emit USE insns before the return. */
8616 for (i = 0; i < XVECLEN (operands[1], 0); i++)
18b42941 8617 emit_use (SET_DEST (XVECEXP (operands[1], 0, i)));
ccd90aaa 8618
8619 /* Construct the return. */
8620 expand_naked_return ();
8621
8622 DONE;
8623 }"
8624)
8625
9c08d1fa 8626;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
8627;; all of memory. This blocks insns from being moved across this point.
8628
8629(define_insn "blockage"
e1159bbe 8630 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
cffb2a26 8631 "TARGET_EITHER"
9c08d1fa 8632 ""
cffb2a26 8633 [(set_attr "length" "0")
8634 (set_attr "type" "block")]
8635)
9c08d1fa 8636
706dca65 8637(define_insn "probe_stack"
f8570abe 8638 [(set (match_operand:SI 0 "memory_operand" "=m")
8639 (unspec:SI [(const_int 0)] UNSPEC_PROBE_STACK))]
706dca65 8640 "TARGET_32BIT"
154ae8e6 8641 "str%?\\tr0, %0"
706dca65 8642 [(set_attr "type" "store1")
8643 (set_attr "predicable" "yes")]
8644)
8645
8646(define_insn "probe_stack_range"
8647 [(set (match_operand:SI 0 "register_operand" "=r")
8648 (unspec_volatile:SI [(match_operand:SI 1 "register_operand" "0")
8649 (match_operand:SI 2 "register_operand" "r")]
dd8aabc9 8650 VUNSPEC_PROBE_STACK_RANGE))]
706dca65 8651 "TARGET_32BIT"
8652{
8653 return output_probe_stack_range (operands[0], operands[2]);
8654}
8655 [(set_attr "type" "multiple")
8656 (set_attr "conds" "clob")]
8657)
8658
f7fbdd4a 8659(define_expand "casesi"
8660 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
aea4c774 8661 (match_operand:SI 1 "const_int_operand" "") ; lower bound
8662 (match_operand:SI 2 "const_int_operand" "") ; total range
f7fbdd4a 8663 (match_operand:SI 3 "" "") ; table label
8664 (match_operand:SI 4 "" "")] ; Out of range label
9753b549 8665 "(TARGET_32BIT || optimize_size || flag_pic) && !target_pure_code"
f7fbdd4a 8666 "
215b30b3 8667 {
e6ac8414 8668 enum insn_code code;
215b30b3 8669 if (operands[1] != const0_rtx)
8670 {
e6ac8414 8671 rtx reg = gen_reg_rtx (SImode);
f7fbdd4a 8672
215b30b3 8673 emit_insn (gen_addsi3 (reg, operands[0],
d022fa24 8674 gen_int_mode (-INTVAL (operands[1]),
8675 SImode)));
215b30b3 8676 operands[0] = reg;
8677 }
9c08d1fa 8678
25f905c2 8679 if (TARGET_ARM)
e6ac8414 8680 code = CODE_FOR_arm_casesi_internal;
3db2019b 8681 else if (TARGET_THUMB1)
e6ac8414 8682 code = CODE_FOR_thumb1_casesi_internal_pic;
25f905c2 8683 else if (flag_pic)
e6ac8414 8684 code = CODE_FOR_thumb2_casesi_internal_pic;
25f905c2 8685 else
e6ac8414 8686 code = CODE_FOR_thumb2_casesi_internal;
8687
8688 if (!insn_data[(int) code].operand[1].predicate(operands[2], SImode))
8689 operands[2] = force_reg (SImode, operands[2]);
8690
8691 emit_jump_insn (GEN_FCN ((int) code) (operands[0], operands[2],
8692 operands[3], operands[4]));
215b30b3 8693 DONE;
8694 }"
8695)
f7fbdd4a 8696
f082f1c4 8697;; The USE in this pattern is needed to tell flow analysis that this is
8698;; a CASESI insn. It has no other purpose.
25f905c2 8699(define_insn "arm_casesi_internal"
f082f1c4 8700 [(parallel [(set (pc)
8701 (if_then_else
8702 (leu (match_operand:SI 0 "s_register_operand" "r")
8703 (match_operand:SI 1 "arm_rhs_operand" "rI"))
8704 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
8705 (label_ref (match_operand 2 "" ""))))
8706 (label_ref (match_operand 3 "" ""))))
bd5b4116 8707 (clobber (reg:CC CC_REGNUM))
f082f1c4 8708 (use (label_ref (match_dup 2)))])]
cffb2a26 8709 "TARGET_ARM"
f7fbdd4a 8710 "*
0d66636f 8711 if (flag_pic)
8712 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
8713 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
8714 "
8715 [(set_attr "conds" "clob")
1b7da4ac 8716 (set_attr "length" "12")
8717 (set_attr "type" "multiple")]
0d66636f 8718)
9c08d1fa 8719
cffb2a26 8720(define_expand "indirect_jump"
9c08d1fa 8721 [(set (pc)
cffb2a26 8722 (match_operand:SI 0 "s_register_operand" ""))]
8723 "TARGET_EITHER"
25f905c2 8724 "
8725 /* Thumb-2 doesn't have mov pc, reg. Explicitly set the low bit of the
8726 address and use bx. */
8727 if (TARGET_THUMB2)
8728 {
8729 rtx tmp;
8730 tmp = gen_reg_rtx (SImode);
8731 emit_insn (gen_iorsi3 (tmp, operands[0], GEN_INT(1)));
8732 operands[0] = tmp;
8733 }
8734 "
cffb2a26 8735)
8736
f1039640 8737;; NB Never uses BX.
cffb2a26 8738(define_insn "*arm_indirect_jump"
8739 [(set (pc)
8740 (match_operand:SI 0 "s_register_operand" "r"))]
8741 "TARGET_ARM"
8742 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
1b7da4ac 8743 [(set_attr "predicable" "yes")
8744 (set_attr "type" "branch")]
cffb2a26 8745)
9c08d1fa 8746
f7fbdd4a 8747(define_insn "*load_indirect_jump"
9c08d1fa 8748 [(set (pc)
8749 (match_operand:SI 0 "memory_operand" "m"))]
cffb2a26 8750 "TARGET_ARM"
8751 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
a2cd141b 8752 [(set_attr "type" "load1")
61a2d04c 8753 (set_attr "pool_range" "4096")
8754 (set_attr "neg_pool_range" "4084")
0d66636f 8755 (set_attr "predicable" "yes")]
cffb2a26 8756)
8757
9c08d1fa 8758\f
8759;; Misc insns
8760
8761(define_insn "nop"
8762 [(const_int 0)]
cffb2a26 8763 "TARGET_EITHER"
3ef90e77 8764 "nop"
cffb2a26 8765 [(set (attr "length")
8766 (if_then_else (eq_attr "is_thumb" "yes")
8767 (const_int 2)
1b7da4ac 8768 (const_int 4)))
8769 (set_attr "type" "mov_reg")]
cffb2a26 8770)
8771
ad9d4399 8772(define_insn "trap"
8773 [(trap_if (const_int 1) (const_int 0))]
8774 ""
8775 "*
8776 if (TARGET_ARM)
8777 return \".inst\\t0xe7f000f0\";
8778 else
8779 return \".inst\\t0xdeff\";
8780 "
8781 [(set (attr "length")
8782 (if_then_else (eq_attr "is_thumb" "yes")
8783 (const_int 2)
8784 (const_int 4)))
8785 (set_attr "type" "trap")
8786 (set_attr "conds" "unconditional")]
8787)
8788
9c08d1fa 8789\f
8790;; Patterns to allow combination of arithmetic, cond code and shifts
8791
0abea32c 8792(define_insn "*<arith_shift_insn>_multsi"
8793 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9b23f0a7 8794 (SHIFTABLE_OPS:SI
0abea32c 8795 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
8796 (match_operand:SI 3 "power_of_two_operand" ""))
8797 (match_operand:SI 1 "s_register_operand" "rk,<t2_binop0>")))]
d5d4dc8d 8798 "TARGET_32BIT"
0abea32c 8799 "<arith_shift_insn>%?\\t%0, %1, %2, lsl %b3"
8800 [(set_attr "predicable" "yes")
8801 (set_attr "predicable_short_it" "no")
753d9835 8802 (set_attr "shift" "2")
0abea32c 8803 (set_attr "arch" "a,t2")
8804 (set_attr "type" "alu_shift_imm")])
8805
8806(define_insn "*<arith_shift_insn>_shiftsi"
8807 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9b23f0a7 8808 (SHIFTABLE_OPS:SI
0abea32c 8809 (match_operator:SI 2 "shift_nomul_operator"
8810 [(match_operand:SI 3 "s_register_operand" "r,r,r")
8811 (match_operand:SI 4 "shift_amount_operand" "M,M,r")])
8812 (match_operand:SI 1 "s_register_operand" "rk,<t2_binop0>,rk")))]
a021b821 8813 "TARGET_32BIT && GET_CODE (operands[2]) != MULT"
0abea32c 8814 "<arith_shift_insn>%?\\t%0, %1, %3%S2"
344495ea 8815 [(set_attr "predicable" "yes")
74ef923b 8816 (set_attr "predicable_short_it" "no")
753d9835 8817 (set_attr "shift" "3")
0abea32c 8818 (set_attr "arch" "a,t2,a")
8819 (set_attr "type" "alu_shift_imm,alu_shift_imm,alu_shift_reg")])
9c08d1fa 8820
d7863cfe 8821(define_split
8822 [(set (match_operand:SI 0 "s_register_operand" "")
8823 (match_operator:SI 1 "shiftable_operator"
8824 [(match_operator:SI 2 "shiftable_operator"
8825 [(match_operator:SI 3 "shift_operator"
8826 [(match_operand:SI 4 "s_register_operand" "")
8827 (match_operand:SI 5 "reg_or_int_operand" "")])
8828 (match_operand:SI 6 "s_register_operand" "")])
8829 (match_operand:SI 7 "arm_rhs_operand" "")]))
8830 (clobber (match_operand:SI 8 "s_register_operand" ""))]
d5d4dc8d 8831 "TARGET_32BIT"
d7863cfe 8832 [(set (match_dup 8)
8833 (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8834 (match_dup 6)]))
8835 (set (match_dup 0)
8836 (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
8837 "")
8838
f7fbdd4a 8839(define_insn "*arith_shiftsi_compare0"
bd5b4116 8840 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 8841 (compare:CC_NOOV
8842 (match_operator:SI 1 "shiftable_operator"
8843 [(match_operator:SI 3 "shift_operator"
8844 [(match_operand:SI 4 "s_register_operand" "r,r")
8845 (match_operand:SI 5 "shift_amount_operand" "M,r")])
8846 (match_operand:SI 2 "s_register_operand" "r,r")])
8847 (const_int 0)))
8848 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 8849 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8850 (match_dup 2)]))]
d5d4dc8d 8851 "TARGET_32BIT"
3ef90e77 8852 "%i1s%?\\t%0, %2, %4%S3"
344495ea 8853 [(set_attr "conds" "set")
331beb1a 8854 (set_attr "shift" "4")
d5d4dc8d 8855 (set_attr "arch" "32,a")
d82e788e 8856 (set_attr "type" "alus_shift_imm,alus_shift_reg")])
9c08d1fa 8857
f7fbdd4a 8858(define_insn "*arith_shiftsi_compare0_scratch"
bd5b4116 8859 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 8860 (compare:CC_NOOV
8861 (match_operator:SI 1 "shiftable_operator"
8862 [(match_operator:SI 3 "shift_operator"
8863 [(match_operand:SI 4 "s_register_operand" "r,r")
8864 (match_operand:SI 5 "shift_amount_operand" "M,r")])
8865 (match_operand:SI 2 "s_register_operand" "r,r")])
8866 (const_int 0)))
8867 (clobber (match_scratch:SI 0 "=r,r"))]
8868 "TARGET_32BIT"
3ef90e77 8869 "%i1s%?\\t%0, %2, %4%S3"
344495ea 8870 [(set_attr "conds" "set")
331beb1a 8871 (set_attr "shift" "4")
d5d4dc8d 8872 (set_attr "arch" "32,a")
d82e788e 8873 (set_attr "type" "alus_shift_imm,alus_shift_reg")])
9c08d1fa 8874
f7fbdd4a 8875(define_insn "*sub_shiftsi"
d5d4dc8d 8876 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8877 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
9c08d1fa 8878 (match_operator:SI 2 "shift_operator"
d5d4dc8d 8879 [(match_operand:SI 3 "s_register_operand" "r,r")
8880 (match_operand:SI 4 "shift_amount_operand" "M,r")])))]
8881 "TARGET_32BIT"
6c4c2133 8882 "sub%?\\t%0, %1, %3%S2"
344495ea 8883 [(set_attr "predicable" "yes")
331beb1a 8884 (set_attr "shift" "3")
d5d4dc8d 8885 (set_attr "arch" "32,a")
d82e788e 8886 (set_attr "type" "alus_shift_imm,alus_shift_reg")])
9c08d1fa 8887
f7fbdd4a 8888(define_insn "*sub_shiftsi_compare0"
bd5b4116 8889 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 8890 (compare:CC_NOOV
d82e788e 8891 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
40dbec34 8892 (match_operator:SI 2 "shift_operator"
d82e788e 8893 [(match_operand:SI 3 "s_register_operand" "r,r,r")
8894 (match_operand:SI 4 "shift_amount_operand" "M,r,M")]))
40dbec34 8895 (const_int 0)))
d82e788e 8896 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
d5d4dc8d 8897 (minus:SI (match_dup 1)
8898 (match_op_dup 2 [(match_dup 3) (match_dup 4)])))]
8899 "TARGET_32BIT"
3ef90e77 8900 "subs%?\\t%0, %1, %3%S2"
344495ea 8901 [(set_attr "conds" "set")
a2cd141b 8902 (set_attr "shift" "3")
d82e788e 8903 (set_attr "arch" "32,a,a")
8904 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
9c08d1fa 8905
f7fbdd4a 8906(define_insn "*sub_shiftsi_compare0_scratch"
bd5b4116 8907 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 8908 (compare:CC_NOOV
d82e788e 8909 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
40dbec34 8910 (match_operator:SI 2 "shift_operator"
d82e788e 8911 [(match_operand:SI 3 "s_register_operand" "r,r,r")
8912 (match_operand:SI 4 "shift_amount_operand" "M,r,M")]))
40dbec34 8913 (const_int 0)))
d82e788e 8914 (clobber (match_scratch:SI 0 "=r,r,r"))]
d5d4dc8d 8915 "TARGET_32BIT"
3ef90e77 8916 "subs%?\\t%0, %1, %3%S2"
344495ea 8917 [(set_attr "conds" "set")
a2cd141b 8918 (set_attr "shift" "3")
d82e788e 8919 (set_attr "arch" "32,a,a")
8920 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
9c08d1fa 8921\f
8922
190efb17 8923(define_insn_and_split "*and_scc"
9c08d1fa 8924 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 8925 (and:SI (match_operator:SI 1 "arm_comparison_operator"
190efb17 8926 [(match_operand 2 "cc_register" "") (const_int 0)])
8927 (match_operand:SI 3 "s_register_operand" "r")))]
cffb2a26 8928 "TARGET_ARM"
190efb17 8929 "#" ; "mov%D1\\t%0, #0\;and%d1\\t%0, %3, #1"
8930 "&& reload_completed"
8931 [(cond_exec (match_dup 5) (set (match_dup 0) (const_int 0)))
8932 (cond_exec (match_dup 4) (set (match_dup 0)
8933 (and:SI (match_dup 3) (const_int 1))))]
8934 {
3754d046 8935 machine_mode mode = GET_MODE (operands[2]);
190efb17 8936 enum rtx_code rc = GET_CODE (operands[1]);
8937
8938 /* Note that operands[4] is the same as operands[1],
8939 but with VOIDmode as the result. */
8940 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
8941 if (mode == CCFPmode || mode == CCFPEmode)
8942 rc = reverse_condition_maybe_unordered (rc);
8943 else
8944 rc = reverse_condition (rc);
8945 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
8946 }
8fa3ba89 8947 [(set_attr "conds" "use")
1b7da4ac 8948 (set_attr "type" "multiple")
8fa3ba89 8949 (set_attr "length" "8")]
8950)
9c08d1fa 8951
190efb17 8952(define_insn_and_split "*ior_scc"
9c08d1fa 8953 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
190efb17 8954 (ior:SI (match_operator:SI 1 "arm_comparison_operator"
8955 [(match_operand 2 "cc_register" "") (const_int 0)])
8956 (match_operand:SI 3 "s_register_operand" "0,?r")))]
cffb2a26 8957 "TARGET_ARM"
e2348bcb 8958 "@
190efb17 8959 orr%d1\\t%0, %3, #1
8960 #"
8961 "&& reload_completed
8962 && REGNO (operands [0]) != REGNO (operands[3])"
8963 ;; && which_alternative == 1
8964 ; mov%D1\\t%0, %3\;orr%d1\\t%0, %3, #1
8965 [(cond_exec (match_dup 5) (set (match_dup 0) (match_dup 3)))
8966 (cond_exec (match_dup 4) (set (match_dup 0)
8967 (ior:SI (match_dup 3) (const_int 1))))]
8968 {
3754d046 8969 machine_mode mode = GET_MODE (operands[2]);
190efb17 8970 enum rtx_code rc = GET_CODE (operands[1]);
8971
8972 /* Note that operands[4] is the same as operands[1],
8973 but with VOIDmode as the result. */
8974 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
8975 if (mode == CCFPmode || mode == CCFPEmode)
8976 rc = reverse_condition_maybe_unordered (rc);
8977 else
8978 rc = reverse_condition (rc);
8979 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
8980 }
8fa3ba89 8981 [(set_attr "conds" "use")
1b7da4ac 8982 (set_attr "length" "4,8")
8983 (set_attr "type" "logic_imm,multiple")]
8fa3ba89 8984)
9c08d1fa 8985
2df9477b 8986; A series of splitters for the compare_scc pattern below. Note that
8987; order is important.
8988(define_split
8989 [(set (match_operand:SI 0 "s_register_operand" "")
8990 (lt:SI (match_operand:SI 1 "s_register_operand" "")
8991 (const_int 0)))
8992 (clobber (reg:CC CC_REGNUM))]
8993 "TARGET_32BIT && reload_completed"
8994 [(set (match_dup 0) (lshiftrt:SI (match_dup 1) (const_int 31)))])
8995
8996(define_split
8997 [(set (match_operand:SI 0 "s_register_operand" "")
8998 (ge:SI (match_operand:SI 1 "s_register_operand" "")
8999 (const_int 0)))
9000 (clobber (reg:CC CC_REGNUM))]
9001 "TARGET_32BIT && reload_completed"
9002 [(set (match_dup 0) (not:SI (match_dup 1)))
9003 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 31)))])
9004
98562479 9005(define_split
9006 [(set (match_operand:SI 0 "s_register_operand" "")
9007 (eq:SI (match_operand:SI 1 "s_register_operand" "")
9008 (const_int 0)))
9009 (clobber (reg:CC CC_REGNUM))]
9010 "arm_arch5 && TARGET_32BIT"
9011 [(set (match_dup 0) (clz:SI (match_dup 1)))
9012 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 5)))]
9013)
9014
2df9477b 9015(define_split
9016 [(set (match_operand:SI 0 "s_register_operand" "")
9017 (eq:SI (match_operand:SI 1 "s_register_operand" "")
9018 (const_int 0)))
9019 (clobber (reg:CC CC_REGNUM))]
9020 "TARGET_32BIT && reload_completed"
9021 [(parallel
080c0b9a 9022 [(set (reg:CC CC_REGNUM)
9023 (compare:CC (const_int 1) (match_dup 1)))
2df9477b 9024 (set (match_dup 0)
9025 (minus:SI (const_int 1) (match_dup 1)))])
080c0b9a 9026 (cond_exec (ltu:CC (reg:CC CC_REGNUM) (const_int 0))
2df9477b 9027 (set (match_dup 0) (const_int 0)))])
9028
9029(define_split
9030 [(set (match_operand:SI 0 "s_register_operand" "")
9031 (ne:SI (match_operand:SI 1 "s_register_operand" "")
9032 (match_operand:SI 2 "const_int_operand" "")))
9033 (clobber (reg:CC CC_REGNUM))]
9034 "TARGET_32BIT && reload_completed"
9035 [(parallel
9036 [(set (reg:CC CC_REGNUM)
9037 (compare:CC (match_dup 1) (match_dup 2)))
9038 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))])
9039 (cond_exec (ne:CC (reg:CC CC_REGNUM) (const_int 0))
9040 (set (match_dup 0) (const_int 1)))]
9041{
9042 operands[3] = GEN_INT (-INTVAL (operands[2]));
9043})
9044
9045(define_split
9046 [(set (match_operand:SI 0 "s_register_operand" "")
9047 (ne:SI (match_operand:SI 1 "s_register_operand" "")
9048 (match_operand:SI 2 "arm_add_operand" "")))
9049 (clobber (reg:CC CC_REGNUM))]
9050 "TARGET_32BIT && reload_completed"
9051 [(parallel
9052 [(set (reg:CC_NOOV CC_REGNUM)
9053 (compare:CC_NOOV (minus:SI (match_dup 1) (match_dup 2))
9054 (const_int 0)))
9055 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
9056 (cond_exec (ne:CC_NOOV (reg:CC_NOOV CC_REGNUM) (const_int 0))
9057 (set (match_dup 0) (const_int 1)))])
9058
9059(define_insn_and_split "*compare_scc"
fd711051 9060 [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts")
8fa3ba89 9061 (match_operator:SI 1 "arm_comparison_operator"
5565501b 9062 [(match_operand:SI 2 "s_register_operand" "r,r")
9063 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
bd5b4116 9064 (clobber (reg:CC CC_REGNUM))]
2df9477b 9065 "TARGET_32BIT"
9066 "#"
9067 "&& reload_completed"
9068 [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 3)))
9069 (cond_exec (match_dup 4) (set (match_dup 0) (const_int 0)))
9070 (cond_exec (match_dup 5) (set (match_dup 0) (const_int 1)))]
9071{
9072 rtx tmp1;
3754d046 9073 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
2df9477b 9074 operands[2], operands[3]);
9075 enum rtx_code rc = GET_CODE (operands[1]);
e2348bcb 9076
2df9477b 9077 tmp1 = gen_rtx_REG (mode, CC_REGNUM);
080c0b9a 9078
2df9477b 9079 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
9080 if (mode == CCFPmode || mode == CCFPEmode)
9081 rc = reverse_condition_maybe_unordered (rc);
9082 else
9083 rc = reverse_condition (rc);
9084 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
1b7da4ac 9085}
9086 [(set_attr "type" "multiple")]
9087)
9c08d1fa 9088
080c0b9a 9089;; Attempt to improve the sequence generated by the compare_scc splitters
9090;; not to use conditional execution.
98562479 9091
9092;; Rd = (eq (reg1) (const_int0)) // ARMv5
9093;; clz Rd, reg1
9094;; lsr Rd, Rd, #5
080c0b9a 9095(define_peephole2
9096 [(set (reg:CC CC_REGNUM)
9097 (compare:CC (match_operand:SI 1 "register_operand" "")
98562479 9098 (const_int 0)))
9099 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
9100 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
9101 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
9102 (set (match_dup 0) (const_int 1)))]
9103 "arm_arch5 && TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)"
9104 [(set (match_dup 0) (clz:SI (match_dup 1)))
9105 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 5)))]
9106)
9107
9108;; Rd = (eq (reg1) (const_int0)) // !ARMv5
9109;; negs Rd, reg1
9110;; adc Rd, Rd, reg1
9111(define_peephole2
9112 [(set (reg:CC CC_REGNUM)
9113 (compare:CC (match_operand:SI 1 "register_operand" "")
9114 (const_int 0)))
080c0b9a 9115 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
9116 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
9117 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
9118 (set (match_dup 0) (const_int 1)))
98562479 9119 (match_scratch:SI 2 "r")]
9120 "TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)"
922b6913 9121 [(parallel
9122 [(set (reg:CC CC_REGNUM)
98562479 9123 (compare:CC (const_int 0) (match_dup 1)))
9124 (set (match_dup 2) (minus:SI (const_int 0) (match_dup 1)))])
9125 (set (match_dup 0)
9126 (plus:SI (plus:SI (match_dup 1) (match_dup 2))
9127 (geu:SI (reg:CC CC_REGNUM) (const_int 0))))]
9128)
9129
31991287 9130;; Rd = (eq (reg1) (reg2/imm)) // ARMv5 and optimising for speed.
98562479 9131;; sub Rd, Reg1, reg2
9132;; clz Rd, Rd
9133;; lsr Rd, Rd, #5
9134(define_peephole2
9135 [(set (reg:CC CC_REGNUM)
9136 (compare:CC (match_operand:SI 1 "register_operand" "")
9137 (match_operand:SI 2 "arm_rhs_operand" "")))
9138 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
9139 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
9140 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
9141 (set (match_dup 0) (const_int 1)))]
31991287 9142 "arm_arch5 && TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)
9143 && !(TARGET_THUMB2 && optimize_insn_for_size_p ())"
98562479 9144 [(set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))
9145 (set (match_dup 0) (clz:SI (match_dup 0)))
9146 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 5)))]
9147)
9148
9149
31991287 9150;; Rd = (eq (reg1) (reg2)) // ! ARMv5 or optimising for size.
98562479 9151;; sub T1, Reg1, reg2
9152;; negs Rd, T1
9153;; adc Rd, Rd, T1
9154(define_peephole2
9155 [(set (reg:CC CC_REGNUM)
9156 (compare:CC (match_operand:SI 1 "register_operand" "")
9157 (match_operand:SI 2 "arm_rhs_operand" "")))
9158 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
9159 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
9160 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
9161 (set (match_dup 0) (const_int 1)))
9162 (match_scratch:SI 3 "r")]
9163 "TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)"
31991287 9164 [(set (match_dup 3) (match_dup 4))
080c0b9a 9165 (parallel
9166 [(set (reg:CC CC_REGNUM)
9167 (compare:CC (const_int 0) (match_dup 3)))
9168 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 3)))])
98562479 9169 (set (match_dup 0)
9170 (plus:SI (plus:SI (match_dup 0) (match_dup 3))
9171 (geu:SI (reg:CC CC_REGNUM) (const_int 0))))]
31991287 9172 "
9173 if (CONST_INT_P (operands[2]))
9174 operands[4] = plus_constant (SImode, operands[1], -INTVAL (operands[2]));
9175 else
9176 operands[4] = gen_rtx_MINUS (SImode, operands[1], operands[2]);
9177 ")
080c0b9a 9178
f7fbdd4a 9179(define_insn "*cond_move"
9c08d1fa 9180 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
aea4c774 9181 (if_then_else:SI (match_operator 3 "equality_operator"
8fa3ba89 9182 [(match_operator 4 "arm_comparison_operator"
8a18b90c 9183 [(match_operand 5 "cc_register" "") (const_int 0)])
aea4c774 9184 (const_int 0)])
9185 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9186 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
cffb2a26 9187 "TARGET_ARM"
9c08d1fa 9188 "*
8fa3ba89 9189 if (GET_CODE (operands[3]) == NE)
9190 {
9191 if (which_alternative != 1)
9192 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
9193 if (which_alternative != 0)
9194 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
9195 return \"\";
9196 }
9197 if (which_alternative != 0)
9198 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9199 if (which_alternative != 1)
9200 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
9201 return \"\";
9202 "
9203 [(set_attr "conds" "use")
282b4c75 9204 (set_attr_alternative "type"
9205 [(if_then_else (match_operand 2 "const_int_operand" "")
9206 (const_string "mov_imm")
9207 (const_string "mov_reg"))
9208 (if_then_else (match_operand 1 "const_int_operand" "")
9209 (const_string "mov_imm")
9210 (const_string "mov_reg"))
9211 (const_string "multiple")])
8fa3ba89 9212 (set_attr "length" "4,4,8")]
9213)
9c08d1fa 9214
f7fbdd4a 9215(define_insn "*cond_arith"
9c08d1fa 9216 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9217 (match_operator:SI 5 "shiftable_operator"
8fa3ba89 9218 [(match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 9219 [(match_operand:SI 2 "s_register_operand" "r,r")
9220 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
9221 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 9222 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9223 "TARGET_ARM"
9c08d1fa 9224 "*
8fa3ba89 9225 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
9226 return \"%i5\\t%0, %1, %2, lsr #31\";
40dbec34 9227
8fa3ba89 9228 output_asm_insn (\"cmp\\t%2, %3\", operands);
9229 if (GET_CODE (operands[5]) == AND)
9230 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
9231 else if (GET_CODE (operands[5]) == MINUS)
9232 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
9233 else if (which_alternative != 0)
9234 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9235 return \"%i5%d4\\t%0, %1, #1\";
9236 "
9237 [(set_attr "conds" "clob")
1b7da4ac 9238 (set_attr "length" "12")
9239 (set_attr "type" "multiple")]
8fa3ba89 9240)
9c08d1fa 9241
f7fbdd4a 9242(define_insn "*cond_sub"
9c08d1fa 9243 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9244 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8fa3ba89 9245 (match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 9246 [(match_operand:SI 2 "s_register_operand" "r,r")
9247 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 9248 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9249 "TARGET_ARM"
9c08d1fa 9250 "*
8fa3ba89 9251 output_asm_insn (\"cmp\\t%2, %3\", operands);
9252 if (which_alternative != 0)
9253 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9254 return \"sub%d4\\t%0, %1, #1\";
9255 "
9256 [(set_attr "conds" "clob")
1b7da4ac 9257 (set_attr "length" "8,12")
9258 (set_attr "type" "multiple")]
8fa3ba89 9259)
9c08d1fa 9260
aea4c774 9261(define_insn "*cmp_ite0"
cffb2a26 9262 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 9263 (compare
9264 (if_then_else:SI
8fa3ba89 9265 (match_operator 4 "arm_comparison_operator"
2ff91fec 9266 [(match_operand:SI 0 "s_register_operand"
9267 "l,l,l,r,r,r,r,r,r")
9268 (match_operand:SI 1 "arm_add_operand"
9269 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
8fa3ba89 9270 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 9271 [(match_operand:SI 2 "s_register_operand"
9272 "l,r,r,l,l,r,r,r,r")
9273 (match_operand:SI 3 "arm_add_operand"
9274 "lPy,rI,L,lPy,lPy,rI,rI,L,L")])
aea4c774 9275 (const_int 0))
9276 (const_int 0)))]
2ff91fec 9277 "TARGET_32BIT"
9c08d1fa 9278 "*
aea4c774 9279 {
2ff91fec 9280 static const char * const cmp1[NUM_OF_COND_CMP][2] =
9281 {
9282 {\"cmp%d5\\t%0, %1\",
9283 \"cmp%d4\\t%2, %3\"},
9284 {\"cmn%d5\\t%0, #%n1\",
9285 \"cmp%d4\\t%2, %3\"},
9286 {\"cmp%d5\\t%0, %1\",
9287 \"cmn%d4\\t%2, #%n3\"},
9288 {\"cmn%d5\\t%0, #%n1\",
9289 \"cmn%d4\\t%2, #%n3\"}
9290 };
9291 static const char * const cmp2[NUM_OF_COND_CMP][2] =
9292 {
9293 {\"cmp\\t%2, %3\",
9294 \"cmp\\t%0, %1\"},
9295 {\"cmp\\t%2, %3\",
9296 \"cmn\\t%0, #%n1\"},
9297 {\"cmn\\t%2, #%n3\",
9298 \"cmp\\t%0, %1\"},
9299 {\"cmn\\t%2, #%n3\",
9300 \"cmn\\t%0, #%n1\"}
9301 };
9302 static const char * const ite[2] =
8fa3ba89 9303 {
2ff91fec 9304 \"it\\t%d5\",
9305 \"it\\t%d4\"
8fa3ba89 9306 };
2ff91fec 9307 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
9308 CMP_CMP, CMN_CMP, CMP_CMP,
9309 CMN_CMP, CMP_CMN, CMN_CMN};
8fa3ba89 9310 int swap =
9311 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9312
2ff91fec 9313 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9314 if (TARGET_THUMB2) {
9315 output_asm_insn (ite[swap], operands);
9316 }
9317 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9318 return \"\";
8fa3ba89 9319 }"
9320 [(set_attr "conds" "set")
2ff91fec 9321 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
1b7da4ac 9322 (set_attr "type" "multiple")
2ff91fec 9323 (set_attr_alternative "length"
9324 [(const_int 6)
9325 (const_int 8)
9326 (const_int 8)
9327 (const_int 8)
9328 (const_int 8)
9329 (if_then_else (eq_attr "is_thumb" "no")
9330 (const_int 8)
9331 (const_int 10))
9332 (if_then_else (eq_attr "is_thumb" "no")
9333 (const_int 8)
9334 (const_int 10))
9335 (if_then_else (eq_attr "is_thumb" "no")
9336 (const_int 8)
9337 (const_int 10))
9338 (if_then_else (eq_attr "is_thumb" "no")
9339 (const_int 8)
9340 (const_int 10))])]
8fa3ba89 9341)
9c08d1fa 9342
aea4c774 9343(define_insn "*cmp_ite1"
cffb2a26 9344 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 9345 (compare
9346 (if_then_else:SI
8fa3ba89 9347 (match_operator 4 "arm_comparison_operator"
2ff91fec 9348 [(match_operand:SI 0 "s_register_operand"
9349 "l,l,l,r,r,r,r,r,r")
9350 (match_operand:SI 1 "arm_add_operand"
9351 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
8fa3ba89 9352 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 9353 [(match_operand:SI 2 "s_register_operand"
9354 "l,r,r,l,l,r,r,r,r")
9355 (match_operand:SI 3 "arm_add_operand"
9356 "lPy,rI,L,lPy,lPy,rI,rI,L,L")])
aea4c774 9357 (const_int 1))
9358 (const_int 0)))]
2ff91fec 9359 "TARGET_32BIT"
9c08d1fa 9360 "*
9c08d1fa 9361 {
2ff91fec 9362 static const char * const cmp1[NUM_OF_COND_CMP][2] =
9363 {
9364 {\"cmp\\t%0, %1\",
9365 \"cmp\\t%2, %3\"},
9366 {\"cmn\\t%0, #%n1\",
9367 \"cmp\\t%2, %3\"},
9368 {\"cmp\\t%0, %1\",
9369 \"cmn\\t%2, #%n3\"},
9370 {\"cmn\\t%0, #%n1\",
9371 \"cmn\\t%2, #%n3\"}
9372 };
9373 static const char * const cmp2[NUM_OF_COND_CMP][2] =
215b30b3 9374 {
2ff91fec 9375 {\"cmp%d4\\t%2, %3\",
9376 \"cmp%D5\\t%0, %1\"},
9377 {\"cmp%d4\\t%2, %3\",
9378 \"cmn%D5\\t%0, #%n1\"},
9379 {\"cmn%d4\\t%2, #%n3\",
9380 \"cmp%D5\\t%0, %1\"},
9381 {\"cmn%d4\\t%2, #%n3\",
9382 \"cmn%D5\\t%0, #%n1\"}
215b30b3 9383 };
2ff91fec 9384 static const char * const ite[2] =
9385 {
9386 \"it\\t%d4\",
9387 \"it\\t%D5\"
9388 };
9389 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
9390 CMP_CMP, CMN_CMP, CMP_CMP,
9391 CMN_CMP, CMP_CMN, CMN_CMN};
215b30b3 9392 int swap =
9393 comparison_dominates_p (GET_CODE (operands[5]),
9394 reverse_condition (GET_CODE (operands[4])));
9395
2ff91fec 9396 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9397 if (TARGET_THUMB2) {
9398 output_asm_insn (ite[swap], operands);
9399 }
9400 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9401 return \"\";
215b30b3 9402 }"
8fa3ba89 9403 [(set_attr "conds" "set")
2ff91fec 9404 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
9405 (set_attr_alternative "length"
9406 [(const_int 6)
9407 (const_int 8)
9408 (const_int 8)
9409 (const_int 8)
9410 (const_int 8)
9411 (if_then_else (eq_attr "is_thumb" "no")
9412 (const_int 8)
9413 (const_int 10))
9414 (if_then_else (eq_attr "is_thumb" "no")
9415 (const_int 8)
9416 (const_int 10))
9417 (if_then_else (eq_attr "is_thumb" "no")
9418 (const_int 8)
9419 (const_int 10))
9420 (if_then_else (eq_attr "is_thumb" "no")
9421 (const_int 8)
1b7da4ac 9422 (const_int 10))])
9423 (set_attr "type" "multiple")]
8fa3ba89 9424)
9c08d1fa 9425
f6c53574 9426(define_insn "*cmp_and"
9427 [(set (match_operand 6 "dominant_cc_register" "")
9428 (compare
9429 (and:SI
9430 (match_operator 4 "arm_comparison_operator"
2ff91fec 9431 [(match_operand:SI 0 "s_register_operand"
9432 "l,l,l,r,r,r,r,r,r")
9433 (match_operand:SI 1 "arm_add_operand"
9434 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
f6c53574 9435 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 9436 [(match_operand:SI 2 "s_register_operand"
9437 "l,r,r,l,l,r,r,r,r")
9438 (match_operand:SI 3 "arm_add_operand"
9439 "lPy,rI,L,lPy,lPy,rI,rI,L,L")]))
f6c53574 9440 (const_int 0)))]
2ff91fec 9441 "TARGET_32BIT"
f6c53574 9442 "*
9443 {
2ff91fec 9444 static const char *const cmp1[NUM_OF_COND_CMP][2] =
f6c53574 9445 {
2ff91fec 9446 {\"cmp%d5\\t%0, %1\",
9447 \"cmp%d4\\t%2, %3\"},
9448 {\"cmn%d5\\t%0, #%n1\",
9449 \"cmp%d4\\t%2, %3\"},
9450 {\"cmp%d5\\t%0, %1\",
9451 \"cmn%d4\\t%2, #%n3\"},
9452 {\"cmn%d5\\t%0, #%n1\",
9453 \"cmn%d4\\t%2, #%n3\"}
f6c53574 9454 };
2ff91fec 9455 static const char *const cmp2[NUM_OF_COND_CMP][2] =
9456 {
9457 {\"cmp\\t%2, %3\",
9458 \"cmp\\t%0, %1\"},
9459 {\"cmp\\t%2, %3\",
9460 \"cmn\\t%0, #%n1\"},
9461 {\"cmn\\t%2, #%n3\",
9462 \"cmp\\t%0, %1\"},
9463 {\"cmn\\t%2, #%n3\",
9464 \"cmn\\t%0, #%n1\"}
9465 };
9466 static const char *const ite[2] =
9467 {
9468 \"it\\t%d5\",
9469 \"it\\t%d4\"
9470 };
9471 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
9472 CMP_CMP, CMN_CMP, CMP_CMP,
9473 CMN_CMP, CMP_CMN, CMN_CMN};
f6c53574 9474 int swap =
9475 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9476
2ff91fec 9477 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9478 if (TARGET_THUMB2) {
9479 output_asm_insn (ite[swap], operands);
9480 }
9481 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9482 return \"\";
f6c53574 9483 }"
9484 [(set_attr "conds" "set")
9485 (set_attr "predicable" "no")
2ff91fec 9486 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
9487 (set_attr_alternative "length"
9488 [(const_int 6)
9489 (const_int 8)
9490 (const_int 8)
9491 (const_int 8)
9492 (const_int 8)
9493 (if_then_else (eq_attr "is_thumb" "no")
9494 (const_int 8)
9495 (const_int 10))
9496 (if_then_else (eq_attr "is_thumb" "no")
9497 (const_int 8)
9498 (const_int 10))
9499 (if_then_else (eq_attr "is_thumb" "no")
9500 (const_int 8)
9501 (const_int 10))
9502 (if_then_else (eq_attr "is_thumb" "no")
9503 (const_int 8)
1b7da4ac 9504 (const_int 10))])
9505 (set_attr "type" "multiple")]
f6c53574 9506)
9507
9508(define_insn "*cmp_ior"
9509 [(set (match_operand 6 "dominant_cc_register" "")
9510 (compare
9511 (ior:SI
9512 (match_operator 4 "arm_comparison_operator"
2ff91fec 9513 [(match_operand:SI 0 "s_register_operand"
9514 "l,l,l,r,r,r,r,r,r")
9515 (match_operand:SI 1 "arm_add_operand"
9516 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
f6c53574 9517 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 9518 [(match_operand:SI 2 "s_register_operand"
9519 "l,r,r,l,l,r,r,r,r")
9520 (match_operand:SI 3 "arm_add_operand"
9521 "lPy,rI,L,lPy,lPy,rI,rI,L,L")]))
f6c53574 9522 (const_int 0)))]
2ff91fec 9523 "TARGET_32BIT"
f6c53574 9524 "*
f6c53574 9525 {
2ff91fec 9526 static const char *const cmp1[NUM_OF_COND_CMP][2] =
9527 {
9528 {\"cmp\\t%0, %1\",
9529 \"cmp\\t%2, %3\"},
9530 {\"cmn\\t%0, #%n1\",
9531 \"cmp\\t%2, %3\"},
9532 {\"cmp\\t%0, %1\",
9533 \"cmn\\t%2, #%n3\"},
9534 {\"cmn\\t%0, #%n1\",
9535 \"cmn\\t%2, #%n3\"}
9536 };
9537 static const char *const cmp2[NUM_OF_COND_CMP][2] =
9538 {
9539 {\"cmp%D4\\t%2, %3\",
9540 \"cmp%D5\\t%0, %1\"},
9541 {\"cmp%D4\\t%2, %3\",
9542 \"cmn%D5\\t%0, #%n1\"},
9543 {\"cmn%D4\\t%2, #%n3\",
9544 \"cmp%D5\\t%0, %1\"},
9545 {\"cmn%D4\\t%2, #%n3\",
9546 \"cmn%D5\\t%0, #%n1\"}
9547 };
9548 static const char *const ite[2] =
9549 {
9550 \"it\\t%D4\",
9551 \"it\\t%D5\"
9552 };
9553 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
9554 CMP_CMP, CMN_CMP, CMP_CMP,
9555 CMN_CMP, CMP_CMN, CMN_CMN};
9556 int swap =
9557 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9558
9559 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9560 if (TARGET_THUMB2) {
9561 output_asm_insn (ite[swap], operands);
9562 }
9563 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9564 return \"\";
9565 }
9566 "
f6c53574 9567 [(set_attr "conds" "set")
2ff91fec 9568 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
9569 (set_attr_alternative "length"
9570 [(const_int 6)
9571 (const_int 8)
9572 (const_int 8)
9573 (const_int 8)
9574 (const_int 8)
9575 (if_then_else (eq_attr "is_thumb" "no")
9576 (const_int 8)
9577 (const_int 10))
9578 (if_then_else (eq_attr "is_thumb" "no")
9579 (const_int 8)
9580 (const_int 10))
9581 (if_then_else (eq_attr "is_thumb" "no")
9582 (const_int 8)
9583 (const_int 10))
9584 (if_then_else (eq_attr "is_thumb" "no")
9585 (const_int 8)
1b7da4ac 9586 (const_int 10))])
9587 (set_attr "type" "multiple")]
f6c53574 9588)
9589
3c5afce6 9590(define_insn_and_split "*ior_scc_scc"
fd711051 9591 [(set (match_operand:SI 0 "s_register_operand" "=Ts")
3c5afce6 9592 (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9593 [(match_operand:SI 1 "s_register_operand" "r")
9594 (match_operand:SI 2 "arm_add_operand" "rIL")])
9595 (match_operator:SI 6 "arm_comparison_operator"
9596 [(match_operand:SI 4 "s_register_operand" "r")
9597 (match_operand:SI 5 "arm_add_operand" "rIL")])))
9598 (clobber (reg:CC CC_REGNUM))]
2ff91fec 9599 "TARGET_32BIT
3c5afce6 9600 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
9601 != CCmode)"
9602 "#"
2ff91fec 9603 "TARGET_32BIT && reload_completed"
3c5afce6 9604 [(set (match_dup 7)
9605 (compare
9606 (ior:SI
9607 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9608 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9609 (const_int 0)))
9610 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9611 "operands[7]
9612 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9613 DOM_CC_X_OR_Y),
601f584c 9614 CC_REGNUM);"
9615 [(set_attr "conds" "clob")
1b7da4ac 9616 (set_attr "length" "16")
9617 (set_attr "type" "multiple")]
9618)
601f584c 9619
9620; If the above pattern is followed by a CMP insn, then the compare is
9621; redundant, since we can rework the conditional instruction that follows.
9622(define_insn_and_split "*ior_scc_scc_cmp"
9623 [(set (match_operand 0 "dominant_cc_register" "")
9624 (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9625 [(match_operand:SI 1 "s_register_operand" "r")
9626 (match_operand:SI 2 "arm_add_operand" "rIL")])
9627 (match_operator:SI 6 "arm_comparison_operator"
9628 [(match_operand:SI 4 "s_register_operand" "r")
9629 (match_operand:SI 5 "arm_add_operand" "rIL")]))
9630 (const_int 0)))
fd711051 9631 (set (match_operand:SI 7 "s_register_operand" "=Ts")
601f584c 9632 (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9633 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
2ff91fec 9634 "TARGET_32BIT"
601f584c 9635 "#"
2ff91fec 9636 "TARGET_32BIT && reload_completed"
601f584c 9637 [(set (match_dup 0)
9638 (compare
9639 (ior:SI
9640 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9641 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9642 (const_int 0)))
9643 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9644 ""
9645 [(set_attr "conds" "set")
1b7da4ac 9646 (set_attr "length" "16")
9647 (set_attr "type" "multiple")]
9648)
3c5afce6 9649
9650(define_insn_and_split "*and_scc_scc"
fd711051 9651 [(set (match_operand:SI 0 "s_register_operand" "=Ts")
3c5afce6 9652 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9653 [(match_operand:SI 1 "s_register_operand" "r")
9654 (match_operand:SI 2 "arm_add_operand" "rIL")])
9655 (match_operator:SI 6 "arm_comparison_operator"
9656 [(match_operand:SI 4 "s_register_operand" "r")
9657 (match_operand:SI 5 "arm_add_operand" "rIL")])))
9658 (clobber (reg:CC CC_REGNUM))]
2ff91fec 9659 "TARGET_32BIT
3c5afce6 9660 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9661 != CCmode)"
9662 "#"
2ff91fec 9663 "TARGET_32BIT && reload_completed
601f584c 9664 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9665 != CCmode)"
3c5afce6 9666 [(set (match_dup 7)
9667 (compare
9668 (and:SI
9669 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9670 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9671 (const_int 0)))
9672 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9673 "operands[7]
9674 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9675 DOM_CC_X_AND_Y),
601f584c 9676 CC_REGNUM);"
9677 [(set_attr "conds" "clob")
1b7da4ac 9678 (set_attr "length" "16")
9679 (set_attr "type" "multiple")]
9680)
601f584c 9681
9682; If the above pattern is followed by a CMP insn, then the compare is
9683; redundant, since we can rework the conditional instruction that follows.
9684(define_insn_and_split "*and_scc_scc_cmp"
9685 [(set (match_operand 0 "dominant_cc_register" "")
9686 (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
9687 [(match_operand:SI 1 "s_register_operand" "r")
9688 (match_operand:SI 2 "arm_add_operand" "rIL")])
9689 (match_operator:SI 6 "arm_comparison_operator"
9690 [(match_operand:SI 4 "s_register_operand" "r")
9691 (match_operand:SI 5 "arm_add_operand" "rIL")]))
9692 (const_int 0)))
fd711051 9693 (set (match_operand:SI 7 "s_register_operand" "=Ts")
601f584c 9694 (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9695 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
2ff91fec 9696 "TARGET_32BIT"
601f584c 9697 "#"
2ff91fec 9698 "TARGET_32BIT && reload_completed"
601f584c 9699 [(set (match_dup 0)
9700 (compare
9701 (and:SI
9702 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9703 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9704 (const_int 0)))
9705 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9706 ""
9707 [(set_attr "conds" "set")
1b7da4ac 9708 (set_attr "length" "16")
9709 (set_attr "type" "multiple")]
9710)
601f584c 9711
9712;; If there is no dominance in the comparison, then we can still save an
9713;; instruction in the AND case, since we can know that the second compare
9714;; need only zero the value if false (if true, then the value is already
9715;; correct).
9716(define_insn_and_split "*and_scc_scc_nodom"
fd711051 9717 [(set (match_operand:SI 0 "s_register_operand" "=&Ts,&Ts,&Ts")
601f584c 9718 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9719 [(match_operand:SI 1 "s_register_operand" "r,r,0")
9720 (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
9721 (match_operator:SI 6 "arm_comparison_operator"
9722 [(match_operand:SI 4 "s_register_operand" "r,r,r")
9723 (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
9724 (clobber (reg:CC CC_REGNUM))]
2ff91fec 9725 "TARGET_32BIT
601f584c 9726 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9727 == CCmode)"
9728 "#"
2ff91fec 9729 "TARGET_32BIT && reload_completed"
601f584c 9730 [(parallel [(set (match_dup 0)
9731 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
9732 (clobber (reg:CC CC_REGNUM))])
9733 (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
9734 (set (match_dup 0)
9735 (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
9736 (match_dup 0)
9737 (const_int 0)))]
9738 "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
9739 operands[4], operands[5]),
9740 CC_REGNUM);
9741 operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
9742 operands[5]);"
9743 [(set_attr "conds" "clob")
1b7da4ac 9744 (set_attr "length" "20")
9745 (set_attr "type" "multiple")]
9746)
3c5afce6 9747
3a0bdee0 9748(define_split
9749 [(set (reg:CC_NOOV CC_REGNUM)
9750 (compare:CC_NOOV (ior:SI
9751 (and:SI (match_operand:SI 0 "s_register_operand" "")
9752 (const_int 1))
b0694be0 9753 (match_operator:SI 1 "arm_comparison_operator"
3a0bdee0 9754 [(match_operand:SI 2 "s_register_operand" "")
9755 (match_operand:SI 3 "arm_add_operand" "")]))
9756 (const_int 0)))
9757 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9758 "TARGET_ARM"
9759 [(set (match_dup 4)
9760 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9761 (match_dup 0)))
9762 (set (reg:CC_NOOV CC_REGNUM)
9763 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9764 (const_int 0)))]
9765 "")
9766
9767(define_split
9768 [(set (reg:CC_NOOV CC_REGNUM)
9769 (compare:CC_NOOV (ior:SI
b0694be0 9770 (match_operator:SI 1 "arm_comparison_operator"
3a0bdee0 9771 [(match_operand:SI 2 "s_register_operand" "")
9772 (match_operand:SI 3 "arm_add_operand" "")])
9773 (and:SI (match_operand:SI 0 "s_register_operand" "")
9774 (const_int 1)))
9775 (const_int 0)))
9776 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9777 "TARGET_ARM"
9778 [(set (match_dup 4)
9779 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9780 (match_dup 0)))
9781 (set (reg:CC_NOOV CC_REGNUM)
9782 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9783 (const_int 0)))]
9784 "")
25f905c2 9785;; ??? The conditional patterns above need checking for Thumb-2 usefulness
3a0bdee0 9786
190efb17 9787(define_insn_and_split "*negscc"
9c08d1fa 9788 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9789 (neg:SI (match_operator 3 "arm_comparison_operator"
9c08d1fa 9790 [(match_operand:SI 1 "s_register_operand" "r")
9791 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
bd5b4116 9792 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9793 "TARGET_ARM"
190efb17 9794 "#"
9795 "&& reload_completed"
9796 [(const_int 0)]
9797 {
9798 rtx cc_reg = gen_rtx_REG (CCmode, CC_REGNUM);
e2348bcb 9799
190efb17 9800 if (GET_CODE (operands[3]) == LT && operands[2] == const0_rtx)
9801 {
9802 /* Emit mov\\t%0, %1, asr #31 */
d1f9b275 9803 emit_insn (gen_rtx_SET (operands[0],
190efb17 9804 gen_rtx_ASHIFTRT (SImode,
9805 operands[1],
9806 GEN_INT (31))));
9807 DONE;
9808 }
9809 else if (GET_CODE (operands[3]) == NE)
9810 {
9811 /* Emit subs\\t%0, %1, %2\;mvnne\\t%0, #0 */
9812 if (CONST_INT_P (operands[2]))
9813 emit_insn (gen_cmpsi2_addneg (operands[0], operands[1], operands[2],
9814 GEN_INT (- INTVAL (operands[2]))));
9815 else
9816 emit_insn (gen_subsi3_compare (operands[0], operands[1], operands[2]));
9817
9818 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
9819 gen_rtx_NE (SImode,
9820 cc_reg,
9821 const0_rtx),
d1f9b275 9822 gen_rtx_SET (operands[0],
190efb17 9823 GEN_INT (~0))));
9824 DONE;
9825 }
9826 else
9827 {
9828 /* Emit: cmp\\t%1, %2\;mov%D3\\t%0, #0\;mvn%d3\\t%0, #0 */
d1f9b275 9829 emit_insn (gen_rtx_SET (cc_reg,
190efb17 9830 gen_rtx_COMPARE (CCmode, operands[1], operands[2])));
9831 enum rtx_code rc = GET_CODE (operands[3]);
9832
9833 rc = reverse_condition (rc);
9834 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
9835 gen_rtx_fmt_ee (rc,
9836 VOIDmode,
9837 cc_reg,
9838 const0_rtx),
d1f9b275 9839 gen_rtx_SET (operands[0], const0_rtx)));
190efb17 9840 rc = GET_CODE (operands[3]);
9841 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
9842 gen_rtx_fmt_ee (rc,
9843 VOIDmode,
9844 cc_reg,
9845 const0_rtx),
d1f9b275 9846 gen_rtx_SET (operands[0],
190efb17 9847 GEN_INT (~0))));
9848 DONE;
9849 }
9850 FAIL;
9851 }
8fa3ba89 9852 [(set_attr "conds" "clob")
1b7da4ac 9853 (set_attr "length" "12")
9854 (set_attr "type" "multiple")]
8fa3ba89 9855)
9c08d1fa 9856
90404b57 9857(define_insn_and_split "movcond_addsi"
9858 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r")
9859 (if_then_else:SI
9860 (match_operator 5 "comparison_operator"
9861 [(plus:SI (match_operand:SI 3 "s_register_operand" "r,r,r")
9862 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL"))
9863 (const_int 0)])
9864 (match_operand:SI 1 "arm_rhs_operand" "rI,rPy,r")
9865 (match_operand:SI 2 "arm_rhs_operand" "rI,rPy,r")))
9866 (clobber (reg:CC CC_REGNUM))]
9867 "TARGET_32BIT"
9868 "#"
9869 "&& reload_completed"
9870 [(set (reg:CC_NOOV CC_REGNUM)
9871 (compare:CC_NOOV
9872 (plus:SI (match_dup 3)
9873 (match_dup 4))
9874 (const_int 0)))
9875 (set (match_dup 0) (match_dup 1))
9876 (cond_exec (match_dup 6)
9877 (set (match_dup 0) (match_dup 2)))]
9878 "
9879 {
3754d046 9880 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[5]),
90404b57 9881 operands[3], operands[4]);
9882 enum rtx_code rc = GET_CODE (operands[5]);
90404b57 9883 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9884 gcc_assert (!(mode == CCFPmode || mode == CCFPEmode));
22440aeb 9885 if (!REG_P (operands[2]) || REGNO (operands[2]) != REGNO (operands[0]))
4d01ce2f 9886 rc = reverse_condition (rc);
f145bcba 9887 else
9888 std::swap (operands[1], operands[2]);
90404b57 9889
9890 operands[6] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9891 }
9892 "
9893 [(set_attr "conds" "clob")
1b7da4ac 9894 (set_attr "enabled_for_depr_it" "no,yes,yes")
9895 (set_attr "type" "multiple")]
90404b57 9896)
9897
9c08d1fa 9898(define_insn "movcond"
9899 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 9900 (if_then_else:SI
8fa3ba89 9901 (match_operator 5 "arm_comparison_operator"
5565501b 9902 [(match_operand:SI 3 "s_register_operand" "r,r,r")
9903 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
9904 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9905 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 9906 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9907 "TARGET_ARM"
9c08d1fa 9908 "*
9909 if (GET_CODE (operands[5]) == LT
9910 && (operands[4] == const0_rtx))
9911 {
0438d37f 9912 if (which_alternative != 1 && REG_P (operands[1]))
9c08d1fa 9913 {
9c08d1fa 9914 if (operands[2] == const0_rtx)
e2348bcb 9915 return \"and\\t%0, %1, %3, asr #31\";
9916 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
9c08d1fa 9917 }
0438d37f 9918 else if (which_alternative != 0 && REG_P (operands[2]))
9c08d1fa 9919 {
9c08d1fa 9920 if (operands[1] == const0_rtx)
e2348bcb 9921 return \"bic\\t%0, %2, %3, asr #31\";
9922 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
9c08d1fa 9923 }
9924 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 9925 are constants. */
9c08d1fa 9926 }
e2348bcb 9927
9c08d1fa 9928 if (GET_CODE (operands[5]) == GE
9929 && (operands[4] == const0_rtx))
9930 {
0438d37f 9931 if (which_alternative != 1 && REG_P (operands[1]))
9c08d1fa 9932 {
9c08d1fa 9933 if (operands[2] == const0_rtx)
e2348bcb 9934 return \"bic\\t%0, %1, %3, asr #31\";
9935 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
9c08d1fa 9936 }
0438d37f 9937 else if (which_alternative != 0 && REG_P (operands[2]))
9c08d1fa 9938 {
9c08d1fa 9939 if (operands[1] == const0_rtx)
e2348bcb 9940 return \"and\\t%0, %2, %3, asr #31\";
9941 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
9c08d1fa 9942 }
9943 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 9944 are constants. */
9c08d1fa 9945 }
0438d37f 9946 if (CONST_INT_P (operands[4])
9c08d1fa 9947 && !const_ok_for_arm (INTVAL (operands[4])))
e2348bcb 9948 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
9c08d1fa 9949 else
e2348bcb 9950 output_asm_insn (\"cmp\\t%3, %4\", operands);
9c08d1fa 9951 if (which_alternative != 0)
e2348bcb 9952 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
9c08d1fa 9953 if (which_alternative != 1)
e2348bcb 9954 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
9c08d1fa 9955 return \"\";
215b30b3 9956 "
8fa3ba89 9957 [(set_attr "conds" "clob")
1b7da4ac 9958 (set_attr "length" "8,8,12")
9959 (set_attr "type" "multiple")]
8fa3ba89 9960)
9c08d1fa 9961
25f905c2 9962;; ??? The patterns below need checking for Thumb-2 usefulness.
9963
8a18b90c 9964(define_insn "*ifcompare_plus_move"
9965 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9966 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 9967 [(match_operand:SI 4 "s_register_operand" "r,r")
9968 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9969 (plus:SI
9970 (match_operand:SI 2 "s_register_operand" "r,r")
9971 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
129a2fe4 9972 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 9973 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9974 "TARGET_ARM"
8a18b90c 9975 "#"
8fa3ba89 9976 [(set_attr "conds" "clob")
1b7da4ac 9977 (set_attr "length" "8,12")
9978 (set_attr "type" "multiple")]
8fa3ba89 9979)
8a18b90c 9980
9981(define_insn "*if_plus_move"
129a2fe4 9982 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 9983 (if_then_else:SI
8fa3ba89 9984 (match_operator 4 "arm_comparison_operator"
8a18b90c 9985 [(match_operand 5 "cc_register" "") (const_int 0)])
9986 (plus:SI
129a2fe4 9987 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9988 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
9989 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
cffb2a26 9990 "TARGET_ARM"
8a18b90c 9991 "@
9992 add%d4\\t%0, %2, %3
9993 sub%d4\\t%0, %2, #%n3
9994 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
129a2fe4 9995 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8fa3ba89 9996 [(set_attr "conds" "use")
9997 (set_attr "length" "4,4,8,8")
65f68e55 9998 (set_attr_alternative "type"
9999 [(if_then_else (match_operand 3 "const_int_operand" "")
d82e788e 10000 (const_string "alu_imm" )
112eda6f 10001 (const_string "alu_sreg"))
d82e788e 10002 (const_string "alu_imm")
282b4c75 10003 (const_string "multiple")
10004 (const_string "multiple")])]
8fa3ba89 10005)
8a18b90c 10006
10007(define_insn "*ifcompare_move_plus"
5565501b 10008 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10009 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 10010 [(match_operand:SI 4 "s_register_operand" "r,r")
10011 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 10012 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 10013 (plus:SI
10014 (match_operand:SI 2 "s_register_operand" "r,r")
10015 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
bd5b4116 10016 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10017 "TARGET_ARM"
8a18b90c 10018 "#"
8fa3ba89 10019 [(set_attr "conds" "clob")
1b7da4ac 10020 (set_attr "length" "8,12")
10021 (set_attr "type" "multiple")]
8fa3ba89 10022)
8a18b90c 10023
10024(define_insn "*if_move_plus"
129a2fe4 10025 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 10026 (if_then_else:SI
8fa3ba89 10027 (match_operator 4 "arm_comparison_operator"
8a18b90c 10028 [(match_operand 5 "cc_register" "") (const_int 0)])
129a2fe4 10029 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8a18b90c 10030 (plus:SI
129a2fe4 10031 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
10032 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
cffb2a26 10033 "TARGET_ARM"
8a18b90c 10034 "@
10035 add%D4\\t%0, %2, %3
10036 sub%D4\\t%0, %2, #%n3
10037 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
129a2fe4 10038 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8fa3ba89 10039 [(set_attr "conds" "use")
10040 (set_attr "length" "4,4,8,8")
282b4c75 10041 (set_attr_alternative "type"
10042 [(if_then_else (match_operand 3 "const_int_operand" "")
10043 (const_string "alu_imm" )
10044 (const_string "alu_sreg"))
10045 (const_string "alu_imm")
10046 (const_string "multiple")
10047 (const_string "multiple")])]
8fa3ba89 10048)
8a18b90c 10049
10050(define_insn "*ifcompare_arith_arith"
10051 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 10052 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8a18b90c 10053 [(match_operand:SI 5 "s_register_operand" "r")
10054 (match_operand:SI 6 "arm_add_operand" "rIL")])
9c08d1fa 10055 (match_operator:SI 8 "shiftable_operator"
8a18b90c 10056 [(match_operand:SI 1 "s_register_operand" "r")
10057 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9c08d1fa 10058 (match_operator:SI 7 "shiftable_operator"
8a18b90c 10059 [(match_operand:SI 3 "s_register_operand" "r")
10060 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
bd5b4116 10061 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10062 "TARGET_ARM"
8a18b90c 10063 "#"
8fa3ba89 10064 [(set_attr "conds" "clob")
1b7da4ac 10065 (set_attr "length" "12")
10066 (set_attr "type" "multiple")]
8fa3ba89 10067)
9c08d1fa 10068
8a18b90c 10069(define_insn "*if_arith_arith"
10070 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 10071 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8a18b90c 10072 [(match_operand 8 "cc_register" "") (const_int 0)])
10073 (match_operator:SI 6 "shiftable_operator"
10074 [(match_operand:SI 1 "s_register_operand" "r")
10075 (match_operand:SI 2 "arm_rhs_operand" "rI")])
10076 (match_operator:SI 7 "shiftable_operator"
10077 [(match_operand:SI 3 "s_register_operand" "r")
10078 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
cffb2a26 10079 "TARGET_ARM"
8a18b90c 10080 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8fa3ba89 10081 [(set_attr "conds" "use")
1b7da4ac 10082 (set_attr "length" "8")
10083 (set_attr "type" "multiple")]
8fa3ba89 10084)
8a18b90c 10085
f7fbdd4a 10086(define_insn "*ifcompare_arith_move"
9c08d1fa 10087 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10088 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 10089 [(match_operand:SI 2 "s_register_operand" "r,r")
5565501b 10090 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
9c08d1fa 10091 (match_operator:SI 7 "shiftable_operator"
10092 [(match_operand:SI 4 "s_register_operand" "r,r")
10093 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
129a2fe4 10094 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 10095 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10096 "TARGET_ARM"
9c08d1fa 10097 "*
9c08d1fa 10098 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 10099 the conditional operator is LT or GE and we are comparing against zero and
674a8f0b 10100 everything is in registers then we can do this in two instructions. */
9c08d1fa 10101 if (operands[3] == const0_rtx
10102 && GET_CODE (operands[7]) != AND
0438d37f 10103 && REG_P (operands[5])
10104 && REG_P (operands[1])
9c08d1fa 10105 && REGNO (operands[1]) == REGNO (operands[4])
10106 && REGNO (operands[4]) != REGNO (operands[0]))
10107 {
10108 if (GET_CODE (operands[6]) == LT)
40dbec34 10109 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 10110 else if (GET_CODE (operands[6]) == GE)
40dbec34 10111 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 10112 }
0438d37f 10113 if (CONST_INT_P (operands[3])
9c08d1fa 10114 && !const_ok_for_arm (INTVAL (operands[3])))
e2348bcb 10115 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
9c08d1fa 10116 else
e2348bcb 10117 output_asm_insn (\"cmp\\t%2, %3\", operands);
40dbec34 10118 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
9c08d1fa 10119 if (which_alternative != 0)
129a2fe4 10120 return \"mov%D6\\t%0, %1\";
9c08d1fa 10121 return \"\";
215b30b3 10122 "
8fa3ba89 10123 [(set_attr "conds" "clob")
1b7da4ac 10124 (set_attr "length" "8,12")
10125 (set_attr "type" "multiple")]
8fa3ba89 10126)
9c08d1fa 10127
8a18b90c 10128(define_insn "*if_arith_move"
129a2fe4 10129 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10130 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8a18b90c 10131 [(match_operand 6 "cc_register" "") (const_int 0)])
10132 (match_operator:SI 5 "shiftable_operator"
129a2fe4 10133 [(match_operand:SI 2 "s_register_operand" "r,r")
10134 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
10135 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
cffb2a26 10136 "TARGET_ARM"
8a18b90c 10137 "@
10138 %I5%d4\\t%0, %2, %3
129a2fe4 10139 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8fa3ba89 10140 [(set_attr "conds" "use")
10141 (set_attr "length" "4,8")
282b4c75 10142 (set_attr_alternative "type"
10143 [(if_then_else (match_operand 3 "const_int_operand" "")
10144 (const_string "alu_shift_imm" )
10145 (const_string "alu_shift_reg"))
10146 (const_string "multiple")])]
8fa3ba89 10147)
8a18b90c 10148
f7fbdd4a 10149(define_insn "*ifcompare_move_arith"
9c08d1fa 10150 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10151 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 10152 [(match_operand:SI 4 "s_register_operand" "r,r")
5565501b 10153 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 10154 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9c08d1fa 10155 (match_operator:SI 7 "shiftable_operator"
10156 [(match_operand:SI 2 "s_register_operand" "r,r")
10157 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 10158 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10159 "TARGET_ARM"
9c08d1fa 10160 "*
9c08d1fa 10161 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 10162 the conditional operator is LT or GE and we are comparing against zero and
9c08d1fa 10163 everything is in registers then we can do this in two instructions */
10164 if (operands[5] == const0_rtx
10165 && GET_CODE (operands[7]) != AND
0438d37f 10166 && REG_P (operands[3])
10167 && REG_P (operands[1])
9c08d1fa 10168 && REGNO (operands[1]) == REGNO (operands[2])
10169 && REGNO (operands[2]) != REGNO (operands[0]))
10170 {
10171 if (GET_CODE (operands[6]) == GE)
40dbec34 10172 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 10173 else if (GET_CODE (operands[6]) == LT)
40dbec34 10174 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 10175 }
40dbec34 10176
0438d37f 10177 if (CONST_INT_P (operands[5])
9c08d1fa 10178 && !const_ok_for_arm (INTVAL (operands[5])))
e2348bcb 10179 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
9c08d1fa 10180 else
e2348bcb 10181 output_asm_insn (\"cmp\\t%4, %5\", operands);
40dbec34 10182
9c08d1fa 10183 if (which_alternative != 0)
129a2fe4 10184 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
40dbec34 10185 return \"%I7%D6\\t%0, %2, %3\";
215b30b3 10186 "
8fa3ba89 10187 [(set_attr "conds" "clob")
1b7da4ac 10188 (set_attr "length" "8,12")
10189 (set_attr "type" "multiple")]
8fa3ba89 10190)
9c08d1fa 10191
8a18b90c 10192(define_insn "*if_move_arith"
129a2fe4 10193 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 10194 (if_then_else:SI
8fa3ba89 10195 (match_operator 4 "arm_comparison_operator"
8a18b90c 10196 [(match_operand 6 "cc_register" "") (const_int 0)])
129a2fe4 10197 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 10198 (match_operator:SI 5 "shiftable_operator"
129a2fe4 10199 [(match_operand:SI 2 "s_register_operand" "r,r")
10200 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
cffb2a26 10201 "TARGET_ARM"
8a18b90c 10202 "@
10203 %I5%D4\\t%0, %2, %3
129a2fe4 10204 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
8fa3ba89 10205 [(set_attr "conds" "use")
10206 (set_attr "length" "4,8")
282b4c75 10207 (set_attr_alternative "type"
10208 [(if_then_else (match_operand 3 "const_int_operand" "")
10209 (const_string "alu_shift_imm" )
10210 (const_string "alu_shift_reg"))
10211 (const_string "multiple")])]
8fa3ba89 10212)
8a18b90c 10213
10214(define_insn "*ifcompare_move_not"
9c08d1fa 10215 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 10216 (if_then_else:SI
8fa3ba89 10217 (match_operator 5 "arm_comparison_operator"
8a18b90c 10218 [(match_operand:SI 3 "s_register_operand" "r,r")
10219 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10220 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
10221 (not:SI
10222 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 10223 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10224 "TARGET_ARM"
8a18b90c 10225 "#"
8fa3ba89 10226 [(set_attr "conds" "clob")
1b7da4ac 10227 (set_attr "length" "8,12")
10228 (set_attr "type" "multiple")]
8fa3ba89 10229)
9c08d1fa 10230
8a18b90c 10231(define_insn "*if_move_not"
10232 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10233 (if_then_else:SI
8fa3ba89 10234 (match_operator 4 "arm_comparison_operator"
8a18b90c 10235 [(match_operand 3 "cc_register" "") (const_int 0)])
10236 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
10237 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
cffb2a26 10238 "TARGET_ARM"
8a18b90c 10239 "@
10240 mvn%D4\\t%0, %2
10241 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
10242 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
8fa3ba89 10243 [(set_attr "conds" "use")
1aed5204 10244 (set_attr "type" "mvn_reg")
1b7da4ac 10245 (set_attr "length" "4,8,8")
10246 (set_attr "type" "mvn_reg,multiple,multiple")]
8fa3ba89 10247)
8a18b90c 10248
10249(define_insn "*ifcompare_not_move"
9c08d1fa 10250 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 10251 (if_then_else:SI
8fa3ba89 10252 (match_operator 5 "arm_comparison_operator"
8a18b90c 10253 [(match_operand:SI 3 "s_register_operand" "r,r")
10254 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10255 (not:SI
10256 (match_operand:SI 2 "s_register_operand" "r,r"))
10257 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 10258 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10259 "TARGET_ARM"
8a18b90c 10260 "#"
8fa3ba89 10261 [(set_attr "conds" "clob")
1b7da4ac 10262 (set_attr "length" "8,12")
10263 (set_attr "type" "multiple")]
8fa3ba89 10264)
9c08d1fa 10265
8a18b90c 10266(define_insn "*if_not_move"
10267 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10268 (if_then_else:SI
8fa3ba89 10269 (match_operator 4 "arm_comparison_operator"
8a18b90c 10270 [(match_operand 3 "cc_register" "") (const_int 0)])
10271 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
10272 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 10273 "TARGET_ARM"
8a18b90c 10274 "@
10275 mvn%d4\\t%0, %2
10276 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
10277 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
8fa3ba89 10278 [(set_attr "conds" "use")
1b7da4ac 10279 (set_attr "type" "mvn_reg,multiple,multiple")
8fa3ba89 10280 (set_attr "length" "4,8,8")]
10281)
8a18b90c 10282
10283(define_insn "*ifcompare_shift_move"
9c08d1fa 10284 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 10285 (if_then_else:SI
8fa3ba89 10286 (match_operator 6 "arm_comparison_operator"
8a18b90c 10287 [(match_operand:SI 4 "s_register_operand" "r,r")
10288 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
10289 (match_operator:SI 7 "shift_operator"
10290 [(match_operand:SI 2 "s_register_operand" "r,r")
10291 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
10292 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 10293 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10294 "TARGET_ARM"
9c08d1fa 10295 "#"
8fa3ba89 10296 [(set_attr "conds" "clob")
1b7da4ac 10297 (set_attr "length" "8,12")
10298 (set_attr "type" "multiple")]
8fa3ba89 10299)
9c08d1fa 10300
8a18b90c 10301(define_insn "*if_shift_move"
10302 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10303 (if_then_else:SI
8fa3ba89 10304 (match_operator 5 "arm_comparison_operator"
8a18b90c 10305 [(match_operand 6 "cc_register" "") (const_int 0)])
10306 (match_operator:SI 4 "shift_operator"
10307 [(match_operand:SI 2 "s_register_operand" "r,r,r")
10308 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
10309 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 10310 "TARGET_ARM"
5565501b 10311 "@
8a18b90c 10312 mov%d5\\t%0, %2%S4
10313 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
10314 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
8fa3ba89 10315 [(set_attr "conds" "use")
331beb1a 10316 (set_attr "shift" "2")
a2cd141b 10317 (set_attr "length" "4,8,8")
282b4c75 10318 (set_attr_alternative "type"
10319 [(if_then_else (match_operand 3 "const_int_operand" "")
10320 (const_string "mov_shift" )
10321 (const_string "mov_shift_reg"))
10322 (const_string "multiple")
10323 (const_string "multiple")])]
8fa3ba89 10324)
5565501b 10325
8a18b90c 10326(define_insn "*ifcompare_move_shift"
10327 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 10328 (if_then_else:SI
8fa3ba89 10329 (match_operator 6 "arm_comparison_operator"
8a18b90c 10330 [(match_operand:SI 4 "s_register_operand" "r,r")
10331 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
10332 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
5565501b 10333 (match_operator:SI 7 "shift_operator"
8a18b90c 10334 [(match_operand:SI 2 "s_register_operand" "r,r")
10335 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
bd5b4116 10336 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10337 "TARGET_ARM"
8a18b90c 10338 "#"
8fa3ba89 10339 [(set_attr "conds" "clob")
1b7da4ac 10340 (set_attr "length" "8,12")
10341 (set_attr "type" "multiple")]
8fa3ba89 10342)
5565501b 10343
8a18b90c 10344(define_insn "*if_move_shift"
10345 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 10346 (if_then_else:SI
8fa3ba89 10347 (match_operator 5 "arm_comparison_operator"
8a18b90c 10348 [(match_operand 6 "cc_register" "") (const_int 0)])
10349 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
10350 (match_operator:SI 4 "shift_operator"
10351 [(match_operand:SI 2 "s_register_operand" "r,r,r")
10352 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
cffb2a26 10353 "TARGET_ARM"
5565501b 10354 "@
8a18b90c 10355 mov%D5\\t%0, %2%S4
10356 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
10357 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
8fa3ba89 10358 [(set_attr "conds" "use")
331beb1a 10359 (set_attr "shift" "2")
a2cd141b 10360 (set_attr "length" "4,8,8")
282b4c75 10361 (set_attr_alternative "type"
10362 [(if_then_else (match_operand 3 "const_int_operand" "")
10363 (const_string "mov_shift" )
10364 (const_string "mov_shift_reg"))
10365 (const_string "multiple")
10366 (const_string "multiple")])]
8fa3ba89 10367)
9c08d1fa 10368
f7fbdd4a 10369(define_insn "*ifcompare_shift_shift"
8a18b90c 10370 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 10371 (if_then_else:SI
8fa3ba89 10372 (match_operator 7 "arm_comparison_operator"
8a18b90c 10373 [(match_operand:SI 5 "s_register_operand" "r")
10374 (match_operand:SI 6 "arm_add_operand" "rIL")])
5565501b 10375 (match_operator:SI 8 "shift_operator"
8a18b90c 10376 [(match_operand:SI 1 "s_register_operand" "r")
10377 (match_operand:SI 2 "arm_rhs_operand" "rM")])
5565501b 10378 (match_operator:SI 9 "shift_operator"
8a18b90c 10379 [(match_operand:SI 3 "s_register_operand" "r")
10380 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
bd5b4116 10381 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10382 "TARGET_ARM"
8a18b90c 10383 "#"
8fa3ba89 10384 [(set_attr "conds" "clob")
1b7da4ac 10385 (set_attr "length" "12")
10386 (set_attr "type" "multiple")]
8fa3ba89 10387)
9c08d1fa 10388
8a18b90c 10389(define_insn "*if_shift_shift"
10390 [(set (match_operand:SI 0 "s_register_operand" "=r")
10391 (if_then_else:SI
8fa3ba89 10392 (match_operator 5 "arm_comparison_operator"
8a18b90c 10393 [(match_operand 8 "cc_register" "") (const_int 0)])
10394 (match_operator:SI 6 "shift_operator"
10395 [(match_operand:SI 1 "s_register_operand" "r")
10396 (match_operand:SI 2 "arm_rhs_operand" "rM")])
10397 (match_operator:SI 7 "shift_operator"
10398 [(match_operand:SI 3 "s_register_operand" "r")
10399 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
cffb2a26 10400 "TARGET_ARM"
8a18b90c 10401 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
8fa3ba89 10402 [(set_attr "conds" "use")
331beb1a 10403 (set_attr "shift" "1")
a2cd141b 10404 (set_attr "length" "8")
10405 (set (attr "type") (if_then_else
10406 (and (match_operand 2 "const_int_operand" "")
10407 (match_operand 4 "const_int_operand" ""))
1aed5204 10408 (const_string "mov_shift")
10409 (const_string "mov_shift_reg")))]
8fa3ba89 10410)
8a18b90c 10411
f7fbdd4a 10412(define_insn "*ifcompare_not_arith"
8a18b90c 10413 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 10414 (if_then_else:SI
8fa3ba89 10415 (match_operator 6 "arm_comparison_operator"
8a18b90c 10416 [(match_operand:SI 4 "s_register_operand" "r")
10417 (match_operand:SI 5 "arm_add_operand" "rIL")])
10418 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5565501b 10419 (match_operator:SI 7 "shiftable_operator"
8a18b90c 10420 [(match_operand:SI 2 "s_register_operand" "r")
10421 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
bd5b4116 10422 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10423 "TARGET_ARM"
8a18b90c 10424 "#"
8fa3ba89 10425 [(set_attr "conds" "clob")
1b7da4ac 10426 (set_attr "length" "12")
10427 (set_attr "type" "multiple")]
8fa3ba89 10428)
9c08d1fa 10429
8a18b90c 10430(define_insn "*if_not_arith"
10431 [(set (match_operand:SI 0 "s_register_operand" "=r")
10432 (if_then_else:SI
8fa3ba89 10433 (match_operator 5 "arm_comparison_operator"
8a18b90c 10434 [(match_operand 4 "cc_register" "") (const_int 0)])
10435 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
10436 (match_operator:SI 6 "shiftable_operator"
10437 [(match_operand:SI 2 "s_register_operand" "r")
10438 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
cffb2a26 10439 "TARGET_ARM"
8a18b90c 10440 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
8fa3ba89 10441 [(set_attr "conds" "use")
1aed5204 10442 (set_attr "type" "mvn_reg")
8fa3ba89 10443 (set_attr "length" "8")]
10444)
8a18b90c 10445
10446(define_insn "*ifcompare_arith_not"
10447 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 10448 (if_then_else:SI
8fa3ba89 10449 (match_operator 6 "arm_comparison_operator"
8a18b90c 10450 [(match_operand:SI 4 "s_register_operand" "r")
10451 (match_operand:SI 5 "arm_add_operand" "rIL")])
5565501b 10452 (match_operator:SI 7 "shiftable_operator"
8a18b90c 10453 [(match_operand:SI 2 "s_register_operand" "r")
10454 (match_operand:SI 3 "arm_rhs_operand" "rI")])
10455 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
bd5b4116 10456 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10457 "TARGET_ARM"
8a18b90c 10458 "#"
8fa3ba89 10459 [(set_attr "conds" "clob")
1b7da4ac 10460 (set_attr "length" "12")
10461 (set_attr "type" "multiple")]
8fa3ba89 10462)
9c08d1fa 10463
8a18b90c 10464(define_insn "*if_arith_not"
10465 [(set (match_operand:SI 0 "s_register_operand" "=r")
10466 (if_then_else:SI
8fa3ba89 10467 (match_operator 5 "arm_comparison_operator"
8a18b90c 10468 [(match_operand 4 "cc_register" "") (const_int 0)])
10469 (match_operator:SI 6 "shiftable_operator"
10470 [(match_operand:SI 2 "s_register_operand" "r")
10471 (match_operand:SI 3 "arm_rhs_operand" "rI")])
10472 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
cffb2a26 10473 "TARGET_ARM"
8a18b90c 10474 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
8fa3ba89 10475 [(set_attr "conds" "use")
1b7da4ac 10476 (set_attr "type" "multiple")
8fa3ba89 10477 (set_attr "length" "8")]
10478)
8a18b90c 10479
f7fbdd4a 10480(define_insn "*ifcompare_neg_move"
8a18b90c 10481 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 10482 (if_then_else:SI
8fa3ba89 10483 (match_operator 5 "arm_comparison_operator"
8a18b90c 10484 [(match_operand:SI 3 "s_register_operand" "r,r")
10485 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10486 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
10487 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 10488 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10489 "TARGET_ARM"
8a18b90c 10490 "#"
8fa3ba89 10491 [(set_attr "conds" "clob")
1b7da4ac 10492 (set_attr "length" "8,12")
10493 (set_attr "type" "multiple")]
8fa3ba89 10494)
8a18b90c 10495
530bb693 10496(define_insn_and_split "*if_neg_move"
10497 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
8a18b90c 10498 (if_then_else:SI
8fa3ba89 10499 (match_operator 4 "arm_comparison_operator"
8a18b90c 10500 [(match_operand 3 "cc_register" "") (const_int 0)])
530bb693 10501 (neg:SI (match_operand:SI 2 "s_register_operand" "l,r"))
10502 (match_operand:SI 1 "s_register_operand" "0,0")))]
10503 "TARGET_32BIT"
10504 "#"
10505 "&& reload_completed"
10506 [(cond_exec (match_op_dup 4 [(match_dup 3) (const_int 0)])
10507 (set (match_dup 0) (neg:SI (match_dup 2))))]
10508 ""
8fa3ba89 10509 [(set_attr "conds" "use")
530bb693 10510 (set_attr "length" "4")
10511 (set_attr "arch" "t2,32")
10512 (set_attr "enabled_for_depr_it" "yes,no")
10513 (set_attr "type" "logic_shift_imm")]
8fa3ba89 10514)
9c08d1fa 10515
f7fbdd4a 10516(define_insn "*ifcompare_move_neg"
8a18b90c 10517 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 10518 (if_then_else:SI
8fa3ba89 10519 (match_operator 5 "arm_comparison_operator"
8a18b90c 10520 [(match_operand:SI 3 "s_register_operand" "r,r")
10521 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10522 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
10523 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 10524 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10525 "TARGET_ARM"
8a18b90c 10526 "#"
8fa3ba89 10527 [(set_attr "conds" "clob")
1b7da4ac 10528 (set_attr "length" "8,12")
10529 (set_attr "type" "multiple")]
8fa3ba89 10530)
8a18b90c 10531
530bb693 10532(define_insn_and_split "*if_move_neg"
10533 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
8a18b90c 10534 (if_then_else:SI
8fa3ba89 10535 (match_operator 4 "arm_comparison_operator"
8a18b90c 10536 [(match_operand 3 "cc_register" "") (const_int 0)])
530bb693 10537 (match_operand:SI 1 "s_register_operand" "0,0")
10538 (neg:SI (match_operand:SI 2 "s_register_operand" "l,r"))))]
10539 "TARGET_32BIT"
10540 "#"
10541 "&& reload_completed"
10542 [(cond_exec (match_dup 5)
10543 (set (match_dup 0) (neg:SI (match_dup 2))))]
10544 {
10545 machine_mode mode = GET_MODE (operands[3]);
10546 rtx_code rc = GET_CODE (operands[4]);
10547
10548 if (mode == CCFPmode || mode == CCFPEmode)
10549 rc = reverse_condition_maybe_unordered (rc);
10550 else
10551 rc = reverse_condition (rc);
10552
10553 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[3], const0_rtx);
10554 }
0d66636f 10555 [(set_attr "conds" "use")
530bb693 10556 (set_attr "length" "4")
10557 (set_attr "arch" "t2,32")
10558 (set_attr "enabled_for_depr_it" "yes,no")
10559 (set_attr "type" "logic_shift_imm")]
0d66636f 10560)
9c08d1fa 10561
f7fbdd4a 10562(define_insn "*arith_adjacentmem"
9c08d1fa 10563 [(set (match_operand:SI 0 "s_register_operand" "=r")
10564 (match_operator:SI 1 "shiftable_operator"
10565 [(match_operand:SI 2 "memory_operand" "m")
10566 (match_operand:SI 3 "memory_operand" "m")]))
10567 (clobber (match_scratch:SI 4 "=r"))]
cffb2a26 10568 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9c08d1fa 10569 "*
215b30b3 10570 {
10571 rtx ldm[3];
10572 rtx arith[4];
94dee231 10573 rtx base_reg;
10574 HOST_WIDE_INT val1 = 0, val2 = 0;
9c08d1fa 10575
215b30b3 10576 if (REGNO (operands[0]) > REGNO (operands[4]))
10577 {
10578 ldm[1] = operands[4];
10579 ldm[2] = operands[0];
10580 }
10581 else
10582 {
10583 ldm[1] = operands[0];
10584 ldm[2] = operands[4];
10585 }
94dee231 10586
10587 base_reg = XEXP (operands[2], 0);
10588
10589 if (!REG_P (base_reg))
10590 {
10591 val1 = INTVAL (XEXP (base_reg, 1));
10592 base_reg = XEXP (base_reg, 0);
10593 }
10594
10595 if (!REG_P (XEXP (operands[3], 0)))
215b30b3 10596 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
94dee231 10597
215b30b3 10598 arith[0] = operands[0];
10599 arith[3] = operands[1];
94dee231 10600
215b30b3 10601 if (val1 < val2)
10602 {
10603 arith[1] = ldm[1];
10604 arith[2] = ldm[2];
10605 }
10606 else
10607 {
10608 arith[1] = ldm[2];
10609 arith[2] = ldm[1];
10610 }
94dee231 10611
10612 ldm[0] = base_reg;
10613 if (val1 !=0 && val2 != 0)
215b30b3 10614 {
cdb1295a 10615 rtx ops[3];
10616
94dee231 10617 if (val1 == 4 || val2 == 4)
10618 /* Other val must be 8, since we know they are adjacent and neither
10619 is zero. */
3ef90e77 10620 output_asm_insn (\"ldmib%?\\t%0, {%1, %2}\", ldm);
cdb1295a 10621 else if (const_ok_for_arm (val1) || const_ok_for_arm (-val1))
94dee231 10622 {
94dee231 10623 ldm[0] = ops[0] = operands[4];
10624 ops[1] = base_reg;
10625 ops[2] = GEN_INT (val1);
10626 output_add_immediate (ops);
10627 if (val1 < val2)
3ef90e77 10628 output_asm_insn (\"ldmia%?\\t%0, {%1, %2}\", ldm);
94dee231 10629 else
3ef90e77 10630 output_asm_insn (\"ldmda%?\\t%0, {%1, %2}\", ldm);
94dee231 10631 }
cdb1295a 10632 else
10633 {
10634 /* Offset is out of range for a single add, so use two ldr. */
10635 ops[0] = ldm[1];
10636 ops[1] = base_reg;
10637 ops[2] = GEN_INT (val1);
10638 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10639 ops[0] = ldm[2];
10640 ops[2] = GEN_INT (val2);
10641 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10642 }
215b30b3 10643 }
94dee231 10644 else if (val1 != 0)
215b30b3 10645 {
215b30b3 10646 if (val1 < val2)
3ef90e77 10647 output_asm_insn (\"ldmda%?\\t%0, {%1, %2}\", ldm);
215b30b3 10648 else
3ef90e77 10649 output_asm_insn (\"ldmia%?\\t%0, {%1, %2}\", ldm);
215b30b3 10650 }
10651 else
10652 {
215b30b3 10653 if (val1 < val2)
3ef90e77 10654 output_asm_insn (\"ldmia%?\\t%0, {%1, %2}\", ldm);
215b30b3 10655 else
3ef90e77 10656 output_asm_insn (\"ldmda%?\\t%0, {%1, %2}\", ldm);
215b30b3 10657 }
10658 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
10659 return \"\";
10660 }"
10661 [(set_attr "length" "12")
10662 (set_attr "predicable" "yes")
a2cd141b 10663 (set_attr "type" "load1")]
215b30b3 10664)
9c08d1fa 10665
9c08d1fa 10666; This pattern is never tried by combine, so do it as a peephole
10667
a0f94409 10668(define_peephole2
372575c7 10669 [(set (match_operand:SI 0 "arm_general_register_operand" "")
10670 (match_operand:SI 1 "arm_general_register_operand" ""))
bd5b4116 10671 (set (reg:CC CC_REGNUM)
aea4c774 10672 (compare:CC (match_dup 1) (const_int 0)))]
372575c7 10673 "TARGET_ARM"
a0f94409 10674 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
10675 (set (match_dup 0) (match_dup 1))])]
10676 ""
0d66636f 10677)
9c08d1fa 10678
9c08d1fa 10679(define_split
10680 [(set (match_operand:SI 0 "s_register_operand" "")
10681 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
10682 (const_int 0))
8fa3ba89 10683 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9c08d1fa 10684 [(match_operand:SI 3 "s_register_operand" "")
10685 (match_operand:SI 4 "arm_rhs_operand" "")]))))
10686 (clobber (match_operand:SI 5 "s_register_operand" ""))]
cffb2a26 10687 "TARGET_ARM"
9c08d1fa 10688 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
10689 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
10690 (match_dup 5)))]
215b30b3 10691 ""
10692)
9c08d1fa 10693
aea4c774 10694;; This split can be used because CC_Z mode implies that the following
10695;; branch will be an equality, or an unsigned inequality, so the sign
10696;; extension is not needed.
9c08d1fa 10697
aea4c774 10698(define_split
bd5b4116 10699 [(set (reg:CC_Z CC_REGNUM)
aea4c774 10700 (compare:CC_Z
10701 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9c08d1fa 10702 (const_int 24))
aea4c774 10703 (match_operand 1 "const_int_operand" "")))
10704 (clobber (match_scratch:SI 2 ""))]
cffb2a26 10705 "TARGET_ARM
8c4e8755 10706 && ((UINTVAL (operands[1]))
10707 == ((UINTVAL (operands[1])) >> 24) << 24)"
aea4c774 10708 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
bd5b4116 10709 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
aea4c774 10710 "
9c08d1fa 10711 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
215b30b3 10712 "
10713)
25f905c2 10714;; ??? Check the patterns above for Thumb-2 usefulness
9c08d1fa 10715
87b22bf7 10716(define_expand "prologue"
10717 [(clobber (const_int 0))]
cffb2a26 10718 "TARGET_EITHER"
25f905c2 10719 "if (TARGET_32BIT)
cffb2a26 10720 arm_expand_prologue ();
10721 else
25f905c2 10722 thumb1_expand_prologue ();
87b22bf7 10723 DONE;
cffb2a26 10724 "
10725)
87b22bf7 10726
56d27660 10727(define_expand "epilogue"
4c44712e 10728 [(clobber (const_int 0))]
cffb2a26 10729 "TARGET_EITHER"
56d27660 10730 "
18d50ae6 10731 if (crtl->calls_eh_return)
fb94f18b 10732 emit_insn (gen_force_register_use (gen_rtx_REG (Pmode, 2)));
25f905c2 10733 if (TARGET_THUMB1)
c3635784 10734 {
10735 thumb1_expand_epilogue ();
10736 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
10737 gen_rtvec (1, ret_rtx), VUNSPEC_EPILOGUE));
10738 }
10739 else if (HAVE_return)
10740 {
10741 /* HAVE_return is testing for USE_RETURN_INSN (FALSE). Hence,
10742 no need for explicit testing again. */
10743 emit_jump_insn (gen_return ());
10744 }
10745 else if (TARGET_32BIT)
10746 {
10747 arm_expand_epilogue (true);
10748 }
cffb2a26 10749 DONE;
10750 "
10751)
56d27660 10752
ef5651d0 10753;; Note - although unspec_volatile's USE all hard registers,
10754;; USEs are ignored after relaod has completed. Thus we need
10755;; to add an unspec of the link register to ensure that flow
10756;; does not think that it is unused by the sibcall branch that
10757;; will replace the standard function epilogue.
c3635784 10758(define_expand "sibcall_epilogue"
fb94f18b 10759 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_REGISTER_USE)
c3635784 10760 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
10761 "TARGET_32BIT"
10762 "
10763 arm_expand_epilogue (false);
10764 DONE;
10765 "
1c494086 10766)
10767
cffb2a26 10768(define_expand "eh_epilogue"
7db9af5d 10769 [(use (match_operand:SI 0 "register_operand" ""))
10770 (use (match_operand:SI 1 "register_operand" ""))
10771 (use (match_operand:SI 2 "register_operand" ""))]
cffb2a26 10772 "TARGET_EITHER"
10773 "
215b30b3 10774 {
10775 cfun->machine->eh_epilogue_sp_ofs = operands[1];
0438d37f 10776 if (!REG_P (operands[2]) || REGNO (operands[2]) != 2)
215b30b3 10777 {
10778 rtx ra = gen_rtx_REG (Pmode, 2);
10779
10780 emit_move_insn (ra, operands[2]);
10781 operands[2] = ra;
10782 }
5cf3595a 10783 /* This is a hack -- we may have crystalized the function type too
10784 early. */
10785 cfun->machine->func_type = 0;
215b30b3 10786 }"
10787)
56d27660 10788
9c08d1fa 10789;; This split is only used during output to reduce the number of patterns
10790;; that need assembler instructions adding to them. We allowed the setting
10791;; of the conditions to be implicit during rtl generation so that
10792;; the conditional compare patterns would work. However this conflicts to
8a18b90c 10793;; some extent with the conditional data operations, so we have to split them
9c08d1fa 10794;; up again here.
10795
25f905c2 10796;; ??? Need to audit these splitters for Thumb-2. Why isn't normal
10797;; conditional execution sufficient?
10798
9c08d1fa 10799(define_split
10800 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 10801 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10802 [(match_operand 2 "" "") (match_operand 3 "" "")])
10803 (match_dup 0)
10804 (match_operand 4 "" "")))
bd5b4116 10805 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10806 "TARGET_ARM && reload_completed"
8fa3ba89 10807 [(set (match_dup 5) (match_dup 6))
10808 (cond_exec (match_dup 7)
10809 (set (match_dup 0) (match_dup 4)))]
10810 "
10811 {
3754d046 10812 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8fa3ba89 10813 operands[2], operands[3]);
10814 enum rtx_code rc = GET_CODE (operands[1]);
10815
bd5b4116 10816 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10817 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10818 if (mode == CCFPmode || mode == CCFPEmode)
10819 rc = reverse_condition_maybe_unordered (rc);
10820 else
10821 rc = reverse_condition (rc);
10822
10823 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
10824 }"
10825)
10826
10827(define_split
10828 [(set (match_operand:SI 0 "s_register_operand" "")
10829 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10830 [(match_operand 2 "" "") (match_operand 3 "" "")])
10831 (match_operand 4 "" "")
10832 (match_dup 0)))
bd5b4116 10833 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10834 "TARGET_ARM && reload_completed"
8fa3ba89 10835 [(set (match_dup 5) (match_dup 6))
10836 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
10837 (set (match_dup 0) (match_dup 4)))]
10838 "
10839 {
3754d046 10840 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8fa3ba89 10841 operands[2], operands[3]);
10842
bd5b4116 10843 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10844 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10845 }"
10846)
10847
10848(define_split
10849 [(set (match_operand:SI 0 "s_register_operand" "")
10850 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9c08d1fa 10851 [(match_operand 2 "" "") (match_operand 3 "" "")])
10852 (match_operand 4 "" "")
10853 (match_operand 5 "" "")))
bd5b4116 10854 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10855 "TARGET_ARM && reload_completed"
8fa3ba89 10856 [(set (match_dup 6) (match_dup 7))
10857 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10858 (set (match_dup 0) (match_dup 4)))
10859 (cond_exec (match_dup 8)
10860 (set (match_dup 0) (match_dup 5)))]
10861 "
10862 {
3754d046 10863 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8fa3ba89 10864 operands[2], operands[3]);
10865 enum rtx_code rc = GET_CODE (operands[1]);
10866
bd5b4116 10867 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10868 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10869 if (mode == CCFPmode || mode == CCFPEmode)
10870 rc = reverse_condition_maybe_unordered (rc);
10871 else
10872 rc = reverse_condition (rc);
10873
10874 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10875 }"
10876)
10877
cffb2a26 10878(define_split
10879 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 10880 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
cffb2a26 10881 [(match_operand:SI 2 "s_register_operand" "")
10882 (match_operand:SI 3 "arm_add_operand" "")])
10883 (match_operand:SI 4 "arm_rhs_operand" "")
10884 (not:SI
10885 (match_operand:SI 5 "s_register_operand" ""))))
bd5b4116 10886 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10887 "TARGET_ARM && reload_completed"
cffb2a26 10888 [(set (match_dup 6) (match_dup 7))
f6c53574 10889 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10890 (set (match_dup 0) (match_dup 4)))
10891 (cond_exec (match_dup 8)
10892 (set (match_dup 0) (not:SI (match_dup 5))))]
cffb2a26 10893 "
215b30b3 10894 {
3754d046 10895 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
215b30b3 10896 operands[2], operands[3]);
f6c53574 10897 enum rtx_code rc = GET_CODE (operands[1]);
cffb2a26 10898
bd5b4116 10899 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
1a83b3ff 10900 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
f6c53574 10901 if (mode == CCFPmode || mode == CCFPEmode)
10902 rc = reverse_condition_maybe_unordered (rc);
10903 else
10904 rc = reverse_condition (rc);
10905
10906 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
215b30b3 10907 }"
10908)
cffb2a26 10909
10910(define_insn "*cond_move_not"
10911 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10912 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
cffb2a26 10913 [(match_operand 3 "cc_register" "") (const_int 0)])
10914 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10915 (not:SI
10916 (match_operand:SI 2 "s_register_operand" "r,r"))))]
10917 "TARGET_ARM"
10918 "@
10919 mvn%D4\\t%0, %2
10920 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
0d66636f 10921 [(set_attr "conds" "use")
1b7da4ac 10922 (set_attr "type" "mvn_reg,multiple")
0d66636f 10923 (set_attr "length" "4,8")]
10924)
cffb2a26 10925
9c08d1fa 10926;; The next two patterns occur when an AND operation is followed by a
10927;; scc insn sequence
10928
f7fbdd4a 10929(define_insn "*sign_extract_onebit"
9c08d1fa 10930 [(set (match_operand:SI 0 "s_register_operand" "=r")
10931 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10932 (const_int 1)
ed750274 10933 (match_operand:SI 2 "const_int_operand" "n")))
10934 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10935 "TARGET_ARM"
9c08d1fa 10936 "*
0d66636f 10937 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10938 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
10939 return \"mvnne\\t%0, #0\";
10940 "
10941 [(set_attr "conds" "clob")
1b7da4ac 10942 (set_attr "length" "8")
10943 (set_attr "type" "multiple")]
0d66636f 10944)
9c08d1fa 10945
f7fbdd4a 10946(define_insn "*not_signextract_onebit"
9c08d1fa 10947 [(set (match_operand:SI 0 "s_register_operand" "=r")
10948 (not:SI
10949 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10950 (const_int 1)
ed750274 10951 (match_operand:SI 2 "const_int_operand" "n"))))
10952 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10953 "TARGET_ARM"
9c08d1fa 10954 "*
0d66636f 10955 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10956 output_asm_insn (\"tst\\t%1, %2\", operands);
10957 output_asm_insn (\"mvneq\\t%0, #0\", operands);
10958 return \"movne\\t%0, #0\";
10959 "
10960 [(set_attr "conds" "clob")
1b7da4ac 10961 (set_attr "length" "12")
10962 (set_attr "type" "multiple")]
0d66636f 10963)
25f905c2 10964;; ??? The above patterns need auditing for Thumb-2
87b22bf7 10965
0d66636f 10966;; Push multiple registers to the stack. Registers are in parallel (use ...)
10967;; expressions. For simplicity, the first register is also in the unspec
10968;; part.
08508cbf 10969;; To avoid the usage of GNU extension, the length attribute is computed
10970;; in a C function arm_attr_length_push_multi.
f7fbdd4a 10971(define_insn "*push_multi"
87b22bf7 10972 [(match_parallel 2 "multi_register_push"
7571d3f7 10973 [(set (match_operand:BLK 0 "push_mult_memory_operand" "")
3cc80a30 10974 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "")]
e1159bbe 10975 UNSPEC_PUSH_MULT))])]
7571d3f7 10976 ""
87b22bf7 10977 "*
215b30b3 10978 {
10979 int num_saves = XVECLEN (operands[2], 0);
ed593f11 10980
215b30b3 10981 /* For the StrongARM at least it is faster to
25f905c2 10982 use STR to store only a single register.
542d5028 10983 In Thumb mode always use push, and the assembler will pick
10984 something appropriate. */
25f905c2 10985 if (num_saves == 1 && TARGET_ARM)
61309563 10986 output_asm_insn (\"str%?\\t%1, [%m0, #-4]!\", operands);
215b30b3 10987 else
10988 {
10989 int i;
10990 char pattern[100];
ed593f11 10991
3ef90e77 10992 if (TARGET_32BIT)
61309563 10993 strcpy (pattern, \"push%?\\t{%1\");
25f905c2 10994 else
10995 strcpy (pattern, \"push\\t{%1\");
215b30b3 10996
6079f055 10997 for (i = 1; i < num_saves; i++)
215b30b3 10998 {
10999 strcat (pattern, \", %|\");
11000 strcat (pattern,
11001 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
11002 }
11003
11004 strcat (pattern, \"}\");
11005 output_asm_insn (pattern, operands);
11006 }
11007
11008 return \"\";
11009 }"
a6864a24 11010 [(set_attr "type" "store4")
11011 (set (attr "length")
08508cbf 11012 (symbol_ref "arm_attr_length_push_multi (operands[2], operands[1])"))]
215b30b3 11013)
f7fbdd4a 11014
4c58c898 11015(define_insn "stack_tie"
11016 [(set (mem:BLK (scratch))
aaa37ad6 11017 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "rk")
11018 (match_operand:SI 1 "s_register_operand" "rk")]
4c58c898 11019 UNSPEC_PRLG_STK))]
11020 ""
11021 ""
1b7da4ac 11022 [(set_attr "length" "0")
11023 (set_attr "type" "block")]
4c58c898 11024)
11025
426be8c5 11026;; Pop (as used in epilogue RTL)
11027;;
11028(define_insn "*load_multiple_with_writeback"
11029 [(match_parallel 0 "load_multiple_operation"
11030 [(set (match_operand:SI 1 "s_register_operand" "+rk")
11031 (plus:SI (match_dup 1)
809003b3 11032 (match_operand:SI 2 "const_int_I_operand" "I")))
426be8c5 11033 (set (match_operand:SI 3 "s_register_operand" "=rk")
11034 (mem:SI (match_dup 1)))
11035 ])]
11036 "TARGET_32BIT && (reload_in_progress || reload_completed)"
11037 "*
11038 {
11039 arm_output_multireg_pop (operands, /*return_pc=*/false,
11040 /*cond=*/const_true_rtx,
11041 /*reverse=*/false,
11042 /*update=*/true);
11043 return \"\";
11044 }
11045 "
11046 [(set_attr "type" "load4")
5431c9c9 11047 (set_attr "predicable" "yes")
11048 (set (attr "length")
11049 (symbol_ref "arm_attr_length_pop_multi (operands,
11050 /*return_pc=*/false,
11051 /*write_back_p=*/true)"))]
426be8c5 11052)
11053
11054;; Pop with return (as used in epilogue RTL)
11055;;
11056;; This instruction is generated when the registers are popped at the end of
11057;; epilogue. Here, instead of popping the value into LR and then generating
11058;; jump to LR, value is popped into PC directly. Hence, the pattern is combined
11059;; with (return).
11060(define_insn "*pop_multiple_with_writeback_and_return"
11061 [(match_parallel 0 "pop_multiple_return"
11062 [(return)
11063 (set (match_operand:SI 1 "s_register_operand" "+rk")
11064 (plus:SI (match_dup 1)
809003b3 11065 (match_operand:SI 2 "const_int_I_operand" "I")))
426be8c5 11066 (set (match_operand:SI 3 "s_register_operand" "=rk")
11067 (mem:SI (match_dup 1)))
11068 ])]
11069 "TARGET_32BIT && (reload_in_progress || reload_completed)"
11070 "*
11071 {
11072 arm_output_multireg_pop (operands, /*return_pc=*/true,
11073 /*cond=*/const_true_rtx,
11074 /*reverse=*/false,
11075 /*update=*/true);
11076 return \"\";
11077 }
11078 "
11079 [(set_attr "type" "load4")
5431c9c9 11080 (set_attr "predicable" "yes")
11081 (set (attr "length")
11082 (symbol_ref "arm_attr_length_pop_multi (operands, /*return_pc=*/true,
11083 /*write_back_p=*/true)"))]
426be8c5 11084)
11085
11086(define_insn "*pop_multiple_with_return"
11087 [(match_parallel 0 "pop_multiple_return"
11088 [(return)
11089 (set (match_operand:SI 2 "s_register_operand" "=rk")
11090 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
11091 ])]
11092 "TARGET_32BIT && (reload_in_progress || reload_completed)"
11093 "*
11094 {
11095 arm_output_multireg_pop (operands, /*return_pc=*/true,
11096 /*cond=*/const_true_rtx,
11097 /*reverse=*/false,
11098 /*update=*/false);
11099 return \"\";
11100 }
11101 "
11102 [(set_attr "type" "load4")
5431c9c9 11103 (set_attr "predicable" "yes")
11104 (set (attr "length")
11105 (symbol_ref "arm_attr_length_pop_multi (operands, /*return_pc=*/true,
11106 /*write_back_p=*/false)"))]
426be8c5 11107)
11108
11109;; Load into PC and return
11110(define_insn "*ldr_with_return"
11111 [(return)
11112 (set (reg:SI PC_REGNUM)
11113 (mem:SI (post_inc:SI (match_operand:SI 0 "s_register_operand" "+rk"))))]
11114 "TARGET_32BIT && (reload_in_progress || reload_completed)"
11115 "ldr%?\t%|pc, [%0], #4"
11116 [(set_attr "type" "load1")
11117 (set_attr "predicable" "yes")]
11118)
1a0b0f12 11119;; Pop for floating point registers (as used in epilogue RTL)
11120(define_insn "*vfp_pop_multiple_with_writeback"
11121 [(match_parallel 0 "pop_multiple_fp"
11122 [(set (match_operand:SI 1 "s_register_operand" "+rk")
11123 (plus:SI (match_dup 1)
809003b3 11124 (match_operand:SI 2 "const_int_I_operand" "I")))
2f2163a4 11125 (set (match_operand:DF 3 "vfp_hard_register_operand" "")
1a0b0f12 11126 (mem:DF (match_dup 1)))])]
d7216193 11127 "TARGET_32BIT && TARGET_HARD_FLOAT"
1a0b0f12 11128 "*
11129 {
11130 int num_regs = XVECLEN (operands[0], 0);
11131 char pattern[100];
11132 rtx op_list[2];
b34d8dac 11133 strcpy (pattern, \"vldm\\t\");
1a0b0f12 11134 strcat (pattern, reg_names[REGNO (SET_DEST (XVECEXP (operands[0], 0, 0)))]);
11135 strcat (pattern, \"!, {\");
11136 op_list[0] = XEXP (XVECEXP (operands[0], 0, 1), 0);
11137 strcat (pattern, \"%P0\");
11138 if ((num_regs - 1) > 1)
11139 {
11140 strcat (pattern, \"-%P1\");
11141 op_list [1] = XEXP (XVECEXP (operands[0], 0, num_regs - 1), 0);
11142 }
11143
11144 strcat (pattern, \"}\");
11145 output_asm_insn (pattern, op_list);
11146 return \"\";
11147 }
11148 "
11149 [(set_attr "type" "load4")
11150 (set_attr "conds" "unconditional")
11151 (set_attr "predicable" "no")]
11152)
11153
f7fbdd4a 11154;; Special patterns for dealing with the constant pool
11155
cffb2a26 11156(define_insn "align_4"
e1159bbe 11157 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
cffb2a26 11158 "TARGET_EITHER"
f7fbdd4a 11159 "*
cffb2a26 11160 assemble_align (32);
f7fbdd4a 11161 return \"\";
cffb2a26 11162 "
1b7da4ac 11163 [(set_attr "type" "no_insn")]
cffb2a26 11164)
f7fbdd4a 11165
755eb2b4 11166(define_insn "align_8"
11167 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
f9273c43 11168 "TARGET_EITHER"
755eb2b4 11169 "*
11170 assemble_align (64);
11171 return \"\";
11172 "
1b7da4ac 11173 [(set_attr "type" "no_insn")]
755eb2b4 11174)
11175
cffb2a26 11176(define_insn "consttable_end"
e1159bbe 11177 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
cffb2a26 11178 "TARGET_EITHER"
f7fbdd4a 11179 "*
cffb2a26 11180 making_const_table = FALSE;
f7fbdd4a 11181 return \"\";
cffb2a26 11182 "
1b7da4ac 11183 [(set_attr "type" "no_insn")]
cffb2a26 11184)
f7fbdd4a 11185
0e207eb8 11186(define_insn "consttable_1"
11187 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
11188 "TARGET_EITHER"
11189 "*
11190 making_const_table = TRUE;
11191 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
11192 assemble_zeros (3);
11193 return \"\";
11194 "
11195 [(set_attr "length" "4")
11196 (set_attr "type" "no_insn")]
11197)
11198
11199(define_insn "consttable_2"
11200 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
11201 "TARGET_EITHER"
11202 "*
11203 {
11204 rtx x = operands[0];
11205 making_const_table = TRUE;
11206 switch (GET_MODE_CLASS (GET_MODE (x)))
11207 {
11208 case MODE_FLOAT:
11209 arm_emit_fp16_const (x);
11210 break;
11211 default:
11212 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
11213 assemble_zeros (2);
11214 break;
11215 }
11216 return \"\";
11217 }"
11218 [(set_attr "length" "4")
11219 (set_attr "type" "no_insn")]
11220)
11221
cffb2a26 11222(define_insn "consttable_4"
e1159bbe 11223 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
cffb2a26 11224 "TARGET_EITHER"
11225 "*
11226 {
9b8516be 11227 rtx x = operands[0];
cffb2a26 11228 making_const_table = TRUE;
9b8516be 11229 switch (GET_MODE_CLASS (GET_MODE (x)))
cffb2a26 11230 {
11231 case MODE_FLOAT:
945f7b03 11232 assemble_real (*CONST_DOUBLE_REAL_VALUE (x), GET_MODE (x),
11233 BITS_PER_WORD);
11234 break;
cffb2a26 11235 default:
7b04c5d5 11236 /* XXX: Sometimes gcc does something really dumb and ends up with
11237 a HIGH in a constant pool entry, usually because it's trying to
11238 load into a VFP register. We know this will always be used in
11239 combination with a LO_SUM which ignores the high bits, so just
11240 strip off the HIGH. */
11241 if (GET_CODE (x) == HIGH)
11242 x = XEXP (x, 0);
9b8516be 11243 assemble_integer (x, 4, BITS_PER_WORD, 1);
11244 mark_symbol_refs_as_used (x);
cffb2a26 11245 break;
11246 }
11247 return \"\";
11248 }"
1b7da4ac 11249 [(set_attr "length" "4")
11250 (set_attr "type" "no_insn")]
cffb2a26 11251)
11252
11253(define_insn "consttable_8"
e1159bbe 11254 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
cffb2a26 11255 "TARGET_EITHER"
11256 "*
11257 {
11258 making_const_table = TRUE;
11259 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
11260 {
945f7b03 11261 case MODE_FLOAT:
11262 assemble_real (*CONST_DOUBLE_REAL_VALUE (operands[0]),
11263 GET_MODE (operands[0]), BITS_PER_WORD);
11264 break;
cffb2a26 11265 default:
09d688ff 11266 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
cffb2a26 11267 break;
11268 }
11269 return \"\";
11270 }"
1b7da4ac 11271 [(set_attr "length" "8")
11272 (set_attr "type" "no_insn")]
cffb2a26 11273)
11274
d98a3884 11275(define_insn "consttable_16"
11276 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_16)]
11277 "TARGET_EITHER"
11278 "*
11279 {
11280 making_const_table = TRUE;
11281 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
11282 {
945f7b03 11283 case MODE_FLOAT:
11284 assemble_real (*CONST_DOUBLE_REAL_VALUE (operands[0]),
11285 GET_MODE (operands[0]), BITS_PER_WORD);
11286 break;
d98a3884 11287 default:
11288 assemble_integer (operands[0], 16, BITS_PER_WORD, 1);
11289 break;
11290 }
11291 return \"\";
11292 }"
1b7da4ac 11293 [(set_attr "length" "16")
11294 (set_attr "type" "no_insn")]
d98a3884 11295)
11296
331beb1a 11297;; V5 Instructions,
11298
8f4be2be 11299(define_insn "clzsi2"
11300 [(set (match_operand:SI 0 "s_register_operand" "=r")
11301 (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 11302 "TARGET_32BIT && arm_arch5"
ee7cbe0e 11303 "clz%?\\t%0, %1"
bcaec148 11304 [(set_attr "predicable" "yes")
4a510717 11305 (set_attr "predicable_short_it" "no")
bebe9bbb 11306 (set_attr "type" "clz")])
331beb1a 11307
099ad98b 11308(define_insn "rbitsi2"
11309 [(set (match_operand:SI 0 "s_register_operand" "=r")
11310 (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")] UNSPEC_RBIT))]
11311 "TARGET_32BIT && arm_arch_thumb2"
11312 "rbit%?\\t%0, %1"
11313 [(set_attr "predicable" "yes")
4a510717 11314 (set_attr "predicable_short_it" "no")
bebe9bbb 11315 (set_attr "type" "clz")])
099ad98b 11316
99ffa689 11317;; Keep this as a CTZ expression until after reload and then split
11318;; into RBIT + CLZ. Since RBIT is represented as an UNSPEC it is unlikely
11319;; to fold with any other expression.
11320
11321(define_insn_and_split "ctzsi2"
11322 [(set (match_operand:SI 0 "s_register_operand" "=r")
11323 (ctz:SI (match_operand:SI 1 "s_register_operand" "r")))]
099ad98b 11324 "TARGET_32BIT && arm_arch_thumb2"
99ffa689 11325 "#"
11326 "&& reload_completed"
11327 [(const_int 0)]
099ad98b 11328 "
99ffa689 11329 emit_insn (gen_rbitsi2 (operands[0], operands[1]));
11330 emit_insn (gen_clzsi2 (operands[0], operands[0]));
11331 DONE;
11332")
099ad98b 11333
e1159bbe 11334;; V5E instructions.
331beb1a 11335
11336(define_insn "prefetch"
f4e79814 11337 [(prefetch (match_operand:SI 0 "address_operand" "p")
11338 (match_operand:SI 1 "" "")
11339 (match_operand:SI 2 "" ""))]
25f905c2 11340 "TARGET_32BIT && arm_arch5e"
1b7da4ac 11341 "pld\\t%a0"
11342 [(set_attr "type" "load1")]
11343)
331beb1a 11344
0d66636f 11345;; General predication pattern
11346
11347(define_cond_exec
11348 [(match_operator 0 "arm_comparison_operator"
11349 [(match_operand 1 "cc_register" "")
11350 (const_int 0)])]
580f4c48 11351 "TARGET_32BIT
11352 && (!TARGET_NO_VOLATILE_CE || !volatile_refs_p (PATTERN (insn)))"
0d66636f 11353 ""
c7a58118 11354[(set_attr "predicated" "yes")]
0d66636f 11355)
11356
fb94f18b 11357(define_insn "force_register_use"
11358 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_REGISTER_USE)]
063a05c7 11359 ""
fb94f18b 11360 "%@ %0 needed"
1b7da4ac 11361 [(set_attr "length" "0")
11362 (set_attr "type" "no_insn")]
063a05c7 11363)
7db9af5d 11364
4c44712e 11365
11366;; Patterns for exception handling
11367
11368(define_expand "eh_return"
11369 [(use (match_operand 0 "general_operand" ""))]
11370 "TARGET_EITHER"
11371 "
11372 {
25f905c2 11373 if (TARGET_32BIT)
4c44712e 11374 emit_insn (gen_arm_eh_return (operands[0]));
11375 else
11376 emit_insn (gen_thumb_eh_return (operands[0]));
11377 DONE;
11378 }"
11379)
11380
11381;; We can't expand this before we know where the link register is stored.
11382(define_insn_and_split "arm_eh_return"
11383 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
11384 VUNSPEC_EH_RETURN)
11385 (clobber (match_scratch:SI 1 "=&r"))]
11386 "TARGET_ARM"
11387 "#"
11388 "&& reload_completed"
11389 [(const_int 0)]
11390 "
11391 {
11392 arm_set_return_address (operands[0], operands[1]);
11393 DONE;
11394 }"
11395)
11396
f655717d 11397\f
11398;; TLS support
11399
11400(define_insn "load_tp_hard"
11401 [(set (match_operand:SI 0 "register_operand" "=r")
11402 (unspec:SI [(const_int 0)] UNSPEC_TLS))]
11403 "TARGET_HARD_TP"
11404 "mrc%?\\tp15, 0, %0, c13, c0, 3\\t@ load_tp_hard"
1b7da4ac 11405 [(set_attr "predicable" "yes")
4b5d7374 11406 (set_attr "type" "mrs")]
f655717d 11407)
11408
11409;; Doesn't clobber R1-R3. Must use r0 for the first operand.
11410(define_insn "load_tp_soft"
11411 [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
11412 (clobber (reg:SI LR_REGNUM))
11413 (clobber (reg:SI IP_REGNUM))
11414 (clobber (reg:CC CC_REGNUM))]
11415 "TARGET_SOFT_TP"
11416 "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
1b7da4ac 11417 [(set_attr "conds" "clob")
11418 (set_attr "type" "branch")]
f655717d 11419)
11420
f41e4452 11421;; tls descriptor call
11422(define_insn "tlscall"
11423 [(set (reg:SI R0_REGNUM)
11424 (unspec:SI [(reg:SI R0_REGNUM)
11425 (match_operand:SI 0 "" "X")
11426 (match_operand 1 "" "")] UNSPEC_TLS))
11427 (clobber (reg:SI R1_REGNUM))
11428 (clobber (reg:SI LR_REGNUM))
11429 (clobber (reg:SI CC_REGNUM))]
11430 "TARGET_GNU2_TLS"
11431 {
11432 targetm.asm_out.internal_label (asm_out_file, "LPIC",
11433 INTVAL (operands[1]));
11434 return "bl\\t%c0(tlscall)";
11435 }
11436 [(set_attr "conds" "clob")
1b7da4ac 11437 (set_attr "length" "4")
11438 (set_attr "type" "branch")]
f41e4452 11439)
11440
1fe0edab 11441;; For thread pointer builtin
11442(define_expand "get_thread_pointersi"
11443 [(match_operand:SI 0 "s_register_operand" "=r")]
11444 ""
11445 "
11446 {
11447 arm_load_tp (operands[0]);
11448 DONE;
11449 }")
11450
f41e4452 11451;;
11452
aabe09ac 11453;; We only care about the lower 16 bits of the constant
11454;; being inserted into the upper 16 bits of the register.
eca5c984 11455(define_insn "*arm_movtas_ze"
417e5cc5 11456 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r,r")
eca5c984 11457 (const_int 16)
11458 (const_int 16))
11459 (match_operand:SI 1 "const_int_operand" ""))]
60a48e7d 11460 "TARGET_HAVE_MOVT"
417e5cc5 11461 "@
11462 movt%?\t%0, %L1
11463 movt\t%0, %L1"
11464 [(set_attr "arch" "32,v8mb")
11465 (set_attr "predicable" "yes")
7c36fe71 11466 (set_attr "predicable_short_it" "no")
1b7da4ac 11467 (set_attr "length" "4")
282b4c75 11468 (set_attr "type" "alu_sreg")]
eca5c984 11469)
11470
c0fc3696 11471(define_insn "*arm_rev"
a486b499 11472 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
11473 (bswap:SI (match_operand:SI 1 "s_register_operand" "l,l,r")))]
11474 "arm_arch6"
11475 "@
11476 rev\t%0, %1
11477 rev%?\t%0, %1
11478 rev%?\t%0, %1"
11479 [(set_attr "arch" "t1,t2,32")
1b7da4ac 11480 (set_attr "length" "2,2,4")
4a510717 11481 (set_attr "predicable" "no,yes,yes")
11482 (set_attr "predicable_short_it" "no")
1b7da4ac 11483 (set_attr "type" "rev")]
ff82f757 11484)
11485
11486(define_expand "arm_legacy_rev"
11487 [(set (match_operand:SI 2 "s_register_operand" "")
11488 (xor:SI (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
11489 (const_int 16))
11490 (match_dup 1)))
11491 (set (match_dup 2)
11492 (lshiftrt:SI (match_dup 2)
11493 (const_int 8)))
11494 (set (match_operand:SI 3 "s_register_operand" "")
11495 (rotatert:SI (match_dup 1)
11496 (const_int 8)))
11497 (set (match_dup 2)
11498 (and:SI (match_dup 2)
11499 (const_int -65281)))
11500 (set (match_operand:SI 0 "s_register_operand" "")
11501 (xor:SI (match_dup 3)
11502 (match_dup 2)))]
11503 "TARGET_32BIT"
11504 ""
11505)
11506
11507;; Reuse temporaries to keep register pressure down.
11508(define_expand "thumb_legacy_rev"
11509 [(set (match_operand:SI 2 "s_register_operand" "")
11510 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
11511 (const_int 24)))
11512 (set (match_operand:SI 3 "s_register_operand" "")
11513 (lshiftrt:SI (match_dup 1)
11514 (const_int 24)))
11515 (set (match_dup 3)
11516 (ior:SI (match_dup 3)
11517 (match_dup 2)))
11518 (set (match_operand:SI 4 "s_register_operand" "")
11519 (const_int 16))
11520 (set (match_operand:SI 5 "s_register_operand" "")
11521 (rotatert:SI (match_dup 1)
11522 (match_dup 4)))
11523 (set (match_dup 2)
11524 (ashift:SI (match_dup 5)
11525 (const_int 24)))
11526 (set (match_dup 5)
11527 (lshiftrt:SI (match_dup 5)
11528 (const_int 24)))
11529 (set (match_dup 5)
11530 (ior:SI (match_dup 5)
11531 (match_dup 2)))
11532 (set (match_dup 5)
11533 (rotatert:SI (match_dup 5)
11534 (match_dup 4)))
11535 (set (match_operand:SI 0 "s_register_operand" "")
11536 (ior:SI (match_dup 5)
11537 (match_dup 3)))]
11538 "TARGET_THUMB"
11539 ""
11540)
11541
62e39b06 11542;; ARM-specific expansion of signed mod by power of 2
11543;; using conditional negate.
11544;; For r0 % n where n is a power of 2 produce:
11545;; rsbs r1, r0, #0
11546;; and r0, r0, #(n - 1)
11547;; and r1, r1, #(n - 1)
11548;; rsbpl r0, r1, #0
11549
11550(define_expand "modsi3"
11551 [(match_operand:SI 0 "register_operand" "")
11552 (match_operand:SI 1 "register_operand" "")
11553 (match_operand:SI 2 "const_int_operand" "")]
11554 "TARGET_32BIT"
11555 {
11556 HOST_WIDE_INT val = INTVAL (operands[2]);
11557
11558 if (val <= 0
11559 || exact_log2 (val) <= 0)
11560 FAIL;
11561
11562 rtx mask = GEN_INT (val - 1);
11563
11564 /* In the special case of x0 % 2 we can do the even shorter:
11565 cmp r0, #0
11566 and r0, r0, #1
11567 rsblt r0, r0, #0. */
11568
11569 if (val == 2)
11570 {
11571 rtx cc_reg = arm_gen_compare_reg (LT,
11572 operands[1], const0_rtx, NULL_RTX);
11573 rtx cond = gen_rtx_LT (SImode, cc_reg, const0_rtx);
11574 rtx masked = gen_reg_rtx (SImode);
11575
11576 emit_insn (gen_andsi3 (masked, operands[1], mask));
11577 emit_move_insn (operands[0],
11578 gen_rtx_IF_THEN_ELSE (SImode, cond,
11579 gen_rtx_NEG (SImode,
11580 masked),
11581 masked));
11582 DONE;
11583 }
11584
11585 rtx neg_op = gen_reg_rtx (SImode);
11586 rtx_insn *insn = emit_insn (gen_subsi3_compare0 (neg_op, const0_rtx,
11587 operands[1]));
11588
11589 /* Extract the condition register and mode. */
11590 rtx cmp = XVECEXP (PATTERN (insn), 0, 0);
11591 rtx cc_reg = SET_DEST (cmp);
11592 rtx cond = gen_rtx_GE (SImode, cc_reg, const0_rtx);
11593
11594 emit_insn (gen_andsi3 (operands[0], operands[1], mask));
11595
11596 rtx masked_neg = gen_reg_rtx (SImode);
11597 emit_insn (gen_andsi3 (masked_neg, neg_op, mask));
11598
11599 /* We want a conditional negate here, but emitting COND_EXEC rtxes
11600 during expand does not always work. Do an IF_THEN_ELSE instead. */
11601 emit_move_insn (operands[0],
11602 gen_rtx_IF_THEN_ELSE (SImode, cond,
11603 gen_rtx_NEG (SImode, masked_neg),
11604 operands[0]));
11605
11606
11607 DONE;
11608 }
11609)
11610
ff82f757 11611(define_expand "bswapsi2"
11612 [(set (match_operand:SI 0 "s_register_operand" "=r")
11613 (bswap:SI (match_operand:SI 1 "s_register_operand" "r")))]
8d1af482 11614"TARGET_EITHER && (arm_arch6 || !optimize_size)"
ff82f757 11615"
8d1af482 11616 if (!arm_arch6)
11617 {
11618 rtx op2 = gen_reg_rtx (SImode);
11619 rtx op3 = gen_reg_rtx (SImode);
ff82f757 11620
8d1af482 11621 if (TARGET_THUMB)
11622 {
11623 rtx op4 = gen_reg_rtx (SImode);
11624 rtx op5 = gen_reg_rtx (SImode);
ff82f757 11625
8d1af482 11626 emit_insn (gen_thumb_legacy_rev (operands[0], operands[1],
11627 op2, op3, op4, op5));
11628 }
11629 else
11630 {
11631 emit_insn (gen_arm_legacy_rev (operands[0], operands[1],
11632 op2, op3));
11633 }
ff82f757 11634
8d1af482 11635 DONE;
11636 }
ff82f757 11637 "
11638)
11639
a486b499 11640;; bswap16 patterns: use revsh and rev16 instructions for the signed
11641;; and unsigned variants, respectively. For rev16, expose
11642;; byte-swapping in the lower 16 bits only.
11643(define_insn "*arm_revsh"
11644 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
11645 (sign_extend:SI (bswap:HI (match_operand:HI 1 "s_register_operand" "l,l,r"))))]
11646 "arm_arch6"
11647 "@
11648 revsh\t%0, %1
11649 revsh%?\t%0, %1
11650 revsh%?\t%0, %1"
11651 [(set_attr "arch" "t1,t2,32")
1b7da4ac 11652 (set_attr "length" "2,2,4")
11653 (set_attr "type" "rev")]
a486b499 11654)
11655
11656(define_insn "*arm_rev16"
11657 [(set (match_operand:HI 0 "s_register_operand" "=l,l,r")
11658 (bswap:HI (match_operand:HI 1 "s_register_operand" "l,l,r")))]
11659 "arm_arch6"
11660 "@
11661 rev16\t%0, %1
11662 rev16%?\t%0, %1
11663 rev16%?\t%0, %1"
11664 [(set_attr "arch" "t1,t2,32")
1b7da4ac 11665 (set_attr "length" "2,2,4")
11666 (set_attr "type" "rev")]
09f69e55 11667)
11668
11669;; There are no canonicalisation rules for the position of the lshiftrt, ashift
11670;; operations within an IOR/AND RTX, therefore we have two patterns matching
11671;; each valid permutation.
11672
11673(define_insn "arm_rev16si2"
11674 [(set (match_operand:SI 0 "register_operand" "=l,l,r")
11675 (ior:SI (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "l,l,r")
11676 (const_int 8))
11677 (match_operand:SI 3 "const_int_operand" "n,n,n"))
11678 (and:SI (lshiftrt:SI (match_dup 1)
11679 (const_int 8))
11680 (match_operand:SI 2 "const_int_operand" "n,n,n"))))]
11681 "arm_arch6
11682 && aarch_rev16_shleft_mask_imm_p (operands[3], SImode)
11683 && aarch_rev16_shright_mask_imm_p (operands[2], SImode)"
11684 "rev16\\t%0, %1"
11685 [(set_attr "arch" "t1,t2,32")
11686 (set_attr "length" "2,2,4")
11687 (set_attr "type" "rev")]
11688)
11689
11690(define_insn "arm_rev16si2_alt"
11691 [(set (match_operand:SI 0 "register_operand" "=l,l,r")
11692 (ior:SI (and:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,l,r")
11693 (const_int 8))
11694 (match_operand:SI 2 "const_int_operand" "n,n,n"))
11695 (and:SI (ashift:SI (match_dup 1)
11696 (const_int 8))
11697 (match_operand:SI 3 "const_int_operand" "n,n,n"))))]
11698 "arm_arch6
11699 && aarch_rev16_shleft_mask_imm_p (operands[3], SImode)
11700 && aarch_rev16_shright_mask_imm_p (operands[2], SImode)"
11701 "rev16\\t%0, %1"
11702 [(set_attr "arch" "t1,t2,32")
11703 (set_attr "length" "2,2,4")
11704 (set_attr "type" "rev")]
a486b499 11705)
11706
11707(define_expand "bswaphi2"
11708 [(set (match_operand:HI 0 "s_register_operand" "=r")
11709 (bswap:HI (match_operand:HI 1 "s_register_operand" "r")))]
11710"arm_arch6"
11711""
11712)
11713
1653cf17 11714;; Patterns for LDRD/STRD in Thumb2 mode
11715
11716(define_insn "*thumb2_ldrd"
11717 [(set (match_operand:SI 0 "s_register_operand" "=r")
11718 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
11719 (match_operand:SI 2 "ldrd_strd_offset_operand" "Do"))))
11720 (set (match_operand:SI 3 "s_register_operand" "=r")
11721 (mem:SI (plus:SI (match_dup 1)
11722 (match_operand:SI 4 "const_int_operand" ""))))]
11723 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
1653cf17 11724 && ((INTVAL (operands[2]) + 4) == INTVAL (operands[4]))
11725 && (operands_ok_ldrd_strd (operands[0], operands[3],
11726 operands[1], INTVAL (operands[2]),
11727 false, true))"
11728 "ldrd%?\t%0, %3, [%1, %2]"
11729 [(set_attr "type" "load2")
d952d547 11730 (set_attr "predicable" "yes")
11731 (set_attr "predicable_short_it" "no")])
1653cf17 11732
11733(define_insn "*thumb2_ldrd_base"
11734 [(set (match_operand:SI 0 "s_register_operand" "=r")
11735 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
11736 (set (match_operand:SI 2 "s_register_operand" "=r")
11737 (mem:SI (plus:SI (match_dup 1)
11738 (const_int 4))))]
11739 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
1653cf17 11740 && (operands_ok_ldrd_strd (operands[0], operands[2],
11741 operands[1], 0, false, true))"
11742 "ldrd%?\t%0, %2, [%1]"
11743 [(set_attr "type" "load2")
d952d547 11744 (set_attr "predicable" "yes")
11745 (set_attr "predicable_short_it" "no")])
1653cf17 11746
11747(define_insn "*thumb2_ldrd_base_neg"
11748 [(set (match_operand:SI 0 "s_register_operand" "=r")
11749 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
11750 (const_int -4))))
11751 (set (match_operand:SI 2 "s_register_operand" "=r")
11752 (mem:SI (match_dup 1)))]
11753 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
1653cf17 11754 && (operands_ok_ldrd_strd (operands[0], operands[2],
11755 operands[1], -4, false, true))"
11756 "ldrd%?\t%0, %2, [%1, #-4]"
11757 [(set_attr "type" "load2")
d952d547 11758 (set_attr "predicable" "yes")
11759 (set_attr "predicable_short_it" "no")])
1653cf17 11760
11761(define_insn "*thumb2_strd"
11762 [(set (mem:SI (plus:SI (match_operand:SI 0 "s_register_operand" "rk")
11763 (match_operand:SI 1 "ldrd_strd_offset_operand" "Do")))
11764 (match_operand:SI 2 "s_register_operand" "r"))
11765 (set (mem:SI (plus:SI (match_dup 0)
11766 (match_operand:SI 3 "const_int_operand" "")))
11767 (match_operand:SI 4 "s_register_operand" "r"))]
11768 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
1653cf17 11769 && ((INTVAL (operands[1]) + 4) == INTVAL (operands[3]))
11770 && (operands_ok_ldrd_strd (operands[2], operands[4],
11771 operands[0], INTVAL (operands[1]),
11772 false, false))"
11773 "strd%?\t%2, %4, [%0, %1]"
11774 [(set_attr "type" "store2")
d952d547 11775 (set_attr "predicable" "yes")
11776 (set_attr "predicable_short_it" "no")])
1653cf17 11777
11778(define_insn "*thumb2_strd_base"
11779 [(set (mem:SI (match_operand:SI 0 "s_register_operand" "rk"))
11780 (match_operand:SI 1 "s_register_operand" "r"))
11781 (set (mem:SI (plus:SI (match_dup 0)
11782 (const_int 4)))
11783 (match_operand:SI 2 "s_register_operand" "r"))]
11784 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
1653cf17 11785 && (operands_ok_ldrd_strd (operands[1], operands[2],
11786 operands[0], 0, false, false))"
11787 "strd%?\t%1, %2, [%0]"
11788 [(set_attr "type" "store2")
d952d547 11789 (set_attr "predicable" "yes")
11790 (set_attr "predicable_short_it" "no")])
1653cf17 11791
11792(define_insn "*thumb2_strd_base_neg"
11793 [(set (mem:SI (plus:SI (match_operand:SI 0 "s_register_operand" "rk")
11794 (const_int -4)))
11795 (match_operand:SI 1 "s_register_operand" "r"))
11796 (set (mem:SI (match_dup 0))
11797 (match_operand:SI 2 "s_register_operand" "r"))]
11798 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
1653cf17 11799 && (operands_ok_ldrd_strd (operands[1], operands[2],
11800 operands[0], -4, false, false))"
11801 "strd%?\t%1, %2, [%0, #-4]"
11802 [(set_attr "type" "store2")
d952d547 11803 (set_attr "predicable" "yes")
11804 (set_attr "predicable_short_it" "no")])
1653cf17 11805
2a0c73f2 11806;; ARMv8 CRC32 instructions.
11807(define_insn "<crc_variant>"
11808 [(set (match_operand:SI 0 "s_register_operand" "=r")
11809 (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")
11810 (match_operand:<crc_mode> 2 "s_register_operand" "r")]
11811 CRC))]
11812 "TARGET_CRC32"
11813 "<crc_variant>\\t%0, %1, %2"
11814 [(set_attr "type" "crc")
11815 (set_attr "conds" "unconditional")]
11816)
1653cf17 11817
353cf59a 11818;; Load the load/store double peephole optimizations.
11819(include "ldrdstrd.md")
11820
320ea44d 11821;; Load the load/store multiple patterns
11822(include "ldmstm.md")
426be8c5 11823
11824;; Patterns in ldmstm.md don't cover more than 4 registers. This pattern covers
11825;; large lists without explicit writeback generated for APCS_FRAME epilogue.
11826(define_insn "*load_multiple"
11827 [(match_parallel 0 "load_multiple_operation"
11828 [(set (match_operand:SI 2 "s_register_operand" "=rk")
11829 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
11830 ])]
11831 "TARGET_32BIT"
11832 "*
11833 {
11834 arm_output_multireg_pop (operands, /*return_pc=*/false,
11835 /*cond=*/const_true_rtx,
11836 /*reverse=*/false,
11837 /*update=*/false);
11838 return \"\";
11839 }
11840 "
11841 [(set_attr "predicable" "yes")]
11842)
11843
84450ddc 11844(define_expand "copysignsf3"
11845 [(match_operand:SF 0 "register_operand")
11846 (match_operand:SF 1 "register_operand")
11847 (match_operand:SF 2 "register_operand")]
11848 "TARGET_SOFT_FLOAT && arm_arch_thumb2"
11849 "{
11850 emit_move_insn (operands[0], operands[2]);
11851 emit_insn (gen_insv_t2 (simplify_gen_subreg (SImode, operands[0], SFmode, 0),
11852 GEN_INT (31), GEN_INT (0),
11853 simplify_gen_subreg (SImode, operands[1], SFmode, 0)));
11854 DONE;
11855 }"
11856)
11857
11858(define_expand "copysigndf3"
11859 [(match_operand:DF 0 "register_operand")
11860 (match_operand:DF 1 "register_operand")
11861 (match_operand:DF 2 "register_operand")]
11862 "TARGET_SOFT_FLOAT && arm_arch_thumb2"
11863 "{
11864 rtx op0_low = gen_lowpart (SImode, operands[0]);
11865 rtx op0_high = gen_highpart (SImode, operands[0]);
11866 rtx op1_low = gen_lowpart (SImode, operands[1]);
11867 rtx op1_high = gen_highpart (SImode, operands[1]);
11868 rtx op2_high = gen_highpart (SImode, operands[2]);
11869
11870 rtx scratch1 = gen_reg_rtx (SImode);
11871 rtx scratch2 = gen_reg_rtx (SImode);
11872 emit_move_insn (scratch1, op2_high);
11873 emit_move_insn (scratch2, op1_high);
11874
d1f9b275 11875 emit_insn(gen_rtx_SET(scratch1,
84450ddc 11876 gen_rtx_LSHIFTRT (SImode, op2_high, GEN_INT(31))));
11877 emit_insn(gen_insv_t2(scratch2, GEN_INT(1), GEN_INT(31), scratch1));
11878 emit_move_insn (op0_low, op1_low);
11879 emit_move_insn (op0_high, scratch2);
11880
11881 DONE;
11882 }"
11883)
11884
115857ef 11885;; movmisalign patterns for HImode and SImode.
11886(define_expand "movmisalign<mode>"
11887 [(match_operand:HSI 0 "general_operand")
11888 (match_operand:HSI 1 "general_operand")]
11889 "unaligned_access"
11890{
11891 /* This pattern is not permitted to fail during expansion: if both arguments
11892 are non-registers (e.g. memory := constant), force operand 1 into a
11893 register. */
11894 rtx (* gen_unaligned_load)(rtx, rtx);
11895 rtx tmp_dest = operands[0];
11896 if (!s_register_operand (operands[0], <MODE>mode)
11897 && !s_register_operand (operands[1], <MODE>mode))
11898 operands[1] = force_reg (<MODE>mode, operands[1]);
11899
11900 if (<MODE>mode == HImode)
11901 {
11902 gen_unaligned_load = gen_unaligned_loadhiu;
11903 tmp_dest = gen_reg_rtx (SImode);
11904 }
11905 else
11906 gen_unaligned_load = gen_unaligned_loadsi;
11907
11908 if (MEM_P (operands[1]))
11909 {
11910 emit_insn (gen_unaligned_load (tmp_dest, operands[1]));
11911 if (<MODE>mode == HImode)
11912 emit_move_insn (operands[0], gen_lowpart (HImode, tmp_dest));
11913 }
11914 else
11915 emit_insn (gen_unaligned_store<mode> (operands[0], operands[1]));
11916
11917 DONE;
11918})
11919
d98a3884 11920;; Vector bits common to IWMMXT and Neon
11921(include "vec-common.md")
755eb2b4 11922;; Load the Intel Wireless Multimedia Extension patterns
11923(include "iwmmxt.md")
a2cd141b 11924;; Load the VFP co-processor patterns
11925(include "vfp.md")
bc360af8 11926;; Thumb-1 patterns
11927(include "thumb1.md")
25f905c2 11928;; Thumb-2 patterns
11929(include "thumb2.md")
d98a3884 11930;; Neon patterns
11931(include "neon.md")
e84fdf6e 11932;; Crypto patterns
11933(include "crypto.md")
06df6b17 11934;; Synchronization Primitives
11935(include "sync.md")
bbbe4599 11936;; Fixed-point patterns
11937(include "arm-fixed.md")