]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/arm/arm.md
[Arm] Add 16-bit thumb alternatives to iorsi3_compare0[_scratch]
[thirdparty/gcc.git] / gcc / config / arm / arm.md
CommitLineData
129a2fe4 1;;- Machine description for ARM for GNU compiler
fbd26352 2;; Copyright (C) 1991-2019 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
e27c5a70 33 (R4_REGNUM 4) ; Fifth CORE register
bffbb863 34 (IP_REGNUM 12) ; Scratch register
35 (SP_REGNUM 13) ; Stack pointer
36 (LR_REGNUM 14) ; Return address register
37 (PC_REGNUM 15) ; Program counter
38 (LAST_ARM_REGNUM 15) ;
39 (CC_REGNUM 100) ; Condition code pseudo register
40 (VFPCC_REGNUM 101) ; VFP Condition code pseudo register
e1159bbe 41 ]
42)
3c5afce6 43;; 3rd operand to select_dominance_cc_mode
44(define_constants
45 [(DOM_CC_X_AND_Y 0)
46 (DOM_CC_NX_OR_Y 1)
47 (DOM_CC_X_OR_Y 2)
48 ]
49)
2ff91fec 50;; conditional compare combination
51(define_constants
52 [(CMP_CMP 0)
53 (CMN_CMP 1)
54 (CMP_CMN 2)
55 (CMN_CMN 3)
56 (NUM_OF_COND_CMP 4)
57 ]
58)
e1159bbe 59
b11cae9e 60\f
e1159bbe 61;;---------------------------------------------------------------------------
9c08d1fa 62;; Attributes
63
a651f34d 64;; Processor type. This is created automatically from arm-cores.def.
65(include "arm-tune.md")
66
861033d5 67;; Instruction classification types
68(include "types.md")
69
215b30b3 70; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
71; generating ARM code. This is used to control the length of some insn
72; patterns that share the same RTL in both ARM and Thumb code.
8724f216 73(define_attr "is_thumb" "yes,no"
74 (const (if_then_else (symbol_ref "TARGET_THUMB")
75 (const_string "yes") (const_string "no"))))
cffb2a26 76
ef51b8e1 77; IS_ARCH6 is set to 'yes' when we are generating code form ARMv6.
78(define_attr "is_arch6" "no,yes" (const (symbol_ref "arm_arch6")))
79
747b7458 80; IS_THUMB1 is set to 'yes' iff we are generating Thumb-1 code.
8724f216 81(define_attr "is_thumb1" "yes,no"
82 (const (if_then_else (symbol_ref "TARGET_THUMB1")
83 (const_string "yes") (const_string "no"))))
747b7458 84
8bdfd6ed 85; Mark an instruction as suitable for "short IT" blocks in Thumb-2.
86; The arm_restrict_it flag enables the "short IT" feature which
87; restricts IT blocks to a single 16-bit instruction.
88; This attribute should only be used on 16-bit Thumb-2 instructions
89; which may be predicated (the "predicable" attribute must be set).
90(define_attr "predicable_short_it" "no,yes" (const_string "no"))
91
92; Mark an instruction as suitable for "short IT" blocks in Thumb-2.
93; This attribute should only be used on instructions which may emit
94; an IT block in their expansion which is not a short IT.
95(define_attr "enabled_for_short_it" "no,yes" (const_string "yes"))
c7a58118 96
331beb1a 97;; Operand number of an input operand that is shifted. Zero if the
98;; given instruction does not shift one of its input operands.
331beb1a 99(define_attr "shift" "" (const_int 0))
100
55a94dda 101;; [For compatibility with AArch64 in pipeline models]
102;; Attribute that specifies whether or not the instruction touches fp
103;; registers.
104(define_attr "fp" "no,yes" (const_string "no"))
105
3d91c5d6 106; Floating Point Unit. If we only have floating point emulation, then there
107; is no point in scheduling the floating point insns. (Well, for best
108; performance we should try and group them together).
bffbb863 109(define_attr "fpu" "none,vfp"
c7f506fd 110 (const (symbol_ref "arm_fpu_attr")))
3d91c5d6 111
b2bcff19 112; Predicated means that the insn form is conditionally executed based on a
113; predicate. We default to 'no' because no Thumb patterns match this rule
114; and not all ARM insns do.
c7a58118 115(define_attr "predicated" "yes,no" (const_string "no"))
116
094e994f 117; LENGTH of an instruction (in bytes)
06df6b17 118(define_attr "length" ""
e1b93706 119 (const_int 4))
9c08d1fa 120
d5d4dc8d 121; The architecture which supports the instruction (or alternative).
122; This can be "a" for ARM, "t" for either of the Thumbs, "32" for
123; TARGET_32BIT, "t1" or "t2" to specify a specific Thumb mode. "v6"
124; for ARM or Thumb-2 with arm_arch6, and nov6 for ARM without
417e5cc5 125; arm_arch6. "v6t2" for Thumb-2 with arm_arch6 and "v8mb" for ARMv8-M
126; Baseline. This attribute is used to compute attribute "enabled",
127; use type "any" to enable an alternative in all cases.
128(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 129 (const_string "any"))
130
131(define_attr "arch_enabled" "no,yes"
132 (cond [(eq_attr "arch" "any")
133 (const_string "yes")
134
135 (and (eq_attr "arch" "a")
0bf497f5 136 (match_test "TARGET_ARM"))
d5d4dc8d 137 (const_string "yes")
138
139 (and (eq_attr "arch" "t")
0bf497f5 140 (match_test "TARGET_THUMB"))
d5d4dc8d 141 (const_string "yes")
142
143 (and (eq_attr "arch" "t1")
0bf497f5 144 (match_test "TARGET_THUMB1"))
d5d4dc8d 145 (const_string "yes")
146
147 (and (eq_attr "arch" "t2")
0bf497f5 148 (match_test "TARGET_THUMB2"))
d5d4dc8d 149 (const_string "yes")
150
151 (and (eq_attr "arch" "32")
0bf497f5 152 (match_test "TARGET_32BIT"))
d5d4dc8d 153 (const_string "yes")
154
155 (and (eq_attr "arch" "v6")
0bf497f5 156 (match_test "TARGET_32BIT && arm_arch6"))
d5d4dc8d 157 (const_string "yes")
158
159 (and (eq_attr "arch" "nov6")
0bf497f5 160 (match_test "TARGET_32BIT && !arm_arch6"))
a651f34d 161 (const_string "yes")
162
e4585731 163 (and (eq_attr "arch" "v6t2")
164 (match_test "TARGET_32BIT && arm_arch6 && arm_arch_thumb2"))
165 (const_string "yes")
166
417e5cc5 167 (and (eq_attr "arch" "v8mb")
168 (match_test "TARGET_THUMB1 && arm_arch8"))
169 (const_string "yes")
170
b6779ddc 171 (and (eq_attr "arch" "avoid_neon_for_64bits")
172 (match_test "TARGET_NEON")
173 (not (match_test "TARGET_PREFER_NEON_64BITS")))
a651f34d 174 (const_string "yes")
175
b6779ddc 176 (and (eq_attr "arch" "neon_for_64bits")
177 (match_test "TARGET_NEON")
178 (match_test "TARGET_PREFER_NEON_64BITS"))
6b8f7c28 179 (const_string "yes")
180
181 (and (eq_attr "arch" "iwmmxt2")
182 (match_test "TARGET_REALLY_IWMMXT2"))
21cc9773 183 (const_string "yes")
184
185 (and (eq_attr "arch" "armv6_or_vfpv3")
186 (match_test "arm_arch6 || TARGET_VFP3"))
187 (const_string "yes")
ac876af5 188
189 (and (eq_attr "arch" "neon")
190 (match_test "TARGET_NEON"))
191 (const_string "yes")
21cc9773 192 ]
6b8f7c28 193
d5d4dc8d 194 (const_string "no")))
195
aa06c51c 196(define_attr "opt" "any,speed,size"
197 (const_string "any"))
198
199(define_attr "opt_enabled" "no,yes"
200 (cond [(eq_attr "opt" "any")
201 (const_string "yes")
202
203 (and (eq_attr "opt" "speed")
204 (match_test "optimize_function_for_speed_p (cfun)"))
205 (const_string "yes")
206
207 (and (eq_attr "opt" "size")
208 (match_test "optimize_function_for_size_p (cfun)"))
209 (const_string "yes")]
210 (const_string "no")))
211
861033d5 212(define_attr "use_literal_pool" "no,yes"
213 (cond [(and (eq_attr "type" "f_loads,f_loadd")
214 (match_test "CONSTANT_P (operands[1])"))
215 (const_string "yes")]
216 (const_string "no")))
217
d5d4dc8d 218; Enable all alternatives that are both arch_enabled and insn_enabled.
951a3f72 219; FIXME:: opt_enabled has been temporarily removed till the time we have
220; an attribute that allows the use of such alternatives.
221; This depends on caching of speed_p, size_p on a per
222; alternative basis. The problem is that the enabled attribute
223; cannot depend on any state that is not cached or is not constant
224; for a compilation unit. We probably need a generic "hot/cold"
225; alternative which if implemented can help with this. We disable this
226; until such a time as this is implemented and / or the improvements or
227; regressions with removing this attribute are double checked.
228; See ashldi3_neon and <shift>di3_neon in neon.md.
229
93b431d9 230 (define_attr "enabled" "no,yes"
0abea32c 231 (cond [(and (eq_attr "predicable_short_it" "no")
c7a58118 232 (and (eq_attr "predicated" "yes")
233 (match_test "arm_restrict_it")))
234 (const_string "no")
235
8bdfd6ed 236 (and (eq_attr "enabled_for_short_it" "no")
c7a58118 237 (match_test "arm_restrict_it"))
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;
f4d3c071 290; UNCONDITIONAL means the instruction cannot be conditionally executed and
ad6d3e2a 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"
9f2c2a36 321 "block,call,load_4")
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,\
1efe0507 387 arm926ejs,arm10e,arm1026ejs,arm1136js,\
e18862f3 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")
1efe0507 399 (eq_attr "tune" "!arm10e,cortexa5,cortexa7,\
e18862f3 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
3934ae0e 447 [(set (match_operand:DI 0 "s_register_operand")
448 (plus:DI (match_operand:DI 1 "s_register_operand")
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"
206f0a3f 464 [(set (match_operand:DI 0 "arm_general_register_operand" "=&r,&r,&r,&r,&r")
465 (plus:DI (match_operand:DI 1 "arm_general_register_operand" "%0, 0, r, 0, r")
466 (match_operand:DI 2 "arm_general_adddi_operand" "r, 0, r, Dd, Dd")))
bd5b4116 467 (clobber (reg:CC CC_REGNUM))]
b805622c 468 "TARGET_32BIT && !TARGET_NEON"
33782ec7 469 "#"
206f0a3f 470 "TARGET_32BIT && ((!TARGET_NEON && !TARGET_IWMMXT) || reload_completed)"
a0f94409 471 [(parallel [(set (reg:CC_C CC_REGNUM)
472 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
473 (match_dup 1)))
474 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 475 (set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (match_dup 5))
476 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
a0f94409 477 "
478 {
479 operands[3] = gen_highpart (SImode, operands[0]);
480 operands[0] = gen_lowpart (SImode, operands[0]);
481 operands[4] = gen_highpart (SImode, operands[1]);
482 operands[1] = gen_lowpart (SImode, operands[1]);
10e5ccd5 483 operands[5] = gen_highpart_mode (SImode, DImode, operands[2]);
a0f94409 484 operands[2] = gen_lowpart (SImode, operands[2]);
485 }"
cffb2a26 486 [(set_attr "conds" "clob")
1b7da4ac 487 (set_attr "length" "8")
488 (set_attr "type" "multiple")]
cffb2a26 489)
9c08d1fa 490
a0f94409 491(define_insn_and_split "*adddi_sesidi_di"
9c08d1fa 492 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
493 (plus:DI (sign_extend:DI
97499065 494 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 495 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 496 (clobber (reg:CC CC_REGNUM))]
b805622c 497 "TARGET_32BIT"
33782ec7 498 "#"
25f905c2 499 "TARGET_32BIT && reload_completed"
a0f94409 500 [(parallel [(set (reg:CC_C CC_REGNUM)
501 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
502 (match_dup 1)))
503 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 504 (set (match_dup 3) (plus:SI (plus:SI (ashiftrt:SI (match_dup 2)
a0f94409 505 (const_int 31))
080c0b9a 506 (match_dup 4))
507 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
a0f94409 508 "
509 {
510 operands[3] = gen_highpart (SImode, operands[0]);
511 operands[0] = gen_lowpart (SImode, operands[0]);
512 operands[4] = gen_highpart (SImode, operands[1]);
513 operands[1] = gen_lowpart (SImode, operands[1]);
514 operands[2] = gen_lowpart (SImode, operands[2]);
515 }"
215b30b3 516 [(set_attr "conds" "clob")
1b7da4ac 517 (set_attr "length" "8")
518 (set_attr "type" "multiple")]
215b30b3 519)
9c08d1fa 520
a0f94409 521(define_insn_and_split "*adddi_zesidi_di"
9c08d1fa 522 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
523 (plus:DI (zero_extend:DI
97499065 524 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 525 (match_operand:DI 1 "s_register_operand" "0,r")))
a0f94409 526 (clobber (reg:CC CC_REGNUM))]
b805622c 527 "TARGET_32BIT"
33782ec7 528 "#"
25f905c2 529 "TARGET_32BIT && reload_completed"
a0f94409 530 [(parallel [(set (reg:CC_C CC_REGNUM)
531 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
532 (match_dup 1)))
533 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 534 (set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (const_int 0))
535 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
a0f94409 536 "
537 {
538 operands[3] = gen_highpart (SImode, operands[0]);
539 operands[0] = gen_lowpart (SImode, operands[0]);
540 operands[4] = gen_highpart (SImode, operands[1]);
541 operands[1] = gen_lowpart (SImode, operands[1]);
542 operands[2] = gen_lowpart (SImode, operands[2]);
543 }"
cffb2a26 544 [(set_attr "conds" "clob")
1b7da4ac 545 (set_attr "length" "8")
546 (set_attr "type" "multiple")]
cffb2a26 547)
b11cae9e 548
f6c98a9a 549(define_expand "addv<mode>4"
550 [(match_operand:SIDI 0 "register_operand")
551 (match_operand:SIDI 1 "register_operand")
552 (match_operand:SIDI 2 "register_operand")
553 (match_operand 3 "")]
554 "TARGET_32BIT"
555{
556 emit_insn (gen_add<mode>3_compareV (operands[0], operands[1], operands[2]));
557 arm_gen_unlikely_cbranch (NE, CC_Vmode, operands[3]);
558
559 DONE;
560})
561
562(define_expand "uaddv<mode>4"
563 [(match_operand:SIDI 0 "register_operand")
564 (match_operand:SIDI 1 "register_operand")
565 (match_operand:SIDI 2 "register_operand")
566 (match_operand 3 "")]
567 "TARGET_32BIT"
568{
569 emit_insn (gen_add<mode>3_compareC (operands[0], operands[1], operands[2]));
570 arm_gen_unlikely_cbranch (NE, CC_Cmode, operands[3]);
571
572 DONE;
573})
574
87b22bf7 575(define_expand "addsi3"
3934ae0e 576 [(set (match_operand:SI 0 "s_register_operand")
577 (plus:SI (match_operand:SI 1 "s_register_operand")
578 (match_operand:SI 2 "reg_or_int_operand")))]
cffb2a26 579 "TARGET_EITHER"
87b22bf7 580 "
0438d37f 581 if (TARGET_32BIT && CONST_INT_P (operands[2]))
87b22bf7 582 {
96f57e36 583 arm_split_constant (PLUS, SImode, NULL_RTX,
584 INTVAL (operands[2]), operands[0], operands[1],
e1ba4a27 585 optimize && can_create_pseudo_p ());
87b22bf7 586 DONE;
587 }
cffb2a26 588 "
589)
87b22bf7 590
5bd751ff 591; If there is a scratch available, this will be faster than synthesizing the
a0f94409 592; addition.
593(define_peephole2
594 [(match_scratch:SI 3 "r")
372575c7 595 (set (match_operand:SI 0 "arm_general_register_operand" "")
596 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
cffb2a26 597 (match_operand:SI 2 "const_int_operand" "")))]
25f905c2 598 "TARGET_32BIT &&
a0f94409 599 !(const_ok_for_arm (INTVAL (operands[2]))
600 || const_ok_for_arm (-INTVAL (operands[2])))
601 && const_ok_for_arm (~INTVAL (operands[2]))"
602 [(set (match_dup 3) (match_dup 2))
603 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
604 ""
605)
87b22bf7 606
2f02c19f 607;; The r/r/k alternative is required when reloading the address
608;; (plus (reg rN) (reg sp)) into (reg rN). In this case reload will
609;; put the duplicated register first, and not try the commutative version.
a0f94409 610(define_insn_and_split "*arm_addsi3"
fa1f9c9e 611 [(set (match_operand:SI 0 "s_register_operand" "=rk,l,l ,l ,r ,k ,r,k ,r ,k ,r ,k,k,r ,k ,r")
612 (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")
613 (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 614 "TARGET_32BIT"
5565501b 615 "@
c24d855d 616 add%?\\t%0, %0, %2
5565501b 617 add%?\\t%0, %1, %2
a0b3420a 618 add%?\\t%0, %1, %2
7c36fe71 619 add%?\\t%0, %1, %2
620 add%?\\t%0, %1, %2
aaa37ad6 621 add%?\\t%0, %1, %2
2f02c19f 622 add%?\\t%0, %2, %1
fa1f9c9e 623 add%?\\t%0, %1, %2
d5cbae34 624 addw%?\\t%0, %1, %2
625 addw%?\\t%0, %1, %2
aaa37ad6 626 sub%?\\t%0, %1, #%n2
87b22bf7 627 sub%?\\t%0, %1, #%n2
d7757711 628 sub%?\\t%0, %1, #%n2
d5cbae34 629 subw%?\\t%0, %1, #%n2
630 subw%?\\t%0, %1, #%n2
87b22bf7 631 #"
a3ffc315 632 "TARGET_32BIT
0438d37f 633 && CONST_INT_P (operands[2])
d5cbae34 634 && !const_ok_for_op (INTVAL (operands[2]), PLUS)
a3ffc315 635 && (reload_completed || !arm_eliminable_register (operands[1]))"
a0f94409 636 [(clobber (const_int 0))]
637 "
96f57e36 638 arm_split_constant (PLUS, SImode, curr_insn,
639 INTVAL (operands[2]), operands[0],
a0f94409 640 operands[1], 0);
641 DONE;
642 "
fa1f9c9e 643 [(set_attr "length" "2,4,4,4,4,4,4,4,4,4,4,4,4,4,4,16")
d5cbae34 644 (set_attr "predicable" "yes")
fa1f9c9e 645 (set_attr "predicable_short_it" "yes,yes,yes,yes,no,no,no,no,no,no,no,no,no,no,no,no")
646 (set_attr "arch" "t2,t2,t2,t2,*,*,*,a,t2,t2,*,*,a,t2,t2,*")
65f68e55 647 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
d82e788e 648 (const_string "alu_imm")
112eda6f 649 (const_string "alu_sreg")))
65f68e55 650 ]
cffb2a26 651)
652
f6c98a9a 653(define_insn_and_split "adddi3_compareV"
654 [(set (reg:CC_V CC_REGNUM)
655 (ne:CC_V
656 (plus:TI
657 (sign_extend:TI (match_operand:DI 1 "register_operand" "r"))
658 (sign_extend:TI (match_operand:DI 2 "register_operand" "r")))
659 (sign_extend:TI (plus:DI (match_dup 1) (match_dup 2)))))
660 (set (match_operand:DI 0 "register_operand" "=&r")
661 (plus:DI (match_dup 1) (match_dup 2)))]
662 "TARGET_32BIT"
663 "#"
664 "&& reload_completed"
665 [(parallel [(set (reg:CC_C CC_REGNUM)
666 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
667 (match_dup 1)))
668 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
669 (parallel [(set (reg:CC_V CC_REGNUM)
670 (ne:CC_V
671 (plus:DI (plus:DI
672 (sign_extend:DI (match_dup 4))
673 (sign_extend:DI (match_dup 5)))
674 (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0)))
675 (plus:DI (sign_extend:DI
676 (plus:SI (match_dup 4) (match_dup 5)))
677 (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0)))))
678 (set (match_dup 3) (plus:SI (plus:SI
679 (match_dup 4) (match_dup 5))
680 (ltu:SI (reg:CC_C CC_REGNUM)
681 (const_int 0))))])]
682 "
683 {
684 operands[3] = gen_highpart (SImode, operands[0]);
685 operands[0] = gen_lowpart (SImode, operands[0]);
686 operands[4] = gen_highpart (SImode, operands[1]);
687 operands[1] = gen_lowpart (SImode, operands[1]);
688 operands[5] = gen_highpart (SImode, operands[2]);
689 operands[2] = gen_lowpart (SImode, operands[2]);
690 }"
691 [(set_attr "conds" "set")
692 (set_attr "length" "8")
693 (set_attr "type" "multiple")]
694)
695
696(define_insn "addsi3_compareV"
697 [(set (reg:CC_V CC_REGNUM)
698 (ne:CC_V
699 (plus:DI
700 (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
701 (sign_extend:DI (match_operand:SI 2 "register_operand" "r")))
702 (sign_extend:DI (plus:SI (match_dup 1) (match_dup 2)))))
703 (set (match_operand:SI 0 "register_operand" "=r")
704 (plus:SI (match_dup 1) (match_dup 2)))]
705 "TARGET_32BIT"
706 "adds%?\\t%0, %1, %2"
707 [(set_attr "conds" "set")
708 (set_attr "type" "alus_sreg")]
709)
710
711(define_insn "*addsi3_compareV_upper"
712 [(set (reg:CC_V CC_REGNUM)
713 (ne:CC_V
714 (plus:DI
715 (plus:DI
716 (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
717 (sign_extend:DI (match_operand:SI 2 "register_operand" "r")))
718 (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0)))
719 (plus:DI (sign_extend:DI
720 (plus:SI (match_dup 1) (match_dup 2)))
721 (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0)))))
722 (set (match_operand:SI 0 "register_operand" "=r")
723 (plus:SI
724 (plus:SI (match_dup 1) (match_dup 2))
725 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
726 "TARGET_32BIT"
727 "adcs%?\\t%0, %1, %2"
728 [(set_attr "conds" "set")
729 (set_attr "type" "adcs_reg")]
730)
731
732(define_insn_and_split "adddi3_compareC"
733 [(set (reg:CC_C CC_REGNUM)
734 (ne:CC_C
735 (plus:TI
736 (zero_extend:TI (match_operand:DI 1 "register_operand" "r"))
737 (zero_extend:TI (match_operand:DI 2 "register_operand" "r")))
738 (zero_extend:TI (plus:DI (match_dup 1) (match_dup 2)))))
739 (set (match_operand:DI 0 "register_operand" "=&r")
740 (plus:DI (match_dup 1) (match_dup 2)))]
741 "TARGET_32BIT"
742 "#"
743 "&& reload_completed"
744 [(parallel [(set (reg:CC_C CC_REGNUM)
745 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
746 (match_dup 1)))
747 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
748 (parallel [(set (reg:CC_C CC_REGNUM)
749 (ne:CC_C
750 (plus:DI (plus:DI
751 (zero_extend:DI (match_dup 4))
752 (zero_extend:DI (match_dup 5)))
753 (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0)))
754 (plus:DI (zero_extend:DI
755 (plus:SI (match_dup 4) (match_dup 5)))
756 (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0)))))
757 (set (match_dup 3) (plus:SI
758 (plus:SI (match_dup 4) (match_dup 5))
759 (ltu:SI (reg:CC_C CC_REGNUM)
760 (const_int 0))))])]
761 "
762 {
763 operands[3] = gen_highpart (SImode, operands[0]);
764 operands[0] = gen_lowpart (SImode, operands[0]);
765 operands[4] = gen_highpart (SImode, operands[1]);
766 operands[5] = gen_highpart (SImode, operands[2]);
767 operands[1] = gen_lowpart (SImode, operands[1]);
768 operands[2] = gen_lowpart (SImode, operands[2]);
769 }"
770 [(set_attr "conds" "set")
771 (set_attr "length" "8")
772 (set_attr "type" "multiple")]
773)
774
775(define_insn "*addsi3_compareC_upper"
776 [(set (reg:CC_C CC_REGNUM)
777 (ne:CC_C
778 (plus:DI
779 (plus:DI
780 (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
781 (zero_extend:DI (match_operand:SI 2 "register_operand" "r")))
782 (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0)))
783 (plus:DI (zero_extend:DI
784 (plus:SI (match_dup 1) (match_dup 2)))
785 (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0)))))
786 (set (match_operand:SI 0 "register_operand" "=r")
787 (plus:SI
788 (plus:SI (match_dup 1) (match_dup 2))
789 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
790 "TARGET_32BIT"
791 "adcs%?\\t%0, %1, %2"
792 [(set_attr "conds" "set")
793 (set_attr "type" "adcs_reg")]
794)
795
796(define_insn "addsi3_compareC"
797 [(set (reg:CC_C CC_REGNUM)
798 (ne:CC_C
799 (plus:DI
800 (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
801 (zero_extend:DI (match_operand:SI 2 "register_operand" "r")))
802 (zero_extend:DI
803 (plus:SI (match_dup 1) (match_dup 2)))))
804 (set (match_operand:SI 0 "register_operand" "=r")
805 (plus:SI (match_dup 1) (match_dup 2)))]
806 "TARGET_32BIT"
807 "adds%?\\t%0, %1, %2"
808 [(set_attr "conds" "set")
809 (set_attr "type" "alus_sreg")]
810)
811
90c2bcf0 812(define_insn "addsi3_compare0"
bd5b4116 813 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 814 (compare:CC_NOOV
65f68e55 815 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r,r")
816 (match_operand:SI 2 "arm_add_operand" "I,L,r"))
5565501b 817 (const_int 0)))
65f68e55 818 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9c08d1fa 819 (plus:SI (match_dup 1) (match_dup 2)))]
ec792a7b 820 "TARGET_ARM"
5565501b 821 "@
3ef90e77 822 adds%?\\t%0, %1, %2
823 subs%?\\t%0, %1, #%n2
824 adds%?\\t%0, %1, %2"
65f68e55 825 [(set_attr "conds" "set")
112eda6f 826 (set_attr "type" "alus_imm,alus_imm,alus_sreg")]
cffb2a26 827)
9c08d1fa 828
aea4c774 829(define_insn "*addsi3_compare0_scratch"
bd5b4116 830 [(set (reg:CC_NOOV CC_REGNUM)
aea4c774 831 (compare:CC_NOOV
65f68e55 832 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r, r")
833 (match_operand:SI 1 "arm_add_operand" "I,L, r"))
aea4c774 834 (const_int 0)))]
ec792a7b 835 "TARGET_ARM"
cffb2a26 836 "@
837 cmn%?\\t%0, %1
65f68e55 838 cmp%?\\t%0, #%n1
839 cmn%?\\t%0, %1"
596e5e8f 840 [(set_attr "conds" "set")
65f68e55 841 (set_attr "predicable" "yes")
112eda6f 842 (set_attr "type" "alus_imm,alus_imm,alus_sreg")]
0d66636f 843)
cffb2a26 844
aed179ae 845(define_insn "*compare_negsi_si"
846 [(set (reg:CC_Z CC_REGNUM)
847 (compare:CC_Z
7c36fe71 848 (neg:SI (match_operand:SI 0 "s_register_operand" "l,r"))
849 (match_operand:SI 1 "s_register_operand" "l,r")))]
25f905c2 850 "TARGET_32BIT"
aed179ae 851 "cmn%?\\t%1, %0"
596e5e8f 852 [(set_attr "conds" "set")
7c36fe71 853 (set_attr "predicable" "yes")
854 (set_attr "arch" "t2,*")
855 (set_attr "length" "2,4")
1b7da4ac 856 (set_attr "predicable_short_it" "yes,no")
112eda6f 857 (set_attr "type" "alus_sreg")]
0d66636f 858)
aea4c774 859
7f100343 860;; This is the canonicalization of subsi3_compare when the
203c488f 861;; addend is a constant.
190efb17 862(define_insn "cmpsi2_addneg"
203c488f 863 [(set (reg:CC CC_REGNUM)
864 (compare:CC
865 (match_operand:SI 1 "s_register_operand" "r,r")
7f100343 866 (match_operand:SI 2 "arm_addimm_operand" "I,L")))
203c488f 867 (set (match_operand:SI 0 "s_register_operand" "=r,r")
868 (plus:SI (match_dup 1)
7f100343 869 (match_operand:SI 3 "arm_addimm_operand" "L,I")))]
e3dcfc16 870 "TARGET_32BIT
871 && (INTVAL (operands[2])
872 == trunc_int_for_mode (-INTVAL (operands[3]), SImode))"
873{
7f100343 874 /* For 0 and INT_MIN it is essential that we use subs, as adds will result
875 in different condition codes (like cmn rather than like cmp), so that
876 alternative comes first. Both alternatives can match for any 0x??000000
877 where except for 0 and INT_MIN it doesn't matter what we choose, and also
878 for -1 and 1 with TARGET_THUMB2, in that case prefer instruction with #1
879 as it is shorter. */
880 if (which_alternative == 0 && operands[3] != const1_rtx)
e3dcfc16 881 return "subs%?\\t%0, %1, #%n3";
882 else
883 return "adds%?\\t%0, %1, %3";
884}
1b7da4ac 885 [(set_attr "conds" "set")
112eda6f 886 (set_attr "type" "alus_sreg")]
203c488f 887)
888
889;; Convert the sequence
890;; sub rd, rn, #1
891;; cmn rd, #1 (equivalent to cmp rd, #-1)
892;; bne dest
893;; into
894;; subs rd, rn, #1
895;; bcs dest ((unsigned)rn >= 1)
896;; similarly for the beq variant using bcc.
897;; This is a common looping idiom (while (n--))
898(define_peephole2
372575c7 899 [(set (match_operand:SI 0 "arm_general_register_operand" "")
900 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
203c488f 901 (const_int -1)))
902 (set (match_operand 2 "cc_register" "")
903 (compare (match_dup 0) (const_int -1)))
904 (set (pc)
905 (if_then_else (match_operator 3 "equality_operator"
906 [(match_dup 2) (const_int 0)])
907 (match_operand 4 "" "")
908 (match_operand 5 "" "")))]
25f905c2 909 "TARGET_32BIT && peep2_reg_dead_p (3, operands[2])"
203c488f 910 [(parallel[
911 (set (match_dup 2)
912 (compare:CC
913 (match_dup 1) (const_int 1)))
914 (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
915 (set (pc)
916 (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
917 (match_dup 4)
918 (match_dup 5)))]
919 "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
920 operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
921 ? GEU : LTU),
922 VOIDmode,
923 operands[2], const0_rtx);"
924)
925
ebcc79bc 926;; The next four insns work because they compare the result with one of
927;; the operands, and we know that the use of the condition code is
928;; either GEU or LTU, so we can use the carry flag from the addition
929;; instead of doing the compare a second time.
930(define_insn "*addsi3_compare_op1"
bd5b4116 931 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 932 (compare:CC_C
4fe655e9 933 (plus:SI (match_operand:SI 1 "s_register_operand" "l,0,l,0,r,r,r")
934 (match_operand:SI 2 "arm_add_operand" "lPd,Py,lPx,Pw,I,L,r"))
ebcc79bc 935 (match_dup 1)))
4fe655e9 936 (set (match_operand:SI 0 "s_register_operand" "=l,l,l,l,r,r,r")
ebcc79bc 937 (plus:SI (match_dup 1) (match_dup 2)))]
25f905c2 938 "TARGET_32BIT"
ebcc79bc 939 "@
4fe655e9 940 adds%?\\t%0, %1, %2
941 adds%?\\t%0, %0, %2
942 subs%?\\t%0, %1, #%n2
943 subs%?\\t%0, %0, #%n2
3ef90e77 944 adds%?\\t%0, %1, %2
945 subs%?\\t%0, %1, #%n2
946 adds%?\\t%0, %1, %2"
65f68e55 947 [(set_attr "conds" "set")
4fe655e9 948 (set_attr "arch" "t2,t2,t2,t2,*,*,*")
949 (set_attr "length" "2,2,2,2,4,4,4")
950 (set_attr "type"
951 "alus_sreg,alus_imm,alus_sreg,alus_imm,alus_imm,alus_imm,alus_sreg")]
0d66636f 952)
ebcc79bc 953
954(define_insn "*addsi3_compare_op2"
bd5b4116 955 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 956 (compare:CC_C
4fe655e9 957 (plus:SI (match_operand:SI 1 "s_register_operand" "l,0,l,0,r,r,r")
958 (match_operand:SI 2 "arm_add_operand" "lPd,Py,lPx,Pw,I,L,r"))
ebcc79bc 959 (match_dup 2)))
4fe655e9 960 (set (match_operand:SI 0 "s_register_operand" "=l,l,l,l,r,r,r")
9c08d1fa 961 (plus:SI (match_dup 1) (match_dup 2)))]
25f905c2 962 "TARGET_32BIT"
5565501b 963 "@
4fe655e9 964 adds%?\\t%0, %1, %2
965 adds%?\\t%0, %0, %2
966 subs%?\\t%0, %1, #%n2
967 subs%?\\t%0, %0, #%n2
3ef90e77 968 adds%?\\t%0, %1, %2
38128b57 969 subs%?\\t%0, %1, #%n2
970 adds%?\\t%0, %1, %2"
65f68e55 971 [(set_attr "conds" "set")
4fe655e9 972 (set_attr "arch" "t2,t2,t2,t2,*,*,*")
973 (set_attr "length" "2,2,2,2,4,4,4")
974 (set_attr "type"
975 "alus_sreg,alus_imm,alus_sreg,alus_imm,alus_imm,alus_imm,alus_sreg")]
0d66636f 976)
9c08d1fa 977
ebcc79bc 978(define_insn "*compare_addsi2_op0"
bd5b4116 979 [(set (reg:CC_C CC_REGNUM)
7c36fe71 980 (compare:CC_C
981 (plus:SI (match_operand:SI 0 "s_register_operand" "l,l,r,r,r")
982 (match_operand:SI 1 "arm_add_operand" "Pv,l,I,L,r"))
983 (match_dup 0)))]
25f905c2 984 "TARGET_32BIT"
ebcc79bc 985 "@
7c36fe71 986 cmp%?\\t%0, #%n1
987 cmn%?\\t%0, %1
ebcc79bc 988 cmn%?\\t%0, %1
65f68e55 989 cmp%?\\t%0, #%n1
990 cmn%?\\t%0, %1"
596e5e8f 991 [(set_attr "conds" "set")
65f68e55 992 (set_attr "predicable" "yes")
7c36fe71 993 (set_attr "arch" "t2,t2,*,*,*")
994 (set_attr "predicable_short_it" "yes,yes,no,no,no")
995 (set_attr "length" "2,2,4,4,4")
112eda6f 996 (set_attr "type" "alus_imm,alus_sreg,alus_imm,alus_imm,alus_sreg")]
0d66636f 997)
ebcc79bc 998
999(define_insn "*compare_addsi2_op1"
bd5b4116 1000 [(set (reg:CC_C CC_REGNUM)
7c36fe71 1001 (compare:CC_C
1002 (plus:SI (match_operand:SI 0 "s_register_operand" "l,l,r,r,r")
1003 (match_operand:SI 1 "arm_add_operand" "Pv,l,I,L,r"))
1004 (match_dup 1)))]
25f905c2 1005 "TARGET_32BIT"
ebcc79bc 1006 "@
7c36fe71 1007 cmp%?\\t%0, #%n1
1008 cmn%?\\t%0, %1
ebcc79bc 1009 cmn%?\\t%0, %1
65f68e55 1010 cmp%?\\t%0, #%n1
1011 cmn%?\\t%0, %1"
596e5e8f 1012 [(set_attr "conds" "set")
65f68e55 1013 (set_attr "predicable" "yes")
7c36fe71 1014 (set_attr "arch" "t2,t2,*,*,*")
1015 (set_attr "predicable_short_it" "yes,yes,no,no,no")
1016 (set_attr "length" "2,2,4,4,4")
112eda6f 1017 (set_attr "type" "alus_imm,alus_sreg,alus_imm,alus_imm,alus_sreg")]
7c36fe71 1018 )
ebcc79bc 1019
080c0b9a 1020(define_insn "*addsi3_carryin_<optab>"
7c36fe71 1021 [(set (match_operand:SI 0 "s_register_operand" "=l,r,r")
1022 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%l,r,r")
1023 (match_operand:SI 2 "arm_not_operand" "0,rI,K"))
1024 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))]
25f905c2 1025 "TARGET_32BIT"
10e5ccd5 1026 "@
a0b3420a 1027 adc%?\\t%0, %1, %2
10e5ccd5 1028 adc%?\\t%0, %1, %2
1029 sbc%?\\t%0, %1, #%B2"
a7de272d 1030 [(set_attr "conds" "use")
7c36fe71 1031 (set_attr "predicable" "yes")
1032 (set_attr "arch" "t2,*,*")
1033 (set_attr "length" "4")
1b7da4ac 1034 (set_attr "predicable_short_it" "yes,no,no")
1035 (set_attr "type" "adc_reg,adc_reg,adc_imm")]
cffb2a26 1036)
ebcc79bc 1037
080c0b9a 1038(define_insn "*addsi3_carryin_alt2_<optab>"
7c36fe71 1039 [(set (match_operand:SI 0 "s_register_operand" "=l,r,r")
1040 (plus:SI (plus:SI (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))
1041 (match_operand:SI 1 "s_register_operand" "%l,r,r"))
1042 (match_operand:SI 2 "arm_rhs_operand" "l,rI,K")))]
25f905c2 1043 "TARGET_32BIT"
10e5ccd5 1044 "@
a0b3420a 1045 adc%?\\t%0, %1, %2
10e5ccd5 1046 adc%?\\t%0, %1, %2
1047 sbc%?\\t%0, %1, #%B2"
a7de272d 1048 [(set_attr "conds" "use")
7c36fe71 1049 (set_attr "predicable" "yes")
1050 (set_attr "arch" "t2,*,*")
1051 (set_attr "length" "4")
1b7da4ac 1052 (set_attr "predicable_short_it" "yes,no,no")
1053 (set_attr "type" "adc_reg,adc_reg,adc_imm")]
0d66636f 1054)
ebcc79bc 1055
080c0b9a 1056(define_insn "*addsi3_carryin_shift_<optab>"
ebcc79bc 1057 [(set (match_operand:SI 0 "s_register_operand" "=r")
080c0b9a 1058 (plus:SI (plus:SI
1059 (match_operator:SI 2 "shift_operator"
1060 [(match_operand:SI 3 "s_register_operand" "r")
1061 (match_operand:SI 4 "reg_or_int_operand" "rM")])
1062 (match_operand:SI 1 "s_register_operand" "r"))
1063 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))]
25f905c2 1064 "TARGET_32BIT"
080c0b9a 1065 "adc%?\\t%0, %1, %3%S2"
1066 [(set_attr "conds" "use")
a7de272d 1067 (set_attr "predicable" "yes")
080c0b9a 1068 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
d82e788e 1069 (const_string "alu_shift_imm")
1070 (const_string "alu_shift_reg")))]
cffb2a26 1071)
ebcc79bc 1072
922b6913 1073(define_insn "*addsi3_carryin_clobercc_<optab>"
1074 [(set (match_operand:SI 0 "s_register_operand" "=r")
1075 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%r")
1076 (match_operand:SI 2 "arm_rhs_operand" "rI"))
1077 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))
1078 (clobber (reg:CC CC_REGNUM))]
1079 "TARGET_32BIT"
3ef90e77 1080 "adcs%?\\t%0, %1, %2"
1b7da4ac 1081 [(set_attr "conds" "set")
1082 (set_attr "type" "adcs_reg")]
922b6913 1083)
1084
f6c98a9a 1085(define_expand "subv<mode>4"
1086 [(match_operand:SIDI 0 "register_operand")
1087 (match_operand:SIDI 1 "register_operand")
1088 (match_operand:SIDI 2 "register_operand")
1089 (match_operand 3 "")]
1090 "TARGET_32BIT"
1091{
1092 emit_insn (gen_sub<mode>3_compare1 (operands[0], operands[1], operands[2]));
1093 arm_gen_unlikely_cbranch (NE, CC_Vmode, operands[3]);
1094
1095 DONE;
1096})
1097
1098(define_expand "usubv<mode>4"
1099 [(match_operand:SIDI 0 "register_operand")
1100 (match_operand:SIDI 1 "register_operand")
1101 (match_operand:SIDI 2 "register_operand")
1102 (match_operand 3 "")]
1103 "TARGET_32BIT"
1104{
1105 emit_insn (gen_sub<mode>3_compare1 (operands[0], operands[1], operands[2]));
1106 arm_gen_unlikely_cbranch (LTU, CCmode, operands[3]);
1107
1108 DONE;
1109})
1110
1111(define_insn_and_split "subdi3_compare1"
1112 [(set (reg:CC CC_REGNUM)
1113 (compare:CC
1114 (match_operand:DI 1 "register_operand" "r")
1115 (match_operand:DI 2 "register_operand" "r")))
1116 (set (match_operand:DI 0 "register_operand" "=&r")
1117 (minus:DI (match_dup 1) (match_dup 2)))]
1118 "TARGET_32BIT"
1119 "#"
1120 "&& reload_completed"
1121 [(parallel [(set (reg:CC CC_REGNUM)
1122 (compare:CC (match_dup 1) (match_dup 2)))
1123 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1124 (parallel [(set (reg:CC CC_REGNUM)
1125 (compare:CC (match_dup 4) (match_dup 5)))
1126 (set (match_dup 3) (minus:SI (minus:SI (match_dup 4) (match_dup 5))
3b0dcaf2 1127 (ltu:SI (reg:CC CC_REGNUM) (const_int 0))))])]
f6c98a9a 1128 {
1129 operands[3] = gen_highpart (SImode, operands[0]);
1130 operands[0] = gen_lowpart (SImode, operands[0]);
1131 operands[4] = gen_highpart (SImode, operands[1]);
1132 operands[1] = gen_lowpart (SImode, operands[1]);
1133 operands[5] = gen_highpart (SImode, operands[2]);
1134 operands[2] = gen_lowpart (SImode, operands[2]);
1135 }
1136 [(set_attr "conds" "set")
1137 (set_attr "length" "8")
1138 (set_attr "type" "multiple")]
1139)
1140
1141(define_insn "subsi3_compare1"
1142 [(set (reg:CC CC_REGNUM)
1143 (compare:CC
1144 (match_operand:SI 1 "register_operand" "r")
1145 (match_operand:SI 2 "register_operand" "r")))
1146 (set (match_operand:SI 0 "register_operand" "=r")
1147 (minus:SI (match_dup 1) (match_dup 2)))]
1148 "TARGET_32BIT"
1149 "subs%?\\t%0, %1, %2"
1150 [(set_attr "conds" "set")
1151 (set_attr "type" "alus_sreg")]
1152)
1153
9154bd82 1154(define_insn "*subsi3_carryin"
d5bf2b53 1155 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1156 (minus:SI (minus:SI (match_operand:SI 1 "reg_or_int_operand" "r,I,Pz")
1157 (match_operand:SI 2 "s_register_operand" "r,r,r"))
3b0dcaf2 1158 (match_operand:SI 3 "arm_borrow_operation" "")))]
9154bd82 1159 "TARGET_32BIT"
1160 "@
1161 sbc%?\\t%0, %1, %2
d5bf2b53 1162 rsc%?\\t%0, %2, %1
1163 sbc%?\\t%0, %2, %2, lsl #1"
9154bd82 1164 [(set_attr "conds" "use")
d5bf2b53 1165 (set_attr "arch" "*,a,t2")
7c36fe71 1166 (set_attr "predicable" "yes")
d5bf2b53 1167 (set_attr "type" "adc_reg,adc_imm,alu_shift_imm")]
9154bd82 1168)
1169
1170(define_insn "*subsi3_carryin_const"
1171 [(set (match_operand:SI 0 "s_register_operand" "=r")
3b0dcaf2 1172 (minus:SI (plus:SI
1173 (match_operand:SI 1 "s_register_operand" "r")
1174 (match_operand:SI 2 "arm_neg_immediate_operand" "L"))
1175 (match_operand:SI 3 "arm_borrow_operation" "")))]
9154bd82 1176 "TARGET_32BIT"
16a3cf9c 1177 "sbc\\t%0, %1, #%n2"
1178 [(set_attr "conds" "use")
1179 (set_attr "type" "adc_imm")]
1180)
1181
1182(define_insn "*subsi3_carryin_const0"
1183 [(set (match_operand:SI 0 "s_register_operand" "=r")
3b0dcaf2 1184 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
1185 (match_operand:SI 2 "arm_borrow_operation" "")))]
16a3cf9c 1186 "TARGET_32BIT"
1187 "sbc\\t%0, %1, #0"
1b7da4ac 1188 [(set_attr "conds" "use")
1189 (set_attr "type" "adc_imm")]
9154bd82 1190)
1191
1192(define_insn "*subsi3_carryin_compare"
1193 [(set (reg:CC CC_REGNUM)
3b0dcaf2 1194 (compare:CC (match_operand:SI 1 "s_register_operand" "r")
1195 (match_operand:SI 2 "s_register_operand" "r")))
9154bd82 1196 (set (match_operand:SI 0 "s_register_operand" "=r")
3b0dcaf2 1197 (minus:SI (minus:SI (match_dup 1) (match_dup 2))
1198 (match_operand:SI 3 "arm_borrow_operation" "")))]
9154bd82 1199 "TARGET_32BIT"
1200 "sbcs\\t%0, %1, %2"
1b7da4ac 1201 [(set_attr "conds" "set")
1202 (set_attr "type" "adcs_reg")]
9154bd82 1203)
1204
1205(define_insn "*subsi3_carryin_compare_const"
1206 [(set (reg:CC CC_REGNUM)
3b0dcaf2 1207 (compare:CC (match_operand:SI 1 "reg_or_int_operand" "r")
1208 (match_operand:SI 2 "const_int_I_operand" "I")))
9154bd82 1209 (set (match_operand:SI 0 "s_register_operand" "=r")
3b0dcaf2 1210 (minus:SI (plus:SI
1211 (match_dup 1)
1212 (match_operand:SI 3 "arm_neg_immediate_operand" "L"))
1213 (match_operand:SI 4 "arm_borrow_operation" "")))]
2b363585 1214 "TARGET_32BIT
1215 && (INTVAL (operands[2])
1216 == trunc_int_for_mode (-INTVAL (operands[3]), SImode))"
16a3cf9c 1217 "sbcs\\t%0, %1, #%n3"
1218 [(set_attr "conds" "set")
1219 (set_attr "type" "adcs_imm")]
1220)
1221
1222(define_insn "*subsi3_carryin_compare_const0"
1223 [(set (reg:CC CC_REGNUM)
3b0dcaf2 1224 (compare:CC (match_operand:SI 1 "reg_or_int_operand" "r")
16a3cf9c 1225 (const_int 0)))
1226 (set (match_operand:SI 0 "s_register_operand" "=r")
3b0dcaf2 1227 (minus:SI (match_dup 1)
1228 (match_operand:SI 2 "arm_borrow_operation" "")))]
9154bd82 1229 "TARGET_32BIT"
16a3cf9c 1230 "sbcs\\t%0, %1, #0"
1b7da4ac 1231 [(set_attr "conds" "set")
1232 (set_attr "type" "adcs_imm")]
9154bd82 1233)
1234
1235(define_insn "*subsi3_carryin_shift"
1236 [(set (match_operand:SI 0 "s_register_operand" "=r")
1237 (minus:SI (minus:SI
3b0dcaf2 1238 (match_operand:SI 1 "s_register_operand" "r")
1239 (match_operator:SI 2 "shift_operator"
1240 [(match_operand:SI 3 "s_register_operand" "r")
1241 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
1242 (match_operand:SI 5 "arm_borrow_operation" "")))]
9154bd82 1243 "TARGET_32BIT"
1244 "sbc%?\\t%0, %1, %3%S2"
1245 [(set_attr "conds" "use")
1246 (set_attr "predicable" "yes")
1247 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
3b0dcaf2 1248 (const_string "alu_shift_imm")
1249 (const_string "alu_shift_reg")))]
9154bd82 1250)
1251
1252(define_insn "*rsbsi3_carryin_shift"
1253 [(set (match_operand:SI 0 "s_register_operand" "=r")
1254 (minus:SI (minus:SI
3b0dcaf2 1255 (match_operator:SI 2 "shift_operator"
1256 [(match_operand:SI 3 "s_register_operand" "r")
1257 (match_operand:SI 4 "reg_or_int_operand" "rM")])
9154bd82 1258 (match_operand:SI 1 "s_register_operand" "r"))
3b0dcaf2 1259 (match_operand:SI 5 "arm_borrow_operation" "")))]
9154bd82 1260 "TARGET_ARM"
1261 "rsc%?\\t%0, %1, %3%S2"
1262 [(set_attr "conds" "use")
1263 (set_attr "predicable" "yes")
1264 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
d82e788e 1265 (const_string "alu_shift_imm")
1266 (const_string "alu_shift_reg")))]
9154bd82 1267)
1268
d795fb69 1269; transform ((x << y) - 1) to ~(~(x-1) << y) Where X is a constant.
1270(define_split
1271 [(set (match_operand:SI 0 "s_register_operand" "")
1272 (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
1273 (match_operand:SI 2 "s_register_operand" ""))
1274 (const_int -1)))
1275 (clobber (match_operand:SI 3 "s_register_operand" ""))]
25f905c2 1276 "TARGET_32BIT"
d795fb69 1277 [(set (match_dup 3) (match_dup 1))
1278 (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
1279 "
1280 operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
1281")
1282
604f3a0a 1283(define_expand "addsf3"
3934ae0e 1284 [(set (match_operand:SF 0 "s_register_operand")
1285 (plus:SF (match_operand:SF 1 "s_register_operand")
1286 (match_operand:SF 2 "s_register_operand")))]
25f905c2 1287 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1288 "
604f3a0a 1289")
1290
604f3a0a 1291(define_expand "adddf3"
3934ae0e 1292 [(set (match_operand:DF 0 "s_register_operand")
1293 (plus:DF (match_operand:DF 1 "s_register_operand")
1294 (match_operand:DF 2 "s_register_operand")))]
a50d7267 1295 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 1296 "
604f3a0a 1297")
1298
cffb2a26 1299(define_expand "subdi3"
1300 [(parallel
3934ae0e 1301 [(set (match_operand:DI 0 "s_register_operand")
1302 (minus:DI (match_operand:DI 1 "s_register_operand")
1303 (match_operand:DI 2 "s_register_operand")))
bd5b4116 1304 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 1305 "TARGET_EITHER"
1306 "
25f905c2 1307 if (TARGET_THUMB1)
cffb2a26 1308 {
0438d37f 1309 if (!REG_P (operands[1]))
5aa8c5f0 1310 operands[1] = force_reg (DImode, operands[1]);
0438d37f 1311 if (!REG_P (operands[2]))
5aa8c5f0 1312 operands[2] = force_reg (DImode, operands[2]);
cffb2a26 1313 }
1314 "
1315)
1316
2f9b23e3 1317(define_insn_and_split "*arm_subdi3"
206f0a3f 1318 [(set (match_operand:DI 0 "arm_general_register_operand" "=&r,&r,&r")
1319 (minus:DI (match_operand:DI 1 "arm_general_register_operand" "0,r,0")
1320 (match_operand:DI 2 "arm_general_register_operand" "r,0,0")))
bd5b4116 1321 (clobber (reg:CC CC_REGNUM))]
94829feb 1322 "TARGET_32BIT && !TARGET_NEON"
2f9b23e3 1323 "#" ; "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
0d84c6e5 1324 "&& (!TARGET_IWMMXT || reload_completed)"
2f9b23e3 1325 [(parallel [(set (reg:CC CC_REGNUM)
1326 (compare:CC (match_dup 1) (match_dup 2)))
1327 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1328 (set (match_dup 3) (minus:SI (minus:SI (match_dup 4) (match_dup 5))
3b0dcaf2 1329 (ltu:SI (reg:CC CC_REGNUM) (const_int 0))))]
2f9b23e3 1330 {
1331 operands[3] = gen_highpart (SImode, operands[0]);
1332 operands[0] = gen_lowpart (SImode, operands[0]);
1333 operands[4] = gen_highpart (SImode, operands[1]);
1334 operands[1] = gen_lowpart (SImode, operands[1]);
1335 operands[5] = gen_highpart (SImode, operands[2]);
1336 operands[2] = gen_lowpart (SImode, operands[2]);
1337 }
cffb2a26 1338 [(set_attr "conds" "clob")
1b7da4ac 1339 (set_attr "length" "8")
1340 (set_attr "type" "multiple")]
cffb2a26 1341)
1342
2f9b23e3 1343(define_insn_and_split "*subdi_di_zesidi"
cffb2a26 1344 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 1345 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r")
9c08d1fa 1346 (zero_extend:DI
cffb2a26 1347 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 1348 (clobber (reg:CC CC_REGNUM))]
25f905c2 1349 "TARGET_32BIT"
2f9b23e3 1350 "#" ; "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
1351 "&& reload_completed"
1352 [(parallel [(set (reg:CC CC_REGNUM)
1353 (compare:CC (match_dup 1) (match_dup 2)))
1354 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
16a3cf9c 1355 (set (match_dup 3) (minus:SI (match_dup 4)
3b0dcaf2 1356 (ltu:SI (reg:CC CC_REGNUM) (const_int 0))))]
2f9b23e3 1357 {
1358 operands[3] = gen_highpart (SImode, operands[0]);
1359 operands[0] = gen_lowpart (SImode, operands[0]);
1360 operands[4] = gen_highpart (SImode, operands[1]);
1361 operands[1] = gen_lowpart (SImode, operands[1]);
2f9b23e3 1362 }
cffb2a26 1363 [(set_attr "conds" "clob")
1b7da4ac 1364 (set_attr "length" "8")
1365 (set_attr "type" "multiple")]
cffb2a26 1366)
9c08d1fa 1367
2f9b23e3 1368(define_insn_and_split "*subdi_di_sesidi"
cffb2a26 1369 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 1370 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r")
9c08d1fa 1371 (sign_extend:DI
cffb2a26 1372 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 1373 (clobber (reg:CC CC_REGNUM))]
25f905c2 1374 "TARGET_32BIT"
2f9b23e3 1375 "#" ; "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
1376 "&& reload_completed"
1377 [(parallel [(set (reg:CC CC_REGNUM)
1378 (compare:CC (match_dup 1) (match_dup 2)))
1379 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1380 (set (match_dup 3) (minus:SI (minus:SI (match_dup 4)
1381 (ashiftrt:SI (match_dup 2)
1382 (const_int 31)))
3b0dcaf2 1383 (ltu:SI (reg:CC CC_REGNUM) (const_int 0))))]
2f9b23e3 1384 {
1385 operands[3] = gen_highpart (SImode, operands[0]);
1386 operands[0] = gen_lowpart (SImode, operands[0]);
1387 operands[4] = gen_highpart (SImode, operands[1]);
1388 operands[1] = gen_lowpart (SImode, operands[1]);
1389 }
cffb2a26 1390 [(set_attr "conds" "clob")
1b7da4ac 1391 (set_attr "length" "8")
1392 (set_attr "type" "multiple")]
cffb2a26 1393)
9c08d1fa 1394
2f9b23e3 1395(define_insn_and_split "*subdi_zesidi_di"
cffb2a26 1396 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1397 (minus:DI (zero_extend:DI
cffb2a26 1398 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 1399 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 1400 (clobber (reg:CC CC_REGNUM))]
cffb2a26 1401 "TARGET_ARM"
2f9b23e3 1402 "#" ; "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
1403 ; is equivalent to:
1404 ; "subs\\t%Q0, %2, %Q1\;rsc\\t%R0, %R1, #0"
1405 "&& reload_completed"
1406 [(parallel [(set (reg:CC CC_REGNUM)
1407 (compare:CC (match_dup 2) (match_dup 1)))
1408 (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))])
1409 (set (match_dup 3) (minus:SI (minus:SI (const_int 0) (match_dup 4))
3b0dcaf2 1410 (ltu:SI (reg:CC CC_REGNUM) (const_int 0))))]
2f9b23e3 1411 {
1412 operands[3] = gen_highpart (SImode, operands[0]);
1413 operands[0] = gen_lowpart (SImode, operands[0]);
1414 operands[4] = gen_highpart (SImode, operands[1]);
1415 operands[1] = gen_lowpart (SImode, operands[1]);
1416 }
cffb2a26 1417 [(set_attr "conds" "clob")
1b7da4ac 1418 (set_attr "length" "8")
1419 (set_attr "type" "multiple")]
cffb2a26 1420)
9c08d1fa 1421
2f9b23e3 1422(define_insn_and_split "*subdi_sesidi_di"
cffb2a26 1423 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1424 (minus:DI (sign_extend:DI
cffb2a26 1425 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 1426 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 1427 (clobber (reg:CC CC_REGNUM))]
cffb2a26 1428 "TARGET_ARM"
2f9b23e3 1429 "#" ; "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
1430 ; is equivalent to:
1431 ; "subs\\t%Q0, %2, %Q1\;rsc\\t%R0, %R1, %2, asr #31"
1432 "&& reload_completed"
1433 [(parallel [(set (reg:CC CC_REGNUM)
1434 (compare:CC (match_dup 2) (match_dup 1)))
1435 (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))])
1436 (set (match_dup 3) (minus:SI (minus:SI
1437 (ashiftrt:SI (match_dup 2)
1438 (const_int 31))
1439 (match_dup 4))
3b0dcaf2 1440 (ltu:SI (reg:CC CC_REGNUM) (const_int 0))))]
2f9b23e3 1441 {
1442 operands[3] = gen_highpart (SImode, operands[0]);
1443 operands[0] = gen_lowpart (SImode, operands[0]);
1444 operands[4] = gen_highpart (SImode, operands[1]);
1445 operands[1] = gen_lowpart (SImode, operands[1]);
1446 }
cffb2a26 1447 [(set_attr "conds" "clob")
1b7da4ac 1448 (set_attr "length" "8")
1449 (set_attr "type" "multiple")]
cffb2a26 1450)
9c08d1fa 1451
2f9b23e3 1452(define_insn_and_split "*subdi_zesidi_zesidi"
cffb2a26 1453 [(set (match_operand:DI 0 "s_register_operand" "=r")
9c08d1fa 1454 (minus:DI (zero_extend:DI
cffb2a26 1455 (match_operand:SI 1 "s_register_operand" "r"))
9c08d1fa 1456 (zero_extend:DI
cffb2a26 1457 (match_operand:SI 2 "s_register_operand" "r"))))
bd5b4116 1458 (clobber (reg:CC CC_REGNUM))]
25f905c2 1459 "TARGET_32BIT"
2f9b23e3 1460 "#" ; "subs\\t%Q0, %1, %2\;sbc\\t%R0, %1, %1"
1461 "&& reload_completed"
1462 [(parallel [(set (reg:CC CC_REGNUM)
1463 (compare:CC (match_dup 1) (match_dup 2)))
1464 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1465 (set (match_dup 3) (minus:SI (minus:SI (match_dup 1) (match_dup 1))
3b0dcaf2 1466 (ltu:SI (reg:CC CC_REGNUM) (const_int 0))))]
2f9b23e3 1467 {
1468 operands[3] = gen_highpart (SImode, operands[0]);
1469 operands[0] = gen_lowpart (SImode, operands[0]);
1470 }
cffb2a26 1471 [(set_attr "conds" "clob")
1b7da4ac 1472 (set_attr "length" "8")
1473 (set_attr "type" "multiple")]
cffb2a26 1474)
b11cae9e 1475
87b22bf7 1476(define_expand "subsi3"
3934ae0e 1477 [(set (match_operand:SI 0 "s_register_operand")
1478 (minus:SI (match_operand:SI 1 "reg_or_int_operand")
1479 (match_operand:SI 2 "s_register_operand")))]
cffb2a26 1480 "TARGET_EITHER"
87b22bf7 1481 "
0438d37f 1482 if (CONST_INT_P (operands[1]))
87b22bf7 1483 {
25f905c2 1484 if (TARGET_32BIT)
cffb2a26 1485 {
17202aa5 1486 if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[1]), MINUS))
1487 operands[1] = force_reg (SImode, operands[1]);
1488 else
1489 {
1490 arm_split_constant (MINUS, SImode, NULL_RTX,
1491 INTVAL (operands[1]), operands[0],
1492 operands[2],
1493 optimize && can_create_pseudo_p ());
1494 DONE;
1495 }
cffb2a26 1496 }
25f905c2 1497 else /* TARGET_THUMB1 */
cffb2a26 1498 operands[1] = force_reg (SImode, operands[1]);
87b22bf7 1499 }
cffb2a26 1500 "
1501)
87b22bf7 1502
25f905c2 1503; ??? Check Thumb-2 split length
a0f94409 1504(define_insn_and_split "*arm_subsi3_insn"
3a44c5a9 1505 [(set (match_operand:SI 0 "s_register_operand" "=l,l ,l ,l ,r,r,r,rk,r")
1506 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "l ,0 ,l ,Pz,I,r,r,k ,?n")
1507 (match_operand:SI 2 "reg_or_int_operand" "l ,Py,Pd,l ,r,I,r,r ,r")))]
25f905c2 1508 "TARGET_32BIT"
e2348bcb 1509 "@
7c36fe71 1510 sub%?\\t%0, %1, %2
1511 sub%?\\t%0, %2
1512 sub%?\\t%0, %1, %2
1513 rsb%?\\t%0, %2, %1
87b22bf7 1514 rsb%?\\t%0, %2, %1
aaa37ad6 1515 sub%?\\t%0, %1, %2
080c0b9a 1516 sub%?\\t%0, %1, %2
65f68e55 1517 sub%?\\t%0, %1, %2
87b22bf7 1518 #"
0438d37f 1519 "&& (CONST_INT_P (operands[1])
91a5e339 1520 && !const_ok_for_arm (INTVAL (operands[1])))"
87b22bf7 1521 [(clobber (const_int 0))]
1522 "
96f57e36 1523 arm_split_constant (MINUS, SImode, curr_insn,
1524 INTVAL (operands[1]), operands[0], operands[2], 0);
87b22bf7 1525 DONE;
cffb2a26 1526 "
7c36fe71 1527 [(set_attr "length" "4,4,4,4,4,4,4,4,16")
1528 (set_attr "arch" "t2,t2,t2,t2,*,*,*,*,*")
65f68e55 1529 (set_attr "predicable" "yes")
7c36fe71 1530 (set_attr "predicable_short_it" "yes,yes,yes,yes,no,no,no,no,no")
112eda6f 1531 (set_attr "type" "alu_sreg,alu_sreg,alu_sreg,alu_sreg,alu_imm,alu_imm,alu_sreg,alu_sreg,multiple")]
a0f94409 1532)
1533
1534(define_peephole2
1535 [(match_scratch:SI 3 "r")
372575c7 1536 (set (match_operand:SI 0 "arm_general_register_operand" "")
a0f94409 1537 (minus:SI (match_operand:SI 1 "const_int_operand" "")
372575c7 1538 (match_operand:SI 2 "arm_general_register_operand" "")))]
25f905c2 1539 "TARGET_32BIT
a0f94409 1540 && !const_ok_for_arm (INTVAL (operands[1]))
1541 && const_ok_for_arm (~INTVAL (operands[1]))"
1542 [(set (match_dup 3) (match_dup 1))
1543 (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1544 ""
cffb2a26 1545)
b11cae9e 1546
62e39b06 1547(define_insn "subsi3_compare0"
bd5b4116 1548 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1549 (compare:CC_NOOV
65f68e55 1550 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,r,I")
1551 (match_operand:SI 2 "arm_rhs_operand" "I,r,r"))
215b30b3 1552 (const_int 0)))
65f68e55 1553 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9c08d1fa 1554 (minus:SI (match_dup 1) (match_dup 2)))]
25f905c2 1555 "TARGET_32BIT"
e2348bcb 1556 "@
3ef90e77 1557 subs%?\\t%0, %1, %2
1558 subs%?\\t%0, %1, %2
1559 rsbs%?\\t%0, %2, %1"
65f68e55 1560 [(set_attr "conds" "set")
112eda6f 1561 (set_attr "type" "alus_imm,alus_sreg,alus_sreg")]
cffb2a26 1562)
9c08d1fa 1563
190efb17 1564(define_insn "subsi3_compare"
080c0b9a 1565 [(set (reg:CC CC_REGNUM)
65f68e55 1566 (compare:CC (match_operand:SI 1 "arm_rhs_operand" "r,r,I")
1567 (match_operand:SI 2 "arm_rhs_operand" "I,r,r")))
1568 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2df9477b 1569 (minus:SI (match_dup 1) (match_dup 2)))]
1570 "TARGET_32BIT"
1571 "@
3ef90e77 1572 subs%?\\t%0, %1, %2
1573 subs%?\\t%0, %1, %2
1574 rsbs%?\\t%0, %2, %1"
65f68e55 1575 [(set_attr "conds" "set")
112eda6f 1576 (set_attr "type" "alus_imm,alus_sreg,alus_sreg")]
2df9477b 1577)
1578
604f3a0a 1579(define_expand "subsf3"
3934ae0e 1580 [(set (match_operand:SF 0 "s_register_operand")
1581 (minus:SF (match_operand:SF 1 "s_register_operand")
1582 (match_operand:SF 2 "s_register_operand")))]
25f905c2 1583 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1584 "
604f3a0a 1585")
1586
604f3a0a 1587(define_expand "subdf3"
3934ae0e 1588 [(set (match_operand:DF 0 "s_register_operand")
1589 (minus:DF (match_operand:DF 1 "s_register_operand")
1590 (match_operand:DF 2 "s_register_operand")))]
a50d7267 1591 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 1592 "
604f3a0a 1593")
1594
b11cae9e 1595\f
1596;; Multiplication insns
1597
4422d91f 1598(define_expand "mulhi3"
3934ae0e 1599 [(set (match_operand:HI 0 "s_register_operand")
1600 (mult:HI (match_operand:HI 1 "s_register_operand")
1601 (match_operand:HI 2 "s_register_operand")))]
4422d91f 1602 "TARGET_DSP_MULTIPLY"
1603 "
1604 {
1605 rtx result = gen_reg_rtx (SImode);
1606 emit_insn (gen_mulhisi3 (result, operands[1], operands[2]));
1607 emit_move_insn (operands[0], gen_lowpart (HImode, result));
1608 DONE;
1609 }"
1610)
1611
cffb2a26 1612(define_expand "mulsi3"
3934ae0e 1613 [(set (match_operand:SI 0 "s_register_operand")
1614 (mult:SI (match_operand:SI 2 "s_register_operand")
1615 (match_operand:SI 1 "s_register_operand")))]
cffb2a26 1616 "TARGET_EITHER"
1617 ""
1618)
1619
9c08d1fa 1620;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
cffb2a26 1621(define_insn "*arm_mulsi3"
1622 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1623 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1624 (match_operand:SI 1 "s_register_operand" "%0,r")))]
58d7d654 1625 "TARGET_32BIT && !arm_arch6"
f7fbdd4a 1626 "mul%?\\t%0, %2, %1"
9da0ec36 1627 [(set_attr "type" "mul")
0d66636f 1628 (set_attr "predicable" "yes")]
cffb2a26 1629)
1630
58d7d654 1631(define_insn "*arm_mulsi3_v6"
d952d547 1632 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
1633 (mult:SI (match_operand:SI 1 "s_register_operand" "0,l,r")
1634 (match_operand:SI 2 "s_register_operand" "l,0,r")))]
58d7d654 1635 "TARGET_32BIT && arm_arch6"
1636 "mul%?\\t%0, %1, %2"
9da0ec36 1637 [(set_attr "type" "mul")
d952d547 1638 (set_attr "predicable" "yes")
1639 (set_attr "arch" "t2,t2,*")
1640 (set_attr "length" "4")
1641 (set_attr "predicable_short_it" "yes,yes,no")]
58d7d654 1642)
1643
f7fbdd4a 1644(define_insn "*mulsi3_compare0"
bd5b4116 1645 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1646 (compare:CC_NOOV (mult:SI
1647 (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1648 (match_operand:SI 1 "s_register_operand" "%0,r"))
9c08d1fa 1649 (const_int 0)))
1650 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1651 (mult:SI (match_dup 2) (match_dup 1)))]
58d7d654 1652 "TARGET_ARM && !arm_arch6"
3ef90e77 1653 "muls%?\\t%0, %2, %1"
58d7d654 1654 [(set_attr "conds" "set")
9da0ec36 1655 (set_attr "type" "muls")]
58d7d654 1656)
1657
1658(define_insn "*mulsi3_compare0_v6"
1659 [(set (reg:CC_NOOV CC_REGNUM)
1660 (compare:CC_NOOV (mult:SI
1661 (match_operand:SI 2 "s_register_operand" "r")
1662 (match_operand:SI 1 "s_register_operand" "r"))
1663 (const_int 0)))
1664 (set (match_operand:SI 0 "s_register_operand" "=r")
1665 (mult:SI (match_dup 2) (match_dup 1)))]
1666 "TARGET_ARM && arm_arch6 && optimize_size"
3ef90e77 1667 "muls%?\\t%0, %2, %1"
cffb2a26 1668 [(set_attr "conds" "set")
9da0ec36 1669 (set_attr "type" "muls")]
cffb2a26 1670)
9c08d1fa 1671
f7fbdd4a 1672(define_insn "*mulsi_compare0_scratch"
bd5b4116 1673 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1674 (compare:CC_NOOV (mult:SI
1675 (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1676 (match_operand:SI 1 "s_register_operand" "%0,r"))
9c08d1fa 1677 (const_int 0)))
1678 (clobber (match_scratch:SI 0 "=&r,&r"))]
58d7d654 1679 "TARGET_ARM && !arm_arch6"
3ef90e77 1680 "muls%?\\t%0, %2, %1"
58d7d654 1681 [(set_attr "conds" "set")
9da0ec36 1682 (set_attr "type" "muls")]
58d7d654 1683)
1684
1685(define_insn "*mulsi_compare0_scratch_v6"
1686 [(set (reg:CC_NOOV CC_REGNUM)
1687 (compare:CC_NOOV (mult:SI
1688 (match_operand:SI 2 "s_register_operand" "r")
1689 (match_operand:SI 1 "s_register_operand" "r"))
1690 (const_int 0)))
1691 (clobber (match_scratch:SI 0 "=r"))]
1692 "TARGET_ARM && arm_arch6 && optimize_size"
3ef90e77 1693 "muls%?\\t%0, %2, %1"
cffb2a26 1694 [(set_attr "conds" "set")
9da0ec36 1695 (set_attr "type" "muls")]
cffb2a26 1696)
9c08d1fa 1697
b11cae9e 1698;; Unnamed templates to match MLA instruction.
1699
f7fbdd4a 1700(define_insn "*mulsi3addsi"
9c08d1fa 1701 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
c8f69309 1702 (plus:SI
9c08d1fa 1703 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1704 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1705 (match_operand:SI 3 "s_register_operand" "r,r,0,0")))]
58d7d654 1706 "TARGET_32BIT && !arm_arch6"
1707 "mla%?\\t%0, %2, %1, %3"
9da0ec36 1708 [(set_attr "type" "mla")
58d7d654 1709 (set_attr "predicable" "yes")]
1710)
1711
1712(define_insn "*mulsi3addsi_v6"
1713 [(set (match_operand:SI 0 "s_register_operand" "=r")
1714 (plus:SI
1715 (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1716 (match_operand:SI 1 "s_register_operand" "r"))
1717 (match_operand:SI 3 "s_register_operand" "r")))]
1718 "TARGET_32BIT && arm_arch6"
f7fbdd4a 1719 "mla%?\\t%0, %2, %1, %3"
9da0ec36 1720 [(set_attr "type" "mla")
8bdfd6ed 1721 (set_attr "predicable" "yes")]
0d66636f 1722)
b11cae9e 1723
f7fbdd4a 1724(define_insn "*mulsi3addsi_compare0"
bd5b4116 1725 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1726 (compare:CC_NOOV
1727 (plus:SI (mult:SI
1728 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1729 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1730 (match_operand:SI 3 "s_register_operand" "r,r,0,0"))
215b30b3 1731 (const_int 0)))
9c08d1fa 1732 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1733 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1734 (match_dup 3)))]
58d7d654 1735 "TARGET_ARM && arm_arch6"
3ef90e77 1736 "mlas%?\\t%0, %2, %1, %3"
58d7d654 1737 [(set_attr "conds" "set")
9da0ec36 1738 (set_attr "type" "mlas")]
58d7d654 1739)
1740
1741(define_insn "*mulsi3addsi_compare0_v6"
1742 [(set (reg:CC_NOOV CC_REGNUM)
1743 (compare:CC_NOOV
1744 (plus:SI (mult:SI
1745 (match_operand:SI 2 "s_register_operand" "r")
1746 (match_operand:SI 1 "s_register_operand" "r"))
1747 (match_operand:SI 3 "s_register_operand" "r"))
1748 (const_int 0)))
1749 (set (match_operand:SI 0 "s_register_operand" "=r")
1750 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1751 (match_dup 3)))]
1752 "TARGET_ARM && arm_arch6 && optimize_size"
3ef90e77 1753 "mlas%?\\t%0, %2, %1, %3"
0d66636f 1754 [(set_attr "conds" "set")
9da0ec36 1755 (set_attr "type" "mlas")]
0d66636f 1756)
9c08d1fa 1757
f7fbdd4a 1758(define_insn "*mulsi3addsi_compare0_scratch"
bd5b4116 1759 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1760 (compare:CC_NOOV
1761 (plus:SI (mult:SI
1762 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1763 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
215b30b3 1764 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1765 (const_int 0)))
9c08d1fa 1766 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
58d7d654 1767 "TARGET_ARM && !arm_arch6"
3ef90e77 1768 "mlas%?\\t%0, %2, %1, %3"
58d7d654 1769 [(set_attr "conds" "set")
9da0ec36 1770 (set_attr "type" "mlas")]
58d7d654 1771)
1772
1773(define_insn "*mulsi3addsi_compare0_scratch_v6"
1774 [(set (reg:CC_NOOV CC_REGNUM)
1775 (compare:CC_NOOV
1776 (plus:SI (mult:SI
1777 (match_operand:SI 2 "s_register_operand" "r")
1778 (match_operand:SI 1 "s_register_operand" "r"))
1779 (match_operand:SI 3 "s_register_operand" "r"))
1780 (const_int 0)))
1781 (clobber (match_scratch:SI 0 "=r"))]
1782 "TARGET_ARM && arm_arch6 && optimize_size"
3ef90e77 1783 "mlas%?\\t%0, %2, %1, %3"
cffb2a26 1784 [(set_attr "conds" "set")
9da0ec36 1785 (set_attr "type" "mlas")]
cffb2a26 1786)
f7fbdd4a 1787
89545238 1788(define_insn "*mulsi3subsi"
1789 [(set (match_operand:SI 0 "s_register_operand" "=r")
1790 (minus:SI
1791 (match_operand:SI 3 "s_register_operand" "r")
1792 (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1793 (match_operand:SI 1 "s_register_operand" "r"))))]
1794 "TARGET_32BIT && arm_arch_thumb2"
1795 "mls%?\\t%0, %2, %1, %3"
9da0ec36 1796 [(set_attr "type" "mla")
8bdfd6ed 1797 (set_attr "predicable" "yes")]
89545238 1798)
1799
5cdca009 1800(define_expand "maddsidi4"
3934ae0e 1801 [(set (match_operand:DI 0 "s_register_operand")
5cdca009 1802 (plus:DI
1803 (mult:DI
3934ae0e 1804 (sign_extend:DI (match_operand:SI 1 "s_register_operand"))
1805 (sign_extend:DI (match_operand:SI 2 "s_register_operand")))
1806 (match_operand:DI 3 "s_register_operand")))]
1930b04c 1807 "TARGET_32BIT"
5cdca009 1808 "")
82b85d08 1809
1810(define_insn "*mulsidi3adddi"
fe8dbf85 1811 [(set (match_operand:DI 0 "s_register_operand" "=&r")
82b85d08 1812 (plus:DI
215b30b3 1813 (mult:DI
fe8dbf85 1814 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1815 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1816 (match_operand:DI 1 "s_register_operand" "0")))]
1930b04c 1817 "TARGET_32BIT && !arm_arch6"
58d7d654 1818 "smlal%?\\t%Q0, %R0, %3, %2"
9da0ec36 1819 [(set_attr "type" "smlal")
58d7d654 1820 (set_attr "predicable" "yes")]
1821)
1822
1823(define_insn "*mulsidi3adddi_v6"
1824 [(set (match_operand:DI 0 "s_register_operand" "=r")
1825 (plus:DI
1826 (mult:DI
1827 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1828 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1829 (match_operand:DI 1 "s_register_operand" "0")))]
1830 "TARGET_32BIT && arm_arch6"
fe8dbf85 1831 "smlal%?\\t%Q0, %R0, %3, %2"
9da0ec36 1832 [(set_attr "type" "smlal")
8bdfd6ed 1833 (set_attr "predicable" "yes")]
0d66636f 1834)
82b85d08 1835
957788b0 1836;; 32x32->64 widening multiply.
1837;; As with mulsi3, the only difference between the v3-5 and v6+
1838;; versions of these patterns is the requirement that the output not
1839;; overlap the inputs, but that still means we have to have a named
1840;; expander and two different starred insns.
1841
1842(define_expand "mulsidi3"
3934ae0e 1843 [(set (match_operand:DI 0 "s_register_operand")
957788b0 1844 (mult:DI
3934ae0e 1845 (sign_extend:DI (match_operand:SI 1 "s_register_operand"))
1846 (sign_extend:DI (match_operand:SI 2 "s_register_operand"))))]
1930b04c 1847 "TARGET_32BIT"
957788b0 1848 ""
1849)
1850
1851(define_insn "*mulsidi3_nov6"
f7fbdd4a 1852 [(set (match_operand:DI 0 "s_register_operand" "=&r")
215b30b3 1853 (mult:DI
1854 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1855 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1930b04c 1856 "TARGET_32BIT && !arm_arch6"
58d7d654 1857 "smull%?\\t%Q0, %R0, %1, %2"
9da0ec36 1858 [(set_attr "type" "smull")
58d7d654 1859 (set_attr "predicable" "yes")]
1860)
1861
957788b0 1862(define_insn "*mulsidi3_v6"
58d7d654 1863 [(set (match_operand:DI 0 "s_register_operand" "=r")
1864 (mult:DI
1865 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1866 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1867 "TARGET_32BIT && arm_arch6"
97499065 1868 "smull%?\\t%Q0, %R0, %1, %2"
9da0ec36 1869 [(set_attr "type" "smull")
8bdfd6ed 1870 (set_attr "predicable" "yes")]
0d66636f 1871)
f7fbdd4a 1872
957788b0 1873(define_expand "umulsidi3"
3934ae0e 1874 [(set (match_operand:DI 0 "s_register_operand")
957788b0 1875 (mult:DI
3934ae0e 1876 (zero_extend:DI (match_operand:SI 1 "s_register_operand"))
1877 (zero_extend:DI (match_operand:SI 2 "s_register_operand"))))]
1930b04c 1878 "TARGET_32BIT"
957788b0 1879 ""
1880)
1881
1882(define_insn "*umulsidi3_nov6"
f7fbdd4a 1883 [(set (match_operand:DI 0 "s_register_operand" "=&r")
215b30b3 1884 (mult:DI
1885 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1886 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1930b04c 1887 "TARGET_32BIT && !arm_arch6"
58d7d654 1888 "umull%?\\t%Q0, %R0, %1, %2"
9da0ec36 1889 [(set_attr "type" "umull")
58d7d654 1890 (set_attr "predicable" "yes")]
1891)
1892
957788b0 1893(define_insn "*umulsidi3_v6"
58d7d654 1894 [(set (match_operand:DI 0 "s_register_operand" "=r")
1895 (mult:DI
1896 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1897 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1898 "TARGET_32BIT && arm_arch6"
97499065 1899 "umull%?\\t%Q0, %R0, %1, %2"
9da0ec36 1900 [(set_attr "type" "umull")
8bdfd6ed 1901 (set_attr "predicable" "yes")]
0d66636f 1902)
b11cae9e 1903
5cdca009 1904(define_expand "umaddsidi4"
3934ae0e 1905 [(set (match_operand:DI 0 "s_register_operand")
5cdca009 1906 (plus:DI
1907 (mult:DI
3934ae0e 1908 (zero_extend:DI (match_operand:SI 1 "s_register_operand"))
1909 (zero_extend:DI (match_operand:SI 2 "s_register_operand")))
1910 (match_operand:DI 3 "s_register_operand")))]
1930b04c 1911 "TARGET_32BIT"
5cdca009 1912 "")
82b85d08 1913
1914(define_insn "*umulsidi3adddi"
8ead09f9 1915 [(set (match_operand:DI 0 "s_register_operand" "=&r")
82b85d08 1916 (plus:DI
215b30b3 1917 (mult:DI
fe8dbf85 1918 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1919 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1920 (match_operand:DI 1 "s_register_operand" "0")))]
1930b04c 1921 "TARGET_32BIT && !arm_arch6"
58d7d654 1922 "umlal%?\\t%Q0, %R0, %3, %2"
9da0ec36 1923 [(set_attr "type" "umlal")
58d7d654 1924 (set_attr "predicable" "yes")]
1925)
1926
1927(define_insn "*umulsidi3adddi_v6"
1928 [(set (match_operand:DI 0 "s_register_operand" "=r")
1929 (plus:DI
1930 (mult:DI
1931 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1932 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1933 (match_operand:DI 1 "s_register_operand" "0")))]
1934 "TARGET_32BIT && arm_arch6"
fe8dbf85 1935 "umlal%?\\t%Q0, %R0, %3, %2"
9da0ec36 1936 [(set_attr "type" "umlal")
8bdfd6ed 1937 (set_attr "predicable" "yes")]
0d66636f 1938)
82b85d08 1939
957788b0 1940(define_expand "smulsi3_highpart"
1941 [(parallel
3934ae0e 1942 [(set (match_operand:SI 0 "s_register_operand")
957788b0 1943 (truncate:SI
1944 (lshiftrt:DI
1945 (mult:DI
3934ae0e 1946 (sign_extend:DI (match_operand:SI 1 "s_register_operand"))
1947 (sign_extend:DI (match_operand:SI 2 "s_register_operand")))
957788b0 1948 (const_int 32))))
1949 (clobber (match_scratch:SI 3 ""))])]
1930b04c 1950 "TARGET_32BIT"
957788b0 1951 ""
1952)
1953
1954(define_insn "*smulsi3_highpart_nov6"
f082f1c4 1955 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1956 (truncate:SI
1957 (lshiftrt:DI
215b30b3 1958 (mult:DI
e5fea38e 1959 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
215b30b3 1960 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
f082f1c4 1961 (const_int 32))))
1962 (clobber (match_scratch:SI 3 "=&r,&r"))]
1930b04c 1963 "TARGET_32BIT && !arm_arch6"
58d7d654 1964 "smull%?\\t%3, %0, %2, %1"
9da0ec36 1965 [(set_attr "type" "smull")
58d7d654 1966 (set_attr "predicable" "yes")]
1967)
1968
957788b0 1969(define_insn "*smulsi3_highpart_v6"
58d7d654 1970 [(set (match_operand:SI 0 "s_register_operand" "=r")
1971 (truncate:SI
1972 (lshiftrt:DI
1973 (mult:DI
1974 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1975 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1976 (const_int 32))))
1977 (clobber (match_scratch:SI 3 "=r"))]
1978 "TARGET_32BIT && arm_arch6"
f082f1c4 1979 "smull%?\\t%3, %0, %2, %1"
9da0ec36 1980 [(set_attr "type" "smull")
8bdfd6ed 1981 (set_attr "predicable" "yes")]
cffb2a26 1982)
f082f1c4 1983
957788b0 1984(define_expand "umulsi3_highpart"
1985 [(parallel
3934ae0e 1986 [(set (match_operand:SI 0 "s_register_operand")
957788b0 1987 (truncate:SI
1988 (lshiftrt:DI
1989 (mult:DI
3934ae0e 1990 (zero_extend:DI (match_operand:SI 1 "s_register_operand"))
1991 (zero_extend:DI (match_operand:SI 2 "s_register_operand")))
957788b0 1992 (const_int 32))))
1993 (clobber (match_scratch:SI 3 ""))])]
1930b04c 1994 "TARGET_32BIT"
957788b0 1995 ""
1996)
1997
1998(define_insn "*umulsi3_highpart_nov6"
f082f1c4 1999 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
2000 (truncate:SI
2001 (lshiftrt:DI
215b30b3 2002 (mult:DI
e5fea38e 2003 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
215b30b3 2004 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
f082f1c4 2005 (const_int 32))))
2006 (clobber (match_scratch:SI 3 "=&r,&r"))]
1930b04c 2007 "TARGET_32BIT && !arm_arch6"
58d7d654 2008 "umull%?\\t%3, %0, %2, %1"
9da0ec36 2009 [(set_attr "type" "umull")
58d7d654 2010 (set_attr "predicable" "yes")]
2011)
2012
957788b0 2013(define_insn "*umulsi3_highpart_v6"
58d7d654 2014 [(set (match_operand:SI 0 "s_register_operand" "=r")
2015 (truncate:SI
2016 (lshiftrt:DI
2017 (mult:DI
2018 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
2019 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
2020 (const_int 32))))
2021 (clobber (match_scratch:SI 3 "=r"))]
2022 "TARGET_32BIT && arm_arch6"
f082f1c4 2023 "umull%?\\t%3, %0, %2, %1"
9da0ec36 2024 [(set_attr "type" "umull")
8bdfd6ed 2025 (set_attr "predicable" "yes")]
cffb2a26 2026)
f082f1c4 2027
331beb1a 2028(define_insn "mulhisi3"
2029 [(set (match_operand:SI 0 "s_register_operand" "=r")
2030 (mult:SI (sign_extend:SI
2031 (match_operand:HI 1 "s_register_operand" "%r"))
2032 (sign_extend:SI
2033 (match_operand:HI 2 "s_register_operand" "r"))))]
25f905c2 2034 "TARGET_DSP_MULTIPLY"
61a2d04c 2035 "smulbb%?\\t%0, %1, %2"
9da0ec36 2036 [(set_attr "type" "smulxy")
fec538d9 2037 (set_attr "predicable" "yes")]
2038)
2039
2040(define_insn "*mulhisi3tb"
2041 [(set (match_operand:SI 0 "s_register_operand" "=r")
2042 (mult:SI (ashiftrt:SI
2043 (match_operand:SI 1 "s_register_operand" "r")
2044 (const_int 16))
2045 (sign_extend:SI
2046 (match_operand:HI 2 "s_register_operand" "r"))))]
25f905c2 2047 "TARGET_DSP_MULTIPLY"
fec538d9 2048 "smultb%?\\t%0, %1, %2"
9da0ec36 2049 [(set_attr "type" "smulxy")
8bdfd6ed 2050 (set_attr "predicable" "yes")]
fec538d9 2051)
2052
2053(define_insn "*mulhisi3bt"
2054 [(set (match_operand:SI 0 "s_register_operand" "=r")
2055 (mult:SI (sign_extend:SI
2056 (match_operand:HI 1 "s_register_operand" "r"))
2057 (ashiftrt:SI
2058 (match_operand:SI 2 "s_register_operand" "r")
2059 (const_int 16))))]
25f905c2 2060 "TARGET_DSP_MULTIPLY"
fec538d9 2061 "smulbt%?\\t%0, %1, %2"
9da0ec36 2062 [(set_attr "type" "smulxy")
8bdfd6ed 2063 (set_attr "predicable" "yes")]
fec538d9 2064)
2065
2066(define_insn "*mulhisi3tt"
2067 [(set (match_operand:SI 0 "s_register_operand" "=r")
2068 (mult:SI (ashiftrt:SI
2069 (match_operand:SI 1 "s_register_operand" "r")
2070 (const_int 16))
2071 (ashiftrt:SI
2072 (match_operand:SI 2 "s_register_operand" "r")
2073 (const_int 16))))]
25f905c2 2074 "TARGET_DSP_MULTIPLY"
fec538d9 2075 "smultt%?\\t%0, %1, %2"
9da0ec36 2076 [(set_attr "type" "smulxy")
8bdfd6ed 2077 (set_attr "predicable" "yes")]
331beb1a 2078)
2079
5cdca009 2080(define_insn "maddhisi4"
331beb1a 2081 [(set (match_operand:SI 0 "s_register_operand" "=r")
cfa6c608 2082 (plus:SI (mult:SI (sign_extend:SI
2083 (match_operand:HI 1 "s_register_operand" "r"))
331beb1a 2084 (sign_extend:SI
cfa6c608 2085 (match_operand:HI 2 "s_register_operand" "r")))
2086 (match_operand:SI 3 "s_register_operand" "r")))]
25f905c2 2087 "TARGET_DSP_MULTIPLY"
5cdca009 2088 "smlabb%?\\t%0, %1, %2, %3"
9da0ec36 2089 [(set_attr "type" "smlaxy")
8bdfd6ed 2090 (set_attr "predicable" "yes")]
331beb1a 2091)
2092
9a92f368 2093;; Note: there is no maddhisi4ibt because this one is canonical form
2094(define_insn "*maddhisi4tb"
2095 [(set (match_operand:SI 0 "s_register_operand" "=r")
2096 (plus:SI (mult:SI (ashiftrt:SI
2097 (match_operand:SI 1 "s_register_operand" "r")
2098 (const_int 16))
2099 (sign_extend:SI
2100 (match_operand:HI 2 "s_register_operand" "r")))
2101 (match_operand:SI 3 "s_register_operand" "r")))]
2102 "TARGET_DSP_MULTIPLY"
2103 "smlatb%?\\t%0, %1, %2, %3"
9da0ec36 2104 [(set_attr "type" "smlaxy")
8bdfd6ed 2105 (set_attr "predicable" "yes")]
9a92f368 2106)
2107
2108(define_insn "*maddhisi4tt"
2109 [(set (match_operand:SI 0 "s_register_operand" "=r")
2110 (plus:SI (mult:SI (ashiftrt:SI
2111 (match_operand:SI 1 "s_register_operand" "r")
2112 (const_int 16))
2113 (ashiftrt:SI
2114 (match_operand:SI 2 "s_register_operand" "r")
2115 (const_int 16)))
2116 (match_operand:SI 3 "s_register_operand" "r")))]
2117 "TARGET_DSP_MULTIPLY"
2118 "smlatt%?\\t%0, %1, %2, %3"
9da0ec36 2119 [(set_attr "type" "smlaxy")
8bdfd6ed 2120 (set_attr "predicable" "yes")]
9a92f368 2121)
2122
aff5fb4d 2123(define_insn "maddhidi4"
331beb1a 2124 [(set (match_operand:DI 0 "s_register_operand" "=r")
2125 (plus:DI
331beb1a 2126 (mult:DI (sign_extend:DI
d952d547 2127 (match_operand:HI 1 "s_register_operand" "r"))
331beb1a 2128 (sign_extend:DI
cfa6c608 2129 (match_operand:HI 2 "s_register_operand" "r")))
2130 (match_operand:DI 3 "s_register_operand" "0")))]
25f905c2 2131 "TARGET_DSP_MULTIPLY"
5cdca009 2132 "smlalbb%?\\t%Q0, %R0, %1, %2"
9da0ec36 2133 [(set_attr "type" "smlalxy")
8bdfd6ed 2134 (set_attr "predicable" "yes")])
331beb1a 2135
9a92f368 2136;; Note: there is no maddhidi4ibt because this one is canonical form
2137(define_insn "*maddhidi4tb"
2138 [(set (match_operand:DI 0 "s_register_operand" "=r")
2139 (plus:DI
2140 (mult:DI (sign_extend:DI
2141 (ashiftrt:SI
2142 (match_operand:SI 1 "s_register_operand" "r")
2143 (const_int 16)))
2144 (sign_extend:DI
2145 (match_operand:HI 2 "s_register_operand" "r")))
2146 (match_operand:DI 3 "s_register_operand" "0")))]
2147 "TARGET_DSP_MULTIPLY"
2148 "smlaltb%?\\t%Q0, %R0, %1, %2"
9da0ec36 2149 [(set_attr "type" "smlalxy")
8bdfd6ed 2150 (set_attr "predicable" "yes")])
9a92f368 2151
2152(define_insn "*maddhidi4tt"
2153 [(set (match_operand:DI 0 "s_register_operand" "=r")
2154 (plus:DI
2155 (mult:DI (sign_extend:DI
2156 (ashiftrt:SI
2157 (match_operand:SI 1 "s_register_operand" "r")
2158 (const_int 16)))
2159 (sign_extend:DI
2160 (ashiftrt:SI
2161 (match_operand:SI 2 "s_register_operand" "r")
2162 (const_int 16))))
2163 (match_operand:DI 3 "s_register_operand" "0")))]
2164 "TARGET_DSP_MULTIPLY"
2165 "smlaltt%?\\t%Q0, %R0, %1, %2"
9da0ec36 2166 [(set_attr "type" "smlalxy")
8bdfd6ed 2167 (set_attr "predicable" "yes")])
9a92f368 2168
604f3a0a 2169(define_expand "mulsf3"
3934ae0e 2170 [(set (match_operand:SF 0 "s_register_operand")
2171 (mult:SF (match_operand:SF 1 "s_register_operand")
2172 (match_operand:SF 2 "s_register_operand")))]
25f905c2 2173 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 2174 "
604f3a0a 2175")
2176
604f3a0a 2177(define_expand "muldf3"
3934ae0e 2178 [(set (match_operand:DF 0 "s_register_operand")
2179 (mult:DF (match_operand:DF 1 "s_register_operand")
2180 (match_operand:DF 2 "s_register_operand")))]
a50d7267 2181 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 2182 "
604f3a0a 2183")
b11cae9e 2184\f
2185;; Division insns
2186
7db9af5d 2187(define_expand "divsf3"
3934ae0e 2188 [(set (match_operand:SF 0 "s_register_operand")
2189 (div:SF (match_operand:SF 1 "s_register_operand")
2190 (match_operand:SF 2 "s_register_operand")))]
d7216193 2191 "TARGET_32BIT && TARGET_HARD_FLOAT"
7db9af5d 2192 "")
9c08d1fa 2193
7db9af5d 2194(define_expand "divdf3"
3934ae0e 2195 [(set (match_operand:DF 0 "s_register_operand")
2196 (div:DF (match_operand:DF 1 "s_register_operand")
2197 (match_operand:DF 2 "s_register_operand")))]
994606f8 2198 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
7db9af5d 2199 "")
b11cae9e 2200\f
2201;; Boolean and,ior,xor insns
2202
f6ebffac 2203;; Split up double word logical operations
2204
2205;; Split up simple DImode logical operations. Simply perform the logical
2206;; operation on the upper and lower halves of the registers.
2207(define_split
2208 [(set (match_operand:DI 0 "s_register_operand" "")
2209 (match_operator:DI 6 "logical_binary_operator"
2210 [(match_operand:DI 1 "s_register_operand" "")
2211 (match_operand:DI 2 "s_register_operand" "")]))]
25f905c2 2212 "TARGET_32BIT && reload_completed
e2669ea7 2213 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))
25f905c2 2214 && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
f6ebffac 2215 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
2216 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
2217 "
215b30b3 2218 {
2219 operands[3] = gen_highpart (SImode, operands[0]);
2220 operands[0] = gen_lowpart (SImode, operands[0]);
2221 operands[4] = gen_highpart (SImode, operands[1]);
2222 operands[1] = gen_lowpart (SImode, operands[1]);
2223 operands[5] = gen_highpart (SImode, operands[2]);
2224 operands[2] = gen_lowpart (SImode, operands[2]);
2225 }"
2226)
f6ebffac 2227
f6ebffac 2228(define_split
2229 [(set (match_operand:DI 0 "s_register_operand" "")
2230 (match_operator:DI 6 "logical_binary_operator"
2231 [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
2232 (match_operand:DI 1 "s_register_operand" "")]))]
25f905c2 2233 "TARGET_32BIT && reload_completed"
f6ebffac 2234 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
2235 (set (match_dup 3) (match_op_dup:SI 6
2236 [(ashiftrt:SI (match_dup 2) (const_int 31))
2237 (match_dup 4)]))]
2238 "
215b30b3 2239 {
2240 operands[3] = gen_highpart (SImode, operands[0]);
2241 operands[0] = gen_lowpart (SImode, operands[0]);
2242 operands[4] = gen_highpart (SImode, operands[1]);
2243 operands[1] = gen_lowpart (SImode, operands[1]);
2244 operands[5] = gen_highpart (SImode, operands[2]);
2245 operands[2] = gen_lowpart (SImode, operands[2]);
2246 }"
2247)
f6ebffac 2248
f6ebffac 2249;; The zero extend of operand 2 means we can just copy the high part of
2250;; operand1 into operand0.
2251(define_split
2252 [(set (match_operand:DI 0 "s_register_operand" "")
2253 (ior:DI
2254 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
2255 (match_operand:DI 1 "s_register_operand" "")))]
25f905c2 2256 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
f6ebffac 2257 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
2258 (set (match_dup 3) (match_dup 4))]
2259 "
215b30b3 2260 {
2261 operands[4] = gen_highpart (SImode, operands[1]);
2262 operands[3] = gen_highpart (SImode, operands[0]);
2263 operands[0] = gen_lowpart (SImode, operands[0]);
2264 operands[1] = gen_lowpart (SImode, operands[1]);
2265 }"
2266)
f6ebffac 2267
2268;; The zero extend of operand 2 means we can just copy the high part of
2269;; operand1 into operand0.
2270(define_split
2271 [(set (match_operand:DI 0 "s_register_operand" "")
2272 (xor:DI
2273 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
2274 (match_operand:DI 1 "s_register_operand" "")))]
25f905c2 2275 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
f6ebffac 2276 [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
2277 (set (match_dup 3) (match_dup 4))]
2278 "
215b30b3 2279 {
2280 operands[4] = gen_highpart (SImode, operands[1]);
2281 operands[3] = gen_highpart (SImode, operands[0]);
2282 operands[0] = gen_lowpart (SImode, operands[0]);
2283 operands[1] = gen_lowpart (SImode, operands[1]);
2284 }"
2285)
f6ebffac 2286
e2669ea7 2287(define_expand "anddi3"
3934ae0e 2288 [(set (match_operand:DI 0 "s_register_operand")
2289 (and:DI (match_operand:DI 1 "s_register_operand")
2290 (match_operand:DI 2 "neon_inv_logic_op2")))]
e2669ea7 2291 "TARGET_32BIT"
0d84c6e5 2292 "
2293 if (!TARGET_NEON && !TARGET_IWMMXT)
2294 {
2295 rtx low = simplify_gen_binary (AND, SImode,
2296 gen_lowpart (SImode, operands[1]),
2297 gen_lowpart (SImode, operands[2]));
2298 rtx high = simplify_gen_binary (AND, SImode,
2299 gen_highpart (SImode, operands[1]),
2300 gen_highpart_mode (SImode, DImode,
2301 operands[2]));
2302
2303 emit_insn (gen_rtx_SET (gen_lowpart (SImode, operands[0]), low));
2304 emit_insn (gen_rtx_SET (gen_highpart (SImode, operands[0]), high));
2305
2306 DONE;
2307 }
2308 /* Otherwise expand pattern as above. */
2309 "
e2669ea7 2310)
2311
f6bbdcf6 2312(define_insn_and_split "*anddi3_insn"
0a314dcd 2313 [(set (match_operand:DI 0 "s_register_operand" "=w,w ,&r,&r,&r,&r,?w,?w")
2314 (and:DI (match_operand:DI 1 "s_register_operand" "%w,0 ,0 ,r ,0 ,r ,w ,0")
2315 (match_operand:DI 2 "arm_anddi_operand_neon" "w ,DL,r ,r ,De,De,w ,DL")))]
f6bbdcf6 2316 "TARGET_32BIT && !TARGET_IWMMXT"
2317{
2318 switch (which_alternative)
2319 {
0a314dcd 2320 case 0: /* fall through */
2321 case 6: return "vand\t%P0, %P1, %P2";
2322 case 1: /* fall through */
2323 case 7: return neon_output_logic_immediate ("vand", &operands[2],
2324 DImode, 1, VALID_NEON_QREG_MODE (DImode));
f6bbdcf6 2325 case 2:
0a314dcd 2326 case 3:
2327 case 4:
f6bbdcf6 2328 case 5: /* fall through */
0a314dcd 2329 return "#";
f6bbdcf6 2330 default: gcc_unreachable ();
2331 }
2332}
0a314dcd 2333 "TARGET_32BIT && !TARGET_IWMMXT && reload_completed
2334 && !(IS_VFP_REGNUM (REGNO (operands[0])))"
f6bbdcf6 2335 [(set (match_dup 3) (match_dup 4))
2336 (set (match_dup 5) (match_dup 6))]
2337 "
2338 {
2339 operands[3] = gen_lowpart (SImode, operands[0]);
2340 operands[5] = gen_highpart (SImode, operands[0]);
2341
2342 operands[4] = simplify_gen_binary (AND, SImode,
2343 gen_lowpart (SImode, operands[1]),
2344 gen_lowpart (SImode, operands[2]));
2345 operands[6] = simplify_gen_binary (AND, SImode,
2346 gen_highpart (SImode, operands[1]),
2347 gen_highpart_mode (SImode, DImode, operands[2]));
2348
2349 }"
32093010 2350 [(set_attr "type" "neon_logic,neon_logic,multiple,multiple,\
2351 multiple,multiple,neon_logic,neon_logic")
0a314dcd 2352 (set_attr "arch" "neon_for_64bits,neon_for_64bits,*,*,*,*,
f6bbdcf6 2353 avoid_neon_for_64bits,avoid_neon_for_64bits")
0a314dcd 2354 (set_attr "length" "*,*,8,8,8,8,*,*")
2355 ]
215b30b3 2356)
b11cae9e 2357
a0f94409 2358(define_insn_and_split "*anddi_zesidi_di"
9c08d1fa 2359 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2360 (and:DI (zero_extend:DI
2361 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 2362 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2363 "TARGET_32BIT"
f6ebffac 2364 "#"
25f905c2 2365 "TARGET_32BIT && reload_completed"
a0f94409 2366 ; The zero extend of operand 2 clears the high word of the output
2367 ; operand.
2368 [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
2369 (set (match_dup 3) (const_int 0))]
2370 "
2371 {
2372 operands[3] = gen_highpart (SImode, operands[0]);
2373 operands[0] = gen_lowpart (SImode, operands[0]);
2374 operands[1] = gen_lowpart (SImode, operands[1]);
2375 }"
1b7da4ac 2376 [(set_attr "length" "8")
2377 (set_attr "type" "multiple")]
215b30b3 2378)
b11cae9e 2379
f7fbdd4a 2380(define_insn "*anddi_sesdi_di"
cffb2a26 2381 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 2382 (and:DI (sign_extend:DI
2383 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 2384 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2385 "TARGET_32BIT"
f6ebffac 2386 "#"
1b7da4ac 2387 [(set_attr "length" "8")
2388 (set_attr "type" "multiple")]
cffb2a26 2389)
b11cae9e 2390
87b22bf7 2391(define_expand "andsi3"
3934ae0e 2392 [(set (match_operand:SI 0 "s_register_operand")
2393 (and:SI (match_operand:SI 1 "s_register_operand")
2394 (match_operand:SI 2 "reg_or_int_operand")))]
cffb2a26 2395 "TARGET_EITHER"
87b22bf7 2396 "
25f905c2 2397 if (TARGET_32BIT)
87b22bf7 2398 {
0438d37f 2399 if (CONST_INT_P (operands[2]))
cffb2a26 2400 {
47b5b27b 2401 if (INTVAL (operands[2]) == 255 && arm_arch6)
2402 {
2403 operands[1] = convert_to_mode (QImode, operands[1], 1);
2404 emit_insn (gen_thumb2_zero_extendqisi2_v6 (operands[0],
2405 operands[1]));
17202aa5 2406 DONE;
47b5b27b 2407 }
17202aa5 2408 else if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[2]), AND))
2409 operands[2] = force_reg (SImode, operands[2]);
47b5b27b 2410 else
17202aa5 2411 {
2412 arm_split_constant (AND, SImode, NULL_RTX,
2413 INTVAL (operands[2]), operands[0],
2414 operands[1],
2415 optimize && can_create_pseudo_p ());
615caa51 2416
17202aa5 2417 DONE;
2418 }
cffb2a26 2419 }
87b22bf7 2420 }
25f905c2 2421 else /* TARGET_THUMB1 */
cffb2a26 2422 {
0438d37f 2423 if (!CONST_INT_P (operands[2]))
923ffadb 2424 {
2425 rtx tmp = force_reg (SImode, operands[2]);
2426 if (rtx_equal_p (operands[0], operands[1]))
2427 operands[2] = tmp;
2428 else
2429 {
2430 operands[2] = operands[1];
2431 operands[1] = tmp;
2432 }
2433 }
cffb2a26 2434 else
2435 {
2436 int i;
2437
215b30b3 2438 if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
cffb2a26 2439 {
215b30b3 2440 operands[2] = force_reg (SImode,
2441 GEN_INT (~INTVAL (operands[2])));
cffb2a26 2442
747b7458 2443 emit_insn (gen_thumb1_bicsi3 (operands[0], operands[2], operands[1]));
cffb2a26 2444
2445 DONE;
2446 }
87b22bf7 2447
cffb2a26 2448 for (i = 9; i <= 31; i++)
2449 {
db2faf44 2450 if ((HOST_WIDE_INT_1 << i) - 1 == INTVAL (operands[2]))
cffb2a26 2451 {
2452 emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
2453 const0_rtx));
2454 DONE;
2455 }
db2faf44 2456 else if ((HOST_WIDE_INT_1 << i) - 1
215b30b3 2457 == ~INTVAL (operands[2]))
cffb2a26 2458 {
2459 rtx shift = GEN_INT (i);
2460 rtx reg = gen_reg_rtx (SImode);
2461
2462 emit_insn (gen_lshrsi3 (reg, operands[1], shift));
2463 emit_insn (gen_ashlsi3 (operands[0], reg, shift));
2464
2465 DONE;
2466 }
2467 }
2468
2469 operands[2] = force_reg (SImode, operands[2]);
2470 }
215b30b3 2471 }
2472 "
cffb2a26 2473)
2474
25f905c2 2475; ??? Check split length for Thumb-2
a0f94409 2476(define_insn_and_split "*arm_andsi3_insn"
29e234a3 2477 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r,r,r")
2478 (and:SI (match_operand:SI 1 "s_register_operand" "%r,0,r,r,r")
2479 (match_operand:SI 2 "reg_or_int_operand" "I,l,K,r,?n")))]
25f905c2 2480 "TARGET_32BIT"
5565501b 2481 "@
29e234a3 2482 and%?\\t%0, %1, %2
5565501b 2483 and%?\\t%0, %1, %2
87b22bf7 2484 bic%?\\t%0, %1, #%B2
65f68e55 2485 and%?\\t%0, %1, %2
87b22bf7 2486 #"
25f905c2 2487 "TARGET_32BIT
0438d37f 2488 && CONST_INT_P (operands[2])
a0f94409 2489 && !(const_ok_for_arm (INTVAL (operands[2]))
2490 || const_ok_for_arm (~INTVAL (operands[2])))"
2491 [(clobber (const_int 0))]
2492 "
96f57e36 2493 arm_split_constant (AND, SImode, curr_insn,
2494 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 2495 DONE;
2496 "
29e234a3 2497 [(set_attr "length" "4,4,4,4,16")
65f68e55 2498 (set_attr "predicable" "yes")
29e234a3 2499 (set_attr "predicable_short_it" "no,yes,no,no,no")
d82e788e 2500 (set_attr "type" "logic_imm,logic_imm,logic_reg,logic_reg,logic_imm")]
cffb2a26 2501)
2502
f7fbdd4a 2503(define_insn "*andsi3_compare0"
bd5b4116 2504 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 2505 (compare:CC_NOOV
65f68e55 2506 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
2507 (match_operand:SI 2 "arm_not_operand" "I,K,r"))
5565501b 2508 (const_int 0)))
65f68e55 2509 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9c08d1fa 2510 (and:SI (match_dup 1) (match_dup 2)))]
25f905c2 2511 "TARGET_32BIT"
5565501b 2512 "@
3ef90e77 2513 ands%?\\t%0, %1, %2
2514 bics%?\\t%0, %1, #%B2
2515 ands%?\\t%0, %1, %2"
65f68e55 2516 [(set_attr "conds" "set")
d82e788e 2517 (set_attr "type" "logics_imm,logics_imm,logics_reg")]
cffb2a26 2518)
9c08d1fa 2519
f7fbdd4a 2520(define_insn "*andsi3_compare0_scratch"
bd5b4116 2521 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 2522 (compare:CC_NOOV
65f68e55 2523 (and:SI (match_operand:SI 0 "s_register_operand" "r,r,r")
2524 (match_operand:SI 1 "arm_not_operand" "I,K,r"))
5565501b 2525 (const_int 0)))
65f68e55 2526 (clobber (match_scratch:SI 2 "=X,r,X"))]
25f905c2 2527 "TARGET_32BIT"
5565501b 2528 "@
2529 tst%?\\t%0, %1
3ef90e77 2530 bics%?\\t%2, %0, #%B1
65f68e55 2531 tst%?\\t%0, %1"
2532 [(set_attr "conds" "set")
d82e788e 2533 (set_attr "type" "logics_imm,logics_imm,logics_reg")]
0d66636f 2534)
9c08d1fa 2535
f7fbdd4a 2536(define_insn "*zeroextractsi_compare0_scratch"
bd5b4116 2537 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2538 (compare:CC_NOOV (zero_extract:SI
2539 (match_operand:SI 0 "s_register_operand" "r")
d952d547 2540 (match_operand 1 "const_int_operand" "n")
206ee9a2 2541 (match_operand 2 "const_int_operand" "n"))
9c08d1fa 2542 (const_int 0)))]
25f905c2 2543 "TARGET_32BIT
cffb2a26 2544 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
2545 && INTVAL (operands[1]) > 0
2546 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
2547 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
9c08d1fa 2548 "*
5c49a439 2549 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
2550 << INTVAL (operands[2]));
40dbec34 2551 output_asm_insn (\"tst%?\\t%0, %1\", operands);
e2348bcb 2552 return \"\";
0d66636f 2553 "
596e5e8f 2554 [(set_attr "conds" "set")
65f68e55 2555 (set_attr "predicable" "yes")
d82e788e 2556 (set_attr "type" "logics_imm")]
0d66636f 2557)
9c08d1fa 2558
f4462328 2559(define_insn_and_split "*ne_zeroextractsi"
c4034607 2560 [(set (match_operand:SI 0 "s_register_operand" "=r")
2561 (ne:SI (zero_extract:SI
2562 (match_operand:SI 1 "s_register_operand" "r")
2563 (match_operand:SI 2 "const_int_operand" "n")
2564 (match_operand:SI 3 "const_int_operand" "n"))
3b8c7f7a 2565 (const_int 0)))
2566 (clobber (reg:CC CC_REGNUM))]
25f905c2 2567 "TARGET_32BIT
cffb2a26 2568 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2569 && INTVAL (operands[2]) > 0
2570 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2571 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
f4462328 2572 "#"
25f905c2 2573 "TARGET_32BIT
f4462328 2574 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2575 && INTVAL (operands[2]) > 0
2576 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2577 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
2578 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2579 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2580 (const_int 0)))
2581 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2582 (set (match_dup 0)
2583 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2584 (match_dup 0) (const_int 1)))]
2585 "
2586 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
2587 << INTVAL (operands[3]));
2588 "
2589 [(set_attr "conds" "clob")
25f905c2 2590 (set (attr "length")
2591 (if_then_else (eq_attr "is_thumb" "yes")
2592 (const_int 12)
1b7da4ac 2593 (const_int 8)))
2594 (set_attr "type" "multiple")]
f4462328 2595)
2596
2597(define_insn_and_split "*ne_zeroextractsi_shifted"
2598 [(set (match_operand:SI 0 "s_register_operand" "=r")
2599 (ne:SI (zero_extract:SI
2600 (match_operand:SI 1 "s_register_operand" "r")
2601 (match_operand:SI 2 "const_int_operand" "n")
2602 (const_int 0))
2603 (const_int 0)))
2604 (clobber (reg:CC CC_REGNUM))]
2605 "TARGET_ARM"
2606 "#"
2607 "TARGET_ARM"
2608 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2609 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2610 (const_int 0)))
2611 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2612 (set (match_dup 0)
2613 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2614 (match_dup 0) (const_int 1)))]
2615 "
2616 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
2617 "
2618 [(set_attr "conds" "clob")
1b7da4ac 2619 (set_attr "length" "8")
2620 (set_attr "type" "multiple")]
f4462328 2621)
2622
2623(define_insn_and_split "*ite_ne_zeroextractsi"
2624 [(set (match_operand:SI 0 "s_register_operand" "=r")
2625 (if_then_else:SI (ne (zero_extract:SI
2626 (match_operand:SI 1 "s_register_operand" "r")
2627 (match_operand:SI 2 "const_int_operand" "n")
2628 (match_operand:SI 3 "const_int_operand" "n"))
2629 (const_int 0))
2630 (match_operand:SI 4 "arm_not_operand" "rIK")
2631 (const_int 0)))
2632 (clobber (reg:CC CC_REGNUM))]
2633 "TARGET_ARM
2634 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2635 && INTVAL (operands[2]) > 0
2636 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 2637 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2638 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 2639 "#"
2640 "TARGET_ARM
2641 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2642 && INTVAL (operands[2]) > 0
2643 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 2644 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2645 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 2646 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2647 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2648 (const_int 0)))
2649 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2650 (set (match_dup 0)
2651 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2652 (match_dup 0) (match_dup 4)))]
2653 "
c4034607 2654 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
f4462328 2655 << INTVAL (operands[3]));
2656 "
2657 [(set_attr "conds" "clob")
1b7da4ac 2658 (set_attr "length" "8")
2659 (set_attr "type" "multiple")]
f4462328 2660)
2661
2662(define_insn_and_split "*ite_ne_zeroextractsi_shifted"
2663 [(set (match_operand:SI 0 "s_register_operand" "=r")
2664 (if_then_else:SI (ne (zero_extract:SI
2665 (match_operand:SI 1 "s_register_operand" "r")
2666 (match_operand:SI 2 "const_int_operand" "n")
2667 (const_int 0))
2668 (const_int 0))
2669 (match_operand:SI 3 "arm_not_operand" "rIK")
2670 (const_int 0)))
2671 (clobber (reg:CC CC_REGNUM))]
f8d7bf2f 2672 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 2673 "#"
f8d7bf2f 2674 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 2675 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2676 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2677 (const_int 0)))
2678 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2679 (set (match_dup 0)
2680 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2681 (match_dup 0) (match_dup 3)))]
2682 "
2683 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
0d66636f 2684 "
2685 [(set_attr "conds" "clob")
1b7da4ac 2686 (set_attr "length" "8")
2687 (set_attr "type" "multiple")]
215b30b3 2688)
9c08d1fa 2689
25f905c2 2690;; ??? Use Thumb-2 has bitfield insert/extract instructions.
d7863cfe 2691(define_split
2692 [(set (match_operand:SI 0 "s_register_operand" "")
2693 (match_operator:SI 1 "shiftable_operator"
2694 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2695 (match_operand:SI 3 "const_int_operand" "")
2696 (match_operand:SI 4 "const_int_operand" ""))
2697 (match_operand:SI 5 "s_register_operand" "")]))
2698 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2699 "TARGET_ARM"
2700 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2701 (set (match_dup 0)
2702 (match_op_dup 1
2703 [(lshiftrt:SI (match_dup 6) (match_dup 4))
2704 (match_dup 5)]))]
2705 "{
2706 HOST_WIDE_INT temp = INTVAL (operands[3]);
2707
2708 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2709 operands[4] = GEN_INT (32 - temp);
2710 }"
2711)
2712
d7863cfe 2713(define_split
2714 [(set (match_operand:SI 0 "s_register_operand" "")
2715 (match_operator:SI 1 "shiftable_operator"
2716 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2717 (match_operand:SI 3 "const_int_operand" "")
2718 (match_operand:SI 4 "const_int_operand" ""))
2719 (match_operand:SI 5 "s_register_operand" "")]))
2720 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2721 "TARGET_ARM"
2722 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2723 (set (match_dup 0)
2724 (match_op_dup 1
2725 [(ashiftrt:SI (match_dup 6) (match_dup 4))
2726 (match_dup 5)]))]
2727 "{
2728 HOST_WIDE_INT temp = INTVAL (operands[3]);
2729
2730 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2731 operands[4] = GEN_INT (32 - temp);
2732 }"
2733)
2734
a42059fd 2735;;; ??? This pattern is bogus. If operand3 has bits outside the range
2736;;; represented by the bitfield, then this will produce incorrect results.
2737;;; Somewhere, the value needs to be truncated. On targets like the m68k,
ceb2fe0f 2738;;; which have a real bit-field insert instruction, the truncation happens
2739;;; in the bit-field insert instruction itself. Since arm does not have a
2740;;; bit-field insert instruction, we would have to emit code here to truncate
a42059fd 2741;;; the value before we insert. This loses some of the advantage of having
2742;;; this insv pattern, so this pattern needs to be reevalutated.
2743
8a18b90c 2744(define_expand "insv"
3934ae0e 2745 [(set (zero_extract (match_operand 0 "nonimmediate_operand")
2746 (match_operand 1 "general_operand")
2747 (match_operand 2 "general_operand"))
2748 (match_operand 3 "reg_or_int_operand"))]
8b054d5a 2749 "TARGET_ARM || arm_arch_thumb2"
8a18b90c 2750 "
215b30b3 2751 {
2752 int start_bit = INTVAL (operands[2]);
2753 int width = INTVAL (operands[1]);
db2faf44 2754 HOST_WIDE_INT mask = (HOST_WIDE_INT_1 << width) - 1;
215b30b3 2755 rtx target, subtarget;
2756
8b054d5a 2757 if (arm_arch_thumb2)
2758 {
eb04cafb 2759 if (unaligned_access && MEM_P (operands[0])
2760 && s_register_operand (operands[3], GET_MODE (operands[3]))
2761 && (width == 16 || width == 32) && (start_bit % BITS_PER_UNIT) == 0)
8b054d5a 2762 {
eb04cafb 2763 rtx base_addr;
2764
2765 if (BYTES_BIG_ENDIAN)
2766 start_bit = GET_MODE_BITSIZE (GET_MODE (operands[3])) - width
2767 - start_bit;
8b054d5a 2768
eb04cafb 2769 if (width == 32)
8b054d5a 2770 {
eb04cafb 2771 base_addr = adjust_address (operands[0], SImode,
2772 start_bit / BITS_PER_UNIT);
2773 emit_insn (gen_unaligned_storesi (base_addr, operands[3]));
8b054d5a 2774 }
eb04cafb 2775 else
2776 {
2777 rtx tmp = gen_reg_rtx (HImode);
8b054d5a 2778
eb04cafb 2779 base_addr = adjust_address (operands[0], HImode,
2780 start_bit / BITS_PER_UNIT);
2781 emit_move_insn (tmp, gen_lowpart (HImode, operands[3]));
2782 emit_insn (gen_unaligned_storehi (base_addr, tmp));
2783 }
2784 DONE;
8b054d5a 2785 }
eb04cafb 2786 else if (s_register_operand (operands[0], GET_MODE (operands[0])))
8b054d5a 2787 {
eb04cafb 2788 bool use_bfi = TRUE;
8b054d5a 2789
0438d37f 2790 if (CONST_INT_P (operands[3]))
eb04cafb 2791 {
2792 HOST_WIDE_INT val = INTVAL (operands[3]) & mask;
2793
2794 if (val == 0)
2795 {
2796 emit_insn (gen_insv_zero (operands[0], operands[1],
2797 operands[2]));
2798 DONE;
2799 }
2800
2801 /* See if the set can be done with a single orr instruction. */
2802 if (val == mask && const_ok_for_arm (val << start_bit))
2803 use_bfi = FALSE;
2804 }
2805
2806 if (use_bfi)
2807 {
0438d37f 2808 if (!REG_P (operands[3]))
eb04cafb 2809 operands[3] = force_reg (SImode, operands[3]);
2810
2811 emit_insn (gen_insv_t2 (operands[0], operands[1], operands[2],
2812 operands[3]));
2813 DONE;
2814 }
8b054d5a 2815 }
eb04cafb 2816 else
2817 FAIL;
8b054d5a 2818 }
2819
eb04cafb 2820 if (!s_register_operand (operands[0], GET_MODE (operands[0])))
2821 FAIL;
2822
3f8fde42 2823 target = copy_rtx (operands[0]);
215b30b3 2824 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
2825 subreg as the final target. */
2826 if (GET_CODE (target) == SUBREG)
2827 {
2828 subtarget = gen_reg_rtx (SImode);
2829 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
2830 < GET_MODE_SIZE (SImode))
2831 target = SUBREG_REG (target);
2832 }
2833 else
2834 subtarget = target;
8a18b90c 2835
0438d37f 2836 if (CONST_INT_P (operands[3]))
215b30b3 2837 {
2838 /* Since we are inserting a known constant, we may be able to
2839 reduce the number of bits that we have to clear so that
2840 the mask becomes simple. */
2841 /* ??? This code does not check to see if the new mask is actually
2842 simpler. It may not be. */
2843 rtx op1 = gen_reg_rtx (SImode);
2844 /* ??? Truncate operand3 to fit in the bitfield. See comment before
2845 start of this pattern. */
2846 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
2847 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
2848
c5b3a71b 2849 emit_insn (gen_andsi3 (op1, operands[0],
2850 gen_int_mode (~mask2, SImode)));
215b30b3 2851 emit_insn (gen_iorsi3 (subtarget, op1,
4292ca6b 2852 gen_int_mode (op3_value << start_bit, SImode)));
215b30b3 2853 }
2854 else if (start_bit == 0
2855 && !(const_ok_for_arm (mask)
2856 || const_ok_for_arm (~mask)))
2857 {
2858 /* A Trick, since we are setting the bottom bits in the word,
2859 we can shift operand[3] up, operand[0] down, OR them together
2860 and rotate the result back again. This takes 3 insns, and
5910bb95 2861 the third might be mergeable into another op. */
215b30b3 2862 /* The shift up copes with the possibility that operand[3] is
2863 wider than the bitfield. */
2864 rtx op0 = gen_reg_rtx (SImode);
2865 rtx op1 = gen_reg_rtx (SImode);
2866
2867 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2868 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
2869 emit_insn (gen_iorsi3 (op1, op1, op0));
2870 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
2871 }
2872 else if ((width + start_bit == 32)
2873 && !(const_ok_for_arm (mask)
2874 || const_ok_for_arm (~mask)))
2875 {
2876 /* Similar trick, but slightly less efficient. */
8a18b90c 2877
215b30b3 2878 rtx op0 = gen_reg_rtx (SImode);
2879 rtx op1 = gen_reg_rtx (SImode);
8a18b90c 2880
215b30b3 2881 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2882 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
2883 emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
2884 emit_insn (gen_iorsi3 (subtarget, op1, op0));
2885 }
2886 else
2887 {
c5b3a71b 2888 rtx op0 = gen_int_mode (mask, SImode);
215b30b3 2889 rtx op1 = gen_reg_rtx (SImode);
2890 rtx op2 = gen_reg_rtx (SImode);
8a18b90c 2891
215b30b3 2892 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
2893 {
2894 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 2895
215b30b3 2896 emit_insn (gen_movsi (tmp, op0));
2897 op0 = tmp;
2898 }
8a18b90c 2899
215b30b3 2900 /* Mask out any bits in operand[3] that are not needed. */
2901 emit_insn (gen_andsi3 (op1, operands[3], op0));
8a18b90c 2902
0438d37f 2903 if (CONST_INT_P (op0)
215b30b3 2904 && (const_ok_for_arm (mask << start_bit)
2905 || const_ok_for_arm (~(mask << start_bit))))
2906 {
c5b3a71b 2907 op0 = gen_int_mode (~(mask << start_bit), SImode);
215b30b3 2908 emit_insn (gen_andsi3 (op2, operands[0], op0));
2909 }
2910 else
2911 {
0438d37f 2912 if (CONST_INT_P (op0))
215b30b3 2913 {
2914 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 2915
215b30b3 2916 emit_insn (gen_movsi (tmp, op0));
2917 op0 = tmp;
2918 }
2919
2920 if (start_bit != 0)
2921 emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
a42059fd 2922
215b30b3 2923 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
2924 }
8a18b90c 2925
215b30b3 2926 if (start_bit != 0)
2927 emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
8a18b90c 2928
215b30b3 2929 emit_insn (gen_iorsi3 (subtarget, op1, op2));
2930 }
f082f1c4 2931
215b30b3 2932 if (subtarget != target)
2933 {
2934 /* If TARGET is still a SUBREG, then it must be wider than a word,
2935 so we must be careful only to set the subword we were asked to. */
2936 if (GET_CODE (target) == SUBREG)
2937 emit_move_insn (target, subtarget);
2938 else
2939 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
2940 }
8a18b90c 2941
215b30b3 2942 DONE;
2943 }"
2944)
8a18b90c 2945
8b054d5a 2946(define_insn "insv_zero"
2947 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
809003b3 2948 (match_operand:SI 1 "const_int_M_operand" "M")
2949 (match_operand:SI 2 "const_int_M_operand" "M"))
8b054d5a 2950 (const_int 0))]
2951 "arm_arch_thumb2"
2952 "bfc%?\t%0, %2, %1"
2953 [(set_attr "length" "4")
d952d547 2954 (set_attr "predicable" "yes")
d82e788e 2955 (set_attr "type" "bfm")]
8b054d5a 2956)
2957
2958(define_insn "insv_t2"
2959 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
809003b3 2960 (match_operand:SI 1 "const_int_M_operand" "M")
2961 (match_operand:SI 2 "const_int_M_operand" "M"))
8b054d5a 2962 (match_operand:SI 3 "s_register_operand" "r"))]
2963 "arm_arch_thumb2"
2964 "bfi%?\t%0, %3, %2, %1"
2965 [(set_attr "length" "4")
d952d547 2966 (set_attr "predicable" "yes")
d82e788e 2967 (set_attr "type" "bfm")]
8b054d5a 2968)
2969
215b30b3 2970; constants for op 2 will never be given to these patterns.
a0f94409 2971(define_insn_and_split "*anddi_notdi_di"
9c08d1fa 2972 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 2973 (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "0,r"))
2974 (match_operand:DI 2 "s_register_operand" "r,0")))]
25f905c2 2975 "TARGET_32BIT"
f6ebffac 2976 "#"
e2669ea7 2977 "TARGET_32BIT && reload_completed
2978 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))
2979 && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
a0f94409 2980 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2981 (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2982 "
2983 {
2984 operands[3] = gen_highpart (SImode, operands[0]);
2985 operands[0] = gen_lowpart (SImode, operands[0]);
2986 operands[4] = gen_highpart (SImode, operands[1]);
2987 operands[1] = gen_lowpart (SImode, operands[1]);
2988 operands[5] = gen_highpart (SImode, operands[2]);
2989 operands[2] = gen_lowpart (SImode, operands[2]);
2990 }"
0d66636f 2991 [(set_attr "length" "8")
1b7da4ac 2992 (set_attr "predicable" "yes")
2993 (set_attr "type" "multiple")]
0d66636f 2994)
d952d547 2995
a0f94409 2996(define_insn_and_split "*anddi_notzesidi_di"
9c08d1fa 2997 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2998 (and:DI (not:DI (zero_extend:DI
2999 (match_operand:SI 2 "s_register_operand" "r,r")))
e2348bcb 3000 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 3001 "TARGET_32BIT"
e2348bcb 3002 "@
97499065 3003 bic%?\\t%Q0, %Q1, %2
f6ebffac 3004 #"
a0f94409 3005 ; (not (zero_extend ...)) allows us to just copy the high word from
3006 ; operand1 to operand0.
25f905c2 3007 "TARGET_32BIT
a0f94409 3008 && reload_completed
3009 && operands[0] != operands[1]"
5a097f7d 3010 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
a0f94409 3011 (set (match_dup 3) (match_dup 4))]
3012 "
3013 {
3014 operands[3] = gen_highpart (SImode, operands[0]);
3015 operands[0] = gen_lowpart (SImode, operands[0]);
3016 operands[4] = gen_highpart (SImode, operands[1]);
3017 operands[1] = gen_lowpart (SImode, operands[1]);
3018 }"
0d66636f 3019 [(set_attr "length" "4,8")
d952d547 3020 (set_attr "predicable" "yes")
1b7da4ac 3021 (set_attr "type" "multiple")]
0d66636f 3022)
d952d547 3023
d8cd5fa0 3024(define_insn_and_split "*anddi_notdi_zesidi"
3025 [(set (match_operand:DI 0 "s_register_operand" "=r")
3026 (and:DI (not:DI (match_operand:DI 2 "s_register_operand" "r"))
3027 (zero_extend:DI
3028 (match_operand:SI 1 "s_register_operand" "r"))))]
3029 "TARGET_32BIT"
3030 "#"
3031 "TARGET_32BIT && reload_completed"
3032 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
3033 (set (match_dup 3) (const_int 0))]
3034 "
3035 {
3036 operands[3] = gen_highpart (SImode, operands[0]);
3037 operands[0] = gen_lowpart (SImode, operands[0]);
3038 operands[2] = gen_lowpart (SImode, operands[2]);
3039 }"
3040 [(set_attr "length" "8")
3041 (set_attr "predicable" "yes")
d8cd5fa0 3042 (set_attr "type" "multiple")]
3043)
3044
a0f94409 3045(define_insn_and_split "*anddi_notsesidi_di"
9c08d1fa 3046 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3047 (and:DI (not:DI (sign_extend:DI
3048 (match_operand:SI 2 "s_register_operand" "r,r")))
5a097f7d 3049 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 3050 "TARGET_32BIT"
f6ebffac 3051 "#"
25f905c2 3052 "TARGET_32BIT && reload_completed"
5a097f7d 3053 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
a0f94409 3054 (set (match_dup 3) (and:SI (not:SI
3055 (ashiftrt:SI (match_dup 2) (const_int 31)))
3056 (match_dup 4)))]
3057 "
3058 {
3059 operands[3] = gen_highpart (SImode, operands[0]);
3060 operands[0] = gen_lowpart (SImode, operands[0]);
3061 operands[4] = gen_highpart (SImode, operands[1]);
3062 operands[1] = gen_lowpart (SImode, operands[1]);
3063 }"
0d66636f 3064 [(set_attr "length" "8")
d952d547 3065 (set_attr "predicable" "yes")
1b7da4ac 3066 (set_attr "type" "multiple")]
0d66636f 3067)
d952d547 3068
8a18b90c 3069(define_insn "andsi_notsi_si"
9c08d1fa 3070 [(set (match_operand:SI 0 "s_register_operand" "=r")
3071 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
3072 (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 3073 "TARGET_32BIT"
0d66636f 3074 "bic%?\\t%0, %1, %2"
d952d547 3075 [(set_attr "predicable" "yes")
1b7da4ac 3076 (set_attr "type" "logic_reg")]
0d66636f 3077)
b11cae9e 3078
8a18b90c 3079(define_insn "andsi_not_shiftsi_si"
a2cd141b 3080 [(set (match_operand:SI 0 "s_register_operand" "=r")
3081 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
3082 [(match_operand:SI 2 "s_register_operand" "r")
3083 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
3084 (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 3085 "TARGET_ARM"
6c4c2133 3086 "bic%?\\t%0, %1, %2%S4"
344495ea 3087 [(set_attr "predicable" "yes")
331beb1a 3088 (set_attr "shift" "2")
a2cd141b 3089 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
d82e788e 3090 (const_string "logic_shift_imm")
3091 (const_string "logic_shift_reg")))]
6c4c2133 3092)
8a18b90c 3093
9ed784d8 3094;; Shifted bics pattern used to set up CC status register and not reusing
3095;; bics output. Pattern restricts Thumb2 shift operand as bics for Thumb2
3096;; does not support shift by register.
3097(define_insn "andsi_not_shiftsi_si_scc_no_reuse"
3098 [(set (reg:CC_NOOV CC_REGNUM)
3099 (compare:CC_NOOV
3100 (and:SI (not:SI (match_operator:SI 0 "shift_operator"
3101 [(match_operand:SI 1 "s_register_operand" "r")
3102 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
3103 (match_operand:SI 3 "s_register_operand" "r"))
3104 (const_int 0)))
3105 (clobber (match_scratch:SI 4 "=r"))]
3106 "TARGET_ARM || (TARGET_THUMB2 && CONST_INT_P (operands[2]))"
3ef90e77 3107 "bics%?\\t%4, %3, %1%S0"
9ed784d8 3108 [(set_attr "predicable" "yes")
9ed784d8 3109 (set_attr "conds" "set")
3110 (set_attr "shift" "1")
3111 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3112 (const_string "logic_shift_imm")
3113 (const_string "logic_shift_reg")))]
3114)
3115
3116;; Same as andsi_not_shiftsi_si_scc_no_reuse, but the bics result is also
3117;; getting reused later.
3118(define_insn "andsi_not_shiftsi_si_scc"
3119 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
3120 (compare:CC_NOOV
3121 (and:SI (not:SI (match_operator:SI 0 "shift_operator"
3122 [(match_operand:SI 1 "s_register_operand" "r")
3123 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
3124 (match_operand:SI 3 "s_register_operand" "r"))
3125 (const_int 0)))
3126 (set (match_operand:SI 4 "s_register_operand" "=r")
3127 (and:SI (not:SI (match_op_dup 0
3128 [(match_dup 1)
3129 (match_dup 2)]))
3130 (match_dup 3)))])]
3131 "TARGET_ARM || (TARGET_THUMB2 && CONST_INT_P (operands[2]))"
3ef90e77 3132 "bics%?\\t%4, %3, %1%S0"
9ed784d8 3133 [(set_attr "predicable" "yes")
9ed784d8 3134 (set_attr "conds" "set")
3135 (set_attr "shift" "1")
3136 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3137 (const_string "logic_shift_imm")
3138 (const_string "logic_shift_reg")))]
3139)
3140
f7fbdd4a 3141(define_insn "*andsi_notsi_si_compare0"
bd5b4116 3142 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 3143 (compare:CC_NOOV
3144 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
3145 (match_operand:SI 1 "s_register_operand" "r"))
3146 (const_int 0)))
9c08d1fa 3147 (set (match_operand:SI 0 "s_register_operand" "=r")
3148 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
25f905c2 3149 "TARGET_32BIT"
3ef90e77 3150 "bics\\t%0, %1, %2"
d82e788e 3151 [(set_attr "conds" "set")
3152 (set_attr "type" "logics_shift_reg")]
0d66636f 3153)
9c08d1fa 3154
f7fbdd4a 3155(define_insn "*andsi_notsi_si_compare0_scratch"
bd5b4116 3156 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 3157 (compare:CC_NOOV
3158 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
3159 (match_operand:SI 1 "s_register_operand" "r"))
3160 (const_int 0)))
9c08d1fa 3161 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 3162 "TARGET_32BIT"
3ef90e77 3163 "bics\\t%0, %1, %2"
d82e788e 3164 [(set_attr "conds" "set")
3165 (set_attr "type" "logics_shift_reg")]
0d66636f 3166)
9c08d1fa 3167
e2669ea7 3168(define_expand "iordi3"
3934ae0e 3169 [(set (match_operand:DI 0 "s_register_operand")
3170 (ior:DI (match_operand:DI 1 "s_register_operand")
3171 (match_operand:DI 2 "neon_logic_op2")))]
e2669ea7 3172 "TARGET_32BIT"
0d84c6e5 3173 "
3174 if (!TARGET_NEON && !TARGET_IWMMXT)
3175 {
3176 rtx low = simplify_gen_binary (IOR, SImode,
3177 gen_lowpart (SImode, operands[1]),
3178 gen_lowpart (SImode, operands[2]));
3179 rtx high = simplify_gen_binary (IOR, SImode,
3180 gen_highpart (SImode, operands[1]),
3181 gen_highpart_mode (SImode, DImode,
3182 operands[2]));
3183
3184 emit_insn (gen_rtx_SET (gen_lowpart (SImode, operands[0]), low));
3185 emit_insn (gen_rtx_SET (gen_highpart (SImode, operands[0]), high));
3186
3187 DONE;
3188 }
3189 /* Otherwise expand pattern as above. */
3190 "
e2669ea7 3191)
3192
74d6113f 3193(define_insn_and_split "*iordi3_insn"
3194 [(set (match_operand:DI 0 "s_register_operand" "=w,w ,&r,&r,&r,&r,?w,?w")
3195 (ior:DI (match_operand:DI 1 "s_register_operand" "%w,0 ,0 ,r ,0 ,r ,w ,0")
e0fe6977 3196 (match_operand:DI 2 "arm_iordi_operand_neon" "w ,Dl,r ,r ,Df,Df,w ,Dl")))]
74d6113f 3197 "TARGET_32BIT && !TARGET_IWMMXT"
3198 {
3199 switch (which_alternative)
3200 {
3201 case 0: /* fall through */
3202 case 6: return "vorr\t%P0, %P1, %P2";
3203 case 1: /* fall through */
3204 case 7: return neon_output_logic_immediate ("vorr", &operands[2],
3205 DImode, 0, VALID_NEON_QREG_MODE (DImode));
3206 case 2:
3207 case 3:
3208 case 4:
3209 case 5:
3210 return "#";
3211 default: gcc_unreachable ();
3212 }
3213 }
3214 "TARGET_32BIT && !TARGET_IWMMXT && reload_completed
3215 && !(IS_VFP_REGNUM (REGNO (operands[0])))"
3216 [(set (match_dup 3) (match_dup 4))
3217 (set (match_dup 5) (match_dup 6))]
3218 "
3219 {
3220 operands[3] = gen_lowpart (SImode, operands[0]);
3221 operands[5] = gen_highpart (SImode, operands[0]);
3222
3223 operands[4] = simplify_gen_binary (IOR, SImode,
3224 gen_lowpart (SImode, operands[1]),
3225 gen_lowpart (SImode, operands[2]));
3226 operands[6] = simplify_gen_binary (IOR, SImode,
3227 gen_highpart (SImode, operands[1]),
3228 gen_highpart_mode (SImode, DImode, operands[2]));
3229
3230 }"
32093010 3231 [(set_attr "type" "neon_logic,neon_logic,multiple,multiple,multiple,\
3232 multiple,neon_logic,neon_logic")
e0fe6977 3233 (set_attr "length" "*,*,8,8,8,8,*,*")
74d6113f 3234 (set_attr "arch" "neon_for_64bits,neon_for_64bits,*,*,*,*,avoid_neon_for_64bits,avoid_neon_for_64bits")]
cffb2a26 3235)
9c08d1fa 3236
f7fbdd4a 3237(define_insn "*iordi_zesidi_di"
9c08d1fa 3238 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3239 (ior:DI (zero_extend:DI
3240 (match_operand:SI 2 "s_register_operand" "r,r"))
e2348bcb 3241 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 3242 "TARGET_32BIT"
e2348bcb 3243 "@
97499065 3244 orr%?\\t%Q0, %Q1, %2
f6ebffac 3245 #"
0d66636f 3246 [(set_attr "length" "4,8")
d952d547 3247 (set_attr "predicable" "yes")
1b7da4ac 3248 (set_attr "type" "logic_reg,multiple")]
cffb2a26 3249)
9c08d1fa 3250
f7fbdd4a 3251(define_insn "*iordi_sesidi_di"
9c08d1fa 3252 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3253 (ior:DI (sign_extend:DI
3254 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 3255 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 3256 "TARGET_32BIT"
f6ebffac 3257 "#"
0d66636f 3258 [(set_attr "length" "8")
1b7da4ac 3259 (set_attr "predicable" "yes")
3260 (set_attr "type" "multiple")]
cffb2a26 3261)
9c08d1fa 3262
87b22bf7 3263(define_expand "iorsi3"
3934ae0e 3264 [(set (match_operand:SI 0 "s_register_operand")
3265 (ior:SI (match_operand:SI 1 "s_register_operand")
3266 (match_operand:SI 2 "reg_or_int_operand")))]
cffb2a26 3267 "TARGET_EITHER"
87b22bf7 3268 "
0438d37f 3269 if (CONST_INT_P (operands[2]))
87b22bf7 3270 {
25f905c2 3271 if (TARGET_32BIT)
cffb2a26 3272 {
17202aa5 3273 if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[2]), IOR))
3274 operands[2] = force_reg (SImode, operands[2]);
3275 else
3276 {
3277 arm_split_constant (IOR, SImode, NULL_RTX,
3278 INTVAL (operands[2]), operands[0],
3279 operands[1],
3280 optimize && can_create_pseudo_p ());
3281 DONE;
3282 }
cffb2a26 3283 }
25f905c2 3284 else /* TARGET_THUMB1 */
923ffadb 3285 {
3286 rtx tmp = force_reg (SImode, operands[2]);
3287 if (rtx_equal_p (operands[0], operands[1]))
3288 operands[2] = tmp;
3289 else
3290 {
3291 operands[2] = operands[1];
3292 operands[1] = tmp;
3293 }
3294 }
87b22bf7 3295 }
cffb2a26 3296 "
3297)
87b22bf7 3298
d5d4dc8d 3299(define_insn_and_split "*iorsi3_insn"
29e234a3 3300 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r,r,r")
3301 (ior:SI (match_operand:SI 1 "s_register_operand" "%r,0,r,r,r")
3302 (match_operand:SI 2 "reg_or_int_operand" "I,l,K,r,?n")))]
d5d4dc8d 3303 "TARGET_32BIT"
87b22bf7 3304 "@
29e234a3 3305 orr%?\\t%0, %1, %2
87b22bf7 3306 orr%?\\t%0, %1, %2
d5d4dc8d 3307 orn%?\\t%0, %1, #%B2
65f68e55 3308 orr%?\\t%0, %1, %2
87b22bf7 3309 #"
d5d4dc8d 3310 "TARGET_32BIT
0438d37f 3311 && CONST_INT_P (operands[2])
d5d4dc8d 3312 && !(const_ok_for_arm (INTVAL (operands[2]))
3313 || (TARGET_THUMB2 && const_ok_for_arm (~INTVAL (operands[2]))))"
a0f94409 3314 [(clobber (const_int 0))]
d5d4dc8d 3315{
29e234a3 3316 arm_split_constant (IOR, SImode, curr_insn,
96f57e36 3317 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 3318 DONE;
d5d4dc8d 3319}
29e234a3 3320 [(set_attr "length" "4,4,4,4,16")
3321 (set_attr "arch" "32,t2,t2,32,32")
65f68e55 3322 (set_attr "predicable" "yes")
29e234a3 3323 (set_attr "predicable_short_it" "no,yes,no,no,no")
d82e788e 3324 (set_attr "type" "logic_imm,logic_reg,logic_imm,logic_reg,logic_reg")]
65f68e55 3325)
cffb2a26 3326
a0f94409 3327(define_peephole2
3328 [(match_scratch:SI 3 "r")
372575c7 3329 (set (match_operand:SI 0 "arm_general_register_operand" "")
3330 (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
87b22bf7 3331 (match_operand:SI 2 "const_int_operand" "")))]
90560cad 3332 "TARGET_ARM
a0f94409 3333 && !const_ok_for_arm (INTVAL (operands[2]))
3334 && const_ok_for_arm (~INTVAL (operands[2]))"
3335 [(set (match_dup 3) (match_dup 2))
3336 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
3337 ""
215b30b3 3338)
a0f94409 3339
f7fbdd4a 3340(define_insn "*iorsi3_compare0"
bd5b4116 3341 [(set (reg:CC_NOOV CC_REGNUM)
a02b858e 3342 (compare:CC_NOOV
3343 (ior:SI (match_operand:SI 1 "s_register_operand" "%r,0,r")
3344 (match_operand:SI 2 "arm_rhs_operand" "I,l,r"))
3345 (const_int 0)))
3346 (set (match_operand:SI 0 "s_register_operand" "=r,l,r")
9c08d1fa 3347 (ior:SI (match_dup 1) (match_dup 2)))]
25f905c2 3348 "TARGET_32BIT"
3ef90e77 3349 "orrs%?\\t%0, %1, %2"
65f68e55 3350 [(set_attr "conds" "set")
a02b858e 3351 (set_attr "arch" "*,t2,*")
3352 (set_attr "length" "4,2,4")
3353 (set_attr "type" "logics_imm,logics_reg,logics_reg")]
cffb2a26 3354)
9c08d1fa 3355
f7fbdd4a 3356(define_insn "*iorsi3_compare0_scratch"
bd5b4116 3357 [(set (reg:CC_NOOV CC_REGNUM)
a02b858e 3358 (compare:CC_NOOV
3359 (ior:SI (match_operand:SI 1 "s_register_operand" "%r,0,r")
3360 (match_operand:SI 2 "arm_rhs_operand" "I,l,r"))
3361 (const_int 0)))
3362 (clobber (match_scratch:SI 0 "=r,l,r"))]
25f905c2 3363 "TARGET_32BIT"
3ef90e77 3364 "orrs%?\\t%0, %1, %2"
65f68e55 3365 [(set_attr "conds" "set")
a02b858e 3366 (set_attr "arch" "*,t2,*")
3367 (set_attr "length" "4,2,4")
3368 (set_attr "type" "logics_imm,logics_reg,logics_reg")]
0d66636f 3369)
9c08d1fa 3370
e2669ea7 3371(define_expand "xordi3"
3934ae0e 3372 [(set (match_operand:DI 0 "s_register_operand")
3373 (xor:DI (match_operand:DI 1 "s_register_operand")
3374 (match_operand:DI 2 "arm_xordi_operand")))]
e2669ea7 3375 "TARGET_32BIT"
8df5e205 3376 {
3377 /* The iWMMXt pattern for xordi3 accepts only register operands but we want
3378 to reuse this expander for all TARGET_32BIT targets so just force the
3379 constants into a register. Unlike for the anddi3 and iordi3 there are
3380 no NEON instructions that take an immediate. */
3381 if (TARGET_IWMMXT && !REG_P (operands[2]))
3382 operands[2] = force_reg (DImode, operands[2]);
0d84c6e5 3383 if (!TARGET_NEON && !TARGET_IWMMXT)
3384 {
3385 rtx low = simplify_gen_binary (XOR, SImode,
3386 gen_lowpart (SImode, operands[1]),
3387 gen_lowpart (SImode, operands[2]));
3388 rtx high = simplify_gen_binary (XOR, SImode,
3389 gen_highpart (SImode, operands[1]),
3390 gen_highpart_mode (SImode, DImode,
3391 operands[2]));
3392
3393 emit_insn (gen_rtx_SET (gen_lowpart (SImode, operands[0]), low));
3394 emit_insn (gen_rtx_SET (gen_highpart (SImode, operands[0]), high));
3395
3396 DONE;
3397 }
3398 /* Otherwise expand pattern as above. */
8df5e205 3399 }
e2669ea7 3400)
3401
8ee7dc6f 3402(define_insn_and_split "*xordi3_insn"
3403 [(set (match_operand:DI 0 "s_register_operand" "=w,&r,&r,&r,&r,?w")
205c3b0a 3404 (xor:DI (match_operand:DI 1 "s_register_operand" "%w ,0,r ,0 ,r ,w")
8ee7dc6f 3405 (match_operand:DI 2 "arm_xordi_operand" "w ,r ,r ,Dg,Dg,w")))]
3406 "TARGET_32BIT && !TARGET_IWMMXT"
3407{
3408 switch (which_alternative)
3409 {
3410 case 1:
3411 case 2:
3412 case 3:
3413 case 4: /* fall through */
3414 return "#";
3415 case 0: /* fall through */
3416 case 5: return "veor\t%P0, %P1, %P2";
3417 default: gcc_unreachable ();
3418 }
3419}
3420 "TARGET_32BIT && !TARGET_IWMMXT && reload_completed
3421 && !(IS_VFP_REGNUM (REGNO (operands[0])))"
3422 [(set (match_dup 3) (match_dup 4))
3423 (set (match_dup 5) (match_dup 6))]
3424 "
3425 {
3426 operands[3] = gen_lowpart (SImode, operands[0]);
3427 operands[5] = gen_highpart (SImode, operands[0]);
3428
3429 operands[4] = simplify_gen_binary (XOR, SImode,
3430 gen_lowpart (SImode, operands[1]),
3431 gen_lowpart (SImode, operands[2]));
3432 operands[6] = simplify_gen_binary (XOR, SImode,
3433 gen_highpart (SImode, operands[1]),
3434 gen_highpart_mode (SImode, DImode, operands[2]));
3435
3436 }"
3437 [(set_attr "length" "*,8,8,8,8,*")
32093010 3438 (set_attr "type" "neon_logic,multiple,multiple,multiple,multiple,neon_logic")
8ee7dc6f 3439 (set_attr "arch" "neon_for_64bits,*,*,*,*,avoid_neon_for_64bits")]
cffb2a26 3440)
9c08d1fa 3441
f7fbdd4a 3442(define_insn "*xordi_zesidi_di"
9c08d1fa 3443 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3444 (xor:DI (zero_extend:DI
3445 (match_operand:SI 2 "s_register_operand" "r,r"))
e2348bcb 3446 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 3447 "TARGET_32BIT"
e2348bcb 3448 "@
97499065 3449 eor%?\\t%Q0, %Q1, %2
f6ebffac 3450 #"
0d66636f 3451 [(set_attr "length" "4,8")
d952d547 3452 (set_attr "predicable" "yes")
1b7da4ac 3453 (set_attr "type" "logic_reg")]
cffb2a26 3454)
9c08d1fa 3455
f7fbdd4a 3456(define_insn "*xordi_sesidi_di"
9c08d1fa 3457 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3458 (xor:DI (sign_extend:DI
3459 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 3460 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 3461 "TARGET_32BIT"
f6ebffac 3462 "#"
0d66636f 3463 [(set_attr "length" "8")
1b7da4ac 3464 (set_attr "predicable" "yes")
3465 (set_attr "type" "multiple")]
cffb2a26 3466)
9c08d1fa 3467
cffb2a26 3468(define_expand "xorsi3"
3934ae0e 3469 [(set (match_operand:SI 0 "s_register_operand")
3470 (xor:SI (match_operand:SI 1 "s_register_operand")
3471 (match_operand:SI 2 "reg_or_int_operand")))]
cffb2a26 3472 "TARGET_EITHER"
0438d37f 3473 "if (CONST_INT_P (operands[2]))
923ffadb 3474 {
3475 if (TARGET_32BIT)
3476 {
17202aa5 3477 if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[2]), XOR))
3478 operands[2] = force_reg (SImode, operands[2]);
3479 else
3480 {
3481 arm_split_constant (XOR, SImode, NULL_RTX,
3482 INTVAL (operands[2]), operands[0],
3483 operands[1],
3484 optimize && can_create_pseudo_p ());
3485 DONE;
3486 }
923ffadb 3487 }
3488 else /* TARGET_THUMB1 */
3489 {
3490 rtx tmp = force_reg (SImode, operands[2]);
3491 if (rtx_equal_p (operands[0], operands[1]))
3492 operands[2] = tmp;
3493 else
3494 {
3495 operands[2] = operands[1];
3496 operands[1] = tmp;
3497 }
3498 }
3499 }"
cffb2a26 3500)
3501
5dcb35d9 3502(define_insn_and_split "*arm_xorsi3"
29e234a3 3503 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r,r")
3504 (xor:SI (match_operand:SI 1 "s_register_operand" "%r,0,r,r")
3505 (match_operand:SI 2 "reg_or_int_operand" "I,l,r,?n")))]
25f905c2 3506 "TARGET_32BIT"
5dcb35d9 3507 "@
29e234a3 3508 eor%?\\t%0, %1, %2
65f68e55 3509 eor%?\\t%0, %1, %2
5dcb35d9 3510 eor%?\\t%0, %1, %2
3511 #"
3512 "TARGET_32BIT
0438d37f 3513 && CONST_INT_P (operands[2])
5dcb35d9 3514 && !const_ok_for_arm (INTVAL (operands[2]))"
3515 [(clobber (const_int 0))]
3516{
3517 arm_split_constant (XOR, SImode, curr_insn,
3518 INTVAL (operands[2]), operands[0], operands[1], 0);
3519 DONE;
3520}
29e234a3 3521 [(set_attr "length" "4,4,4,16")
65f68e55 3522 (set_attr "predicable" "yes")
29e234a3 3523 (set_attr "predicable_short_it" "no,yes,no,no")
1b7da4ac 3524 (set_attr "type" "logic_imm,logic_reg,logic_reg,multiple")]
cffb2a26 3525)
3526
f7fbdd4a 3527(define_insn "*xorsi3_compare0"
bd5b4116 3528 [(set (reg:CC_NOOV CC_REGNUM)
65f68e55 3529 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r,r")
3530 (match_operand:SI 2 "arm_rhs_operand" "I,r"))
9c08d1fa 3531 (const_int 0)))
65f68e55 3532 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 3533 (xor:SI (match_dup 1) (match_dup 2)))]
25f905c2 3534 "TARGET_32BIT"
3ef90e77 3535 "eors%?\\t%0, %1, %2"
65f68e55 3536 [(set_attr "conds" "set")
d82e788e 3537 (set_attr "type" "logics_imm,logics_reg")]
0d66636f 3538)
9c08d1fa 3539
f7fbdd4a 3540(define_insn "*xorsi3_compare0_scratch"
bd5b4116 3541 [(set (reg:CC_NOOV CC_REGNUM)
65f68e55 3542 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r,r")
3543 (match_operand:SI 1 "arm_rhs_operand" "I,r"))
9c08d1fa 3544 (const_int 0)))]
25f905c2 3545 "TARGET_32BIT"
40dbec34 3546 "teq%?\\t%0, %1"
65f68e55 3547 [(set_attr "conds" "set")
d82e788e 3548 (set_attr "type" "logics_imm,logics_reg")]
cffb2a26 3549)
9c08d1fa 3550
215b30b3 3551; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
3552; (NOT D) we can sometimes merge the final NOT into one of the following
3553; insns.
9c08d1fa 3554
3555(define_split
a058e94a 3556 [(set (match_operand:SI 0 "s_register_operand" "")
3557 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
3558 (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
3559 (match_operand:SI 3 "arm_rhs_operand" "")))
3560 (clobber (match_operand:SI 4 "s_register_operand" ""))]
25f905c2 3561 "TARGET_32BIT"
9c08d1fa 3562 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
3563 (not:SI (match_dup 3))))
3564 (set (match_dup 0) (not:SI (match_dup 4)))]
3565 ""
3566)
3567
ba6a3b2f 3568(define_insn_and_split "*andsi_iorsi3_notsi"
9c08d1fa 3569 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
e5fea38e 3570 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "%0,r,r")
9c08d1fa 3571 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
3572 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
25f905c2 3573 "TARGET_32BIT"
ba6a3b2f 3574 "#" ; "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
3575 "&& reload_completed"
3576 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
054fd237 3577 (set (match_dup 0) (and:SI (match_dup 4) (match_dup 5)))]
3578 {
3579 /* If operands[3] is a constant make sure to fold the NOT into it
3580 to avoid creating a NOT of a CONST_INT. */
3581 rtx not_rtx = simplify_gen_unary (NOT, SImode, operands[3], SImode);
3582 if (CONST_INT_P (not_rtx))
3583 {
3584 operands[4] = operands[0];
3585 operands[5] = not_rtx;
3586 }
3587 else
3588 {
3589 operands[5] = operands[0];
3590 operands[4] = not_rtx;
3591 }
3592 }
0d66636f 3593 [(set_attr "length" "8")
25f905c2 3594 (set_attr "ce_count" "2")
d952d547 3595 (set_attr "predicable" "yes")
1b7da4ac 3596 (set_attr "type" "multiple")]
cffb2a26 3597)
9c08d1fa 3598
25f905c2 3599; ??? Are these four splitters still beneficial when the Thumb-2 bitfield
3600; insns are available?
d7863cfe 3601(define_split
3602 [(set (match_operand:SI 0 "s_register_operand" "")
3603 (match_operator:SI 1 "logical_binary_operator"
3604 [(zero_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 (match_operator:SI 9 "logical_binary_operator"
3608 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3609 (match_operand:SI 6 "const_int_operand" ""))
3610 (match_operand:SI 7 "s_register_operand" "")])]))
3611 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3612 "TARGET_32BIT
d7863cfe 3613 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3614 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3615 [(set (match_dup 8)
3616 (match_op_dup 1
3617 [(ashift:SI (match_dup 2) (match_dup 4))
3618 (match_dup 5)]))
3619 (set (match_dup 0)
3620 (match_op_dup 1
3621 [(lshiftrt:SI (match_dup 8) (match_dup 6))
3622 (match_dup 7)]))]
3623 "
3624 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3625")
3626
3627(define_split
3628 [(set (match_operand:SI 0 "s_register_operand" "")
3629 (match_operator:SI 1 "logical_binary_operator"
3630 [(match_operator:SI 9 "logical_binary_operator"
3631 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3632 (match_operand:SI 6 "const_int_operand" ""))
3633 (match_operand:SI 7 "s_register_operand" "")])
3634 (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
3635 (match_operand:SI 3 "const_int_operand" "")
3636 (match_operand:SI 4 "const_int_operand" ""))]))
3637 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3638 "TARGET_32BIT
d7863cfe 3639 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3640 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3641 [(set (match_dup 8)
3642 (match_op_dup 1
3643 [(ashift:SI (match_dup 2) (match_dup 4))
3644 (match_dup 5)]))
3645 (set (match_dup 0)
3646 (match_op_dup 1
3647 [(lshiftrt:SI (match_dup 8) (match_dup 6))
3648 (match_dup 7)]))]
3649 "
3650 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3651")
3652
3653(define_split
3654 [(set (match_operand:SI 0 "s_register_operand" "")
3655 (match_operator:SI 1 "logical_binary_operator"
3656 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
3657 (match_operand:SI 3 "const_int_operand" "")
3658 (match_operand:SI 4 "const_int_operand" ""))
3659 (match_operator:SI 9 "logical_binary_operator"
3660 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3661 (match_operand:SI 6 "const_int_operand" ""))
3662 (match_operand:SI 7 "s_register_operand" "")])]))
3663 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3664 "TARGET_32BIT
d7863cfe 3665 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3666 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3667 [(set (match_dup 8)
3668 (match_op_dup 1
3669 [(ashift:SI (match_dup 2) (match_dup 4))
3670 (match_dup 5)]))
3671 (set (match_dup 0)
3672 (match_op_dup 1
3673 [(ashiftrt:SI (match_dup 8) (match_dup 6))
3674 (match_dup 7)]))]
3675 "
3676 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3677")
3678
3679(define_split
3680 [(set (match_operand:SI 0 "s_register_operand" "")
3681 (match_operator:SI 1 "logical_binary_operator"
3682 [(match_operator:SI 9 "logical_binary_operator"
3683 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3684 (match_operand:SI 6 "const_int_operand" ""))
3685 (match_operand:SI 7 "s_register_operand" "")])
3686 (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
3687 (match_operand:SI 3 "const_int_operand" "")
3688 (match_operand:SI 4 "const_int_operand" ""))]))
3689 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3690 "TARGET_32BIT
d7863cfe 3691 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3692 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3693 [(set (match_dup 8)
3694 (match_op_dup 1
3695 [(ashift:SI (match_dup 2) (match_dup 4))
3696 (match_dup 5)]))
3697 (set (match_dup 0)
3698 (match_op_dup 1
3699 [(ashiftrt:SI (match_dup 8) (match_dup 6))
3700 (match_dup 7)]))]
3701 "
3702 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3703")
9c08d1fa 3704\f
3705
3706;; Minimum and maximum insns
3707
8b9dc177 3708(define_expand "smaxsi3"
3709 [(parallel [
3934ae0e 3710 (set (match_operand:SI 0 "s_register_operand")
3711 (smax:SI (match_operand:SI 1 "s_register_operand")
3712 (match_operand:SI 2 "arm_rhs_operand")))
8b9dc177 3713 (clobber (reg:CC CC_REGNUM))])]
25f905c2 3714 "TARGET_32BIT"
8b9dc177 3715 "
8774928b 3716 if (operands[2] == const0_rtx || operands[2] == constm1_rtx)
8b9dc177 3717 {
3718 /* No need for a clobber of the condition code register here. */
d1f9b275 3719 emit_insn (gen_rtx_SET (operands[0],
8b9dc177 3720 gen_rtx_SMAX (SImode, operands[1],
3721 operands[2])));
3722 DONE;
3723 }
3724")
3725
3726(define_insn "*smax_0"
3727 [(set (match_operand:SI 0 "s_register_operand" "=r")
3728 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3729 (const_int 0)))]
25f905c2 3730 "TARGET_32BIT"
8b9dc177 3731 "bic%?\\t%0, %1, %1, asr #31"
d952d547 3732 [(set_attr "predicable" "yes")
1b7da4ac 3733 (set_attr "type" "logic_shift_reg")]
8b9dc177 3734)
3735
8774928b 3736(define_insn "*smax_m1"
3737 [(set (match_operand:SI 0 "s_register_operand" "=r")
3738 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3739 (const_int -1)))]
25f905c2 3740 "TARGET_32BIT"
8774928b 3741 "orr%?\\t%0, %1, %1, asr #31"
d952d547 3742 [(set_attr "predicable" "yes")
1b7da4ac 3743 (set_attr "type" "logic_shift_reg")]
8774928b 3744)
3745
3dc953f2 3746(define_insn_and_split "*arm_smax_insn"
8b9dc177 3747 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3748 (smax:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3749 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
bd5b4116 3750 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3751 "TARGET_ARM"
3dc953f2 3752 "#"
3753 ; cmp\\t%1, %2\;movlt\\t%0, %2
3754 ; cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
3755 "TARGET_ARM"
3756 [(set (reg:CC CC_REGNUM)
3757 (compare:CC (match_dup 1) (match_dup 2)))
3758 (set (match_dup 0)
3759 (if_then_else:SI (ge:SI (reg:CC CC_REGNUM) (const_int 0))
3760 (match_dup 1)
3761 (match_dup 2)))]
3762 ""
cffb2a26 3763 [(set_attr "conds" "clob")
1b7da4ac 3764 (set_attr "length" "8,12")
3765 (set_attr "type" "multiple")]
cffb2a26 3766)
9c08d1fa 3767
8b9dc177 3768(define_expand "sminsi3"
3769 [(parallel [
3934ae0e 3770 (set (match_operand:SI 0 "s_register_operand")
3771 (smin:SI (match_operand:SI 1 "s_register_operand")
3772 (match_operand:SI 2 "arm_rhs_operand")))
8b9dc177 3773 (clobber (reg:CC CC_REGNUM))])]
25f905c2 3774 "TARGET_32BIT"
8b9dc177 3775 "
3776 if (operands[2] == const0_rtx)
3777 {
3778 /* No need for a clobber of the condition code register here. */
d1f9b275 3779 emit_insn (gen_rtx_SET (operands[0],
8b9dc177 3780 gen_rtx_SMIN (SImode, operands[1],
3781 operands[2])));
3782 DONE;
3783 }
3784")
3785
3786(define_insn "*smin_0"
3787 [(set (match_operand:SI 0 "s_register_operand" "=r")
3788 (smin:SI (match_operand:SI 1 "s_register_operand" "r")
3789 (const_int 0)))]
25f905c2 3790 "TARGET_32BIT"
8b9dc177 3791 "and%?\\t%0, %1, %1, asr #31"
d952d547 3792 [(set_attr "predicable" "yes")
1b7da4ac 3793 (set_attr "type" "logic_shift_reg")]
8b9dc177 3794)
3795
3dc953f2 3796(define_insn_and_split "*arm_smin_insn"
8b9dc177 3797 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3798 (smin:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3799 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
bd5b4116 3800 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3801 "TARGET_ARM"
3dc953f2 3802 "#"
3803 ; cmp\\t%1, %2\;movge\\t%0, %2
3804 ; cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
3805 "TARGET_ARM"
3806 [(set (reg:CC CC_REGNUM)
3807 (compare:CC (match_dup 1) (match_dup 2)))
3808 (set (match_dup 0)
3809 (if_then_else:SI (lt:SI (reg:CC CC_REGNUM) (const_int 0))
3810 (match_dup 1)
3811 (match_dup 2)))]
3812 ""
0d66636f 3813 [(set_attr "conds" "clob")
1b7da4ac 3814 (set_attr "length" "8,12")
3815 (set_attr "type" "multiple,multiple")]
0d66636f 3816)
9c08d1fa 3817
25f905c2 3818(define_expand "umaxsi3"
3819 [(parallel [
3934ae0e 3820 (set (match_operand:SI 0 "s_register_operand")
3821 (umax:SI (match_operand:SI 1 "s_register_operand")
3822 (match_operand:SI 2 "arm_rhs_operand")))
25f905c2 3823 (clobber (reg:CC CC_REGNUM))])]
3824 "TARGET_32BIT"
3825 ""
3826)
3827
3dc953f2 3828(define_insn_and_split "*arm_umaxsi3"
9c08d1fa 3829 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3830 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3831 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 3832 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3833 "TARGET_ARM"
3dc953f2 3834 "#"
3835 ; cmp\\t%1, %2\;movcc\\t%0, %2
3836 ; cmp\\t%1, %2\;movcs\\t%0, %1
3837 ; cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
3838 "TARGET_ARM"
3839 [(set (reg:CC CC_REGNUM)
3840 (compare:CC (match_dup 1) (match_dup 2)))
3841 (set (match_dup 0)
3842 (if_then_else:SI (geu:SI (reg:CC CC_REGNUM) (const_int 0))
3843 (match_dup 1)
3844 (match_dup 2)))]
3845 ""
0d66636f 3846 [(set_attr "conds" "clob")
1b7da4ac 3847 (set_attr "length" "8,8,12")
9f2c2a36 3848 (set_attr "type" "store_4")]
0d66636f 3849)
9c08d1fa 3850
25f905c2 3851(define_expand "uminsi3"
3852 [(parallel [
3934ae0e 3853 (set (match_operand:SI 0 "s_register_operand")
3854 (umin:SI (match_operand:SI 1 "s_register_operand")
3855 (match_operand:SI 2 "arm_rhs_operand")))
25f905c2 3856 (clobber (reg:CC CC_REGNUM))])]
3857 "TARGET_32BIT"
3858 ""
3859)
3860
3dc953f2 3861(define_insn_and_split "*arm_uminsi3"
9c08d1fa 3862 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3863 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3864 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 3865 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3866 "TARGET_ARM"
3dc953f2 3867 "#"
3868 ; cmp\\t%1, %2\;movcs\\t%0, %2
3869 ; cmp\\t%1, %2\;movcc\\t%0, %1
3870 ; cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
3871 "TARGET_ARM"
3872 [(set (reg:CC CC_REGNUM)
3873 (compare:CC (match_dup 1) (match_dup 2)))
3874 (set (match_dup 0)
3875 (if_then_else:SI (ltu:SI (reg:CC CC_REGNUM) (const_int 0))
3876 (match_dup 1)
3877 (match_dup 2)))]
3878 ""
0d66636f 3879 [(set_attr "conds" "clob")
1b7da4ac 3880 (set_attr "length" "8,8,12")
9f2c2a36 3881 (set_attr "type" "store_4")]
0d66636f 3882)
9c08d1fa 3883
8a18b90c 3884(define_insn "*store_minmaxsi"
9c08d1fa 3885 [(set (match_operand:SI 0 "memory_operand" "=m")
3886 (match_operator:SI 3 "minmax_operator"
3887 [(match_operand:SI 1 "s_register_operand" "r")
3888 (match_operand:SI 2 "s_register_operand" "r")]))
bd5b4116 3889 (clobber (reg:CC CC_REGNUM))]
b207d152 3890 "TARGET_32BIT && optimize_function_for_size_p (cfun) && !arm_restrict_it"
9c08d1fa 3891 "*
dc55b8a9 3892 operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
3893 operands[1], operands[2]);
e2348bcb 3894 output_asm_insn (\"cmp\\t%1, %2\", operands);
25f905c2 3895 if (TARGET_THUMB2)
3896 output_asm_insn (\"ite\t%d3\", operands);
e2348bcb 3897 output_asm_insn (\"str%d3\\t%1, %0\", operands);
3898 output_asm_insn (\"str%D3\\t%2, %0\", operands);
3899 return \"\";
0d66636f 3900 "
3901 [(set_attr "conds" "clob")
25f905c2 3902 (set (attr "length")
3903 (if_then_else (eq_attr "is_thumb" "yes")
3904 (const_int 14)
3905 (const_int 12)))
9f2c2a36 3906 (set_attr "type" "store_4")]
0d66636f 3907)
9c08d1fa 3908
8a18b90c 3909; Reject the frame pointer in operand[1], since reloading this after
3910; it has been eliminated can cause carnage.
f7fbdd4a 3911(define_insn "*minmax_arithsi"
9c08d1fa 3912 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3913 (match_operator:SI 4 "shiftable_operator"
3914 [(match_operator:SI 5 "minmax_operator"
3915 [(match_operand:SI 2 "s_register_operand" "r,r")
3916 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
3917 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 3918 (clobber (reg:CC CC_REGNUM))]
7c36fe71 3919 "TARGET_32BIT && !arm_eliminable_register (operands[1]) && !arm_restrict_it"
9c08d1fa 3920 "*
0d66636f 3921 {
3922 enum rtx_code code = GET_CODE (operands[4]);
25f905c2 3923 bool need_else;
3924
3925 if (which_alternative != 0 || operands[3] != const0_rtx
ca0fc5a2 3926 || (code != PLUS && code != IOR && code != XOR))
25f905c2 3927 need_else = true;
3928 else
3929 need_else = false;
0d66636f 3930
dc55b8a9 3931 operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
3932 operands[2], operands[3]);
0d66636f 3933 output_asm_insn (\"cmp\\t%2, %3\", operands);
25f905c2 3934 if (TARGET_THUMB2)
3935 {
3936 if (need_else)
3937 output_asm_insn (\"ite\\t%d5\", operands);
3938 else
3939 output_asm_insn (\"it\\t%d5\", operands);
3940 }
0d66636f 3941 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
25f905c2 3942 if (need_else)
0d66636f 3943 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
3944 return \"\";
215b30b3 3945 }"
0d66636f 3946 [(set_attr "conds" "clob")
25f905c2 3947 (set (attr "length")
3948 (if_then_else (eq_attr "is_thumb" "yes")
3949 (const_int 14)
1b7da4ac 3950 (const_int 12)))
3951 (set_attr "type" "multiple")]
0d66636f 3952)
9c08d1fa 3953
4164bca1 3954; Reject the frame pointer in operand[1], since reloading this after
3955; it has been eliminated can cause carnage.
3956(define_insn_and_split "*minmax_arithsi_non_canon"
7c36fe71 3957 [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts")
4164bca1 3958 (minus:SI
7c36fe71 3959 (match_operand:SI 1 "s_register_operand" "0,?Ts")
4164bca1 3960 (match_operator:SI 4 "minmax_operator"
7c36fe71 3961 [(match_operand:SI 2 "s_register_operand" "Ts,Ts")
3962 (match_operand:SI 3 "arm_rhs_operand" "TsI,TsI")])))
4164bca1 3963 (clobber (reg:CC CC_REGNUM))]
7c36fe71 3964 "TARGET_32BIT && !arm_eliminable_register (operands[1])
3965 && !(arm_restrict_it && CONST_INT_P (operands[3]))"
4164bca1 3966 "#"
3967 "TARGET_32BIT && !arm_eliminable_register (operands[1]) && reload_completed"
3968 [(set (reg:CC CC_REGNUM)
3969 (compare:CC (match_dup 2) (match_dup 3)))
3970
3971 (cond_exec (match_op_dup 4 [(reg:CC CC_REGNUM) (const_int 0)])
3972 (set (match_dup 0)
3973 (minus:SI (match_dup 1)
3974 (match_dup 2))))
3975 (cond_exec (match_op_dup 5 [(reg:CC CC_REGNUM) (const_int 0)])
3976 (set (match_dup 0)
36ee0cde 3977 (match_dup 6)))]
4164bca1 3978 {
3754d046 3979 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
4164bca1 3980 operands[2], operands[3]);
3981 enum rtx_code rc = minmax_code (operands[4]);
3982 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode,
3983 operands[2], operands[3]);
3984
3985 if (mode == CCFPmode || mode == CCFPEmode)
3986 rc = reverse_condition_maybe_unordered (rc);
3987 else
3988 rc = reverse_condition (rc);
3989 operands[5] = gen_rtx_fmt_ee (rc, SImode, operands[2], operands[3]);
36ee0cde 3990 if (CONST_INT_P (operands[3]))
3991 operands[6] = plus_constant (SImode, operands[1], -INTVAL (operands[3]));
3992 else
3993 operands[6] = gen_rtx_MINUS (SImode, operands[1], operands[3]);
4164bca1 3994 }
3995 [(set_attr "conds" "clob")
3996 (set (attr "length")
3997 (if_then_else (eq_attr "is_thumb" "yes")
3998 (const_int 14)
1b7da4ac 3999 (const_int 12)))
4000 (set_attr "type" "multiple")]
4164bca1 4001)
4002
b49e3742 4003(define_code_iterator SAT [smin smax])
f0038cf3 4004(define_code_attr SATrev [(smin "smax") (smax "smin")])
b49e3742 4005(define_code_attr SATlo [(smin "1") (smax "2")])
4006(define_code_attr SAThi [(smin "2") (smax "1")])
4007
4008(define_insn "*satsi_<SAT:code>"
4009 [(set (match_operand:SI 0 "s_register_operand" "=r")
f0038cf3 4010 (SAT:SI (<SATrev>:SI (match_operand:SI 3 "s_register_operand" "r")
b49e3742 4011 (match_operand:SI 1 "const_int_operand" "i"))
4012 (match_operand:SI 2 "const_int_operand" "i")))]
f0038cf3 4013 "TARGET_32BIT && arm_arch6
b49e3742 4014 && arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>], NULL, NULL)"
4015{
4016 int mask;
4017 bool signed_sat;
4018 if (!arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>],
4019 &mask, &signed_sat))
4020 gcc_unreachable ();
4021
4022 operands[1] = GEN_INT (mask);
4023 if (signed_sat)
4024 return "ssat%?\t%0, %1, %3";
4025 else
4026 return "usat%?\t%0, %1, %3";
4027}
7c36fe71 4028 [(set_attr "predicable" "yes")
1b7da4ac 4029 (set_attr "type" "alus_imm")]
bebe9bbb 4030)
b49e3742 4031
4032(define_insn "*satsi_<SAT:code>_shift"
4033 [(set (match_operand:SI 0 "s_register_operand" "=r")
f0038cf3 4034 (SAT:SI (<SATrev>:SI (match_operator:SI 3 "sat_shift_operator"
b49e3742 4035 [(match_operand:SI 4 "s_register_operand" "r")
4036 (match_operand:SI 5 "const_int_operand" "i")])
4037 (match_operand:SI 1 "const_int_operand" "i"))
4038 (match_operand:SI 2 "const_int_operand" "i")))]
f0038cf3 4039 "TARGET_32BIT && arm_arch6
b49e3742 4040 && arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>], NULL, NULL)"
4041{
4042 int mask;
4043 bool signed_sat;
4044 if (!arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>],
4045 &mask, &signed_sat))
4046 gcc_unreachable ();
4047
4048 operands[1] = GEN_INT (mask);
4049 if (signed_sat)
4050 return "ssat%?\t%0, %1, %4%S3";
4051 else
4052 return "usat%?\t%0, %1, %4%S3";
4053}
4054 [(set_attr "predicable" "yes")
b49e3742 4055 (set_attr "shift" "3")
d82e788e 4056 (set_attr "type" "logic_shift_reg")])
b11cae9e 4057\f
4058;; Shift and rotation insns
4059
a2cd141b 4060(define_expand "ashldi3"
3934ae0e 4061 [(set (match_operand:DI 0 "s_register_operand")
4062 (ashift:DI (match_operand:DI 1 "s_register_operand")
4063 (match_operand:SI 2 "general_operand")))]
25f905c2 4064 "TARGET_32BIT"
a2cd141b 4065 "
aa06c51c 4066 if (TARGET_NEON)
4067 {
4068 /* Delay the decision whether to use NEON or core-regs until
4069 register allocation. */
4070 emit_insn (gen_ashldi3_neon (operands[0], operands[1], operands[2]));
4071 DONE;
4072 }
4073 else
4074 {
4075 /* Only the NEON case can handle in-memory shift counts. */
4076 if (!reg_or_int_operand (operands[2], SImode))
4077 operands[2] = force_reg (SImode, operands[2]);
4078 }
4079
b805622c 4080 if (!CONST_INT_P (operands[2]) && TARGET_REALLY_IWMMXT)
ffcc986d 4081 ; /* No special preparation statements; expand pattern as above. */
4082 else
a2cd141b 4083 {
ffcc986d 4084 rtx scratch1, scratch2;
4085
ffcc986d 4086 /* Ideally we should use iwmmxt here if we could know that operands[1]
4087 ends up already living in an iwmmxt register. Otherwise it's
4088 cheaper to have the alternate code being generated than moving
4089 values to iwmmxt regs and back. */
4090
ffcc986d 4091 /* Expand operation using core-registers.
4092 'FAIL' would achieve the same thing, but this is a bit smarter. */
4093 scratch1 = gen_reg_rtx (SImode);
4094 scratch2 = gen_reg_rtx (SImode);
4095 arm_emit_coreregs_64bit_shift (ASHIFT, operands[0], operands[1],
4096 operands[2], scratch1, scratch2);
4097 DONE;
a2cd141b 4098 }
a2cd141b 4099 "
4100)
4101
87b22bf7 4102(define_expand "ashlsi3"
3934ae0e 4103 [(set (match_operand:SI 0 "s_register_operand")
4104 (ashift:SI (match_operand:SI 1 "s_register_operand")
4105 (match_operand:SI 2 "arm_rhs_operand")))]
cffb2a26 4106 "TARGET_EITHER"
87b22bf7 4107 "
0438d37f 4108 if (CONST_INT_P (operands[2])
8c4e8755 4109 && (UINTVAL (operands[2])) > 31)
87b22bf7 4110 {
4111 emit_insn (gen_movsi (operands[0], const0_rtx));
4112 DONE;
4113 }
cffb2a26 4114 "
4115)
4116
a2cd141b 4117(define_expand "ashrdi3"
3934ae0e 4118 [(set (match_operand:DI 0 "s_register_operand")
4119 (ashiftrt:DI (match_operand:DI 1 "s_register_operand")
4120 (match_operand:SI 2 "reg_or_int_operand")))]
25f905c2 4121 "TARGET_32BIT"
a2cd141b 4122 "
aa06c51c 4123 if (TARGET_NEON)
4124 {
4125 /* Delay the decision whether to use NEON or core-regs until
4126 register allocation. */
4127 emit_insn (gen_ashrdi3_neon (operands[0], operands[1], operands[2]));
4128 DONE;
4129 }
4130
b805622c 4131 if (!CONST_INT_P (operands[2]) && TARGET_REALLY_IWMMXT)
ffcc986d 4132 ; /* No special preparation statements; expand pattern as above. */
4133 else
a2cd141b 4134 {
ffcc986d 4135 rtx scratch1, scratch2;
4136
ffcc986d 4137 /* Ideally we should use iwmmxt here if we could know that operands[1]
4138 ends up already living in an iwmmxt register. Otherwise it's
4139 cheaper to have the alternate code being generated than moving
4140 values to iwmmxt regs and back. */
4141
ffcc986d 4142 /* Expand operation using core-registers.
4143 'FAIL' would achieve the same thing, but this is a bit smarter. */
4144 scratch1 = gen_reg_rtx (SImode);
4145 scratch2 = gen_reg_rtx (SImode);
4146 arm_emit_coreregs_64bit_shift (ASHIFTRT, operands[0], operands[1],
4147 operands[2], scratch1, scratch2);
4148 DONE;
a2cd141b 4149 }
a2cd141b 4150 "
4151)
4152
87b22bf7 4153(define_expand "ashrsi3"
3934ae0e 4154 [(set (match_operand:SI 0 "s_register_operand")
4155 (ashiftrt:SI (match_operand:SI 1 "s_register_operand")
4156 (match_operand:SI 2 "arm_rhs_operand")))]
cffb2a26 4157 "TARGET_EITHER"
87b22bf7 4158 "
0438d37f 4159 if (CONST_INT_P (operands[2])
8c4e8755 4160 && UINTVAL (operands[2]) > 31)
87b22bf7 4161 operands[2] = GEN_INT (31);
cffb2a26 4162 "
4163)
4164
a2cd141b 4165(define_expand "lshrdi3"
3934ae0e 4166 [(set (match_operand:DI 0 "s_register_operand")
4167 (lshiftrt:DI (match_operand:DI 1 "s_register_operand")
4168 (match_operand:SI 2 "reg_or_int_operand")))]
25f905c2 4169 "TARGET_32BIT"
a2cd141b 4170 "
aa06c51c 4171 if (TARGET_NEON)
4172 {
4173 /* Delay the decision whether to use NEON or core-regs until
4174 register allocation. */
4175 emit_insn (gen_lshrdi3_neon (operands[0], operands[1], operands[2]));
4176 DONE;
4177 }
4178
b805622c 4179 if (!CONST_INT_P (operands[2]) && TARGET_REALLY_IWMMXT)
ffcc986d 4180 ; /* No special preparation statements; expand pattern as above. */
4181 else
a2cd141b 4182 {
ffcc986d 4183 rtx scratch1, scratch2;
4184
ffcc986d 4185 /* Ideally we should use iwmmxt here if we could know that operands[1]
4186 ends up already living in an iwmmxt register. Otherwise it's
4187 cheaper to have the alternate code being generated than moving
4188 values to iwmmxt regs and back. */
4189
ffcc986d 4190 /* Expand operation using core-registers.
4191 'FAIL' would achieve the same thing, but this is a bit smarter. */
4192 scratch1 = gen_reg_rtx (SImode);
4193 scratch2 = gen_reg_rtx (SImode);
4194 arm_emit_coreregs_64bit_shift (LSHIFTRT, operands[0], operands[1],
4195 operands[2], scratch1, scratch2);
4196 DONE;
a2cd141b 4197 }
a2cd141b 4198 "
4199)
4200
87b22bf7 4201(define_expand "lshrsi3"
3934ae0e 4202 [(set (match_operand:SI 0 "s_register_operand")
4203 (lshiftrt:SI (match_operand:SI 1 "s_register_operand")
4204 (match_operand:SI 2 "arm_rhs_operand")))]
cffb2a26 4205 "TARGET_EITHER"
87b22bf7 4206 "
0438d37f 4207 if (CONST_INT_P (operands[2])
8c4e8755 4208 && (UINTVAL (operands[2])) > 31)
87b22bf7 4209 {
4210 emit_insn (gen_movsi (operands[0], const0_rtx));
4211 DONE;
4212 }
cffb2a26 4213 "
4214)
4215
87b22bf7 4216(define_expand "rotlsi3"
3934ae0e 4217 [(set (match_operand:SI 0 "s_register_operand")
4218 (rotatert:SI (match_operand:SI 1 "s_register_operand")
4219 (match_operand:SI 2 "reg_or_int_operand")))]
25f905c2 4220 "TARGET_32BIT"
87b22bf7 4221 "
0438d37f 4222 if (CONST_INT_P (operands[2]))
87b22bf7 4223 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
4224 else
b11cae9e 4225 {
87b22bf7 4226 rtx reg = gen_reg_rtx (SImode);
4227 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
4228 operands[2] = reg;
b11cae9e 4229 }
cffb2a26 4230 "
4231)
9c08d1fa 4232
87b22bf7 4233(define_expand "rotrsi3"
3934ae0e 4234 [(set (match_operand:SI 0 "s_register_operand")
4235 (rotatert:SI (match_operand:SI 1 "s_register_operand")
4236 (match_operand:SI 2 "arm_rhs_operand")))]
cffb2a26 4237 "TARGET_EITHER"
87b22bf7 4238 "
25f905c2 4239 if (TARGET_32BIT)
cffb2a26 4240 {
0438d37f 4241 if (CONST_INT_P (operands[2])
8c4e8755 4242 && UINTVAL (operands[2]) > 31)
cffb2a26 4243 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
4244 }
25f905c2 4245 else /* TARGET_THUMB1 */
cffb2a26 4246 {
0438d37f 4247 if (CONST_INT_P (operands [2]))
cffb2a26 4248 operands [2] = force_reg (SImode, operands[2]);
4249 }
4250 "
4251)
87b22bf7 4252
cffb2a26 4253(define_insn "*arm_shiftsi3"
88c29385 4254 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r,r")
cffb2a26 4255 (match_operator:SI 3 "shift_operator"
88c29385 4256 [(match_operand:SI 1 "s_register_operand" "0,l,r,r")
4257 (match_operand:SI 2 "reg_or_int_operand" "l,M,M,r")]))]
25f905c2 4258 "TARGET_32BIT"
4259 "* return arm_output_shift(operands, 0);"
344495ea 4260 [(set_attr "predicable" "yes")
88c29385 4261 (set_attr "arch" "t2,t2,*,*")
4262 (set_attr "predicable_short_it" "yes,yes,no,no")
7c36fe71 4263 (set_attr "length" "4")
331beb1a 4264 (set_attr "shift" "1")
88c29385 4265 (set_attr "type" "alu_shift_reg,alu_shift_imm,alu_shift_imm,alu_shift_reg")]
6c4c2133 4266)
87b22bf7 4267
f7fbdd4a 4268(define_insn "*shiftsi3_compare0"
bd5b4116 4269 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 4270 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
6b6abc9c 4271 [(match_operand:SI 1 "s_register_operand" "r,r")
4272 (match_operand:SI 2 "arm_rhs_operand" "M,r")])
9c08d1fa 4273 (const_int 0)))
6b6abc9c 4274 (set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 4275 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
25f905c2 4276 "TARGET_32BIT"
4277 "* return arm_output_shift(operands, 1);"
344495ea 4278 [(set_attr "conds" "set")
331beb1a 4279 (set_attr "shift" "1")
d82e788e 4280 (set_attr "type" "alus_shift_imm,alus_shift_reg")]
0d66636f 4281)
9c08d1fa 4282
f7fbdd4a 4283(define_insn "*shiftsi3_compare0_scratch"
bd5b4116 4284 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 4285 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
6b6abc9c 4286 [(match_operand:SI 1 "s_register_operand" "r,r")
4287 (match_operand:SI 2 "arm_rhs_operand" "M,r")])
9c08d1fa 4288 (const_int 0)))
6b6abc9c 4289 (clobber (match_scratch:SI 0 "=r,r"))]
25f905c2 4290 "TARGET_32BIT"
4291 "* return arm_output_shift(operands, 1);"
344495ea 4292 [(set_attr "conds" "set")
6b6abc9c 4293 (set_attr "shift" "1")
d82e788e 4294 (set_attr "type" "shift_imm,shift_reg")]
0d66636f 4295)
9c08d1fa 4296
d5d4dc8d 4297(define_insn "*not_shiftsi"
4298 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 4299 (not:SI (match_operator:SI 3 "shift_operator"
d5d4dc8d 4300 [(match_operand:SI 1 "s_register_operand" "r,r")
4301 (match_operand:SI 2 "shift_amount_operand" "M,rM")])))]
4302 "TARGET_32BIT"
6c4c2133 4303 "mvn%?\\t%0, %1%S3"
344495ea 4304 [(set_attr "predicable" "yes")
331beb1a 4305 (set_attr "shift" "1")
d5d4dc8d 4306 (set_attr "arch" "32,a")
1aed5204 4307 (set_attr "type" "mvn_shift,mvn_shift_reg")])
9c08d1fa 4308
d5d4dc8d 4309(define_insn "*not_shiftsi_compare0"
bd5b4116 4310 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 4311 (compare:CC_NOOV
4312 (not:SI (match_operator:SI 3 "shift_operator"
4313 [(match_operand:SI 1 "s_register_operand" "r,r")
4314 (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
4315 (const_int 0)))
4316 (set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 4317 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
d5d4dc8d 4318 "TARGET_32BIT"
3ef90e77 4319 "mvns%?\\t%0, %1%S3"
344495ea 4320 [(set_attr "conds" "set")
331beb1a 4321 (set_attr "shift" "1")
d5d4dc8d 4322 (set_attr "arch" "32,a")
1aed5204 4323 (set_attr "type" "mvn_shift,mvn_shift_reg")])
9c08d1fa 4324
d5d4dc8d 4325(define_insn "*not_shiftsi_compare0_scratch"
bd5b4116 4326 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 4327 (compare:CC_NOOV
4328 (not:SI (match_operator:SI 3 "shift_operator"
4329 [(match_operand:SI 1 "s_register_operand" "r,r")
4330 (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
4331 (const_int 0)))
4332 (clobber (match_scratch:SI 0 "=r,r"))]
4333 "TARGET_32BIT"
3ef90e77 4334 "mvns%?\\t%0, %1%S3"
344495ea 4335 [(set_attr "conds" "set")
331beb1a 4336 (set_attr "shift" "1")
d5d4dc8d 4337 (set_attr "arch" "32,a")
1aed5204 4338 (set_attr "type" "mvn_shift,mvn_shift_reg")])
9c08d1fa 4339
cffb2a26 4340;; We don't really have extzv, but defining this using shifts helps
4341;; to reduce register pressure later on.
4342
4343(define_expand "extzv"
3934ae0e 4344 [(set (match_operand 0 "s_register_operand")
4345 (zero_extract (match_operand 1 "nonimmediate_operand")
4346 (match_operand 2 "const_int_operand")
4347 (match_operand 3 "const_int_operand")))]
8b054d5a 4348 "TARGET_THUMB1 || arm_arch_thumb2"
cffb2a26 4349 "
4350 {
4351 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
4352 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
4353
8b054d5a 4354 if (arm_arch_thumb2)
4355 {
eb04cafb 4356 HOST_WIDE_INT width = INTVAL (operands[2]);
4357 HOST_WIDE_INT bitpos = INTVAL (operands[3]);
4358
4359 if (unaligned_access && MEM_P (operands[1])
4360 && (width == 16 || width == 32) && (bitpos % BITS_PER_UNIT) == 0)
4361 {
4362 rtx base_addr;
4363
4364 if (BYTES_BIG_ENDIAN)
4365 bitpos = GET_MODE_BITSIZE (GET_MODE (operands[0])) - width
4366 - bitpos;
4367
4368 if (width == 32)
4369 {
4370 base_addr = adjust_address (operands[1], SImode,
4371 bitpos / BITS_PER_UNIT);
4372 emit_insn (gen_unaligned_loadsi (operands[0], base_addr));
4373 }
4374 else
4375 {
4376 rtx dest = operands[0];
4377 rtx tmp = gen_reg_rtx (SImode);
4378
4379 /* We may get a paradoxical subreg here. Strip it off. */
4380 if (GET_CODE (dest) == SUBREG
4381 && GET_MODE (dest) == SImode
4382 && GET_MODE (SUBREG_REG (dest)) == HImode)
4383 dest = SUBREG_REG (dest);
4384
4385 if (GET_MODE_BITSIZE (GET_MODE (dest)) != width)
4386 FAIL;
4387
4388 base_addr = adjust_address (operands[1], HImode,
4389 bitpos / BITS_PER_UNIT);
4390 emit_insn (gen_unaligned_loadhiu (tmp, base_addr));
4391 emit_move_insn (gen_lowpart (SImode, dest), tmp);
4392 }
4393 DONE;
4394 }
4395 else if (s_register_operand (operands[1], GET_MODE (operands[1])))
4396 {
4397 emit_insn (gen_extzv_t2 (operands[0], operands[1], operands[2],
4398 operands[3]));
4399 DONE;
4400 }
4401 else
4402 FAIL;
8b054d5a 4403 }
eb04cafb 4404
4405 if (!s_register_operand (operands[1], GET_MODE (operands[1])))
4406 FAIL;
8b054d5a 4407
cffb2a26 4408 operands[3] = GEN_INT (rshift);
4409
4410 if (lshift == 0)
4411 {
4412 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
4413 DONE;
4414 }
4415
eb04cafb 4416 emit_insn (gen_extzv_t1 (operands[0], operands[1], GEN_INT (lshift),
4417 operands[3], gen_reg_rtx (SImode)));
4418 DONE;
215b30b3 4419 }"
cffb2a26 4420)
4421
eb04cafb 4422;; Helper for extzv, for the Thumb-1 register-shifts case.
4423
4424(define_expand "extzv_t1"
3934ae0e 4425 [(set (match_operand:SI 4 "s_register_operand")
4426 (ashift:SI (match_operand:SI 1 "nonimmediate_operand")
4427 (match_operand:SI 2 "const_int_operand")))
4428 (set (match_operand:SI 0 "s_register_operand")
eb04cafb 4429 (lshiftrt:SI (match_dup 4)
3934ae0e 4430 (match_operand:SI 3 "const_int_operand")))]
eb04cafb 4431 "TARGET_THUMB1"
4432 "")
4433
4434(define_expand "extv"
3934ae0e 4435 [(set (match_operand 0 "s_register_operand")
4436 (sign_extract (match_operand 1 "nonimmediate_operand")
4437 (match_operand 2 "const_int_operand")
4438 (match_operand 3 "const_int_operand")))]
eb04cafb 4439 "arm_arch_thumb2"
4440{
4441 HOST_WIDE_INT width = INTVAL (operands[2]);
4442 HOST_WIDE_INT bitpos = INTVAL (operands[3]);
4443
4444 if (unaligned_access && MEM_P (operands[1]) && (width == 16 || width == 32)
4445 && (bitpos % BITS_PER_UNIT) == 0)
4446 {
4447 rtx base_addr;
4448
4449 if (BYTES_BIG_ENDIAN)
4450 bitpos = GET_MODE_BITSIZE (GET_MODE (operands[0])) - width - bitpos;
4451
4452 if (width == 32)
4453 {
4454 base_addr = adjust_address (operands[1], SImode,
4455 bitpos / BITS_PER_UNIT);
4456 emit_insn (gen_unaligned_loadsi (operands[0], base_addr));
4457 }
4458 else
4459 {
4460 rtx dest = operands[0];
4461 rtx tmp = gen_reg_rtx (SImode);
4462
4463 /* We may get a paradoxical subreg here. Strip it off. */
4464 if (GET_CODE (dest) == SUBREG
4465 && GET_MODE (dest) == SImode
4466 && GET_MODE (SUBREG_REG (dest)) == HImode)
4467 dest = SUBREG_REG (dest);
4468
4469 if (GET_MODE_BITSIZE (GET_MODE (dest)) != width)
4470 FAIL;
4471
4472 base_addr = adjust_address (operands[1], HImode,
4473 bitpos / BITS_PER_UNIT);
4474 emit_insn (gen_unaligned_loadhis (tmp, base_addr));
4475 emit_move_insn (gen_lowpart (SImode, dest), tmp);
4476 }
4477
4478 DONE;
4479 }
4480 else if (!s_register_operand (operands[1], GET_MODE (operands[1])))
4481 FAIL;
4482 else if (GET_MODE (operands[0]) == SImode
4483 && GET_MODE (operands[1]) == SImode)
4484 {
4485 emit_insn (gen_extv_regsi (operands[0], operands[1], operands[2],
4486 operands[3]));
4487 DONE;
4488 }
4489
4490 FAIL;
4491})
4492
4493; Helper to expand register forms of extv with the proper modes.
4494
4495(define_expand "extv_regsi"
3934ae0e 4496 [(set (match_operand:SI 0 "s_register_operand")
4497 (sign_extract:SI (match_operand:SI 1 "s_register_operand")
4498 (match_operand 2 "const_int_operand")
4499 (match_operand 3 "const_int_operand")))]
eb04cafb 4500 ""
4501{
4502})
4503
4504; ARMv6+ unaligned load/store instructions (used for packed structure accesses).
4505
4506(define_insn "unaligned_loadsi"
70ce330a 4507 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
4508 (unspec:SI [(match_operand:SI 1 "memory_operand" "m,Uw,m")]
eb04cafb 4509 UNSPEC_UNALIGNED_LOAD))]
8fe38eb2 4510 "unaligned_access"
70ce330a 4511 "@
4512 ldr\t%0, %1\t@ unaligned
4513 ldr%?\t%0, %1\t@ unaligned
4514 ldr%?\t%0, %1\t@ unaligned"
4515 [(set_attr "arch" "t1,t2,32")
4516 (set_attr "length" "2,2,4")
4517 (set_attr "predicable" "no,yes,yes")
4518 (set_attr "predicable_short_it" "no,yes,no")
9f2c2a36 4519 (set_attr "type" "load_4")])
eb04cafb 4520
70ce330a 4521;; The 16-bit Thumb1 variant of ldrsh requires two registers in the
4522;; address (there's no immediate format). That's tricky to support
4523;; here and we don't really need this pattern for that case, so only
4524;; enable for 32-bit ISAs.
eb04cafb 4525(define_insn "unaligned_loadhis"
5d79b75e 4526 [(set (match_operand:SI 0 "s_register_operand" "=r")
eb04cafb 4527 (sign_extend:SI
5d79b75e 4528 (unspec:HI [(match_operand:HI 1 "memory_operand" "Uh")]
eb04cafb 4529 UNSPEC_UNALIGNED_LOAD)))]
70ce330a 4530 "unaligned_access && TARGET_32BIT"
3ef90e77 4531 "ldrsh%?\t%0, %1\t@ unaligned"
5d79b75e 4532 [(set_attr "predicable" "yes")
eb04cafb 4533 (set_attr "type" "load_byte")])
4534
4535(define_insn "unaligned_loadhiu"
70ce330a 4536 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
eb04cafb 4537 (zero_extend:SI
70ce330a 4538 (unspec:HI [(match_operand:HI 1 "memory_operand" "m,Uw,m")]
eb04cafb 4539 UNSPEC_UNALIGNED_LOAD)))]
8fe38eb2 4540 "unaligned_access"
70ce330a 4541 "@
4542 ldrh\t%0, %1\t@ unaligned
4543 ldrh%?\t%0, %1\t@ unaligned
4544 ldrh%?\t%0, %1\t@ unaligned"
4545 [(set_attr "arch" "t1,t2,32")
4546 (set_attr "length" "2,2,4")
4547 (set_attr "predicable" "no,yes,yes")
4548 (set_attr "predicable_short_it" "no,yes,no")
eb04cafb 4549 (set_attr "type" "load_byte")])
4550
4551(define_insn "unaligned_storesi"
70ce330a 4552 [(set (match_operand:SI 0 "memory_operand" "=m,Uw,m")
4553 (unspec:SI [(match_operand:SI 1 "s_register_operand" "l,l,r")]
eb04cafb 4554 UNSPEC_UNALIGNED_STORE))]
8fe38eb2 4555 "unaligned_access"
70ce330a 4556 "@
4557 str\t%1, %0\t@ unaligned
4558 str%?\t%1, %0\t@ unaligned
4559 str%?\t%1, %0\t@ unaligned"
4560 [(set_attr "arch" "t1,t2,32")
4561 (set_attr "length" "2,2,4")
4562 (set_attr "predicable" "no,yes,yes")
4563 (set_attr "predicable_short_it" "no,yes,no")
9f2c2a36 4564 (set_attr "type" "store_4")])
eb04cafb 4565
4566(define_insn "unaligned_storehi"
70ce330a 4567 [(set (match_operand:HI 0 "memory_operand" "=m,Uw,m")
4568 (unspec:HI [(match_operand:HI 1 "s_register_operand" "l,l,r")]
eb04cafb 4569 UNSPEC_UNALIGNED_STORE))]
8fe38eb2 4570 "unaligned_access"
70ce330a 4571 "@
4572 strh\t%1, %0\t@ unaligned
4573 strh%?\t%1, %0\t@ unaligned
4574 strh%?\t%1, %0\t@ unaligned"
4575 [(set_attr "arch" "t1,t2,32")
4576 (set_attr "length" "2,2,4")
4577 (set_attr "predicable" "no,yes,yes")
4578 (set_attr "predicable_short_it" "no,yes,no")
9f2c2a36 4579 (set_attr "type" "store_4")])
eb04cafb 4580
ae51a965 4581
eb04cafb 4582(define_insn "*extv_reg"
8b054d5a 4583 [(set (match_operand:SI 0 "s_register_operand" "=r")
4584 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
13051f13 4585 (match_operand:SI 2 "const_int_operand" "n")
4586 (match_operand:SI 3 "const_int_operand" "n")))]
4587 "arm_arch_thumb2
4588 && IN_RANGE (INTVAL (operands[3]), 0, 31)
4589 && IN_RANGE (INTVAL (operands[2]), 1, 32 - INTVAL (operands[3]))"
8b054d5a 4590 "sbfx%?\t%0, %1, %3, %2"
4591 [(set_attr "length" "4")
d952d547 4592 (set_attr "predicable" "yes")
d82e788e 4593 (set_attr "type" "bfm")]
8b054d5a 4594)
4595
4596(define_insn "extzv_t2"
4597 [(set (match_operand:SI 0 "s_register_operand" "=r")
4598 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "r")
13051f13 4599 (match_operand:SI 2 "const_int_operand" "n")
4600 (match_operand:SI 3 "const_int_operand" "n")))]
4601 "arm_arch_thumb2
4602 && IN_RANGE (INTVAL (operands[3]), 0, 31)
4603 && IN_RANGE (INTVAL (operands[2]), 1, 32 - INTVAL (operands[3]))"
8b054d5a 4604 "ubfx%?\t%0, %1, %3, %2"
4605 [(set_attr "length" "4")
d952d547 4606 (set_attr "predicable" "yes")
d82e788e 4607 (set_attr "type" "bfm")]
8b054d5a 4608)
4609
7d3cda8c 4610
4611;; Division instructions
4612(define_insn "divsi3"
8f5f2788 4613 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4614 (div:SI (match_operand:SI 1 "s_register_operand" "r,r")
4615 (match_operand:SI 2 "s_register_operand" "r,r")))]
7d3cda8c 4616 "TARGET_IDIV"
8f5f2788 4617 "@
4618 sdiv%?\t%0, %1, %2
4619 sdiv\t%0, %1, %2"
4620 [(set_attr "arch" "32,v8mb")
4621 (set_attr "predicable" "yes")
9da0ec36 4622 (set_attr "type" "sdiv")]
7d3cda8c 4623)
4624
4625(define_insn "udivsi3"
8f5f2788 4626 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4627 (udiv:SI (match_operand:SI 1 "s_register_operand" "r,r")
4628 (match_operand:SI 2 "s_register_operand" "r,r")))]
7d3cda8c 4629 "TARGET_IDIV"
8f5f2788 4630 "@
4631 udiv%?\t%0, %1, %2
4632 udiv\t%0, %1, %2"
4633 [(set_attr "arch" "32,v8mb")
4634 (set_attr "predicable" "yes")
9da0ec36 4635 (set_attr "type" "udiv")]
7d3cda8c 4636)
4637
b11cae9e 4638\f
4639;; Unary arithmetic insns
4640
f6c98a9a 4641(define_expand "negvsi3"
4642 [(match_operand:SI 0 "register_operand")
4643 (match_operand:SI 1 "register_operand")
4644 (match_operand 2 "")]
4645 "TARGET_32BIT"
4646{
4647 emit_insn (gen_subsi3_compare (operands[0], const0_rtx, operands[1]));
4648 arm_gen_unlikely_cbranch (NE, CC_Vmode, operands[2]);
4649
4650 DONE;
4651})
4652
4653(define_expand "negvdi3"
4654 [(match_operand:DI 0 "register_operand")
4655 (match_operand:DI 1 "register_operand")
4656 (match_operand 2 "")]
4657 "TARGET_ARM"
4658{
4659 emit_insn (gen_negdi2_compare (operands[0], operands[1]));
4660 arm_gen_unlikely_cbranch (NE, CC_Vmode, operands[2]);
4661
4662 DONE;
4663})
4664
4665
4666(define_insn_and_split "negdi2_compare"
4667 [(set (reg:CC CC_REGNUM)
4668 (compare:CC
4669 (const_int 0)
4670 (match_operand:DI 1 "register_operand" "0,r")))
4671 (set (match_operand:DI 0 "register_operand" "=r,&r")
4672 (minus:DI (const_int 0) (match_dup 1)))]
4673 "TARGET_ARM"
4674 "#"
4675 "&& reload_completed"
4676 [(parallel [(set (reg:CC CC_REGNUM)
4677 (compare:CC (const_int 0) (match_dup 1)))
4678 (set (match_dup 0) (minus:SI (const_int 0)
4679 (match_dup 1)))])
4680 (parallel [(set (reg:CC CC_REGNUM)
4681 (compare:CC (const_int 0) (match_dup 3)))
4682 (set (match_dup 2)
4683 (minus:SI
4684 (minus:SI (const_int 0) (match_dup 3))
3b0dcaf2 4685 (ltu:SI (reg:CC CC_REGNUM)
f6c98a9a 4686 (const_int 0))))])]
4687 {
4688 operands[2] = gen_highpart (SImode, operands[0]);
4689 operands[0] = gen_lowpart (SImode, operands[0]);
4690 operands[3] = gen_highpart (SImode, operands[1]);
4691 operands[1] = gen_lowpart (SImode, operands[1]);
4692 }
4693 [(set_attr "conds" "set")
4694 (set_attr "length" "8")
4695 (set_attr "type" "multiple")]
4696)
4697
cffb2a26 4698(define_expand "negdi2"
4699 [(parallel
3934ae0e 4700 [(set (match_operand:DI 0 "s_register_operand")
4701 (neg:DI (match_operand:DI 1 "s_register_operand")))
bd5b4116 4702 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 4703 "TARGET_EITHER"
774d2fbb 4704 {
4705 if (TARGET_NEON)
4706 {
4707 emit_insn (gen_negdi2_neon (operands[0], operands[1]));
4708 DONE;
4709 }
4710 }
cffb2a26 4711)
4712
4713;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
e5fea38e 4714;; The first alternative allows the common case of a *full* overlap.
d5bf2b53 4715(define_insn_and_split "*negdi2_insn"
458a8706 4716 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 4717 (neg:DI (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 4718 (clobber (reg:CC CC_REGNUM))]
d5bf2b53 4719 "TARGET_32BIT"
4720 "#" ; rsbs %Q0, %Q1, #0; rsc %R0, %R1, #0 (ARM)
4721 ; negs %Q0, %Q1 ; sbc %R0, %R1, %R1, lsl #1 (Thumb-2)
ba6a3b2f 4722 "&& reload_completed"
4723 [(parallel [(set (reg:CC CC_REGNUM)
4724 (compare:CC (const_int 0) (match_dup 1)))
4725 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 1)))])
4726 (set (match_dup 2) (minus:SI (minus:SI (const_int 0) (match_dup 3))
3b0dcaf2 4727 (ltu:SI (reg:CC CC_REGNUM) (const_int 0))))]
ba6a3b2f 4728 {
4729 operands[2] = gen_highpart (SImode, operands[0]);
4730 operands[0] = gen_lowpart (SImode, operands[0]);
4731 operands[3] = gen_highpart (SImode, operands[1]);
4732 operands[1] = gen_lowpart (SImode, operands[1]);
4733 }
cffb2a26 4734 [(set_attr "conds" "clob")
1b7da4ac 4735 (set_attr "length" "8")
4736 (set_attr "type" "multiple")]
cffb2a26 4737)
b11cae9e 4738
f6c98a9a 4739(define_insn "*negsi2_carryin_compare"
4740 [(set (reg:CC CC_REGNUM)
4741 (compare:CC (const_int 0)
4742 (match_operand:SI 1 "s_register_operand" "r")))
4743 (set (match_operand:SI 0 "s_register_operand" "=r")
4744 (minus:SI (minus:SI (const_int 0)
4745 (match_dup 1))
3b0dcaf2 4746 (match_operand:SI 2 "arm_borrow_operation" "")))]
f6c98a9a 4747 "TARGET_ARM"
4748 "rscs\\t%0, %1, #0"
4749 [(set_attr "conds" "set")
4750 (set_attr "type" "alus_imm")]
4751)
4752
cffb2a26 4753(define_expand "negsi2"
3934ae0e 4754 [(set (match_operand:SI 0 "s_register_operand")
4755 (neg:SI (match_operand:SI 1 "s_register_operand")))]
cffb2a26 4756 "TARGET_EITHER"
b11cae9e 4757 ""
cffb2a26 4758)
4759
4760(define_insn "*arm_negsi2"
d952d547 4761 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4762 (neg:SI (match_operand:SI 1 "s_register_operand" "l,r")))]
25f905c2 4763 "TARGET_32BIT"
cffb2a26 4764 "rsb%?\\t%0, %1, #0"
d952d547 4765 [(set_attr "predicable" "yes")
4766 (set_attr "predicable_short_it" "yes,no")
4767 (set_attr "arch" "t2,*")
1b7da4ac 4768 (set_attr "length" "4")
112eda6f 4769 (set_attr "type" "alu_sreg")]
cffb2a26 4770)
4771
604f3a0a 4772(define_expand "negsf2"
3934ae0e 4773 [(set (match_operand:SF 0 "s_register_operand")
4774 (neg:SF (match_operand:SF 1 "s_register_operand")))]
d7216193 4775 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 4776 ""
4777)
4778
4779(define_expand "negdf2"
3934ae0e 4780 [(set (match_operand:DF 0 "s_register_operand")
4781 (neg:DF (match_operand:DF 1 "s_register_operand")))]
994606f8 4782 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
604f3a0a 4783 "")
4784
7eaf2be0 4785(define_insn_and_split "*zextendsidi_negsi"
4786 [(set (match_operand:DI 0 "s_register_operand" "=r")
4787 (zero_extend:DI (neg:SI (match_operand:SI 1 "s_register_operand" "r"))))]
4788 "TARGET_32BIT"
4789 "#"
4790 ""
4791 [(set (match_dup 2)
4792 (neg:SI (match_dup 1)))
4793 (set (match_dup 3)
4794 (const_int 0))]
4795 {
4796 operands[2] = gen_lowpart (SImode, operands[0]);
4797 operands[3] = gen_highpart (SImode, operands[0]);
4798 }
4799 [(set_attr "length" "8")
4800 (set_attr "type" "multiple")]
4801)
4802
83e2b922 4803;; Negate an extended 32-bit value.
4804(define_insn_and_split "*negdi_extendsidi"
61fa8ff2 4805 [(set (match_operand:DI 0 "s_register_operand" "=l,r")
4806 (neg:DI (sign_extend:DI
4807 (match_operand:SI 1 "s_register_operand" "l,r"))))
83e2b922 4808 (clobber (reg:CC CC_REGNUM))]
4809 "TARGET_32BIT"
61fa8ff2 4810 "#"
83e2b922 4811 "&& reload_completed"
4812 [(const_int 0)]
4813 {
61fa8ff2 4814 rtx low = gen_lowpart (SImode, operands[0]);
4815 rtx high = gen_highpart (SImode, operands[0]);
4816
4817 if (reg_overlap_mentioned_p (low, operands[1]))
4818 {
4819 /* Input overlaps the low word of the output. Use:
4820 asr Rhi, Rin, #31
4821 rsbs Rlo, Rin, #0
4822 rsc Rhi, Rhi, #0 (thumb2: sbc Rhi, Rhi, Rhi, lsl #1). */
3b0dcaf2 4823 rtx cc_reg = gen_rtx_REG (CCmode, CC_REGNUM);
61fa8ff2 4824
d1f9b275 4825 emit_insn (gen_rtx_SET (high,
61fa8ff2 4826 gen_rtx_ASHIFTRT (SImode, operands[1],
4827 GEN_INT (31))));
4828
4829 emit_insn (gen_subsi3_compare (low, const0_rtx, operands[1]));
4830 if (TARGET_ARM)
d1f9b275 4831 emit_insn (gen_rtx_SET (high,
61fa8ff2 4832 gen_rtx_MINUS (SImode,
4833 gen_rtx_MINUS (SImode,
4834 const0_rtx,
4835 high),
4836 gen_rtx_LTU (SImode,
4837 cc_reg,
4838 const0_rtx))));
4839 else
4840 {
4841 rtx two_x = gen_rtx_ASHIFT (SImode, high, GEN_INT (1));
d1f9b275 4842 emit_insn (gen_rtx_SET (high,
61fa8ff2 4843 gen_rtx_MINUS (SImode,
4844 gen_rtx_MINUS (SImode,
4845 high,
4846 two_x),
4847 gen_rtx_LTU (SImode,
4848 cc_reg,
4849 const0_rtx))));
4850 }
4851 }
4852 else
4853 {
4854 /* No overlap, or overlap on high word. Use:
4855 rsb Rlo, Rin, #0
4856 bic Rhi, Rlo, Rin
4857 asr Rhi, Rhi, #31
4858 Flags not needed for this sequence. */
d1f9b275 4859 emit_insn (gen_rtx_SET (low, gen_rtx_NEG (SImode, operands[1])));
4860 emit_insn (gen_rtx_SET (high,
61fa8ff2 4861 gen_rtx_AND (SImode,
4862 gen_rtx_NOT (SImode, operands[1]),
4863 low)));
d1f9b275 4864 emit_insn (gen_rtx_SET (high,
61fa8ff2 4865 gen_rtx_ASHIFTRT (SImode, high,
4866 GEN_INT (31))));
4867 }
4868 DONE;
83e2b922 4869 }
61fa8ff2 4870 [(set_attr "length" "12")
4871 (set_attr "arch" "t2,*")
1b7da4ac 4872 (set_attr "type" "multiple")]
83e2b922 4873)
4874
4875(define_insn_and_split "*negdi_zero_extendsidi"
4876 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
4877 (neg:DI (zero_extend:DI (match_operand:SI 1 "s_register_operand" "0,r"))))
4878 (clobber (reg:CC CC_REGNUM))]
4879 "TARGET_32BIT"
4880 "#" ; "rsbs\\t%Q0, %1, #0\;sbc\\t%R0,%R0,%R0"
4881 ;; Don't care what register is input to sbc,
47ae02b7 4882 ;; since we just need to propagate the carry.
83e2b922 4883 "&& reload_completed"
4884 [(parallel [(set (reg:CC CC_REGNUM)
3b0dcaf2 4885 (compare:CC (const_int 0) (match_dup 1)))
4886 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 1)))])
83e2b922 4887 (set (match_dup 2) (minus:SI (minus:SI (match_dup 2) (match_dup 2))
3b0dcaf2 4888 (ltu:SI (reg:CC CC_REGNUM) (const_int 0))))]
83e2b922 4889 {
4890 operands[2] = gen_highpart (SImode, operands[0]);
4891 operands[0] = gen_lowpart (SImode, operands[0]);
4892 }
4893 [(set_attr "conds" "clob")
1b7da4ac 4894 (set_attr "length" "8")
4895 (set_attr "type" "multiple")] ;; length in thumb is 4
83e2b922 4896)
4897
9c08d1fa 4898;; abssi2 doesn't really clobber the condition codes if a different register
4899;; is being set. To keep things simple, assume during rtl manipulations that
4900;; it does, but tell the final scan operator the truth. Similarly for
4901;; (neg (abs...))
4902
604f3a0a 4903(define_expand "abssi2"
4904 [(parallel
3934ae0e 4905 [(set (match_operand:SI 0 "s_register_operand")
4906 (abs:SI (match_operand:SI 1 "s_register_operand")))
ba156559 4907 (clobber (match_dup 2))])]
4908 "TARGET_EITHER"
4909 "
25f905c2 4910 if (TARGET_THUMB1)
ba156559 4911 operands[2] = gen_rtx_SCRATCH (SImode);
4912 else
4913 operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
4914")
604f3a0a 4915
ba6a3b2f 4916(define_insn_and_split "*arm_abssi2"
ba156559 4917 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
9c08d1fa 4918 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
bd5b4116 4919 (clobber (reg:CC CC_REGNUM))]
cffb2a26 4920 "TARGET_ARM"
ba6a3b2f 4921 "#"
4922 "&& reload_completed"
4923 [(const_int 0)]
4924 {
4925 /* if (which_alternative == 0) */
4926 if (REGNO(operands[0]) == REGNO(operands[1]))
4927 {
4928 /* Emit the pattern:
4929 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
4930 [(set (reg:CC CC_REGNUM)
4931 (compare:CC (match_dup 0) (const_int 0)))
4932 (cond_exec (lt:CC (reg:CC CC_REGNUM) (const_int 0))
4933 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 1))))]
4934 */
d1f9b275 4935 emit_insn (gen_rtx_SET (gen_rtx_REG (CCmode, CC_REGNUM),
ba6a3b2f 4936 gen_rtx_COMPARE (CCmode, operands[0], const0_rtx)));
4937 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
4938 (gen_rtx_LT (SImode,
4939 gen_rtx_REG (CCmode, CC_REGNUM),
4940 const0_rtx)),
d1f9b275 4941 (gen_rtx_SET (operands[0],
ba6a3b2f 4942 (gen_rtx_MINUS (SImode,
4943 const0_rtx,
4944 operands[1]))))));
4945 DONE;
4946 }
4947 else
4948 {
4949 /* Emit the pattern:
4950 alt1: eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31
4951 [(set (match_dup 0)
4952 (xor:SI (match_dup 1)
4953 (ashiftrt:SI (match_dup 1) (const_int 31))))
4954 (set (match_dup 0)
4955 (minus:SI (match_dup 0)
4956 (ashiftrt:SI (match_dup 1) (const_int 31))))]
4957 */
d1f9b275 4958 emit_insn (gen_rtx_SET (operands[0],
ba6a3b2f 4959 gen_rtx_XOR (SImode,
4960 gen_rtx_ASHIFTRT (SImode,
4961 operands[1],
4962 GEN_INT (31)),
4963 operands[1])));
d1f9b275 4964 emit_insn (gen_rtx_SET (operands[0],
ba6a3b2f 4965 gen_rtx_MINUS (SImode,
4966 operands[0],
4967 gen_rtx_ASHIFTRT (SImode,
4968 operands[1],
4969 GEN_INT (31)))));
4970 DONE;
4971 }
4972 }
cffb2a26 4973 [(set_attr "conds" "clob,*")
331beb1a 4974 (set_attr "shift" "1")
2ad08b65 4975 (set_attr "predicable" "no, yes")
1b7da4ac 4976 (set_attr "length" "8")
4977 (set_attr "type" "multiple")]
cffb2a26 4978)
9c08d1fa 4979
ba6a3b2f 4980(define_insn_and_split "*arm_neg_abssi2"
9c08d1fa 4981 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
4982 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
bd5b4116 4983 (clobber (reg:CC CC_REGNUM))]
cffb2a26 4984 "TARGET_ARM"
ba6a3b2f 4985 "#"
4986 "&& reload_completed"
4987 [(const_int 0)]
4988 {
4989 /* if (which_alternative == 0) */
4990 if (REGNO (operands[0]) == REGNO (operands[1]))
4991 {
4992 /* Emit the pattern:
4993 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
4994 */
d1f9b275 4995 emit_insn (gen_rtx_SET (gen_rtx_REG (CCmode, CC_REGNUM),
ba6a3b2f 4996 gen_rtx_COMPARE (CCmode, operands[0], const0_rtx)));
4997 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
4998 gen_rtx_GT (SImode,
4999 gen_rtx_REG (CCmode, CC_REGNUM),
5000 const0_rtx),
d1f9b275 5001 gen_rtx_SET (operands[0],
ba6a3b2f 5002 (gen_rtx_MINUS (SImode,
5003 const0_rtx,
5004 operands[1])))));
5005 }
5006 else
5007 {
5008 /* Emit the pattern:
5009 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31
5010 */
d1f9b275 5011 emit_insn (gen_rtx_SET (operands[0],
ba6a3b2f 5012 gen_rtx_XOR (SImode,
5013 gen_rtx_ASHIFTRT (SImode,
5014 operands[1],
5015 GEN_INT (31)),
5016 operands[1])));
d1f9b275 5017 emit_insn (gen_rtx_SET (operands[0],
ba6a3b2f 5018 gen_rtx_MINUS (SImode,
5019 gen_rtx_ASHIFTRT (SImode,
5020 operands[1],
5021 GEN_INT (31)),
5022 operands[0])));
5023 }
5024 DONE;
5025 }
cffb2a26 5026 [(set_attr "conds" "clob,*")
331beb1a 5027 (set_attr "shift" "1")
2ad08b65 5028 (set_attr "predicable" "no, yes")
1b7da4ac 5029 (set_attr "length" "8")
5030 (set_attr "type" "multiple")]
cffb2a26 5031)
b11cae9e 5032
604f3a0a 5033(define_expand "abssf2"
3934ae0e 5034 [(set (match_operand:SF 0 "s_register_operand")
5035 (abs:SF (match_operand:SF 1 "s_register_operand")))]
25f905c2 5036 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 5037 "")
5038
604f3a0a 5039(define_expand "absdf2"
3934ae0e 5040 [(set (match_operand:DF 0 "s_register_operand")
5041 (abs:DF (match_operand:DF 1 "s_register_operand")))]
a50d7267 5042 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 5043 "")
5044
7db9af5d 5045(define_expand "sqrtsf2"
3934ae0e 5046 [(set (match_operand:SF 0 "s_register_operand")
5047 (sqrt:SF (match_operand:SF 1 "s_register_operand")))]
d7216193 5048 "TARGET_32BIT && TARGET_HARD_FLOAT"
7db9af5d 5049 "")
9c08d1fa 5050
7db9af5d 5051(define_expand "sqrtdf2"
3934ae0e 5052 [(set (match_operand:DF 0 "s_register_operand")
5053 (sqrt:DF (match_operand:DF 1 "s_register_operand")))]
994606f8 5054 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
7db9af5d 5055 "")
9c08d1fa 5056
0d84c6e5 5057(define_expand "one_cmpldi2"
3934ae0e 5058 [(set (match_operand:DI 0 "s_register_operand")
5059 (not:DI (match_operand:DI 1 "s_register_operand")))]
0d84c6e5 5060 "TARGET_32BIT"
5061 "
5062 if (!TARGET_NEON && !TARGET_IWMMXT)
5063 {
5064 rtx low = simplify_gen_unary (NOT, SImode,
5065 gen_lowpart (SImode, operands[1]),
5066 SImode);
5067 rtx high = simplify_gen_unary (NOT, SImode,
5068 gen_highpart_mode (SImode, DImode,
5069 operands[1]),
5070 SImode);
5071
5072 emit_insn (gen_rtx_SET (gen_lowpart (SImode, operands[0]), low));
5073 emit_insn (gen_rtx_SET (gen_highpart (SImode, operands[0]), high));
5074
5075 DONE;
5076 }
5077 /* Otherwise expand pattern as above. */
5078 "
5079)
5080
5081(define_insn_and_split "*one_cmpldi2_insn"
10efb95f 5082 [(set (match_operand:DI 0 "s_register_operand" "=w,&r,&r,?w")
5083 (not:DI (match_operand:DI 1 "s_register_operand" " w, 0, r, w")))]
25f905c2 5084 "TARGET_32BIT"
10efb95f 5085 "@
5086 vmvn\t%P0, %P1
5087 #
5088 #
5089 vmvn\t%P0, %P1"
5090 "TARGET_32BIT && reload_completed
5091 && arm_general_register_operand (operands[0], DImode)"
a0f94409 5092 [(set (match_dup 0) (not:SI (match_dup 1)))
5093 (set (match_dup 2) (not:SI (match_dup 3)))]
5094 "
5095 {
5096 operands[2] = gen_highpart (SImode, operands[0]);
5097 operands[0] = gen_lowpart (SImode, operands[0]);
5098 operands[3] = gen_highpart (SImode, operands[1]);
5099 operands[1] = gen_lowpart (SImode, operands[1]);
5100 }"
10efb95f 5101 [(set_attr "length" "*,8,8,*")
5102 (set_attr "predicable" "no,yes,yes,no")
32093010 5103 (set_attr "type" "neon_move,multiple,multiple,neon_move")
b6779ddc 5104 (set_attr "arch" "neon_for_64bits,*,*,avoid_neon_for_64bits")]
cffb2a26 5105)
b11cae9e 5106
cffb2a26 5107(define_expand "one_cmplsi2"
3934ae0e 5108 [(set (match_operand:SI 0 "s_register_operand")
5109 (not:SI (match_operand:SI 1 "s_register_operand")))]
cffb2a26 5110 "TARGET_EITHER"
b11cae9e 5111 ""
cffb2a26 5112)
5113
5114(define_insn "*arm_one_cmplsi2"
d952d547 5115 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
5116 (not:SI (match_operand:SI 1 "s_register_operand" "l,r")))]
25f905c2 5117 "TARGET_32BIT"
cffb2a26 5118 "mvn%?\\t%0, %1"
d2a518d1 5119 [(set_attr "predicable" "yes")
d952d547 5120 (set_attr "predicable_short_it" "yes,no")
5121 (set_attr "arch" "t2,*")
5122 (set_attr "length" "4")
1aed5204 5123 (set_attr "type" "mvn_reg")]
cffb2a26 5124)
5125
f7fbdd4a 5126(define_insn "*notsi_compare0"
bd5b4116 5127 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 5128 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5129 (const_int 0)))
5130 (set (match_operand:SI 0 "s_register_operand" "=r")
5131 (not:SI (match_dup 1)))]
25f905c2 5132 "TARGET_32BIT"
3ef90e77 5133 "mvns%?\\t%0, %1"
d2a518d1 5134 [(set_attr "conds" "set")
1aed5204 5135 (set_attr "type" "mvn_reg")]
cffb2a26 5136)
9c08d1fa 5137
f7fbdd4a 5138(define_insn "*notsi_compare0_scratch"
bd5b4116 5139 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 5140 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5141 (const_int 0)))
5142 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 5143 "TARGET_32BIT"
3ef90e77 5144 "mvns%?\\t%0, %1"
d2a518d1 5145 [(set_attr "conds" "set")
1aed5204 5146 (set_attr "type" "mvn_reg")]
cffb2a26 5147)
b11cae9e 5148\f
5149;; Fixed <--> Floating conversion insns
5150
9b8516be 5151(define_expand "floatsihf2"
3934ae0e 5152 [(set (match_operand:HF 0 "general_operand")
5153 (float:HF (match_operand:SI 1 "general_operand")))]
9b8516be 5154 "TARGET_EITHER"
5155 "
5156 {
5157 rtx op1 = gen_reg_rtx (SFmode);
5158 expand_float (op1, operands[1], 0);
5159 op1 = convert_to_mode (HFmode, op1, 0);
5160 emit_move_insn (operands[0], op1);
5161 DONE;
5162 }"
5163)
5164
5165(define_expand "floatdihf2"
3934ae0e 5166 [(set (match_operand:HF 0 "general_operand")
5167 (float:HF (match_operand:DI 1 "general_operand")))]
9b8516be 5168 "TARGET_EITHER"
5169 "
5170 {
5171 rtx op1 = gen_reg_rtx (SFmode);
5172 expand_float (op1, operands[1], 0);
5173 op1 = convert_to_mode (HFmode, op1, 0);
5174 emit_move_insn (operands[0], op1);
5175 DONE;
5176 }"
5177)
5178
604f3a0a 5179(define_expand "floatsisf2"
3934ae0e 5180 [(set (match_operand:SF 0 "s_register_operand")
5181 (float:SF (match_operand:SI 1 "s_register_operand")))]
25f905c2 5182 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 5183 "
604f3a0a 5184")
5185
604f3a0a 5186(define_expand "floatsidf2"
3934ae0e 5187 [(set (match_operand:DF 0 "s_register_operand")
5188 (float:DF (match_operand:SI 1 "s_register_operand")))]
a50d7267 5189 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 5190 "
604f3a0a 5191")
5192
9b8516be 5193(define_expand "fix_trunchfsi2"
3934ae0e 5194 [(set (match_operand:SI 0 "general_operand")
5195 (fix:SI (fix:HF (match_operand:HF 1 "general_operand"))))]
9b8516be 5196 "TARGET_EITHER"
5197 "
5198 {
5199 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
5200 expand_fix (operands[0], op1, 0);
5201 DONE;
5202 }"
5203)
5204
5205(define_expand "fix_trunchfdi2"
3934ae0e 5206 [(set (match_operand:DI 0 "general_operand")
5207 (fix:DI (fix:HF (match_operand:HF 1 "general_operand"))))]
9b8516be 5208 "TARGET_EITHER"
5209 "
5210 {
5211 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
5212 expand_fix (operands[0], op1, 0);
5213 DONE;
5214 }"
5215)
5216
604f3a0a 5217(define_expand "fix_truncsfsi2"
3934ae0e 5218 [(set (match_operand:SI 0 "s_register_operand")
5219 (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand"))))]
25f905c2 5220 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 5221 "
604f3a0a 5222")
5223
604f3a0a 5224(define_expand "fix_truncdfsi2"
3934ae0e 5225 [(set (match_operand:SI 0 "s_register_operand")
5226 (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand"))))]
a50d7267 5227 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 5228 "
604f3a0a 5229")
5230
f544c6d2 5231;; Truncation insns
b11cae9e 5232
604f3a0a 5233(define_expand "truncdfsf2"
3934ae0e 5234 [(set (match_operand:SF 0 "s_register_operand")
604f3a0a 5235 (float_truncate:SF
3934ae0e 5236 (match_operand:DF 1 "s_register_operand")))]
a50d7267 5237 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 5238 ""
5239)
9b8516be 5240
539b44ee 5241;; DFmode to HFmode conversions on targets without a single-step hardware
5242;; instruction for it would have to go through SFmode. This is dangerous
5243;; as it introduces double rounding.
5244;;
5245;; Disable this pattern unless we are in an unsafe math mode, or we have
5246;; a single-step instruction.
5247
9b8516be 5248(define_expand "truncdfhf2"
3934ae0e 5249 [(set (match_operand:HF 0 "s_register_operand")
9b8516be 5250 (float_truncate:HF
3934ae0e 5251 (match_operand:DF 1 "s_register_operand")))]
539b44ee 5252 "(TARGET_EITHER && flag_unsafe_math_optimizations)
5253 || (TARGET_32BIT && TARGET_FP16_TO_DOUBLE)"
5254{
5255 /* We don't have a direct instruction for this, so we must be in
5256 an unsafe math mode, and going via SFmode. */
5257
5258 if (!(TARGET_32BIT && TARGET_FP16_TO_DOUBLE))
5259 {
5260 rtx op1;
5261 op1 = convert_to_mode (SFmode, operands[1], 0);
5262 op1 = convert_to_mode (HFmode, op1, 0);
5263 emit_move_insn (operands[0], op1);
5264 DONE;
5265 }
5266 /* Otherwise, we will pick this up as a single instruction with
5267 no intermediary rounding. */
5268}
9b8516be 5269)
b11cae9e 5270\f
9c08d1fa 5271;; Zero and sign extension instructions.
b11cae9e 5272
848e66ac 5273(define_insn "zero_extend<mode>di2"
6aa689e8 5274 [(set (match_operand:DI 0 "s_register_operand" "=w,r,?r,w")
6d97728e 5275 (zero_extend:DI (match_operand:QHSI 1 "<qhs_zextenddi_op>"
5276 "<qhs_zextenddi_cstr>")))]
848e66ac 5277 "TARGET_32BIT <qhs_zextenddi_cond>"
5278 "#"
6aa689e8 5279 [(set_attr "length" "8,4,8,8")
b6779ddc 5280 (set_attr "arch" "neon_for_64bits,*,*,avoid_neon_for_64bits")
848e66ac 5281 (set_attr "ce_count" "2")
efbb5e19 5282 (set_attr "predicable" "yes")
5283 (set_attr "type" "multiple,mov_reg,multiple,multiple")]
25f905c2 5284)
5285
848e66ac 5286(define_insn "extend<mode>di2"
6aa689e8 5287 [(set (match_operand:DI 0 "s_register_operand" "=w,r,?r,?r,w")
63d204a8 5288 (sign_extend:DI (match_operand:QHSI 1 "<qhs_extenddi_op>"
5289 "<qhs_extenddi_cstr>")))]
848e66ac 5290 "TARGET_32BIT <qhs_sextenddi_cond>"
5291 "#"
6aa689e8 5292 [(set_attr "length" "8,4,8,8,8")
848e66ac 5293 (set_attr "ce_count" "2")
5294 (set_attr "shift" "1")
8012d2c2 5295 (set_attr "predicable" "yes")
1b7da4ac 5296 (set_attr "arch" "neon_for_64bits,*,a,t,avoid_neon_for_64bits")
5297 (set_attr "type" "multiple,mov_reg,multiple,multiple,multiple")]
0d66636f 5298)
9c08d1fa 5299
848e66ac 5300;; Splits for all extensions to DImode
5301(define_split
5302 [(set (match_operand:DI 0 "s_register_operand" "")
5303 (zero_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
6aa689e8 5304 "TARGET_32BIT && reload_completed && !IS_VFP_REGNUM (REGNO (operands[0]))"
848e66ac 5305 [(set (match_dup 0) (match_dup 1))]
5306{
848e66ac 5307 rtx lo_part = gen_lowpart (SImode, operands[0]);
3754d046 5308 machine_mode src_mode = GET_MODE (operands[1]);
848e66ac 5309
5310 if (REG_P (operands[0])
5311 && !reg_overlap_mentioned_p (operands[0], operands[1]))
5312 emit_clobber (operands[0]);
5313 if (!REG_P (lo_part) || src_mode != SImode
5314 || !rtx_equal_p (lo_part, operands[1]))
5315 {
5316 if (src_mode == SImode)
5317 emit_move_insn (lo_part, operands[1]);
5318 else
d1f9b275 5319 emit_insn (gen_rtx_SET (lo_part,
848e66ac 5320 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
5321 operands[1] = lo_part;
5322 }
5323 operands[0] = gen_highpart (SImode, operands[0]);
5324 operands[1] = const0_rtx;
5325})
9c08d1fa 5326
848e66ac 5327(define_split
25f905c2 5328 [(set (match_operand:DI 0 "s_register_operand" "")
848e66ac 5329 (sign_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
6aa689e8 5330 "TARGET_32BIT && reload_completed && !IS_VFP_REGNUM (REGNO (operands[0]))"
848e66ac 5331 [(set (match_dup 0) (ashiftrt:SI (match_dup 1) (const_int 31)))]
5332{
5333 rtx lo_part = gen_lowpart (SImode, operands[0]);
3754d046 5334 machine_mode src_mode = GET_MODE (operands[1]);
25f905c2 5335
848e66ac 5336 if (REG_P (operands[0])
5337 && !reg_overlap_mentioned_p (operands[0], operands[1]))
5338 emit_clobber (operands[0]);
5339
5340 if (!REG_P (lo_part) || src_mode != SImode
5341 || !rtx_equal_p (lo_part, operands[1]))
5342 {
5343 if (src_mode == SImode)
5344 emit_move_insn (lo_part, operands[1]);
5345 else
d1f9b275 5346 emit_insn (gen_rtx_SET (lo_part,
848e66ac 5347 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
5348 operands[1] = lo_part;
5349 }
5350 operands[0] = gen_highpart (SImode, operands[0]);
5351})
9c08d1fa 5352
5353(define_expand "zero_extendhisi2"
3934ae0e 5354 [(set (match_operand:SI 0 "s_register_operand")
5355 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand")))]
cffb2a26 5356 "TARGET_EITHER"
ef51b8e1 5357{
5358 if (TARGET_ARM && !arm_arch4 && MEM_P (operands[1]))
f7fbdd4a 5359 {
ef51b8e1 5360 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
5361 DONE;
25f7a26e 5362 }
ef51b8e1 5363 if (!arm_arch6 && !MEM_P (operands[1]))
5364 {
5365 rtx t = gen_lowpart (SImode, operands[1]);
5366 rtx tmp = gen_reg_rtx (SImode);
5367 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
5368 emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (16)));
5369 DONE;
5370 }
5371})
9c08d1fa 5372
ef51b8e1 5373(define_split
b146458f 5374 [(set (match_operand:SI 0 "s_register_operand" "")
5375 (zero_extend:SI (match_operand:HI 1 "s_register_operand" "")))]
ef51b8e1 5376 "!TARGET_THUMB2 && !arm_arch6"
5377 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
5378 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 16)))]
5379{
5380 operands[2] = gen_lowpart (SImode, operands[1]);
5381})
5382
cffb2a26 5383(define_insn "*arm_zero_extendhisi2"
ef51b8e1 5384 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5385 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 5386 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 5387 "@
5388 #
3ef90e77 5389 ldrh%?\\t%0, %1"
d82e788e 5390 [(set_attr "type" "alu_shift_reg,load_byte")
848e66ac 5391 (set_attr "predicable" "yes")]
cffb2a26 5392)
f7fbdd4a 5393
a2cd141b 5394(define_insn "*arm_zero_extendhisi2_v6"
5395 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
e3f4ccee 5396 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,Uh")))]
a2cd141b 5397 "TARGET_ARM && arm_arch6"
5398 "@
5399 uxth%?\\t%0, %1
3ef90e77 5400 ldrh%?\\t%0, %1"
65f68e55 5401 [(set_attr "predicable" "yes")
6b6abc9c 5402 (set_attr "type" "extend,load_byte")]
a2cd141b 5403)
5404
5405(define_insn "*arm_zero_extendhisi2addsi"
5406 [(set (match_operand:SI 0 "s_register_operand" "=r")
5407 (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
5408 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 5409 "TARGET_INT_SIMD"
a2cd141b 5410 "uxtah%?\\t%0, %2, %1"
d82e788e 5411 [(set_attr "type" "alu_shift_reg")
8bdfd6ed 5412 (set_attr "predicable" "yes")]
a2cd141b 5413)
5414
87b22bf7 5415(define_expand "zero_extendqisi2"
3934ae0e 5416 [(set (match_operand:SI 0 "s_register_operand")
5417 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand")))]
cffb2a26 5418 "TARGET_EITHER"
ef51b8e1 5419{
0438d37f 5420 if (TARGET_ARM && !arm_arch6 && !MEM_P (operands[1]))
87b22bf7 5421 {
ef51b8e1 5422 emit_insn (gen_andsi3 (operands[0],
5423 gen_lowpart (SImode, operands[1]),
5424 GEN_INT (255)));
5425 DONE;
5426 }
5427 if (!arm_arch6 && !MEM_P (operands[1]))
5428 {
5429 rtx t = gen_lowpart (SImode, operands[1]);
5430 rtx tmp = gen_reg_rtx (SImode);
5431 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
5432 emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (24)));
5433 DONE;
5434 }
5435})
cffb2a26 5436
ef51b8e1 5437(define_split
b146458f 5438 [(set (match_operand:SI 0 "s_register_operand" "")
5439 (zero_extend:SI (match_operand:QI 1 "s_register_operand" "")))]
ef51b8e1 5440 "!arm_arch6"
5441 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
5442 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 24)))]
5443{
5444 operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
5445 if (TARGET_ARM)
5446 {
5447 emit_insn (gen_andsi3 (operands[0], operands[2], GEN_INT (255)));
87b22bf7 5448 DONE;
5449 }
ef51b8e1 5450})
9c08d1fa 5451
cffb2a26 5452(define_insn "*arm_zero_extendqisi2"
ef51b8e1 5453 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5454 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 5455 "TARGET_ARM && !arm_arch6"
ef51b8e1 5456 "@
5457 #
3ef90e77 5458 ldrb%?\\t%0, %1\\t%@ zero_extendqisi2"
ef51b8e1 5459 [(set_attr "length" "8,4")
d82e788e 5460 (set_attr "type" "alu_shift_reg,load_byte")
848e66ac 5461 (set_attr "predicable" "yes")]
cffb2a26 5462)
87b22bf7 5463
a2cd141b 5464(define_insn "*arm_zero_extendqisi2_v6"
5465 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
e3f4ccee 5466 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,Uh")))]
a2cd141b 5467 "TARGET_ARM && arm_arch6"
5468 "@
3ef90e77 5469 uxtb%?\\t%0, %1
5470 ldrb%?\\t%0, %1\\t%@ zero_extendqisi2"
6b6abc9c 5471 [(set_attr "type" "extend,load_byte")
848e66ac 5472 (set_attr "predicable" "yes")]
a2cd141b 5473)
5474
5475(define_insn "*arm_zero_extendqisi2addsi"
5476 [(set (match_operand:SI 0 "s_register_operand" "=r")
5477 (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
5478 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 5479 "TARGET_INT_SIMD"
a2cd141b 5480 "uxtab%?\\t%0, %2, %1"
5481 [(set_attr "predicable" "yes")
d82e788e 5482 (set_attr "type" "alu_shift_reg")]
a2cd141b 5483)
5484
87b22bf7 5485(define_split
5486 [(set (match_operand:SI 0 "s_register_operand" "")
5487 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
5488 (clobber (match_operand:SI 2 "s_register_operand" ""))]
0438d37f 5489 "TARGET_32BIT && (!MEM_P (operands[1])) && ! BYTES_BIG_ENDIAN"
87b22bf7 5490 [(set (match_dup 2) (match_dup 1))
5491 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
cffb2a26 5492 ""
5493)
9c08d1fa 5494
8a4d25d6 5495(define_split
5496 [(set (match_operand:SI 0 "s_register_operand" "")
5497 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 3)))
5498 (clobber (match_operand:SI 2 "s_register_operand" ""))]
0438d37f 5499 "TARGET_32BIT && (!MEM_P (operands[1])) && BYTES_BIG_ENDIAN"
8a4d25d6 5500 [(set (match_dup 2) (match_dup 1))
5501 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
5502 ""
5503)
5504
1c274529 5505
5506(define_split
5507 [(set (match_operand:SI 0 "s_register_operand" "")
9b23f0a7 5508 (IOR_XOR:SI (and:SI (ashift:SI
1c274529 5509 (match_operand:SI 1 "s_register_operand" "")
5510 (match_operand:SI 2 "const_int_operand" ""))
5511 (match_operand:SI 3 "const_int_operand" ""))
5512 (zero_extend:SI
5513 (match_operator 5 "subreg_lowpart_operator"
5514 [(match_operand:SI 4 "s_register_operand" "")]))))]
5515 "TARGET_32BIT
8c4e8755 5516 && (UINTVAL (operands[3])
1c274529 5517 == (GET_MODE_MASK (GET_MODE (operands[5]))
5518 & (GET_MODE_MASK (GET_MODE (operands[5]))
5519 << (INTVAL (operands[2])))))"
9b23f0a7 5520 [(set (match_dup 0) (IOR_XOR:SI (ashift:SI (match_dup 1) (match_dup 2))
1c274529 5521 (match_dup 4)))
5522 (set (match_dup 0) (zero_extend:SI (match_dup 5)))]
5523 "operands[5] = gen_lowpart (GET_MODE (operands[5]), operands[0]);"
5524)
5525
f7fbdd4a 5526(define_insn "*compareqi_eq0"
bd5b4116 5527 [(set (reg:CC_Z CC_REGNUM)
206ee9a2 5528 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
87b22bf7 5529 (const_int 0)))]
25f905c2 5530 "TARGET_32BIT"
596e5e8f 5531 "tst%?\\t%0, #255"
5532 [(set_attr "conds" "set")
d952d547 5533 (set_attr "predicable" "yes")
1b7da4ac 5534 (set_attr "type" "logic_imm")]
cffb2a26 5535)
b11cae9e 5536
b11cae9e 5537(define_expand "extendhisi2"
3934ae0e 5538 [(set (match_operand:SI 0 "s_register_operand")
5539 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand")))]
cffb2a26 5540 "TARGET_EITHER"
ef51b8e1 5541{
5542 if (TARGET_THUMB1)
5543 {
5544 emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1]));
5545 DONE;
5546 }
5547 if (MEM_P (operands[1]) && TARGET_ARM && !arm_arch4)
5548 {
5549 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
5550 DONE;
5551 }
ed29c566 5552
ef51b8e1 5553 if (!arm_arch6 && !MEM_P (operands[1]))
5554 {
5555 rtx t = gen_lowpart (SImode, operands[1]);
5556 rtx tmp = gen_reg_rtx (SImode);
5557 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
5558 emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (16)));
5559 DONE;
5560 }
5561})
cffb2a26 5562
ef51b8e1 5563(define_split
5564 [(parallel
5565 [(set (match_operand:SI 0 "register_operand" "")
5566 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))
5567 (clobber (match_scratch:SI 2 ""))])]
5568 "!arm_arch6"
5569 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
5570 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
5571{
5572 operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
5573})
25f7a26e 5574
25f905c2 5575;; This pattern will only be used when ldsh is not available
25f7a26e 5576(define_expand "extendhisi2_mem"
eab14235 5577 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 5578 (set (match_dup 3)
eab14235 5579 (zero_extend:SI (match_dup 7)))
25f7a26e 5580 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
5581 (set (match_operand:SI 0 "" "")
5582 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
cffb2a26 5583 "TARGET_ARM"
25f7a26e 5584 "
215b30b3 5585 {
5586 rtx mem1, mem2;
5587 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
5588
788fcce0 5589 mem1 = change_address (operands[1], QImode, addr);
29c05e22 5590 mem2 = change_address (operands[1], QImode,
5591 plus_constant (Pmode, addr, 1));
215b30b3 5592 operands[0] = gen_lowpart (SImode, operands[0]);
5593 operands[1] = mem1;
5594 operands[2] = gen_reg_rtx (SImode);
5595 operands[3] = gen_reg_rtx (SImode);
5596 operands[6] = gen_reg_rtx (SImode);
5597 operands[7] = mem2;
25f7a26e 5598
215b30b3 5599 if (BYTES_BIG_ENDIAN)
5600 {
5601 operands[4] = operands[2];
5602 operands[5] = operands[3];
5603 }
5604 else
5605 {
5606 operands[4] = operands[3];
5607 operands[5] = operands[2];
5608 }
5609 }"
5610)
b11cae9e 5611
ef51b8e1 5612(define_split
5613 [(set (match_operand:SI 0 "register_operand" "")
5614 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
5615 "!arm_arch6"
5616 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
5617 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
5618{
5619 operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
5620})
5621
a2cd141b 5622(define_insn "*arm_extendhisi2"
ef51b8e1 5623 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
e3f4ccee 5624 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,Uh")))]
a2cd141b 5625 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 5626 "@
5627 #
3ef90e77 5628 ldrsh%?\\t%0, %1"
ef51b8e1 5629 [(set_attr "length" "8,4")
d82e788e 5630 (set_attr "type" "alu_shift_reg,load_byte")
e3f4ccee 5631 (set_attr "predicable" "yes")]
cffb2a26 5632)
f7fbdd4a 5633
25f905c2 5634;; ??? Check Thumb-2 pool range
a2cd141b 5635(define_insn "*arm_extendhisi2_v6"
5636 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
e3f4ccee 5637 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,Uh")))]
25f905c2 5638 "TARGET_32BIT && arm_arch6"
a2cd141b 5639 "@
5640 sxth%?\\t%0, %1
3ef90e77 5641 ldrsh%?\\t%0, %1"
6b6abc9c 5642 [(set_attr "type" "extend,load_byte")
8bdfd6ed 5643 (set_attr "predicable" "yes")]
a2cd141b 5644)
5645
5646(define_insn "*arm_extendhisi2addsi"
5647 [(set (match_operand:SI 0 "s_register_operand" "=r")
5648 (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
5649 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 5650 "TARGET_INT_SIMD"
a2cd141b 5651 "sxtah%?\\t%0, %2, %1"
1b7da4ac 5652 [(set_attr "type" "alu_shift_reg")]
a2cd141b 5653)
5654
c8f69309 5655(define_expand "extendqihi2"
5656 [(set (match_dup 2)
3934ae0e 5657 (ashift:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op")
c8f69309 5658 (const_int 24)))
3934ae0e 5659 (set (match_operand:HI 0 "s_register_operand")
c8f69309 5660 (ashiftrt:SI (match_dup 2)
5661 (const_int 24)))]
cffb2a26 5662 "TARGET_ARM"
c8f69309 5663 "
215b30b3 5664 {
0438d37f 5665 if (arm_arch4 && MEM_P (operands[1]))
215b30b3 5666 {
d1f9b275 5667 emit_insn (gen_rtx_SET (operands[0],
215b30b3 5668 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
5669 DONE;
5670 }
5671 if (!s_register_operand (operands[1], QImode))
5672 operands[1] = copy_to_mode_reg (QImode, operands[1]);
5673 operands[0] = gen_lowpart (SImode, operands[0]);
5674 operands[1] = gen_lowpart (SImode, operands[1]);
5675 operands[2] = gen_reg_rtx (SImode);
5676 }"
5677)
f7fbdd4a 5678
25f905c2 5679(define_insn "*arm_extendqihi_insn"
b4e8a300 5680 [(set (match_operand:HI 0 "s_register_operand" "=r")
bed7d9a5 5681 (sign_extend:HI (match_operand:QI 1 "arm_extendqisi_mem_op" "Uq")))]
cffb2a26 5682 "TARGET_ARM && arm_arch4"
3ef90e77 5683 "ldrsb%?\\t%0, %1"
a2cd141b 5684 [(set_attr "type" "load_byte")
e3f4ccee 5685 (set_attr "predicable" "yes")]
cffb2a26 5686)
3fc2009e 5687
b11cae9e 5688(define_expand "extendqisi2"
3934ae0e 5689 [(set (match_operand:SI 0 "s_register_operand")
5690 (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op")))]
cffb2a26 5691 "TARGET_EITHER"
ef51b8e1 5692{
5693 if (!arm_arch4 && MEM_P (operands[1]))
5694 operands[1] = copy_to_mode_reg (QImode, operands[1]);
a2cd141b 5695
ef51b8e1 5696 if (!arm_arch6 && !MEM_P (operands[1]))
5697 {
5698 rtx t = gen_lowpart (SImode, operands[1]);
5699 rtx tmp = gen_reg_rtx (SImode);
5700 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
5701 emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (24)));
5702 DONE;
5703 }
5704})
a2cd141b 5705
ef51b8e1 5706(define_split
5707 [(set (match_operand:SI 0 "register_operand" "")
5708 (sign_extend:SI (match_operand:QI 1 "register_operand" "")))]
5709 "!arm_arch6"
5710 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
5711 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))]
5712{
5713 operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
5714})
f7fbdd4a 5715
a2cd141b 5716(define_insn "*arm_extendqisi"
ef51b8e1 5717 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5718 (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
a2cd141b 5719 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 5720 "@
5721 #
3ef90e77 5722 ldrsb%?\\t%0, %1"
ef51b8e1 5723 [(set_attr "length" "8,4")
d82e788e 5724 (set_attr "type" "alu_shift_reg,load_byte")
e3f4ccee 5725 (set_attr "predicable" "yes")]
cffb2a26 5726)
3fc2009e 5727
a2cd141b 5728(define_insn "*arm_extendqisi_v6"
5729 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
bed7d9a5 5730 (sign_extend:SI
5731 (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
a2cd141b 5732 "TARGET_ARM && arm_arch6"
b4e8a300 5733 "@
5734 sxtb%?\\t%0, %1
3ef90e77 5735 ldrsb%?\\t%0, %1"
6b6abc9c 5736 [(set_attr "type" "extend,load_byte")
e3f4ccee 5737 (set_attr "predicable" "yes")]
a2cd141b 5738)
5739
5740(define_insn "*arm_extendqisi2addsi"
5741 [(set (match_operand:SI 0 "s_register_operand" "=r")
5742 (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
5743 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 5744 "TARGET_INT_SIMD"
a2cd141b 5745 "sxtab%?\\t%0, %2, %1"
d82e788e 5746 [(set_attr "type" "alu_shift_reg")
8bdfd6ed 5747 (set_attr "predicable" "yes")]
a2cd141b 5748)
5749
caedf871 5750(define_expand "extendsfdf2"
3934ae0e 5751 [(set (match_operand:DF 0 "s_register_operand")
5752 (float_extend:DF (match_operand:SF 1 "s_register_operand")))]
a50d7267 5753 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
caedf871 5754 ""
5755)
9b8516be 5756
539b44ee 5757;; HFmode -> DFmode conversions where we don't have an instruction for it
5758;; must go through SFmode.
5759;;
5760;; This is always safe for an extend.
5761
9b8516be 5762(define_expand "extendhfdf2"
3934ae0e 5763 [(set (match_operand:DF 0 "s_register_operand")
5764 (float_extend:DF (match_operand:HF 1 "s_register_operand")))]
9b8516be 5765 "TARGET_EITHER"
539b44ee 5766{
5767 /* We don't have a direct instruction for this, so go via SFmode. */
5768 if (!(TARGET_32BIT && TARGET_FP16_TO_DOUBLE))
5769 {
5770 rtx op1;
5771 op1 = convert_to_mode (SFmode, operands[1], 0);
5772 op1 = convert_to_mode (DFmode, op1, 0);
5773 emit_insn (gen_movdf (operands[0], op1));
5774 DONE;
5775 }
5776 /* Otherwise, we're done producing RTL and will pick up the correct
5777 pattern to do this with one rounding-step in a single instruction. */
5778}
9b8516be 5779)
b11cae9e 5780\f
5781;; Move insns (including loads and stores)
5782
5783;; XXX Just some ideas about movti.
9c08d1fa 5784;; I don't think these are a good idea on the arm, there just aren't enough
5785;; registers
b11cae9e 5786;;(define_expand "loadti"
3934ae0e 5787;; [(set (match_operand:TI 0 "s_register_operand")
5788;; (mem:TI (match_operand:SI 1 "address_operand")))]
b11cae9e 5789;; "" "")
5790
5791;;(define_expand "storeti"
3934ae0e 5792;; [(set (mem:TI (match_operand:TI 0 "address_operand"))
5793;; (match_operand:TI 1 "s_register_operand"))]
b11cae9e 5794;; "" "")
5795
5796;;(define_expand "movti"
3934ae0e 5797;; [(set (match_operand:TI 0 "general_operand")
5798;; (match_operand:TI 1 "general_operand"))]
b11cae9e 5799;; ""
5800;; "
5801;;{
5802;; rtx insn;
5803;;
0438d37f 5804;; if (MEM_P (operands[0]) && MEM_P (operands[1]))
b11cae9e 5805;; operands[1] = copy_to_reg (operands[1]);
0438d37f 5806;; if (MEM_P (operands[0]))
b11cae9e 5807;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
0438d37f 5808;; else if (MEM_P (operands[1]))
b11cae9e 5809;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
5810;; else
5811;; FAIL;
5812;;
5813;; emit_insn (insn);
5814;; DONE;
5815;;}")
5816
a2f10574 5817;; Recognize garbage generated above.
b11cae9e 5818
5819;;(define_insn ""
5820;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
5821;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
5822;; ""
5823;; "*
5824;; {
5825;; register mem = (which_alternative < 3);
0d66636f 5826;; register const char *template;
b11cae9e 5827;;
5828;; operands[mem] = XEXP (operands[mem], 0);
5829;; switch (which_alternative)
5830;; {
5831;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
5832;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
5833;; case 2: template = \"ldmia\\t%1, %M0\"; break;
5834;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
5835;; case 4: template = \"stmia\\t%0!, %M1\"; break;
5836;; case 5: template = \"stmia\\t%0, %M1\"; break;
5837;; }
e2348bcb 5838;; output_asm_insn (template, operands);
5839;; return \"\";
b11cae9e 5840;; }")
5841
cffb2a26 5842(define_expand "movdi"
3934ae0e 5843 [(set (match_operand:DI 0 "general_operand")
5844 (match_operand:DI 1 "general_operand"))]
cffb2a26 5845 "TARGET_EITHER"
5846 "
e1ba4a27 5847 if (can_create_pseudo_p ())
cffb2a26 5848 {
0438d37f 5849 if (!REG_P (operands[0]))
b2778788 5850 operands[1] = force_reg (DImode, operands[1]);
cffb2a26 5851 }
6b97fdcc 5852 if (REG_P (operands[0]) && REGNO (operands[0]) <= LAST_ARM_REGNUM
b395382f 5853 && !targetm.hard_regno_mode_ok (REGNO (operands[0]), DImode))
4f0e25ca 5854 {
5855 /* Avoid LDRD's into an odd-numbered register pair in ARM state
5856 when expanding function calls. */
5857 gcc_assert (can_create_pseudo_p ());
5858 if (MEM_P (operands[1]) && MEM_VOLATILE_P (operands[1]))
5859 {
5860 /* Perform load into legal reg pair first, then move. */
5861 rtx reg = gen_reg_rtx (DImode);
5862 emit_insn (gen_movdi (reg, operands[1]));
5863 operands[1] = reg;
5864 }
5865 emit_move_insn (gen_lowpart (SImode, operands[0]),
5866 gen_lowpart (SImode, operands[1]));
5867 emit_move_insn (gen_highpart (SImode, operands[0]),
5868 gen_highpart (SImode, operands[1]));
5869 DONE;
5870 }
6b97fdcc 5871 else if (REG_P (operands[1]) && REGNO (operands[1]) <= LAST_ARM_REGNUM
b395382f 5872 && !targetm.hard_regno_mode_ok (REGNO (operands[1]), DImode))
4f0e25ca 5873 {
5874 /* Avoid STRD's from an odd-numbered register pair in ARM state
5875 when expanding function prologue. */
5876 gcc_assert (can_create_pseudo_p ());
5877 rtx split_dest = (MEM_P (operands[0]) && MEM_VOLATILE_P (operands[0]))
5878 ? gen_reg_rtx (DImode)
5879 : operands[0];
5880 emit_move_insn (gen_lowpart (SImode, split_dest),
5881 gen_lowpart (SImode, operands[1]));
5882 emit_move_insn (gen_highpart (SImode, split_dest),
5883 gen_highpart (SImode, operands[1]));
5884 if (split_dest != operands[0])
5885 emit_insn (gen_movdi (operands[0], split_dest));
5886 DONE;
5887 }
cffb2a26 5888 "
5889)
b11cae9e 5890
cffb2a26 5891(define_insn "*arm_movdi"
8f1c7041 5892 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, r, m")
5893 (match_operand:DI 1 "di_operand" "rDa,Db,Dc,mi,r"))]
cde1623a 5894 "TARGET_32BIT
d7216193 5895 && !(TARGET_HARD_FLOAT)
b2778788 5896 && !TARGET_IWMMXT
5897 && ( register_operand (operands[0], DImode)
5898 || register_operand (operands[1], DImode))"
b11cae9e 5899 "*
d51f92df 5900 switch (which_alternative)
5901 {
5902 case 0:
5903 case 1:
5904 case 2:
5905 return \"#\";
581f16e5 5906 case 3:
5907 /* Cannot load it directly, split to load it via MOV / MOVT. */
5908 if (!MEM_P (operands[1]) && arm_disable_literal_pool)
5909 return \"#\";
5910 /* Fall through. */
d51f92df 5911 default:
26ff80c0 5912 return output_move_double (operands, true, NULL);
d51f92df 5913 }
cffb2a26 5914 "
359a6e9f 5915 [(set_attr "length" "8,12,16,8,8")
9f2c2a36 5916 (set_attr "type" "multiple,multiple,multiple,load_8,store_8")
cde1623a 5917 (set_attr "arm_pool_range" "*,*,*,1020,*")
8848d797 5918 (set_attr "arm_neg_pool_range" "*,*,*,1004,*")
42e1de19 5919 (set_attr "thumb2_pool_range" "*,*,*,4094,*")
cde1623a 5920 (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
cffb2a26 5921)
5922
d51f92df 5923(define_split
5924 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
e6dd3afa 5925 (match_operand:ANY64 1 "immediate_operand" ""))]
25f905c2 5926 "TARGET_32BIT
d51f92df 5927 && reload_completed
a869c476 5928 && (arm_disable_literal_pool
5929 || (arm_const_double_inline_cost (operands[1])
5930 <= arm_max_const_double_inline_cost ()))"
d51f92df 5931 [(const_int 0)]
5932 "
5933 arm_split_constant (SET, SImode, curr_insn,
5934 INTVAL (gen_lowpart (SImode, operands[1])),
5935 gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
5936 arm_split_constant (SET, SImode, curr_insn,
5937 INTVAL (gen_highpart_mode (SImode,
5938 GET_MODE (operands[0]),
5939 operands[1])),
5940 gen_highpart (SImode, operands[0]), NULL_RTX, 0);
5941 DONE;
5942 "
5943)
5944
e5ba9289 5945; If optimizing for size, or if we have load delay slots, then
5946; we want to split the constant into two separate operations.
5947; In both cases this may split a trivial part into a single data op
5948; leaving a single complex constant to load. We can also get longer
5949; offsets in a LDR which means we get better chances of sharing the pool
5950; entries. Finally, we can normally do a better job of scheduling
5951; LDR instructions than we can with LDM.
5952; This pattern will only match if the one above did not.
5953(define_split
5954 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
5955 (match_operand:ANY64 1 "const_double_operand" ""))]
5956 "TARGET_ARM && reload_completed
5957 && arm_const_double_by_parts (operands[1])"
5958 [(set (match_dup 0) (match_dup 1))
5959 (set (match_dup 2) (match_dup 3))]
5960 "
5961 operands[2] = gen_highpart (SImode, operands[0]);
5962 operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
5963 operands[1]);
5964 operands[0] = gen_lowpart (SImode, operands[0]);
5965 operands[1] = gen_lowpart (SImode, operands[1]);
5966 "
5967)
5968
d51f92df 5969(define_split
5970 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
5971 (match_operand:ANY64 1 "arm_general_register_operand" ""))]
5972 "TARGET_EITHER && reload_completed"
5973 [(set (match_dup 0) (match_dup 1))
5974 (set (match_dup 2) (match_dup 3))]
5975 "
5976 operands[2] = gen_highpart (SImode, operands[0]);
5977 operands[3] = gen_highpart (SImode, operands[1]);
5978 operands[0] = gen_lowpart (SImode, operands[0]);
5979 operands[1] = gen_lowpart (SImode, operands[1]);
5980
5981 /* Handle a partial overlap. */
5982 if (rtx_equal_p (operands[0], operands[3]))
5983 {
5984 rtx tmp0 = operands[0];
5985 rtx tmp1 = operands[1];
5986
5987 operands[0] = operands[2];
5988 operands[1] = operands[3];
5989 operands[2] = tmp0;
5990 operands[3] = tmp1;
5991 }
5992 "
5993)
5994
a8a3b539 5995;; We can't actually do base+index doubleword loads if the index and
5996;; destination overlap. Split here so that we at least have chance to
5997;; schedule.
5998(define_split
5999 [(set (match_operand:DI 0 "s_register_operand" "")
6000 (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
6001 (match_operand:SI 2 "s_register_operand" ""))))]
6002 "TARGET_LDRD
6003 && reg_overlap_mentioned_p (operands[0], operands[1])
6004 && reg_overlap_mentioned_p (operands[0], operands[2])"
6005 [(set (match_dup 4)
6006 (plus:SI (match_dup 1)
6007 (match_dup 2)))
6008 (set (match_dup 0)
6009 (mem:DI (match_dup 4)))]
6010 "
6011 operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
6012 "
6013)
6014
9c08d1fa 6015(define_expand "movsi"
3934ae0e 6016 [(set (match_operand:SI 0 "general_operand")
6017 (match_operand:SI 1 "general_operand"))]
cffb2a26 6018 "TARGET_EITHER"
9c08d1fa 6019 "
befb0bac 6020 {
e348ff3e 6021 rtx base, offset, tmp;
6022
6e291830 6023 if (TARGET_32BIT || TARGET_HAVE_MOVT)
9c08d1fa 6024 {
674a8f0b 6025 /* Everything except mem = const or mem = mem can be done easily. */
0438d37f 6026 if (MEM_P (operands[0]))
cffb2a26 6027 operands[1] = force_reg (SImode, operands[1]);
a2cd141b 6028 if (arm_general_register_operand (operands[0], SImode)
0438d37f 6029 && CONST_INT_P (operands[1])
cffb2a26 6030 && !(const_ok_for_arm (INTVAL (operands[1]))
6031 || const_ok_for_arm (~INTVAL (operands[1]))))
6032 {
17202aa5 6033 if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[1]), SET))
6034 {
6035 emit_insn (gen_rtx_SET (operands[0], operands[1]));
6036 DONE;
6037 }
6038 else
6039 {
6040 arm_split_constant (SET, SImode, NULL_RTX,
6041 INTVAL (operands[1]), operands[0], NULL_RTX,
6042 optimize && can_create_pseudo_p ());
6043 DONE;
6044 }
cffb2a26 6045 }
6046 }
75612252 6047 else /* Target doesn't have MOVT... */
cffb2a26 6048 {
e1ba4a27 6049 if (can_create_pseudo_p ())
cffb2a26 6050 {
0438d37f 6051 if (!REG_P (operands[0]))
cffb2a26 6052 operands[1] = force_reg (SImode, operands[1]);
6053 }
9c08d1fa 6054 }
f655717d 6055
eeb22b66 6056 split_const (operands[1], &base, &offset);
6057 if (INTVAL (offset) != 0
6058 && targetm.cannot_force_const_mem (SImode, operands[1]))
e348ff3e 6059 {
eeb22b66 6060 tmp = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
6061 emit_move_insn (tmp, base);
6062 emit_insn (gen_addsi3 (operands[0], tmp, offset));
6063 DONE;
e348ff3e 6064 }
6065
eeb22b66 6066 tmp = can_create_pseudo_p () ? NULL_RTX : operands[0];
6067
f655717d 6068 /* Recognize the case where operand[1] is a reference to thread-local
eeb22b66 6069 data and load its address to a register. Offsets have been split off
6070 already. */
f655717d 6071 if (arm_tls_referenced_p (operands[1]))
eeb22b66 6072 operands[1] = legitimize_tls_address (operands[1], tmp);
f655717d 6073 else if (flag_pic
6074 && (CONSTANT_P (operands[1])
6075 || symbol_mentioned_p (operands[1])
6076 || label_mentioned_p (operands[1])))
eeb22b66 6077 operands[1] =
6078 legitimize_pic_address (operands[1], SImode, tmp, NULL_RTX, false);
befb0bac 6079 }
215b30b3 6080 "
6081)
9c08d1fa 6082
d0e6a121 6083;; The ARM LO_SUM and HIGH are backwards - HIGH sets the low bits, and
6084;; LO_SUM adds in the high bits. Fortunately these are opaque operations
6085;; so this does not matter.
6086(define_insn "*arm_movt"
417e5cc5 6087 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r")
6088 (lo_sum:SI (match_operand:SI 1 "nonimmediate_operand" "0,0")
6089 (match_operand:SI 2 "general_operand" "i,i")))]
60a48e7d 6090 "TARGET_HAVE_MOVT && arm_valid_symbolic_address_p (operands[2])"
417e5cc5 6091 "@
6092 movt%?\t%0, #:upper16:%c2
6093 movt\t%0, #:upper16:%c2"
6094 [(set_attr "arch" "32,v8mb")
6095 (set_attr "predicable" "yes")
1b7da4ac 6096 (set_attr "length" "4")
282b4c75 6097 (set_attr "type" "alu_sreg")]
d0e6a121 6098)
6099
cffb2a26 6100(define_insn "*arm_movsi_insn"
aaa37ad6 6101 [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,rk,m")
110eae03 6102 (match_operand:SI 1 "general_operand" "rk, I,K,j,mi,rk"))]
d7216193 6103 "TARGET_ARM && !TARGET_IWMMXT && !TARGET_HARD_FLOAT
cffb2a26 6104 && ( register_operand (operands[0], SImode)
6105 || register_operand (operands[1], SImode))"
f7fbdd4a 6106 "@
aaa37ad6 6107 mov%?\\t%0, %1
f7fbdd4a 6108 mov%?\\t%0, %1
6109 mvn%?\\t%0, #%B1
25f905c2 6110 movw%?\\t%0, %1
f7fbdd4a 6111 ldr%?\\t%0, %1
6112 str%?\\t%1, %0"
9f2c2a36 6113 [(set_attr "type" "mov_reg,mov_imm,mvn_imm,mov_imm,load_4,store_4")
0d66636f 6114 (set_attr "predicable" "yes")
100cd063 6115 (set_attr "arch" "*,*,*,v6t2,*,*")
aaa37ad6 6116 (set_attr "pool_range" "*,*,*,*,4096,*")
6117 (set_attr "neg_pool_range" "*,*,*,*,4084,*")]
cffb2a26 6118)
87b22bf7 6119
6120(define_split
a2cd141b 6121 [(set (match_operand:SI 0 "arm_general_register_operand" "")
87b22bf7 6122 (match_operand:SI 1 "const_int_operand" ""))]
6e291830 6123 "(TARGET_32BIT || TARGET_HAVE_MOVT)
215b30b3 6124 && (!(const_ok_for_arm (INTVAL (operands[1]))
6125 || const_ok_for_arm (~INTVAL (operands[1]))))"
87b22bf7 6126 [(clobber (const_int 0))]
6127 "
96f57e36 6128 arm_split_constant (SET, SImode, NULL_RTX,
6129 INTVAL (operands[1]), operands[0], NULL_RTX, 0);
87b22bf7 6130 DONE;
215b30b3 6131 "
6132)
9c08d1fa 6133
861033d5 6134;; A normal way to do (symbol + offset) requires three instructions at least
6135;; (depends on how big the offset is) as below:
6136;; movw r0, #:lower16:g
6137;; movw r0, #:upper16:g
6138;; adds r0, #4
6139;;
6140;; A better way would be:
6141;; movw r0, #:lower16:g+4
6142;; movw r0, #:upper16:g+4
6143;;
6144;; The limitation of this way is that the length of offset should be a 16-bit
6145;; signed value, because current assembler only supports REL type relocation for
6146;; such case. If the more powerful RELA type is supported in future, we should
6147;; update this pattern to go with better way.
6148(define_split
6149 [(set (match_operand:SI 0 "arm_general_register_operand" "")
6150 (const:SI (plus:SI (match_operand:SI 1 "general_operand" "")
6151 (match_operand:SI 2 "const_int_operand" ""))))]
60a48e7d 6152 "TARGET_THUMB
6153 && TARGET_HAVE_MOVT
861033d5 6154 && arm_disable_literal_pool
6155 && reload_completed
6156 && GET_CODE (operands[1]) == SYMBOL_REF"
6157 [(clobber (const_int 0))]
6158 "
6159 int offset = INTVAL (operands[2]);
6160
6161 if (offset < -0x8000 || offset > 0x7fff)
6162 {
6163 arm_emit_movpair (operands[0], operands[1]);
d1f9b275 6164 emit_insn (gen_rtx_SET (operands[0],
861033d5 6165 gen_rtx_PLUS (SImode, operands[0], operands[2])));
6166 }
6167 else
6168 {
6169 rtx op = gen_rtx_CONST (SImode,
6170 gen_rtx_PLUS (SImode, operands[1], operands[2]));
6171 arm_emit_movpair (operands[0], op);
6172 }
6173 "
6174)
6175
b8d5d078 6176;; Split symbol_refs at the later stage (after cprop), instead of generating
6177;; movt/movw pair directly at expand. Otherwise corresponding high_sum
6178;; and lo_sum would be merged back into memory load at cprop. However,
6179;; if the default is to prefer movt/movw rather than a load from the constant
6180;; pool, the performance is better.
6181(define_split
6182 [(set (match_operand:SI 0 "arm_general_register_operand" "")
6183 (match_operand:SI 1 "general_operand" ""))]
60a48e7d 6184 "TARGET_USE_MOVT && GET_CODE (operands[1]) == SYMBOL_REF
d022aaf3 6185 && !target_word_relocations
b8d5d078 6186 && !arm_tls_referenced_p (operands[1])"
6187 [(clobber (const_int 0))]
6188{
6189 arm_emit_movpair (operands[0], operands[1]);
6190 DONE;
6191})
6192
bc360af8 6193;; When generating pic, we need to load the symbol offset into a register.
6194;; So that the optimizer does not confuse this with a normal symbol load
6195;; we use an unspec. The offset will be loaded from a constant pool entry,
6196;; since that is the only type of relocation we can use.
cffb2a26 6197
bc360af8 6198;; Wrap calculation of the whole PIC address in a single pattern for the
6199;; benefit of optimizers, particularly, PRE and HOIST. Calculation of
6200;; a PIC address involves two loads from memory, so we want to CSE it
6201;; as often as possible.
6202;; This pattern will be split into one of the pic_load_addr_* patterns
6203;; and a move after GCSE optimizations.
6204;;
6205;; Note: Update arm.c: legitimize_pic_address() when changing this pattern.
6206(define_expand "calculate_pic_address"
3934ae0e 6207 [(set (match_operand:SI 0 "register_operand")
6208 (mem:SI (plus:SI (match_operand:SI 1 "register_operand")
94f8caca 6209 (unspec:SI [(match_operand:SI 2 "" "")]
6210 UNSPEC_PIC_SYM))))]
6211 "flag_pic"
6212)
6213
6214;; Split calculate_pic_address into pic_load_addr_* and a move.
6215(define_split
6216 [(set (match_operand:SI 0 "register_operand" "")
6217 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "")
6218 (unspec:SI [(match_operand:SI 2 "" "")]
6219 UNSPEC_PIC_SYM))))]
6220 "flag_pic"
6221 [(set (match_dup 3) (unspec:SI [(match_dup 2)] UNSPEC_PIC_SYM))
6222 (set (match_dup 0) (mem:SI (plus:SI (match_dup 1) (match_dup 3))))]
6223 "operands[3] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];"
6224)
6225
350ccca5 6226;; operand1 is the memory address to go into
6227;; pic_load_addr_32bit.
6228;; operand2 is the PIC label to be emitted
6229;; from pic_add_dot_plus_eight.
6230;; We do this to allow hoisting of the entire insn.
6231(define_insn_and_split "pic_load_addr_unified"
6232 [(set (match_operand:SI 0 "s_register_operand" "=r,r,l")
6233 (unspec:SI [(match_operand:SI 1 "" "mX,mX,mX")
6234 (match_operand:SI 2 "" "")]
6235 UNSPEC_PIC_UNIFIED))]
6236 "flag_pic"
6237 "#"
6238 "&& reload_completed"
6239 [(set (match_dup 0) (unspec:SI [(match_dup 1)] UNSPEC_PIC_SYM))
6240 (set (match_dup 0) (unspec:SI [(match_dup 0) (match_dup 3)
6241 (match_dup 2)] UNSPEC_PIC_BASE))]
6242 "operands[3] = TARGET_THUMB ? GEN_INT (4) : GEN_INT (8);"
9f2c2a36 6243 [(set_attr "type" "load_4,load_4,load_4")
42e1de19 6244 (set_attr "pool_range" "4096,4094,1022")
350ccca5 6245 (set_attr "neg_pool_range" "4084,0,0")
6246 (set_attr "arch" "a,t2,t1")
6247 (set_attr "length" "8,6,4")]
6248)
6249
67336bcf 6250;; The rather odd constraints on the following are to force reload to leave
6251;; the insn alone, and to force the minipool generation pass to then move
6252;; the GOT symbol to memory.
849170fd 6253
b3cd5f55 6254(define_insn "pic_load_addr_32bit"
849170fd 6255 [(set (match_operand:SI 0 "s_register_operand" "=r")
e1159bbe 6256 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
b3cd5f55 6257 "TARGET_32BIT && flag_pic"
67336bcf 6258 "ldr%?\\t%0, %1"
9f2c2a36 6259 [(set_attr "type" "load_4")
42e1de19 6260 (set (attr "pool_range")
6261 (if_then_else (eq_attr "is_thumb" "no")
6262 (const_int 4096)
6263 (const_int 4094)))
b3cd5f55 6264 (set (attr "neg_pool_range")
6265 (if_then_else (eq_attr "is_thumb" "no")
6266 (const_int 4084)
6267 (const_int 0)))]
8c4d8060 6268)
6269
25f905c2 6270(define_insn "pic_load_addr_thumb1"
8c4d8060 6271 [(set (match_operand:SI 0 "s_register_operand" "=l")
e1159bbe 6272 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
25f905c2 6273 "TARGET_THUMB1 && flag_pic"
8c4d8060 6274 "ldr\\t%0, %1"
9f2c2a36 6275 [(set_attr "type" "load_4")
42e1de19 6276 (set (attr "pool_range") (const_int 1018))]
cffb2a26 6277)
849170fd 6278
cffb2a26 6279(define_insn "pic_add_dot_plus_four"
15d5d060 6280 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 6281 (unspec:SI [(match_operand:SI 1 "register_operand" "0")
6282 (const_int 4)
beef0fb5 6283 (match_operand 2 "" "")]
6284 UNSPEC_PIC_BASE))]
b3cd5f55 6285 "TARGET_THUMB"
cffb2a26 6286 "*
6cdcb15c 6287 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
6288 INTVAL (operands[2]));
cffb2a26 6289 return \"add\\t%0, %|pc\";
6290 "
1b7da4ac 6291 [(set_attr "length" "2")
112eda6f 6292 (set_attr "type" "alu_sreg")]
cffb2a26 6293)
849170fd 6294
6295(define_insn "pic_add_dot_plus_eight"
15d5d060 6296 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 6297 (unspec:SI [(match_operand:SI 1 "register_operand" "r")
6298 (const_int 8)
beef0fb5 6299 (match_operand 2 "" "")]
6300 UNSPEC_PIC_BASE))]
f655717d 6301 "TARGET_ARM"
c4034607 6302 "*
6cdcb15c 6303 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
6304 INTVAL (operands[2]));
15d5d060 6305 return \"add%?\\t%0, %|pc, %1\";
cffb2a26 6306 "
1b7da4ac 6307 [(set_attr "predicable" "yes")
112eda6f 6308 (set_attr "type" "alu_sreg")]
cffb2a26 6309)
849170fd 6310
f655717d 6311(define_insn "tls_load_dot_plus_eight"
cc071db6 6312 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 6313 (mem:SI (unspec:SI [(match_operand:SI 1 "register_operand" "r")
6314 (const_int 8)
beef0fb5 6315 (match_operand 2 "" "")]
6316 UNSPEC_PIC_BASE)))]
f655717d 6317 "TARGET_ARM"
6318 "*
6cdcb15c 6319 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
6320 INTVAL (operands[2]));
f655717d 6321 return \"ldr%?\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_eight\";
6322 "
1b7da4ac 6323 [(set_attr "predicable" "yes")
9f2c2a36 6324 (set_attr "type" "load_4")]
f655717d 6325)
6326
6327;; PIC references to local variables can generate pic_add_dot_plus_eight
6328;; followed by a load. These sequences can be crunched down to
6329;; tls_load_dot_plus_eight by a peephole.
6330
6331(define_peephole2
c0c1fba5 6332 [(set (match_operand:SI 0 "register_operand" "")
6333 (unspec:SI [(match_operand:SI 3 "register_operand" "")
6334 (const_int 8)
6335 (match_operand 1 "" "")]
6336 UNSPEC_PIC_BASE))
2d05dfad 6337 (set (match_operand:SI 2 "arm_general_register_operand" "")
6338 (mem:SI (match_dup 0)))]
f655717d 6339 "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
c0c1fba5 6340 [(set (match_dup 2)
6341 (mem:SI (unspec:SI [(match_dup 3)
6342 (const_int 8)
6343 (match_dup 1)]
6344 UNSPEC_PIC_BASE)))]
f655717d 6345 ""
6346)
6347
bac7fc85 6348(define_insn "pic_offset_arm"
6349 [(set (match_operand:SI 0 "register_operand" "=r")
6350 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
6351 (unspec:SI [(match_operand:SI 2 "" "X")]
6352 UNSPEC_PIC_OFFSET))))]
6353 "TARGET_VXWORKS_RTP && TARGET_ARM && flag_pic"
6354 "ldr%?\\t%0, [%1,%2]"
9f2c2a36 6355 [(set_attr "type" "load_4")]
bac7fc85 6356)
6357
95373f08 6358(define_expand "builtin_setjmp_receiver"
6359 [(label_ref (match_operand 0 "" ""))]
6360 "flag_pic"
6361 "
6362{
b935b306 6363 /* r3 is clobbered by set/longjmp, so we can use it as a scratch
6364 register. */
2cb7d577 6365 if (arm_pic_register != INVALID_REGNUM)
f98495d9 6366 arm_load_pic_register (1UL << 3, NULL_RTX);
95373f08 6367 DONE;
6368}")
6369
9c08d1fa 6370;; If copying one reg to another we can set the condition codes according to
6371;; its value. Such a move is common after a return from subroutine and the
6372;; result is being tested against zero.
6373
f7fbdd4a 6374(define_insn "*movsi_compare0"
bd5b4116 6375 [(set (reg:CC CC_REGNUM)
cffb2a26 6376 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
6377 (const_int 0)))
6378 (set (match_operand:SI 0 "s_register_operand" "=r,r")
6379 (match_dup 1))]
25f905c2 6380 "TARGET_32BIT"
e2348bcb 6381 "@
40dbec34 6382 cmp%?\\t%0, #0
3ef90e77 6383 subs%?\\t%0, %1, #0"
65f68e55 6384 [(set_attr "conds" "set")
d82e788e 6385 (set_attr "type" "alus_imm,alus_imm")]
cffb2a26 6386)
b11cae9e 6387
b11cae9e 6388;; Subroutine to store a half word from a register into memory.
6389;; Operand 0 is the source register (HImode)
c8f69309 6390;; Operand 1 is the destination address in a register (SImode)
b11cae9e 6391
9c08d1fa 6392;; In both this routine and the next, we must be careful not to spill
01cc3b75 6393;; a memory address of reg+large_const into a separate PLUS insn, since this
9c08d1fa 6394;; can generate unrecognizable rtl.
6395
b11cae9e 6396(define_expand "storehi"
c8f69309 6397 [;; store the low byte
f082f1c4 6398 (set (match_operand 1 "" "") (match_dup 3))
b11cae9e 6399 ;; extract the high byte
c8f69309 6400 (set (match_dup 2)
6401 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
b11cae9e 6402 ;; store the high byte
787f8210 6403 (set (match_dup 4) (match_dup 5))]
cffb2a26 6404 "TARGET_ARM"
b11cae9e 6405 "
215b30b3 6406 {
537ffcfc 6407 rtx op1 = operands[1];
6408 rtx addr = XEXP (op1, 0);
215b30b3 6409 enum rtx_code code = GET_CODE (addr);
6410
0438d37f 6411 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
215b30b3 6412 || code == MINUS)
537ffcfc 6413 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
215b30b3 6414
537ffcfc 6415 operands[4] = adjust_address (op1, QImode, 1);
e513d163 6416 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 6417 operands[3] = gen_lowpart (QImode, operands[0]);
6418 operands[0] = gen_lowpart (SImode, operands[0]);
787f8210 6419 operands[2] = gen_reg_rtx (SImode);
6420 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 6421 }"
6422)
b11cae9e 6423
c7597b5d 6424(define_expand "storehi_bigend"
f082f1c4 6425 [(set (match_dup 4) (match_dup 3))
c7597b5d 6426 (set (match_dup 2)
6427 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
787f8210 6428 (set (match_operand 1 "" "") (match_dup 5))]
cffb2a26 6429 "TARGET_ARM"
b11cae9e 6430 "
215b30b3 6431 {
537ffcfc 6432 rtx op1 = operands[1];
6433 rtx addr = XEXP (op1, 0);
215b30b3 6434 enum rtx_code code = GET_CODE (addr);
6435
0438d37f 6436 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
215b30b3 6437 || code == MINUS)
537ffcfc 6438 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
215b30b3 6439
537ffcfc 6440 operands[4] = adjust_address (op1, QImode, 1);
e513d163 6441 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 6442 operands[3] = gen_lowpart (QImode, operands[0]);
6443 operands[0] = gen_lowpart (SImode, operands[0]);
6444 operands[2] = gen_reg_rtx (SImode);
787f8210 6445 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 6446 }"
6447)
c7597b5d 6448
6449;; Subroutine to store a half word integer constant into memory.
6450(define_expand "storeinthi"
f082f1c4 6451 [(set (match_operand 0 "" "")
787f8210 6452 (match_operand 1 "" ""))
9e8503e6 6453 (set (match_dup 3) (match_dup 2))]
cffb2a26 6454 "TARGET_ARM"
c7597b5d 6455 "
215b30b3 6456 {
6457 HOST_WIDE_INT value = INTVAL (operands[1]);
6458 rtx addr = XEXP (operands[0], 0);
537ffcfc 6459 rtx op0 = operands[0];
215b30b3 6460 enum rtx_code code = GET_CODE (addr);
c7597b5d 6461
0438d37f 6462 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
215b30b3 6463 || code == MINUS)
537ffcfc 6464 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
c7597b5d 6465
215b30b3 6466 operands[1] = gen_reg_rtx (SImode);
6467 if (BYTES_BIG_ENDIAN)
6468 {
6469 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
6470 if ((value & 255) == ((value >> 8) & 255))
6471 operands[2] = operands[1];
6472 else
6473 {
6474 operands[2] = gen_reg_rtx (SImode);
6475 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
6476 }
6477 }
6478 else
6479 {
6480 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
6481 if ((value & 255) == ((value >> 8) & 255))
6482 operands[2] = operands[1];
6483 else
6484 {
6485 operands[2] = gen_reg_rtx (SImode);
6486 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
6487 }
6488 }
c7597b5d 6489
537ffcfc 6490 operands[3] = adjust_address (op0, QImode, 1);
e513d163 6491 operands[0] = adjust_address (operands[0], QImode, 0);
9e8503e6 6492 operands[2] = gen_lowpart (QImode, operands[2]);
787f8210 6493 operands[1] = gen_lowpart (QImode, operands[1]);
215b30b3 6494 }"
6495)
b11cae9e 6496
f7fbdd4a 6497(define_expand "storehi_single_op"
3934ae0e 6498 [(set (match_operand:HI 0 "memory_operand")
6499 (match_operand:HI 1 "general_operand"))]
25f905c2 6500 "TARGET_32BIT && arm_arch4"
f7fbdd4a 6501 "
215b30b3 6502 if (!s_register_operand (operands[1], HImode))
f7fbdd4a 6503 operands[1] = copy_to_mode_reg (HImode, operands[1]);
215b30b3 6504 "
6505)
f7fbdd4a 6506
b11cae9e 6507(define_expand "movhi"
3934ae0e 6508 [(set (match_operand:HI 0 "general_operand")
6509 (match_operand:HI 1 "general_operand"))]
cffb2a26 6510 "TARGET_EITHER"
b11cae9e 6511 "
cffb2a26 6512 if (TARGET_ARM)
b11cae9e 6513 {
e1ba4a27 6514 if (can_create_pseudo_p ())
cffb2a26 6515 {
0438d37f 6516 if (MEM_P (operands[0]))
b11cae9e 6517 {
cffb2a26 6518 if (arm_arch4)
6519 {
6520 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
6521 DONE;
6522 }
0438d37f 6523 if (CONST_INT_P (operands[1]))
cffb2a26 6524 emit_insn (gen_storeinthi (operands[0], operands[1]));
c7597b5d 6525 else
cffb2a26 6526 {
0438d37f 6527 if (MEM_P (operands[1]))
cffb2a26 6528 operands[1] = force_reg (HImode, operands[1]);
6529 if (BYTES_BIG_ENDIAN)
6530 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
6531 else
6532 emit_insn (gen_storehi (operands[1], operands[0]));
6533 }
6534 DONE;
b11cae9e 6535 }
cffb2a26 6536 /* Sign extend a constant, and keep it in an SImode reg. */
0438d37f 6537 else if (CONST_INT_P (operands[1]))
9c08d1fa 6538 {
cffb2a26 6539 rtx reg = gen_reg_rtx (SImode);
6540 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
6541
6542 /* If the constant is already valid, leave it alone. */
215b30b3 6543 if (!const_ok_for_arm (val))
cffb2a26 6544 {
6545 /* If setting all the top bits will make the constant
6546 loadable in a single instruction, then set them.
6547 Otherwise, sign extend the number. */
6548
215b30b3 6549 if (const_ok_for_arm (~(val | ~0xffff)))
cffb2a26 6550 val |= ~0xffff;
6551 else if (val & 0x8000)
6552 val |= ~0xffff;
6553 }
6554
6555 emit_insn (gen_movsi (reg, GEN_INT (val)));
9e8503e6 6556 operands[1] = gen_lowpart (HImode, reg);
9c08d1fa 6557 }
e1ba4a27 6558 else if (arm_arch4 && optimize && can_create_pseudo_p ()
0438d37f 6559 && MEM_P (operands[1]))
0045890a 6560 {
6561 rtx reg = gen_reg_rtx (SImode);
6562
6563 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
6564 operands[1] = gen_lowpart (HImode, reg);
6565 }
215b30b3 6566 else if (!arm_arch4)
f7fbdd4a 6567 {
0438d37f 6568 if (MEM_P (operands[1]))
cffb2a26 6569 {
c1a66faf 6570 rtx base;
6571 rtx offset = const0_rtx;
6572 rtx reg = gen_reg_rtx (SImode);
6573
0438d37f 6574 if ((REG_P (base = XEXP (operands[1], 0))
c1a66faf 6575 || (GET_CODE (base) == PLUS
0438d37f 6576 && (CONST_INT_P (offset = XEXP (base, 1)))
c1a66faf 6577 && ((INTVAL(offset) & 1) != 1)
0438d37f 6578 && REG_P (base = XEXP (base, 0))))
c1a66faf 6579 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
206ee9a2 6580 {
8deb3959 6581 rtx new_rtx;
c1a66faf 6582
8deb3959 6583 new_rtx = widen_memory_access (operands[1], SImode,
6584 ((INTVAL (offset) & ~3)
6585 - INTVAL (offset)));
6586 emit_insn (gen_movsi (reg, new_rtx));
c1a66faf 6587 if (((INTVAL (offset) & 2) != 0)
6588 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
6589 {
6590 rtx reg2 = gen_reg_rtx (SImode);
6591
6592 emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
6593 reg = reg2;
6594 }
206ee9a2 6595 }
c1a66faf 6596 else
6597 emit_insn (gen_movhi_bytes (reg, operands[1]));
6598
6599 operands[1] = gen_lowpart (HImode, reg);
cffb2a26 6600 }
6601 }
6602 }
674a8f0b 6603 /* Handle loading a large integer during reload. */
0438d37f 6604 else if (CONST_INT_P (operands[1])
215b30b3 6605 && !const_ok_for_arm (INTVAL (operands[1]))
6606 && !const_ok_for_arm (~INTVAL (operands[1])))
cffb2a26 6607 {
6608 /* Writing a constant to memory needs a scratch, which should
6609 be handled with SECONDARY_RELOADs. */
0438d37f 6610 gcc_assert (REG_P (operands[0]));
cffb2a26 6611
6612 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
6613 emit_insn (gen_movsi (operands[0], operands[1]));
6614 DONE;
6615 }
6616 }
25f905c2 6617 else if (TARGET_THUMB2)
6618 {
6619 /* Thumb-2 can do everything except mem=mem and mem=const easily. */
e1ba4a27 6620 if (can_create_pseudo_p ())
25f905c2 6621 {
0438d37f 6622 if (!REG_P (operands[0]))
25f905c2 6623 operands[1] = force_reg (HImode, operands[1]);
6624 /* Zero extend a constant, and keep it in an SImode reg. */
0438d37f 6625 else if (CONST_INT_P (operands[1]))
25f905c2 6626 {
6627 rtx reg = gen_reg_rtx (SImode);
6628 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
6629
6630 emit_insn (gen_movsi (reg, GEN_INT (val)));
6631 operands[1] = gen_lowpart (HImode, reg);
6632 }
6633 }
6634 }
6635 else /* TARGET_THUMB1 */
cffb2a26 6636 {
e1ba4a27 6637 if (can_create_pseudo_p ())
cffb2a26 6638 {
0438d37f 6639 if (CONST_INT_P (operands[1]))
6cffc037 6640 {
6641 rtx reg = gen_reg_rtx (SImode);
6642
6643 emit_insn (gen_movsi (reg, operands[1]));
6644 operands[1] = gen_lowpart (HImode, reg);
6645 }
cffb2a26 6646
6647 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 6648 happen if we are passed a SP (never OK for HImode/QImode) or
bc409cb4 6649 virtual register (also rejected as illegitimate for HImode/QImode)
6650 relative address. */
cffb2a26 6651 /* ??? This should perhaps be fixed elsewhere, for instance, in
6652 fixup_stack_1, by checking for other kinds of invalid addresses,
6653 e.g. a bare reference to a virtual register. This may confuse the
6654 alpha though, which must handle this case differently. */
0438d37f 6655 if (MEM_P (operands[0])
215b30b3 6656 && !memory_address_p (GET_MODE (operands[0]),
6657 XEXP (operands[0], 0)))
537ffcfc 6658 operands[0]
6659 = replace_equiv_address (operands[0],
6660 copy_to_reg (XEXP (operands[0], 0)));
cffb2a26 6661
0438d37f 6662 if (MEM_P (operands[1])
215b30b3 6663 && !memory_address_p (GET_MODE (operands[1]),
6664 XEXP (operands[1], 0)))
537ffcfc 6665 operands[1]
6666 = replace_equiv_address (operands[1],
6667 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 6668
0438d37f 6669 if (MEM_P (operands[1]) && optimize > 0)
6cffc037 6670 {
6671 rtx reg = gen_reg_rtx (SImode);
6672
6673 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
6674 operands[1] = gen_lowpart (HImode, reg);
6675 }
6676
0438d37f 6677 if (MEM_P (operands[0]))
6cffc037 6678 operands[1] = force_reg (HImode, operands[1]);
cffb2a26 6679 }
0438d37f 6680 else if (CONST_INT_P (operands[1])
234f6557 6681 && !satisfies_constraint_I (operands[1]))
cffb2a26 6682 {
6cffc037 6683 /* Handle loading a large integer during reload. */
6684
cffb2a26 6685 /* Writing a constant to memory needs a scratch, which should
6686 be handled with SECONDARY_RELOADs. */
0438d37f 6687 gcc_assert (REG_P (operands[0]));
cffb2a26 6688
1a83b3ff 6689 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
cffb2a26 6690 emit_insn (gen_movsi (operands[0], operands[1]));
6691 DONE;
6692 }
b11cae9e 6693 }
cffb2a26 6694 "
6695)
6696
25f7a26e 6697(define_expand "movhi_bytes"
eab14235 6698 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 6699 (set (match_dup 3)
eab14235 6700 (zero_extend:SI (match_dup 6)))
25f7a26e 6701 (set (match_operand:SI 0 "" "")
6702 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
cffb2a26 6703 "TARGET_ARM"
25f7a26e 6704 "
215b30b3 6705 {
6706 rtx mem1, mem2;
6707 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
6708
788fcce0 6709 mem1 = change_address (operands[1], QImode, addr);
29c05e22 6710 mem2 = change_address (operands[1], QImode,
6711 plus_constant (Pmode, addr, 1));
215b30b3 6712 operands[0] = gen_lowpart (SImode, operands[0]);
6713 operands[1] = mem1;
6714 operands[2] = gen_reg_rtx (SImode);
6715 operands[3] = gen_reg_rtx (SImode);
6716 operands[6] = mem2;
25f7a26e 6717
215b30b3 6718 if (BYTES_BIG_ENDIAN)
6719 {
6720 operands[4] = operands[2];
6721 operands[5] = operands[3];
6722 }
6723 else
6724 {
6725 operands[4] = operands[3];
6726 operands[5] = operands[2];
6727 }
6728 }"
6729)
25f7a26e 6730
c7597b5d 6731(define_expand "movhi_bigend"
6732 [(set (match_dup 2)
3934ae0e 6733 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand") 0)
c7597b5d 6734 (const_int 16)))
6735 (set (match_dup 3)
6736 (ashiftrt:SI (match_dup 2) (const_int 16)))
3934ae0e 6737 (set (match_operand:HI 0 "s_register_operand")
787f8210 6738 (match_dup 4))]
cffb2a26 6739 "TARGET_ARM"
c7597b5d 6740 "
6741 operands[2] = gen_reg_rtx (SImode);
6742 operands[3] = gen_reg_rtx (SImode);
787f8210 6743 operands[4] = gen_lowpart (HImode, operands[3]);
215b30b3 6744 "
6745)
b11cae9e 6746
a2f10574 6747;; Pattern to recognize insn generated default case above
f7fbdd4a 6748(define_insn "*movhi_insn_arch4"
e4585731 6749 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r,m,r")
6750 (match_operand:HI 1 "general_operand" "rIk,K,n,r,mi"))]
cffb2a26 6751 "TARGET_ARM
d7216193 6752 && arm_arch4 && !TARGET_HARD_FLOAT
85e02ccb 6753 && (register_operand (operands[0], HImode)
6754 || register_operand (operands[1], HImode))"
f7fbdd4a 6755 "@
6756 mov%?\\t%0, %1\\t%@ movhi
6757 mvn%?\\t%0, #%B1\\t%@ movhi
b1c1a101 6758 movw%?\\t%0, %L1\\t%@ movhi
3ef90e77 6759 strh%?\\t%1, %0\\t%@ movhi
6760 ldrh%?\\t%0, %1\\t%@ movhi"
65f68e55 6761 [(set_attr "predicable" "yes")
e4585731 6762 (set_attr "pool_range" "*,*,*,*,256")
6763 (set_attr "neg_pool_range" "*,*,*,*,244")
6764 (set_attr "arch" "*,*,v6t2,*,*")
65f68e55 6765 (set_attr_alternative "type"
6766 [(if_then_else (match_operand 1 "const_int_operand" "")
1aed5204 6767 (const_string "mov_imm" )
6768 (const_string "mov_reg"))
6769 (const_string "mvn_imm")
e4585731 6770 (const_string "mov_imm")
9f2c2a36 6771 (const_string "store_4")
6772 (const_string "load_4")])]
cffb2a26 6773)
f7fbdd4a 6774
f7fbdd4a 6775(define_insn "*movhi_bytes"
65f68e55 6776 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
5fd254ed 6777 (match_operand:HI 1 "arm_rhs_operand" "I,rk,K"))]
d7216193 6778 "TARGET_ARM && !TARGET_HARD_FLOAT"
25f7a26e 6779 "@
65f68e55 6780 mov%?\\t%0, %1\\t%@ movhi
25f7a26e 6781 mov%?\\t%0, %1\\t%@ movhi
0d66636f 6782 mvn%?\\t%0, #%B1\\t%@ movhi"
d2a518d1 6783 [(set_attr "predicable" "yes")
1aed5204 6784 (set_attr "type" "mov_imm,mov_reg,mvn_imm")]
0d66636f 6785)
837bb76e 6786
bc5c7e08 6787;; We use a DImode scratch because we may occasionally need an additional
6788;; temporary if the address isn't offsettable -- push_reload doesn't seem
6789;; to take any notice of the "o" constraints on reload_memory_operand operand.
3934ae0e 6790;; The reload_in<m> and reload_out<m> patterns require special constraints
6791;; to be correctly handled in default_secondary_reload function.
d3373b54 6792(define_expand "reload_outhi"
cffb2a26 6793 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
215b30b3 6794 (match_operand:HI 1 "s_register_operand" "r")
6795 (match_operand:DI 2 "s_register_operand" "=&l")])]
cffb2a26 6796 "TARGET_EITHER"
6797 "if (TARGET_ARM)
6798 arm_reload_out_hi (operands);
6799 else
6800 thumb_reload_out_hi (operands);
d3373b54 6801 DONE;
cffb2a26 6802 "
6803)
d3373b54 6804
25f7a26e 6805(define_expand "reload_inhi"
6806 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
cffb2a26 6807 (match_operand:HI 1 "arm_reload_memory_operand" "o")
bc5c7e08 6808 (match_operand:DI 2 "s_register_operand" "=&r")])]
c1a66faf 6809 "TARGET_EITHER"
25f7a26e 6810 "
cffb2a26 6811 if (TARGET_ARM)
6812 arm_reload_in_hi (operands);
6813 else
6814 thumb_reload_out_hi (operands);
25f7a26e 6815 DONE;
6816")
6817
9c08d1fa 6818(define_expand "movqi"
3934ae0e 6819 [(set (match_operand:QI 0 "general_operand")
6820 (match_operand:QI 1 "general_operand"))]
cffb2a26 6821 "TARGET_EITHER"
9c08d1fa 6822 "
6cffc037 6823 /* Everything except mem = const or mem = mem can be done easily */
0045890a 6824
e1ba4a27 6825 if (can_create_pseudo_p ())
cffb2a26 6826 {
0438d37f 6827 if (CONST_INT_P (operands[1]))
6cffc037 6828 {
6829 rtx reg = gen_reg_rtx (SImode);
6830
03770691 6831 /* For thumb we want an unsigned immediate, then we are more likely
6832 to be able to use a movs insn. */
6833 if (TARGET_THUMB)
6834 operands[1] = GEN_INT (INTVAL (operands[1]) & 255);
6835
6cffc037 6836 emit_insn (gen_movsi (reg, operands[1]));
6837 operands[1] = gen_lowpart (QImode, reg);
6838 }
cffb2a26 6839
6cffc037 6840 if (TARGET_THUMB)
6841 {
cffb2a26 6842 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 6843 happen if we are passed a SP (never OK for HImode/QImode) or
bc409cb4 6844 virtual register (also rejected as illegitimate for HImode/QImode)
6845 relative address. */
cffb2a26 6846 /* ??? This should perhaps be fixed elsewhere, for instance, in
6847 fixup_stack_1, by checking for other kinds of invalid addresses,
6848 e.g. a bare reference to a virtual register. This may confuse the
6849 alpha though, which must handle this case differently. */
0438d37f 6850 if (MEM_P (operands[0])
215b30b3 6851 && !memory_address_p (GET_MODE (operands[0]),
cffb2a26 6852 XEXP (operands[0], 0)))
537ffcfc 6853 operands[0]
6854 = replace_equiv_address (operands[0],
6855 copy_to_reg (XEXP (operands[0], 0)));
0438d37f 6856 if (MEM_P (operands[1])
215b30b3 6857 && !memory_address_p (GET_MODE (operands[1]),
cffb2a26 6858 XEXP (operands[1], 0)))
537ffcfc 6859 operands[1]
6860 = replace_equiv_address (operands[1],
6861 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 6862 }
6863
0438d37f 6864 if (MEM_P (operands[1]) && optimize > 0)
6cffc037 6865 {
6866 rtx reg = gen_reg_rtx (SImode);
6867
6868 emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
6869 operands[1] = gen_lowpart (QImode, reg);
6870 }
6871
0438d37f 6872 if (MEM_P (operands[0]))
6cffc037 6873 operands[1] = force_reg (QImode, operands[1]);
6874 }
6875 else if (TARGET_THUMB
0438d37f 6876 && CONST_INT_P (operands[1])
234f6557 6877 && !satisfies_constraint_I (operands[1]))
6cffc037 6878 {
674a8f0b 6879 /* Handle loading a large integer during reload. */
cffb2a26 6880
6cffc037 6881 /* Writing a constant to memory needs a scratch, which should
6882 be handled with SECONDARY_RELOADs. */
0438d37f 6883 gcc_assert (REG_P (operands[0]));
6cffc037 6884
6885 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
6886 emit_insn (gen_movsi (operands[0], operands[1]));
6887 DONE;
cffb2a26 6888 }
6889 "
6890)
b11cae9e 6891
cffb2a26 6892(define_insn "*arm_movqi_insn"
fd711051 6893 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,l,r,l,Uu,r,m")
490f62ca 6894 (match_operand:QI 1 "general_operand" "rk,rk,I,Py,K,Uu,l,Uh,r"))]
25f905c2 6895 "TARGET_32BIT
cffb2a26 6896 && ( register_operand (operands[0], QImode)
6897 || register_operand (operands[1], QImode))"
5565501b 6898 "@
fd711051 6899 mov%?\\t%0, %1
6900 mov%?\\t%0, %1
65f68e55 6901 mov%?\\t%0, %1
5565501b 6902 mov%?\\t%0, %1
6903 mvn%?\\t%0, #%B1
3ef90e77 6904 ldrb%?\\t%0, %1
6905 strb%?\\t%1, %0
6906 ldrb%?\\t%0, %1
6907 strb%?\\t%1, %0"
9f2c2a36 6908 [(set_attr "type" "mov_reg,mov_reg,mov_imm,mov_imm,mvn_imm,load_4,store_4,load_4,store_4")
a54e3e7b 6909 (set_attr "predicable" "yes")
5233bf6a 6910 (set_attr "predicable_short_it" "yes,yes,no,yes,no,no,no,no,no")
fd711051 6911 (set_attr "arch" "t2,any,any,t2,any,t2,t2,any,any")
6912 (set_attr "length" "2,4,4,2,4,2,2,4,4")]
cffb2a26 6913)
6914
9b8516be 6915;; HFmode moves
6916(define_expand "movhf"
3934ae0e 6917 [(set (match_operand:HF 0 "general_operand")
6918 (match_operand:HF 1 "general_operand"))]
9b8516be 6919 "TARGET_EITHER"
6920 "
6921 if (TARGET_32BIT)
6922 {
0438d37f 6923 if (MEM_P (operands[0]))
9b8516be 6924 operands[1] = force_reg (HFmode, operands[1]);
6925 }
6926 else /* TARGET_THUMB1 */
6927 {
6928 if (can_create_pseudo_p ())
6929 {
0438d37f 6930 if (!REG_P (operands[0]))
9b8516be 6931 operands[1] = force_reg (HFmode, operands[1]);
6932 }
6933 }
6934 "
6935)
6936
6937(define_insn "*arm32_movhf"
6938 [(set (match_operand:HF 0 "nonimmediate_operand" "=r,m,r,r")
6939 (match_operand:HF 1 "general_operand" " m,r,r,F"))]
d7216193 6940 "TARGET_32BIT && !TARGET_HARD_FLOAT
9b8516be 6941 && ( s_register_operand (operands[0], HFmode)
6942 || s_register_operand (operands[1], HFmode))"
6943 "*
6944 switch (which_alternative)
6945 {
6946 case 0: /* ARM register from memory */
3ef90e77 6947 return \"ldrh%?\\t%0, %1\\t%@ __fp16\";
9b8516be 6948 case 1: /* memory from ARM register */
3ef90e77 6949 return \"strh%?\\t%1, %0\\t%@ __fp16\";
9b8516be 6950 case 2: /* ARM register from ARM register */
6951 return \"mov%?\\t%0, %1\\t%@ __fp16\";
6952 case 3: /* ARM register from constant */
6953 {
9b8516be 6954 long bits;
6955 rtx ops[4];
6956
945f7b03 6957 bits = real_to_target (NULL, CONST_DOUBLE_REAL_VALUE (operands[1]),
6958 HFmode);
9b8516be 6959 ops[0] = operands[0];
6960 ops[1] = GEN_INT (bits);
6961 ops[2] = GEN_INT (bits & 0xff00);
6962 ops[3] = GEN_INT (bits & 0x00ff);
6963
6964 if (arm_arch_thumb2)
6965 output_asm_insn (\"movw%?\\t%0, %1\", ops);
6966 else
6967 output_asm_insn (\"mov%?\\t%0, %2\;orr%?\\t%0, %0, %3\", ops);
6968 return \"\";
6969 }
6970 default:
6971 gcc_unreachable ();
6972 }
6973 "
6974 [(set_attr "conds" "unconditional")
9f2c2a36 6975 (set_attr "type" "load_4,store_4,mov_reg,multiple")
9b8516be 6976 (set_attr "length" "4,4,4,8")
8bdfd6ed 6977 (set_attr "predicable" "yes")]
9b8516be 6978)
6979
87b22bf7 6980(define_expand "movsf"
3934ae0e 6981 [(set (match_operand:SF 0 "general_operand")
6982 (match_operand:SF 1 "general_operand"))]
cffb2a26 6983 "TARGET_EITHER"
87b22bf7 6984 "
25f905c2 6985 if (TARGET_32BIT)
cffb2a26 6986 {
0438d37f 6987 if (MEM_P (operands[0]))
cffb2a26 6988 operands[1] = force_reg (SFmode, operands[1]);
6989 }
25f905c2 6990 else /* TARGET_THUMB1 */
cffb2a26 6991 {
e1ba4a27 6992 if (can_create_pseudo_p ())
cffb2a26 6993 {
0438d37f 6994 if (!REG_P (operands[0]))
cffb2a26 6995 operands[1] = force_reg (SFmode, operands[1]);
6996 }
6997 }
581f16e5 6998
6999 /* Cannot load it directly, generate a load with clobber so that it can be
7000 loaded via GPR with MOV / MOVT. */
7001 if (arm_disable_literal_pool
7002 && (REG_P (operands[0]) || SUBREG_P (operands[0]))
7003 && CONST_DOUBLE_P (operands[1])
7004 && TARGET_HARD_FLOAT
7005 && !vfp3_const_double_rtx (operands[1]))
7006 {
7007 rtx clobreg = gen_reg_rtx (SFmode);
7008 emit_insn (gen_no_literal_pool_sf_immediate (operands[0], operands[1],
7009 clobreg));
7010 DONE;
7011 }
cffb2a26 7012 "
7013)
7014
03d440a6 7015;; Transform a floating-point move of a constant into a core register into
7016;; an SImode operation.
cffb2a26 7017(define_split
03d440a6 7018 [(set (match_operand:SF 0 "arm_general_register_operand" "")
cffb2a26 7019 (match_operand:SF 1 "immediate_operand" ""))]
339034d0 7020 "TARGET_EITHER
cffb2a26 7021 && reload_completed
0438d37f 7022 && CONST_DOUBLE_P (operands[1])"
cffb2a26 7023 [(set (match_dup 2) (match_dup 3))]
7024 "
7025 operands[2] = gen_lowpart (SImode, operands[0]);
7026 operands[3] = gen_lowpart (SImode, operands[1]);
7027 if (operands[2] == 0 || operands[3] == 0)
7028 FAIL;
215b30b3 7029 "
7030)
87b22bf7 7031
cffb2a26 7032(define_insn "*arm_movsf_soft_insn"
7033 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
7034 (match_operand:SF 1 "general_operand" "r,mE,r"))]
cde1623a 7035 "TARGET_32BIT
cffb2a26 7036 && TARGET_SOFT_FLOAT
0438d37f 7037 && (!MEM_P (operands[0])
215b30b3 7038 || register_operand (operands[1], SFmode))"
581f16e5 7039{
7040 switch (which_alternative)
7041 {
7042 case 0: return \"mov%?\\t%0, %1\";
7043 case 1:
7044 /* Cannot load it directly, split to load it via MOV / MOVT. */
7045 if (!MEM_P (operands[1]) && arm_disable_literal_pool)
7046 return \"#\";
7047 return \"ldr%?\\t%0, %1\\t%@ float\";
7048 case 2: return \"str%?\\t%1, %0\\t%@ float\";
7049 default: gcc_unreachable ();
7050 }
7051}
cde1623a 7052 [(set_attr "predicable" "yes")
9f2c2a36 7053 (set_attr "type" "mov_reg,load_4,store_4")
42e1de19 7054 (set_attr "arm_pool_range" "*,4096,*")
7055 (set_attr "thumb2_pool_range" "*,4094,*")
cde1623a 7056 (set_attr "arm_neg_pool_range" "*,4084,*")
7057 (set_attr "thumb2_neg_pool_range" "*,0,*")]
cffb2a26 7058)
7059
581f16e5 7060;; Splitter for the above.
7061(define_split
7062 [(set (match_operand:SF 0 "s_register_operand")
7063 (match_operand:SF 1 "const_double_operand"))]
7064 "arm_disable_literal_pool && TARGET_SOFT_FLOAT"
7065 [(const_int 0)]
7066{
7067 long buf;
7068 real_to_target (&buf, CONST_DOUBLE_REAL_VALUE (operands[1]), SFmode);
7069 rtx cst = gen_int_mode (buf, SImode);
7070 emit_move_insn (simplify_gen_subreg (SImode, operands[0], SFmode, 0), cst);
7071 DONE;
7072}
7073)
7074
9c08d1fa 7075(define_expand "movdf"
3934ae0e 7076 [(set (match_operand:DF 0 "general_operand")
7077 (match_operand:DF 1 "general_operand"))]
cffb2a26 7078 "TARGET_EITHER"
9c08d1fa 7079 "
25f905c2 7080 if (TARGET_32BIT)
cffb2a26 7081 {
0438d37f 7082 if (MEM_P (operands[0]))
cffb2a26 7083 operands[1] = force_reg (DFmode, operands[1]);
7084 }
7085 else /* TARGET_THUMB */
7086 {
e1ba4a27 7087 if (can_create_pseudo_p ())
cffb2a26 7088 {
0438d37f 7089 if (!REG_P (operands[0]))
cffb2a26 7090 operands[1] = force_reg (DFmode, operands[1]);
7091 }
7092 }
581f16e5 7093
7094 /* Cannot load it directly, generate a load with clobber so that it can be
7095 loaded via GPR with MOV / MOVT. */
7096 if (arm_disable_literal_pool
7097 && (REG_P (operands[0]) || SUBREG_P (operands[0]))
7098 && CONSTANT_P (operands[1])
7099 && TARGET_HARD_FLOAT
7100 && !arm_const_double_rtx (operands[1])
7101 && !(TARGET_VFP_DOUBLE && vfp3_const_double_rtx (operands[1])))
7102 {
7103 rtx clobreg = gen_reg_rtx (DFmode);
7104 emit_insn (gen_no_literal_pool_df_immediate (operands[0], operands[1],
7105 clobreg));
7106 DONE;
7107 }
cffb2a26 7108 "
7109)
b11cae9e 7110
9c08d1fa 7111;; Reloading a df mode value stored in integer regs to memory can require a
7112;; scratch reg.
3934ae0e 7113;; Another reload_out<m> pattern that requires special constraints.
9c08d1fa 7114(define_expand "reload_outdf"
cffb2a26 7115 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
87b22bf7 7116 (match_operand:DF 1 "s_register_operand" "r")
7117 (match_operand:SI 2 "s_register_operand" "=&r")]
06adefdc 7118 "TARGET_THUMB2"
87b22bf7 7119 "
215b30b3 7120 {
7121 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
f7fbdd4a 7122
215b30b3 7123 if (code == REG)
7124 operands[2] = XEXP (operands[0], 0);
7125 else if (code == POST_INC || code == PRE_DEC)
7126 {
7127 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
7128 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
7129 emit_insn (gen_movdi (operands[0], operands[1]));
7130 DONE;
7131 }
7132 else if (code == PRE_INC)
7133 {
7134 rtx reg = XEXP (XEXP (operands[0], 0), 0);
f7fbdd4a 7135
215b30b3 7136 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
7137 operands[2] = reg;
7138 }
7139 else if (code == POST_DEC)
7140 operands[2] = XEXP (XEXP (operands[0], 0), 0);
7141 else
7142 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
7143 XEXP (XEXP (operands[0], 0), 1)));
f7fbdd4a 7144
d1f9b275 7145 emit_insn (gen_rtx_SET (replace_equiv_address (operands[0], operands[2]),
215b30b3 7146 operands[1]));
f7fbdd4a 7147
215b30b3 7148 if (code == POST_DEC)
7149 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
7150
7151 DONE;
7152 }"
7153)
9c08d1fa 7154
9a1112d7 7155(define_insn "*movdf_soft_insn"
8f1c7041 7156 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,r,m")
7157 (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))]
cde1623a 7158 "TARGET_32BIT && TARGET_SOFT_FLOAT
b2778788 7159 && ( register_operand (operands[0], DFmode)
7160 || register_operand (operands[1], DFmode))"
d51f92df 7161 "*
7162 switch (which_alternative)
7163 {
7164 case 0:
7165 case 1:
7166 case 2:
7167 return \"#\";
581f16e5 7168 case 3:
7169 /* Cannot load it directly, split to load it via MOV / MOVT. */
7170 if (!MEM_P (operands[1]) && arm_disable_literal_pool)
7171 return \"#\";
7172 /* Fall through. */
d51f92df 7173 default:
26ff80c0 7174 return output_move_double (operands, true, NULL);
d51f92df 7175 }
7176 "
359a6e9f 7177 [(set_attr "length" "8,12,16,8,8")
9f2c2a36 7178 (set_attr "type" "multiple,multiple,multiple,load_8,store_8")
42e1de19 7179 (set_attr "arm_pool_range" "*,*,*,1020,*")
7180 (set_attr "thumb2_pool_range" "*,*,*,1018,*")
8848d797 7181 (set_attr "arm_neg_pool_range" "*,*,*,1004,*")
cde1623a 7182 (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
cffb2a26 7183)
581f16e5 7184
7185;; Splitter for the above.
7186(define_split
7187 [(set (match_operand:DF 0 "s_register_operand")
7188 (match_operand:DF 1 "const_double_operand"))]
7189 "arm_disable_literal_pool && TARGET_SOFT_FLOAT"
7190 [(const_int 0)]
7191{
7192 long buf[2];
7193 int order = BYTES_BIG_ENDIAN ? 1 : 0;
7194 real_to_target (buf, CONST_DOUBLE_REAL_VALUE (operands[1]), DFmode);
7195 unsigned HOST_WIDE_INT ival = zext_hwi (buf[order], 32);
7196 ival |= (zext_hwi (buf[1 - order], 32) << 32);
7197 rtx cst = gen_int_mode (ival, DImode);
7198 emit_move_insn (simplify_gen_subreg (DImode, operands[0], DFmode, 0), cst);
7199 DONE;
7200}
7201)
b11cae9e 7202\f
b11cae9e 7203
9c08d1fa 7204;; load- and store-multiple insns
7205;; The arm can load/store any set of registers, provided that they are in
320ea44d 7206;; ascending order, but these expanders assume a contiguous set.
b11cae9e 7207
9c08d1fa 7208(define_expand "load_multiple"
7209 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
7210 (match_operand:SI 1 "" ""))
7211 (use (match_operand:SI 2 "" ""))])]
25f905c2 7212 "TARGET_32BIT"
9580c25f 7213{
7214 HOST_WIDE_INT offset = 0;
7215
bd5b4116 7216 /* Support only fixed point registers. */
0438d37f 7217 if (!CONST_INT_P (operands[2])
6e628811 7218 || INTVAL (operands[2]) > MAX_LDM_STM_OPS
9c08d1fa 7219 || INTVAL (operands[2]) < 2
0438d37f 7220 || !MEM_P (operands[1])
7221 || !REG_P (operands[0])
bd5b4116 7222 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
7223 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 7224 FAIL;
7225
7226 operands[3]
320ea44d 7227 = arm_gen_load_multiple (arm_regs_in_sequence + REGNO (operands[0]),
7228 INTVAL (operands[2]),
f082f1c4 7229 force_reg (SImode, XEXP (operands[1], 0)),
320ea44d 7230 FALSE, operands[1], &offset);
9580c25f 7231})
b11cae9e 7232
9c08d1fa 7233(define_expand "store_multiple"
7234 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
7235 (match_operand:SI 1 "" ""))
7236 (use (match_operand:SI 2 "" ""))])]
25f905c2 7237 "TARGET_32BIT"
9580c25f 7238{
7239 HOST_WIDE_INT offset = 0;
7240
674a8f0b 7241 /* Support only fixed point registers. */
0438d37f 7242 if (!CONST_INT_P (operands[2])
6e628811 7243 || INTVAL (operands[2]) > MAX_LDM_STM_OPS
9c08d1fa 7244 || INTVAL (operands[2]) < 2
0438d37f 7245 || !REG_P (operands[1])
7246 || !MEM_P (operands[0])
bd5b4116 7247 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
7248 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 7249 FAIL;
7250
7251 operands[3]
320ea44d 7252 = arm_gen_store_multiple (arm_regs_in_sequence + REGNO (operands[1]),
7253 INTVAL (operands[2]),
f082f1c4 7254 force_reg (SImode, XEXP (operands[0], 0)),
320ea44d 7255 FALSE, operands[0], &offset);
9580c25f 7256})
b11cae9e 7257
9c08d1fa 7258
e34ebfca 7259(define_expand "setmemsi"
3934ae0e 7260 [(match_operand:BLK 0 "general_operand")
7261 (match_operand:SI 1 "const_int_operand")
7262 (match_operand:SI 2 "const_int_operand")
7263 (match_operand:SI 3 "const_int_operand")]
e34ebfca 7264 "TARGET_32BIT"
7265{
7266 if (arm_gen_setmem (operands))
7267 DONE;
7268
7269 FAIL;
7270})
7271
7272
9c08d1fa 7273;; Move a block of memory if it is word aligned and MORE than 2 words long.
7274;; We could let this apply for blocks of less than this, but it clobbers so
7275;; many registers that there is then probably a better way.
7276
f135a8d4 7277(define_expand "cpymemqi"
3934ae0e 7278 [(match_operand:BLK 0 "general_operand")
7279 (match_operand:BLK 1 "general_operand")
7280 (match_operand:SI 2 "const_int_operand")
7281 (match_operand:SI 3 "const_int_operand")]
ae51a965 7282 ""
9c08d1fa 7283 "
25f905c2 7284 if (TARGET_32BIT)
cffb2a26 7285 {
ae51a965 7286 if (TARGET_LDRD && current_tune->prefer_ldrd_strd
7287 && !optimize_function_for_size_p (cfun))
7288 {
f135a8d4 7289 if (gen_cpymem_ldrd_strd (operands))
ae51a965 7290 DONE;
7291 FAIL;
7292 }
7293
f135a8d4 7294 if (arm_gen_cpymemqi (operands))
cffb2a26 7295 DONE;
7296 FAIL;
7297 }
25f905c2 7298 else /* TARGET_THUMB1 */
cffb2a26 7299 {
7300 if ( INTVAL (operands[3]) != 4
7301 || INTVAL (operands[2]) > 48)
7302 FAIL;
7303
f135a8d4 7304 thumb_expand_cpymemqi (operands);
cffb2a26 7305 DONE;
7306 }
7307 "
7308)
9c08d1fa 7309\f
b11cae9e 7310
341940e8 7311;; Compare & branch insns
8d232dc7 7312;; The range calculations are based as follows:
341940e8 7313;; For forward branches, the address calculation returns the address of
7314;; the next instruction. This is 2 beyond the branch instruction.
7315;; For backward branches, the address calculation returns the address of
7316;; the first instruction in this pattern (cmp). This is 2 before the branch
7317;; instruction for the shortest sequence, and 4 before the branch instruction
7318;; if we have to jump around an unconditional branch.
7319;; To the basic branch range the PC offset must be added (this is +4).
7320;; So for forward branches we have
7321;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
7322;; And for backward branches we have
7323;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
7324;;
7325;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
7326;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
cffb2a26 7327
aeac46d4 7328(define_expand "cbranchsi4"
7329 [(set (pc) (if_then_else
aa06947a 7330 (match_operator 0 "expandable_comparison_operator"
3934ae0e 7331 [(match_operand:SI 1 "s_register_operand")
7332 (match_operand:SI 2 "nonmemory_operand")])
aeac46d4 7333 (label_ref (match_operand 3 "" ""))
7334 (pc)))]
f9aa4160 7335 "TARGET_EITHER"
aeac46d4 7336 "
74f4459c 7337 if (!TARGET_THUMB1)
7338 {
f9aa4160 7339 if (!arm_validize_comparison (&operands[0], &operands[1], &operands[2]))
7340 FAIL;
74f4459c 7341 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
7342 operands[3]));
7343 DONE;
7344 }
25f905c2 7345 if (thumb1_cmpneg_operand (operands[2], SImode))
aeac46d4 7346 {
7347 emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
7348 operands[3], operands[0]));
7349 DONE;
7350 }
25f905c2 7351 if (!thumb1_cmp_operand (operands[2], SImode))
aeac46d4 7352 operands[2] = force_reg (SImode, operands[2]);
7353 ")
7354
74f4459c 7355(define_expand "cbranchsf4"
7356 [(set (pc) (if_then_else
aa06947a 7357 (match_operator 0 "expandable_comparison_operator"
3934ae0e 7358 [(match_operand:SF 1 "s_register_operand")
7359 (match_operand:SF 2 "vfp_compare_operand")])
74f4459c 7360 (label_ref (match_operand 3 "" ""))
7361 (pc)))]
7362 "TARGET_32BIT && TARGET_HARD_FLOAT"
7363 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
7364 operands[3])); DONE;"
7365)
7366
7367(define_expand "cbranchdf4"
7368 [(set (pc) (if_then_else
aa06947a 7369 (match_operator 0 "expandable_comparison_operator"
3934ae0e 7370 [(match_operand:DF 1 "s_register_operand")
7371 (match_operand:DF 2 "vfp_compare_operand")])
74f4459c 7372 (label_ref (match_operand 3 "" ""))
7373 (pc)))]
a50d7267 7374 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
74f4459c 7375 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
7376 operands[3])); DONE;"
7377)
7378
74f4459c 7379(define_expand "cbranchdi4"
7380 [(set (pc) (if_then_else
aa06947a 7381 (match_operator 0 "expandable_comparison_operator"
3934ae0e 7382 [(match_operand:DI 1 "s_register_operand")
7383 (match_operand:DI 2 "cmpdi_operand")])
74f4459c 7384 (label_ref (match_operand 3 "" ""))
7385 (pc)))]
a8045a4f 7386 "TARGET_32BIT"
7387 "{
0438d37f 7388 if (!arm_validize_comparison (&operands[0], &operands[1], &operands[2]))
f9aa4160 7389 FAIL;
7390 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
a8045a4f 7391 operands[3]));
7392 DONE;
7393 }"
74f4459c 7394)
7395
9c08d1fa 7396;; Comparison and test insns
7397
cffb2a26 7398(define_insn "*arm_cmpsi_insn"
bd5b4116 7399 [(set (reg:CC CC_REGNUM)
f9f234ec 7400 (compare:CC (match_operand:SI 0 "s_register_operand" "l,r,r,r,r")
7401 (match_operand:SI 1 "arm_add_operand" "Py,r,r,I,L")))]
25f905c2 7402 "TARGET_32BIT"
5565501b 7403 "@
a6864a24 7404 cmp%?\\t%0, %1
7405 cmp%?\\t%0, %1
aea4c774 7406 cmp%?\\t%0, %1
f9f234ec 7407 cmp%?\\t%0, %1
aea4c774 7408 cmn%?\\t%0, #%n1"
a6864a24 7409 [(set_attr "conds" "set")
f9f234ec 7410 (set_attr "arch" "t2,t2,any,any,any")
7411 (set_attr "length" "2,2,4,4,4")
65f68e55 7412 (set_attr "predicable" "yes")
f9f234ec 7413 (set_attr "predicable_short_it" "yes,yes,yes,no,no")
112eda6f 7414 (set_attr "type" "alus_imm,alus_sreg,alus_sreg,alus_imm,alus_imm")]
cffb2a26 7415)
b11cae9e 7416
d5d4dc8d 7417(define_insn "*cmpsi_shiftsi"
bd5b4116 7418 [(set (reg:CC CC_REGNUM)
d82e788e 7419 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r,r")
cffb2a26 7420 (match_operator:SI 3 "shift_operator"
d82e788e 7421 [(match_operand:SI 1 "s_register_operand" "r,r,r")
7422 (match_operand:SI 2 "shift_amount_operand" "M,r,M")])))]
d5d4dc8d 7423 "TARGET_32BIT"
f9f234ec 7424 "cmp\\t%0, %1%S3"
344495ea 7425 [(set_attr "conds" "set")
331beb1a 7426 (set_attr "shift" "1")
d82e788e 7427 (set_attr "arch" "32,a,a")
282b4c75 7428 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
b11cae9e 7429
d5d4dc8d 7430(define_insn "*cmpsi_shiftsi_swp"
bd5b4116 7431 [(set (reg:CC_SWP CC_REGNUM)
aea4c774 7432 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
d82e788e 7433 [(match_operand:SI 1 "s_register_operand" "r,r,r")
7434 (match_operand:SI 2 "shift_amount_operand" "M,r,M")])
7435 (match_operand:SI 0 "s_register_operand" "r,r,r")))]
d5d4dc8d 7436 "TARGET_32BIT"
aea4c774 7437 "cmp%?\\t%0, %1%S3"
344495ea 7438 [(set_attr "conds" "set")
331beb1a 7439 (set_attr "shift" "1")
d82e788e 7440 (set_attr "arch" "32,a,a")
282b4c75 7441 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
b11cae9e 7442
25f905c2 7443(define_insn "*arm_cmpsi_negshiftsi_si"
aed179ae 7444 [(set (reg:CC_Z CC_REGNUM)
7445 (compare:CC_Z
7446 (neg:SI (match_operator:SI 1 "shift_operator"
7447 [(match_operand:SI 2 "s_register_operand" "r")
7448 (match_operand:SI 3 "reg_or_int_operand" "rM")]))
7449 (match_operand:SI 0 "s_register_operand" "r")))]
cffb2a26 7450 "TARGET_ARM"
aed179ae 7451 "cmn%?\\t%0, %2%S1"
344495ea 7452 [(set_attr "conds" "set")
aed179ae 7453 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
d82e788e 7454 (const_string "alus_shift_imm")
7455 (const_string "alus_shift_reg")))
596e5e8f 7456 (set_attr "predicable" "yes")]
0d66636f 7457)
b11cae9e 7458
a8045a4f 7459;; DImode comparisons. The generic code generates branches that
f4d3c071 7460;; if-conversion cannot reduce to a conditional compare, so we do
a8045a4f 7461;; that directly.
7462
ba6a3b2f 7463(define_insn_and_split "*arm_cmpdi_insn"
a8045a4f 7464 [(set (reg:CC_NCV CC_REGNUM)
7465 (compare:CC_NCV (match_operand:DI 0 "s_register_operand" "r")
7466 (match_operand:DI 1 "arm_di_operand" "rDi")))
7467 (clobber (match_scratch:SI 2 "=r"))]
b805622c 7468 "TARGET_32BIT"
ba6a3b2f 7469 "#" ; "cmp\\t%Q0, %Q1\;sbcs\\t%2, %R0, %R1"
7470 "&& reload_completed"
7471 [(set (reg:CC CC_REGNUM)
3b0dcaf2 7472 (compare:CC (match_dup 0) (match_dup 1)))
ba6a3b2f 7473 (parallel [(set (reg:CC CC_REGNUM)
3b0dcaf2 7474 (compare:CC (match_dup 3) (match_dup 4)))
7475 (set (match_dup 2)
7476 (minus:SI (match_dup 5)
7477 (ltu:SI (reg:CC CC_REGNUM) (const_int 0))))])]
ba6a3b2f 7478 {
7479 operands[3] = gen_highpart (SImode, operands[0]);
7480 operands[0] = gen_lowpart (SImode, operands[0]);
7481 if (CONST_INT_P (operands[1]))
7482 {
16a3cf9c 7483 operands[4] = gen_highpart_mode (SImode, DImode, operands[1]);
7484 if (operands[4] == const0_rtx)
7485 operands[5] = operands[3];
7486 else
7487 operands[5] = gen_rtx_PLUS (SImode, operands[3],
7488 gen_int_mode (-UINTVAL (operands[4]),
7489 SImode));
ba6a3b2f 7490 }
7491 else
7492 {
7493 operands[4] = gen_highpart (SImode, operands[1]);
7494 operands[5] = gen_rtx_MINUS (SImode, operands[3], operands[4]);
7495 }
7496 operands[1] = gen_lowpart (SImode, operands[1]);
7497 operands[2] = gen_lowpart (SImode, operands[2]);
7498 }
a8045a4f 7499 [(set_attr "conds" "set")
1b7da4ac 7500 (set_attr "length" "8")
7501 (set_attr "type" "multiple")]
a8045a4f 7502)
7503
ba6a3b2f 7504(define_insn_and_split "*arm_cmpdi_unsigned"
a8045a4f 7505 [(set (reg:CC_CZ CC_REGNUM)
1a86364b 7506 (compare:CC_CZ (match_operand:DI 0 "s_register_operand" "l,r,r,r")
7507 (match_operand:DI 1 "arm_di_operand" "Py,r,Di,rDi")))]
7c36fe71 7508
48a98053 7509 "TARGET_32BIT"
ba6a3b2f 7510 "#" ; "cmp\\t%R0, %R1\;it eq\;cmpeq\\t%Q0, %Q1"
7511 "&& reload_completed"
7512 [(set (reg:CC CC_REGNUM)
7513 (compare:CC (match_dup 2) (match_dup 3)))
7514 (cond_exec (eq:SI (reg:CC CC_REGNUM) (const_int 0))
7515 (set (reg:CC CC_REGNUM)
7516 (compare:CC (match_dup 0) (match_dup 1))))]
7517 {
7518 operands[2] = gen_highpart (SImode, operands[0]);
7519 operands[0] = gen_lowpart (SImode, operands[0]);
7520 if (CONST_INT_P (operands[1]))
7521 operands[3] = gen_highpart_mode (SImode, DImode, operands[1]);
7522 else
7523 operands[3] = gen_highpart (SImode, operands[1]);
7524 operands[1] = gen_lowpart (SImode, operands[1]);
7525 }
a8045a4f 7526 [(set_attr "conds" "set")
8bdfd6ed 7527 (set_attr "enabled_for_short_it" "yes,yes,no,*")
1a86364b 7528 (set_attr "arch" "t2,t2,t2,a")
7529 (set_attr "length" "6,6,10,8")
1b7da4ac 7530 (set_attr "type" "multiple")]
a8045a4f 7531)
7532
7533(define_insn "*arm_cmpdi_zero"
7534 [(set (reg:CC_Z CC_REGNUM)
7535 (compare:CC_Z (match_operand:DI 0 "s_register_operand" "r")
7536 (const_int 0)))
7537 (clobber (match_scratch:SI 1 "=r"))]
7538 "TARGET_32BIT"
3ef90e77 7539 "orrs%?\\t%1, %Q0, %R0"
1b7da4ac 7540 [(set_attr "conds" "set")
7541 (set_attr "type" "logics_reg")]
a8045a4f 7542)
7543
9c08d1fa 7544; This insn allows redundant compares to be removed by cse, nothing should
7545; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
7546; is deleted later on. The match_dup will match the mode here, so that
7547; mode changes of the condition codes aren't lost by this even though we don't
7548; specify what they are.
7549
8a18b90c 7550(define_insn "*deleted_compare"
9c08d1fa 7551 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
25f905c2 7552 "TARGET_32BIT"
40dbec34 7553 "\\t%@ deleted compare"
cffb2a26 7554 [(set_attr "conds" "set")
1b7da4ac 7555 (set_attr "length" "0")
7556 (set_attr "type" "no_insn")]
cffb2a26 7557)
9c08d1fa 7558
7559\f
7560;; Conditional branch insns
7561
74f4459c 7562(define_expand "cbranch_cc"
9c08d1fa 7563 [(set (pc)
74f4459c 7564 (if_then_else (match_operator 0 "" [(match_operand 1 "" "")
7565 (match_operand 2 "" "")])
7566 (label_ref (match_operand 3 "" ""))
9c08d1fa 7567 (pc)))]
25f905c2 7568 "TARGET_32BIT"
74f4459c 7569 "operands[1] = arm_gen_compare_reg (GET_CODE (operands[0]),
e1b93706 7570 operands[1], operands[2], NULL_RTX);
74f4459c 7571 operands[2] = const0_rtx;"
8fa3ba89 7572)
7573
7574;;
7575;; Patterns to match conditional branch insns.
7576;;
7577
ffcc986d 7578(define_insn "arm_cond_branch"
9c08d1fa 7579 [(set (pc)
8fa3ba89 7580 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 7581 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 7582 (label_ref (match_operand 0 "" ""))
7583 (pc)))]
25f905c2 7584 "TARGET_32BIT"
d75350ce 7585 "*
9c08d1fa 7586 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 7587 {
7588 arm_ccfsm_state += 2;
7589 return \"\";
7590 }
e2348bcb 7591 return \"b%d1\\t%l0\";
cffb2a26 7592 "
a2cd141b 7593 [(set_attr "conds" "use")
a6864a24 7594 (set_attr "type" "branch")
7595 (set (attr "length")
7596 (if_then_else
0bf497f5 7597 (and (match_test "TARGET_THUMB2")
a6864a24 7598 (and (ge (minus (match_dup 0) (pc)) (const_int -250))
7599 (le (minus (match_dup 0) (pc)) (const_int 256))))
7600 (const_int 2)
7601 (const_int 4)))]
cffb2a26 7602)
d75350ce 7603
cffb2a26 7604(define_insn "*arm_cond_branch_reversed"
9c08d1fa 7605 [(set (pc)
8fa3ba89 7606 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 7607 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 7608 (pc)
7609 (label_ref (match_operand 0 "" ""))))]
25f905c2 7610 "TARGET_32BIT"
d75350ce 7611 "*
9c08d1fa 7612 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 7613 {
7614 arm_ccfsm_state += 2;
7615 return \"\";
7616 }
e2348bcb 7617 return \"b%D1\\t%l0\";
cffb2a26 7618 "
a2cd141b 7619 [(set_attr "conds" "use")
a6864a24 7620 (set_attr "type" "branch")
7621 (set (attr "length")
7622 (if_then_else
0bf497f5 7623 (and (match_test "TARGET_THUMB2")
a6864a24 7624 (and (ge (minus (match_dup 0) (pc)) (const_int -250))
7625 (le (minus (match_dup 0) (pc)) (const_int 256))))
7626 (const_int 2)
7627 (const_int 4)))]
cffb2a26 7628)
7629
b11cae9e 7630\f
9c08d1fa 7631
7632; scc insns
7633
74f4459c 7634(define_expand "cstore_cc"
3934ae0e 7635 [(set (match_operand:SI 0 "s_register_operand")
74f4459c 7636 (match_operator:SI 1 "" [(match_operand 2 "" "")
7637 (match_operand 3 "" "")]))]
25f905c2 7638 "TARGET_32BIT"
74f4459c 7639 "operands[2] = arm_gen_compare_reg (GET_CODE (operands[1]),
e1b93706 7640 operands[2], operands[3], NULL_RTX);
74f4459c 7641 operands[3] = const0_rtx;"
8fa3ba89 7642)
7643
a3b84066 7644(define_insn_and_split "*mov_scc"
9c08d1fa 7645 [(set (match_operand:SI 0 "s_register_operand" "=r")
ff74dd54 7646 (match_operator:SI 1 "arm_comparison_operator_mode"
8a18b90c 7647 [(match_operand 2 "cc_register" "") (const_int 0)]))]
cffb2a26 7648 "TARGET_ARM"
a3b84066 7649 "#" ; "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
7650 "TARGET_ARM"
7651 [(set (match_dup 0)
7652 (if_then_else:SI (match_dup 1)
7653 (const_int 1)
7654 (const_int 0)))]
7655 ""
cffb2a26 7656 [(set_attr "conds" "use")
1b7da4ac 7657 (set_attr "length" "8")
7658 (set_attr "type" "multiple")]
cffb2a26 7659)
9c08d1fa 7660
a3b84066 7661(define_insn_and_split "*mov_negscc"
9c08d1fa 7662 [(set (match_operand:SI 0 "s_register_operand" "=r")
ff74dd54 7663 (neg:SI (match_operator:SI 1 "arm_comparison_operator_mode"
8a18b90c 7664 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 7665 "TARGET_ARM"
a3b84066 7666 "#" ; "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
7667 "TARGET_ARM"
7668 [(set (match_dup 0)
7669 (if_then_else:SI (match_dup 1)
7670 (match_dup 3)
7671 (const_int 0)))]
7672 {
7673 operands[3] = GEN_INT (~0);
7674 }
cffb2a26 7675 [(set_attr "conds" "use")
1b7da4ac 7676 (set_attr "length" "8")
7677 (set_attr "type" "multiple")]
cffb2a26 7678)
9c08d1fa 7679
a3b84066 7680(define_insn_and_split "*mov_notscc"
9c08d1fa 7681 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7682 (not:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7683 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 7684 "TARGET_ARM"
a3b84066 7685 "#" ; "mvn%D1\\t%0, #0\;mvn%d1\\t%0, #1"
7686 "TARGET_ARM"
7687 [(set (match_dup 0)
7688 (if_then_else:SI (match_dup 1)
7689 (match_dup 3)
7690 (match_dup 4)))]
7691 {
7692 operands[3] = GEN_INT (~1);
7693 operands[4] = GEN_INT (~0);
7694 }
cffb2a26 7695 [(set_attr "conds" "use")
1b7da4ac 7696 (set_attr "length" "8")
7697 (set_attr "type" "multiple")]
cffb2a26 7698)
9c08d1fa 7699
595d88b5 7700(define_expand "cstoresi4"
3934ae0e 7701 [(set (match_operand:SI 0 "s_register_operand")
aa06947a 7702 (match_operator:SI 1 "expandable_comparison_operator"
3934ae0e 7703 [(match_operand:SI 2 "s_register_operand")
7704 (match_operand:SI 3 "reg_or_int_operand")]))]
74f4459c 7705 "TARGET_32BIT || TARGET_THUMB1"
595d88b5 7706 "{
7707 rtx op3, scratch, scratch2;
7708
74f4459c 7709 if (!TARGET_THUMB1)
7710 {
7711 if (!arm_add_operand (operands[3], SImode))
7712 operands[3] = force_reg (SImode, operands[3]);
7713 emit_insn (gen_cstore_cc (operands[0], operands[1],
7714 operands[2], operands[3]));
7715 DONE;
7716 }
7717
595d88b5 7718 if (operands[3] == const0_rtx)
7719 {
7720 switch (GET_CODE (operands[1]))
7721 {
7722 case EQ:
25f905c2 7723 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], operands[2]));
595d88b5 7724 break;
7725
7726 case NE:
25f905c2 7727 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], operands[2]));
595d88b5 7728 break;
7729
7730 case LE:
7731 scratch = expand_binop (SImode, add_optab, operands[2], constm1_rtx,
7732 NULL_RTX, 0, OPTAB_WIDEN);
7733 scratch = expand_binop (SImode, ior_optab, operands[2], scratch,
7734 NULL_RTX, 0, OPTAB_WIDEN);
7735 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7736 operands[0], 1, OPTAB_WIDEN);
7737 break;
7738
7739 case GE:
7740 scratch = expand_unop (SImode, one_cmpl_optab, operands[2],
7741 NULL_RTX, 1);
7742 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7743 NULL_RTX, 1, OPTAB_WIDEN);
7744 break;
7745
7746 case GT:
7747 scratch = expand_binop (SImode, ashr_optab, operands[2],
7748 GEN_INT (31), NULL_RTX, 0, OPTAB_WIDEN);
7749 scratch = expand_binop (SImode, sub_optab, scratch, operands[2],
7750 NULL_RTX, 0, OPTAB_WIDEN);
7751 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31), operands[0],
7752 0, OPTAB_WIDEN);
7753 break;
7754
7755 /* LT is handled by generic code. No need for unsigned with 0. */
7756 default:
7757 FAIL;
7758 }
7759 DONE;
7760 }
7761
7762 switch (GET_CODE (operands[1]))
7763 {
7764 case EQ:
7765 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7766 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7767 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], scratch));
595d88b5 7768 break;
7769
7770 case NE:
7771 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7772 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7773 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], scratch));
595d88b5 7774 break;
7775
7776 case LE:
7777 op3 = force_reg (SImode, operands[3]);
7778
7779 scratch = expand_binop (SImode, lshr_optab, operands[2], GEN_INT (31),
7780 NULL_RTX, 1, OPTAB_WIDEN);
7781 scratch2 = expand_binop (SImode, ashr_optab, op3, GEN_INT (31),
7782 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7783 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
595d88b5 7784 op3, operands[2]));
7785 break;
7786
7787 case GE:
7788 op3 = operands[3];
25f905c2 7789 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7790 op3 = force_reg (SImode, op3);
7791 scratch = expand_binop (SImode, ashr_optab, operands[2], GEN_INT (31),
7792 NULL_RTX, 0, OPTAB_WIDEN);
7793 scratch2 = expand_binop (SImode, lshr_optab, op3, GEN_INT (31),
7794 NULL_RTX, 1, OPTAB_WIDEN);
25f905c2 7795 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
595d88b5 7796 operands[2], op3));
7797 break;
7798
7799 case LEU:
7800 op3 = force_reg (SImode, operands[3]);
7801 scratch = force_reg (SImode, const0_rtx);
25f905c2 7802 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
595d88b5 7803 op3, operands[2]));
7804 break;
7805
7806 case GEU:
7807 op3 = operands[3];
25f905c2 7808 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7809 op3 = force_reg (SImode, op3);
7810 scratch = force_reg (SImode, const0_rtx);
25f905c2 7811 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
595d88b5 7812 operands[2], op3));
7813 break;
7814
7815 case LTU:
7816 op3 = operands[3];
25f905c2 7817 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7818 op3 = force_reg (SImode, op3);
7819 scratch = gen_reg_rtx (SImode);
408b7ae5 7820 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], operands[2], op3));
595d88b5 7821 break;
7822
7823 case GTU:
7824 op3 = force_reg (SImode, operands[3]);
7825 scratch = gen_reg_rtx (SImode);
408b7ae5 7826 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], op3, operands[2]));
595d88b5 7827 break;
7828
7829 /* No good sequences for GT, LT. */
7830 default:
7831 FAIL;
7832 }
7833 DONE;
7834}")
7835
9854d864 7836(define_expand "cstorehf4"
7837 [(set (match_operand:SI 0 "s_register_operand")
7838 (match_operator:SI 1 "expandable_comparison_operator"
7839 [(match_operand:HF 2 "s_register_operand")
d7216193 7840 (match_operand:HF 3 "vfp_compare_operand")]))]
9854d864 7841 "TARGET_VFP_FP16INST"
7842 {
7843 if (!arm_validize_comparison (&operands[1],
7844 &operands[2],
7845 &operands[3]))
7846 FAIL;
7847
7848 emit_insn (gen_cstore_cc (operands[0], operands[1],
7849 operands[2], operands[3]));
7850 DONE;
7851 }
7852)
7853
74f4459c 7854(define_expand "cstoresf4"
3934ae0e 7855 [(set (match_operand:SI 0 "s_register_operand")
aa06947a 7856 (match_operator:SI 1 "expandable_comparison_operator"
3934ae0e 7857 [(match_operand:SF 2 "s_register_operand")
7858 (match_operand:SF 3 "vfp_compare_operand")]))]
74f4459c 7859 "TARGET_32BIT && TARGET_HARD_FLOAT"
7860 "emit_insn (gen_cstore_cc (operands[0], operands[1],
7861 operands[2], operands[3])); DONE;"
7862)
7863
7864(define_expand "cstoredf4"
3934ae0e 7865 [(set (match_operand:SI 0 "s_register_operand")
aa06947a 7866 (match_operator:SI 1 "expandable_comparison_operator"
3934ae0e 7867 [(match_operand:DF 2 "s_register_operand")
7868 (match_operand:DF 3 "vfp_compare_operand")]))]
d63ed457 7869 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
74f4459c 7870 "emit_insn (gen_cstore_cc (operands[0], operands[1],
7871 operands[2], operands[3])); DONE;"
7872)
7873
74f4459c 7874(define_expand "cstoredi4"
3934ae0e 7875 [(set (match_operand:SI 0 "s_register_operand")
aa06947a 7876 (match_operator:SI 1 "expandable_comparison_operator"
3934ae0e 7877 [(match_operand:DI 2 "s_register_operand")
7878 (match_operand:DI 3 "cmpdi_operand")]))]
a8045a4f 7879 "TARGET_32BIT"
7880 "{
f9aa4160 7881 if (!arm_validize_comparison (&operands[1],
7882 &operands[2],
7883 &operands[3]))
7884 FAIL;
7885 emit_insn (gen_cstore_cc (operands[0], operands[1], operands[2],
a8045a4f 7886 operands[3]));
7887 DONE;
7888 }"
74f4459c 7889)
7890
9c08d1fa 7891\f
39b5e676 7892;; Conditional move insns
7893
7894(define_expand "movsicc"
3934ae0e 7895 [(set (match_operand:SI 0 "s_register_operand")
7896 (if_then_else:SI (match_operand 1 "expandable_comparison_operator")
7897 (match_operand:SI 2 "arm_not_operand")
7898 (match_operand:SI 3 "arm_not_operand")))]
25f905c2 7899 "TARGET_32BIT"
39b5e676 7900 "
215b30b3 7901 {
f9aa4160 7902 enum rtx_code code;
278b301d 7903 rtx ccreg;
7904
f9aa4160 7905 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
9854d864 7906 &XEXP (operands[1], 1)))
278b301d 7907 FAIL;
9854d864 7908
7909 code = GET_CODE (operands[1]);
7910 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
7911 XEXP (operands[1], 1), NULL_RTX);
7912 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7913 }"
7914)
7915
7916(define_expand "movhfcc"
7917 [(set (match_operand:HF 0 "s_register_operand")
7918 (if_then_else:HF (match_operand 1 "arm_cond_move_operator")
7919 (match_operand:HF 2 "s_register_operand")
7920 (match_operand:HF 3 "s_register_operand")))]
7921 "TARGET_VFP_FP16INST"
7922 "
7923 {
7924 enum rtx_code code = GET_CODE (operands[1]);
7925 rtx ccreg;
7926
7927 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
7928 &XEXP (operands[1], 1)))
7929 FAIL;
7930
f9aa4160 7931 code = GET_CODE (operands[1]);
74f4459c 7932 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
e1b93706 7933 XEXP (operands[1], 1), NULL_RTX);
29bb088d 7934 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7935 }"
7936)
39b5e676 7937
7938(define_expand "movsfcc"
3934ae0e 7939 [(set (match_operand:SF 0 "s_register_operand")
7940 (if_then_else:SF (match_operand 1 "arm_cond_move_operator")
7941 (match_operand:SF 2 "s_register_operand")
7942 (match_operand:SF 3 "s_register_operand")))]
19f6bf8d 7943 "TARGET_32BIT && TARGET_HARD_FLOAT"
39b5e676 7944 "
215b30b3 7945 {
7946 enum rtx_code code = GET_CODE (operands[1]);
7947 rtx ccreg;
f082f1c4 7948
9854d864 7949 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
f9aa4160 7950 &XEXP (operands[1], 1)))
7951 FAIL;
39b5e676 7952
f9aa4160 7953 code = GET_CODE (operands[1]);
74f4459c 7954 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
e1b93706 7955 XEXP (operands[1], 1), NULL_RTX);
29bb088d 7956 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7957 }"
7958)
39b5e676 7959
7960(define_expand "movdfcc"
3934ae0e 7961 [(set (match_operand:DF 0 "s_register_operand")
7962 (if_then_else:DF (match_operand 1 "arm_cond_move_operator")
7963 (match_operand:DF 2 "s_register_operand")
7964 (match_operand:DF 3 "s_register_operand")))]
994606f8 7965 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
39b5e676 7966 "
215b30b3 7967 {
7968 enum rtx_code code = GET_CODE (operands[1]);
278b301d 7969 rtx ccreg;
39b5e676 7970
f9aa4160 7971 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
7972 &XEXP (operands[1], 1)))
7973 FAIL;
7974 code = GET_CODE (operands[1]);
74f4459c 7975 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
e1b93706 7976 XEXP (operands[1], 1), NULL_RTX);
29bb088d 7977 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7978 }"
7979)
39b5e676 7980
91cb50d2 7981(define_insn "*cmov<mode>"
7982 [(set (match_operand:SDF 0 "s_register_operand" "=<F_constraint>")
7983 (if_then_else:SDF (match_operator 1 "arm_vsel_comparison_operator"
7984 [(match_operand 2 "cc_register" "") (const_int 0)])
7985 (match_operand:SDF 3 "s_register_operand"
7986 "<F_constraint>")
7987 (match_operand:SDF 4 "s_register_operand"
7988 "<F_constraint>")))]
c79c1b1b 7989 "TARGET_HARD_FLOAT && TARGET_VFP5 <vfp_double_cond>"
91cb50d2 7990 "*
7991 {
7992 enum arm_cond_code code = maybe_get_arm_condition_code (operands[1]);
7993 switch (code)
7994 {
7995 case ARM_GE:
7996 case ARM_GT:
7997 case ARM_EQ:
7998 case ARM_VS:
7999 return \"vsel%d1.<V_if_elem>\\t%<V_reg>0, %<V_reg>3, %<V_reg>4\";
8000 case ARM_LT:
8001 case ARM_LE:
8002 case ARM_NE:
8003 case ARM_VC:
8004 return \"vsel%D1.<V_if_elem>\\t%<V_reg>0, %<V_reg>4, %<V_reg>3\";
8005 default:
8006 gcc_unreachable ();
8007 }
8008 return \"\";
8009 }"
8010 [(set_attr "conds" "use")
6664d308 8011 (set_attr "type" "fcsel")]
91cb50d2 8012)
8013
9854d864 8014(define_insn "*cmovhf"
8015 [(set (match_operand:HF 0 "s_register_operand" "=t")
8016 (if_then_else:HF (match_operator 1 "arm_vsel_comparison_operator"
8017 [(match_operand 2 "cc_register" "") (const_int 0)])
8018 (match_operand:HF 3 "s_register_operand" "t")
8019 (match_operand:HF 4 "s_register_operand" "t")))]
8020 "TARGET_VFP_FP16INST"
8021 "*
8022 {
8023 enum arm_cond_code code = maybe_get_arm_condition_code (operands[1]);
8024 switch (code)
8025 {
8026 case ARM_GE:
8027 case ARM_GT:
8028 case ARM_EQ:
8029 case ARM_VS:
8030 return \"vsel%d1.f16\\t%0, %3, %4\";
8031 case ARM_LT:
8032 case ARM_LE:
8033 case ARM_NE:
8034 case ARM_VC:
8035 return \"vsel%D1.f16\\t%0, %4, %3\";
8036 default:
8037 gcc_unreachable ();
8038 }
8039 return \"\";
8040 }"
8041 [(set_attr "conds" "use")
8042 (set_attr "type" "fcsel")]
8043)
8044
190efb17 8045(define_insn_and_split "*movsicc_insn"
f082f1c4 8046 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
8a18b90c 8047 (if_then_else:SI
8fa3ba89 8048 (match_operator 3 "arm_comparison_operator"
8a18b90c 8049 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 8050 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
8051 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
cffb2a26 8052 "TARGET_ARM"
39b5e676 8053 "@
8a18b90c 8054 mov%D3\\t%0, %2
8055 mvn%D3\\t%0, #%B2
f082f1c4 8056 mov%d3\\t%0, %1
8057 mvn%d3\\t%0, #%B1
190efb17 8058 #
8059 #
8060 #
8061 #"
8062 ; alt4: mov%d3\\t%0, %1\;mov%D3\\t%0, %2
8063 ; alt5: mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
8064 ; alt6: mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
8065 ; alt7: mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
8066 "&& reload_completed"
8067 [(const_int 0)]
8068 {
8069 enum rtx_code rev_code;
3754d046 8070 machine_mode mode;
190efb17 8071 rtx rev_cond;
8072
8073 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
8074 operands[3],
d1f9b275 8075 gen_rtx_SET (operands[0], operands[1])));
190efb17 8076
8077 rev_code = GET_CODE (operands[3]);
8078 mode = GET_MODE (operands[4]);
8079 if (mode == CCFPmode || mode == CCFPEmode)
8080 rev_code = reverse_condition_maybe_unordered (rev_code);
8081 else
8082 rev_code = reverse_condition (rev_code);
8083
8084 rev_cond = gen_rtx_fmt_ee (rev_code,
8085 VOIDmode,
8086 operands[4],
8087 const0_rtx);
8088 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
8089 rev_cond,
d1f9b275 8090 gen_rtx_SET (operands[0], operands[2])));
190efb17 8091 DONE;
8092 }
f082f1c4 8093 [(set_attr "length" "4,4,4,4,8,8,8,8")
d2a518d1 8094 (set_attr "conds" "use")
65f68e55 8095 (set_attr_alternative "type"
8096 [(if_then_else (match_operand 2 "const_int_operand" "")
1aed5204 8097 (const_string "mov_imm")
8098 (const_string "mov_reg"))
8099 (const_string "mvn_imm")
65f68e55 8100 (if_then_else (match_operand 1 "const_int_operand" "")
1aed5204 8101 (const_string "mov_imm")
8102 (const_string "mov_reg"))
8103 (const_string "mvn_imm")
282b4c75 8104 (const_string "multiple")
8105 (const_string "multiple")
8106 (const_string "multiple")
8107 (const_string "multiple")])]
215b30b3 8108)
39b5e676 8109
39b5e676 8110(define_insn "*movsfcc_soft_insn"
f082f1c4 8111 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
8fa3ba89 8112 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
8a18b90c 8113 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 8114 (match_operand:SF 1 "s_register_operand" "0,r")
8115 (match_operand:SF 2 "s_register_operand" "r,0")))]
cffb2a26 8116 "TARGET_ARM && TARGET_SOFT_FLOAT"
f082f1c4 8117 "@
8118 mov%D3\\t%0, %2
8119 mov%d3\\t%0, %1"
d2a518d1 8120 [(set_attr "conds" "use")
1aed5204 8121 (set_attr "type" "mov_reg")]
8fa3ba89 8122)
39b5e676 8123
39b5e676 8124\f
9c08d1fa 8125;; Jump and linkage insns
8126
cffb2a26 8127(define_expand "jump"
9c08d1fa 8128 [(set (pc)
8129 (label_ref (match_operand 0 "" "")))]
cffb2a26 8130 "TARGET_EITHER"
9c08d1fa 8131 ""
cffb2a26 8132)
8133
8134(define_insn "*arm_jump"
8135 [(set (pc)
8136 (label_ref (match_operand 0 "" "")))]
25f905c2 8137 "TARGET_32BIT"
9c08d1fa 8138 "*
0d66636f 8139 {
8140 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
8141 {
8142 arm_ccfsm_state += 2;
8143 return \"\";
8144 }
8145 return \"b%?\\t%l0\";
8146 }
8147 "
a6864a24 8148 [(set_attr "predicable" "yes")
8149 (set (attr "length")
8150 (if_then_else
0bf497f5 8151 (and (match_test "TARGET_THUMB2")
a6864a24 8152 (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
8153 (le (minus (match_dup 0) (pc)) (const_int 2048))))
8154 (const_int 2)
1b7da4ac 8155 (const_int 4)))
8156 (set_attr "type" "branch")]
0d66636f 8157)
9c08d1fa 8158
d3373b54 8159(define_expand "call"
3934ae0e 8160 [(parallel [(call (match_operand 0 "memory_operand")
8161 (match_operand 1 "general_operand"))
cffb2a26 8162 (use (match_operand 2 "" ""))
bd5b4116 8163 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 8164 "TARGET_EITHER"
6c4c2133 8165 "
8166 {
bac7fc85 8167 rtx callee, pat;
2d3a01a7 8168 tree addr = MEM_EXPR (operands[0]);
bbe777ea 8169
bbe777ea 8170 /* In an untyped call, we can get NULL for operand 2. */
8171 if (operands[2] == NULL_RTX)
8172 operands[2] = const0_rtx;
8173
de55252a 8174 /* Decide if we should generate indirect calls by loading the
85c36fd1 8175 32-bit address of the callee into a register before performing the
de55252a 8176 branch and link. */
8177 callee = XEXP (operands[0], 0);
8178 if (GET_CODE (callee) == SYMBOL_REF
8179 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
8180 : !REG_P (callee))
bbe777ea 8181 XEXP (operands[0], 0) = force_reg (Pmode, callee);
bac7fc85 8182
2d3a01a7 8183 if (detect_cmse_nonsecure_call (addr))
8184 {
8185 pat = gen_nonsecure_call_internal (operands[0], operands[1],
8186 operands[2]);
8187 emit_call_insn (pat);
8188 }
8189 else
8190 {
8191 pat = gen_call_internal (operands[0], operands[1], operands[2]);
8192 arm_emit_call_insn (pat, XEXP (operands[0], 0), false);
8193 }
bac7fc85 8194 DONE;
6c4c2133 8195 }"
8196)
d3373b54 8197
bac7fc85 8198(define_expand "call_internal"
3934ae0e 8199 [(parallel [(call (match_operand 0 "memory_operand")
8200 (match_operand 1 "general_operand"))
bac7fc85 8201 (use (match_operand 2 "" ""))
8202 (clobber (reg:SI LR_REGNUM))])])
8203
2d3a01a7 8204(define_expand "nonsecure_call_internal"
3934ae0e 8205 [(parallel [(call (unspec:SI [(match_operand 0 "memory_operand")]
2d3a01a7 8206 UNSPEC_NONSECURE_MEM)
3934ae0e 8207 (match_operand 1 "general_operand"))
2d3a01a7 8208 (use (match_operand 2 "" ""))
e27c5a70 8209 (clobber (reg:SI LR_REGNUM))])]
2d3a01a7 8210 "use_cmse"
8211 "
8212 {
8213 rtx tmp;
8214 tmp = copy_to_suggested_reg (XEXP (operands[0], 0),
e27c5a70 8215 gen_rtx_REG (SImode, R4_REGNUM),
2d3a01a7 8216 SImode);
8217
8218 operands[0] = replace_equiv_address (operands[0], tmp);
8219 }")
8220
f1039640 8221(define_insn "*call_reg_armv5"
d3373b54 8222 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
cffb2a26 8223 (match_operand 1 "" ""))
8224 (use (match_operand 2 "" ""))
bd5b4116 8225 (clobber (reg:SI LR_REGNUM))]
b232e6b5 8226 "TARGET_ARM && arm_arch5t && !SIBLING_CALL_P (insn)"
f1039640 8227 "blx%?\\t%0"
8228 [(set_attr "type" "call")]
8229)
8230
8231(define_insn "*call_reg_arm"
8232 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
8233 (match_operand 1 "" ""))
8234 (use (match_operand 2 "" ""))
8235 (clobber (reg:SI LR_REGNUM))]
b232e6b5 8236 "TARGET_ARM && !arm_arch5t && !SIBLING_CALL_P (insn)"
9c08d1fa 8237 "*
5565501b 8238 return output_call (operands);
cffb2a26 8239 "
8240 ;; length is worst case, normally it is only two
8241 [(set_attr "length" "12")
8242 (set_attr "type" "call")]
8243)
9c08d1fa 8244
89504fc1 8245
d3373b54 8246(define_expand "call_value"
e0698af7 8247 [(parallel [(set (match_operand 0 "" "")
3934ae0e 8248 (call (match_operand 1 "memory_operand")
8249 (match_operand 2 "general_operand")))
cffb2a26 8250 (use (match_operand 3 "" ""))
bd5b4116 8251 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 8252 "TARGET_EITHER"
6c4c2133 8253 "
8254 {
bac7fc85 8255 rtx pat, callee;
2d3a01a7 8256 tree addr = MEM_EXPR (operands[1]);
bbe777ea 8257
8258 /* In an untyped call, we can get NULL for operand 2. */
8259 if (operands[3] == 0)
8260 operands[3] = const0_rtx;
8261
de55252a 8262 /* Decide if we should generate indirect calls by loading the
8263 32-bit address of the callee into a register before performing the
8264 branch and link. */
8265 callee = XEXP (operands[1], 0);
8266 if (GET_CODE (callee) == SYMBOL_REF
8267 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
8268 : !REG_P (callee))
78fe751b 8269 XEXP (operands[1], 0) = force_reg (Pmode, callee);
bac7fc85 8270
2d3a01a7 8271 if (detect_cmse_nonsecure_call (addr))
8272 {
8273 pat = gen_nonsecure_call_value_internal (operands[0], operands[1],
8274 operands[2], operands[3]);
8275 emit_call_insn (pat);
8276 }
8277 else
8278 {
8279 pat = gen_call_value_internal (operands[0], operands[1],
8280 operands[2], operands[3]);
8281 arm_emit_call_insn (pat, XEXP (operands[1], 0), false);
8282 }
bac7fc85 8283 DONE;
6c4c2133 8284 }"
8285)
d3373b54 8286
bac7fc85 8287(define_expand "call_value_internal"
8288 [(parallel [(set (match_operand 0 "" "")
3934ae0e 8289 (call (match_operand 1 "memory_operand")
8290 (match_operand 2 "general_operand")))
bac7fc85 8291 (use (match_operand 3 "" ""))
8292 (clobber (reg:SI LR_REGNUM))])])
8293
2d3a01a7 8294(define_expand "nonsecure_call_value_internal"
8295 [(parallel [(set (match_operand 0 "" "")
3934ae0e 8296 (call (unspec:SI [(match_operand 1 "memory_operand")]
2d3a01a7 8297 UNSPEC_NONSECURE_MEM)
3934ae0e 8298 (match_operand 2 "general_operand")))
2d3a01a7 8299 (use (match_operand 3 "" ""))
e27c5a70 8300 (clobber (reg:SI LR_REGNUM))])]
2d3a01a7 8301 "use_cmse"
8302 "
8303 {
8304 rtx tmp;
8305 tmp = copy_to_suggested_reg (XEXP (operands[1], 0),
e27c5a70 8306 gen_rtx_REG (SImode, R4_REGNUM),
2d3a01a7 8307 SImode);
8308
8309 operands[1] = replace_equiv_address (operands[1], tmp);
8310 }")
8311
f1039640 8312(define_insn "*call_value_reg_armv5"
27ed6835 8313 [(set (match_operand 0 "" "")
755eb2b4 8314 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
cffb2a26 8315 (match_operand 2 "" "")))
bbe777ea 8316 (use (match_operand 3 "" ""))
bd5b4116 8317 (clobber (reg:SI LR_REGNUM))]
b232e6b5 8318 "TARGET_ARM && arm_arch5t && !SIBLING_CALL_P (insn)"
f1039640 8319 "blx%?\\t%1"
8320 [(set_attr "type" "call")]
8321)
8322
8323(define_insn "*call_value_reg_arm"
8324 [(set (match_operand 0 "" "")
8325 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
8326 (match_operand 2 "" "")))
8327 (use (match_operand 3 "" ""))
8328 (clobber (reg:SI LR_REGNUM))]
b232e6b5 8329 "TARGET_ARM && !arm_arch5t && !SIBLING_CALL_P (insn)"
9c08d1fa 8330 "*
215b30b3 8331 return output_call (&operands[1]);
cffb2a26 8332 "
8333 [(set_attr "length" "12")
8334 (set_attr "type" "call")]
8335)
9c08d1fa 8336
9c08d1fa 8337;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
8338;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
8339
f7fbdd4a 8340(define_insn "*call_symbol"
27ed6835 8341 [(call (mem:SI (match_operand:SI 0 "" ""))
cffb2a26 8342 (match_operand 1 "" ""))
bbe777ea 8343 (use (match_operand 2 "" ""))
bd5b4116 8344 (clobber (reg:SI LR_REGNUM))]
d68c2c10 8345 "TARGET_32BIT
33ae7c4b 8346 && !SIBLING_CALL_P (insn)
cffb2a26 8347 && (GET_CODE (operands[0]) == SYMBOL_REF)
de55252a 8348 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
6ebaa29d 8349 "*
8350 {
95f1e0d1 8351 rtx op = operands[0];
8352
8353 /* Switch mode now when possible. */
8354 if (SYMBOL_REF_DECL (op) && !TREE_PUBLIC (SYMBOL_REF_DECL (op))
b232e6b5 8355 && arm_arch5t && arm_change_mode_p (SYMBOL_REF_DECL (op)))
95f1e0d1 8356 return NEED_PLT_RELOC ? \"blx%?\\t%a0(PLT)\" : \"blx%?\\t(%a0)\";
8357
55c1e470 8358 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
6ebaa29d 8359 }"
cffb2a26 8360 [(set_attr "type" "call")]
8361)
9c08d1fa 8362
f7fbdd4a 8363(define_insn "*call_value_symbol"
ccd90aaa 8364 [(set (match_operand 0 "" "")
27ed6835 8365 (call (mem:SI (match_operand:SI 1 "" ""))
dd6d7504 8366 (match_operand:SI 2 "" "")))
bbe777ea 8367 (use (match_operand 3 "" ""))
bd5b4116 8368 (clobber (reg:SI LR_REGNUM))]
d68c2c10 8369 "TARGET_32BIT
33ae7c4b 8370 && !SIBLING_CALL_P (insn)
cffb2a26 8371 && (GET_CODE (operands[1]) == SYMBOL_REF)
de55252a 8372 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
6ebaa29d 8373 "*
8374 {
95f1e0d1 8375 rtx op = operands[1];
8376
8377 /* Switch mode now when possible. */
8378 if (SYMBOL_REF_DECL (op) && !TREE_PUBLIC (SYMBOL_REF_DECL (op))
b232e6b5 8379 && arm_arch5t && arm_change_mode_p (SYMBOL_REF_DECL (op)))
3f6b66fa 8380 return NEED_PLT_RELOC ? \"blx%?\\t%a1(PLT)\" : \"blx%?\\t(%a1)\";
95f1e0d1 8381
55c1e470 8382 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
6ebaa29d 8383 }"
cffb2a26 8384 [(set_attr "type" "call")]
8385)
8386
ca373797 8387(define_expand "sibcall_internal"
3934ae0e 8388 [(parallel [(call (match_operand 0 "memory_operand")
8389 (match_operand 1 "general_operand"))
ca373797 8390 (return)
8391 (use (match_operand 2 "" ""))])])
8392
1c494086 8393;; We may also be able to do sibcalls for Thumb, but it's much harder...
8394(define_expand "sibcall"
3934ae0e 8395 [(parallel [(call (match_operand 0 "memory_operand")
8396 (match_operand 1 "general_operand"))
2ba80634 8397 (return)
8398 (use (match_operand 2 "" ""))])]
d68c2c10 8399 "TARGET_32BIT"
1c494086 8400 "
8401 {
ca373797 8402 rtx pat;
8403
3112c3f7 8404 if ((!REG_P (XEXP (operands[0], 0))
8405 && GET_CODE (XEXP (operands[0], 0)) != SYMBOL_REF)
8406 || (GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
8407 && arm_is_long_call_p (SYMBOL_REF_DECL (XEXP (operands[0], 0)))))
33ae7c4b 8408 XEXP (operands[0], 0) = force_reg (SImode, XEXP (operands[0], 0));
8409
1c494086 8410 if (operands[2] == NULL_RTX)
8411 operands[2] = const0_rtx;
ca373797 8412
8413 pat = gen_sibcall_internal (operands[0], operands[1], operands[2]);
8414 arm_emit_call_insn (pat, operands[0], true);
8415 DONE;
1c494086 8416 }"
8417)
8418
ca373797 8419(define_expand "sibcall_value_internal"
8420 [(parallel [(set (match_operand 0 "" "")
3934ae0e 8421 (call (match_operand 1 "memory_operand")
8422 (match_operand 2 "general_operand")))
ca373797 8423 (return)
8424 (use (match_operand 3 "" ""))])])
8425
1c494086 8426(define_expand "sibcall_value"
ccd90aaa 8427 [(parallel [(set (match_operand 0 "" "")
3934ae0e 8428 (call (match_operand 1 "memory_operand")
8429 (match_operand 2 "general_operand")))
2ba80634 8430 (return)
8431 (use (match_operand 3 "" ""))])]
d68c2c10 8432 "TARGET_32BIT"
1c494086 8433 "
8434 {
ca373797 8435 rtx pat;
8436
3112c3f7 8437 if ((!REG_P (XEXP (operands[1], 0))
8438 && GET_CODE (XEXP (operands[1], 0)) != SYMBOL_REF)
8439 || (GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
8440 && arm_is_long_call_p (SYMBOL_REF_DECL (XEXP (operands[1], 0)))))
33ae7c4b 8441 XEXP (operands[1], 0) = force_reg (SImode, XEXP (operands[1], 0));
8442
1c494086 8443 if (operands[3] == NULL_RTX)
8444 operands[3] = const0_rtx;
ca373797 8445
8446 pat = gen_sibcall_value_internal (operands[0], operands[1],
8447 operands[2], operands[3]);
8448 arm_emit_call_insn (pat, operands[1], true);
8449 DONE;
1c494086 8450 }"
8451)
8452
8453(define_insn "*sibcall_insn"
84ce8e5c 8454 [(call (mem:SI (match_operand:SI 0 "call_insn_operand" "Cs, US"))
1c494086 8455 (match_operand 1 "" ""))
2ba80634 8456 (return)
8457 (use (match_operand 2 "" ""))]
33ae7c4b 8458 "TARGET_32BIT && SIBLING_CALL_P (insn)"
1c494086 8459 "*
33ae7c4b 8460 if (which_alternative == 1)
8461 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
8462 else
8463 {
b232e6b5 8464 if (arm_arch5t || arm_arch4t)
947d113e 8465 return \"bx%?\\t%0\\t%@ indirect register sibling call\";
33ae7c4b 8466 else
8467 return \"mov%?\\t%|pc, %0\\t%@ indirect register sibling call\";
8468 }
1c494086 8469 "
8470 [(set_attr "type" "call")]
8471)
8472
8473(define_insn "*sibcall_value_insn"
84ce8e5c 8474 [(set (match_operand 0 "" "")
8475 (call (mem:SI (match_operand:SI 1 "call_insn_operand" "Cs,US"))
1c494086 8476 (match_operand 2 "" "")))
2ba80634 8477 (return)
8478 (use (match_operand 3 "" ""))]
33ae7c4b 8479 "TARGET_32BIT && SIBLING_CALL_P (insn)"
1c494086 8480 "*
33ae7c4b 8481 if (which_alternative == 1)
8482 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
8483 else
8484 {
b232e6b5 8485 if (arm_arch5t || arm_arch4t)
84ce8e5c 8486 return \"bx%?\\t%1\";
33ae7c4b 8487 else
8488 return \"mov%?\\t%|pc, %1\\t@ indirect sibling call \";
8489 }
1c494086 8490 "
8491 [(set_attr "type" "call")]
8492)
8493
0686440e 8494(define_expand "<return_str>return"
9b23f0a7 8495 [(RETURNS)]
8cba51a5 8496 "(TARGET_ARM || (TARGET_THUMB2
8497 && ARM_FUNC_TYPE (arm_current_func_type ()) == ARM_FT_NORMAL
8498 && !IS_STACKALIGN (arm_current_func_type ())))
0686440e 8499 <return_cond_false>"
8cba51a5 8500 "
8501 {
8502 if (TARGET_THUMB2)
8503 {
0686440e 8504 thumb2_expand_return (<return_simple_p>);
8cba51a5 8505 DONE;
8506 }
8507 }
8508 "
8509)
d68c2c10 8510
9c08d1fa 8511;; Often the return insn will be the same as loading from memory, so set attr
d68c2c10 8512(define_insn "*arm_return"
9c08d1fa 8513 [(return)]
cffb2a26 8514 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
9c08d1fa 8515 "*
9c08d1fa 8516 {
cffb2a26 8517 if (arm_ccfsm_state == 2)
8518 {
8519 arm_ccfsm_state += 2;
8520 return \"\";
8521 }
e2549f81 8522 return output_return_instruction (const_true_rtx, true, false, false);
cffb2a26 8523 }"
9f2c2a36 8524 [(set_attr "type" "load_4")
755eb2b4 8525 (set_attr "length" "12")
0d66636f 8526 (set_attr "predicable" "yes")]
cffb2a26 8527)
9c08d1fa 8528
0686440e 8529(define_insn "*cond_<return_str>return"
9c08d1fa 8530 [(set (pc)
8fa3ba89 8531 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 8532 [(match_operand 1 "cc_register" "") (const_int 0)])
9b23f0a7 8533 (RETURNS)
9c08d1fa 8534 (pc)))]
0686440e 8535 "TARGET_ARM <return_cond_true>"
9c08d1fa 8536 "*
8fa3ba89 8537 {
8538 if (arm_ccfsm_state == 2)
8539 {
8540 arm_ccfsm_state += 2;
8541 return \"\";
8542 }
0686440e 8543 return output_return_instruction (operands[0], true, false,
8544 <return_simple_p>);
8fa3ba89 8545 }"
8546 [(set_attr "conds" "use")
755eb2b4 8547 (set_attr "length" "12")
9f2c2a36 8548 (set_attr "type" "load_4")]
8fa3ba89 8549)
9c08d1fa 8550
0686440e 8551(define_insn "*cond_<return_str>return_inverted"
9c08d1fa 8552 [(set (pc)
8fa3ba89 8553 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 8554 [(match_operand 1 "cc_register" "") (const_int 0)])
9c08d1fa 8555 (pc)
9b23f0a7 8556 (RETURNS)))]
0686440e 8557 "TARGET_ARM <return_cond_true>"
9c08d1fa 8558 "*
8fa3ba89 8559 {
8560 if (arm_ccfsm_state == 2)
8561 {
8562 arm_ccfsm_state += 2;
8563 return \"\";
8564 }
0686440e 8565 return output_return_instruction (operands[0], true, true,
8566 <return_simple_p>);
8fa3ba89 8567 }"
8568 [(set_attr "conds" "use")
37a1317b 8569 (set_attr "length" "12")
9f2c2a36 8570 (set_attr "type" "load_4")]
8fa3ba89 8571)
9c08d1fa 8572
e2549f81 8573(define_insn "*arm_simple_return"
8574 [(simple_return)]
8575 "TARGET_ARM"
8576 "*
8577 {
8578 if (arm_ccfsm_state == 2)
8579 {
8580 arm_ccfsm_state += 2;
8581 return \"\";
8582 }
8583 return output_return_instruction (const_true_rtx, true, false, true);
8584 }"
8585 [(set_attr "type" "branch")
8586 (set_attr "length" "4")
8587 (set_attr "predicable" "yes")]
8588)
8589
68121397 8590;; Generate a sequence of instructions to determine if the processor is
8591;; in 26-bit or 32-bit mode, and return the appropriate return address
8592;; mask.
8593
8594(define_expand "return_addr_mask"
8595 [(set (match_dup 1)
8596 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8597 (const_int 0)))
3934ae0e 8598 (set (match_operand:SI 0 "s_register_operand")
68121397 8599 (if_then_else:SI (eq (match_dup 1) (const_int 0))
8600 (const_int -1)
8601 (const_int 67108860)))] ; 0x03fffffc
8602 "TARGET_ARM"
8603 "
62eddbd4 8604 operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
68121397 8605 ")
8606
8607(define_insn "*check_arch2"
8608 [(set (match_operand:CC_NOOV 0 "cc_register" "")
8609 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8610 (const_int 0)))]
8611 "TARGET_ARM"
8612 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
8613 [(set_attr "length" "8")
1b7da4ac 8614 (set_attr "conds" "set")
8615 (set_attr "type" "multiple")]
68121397 8616)
8617
9c08d1fa 8618;; Call subroutine returning any type.
8619
8620(define_expand "untyped_call"
8621 [(parallel [(call (match_operand 0 "" "")
8622 (const_int 0))
8623 (match_operand 1 "" "")
8624 (match_operand 2 "" "")])]
ccd90aaa 8625 "TARGET_EITHER"
9c08d1fa 8626 "
215b30b3 8627 {
8628 int i;
ccd90aaa 8629 rtx par = gen_rtx_PARALLEL (VOIDmode,
8630 rtvec_alloc (XVECLEN (operands[2], 0)));
8631 rtx addr = gen_reg_rtx (Pmode);
8632 rtx mem;
8633 int size = 0;
9c08d1fa 8634
ccd90aaa 8635 emit_move_insn (addr, XEXP (operands[1], 0));
8636 mem = change_address (operands[1], BLKmode, addr);
9c08d1fa 8637
215b30b3 8638 for (i = 0; i < XVECLEN (operands[2], 0); i++)
8639 {
ccd90aaa 8640 rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
9c08d1fa 8641
ccd90aaa 8642 /* Default code only uses r0 as a return value, but we could
8643 be using anything up to 4 registers. */
8644 if (REGNO (src) == R0_REGNUM)
8645 src = gen_rtx_REG (TImode, R0_REGNUM);
8646
8647 XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
8648 GEN_INT (size));
8649 size += GET_MODE_SIZE (GET_MODE (src));
8650 }
8651
7f265a08 8652 emit_call_insn (gen_call_value (par, operands[0], const0_rtx, NULL));
ccd90aaa 8653
8654 size = 0;
8655
8656 for (i = 0; i < XVECLEN (par, 0); i++)
8657 {
8658 HOST_WIDE_INT offset = 0;
8659 rtx reg = XEXP (XVECEXP (par, 0, i), 0);
8660
8661 if (size != 0)
29c05e22 8662 emit_move_insn (addr, plus_constant (Pmode, addr, size));
ccd90aaa 8663
8664 mem = change_address (mem, GET_MODE (reg), NULL);
8665 if (REGNO (reg) == R0_REGNUM)
8666 {
8667 /* On thumb we have to use a write-back instruction. */
320ea44d 8668 emit_insn (arm_gen_store_multiple (arm_regs_in_sequence, 4, addr,
8669 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
ccd90aaa 8670 size = TARGET_ARM ? 16 : 0;
8671 }
8672 else
8673 {
8674 emit_move_insn (mem, reg);
8675 size = GET_MODE_SIZE (GET_MODE (reg));
8676 }
215b30b3 8677 }
9c08d1fa 8678
215b30b3 8679 /* The optimizer does not know that the call sets the function value
8680 registers we stored in the result block. We avoid problems by
8681 claiming that all hard registers are used and clobbered at this
8682 point. */
8683 emit_insn (gen_blockage ());
8684
8685 DONE;
8686 }"
8687)
9c08d1fa 8688
ccd90aaa 8689(define_expand "untyped_return"
3934ae0e 8690 [(match_operand:BLK 0 "memory_operand")
ccd90aaa 8691 (match_operand 1 "" "")]
8692 "TARGET_EITHER"
8693 "
8694 {
8695 int i;
8696 rtx addr = gen_reg_rtx (Pmode);
8697 rtx mem;
8698 int size = 0;
8699
8700 emit_move_insn (addr, XEXP (operands[0], 0));
8701 mem = change_address (operands[0], BLKmode, addr);
8702
8703 for (i = 0; i < XVECLEN (operands[1], 0); i++)
8704 {
8705 HOST_WIDE_INT offset = 0;
8706 rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
8707
8708 if (size != 0)
29c05e22 8709 emit_move_insn (addr, plus_constant (Pmode, addr, size));
ccd90aaa 8710
8711 mem = change_address (mem, GET_MODE (reg), NULL);
8712 if (REGNO (reg) == R0_REGNUM)
8713 {
8714 /* On thumb we have to use a write-back instruction. */
320ea44d 8715 emit_insn (arm_gen_load_multiple (arm_regs_in_sequence, 4, addr,
8716 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
ccd90aaa 8717 size = TARGET_ARM ? 16 : 0;
8718 }
8719 else
8720 {
8721 emit_move_insn (reg, mem);
8722 size = GET_MODE_SIZE (GET_MODE (reg));
8723 }
8724 }
8725
8726 /* Emit USE insns before the return. */
8727 for (i = 0; i < XVECLEN (operands[1], 0); i++)
18b42941 8728 emit_use (SET_DEST (XVECEXP (operands[1], 0, i)));
ccd90aaa 8729
8730 /* Construct the return. */
8731 expand_naked_return ();
8732
8733 DONE;
8734 }"
8735)
8736
9c08d1fa 8737;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
8738;; all of memory. This blocks insns from being moved across this point.
8739
8740(define_insn "blockage"
e1159bbe 8741 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
cffb2a26 8742 "TARGET_EITHER"
9c08d1fa 8743 ""
cffb2a26 8744 [(set_attr "length" "0")
8745 (set_attr "type" "block")]
8746)
9c08d1fa 8747
80c63fc3 8748;; Since we hard code r0 here use the 'o' constraint to prevent
8749;; provoking undefined behaviour in the hardware with putting out
8750;; auto-increment operations with potentially r0 as the base register.
706dca65 8751(define_insn "probe_stack"
80c63fc3 8752 [(set (match_operand:SI 0 "memory_operand" "=o")
f8570abe 8753 (unspec:SI [(const_int 0)] UNSPEC_PROBE_STACK))]
706dca65 8754 "TARGET_32BIT"
154ae8e6 8755 "str%?\\tr0, %0"
9f2c2a36 8756 [(set_attr "type" "store_4")
706dca65 8757 (set_attr "predicable" "yes")]
8758)
8759
8760(define_insn "probe_stack_range"
8761 [(set (match_operand:SI 0 "register_operand" "=r")
8762 (unspec_volatile:SI [(match_operand:SI 1 "register_operand" "0")
8763 (match_operand:SI 2 "register_operand" "r")]
dd8aabc9 8764 VUNSPEC_PROBE_STACK_RANGE))]
706dca65 8765 "TARGET_32BIT"
8766{
8767 return output_probe_stack_range (operands[0], operands[2]);
8768}
8769 [(set_attr "type" "multiple")
8770 (set_attr "conds" "clob")]
8771)
8772
f98495d9 8773;; Named patterns for stack smashing protection.
8774(define_expand "stack_protect_combined_set"
8775 [(parallel
3934ae0e 8776 [(set (match_operand:SI 0 "memory_operand")
8777 (unspec:SI [(match_operand:SI 1 "guard_operand")]
f98495d9 8778 UNSPEC_SP_SET))
8779 (clobber (match_scratch:SI 2 ""))
8780 (clobber (match_scratch:SI 3 ""))])]
8781 ""
8782 ""
8783)
8784
8785;; Use a separate insn from the above expand to be able to have the mem outside
8786;; the operand #1 when register allocation comes. This is needed to avoid LRA
8787;; try to reload the guard since we need to control how PIC access is done in
8788;; the -fpic/-fPIC case (see COMPUTE_NOW parameter when calling
8789;; legitimize_pic_address ()).
8790(define_insn_and_split "*stack_protect_combined_set_insn"
8791 [(set (match_operand:SI 0 "memory_operand" "=m,m")
8792 (unspec:SI [(mem:SI (match_operand:SI 1 "guard_addr_operand" "X,X"))]
8793 UNSPEC_SP_SET))
8794 (clobber (match_scratch:SI 2 "=&l,&r"))
8795 (clobber (match_scratch:SI 3 "=&l,&r"))]
8796 ""
8797 "#"
8798 "reload_completed"
8799 [(parallel [(set (match_dup 0) (unspec:SI [(mem:SI (match_dup 2))]
8800 UNSPEC_SP_SET))
8801 (clobber (match_dup 2))])]
8802 "
8803{
8804 if (flag_pic)
8805 {
8806 /* Forces recomputing of GOT base now. */
8807 legitimize_pic_address (operands[1], SImode, operands[2], operands[3],
8808 true /*compute_now*/);
8809 }
8810 else
8811 {
8812 if (address_operand (operands[1], SImode))
8813 operands[2] = operands[1];
8814 else
8815 {
8816 rtx mem = XEXP (force_const_mem (SImode, operands[1]), 0);
8817 emit_move_insn (operands[2], mem);
8818 }
8819 }
8820}"
8821 [(set_attr "arch" "t1,32")]
8822)
8823
8824(define_insn "*stack_protect_set_insn"
8825 [(set (match_operand:SI 0 "memory_operand" "=m,m")
8826 (unspec:SI [(mem:SI (match_operand:SI 1 "register_operand" "+&l,&r"))]
8827 UNSPEC_SP_SET))
8828 (clobber (match_dup 1))]
8829 ""
8830 "@
8831 ldr\\t%1, [%1]\;str\\t%1, %0\;movs\t%1,#0
8832 ldr\\t%1, [%1]\;str\\t%1, %0\;mov\t%1,#0"
8833 [(set_attr "length" "8,12")
8834 (set_attr "conds" "clob,nocond")
8835 (set_attr "type" "multiple")
8836 (set_attr "arch" "t1,32")]
8837)
8838
8839(define_expand "stack_protect_combined_test"
8840 [(parallel
8841 [(set (pc)
8842 (if_then_else
3934ae0e 8843 (eq (match_operand:SI 0 "memory_operand")
8844 (unspec:SI [(match_operand:SI 1 "guard_operand")]
f98495d9 8845 UNSPEC_SP_TEST))
8846 (label_ref (match_operand 2))
8847 (pc)))
8848 (clobber (match_scratch:SI 3 ""))
8849 (clobber (match_scratch:SI 4 ""))
8850 (clobber (reg:CC CC_REGNUM))])]
8851 ""
8852 ""
8853)
8854
8855;; Use a separate insn from the above expand to be able to have the mem outside
8856;; the operand #1 when register allocation comes. This is needed to avoid LRA
8857;; try to reload the guard since we need to control how PIC access is done in
8858;; the -fpic/-fPIC case (see COMPUTE_NOW parameter when calling
8859;; legitimize_pic_address ()).
8860(define_insn_and_split "*stack_protect_combined_test_insn"
8861 [(set (pc)
8862 (if_then_else
8863 (eq (match_operand:SI 0 "memory_operand" "m,m")
8864 (unspec:SI [(mem:SI (match_operand:SI 1 "guard_addr_operand" "X,X"))]
8865 UNSPEC_SP_TEST))
8866 (label_ref (match_operand 2))
8867 (pc)))
8868 (clobber (match_scratch:SI 3 "=&l,&r"))
8869 (clobber (match_scratch:SI 4 "=&l,&r"))
8870 (clobber (reg:CC CC_REGNUM))]
8871 ""
8872 "#"
8873 "reload_completed"
8874 [(const_int 0)]
8875{
8876 rtx eq;
8877
8878 if (flag_pic)
8879 {
8880 /* Forces recomputing of GOT base now. */
8881 legitimize_pic_address (operands[1], SImode, operands[3], operands[4],
8882 true /*compute_now*/);
8883 }
8884 else
8885 {
8886 if (address_operand (operands[1], SImode))
8887 operands[3] = operands[1];
8888 else
8889 {
8890 rtx mem = XEXP (force_const_mem (SImode, operands[1]), 0);
8891 emit_move_insn (operands[3], mem);
8892 }
8893 }
8894 if (TARGET_32BIT)
8895 {
8896 emit_insn (gen_arm_stack_protect_test_insn (operands[4], operands[0],
8897 operands[3]));
8898 rtx cc_reg = gen_rtx_REG (CC_Zmode, CC_REGNUM);
8899 eq = gen_rtx_EQ (CC_Zmode, cc_reg, const0_rtx);
8900 emit_jump_insn (gen_arm_cond_branch (operands[2], eq, cc_reg));
8901 }
8902 else
8903 {
8904 emit_insn (gen_thumb1_stack_protect_test_insn (operands[4], operands[0],
8905 operands[3]));
8906 eq = gen_rtx_EQ (VOIDmode, operands[4], const0_rtx);
8907 emit_jump_insn (gen_cbranchsi4 (eq, operands[4], const0_rtx,
8908 operands[2]));
8909 }
8910 DONE;
8911}
8912 [(set_attr "arch" "t1,32")]
8913)
8914
8915(define_insn "arm_stack_protect_test_insn"
8916 [(set (reg:CC_Z CC_REGNUM)
8917 (compare:CC_Z (unspec:SI [(match_operand:SI 1 "memory_operand" "m,m")
8918 (mem:SI (match_operand:SI 2 "register_operand" "+l,r"))]
8919 UNSPEC_SP_TEST)
8920 (const_int 0)))
8921 (clobber (match_operand:SI 0 "register_operand" "=&l,&r"))
8922 (clobber (match_dup 2))]
8923 "TARGET_32BIT"
8924 "ldr\t%0, [%2]\;ldr\t%2, %1\;eors\t%0, %2, %0"
8925 [(set_attr "length" "8,12")
8926 (set_attr "conds" "set")
8927 (set_attr "type" "multiple")
8928 (set_attr "arch" "t,32")]
8929)
8930
f7fbdd4a 8931(define_expand "casesi"
3934ae0e 8932 [(match_operand:SI 0 "s_register_operand") ; index to jump on
8933 (match_operand:SI 1 "const_int_operand") ; lower bound
8934 (match_operand:SI 2 "const_int_operand") ; total range
f7fbdd4a 8935 (match_operand:SI 3 "" "") ; table label
8936 (match_operand:SI 4 "" "")] ; Out of range label
9753b549 8937 "(TARGET_32BIT || optimize_size || flag_pic) && !target_pure_code"
f7fbdd4a 8938 "
215b30b3 8939 {
e6ac8414 8940 enum insn_code code;
215b30b3 8941 if (operands[1] != const0_rtx)
8942 {
e6ac8414 8943 rtx reg = gen_reg_rtx (SImode);
f7fbdd4a 8944
215b30b3 8945 emit_insn (gen_addsi3 (reg, operands[0],
d022fa24 8946 gen_int_mode (-INTVAL (operands[1]),
8947 SImode)));
215b30b3 8948 operands[0] = reg;
8949 }
9c08d1fa 8950
25f905c2 8951 if (TARGET_ARM)
e6ac8414 8952 code = CODE_FOR_arm_casesi_internal;
3db2019b 8953 else if (TARGET_THUMB1)
e6ac8414 8954 code = CODE_FOR_thumb1_casesi_internal_pic;
25f905c2 8955 else if (flag_pic)
e6ac8414 8956 code = CODE_FOR_thumb2_casesi_internal_pic;
25f905c2 8957 else
e6ac8414 8958 code = CODE_FOR_thumb2_casesi_internal;
8959
8960 if (!insn_data[(int) code].operand[1].predicate(operands[2], SImode))
8961 operands[2] = force_reg (SImode, operands[2]);
8962
8963 emit_jump_insn (GEN_FCN ((int) code) (operands[0], operands[2],
8964 operands[3], operands[4]));
215b30b3 8965 DONE;
8966 }"
8967)
f7fbdd4a 8968
f082f1c4 8969;; The USE in this pattern is needed to tell flow analysis that this is
8970;; a CASESI insn. It has no other purpose.
b634d96a 8971(define_expand "arm_casesi_internal"
8972 [(parallel [(set (pc)
8973 (if_then_else
8974 (leu (match_operand:SI 0 "s_register_operand")
8975 (match_operand:SI 1 "arm_rhs_operand"))
8976 (match_dup 4)
8977 (label_ref:SI (match_operand 3 ""))))
8978 (clobber (reg:CC CC_REGNUM))
8979 (use (label_ref:SI (match_operand 2 "")))])]
8980 "TARGET_ARM"
8981{
8982 operands[4] = gen_rtx_MULT (SImode, operands[0], GEN_INT (4));
8983 operands[4] = gen_rtx_PLUS (SImode, operands[4],
8984 gen_rtx_LABEL_REF (SImode, operands[2]));
8985 operands[4] = gen_rtx_MEM (SImode, operands[4]);
8986 MEM_READONLY_P (operands[4]) = 1;
8987 MEM_NOTRAP_P (operands[4]) = 1;
8988})
8989
8990(define_insn "*arm_casesi_internal"
f082f1c4 8991 [(parallel [(set (pc)
8992 (if_then_else
8993 (leu (match_operand:SI 0 "s_register_operand" "r")
8994 (match_operand:SI 1 "arm_rhs_operand" "rI"))
8995 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
b634d96a 8996 (label_ref:SI (match_operand 2 "" ""))))
8997 (label_ref:SI (match_operand 3 "" ""))))
bd5b4116 8998 (clobber (reg:CC CC_REGNUM))
b634d96a 8999 (use (label_ref:SI (match_dup 2)))])]
cffb2a26 9000 "TARGET_ARM"
f7fbdd4a 9001 "*
0d66636f 9002 if (flag_pic)
9003 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
9004 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
9005 "
9006 [(set_attr "conds" "clob")
1b7da4ac 9007 (set_attr "length" "12")
9008 (set_attr "type" "multiple")]
0d66636f 9009)
9c08d1fa 9010
cffb2a26 9011(define_expand "indirect_jump"
9c08d1fa 9012 [(set (pc)
3934ae0e 9013 (match_operand:SI 0 "s_register_operand"))]
cffb2a26 9014 "TARGET_EITHER"
25f905c2 9015 "
9016 /* Thumb-2 doesn't have mov pc, reg. Explicitly set the low bit of the
9017 address and use bx. */
9018 if (TARGET_THUMB2)
9019 {
9020 rtx tmp;
9021 tmp = gen_reg_rtx (SImode);
9022 emit_insn (gen_iorsi3 (tmp, operands[0], GEN_INT(1)));
9023 operands[0] = tmp;
9024 }
9025 "
cffb2a26 9026)
9027
f1039640 9028;; NB Never uses BX.
cffb2a26 9029(define_insn "*arm_indirect_jump"
9030 [(set (pc)
9031 (match_operand:SI 0 "s_register_operand" "r"))]
9032 "TARGET_ARM"
9033 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
1b7da4ac 9034 [(set_attr "predicable" "yes")
9035 (set_attr "type" "branch")]
cffb2a26 9036)
9c08d1fa 9037
f7fbdd4a 9038(define_insn "*load_indirect_jump"
9c08d1fa 9039 [(set (pc)
9040 (match_operand:SI 0 "memory_operand" "m"))]
cffb2a26 9041 "TARGET_ARM"
9042 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
9f2c2a36 9043 [(set_attr "type" "load_4")
61a2d04c 9044 (set_attr "pool_range" "4096")
9045 (set_attr "neg_pool_range" "4084")
0d66636f 9046 (set_attr "predicable" "yes")]
cffb2a26 9047)
9048
9c08d1fa 9049\f
9050;; Misc insns
9051
9052(define_insn "nop"
9053 [(const_int 0)]
cffb2a26 9054 "TARGET_EITHER"
3ef90e77 9055 "nop"
cffb2a26 9056 [(set (attr "length")
9057 (if_then_else (eq_attr "is_thumb" "yes")
9058 (const_int 2)
1b7da4ac 9059 (const_int 4)))
9060 (set_attr "type" "mov_reg")]
cffb2a26 9061)
9062
ad9d4399 9063(define_insn "trap"
9064 [(trap_if (const_int 1) (const_int 0))]
9065 ""
9066 "*
9067 if (TARGET_ARM)
9068 return \".inst\\t0xe7f000f0\";
9069 else
9070 return \".inst\\t0xdeff\";
9071 "
9072 [(set (attr "length")
9073 (if_then_else (eq_attr "is_thumb" "yes")
9074 (const_int 2)
9075 (const_int 4)))
9076 (set_attr "type" "trap")
9077 (set_attr "conds" "unconditional")]
9078)
9079
9c08d1fa 9080\f
9081;; Patterns to allow combination of arithmetic, cond code and shifts
9082
0abea32c 9083(define_insn "*<arith_shift_insn>_multsi"
9084 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9b23f0a7 9085 (SHIFTABLE_OPS:SI
0abea32c 9086 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
9087 (match_operand:SI 3 "power_of_two_operand" ""))
9088 (match_operand:SI 1 "s_register_operand" "rk,<t2_binop0>")))]
d5d4dc8d 9089 "TARGET_32BIT"
0abea32c 9090 "<arith_shift_insn>%?\\t%0, %1, %2, lsl %b3"
9091 [(set_attr "predicable" "yes")
753d9835 9092 (set_attr "shift" "2")
0abea32c 9093 (set_attr "arch" "a,t2")
9094 (set_attr "type" "alu_shift_imm")])
9095
9096(define_insn "*<arith_shift_insn>_shiftsi"
9097 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9b23f0a7 9098 (SHIFTABLE_OPS:SI
0abea32c 9099 (match_operator:SI 2 "shift_nomul_operator"
9100 [(match_operand:SI 3 "s_register_operand" "r,r,r")
9101 (match_operand:SI 4 "shift_amount_operand" "M,M,r")])
9102 (match_operand:SI 1 "s_register_operand" "rk,<t2_binop0>,rk")))]
a021b821 9103 "TARGET_32BIT && GET_CODE (operands[2]) != MULT"
0abea32c 9104 "<arith_shift_insn>%?\\t%0, %1, %3%S2"
344495ea 9105 [(set_attr "predicable" "yes")
753d9835 9106 (set_attr "shift" "3")
0abea32c 9107 (set_attr "arch" "a,t2,a")
9108 (set_attr "type" "alu_shift_imm,alu_shift_imm,alu_shift_reg")])
9c08d1fa 9109
d7863cfe 9110(define_split
9111 [(set (match_operand:SI 0 "s_register_operand" "")
9112 (match_operator:SI 1 "shiftable_operator"
9113 [(match_operator:SI 2 "shiftable_operator"
9114 [(match_operator:SI 3 "shift_operator"
9115 [(match_operand:SI 4 "s_register_operand" "")
9116 (match_operand:SI 5 "reg_or_int_operand" "")])
9117 (match_operand:SI 6 "s_register_operand" "")])
9118 (match_operand:SI 7 "arm_rhs_operand" "")]))
9119 (clobber (match_operand:SI 8 "s_register_operand" ""))]
d5d4dc8d 9120 "TARGET_32BIT"
d7863cfe 9121 [(set (match_dup 8)
9122 (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
9123 (match_dup 6)]))
9124 (set (match_dup 0)
9125 (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
9126 "")
9127
f7fbdd4a 9128(define_insn "*arith_shiftsi_compare0"
bd5b4116 9129 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 9130 (compare:CC_NOOV
9131 (match_operator:SI 1 "shiftable_operator"
9132 [(match_operator:SI 3 "shift_operator"
9133 [(match_operand:SI 4 "s_register_operand" "r,r")
9134 (match_operand:SI 5 "shift_amount_operand" "M,r")])
9135 (match_operand:SI 2 "s_register_operand" "r,r")])
9136 (const_int 0)))
9137 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 9138 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
9139 (match_dup 2)]))]
d5d4dc8d 9140 "TARGET_32BIT"
3ef90e77 9141 "%i1s%?\\t%0, %2, %4%S3"
344495ea 9142 [(set_attr "conds" "set")
331beb1a 9143 (set_attr "shift" "4")
d5d4dc8d 9144 (set_attr "arch" "32,a")
d82e788e 9145 (set_attr "type" "alus_shift_imm,alus_shift_reg")])
9c08d1fa 9146
f7fbdd4a 9147(define_insn "*arith_shiftsi_compare0_scratch"
bd5b4116 9148 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 9149 (compare:CC_NOOV
9150 (match_operator:SI 1 "shiftable_operator"
9151 [(match_operator:SI 3 "shift_operator"
9152 [(match_operand:SI 4 "s_register_operand" "r,r")
9153 (match_operand:SI 5 "shift_amount_operand" "M,r")])
9154 (match_operand:SI 2 "s_register_operand" "r,r")])
9155 (const_int 0)))
9156 (clobber (match_scratch:SI 0 "=r,r"))]
9157 "TARGET_32BIT"
3ef90e77 9158 "%i1s%?\\t%0, %2, %4%S3"
344495ea 9159 [(set_attr "conds" "set")
331beb1a 9160 (set_attr "shift" "4")
d5d4dc8d 9161 (set_attr "arch" "32,a")
d82e788e 9162 (set_attr "type" "alus_shift_imm,alus_shift_reg")])
9c08d1fa 9163
f7fbdd4a 9164(define_insn "*sub_shiftsi"
d5d4dc8d 9165 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9166 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
9c08d1fa 9167 (match_operator:SI 2 "shift_operator"
d5d4dc8d 9168 [(match_operand:SI 3 "s_register_operand" "r,r")
9169 (match_operand:SI 4 "shift_amount_operand" "M,r")])))]
9170 "TARGET_32BIT"
6c4c2133 9171 "sub%?\\t%0, %1, %3%S2"
344495ea 9172 [(set_attr "predicable" "yes")
2df5a382 9173 (set_attr "predicable_short_it" "no")
331beb1a 9174 (set_attr "shift" "3")
d5d4dc8d 9175 (set_attr "arch" "32,a")
d82e788e 9176 (set_attr "type" "alus_shift_imm,alus_shift_reg")])
9c08d1fa 9177
f7fbdd4a 9178(define_insn "*sub_shiftsi_compare0"
bd5b4116 9179 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 9180 (compare:CC_NOOV
d82e788e 9181 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
40dbec34 9182 (match_operator:SI 2 "shift_operator"
d82e788e 9183 [(match_operand:SI 3 "s_register_operand" "r,r,r")
9184 (match_operand:SI 4 "shift_amount_operand" "M,r,M")]))
40dbec34 9185 (const_int 0)))
d82e788e 9186 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
d5d4dc8d 9187 (minus:SI (match_dup 1)
9188 (match_op_dup 2 [(match_dup 3) (match_dup 4)])))]
9189 "TARGET_32BIT"
3ef90e77 9190 "subs%?\\t%0, %1, %3%S2"
344495ea 9191 [(set_attr "conds" "set")
a2cd141b 9192 (set_attr "shift" "3")
d82e788e 9193 (set_attr "arch" "32,a,a")
9194 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
9c08d1fa 9195
f7fbdd4a 9196(define_insn "*sub_shiftsi_compare0_scratch"
bd5b4116 9197 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 9198 (compare:CC_NOOV
d82e788e 9199 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
40dbec34 9200 (match_operator:SI 2 "shift_operator"
d82e788e 9201 [(match_operand:SI 3 "s_register_operand" "r,r,r")
9202 (match_operand:SI 4 "shift_amount_operand" "M,r,M")]))
40dbec34 9203 (const_int 0)))
d82e788e 9204 (clobber (match_scratch:SI 0 "=r,r,r"))]
d5d4dc8d 9205 "TARGET_32BIT"
3ef90e77 9206 "subs%?\\t%0, %1, %3%S2"
344495ea 9207 [(set_attr "conds" "set")
a2cd141b 9208 (set_attr "shift" "3")
d82e788e 9209 (set_attr "arch" "32,a,a")
9210 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
9c08d1fa 9211\f
9212
190efb17 9213(define_insn_and_split "*and_scc"
9c08d1fa 9214 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9215 (and:SI (match_operator:SI 1 "arm_comparison_operator"
190efb17 9216 [(match_operand 2 "cc_register" "") (const_int 0)])
9217 (match_operand:SI 3 "s_register_operand" "r")))]
cffb2a26 9218 "TARGET_ARM"
190efb17 9219 "#" ; "mov%D1\\t%0, #0\;and%d1\\t%0, %3, #1"
9220 "&& reload_completed"
9221 [(cond_exec (match_dup 5) (set (match_dup 0) (const_int 0)))
9222 (cond_exec (match_dup 4) (set (match_dup 0)
9223 (and:SI (match_dup 3) (const_int 1))))]
9224 {
3754d046 9225 machine_mode mode = GET_MODE (operands[2]);
190efb17 9226 enum rtx_code rc = GET_CODE (operands[1]);
9227
9228 /* Note that operands[4] is the same as operands[1],
9229 but with VOIDmode as the result. */
9230 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
9231 if (mode == CCFPmode || mode == CCFPEmode)
9232 rc = reverse_condition_maybe_unordered (rc);
9233 else
9234 rc = reverse_condition (rc);
9235 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
9236 }
8fa3ba89 9237 [(set_attr "conds" "use")
1b7da4ac 9238 (set_attr "type" "multiple")
8fa3ba89 9239 (set_attr "length" "8")]
9240)
9c08d1fa 9241
190efb17 9242(define_insn_and_split "*ior_scc"
9c08d1fa 9243 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
190efb17 9244 (ior:SI (match_operator:SI 1 "arm_comparison_operator"
9245 [(match_operand 2 "cc_register" "") (const_int 0)])
9246 (match_operand:SI 3 "s_register_operand" "0,?r")))]
cffb2a26 9247 "TARGET_ARM"
e2348bcb 9248 "@
190efb17 9249 orr%d1\\t%0, %3, #1
9250 #"
9251 "&& reload_completed
9252 && REGNO (operands [0]) != REGNO (operands[3])"
9253 ;; && which_alternative == 1
9254 ; mov%D1\\t%0, %3\;orr%d1\\t%0, %3, #1
9255 [(cond_exec (match_dup 5) (set (match_dup 0) (match_dup 3)))
9256 (cond_exec (match_dup 4) (set (match_dup 0)
9257 (ior:SI (match_dup 3) (const_int 1))))]
9258 {
3754d046 9259 machine_mode mode = GET_MODE (operands[2]);
190efb17 9260 enum rtx_code rc = GET_CODE (operands[1]);
9261
9262 /* Note that operands[4] is the same as operands[1],
9263 but with VOIDmode as the result. */
9264 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
9265 if (mode == CCFPmode || mode == CCFPEmode)
9266 rc = reverse_condition_maybe_unordered (rc);
9267 else
9268 rc = reverse_condition (rc);
9269 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
9270 }
8fa3ba89 9271 [(set_attr "conds" "use")
1b7da4ac 9272 (set_attr "length" "4,8")
9273 (set_attr "type" "logic_imm,multiple")]
8fa3ba89 9274)
9c08d1fa 9275
2df9477b 9276; A series of splitters for the compare_scc pattern below. Note that
9277; order is important.
9278(define_split
9279 [(set (match_operand:SI 0 "s_register_operand" "")
9280 (lt:SI (match_operand:SI 1 "s_register_operand" "")
9281 (const_int 0)))
9282 (clobber (reg:CC CC_REGNUM))]
9283 "TARGET_32BIT && reload_completed"
9284 [(set (match_dup 0) (lshiftrt:SI (match_dup 1) (const_int 31)))])
9285
9286(define_split
9287 [(set (match_operand:SI 0 "s_register_operand" "")
9288 (ge:SI (match_operand:SI 1 "s_register_operand" "")
9289 (const_int 0)))
9290 (clobber (reg:CC CC_REGNUM))]
9291 "TARGET_32BIT && reload_completed"
9292 [(set (match_dup 0) (not:SI (match_dup 1)))
9293 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 31)))])
9294
98562479 9295(define_split
9296 [(set (match_operand:SI 0 "s_register_operand" "")
9297 (eq:SI (match_operand:SI 1 "s_register_operand" "")
9298 (const_int 0)))
9299 (clobber (reg:CC CC_REGNUM))]
b232e6b5 9300 "arm_arch5t && TARGET_32BIT"
98562479 9301 [(set (match_dup 0) (clz:SI (match_dup 1)))
9302 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 5)))]
9303)
9304
2df9477b 9305(define_split
9306 [(set (match_operand:SI 0 "s_register_operand" "")
9307 (eq:SI (match_operand:SI 1 "s_register_operand" "")
9308 (const_int 0)))
9309 (clobber (reg:CC CC_REGNUM))]
9310 "TARGET_32BIT && reload_completed"
9311 [(parallel
080c0b9a 9312 [(set (reg:CC CC_REGNUM)
9313 (compare:CC (const_int 1) (match_dup 1)))
2df9477b 9314 (set (match_dup 0)
9315 (minus:SI (const_int 1) (match_dup 1)))])
080c0b9a 9316 (cond_exec (ltu:CC (reg:CC CC_REGNUM) (const_int 0))
2df9477b 9317 (set (match_dup 0) (const_int 0)))])
9318
9319(define_split
9320 [(set (match_operand:SI 0 "s_register_operand" "")
9321 (ne:SI (match_operand:SI 1 "s_register_operand" "")
9322 (match_operand:SI 2 "const_int_operand" "")))
9323 (clobber (reg:CC CC_REGNUM))]
9324 "TARGET_32BIT && reload_completed"
9325 [(parallel
9326 [(set (reg:CC CC_REGNUM)
9327 (compare:CC (match_dup 1) (match_dup 2)))
9328 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))])
9329 (cond_exec (ne:CC (reg:CC CC_REGNUM) (const_int 0))
9330 (set (match_dup 0) (const_int 1)))]
9331{
e3dcfc16 9332 operands[3] = gen_int_mode (-INTVAL (operands[2]), SImode);
2df9477b 9333})
9334
9335(define_split
9336 [(set (match_operand:SI 0 "s_register_operand" "")
9337 (ne:SI (match_operand:SI 1 "s_register_operand" "")
9338 (match_operand:SI 2 "arm_add_operand" "")))
9339 (clobber (reg:CC CC_REGNUM))]
9340 "TARGET_32BIT && reload_completed"
9341 [(parallel
9342 [(set (reg:CC_NOOV CC_REGNUM)
9343 (compare:CC_NOOV (minus:SI (match_dup 1) (match_dup 2))
9344 (const_int 0)))
9345 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
9346 (cond_exec (ne:CC_NOOV (reg:CC_NOOV CC_REGNUM) (const_int 0))
9347 (set (match_dup 0) (const_int 1)))])
9348
9349(define_insn_and_split "*compare_scc"
fd711051 9350 [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts")
8fa3ba89 9351 (match_operator:SI 1 "arm_comparison_operator"
5565501b 9352 [(match_operand:SI 2 "s_register_operand" "r,r")
9353 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
bd5b4116 9354 (clobber (reg:CC CC_REGNUM))]
2df9477b 9355 "TARGET_32BIT"
9356 "#"
9357 "&& reload_completed"
9358 [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 3)))
9359 (cond_exec (match_dup 4) (set (match_dup 0) (const_int 0)))
9360 (cond_exec (match_dup 5) (set (match_dup 0) (const_int 1)))]
9361{
9362 rtx tmp1;
3754d046 9363 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
2df9477b 9364 operands[2], operands[3]);
9365 enum rtx_code rc = GET_CODE (operands[1]);
e2348bcb 9366
2df9477b 9367 tmp1 = gen_rtx_REG (mode, CC_REGNUM);
080c0b9a 9368
2df9477b 9369 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
9370 if (mode == CCFPmode || mode == CCFPEmode)
9371 rc = reverse_condition_maybe_unordered (rc);
9372 else
9373 rc = reverse_condition (rc);
9374 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
1b7da4ac 9375}
9376 [(set_attr "type" "multiple")]
9377)
9c08d1fa 9378
080c0b9a 9379;; Attempt to improve the sequence generated by the compare_scc splitters
9380;; not to use conditional execution.
98562479 9381
9382;; Rd = (eq (reg1) (const_int0)) // ARMv5
9383;; clz Rd, reg1
9384;; lsr Rd, Rd, #5
080c0b9a 9385(define_peephole2
9386 [(set (reg:CC CC_REGNUM)
9387 (compare:CC (match_operand:SI 1 "register_operand" "")
98562479 9388 (const_int 0)))
9389 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
9390 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
9391 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
9392 (set (match_dup 0) (const_int 1)))]
b232e6b5 9393 "arm_arch5t && TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)"
98562479 9394 [(set (match_dup 0) (clz:SI (match_dup 1)))
9395 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 5)))]
9396)
9397
9398;; Rd = (eq (reg1) (const_int0)) // !ARMv5
9399;; negs Rd, reg1
9400;; adc Rd, Rd, reg1
9401(define_peephole2
9402 [(set (reg:CC CC_REGNUM)
9403 (compare:CC (match_operand:SI 1 "register_operand" "")
9404 (const_int 0)))
080c0b9a 9405 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
9406 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
9407 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
9408 (set (match_dup 0) (const_int 1)))
98562479 9409 (match_scratch:SI 2 "r")]
9410 "TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)"
922b6913 9411 [(parallel
9412 [(set (reg:CC CC_REGNUM)
98562479 9413 (compare:CC (const_int 0) (match_dup 1)))
9414 (set (match_dup 2) (minus:SI (const_int 0) (match_dup 1)))])
9415 (set (match_dup 0)
9416 (plus:SI (plus:SI (match_dup 1) (match_dup 2))
9417 (geu:SI (reg:CC CC_REGNUM) (const_int 0))))]
9418)
9419
31991287 9420;; Rd = (eq (reg1) (reg2/imm)) // ARMv5 and optimising for speed.
98562479 9421;; sub Rd, Reg1, reg2
9422;; clz Rd, Rd
9423;; lsr Rd, Rd, #5
9424(define_peephole2
9425 [(set (reg:CC CC_REGNUM)
9426 (compare:CC (match_operand:SI 1 "register_operand" "")
9427 (match_operand:SI 2 "arm_rhs_operand" "")))
9428 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
9429 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
9430 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
9431 (set (match_dup 0) (const_int 1)))]
b232e6b5 9432 "arm_arch5t && TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)
31991287 9433 && !(TARGET_THUMB2 && optimize_insn_for_size_p ())"
98562479 9434 [(set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))
9435 (set (match_dup 0) (clz:SI (match_dup 0)))
9436 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 5)))]
9437)
9438
9439
31991287 9440;; Rd = (eq (reg1) (reg2)) // ! ARMv5 or optimising for size.
98562479 9441;; sub T1, Reg1, reg2
9442;; negs Rd, T1
9443;; adc Rd, Rd, T1
9444(define_peephole2
9445 [(set (reg:CC CC_REGNUM)
9446 (compare:CC (match_operand:SI 1 "register_operand" "")
9447 (match_operand:SI 2 "arm_rhs_operand" "")))
9448 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
9449 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
9450 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
9451 (set (match_dup 0) (const_int 1)))
9452 (match_scratch:SI 3 "r")]
9453 "TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)"
31991287 9454 [(set (match_dup 3) (match_dup 4))
080c0b9a 9455 (parallel
9456 [(set (reg:CC CC_REGNUM)
9457 (compare:CC (const_int 0) (match_dup 3)))
9458 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 3)))])
98562479 9459 (set (match_dup 0)
9460 (plus:SI (plus:SI (match_dup 0) (match_dup 3))
9461 (geu:SI (reg:CC CC_REGNUM) (const_int 0))))]
31991287 9462 "
9463 if (CONST_INT_P (operands[2]))
9464 operands[4] = plus_constant (SImode, operands[1], -INTVAL (operands[2]));
9465 else
9466 operands[4] = gen_rtx_MINUS (SImode, operands[1], operands[2]);
9467 ")
080c0b9a 9468
f7fbdd4a 9469(define_insn "*cond_move"
9c08d1fa 9470 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
aea4c774 9471 (if_then_else:SI (match_operator 3 "equality_operator"
8fa3ba89 9472 [(match_operator 4 "arm_comparison_operator"
8a18b90c 9473 [(match_operand 5 "cc_register" "") (const_int 0)])
aea4c774 9474 (const_int 0)])
9475 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9476 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
cffb2a26 9477 "TARGET_ARM"
9c08d1fa 9478 "*
8fa3ba89 9479 if (GET_CODE (operands[3]) == NE)
9480 {
9481 if (which_alternative != 1)
9482 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
9483 if (which_alternative != 0)
9484 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
9485 return \"\";
9486 }
9487 if (which_alternative != 0)
9488 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9489 if (which_alternative != 1)
9490 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
9491 return \"\";
9492 "
9493 [(set_attr "conds" "use")
282b4c75 9494 (set_attr_alternative "type"
9495 [(if_then_else (match_operand 2 "const_int_operand" "")
9496 (const_string "mov_imm")
9497 (const_string "mov_reg"))
9498 (if_then_else (match_operand 1 "const_int_operand" "")
9499 (const_string "mov_imm")
9500 (const_string "mov_reg"))
9501 (const_string "multiple")])
8fa3ba89 9502 (set_attr "length" "4,4,8")]
9503)
9c08d1fa 9504
f7fbdd4a 9505(define_insn "*cond_arith"
9c08d1fa 9506 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9507 (match_operator:SI 5 "shiftable_operator"
8fa3ba89 9508 [(match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 9509 [(match_operand:SI 2 "s_register_operand" "r,r")
9510 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
9511 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 9512 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9513 "TARGET_ARM"
9c08d1fa 9514 "*
8fa3ba89 9515 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
9516 return \"%i5\\t%0, %1, %2, lsr #31\";
40dbec34 9517
8fa3ba89 9518 output_asm_insn (\"cmp\\t%2, %3\", operands);
9519 if (GET_CODE (operands[5]) == AND)
9520 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
9521 else if (GET_CODE (operands[5]) == MINUS)
9522 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
9523 else if (which_alternative != 0)
9524 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9525 return \"%i5%d4\\t%0, %1, #1\";
9526 "
9527 [(set_attr "conds" "clob")
1b7da4ac 9528 (set_attr "length" "12")
9529 (set_attr "type" "multiple")]
8fa3ba89 9530)
9c08d1fa 9531
f7fbdd4a 9532(define_insn "*cond_sub"
9c08d1fa 9533 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9534 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8fa3ba89 9535 (match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 9536 [(match_operand:SI 2 "s_register_operand" "r,r")
9537 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 9538 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9539 "TARGET_ARM"
9c08d1fa 9540 "*
8fa3ba89 9541 output_asm_insn (\"cmp\\t%2, %3\", operands);
9542 if (which_alternative != 0)
9543 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9544 return \"sub%d4\\t%0, %1, #1\";
9545 "
9546 [(set_attr "conds" "clob")
1b7da4ac 9547 (set_attr "length" "8,12")
9548 (set_attr "type" "multiple")]
8fa3ba89 9549)
9c08d1fa 9550
aea4c774 9551(define_insn "*cmp_ite0"
cffb2a26 9552 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 9553 (compare
9554 (if_then_else:SI
8fa3ba89 9555 (match_operator 4 "arm_comparison_operator"
2ff91fec 9556 [(match_operand:SI 0 "s_register_operand"
9557 "l,l,l,r,r,r,r,r,r")
9558 (match_operand:SI 1 "arm_add_operand"
9559 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
8fa3ba89 9560 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 9561 [(match_operand:SI 2 "s_register_operand"
9562 "l,r,r,l,l,r,r,r,r")
9563 (match_operand:SI 3 "arm_add_operand"
9564 "lPy,rI,L,lPy,lPy,rI,rI,L,L")])
aea4c774 9565 (const_int 0))
9566 (const_int 0)))]
2ff91fec 9567 "TARGET_32BIT"
9c08d1fa 9568 "*
aea4c774 9569 {
2ff91fec 9570 static const char * const cmp1[NUM_OF_COND_CMP][2] =
9571 {
9572 {\"cmp%d5\\t%0, %1\",
9573 \"cmp%d4\\t%2, %3\"},
9574 {\"cmn%d5\\t%0, #%n1\",
9575 \"cmp%d4\\t%2, %3\"},
9576 {\"cmp%d5\\t%0, %1\",
9577 \"cmn%d4\\t%2, #%n3\"},
9578 {\"cmn%d5\\t%0, #%n1\",
9579 \"cmn%d4\\t%2, #%n3\"}
9580 };
9581 static const char * const cmp2[NUM_OF_COND_CMP][2] =
9582 {
9583 {\"cmp\\t%2, %3\",
9584 \"cmp\\t%0, %1\"},
9585 {\"cmp\\t%2, %3\",
9586 \"cmn\\t%0, #%n1\"},
9587 {\"cmn\\t%2, #%n3\",
9588 \"cmp\\t%0, %1\"},
9589 {\"cmn\\t%2, #%n3\",
9590 \"cmn\\t%0, #%n1\"}
9591 };
9592 static const char * const ite[2] =
8fa3ba89 9593 {
2ff91fec 9594 \"it\\t%d5\",
9595 \"it\\t%d4\"
8fa3ba89 9596 };
2ff91fec 9597 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
9598 CMP_CMP, CMN_CMP, CMP_CMP,
9599 CMN_CMP, CMP_CMN, CMN_CMN};
8fa3ba89 9600 int swap =
9601 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9602
2ff91fec 9603 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9604 if (TARGET_THUMB2) {
9605 output_asm_insn (ite[swap], operands);
9606 }
9607 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9608 return \"\";
8fa3ba89 9609 }"
9610 [(set_attr "conds" "set")
2ff91fec 9611 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
8bdfd6ed 9612 (set_attr "enabled_for_short_it" "yes,no,no,no,no,no,no,no,no")
1b7da4ac 9613 (set_attr "type" "multiple")
2ff91fec 9614 (set_attr_alternative "length"
9615 [(const_int 6)
9616 (const_int 8)
9617 (const_int 8)
9618 (const_int 8)
9619 (const_int 8)
9620 (if_then_else (eq_attr "is_thumb" "no")
9621 (const_int 8)
9622 (const_int 10))
9623 (if_then_else (eq_attr "is_thumb" "no")
9624 (const_int 8)
9625 (const_int 10))
9626 (if_then_else (eq_attr "is_thumb" "no")
9627 (const_int 8)
9628 (const_int 10))
9629 (if_then_else (eq_attr "is_thumb" "no")
9630 (const_int 8)
9631 (const_int 10))])]
8fa3ba89 9632)
9c08d1fa 9633
aea4c774 9634(define_insn "*cmp_ite1"
cffb2a26 9635 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 9636 (compare
9637 (if_then_else:SI
8fa3ba89 9638 (match_operator 4 "arm_comparison_operator"
2ff91fec 9639 [(match_operand:SI 0 "s_register_operand"
9640 "l,l,l,r,r,r,r,r,r")
9641 (match_operand:SI 1 "arm_add_operand"
9642 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
8fa3ba89 9643 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 9644 [(match_operand:SI 2 "s_register_operand"
9645 "l,r,r,l,l,r,r,r,r")
9646 (match_operand:SI 3 "arm_add_operand"
9647 "lPy,rI,L,lPy,lPy,rI,rI,L,L")])
aea4c774 9648 (const_int 1))
9649 (const_int 0)))]
2ff91fec 9650 "TARGET_32BIT"
9c08d1fa 9651 "*
9c08d1fa 9652 {
2ff91fec 9653 static const char * const cmp1[NUM_OF_COND_CMP][2] =
9654 {
9655 {\"cmp\\t%0, %1\",
9656 \"cmp\\t%2, %3\"},
9657 {\"cmn\\t%0, #%n1\",
9658 \"cmp\\t%2, %3\"},
9659 {\"cmp\\t%0, %1\",
9660 \"cmn\\t%2, #%n3\"},
9661 {\"cmn\\t%0, #%n1\",
9662 \"cmn\\t%2, #%n3\"}
9663 };
9664 static const char * const cmp2[NUM_OF_COND_CMP][2] =
215b30b3 9665 {
2ff91fec 9666 {\"cmp%d4\\t%2, %3\",
9667 \"cmp%D5\\t%0, %1\"},
9668 {\"cmp%d4\\t%2, %3\",
9669 \"cmn%D5\\t%0, #%n1\"},
9670 {\"cmn%d4\\t%2, #%n3\",
9671 \"cmp%D5\\t%0, %1\"},
9672 {\"cmn%d4\\t%2, #%n3\",
9673 \"cmn%D5\\t%0, #%n1\"}
215b30b3 9674 };
2ff91fec 9675 static const char * const ite[2] =
9676 {
9677 \"it\\t%d4\",
9678 \"it\\t%D5\"
9679 };
9680 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
9681 CMP_CMP, CMN_CMP, CMP_CMP,
9682 CMN_CMP, CMP_CMN, CMN_CMN};
215b30b3 9683 int swap =
9684 comparison_dominates_p (GET_CODE (operands[5]),
9685 reverse_condition (GET_CODE (operands[4])));
9686
2ff91fec 9687 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9688 if (TARGET_THUMB2) {
9689 output_asm_insn (ite[swap], operands);
9690 }
9691 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9692 return \"\";
215b30b3 9693 }"
8fa3ba89 9694 [(set_attr "conds" "set")
2ff91fec 9695 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
8bdfd6ed 9696 (set_attr "enabled_for_short_it" "yes,no,no,no,no,no,no,no,no")
2ff91fec 9697 (set_attr_alternative "length"
9698 [(const_int 6)
9699 (const_int 8)
9700 (const_int 8)
9701 (const_int 8)
9702 (const_int 8)
9703 (if_then_else (eq_attr "is_thumb" "no")
9704 (const_int 8)
9705 (const_int 10))
9706 (if_then_else (eq_attr "is_thumb" "no")
9707 (const_int 8)
9708 (const_int 10))
9709 (if_then_else (eq_attr "is_thumb" "no")
9710 (const_int 8)
9711 (const_int 10))
9712 (if_then_else (eq_attr "is_thumb" "no")
9713 (const_int 8)
1b7da4ac 9714 (const_int 10))])
9715 (set_attr "type" "multiple")]
8fa3ba89 9716)
9c08d1fa 9717
f6c53574 9718(define_insn "*cmp_and"
9719 [(set (match_operand 6 "dominant_cc_register" "")
9720 (compare
9721 (and:SI
9722 (match_operator 4 "arm_comparison_operator"
2ff91fec 9723 [(match_operand:SI 0 "s_register_operand"
9724 "l,l,l,r,r,r,r,r,r")
9725 (match_operand:SI 1 "arm_add_operand"
9726 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
f6c53574 9727 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 9728 [(match_operand:SI 2 "s_register_operand"
9729 "l,r,r,l,l,r,r,r,r")
9730 (match_operand:SI 3 "arm_add_operand"
9731 "lPy,rI,L,lPy,lPy,rI,rI,L,L")]))
f6c53574 9732 (const_int 0)))]
2ff91fec 9733 "TARGET_32BIT"
f6c53574 9734 "*
9735 {
2ff91fec 9736 static const char *const cmp1[NUM_OF_COND_CMP][2] =
f6c53574 9737 {
2ff91fec 9738 {\"cmp%d5\\t%0, %1\",
9739 \"cmp%d4\\t%2, %3\"},
9740 {\"cmn%d5\\t%0, #%n1\",
9741 \"cmp%d4\\t%2, %3\"},
9742 {\"cmp%d5\\t%0, %1\",
9743 \"cmn%d4\\t%2, #%n3\"},
9744 {\"cmn%d5\\t%0, #%n1\",
9745 \"cmn%d4\\t%2, #%n3\"}
f6c53574 9746 };
2ff91fec 9747 static const char *const cmp2[NUM_OF_COND_CMP][2] =
9748 {
9749 {\"cmp\\t%2, %3\",
9750 \"cmp\\t%0, %1\"},
9751 {\"cmp\\t%2, %3\",
9752 \"cmn\\t%0, #%n1\"},
9753 {\"cmn\\t%2, #%n3\",
9754 \"cmp\\t%0, %1\"},
9755 {\"cmn\\t%2, #%n3\",
9756 \"cmn\\t%0, #%n1\"}
9757 };
9758 static const char *const ite[2] =
9759 {
9760 \"it\\t%d5\",
9761 \"it\\t%d4\"
9762 };
9763 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
9764 CMP_CMP, CMN_CMP, CMP_CMP,
9765 CMN_CMP, CMP_CMN, CMN_CMN};
f6c53574 9766 int swap =
9767 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9768
2ff91fec 9769 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9770 if (TARGET_THUMB2) {
9771 output_asm_insn (ite[swap], operands);
9772 }
9773 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9774 return \"\";
f6c53574 9775 }"
9776 [(set_attr "conds" "set")
9777 (set_attr "predicable" "no")
2ff91fec 9778 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
8bdfd6ed 9779 (set_attr "enabled_for_short_it" "yes,no,no,no,no,no,no,no,no")
2ff91fec 9780 (set_attr_alternative "length"
9781 [(const_int 6)
9782 (const_int 8)
9783 (const_int 8)
9784 (const_int 8)
9785 (const_int 8)
9786 (if_then_else (eq_attr "is_thumb" "no")
9787 (const_int 8)
9788 (const_int 10))
9789 (if_then_else (eq_attr "is_thumb" "no")
9790 (const_int 8)
9791 (const_int 10))
9792 (if_then_else (eq_attr "is_thumb" "no")
9793 (const_int 8)
9794 (const_int 10))
9795 (if_then_else (eq_attr "is_thumb" "no")
9796 (const_int 8)
1b7da4ac 9797 (const_int 10))])
9798 (set_attr "type" "multiple")]
f6c53574 9799)
9800
9801(define_insn "*cmp_ior"
9802 [(set (match_operand 6 "dominant_cc_register" "")
9803 (compare
9804 (ior:SI
9805 (match_operator 4 "arm_comparison_operator"
2ff91fec 9806 [(match_operand:SI 0 "s_register_operand"
9807 "l,l,l,r,r,r,r,r,r")
9808 (match_operand:SI 1 "arm_add_operand"
9809 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
f6c53574 9810 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 9811 [(match_operand:SI 2 "s_register_operand"
9812 "l,r,r,l,l,r,r,r,r")
9813 (match_operand:SI 3 "arm_add_operand"
9814 "lPy,rI,L,lPy,lPy,rI,rI,L,L")]))
f6c53574 9815 (const_int 0)))]
2ff91fec 9816 "TARGET_32BIT"
f6c53574 9817 "*
f6c53574 9818 {
2ff91fec 9819 static const char *const cmp1[NUM_OF_COND_CMP][2] =
9820 {
9821 {\"cmp\\t%0, %1\",
9822 \"cmp\\t%2, %3\"},
9823 {\"cmn\\t%0, #%n1\",
9824 \"cmp\\t%2, %3\"},
9825 {\"cmp\\t%0, %1\",
9826 \"cmn\\t%2, #%n3\"},
9827 {\"cmn\\t%0, #%n1\",
9828 \"cmn\\t%2, #%n3\"}
9829 };
9830 static const char *const cmp2[NUM_OF_COND_CMP][2] =
9831 {
9832 {\"cmp%D4\\t%2, %3\",
9833 \"cmp%D5\\t%0, %1\"},
9834 {\"cmp%D4\\t%2, %3\",
9835 \"cmn%D5\\t%0, #%n1\"},
9836 {\"cmn%D4\\t%2, #%n3\",
9837 \"cmp%D5\\t%0, %1\"},
9838 {\"cmn%D4\\t%2, #%n3\",
9839 \"cmn%D5\\t%0, #%n1\"}
9840 };
9841 static const char *const ite[2] =
9842 {
9843 \"it\\t%D4\",
9844 \"it\\t%D5\"
9845 };
9846 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
9847 CMP_CMP, CMN_CMP, CMP_CMP,
9848 CMN_CMP, CMP_CMN, CMN_CMN};
9849 int swap =
9850 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9851
9852 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9853 if (TARGET_THUMB2) {
9854 output_asm_insn (ite[swap], operands);
9855 }
9856 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9857 return \"\";
9858 }
9859 "
f6c53574 9860 [(set_attr "conds" "set")
2ff91fec 9861 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
8bdfd6ed 9862 (set_attr "enabled_for_short_it" "yes,no,no,no,no,no,no,no,no")
2ff91fec 9863 (set_attr_alternative "length"
9864 [(const_int 6)
9865 (const_int 8)
9866 (const_int 8)
9867 (const_int 8)
9868 (const_int 8)
9869 (if_then_else (eq_attr "is_thumb" "no")
9870 (const_int 8)
9871 (const_int 10))
9872 (if_then_else (eq_attr "is_thumb" "no")
9873 (const_int 8)
9874 (const_int 10))
9875 (if_then_else (eq_attr "is_thumb" "no")
9876 (const_int 8)
9877 (const_int 10))
9878 (if_then_else (eq_attr "is_thumb" "no")
9879 (const_int 8)
1b7da4ac 9880 (const_int 10))])
9881 (set_attr "type" "multiple")]
f6c53574 9882)
9883
3c5afce6 9884(define_insn_and_split "*ior_scc_scc"
f9d240a0 9885 [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts")
3c5afce6 9886 (ior:SI (match_operator:SI 3 "arm_comparison_operator"
f9d240a0 9887 [(match_operand:SI 1 "s_register_operand" "l,r")
9888 (match_operand:SI 2 "arm_add_operand" "lPy,rIL")])
3c5afce6 9889 (match_operator:SI 6 "arm_comparison_operator"
f9d240a0 9890 [(match_operand:SI 4 "s_register_operand" "l,r")
9891 (match_operand:SI 5 "arm_add_operand" "lPy,rIL")])))
3c5afce6 9892 (clobber (reg:CC CC_REGNUM))]
2ff91fec 9893 "TARGET_32BIT
3c5afce6 9894 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
9895 != CCmode)"
9896 "#"
2ff91fec 9897 "TARGET_32BIT && reload_completed"
3c5afce6 9898 [(set (match_dup 7)
9899 (compare
9900 (ior:SI
9901 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9902 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9903 (const_int 0)))
9904 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9905 "operands[7]
9906 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9907 DOM_CC_X_OR_Y),
601f584c 9908 CC_REGNUM);"
9909 [(set_attr "conds" "clob")
8bdfd6ed 9910 (set_attr "enabled_for_short_it" "yes,no")
1b7da4ac 9911 (set_attr "length" "16")
9912 (set_attr "type" "multiple")]
9913)
601f584c 9914
9915; If the above pattern is followed by a CMP insn, then the compare is
9916; redundant, since we can rework the conditional instruction that follows.
9917(define_insn_and_split "*ior_scc_scc_cmp"
9918 [(set (match_operand 0 "dominant_cc_register" "")
9919 (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
f9d240a0 9920 [(match_operand:SI 1 "s_register_operand" "l,r")
9921 (match_operand:SI 2 "arm_add_operand" "lPy,rIL")])
601f584c 9922 (match_operator:SI 6 "arm_comparison_operator"
f9d240a0 9923 [(match_operand:SI 4 "s_register_operand" "l,r")
9924 (match_operand:SI 5 "arm_add_operand" "lPy,rIL")]))
601f584c 9925 (const_int 0)))
f9d240a0 9926 (set (match_operand:SI 7 "s_register_operand" "=Ts,Ts")
601f584c 9927 (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9928 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
2ff91fec 9929 "TARGET_32BIT"
601f584c 9930 "#"
2ff91fec 9931 "TARGET_32BIT && reload_completed"
601f584c 9932 [(set (match_dup 0)
9933 (compare
9934 (ior:SI
9935 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9936 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9937 (const_int 0)))
9938 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9939 ""
9940 [(set_attr "conds" "set")
8bdfd6ed 9941 (set_attr "enabled_for_short_it" "yes,no")
1b7da4ac 9942 (set_attr "length" "16")
9943 (set_attr "type" "multiple")]
9944)
3c5afce6 9945
9946(define_insn_and_split "*and_scc_scc"
f9d240a0 9947 [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts")
3c5afce6 9948 (and:SI (match_operator:SI 3 "arm_comparison_operator"
f9d240a0 9949 [(match_operand:SI 1 "s_register_operand" "l,r")
9950 (match_operand:SI 2 "arm_add_operand" "lPy,rIL")])
3c5afce6 9951 (match_operator:SI 6 "arm_comparison_operator"
f9d240a0 9952 [(match_operand:SI 4 "s_register_operand" "l,r")
9953 (match_operand:SI 5 "arm_add_operand" "lPy,rIL")])))
3c5afce6 9954 (clobber (reg:CC CC_REGNUM))]
2ff91fec 9955 "TARGET_32BIT
3c5afce6 9956 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9957 != CCmode)"
9958 "#"
2ff91fec 9959 "TARGET_32BIT && reload_completed
601f584c 9960 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9961 != CCmode)"
3c5afce6 9962 [(set (match_dup 7)
9963 (compare
9964 (and:SI
9965 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9966 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9967 (const_int 0)))
9968 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9969 "operands[7]
9970 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9971 DOM_CC_X_AND_Y),
601f584c 9972 CC_REGNUM);"
9973 [(set_attr "conds" "clob")
8bdfd6ed 9974 (set_attr "enabled_for_short_it" "yes,no")
1b7da4ac 9975 (set_attr "length" "16")
9976 (set_attr "type" "multiple")]
9977)
601f584c 9978
9979; If the above pattern is followed by a CMP insn, then the compare is
9980; redundant, since we can rework the conditional instruction that follows.
9981(define_insn_and_split "*and_scc_scc_cmp"
9982 [(set (match_operand 0 "dominant_cc_register" "")
9983 (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
f9d240a0 9984 [(match_operand:SI 1 "s_register_operand" "l,r")
9985 (match_operand:SI 2 "arm_add_operand" "lPy,rIL")])
601f584c 9986 (match_operator:SI 6 "arm_comparison_operator"
f9d240a0 9987 [(match_operand:SI 4 "s_register_operand" "l,r")
9988 (match_operand:SI 5 "arm_add_operand" "lPy,rIL")]))
601f584c 9989 (const_int 0)))
f9d240a0 9990 (set (match_operand:SI 7 "s_register_operand" "=Ts,Ts")
601f584c 9991 (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9992 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
2ff91fec 9993 "TARGET_32BIT"
601f584c 9994 "#"
2ff91fec 9995 "TARGET_32BIT && reload_completed"
601f584c 9996 [(set (match_dup 0)
9997 (compare
9998 (and:SI
9999 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
10000 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
10001 (const_int 0)))
10002 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
10003 ""
10004 [(set_attr "conds" "set")
8bdfd6ed 10005 (set_attr "enabled_for_short_it" "yes,no")
1b7da4ac 10006 (set_attr "length" "16")
10007 (set_attr "type" "multiple")]
10008)
601f584c 10009
10010;; If there is no dominance in the comparison, then we can still save an
10011;; instruction in the AND case, since we can know that the second compare
10012;; need only zero the value if false (if true, then the value is already
10013;; correct).
10014(define_insn_and_split "*and_scc_scc_nodom"
fd711051 10015 [(set (match_operand:SI 0 "s_register_operand" "=&Ts,&Ts,&Ts")
601f584c 10016 (and:SI (match_operator:SI 3 "arm_comparison_operator"
10017 [(match_operand:SI 1 "s_register_operand" "r,r,0")
10018 (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
10019 (match_operator:SI 6 "arm_comparison_operator"
10020 [(match_operand:SI 4 "s_register_operand" "r,r,r")
10021 (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
10022 (clobber (reg:CC CC_REGNUM))]
2ff91fec 10023 "TARGET_32BIT
601f584c 10024 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
10025 == CCmode)"
10026 "#"
2ff91fec 10027 "TARGET_32BIT && reload_completed"
601f584c 10028 [(parallel [(set (match_dup 0)
10029 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
10030 (clobber (reg:CC CC_REGNUM))])
10031 (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
10032 (set (match_dup 0)
10033 (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
10034 (match_dup 0)
10035 (const_int 0)))]
10036 "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
10037 operands[4], operands[5]),
10038 CC_REGNUM);
10039 operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
10040 operands[5]);"
10041 [(set_attr "conds" "clob")
1b7da4ac 10042 (set_attr "length" "20")
10043 (set_attr "type" "multiple")]
10044)
3c5afce6 10045
3a0bdee0 10046(define_split
10047 [(set (reg:CC_NOOV CC_REGNUM)
10048 (compare:CC_NOOV (ior:SI
10049 (and:SI (match_operand:SI 0 "s_register_operand" "")
10050 (const_int 1))
b0694be0 10051 (match_operator:SI 1 "arm_comparison_operator"
3a0bdee0 10052 [(match_operand:SI 2 "s_register_operand" "")
10053 (match_operand:SI 3 "arm_add_operand" "")]))
10054 (const_int 0)))
10055 (clobber (match_operand:SI 4 "s_register_operand" ""))]
10056 "TARGET_ARM"
10057 [(set (match_dup 4)
10058 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
10059 (match_dup 0)))
10060 (set (reg:CC_NOOV CC_REGNUM)
10061 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
10062 (const_int 0)))]
10063 "")
10064
10065(define_split
10066 [(set (reg:CC_NOOV CC_REGNUM)
10067 (compare:CC_NOOV (ior:SI
b0694be0 10068 (match_operator:SI 1 "arm_comparison_operator"
3a0bdee0 10069 [(match_operand:SI 2 "s_register_operand" "")
10070 (match_operand:SI 3 "arm_add_operand" "")])
10071 (and:SI (match_operand:SI 0 "s_register_operand" "")
10072 (const_int 1)))
10073 (const_int 0)))
10074 (clobber (match_operand:SI 4 "s_register_operand" ""))]
10075 "TARGET_ARM"
10076 [(set (match_dup 4)
10077 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
10078 (match_dup 0)))
10079 (set (reg:CC_NOOV CC_REGNUM)
10080 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
10081 (const_int 0)))]
10082 "")
25f905c2 10083;; ??? The conditional patterns above need checking for Thumb-2 usefulness
3a0bdee0 10084
190efb17 10085(define_insn_and_split "*negscc"
9c08d1fa 10086 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 10087 (neg:SI (match_operator 3 "arm_comparison_operator"
9c08d1fa 10088 [(match_operand:SI 1 "s_register_operand" "r")
10089 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
bd5b4116 10090 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10091 "TARGET_ARM"
190efb17 10092 "#"
10093 "&& reload_completed"
10094 [(const_int 0)]
10095 {
10096 rtx cc_reg = gen_rtx_REG (CCmode, CC_REGNUM);
e2348bcb 10097
190efb17 10098 if (GET_CODE (operands[3]) == LT && operands[2] == const0_rtx)
10099 {
10100 /* Emit mov\\t%0, %1, asr #31 */
d1f9b275 10101 emit_insn (gen_rtx_SET (operands[0],
190efb17 10102 gen_rtx_ASHIFTRT (SImode,
10103 operands[1],
10104 GEN_INT (31))));
10105 DONE;
10106 }
10107 else if (GET_CODE (operands[3]) == NE)
10108 {
10109 /* Emit subs\\t%0, %1, %2\;mvnne\\t%0, #0 */
10110 if (CONST_INT_P (operands[2]))
10111 emit_insn (gen_cmpsi2_addneg (operands[0], operands[1], operands[2],
e3dcfc16 10112 gen_int_mode (-INTVAL (operands[2]),
10113 SImode)));
190efb17 10114 else
10115 emit_insn (gen_subsi3_compare (operands[0], operands[1], operands[2]));
10116
10117 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
10118 gen_rtx_NE (SImode,
10119 cc_reg,
10120 const0_rtx),
d1f9b275 10121 gen_rtx_SET (operands[0],
190efb17 10122 GEN_INT (~0))));
10123 DONE;
10124 }
10125 else
10126 {
10127 /* Emit: cmp\\t%1, %2\;mov%D3\\t%0, #0\;mvn%d3\\t%0, #0 */
d1f9b275 10128 emit_insn (gen_rtx_SET (cc_reg,
190efb17 10129 gen_rtx_COMPARE (CCmode, operands[1], operands[2])));
10130 enum rtx_code rc = GET_CODE (operands[3]);
10131
10132 rc = reverse_condition (rc);
10133 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
10134 gen_rtx_fmt_ee (rc,
10135 VOIDmode,
10136 cc_reg,
10137 const0_rtx),
d1f9b275 10138 gen_rtx_SET (operands[0], const0_rtx)));
190efb17 10139 rc = GET_CODE (operands[3]);
10140 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
10141 gen_rtx_fmt_ee (rc,
10142 VOIDmode,
10143 cc_reg,
10144 const0_rtx),
d1f9b275 10145 gen_rtx_SET (operands[0],
190efb17 10146 GEN_INT (~0))));
10147 DONE;
10148 }
10149 FAIL;
10150 }
8fa3ba89 10151 [(set_attr "conds" "clob")
1b7da4ac 10152 (set_attr "length" "12")
10153 (set_attr "type" "multiple")]
8fa3ba89 10154)
9c08d1fa 10155
90404b57 10156(define_insn_and_split "movcond_addsi"
10157 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r")
10158 (if_then_else:SI
10159 (match_operator 5 "comparison_operator"
10160 [(plus:SI (match_operand:SI 3 "s_register_operand" "r,r,r")
10161 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL"))
10162 (const_int 0)])
10163 (match_operand:SI 1 "arm_rhs_operand" "rI,rPy,r")
10164 (match_operand:SI 2 "arm_rhs_operand" "rI,rPy,r")))
10165 (clobber (reg:CC CC_REGNUM))]
10166 "TARGET_32BIT"
10167 "#"
10168 "&& reload_completed"
10169 [(set (reg:CC_NOOV CC_REGNUM)
10170 (compare:CC_NOOV
10171 (plus:SI (match_dup 3)
10172 (match_dup 4))
10173 (const_int 0)))
10174 (set (match_dup 0) (match_dup 1))
10175 (cond_exec (match_dup 6)
10176 (set (match_dup 0) (match_dup 2)))]
10177 "
10178 {
3754d046 10179 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[5]),
90404b57 10180 operands[3], operands[4]);
10181 enum rtx_code rc = GET_CODE (operands[5]);
90404b57 10182 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
10183 gcc_assert (!(mode == CCFPmode || mode == CCFPEmode));
22440aeb 10184 if (!REG_P (operands[2]) || REGNO (operands[2]) != REGNO (operands[0]))
4d01ce2f 10185 rc = reverse_condition (rc);
f145bcba 10186 else
10187 std::swap (operands[1], operands[2]);
90404b57 10188
10189 operands[6] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10190 }
10191 "
10192 [(set_attr "conds" "clob")
8bdfd6ed 10193 (set_attr "enabled_for_short_it" "no,yes,yes")
1b7da4ac 10194 (set_attr "type" "multiple")]
90404b57 10195)
10196
9c08d1fa 10197(define_insn "movcond"
10198 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 10199 (if_then_else:SI
8fa3ba89 10200 (match_operator 5 "arm_comparison_operator"
5565501b 10201 [(match_operand:SI 3 "s_register_operand" "r,r,r")
10202 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
10203 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
10204 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 10205 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10206 "TARGET_ARM"
9c08d1fa 10207 "*
10208 if (GET_CODE (operands[5]) == LT
10209 && (operands[4] == const0_rtx))
10210 {
0438d37f 10211 if (which_alternative != 1 && REG_P (operands[1]))
9c08d1fa 10212 {
9c08d1fa 10213 if (operands[2] == const0_rtx)
e2348bcb 10214 return \"and\\t%0, %1, %3, asr #31\";
10215 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
9c08d1fa 10216 }
0438d37f 10217 else if (which_alternative != 0 && REG_P (operands[2]))
9c08d1fa 10218 {
9c08d1fa 10219 if (operands[1] == const0_rtx)
e2348bcb 10220 return \"bic\\t%0, %2, %3, asr #31\";
10221 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
9c08d1fa 10222 }
10223 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 10224 are constants. */
9c08d1fa 10225 }
e2348bcb 10226
9c08d1fa 10227 if (GET_CODE (operands[5]) == GE
10228 && (operands[4] == const0_rtx))
10229 {
0438d37f 10230 if (which_alternative != 1 && REG_P (operands[1]))
9c08d1fa 10231 {
9c08d1fa 10232 if (operands[2] == const0_rtx)
e2348bcb 10233 return \"bic\\t%0, %1, %3, asr #31\";
10234 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
9c08d1fa 10235 }
0438d37f 10236 else if (which_alternative != 0 && REG_P (operands[2]))
9c08d1fa 10237 {
9c08d1fa 10238 if (operands[1] == const0_rtx)
e2348bcb 10239 return \"and\\t%0, %2, %3, asr #31\";
10240 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
9c08d1fa 10241 }
10242 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 10243 are constants. */
9c08d1fa 10244 }
0438d37f 10245 if (CONST_INT_P (operands[4])
9c08d1fa 10246 && !const_ok_for_arm (INTVAL (operands[4])))
e2348bcb 10247 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
9c08d1fa 10248 else
e2348bcb 10249 output_asm_insn (\"cmp\\t%3, %4\", operands);
9c08d1fa 10250 if (which_alternative != 0)
e2348bcb 10251 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
9c08d1fa 10252 if (which_alternative != 1)
e2348bcb 10253 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
9c08d1fa 10254 return \"\";
215b30b3 10255 "
8fa3ba89 10256 [(set_attr "conds" "clob")
1b7da4ac 10257 (set_attr "length" "8,8,12")
10258 (set_attr "type" "multiple")]
8fa3ba89 10259)
9c08d1fa 10260
25f905c2 10261;; ??? The patterns below need checking for Thumb-2 usefulness.
10262
8a18b90c 10263(define_insn "*ifcompare_plus_move"
10264 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10265 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 10266 [(match_operand:SI 4 "s_register_operand" "r,r")
10267 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
10268 (plus:SI
10269 (match_operand:SI 2 "s_register_operand" "r,r")
10270 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
129a2fe4 10271 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 10272 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10273 "TARGET_ARM"
8a18b90c 10274 "#"
8fa3ba89 10275 [(set_attr "conds" "clob")
1b7da4ac 10276 (set_attr "length" "8,12")
10277 (set_attr "type" "multiple")]
8fa3ba89 10278)
8a18b90c 10279
10280(define_insn "*if_plus_move"
129a2fe4 10281 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 10282 (if_then_else:SI
8fa3ba89 10283 (match_operator 4 "arm_comparison_operator"
8a18b90c 10284 [(match_operand 5 "cc_register" "") (const_int 0)])
10285 (plus:SI
129a2fe4 10286 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
10287 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
10288 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
cffb2a26 10289 "TARGET_ARM"
8a18b90c 10290 "@
10291 add%d4\\t%0, %2, %3
10292 sub%d4\\t%0, %2, #%n3
10293 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
129a2fe4 10294 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8fa3ba89 10295 [(set_attr "conds" "use")
10296 (set_attr "length" "4,4,8,8")
65f68e55 10297 (set_attr_alternative "type"
10298 [(if_then_else (match_operand 3 "const_int_operand" "")
d82e788e 10299 (const_string "alu_imm" )
112eda6f 10300 (const_string "alu_sreg"))
d82e788e 10301 (const_string "alu_imm")
282b4c75 10302 (const_string "multiple")
10303 (const_string "multiple")])]
8fa3ba89 10304)
8a18b90c 10305
10306(define_insn "*ifcompare_move_plus"
5565501b 10307 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10308 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 10309 [(match_operand:SI 4 "s_register_operand" "r,r")
10310 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 10311 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 10312 (plus:SI
10313 (match_operand:SI 2 "s_register_operand" "r,r")
10314 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
bd5b4116 10315 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10316 "TARGET_ARM"
8a18b90c 10317 "#"
8fa3ba89 10318 [(set_attr "conds" "clob")
1b7da4ac 10319 (set_attr "length" "8,12")
10320 (set_attr "type" "multiple")]
8fa3ba89 10321)
8a18b90c 10322
10323(define_insn "*if_move_plus"
129a2fe4 10324 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 10325 (if_then_else:SI
8fa3ba89 10326 (match_operator 4 "arm_comparison_operator"
8a18b90c 10327 [(match_operand 5 "cc_register" "") (const_int 0)])
129a2fe4 10328 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8a18b90c 10329 (plus:SI
129a2fe4 10330 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
10331 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
cffb2a26 10332 "TARGET_ARM"
8a18b90c 10333 "@
10334 add%D4\\t%0, %2, %3
10335 sub%D4\\t%0, %2, #%n3
10336 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
129a2fe4 10337 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8fa3ba89 10338 [(set_attr "conds" "use")
10339 (set_attr "length" "4,4,8,8")
282b4c75 10340 (set_attr_alternative "type"
10341 [(if_then_else (match_operand 3 "const_int_operand" "")
10342 (const_string "alu_imm" )
10343 (const_string "alu_sreg"))
10344 (const_string "alu_imm")
10345 (const_string "multiple")
10346 (const_string "multiple")])]
8fa3ba89 10347)
8a18b90c 10348
10349(define_insn "*ifcompare_arith_arith"
10350 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 10351 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8a18b90c 10352 [(match_operand:SI 5 "s_register_operand" "r")
10353 (match_operand:SI 6 "arm_add_operand" "rIL")])
9c08d1fa 10354 (match_operator:SI 8 "shiftable_operator"
8a18b90c 10355 [(match_operand:SI 1 "s_register_operand" "r")
10356 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9c08d1fa 10357 (match_operator:SI 7 "shiftable_operator"
8a18b90c 10358 [(match_operand:SI 3 "s_register_operand" "r")
10359 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
bd5b4116 10360 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10361 "TARGET_ARM"
8a18b90c 10362 "#"
8fa3ba89 10363 [(set_attr "conds" "clob")
1b7da4ac 10364 (set_attr "length" "12")
10365 (set_attr "type" "multiple")]
8fa3ba89 10366)
9c08d1fa 10367
8a18b90c 10368(define_insn "*if_arith_arith"
10369 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 10370 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8a18b90c 10371 [(match_operand 8 "cc_register" "") (const_int 0)])
10372 (match_operator:SI 6 "shiftable_operator"
10373 [(match_operand:SI 1 "s_register_operand" "r")
10374 (match_operand:SI 2 "arm_rhs_operand" "rI")])
10375 (match_operator:SI 7 "shiftable_operator"
10376 [(match_operand:SI 3 "s_register_operand" "r")
10377 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
cffb2a26 10378 "TARGET_ARM"
8a18b90c 10379 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8fa3ba89 10380 [(set_attr "conds" "use")
1b7da4ac 10381 (set_attr "length" "8")
10382 (set_attr "type" "multiple")]
8fa3ba89 10383)
8a18b90c 10384
f7fbdd4a 10385(define_insn "*ifcompare_arith_move"
9c08d1fa 10386 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10387 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 10388 [(match_operand:SI 2 "s_register_operand" "r,r")
5565501b 10389 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
9c08d1fa 10390 (match_operator:SI 7 "shiftable_operator"
10391 [(match_operand:SI 4 "s_register_operand" "r,r")
10392 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
129a2fe4 10393 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 10394 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10395 "TARGET_ARM"
9c08d1fa 10396 "*
9c08d1fa 10397 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 10398 the conditional operator is LT or GE and we are comparing against zero and
674a8f0b 10399 everything is in registers then we can do this in two instructions. */
9c08d1fa 10400 if (operands[3] == const0_rtx
10401 && GET_CODE (operands[7]) != AND
0438d37f 10402 && REG_P (operands[5])
10403 && REG_P (operands[1])
9c08d1fa 10404 && REGNO (operands[1]) == REGNO (operands[4])
10405 && REGNO (operands[4]) != REGNO (operands[0]))
10406 {
10407 if (GET_CODE (operands[6]) == LT)
40dbec34 10408 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 10409 else if (GET_CODE (operands[6]) == GE)
40dbec34 10410 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 10411 }
0438d37f 10412 if (CONST_INT_P (operands[3])
9c08d1fa 10413 && !const_ok_for_arm (INTVAL (operands[3])))
e2348bcb 10414 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
9c08d1fa 10415 else
e2348bcb 10416 output_asm_insn (\"cmp\\t%2, %3\", operands);
40dbec34 10417 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
9c08d1fa 10418 if (which_alternative != 0)
129a2fe4 10419 return \"mov%D6\\t%0, %1\";
9c08d1fa 10420 return \"\";
215b30b3 10421 "
8fa3ba89 10422 [(set_attr "conds" "clob")
1b7da4ac 10423 (set_attr "length" "8,12")
10424 (set_attr "type" "multiple")]
8fa3ba89 10425)
9c08d1fa 10426
8a18b90c 10427(define_insn "*if_arith_move"
129a2fe4 10428 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10429 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8a18b90c 10430 [(match_operand 6 "cc_register" "") (const_int 0)])
10431 (match_operator:SI 5 "shiftable_operator"
129a2fe4 10432 [(match_operand:SI 2 "s_register_operand" "r,r")
10433 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
10434 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
cffb2a26 10435 "TARGET_ARM"
8a18b90c 10436 "@
10437 %I5%d4\\t%0, %2, %3
129a2fe4 10438 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8fa3ba89 10439 [(set_attr "conds" "use")
10440 (set_attr "length" "4,8")
282b4c75 10441 (set_attr_alternative "type"
10442 [(if_then_else (match_operand 3 "const_int_operand" "")
10443 (const_string "alu_shift_imm" )
10444 (const_string "alu_shift_reg"))
10445 (const_string "multiple")])]
8fa3ba89 10446)
8a18b90c 10447
f7fbdd4a 10448(define_insn "*ifcompare_move_arith"
9c08d1fa 10449 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10450 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 10451 [(match_operand:SI 4 "s_register_operand" "r,r")
5565501b 10452 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 10453 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9c08d1fa 10454 (match_operator:SI 7 "shiftable_operator"
10455 [(match_operand:SI 2 "s_register_operand" "r,r")
10456 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 10457 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10458 "TARGET_ARM"
9c08d1fa 10459 "*
9c08d1fa 10460 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 10461 the conditional operator is LT or GE and we are comparing against zero and
9c08d1fa 10462 everything is in registers then we can do this in two instructions */
10463 if (operands[5] == const0_rtx
10464 && GET_CODE (operands[7]) != AND
0438d37f 10465 && REG_P (operands[3])
10466 && REG_P (operands[1])
9c08d1fa 10467 && REGNO (operands[1]) == REGNO (operands[2])
10468 && REGNO (operands[2]) != REGNO (operands[0]))
10469 {
10470 if (GET_CODE (operands[6]) == GE)
40dbec34 10471 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 10472 else if (GET_CODE (operands[6]) == LT)
40dbec34 10473 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 10474 }
40dbec34 10475
0438d37f 10476 if (CONST_INT_P (operands[5])
9c08d1fa 10477 && !const_ok_for_arm (INTVAL (operands[5])))
e2348bcb 10478 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
9c08d1fa 10479 else
e2348bcb 10480 output_asm_insn (\"cmp\\t%4, %5\", operands);
40dbec34 10481
9c08d1fa 10482 if (which_alternative != 0)
129a2fe4 10483 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
40dbec34 10484 return \"%I7%D6\\t%0, %2, %3\";
215b30b3 10485 "
8fa3ba89 10486 [(set_attr "conds" "clob")
1b7da4ac 10487 (set_attr "length" "8,12")
10488 (set_attr "type" "multiple")]
8fa3ba89 10489)
9c08d1fa 10490
8a18b90c 10491(define_insn "*if_move_arith"
129a2fe4 10492 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 10493 (if_then_else:SI
8fa3ba89 10494 (match_operator 4 "arm_comparison_operator"
8a18b90c 10495 [(match_operand 6 "cc_register" "") (const_int 0)])
129a2fe4 10496 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 10497 (match_operator:SI 5 "shiftable_operator"
129a2fe4 10498 [(match_operand:SI 2 "s_register_operand" "r,r")
10499 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
cffb2a26 10500 "TARGET_ARM"
8a18b90c 10501 "@
10502 %I5%D4\\t%0, %2, %3
129a2fe4 10503 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
8fa3ba89 10504 [(set_attr "conds" "use")
10505 (set_attr "length" "4,8")
282b4c75 10506 (set_attr_alternative "type"
10507 [(if_then_else (match_operand 3 "const_int_operand" "")
10508 (const_string "alu_shift_imm" )
10509 (const_string "alu_shift_reg"))
10510 (const_string "multiple")])]
8fa3ba89 10511)
8a18b90c 10512
10513(define_insn "*ifcompare_move_not"
9c08d1fa 10514 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 10515 (if_then_else:SI
8fa3ba89 10516 (match_operator 5 "arm_comparison_operator"
8a18b90c 10517 [(match_operand:SI 3 "s_register_operand" "r,r")
10518 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10519 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
10520 (not:SI
10521 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 10522 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10523 "TARGET_ARM"
8a18b90c 10524 "#"
8fa3ba89 10525 [(set_attr "conds" "clob")
1b7da4ac 10526 (set_attr "length" "8,12")
10527 (set_attr "type" "multiple")]
8fa3ba89 10528)
9c08d1fa 10529
8a18b90c 10530(define_insn "*if_move_not"
10531 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10532 (if_then_else:SI
8fa3ba89 10533 (match_operator 4 "arm_comparison_operator"
8a18b90c 10534 [(match_operand 3 "cc_register" "") (const_int 0)])
10535 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
10536 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
cffb2a26 10537 "TARGET_ARM"
8a18b90c 10538 "@
10539 mvn%D4\\t%0, %2
10540 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
10541 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
8fa3ba89 10542 [(set_attr "conds" "use")
1aed5204 10543 (set_attr "type" "mvn_reg")
1b7da4ac 10544 (set_attr "length" "4,8,8")
10545 (set_attr "type" "mvn_reg,multiple,multiple")]
8fa3ba89 10546)
8a18b90c 10547
10548(define_insn "*ifcompare_not_move"
9c08d1fa 10549 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 10550 (if_then_else:SI
8fa3ba89 10551 (match_operator 5 "arm_comparison_operator"
8a18b90c 10552 [(match_operand:SI 3 "s_register_operand" "r,r")
10553 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10554 (not:SI
10555 (match_operand:SI 2 "s_register_operand" "r,r"))
10556 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 10557 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10558 "TARGET_ARM"
8a18b90c 10559 "#"
8fa3ba89 10560 [(set_attr "conds" "clob")
1b7da4ac 10561 (set_attr "length" "8,12")
10562 (set_attr "type" "multiple")]
8fa3ba89 10563)
9c08d1fa 10564
8a18b90c 10565(define_insn "*if_not_move"
10566 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10567 (if_then_else:SI
8fa3ba89 10568 (match_operator 4 "arm_comparison_operator"
8a18b90c 10569 [(match_operand 3 "cc_register" "") (const_int 0)])
10570 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
10571 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 10572 "TARGET_ARM"
8a18b90c 10573 "@
10574 mvn%d4\\t%0, %2
10575 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
10576 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
8fa3ba89 10577 [(set_attr "conds" "use")
1b7da4ac 10578 (set_attr "type" "mvn_reg,multiple,multiple")
8fa3ba89 10579 (set_attr "length" "4,8,8")]
10580)
8a18b90c 10581
10582(define_insn "*ifcompare_shift_move"
9c08d1fa 10583 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 10584 (if_then_else:SI
8fa3ba89 10585 (match_operator 6 "arm_comparison_operator"
8a18b90c 10586 [(match_operand:SI 4 "s_register_operand" "r,r")
10587 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
10588 (match_operator:SI 7 "shift_operator"
10589 [(match_operand:SI 2 "s_register_operand" "r,r")
10590 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
10591 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 10592 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10593 "TARGET_ARM"
9c08d1fa 10594 "#"
8fa3ba89 10595 [(set_attr "conds" "clob")
1b7da4ac 10596 (set_attr "length" "8,12")
10597 (set_attr "type" "multiple")]
8fa3ba89 10598)
9c08d1fa 10599
8a18b90c 10600(define_insn "*if_shift_move"
10601 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10602 (if_then_else:SI
8fa3ba89 10603 (match_operator 5 "arm_comparison_operator"
8a18b90c 10604 [(match_operand 6 "cc_register" "") (const_int 0)])
10605 (match_operator:SI 4 "shift_operator"
10606 [(match_operand:SI 2 "s_register_operand" "r,r,r")
10607 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
10608 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 10609 "TARGET_ARM"
5565501b 10610 "@
8a18b90c 10611 mov%d5\\t%0, %2%S4
10612 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
10613 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
8fa3ba89 10614 [(set_attr "conds" "use")
331beb1a 10615 (set_attr "shift" "2")
a2cd141b 10616 (set_attr "length" "4,8,8")
282b4c75 10617 (set_attr_alternative "type"
10618 [(if_then_else (match_operand 3 "const_int_operand" "")
10619 (const_string "mov_shift" )
10620 (const_string "mov_shift_reg"))
10621 (const_string "multiple")
10622 (const_string "multiple")])]
8fa3ba89 10623)
5565501b 10624
8a18b90c 10625(define_insn "*ifcompare_move_shift"
10626 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 10627 (if_then_else:SI
8fa3ba89 10628 (match_operator 6 "arm_comparison_operator"
8a18b90c 10629 [(match_operand:SI 4 "s_register_operand" "r,r")
10630 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
10631 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
5565501b 10632 (match_operator:SI 7 "shift_operator"
8a18b90c 10633 [(match_operand:SI 2 "s_register_operand" "r,r")
10634 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
bd5b4116 10635 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10636 "TARGET_ARM"
8a18b90c 10637 "#"
8fa3ba89 10638 [(set_attr "conds" "clob")
1b7da4ac 10639 (set_attr "length" "8,12")
10640 (set_attr "type" "multiple")]
8fa3ba89 10641)
5565501b 10642
8a18b90c 10643(define_insn "*if_move_shift"
10644 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 10645 (if_then_else:SI
8fa3ba89 10646 (match_operator 5 "arm_comparison_operator"
8a18b90c 10647 [(match_operand 6 "cc_register" "") (const_int 0)])
10648 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
10649 (match_operator:SI 4 "shift_operator"
10650 [(match_operand:SI 2 "s_register_operand" "r,r,r")
10651 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
cffb2a26 10652 "TARGET_ARM"
5565501b 10653 "@
8a18b90c 10654 mov%D5\\t%0, %2%S4
10655 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
10656 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
8fa3ba89 10657 [(set_attr "conds" "use")
331beb1a 10658 (set_attr "shift" "2")
a2cd141b 10659 (set_attr "length" "4,8,8")
282b4c75 10660 (set_attr_alternative "type"
10661 [(if_then_else (match_operand 3 "const_int_operand" "")
10662 (const_string "mov_shift" )
10663 (const_string "mov_shift_reg"))
10664 (const_string "multiple")
10665 (const_string "multiple")])]
8fa3ba89 10666)
9c08d1fa 10667
f7fbdd4a 10668(define_insn "*ifcompare_shift_shift"
8a18b90c 10669 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 10670 (if_then_else:SI
8fa3ba89 10671 (match_operator 7 "arm_comparison_operator"
8a18b90c 10672 [(match_operand:SI 5 "s_register_operand" "r")
10673 (match_operand:SI 6 "arm_add_operand" "rIL")])
5565501b 10674 (match_operator:SI 8 "shift_operator"
8a18b90c 10675 [(match_operand:SI 1 "s_register_operand" "r")
10676 (match_operand:SI 2 "arm_rhs_operand" "rM")])
5565501b 10677 (match_operator:SI 9 "shift_operator"
8a18b90c 10678 [(match_operand:SI 3 "s_register_operand" "r")
10679 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
bd5b4116 10680 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10681 "TARGET_ARM"
8a18b90c 10682 "#"
8fa3ba89 10683 [(set_attr "conds" "clob")
1b7da4ac 10684 (set_attr "length" "12")
10685 (set_attr "type" "multiple")]
8fa3ba89 10686)
9c08d1fa 10687
8a18b90c 10688(define_insn "*if_shift_shift"
10689 [(set (match_operand:SI 0 "s_register_operand" "=r")
10690 (if_then_else:SI
8fa3ba89 10691 (match_operator 5 "arm_comparison_operator"
8a18b90c 10692 [(match_operand 8 "cc_register" "") (const_int 0)])
10693 (match_operator:SI 6 "shift_operator"
10694 [(match_operand:SI 1 "s_register_operand" "r")
10695 (match_operand:SI 2 "arm_rhs_operand" "rM")])
10696 (match_operator:SI 7 "shift_operator"
10697 [(match_operand:SI 3 "s_register_operand" "r")
10698 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
cffb2a26 10699 "TARGET_ARM"
8a18b90c 10700 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
8fa3ba89 10701 [(set_attr "conds" "use")
331beb1a 10702 (set_attr "shift" "1")
a2cd141b 10703 (set_attr "length" "8")
10704 (set (attr "type") (if_then_else
10705 (and (match_operand 2 "const_int_operand" "")
10706 (match_operand 4 "const_int_operand" ""))
1aed5204 10707 (const_string "mov_shift")
10708 (const_string "mov_shift_reg")))]
8fa3ba89 10709)
8a18b90c 10710
f7fbdd4a 10711(define_insn "*ifcompare_not_arith"
8a18b90c 10712 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 10713 (if_then_else:SI
8fa3ba89 10714 (match_operator 6 "arm_comparison_operator"
8a18b90c 10715 [(match_operand:SI 4 "s_register_operand" "r")
10716 (match_operand:SI 5 "arm_add_operand" "rIL")])
10717 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5565501b 10718 (match_operator:SI 7 "shiftable_operator"
8a18b90c 10719 [(match_operand:SI 2 "s_register_operand" "r")
10720 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
bd5b4116 10721 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10722 "TARGET_ARM"
8a18b90c 10723 "#"
8fa3ba89 10724 [(set_attr "conds" "clob")
1b7da4ac 10725 (set_attr "length" "12")
10726 (set_attr "type" "multiple")]
8fa3ba89 10727)
9c08d1fa 10728
8a18b90c 10729(define_insn "*if_not_arith"
10730 [(set (match_operand:SI 0 "s_register_operand" "=r")
10731 (if_then_else:SI
8fa3ba89 10732 (match_operator 5 "arm_comparison_operator"
8a18b90c 10733 [(match_operand 4 "cc_register" "") (const_int 0)])
10734 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
10735 (match_operator:SI 6 "shiftable_operator"
10736 [(match_operand:SI 2 "s_register_operand" "r")
10737 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
cffb2a26 10738 "TARGET_ARM"
8a18b90c 10739 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
8fa3ba89 10740 [(set_attr "conds" "use")
1aed5204 10741 (set_attr "type" "mvn_reg")
8fa3ba89 10742 (set_attr "length" "8")]
10743)
8a18b90c 10744
10745(define_insn "*ifcompare_arith_not"
10746 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 10747 (if_then_else:SI
8fa3ba89 10748 (match_operator 6 "arm_comparison_operator"
8a18b90c 10749 [(match_operand:SI 4 "s_register_operand" "r")
10750 (match_operand:SI 5 "arm_add_operand" "rIL")])
5565501b 10751 (match_operator:SI 7 "shiftable_operator"
8a18b90c 10752 [(match_operand:SI 2 "s_register_operand" "r")
10753 (match_operand:SI 3 "arm_rhs_operand" "rI")])
10754 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
bd5b4116 10755 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10756 "TARGET_ARM"
8a18b90c 10757 "#"
8fa3ba89 10758 [(set_attr "conds" "clob")
1b7da4ac 10759 (set_attr "length" "12")
10760 (set_attr "type" "multiple")]
8fa3ba89 10761)
9c08d1fa 10762
8a18b90c 10763(define_insn "*if_arith_not"
10764 [(set (match_operand:SI 0 "s_register_operand" "=r")
10765 (if_then_else:SI
8fa3ba89 10766 (match_operator 5 "arm_comparison_operator"
8a18b90c 10767 [(match_operand 4 "cc_register" "") (const_int 0)])
10768 (match_operator:SI 6 "shiftable_operator"
10769 [(match_operand:SI 2 "s_register_operand" "r")
10770 (match_operand:SI 3 "arm_rhs_operand" "rI")])
10771 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
cffb2a26 10772 "TARGET_ARM"
8a18b90c 10773 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
8fa3ba89 10774 [(set_attr "conds" "use")
1b7da4ac 10775 (set_attr "type" "multiple")
8fa3ba89 10776 (set_attr "length" "8")]
10777)
8a18b90c 10778
f7fbdd4a 10779(define_insn "*ifcompare_neg_move"
8a18b90c 10780 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 10781 (if_then_else:SI
8fa3ba89 10782 (match_operator 5 "arm_comparison_operator"
8a18b90c 10783 [(match_operand:SI 3 "s_register_operand" "r,r")
10784 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10785 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
10786 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 10787 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10788 "TARGET_ARM"
8a18b90c 10789 "#"
8fa3ba89 10790 [(set_attr "conds" "clob")
1b7da4ac 10791 (set_attr "length" "8,12")
10792 (set_attr "type" "multiple")]
8fa3ba89 10793)
8a18b90c 10794
530bb693 10795(define_insn_and_split "*if_neg_move"
10796 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
8a18b90c 10797 (if_then_else:SI
8fa3ba89 10798 (match_operator 4 "arm_comparison_operator"
8a18b90c 10799 [(match_operand 3 "cc_register" "") (const_int 0)])
530bb693 10800 (neg:SI (match_operand:SI 2 "s_register_operand" "l,r"))
10801 (match_operand:SI 1 "s_register_operand" "0,0")))]
10802 "TARGET_32BIT"
10803 "#"
10804 "&& reload_completed"
10805 [(cond_exec (match_op_dup 4 [(match_dup 3) (const_int 0)])
10806 (set (match_dup 0) (neg:SI (match_dup 2))))]
10807 ""
8fa3ba89 10808 [(set_attr "conds" "use")
530bb693 10809 (set_attr "length" "4")
10810 (set_attr "arch" "t2,32")
8bdfd6ed 10811 (set_attr "enabled_for_short_it" "yes,no")
530bb693 10812 (set_attr "type" "logic_shift_imm")]
8fa3ba89 10813)
9c08d1fa 10814
f7fbdd4a 10815(define_insn "*ifcompare_move_neg"
8a18b90c 10816 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 10817 (if_then_else:SI
8fa3ba89 10818 (match_operator 5 "arm_comparison_operator"
8a18b90c 10819 [(match_operand:SI 3 "s_register_operand" "r,r")
10820 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10821 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
10822 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 10823 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10824 "TARGET_ARM"
8a18b90c 10825 "#"
8fa3ba89 10826 [(set_attr "conds" "clob")
1b7da4ac 10827 (set_attr "length" "8,12")
10828 (set_attr "type" "multiple")]
8fa3ba89 10829)
8a18b90c 10830
530bb693 10831(define_insn_and_split "*if_move_neg"
10832 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
8a18b90c 10833 (if_then_else:SI
8fa3ba89 10834 (match_operator 4 "arm_comparison_operator"
8a18b90c 10835 [(match_operand 3 "cc_register" "") (const_int 0)])
530bb693 10836 (match_operand:SI 1 "s_register_operand" "0,0")
10837 (neg:SI (match_operand:SI 2 "s_register_operand" "l,r"))))]
10838 "TARGET_32BIT"
10839 "#"
10840 "&& reload_completed"
10841 [(cond_exec (match_dup 5)
10842 (set (match_dup 0) (neg:SI (match_dup 2))))]
10843 {
10844 machine_mode mode = GET_MODE (operands[3]);
10845 rtx_code rc = GET_CODE (operands[4]);
10846
10847 if (mode == CCFPmode || mode == CCFPEmode)
10848 rc = reverse_condition_maybe_unordered (rc);
10849 else
10850 rc = reverse_condition (rc);
10851
10852 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[3], const0_rtx);
10853 }
0d66636f 10854 [(set_attr "conds" "use")
530bb693 10855 (set_attr "length" "4")
10856 (set_attr "arch" "t2,32")
8bdfd6ed 10857 (set_attr "enabled_for_short_it" "yes,no")
530bb693 10858 (set_attr "type" "logic_shift_imm")]
0d66636f 10859)
9c08d1fa 10860
f7fbdd4a 10861(define_insn "*arith_adjacentmem"
9c08d1fa 10862 [(set (match_operand:SI 0 "s_register_operand" "=r")
10863 (match_operator:SI 1 "shiftable_operator"
10864 [(match_operand:SI 2 "memory_operand" "m")
10865 (match_operand:SI 3 "memory_operand" "m")]))
10866 (clobber (match_scratch:SI 4 "=r"))]
cffb2a26 10867 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9c08d1fa 10868 "*
215b30b3 10869 {
10870 rtx ldm[3];
10871 rtx arith[4];
94dee231 10872 rtx base_reg;
10873 HOST_WIDE_INT val1 = 0, val2 = 0;
9c08d1fa 10874
215b30b3 10875 if (REGNO (operands[0]) > REGNO (operands[4]))
10876 {
10877 ldm[1] = operands[4];
10878 ldm[2] = operands[0];
10879 }
10880 else
10881 {
10882 ldm[1] = operands[0];
10883 ldm[2] = operands[4];
10884 }
94dee231 10885
10886 base_reg = XEXP (operands[2], 0);
10887
10888 if (!REG_P (base_reg))
10889 {
10890 val1 = INTVAL (XEXP (base_reg, 1));
10891 base_reg = XEXP (base_reg, 0);
10892 }
10893
10894 if (!REG_P (XEXP (operands[3], 0)))
215b30b3 10895 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
94dee231 10896
215b30b3 10897 arith[0] = operands[0];
10898 arith[3] = operands[1];
94dee231 10899
215b30b3 10900 if (val1 < val2)
10901 {
10902 arith[1] = ldm[1];
10903 arith[2] = ldm[2];
10904 }
10905 else
10906 {
10907 arith[1] = ldm[2];
10908 arith[2] = ldm[1];
10909 }
94dee231 10910
10911 ldm[0] = base_reg;
10912 if (val1 !=0 && val2 != 0)
215b30b3 10913 {
cdb1295a 10914 rtx ops[3];
10915
94dee231 10916 if (val1 == 4 || val2 == 4)
10917 /* Other val must be 8, since we know they are adjacent and neither
10918 is zero. */
3ef90e77 10919 output_asm_insn (\"ldmib%?\\t%0, {%1, %2}\", ldm);
cdb1295a 10920 else if (const_ok_for_arm (val1) || const_ok_for_arm (-val1))
94dee231 10921 {
94dee231 10922 ldm[0] = ops[0] = operands[4];
10923 ops[1] = base_reg;
10924 ops[2] = GEN_INT (val1);
10925 output_add_immediate (ops);
10926 if (val1 < val2)
3ef90e77 10927 output_asm_insn (\"ldmia%?\\t%0, {%1, %2}\", ldm);
94dee231 10928 else
3ef90e77 10929 output_asm_insn (\"ldmda%?\\t%0, {%1, %2}\", ldm);
94dee231 10930 }
cdb1295a 10931 else
10932 {
10933 /* Offset is out of range for a single add, so use two ldr. */
10934 ops[0] = ldm[1];
10935 ops[1] = base_reg;
10936 ops[2] = GEN_INT (val1);
10937 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10938 ops[0] = ldm[2];
10939 ops[2] = GEN_INT (val2);
10940 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10941 }
215b30b3 10942 }
94dee231 10943 else if (val1 != 0)
215b30b3 10944 {
215b30b3 10945 if (val1 < val2)
3ef90e77 10946 output_asm_insn (\"ldmda%?\\t%0, {%1, %2}\", ldm);
215b30b3 10947 else
3ef90e77 10948 output_asm_insn (\"ldmia%?\\t%0, {%1, %2}\", ldm);
215b30b3 10949 }
10950 else
10951 {
215b30b3 10952 if (val1 < val2)
3ef90e77 10953 output_asm_insn (\"ldmia%?\\t%0, {%1, %2}\", ldm);
215b30b3 10954 else
3ef90e77 10955 output_asm_insn (\"ldmda%?\\t%0, {%1, %2}\", ldm);
215b30b3 10956 }
10957 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
10958 return \"\";
10959 }"
10960 [(set_attr "length" "12")
10961 (set_attr "predicable" "yes")
9f2c2a36 10962 (set_attr "type" "load_4")]
215b30b3 10963)
9c08d1fa 10964
9c08d1fa 10965; This pattern is never tried by combine, so do it as a peephole
10966
a0f94409 10967(define_peephole2
372575c7 10968 [(set (match_operand:SI 0 "arm_general_register_operand" "")
10969 (match_operand:SI 1 "arm_general_register_operand" ""))
bd5b4116 10970 (set (reg:CC CC_REGNUM)
aea4c774 10971 (compare:CC (match_dup 1) (const_int 0)))]
372575c7 10972 "TARGET_ARM"
a0f94409 10973 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
10974 (set (match_dup 0) (match_dup 1))])]
10975 ""
0d66636f 10976)
9c08d1fa 10977
9c08d1fa 10978(define_split
10979 [(set (match_operand:SI 0 "s_register_operand" "")
10980 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
10981 (const_int 0))
8fa3ba89 10982 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9c08d1fa 10983 [(match_operand:SI 3 "s_register_operand" "")
10984 (match_operand:SI 4 "arm_rhs_operand" "")]))))
10985 (clobber (match_operand:SI 5 "s_register_operand" ""))]
cffb2a26 10986 "TARGET_ARM"
9c08d1fa 10987 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
10988 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
10989 (match_dup 5)))]
215b30b3 10990 ""
10991)
9c08d1fa 10992
aea4c774 10993;; This split can be used because CC_Z mode implies that the following
10994;; branch will be an equality, or an unsigned inequality, so the sign
10995;; extension is not needed.
9c08d1fa 10996
aea4c774 10997(define_split
bd5b4116 10998 [(set (reg:CC_Z CC_REGNUM)
aea4c774 10999 (compare:CC_Z
11000 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9c08d1fa 11001 (const_int 24))
aea4c774 11002 (match_operand 1 "const_int_operand" "")))
11003 (clobber (match_scratch:SI 2 ""))]
cffb2a26 11004 "TARGET_ARM
8c4e8755 11005 && ((UINTVAL (operands[1]))
11006 == ((UINTVAL (operands[1])) >> 24) << 24)"
aea4c774 11007 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
bd5b4116 11008 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
aea4c774 11009 "
9c08d1fa 11010 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
215b30b3 11011 "
11012)
25f905c2 11013;; ??? Check the patterns above for Thumb-2 usefulness
9c08d1fa 11014
87b22bf7 11015(define_expand "prologue"
11016 [(clobber (const_int 0))]
cffb2a26 11017 "TARGET_EITHER"
25f905c2 11018 "if (TARGET_32BIT)
cffb2a26 11019 arm_expand_prologue ();
11020 else
25f905c2 11021 thumb1_expand_prologue ();
87b22bf7 11022 DONE;
cffb2a26 11023 "
11024)
87b22bf7 11025
56d27660 11026(define_expand "epilogue"
4c44712e 11027 [(clobber (const_int 0))]
cffb2a26 11028 "TARGET_EITHER"
56d27660 11029 "
18d50ae6 11030 if (crtl->calls_eh_return)
fb94f18b 11031 emit_insn (gen_force_register_use (gen_rtx_REG (Pmode, 2)));
25f905c2 11032 if (TARGET_THUMB1)
c3635784 11033 {
11034 thumb1_expand_epilogue ();
11035 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
11036 gen_rtvec (1, ret_rtx), VUNSPEC_EPILOGUE));
11037 }
11038 else if (HAVE_return)
11039 {
11040 /* HAVE_return is testing for USE_RETURN_INSN (FALSE). Hence,
11041 no need for explicit testing again. */
11042 emit_jump_insn (gen_return ());
11043 }
11044 else if (TARGET_32BIT)
11045 {
11046 arm_expand_epilogue (true);
11047 }
cffb2a26 11048 DONE;
11049 "
11050)
56d27660 11051
ef5651d0 11052;; Note - although unspec_volatile's USE all hard registers,
11053;; USEs are ignored after relaod has completed. Thus we need
11054;; to add an unspec of the link register to ensure that flow
11055;; does not think that it is unused by the sibcall branch that
11056;; will replace the standard function epilogue.
c3635784 11057(define_expand "sibcall_epilogue"
fb94f18b 11058 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_REGISTER_USE)
c3635784 11059 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
11060 "TARGET_32BIT"
11061 "
11062 arm_expand_epilogue (false);
11063 DONE;
11064 "
1c494086 11065)
11066
cffb2a26 11067(define_expand "eh_epilogue"
3934ae0e 11068 [(use (match_operand:SI 0 "register_operand"))
11069 (use (match_operand:SI 1 "register_operand"))
11070 (use (match_operand:SI 2 "register_operand"))]
cffb2a26 11071 "TARGET_EITHER"
11072 "
215b30b3 11073 {
11074 cfun->machine->eh_epilogue_sp_ofs = operands[1];
0438d37f 11075 if (!REG_P (operands[2]) || REGNO (operands[2]) != 2)
215b30b3 11076 {
11077 rtx ra = gen_rtx_REG (Pmode, 2);
11078
11079 emit_move_insn (ra, operands[2]);
11080 operands[2] = ra;
11081 }
5cf3595a 11082 /* This is a hack -- we may have crystalized the function type too
11083 early. */
11084 cfun->machine->func_type = 0;
215b30b3 11085 }"
11086)
56d27660 11087
9c08d1fa 11088;; This split is only used during output to reduce the number of patterns
11089;; that need assembler instructions adding to them. We allowed the setting
11090;; of the conditions to be implicit during rtl generation so that
11091;; the conditional compare patterns would work. However this conflicts to
8a18b90c 11092;; some extent with the conditional data operations, so we have to split them
9c08d1fa 11093;; up again here.
11094
25f905c2 11095;; ??? Need to audit these splitters for Thumb-2. Why isn't normal
11096;; conditional execution sufficient?
11097
9c08d1fa 11098(define_split
11099 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 11100 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
11101 [(match_operand 2 "" "") (match_operand 3 "" "")])
11102 (match_dup 0)
11103 (match_operand 4 "" "")))
bd5b4116 11104 (clobber (reg:CC CC_REGNUM))]
ac8b093b 11105 "TARGET_ARM && reload_completed"
8fa3ba89 11106 [(set (match_dup 5) (match_dup 6))
11107 (cond_exec (match_dup 7)
11108 (set (match_dup 0) (match_dup 4)))]
11109 "
11110 {
3754d046 11111 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8fa3ba89 11112 operands[2], operands[3]);
11113 enum rtx_code rc = GET_CODE (operands[1]);
11114
bd5b4116 11115 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 11116 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
11117 if (mode == CCFPmode || mode == CCFPEmode)
11118 rc = reverse_condition_maybe_unordered (rc);
11119 else
11120 rc = reverse_condition (rc);
11121
11122 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
11123 }"
11124)
11125
11126(define_split
11127 [(set (match_operand:SI 0 "s_register_operand" "")
11128 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
11129 [(match_operand 2 "" "") (match_operand 3 "" "")])
11130 (match_operand 4 "" "")
11131 (match_dup 0)))
bd5b4116 11132 (clobber (reg:CC CC_REGNUM))]
ac8b093b 11133 "TARGET_ARM && reload_completed"
8fa3ba89 11134 [(set (match_dup 5) (match_dup 6))
11135 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
11136 (set (match_dup 0) (match_dup 4)))]
11137 "
11138 {
3754d046 11139 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8fa3ba89 11140 operands[2], operands[3]);
11141
bd5b4116 11142 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 11143 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
11144 }"
11145)
11146
11147(define_split
11148 [(set (match_operand:SI 0 "s_register_operand" "")
11149 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9c08d1fa 11150 [(match_operand 2 "" "") (match_operand 3 "" "")])
11151 (match_operand 4 "" "")
11152 (match_operand 5 "" "")))
bd5b4116 11153 (clobber (reg:CC CC_REGNUM))]
ac8b093b 11154 "TARGET_ARM && reload_completed"
8fa3ba89 11155 [(set (match_dup 6) (match_dup 7))
11156 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
11157 (set (match_dup 0) (match_dup 4)))
11158 (cond_exec (match_dup 8)
11159 (set (match_dup 0) (match_dup 5)))]
11160 "
11161 {
3754d046 11162 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8fa3ba89 11163 operands[2], operands[3]);
11164 enum rtx_code rc = GET_CODE (operands[1]);
11165
bd5b4116 11166 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 11167 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
11168 if (mode == CCFPmode || mode == CCFPEmode)
11169 rc = reverse_condition_maybe_unordered (rc);
11170 else
11171 rc = reverse_condition (rc);
11172
11173 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
11174 }"
11175)
11176
cffb2a26 11177(define_split
11178 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 11179 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
cffb2a26 11180 [(match_operand:SI 2 "s_register_operand" "")
11181 (match_operand:SI 3 "arm_add_operand" "")])
11182 (match_operand:SI 4 "arm_rhs_operand" "")
11183 (not:SI
11184 (match_operand:SI 5 "s_register_operand" ""))))
bd5b4116 11185 (clobber (reg:CC CC_REGNUM))]
ac8b093b 11186 "TARGET_ARM && reload_completed"
cffb2a26 11187 [(set (match_dup 6) (match_dup 7))
f6c53574 11188 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
11189 (set (match_dup 0) (match_dup 4)))
11190 (cond_exec (match_dup 8)
11191 (set (match_dup 0) (not:SI (match_dup 5))))]
cffb2a26 11192 "
215b30b3 11193 {
3754d046 11194 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
215b30b3 11195 operands[2], operands[3]);
f6c53574 11196 enum rtx_code rc = GET_CODE (operands[1]);
cffb2a26 11197
bd5b4116 11198 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
1a83b3ff 11199 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
f6c53574 11200 if (mode == CCFPmode || mode == CCFPEmode)
11201 rc = reverse_condition_maybe_unordered (rc);
11202 else
11203 rc = reverse_condition (rc);
11204
11205 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
215b30b3 11206 }"
11207)
cffb2a26 11208
11209(define_insn "*cond_move_not"
11210 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 11211 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
cffb2a26 11212 [(match_operand 3 "cc_register" "") (const_int 0)])
11213 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
11214 (not:SI
11215 (match_operand:SI 2 "s_register_operand" "r,r"))))]
11216 "TARGET_ARM"
11217 "@
11218 mvn%D4\\t%0, %2
11219 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
0d66636f 11220 [(set_attr "conds" "use")
1b7da4ac 11221 (set_attr "type" "mvn_reg,multiple")
0d66636f 11222 (set_attr "length" "4,8")]
11223)
cffb2a26 11224
9c08d1fa 11225;; The next two patterns occur when an AND operation is followed by a
11226;; scc insn sequence
11227
f7fbdd4a 11228(define_insn "*sign_extract_onebit"
9c08d1fa 11229 [(set (match_operand:SI 0 "s_register_operand" "=r")
11230 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
11231 (const_int 1)
ed750274 11232 (match_operand:SI 2 "const_int_operand" "n")))
11233 (clobber (reg:CC CC_REGNUM))]
cffb2a26 11234 "TARGET_ARM"
9c08d1fa 11235 "*
0d66636f 11236 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
11237 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
11238 return \"mvnne\\t%0, #0\";
11239 "
11240 [(set_attr "conds" "clob")
1b7da4ac 11241 (set_attr "length" "8")
11242 (set_attr "type" "multiple")]
0d66636f 11243)
9c08d1fa 11244
f7fbdd4a 11245(define_insn "*not_signextract_onebit"
9c08d1fa 11246 [(set (match_operand:SI 0 "s_register_operand" "=r")
11247 (not:SI
11248 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
11249 (const_int 1)
ed750274 11250 (match_operand:SI 2 "const_int_operand" "n"))))
11251 (clobber (reg:CC CC_REGNUM))]
cffb2a26 11252 "TARGET_ARM"
9c08d1fa 11253 "*
0d66636f 11254 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
11255 output_asm_insn (\"tst\\t%1, %2\", operands);
11256 output_asm_insn (\"mvneq\\t%0, #0\", operands);
11257 return \"movne\\t%0, #0\";
11258 "
11259 [(set_attr "conds" "clob")
1b7da4ac 11260 (set_attr "length" "12")
11261 (set_attr "type" "multiple")]
0d66636f 11262)
25f905c2 11263;; ??? The above patterns need auditing for Thumb-2
87b22bf7 11264
0d66636f 11265;; Push multiple registers to the stack. Registers are in parallel (use ...)
11266;; expressions. For simplicity, the first register is also in the unspec
11267;; part.
08508cbf 11268;; To avoid the usage of GNU extension, the length attribute is computed
11269;; in a C function arm_attr_length_push_multi.
f7fbdd4a 11270(define_insn "*push_multi"
87b22bf7 11271 [(match_parallel 2 "multi_register_push"
7571d3f7 11272 [(set (match_operand:BLK 0 "push_mult_memory_operand" "")
3cc80a30 11273 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "")]
e1159bbe 11274 UNSPEC_PUSH_MULT))])]
7571d3f7 11275 ""
87b22bf7 11276 "*
215b30b3 11277 {
11278 int num_saves = XVECLEN (operands[2], 0);
ed593f11 11279
215b30b3 11280 /* For the StrongARM at least it is faster to
25f905c2 11281 use STR to store only a single register.
542d5028 11282 In Thumb mode always use push, and the assembler will pick
11283 something appropriate. */
25f905c2 11284 if (num_saves == 1 && TARGET_ARM)
61309563 11285 output_asm_insn (\"str%?\\t%1, [%m0, #-4]!\", operands);
215b30b3 11286 else
11287 {
11288 int i;
11289 char pattern[100];
ed593f11 11290
3ef90e77 11291 if (TARGET_32BIT)
61309563 11292 strcpy (pattern, \"push%?\\t{%1\");
25f905c2 11293 else
11294 strcpy (pattern, \"push\\t{%1\");
215b30b3 11295
6079f055 11296 for (i = 1; i < num_saves; i++)
215b30b3 11297 {
11298 strcat (pattern, \", %|\");
11299 strcat (pattern,
11300 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
11301 }
11302
11303 strcat (pattern, \"}\");
11304 output_asm_insn (pattern, operands);
11305 }
11306
11307 return \"\";
11308 }"
9f2c2a36 11309 [(set_attr "type" "store_16")
a6864a24 11310 (set (attr "length")
08508cbf 11311 (symbol_ref "arm_attr_length_push_multi (operands[2], operands[1])"))]
215b30b3 11312)
f7fbdd4a 11313
4c58c898 11314(define_insn "stack_tie"
11315 [(set (mem:BLK (scratch))
aaa37ad6 11316 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "rk")
11317 (match_operand:SI 1 "s_register_operand" "rk")]
4c58c898 11318 UNSPEC_PRLG_STK))]
11319 ""
11320 ""
1b7da4ac 11321 [(set_attr "length" "0")
11322 (set_attr "type" "block")]
4c58c898 11323)
11324
426be8c5 11325;; Pop (as used in epilogue RTL)
11326;;
11327(define_insn "*load_multiple_with_writeback"
11328 [(match_parallel 0 "load_multiple_operation"
11329 [(set (match_operand:SI 1 "s_register_operand" "+rk")
11330 (plus:SI (match_dup 1)
809003b3 11331 (match_operand:SI 2 "const_int_I_operand" "I")))
426be8c5 11332 (set (match_operand:SI 3 "s_register_operand" "=rk")
11333 (mem:SI (match_dup 1)))
11334 ])]
11335 "TARGET_32BIT && (reload_in_progress || reload_completed)"
11336 "*
11337 {
11338 arm_output_multireg_pop (operands, /*return_pc=*/false,
11339 /*cond=*/const_true_rtx,
11340 /*reverse=*/false,
11341 /*update=*/true);
11342 return \"\";
11343 }
11344 "
9f2c2a36 11345 [(set_attr "type" "load_16")
5431c9c9 11346 (set_attr "predicable" "yes")
11347 (set (attr "length")
11348 (symbol_ref "arm_attr_length_pop_multi (operands,
11349 /*return_pc=*/false,
11350 /*write_back_p=*/true)"))]
426be8c5 11351)
11352
11353;; Pop with return (as used in epilogue RTL)
11354;;
11355;; This instruction is generated when the registers are popped at the end of
11356;; epilogue. Here, instead of popping the value into LR and then generating
11357;; jump to LR, value is popped into PC directly. Hence, the pattern is combined
11358;; with (return).
11359(define_insn "*pop_multiple_with_writeback_and_return"
11360 [(match_parallel 0 "pop_multiple_return"
11361 [(return)
11362 (set (match_operand:SI 1 "s_register_operand" "+rk")
11363 (plus:SI (match_dup 1)
809003b3 11364 (match_operand:SI 2 "const_int_I_operand" "I")))
426be8c5 11365 (set (match_operand:SI 3 "s_register_operand" "=rk")
11366 (mem:SI (match_dup 1)))
11367 ])]
11368 "TARGET_32BIT && (reload_in_progress || reload_completed)"
11369 "*
11370 {
11371 arm_output_multireg_pop (operands, /*return_pc=*/true,
11372 /*cond=*/const_true_rtx,
11373 /*reverse=*/false,
11374 /*update=*/true);
11375 return \"\";
11376 }
11377 "
9f2c2a36 11378 [(set_attr "type" "load_16")
5431c9c9 11379 (set_attr "predicable" "yes")
11380 (set (attr "length")
11381 (symbol_ref "arm_attr_length_pop_multi (operands, /*return_pc=*/true,
11382 /*write_back_p=*/true)"))]
426be8c5 11383)
11384
11385(define_insn "*pop_multiple_with_return"
11386 [(match_parallel 0 "pop_multiple_return"
11387 [(return)
11388 (set (match_operand:SI 2 "s_register_operand" "=rk")
11389 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
11390 ])]
11391 "TARGET_32BIT && (reload_in_progress || reload_completed)"
11392 "*
11393 {
11394 arm_output_multireg_pop (operands, /*return_pc=*/true,
11395 /*cond=*/const_true_rtx,
11396 /*reverse=*/false,
11397 /*update=*/false);
11398 return \"\";
11399 }
11400 "
9f2c2a36 11401 [(set_attr "type" "load_16")
5431c9c9 11402 (set_attr "predicable" "yes")
11403 (set (attr "length")
11404 (symbol_ref "arm_attr_length_pop_multi (operands, /*return_pc=*/true,
11405 /*write_back_p=*/false)"))]
426be8c5 11406)
11407
11408;; Load into PC and return
11409(define_insn "*ldr_with_return"
11410 [(return)
11411 (set (reg:SI PC_REGNUM)
11412 (mem:SI (post_inc:SI (match_operand:SI 0 "s_register_operand" "+rk"))))]
11413 "TARGET_32BIT && (reload_in_progress || reload_completed)"
11414 "ldr%?\t%|pc, [%0], #4"
9f2c2a36 11415 [(set_attr "type" "load_4")
426be8c5 11416 (set_attr "predicable" "yes")]
11417)
1a0b0f12 11418;; Pop for floating point registers (as used in epilogue RTL)
11419(define_insn "*vfp_pop_multiple_with_writeback"
11420 [(match_parallel 0 "pop_multiple_fp"
11421 [(set (match_operand:SI 1 "s_register_operand" "+rk")
11422 (plus:SI (match_dup 1)
809003b3 11423 (match_operand:SI 2 "const_int_I_operand" "I")))
2f2163a4 11424 (set (match_operand:DF 3 "vfp_hard_register_operand" "")
1a0b0f12 11425 (mem:DF (match_dup 1)))])]
d7216193 11426 "TARGET_32BIT && TARGET_HARD_FLOAT"
1a0b0f12 11427 "*
11428 {
11429 int num_regs = XVECLEN (operands[0], 0);
11430 char pattern[100];
11431 rtx op_list[2];
b34d8dac 11432 strcpy (pattern, \"vldm\\t\");
1a0b0f12 11433 strcat (pattern, reg_names[REGNO (SET_DEST (XVECEXP (operands[0], 0, 0)))]);
11434 strcat (pattern, \"!, {\");
11435 op_list[0] = XEXP (XVECEXP (operands[0], 0, 1), 0);
11436 strcat (pattern, \"%P0\");
11437 if ((num_regs - 1) > 1)
11438 {
11439 strcat (pattern, \"-%P1\");
11440 op_list [1] = XEXP (XVECEXP (operands[0], 0, num_regs - 1), 0);
11441 }
11442
11443 strcat (pattern, \"}\");
11444 output_asm_insn (pattern, op_list);
11445 return \"\";
11446 }
11447 "
9f2c2a36 11448 [(set_attr "type" "load_16")
1a0b0f12 11449 (set_attr "conds" "unconditional")
11450 (set_attr "predicable" "no")]
11451)
11452
f7fbdd4a 11453;; Special patterns for dealing with the constant pool
11454
cffb2a26 11455(define_insn "align_4"
e1159bbe 11456 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
cffb2a26 11457 "TARGET_EITHER"
f7fbdd4a 11458 "*
cffb2a26 11459 assemble_align (32);
f7fbdd4a 11460 return \"\";
cffb2a26 11461 "
1b7da4ac 11462 [(set_attr "type" "no_insn")]
cffb2a26 11463)
f7fbdd4a 11464
755eb2b4 11465(define_insn "align_8"
11466 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
f9273c43 11467 "TARGET_EITHER"
755eb2b4 11468 "*
11469 assemble_align (64);
11470 return \"\";
11471 "
1b7da4ac 11472 [(set_attr "type" "no_insn")]
755eb2b4 11473)
11474
cffb2a26 11475(define_insn "consttable_end"
e1159bbe 11476 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
cffb2a26 11477 "TARGET_EITHER"
f7fbdd4a 11478 "*
cffb2a26 11479 making_const_table = FALSE;
f7fbdd4a 11480 return \"\";
cffb2a26 11481 "
1b7da4ac 11482 [(set_attr "type" "no_insn")]
cffb2a26 11483)
f7fbdd4a 11484
0e207eb8 11485(define_insn "consttable_1"
11486 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
11487 "TARGET_EITHER"
11488 "*
11489 making_const_table = TRUE;
11490 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
11491 assemble_zeros (3);
11492 return \"\";
11493 "
11494 [(set_attr "length" "4")
11495 (set_attr "type" "no_insn")]
11496)
11497
11498(define_insn "consttable_2"
11499 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
11500 "TARGET_EITHER"
11501 "*
11502 {
11503 rtx x = operands[0];
11504 making_const_table = TRUE;
11505 switch (GET_MODE_CLASS (GET_MODE (x)))
11506 {
11507 case MODE_FLOAT:
11508 arm_emit_fp16_const (x);
11509 break;
11510 default:
11511 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
11512 assemble_zeros (2);
11513 break;
11514 }
11515 return \"\";
11516 }"
11517 [(set_attr "length" "4")
11518 (set_attr "type" "no_insn")]
11519)
11520
cffb2a26 11521(define_insn "consttable_4"
e1159bbe 11522 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
cffb2a26 11523 "TARGET_EITHER"
11524 "*
11525 {
9b8516be 11526 rtx x = operands[0];
cffb2a26 11527 making_const_table = TRUE;
0f97e0f5 11528 scalar_float_mode float_mode;
11529 if (is_a <scalar_float_mode> (GET_MODE (x), &float_mode))
11530 assemble_real (*CONST_DOUBLE_REAL_VALUE (x), float_mode, BITS_PER_WORD);
11531 else
cffb2a26 11532 {
7b04c5d5 11533 /* XXX: Sometimes gcc does something really dumb and ends up with
11534 a HIGH in a constant pool entry, usually because it's trying to
11535 load into a VFP register. We know this will always be used in
11536 combination with a LO_SUM which ignores the high bits, so just
11537 strip off the HIGH. */
11538 if (GET_CODE (x) == HIGH)
11539 x = XEXP (x, 0);
9b8516be 11540 assemble_integer (x, 4, BITS_PER_WORD, 1);
11541 mark_symbol_refs_as_used (x);
cffb2a26 11542 }
11543 return \"\";
11544 }"
1b7da4ac 11545 [(set_attr "length" "4")
11546 (set_attr "type" "no_insn")]
cffb2a26 11547)
11548
11549(define_insn "consttable_8"
e1159bbe 11550 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
cffb2a26 11551 "TARGET_EITHER"
11552 "*
11553 {
11554 making_const_table = TRUE;
0f97e0f5 11555 scalar_float_mode float_mode;
11556 if (is_a <scalar_float_mode> (GET_MODE (operands[0]), &float_mode))
11557 assemble_real (*CONST_DOUBLE_REAL_VALUE (operands[0]),
11558 float_mode, BITS_PER_WORD);
11559 else
11560 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
cffb2a26 11561 return \"\";
11562 }"
1b7da4ac 11563 [(set_attr "length" "8")
11564 (set_attr "type" "no_insn")]
cffb2a26 11565)
11566
d98a3884 11567(define_insn "consttable_16"
11568 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_16)]
11569 "TARGET_EITHER"
11570 "*
11571 {
11572 making_const_table = TRUE;
0f97e0f5 11573 scalar_float_mode float_mode;
11574 if (is_a <scalar_float_mode> (GET_MODE (operands[0]), &float_mode))
11575 assemble_real (*CONST_DOUBLE_REAL_VALUE (operands[0]),
11576 float_mode, BITS_PER_WORD);
11577 else
11578 assemble_integer (operands[0], 16, BITS_PER_WORD, 1);
d98a3884 11579 return \"\";
11580 }"
1b7da4ac 11581 [(set_attr "length" "16")
11582 (set_attr "type" "no_insn")]
d98a3884 11583)
11584
331beb1a 11585;; V5 Instructions,
11586
8f4be2be 11587(define_insn "clzsi2"
11588 [(set (match_operand:SI 0 "s_register_operand" "=r")
11589 (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
b232e6b5 11590 "TARGET_32BIT && arm_arch5t"
ee7cbe0e 11591 "clz%?\\t%0, %1"
bcaec148 11592 [(set_attr "predicable" "yes")
bebe9bbb 11593 (set_attr "type" "clz")])
331beb1a 11594
099ad98b 11595(define_insn "rbitsi2"
11596 [(set (match_operand:SI 0 "s_register_operand" "=r")
11597 (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")] UNSPEC_RBIT))]
11598 "TARGET_32BIT && arm_arch_thumb2"
11599 "rbit%?\\t%0, %1"
11600 [(set_attr "predicable" "yes")
bebe9bbb 11601 (set_attr "type" "clz")])
099ad98b 11602
99ffa689 11603;; Keep this as a CTZ expression until after reload and then split
11604;; into RBIT + CLZ. Since RBIT is represented as an UNSPEC it is unlikely
11605;; to fold with any other expression.
11606
11607(define_insn_and_split "ctzsi2"
11608 [(set (match_operand:SI 0 "s_register_operand" "=r")
11609 (ctz:SI (match_operand:SI 1 "s_register_operand" "r")))]
099ad98b 11610 "TARGET_32BIT && arm_arch_thumb2"
99ffa689 11611 "#"
11612 "&& reload_completed"
11613 [(const_int 0)]
099ad98b 11614 "
99ffa689 11615 emit_insn (gen_rbitsi2 (operands[0], operands[1]));
11616 emit_insn (gen_clzsi2 (operands[0], operands[0]));
11617 DONE;
11618")
099ad98b 11619
e1159bbe 11620;; V5E instructions.
331beb1a 11621
11622(define_insn "prefetch"
f4e79814 11623 [(prefetch (match_operand:SI 0 "address_operand" "p")
11624 (match_operand:SI 1 "" "")
11625 (match_operand:SI 2 "" ""))]
b232e6b5 11626 "TARGET_32BIT && arm_arch5te"
1b7da4ac 11627 "pld\\t%a0"
9f2c2a36 11628 [(set_attr "type" "load_4")]
1b7da4ac 11629)
331beb1a 11630
0d66636f 11631;; General predication pattern
11632
11633(define_cond_exec
11634 [(match_operator 0 "arm_comparison_operator"
11635 [(match_operand 1 "cc_register" "")
11636 (const_int 0)])]
580f4c48 11637 "TARGET_32BIT
11638 && (!TARGET_NO_VOLATILE_CE || !volatile_refs_p (PATTERN (insn)))"
0d66636f 11639 ""
c7a58118 11640[(set_attr "predicated" "yes")]
0d66636f 11641)
11642
fb94f18b 11643(define_insn "force_register_use"
11644 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_REGISTER_USE)]
063a05c7 11645 ""
fb94f18b 11646 "%@ %0 needed"
1b7da4ac 11647 [(set_attr "length" "0")
11648 (set_attr "type" "no_insn")]
063a05c7 11649)
7db9af5d 11650
4c44712e 11651
11652;; Patterns for exception handling
11653
11654(define_expand "eh_return"
3934ae0e 11655 [(use (match_operand 0 "general_operand"))]
4c44712e 11656 "TARGET_EITHER"
11657 "
11658 {
25f905c2 11659 if (TARGET_32BIT)
4c44712e 11660 emit_insn (gen_arm_eh_return (operands[0]));
11661 else
11662 emit_insn (gen_thumb_eh_return (operands[0]));
11663 DONE;
11664 }"
11665)
11666
11667;; We can't expand this before we know where the link register is stored.
11668(define_insn_and_split "arm_eh_return"
11669 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
11670 VUNSPEC_EH_RETURN)
11671 (clobber (match_scratch:SI 1 "=&r"))]
11672 "TARGET_ARM"
11673 "#"
11674 "&& reload_completed"
11675 [(const_int 0)]
11676 "
11677 {
11678 arm_set_return_address (operands[0], operands[1]);
11679 DONE;
11680 }"
11681)
11682
f655717d 11683\f
11684;; TLS support
11685
11686(define_insn "load_tp_hard"
11687 [(set (match_operand:SI 0 "register_operand" "=r")
11688 (unspec:SI [(const_int 0)] UNSPEC_TLS))]
11689 "TARGET_HARD_TP"
11690 "mrc%?\\tp15, 0, %0, c13, c0, 3\\t@ load_tp_hard"
1b7da4ac 11691 [(set_attr "predicable" "yes")
4b5d7374 11692 (set_attr "type" "mrs")]
f655717d 11693)
11694
11695;; Doesn't clobber R1-R3. Must use r0 for the first operand.
11696(define_insn "load_tp_soft"
11697 [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
11698 (clobber (reg:SI LR_REGNUM))
11699 (clobber (reg:SI IP_REGNUM))
11700 (clobber (reg:CC CC_REGNUM))]
11701 "TARGET_SOFT_TP"
11702 "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
1b7da4ac 11703 [(set_attr "conds" "clob")
11704 (set_attr "type" "branch")]
f655717d 11705)
11706
f41e4452 11707;; tls descriptor call
11708(define_insn "tlscall"
11709 [(set (reg:SI R0_REGNUM)
11710 (unspec:SI [(reg:SI R0_REGNUM)
11711 (match_operand:SI 0 "" "X")
11712 (match_operand 1 "" "")] UNSPEC_TLS))
11713 (clobber (reg:SI R1_REGNUM))
11714 (clobber (reg:SI LR_REGNUM))
11715 (clobber (reg:SI CC_REGNUM))]
11716 "TARGET_GNU2_TLS"
11717 {
11718 targetm.asm_out.internal_label (asm_out_file, "LPIC",
11719 INTVAL (operands[1]));
11720 return "bl\\t%c0(tlscall)";
11721 }
11722 [(set_attr "conds" "clob")
1b7da4ac 11723 (set_attr "length" "4")
11724 (set_attr "type" "branch")]
f41e4452 11725)
11726
1fe0edab 11727;; For thread pointer builtin
11728(define_expand "get_thread_pointersi"
3934ae0e 11729 [(match_operand:SI 0 "s_register_operand")]
1fe0edab 11730 ""
11731 "
11732 {
11733 arm_load_tp (operands[0]);
11734 DONE;
11735 }")
11736
f41e4452 11737;;
11738
aabe09ac 11739;; We only care about the lower 16 bits of the constant
11740;; being inserted into the upper 16 bits of the register.
eca5c984 11741(define_insn "*arm_movtas_ze"
417e5cc5 11742 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r,r")
eca5c984 11743 (const_int 16)
11744 (const_int 16))
11745 (match_operand:SI 1 "const_int_operand" ""))]
60a48e7d 11746 "TARGET_HAVE_MOVT"
417e5cc5 11747 "@
11748 movt%?\t%0, %L1
11749 movt\t%0, %L1"
11750 [(set_attr "arch" "32,v8mb")
11751 (set_attr "predicable" "yes")
1b7da4ac 11752 (set_attr "length" "4")
282b4c75 11753 (set_attr "type" "alu_sreg")]
eca5c984 11754)
11755
c0fc3696 11756(define_insn "*arm_rev"
a486b499 11757 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
11758 (bswap:SI (match_operand:SI 1 "s_register_operand" "l,l,r")))]
11759 "arm_arch6"
11760 "@
11761 rev\t%0, %1
11762 rev%?\t%0, %1
11763 rev%?\t%0, %1"
11764 [(set_attr "arch" "t1,t2,32")
1b7da4ac 11765 (set_attr "length" "2,2,4")
4a510717 11766 (set_attr "predicable" "no,yes,yes")
1b7da4ac 11767 (set_attr "type" "rev")]
ff82f757 11768)
11769
11770(define_expand "arm_legacy_rev"
3934ae0e 11771 [(set (match_operand:SI 2 "s_register_operand")
11772 (xor:SI (rotatert:SI (match_operand:SI 1 "s_register_operand")
ff82f757 11773 (const_int 16))
11774 (match_dup 1)))
11775 (set (match_dup 2)
11776 (lshiftrt:SI (match_dup 2)
11777 (const_int 8)))
3934ae0e 11778 (set (match_operand:SI 3 "s_register_operand")
ff82f757 11779 (rotatert:SI (match_dup 1)
11780 (const_int 8)))
11781 (set (match_dup 2)
11782 (and:SI (match_dup 2)
11783 (const_int -65281)))
3934ae0e 11784 (set (match_operand:SI 0 "s_register_operand")
ff82f757 11785 (xor:SI (match_dup 3)
11786 (match_dup 2)))]
11787 "TARGET_32BIT"
11788 ""
11789)
11790
11791;; Reuse temporaries to keep register pressure down.
11792(define_expand "thumb_legacy_rev"
3934ae0e 11793 [(set (match_operand:SI 2 "s_register_operand")
11794 (ashift:SI (match_operand:SI 1 "s_register_operand")
ff82f757 11795 (const_int 24)))
3934ae0e 11796 (set (match_operand:SI 3 "s_register_operand")
ff82f757 11797 (lshiftrt:SI (match_dup 1)
11798 (const_int 24)))
11799 (set (match_dup 3)
11800 (ior:SI (match_dup 3)
11801 (match_dup 2)))
3934ae0e 11802 (set (match_operand:SI 4 "s_register_operand")
ff82f757 11803 (const_int 16))
3934ae0e 11804 (set (match_operand:SI 5 "s_register_operand")
ff82f757 11805 (rotatert:SI (match_dup 1)
11806 (match_dup 4)))
11807 (set (match_dup 2)
11808 (ashift:SI (match_dup 5)
11809 (const_int 24)))
11810 (set (match_dup 5)
11811 (lshiftrt:SI (match_dup 5)
11812 (const_int 24)))
11813 (set (match_dup 5)
11814 (ior:SI (match_dup 5)
11815 (match_dup 2)))
11816 (set (match_dup 5)
11817 (rotatert:SI (match_dup 5)
11818 (match_dup 4)))
3934ae0e 11819 (set (match_operand:SI 0 "s_register_operand")
ff82f757 11820 (ior:SI (match_dup 5)
11821 (match_dup 3)))]
11822 "TARGET_THUMB"
11823 ""
11824)
11825
62e39b06 11826;; ARM-specific expansion of signed mod by power of 2
11827;; using conditional negate.
11828;; For r0 % n where n is a power of 2 produce:
11829;; rsbs r1, r0, #0
11830;; and r0, r0, #(n - 1)
11831;; and r1, r1, #(n - 1)
11832;; rsbpl r0, r1, #0
11833
11834(define_expand "modsi3"
3934ae0e 11835 [(match_operand:SI 0 "register_operand")
11836 (match_operand:SI 1 "register_operand")
11837 (match_operand:SI 2 "const_int_operand")]
62e39b06 11838 "TARGET_32BIT"
11839 {
11840 HOST_WIDE_INT val = INTVAL (operands[2]);
11841
11842 if (val <= 0
11843 || exact_log2 (val) <= 0)
11844 FAIL;
11845
11846 rtx mask = GEN_INT (val - 1);
11847
11848 /* In the special case of x0 % 2 we can do the even shorter:
11849 cmp r0, #0
11850 and r0, r0, #1
11851 rsblt r0, r0, #0. */
11852
11853 if (val == 2)
11854 {
11855 rtx cc_reg = arm_gen_compare_reg (LT,
11856 operands[1], const0_rtx, NULL_RTX);
11857 rtx cond = gen_rtx_LT (SImode, cc_reg, const0_rtx);
11858 rtx masked = gen_reg_rtx (SImode);
11859
11860 emit_insn (gen_andsi3 (masked, operands[1], mask));
11861 emit_move_insn (operands[0],
11862 gen_rtx_IF_THEN_ELSE (SImode, cond,
11863 gen_rtx_NEG (SImode,
11864 masked),
11865 masked));
11866 DONE;
11867 }
11868
11869 rtx neg_op = gen_reg_rtx (SImode);
11870 rtx_insn *insn = emit_insn (gen_subsi3_compare0 (neg_op, const0_rtx,
11871 operands[1]));
11872
11873 /* Extract the condition register and mode. */
11874 rtx cmp = XVECEXP (PATTERN (insn), 0, 0);
11875 rtx cc_reg = SET_DEST (cmp);
11876 rtx cond = gen_rtx_GE (SImode, cc_reg, const0_rtx);
11877
11878 emit_insn (gen_andsi3 (operands[0], operands[1], mask));
11879
11880 rtx masked_neg = gen_reg_rtx (SImode);
11881 emit_insn (gen_andsi3 (masked_neg, neg_op, mask));
11882
11883 /* We want a conditional negate here, but emitting COND_EXEC rtxes
11884 during expand does not always work. Do an IF_THEN_ELSE instead. */
11885 emit_move_insn (operands[0],
11886 gen_rtx_IF_THEN_ELSE (SImode, cond,
11887 gen_rtx_NEG (SImode, masked_neg),
11888 operands[0]));
11889
11890
11891 DONE;
11892 }
11893)
11894
ff82f757 11895(define_expand "bswapsi2"
3934ae0e 11896 [(set (match_operand:SI 0 "s_register_operand")
11897 (bswap:SI (match_operand:SI 1 "s_register_operand")))]
8d1af482 11898"TARGET_EITHER && (arm_arch6 || !optimize_size)"
ff82f757 11899"
8d1af482 11900 if (!arm_arch6)
11901 {
11902 rtx op2 = gen_reg_rtx (SImode);
11903 rtx op3 = gen_reg_rtx (SImode);
ff82f757 11904
8d1af482 11905 if (TARGET_THUMB)
11906 {
11907 rtx op4 = gen_reg_rtx (SImode);
11908 rtx op5 = gen_reg_rtx (SImode);
ff82f757 11909
8d1af482 11910 emit_insn (gen_thumb_legacy_rev (operands[0], operands[1],
11911 op2, op3, op4, op5));
11912 }
11913 else
11914 {
11915 emit_insn (gen_arm_legacy_rev (operands[0], operands[1],
11916 op2, op3));
11917 }
ff82f757 11918
8d1af482 11919 DONE;
11920 }
ff82f757 11921 "
11922)
11923
a486b499 11924;; bswap16 patterns: use revsh and rev16 instructions for the signed
11925;; and unsigned variants, respectively. For rev16, expose
11926;; byte-swapping in the lower 16 bits only.
11927(define_insn "*arm_revsh"
11928 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
11929 (sign_extend:SI (bswap:HI (match_operand:HI 1 "s_register_operand" "l,l,r"))))]
11930 "arm_arch6"
11931 "@
11932 revsh\t%0, %1
11933 revsh%?\t%0, %1
11934 revsh%?\t%0, %1"
11935 [(set_attr "arch" "t1,t2,32")
1b7da4ac 11936 (set_attr "length" "2,2,4")
11937 (set_attr "type" "rev")]
a486b499 11938)
11939
11940(define_insn "*arm_rev16"
11941 [(set (match_operand:HI 0 "s_register_operand" "=l,l,r")
11942 (bswap:HI (match_operand:HI 1 "s_register_operand" "l,l,r")))]
11943 "arm_arch6"
11944 "@
11945 rev16\t%0, %1
11946 rev16%?\t%0, %1
11947 rev16%?\t%0, %1"
11948 [(set_attr "arch" "t1,t2,32")
1b7da4ac 11949 (set_attr "length" "2,2,4")
11950 (set_attr "type" "rev")]
09f69e55 11951)
11952
11953;; There are no canonicalisation rules for the position of the lshiftrt, ashift
11954;; operations within an IOR/AND RTX, therefore we have two patterns matching
11955;; each valid permutation.
11956
11957(define_insn "arm_rev16si2"
11958 [(set (match_operand:SI 0 "register_operand" "=l,l,r")
11959 (ior:SI (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "l,l,r")
11960 (const_int 8))
11961 (match_operand:SI 3 "const_int_operand" "n,n,n"))
11962 (and:SI (lshiftrt:SI (match_dup 1)
11963 (const_int 8))
11964 (match_operand:SI 2 "const_int_operand" "n,n,n"))))]
11965 "arm_arch6
11966 && aarch_rev16_shleft_mask_imm_p (operands[3], SImode)
11967 && aarch_rev16_shright_mask_imm_p (operands[2], SImode)"
11968 "rev16\\t%0, %1"
11969 [(set_attr "arch" "t1,t2,32")
11970 (set_attr "length" "2,2,4")
11971 (set_attr "type" "rev")]
11972)
11973
11974(define_insn "arm_rev16si2_alt"
11975 [(set (match_operand:SI 0 "register_operand" "=l,l,r")
11976 (ior:SI (and:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,l,r")
11977 (const_int 8))
11978 (match_operand:SI 2 "const_int_operand" "n,n,n"))
11979 (and:SI (ashift:SI (match_dup 1)
11980 (const_int 8))
11981 (match_operand:SI 3 "const_int_operand" "n,n,n"))))]
11982 "arm_arch6
11983 && aarch_rev16_shleft_mask_imm_p (operands[3], SImode)
11984 && aarch_rev16_shright_mask_imm_p (operands[2], SImode)"
11985 "rev16\\t%0, %1"
11986 [(set_attr "arch" "t1,t2,32")
11987 (set_attr "length" "2,2,4")
11988 (set_attr "type" "rev")]
a486b499 11989)
11990
11991(define_expand "bswaphi2"
3934ae0e 11992 [(set (match_operand:HI 0 "s_register_operand")
11993 (bswap:HI (match_operand:HI 1 "s_register_operand")))]
a486b499 11994"arm_arch6"
11995""
11996)
11997
1653cf17 11998;; Patterns for LDRD/STRD in Thumb2 mode
11999
12000(define_insn "*thumb2_ldrd"
12001 [(set (match_operand:SI 0 "s_register_operand" "=r")
12002 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
12003 (match_operand:SI 2 "ldrd_strd_offset_operand" "Do"))))
12004 (set (match_operand:SI 3 "s_register_operand" "=r")
12005 (mem:SI (plus:SI (match_dup 1)
12006 (match_operand:SI 4 "const_int_operand" ""))))]
12007 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
1653cf17 12008 && ((INTVAL (operands[2]) + 4) == INTVAL (operands[4]))
12009 && (operands_ok_ldrd_strd (operands[0], operands[3],
12010 operands[1], INTVAL (operands[2]),
12011 false, true))"
12012 "ldrd%?\t%0, %3, [%1, %2]"
9f2c2a36 12013 [(set_attr "type" "load_8")
8bdfd6ed 12014 (set_attr "predicable" "yes")])
1653cf17 12015
12016(define_insn "*thumb2_ldrd_base"
12017 [(set (match_operand:SI 0 "s_register_operand" "=r")
12018 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
12019 (set (match_operand:SI 2 "s_register_operand" "=r")
12020 (mem:SI (plus:SI (match_dup 1)
12021 (const_int 4))))]
12022 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
1653cf17 12023 && (operands_ok_ldrd_strd (operands[0], operands[2],
12024 operands[1], 0, false, true))"
12025 "ldrd%?\t%0, %2, [%1]"
9f2c2a36 12026 [(set_attr "type" "load_8")
8bdfd6ed 12027 (set_attr "predicable" "yes")])
1653cf17 12028
12029(define_insn "*thumb2_ldrd_base_neg"
12030 [(set (match_operand:SI 0 "s_register_operand" "=r")
12031 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
12032 (const_int -4))))
12033 (set (match_operand:SI 2 "s_register_operand" "=r")
12034 (mem:SI (match_dup 1)))]
12035 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
1653cf17 12036 && (operands_ok_ldrd_strd (operands[0], operands[2],
12037 operands[1], -4, false, true))"
12038 "ldrd%?\t%0, %2, [%1, #-4]"
9f2c2a36 12039 [(set_attr "type" "load_8")
8bdfd6ed 12040 (set_attr "predicable" "yes")])
1653cf17 12041
12042(define_insn "*thumb2_strd"
12043 [(set (mem:SI (plus:SI (match_operand:SI 0 "s_register_operand" "rk")
12044 (match_operand:SI 1 "ldrd_strd_offset_operand" "Do")))
12045 (match_operand:SI 2 "s_register_operand" "r"))
12046 (set (mem:SI (plus:SI (match_dup 0)
12047 (match_operand:SI 3 "const_int_operand" "")))
12048 (match_operand:SI 4 "s_register_operand" "r"))]
12049 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
1653cf17 12050 && ((INTVAL (operands[1]) + 4) == INTVAL (operands[3]))
12051 && (operands_ok_ldrd_strd (operands[2], operands[4],
12052 operands[0], INTVAL (operands[1]),
12053 false, false))"
12054 "strd%?\t%2, %4, [%0, %1]"
9f2c2a36 12055 [(set_attr "type" "store_8")
8bdfd6ed 12056 (set_attr "predicable" "yes")])
1653cf17 12057
12058(define_insn "*thumb2_strd_base"
12059 [(set (mem:SI (match_operand:SI 0 "s_register_operand" "rk"))
12060 (match_operand:SI 1 "s_register_operand" "r"))
12061 (set (mem:SI (plus:SI (match_dup 0)
12062 (const_int 4)))
12063 (match_operand:SI 2 "s_register_operand" "r"))]
12064 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
1653cf17 12065 && (operands_ok_ldrd_strd (operands[1], operands[2],
12066 operands[0], 0, false, false))"
12067 "strd%?\t%1, %2, [%0]"
9f2c2a36 12068 [(set_attr "type" "store_8")
8bdfd6ed 12069 (set_attr "predicable" "yes")])
1653cf17 12070
12071(define_insn "*thumb2_strd_base_neg"
12072 [(set (mem:SI (plus:SI (match_operand:SI 0 "s_register_operand" "rk")
12073 (const_int -4)))
12074 (match_operand:SI 1 "s_register_operand" "r"))
12075 (set (mem:SI (match_dup 0))
12076 (match_operand:SI 2 "s_register_operand" "r"))]
12077 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
1653cf17 12078 && (operands_ok_ldrd_strd (operands[1], operands[2],
12079 operands[0], -4, false, false))"
12080 "strd%?\t%1, %2, [%0, #-4]"
9f2c2a36 12081 [(set_attr "type" "store_8")
8bdfd6ed 12082 (set_attr "predicable" "yes")])
1653cf17 12083
2a0c73f2 12084;; ARMv8 CRC32 instructions.
8656245d 12085(define_insn "arm_<crc_variant>"
2a0c73f2 12086 [(set (match_operand:SI 0 "s_register_operand" "=r")
12087 (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")
12088 (match_operand:<crc_mode> 2 "s_register_operand" "r")]
12089 CRC))]
12090 "TARGET_CRC32"
12091 "<crc_variant>\\t%0, %1, %2"
12092 [(set_attr "type" "crc")
12093 (set_attr "conds" "unconditional")]
12094)
1653cf17 12095
353cf59a 12096;; Load the load/store double peephole optimizations.
12097(include "ldrdstrd.md")
12098
320ea44d 12099;; Load the load/store multiple patterns
12100(include "ldmstm.md")
426be8c5 12101
12102;; Patterns in ldmstm.md don't cover more than 4 registers. This pattern covers
12103;; large lists without explicit writeback generated for APCS_FRAME epilogue.
3873efff 12104;; The operands are validated through the load_multiple_operation
12105;; match_parallel predicate rather than through constraints so enable it only
12106;; after reload.
426be8c5 12107(define_insn "*load_multiple"
12108 [(match_parallel 0 "load_multiple_operation"
12109 [(set (match_operand:SI 2 "s_register_operand" "=rk")
12110 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
12111 ])]
3873efff 12112 "TARGET_32BIT && reload_completed"
426be8c5 12113 "*
12114 {
12115 arm_output_multireg_pop (operands, /*return_pc=*/false,
12116 /*cond=*/const_true_rtx,
12117 /*reverse=*/false,
12118 /*update=*/false);
12119 return \"\";
12120 }
12121 "
12122 [(set_attr "predicable" "yes")]
12123)
12124
84450ddc 12125(define_expand "copysignsf3"
12126 [(match_operand:SF 0 "register_operand")
12127 (match_operand:SF 1 "register_operand")
12128 (match_operand:SF 2 "register_operand")]
12129 "TARGET_SOFT_FLOAT && arm_arch_thumb2"
12130 "{
12131 emit_move_insn (operands[0], operands[2]);
12132 emit_insn (gen_insv_t2 (simplify_gen_subreg (SImode, operands[0], SFmode, 0),
12133 GEN_INT (31), GEN_INT (0),
12134 simplify_gen_subreg (SImode, operands[1], SFmode, 0)));
12135 DONE;
12136 }"
12137)
12138
12139(define_expand "copysigndf3"
12140 [(match_operand:DF 0 "register_operand")
12141 (match_operand:DF 1 "register_operand")
12142 (match_operand:DF 2 "register_operand")]
12143 "TARGET_SOFT_FLOAT && arm_arch_thumb2"
12144 "{
12145 rtx op0_low = gen_lowpart (SImode, operands[0]);
12146 rtx op0_high = gen_highpart (SImode, operands[0]);
12147 rtx op1_low = gen_lowpart (SImode, operands[1]);
12148 rtx op1_high = gen_highpart (SImode, operands[1]);
12149 rtx op2_high = gen_highpart (SImode, operands[2]);
12150
12151 rtx scratch1 = gen_reg_rtx (SImode);
12152 rtx scratch2 = gen_reg_rtx (SImode);
12153 emit_move_insn (scratch1, op2_high);
12154 emit_move_insn (scratch2, op1_high);
12155
d1f9b275 12156 emit_insn(gen_rtx_SET(scratch1,
84450ddc 12157 gen_rtx_LSHIFTRT (SImode, op2_high, GEN_INT(31))));
12158 emit_insn(gen_insv_t2(scratch2, GEN_INT(1), GEN_INT(31), scratch1));
12159 emit_move_insn (op0_low, op1_low);
12160 emit_move_insn (op0_high, scratch2);
12161
12162 DONE;
12163 }"
12164)
12165
115857ef 12166;; movmisalign patterns for HImode and SImode.
12167(define_expand "movmisalign<mode>"
12168 [(match_operand:HSI 0 "general_operand")
12169 (match_operand:HSI 1 "general_operand")]
12170 "unaligned_access"
12171{
12172 /* This pattern is not permitted to fail during expansion: if both arguments
12173 are non-registers (e.g. memory := constant), force operand 1 into a
12174 register. */
12175 rtx (* gen_unaligned_load)(rtx, rtx);
12176 rtx tmp_dest = operands[0];
12177 if (!s_register_operand (operands[0], <MODE>mode)
12178 && !s_register_operand (operands[1], <MODE>mode))
12179 operands[1] = force_reg (<MODE>mode, operands[1]);
12180
12181 if (<MODE>mode == HImode)
12182 {
12183 gen_unaligned_load = gen_unaligned_loadhiu;
12184 tmp_dest = gen_reg_rtx (SImode);
12185 }
12186 else
12187 gen_unaligned_load = gen_unaligned_loadsi;
12188
12189 if (MEM_P (operands[1]))
12190 {
12191 emit_insn (gen_unaligned_load (tmp_dest, operands[1]));
12192 if (<MODE>mode == HImode)
12193 emit_move_insn (operands[0], gen_lowpart (HImode, tmp_dest));
12194 }
12195 else
12196 emit_insn (gen_unaligned_store<mode> (operands[0], operands[1]));
12197
12198 DONE;
12199})
12200
8656245d 12201(define_insn "arm_<cdp>"
1be6395a 12202 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "n")
12203 (match_operand:SI 1 "immediate_operand" "n")
12204 (match_operand:SI 2 "immediate_operand" "n")
12205 (match_operand:SI 3 "immediate_operand" "n")
12206 (match_operand:SI 4 "immediate_operand" "n")
12207 (match_operand:SI 5 "immediate_operand" "n")] CDPI)]
12208 "arm_coproc_builtin_available (VUNSPEC_<CDP>)"
12209{
12210 arm_const_bounds (operands[0], 0, 16);
12211 arm_const_bounds (operands[1], 0, 16);
12212 arm_const_bounds (operands[2], 0, (1 << 5));
12213 arm_const_bounds (operands[3], 0, (1 << 5));
12214 arm_const_bounds (operands[4], 0, (1 << 5));
12215 arm_const_bounds (operands[5], 0, 8);
12216 return "<cdp>\\tp%c0, %1, CR%c2, CR%c3, CR%c4, %5";
12217}
12218 [(set_attr "length" "4")
12219 (set_attr "type" "coproc")])
12220
638b44bd 12221(define_insn "*ldc"
12222 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "n")
12223 (match_operand:SI 1 "immediate_operand" "n")
12224 (match_operand:SI 2 "memory_operand" "Uz")] LDCI)]
12225 "arm_coproc_builtin_available (VUNSPEC_<LDC>)"
12226{
12227 arm_const_bounds (operands[0], 0, 16);
12228 arm_const_bounds (operands[1], 0, (1 << 5));
12229 return "<ldc>\\tp%c0, CR%c1, %2";
12230}
12231 [(set_attr "length" "4")
12232 (set_attr "type" "coproc")])
12233
12234(define_insn "*stc"
12235 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "n")
12236 (match_operand:SI 1 "immediate_operand" "n")
12237 (match_operand:SI 2 "memory_operand" "=Uz")] STCI)]
12238 "arm_coproc_builtin_available (VUNSPEC_<STC>)"
12239{
12240 arm_const_bounds (operands[0], 0, 16);
12241 arm_const_bounds (operands[1], 0, (1 << 5));
12242 return "<stc>\\tp%c0, CR%c1, %2";
12243}
12244 [(set_attr "length" "4")
12245 (set_attr "type" "coproc")])
12246
8656245d 12247(define_expand "arm_<ldc>"
638b44bd 12248 [(unspec_volatile [(match_operand:SI 0 "immediate_operand")
12249 (match_operand:SI 1 "immediate_operand")
12250 (mem:SI (match_operand:SI 2 "s_register_operand"))] LDCI)]
12251 "arm_coproc_builtin_available (VUNSPEC_<LDC>)")
12252
8656245d 12253(define_expand "arm_<stc>"
638b44bd 12254 [(unspec_volatile [(match_operand:SI 0 "immediate_operand")
12255 (match_operand:SI 1 "immediate_operand")
12256 (mem:SI (match_operand:SI 2 "s_register_operand"))] STCI)]
12257 "arm_coproc_builtin_available (VUNSPEC_<STC>)")
12258
8656245d 12259(define_insn "arm_<mcr>"
415e9b1f 12260 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "n")
12261 (match_operand:SI 1 "immediate_operand" "n")
12262 (match_operand:SI 2 "s_register_operand" "r")
12263 (match_operand:SI 3 "immediate_operand" "n")
12264 (match_operand:SI 4 "immediate_operand" "n")
12265 (match_operand:SI 5 "immediate_operand" "n")] MCRI)
12266 (use (match_dup 2))]
12267 "arm_coproc_builtin_available (VUNSPEC_<MCR>)"
12268{
12269 arm_const_bounds (operands[0], 0, 16);
12270 arm_const_bounds (operands[1], 0, 8);
12271 arm_const_bounds (operands[3], 0, (1 << 5));
12272 arm_const_bounds (operands[4], 0, (1 << 5));
12273 arm_const_bounds (operands[5], 0, 8);
12274 return "<mcr>\\tp%c0, %1, %2, CR%c3, CR%c4, %5";
12275}
12276 [(set_attr "length" "4")
12277 (set_attr "type" "coproc")])
12278
8656245d 12279(define_insn "arm_<mrc>"
415e9b1f 12280 [(set (match_operand:SI 0 "s_register_operand" "=r")
6f8d7784 12281 (unspec_volatile:SI [(match_operand:SI 1 "immediate_operand" "n")
415e9b1f 12282 (match_operand:SI 2 "immediate_operand" "n")
12283 (match_operand:SI 3 "immediate_operand" "n")
12284 (match_operand:SI 4 "immediate_operand" "n")
12285 (match_operand:SI 5 "immediate_operand" "n")] MRCI))]
12286 "arm_coproc_builtin_available (VUNSPEC_<MRC>)"
12287{
12288 arm_const_bounds (operands[1], 0, 16);
12289 arm_const_bounds (operands[2], 0, 8);
12290 arm_const_bounds (operands[3], 0, (1 << 5));
12291 arm_const_bounds (operands[4], 0, (1 << 5));
12292 arm_const_bounds (operands[5], 0, 8);
12293 return "<mrc>\\tp%c1, %2, %0, CR%c3, CR%c4, %5";
12294}
12295 [(set_attr "length" "4")
12296 (set_attr "type" "coproc")])
12297
8656245d 12298(define_insn "arm_<mcrr>"
cabfd710 12299 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "n")
12300 (match_operand:SI 1 "immediate_operand" "n")
12301 (match_operand:DI 2 "s_register_operand" "r")
12302 (match_operand:SI 3 "immediate_operand" "n")] MCRRI)
12303 (use (match_dup 2))]
12304 "arm_coproc_builtin_available (VUNSPEC_<MCRR>)"
12305{
12306 arm_const_bounds (operands[0], 0, 16);
12307 arm_const_bounds (operands[1], 0, 8);
12308 arm_const_bounds (operands[3], 0, (1 << 5));
12309 return "<mcrr>\\tp%c0, %1, %Q2, %R2, CR%c3";
12310}
12311 [(set_attr "length" "4")
12312 (set_attr "type" "coproc")])
12313
8656245d 12314(define_insn "arm_<mrrc>"
cabfd710 12315 [(set (match_operand:DI 0 "s_register_operand" "=r")
6f8d7784 12316 (unspec_volatile:DI [(match_operand:SI 1 "immediate_operand" "n")
cabfd710 12317 (match_operand:SI 2 "immediate_operand" "n")
12318 (match_operand:SI 3 "immediate_operand" "n")] MRRCI))]
12319 "arm_coproc_builtin_available (VUNSPEC_<MRRC>)"
12320{
12321 arm_const_bounds (operands[1], 0, 16);
12322 arm_const_bounds (operands[2], 0, 8);
12323 arm_const_bounds (operands[3], 0, (1 << 5));
12324 return "<mrrc>\\tp%c1, %2, %Q0, %R0, CR%c3";
12325}
12326 [(set_attr "length" "4")
12327 (set_attr "type" "coproc")])
12328
be626997 12329(define_expand "speculation_barrier"
12330 [(unspec_volatile [(const_int 0)] VUNSPEC_SPECULATION_BARRIER)]
12331 "TARGET_EITHER"
12332 "
a7852b35 12333 /* For thumb1 (except Armv8 derivatives), and for pre-Armv7 we don't
12334 have a usable barrier (and probably don't need one in practice).
12335 But to be safe if such code is run on later architectures, call a
12336 helper function in libgcc that will do the thing for the active
12337 system. */
12338 if (!(arm_arch7 || arm_arch8))
12339 {
12340 arm_emit_speculation_barrier_function ();
12341 DONE;
12342 }
be626997 12343 "
12344)
12345
12346;; Generate a hard speculation barrier when we have not enabled speculation
12347;; tracking.
12348(define_insn "*speculation_barrier_insn"
12349 [(unspec_volatile [(const_int 0)] VUNSPEC_SPECULATION_BARRIER)]
a7852b35 12350 "arm_arch7 || arm_arch8"
be626997 12351 "isb\;dsb\\tsy"
12352 [(set_attr "type" "block")
12353 (set_attr "length" "8")]
12354)
12355
d98a3884 12356;; Vector bits common to IWMMXT and Neon
12357(include "vec-common.md")
755eb2b4 12358;; Load the Intel Wireless Multimedia Extension patterns
12359(include "iwmmxt.md")
a2cd141b 12360;; Load the VFP co-processor patterns
12361(include "vfp.md")
bc360af8 12362;; Thumb-1 patterns
12363(include "thumb1.md")
25f905c2 12364;; Thumb-2 patterns
12365(include "thumb2.md")
d98a3884 12366;; Neon patterns
12367(include "neon.md")
e84fdf6e 12368;; Crypto patterns
12369(include "crypto.md")
06df6b17 12370;; Synchronization Primitives
12371(include "sync.md")
bbbe4599 12372;; Fixed-point patterns
12373(include "arm-fixed.md")