]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/arm/arm.md
[ARM] Implement support for ACLE Coprocessor MCR and MRC intrinsics
[thirdparty/gcc.git] / gcc / config / arm / arm.md
CommitLineData
129a2fe4 1;;- Machine description for ARM for GNU compiler
aad93da1 2;; Copyright (C) 1991-2017 Free Software Foundation, Inc.
b11cae9e 3;; Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
f082f1c4 4;; and Martin Simmons (@harleqn.co.uk).
129a2fe4 5;; More major hacks by Richard Earnshaw (rearnsha@arm.com).
b11cae9e 6
acf6ed70 7;; This file is part of GCC.
b11cae9e 8
acf6ed70 9;; GCC is free software; you can redistribute it and/or modify it
10;; under the terms of the GNU General Public License as published
038d1e19 11;; by the Free Software Foundation; either version 3, or (at your
acf6ed70 12;; option) any later version.
b11cae9e 13
acf6ed70 14;; GCC is distributed in the hope that it will be useful, but WITHOUT
15;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
17;; License for more details.
b11cae9e 18
19;; You should have received a copy of the GNU General Public License
038d1e19 20;; along with GCC; see the file COPYING3. If not see
21;; <http://www.gnu.org/licenses/>.
b11cae9e 22
23;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
24
9c08d1fa 25\f
e1159bbe 26;;---------------------------------------------------------------------------
27;; Constants
28
bffbb863 29;; Register numbers -- All machine registers should be defined here
e1159bbe 30(define_constants
bffbb863 31 [(R0_REGNUM 0) ; First CORE register
32 (R1_REGNUM 1) ; Second CORE register
33 (IP_REGNUM 12) ; Scratch register
34 (SP_REGNUM 13) ; Stack pointer
35 (LR_REGNUM 14) ; Return address register
36 (PC_REGNUM 15) ; Program counter
37 (LAST_ARM_REGNUM 15) ;
38 (CC_REGNUM 100) ; Condition code pseudo register
39 (VFPCC_REGNUM 101) ; VFP Condition code pseudo register
e1159bbe 40 ]
41)
3c5afce6 42;; 3rd operand to select_dominance_cc_mode
43(define_constants
44 [(DOM_CC_X_AND_Y 0)
45 (DOM_CC_NX_OR_Y 1)
46 (DOM_CC_X_OR_Y 2)
47 ]
48)
2ff91fec 49;; conditional compare combination
50(define_constants
51 [(CMP_CMP 0)
52 (CMN_CMP 1)
53 (CMP_CMN 2)
54 (CMN_CMN 3)
55 (NUM_OF_COND_CMP 4)
56 ]
57)
e1159bbe 58
b11cae9e 59\f
e1159bbe 60;;---------------------------------------------------------------------------
9c08d1fa 61;; Attributes
62
a651f34d 63;; Processor type. This is created automatically from arm-cores.def.
64(include "arm-tune.md")
65
861033d5 66;; Instruction classification types
67(include "types.md")
68
215b30b3 69; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
70; generating ARM code. This is used to control the length of some insn
71; patterns that share the same RTL in both ARM and Thumb code.
8724f216 72(define_attr "is_thumb" "yes,no"
73 (const (if_then_else (symbol_ref "TARGET_THUMB")
74 (const_string "yes") (const_string "no"))))
cffb2a26 75
ef51b8e1 76; IS_ARCH6 is set to 'yes' when we are generating code form ARMv6.
77(define_attr "is_arch6" "no,yes" (const (symbol_ref "arm_arch6")))
78
747b7458 79; IS_THUMB1 is set to 'yes' iff we are generating Thumb-1 code.
8724f216 80(define_attr "is_thumb1" "yes,no"
81 (const (if_then_else (symbol_ref "TARGET_THUMB1")
82 (const_string "yes") (const_string "no"))))
747b7458 83
c7a58118 84; We use this attribute to disable alternatives that can produce 32-bit
85; instructions inside an IT-block in Thumb2 state. ARMv8 deprecates IT blocks
86; that contain 32-bit instructions.
87(define_attr "enabled_for_depr_it" "no,yes" (const_string "yes"))
88
89; This attribute is used to disable a predicated alternative when we have
90; arm_restrict_it.
91(define_attr "predicable_short_it" "no,yes" (const_string "yes"))
92
331beb1a 93;; Operand number of an input operand that is shifted. Zero if the
94;; given instruction does not shift one of its input operands.
331beb1a 95(define_attr "shift" "" (const_int 0))
96
55a94dda 97;; [For compatibility with AArch64 in pipeline models]
98;; Attribute that specifies whether or not the instruction touches fp
99;; registers.
100(define_attr "fp" "no,yes" (const_string "no"))
101
3d91c5d6 102; Floating Point Unit. If we only have floating point emulation, then there
103; is no point in scheduling the floating point insns. (Well, for best
104; performance we should try and group them together).
bffbb863 105(define_attr "fpu" "none,vfp"
c7f506fd 106 (const (symbol_ref "arm_fpu_attr")))
3d91c5d6 107
b2bcff19 108; Predicated means that the insn form is conditionally executed based on a
109; predicate. We default to 'no' because no Thumb patterns match this rule
110; and not all ARM insns do.
c7a58118 111(define_attr "predicated" "yes,no" (const_string "no"))
112
094e994f 113; LENGTH of an instruction (in bytes)
06df6b17 114(define_attr "length" ""
e1b93706 115 (const_int 4))
9c08d1fa 116
d5d4dc8d 117; The architecture which supports the instruction (or alternative).
118; This can be "a" for ARM, "t" for either of the Thumbs, "32" for
119; TARGET_32BIT, "t1" or "t2" to specify a specific Thumb mode. "v6"
120; for ARM or Thumb-2 with arm_arch6, and nov6 for ARM without
417e5cc5 121; arm_arch6. "v6t2" for Thumb-2 with arm_arch6 and "v8mb" for ARMv8-M
122; Baseline. This attribute is used to compute attribute "enabled",
123; use type "any" to enable an alternative in all cases.
124(define_attr "arch" "any,a,t,32,t1,t2,v6,nov6,v6t2,v8mb,neon_for_64bits,avoid_neon_for_64bits,iwmmxt,iwmmxt2,armv6_or_vfpv3,neon"
d5d4dc8d 125 (const_string "any"))
126
127(define_attr "arch_enabled" "no,yes"
128 (cond [(eq_attr "arch" "any")
129 (const_string "yes")
130
131 (and (eq_attr "arch" "a")
0bf497f5 132 (match_test "TARGET_ARM"))
d5d4dc8d 133 (const_string "yes")
134
135 (and (eq_attr "arch" "t")
0bf497f5 136 (match_test "TARGET_THUMB"))
d5d4dc8d 137 (const_string "yes")
138
139 (and (eq_attr "arch" "t1")
0bf497f5 140 (match_test "TARGET_THUMB1"))
d5d4dc8d 141 (const_string "yes")
142
143 (and (eq_attr "arch" "t2")
0bf497f5 144 (match_test "TARGET_THUMB2"))
d5d4dc8d 145 (const_string "yes")
146
147 (and (eq_attr "arch" "32")
0bf497f5 148 (match_test "TARGET_32BIT"))
d5d4dc8d 149 (const_string "yes")
150
151 (and (eq_attr "arch" "v6")
0bf497f5 152 (match_test "TARGET_32BIT && arm_arch6"))
d5d4dc8d 153 (const_string "yes")
154
155 (and (eq_attr "arch" "nov6")
0bf497f5 156 (match_test "TARGET_32BIT && !arm_arch6"))
a651f34d 157 (const_string "yes")
158
e4585731 159 (and (eq_attr "arch" "v6t2")
160 (match_test "TARGET_32BIT && arm_arch6 && arm_arch_thumb2"))
161 (const_string "yes")
162
417e5cc5 163 (and (eq_attr "arch" "v8mb")
164 (match_test "TARGET_THUMB1 && arm_arch8"))
165 (const_string "yes")
166
b6779ddc 167 (and (eq_attr "arch" "avoid_neon_for_64bits")
168 (match_test "TARGET_NEON")
169 (not (match_test "TARGET_PREFER_NEON_64BITS")))
a651f34d 170 (const_string "yes")
171
b6779ddc 172 (and (eq_attr "arch" "neon_for_64bits")
173 (match_test "TARGET_NEON")
174 (match_test "TARGET_PREFER_NEON_64BITS"))
6b8f7c28 175 (const_string "yes")
176
177 (and (eq_attr "arch" "iwmmxt2")
178 (match_test "TARGET_REALLY_IWMMXT2"))
21cc9773 179 (const_string "yes")
180
181 (and (eq_attr "arch" "armv6_or_vfpv3")
182 (match_test "arm_arch6 || TARGET_VFP3"))
183 (const_string "yes")
ac876af5 184
185 (and (eq_attr "arch" "neon")
186 (match_test "TARGET_NEON"))
187 (const_string "yes")
21cc9773 188 ]
6b8f7c28 189
d5d4dc8d 190 (const_string "no")))
191
aa06c51c 192(define_attr "opt" "any,speed,size"
193 (const_string "any"))
194
195(define_attr "opt_enabled" "no,yes"
196 (cond [(eq_attr "opt" "any")
197 (const_string "yes")
198
199 (and (eq_attr "opt" "speed")
200 (match_test "optimize_function_for_speed_p (cfun)"))
201 (const_string "yes")
202
203 (and (eq_attr "opt" "size")
204 (match_test "optimize_function_for_size_p (cfun)"))
205 (const_string "yes")]
206 (const_string "no")))
207
861033d5 208(define_attr "use_literal_pool" "no,yes"
209 (cond [(and (eq_attr "type" "f_loads,f_loadd")
210 (match_test "CONSTANT_P (operands[1])"))
211 (const_string "yes")]
212 (const_string "no")))
213
d5d4dc8d 214; Enable all alternatives that are both arch_enabled and insn_enabled.
951a3f72 215; FIXME:: opt_enabled has been temporarily removed till the time we have
216; an attribute that allows the use of such alternatives.
217; This depends on caching of speed_p, size_p on a per
218; alternative basis. The problem is that the enabled attribute
219; cannot depend on any state that is not cached or is not constant
220; for a compilation unit. We probably need a generic "hot/cold"
221; alternative which if implemented can help with this. We disable this
222; until such a time as this is implemented and / or the improvements or
223; regressions with removing this attribute are double checked.
224; See ashldi3_neon and <shift>di3_neon in neon.md.
225
93b431d9 226 (define_attr "enabled" "no,yes"
0abea32c 227 (cond [(and (eq_attr "predicable_short_it" "no")
c7a58118 228 (and (eq_attr "predicated" "yes")
229 (match_test "arm_restrict_it")))
230 (const_string "no")
231
232 (and (eq_attr "enabled_for_depr_it" "no")
233 (match_test "arm_restrict_it"))
234 (const_string "no")
235
861033d5 236 (and (eq_attr "use_literal_pool" "yes")
237 (match_test "arm_disable_literal_pool"))
238 (const_string "no")
239
aa06c51c 240 (eq_attr "arch_enabled" "no")
aa06c51c 241 (const_string "no")]
242 (const_string "yes")))
d5d4dc8d 243
56d27660 244; POOL_RANGE is how far away from a constant pool entry that this insn
245; can be placed. If the distance is zero, then this insn will never
246; reference the pool.
42e1de19 247; Note that for Thumb constant pools the PC value is rounded down to the
248; nearest multiple of four. Therefore, THUMB2_POOL_RANGE (and POOL_RANGE for
249; Thumb insns) should be set to <max_range> - 2.
cffb2a26 250; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
8848d797 251; before its address. It is set to <max_range> - (8 + <data_size>).
cde1623a 252(define_attr "arm_pool_range" "" (const_int 0))
253(define_attr "thumb2_pool_range" "" (const_int 0))
254(define_attr "arm_neg_pool_range" "" (const_int 0))
255(define_attr "thumb2_neg_pool_range" "" (const_int 0))
256
257(define_attr "pool_range" ""
258 (cond [(eq_attr "is_thumb" "yes") (attr "thumb2_pool_range")]
259 (attr "arm_pool_range")))
260(define_attr "neg_pool_range" ""
261 (cond [(eq_attr "is_thumb" "yes") (attr "thumb2_neg_pool_range")]
262 (attr "arm_neg_pool_range")))
56d27660 263
215b30b3 264; An assembler sequence may clobber the condition codes without us knowing.
4d7a8451 265; If such an insn references the pool, then we have no way of knowing how,
266; so use the most conservative value for pool_range.
9c08d1fa 267(define_asm_attributes
4d7a8451 268 [(set_attr "conds" "clob")
269 (set_attr "length" "4")
270 (set_attr "pool_range" "250")])
9c08d1fa 271
9888ad6d 272; Load scheduling, set from the arm_ld_sched variable
4c834714 273; initialized by arm_option_override()
9888ad6d 274(define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
849170fd 275
f7fbdd4a 276; condition codes: this one is used by final_prescan_insn to speed up
277; conditionalizing instructions. It saves having to scan the rtl to see if
278; it uses or alters the condition codes.
215b30b3 279;
f7fbdd4a 280; USE means that the condition codes are used by the insn in the process of
215b30b3 281; outputting code, this means (at present) that we can't use the insn in
282; inlined branches
283;
f7fbdd4a 284; SET means that the purpose of the insn is to set the condition codes in a
215b30b3 285; well defined manner.
286;
f7fbdd4a 287; CLOB means that the condition codes are altered in an undefined manner, if
215b30b3 288; they are altered at all
289;
ad6d3e2a 290; UNCONDITIONAL means the instruction can not be conditionally executed and
291; that the instruction does not use or alter the condition codes.
c52acdd2 292;
ad6d3e2a 293; NOCOND means that the instruction does not use or alter the condition
294; codes but can be converted into a conditionally exectuted instruction.
f7fbdd4a 295
b0694be0 296(define_attr "conds" "use,set,clob,unconditional,nocond"
747b7458 297 (if_then_else
298 (ior (eq_attr "is_thumb1" "yes")
299 (eq_attr "type" "call"))
c1a66faf 300 (const_string "clob")
32093010 301 (if_then_else (eq_attr "is_neon_type" "no")
52432540 302 (const_string "nocond")
303 (const_string "unconditional"))))
f7fbdd4a 304
215b30b3 305; Predicable means that the insn can be conditionally executed based on
306; an automatically added predicate (additional patterns are generated by
307; gen...). We default to 'no' because no Thumb patterns match this rule
308; and not all ARM patterns do.
0d66636f 309(define_attr "predicable" "no,yes" (const_string "no"))
310
129a2fe4 311; Only model the write buffer for ARM6 and ARM7. Earlier processors don't
312; have one. Later ones, such as StrongARM, have write-back caches, so don't
8d232dc7 313; suffer blockages enough to warrant modelling this (and it can adversely
129a2fe4 314; affect the schedule).
74a71f7d 315(define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_tune_wbuf")))
129a2fe4 316
215b30b3 317; WRITE_CONFLICT implies that a read following an unrelated write is likely
318; to stall the processor. Used with model_wbuf above.
9c08d1fa 319(define_attr "write_conflict" "no,yes"
320 (if_then_else (eq_attr "type"
96854199 321 "block,call,load1")
9c08d1fa 322 (const_string "yes")
323 (const_string "no")))
324
215b30b3 325; Classify the insns into those that take one cycle and those that take more
326; than one on the main cpu execution unit.
f7fbdd4a 327(define_attr "core_cycles" "single,multi"
328 (if_then_else (eq_attr "type"
112eda6f 329 "adc_imm, adc_reg, adcs_imm, adcs_reg, adr, alu_ext, alu_imm, alu_sreg,\
330 alu_shift_imm, alu_shift_reg, alu_dsp_reg, alus_ext, alus_imm, alus_sreg,\
d82e788e 331 alus_shift_imm, alus_shift_reg, bfm, csel, rev, logic_imm, logic_reg,\
332 logic_shift_imm, logic_shift_reg, logics_imm, logics_reg,\
333 logics_shift_imm, logics_shift_reg, extend, shift_imm, float, fcsel,\
7cb6c048 334 wmmx_wor, wmmx_wxor, wmmx_wand, wmmx_wandn, wmmx_wmov, wmmx_tmcrr,\
335 wmmx_tmrrc, wmmx_wldr, wmmx_wstr, wmmx_tmcr, wmmx_tmrc, wmmx_wadd,\
336 wmmx_wsub, wmmx_wmul, wmmx_wmac, wmmx_wavg2, wmmx_tinsr, wmmx_textrm,\
337 wmmx_wshufh, wmmx_wcmpeq, wmmx_wcmpgt, wmmx_wmax, wmmx_wmin, wmmx_wpack,\
338 wmmx_wunpckih, wmmx_wunpckil, wmmx_wunpckeh, wmmx_wunpckel, wmmx_wror,\
339 wmmx_wsra, wmmx_wsrl, wmmx_wsll, wmmx_wmadd, wmmx_tmia, wmmx_tmiaph,\
340 wmmx_tmiaxy, wmmx_tbcst, wmmx_tmovmsk, wmmx_wacc, wmmx_waligni,\
341 wmmx_walignr, wmmx_tandc, wmmx_textrc, wmmx_torc, wmmx_torvsc, wmmx_wsad,\
342 wmmx_wabs, wmmx_wabsdiff, wmmx_waddsubhx, wmmx_wsubaddhx, wmmx_wavg4,\
343 wmmx_wmulw, wmmx_wqmulm, wmmx_wqmulwm, wmmx_waddbhus, wmmx_wqmiaxy,\
344 wmmx_wmiaxy, wmmx_wmiawxy, wmmx_wmerge")
f7fbdd4a 345 (const_string "single")
346 (const_string "multi")))
347
cffb2a26 348;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
215b30b3 349;; distant label. Only applicable to Thumb code.
cffb2a26 350(define_attr "far_jump" "yes,no" (const_string "no"))
351
d51f92df 352
25f905c2 353;; The number of machine instructions this pattern expands to.
354;; Used for Thumb-2 conditional execution.
355(define_attr "ce_count" "" (const_int 1))
356
4182b724 357;;---------------------------------------------------------------------------
358;; Unspecs
359
360(include "unspecs.md")
361
d51f92df 362;;---------------------------------------------------------------------------
fd781bb2 363;; Mode iterators
d51f92df 364
3de0dec6 365(include "iterators.md")
03770691 366
d51f92df 367;;---------------------------------------------------------------------------
368;; Predicates
369
9c9db025 370(include "predicates.md")
234f6557 371(include "constraints.md")
9c9db025 372
a2cd141b 373;;---------------------------------------------------------------------------
374;; Pipeline descriptions
215b30b3 375
e3879fd0 376(define_attr "tune_cortexr4" "yes,no"
377 (const (if_then_else
7d3cda8c 378 (eq_attr "tune" "cortexr4,cortexr4f,cortexr5")
e3879fd0 379 (const_string "yes")
380 (const_string "no"))))
381
a2cd141b 382;; True if the generic scheduling description should be used.
383
384(define_attr "generic_sched" "yes,no"
2546d93a 385 (const (if_then_else
e18862f3 386 (ior (eq_attr "tune" "fa526,fa626,fa606te,fa626te,fmp626,fa726te,\
387 arm926ejs,arm1020e,arm1026ejs,arm1136js,\
388 arm1136jfs,cortexa5,cortexa7,cortexa8,\
42e7b263 389 cortexa9,cortexa12,cortexa15,cortexa17,\
b1099bfd 390 cortexa53,cortexa57,cortexm4,cortexm7,\
802e6377 391 exynosm1,marvell_pj4,xgene1")
2546d93a 392 (eq_attr "tune_cortexr4" "yes"))
4d5cb40d 393 (const_string "no")
394 (const_string "yes"))))
395
c0e1af52 396(define_attr "generic_vfp" "yes,no"
397 (const (if_then_else
398 (and (eq_attr "fpu" "vfp")
e18862f3 399 (eq_attr "tune" "!arm1020e,arm1022e,cortexa5,cortexa7,\
400 cortexa8,cortexa9,cortexa53,cortexm4,\
55a94dda 401 cortexm7,marvell_pj4,xgene1")
e3879fd0 402 (eq_attr "tune_cortexr4" "no"))
c0e1af52 403 (const_string "yes")
404 (const_string "no"))))
405
6b8f7c28 406(include "marvell-f-iwmmxt.md")
a2cd141b 407(include "arm-generic.md")
408(include "arm926ejs.md")
c0e1af52 409(include "arm1020e.md")
a2cd141b 410(include "arm1026ejs.md")
411(include "arm1136jfs.md")
0e266d06 412(include "fa526.md")
413(include "fa606te.md")
414(include "fa626te.md")
415(include "fmp626.md")
416(include "fa726te.md")
3f1e069f 417(include "cortex-a5.md")
d6b7f019 418(include "cortex-a7.md")
bcaec148 419(include "cortex-a8.md")
036068af 420(include "cortex-a9.md")
65f2f758 421(include "cortex-a15.md")
42e7b263 422(include "cortex-a17.md")
da10bc87 423(include "cortex-a53.md")
b1099bfd 424(include "cortex-a57.md")
934a1e72 425(include "cortex-r4.md")
e3879fd0 426(include "cortex-r4f.md")
e18862f3 427(include "cortex-m7.md")
2546d93a 428(include "cortex-m4.md")
429(include "cortex-m4-fpu.md")
802e6377 430(include "exynos-m1.md")
55e3ada8 431(include "vfp11.md")
ea7d210b 432(include "marvell-pj4.md")
55a94dda 433(include "xgene1.md")
3586df96 434
9c08d1fa 435\f
215b30b3 436;;---------------------------------------------------------------------------
e1159bbe 437;; Insn patterns
438;;
a0f94409 439;; Addition insns.
215b30b3 440
9c08d1fa 441;; Note: For DImode insns, there is normally no reason why operands should
442;; not be in the same register, what we don't want is for something being
443;; written to partially overlap something that is an input.
444
cffb2a26 445(define_expand "adddi3"
446 [(parallel
215b30b3 447 [(set (match_operand:DI 0 "s_register_operand" "")
cffb2a26 448 (plus:DI (match_operand:DI 1 "s_register_operand" "")
10e5ccd5 449 (match_operand:DI 2 "arm_adddi_operand" "")))
bd5b4116 450 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 451 "TARGET_EITHER"
452 "
25f905c2 453 if (TARGET_THUMB1)
cffb2a26 454 {
0438d37f 455 if (!REG_P (operands[1]))
bc5a93af 456 operands[1] = force_reg (DImode, operands[1]);
0438d37f 457 if (!REG_P (operands[2]))
bc5a93af 458 operands[2] = force_reg (DImode, operands[2]);
cffb2a26 459 }
460 "
461)
462
a0f94409 463(define_insn_and_split "*arm_adddi3"
10e5ccd5 464 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r,&r,&r")
465 (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0, r, 0, r")
466 (match_operand:DI 2 "arm_adddi_operand" "r, 0, r, Dd, Dd")))
bd5b4116 467 (clobber (reg:CC CC_REGNUM))]
b805622c 468 "TARGET_32BIT && !TARGET_NEON"
33782ec7 469 "#"
94829feb 470 "TARGET_32BIT && reload_completed
471 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))"
a0f94409 472 [(parallel [(set (reg:CC_C CC_REGNUM)
473 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
474 (match_dup 1)))
475 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 476 (set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (match_dup 5))
477 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
a0f94409 478 "
479 {
480 operands[3] = gen_highpart (SImode, operands[0]);
481 operands[0] = gen_lowpart (SImode, operands[0]);
482 operands[4] = gen_highpart (SImode, operands[1]);
483 operands[1] = gen_lowpart (SImode, operands[1]);
10e5ccd5 484 operands[5] = gen_highpart_mode (SImode, DImode, operands[2]);
a0f94409 485 operands[2] = gen_lowpart (SImode, operands[2]);
486 }"
cffb2a26 487 [(set_attr "conds" "clob")
1b7da4ac 488 (set_attr "length" "8")
489 (set_attr "type" "multiple")]
cffb2a26 490)
9c08d1fa 491
a0f94409 492(define_insn_and_split "*adddi_sesidi_di"
9c08d1fa 493 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
494 (plus:DI (sign_extend:DI
97499065 495 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 496 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 497 (clobber (reg:CC CC_REGNUM))]
b805622c 498 "TARGET_32BIT"
33782ec7 499 "#"
25f905c2 500 "TARGET_32BIT && reload_completed"
a0f94409 501 [(parallel [(set (reg:CC_C CC_REGNUM)
502 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
503 (match_dup 1)))
504 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 505 (set (match_dup 3) (plus:SI (plus:SI (ashiftrt:SI (match_dup 2)
a0f94409 506 (const_int 31))
080c0b9a 507 (match_dup 4))
508 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
a0f94409 509 "
510 {
511 operands[3] = gen_highpart (SImode, operands[0]);
512 operands[0] = gen_lowpart (SImode, operands[0]);
513 operands[4] = gen_highpart (SImode, operands[1]);
514 operands[1] = gen_lowpart (SImode, operands[1]);
515 operands[2] = gen_lowpart (SImode, operands[2]);
516 }"
215b30b3 517 [(set_attr "conds" "clob")
1b7da4ac 518 (set_attr "length" "8")
519 (set_attr "type" "multiple")]
215b30b3 520)
9c08d1fa 521
a0f94409 522(define_insn_and_split "*adddi_zesidi_di"
9c08d1fa 523 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
524 (plus:DI (zero_extend:DI
97499065 525 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 526 (match_operand:DI 1 "s_register_operand" "0,r")))
a0f94409 527 (clobber (reg:CC CC_REGNUM))]
b805622c 528 "TARGET_32BIT"
33782ec7 529 "#"
25f905c2 530 "TARGET_32BIT && reload_completed"
a0f94409 531 [(parallel [(set (reg:CC_C CC_REGNUM)
532 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
533 (match_dup 1)))
534 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 535 (set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (const_int 0))
536 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
a0f94409 537 "
538 {
539 operands[3] = gen_highpart (SImode, operands[0]);
540 operands[0] = gen_lowpart (SImode, operands[0]);
541 operands[4] = gen_highpart (SImode, operands[1]);
542 operands[1] = gen_lowpart (SImode, operands[1]);
543 operands[2] = gen_lowpart (SImode, operands[2]);
544 }"
cffb2a26 545 [(set_attr "conds" "clob")
1b7da4ac 546 (set_attr "length" "8")
547 (set_attr "type" "multiple")]
cffb2a26 548)
b11cae9e 549
f6c98a9a 550(define_expand "addv<mode>4"
551 [(match_operand:SIDI 0 "register_operand")
552 (match_operand:SIDI 1 "register_operand")
553 (match_operand:SIDI 2 "register_operand")
554 (match_operand 3 "")]
555 "TARGET_32BIT"
556{
557 emit_insn (gen_add<mode>3_compareV (operands[0], operands[1], operands[2]));
558 arm_gen_unlikely_cbranch (NE, CC_Vmode, operands[3]);
559
560 DONE;
561})
562
563(define_expand "uaddv<mode>4"
564 [(match_operand:SIDI 0 "register_operand")
565 (match_operand:SIDI 1 "register_operand")
566 (match_operand:SIDI 2 "register_operand")
567 (match_operand 3 "")]
568 "TARGET_32BIT"
569{
570 emit_insn (gen_add<mode>3_compareC (operands[0], operands[1], operands[2]));
571 arm_gen_unlikely_cbranch (NE, CC_Cmode, operands[3]);
572
573 DONE;
574})
575
87b22bf7 576(define_expand "addsi3"
cffb2a26 577 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 578 (plus:SI (match_operand:SI 1 "s_register_operand" "")
579 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 580 "TARGET_EITHER"
87b22bf7 581 "
0438d37f 582 if (TARGET_32BIT && CONST_INT_P (operands[2]))
87b22bf7 583 {
96f57e36 584 arm_split_constant (PLUS, SImode, NULL_RTX,
585 INTVAL (operands[2]), operands[0], operands[1],
e1ba4a27 586 optimize && can_create_pseudo_p ());
87b22bf7 587 DONE;
588 }
cffb2a26 589 "
590)
87b22bf7 591
5bd751ff 592; If there is a scratch available, this will be faster than synthesizing the
a0f94409 593; addition.
594(define_peephole2
595 [(match_scratch:SI 3 "r")
372575c7 596 (set (match_operand:SI 0 "arm_general_register_operand" "")
597 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
cffb2a26 598 (match_operand:SI 2 "const_int_operand" "")))]
25f905c2 599 "TARGET_32BIT &&
a0f94409 600 !(const_ok_for_arm (INTVAL (operands[2]))
601 || const_ok_for_arm (-INTVAL (operands[2])))
602 && const_ok_for_arm (~INTVAL (operands[2]))"
603 [(set (match_dup 3) (match_dup 2))
604 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
605 ""
606)
87b22bf7 607
2f02c19f 608;; The r/r/k alternative is required when reloading the address
609;; (plus (reg rN) (reg sp)) into (reg rN). In this case reload will
610;; put the duplicated register first, and not try the commutative version.
a0f94409 611(define_insn_and_split "*arm_addsi3"
fa1f9c9e 612 [(set (match_operand:SI 0 "s_register_operand" "=rk,l,l ,l ,r ,k ,r,k ,r ,k ,r ,k,k,r ,k ,r")
613 (plus:SI (match_operand:SI 1 "s_register_operand" "%0 ,l,0 ,l ,rk,k ,r,r ,rk,k ,rk,k,r,rk,k ,rk")
614 (match_operand:SI 2 "reg_or_int_operand" "rk ,l,Py,Pd,rI,rI,k,rI,Pj,Pj,L ,L,L,PJ,PJ,?n")))]
25f905c2 615 "TARGET_32BIT"
5565501b 616 "@
c24d855d 617 add%?\\t%0, %0, %2
5565501b 618 add%?\\t%0, %1, %2
a0b3420a 619 add%?\\t%0, %1, %2
7c36fe71 620 add%?\\t%0, %1, %2
621 add%?\\t%0, %1, %2
aaa37ad6 622 add%?\\t%0, %1, %2
2f02c19f 623 add%?\\t%0, %2, %1
fa1f9c9e 624 add%?\\t%0, %1, %2
d5cbae34 625 addw%?\\t%0, %1, %2
626 addw%?\\t%0, %1, %2
aaa37ad6 627 sub%?\\t%0, %1, #%n2
87b22bf7 628 sub%?\\t%0, %1, #%n2
d7757711 629 sub%?\\t%0, %1, #%n2
d5cbae34 630 subw%?\\t%0, %1, #%n2
631 subw%?\\t%0, %1, #%n2
87b22bf7 632 #"
a3ffc315 633 "TARGET_32BIT
0438d37f 634 && CONST_INT_P (operands[2])
d5cbae34 635 && !const_ok_for_op (INTVAL (operands[2]), PLUS)
a3ffc315 636 && (reload_completed || !arm_eliminable_register (operands[1]))"
a0f94409 637 [(clobber (const_int 0))]
638 "
96f57e36 639 arm_split_constant (PLUS, SImode, curr_insn,
640 INTVAL (operands[2]), operands[0],
a0f94409 641 operands[1], 0);
642 DONE;
643 "
fa1f9c9e 644 [(set_attr "length" "2,4,4,4,4,4,4,4,4,4,4,4,4,4,4,16")
d5cbae34 645 (set_attr "predicable" "yes")
fa1f9c9e 646 (set_attr "predicable_short_it" "yes,yes,yes,yes,no,no,no,no,no,no,no,no,no,no,no,no")
647 (set_attr "arch" "t2,t2,t2,t2,*,*,*,a,t2,t2,*,*,a,t2,t2,*")
65f68e55 648 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
d82e788e 649 (const_string "alu_imm")
112eda6f 650 (const_string "alu_sreg")))
65f68e55 651 ]
cffb2a26 652)
653
f6c98a9a 654(define_insn_and_split "adddi3_compareV"
655 [(set (reg:CC_V CC_REGNUM)
656 (ne:CC_V
657 (plus:TI
658 (sign_extend:TI (match_operand:DI 1 "register_operand" "r"))
659 (sign_extend:TI (match_operand:DI 2 "register_operand" "r")))
660 (sign_extend:TI (plus:DI (match_dup 1) (match_dup 2)))))
661 (set (match_operand:DI 0 "register_operand" "=&r")
662 (plus:DI (match_dup 1) (match_dup 2)))]
663 "TARGET_32BIT"
664 "#"
665 "&& reload_completed"
666 [(parallel [(set (reg:CC_C CC_REGNUM)
667 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
668 (match_dup 1)))
669 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
670 (parallel [(set (reg:CC_V CC_REGNUM)
671 (ne:CC_V
672 (plus:DI (plus:DI
673 (sign_extend:DI (match_dup 4))
674 (sign_extend:DI (match_dup 5)))
675 (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0)))
676 (plus:DI (sign_extend:DI
677 (plus:SI (match_dup 4) (match_dup 5)))
678 (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0)))))
679 (set (match_dup 3) (plus:SI (plus:SI
680 (match_dup 4) (match_dup 5))
681 (ltu:SI (reg:CC_C CC_REGNUM)
682 (const_int 0))))])]
683 "
684 {
685 operands[3] = gen_highpart (SImode, operands[0]);
686 operands[0] = gen_lowpart (SImode, operands[0]);
687 operands[4] = gen_highpart (SImode, operands[1]);
688 operands[1] = gen_lowpart (SImode, operands[1]);
689 operands[5] = gen_highpart (SImode, operands[2]);
690 operands[2] = gen_lowpart (SImode, operands[2]);
691 }"
692 [(set_attr "conds" "set")
693 (set_attr "length" "8")
694 (set_attr "type" "multiple")]
695)
696
697(define_insn "addsi3_compareV"
698 [(set (reg:CC_V CC_REGNUM)
699 (ne:CC_V
700 (plus:DI
701 (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
702 (sign_extend:DI (match_operand:SI 2 "register_operand" "r")))
703 (sign_extend:DI (plus:SI (match_dup 1) (match_dup 2)))))
704 (set (match_operand:SI 0 "register_operand" "=r")
705 (plus:SI (match_dup 1) (match_dup 2)))]
706 "TARGET_32BIT"
707 "adds%?\\t%0, %1, %2"
708 [(set_attr "conds" "set")
709 (set_attr "type" "alus_sreg")]
710)
711
712(define_insn "*addsi3_compareV_upper"
713 [(set (reg:CC_V CC_REGNUM)
714 (ne:CC_V
715 (plus:DI
716 (plus:DI
717 (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
718 (sign_extend:DI (match_operand:SI 2 "register_operand" "r")))
719 (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0)))
720 (plus:DI (sign_extend:DI
721 (plus:SI (match_dup 1) (match_dup 2)))
722 (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0)))))
723 (set (match_operand:SI 0 "register_operand" "=r")
724 (plus:SI
725 (plus:SI (match_dup 1) (match_dup 2))
726 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
727 "TARGET_32BIT"
728 "adcs%?\\t%0, %1, %2"
729 [(set_attr "conds" "set")
730 (set_attr "type" "adcs_reg")]
731)
732
733(define_insn_and_split "adddi3_compareC"
734 [(set (reg:CC_C CC_REGNUM)
735 (ne:CC_C
736 (plus:TI
737 (zero_extend:TI (match_operand:DI 1 "register_operand" "r"))
738 (zero_extend:TI (match_operand:DI 2 "register_operand" "r")))
739 (zero_extend:TI (plus:DI (match_dup 1) (match_dup 2)))))
740 (set (match_operand:DI 0 "register_operand" "=&r")
741 (plus:DI (match_dup 1) (match_dup 2)))]
742 "TARGET_32BIT"
743 "#"
744 "&& reload_completed"
745 [(parallel [(set (reg:CC_C CC_REGNUM)
746 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
747 (match_dup 1)))
748 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
749 (parallel [(set (reg:CC_C CC_REGNUM)
750 (ne:CC_C
751 (plus:DI (plus:DI
752 (zero_extend:DI (match_dup 4))
753 (zero_extend:DI (match_dup 5)))
754 (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0)))
755 (plus:DI (zero_extend:DI
756 (plus:SI (match_dup 4) (match_dup 5)))
757 (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0)))))
758 (set (match_dup 3) (plus:SI
759 (plus:SI (match_dup 4) (match_dup 5))
760 (ltu:SI (reg:CC_C CC_REGNUM)
761 (const_int 0))))])]
762 "
763 {
764 operands[3] = gen_highpart (SImode, operands[0]);
765 operands[0] = gen_lowpart (SImode, operands[0]);
766 operands[4] = gen_highpart (SImode, operands[1]);
767 operands[5] = gen_highpart (SImode, operands[2]);
768 operands[1] = gen_lowpart (SImode, operands[1]);
769 operands[2] = gen_lowpart (SImode, operands[2]);
770 }"
771 [(set_attr "conds" "set")
772 (set_attr "length" "8")
773 (set_attr "type" "multiple")]
774)
775
776(define_insn "*addsi3_compareC_upper"
777 [(set (reg:CC_C CC_REGNUM)
778 (ne:CC_C
779 (plus:DI
780 (plus:DI
781 (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
782 (zero_extend:DI (match_operand:SI 2 "register_operand" "r")))
783 (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0)))
784 (plus:DI (zero_extend:DI
785 (plus:SI (match_dup 1) (match_dup 2)))
786 (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0)))))
787 (set (match_operand:SI 0 "register_operand" "=r")
788 (plus:SI
789 (plus:SI (match_dup 1) (match_dup 2))
790 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
791 "TARGET_32BIT"
792 "adcs%?\\t%0, %1, %2"
793 [(set_attr "conds" "set")
794 (set_attr "type" "adcs_reg")]
795)
796
797(define_insn "addsi3_compareC"
798 [(set (reg:CC_C CC_REGNUM)
799 (ne:CC_C
800 (plus:DI
801 (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
802 (zero_extend:DI (match_operand:SI 2 "register_operand" "r")))
803 (zero_extend:DI
804 (plus:SI (match_dup 1) (match_dup 2)))))
805 (set (match_operand:SI 0 "register_operand" "=r")
806 (plus:SI (match_dup 1) (match_dup 2)))]
807 "TARGET_32BIT"
808 "adds%?\\t%0, %1, %2"
809 [(set_attr "conds" "set")
810 (set_attr "type" "alus_sreg")]
811)
812
90c2bcf0 813(define_insn "addsi3_compare0"
bd5b4116 814 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 815 (compare:CC_NOOV
65f68e55 816 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r,r")
817 (match_operand:SI 2 "arm_add_operand" "I,L,r"))
5565501b 818 (const_int 0)))
65f68e55 819 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9c08d1fa 820 (plus:SI (match_dup 1) (match_dup 2)))]
ec792a7b 821 "TARGET_ARM"
5565501b 822 "@
3ef90e77 823 adds%?\\t%0, %1, %2
824 subs%?\\t%0, %1, #%n2
825 adds%?\\t%0, %1, %2"
65f68e55 826 [(set_attr "conds" "set")
112eda6f 827 (set_attr "type" "alus_imm,alus_imm,alus_sreg")]
cffb2a26 828)
9c08d1fa 829
aea4c774 830(define_insn "*addsi3_compare0_scratch"
bd5b4116 831 [(set (reg:CC_NOOV CC_REGNUM)
aea4c774 832 (compare:CC_NOOV
65f68e55 833 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r, r")
834 (match_operand:SI 1 "arm_add_operand" "I,L, r"))
aea4c774 835 (const_int 0)))]
ec792a7b 836 "TARGET_ARM"
cffb2a26 837 "@
838 cmn%?\\t%0, %1
65f68e55 839 cmp%?\\t%0, #%n1
840 cmn%?\\t%0, %1"
596e5e8f 841 [(set_attr "conds" "set")
65f68e55 842 (set_attr "predicable" "yes")
112eda6f 843 (set_attr "type" "alus_imm,alus_imm,alus_sreg")]
0d66636f 844)
cffb2a26 845
aed179ae 846(define_insn "*compare_negsi_si"
847 [(set (reg:CC_Z CC_REGNUM)
848 (compare:CC_Z
7c36fe71 849 (neg:SI (match_operand:SI 0 "s_register_operand" "l,r"))
850 (match_operand:SI 1 "s_register_operand" "l,r")))]
25f905c2 851 "TARGET_32BIT"
aed179ae 852 "cmn%?\\t%1, %0"
596e5e8f 853 [(set_attr "conds" "set")
7c36fe71 854 (set_attr "predicable" "yes")
855 (set_attr "arch" "t2,*")
856 (set_attr "length" "2,4")
1b7da4ac 857 (set_attr "predicable_short_it" "yes,no")
112eda6f 858 (set_attr "type" "alus_sreg")]
0d66636f 859)
aea4c774 860
203c488f 861;; This is the canonicalization of addsi3_compare0_for_combiner when the
862;; addend is a constant.
190efb17 863(define_insn "cmpsi2_addneg"
203c488f 864 [(set (reg:CC CC_REGNUM)
865 (compare:CC
866 (match_operand:SI 1 "s_register_operand" "r,r")
2a977b78 867 (match_operand:SI 2 "arm_addimm_operand" "L,I")))
203c488f 868 (set (match_operand:SI 0 "s_register_operand" "=r,r")
869 (plus:SI (match_dup 1)
2a977b78 870 (match_operand:SI 3 "arm_addimm_operand" "I,L")))]
25f905c2 871 "TARGET_32BIT && INTVAL (operands[2]) == -INTVAL (operands[3])"
203c488f 872 "@
3ef90e77 873 adds%?\\t%0, %1, %3
874 subs%?\\t%0, %1, #%n3"
1b7da4ac 875 [(set_attr "conds" "set")
112eda6f 876 (set_attr "type" "alus_sreg")]
203c488f 877)
878
879;; Convert the sequence
880;; sub rd, rn, #1
881;; cmn rd, #1 (equivalent to cmp rd, #-1)
882;; bne dest
883;; into
884;; subs rd, rn, #1
885;; bcs dest ((unsigned)rn >= 1)
886;; similarly for the beq variant using bcc.
887;; This is a common looping idiom (while (n--))
888(define_peephole2
372575c7 889 [(set (match_operand:SI 0 "arm_general_register_operand" "")
890 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
203c488f 891 (const_int -1)))
892 (set (match_operand 2 "cc_register" "")
893 (compare (match_dup 0) (const_int -1)))
894 (set (pc)
895 (if_then_else (match_operator 3 "equality_operator"
896 [(match_dup 2) (const_int 0)])
897 (match_operand 4 "" "")
898 (match_operand 5 "" "")))]
25f905c2 899 "TARGET_32BIT && peep2_reg_dead_p (3, operands[2])"
203c488f 900 [(parallel[
901 (set (match_dup 2)
902 (compare:CC
903 (match_dup 1) (const_int 1)))
904 (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
905 (set (pc)
906 (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
907 (match_dup 4)
908 (match_dup 5)))]
909 "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
910 operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
911 ? GEU : LTU),
912 VOIDmode,
913 operands[2], const0_rtx);"
914)
915
ebcc79bc 916;; The next four insns work because they compare the result with one of
917;; the operands, and we know that the use of the condition code is
918;; either GEU or LTU, so we can use the carry flag from the addition
919;; instead of doing the compare a second time.
920(define_insn "*addsi3_compare_op1"
bd5b4116 921 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 922 (compare:CC_C
65f68e55 923 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
924 (match_operand:SI 2 "arm_add_operand" "I,L,r"))
ebcc79bc 925 (match_dup 1)))
65f68e55 926 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
ebcc79bc 927 (plus:SI (match_dup 1) (match_dup 2)))]
25f905c2 928 "TARGET_32BIT"
ebcc79bc 929 "@
3ef90e77 930 adds%?\\t%0, %1, %2
931 subs%?\\t%0, %1, #%n2
932 adds%?\\t%0, %1, %2"
65f68e55 933 [(set_attr "conds" "set")
112eda6f 934 (set_attr "type" "alus_imm,alus_imm,alus_sreg")]
0d66636f 935)
ebcc79bc 936
937(define_insn "*addsi3_compare_op2"
bd5b4116 938 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 939 (compare:CC_C
65f68e55 940 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
941 (match_operand:SI 2 "arm_add_operand" "I,L,r"))
ebcc79bc 942 (match_dup 2)))
65f68e55 943 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9c08d1fa 944 (plus:SI (match_dup 1) (match_dup 2)))]
25f905c2 945 "TARGET_32BIT"
5565501b 946 "@
3ef90e77 947 adds%?\\t%0, %1, %2
38128b57 948 subs%?\\t%0, %1, #%n2
949 adds%?\\t%0, %1, %2"
65f68e55 950 [(set_attr "conds" "set")
112eda6f 951 (set_attr "type" "alus_imm,alus_imm,alus_sreg")]
0d66636f 952)
9c08d1fa 953
ebcc79bc 954(define_insn "*compare_addsi2_op0"
bd5b4116 955 [(set (reg:CC_C CC_REGNUM)
7c36fe71 956 (compare:CC_C
957 (plus:SI (match_operand:SI 0 "s_register_operand" "l,l,r,r,r")
958 (match_operand:SI 1 "arm_add_operand" "Pv,l,I,L,r"))
959 (match_dup 0)))]
25f905c2 960 "TARGET_32BIT"
ebcc79bc 961 "@
7c36fe71 962 cmp%?\\t%0, #%n1
963 cmn%?\\t%0, %1
ebcc79bc 964 cmn%?\\t%0, %1
65f68e55 965 cmp%?\\t%0, #%n1
966 cmn%?\\t%0, %1"
596e5e8f 967 [(set_attr "conds" "set")
65f68e55 968 (set_attr "predicable" "yes")
7c36fe71 969 (set_attr "arch" "t2,t2,*,*,*")
970 (set_attr "predicable_short_it" "yes,yes,no,no,no")
971 (set_attr "length" "2,2,4,4,4")
112eda6f 972 (set_attr "type" "alus_imm,alus_sreg,alus_imm,alus_imm,alus_sreg")]
0d66636f 973)
ebcc79bc 974
975(define_insn "*compare_addsi2_op1"
bd5b4116 976 [(set (reg:CC_C CC_REGNUM)
7c36fe71 977 (compare:CC_C
978 (plus:SI (match_operand:SI 0 "s_register_operand" "l,l,r,r,r")
979 (match_operand:SI 1 "arm_add_operand" "Pv,l,I,L,r"))
980 (match_dup 1)))]
25f905c2 981 "TARGET_32BIT"
ebcc79bc 982 "@
7c36fe71 983 cmp%?\\t%0, #%n1
984 cmn%?\\t%0, %1
ebcc79bc 985 cmn%?\\t%0, %1
65f68e55 986 cmp%?\\t%0, #%n1
987 cmn%?\\t%0, %1"
596e5e8f 988 [(set_attr "conds" "set")
65f68e55 989 (set_attr "predicable" "yes")
7c36fe71 990 (set_attr "arch" "t2,t2,*,*,*")
991 (set_attr "predicable_short_it" "yes,yes,no,no,no")
992 (set_attr "length" "2,2,4,4,4")
112eda6f 993 (set_attr "type" "alus_imm,alus_sreg,alus_imm,alus_imm,alus_sreg")]
7c36fe71 994 )
ebcc79bc 995
080c0b9a 996(define_insn "*addsi3_carryin_<optab>"
7c36fe71 997 [(set (match_operand:SI 0 "s_register_operand" "=l,r,r")
998 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%l,r,r")
999 (match_operand:SI 2 "arm_not_operand" "0,rI,K"))
1000 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))]
25f905c2 1001 "TARGET_32BIT"
10e5ccd5 1002 "@
a0b3420a 1003 adc%?\\t%0, %1, %2
10e5ccd5 1004 adc%?\\t%0, %1, %2
1005 sbc%?\\t%0, %1, #%B2"
a7de272d 1006 [(set_attr "conds" "use")
7c36fe71 1007 (set_attr "predicable" "yes")
1008 (set_attr "arch" "t2,*,*")
1009 (set_attr "length" "4")
1b7da4ac 1010 (set_attr "predicable_short_it" "yes,no,no")
1011 (set_attr "type" "adc_reg,adc_reg,adc_imm")]
cffb2a26 1012)
ebcc79bc 1013
080c0b9a 1014(define_insn "*addsi3_carryin_alt2_<optab>"
7c36fe71 1015 [(set (match_operand:SI 0 "s_register_operand" "=l,r,r")
1016 (plus:SI (plus:SI (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))
1017 (match_operand:SI 1 "s_register_operand" "%l,r,r"))
1018 (match_operand:SI 2 "arm_rhs_operand" "l,rI,K")))]
25f905c2 1019 "TARGET_32BIT"
10e5ccd5 1020 "@
a0b3420a 1021 adc%?\\t%0, %1, %2
10e5ccd5 1022 adc%?\\t%0, %1, %2
1023 sbc%?\\t%0, %1, #%B2"
a7de272d 1024 [(set_attr "conds" "use")
7c36fe71 1025 (set_attr "predicable" "yes")
1026 (set_attr "arch" "t2,*,*")
1027 (set_attr "length" "4")
1b7da4ac 1028 (set_attr "predicable_short_it" "yes,no,no")
1029 (set_attr "type" "adc_reg,adc_reg,adc_imm")]
0d66636f 1030)
ebcc79bc 1031
080c0b9a 1032(define_insn "*addsi3_carryin_shift_<optab>"
ebcc79bc 1033 [(set (match_operand:SI 0 "s_register_operand" "=r")
080c0b9a 1034 (plus:SI (plus:SI
1035 (match_operator:SI 2 "shift_operator"
1036 [(match_operand:SI 3 "s_register_operand" "r")
1037 (match_operand:SI 4 "reg_or_int_operand" "rM")])
1038 (match_operand:SI 1 "s_register_operand" "r"))
1039 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))]
25f905c2 1040 "TARGET_32BIT"
080c0b9a 1041 "adc%?\\t%0, %1, %3%S2"
1042 [(set_attr "conds" "use")
a7de272d 1043 (set_attr "predicable" "yes")
7c36fe71 1044 (set_attr "predicable_short_it" "no")
080c0b9a 1045 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
d82e788e 1046 (const_string "alu_shift_imm")
1047 (const_string "alu_shift_reg")))]
cffb2a26 1048)
ebcc79bc 1049
922b6913 1050(define_insn "*addsi3_carryin_clobercc_<optab>"
1051 [(set (match_operand:SI 0 "s_register_operand" "=r")
1052 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%r")
1053 (match_operand:SI 2 "arm_rhs_operand" "rI"))
1054 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))
1055 (clobber (reg:CC CC_REGNUM))]
1056 "TARGET_32BIT"
3ef90e77 1057 "adcs%?\\t%0, %1, %2"
1b7da4ac 1058 [(set_attr "conds" "set")
1059 (set_attr "type" "adcs_reg")]
922b6913 1060)
1061
f6c98a9a 1062(define_expand "subv<mode>4"
1063 [(match_operand:SIDI 0 "register_operand")
1064 (match_operand:SIDI 1 "register_operand")
1065 (match_operand:SIDI 2 "register_operand")
1066 (match_operand 3 "")]
1067 "TARGET_32BIT"
1068{
1069 emit_insn (gen_sub<mode>3_compare1 (operands[0], operands[1], operands[2]));
1070 arm_gen_unlikely_cbranch (NE, CC_Vmode, operands[3]);
1071
1072 DONE;
1073})
1074
1075(define_expand "usubv<mode>4"
1076 [(match_operand:SIDI 0 "register_operand")
1077 (match_operand:SIDI 1 "register_operand")
1078 (match_operand:SIDI 2 "register_operand")
1079 (match_operand 3 "")]
1080 "TARGET_32BIT"
1081{
1082 emit_insn (gen_sub<mode>3_compare1 (operands[0], operands[1], operands[2]));
1083 arm_gen_unlikely_cbranch (LTU, CCmode, operands[3]);
1084
1085 DONE;
1086})
1087
1088(define_insn_and_split "subdi3_compare1"
1089 [(set (reg:CC CC_REGNUM)
1090 (compare:CC
1091 (match_operand:DI 1 "register_operand" "r")
1092 (match_operand:DI 2 "register_operand" "r")))
1093 (set (match_operand:DI 0 "register_operand" "=&r")
1094 (minus:DI (match_dup 1) (match_dup 2)))]
1095 "TARGET_32BIT"
1096 "#"
1097 "&& reload_completed"
1098 [(parallel [(set (reg:CC CC_REGNUM)
1099 (compare:CC (match_dup 1) (match_dup 2)))
1100 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1101 (parallel [(set (reg:CC CC_REGNUM)
1102 (compare:CC (match_dup 4) (match_dup 5)))
1103 (set (match_dup 3) (minus:SI (minus:SI (match_dup 4) (match_dup 5))
1104 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))])]
1105 {
1106 operands[3] = gen_highpart (SImode, operands[0]);
1107 operands[0] = gen_lowpart (SImode, operands[0]);
1108 operands[4] = gen_highpart (SImode, operands[1]);
1109 operands[1] = gen_lowpart (SImode, operands[1]);
1110 operands[5] = gen_highpart (SImode, operands[2]);
1111 operands[2] = gen_lowpart (SImode, operands[2]);
1112 }
1113 [(set_attr "conds" "set")
1114 (set_attr "length" "8")
1115 (set_attr "type" "multiple")]
1116)
1117
1118(define_insn "subsi3_compare1"
1119 [(set (reg:CC CC_REGNUM)
1120 (compare:CC
1121 (match_operand:SI 1 "register_operand" "r")
1122 (match_operand:SI 2 "register_operand" "r")))
1123 (set (match_operand:SI 0 "register_operand" "=r")
1124 (minus:SI (match_dup 1) (match_dup 2)))]
1125 "TARGET_32BIT"
1126 "subs%?\\t%0, %1, %2"
1127 [(set_attr "conds" "set")
1128 (set_attr "type" "alus_sreg")]
1129)
1130
9154bd82 1131(define_insn "*subsi3_carryin"
d5bf2b53 1132 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1133 (minus:SI (minus:SI (match_operand:SI 1 "reg_or_int_operand" "r,I,Pz")
1134 (match_operand:SI 2 "s_register_operand" "r,r,r"))
1135 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
9154bd82 1136 "TARGET_32BIT"
1137 "@
1138 sbc%?\\t%0, %1, %2
d5bf2b53 1139 rsc%?\\t%0, %2, %1
1140 sbc%?\\t%0, %2, %2, lsl #1"
9154bd82 1141 [(set_attr "conds" "use")
d5bf2b53 1142 (set_attr "arch" "*,a,t2")
7c36fe71 1143 (set_attr "predicable" "yes")
1b7da4ac 1144 (set_attr "predicable_short_it" "no")
d5bf2b53 1145 (set_attr "type" "adc_reg,adc_imm,alu_shift_imm")]
9154bd82 1146)
1147
1148(define_insn "*subsi3_carryin_const"
1149 [(set (match_operand:SI 0 "s_register_operand" "=r")
df46fd5e 1150 (minus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1151 (match_operand:SI 2 "arm_not_immediate_operand" "K"))
9154bd82 1152 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1153 "TARGET_32BIT"
1154 "sbc\\t%0, %1, #%B2"
1b7da4ac 1155 [(set_attr "conds" "use")
1156 (set_attr "type" "adc_imm")]
9154bd82 1157)
1158
1159(define_insn "*subsi3_carryin_compare"
1160 [(set (reg:CC CC_REGNUM)
1161 (compare:CC (match_operand:SI 1 "s_register_operand" "r")
1162 (match_operand:SI 2 "s_register_operand" "r")))
1163 (set (match_operand:SI 0 "s_register_operand" "=r")
1164 (minus:SI (minus:SI (match_dup 1)
1165 (match_dup 2))
1166 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1167 "TARGET_32BIT"
1168 "sbcs\\t%0, %1, %2"
1b7da4ac 1169 [(set_attr "conds" "set")
1170 (set_attr "type" "adcs_reg")]
9154bd82 1171)
1172
1173(define_insn "*subsi3_carryin_compare_const"
1174 [(set (reg:CC CC_REGNUM)
1175 (compare:CC (match_operand:SI 1 "reg_or_int_operand" "r")
1176 (match_operand:SI 2 "arm_not_operand" "K")))
1177 (set (match_operand:SI 0 "s_register_operand" "=r")
1178 (minus:SI (plus:SI (match_dup 1)
1179 (match_dup 2))
1180 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1181 "TARGET_32BIT"
1182 "sbcs\\t%0, %1, #%B2"
1b7da4ac 1183 [(set_attr "conds" "set")
1184 (set_attr "type" "adcs_imm")]
9154bd82 1185)
1186
1187(define_insn "*subsi3_carryin_shift"
1188 [(set (match_operand:SI 0 "s_register_operand" "=r")
1189 (minus:SI (minus:SI
1190 (match_operand:SI 1 "s_register_operand" "r")
1191 (match_operator:SI 2 "shift_operator"
1192 [(match_operand:SI 3 "s_register_operand" "r")
1193 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
1194 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1195 "TARGET_32BIT"
1196 "sbc%?\\t%0, %1, %3%S2"
1197 [(set_attr "conds" "use")
1198 (set_attr "predicable" "yes")
1199 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
d82e788e 1200 (const_string "alu_shift_imm")
1201 (const_string "alu_shift_reg")))]
9154bd82 1202)
1203
1204(define_insn "*rsbsi3_carryin_shift"
1205 [(set (match_operand:SI 0 "s_register_operand" "=r")
1206 (minus:SI (minus:SI
1207 (match_operator:SI 2 "shift_operator"
1208 [(match_operand:SI 3 "s_register_operand" "r")
1209 (match_operand:SI 4 "reg_or_int_operand" "rM")])
1210 (match_operand:SI 1 "s_register_operand" "r"))
1211 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1212 "TARGET_ARM"
1213 "rsc%?\\t%0, %1, %3%S2"
1214 [(set_attr "conds" "use")
1215 (set_attr "predicable" "yes")
1216 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
d82e788e 1217 (const_string "alu_shift_imm")
1218 (const_string "alu_shift_reg")))]
9154bd82 1219)
1220
d795fb69 1221; transform ((x << y) - 1) to ~(~(x-1) << y) Where X is a constant.
1222(define_split
1223 [(set (match_operand:SI 0 "s_register_operand" "")
1224 (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
1225 (match_operand:SI 2 "s_register_operand" ""))
1226 (const_int -1)))
1227 (clobber (match_operand:SI 3 "s_register_operand" ""))]
25f905c2 1228 "TARGET_32BIT"
d795fb69 1229 [(set (match_dup 3) (match_dup 1))
1230 (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
1231 "
1232 operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
1233")
1234
604f3a0a 1235(define_expand "addsf3"
1236 [(set (match_operand:SF 0 "s_register_operand" "")
1237 (plus:SF (match_operand:SF 1 "s_register_operand" "")
d86c91f6 1238 (match_operand:SF 2 "s_register_operand" "")))]
25f905c2 1239 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1240 "
604f3a0a 1241")
1242
604f3a0a 1243(define_expand "adddf3"
1244 [(set (match_operand:DF 0 "s_register_operand" "")
1245 (plus:DF (match_operand:DF 1 "s_register_operand" "")
d86c91f6 1246 (match_operand:DF 2 "s_register_operand" "")))]
a50d7267 1247 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 1248 "
604f3a0a 1249")
1250
cffb2a26 1251(define_expand "subdi3"
1252 [(parallel
1253 [(set (match_operand:DI 0 "s_register_operand" "")
1254 (minus:DI (match_operand:DI 1 "s_register_operand" "")
1255 (match_operand:DI 2 "s_register_operand" "")))
bd5b4116 1256 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 1257 "TARGET_EITHER"
1258 "
25f905c2 1259 if (TARGET_THUMB1)
cffb2a26 1260 {
0438d37f 1261 if (!REG_P (operands[1]))
5aa8c5f0 1262 operands[1] = force_reg (DImode, operands[1]);
0438d37f 1263 if (!REG_P (operands[2]))
5aa8c5f0 1264 operands[2] = force_reg (DImode, operands[2]);
cffb2a26 1265 }
1266 "
1267)
1268
2f9b23e3 1269(define_insn_and_split "*arm_subdi3"
cffb2a26 1270 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
9c08d1fa 1271 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
1272 (match_operand:DI 2 "s_register_operand" "r,0,0")))
bd5b4116 1273 (clobber (reg:CC CC_REGNUM))]
94829feb 1274 "TARGET_32BIT && !TARGET_NEON"
2f9b23e3 1275 "#" ; "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
1276 "&& reload_completed"
1277 [(parallel [(set (reg:CC CC_REGNUM)
1278 (compare:CC (match_dup 1) (match_dup 2)))
1279 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1280 (set (match_dup 3) (minus:SI (minus:SI (match_dup 4) (match_dup 5))
1281 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1282 {
1283 operands[3] = gen_highpart (SImode, operands[0]);
1284 operands[0] = gen_lowpart (SImode, operands[0]);
1285 operands[4] = gen_highpart (SImode, operands[1]);
1286 operands[1] = gen_lowpart (SImode, operands[1]);
1287 operands[5] = gen_highpart (SImode, operands[2]);
1288 operands[2] = gen_lowpart (SImode, operands[2]);
1289 }
cffb2a26 1290 [(set_attr "conds" "clob")
1b7da4ac 1291 (set_attr "length" "8")
1292 (set_attr "type" "multiple")]
cffb2a26 1293)
1294
2f9b23e3 1295(define_insn_and_split "*subdi_di_zesidi"
cffb2a26 1296 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 1297 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r")
9c08d1fa 1298 (zero_extend:DI
cffb2a26 1299 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 1300 (clobber (reg:CC CC_REGNUM))]
25f905c2 1301 "TARGET_32BIT"
2f9b23e3 1302 "#" ; "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
1303 "&& reload_completed"
1304 [(parallel [(set (reg:CC CC_REGNUM)
1305 (compare:CC (match_dup 1) (match_dup 2)))
1306 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1307 (set (match_dup 3) (minus:SI (plus:SI (match_dup 4) (match_dup 5))
1308 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1309 {
1310 operands[3] = gen_highpart (SImode, operands[0]);
1311 operands[0] = gen_lowpart (SImode, operands[0]);
1312 operands[4] = gen_highpart (SImode, operands[1]);
1313 operands[1] = gen_lowpart (SImode, operands[1]);
1314 operands[5] = GEN_INT (~0);
1315 }
cffb2a26 1316 [(set_attr "conds" "clob")
1b7da4ac 1317 (set_attr "length" "8")
1318 (set_attr "type" "multiple")]
cffb2a26 1319)
9c08d1fa 1320
2f9b23e3 1321(define_insn_and_split "*subdi_di_sesidi"
cffb2a26 1322 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 1323 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r")
9c08d1fa 1324 (sign_extend:DI
cffb2a26 1325 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 1326 (clobber (reg:CC CC_REGNUM))]
25f905c2 1327 "TARGET_32BIT"
2f9b23e3 1328 "#" ; "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
1329 "&& reload_completed"
1330 [(parallel [(set (reg:CC CC_REGNUM)
1331 (compare:CC (match_dup 1) (match_dup 2)))
1332 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1333 (set (match_dup 3) (minus:SI (minus:SI (match_dup 4)
1334 (ashiftrt:SI (match_dup 2)
1335 (const_int 31)))
1336 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1337 {
1338 operands[3] = gen_highpart (SImode, operands[0]);
1339 operands[0] = gen_lowpart (SImode, operands[0]);
1340 operands[4] = gen_highpart (SImode, operands[1]);
1341 operands[1] = gen_lowpart (SImode, operands[1]);
1342 }
cffb2a26 1343 [(set_attr "conds" "clob")
1b7da4ac 1344 (set_attr "length" "8")
1345 (set_attr "type" "multiple")]
cffb2a26 1346)
9c08d1fa 1347
2f9b23e3 1348(define_insn_and_split "*subdi_zesidi_di"
cffb2a26 1349 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1350 (minus:DI (zero_extend:DI
cffb2a26 1351 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 1352 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 1353 (clobber (reg:CC CC_REGNUM))]
cffb2a26 1354 "TARGET_ARM"
2f9b23e3 1355 "#" ; "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
1356 ; is equivalent to:
1357 ; "subs\\t%Q0, %2, %Q1\;rsc\\t%R0, %R1, #0"
1358 "&& reload_completed"
1359 [(parallel [(set (reg:CC CC_REGNUM)
1360 (compare:CC (match_dup 2) (match_dup 1)))
1361 (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))])
1362 (set (match_dup 3) (minus:SI (minus:SI (const_int 0) (match_dup 4))
1363 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1364 {
1365 operands[3] = gen_highpart (SImode, operands[0]);
1366 operands[0] = gen_lowpart (SImode, operands[0]);
1367 operands[4] = gen_highpart (SImode, operands[1]);
1368 operands[1] = gen_lowpart (SImode, operands[1]);
1369 }
cffb2a26 1370 [(set_attr "conds" "clob")
1b7da4ac 1371 (set_attr "length" "8")
1372 (set_attr "type" "multiple")]
cffb2a26 1373)
9c08d1fa 1374
2f9b23e3 1375(define_insn_and_split "*subdi_sesidi_di"
cffb2a26 1376 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1377 (minus:DI (sign_extend:DI
cffb2a26 1378 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 1379 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 1380 (clobber (reg:CC CC_REGNUM))]
cffb2a26 1381 "TARGET_ARM"
2f9b23e3 1382 "#" ; "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
1383 ; is equivalent to:
1384 ; "subs\\t%Q0, %2, %Q1\;rsc\\t%R0, %R1, %2, asr #31"
1385 "&& reload_completed"
1386 [(parallel [(set (reg:CC CC_REGNUM)
1387 (compare:CC (match_dup 2) (match_dup 1)))
1388 (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))])
1389 (set (match_dup 3) (minus:SI (minus:SI
1390 (ashiftrt:SI (match_dup 2)
1391 (const_int 31))
1392 (match_dup 4))
1393 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1394 {
1395 operands[3] = gen_highpart (SImode, operands[0]);
1396 operands[0] = gen_lowpart (SImode, operands[0]);
1397 operands[4] = gen_highpart (SImode, operands[1]);
1398 operands[1] = gen_lowpart (SImode, operands[1]);
1399 }
cffb2a26 1400 [(set_attr "conds" "clob")
1b7da4ac 1401 (set_attr "length" "8")
1402 (set_attr "type" "multiple")]
cffb2a26 1403)
9c08d1fa 1404
2f9b23e3 1405(define_insn_and_split "*subdi_zesidi_zesidi"
cffb2a26 1406 [(set (match_operand:DI 0 "s_register_operand" "=r")
9c08d1fa 1407 (minus:DI (zero_extend:DI
cffb2a26 1408 (match_operand:SI 1 "s_register_operand" "r"))
9c08d1fa 1409 (zero_extend:DI
cffb2a26 1410 (match_operand:SI 2 "s_register_operand" "r"))))
bd5b4116 1411 (clobber (reg:CC CC_REGNUM))]
25f905c2 1412 "TARGET_32BIT"
2f9b23e3 1413 "#" ; "subs\\t%Q0, %1, %2\;sbc\\t%R0, %1, %1"
1414 "&& reload_completed"
1415 [(parallel [(set (reg:CC CC_REGNUM)
1416 (compare:CC (match_dup 1) (match_dup 2)))
1417 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1418 (set (match_dup 3) (minus:SI (minus:SI (match_dup 1) (match_dup 1))
1419 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1420 {
1421 operands[3] = gen_highpart (SImode, operands[0]);
1422 operands[0] = gen_lowpart (SImode, operands[0]);
1423 }
cffb2a26 1424 [(set_attr "conds" "clob")
1b7da4ac 1425 (set_attr "length" "8")
1426 (set_attr "type" "multiple")]
cffb2a26 1427)
b11cae9e 1428
87b22bf7 1429(define_expand "subsi3"
cffb2a26 1430 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 1431 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
1432 (match_operand:SI 2 "s_register_operand" "")))]
cffb2a26 1433 "TARGET_EITHER"
87b22bf7 1434 "
0438d37f 1435 if (CONST_INT_P (operands[1]))
87b22bf7 1436 {
25f905c2 1437 if (TARGET_32BIT)
cffb2a26 1438 {
17202aa5 1439 if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[1]), MINUS))
1440 operands[1] = force_reg (SImode, operands[1]);
1441 else
1442 {
1443 arm_split_constant (MINUS, SImode, NULL_RTX,
1444 INTVAL (operands[1]), operands[0],
1445 operands[2],
1446 optimize && can_create_pseudo_p ());
1447 DONE;
1448 }
cffb2a26 1449 }
25f905c2 1450 else /* TARGET_THUMB1 */
cffb2a26 1451 operands[1] = force_reg (SImode, operands[1]);
87b22bf7 1452 }
cffb2a26 1453 "
1454)
87b22bf7 1455
25f905c2 1456; ??? Check Thumb-2 split length
a0f94409 1457(define_insn_and_split "*arm_subsi3_insn"
3a44c5a9 1458 [(set (match_operand:SI 0 "s_register_operand" "=l,l ,l ,l ,r,r,r,rk,r")
1459 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "l ,0 ,l ,Pz,I,r,r,k ,?n")
1460 (match_operand:SI 2 "reg_or_int_operand" "l ,Py,Pd,l ,r,I,r,r ,r")))]
25f905c2 1461 "TARGET_32BIT"
e2348bcb 1462 "@
7c36fe71 1463 sub%?\\t%0, %1, %2
1464 sub%?\\t%0, %2
1465 sub%?\\t%0, %1, %2
1466 rsb%?\\t%0, %2, %1
87b22bf7 1467 rsb%?\\t%0, %2, %1
aaa37ad6 1468 sub%?\\t%0, %1, %2
080c0b9a 1469 sub%?\\t%0, %1, %2
65f68e55 1470 sub%?\\t%0, %1, %2
87b22bf7 1471 #"
0438d37f 1472 "&& (CONST_INT_P (operands[1])
91a5e339 1473 && !const_ok_for_arm (INTVAL (operands[1])))"
87b22bf7 1474 [(clobber (const_int 0))]
1475 "
96f57e36 1476 arm_split_constant (MINUS, SImode, curr_insn,
1477 INTVAL (operands[1]), operands[0], operands[2], 0);
87b22bf7 1478 DONE;
cffb2a26 1479 "
7c36fe71 1480 [(set_attr "length" "4,4,4,4,4,4,4,4,16")
1481 (set_attr "arch" "t2,t2,t2,t2,*,*,*,*,*")
65f68e55 1482 (set_attr "predicable" "yes")
7c36fe71 1483 (set_attr "predicable_short_it" "yes,yes,yes,yes,no,no,no,no,no")
112eda6f 1484 (set_attr "type" "alu_sreg,alu_sreg,alu_sreg,alu_sreg,alu_imm,alu_imm,alu_sreg,alu_sreg,multiple")]
a0f94409 1485)
1486
1487(define_peephole2
1488 [(match_scratch:SI 3 "r")
372575c7 1489 (set (match_operand:SI 0 "arm_general_register_operand" "")
a0f94409 1490 (minus:SI (match_operand:SI 1 "const_int_operand" "")
372575c7 1491 (match_operand:SI 2 "arm_general_register_operand" "")))]
25f905c2 1492 "TARGET_32BIT
a0f94409 1493 && !const_ok_for_arm (INTVAL (operands[1]))
1494 && const_ok_for_arm (~INTVAL (operands[1]))"
1495 [(set (match_dup 3) (match_dup 1))
1496 (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1497 ""
cffb2a26 1498)
b11cae9e 1499
62e39b06 1500(define_insn "subsi3_compare0"
bd5b4116 1501 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1502 (compare:CC_NOOV
65f68e55 1503 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,r,I")
1504 (match_operand:SI 2 "arm_rhs_operand" "I,r,r"))
215b30b3 1505 (const_int 0)))
65f68e55 1506 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9c08d1fa 1507 (minus:SI (match_dup 1) (match_dup 2)))]
25f905c2 1508 "TARGET_32BIT"
e2348bcb 1509 "@
3ef90e77 1510 subs%?\\t%0, %1, %2
1511 subs%?\\t%0, %1, %2
1512 rsbs%?\\t%0, %2, %1"
65f68e55 1513 [(set_attr "conds" "set")
112eda6f 1514 (set_attr "type" "alus_imm,alus_sreg,alus_sreg")]
cffb2a26 1515)
9c08d1fa 1516
190efb17 1517(define_insn "subsi3_compare"
080c0b9a 1518 [(set (reg:CC CC_REGNUM)
65f68e55 1519 (compare:CC (match_operand:SI 1 "arm_rhs_operand" "r,r,I")
1520 (match_operand:SI 2 "arm_rhs_operand" "I,r,r")))
1521 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2df9477b 1522 (minus:SI (match_dup 1) (match_dup 2)))]
1523 "TARGET_32BIT"
1524 "@
3ef90e77 1525 subs%?\\t%0, %1, %2
1526 subs%?\\t%0, %1, %2
1527 rsbs%?\\t%0, %2, %1"
65f68e55 1528 [(set_attr "conds" "set")
112eda6f 1529 (set_attr "type" "alus_imm,alus_sreg,alus_sreg")]
2df9477b 1530)
1531
604f3a0a 1532(define_expand "subsf3"
1533 [(set (match_operand:SF 0 "s_register_operand" "")
d86c91f6 1534 (minus:SF (match_operand:SF 1 "s_register_operand" "")
1535 (match_operand:SF 2 "s_register_operand" "")))]
25f905c2 1536 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1537 "
604f3a0a 1538")
1539
604f3a0a 1540(define_expand "subdf3"
1541 [(set (match_operand:DF 0 "s_register_operand" "")
d86c91f6 1542 (minus:DF (match_operand:DF 1 "s_register_operand" "")
1543 (match_operand:DF 2 "s_register_operand" "")))]
a50d7267 1544 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 1545 "
604f3a0a 1546")
1547
b11cae9e 1548\f
1549;; Multiplication insns
1550
4422d91f 1551(define_expand "mulhi3"
1552 [(set (match_operand:HI 0 "s_register_operand" "")
1553 (mult:HI (match_operand:HI 1 "s_register_operand" "")
1554 (match_operand:HI 2 "s_register_operand" "")))]
1555 "TARGET_DSP_MULTIPLY"
1556 "
1557 {
1558 rtx result = gen_reg_rtx (SImode);
1559 emit_insn (gen_mulhisi3 (result, operands[1], operands[2]));
1560 emit_move_insn (operands[0], gen_lowpart (HImode, result));
1561 DONE;
1562 }"
1563)
1564
cffb2a26 1565(define_expand "mulsi3"
1566 [(set (match_operand:SI 0 "s_register_operand" "")
1567 (mult:SI (match_operand:SI 2 "s_register_operand" "")
1568 (match_operand:SI 1 "s_register_operand" "")))]
1569 "TARGET_EITHER"
1570 ""
1571)
1572
9c08d1fa 1573;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
cffb2a26 1574(define_insn "*arm_mulsi3"
1575 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1576 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1577 (match_operand:SI 1 "s_register_operand" "%0,r")))]
58d7d654 1578 "TARGET_32BIT && !arm_arch6"
f7fbdd4a 1579 "mul%?\\t%0, %2, %1"
9da0ec36 1580 [(set_attr "type" "mul")
0d66636f 1581 (set_attr "predicable" "yes")]
cffb2a26 1582)
1583
58d7d654 1584(define_insn "*arm_mulsi3_v6"
d952d547 1585 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
1586 (mult:SI (match_operand:SI 1 "s_register_operand" "0,l,r")
1587 (match_operand:SI 2 "s_register_operand" "l,0,r")))]
58d7d654 1588 "TARGET_32BIT && arm_arch6"
1589 "mul%?\\t%0, %1, %2"
9da0ec36 1590 [(set_attr "type" "mul")
d952d547 1591 (set_attr "predicable" "yes")
1592 (set_attr "arch" "t2,t2,*")
1593 (set_attr "length" "4")
1594 (set_attr "predicable_short_it" "yes,yes,no")]
58d7d654 1595)
1596
f7fbdd4a 1597(define_insn "*mulsi3_compare0"
bd5b4116 1598 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1599 (compare:CC_NOOV (mult:SI
1600 (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1601 (match_operand:SI 1 "s_register_operand" "%0,r"))
9c08d1fa 1602 (const_int 0)))
1603 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1604 (mult:SI (match_dup 2) (match_dup 1)))]
58d7d654 1605 "TARGET_ARM && !arm_arch6"
3ef90e77 1606 "muls%?\\t%0, %2, %1"
58d7d654 1607 [(set_attr "conds" "set")
9da0ec36 1608 (set_attr "type" "muls")]
58d7d654 1609)
1610
1611(define_insn "*mulsi3_compare0_v6"
1612 [(set (reg:CC_NOOV CC_REGNUM)
1613 (compare:CC_NOOV (mult:SI
1614 (match_operand:SI 2 "s_register_operand" "r")
1615 (match_operand:SI 1 "s_register_operand" "r"))
1616 (const_int 0)))
1617 (set (match_operand:SI 0 "s_register_operand" "=r")
1618 (mult:SI (match_dup 2) (match_dup 1)))]
1619 "TARGET_ARM && arm_arch6 && optimize_size"
3ef90e77 1620 "muls%?\\t%0, %2, %1"
cffb2a26 1621 [(set_attr "conds" "set")
9da0ec36 1622 (set_attr "type" "muls")]
cffb2a26 1623)
9c08d1fa 1624
f7fbdd4a 1625(define_insn "*mulsi_compare0_scratch"
bd5b4116 1626 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1627 (compare:CC_NOOV (mult:SI
1628 (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1629 (match_operand:SI 1 "s_register_operand" "%0,r"))
9c08d1fa 1630 (const_int 0)))
1631 (clobber (match_scratch:SI 0 "=&r,&r"))]
58d7d654 1632 "TARGET_ARM && !arm_arch6"
3ef90e77 1633 "muls%?\\t%0, %2, %1"
58d7d654 1634 [(set_attr "conds" "set")
9da0ec36 1635 (set_attr "type" "muls")]
58d7d654 1636)
1637
1638(define_insn "*mulsi_compare0_scratch_v6"
1639 [(set (reg:CC_NOOV CC_REGNUM)
1640 (compare:CC_NOOV (mult:SI
1641 (match_operand:SI 2 "s_register_operand" "r")
1642 (match_operand:SI 1 "s_register_operand" "r"))
1643 (const_int 0)))
1644 (clobber (match_scratch:SI 0 "=r"))]
1645 "TARGET_ARM && arm_arch6 && optimize_size"
3ef90e77 1646 "muls%?\\t%0, %2, %1"
cffb2a26 1647 [(set_attr "conds" "set")
9da0ec36 1648 (set_attr "type" "muls")]
cffb2a26 1649)
9c08d1fa 1650
b11cae9e 1651;; Unnamed templates to match MLA instruction.
1652
f7fbdd4a 1653(define_insn "*mulsi3addsi"
9c08d1fa 1654 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
c8f69309 1655 (plus:SI
9c08d1fa 1656 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1657 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1658 (match_operand:SI 3 "s_register_operand" "r,r,0,0")))]
58d7d654 1659 "TARGET_32BIT && !arm_arch6"
1660 "mla%?\\t%0, %2, %1, %3"
9da0ec36 1661 [(set_attr "type" "mla")
58d7d654 1662 (set_attr "predicable" "yes")]
1663)
1664
1665(define_insn "*mulsi3addsi_v6"
1666 [(set (match_operand:SI 0 "s_register_operand" "=r")
1667 (plus:SI
1668 (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1669 (match_operand:SI 1 "s_register_operand" "r"))
1670 (match_operand:SI 3 "s_register_operand" "r")))]
1671 "TARGET_32BIT && arm_arch6"
f7fbdd4a 1672 "mla%?\\t%0, %2, %1, %3"
9da0ec36 1673 [(set_attr "type" "mla")
d952d547 1674 (set_attr "predicable" "yes")
1675 (set_attr "predicable_short_it" "no")]
0d66636f 1676)
b11cae9e 1677
f7fbdd4a 1678(define_insn "*mulsi3addsi_compare0"
bd5b4116 1679 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1680 (compare:CC_NOOV
1681 (plus:SI (mult:SI
1682 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1683 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1684 (match_operand:SI 3 "s_register_operand" "r,r,0,0"))
215b30b3 1685 (const_int 0)))
9c08d1fa 1686 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1687 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1688 (match_dup 3)))]
58d7d654 1689 "TARGET_ARM && arm_arch6"
3ef90e77 1690 "mlas%?\\t%0, %2, %1, %3"
58d7d654 1691 [(set_attr "conds" "set")
9da0ec36 1692 (set_attr "type" "mlas")]
58d7d654 1693)
1694
1695(define_insn "*mulsi3addsi_compare0_v6"
1696 [(set (reg:CC_NOOV CC_REGNUM)
1697 (compare:CC_NOOV
1698 (plus:SI (mult:SI
1699 (match_operand:SI 2 "s_register_operand" "r")
1700 (match_operand:SI 1 "s_register_operand" "r"))
1701 (match_operand:SI 3 "s_register_operand" "r"))
1702 (const_int 0)))
1703 (set (match_operand:SI 0 "s_register_operand" "=r")
1704 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1705 (match_dup 3)))]
1706 "TARGET_ARM && arm_arch6 && optimize_size"
3ef90e77 1707 "mlas%?\\t%0, %2, %1, %3"
0d66636f 1708 [(set_attr "conds" "set")
9da0ec36 1709 (set_attr "type" "mlas")]
0d66636f 1710)
9c08d1fa 1711
f7fbdd4a 1712(define_insn "*mulsi3addsi_compare0_scratch"
bd5b4116 1713 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1714 (compare:CC_NOOV
1715 (plus:SI (mult:SI
1716 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1717 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
215b30b3 1718 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1719 (const_int 0)))
9c08d1fa 1720 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
58d7d654 1721 "TARGET_ARM && !arm_arch6"
3ef90e77 1722 "mlas%?\\t%0, %2, %1, %3"
58d7d654 1723 [(set_attr "conds" "set")
9da0ec36 1724 (set_attr "type" "mlas")]
58d7d654 1725)
1726
1727(define_insn "*mulsi3addsi_compare0_scratch_v6"
1728 [(set (reg:CC_NOOV CC_REGNUM)
1729 (compare:CC_NOOV
1730 (plus:SI (mult:SI
1731 (match_operand:SI 2 "s_register_operand" "r")
1732 (match_operand:SI 1 "s_register_operand" "r"))
1733 (match_operand:SI 3 "s_register_operand" "r"))
1734 (const_int 0)))
1735 (clobber (match_scratch:SI 0 "=r"))]
1736 "TARGET_ARM && arm_arch6 && optimize_size"
3ef90e77 1737 "mlas%?\\t%0, %2, %1, %3"
cffb2a26 1738 [(set_attr "conds" "set")
9da0ec36 1739 (set_attr "type" "mlas")]
cffb2a26 1740)
f7fbdd4a 1741
89545238 1742(define_insn "*mulsi3subsi"
1743 [(set (match_operand:SI 0 "s_register_operand" "=r")
1744 (minus:SI
1745 (match_operand:SI 3 "s_register_operand" "r")
1746 (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1747 (match_operand:SI 1 "s_register_operand" "r"))))]
1748 "TARGET_32BIT && arm_arch_thumb2"
1749 "mls%?\\t%0, %2, %1, %3"
9da0ec36 1750 [(set_attr "type" "mla")
d952d547 1751 (set_attr "predicable" "yes")
1752 (set_attr "predicable_short_it" "no")]
89545238 1753)
1754
5cdca009 1755(define_expand "maddsidi4"
1756 [(set (match_operand:DI 0 "s_register_operand" "")
1757 (plus:DI
1758 (mult:DI
1759 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1760 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1761 (match_operand:DI 3 "s_register_operand" "")))]
1762 "TARGET_32BIT && arm_arch3m"
1763 "")
82b85d08 1764
1765(define_insn "*mulsidi3adddi"
fe8dbf85 1766 [(set (match_operand:DI 0 "s_register_operand" "=&r")
82b85d08 1767 (plus:DI
215b30b3 1768 (mult:DI
fe8dbf85 1769 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1770 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1771 (match_operand:DI 1 "s_register_operand" "0")))]
58d7d654 1772 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1773 "smlal%?\\t%Q0, %R0, %3, %2"
9da0ec36 1774 [(set_attr "type" "smlal")
58d7d654 1775 (set_attr "predicable" "yes")]
1776)
1777
1778(define_insn "*mulsidi3adddi_v6"
1779 [(set (match_operand:DI 0 "s_register_operand" "=r")
1780 (plus:DI
1781 (mult:DI
1782 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1783 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1784 (match_operand:DI 1 "s_register_operand" "0")))]
1785 "TARGET_32BIT && arm_arch6"
fe8dbf85 1786 "smlal%?\\t%Q0, %R0, %3, %2"
9da0ec36 1787 [(set_attr "type" "smlal")
d952d547 1788 (set_attr "predicable" "yes")
1789 (set_attr "predicable_short_it" "no")]
0d66636f 1790)
82b85d08 1791
957788b0 1792;; 32x32->64 widening multiply.
1793;; As with mulsi3, the only difference between the v3-5 and v6+
1794;; versions of these patterns is the requirement that the output not
1795;; overlap the inputs, but that still means we have to have a named
1796;; expander and two different starred insns.
1797
1798(define_expand "mulsidi3"
1799 [(set (match_operand:DI 0 "s_register_operand" "")
1800 (mult:DI
1801 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1802 (sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1803 "TARGET_32BIT && arm_arch3m"
1804 ""
1805)
1806
1807(define_insn "*mulsidi3_nov6"
f7fbdd4a 1808 [(set (match_operand:DI 0 "s_register_operand" "=&r")
215b30b3 1809 (mult:DI
1810 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1811 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
58d7d654 1812 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1813 "smull%?\\t%Q0, %R0, %1, %2"
9da0ec36 1814 [(set_attr "type" "smull")
58d7d654 1815 (set_attr "predicable" "yes")]
1816)
1817
957788b0 1818(define_insn "*mulsidi3_v6"
58d7d654 1819 [(set (match_operand:DI 0 "s_register_operand" "=r")
1820 (mult:DI
1821 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1822 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1823 "TARGET_32BIT && arm_arch6"
97499065 1824 "smull%?\\t%Q0, %R0, %1, %2"
9da0ec36 1825 [(set_attr "type" "smull")
d952d547 1826 (set_attr "predicable" "yes")
1827 (set_attr "predicable_short_it" "no")]
0d66636f 1828)
f7fbdd4a 1829
957788b0 1830(define_expand "umulsidi3"
1831 [(set (match_operand:DI 0 "s_register_operand" "")
1832 (mult:DI
1833 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1834 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1835 "TARGET_32BIT && arm_arch3m"
1836 ""
1837)
1838
1839(define_insn "*umulsidi3_nov6"
f7fbdd4a 1840 [(set (match_operand:DI 0 "s_register_operand" "=&r")
215b30b3 1841 (mult:DI
1842 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1843 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
58d7d654 1844 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1845 "umull%?\\t%Q0, %R0, %1, %2"
9da0ec36 1846 [(set_attr "type" "umull")
58d7d654 1847 (set_attr "predicable" "yes")]
1848)
1849
957788b0 1850(define_insn "*umulsidi3_v6"
58d7d654 1851 [(set (match_operand:DI 0 "s_register_operand" "=r")
1852 (mult:DI
1853 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1854 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1855 "TARGET_32BIT && arm_arch6"
97499065 1856 "umull%?\\t%Q0, %R0, %1, %2"
9da0ec36 1857 [(set_attr "type" "umull")
d952d547 1858 (set_attr "predicable" "yes")
1859 (set_attr "predicable_short_it" "no")]
0d66636f 1860)
b11cae9e 1861
5cdca009 1862(define_expand "umaddsidi4"
1863 [(set (match_operand:DI 0 "s_register_operand" "")
1864 (plus:DI
1865 (mult:DI
1866 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1867 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1868 (match_operand:DI 3 "s_register_operand" "")))]
1869 "TARGET_32BIT && arm_arch3m"
1870 "")
82b85d08 1871
1872(define_insn "*umulsidi3adddi"
8ead09f9 1873 [(set (match_operand:DI 0 "s_register_operand" "=&r")
82b85d08 1874 (plus:DI
215b30b3 1875 (mult:DI
fe8dbf85 1876 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1877 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1878 (match_operand:DI 1 "s_register_operand" "0")))]
58d7d654 1879 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1880 "umlal%?\\t%Q0, %R0, %3, %2"
9da0ec36 1881 [(set_attr "type" "umlal")
58d7d654 1882 (set_attr "predicable" "yes")]
1883)
1884
1885(define_insn "*umulsidi3adddi_v6"
1886 [(set (match_operand:DI 0 "s_register_operand" "=r")
1887 (plus:DI
1888 (mult:DI
1889 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1890 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1891 (match_operand:DI 1 "s_register_operand" "0")))]
1892 "TARGET_32BIT && arm_arch6"
fe8dbf85 1893 "umlal%?\\t%Q0, %R0, %3, %2"
9da0ec36 1894 [(set_attr "type" "umlal")
d952d547 1895 (set_attr "predicable" "yes")
1896 (set_attr "predicable_short_it" "no")]
0d66636f 1897)
82b85d08 1898
957788b0 1899(define_expand "smulsi3_highpart"
1900 [(parallel
1901 [(set (match_operand:SI 0 "s_register_operand" "")
1902 (truncate:SI
1903 (lshiftrt:DI
1904 (mult:DI
1905 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1906 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1907 (const_int 32))))
1908 (clobber (match_scratch:SI 3 ""))])]
1909 "TARGET_32BIT && arm_arch3m"
1910 ""
1911)
1912
1913(define_insn "*smulsi3_highpart_nov6"
f082f1c4 1914 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1915 (truncate:SI
1916 (lshiftrt:DI
215b30b3 1917 (mult:DI
e5fea38e 1918 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
215b30b3 1919 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
f082f1c4 1920 (const_int 32))))
1921 (clobber (match_scratch:SI 3 "=&r,&r"))]
58d7d654 1922 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1923 "smull%?\\t%3, %0, %2, %1"
9da0ec36 1924 [(set_attr "type" "smull")
58d7d654 1925 (set_attr "predicable" "yes")]
1926)
1927
957788b0 1928(define_insn "*smulsi3_highpart_v6"
58d7d654 1929 [(set (match_operand:SI 0 "s_register_operand" "=r")
1930 (truncate:SI
1931 (lshiftrt:DI
1932 (mult:DI
1933 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1934 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1935 (const_int 32))))
1936 (clobber (match_scratch:SI 3 "=r"))]
1937 "TARGET_32BIT && arm_arch6"
f082f1c4 1938 "smull%?\\t%3, %0, %2, %1"
9da0ec36 1939 [(set_attr "type" "smull")
d952d547 1940 (set_attr "predicable" "yes")
1941 (set_attr "predicable_short_it" "no")]
cffb2a26 1942)
f082f1c4 1943
957788b0 1944(define_expand "umulsi3_highpart"
1945 [(parallel
1946 [(set (match_operand:SI 0 "s_register_operand" "")
1947 (truncate:SI
1948 (lshiftrt:DI
1949 (mult:DI
1950 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1951 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1952 (const_int 32))))
1953 (clobber (match_scratch:SI 3 ""))])]
1954 "TARGET_32BIT && arm_arch3m"
1955 ""
1956)
1957
1958(define_insn "*umulsi3_highpart_nov6"
f082f1c4 1959 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1960 (truncate:SI
1961 (lshiftrt:DI
215b30b3 1962 (mult:DI
e5fea38e 1963 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
215b30b3 1964 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
f082f1c4 1965 (const_int 32))))
1966 (clobber (match_scratch:SI 3 "=&r,&r"))]
58d7d654 1967 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1968 "umull%?\\t%3, %0, %2, %1"
9da0ec36 1969 [(set_attr "type" "umull")
58d7d654 1970 (set_attr "predicable" "yes")]
1971)
1972
957788b0 1973(define_insn "*umulsi3_highpart_v6"
58d7d654 1974 [(set (match_operand:SI 0 "s_register_operand" "=r")
1975 (truncate:SI
1976 (lshiftrt:DI
1977 (mult:DI
1978 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1979 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1980 (const_int 32))))
1981 (clobber (match_scratch:SI 3 "=r"))]
1982 "TARGET_32BIT && arm_arch6"
f082f1c4 1983 "umull%?\\t%3, %0, %2, %1"
9da0ec36 1984 [(set_attr "type" "umull")
d952d547 1985 (set_attr "predicable" "yes")
1986 (set_attr "predicable_short_it" "no")]
cffb2a26 1987)
f082f1c4 1988
331beb1a 1989(define_insn "mulhisi3"
1990 [(set (match_operand:SI 0 "s_register_operand" "=r")
1991 (mult:SI (sign_extend:SI
1992 (match_operand:HI 1 "s_register_operand" "%r"))
1993 (sign_extend:SI
1994 (match_operand:HI 2 "s_register_operand" "r"))))]
25f905c2 1995 "TARGET_DSP_MULTIPLY"
61a2d04c 1996 "smulbb%?\\t%0, %1, %2"
9da0ec36 1997 [(set_attr "type" "smulxy")
fec538d9 1998 (set_attr "predicable" "yes")]
1999)
2000
2001(define_insn "*mulhisi3tb"
2002 [(set (match_operand:SI 0 "s_register_operand" "=r")
2003 (mult:SI (ashiftrt:SI
2004 (match_operand:SI 1 "s_register_operand" "r")
2005 (const_int 16))
2006 (sign_extend:SI
2007 (match_operand:HI 2 "s_register_operand" "r"))))]
25f905c2 2008 "TARGET_DSP_MULTIPLY"
fec538d9 2009 "smultb%?\\t%0, %1, %2"
9da0ec36 2010 [(set_attr "type" "smulxy")
d952d547 2011 (set_attr "predicable" "yes")
2012 (set_attr "predicable_short_it" "no")]
fec538d9 2013)
2014
2015(define_insn "*mulhisi3bt"
2016 [(set (match_operand:SI 0 "s_register_operand" "=r")
2017 (mult:SI (sign_extend:SI
2018 (match_operand:HI 1 "s_register_operand" "r"))
2019 (ashiftrt:SI
2020 (match_operand:SI 2 "s_register_operand" "r")
2021 (const_int 16))))]
25f905c2 2022 "TARGET_DSP_MULTIPLY"
fec538d9 2023 "smulbt%?\\t%0, %1, %2"
9da0ec36 2024 [(set_attr "type" "smulxy")
d952d547 2025 (set_attr "predicable" "yes")
2026 (set_attr "predicable_short_it" "no")]
fec538d9 2027)
2028
2029(define_insn "*mulhisi3tt"
2030 [(set (match_operand:SI 0 "s_register_operand" "=r")
2031 (mult:SI (ashiftrt:SI
2032 (match_operand:SI 1 "s_register_operand" "r")
2033 (const_int 16))
2034 (ashiftrt:SI
2035 (match_operand:SI 2 "s_register_operand" "r")
2036 (const_int 16))))]
25f905c2 2037 "TARGET_DSP_MULTIPLY"
fec538d9 2038 "smultt%?\\t%0, %1, %2"
9da0ec36 2039 [(set_attr "type" "smulxy")
d952d547 2040 (set_attr "predicable" "yes")
2041 (set_attr "predicable_short_it" "no")]
331beb1a 2042)
2043
5cdca009 2044(define_insn "maddhisi4"
331beb1a 2045 [(set (match_operand:SI 0 "s_register_operand" "=r")
cfa6c608 2046 (plus:SI (mult:SI (sign_extend:SI
2047 (match_operand:HI 1 "s_register_operand" "r"))
331beb1a 2048 (sign_extend:SI
cfa6c608 2049 (match_operand:HI 2 "s_register_operand" "r")))
2050 (match_operand:SI 3 "s_register_operand" "r")))]
25f905c2 2051 "TARGET_DSP_MULTIPLY"
5cdca009 2052 "smlabb%?\\t%0, %1, %2, %3"
9da0ec36 2053 [(set_attr "type" "smlaxy")
d952d547 2054 (set_attr "predicable" "yes")
2055 (set_attr "predicable_short_it" "no")]
331beb1a 2056)
2057
9a92f368 2058;; Note: there is no maddhisi4ibt because this one is canonical form
2059(define_insn "*maddhisi4tb"
2060 [(set (match_operand:SI 0 "s_register_operand" "=r")
2061 (plus:SI (mult:SI (ashiftrt:SI
2062 (match_operand:SI 1 "s_register_operand" "r")
2063 (const_int 16))
2064 (sign_extend:SI
2065 (match_operand:HI 2 "s_register_operand" "r")))
2066 (match_operand:SI 3 "s_register_operand" "r")))]
2067 "TARGET_DSP_MULTIPLY"
2068 "smlatb%?\\t%0, %1, %2, %3"
9da0ec36 2069 [(set_attr "type" "smlaxy")
d952d547 2070 (set_attr "predicable" "yes")
2071 (set_attr "predicable_short_it" "no")]
9a92f368 2072)
2073
2074(define_insn "*maddhisi4tt"
2075 [(set (match_operand:SI 0 "s_register_operand" "=r")
2076 (plus:SI (mult:SI (ashiftrt:SI
2077 (match_operand:SI 1 "s_register_operand" "r")
2078 (const_int 16))
2079 (ashiftrt:SI
2080 (match_operand:SI 2 "s_register_operand" "r")
2081 (const_int 16)))
2082 (match_operand:SI 3 "s_register_operand" "r")))]
2083 "TARGET_DSP_MULTIPLY"
2084 "smlatt%?\\t%0, %1, %2, %3"
9da0ec36 2085 [(set_attr "type" "smlaxy")
d952d547 2086 (set_attr "predicable" "yes")
2087 (set_attr "predicable_short_it" "no")]
9a92f368 2088)
2089
aff5fb4d 2090(define_insn "maddhidi4"
331beb1a 2091 [(set (match_operand:DI 0 "s_register_operand" "=r")
2092 (plus:DI
331beb1a 2093 (mult:DI (sign_extend:DI
d952d547 2094 (match_operand:HI 1 "s_register_operand" "r"))
331beb1a 2095 (sign_extend:DI
cfa6c608 2096 (match_operand:HI 2 "s_register_operand" "r")))
2097 (match_operand:DI 3 "s_register_operand" "0")))]
25f905c2 2098 "TARGET_DSP_MULTIPLY"
5cdca009 2099 "smlalbb%?\\t%Q0, %R0, %1, %2"
9da0ec36 2100 [(set_attr "type" "smlalxy")
d952d547 2101 (set_attr "predicable" "yes")
2102 (set_attr "predicable_short_it" "no")])
331beb1a 2103
9a92f368 2104;; Note: there is no maddhidi4ibt because this one is canonical form
2105(define_insn "*maddhidi4tb"
2106 [(set (match_operand:DI 0 "s_register_operand" "=r")
2107 (plus:DI
2108 (mult:DI (sign_extend:DI
2109 (ashiftrt:SI
2110 (match_operand:SI 1 "s_register_operand" "r")
2111 (const_int 16)))
2112 (sign_extend:DI
2113 (match_operand:HI 2 "s_register_operand" "r")))
2114 (match_operand:DI 3 "s_register_operand" "0")))]
2115 "TARGET_DSP_MULTIPLY"
2116 "smlaltb%?\\t%Q0, %R0, %1, %2"
9da0ec36 2117 [(set_attr "type" "smlalxy")
d952d547 2118 (set_attr "predicable" "yes")
2119 (set_attr "predicable_short_it" "no")])
9a92f368 2120
2121(define_insn "*maddhidi4tt"
2122 [(set (match_operand:DI 0 "s_register_operand" "=r")
2123 (plus:DI
2124 (mult:DI (sign_extend:DI
2125 (ashiftrt:SI
2126 (match_operand:SI 1 "s_register_operand" "r")
2127 (const_int 16)))
2128 (sign_extend:DI
2129 (ashiftrt:SI
2130 (match_operand:SI 2 "s_register_operand" "r")
2131 (const_int 16))))
2132 (match_operand:DI 3 "s_register_operand" "0")))]
2133 "TARGET_DSP_MULTIPLY"
2134 "smlaltt%?\\t%Q0, %R0, %1, %2"
9da0ec36 2135 [(set_attr "type" "smlalxy")
d952d547 2136 (set_attr "predicable" "yes")
2137 (set_attr "predicable_short_it" "no")])
9a92f368 2138
604f3a0a 2139(define_expand "mulsf3"
2140 [(set (match_operand:SF 0 "s_register_operand" "")
2141 (mult:SF (match_operand:SF 1 "s_register_operand" "")
d86c91f6 2142 (match_operand:SF 2 "s_register_operand" "")))]
25f905c2 2143 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 2144 "
604f3a0a 2145")
2146
604f3a0a 2147(define_expand "muldf3"
2148 [(set (match_operand:DF 0 "s_register_operand" "")
2149 (mult:DF (match_operand:DF 1 "s_register_operand" "")
d86c91f6 2150 (match_operand:DF 2 "s_register_operand" "")))]
a50d7267 2151 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 2152 "
604f3a0a 2153")
b11cae9e 2154\f
2155;; Division insns
2156
7db9af5d 2157(define_expand "divsf3"
2158 [(set (match_operand:SF 0 "s_register_operand" "")
d86c91f6 2159 (div:SF (match_operand:SF 1 "s_register_operand" "")
2160 (match_operand:SF 2 "s_register_operand" "")))]
d7216193 2161 "TARGET_32BIT && TARGET_HARD_FLOAT"
7db9af5d 2162 "")
9c08d1fa 2163
7db9af5d 2164(define_expand "divdf3"
2165 [(set (match_operand:DF 0 "s_register_operand" "")
d86c91f6 2166 (div:DF (match_operand:DF 1 "s_register_operand" "")
2167 (match_operand:DF 2 "s_register_operand" "")))]
994606f8 2168 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
7db9af5d 2169 "")
b11cae9e 2170\f
2171;; Boolean and,ior,xor insns
2172
f6ebffac 2173;; Split up double word logical operations
2174
2175;; Split up simple DImode logical operations. Simply perform the logical
2176;; operation on the upper and lower halves of the registers.
2177(define_split
2178 [(set (match_operand:DI 0 "s_register_operand" "")
2179 (match_operator:DI 6 "logical_binary_operator"
2180 [(match_operand:DI 1 "s_register_operand" "")
2181 (match_operand:DI 2 "s_register_operand" "")]))]
25f905c2 2182 "TARGET_32BIT && reload_completed
e2669ea7 2183 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))
25f905c2 2184 && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
f6ebffac 2185 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
2186 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
2187 "
215b30b3 2188 {
2189 operands[3] = gen_highpart (SImode, operands[0]);
2190 operands[0] = gen_lowpart (SImode, operands[0]);
2191 operands[4] = gen_highpart (SImode, operands[1]);
2192 operands[1] = gen_lowpart (SImode, operands[1]);
2193 operands[5] = gen_highpart (SImode, operands[2]);
2194 operands[2] = gen_lowpart (SImode, operands[2]);
2195 }"
2196)
f6ebffac 2197
f6ebffac 2198(define_split
2199 [(set (match_operand:DI 0 "s_register_operand" "")
2200 (match_operator:DI 6 "logical_binary_operator"
2201 [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
2202 (match_operand:DI 1 "s_register_operand" "")]))]
25f905c2 2203 "TARGET_32BIT && reload_completed"
f6ebffac 2204 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
2205 (set (match_dup 3) (match_op_dup:SI 6
2206 [(ashiftrt:SI (match_dup 2) (const_int 31))
2207 (match_dup 4)]))]
2208 "
215b30b3 2209 {
2210 operands[3] = gen_highpart (SImode, operands[0]);
2211 operands[0] = gen_lowpart (SImode, operands[0]);
2212 operands[4] = gen_highpart (SImode, operands[1]);
2213 operands[1] = gen_lowpart (SImode, operands[1]);
2214 operands[5] = gen_highpart (SImode, operands[2]);
2215 operands[2] = gen_lowpart (SImode, operands[2]);
2216 }"
2217)
f6ebffac 2218
f6ebffac 2219;; The zero extend of operand 2 means we can just copy the high part of
2220;; operand1 into operand0.
2221(define_split
2222 [(set (match_operand:DI 0 "s_register_operand" "")
2223 (ior:DI
2224 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
2225 (match_operand:DI 1 "s_register_operand" "")))]
25f905c2 2226 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
f6ebffac 2227 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
2228 (set (match_dup 3) (match_dup 4))]
2229 "
215b30b3 2230 {
2231 operands[4] = gen_highpart (SImode, operands[1]);
2232 operands[3] = gen_highpart (SImode, operands[0]);
2233 operands[0] = gen_lowpart (SImode, operands[0]);
2234 operands[1] = gen_lowpart (SImode, operands[1]);
2235 }"
2236)
f6ebffac 2237
2238;; The zero extend of operand 2 means we can just copy the high part of
2239;; operand1 into operand0.
2240(define_split
2241 [(set (match_operand:DI 0 "s_register_operand" "")
2242 (xor:DI
2243 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
2244 (match_operand:DI 1 "s_register_operand" "")))]
25f905c2 2245 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
f6ebffac 2246 [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
2247 (set (match_dup 3) (match_dup 4))]
2248 "
215b30b3 2249 {
2250 operands[4] = gen_highpart (SImode, operands[1]);
2251 operands[3] = gen_highpart (SImode, operands[0]);
2252 operands[0] = gen_lowpart (SImode, operands[0]);
2253 operands[1] = gen_lowpart (SImode, operands[1]);
2254 }"
2255)
f6ebffac 2256
e2669ea7 2257(define_expand "anddi3"
2258 [(set (match_operand:DI 0 "s_register_operand" "")
2259 (and:DI (match_operand:DI 1 "s_register_operand" "")
2260 (match_operand:DI 2 "neon_inv_logic_op2" "")))]
2261 "TARGET_32BIT"
2262 ""
2263)
2264
f6bbdcf6 2265(define_insn_and_split "*anddi3_insn"
0a314dcd 2266 [(set (match_operand:DI 0 "s_register_operand" "=w,w ,&r,&r,&r,&r,?w,?w")
2267 (and:DI (match_operand:DI 1 "s_register_operand" "%w,0 ,0 ,r ,0 ,r ,w ,0")
2268 (match_operand:DI 2 "arm_anddi_operand_neon" "w ,DL,r ,r ,De,De,w ,DL")))]
f6bbdcf6 2269 "TARGET_32BIT && !TARGET_IWMMXT"
2270{
2271 switch (which_alternative)
2272 {
0a314dcd 2273 case 0: /* fall through */
2274 case 6: return "vand\t%P0, %P1, %P2";
2275 case 1: /* fall through */
2276 case 7: return neon_output_logic_immediate ("vand", &operands[2],
2277 DImode, 1, VALID_NEON_QREG_MODE (DImode));
f6bbdcf6 2278 case 2:
0a314dcd 2279 case 3:
2280 case 4:
f6bbdcf6 2281 case 5: /* fall through */
0a314dcd 2282 return "#";
f6bbdcf6 2283 default: gcc_unreachable ();
2284 }
2285}
0a314dcd 2286 "TARGET_32BIT && !TARGET_IWMMXT && reload_completed
2287 && !(IS_VFP_REGNUM (REGNO (operands[0])))"
f6bbdcf6 2288 [(set (match_dup 3) (match_dup 4))
2289 (set (match_dup 5) (match_dup 6))]
2290 "
2291 {
2292 operands[3] = gen_lowpart (SImode, operands[0]);
2293 operands[5] = gen_highpart (SImode, operands[0]);
2294
2295 operands[4] = simplify_gen_binary (AND, SImode,
2296 gen_lowpart (SImode, operands[1]),
2297 gen_lowpart (SImode, operands[2]));
2298 operands[6] = simplify_gen_binary (AND, SImode,
2299 gen_highpart (SImode, operands[1]),
2300 gen_highpart_mode (SImode, DImode, operands[2]));
2301
2302 }"
32093010 2303 [(set_attr "type" "neon_logic,neon_logic,multiple,multiple,\
2304 multiple,multiple,neon_logic,neon_logic")
0a314dcd 2305 (set_attr "arch" "neon_for_64bits,neon_for_64bits,*,*,*,*,
f6bbdcf6 2306 avoid_neon_for_64bits,avoid_neon_for_64bits")
0a314dcd 2307 (set_attr "length" "*,*,8,8,8,8,*,*")
2308 ]
215b30b3 2309)
b11cae9e 2310
a0f94409 2311(define_insn_and_split "*anddi_zesidi_di"
9c08d1fa 2312 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2313 (and:DI (zero_extend:DI
2314 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 2315 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2316 "TARGET_32BIT"
f6ebffac 2317 "#"
25f905c2 2318 "TARGET_32BIT && reload_completed"
a0f94409 2319 ; The zero extend of operand 2 clears the high word of the output
2320 ; operand.
2321 [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
2322 (set (match_dup 3) (const_int 0))]
2323 "
2324 {
2325 operands[3] = gen_highpart (SImode, operands[0]);
2326 operands[0] = gen_lowpart (SImode, operands[0]);
2327 operands[1] = gen_lowpart (SImode, operands[1]);
2328 }"
1b7da4ac 2329 [(set_attr "length" "8")
2330 (set_attr "type" "multiple")]
215b30b3 2331)
b11cae9e 2332
f7fbdd4a 2333(define_insn "*anddi_sesdi_di"
cffb2a26 2334 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 2335 (and:DI (sign_extend:DI
2336 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 2337 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2338 "TARGET_32BIT"
f6ebffac 2339 "#"
1b7da4ac 2340 [(set_attr "length" "8")
2341 (set_attr "type" "multiple")]
cffb2a26 2342)
b11cae9e 2343
87b22bf7 2344(define_expand "andsi3"
cffb2a26 2345 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2346 (and:SI (match_operand:SI 1 "s_register_operand" "")
2347 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 2348 "TARGET_EITHER"
87b22bf7 2349 "
25f905c2 2350 if (TARGET_32BIT)
87b22bf7 2351 {
0438d37f 2352 if (CONST_INT_P (operands[2]))
cffb2a26 2353 {
47b5b27b 2354 if (INTVAL (operands[2]) == 255 && arm_arch6)
2355 {
2356 operands[1] = convert_to_mode (QImode, operands[1], 1);
2357 emit_insn (gen_thumb2_zero_extendqisi2_v6 (operands[0],
2358 operands[1]));
17202aa5 2359 DONE;
47b5b27b 2360 }
17202aa5 2361 else if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[2]), AND))
2362 operands[2] = force_reg (SImode, operands[2]);
47b5b27b 2363 else
17202aa5 2364 {
2365 arm_split_constant (AND, SImode, NULL_RTX,
2366 INTVAL (operands[2]), operands[0],
2367 operands[1],
2368 optimize && can_create_pseudo_p ());
615caa51 2369
17202aa5 2370 DONE;
2371 }
cffb2a26 2372 }
87b22bf7 2373 }
25f905c2 2374 else /* TARGET_THUMB1 */
cffb2a26 2375 {
0438d37f 2376 if (!CONST_INT_P (operands[2]))
923ffadb 2377 {
2378 rtx tmp = force_reg (SImode, operands[2]);
2379 if (rtx_equal_p (operands[0], operands[1]))
2380 operands[2] = tmp;
2381 else
2382 {
2383 operands[2] = operands[1];
2384 operands[1] = tmp;
2385 }
2386 }
cffb2a26 2387 else
2388 {
2389 int i;
2390
215b30b3 2391 if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
cffb2a26 2392 {
215b30b3 2393 operands[2] = force_reg (SImode,
2394 GEN_INT (~INTVAL (operands[2])));
cffb2a26 2395
747b7458 2396 emit_insn (gen_thumb1_bicsi3 (operands[0], operands[2], operands[1]));
cffb2a26 2397
2398 DONE;
2399 }
87b22bf7 2400
cffb2a26 2401 for (i = 9; i <= 31; i++)
2402 {
db2faf44 2403 if ((HOST_WIDE_INT_1 << i) - 1 == INTVAL (operands[2]))
cffb2a26 2404 {
2405 emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
2406 const0_rtx));
2407 DONE;
2408 }
db2faf44 2409 else if ((HOST_WIDE_INT_1 << i) - 1
215b30b3 2410 == ~INTVAL (operands[2]))
cffb2a26 2411 {
2412 rtx shift = GEN_INT (i);
2413 rtx reg = gen_reg_rtx (SImode);
2414
2415 emit_insn (gen_lshrsi3 (reg, operands[1], shift));
2416 emit_insn (gen_ashlsi3 (operands[0], reg, shift));
2417
2418 DONE;
2419 }
2420 }
2421
2422 operands[2] = force_reg (SImode, operands[2]);
2423 }
215b30b3 2424 }
2425 "
cffb2a26 2426)
2427
25f905c2 2428; ??? Check split length for Thumb-2
a0f94409 2429(define_insn_and_split "*arm_andsi3_insn"
29e234a3 2430 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r,r,r")
2431 (and:SI (match_operand:SI 1 "s_register_operand" "%r,0,r,r,r")
2432 (match_operand:SI 2 "reg_or_int_operand" "I,l,K,r,?n")))]
25f905c2 2433 "TARGET_32BIT"
5565501b 2434 "@
29e234a3 2435 and%?\\t%0, %1, %2
5565501b 2436 and%?\\t%0, %1, %2
87b22bf7 2437 bic%?\\t%0, %1, #%B2
65f68e55 2438 and%?\\t%0, %1, %2
87b22bf7 2439 #"
25f905c2 2440 "TARGET_32BIT
0438d37f 2441 && CONST_INT_P (operands[2])
a0f94409 2442 && !(const_ok_for_arm (INTVAL (operands[2]))
2443 || const_ok_for_arm (~INTVAL (operands[2])))"
2444 [(clobber (const_int 0))]
2445 "
96f57e36 2446 arm_split_constant (AND, SImode, curr_insn,
2447 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 2448 DONE;
2449 "
29e234a3 2450 [(set_attr "length" "4,4,4,4,16")
65f68e55 2451 (set_attr "predicable" "yes")
29e234a3 2452 (set_attr "predicable_short_it" "no,yes,no,no,no")
d82e788e 2453 (set_attr "type" "logic_imm,logic_imm,logic_reg,logic_reg,logic_imm")]
cffb2a26 2454)
2455
f7fbdd4a 2456(define_insn "*andsi3_compare0"
bd5b4116 2457 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 2458 (compare:CC_NOOV
65f68e55 2459 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
2460 (match_operand:SI 2 "arm_not_operand" "I,K,r"))
5565501b 2461 (const_int 0)))
65f68e55 2462 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9c08d1fa 2463 (and:SI (match_dup 1) (match_dup 2)))]
25f905c2 2464 "TARGET_32BIT"
5565501b 2465 "@
3ef90e77 2466 ands%?\\t%0, %1, %2
2467 bics%?\\t%0, %1, #%B2
2468 ands%?\\t%0, %1, %2"
65f68e55 2469 [(set_attr "conds" "set")
d82e788e 2470 (set_attr "type" "logics_imm,logics_imm,logics_reg")]
cffb2a26 2471)
9c08d1fa 2472
f7fbdd4a 2473(define_insn "*andsi3_compare0_scratch"
bd5b4116 2474 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 2475 (compare:CC_NOOV
65f68e55 2476 (and:SI (match_operand:SI 0 "s_register_operand" "r,r,r")
2477 (match_operand:SI 1 "arm_not_operand" "I,K,r"))
5565501b 2478 (const_int 0)))
65f68e55 2479 (clobber (match_scratch:SI 2 "=X,r,X"))]
25f905c2 2480 "TARGET_32BIT"
5565501b 2481 "@
2482 tst%?\\t%0, %1
3ef90e77 2483 bics%?\\t%2, %0, #%B1
65f68e55 2484 tst%?\\t%0, %1"
2485 [(set_attr "conds" "set")
d82e788e 2486 (set_attr "type" "logics_imm,logics_imm,logics_reg")]
0d66636f 2487)
9c08d1fa 2488
f7fbdd4a 2489(define_insn "*zeroextractsi_compare0_scratch"
bd5b4116 2490 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2491 (compare:CC_NOOV (zero_extract:SI
2492 (match_operand:SI 0 "s_register_operand" "r")
d952d547 2493 (match_operand 1 "const_int_operand" "n")
206ee9a2 2494 (match_operand 2 "const_int_operand" "n"))
9c08d1fa 2495 (const_int 0)))]
25f905c2 2496 "TARGET_32BIT
cffb2a26 2497 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
2498 && INTVAL (operands[1]) > 0
2499 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
2500 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
9c08d1fa 2501 "*
5c49a439 2502 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
2503 << INTVAL (operands[2]));
40dbec34 2504 output_asm_insn (\"tst%?\\t%0, %1\", operands);
e2348bcb 2505 return \"\";
0d66636f 2506 "
596e5e8f 2507 [(set_attr "conds" "set")
65f68e55 2508 (set_attr "predicable" "yes")
d952d547 2509 (set_attr "predicable_short_it" "no")
d82e788e 2510 (set_attr "type" "logics_imm")]
0d66636f 2511)
9c08d1fa 2512
f4462328 2513(define_insn_and_split "*ne_zeroextractsi"
c4034607 2514 [(set (match_operand:SI 0 "s_register_operand" "=r")
2515 (ne:SI (zero_extract:SI
2516 (match_operand:SI 1 "s_register_operand" "r")
2517 (match_operand:SI 2 "const_int_operand" "n")
2518 (match_operand:SI 3 "const_int_operand" "n"))
3b8c7f7a 2519 (const_int 0)))
2520 (clobber (reg:CC CC_REGNUM))]
25f905c2 2521 "TARGET_32BIT
cffb2a26 2522 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2523 && INTVAL (operands[2]) > 0
2524 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2525 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
f4462328 2526 "#"
25f905c2 2527 "TARGET_32BIT
f4462328 2528 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2529 && INTVAL (operands[2]) > 0
2530 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2531 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
2532 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2533 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2534 (const_int 0)))
2535 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2536 (set (match_dup 0)
2537 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2538 (match_dup 0) (const_int 1)))]
2539 "
2540 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
2541 << INTVAL (operands[3]));
2542 "
2543 [(set_attr "conds" "clob")
25f905c2 2544 (set (attr "length")
2545 (if_then_else (eq_attr "is_thumb" "yes")
2546 (const_int 12)
1b7da4ac 2547 (const_int 8)))
2548 (set_attr "type" "multiple")]
f4462328 2549)
2550
2551(define_insn_and_split "*ne_zeroextractsi_shifted"
2552 [(set (match_operand:SI 0 "s_register_operand" "=r")
2553 (ne:SI (zero_extract:SI
2554 (match_operand:SI 1 "s_register_operand" "r")
2555 (match_operand:SI 2 "const_int_operand" "n")
2556 (const_int 0))
2557 (const_int 0)))
2558 (clobber (reg:CC CC_REGNUM))]
2559 "TARGET_ARM"
2560 "#"
2561 "TARGET_ARM"
2562 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2563 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2564 (const_int 0)))
2565 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2566 (set (match_dup 0)
2567 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2568 (match_dup 0) (const_int 1)))]
2569 "
2570 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
2571 "
2572 [(set_attr "conds" "clob")
1b7da4ac 2573 (set_attr "length" "8")
2574 (set_attr "type" "multiple")]
f4462328 2575)
2576
2577(define_insn_and_split "*ite_ne_zeroextractsi"
2578 [(set (match_operand:SI 0 "s_register_operand" "=r")
2579 (if_then_else:SI (ne (zero_extract:SI
2580 (match_operand:SI 1 "s_register_operand" "r")
2581 (match_operand:SI 2 "const_int_operand" "n")
2582 (match_operand:SI 3 "const_int_operand" "n"))
2583 (const_int 0))
2584 (match_operand:SI 4 "arm_not_operand" "rIK")
2585 (const_int 0)))
2586 (clobber (reg:CC CC_REGNUM))]
2587 "TARGET_ARM
2588 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2589 && INTVAL (operands[2]) > 0
2590 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 2591 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2592 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 2593 "#"
2594 "TARGET_ARM
2595 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2596 && INTVAL (operands[2]) > 0
2597 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 2598 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2599 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 2600 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2601 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2602 (const_int 0)))
2603 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2604 (set (match_dup 0)
2605 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2606 (match_dup 0) (match_dup 4)))]
2607 "
c4034607 2608 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
f4462328 2609 << INTVAL (operands[3]));
2610 "
2611 [(set_attr "conds" "clob")
1b7da4ac 2612 (set_attr "length" "8")
2613 (set_attr "type" "multiple")]
f4462328 2614)
2615
2616(define_insn_and_split "*ite_ne_zeroextractsi_shifted"
2617 [(set (match_operand:SI 0 "s_register_operand" "=r")
2618 (if_then_else:SI (ne (zero_extract:SI
2619 (match_operand:SI 1 "s_register_operand" "r")
2620 (match_operand:SI 2 "const_int_operand" "n")
2621 (const_int 0))
2622 (const_int 0))
2623 (match_operand:SI 3 "arm_not_operand" "rIK")
2624 (const_int 0)))
2625 (clobber (reg:CC CC_REGNUM))]
f8d7bf2f 2626 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 2627 "#"
f8d7bf2f 2628 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 2629 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2630 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2631 (const_int 0)))
2632 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2633 (set (match_dup 0)
2634 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2635 (match_dup 0) (match_dup 3)))]
2636 "
2637 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
0d66636f 2638 "
2639 [(set_attr "conds" "clob")
1b7da4ac 2640 (set_attr "length" "8")
2641 (set_attr "type" "multiple")]
215b30b3 2642)
9c08d1fa 2643
25f905c2 2644;; ??? Use Thumb-2 has bitfield insert/extract instructions.
d7863cfe 2645(define_split
2646 [(set (match_operand:SI 0 "s_register_operand" "")
2647 (match_operator:SI 1 "shiftable_operator"
2648 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2649 (match_operand:SI 3 "const_int_operand" "")
2650 (match_operand:SI 4 "const_int_operand" ""))
2651 (match_operand:SI 5 "s_register_operand" "")]))
2652 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2653 "TARGET_ARM"
2654 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2655 (set (match_dup 0)
2656 (match_op_dup 1
2657 [(lshiftrt:SI (match_dup 6) (match_dup 4))
2658 (match_dup 5)]))]
2659 "{
2660 HOST_WIDE_INT temp = INTVAL (operands[3]);
2661
2662 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2663 operands[4] = GEN_INT (32 - temp);
2664 }"
2665)
2666
d7863cfe 2667(define_split
2668 [(set (match_operand:SI 0 "s_register_operand" "")
2669 (match_operator:SI 1 "shiftable_operator"
2670 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2671 (match_operand:SI 3 "const_int_operand" "")
2672 (match_operand:SI 4 "const_int_operand" ""))
2673 (match_operand:SI 5 "s_register_operand" "")]))
2674 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2675 "TARGET_ARM"
2676 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2677 (set (match_dup 0)
2678 (match_op_dup 1
2679 [(ashiftrt:SI (match_dup 6) (match_dup 4))
2680 (match_dup 5)]))]
2681 "{
2682 HOST_WIDE_INT temp = INTVAL (operands[3]);
2683
2684 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2685 operands[4] = GEN_INT (32 - temp);
2686 }"
2687)
2688
a42059fd 2689;;; ??? This pattern is bogus. If operand3 has bits outside the range
2690;;; represented by the bitfield, then this will produce incorrect results.
2691;;; Somewhere, the value needs to be truncated. On targets like the m68k,
ceb2fe0f 2692;;; which have a real bit-field insert instruction, the truncation happens
2693;;; in the bit-field insert instruction itself. Since arm does not have a
2694;;; bit-field insert instruction, we would have to emit code here to truncate
a42059fd 2695;;; the value before we insert. This loses some of the advantage of having
2696;;; this insv pattern, so this pattern needs to be reevalutated.
2697
8a18b90c 2698(define_expand "insv"
eb04cafb 2699 [(set (zero_extract (match_operand 0 "nonimmediate_operand" "")
2700 (match_operand 1 "general_operand" "")
2701 (match_operand 2 "general_operand" ""))
2702 (match_operand 3 "reg_or_int_operand" ""))]
8b054d5a 2703 "TARGET_ARM || arm_arch_thumb2"
8a18b90c 2704 "
215b30b3 2705 {
2706 int start_bit = INTVAL (operands[2]);
2707 int width = INTVAL (operands[1]);
db2faf44 2708 HOST_WIDE_INT mask = (HOST_WIDE_INT_1 << width) - 1;
215b30b3 2709 rtx target, subtarget;
2710
8b054d5a 2711 if (arm_arch_thumb2)
2712 {
eb04cafb 2713 if (unaligned_access && MEM_P (operands[0])
2714 && s_register_operand (operands[3], GET_MODE (operands[3]))
2715 && (width == 16 || width == 32) && (start_bit % BITS_PER_UNIT) == 0)
8b054d5a 2716 {
eb04cafb 2717 rtx base_addr;
2718
2719 if (BYTES_BIG_ENDIAN)
2720 start_bit = GET_MODE_BITSIZE (GET_MODE (operands[3])) - width
2721 - start_bit;
8b054d5a 2722
eb04cafb 2723 if (width == 32)
8b054d5a 2724 {
eb04cafb 2725 base_addr = adjust_address (operands[0], SImode,
2726 start_bit / BITS_PER_UNIT);
2727 emit_insn (gen_unaligned_storesi (base_addr, operands[3]));
8b054d5a 2728 }
eb04cafb 2729 else
2730 {
2731 rtx tmp = gen_reg_rtx (HImode);
8b054d5a 2732
eb04cafb 2733 base_addr = adjust_address (operands[0], HImode,
2734 start_bit / BITS_PER_UNIT);
2735 emit_move_insn (tmp, gen_lowpart (HImode, operands[3]));
2736 emit_insn (gen_unaligned_storehi (base_addr, tmp));
2737 }
2738 DONE;
8b054d5a 2739 }
eb04cafb 2740 else if (s_register_operand (operands[0], GET_MODE (operands[0])))
8b054d5a 2741 {
eb04cafb 2742 bool use_bfi = TRUE;
8b054d5a 2743
0438d37f 2744 if (CONST_INT_P (operands[3]))
eb04cafb 2745 {
2746 HOST_WIDE_INT val = INTVAL (operands[3]) & mask;
2747
2748 if (val == 0)
2749 {
2750 emit_insn (gen_insv_zero (operands[0], operands[1],
2751 operands[2]));
2752 DONE;
2753 }
2754
2755 /* See if the set can be done with a single orr instruction. */
2756 if (val == mask && const_ok_for_arm (val << start_bit))
2757 use_bfi = FALSE;
2758 }
2759
2760 if (use_bfi)
2761 {
0438d37f 2762 if (!REG_P (operands[3]))
eb04cafb 2763 operands[3] = force_reg (SImode, operands[3]);
2764
2765 emit_insn (gen_insv_t2 (operands[0], operands[1], operands[2],
2766 operands[3]));
2767 DONE;
2768 }
8b054d5a 2769 }
eb04cafb 2770 else
2771 FAIL;
8b054d5a 2772 }
2773
eb04cafb 2774 if (!s_register_operand (operands[0], GET_MODE (operands[0])))
2775 FAIL;
2776
3f8fde42 2777 target = copy_rtx (operands[0]);
215b30b3 2778 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
2779 subreg as the final target. */
2780 if (GET_CODE (target) == SUBREG)
2781 {
2782 subtarget = gen_reg_rtx (SImode);
2783 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
2784 < GET_MODE_SIZE (SImode))
2785 target = SUBREG_REG (target);
2786 }
2787 else
2788 subtarget = target;
8a18b90c 2789
0438d37f 2790 if (CONST_INT_P (operands[3]))
215b30b3 2791 {
2792 /* Since we are inserting a known constant, we may be able to
2793 reduce the number of bits that we have to clear so that
2794 the mask becomes simple. */
2795 /* ??? This code does not check to see if the new mask is actually
2796 simpler. It may not be. */
2797 rtx op1 = gen_reg_rtx (SImode);
2798 /* ??? Truncate operand3 to fit in the bitfield. See comment before
2799 start of this pattern. */
2800 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
2801 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
2802
c5b3a71b 2803 emit_insn (gen_andsi3 (op1, operands[0],
2804 gen_int_mode (~mask2, SImode)));
215b30b3 2805 emit_insn (gen_iorsi3 (subtarget, op1,
4292ca6b 2806 gen_int_mode (op3_value << start_bit, SImode)));
215b30b3 2807 }
2808 else if (start_bit == 0
2809 && !(const_ok_for_arm (mask)
2810 || const_ok_for_arm (~mask)))
2811 {
2812 /* A Trick, since we are setting the bottom bits in the word,
2813 we can shift operand[3] up, operand[0] down, OR them together
2814 and rotate the result back again. This takes 3 insns, and
5910bb95 2815 the third might be mergeable into another op. */
215b30b3 2816 /* The shift up copes with the possibility that operand[3] is
2817 wider than the bitfield. */
2818 rtx op0 = gen_reg_rtx (SImode);
2819 rtx op1 = gen_reg_rtx (SImode);
2820
2821 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2822 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
2823 emit_insn (gen_iorsi3 (op1, op1, op0));
2824 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
2825 }
2826 else if ((width + start_bit == 32)
2827 && !(const_ok_for_arm (mask)
2828 || const_ok_for_arm (~mask)))
2829 {
2830 /* Similar trick, but slightly less efficient. */
8a18b90c 2831
215b30b3 2832 rtx op0 = gen_reg_rtx (SImode);
2833 rtx op1 = gen_reg_rtx (SImode);
8a18b90c 2834
215b30b3 2835 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2836 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
2837 emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
2838 emit_insn (gen_iorsi3 (subtarget, op1, op0));
2839 }
2840 else
2841 {
c5b3a71b 2842 rtx op0 = gen_int_mode (mask, SImode);
215b30b3 2843 rtx op1 = gen_reg_rtx (SImode);
2844 rtx op2 = gen_reg_rtx (SImode);
8a18b90c 2845
215b30b3 2846 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
2847 {
2848 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 2849
215b30b3 2850 emit_insn (gen_movsi (tmp, op0));
2851 op0 = tmp;
2852 }
8a18b90c 2853
215b30b3 2854 /* Mask out any bits in operand[3] that are not needed. */
2855 emit_insn (gen_andsi3 (op1, operands[3], op0));
8a18b90c 2856
0438d37f 2857 if (CONST_INT_P (op0)
215b30b3 2858 && (const_ok_for_arm (mask << start_bit)
2859 || const_ok_for_arm (~(mask << start_bit))))
2860 {
c5b3a71b 2861 op0 = gen_int_mode (~(mask << start_bit), SImode);
215b30b3 2862 emit_insn (gen_andsi3 (op2, operands[0], op0));
2863 }
2864 else
2865 {
0438d37f 2866 if (CONST_INT_P (op0))
215b30b3 2867 {
2868 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 2869
215b30b3 2870 emit_insn (gen_movsi (tmp, op0));
2871 op0 = tmp;
2872 }
2873
2874 if (start_bit != 0)
2875 emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
a42059fd 2876
215b30b3 2877 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
2878 }
8a18b90c 2879
215b30b3 2880 if (start_bit != 0)
2881 emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
8a18b90c 2882
215b30b3 2883 emit_insn (gen_iorsi3 (subtarget, op1, op2));
2884 }
f082f1c4 2885
215b30b3 2886 if (subtarget != target)
2887 {
2888 /* If TARGET is still a SUBREG, then it must be wider than a word,
2889 so we must be careful only to set the subword we were asked to. */
2890 if (GET_CODE (target) == SUBREG)
2891 emit_move_insn (target, subtarget);
2892 else
2893 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
2894 }
8a18b90c 2895
215b30b3 2896 DONE;
2897 }"
2898)
8a18b90c 2899
8b054d5a 2900(define_insn "insv_zero"
2901 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
809003b3 2902 (match_operand:SI 1 "const_int_M_operand" "M")
2903 (match_operand:SI 2 "const_int_M_operand" "M"))
8b054d5a 2904 (const_int 0))]
2905 "arm_arch_thumb2"
2906 "bfc%?\t%0, %2, %1"
2907 [(set_attr "length" "4")
d952d547 2908 (set_attr "predicable" "yes")
d82e788e 2909 (set_attr "predicable_short_it" "no")
2910 (set_attr "type" "bfm")]
8b054d5a 2911)
2912
2913(define_insn "insv_t2"
2914 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
809003b3 2915 (match_operand:SI 1 "const_int_M_operand" "M")
2916 (match_operand:SI 2 "const_int_M_operand" "M"))
8b054d5a 2917 (match_operand:SI 3 "s_register_operand" "r"))]
2918 "arm_arch_thumb2"
2919 "bfi%?\t%0, %3, %2, %1"
2920 [(set_attr "length" "4")
d952d547 2921 (set_attr "predicable" "yes")
d82e788e 2922 (set_attr "predicable_short_it" "no")
2923 (set_attr "type" "bfm")]
8b054d5a 2924)
2925
215b30b3 2926; constants for op 2 will never be given to these patterns.
a0f94409 2927(define_insn_and_split "*anddi_notdi_di"
9c08d1fa 2928 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 2929 (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "0,r"))
2930 (match_operand:DI 2 "s_register_operand" "r,0")))]
25f905c2 2931 "TARGET_32BIT"
f6ebffac 2932 "#"
e2669ea7 2933 "TARGET_32BIT && reload_completed
2934 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))
2935 && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
a0f94409 2936 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2937 (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2938 "
2939 {
2940 operands[3] = gen_highpart (SImode, operands[0]);
2941 operands[0] = gen_lowpart (SImode, operands[0]);
2942 operands[4] = gen_highpart (SImode, operands[1]);
2943 operands[1] = gen_lowpart (SImode, operands[1]);
2944 operands[5] = gen_highpart (SImode, operands[2]);
2945 operands[2] = gen_lowpart (SImode, operands[2]);
2946 }"
0d66636f 2947 [(set_attr "length" "8")
1b7da4ac 2948 (set_attr "predicable" "yes")
2949 (set_attr "type" "multiple")]
0d66636f 2950)
d952d547 2951
a0f94409 2952(define_insn_and_split "*anddi_notzesidi_di"
9c08d1fa 2953 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2954 (and:DI (not:DI (zero_extend:DI
2955 (match_operand:SI 2 "s_register_operand" "r,r")))
e2348bcb 2956 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 2957 "TARGET_32BIT"
e2348bcb 2958 "@
97499065 2959 bic%?\\t%Q0, %Q1, %2
f6ebffac 2960 #"
a0f94409 2961 ; (not (zero_extend ...)) allows us to just copy the high word from
2962 ; operand1 to operand0.
25f905c2 2963 "TARGET_32BIT
a0f94409 2964 && reload_completed
2965 && operands[0] != operands[1]"
5a097f7d 2966 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
a0f94409 2967 (set (match_dup 3) (match_dup 4))]
2968 "
2969 {
2970 operands[3] = gen_highpart (SImode, operands[0]);
2971 operands[0] = gen_lowpart (SImode, operands[0]);
2972 operands[4] = gen_highpart (SImode, operands[1]);
2973 operands[1] = gen_lowpart (SImode, operands[1]);
2974 }"
0d66636f 2975 [(set_attr "length" "4,8")
d952d547 2976 (set_attr "predicable" "yes")
1b7da4ac 2977 (set_attr "predicable_short_it" "no")
2978 (set_attr "type" "multiple")]
0d66636f 2979)
d952d547 2980
d8cd5fa0 2981(define_insn_and_split "*anddi_notdi_zesidi"
2982 [(set (match_operand:DI 0 "s_register_operand" "=r")
2983 (and:DI (not:DI (match_operand:DI 2 "s_register_operand" "r"))
2984 (zero_extend:DI
2985 (match_operand:SI 1 "s_register_operand" "r"))))]
2986 "TARGET_32BIT"
2987 "#"
2988 "TARGET_32BIT && reload_completed"
2989 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2990 (set (match_dup 3) (const_int 0))]
2991 "
2992 {
2993 operands[3] = gen_highpart (SImode, operands[0]);
2994 operands[0] = gen_lowpart (SImode, operands[0]);
2995 operands[2] = gen_lowpart (SImode, operands[2]);
2996 }"
2997 [(set_attr "length" "8")
2998 (set_attr "predicable" "yes")
2999 (set_attr "predicable_short_it" "no")
3000 (set_attr "type" "multiple")]
3001)
3002
a0f94409 3003(define_insn_and_split "*anddi_notsesidi_di"
9c08d1fa 3004 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3005 (and:DI (not:DI (sign_extend:DI
3006 (match_operand:SI 2 "s_register_operand" "r,r")))
5a097f7d 3007 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 3008 "TARGET_32BIT"
f6ebffac 3009 "#"
25f905c2 3010 "TARGET_32BIT && reload_completed"
5a097f7d 3011 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
a0f94409 3012 (set (match_dup 3) (and:SI (not:SI
3013 (ashiftrt:SI (match_dup 2) (const_int 31)))
3014 (match_dup 4)))]
3015 "
3016 {
3017 operands[3] = gen_highpart (SImode, operands[0]);
3018 operands[0] = gen_lowpart (SImode, operands[0]);
3019 operands[4] = gen_highpart (SImode, operands[1]);
3020 operands[1] = gen_lowpart (SImode, operands[1]);
3021 }"
0d66636f 3022 [(set_attr "length" "8")
d952d547 3023 (set_attr "predicable" "yes")
1b7da4ac 3024 (set_attr "predicable_short_it" "no")
3025 (set_attr "type" "multiple")]
0d66636f 3026)
d952d547 3027
8a18b90c 3028(define_insn "andsi_notsi_si"
9c08d1fa 3029 [(set (match_operand:SI 0 "s_register_operand" "=r")
3030 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
3031 (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 3032 "TARGET_32BIT"
0d66636f 3033 "bic%?\\t%0, %1, %2"
d952d547 3034 [(set_attr "predicable" "yes")
1b7da4ac 3035 (set_attr "predicable_short_it" "no")
3036 (set_attr "type" "logic_reg")]
0d66636f 3037)
b11cae9e 3038
8a18b90c 3039(define_insn "andsi_not_shiftsi_si"
a2cd141b 3040 [(set (match_operand:SI 0 "s_register_operand" "=r")
3041 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
3042 [(match_operand:SI 2 "s_register_operand" "r")
3043 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
3044 (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 3045 "TARGET_ARM"
6c4c2133 3046 "bic%?\\t%0, %1, %2%S4"
344495ea 3047 [(set_attr "predicable" "yes")
331beb1a 3048 (set_attr "shift" "2")
a2cd141b 3049 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
d82e788e 3050 (const_string "logic_shift_imm")
3051 (const_string "logic_shift_reg")))]
6c4c2133 3052)
8a18b90c 3053
9ed784d8 3054;; Shifted bics pattern used to set up CC status register and not reusing
3055;; bics output. Pattern restricts Thumb2 shift operand as bics for Thumb2
3056;; does not support shift by register.
3057(define_insn "andsi_not_shiftsi_si_scc_no_reuse"
3058 [(set (reg:CC_NOOV CC_REGNUM)
3059 (compare:CC_NOOV
3060 (and:SI (not:SI (match_operator:SI 0 "shift_operator"
3061 [(match_operand:SI 1 "s_register_operand" "r")
3062 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
3063 (match_operand:SI 3 "s_register_operand" "r"))
3064 (const_int 0)))
3065 (clobber (match_scratch:SI 4 "=r"))]
3066 "TARGET_ARM || (TARGET_THUMB2 && CONST_INT_P (operands[2]))"
3ef90e77 3067 "bics%?\\t%4, %3, %1%S0"
9ed784d8 3068 [(set_attr "predicable" "yes")
3069 (set_attr "predicable_short_it" "no")
3070 (set_attr "conds" "set")
3071 (set_attr "shift" "1")
3072 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3073 (const_string "logic_shift_imm")
3074 (const_string "logic_shift_reg")))]
3075)
3076
3077;; Same as andsi_not_shiftsi_si_scc_no_reuse, but the bics result is also
3078;; getting reused later.
3079(define_insn "andsi_not_shiftsi_si_scc"
3080 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
3081 (compare:CC_NOOV
3082 (and:SI (not:SI (match_operator:SI 0 "shift_operator"
3083 [(match_operand:SI 1 "s_register_operand" "r")
3084 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
3085 (match_operand:SI 3 "s_register_operand" "r"))
3086 (const_int 0)))
3087 (set (match_operand:SI 4 "s_register_operand" "=r")
3088 (and:SI (not:SI (match_op_dup 0
3089 [(match_dup 1)
3090 (match_dup 2)]))
3091 (match_dup 3)))])]
3092 "TARGET_ARM || (TARGET_THUMB2 && CONST_INT_P (operands[2]))"
3ef90e77 3093 "bics%?\\t%4, %3, %1%S0"
9ed784d8 3094 [(set_attr "predicable" "yes")
3095 (set_attr "predicable_short_it" "no")
3096 (set_attr "conds" "set")
3097 (set_attr "shift" "1")
3098 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3099 (const_string "logic_shift_imm")
3100 (const_string "logic_shift_reg")))]
3101)
3102
f7fbdd4a 3103(define_insn "*andsi_notsi_si_compare0"
bd5b4116 3104 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 3105 (compare:CC_NOOV
3106 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
3107 (match_operand:SI 1 "s_register_operand" "r"))
3108 (const_int 0)))
9c08d1fa 3109 (set (match_operand:SI 0 "s_register_operand" "=r")
3110 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
25f905c2 3111 "TARGET_32BIT"
3ef90e77 3112 "bics\\t%0, %1, %2"
d82e788e 3113 [(set_attr "conds" "set")
3114 (set_attr "type" "logics_shift_reg")]
0d66636f 3115)
9c08d1fa 3116
f7fbdd4a 3117(define_insn "*andsi_notsi_si_compare0_scratch"
bd5b4116 3118 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 3119 (compare:CC_NOOV
3120 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
3121 (match_operand:SI 1 "s_register_operand" "r"))
3122 (const_int 0)))
9c08d1fa 3123 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 3124 "TARGET_32BIT"
3ef90e77 3125 "bics\\t%0, %1, %2"
d82e788e 3126 [(set_attr "conds" "set")
3127 (set_attr "type" "logics_shift_reg")]
0d66636f 3128)
9c08d1fa 3129
e2669ea7 3130(define_expand "iordi3"
3131 [(set (match_operand:DI 0 "s_register_operand" "")
3132 (ior:DI (match_operand:DI 1 "s_register_operand" "")
3133 (match_operand:DI 2 "neon_logic_op2" "")))]
3134 "TARGET_32BIT"
3135 ""
3136)
3137
74d6113f 3138(define_insn_and_split "*iordi3_insn"
3139 [(set (match_operand:DI 0 "s_register_operand" "=w,w ,&r,&r,&r,&r,?w,?w")
3140 (ior:DI (match_operand:DI 1 "s_register_operand" "%w,0 ,0 ,r ,0 ,r ,w ,0")
e0fe6977 3141 (match_operand:DI 2 "arm_iordi_operand_neon" "w ,Dl,r ,r ,Df,Df,w ,Dl")))]
74d6113f 3142 "TARGET_32BIT && !TARGET_IWMMXT"
3143 {
3144 switch (which_alternative)
3145 {
3146 case 0: /* fall through */
3147 case 6: return "vorr\t%P0, %P1, %P2";
3148 case 1: /* fall through */
3149 case 7: return neon_output_logic_immediate ("vorr", &operands[2],
3150 DImode, 0, VALID_NEON_QREG_MODE (DImode));
3151 case 2:
3152 case 3:
3153 case 4:
3154 case 5:
3155 return "#";
3156 default: gcc_unreachable ();
3157 }
3158 }
3159 "TARGET_32BIT && !TARGET_IWMMXT && reload_completed
3160 && !(IS_VFP_REGNUM (REGNO (operands[0])))"
3161 [(set (match_dup 3) (match_dup 4))
3162 (set (match_dup 5) (match_dup 6))]
3163 "
3164 {
3165 operands[3] = gen_lowpart (SImode, operands[0]);
3166 operands[5] = gen_highpart (SImode, operands[0]);
3167
3168 operands[4] = simplify_gen_binary (IOR, SImode,
3169 gen_lowpart (SImode, operands[1]),
3170 gen_lowpart (SImode, operands[2]));
3171 operands[6] = simplify_gen_binary (IOR, SImode,
3172 gen_highpart (SImode, operands[1]),
3173 gen_highpart_mode (SImode, DImode, operands[2]));
3174
3175 }"
32093010 3176 [(set_attr "type" "neon_logic,neon_logic,multiple,multiple,multiple,\
3177 multiple,neon_logic,neon_logic")
e0fe6977 3178 (set_attr "length" "*,*,8,8,8,8,*,*")
74d6113f 3179 (set_attr "arch" "neon_for_64bits,neon_for_64bits,*,*,*,*,avoid_neon_for_64bits,avoid_neon_for_64bits")]
cffb2a26 3180)
9c08d1fa 3181
f7fbdd4a 3182(define_insn "*iordi_zesidi_di"
9c08d1fa 3183 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3184 (ior:DI (zero_extend:DI
3185 (match_operand:SI 2 "s_register_operand" "r,r"))
e2348bcb 3186 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 3187 "TARGET_32BIT"
e2348bcb 3188 "@
97499065 3189 orr%?\\t%Q0, %Q1, %2
f6ebffac 3190 #"
0d66636f 3191 [(set_attr "length" "4,8")
d952d547 3192 (set_attr "predicable" "yes")
1b7da4ac 3193 (set_attr "predicable_short_it" "no")
3194 (set_attr "type" "logic_reg,multiple")]
cffb2a26 3195)
9c08d1fa 3196
f7fbdd4a 3197(define_insn "*iordi_sesidi_di"
9c08d1fa 3198 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3199 (ior:DI (sign_extend:DI
3200 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 3201 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 3202 "TARGET_32BIT"
f6ebffac 3203 "#"
0d66636f 3204 [(set_attr "length" "8")
1b7da4ac 3205 (set_attr "predicable" "yes")
3206 (set_attr "type" "multiple")]
cffb2a26 3207)
9c08d1fa 3208
87b22bf7 3209(define_expand "iorsi3"
cffb2a26 3210 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3211 (ior:SI (match_operand:SI 1 "s_register_operand" "")
3212 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 3213 "TARGET_EITHER"
87b22bf7 3214 "
0438d37f 3215 if (CONST_INT_P (operands[2]))
87b22bf7 3216 {
25f905c2 3217 if (TARGET_32BIT)
cffb2a26 3218 {
17202aa5 3219 if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[2]), IOR))
3220 operands[2] = force_reg (SImode, operands[2]);
3221 else
3222 {
3223 arm_split_constant (IOR, SImode, NULL_RTX,
3224 INTVAL (operands[2]), operands[0],
3225 operands[1],
3226 optimize && can_create_pseudo_p ());
3227 DONE;
3228 }
cffb2a26 3229 }
25f905c2 3230 else /* TARGET_THUMB1 */
923ffadb 3231 {
3232 rtx tmp = force_reg (SImode, operands[2]);
3233 if (rtx_equal_p (operands[0], operands[1]))
3234 operands[2] = tmp;
3235 else
3236 {
3237 operands[2] = operands[1];
3238 operands[1] = tmp;
3239 }
3240 }
87b22bf7 3241 }
cffb2a26 3242 "
3243)
87b22bf7 3244
d5d4dc8d 3245(define_insn_and_split "*iorsi3_insn"
29e234a3 3246 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r,r,r")
3247 (ior:SI (match_operand:SI 1 "s_register_operand" "%r,0,r,r,r")
3248 (match_operand:SI 2 "reg_or_int_operand" "I,l,K,r,?n")))]
d5d4dc8d 3249 "TARGET_32BIT"
87b22bf7 3250 "@
29e234a3 3251 orr%?\\t%0, %1, %2
87b22bf7 3252 orr%?\\t%0, %1, %2
d5d4dc8d 3253 orn%?\\t%0, %1, #%B2
65f68e55 3254 orr%?\\t%0, %1, %2
87b22bf7 3255 #"
d5d4dc8d 3256 "TARGET_32BIT
0438d37f 3257 && CONST_INT_P (operands[2])
d5d4dc8d 3258 && !(const_ok_for_arm (INTVAL (operands[2]))
3259 || (TARGET_THUMB2 && const_ok_for_arm (~INTVAL (operands[2]))))"
a0f94409 3260 [(clobber (const_int 0))]
d5d4dc8d 3261{
29e234a3 3262 arm_split_constant (IOR, SImode, curr_insn,
96f57e36 3263 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 3264 DONE;
d5d4dc8d 3265}
29e234a3 3266 [(set_attr "length" "4,4,4,4,16")
3267 (set_attr "arch" "32,t2,t2,32,32")
65f68e55 3268 (set_attr "predicable" "yes")
29e234a3 3269 (set_attr "predicable_short_it" "no,yes,no,no,no")
d82e788e 3270 (set_attr "type" "logic_imm,logic_reg,logic_imm,logic_reg,logic_reg")]
65f68e55 3271)
cffb2a26 3272
a0f94409 3273(define_peephole2
3274 [(match_scratch:SI 3 "r")
372575c7 3275 (set (match_operand:SI 0 "arm_general_register_operand" "")
3276 (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
87b22bf7 3277 (match_operand:SI 2 "const_int_operand" "")))]
90560cad 3278 "TARGET_ARM
a0f94409 3279 && !const_ok_for_arm (INTVAL (operands[2]))
3280 && const_ok_for_arm (~INTVAL (operands[2]))"
3281 [(set (match_dup 3) (match_dup 2))
3282 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
3283 ""
215b30b3 3284)
a0f94409 3285
f7fbdd4a 3286(define_insn "*iorsi3_compare0"
bd5b4116 3287 [(set (reg:CC_NOOV CC_REGNUM)
65f68e55 3288 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r,r")
3289 (match_operand:SI 2 "arm_rhs_operand" "I,r"))
9c08d1fa 3290 (const_int 0)))
65f68e55 3291 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 3292 (ior:SI (match_dup 1) (match_dup 2)))]
25f905c2 3293 "TARGET_32BIT"
3ef90e77 3294 "orrs%?\\t%0, %1, %2"
65f68e55 3295 [(set_attr "conds" "set")
d82e788e 3296 (set_attr "type" "logics_imm,logics_reg")]
cffb2a26 3297)
9c08d1fa 3298
f7fbdd4a 3299(define_insn "*iorsi3_compare0_scratch"
bd5b4116 3300 [(set (reg:CC_NOOV CC_REGNUM)
65f68e55 3301 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r,r")
3302 (match_operand:SI 2 "arm_rhs_operand" "I,r"))
9c08d1fa 3303 (const_int 0)))
65f68e55 3304 (clobber (match_scratch:SI 0 "=r,r"))]
25f905c2 3305 "TARGET_32BIT"
3ef90e77 3306 "orrs%?\\t%0, %1, %2"
65f68e55 3307 [(set_attr "conds" "set")
d82e788e 3308 (set_attr "type" "logics_imm,logics_reg")]
0d66636f 3309)
9c08d1fa 3310
e2669ea7 3311(define_expand "xordi3"
3312 [(set (match_operand:DI 0 "s_register_operand" "")
3313 (xor:DI (match_operand:DI 1 "s_register_operand" "")
8ee7dc6f 3314 (match_operand:DI 2 "arm_xordi_operand" "")))]
e2669ea7 3315 "TARGET_32BIT"
3316 ""
3317)
3318
8ee7dc6f 3319(define_insn_and_split "*xordi3_insn"
3320 [(set (match_operand:DI 0 "s_register_operand" "=w,&r,&r,&r,&r,?w")
205c3b0a 3321 (xor:DI (match_operand:DI 1 "s_register_operand" "%w ,0,r ,0 ,r ,w")
8ee7dc6f 3322 (match_operand:DI 2 "arm_xordi_operand" "w ,r ,r ,Dg,Dg,w")))]
3323 "TARGET_32BIT && !TARGET_IWMMXT"
3324{
3325 switch (which_alternative)
3326 {
3327 case 1:
3328 case 2:
3329 case 3:
3330 case 4: /* fall through */
3331 return "#";
3332 case 0: /* fall through */
3333 case 5: return "veor\t%P0, %P1, %P2";
3334 default: gcc_unreachable ();
3335 }
3336}
3337 "TARGET_32BIT && !TARGET_IWMMXT && reload_completed
3338 && !(IS_VFP_REGNUM (REGNO (operands[0])))"
3339 [(set (match_dup 3) (match_dup 4))
3340 (set (match_dup 5) (match_dup 6))]
3341 "
3342 {
3343 operands[3] = gen_lowpart (SImode, operands[0]);
3344 operands[5] = gen_highpart (SImode, operands[0]);
3345
3346 operands[4] = simplify_gen_binary (XOR, SImode,
3347 gen_lowpart (SImode, operands[1]),
3348 gen_lowpart (SImode, operands[2]));
3349 operands[6] = simplify_gen_binary (XOR, SImode,
3350 gen_highpart (SImode, operands[1]),
3351 gen_highpart_mode (SImode, DImode, operands[2]));
3352
3353 }"
3354 [(set_attr "length" "*,8,8,8,8,*")
32093010 3355 (set_attr "type" "neon_logic,multiple,multiple,multiple,multiple,neon_logic")
8ee7dc6f 3356 (set_attr "arch" "neon_for_64bits,*,*,*,*,avoid_neon_for_64bits")]
cffb2a26 3357)
9c08d1fa 3358
f7fbdd4a 3359(define_insn "*xordi_zesidi_di"
9c08d1fa 3360 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3361 (xor:DI (zero_extend:DI
3362 (match_operand:SI 2 "s_register_operand" "r,r"))
e2348bcb 3363 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 3364 "TARGET_32BIT"
e2348bcb 3365 "@
97499065 3366 eor%?\\t%Q0, %Q1, %2
f6ebffac 3367 #"
0d66636f 3368 [(set_attr "length" "4,8")
d952d547 3369 (set_attr "predicable" "yes")
1b7da4ac 3370 (set_attr "predicable_short_it" "no")
3371 (set_attr "type" "logic_reg")]
cffb2a26 3372)
9c08d1fa 3373
f7fbdd4a 3374(define_insn "*xordi_sesidi_di"
9c08d1fa 3375 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3376 (xor:DI (sign_extend:DI
3377 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 3378 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 3379 "TARGET_32BIT"
f6ebffac 3380 "#"
0d66636f 3381 [(set_attr "length" "8")
1b7da4ac 3382 (set_attr "predicable" "yes")
3383 (set_attr "type" "multiple")]
cffb2a26 3384)
9c08d1fa 3385
cffb2a26 3386(define_expand "xorsi3"
3387 [(set (match_operand:SI 0 "s_register_operand" "")
3388 (xor:SI (match_operand:SI 1 "s_register_operand" "")
923ffadb 3389 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 3390 "TARGET_EITHER"
0438d37f 3391 "if (CONST_INT_P (operands[2]))
923ffadb 3392 {
3393 if (TARGET_32BIT)
3394 {
17202aa5 3395 if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[2]), XOR))
3396 operands[2] = force_reg (SImode, operands[2]);
3397 else
3398 {
3399 arm_split_constant (XOR, SImode, NULL_RTX,
3400 INTVAL (operands[2]), operands[0],
3401 operands[1],
3402 optimize && can_create_pseudo_p ());
3403 DONE;
3404 }
923ffadb 3405 }
3406 else /* TARGET_THUMB1 */
3407 {
3408 rtx tmp = force_reg (SImode, operands[2]);
3409 if (rtx_equal_p (operands[0], operands[1]))
3410 operands[2] = tmp;
3411 else
3412 {
3413 operands[2] = operands[1];
3414 operands[1] = tmp;
3415 }
3416 }
3417 }"
cffb2a26 3418)
3419
5dcb35d9 3420(define_insn_and_split "*arm_xorsi3"
29e234a3 3421 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r,r")
3422 (xor:SI (match_operand:SI 1 "s_register_operand" "%r,0,r,r")
3423 (match_operand:SI 2 "reg_or_int_operand" "I,l,r,?n")))]
25f905c2 3424 "TARGET_32BIT"
5dcb35d9 3425 "@
29e234a3 3426 eor%?\\t%0, %1, %2
65f68e55 3427 eor%?\\t%0, %1, %2
5dcb35d9 3428 eor%?\\t%0, %1, %2
3429 #"
3430 "TARGET_32BIT
0438d37f 3431 && CONST_INT_P (operands[2])
5dcb35d9 3432 && !const_ok_for_arm (INTVAL (operands[2]))"
3433 [(clobber (const_int 0))]
3434{
3435 arm_split_constant (XOR, SImode, curr_insn,
3436 INTVAL (operands[2]), operands[0], operands[1], 0);
3437 DONE;
3438}
29e234a3 3439 [(set_attr "length" "4,4,4,16")
65f68e55 3440 (set_attr "predicable" "yes")
29e234a3 3441 (set_attr "predicable_short_it" "no,yes,no,no")
1b7da4ac 3442 (set_attr "type" "logic_imm,logic_reg,logic_reg,multiple")]
cffb2a26 3443)
3444
f7fbdd4a 3445(define_insn "*xorsi3_compare0"
bd5b4116 3446 [(set (reg:CC_NOOV CC_REGNUM)
65f68e55 3447 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r,r")
3448 (match_operand:SI 2 "arm_rhs_operand" "I,r"))
9c08d1fa 3449 (const_int 0)))
65f68e55 3450 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 3451 (xor:SI (match_dup 1) (match_dup 2)))]
25f905c2 3452 "TARGET_32BIT"
3ef90e77 3453 "eors%?\\t%0, %1, %2"
65f68e55 3454 [(set_attr "conds" "set")
d82e788e 3455 (set_attr "type" "logics_imm,logics_reg")]
0d66636f 3456)
9c08d1fa 3457
f7fbdd4a 3458(define_insn "*xorsi3_compare0_scratch"
bd5b4116 3459 [(set (reg:CC_NOOV CC_REGNUM)
65f68e55 3460 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r,r")
3461 (match_operand:SI 1 "arm_rhs_operand" "I,r"))
9c08d1fa 3462 (const_int 0)))]
25f905c2 3463 "TARGET_32BIT"
40dbec34 3464 "teq%?\\t%0, %1"
65f68e55 3465 [(set_attr "conds" "set")
d82e788e 3466 (set_attr "type" "logics_imm,logics_reg")]
cffb2a26 3467)
9c08d1fa 3468
215b30b3 3469; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
3470; (NOT D) we can sometimes merge the final NOT into one of the following
3471; insns.
9c08d1fa 3472
3473(define_split
a058e94a 3474 [(set (match_operand:SI 0 "s_register_operand" "")
3475 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
3476 (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
3477 (match_operand:SI 3 "arm_rhs_operand" "")))
3478 (clobber (match_operand:SI 4 "s_register_operand" ""))]
25f905c2 3479 "TARGET_32BIT"
9c08d1fa 3480 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
3481 (not:SI (match_dup 3))))
3482 (set (match_dup 0) (not:SI (match_dup 4)))]
3483 ""
3484)
3485
ba6a3b2f 3486(define_insn_and_split "*andsi_iorsi3_notsi"
9c08d1fa 3487 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
e5fea38e 3488 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "%0,r,r")
9c08d1fa 3489 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
3490 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
25f905c2 3491 "TARGET_32BIT"
ba6a3b2f 3492 "#" ; "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
3493 "&& reload_completed"
3494 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
054fd237 3495 (set (match_dup 0) (and:SI (match_dup 4) (match_dup 5)))]
3496 {
3497 /* If operands[3] is a constant make sure to fold the NOT into it
3498 to avoid creating a NOT of a CONST_INT. */
3499 rtx not_rtx = simplify_gen_unary (NOT, SImode, operands[3], SImode);
3500 if (CONST_INT_P (not_rtx))
3501 {
3502 operands[4] = operands[0];
3503 operands[5] = not_rtx;
3504 }
3505 else
3506 {
3507 operands[5] = operands[0];
3508 operands[4] = not_rtx;
3509 }
3510 }
0d66636f 3511 [(set_attr "length" "8")
25f905c2 3512 (set_attr "ce_count" "2")
d952d547 3513 (set_attr "predicable" "yes")
1b7da4ac 3514 (set_attr "predicable_short_it" "no")
3515 (set_attr "type" "multiple")]
cffb2a26 3516)
9c08d1fa 3517
25f905c2 3518; ??? Are these four splitters still beneficial when the Thumb-2 bitfield
3519; insns are available?
d7863cfe 3520(define_split
3521 [(set (match_operand:SI 0 "s_register_operand" "")
3522 (match_operator:SI 1 "logical_binary_operator"
3523 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
3524 (match_operand:SI 3 "const_int_operand" "")
3525 (match_operand:SI 4 "const_int_operand" ""))
3526 (match_operator:SI 9 "logical_binary_operator"
3527 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3528 (match_operand:SI 6 "const_int_operand" ""))
3529 (match_operand:SI 7 "s_register_operand" "")])]))
3530 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3531 "TARGET_32BIT
d7863cfe 3532 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3533 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3534 [(set (match_dup 8)
3535 (match_op_dup 1
3536 [(ashift:SI (match_dup 2) (match_dup 4))
3537 (match_dup 5)]))
3538 (set (match_dup 0)
3539 (match_op_dup 1
3540 [(lshiftrt:SI (match_dup 8) (match_dup 6))
3541 (match_dup 7)]))]
3542 "
3543 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3544")
3545
3546(define_split
3547 [(set (match_operand:SI 0 "s_register_operand" "")
3548 (match_operator:SI 1 "logical_binary_operator"
3549 [(match_operator:SI 9 "logical_binary_operator"
3550 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3551 (match_operand:SI 6 "const_int_operand" ""))
3552 (match_operand:SI 7 "s_register_operand" "")])
3553 (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
3554 (match_operand:SI 3 "const_int_operand" "")
3555 (match_operand:SI 4 "const_int_operand" ""))]))
3556 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3557 "TARGET_32BIT
d7863cfe 3558 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3559 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3560 [(set (match_dup 8)
3561 (match_op_dup 1
3562 [(ashift:SI (match_dup 2) (match_dup 4))
3563 (match_dup 5)]))
3564 (set (match_dup 0)
3565 (match_op_dup 1
3566 [(lshiftrt:SI (match_dup 8) (match_dup 6))
3567 (match_dup 7)]))]
3568 "
3569 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3570")
3571
3572(define_split
3573 [(set (match_operand:SI 0 "s_register_operand" "")
3574 (match_operator:SI 1 "logical_binary_operator"
3575 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
3576 (match_operand:SI 3 "const_int_operand" "")
3577 (match_operand:SI 4 "const_int_operand" ""))
3578 (match_operator:SI 9 "logical_binary_operator"
3579 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3580 (match_operand:SI 6 "const_int_operand" ""))
3581 (match_operand:SI 7 "s_register_operand" "")])]))
3582 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3583 "TARGET_32BIT
d7863cfe 3584 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3585 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3586 [(set (match_dup 8)
3587 (match_op_dup 1
3588 [(ashift:SI (match_dup 2) (match_dup 4))
3589 (match_dup 5)]))
3590 (set (match_dup 0)
3591 (match_op_dup 1
3592 [(ashiftrt:SI (match_dup 8) (match_dup 6))
3593 (match_dup 7)]))]
3594 "
3595 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3596")
3597
3598(define_split
3599 [(set (match_operand:SI 0 "s_register_operand" "")
3600 (match_operator:SI 1 "logical_binary_operator"
3601 [(match_operator:SI 9 "logical_binary_operator"
3602 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3603 (match_operand:SI 6 "const_int_operand" ""))
3604 (match_operand:SI 7 "s_register_operand" "")])
3605 (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
3606 (match_operand:SI 3 "const_int_operand" "")
3607 (match_operand:SI 4 "const_int_operand" ""))]))
3608 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3609 "TARGET_32BIT
d7863cfe 3610 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3611 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3612 [(set (match_dup 8)
3613 (match_op_dup 1
3614 [(ashift:SI (match_dup 2) (match_dup 4))
3615 (match_dup 5)]))
3616 (set (match_dup 0)
3617 (match_op_dup 1
3618 [(ashiftrt:SI (match_dup 8) (match_dup 6))
3619 (match_dup 7)]))]
3620 "
3621 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3622")
9c08d1fa 3623\f
3624
3625;; Minimum and maximum insns
3626
8b9dc177 3627(define_expand "smaxsi3"
3628 [(parallel [
3629 (set (match_operand:SI 0 "s_register_operand" "")
3630 (smax:SI (match_operand:SI 1 "s_register_operand" "")
3631 (match_operand:SI 2 "arm_rhs_operand" "")))
3632 (clobber (reg:CC CC_REGNUM))])]
25f905c2 3633 "TARGET_32BIT"
8b9dc177 3634 "
8774928b 3635 if (operands[2] == const0_rtx || operands[2] == constm1_rtx)
8b9dc177 3636 {
3637 /* No need for a clobber of the condition code register here. */
d1f9b275 3638 emit_insn (gen_rtx_SET (operands[0],
8b9dc177 3639 gen_rtx_SMAX (SImode, operands[1],
3640 operands[2])));
3641 DONE;
3642 }
3643")
3644
3645(define_insn "*smax_0"
3646 [(set (match_operand:SI 0 "s_register_operand" "=r")
3647 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3648 (const_int 0)))]
25f905c2 3649 "TARGET_32BIT"
8b9dc177 3650 "bic%?\\t%0, %1, %1, asr #31"
d952d547 3651 [(set_attr "predicable" "yes")
1b7da4ac 3652 (set_attr "predicable_short_it" "no")
3653 (set_attr "type" "logic_shift_reg")]
8b9dc177 3654)
3655
8774928b 3656(define_insn "*smax_m1"
3657 [(set (match_operand:SI 0 "s_register_operand" "=r")
3658 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3659 (const_int -1)))]
25f905c2 3660 "TARGET_32BIT"
8774928b 3661 "orr%?\\t%0, %1, %1, asr #31"
d952d547 3662 [(set_attr "predicable" "yes")
1b7da4ac 3663 (set_attr "predicable_short_it" "no")
3664 (set_attr "type" "logic_shift_reg")]
8774928b 3665)
3666
3dc953f2 3667(define_insn_and_split "*arm_smax_insn"
8b9dc177 3668 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3669 (smax:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3670 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
bd5b4116 3671 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3672 "TARGET_ARM"
3dc953f2 3673 "#"
3674 ; cmp\\t%1, %2\;movlt\\t%0, %2
3675 ; cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
3676 "TARGET_ARM"
3677 [(set (reg:CC CC_REGNUM)
3678 (compare:CC (match_dup 1) (match_dup 2)))
3679 (set (match_dup 0)
3680 (if_then_else:SI (ge:SI (reg:CC CC_REGNUM) (const_int 0))
3681 (match_dup 1)
3682 (match_dup 2)))]
3683 ""
cffb2a26 3684 [(set_attr "conds" "clob")
1b7da4ac 3685 (set_attr "length" "8,12")
3686 (set_attr "type" "multiple")]
cffb2a26 3687)
9c08d1fa 3688
8b9dc177 3689(define_expand "sminsi3"
3690 [(parallel [
3691 (set (match_operand:SI 0 "s_register_operand" "")
3692 (smin:SI (match_operand:SI 1 "s_register_operand" "")
3693 (match_operand:SI 2 "arm_rhs_operand" "")))
3694 (clobber (reg:CC CC_REGNUM))])]
25f905c2 3695 "TARGET_32BIT"
8b9dc177 3696 "
3697 if (operands[2] == const0_rtx)
3698 {
3699 /* No need for a clobber of the condition code register here. */
d1f9b275 3700 emit_insn (gen_rtx_SET (operands[0],
8b9dc177 3701 gen_rtx_SMIN (SImode, operands[1],
3702 operands[2])));
3703 DONE;
3704 }
3705")
3706
3707(define_insn "*smin_0"
3708 [(set (match_operand:SI 0 "s_register_operand" "=r")
3709 (smin:SI (match_operand:SI 1 "s_register_operand" "r")
3710 (const_int 0)))]
25f905c2 3711 "TARGET_32BIT"
8b9dc177 3712 "and%?\\t%0, %1, %1, asr #31"
d952d547 3713 [(set_attr "predicable" "yes")
1b7da4ac 3714 (set_attr "predicable_short_it" "no")
3715 (set_attr "type" "logic_shift_reg")]
8b9dc177 3716)
3717
3dc953f2 3718(define_insn_and_split "*arm_smin_insn"
8b9dc177 3719 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3720 (smin:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3721 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
bd5b4116 3722 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3723 "TARGET_ARM"
3dc953f2 3724 "#"
3725 ; cmp\\t%1, %2\;movge\\t%0, %2
3726 ; cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
3727 "TARGET_ARM"
3728 [(set (reg:CC CC_REGNUM)
3729 (compare:CC (match_dup 1) (match_dup 2)))
3730 (set (match_dup 0)
3731 (if_then_else:SI (lt:SI (reg:CC CC_REGNUM) (const_int 0))
3732 (match_dup 1)
3733 (match_dup 2)))]
3734 ""
0d66636f 3735 [(set_attr "conds" "clob")
1b7da4ac 3736 (set_attr "length" "8,12")
3737 (set_attr "type" "multiple,multiple")]
0d66636f 3738)
9c08d1fa 3739
25f905c2 3740(define_expand "umaxsi3"
3741 [(parallel [
3742 (set (match_operand:SI 0 "s_register_operand" "")
3743 (umax:SI (match_operand:SI 1 "s_register_operand" "")
3744 (match_operand:SI 2 "arm_rhs_operand" "")))
3745 (clobber (reg:CC CC_REGNUM))])]
3746 "TARGET_32BIT"
3747 ""
3748)
3749
3dc953f2 3750(define_insn_and_split "*arm_umaxsi3"
9c08d1fa 3751 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3752 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3753 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 3754 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3755 "TARGET_ARM"
3dc953f2 3756 "#"
3757 ; cmp\\t%1, %2\;movcc\\t%0, %2
3758 ; cmp\\t%1, %2\;movcs\\t%0, %1
3759 ; cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
3760 "TARGET_ARM"
3761 [(set (reg:CC CC_REGNUM)
3762 (compare:CC (match_dup 1) (match_dup 2)))
3763 (set (match_dup 0)
3764 (if_then_else:SI (geu:SI (reg:CC CC_REGNUM) (const_int 0))
3765 (match_dup 1)
3766 (match_dup 2)))]
3767 ""
0d66636f 3768 [(set_attr "conds" "clob")
1b7da4ac 3769 (set_attr "length" "8,8,12")
3770 (set_attr "type" "store1")]
0d66636f 3771)
9c08d1fa 3772
25f905c2 3773(define_expand "uminsi3"
3774 [(parallel [
3775 (set (match_operand:SI 0 "s_register_operand" "")
3776 (umin:SI (match_operand:SI 1 "s_register_operand" "")
3777 (match_operand:SI 2 "arm_rhs_operand" "")))
3778 (clobber (reg:CC CC_REGNUM))])]
3779 "TARGET_32BIT"
3780 ""
3781)
3782
3dc953f2 3783(define_insn_and_split "*arm_uminsi3"
9c08d1fa 3784 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3785 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3786 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 3787 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3788 "TARGET_ARM"
3dc953f2 3789 "#"
3790 ; cmp\\t%1, %2\;movcs\\t%0, %2
3791 ; cmp\\t%1, %2\;movcc\\t%0, %1
3792 ; cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
3793 "TARGET_ARM"
3794 [(set (reg:CC CC_REGNUM)
3795 (compare:CC (match_dup 1) (match_dup 2)))
3796 (set (match_dup 0)
3797 (if_then_else:SI (ltu:SI (reg:CC CC_REGNUM) (const_int 0))
3798 (match_dup 1)
3799 (match_dup 2)))]
3800 ""
0d66636f 3801 [(set_attr "conds" "clob")
1b7da4ac 3802 (set_attr "length" "8,8,12")
3803 (set_attr "type" "store1")]
0d66636f 3804)
9c08d1fa 3805
8a18b90c 3806(define_insn "*store_minmaxsi"
9c08d1fa 3807 [(set (match_operand:SI 0 "memory_operand" "=m")
3808 (match_operator:SI 3 "minmax_operator"
3809 [(match_operand:SI 1 "s_register_operand" "r")
3810 (match_operand:SI 2 "s_register_operand" "r")]))
bd5b4116 3811 (clobber (reg:CC CC_REGNUM))]
b207d152 3812 "TARGET_32BIT && optimize_function_for_size_p (cfun) && !arm_restrict_it"
9c08d1fa 3813 "*
dc55b8a9 3814 operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
3815 operands[1], operands[2]);
e2348bcb 3816 output_asm_insn (\"cmp\\t%1, %2\", operands);
25f905c2 3817 if (TARGET_THUMB2)
3818 output_asm_insn (\"ite\t%d3\", operands);
e2348bcb 3819 output_asm_insn (\"str%d3\\t%1, %0\", operands);
3820 output_asm_insn (\"str%D3\\t%2, %0\", operands);
3821 return \"\";
0d66636f 3822 "
3823 [(set_attr "conds" "clob")
25f905c2 3824 (set (attr "length")
3825 (if_then_else (eq_attr "is_thumb" "yes")
3826 (const_int 14)
3827 (const_int 12)))
0d66636f 3828 (set_attr "type" "store1")]
3829)
9c08d1fa 3830
8a18b90c 3831; Reject the frame pointer in operand[1], since reloading this after
3832; it has been eliminated can cause carnage.
f7fbdd4a 3833(define_insn "*minmax_arithsi"
9c08d1fa 3834 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3835 (match_operator:SI 4 "shiftable_operator"
3836 [(match_operator:SI 5 "minmax_operator"
3837 [(match_operand:SI 2 "s_register_operand" "r,r")
3838 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
3839 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 3840 (clobber (reg:CC CC_REGNUM))]
7c36fe71 3841 "TARGET_32BIT && !arm_eliminable_register (operands[1]) && !arm_restrict_it"
9c08d1fa 3842 "*
0d66636f 3843 {
3844 enum rtx_code code = GET_CODE (operands[4]);
25f905c2 3845 bool need_else;
3846
3847 if (which_alternative != 0 || operands[3] != const0_rtx
ca0fc5a2 3848 || (code != PLUS && code != IOR && code != XOR))
25f905c2 3849 need_else = true;
3850 else
3851 need_else = false;
0d66636f 3852
dc55b8a9 3853 operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
3854 operands[2], operands[3]);
0d66636f 3855 output_asm_insn (\"cmp\\t%2, %3\", operands);
25f905c2 3856 if (TARGET_THUMB2)
3857 {
3858 if (need_else)
3859 output_asm_insn (\"ite\\t%d5\", operands);
3860 else
3861 output_asm_insn (\"it\\t%d5\", operands);
3862 }
0d66636f 3863 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
25f905c2 3864 if (need_else)
0d66636f 3865 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
3866 return \"\";
215b30b3 3867 }"
0d66636f 3868 [(set_attr "conds" "clob")
25f905c2 3869 (set (attr "length")
3870 (if_then_else (eq_attr "is_thumb" "yes")
3871 (const_int 14)
1b7da4ac 3872 (const_int 12)))
3873 (set_attr "type" "multiple")]
0d66636f 3874)
9c08d1fa 3875
4164bca1 3876; Reject the frame pointer in operand[1], since reloading this after
3877; it has been eliminated can cause carnage.
3878(define_insn_and_split "*minmax_arithsi_non_canon"
7c36fe71 3879 [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts")
4164bca1 3880 (minus:SI
7c36fe71 3881 (match_operand:SI 1 "s_register_operand" "0,?Ts")
4164bca1 3882 (match_operator:SI 4 "minmax_operator"
7c36fe71 3883 [(match_operand:SI 2 "s_register_operand" "Ts,Ts")
3884 (match_operand:SI 3 "arm_rhs_operand" "TsI,TsI")])))
4164bca1 3885 (clobber (reg:CC CC_REGNUM))]
7c36fe71 3886 "TARGET_32BIT && !arm_eliminable_register (operands[1])
3887 && !(arm_restrict_it && CONST_INT_P (operands[3]))"
4164bca1 3888 "#"
3889 "TARGET_32BIT && !arm_eliminable_register (operands[1]) && reload_completed"
3890 [(set (reg:CC CC_REGNUM)
3891 (compare:CC (match_dup 2) (match_dup 3)))
3892
3893 (cond_exec (match_op_dup 4 [(reg:CC CC_REGNUM) (const_int 0)])
3894 (set (match_dup 0)
3895 (minus:SI (match_dup 1)
3896 (match_dup 2))))
3897 (cond_exec (match_op_dup 5 [(reg:CC CC_REGNUM) (const_int 0)])
3898 (set (match_dup 0)
36ee0cde 3899 (match_dup 6)))]
4164bca1 3900 {
3754d046 3901 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
4164bca1 3902 operands[2], operands[3]);
3903 enum rtx_code rc = minmax_code (operands[4]);
3904 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode,
3905 operands[2], operands[3]);
3906
3907 if (mode == CCFPmode || mode == CCFPEmode)
3908 rc = reverse_condition_maybe_unordered (rc);
3909 else
3910 rc = reverse_condition (rc);
3911 operands[5] = gen_rtx_fmt_ee (rc, SImode, operands[2], operands[3]);
36ee0cde 3912 if (CONST_INT_P (operands[3]))
3913 operands[6] = plus_constant (SImode, operands[1], -INTVAL (operands[3]));
3914 else
3915 operands[6] = gen_rtx_MINUS (SImode, operands[1], operands[3]);
4164bca1 3916 }
3917 [(set_attr "conds" "clob")
3918 (set (attr "length")
3919 (if_then_else (eq_attr "is_thumb" "yes")
3920 (const_int 14)
1b7da4ac 3921 (const_int 12)))
3922 (set_attr "type" "multiple")]
4164bca1 3923)
3924
b49e3742 3925(define_code_iterator SAT [smin smax])
3926(define_code_iterator SATrev [smin smax])
3927(define_code_attr SATlo [(smin "1") (smax "2")])
3928(define_code_attr SAThi [(smin "2") (smax "1")])
3929
3930(define_insn "*satsi_<SAT:code>"
3931 [(set (match_operand:SI 0 "s_register_operand" "=r")
3932 (SAT:SI (SATrev:SI (match_operand:SI 3 "s_register_operand" "r")
3933 (match_operand:SI 1 "const_int_operand" "i"))
3934 (match_operand:SI 2 "const_int_operand" "i")))]
3935 "TARGET_32BIT && arm_arch6 && <SAT:CODE> != <SATrev:CODE>
3936 && arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>], NULL, NULL)"
3937{
3938 int mask;
3939 bool signed_sat;
3940 if (!arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>],
3941 &mask, &signed_sat))
3942 gcc_unreachable ();
3943
3944 operands[1] = GEN_INT (mask);
3945 if (signed_sat)
3946 return "ssat%?\t%0, %1, %3";
3947 else
3948 return "usat%?\t%0, %1, %3";
3949}
7c36fe71 3950 [(set_attr "predicable" "yes")
1b7da4ac 3951 (set_attr "predicable_short_it" "no")
3952 (set_attr "type" "alus_imm")]
bebe9bbb 3953)
b49e3742 3954
3955(define_insn "*satsi_<SAT:code>_shift"
3956 [(set (match_operand:SI 0 "s_register_operand" "=r")
3957 (SAT:SI (SATrev:SI (match_operator:SI 3 "sat_shift_operator"
3958 [(match_operand:SI 4 "s_register_operand" "r")
3959 (match_operand:SI 5 "const_int_operand" "i")])
3960 (match_operand:SI 1 "const_int_operand" "i"))
3961 (match_operand:SI 2 "const_int_operand" "i")))]
3962 "TARGET_32BIT && arm_arch6 && <SAT:CODE> != <SATrev:CODE>
3963 && arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>], NULL, NULL)"
3964{
3965 int mask;
3966 bool signed_sat;
3967 if (!arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>],
3968 &mask, &signed_sat))
3969 gcc_unreachable ();
3970
3971 operands[1] = GEN_INT (mask);
3972 if (signed_sat)
3973 return "ssat%?\t%0, %1, %4%S3";
3974 else
3975 return "usat%?\t%0, %1, %4%S3";
3976}
3977 [(set_attr "predicable" "yes")
7c36fe71 3978 (set_attr "predicable_short_it" "no")
b49e3742 3979 (set_attr "shift" "3")
d82e788e 3980 (set_attr "type" "logic_shift_reg")])
b11cae9e 3981\f
3982;; Shift and rotation insns
3983
a2cd141b 3984(define_expand "ashldi3"
3985 [(set (match_operand:DI 0 "s_register_operand" "")
3986 (ashift:DI (match_operand:DI 1 "s_register_operand" "")
aa06c51c 3987 (match_operand:SI 2 "general_operand" "")))]
25f905c2 3988 "TARGET_32BIT"
a2cd141b 3989 "
aa06c51c 3990 if (TARGET_NEON)
3991 {
3992 /* Delay the decision whether to use NEON or core-regs until
3993 register allocation. */
3994 emit_insn (gen_ashldi3_neon (operands[0], operands[1], operands[2]));
3995 DONE;
3996 }
3997 else
3998 {
3999 /* Only the NEON case can handle in-memory shift counts. */
4000 if (!reg_or_int_operand (operands[2], SImode))
4001 operands[2] = force_reg (SImode, operands[2]);
4002 }
4003
b805622c 4004 if (!CONST_INT_P (operands[2]) && TARGET_REALLY_IWMMXT)
ffcc986d 4005 ; /* No special preparation statements; expand pattern as above. */
4006 else
a2cd141b 4007 {
ffcc986d 4008 rtx scratch1, scratch2;
4009
8c4e8755 4010 if (operands[2] == CONST1_RTX (SImode))
a2cd141b 4011 {
4012 emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
4013 DONE;
4014 }
ffcc986d 4015
4016 /* Ideally we should use iwmmxt here if we could know that operands[1]
4017 ends up already living in an iwmmxt register. Otherwise it's
4018 cheaper to have the alternate code being generated than moving
4019 values to iwmmxt regs and back. */
4020
ffcc986d 4021 /* Expand operation using core-registers.
4022 'FAIL' would achieve the same thing, but this is a bit smarter. */
4023 scratch1 = gen_reg_rtx (SImode);
4024 scratch2 = gen_reg_rtx (SImode);
4025 arm_emit_coreregs_64bit_shift (ASHIFT, operands[0], operands[1],
4026 operands[2], scratch1, scratch2);
4027 DONE;
a2cd141b 4028 }
a2cd141b 4029 "
4030)
4031
2837e3fb 4032(define_insn "arm_ashldi3_1bit"
50ad1bf9 4033 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 4034 (ashift:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 4035 (const_int 1)))
4036 (clobber (reg:CC CC_REGNUM))]
25f905c2 4037 "TARGET_32BIT"
2837e3fb 4038 "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
a2cd141b 4039 [(set_attr "conds" "clob")
1b7da4ac 4040 (set_attr "length" "8")
4041 (set_attr "type" "multiple")]
a2cd141b 4042)
4043
87b22bf7 4044(define_expand "ashlsi3"
cffb2a26 4045 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 4046 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
4047 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 4048 "TARGET_EITHER"
87b22bf7 4049 "
0438d37f 4050 if (CONST_INT_P (operands[2])
8c4e8755 4051 && (UINTVAL (operands[2])) > 31)
87b22bf7 4052 {
4053 emit_insn (gen_movsi (operands[0], const0_rtx));
4054 DONE;
4055 }
cffb2a26 4056 "
4057)
4058
a2cd141b 4059(define_expand "ashrdi3"
4060 [(set (match_operand:DI 0 "s_register_operand" "")
4061 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
4062 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 4063 "TARGET_32BIT"
a2cd141b 4064 "
aa06c51c 4065 if (TARGET_NEON)
4066 {
4067 /* Delay the decision whether to use NEON or core-regs until
4068 register allocation. */
4069 emit_insn (gen_ashrdi3_neon (operands[0], operands[1], operands[2]));
4070 DONE;
4071 }
4072
b805622c 4073 if (!CONST_INT_P (operands[2]) && TARGET_REALLY_IWMMXT)
ffcc986d 4074 ; /* No special preparation statements; expand pattern as above. */
4075 else
a2cd141b 4076 {
ffcc986d 4077 rtx scratch1, scratch2;
4078
8c4e8755 4079 if (operands[2] == CONST1_RTX (SImode))
a2cd141b 4080 {
4081 emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
4082 DONE;
4083 }
ffcc986d 4084
4085 /* Ideally we should use iwmmxt here if we could know that operands[1]
4086 ends up already living in an iwmmxt register. Otherwise it's
4087 cheaper to have the alternate code being generated than moving
4088 values to iwmmxt regs and back. */
4089
ffcc986d 4090 /* Expand operation using core-registers.
4091 'FAIL' would achieve the same thing, but this is a bit smarter. */
4092 scratch1 = gen_reg_rtx (SImode);
4093 scratch2 = gen_reg_rtx (SImode);
4094 arm_emit_coreregs_64bit_shift (ASHIFTRT, operands[0], operands[1],
4095 operands[2], scratch1, scratch2);
4096 DONE;
a2cd141b 4097 }
a2cd141b 4098 "
4099)
4100
2837e3fb 4101(define_insn "arm_ashrdi3_1bit"
50ad1bf9 4102 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 4103 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 4104 (const_int 1)))
4105 (clobber (reg:CC CC_REGNUM))]
25f905c2 4106 "TARGET_32BIT"
2837e3fb 4107 "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
a2cd141b 4108 [(set_attr "conds" "clob")
1b7da4ac 4109 (set_attr "length" "8")
4110 (set_attr "type" "multiple")]
a2cd141b 4111)
4112
87b22bf7 4113(define_expand "ashrsi3"
cffb2a26 4114 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 4115 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
4116 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 4117 "TARGET_EITHER"
87b22bf7 4118 "
0438d37f 4119 if (CONST_INT_P (operands[2])
8c4e8755 4120 && UINTVAL (operands[2]) > 31)
87b22bf7 4121 operands[2] = GEN_INT (31);
cffb2a26 4122 "
4123)
4124
a2cd141b 4125(define_expand "lshrdi3"
4126 [(set (match_operand:DI 0 "s_register_operand" "")
4127 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
4128 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 4129 "TARGET_32BIT"
a2cd141b 4130 "
aa06c51c 4131 if (TARGET_NEON)
4132 {
4133 /* Delay the decision whether to use NEON or core-regs until
4134 register allocation. */
4135 emit_insn (gen_lshrdi3_neon (operands[0], operands[1], operands[2]));
4136 DONE;
4137 }
4138
b805622c 4139 if (!CONST_INT_P (operands[2]) && TARGET_REALLY_IWMMXT)
ffcc986d 4140 ; /* No special preparation statements; expand pattern as above. */
4141 else
a2cd141b 4142 {
ffcc986d 4143 rtx scratch1, scratch2;
4144
8c4e8755 4145 if (operands[2] == CONST1_RTX (SImode))
a2cd141b 4146 {
4147 emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
4148 DONE;
4149 }
ffcc986d 4150
4151 /* Ideally we should use iwmmxt here if we could know that operands[1]
4152 ends up already living in an iwmmxt register. Otherwise it's
4153 cheaper to have the alternate code being generated than moving
4154 values to iwmmxt regs and back. */
4155
ffcc986d 4156 /* Expand operation using core-registers.
4157 'FAIL' would achieve the same thing, but this is a bit smarter. */
4158 scratch1 = gen_reg_rtx (SImode);
4159 scratch2 = gen_reg_rtx (SImode);
4160 arm_emit_coreregs_64bit_shift (LSHIFTRT, operands[0], operands[1],
4161 operands[2], scratch1, scratch2);
4162 DONE;
a2cd141b 4163 }
a2cd141b 4164 "
4165)
4166
2837e3fb 4167(define_insn "arm_lshrdi3_1bit"
50ad1bf9 4168 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 4169 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 4170 (const_int 1)))
4171 (clobber (reg:CC CC_REGNUM))]
25f905c2 4172 "TARGET_32BIT"
2837e3fb 4173 "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
a2cd141b 4174 [(set_attr "conds" "clob")
1b7da4ac 4175 (set_attr "length" "8")
4176 (set_attr "type" "multiple")]
a2cd141b 4177)
4178
87b22bf7 4179(define_expand "lshrsi3"
cffb2a26 4180 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 4181 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
4182 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 4183 "TARGET_EITHER"
87b22bf7 4184 "
0438d37f 4185 if (CONST_INT_P (operands[2])
8c4e8755 4186 && (UINTVAL (operands[2])) > 31)
87b22bf7 4187 {
4188 emit_insn (gen_movsi (operands[0], const0_rtx));
4189 DONE;
4190 }
cffb2a26 4191 "
4192)
4193
87b22bf7 4194(define_expand "rotlsi3"
cffb2a26 4195 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 4196 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
4197 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 4198 "TARGET_32BIT"
87b22bf7 4199 "
0438d37f 4200 if (CONST_INT_P (operands[2]))
87b22bf7 4201 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
4202 else
b11cae9e 4203 {
87b22bf7 4204 rtx reg = gen_reg_rtx (SImode);
4205 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
4206 operands[2] = reg;
b11cae9e 4207 }
cffb2a26 4208 "
4209)
9c08d1fa 4210
87b22bf7 4211(define_expand "rotrsi3"
cffb2a26 4212 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 4213 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
4214 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 4215 "TARGET_EITHER"
87b22bf7 4216 "
25f905c2 4217 if (TARGET_32BIT)
cffb2a26 4218 {
0438d37f 4219 if (CONST_INT_P (operands[2])
8c4e8755 4220 && UINTVAL (operands[2]) > 31)
cffb2a26 4221 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
4222 }
25f905c2 4223 else /* TARGET_THUMB1 */
cffb2a26 4224 {
0438d37f 4225 if (CONST_INT_P (operands [2]))
cffb2a26 4226 operands [2] = force_reg (SImode, operands[2]);
4227 }
4228 "
4229)
87b22bf7 4230
cffb2a26 4231(define_insn "*arm_shiftsi3"
88c29385 4232 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r,r")
cffb2a26 4233 (match_operator:SI 3 "shift_operator"
88c29385 4234 [(match_operand:SI 1 "s_register_operand" "0,l,r,r")
4235 (match_operand:SI 2 "reg_or_int_operand" "l,M,M,r")]))]
25f905c2 4236 "TARGET_32BIT"
4237 "* return arm_output_shift(operands, 0);"
344495ea 4238 [(set_attr "predicable" "yes")
88c29385 4239 (set_attr "arch" "t2,t2,*,*")
4240 (set_attr "predicable_short_it" "yes,yes,no,no")
7c36fe71 4241 (set_attr "length" "4")
331beb1a 4242 (set_attr "shift" "1")
88c29385 4243 (set_attr "type" "alu_shift_reg,alu_shift_imm,alu_shift_imm,alu_shift_reg")]
6c4c2133 4244)
87b22bf7 4245
f7fbdd4a 4246(define_insn "*shiftsi3_compare0"
bd5b4116 4247 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 4248 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
6b6abc9c 4249 [(match_operand:SI 1 "s_register_operand" "r,r")
4250 (match_operand:SI 2 "arm_rhs_operand" "M,r")])
9c08d1fa 4251 (const_int 0)))
6b6abc9c 4252 (set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 4253 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
25f905c2 4254 "TARGET_32BIT"
4255 "* return arm_output_shift(operands, 1);"
344495ea 4256 [(set_attr "conds" "set")
331beb1a 4257 (set_attr "shift" "1")
d82e788e 4258 (set_attr "type" "alus_shift_imm,alus_shift_reg")]
0d66636f 4259)
9c08d1fa 4260
f7fbdd4a 4261(define_insn "*shiftsi3_compare0_scratch"
bd5b4116 4262 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 4263 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
6b6abc9c 4264 [(match_operand:SI 1 "s_register_operand" "r,r")
4265 (match_operand:SI 2 "arm_rhs_operand" "M,r")])
9c08d1fa 4266 (const_int 0)))
6b6abc9c 4267 (clobber (match_scratch:SI 0 "=r,r"))]
25f905c2 4268 "TARGET_32BIT"
4269 "* return arm_output_shift(operands, 1);"
344495ea 4270 [(set_attr "conds" "set")
6b6abc9c 4271 (set_attr "shift" "1")
d82e788e 4272 (set_attr "type" "shift_imm,shift_reg")]
0d66636f 4273)
9c08d1fa 4274
d5d4dc8d 4275(define_insn "*not_shiftsi"
4276 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 4277 (not:SI (match_operator:SI 3 "shift_operator"
d5d4dc8d 4278 [(match_operand:SI 1 "s_register_operand" "r,r")
4279 (match_operand:SI 2 "shift_amount_operand" "M,rM")])))]
4280 "TARGET_32BIT"
6c4c2133 4281 "mvn%?\\t%0, %1%S3"
344495ea 4282 [(set_attr "predicable" "yes")
d952d547 4283 (set_attr "predicable_short_it" "no")
331beb1a 4284 (set_attr "shift" "1")
d5d4dc8d 4285 (set_attr "arch" "32,a")
1aed5204 4286 (set_attr "type" "mvn_shift,mvn_shift_reg")])
9c08d1fa 4287
d5d4dc8d 4288(define_insn "*not_shiftsi_compare0"
bd5b4116 4289 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 4290 (compare:CC_NOOV
4291 (not:SI (match_operator:SI 3 "shift_operator"
4292 [(match_operand:SI 1 "s_register_operand" "r,r")
4293 (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
4294 (const_int 0)))
4295 (set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 4296 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
d5d4dc8d 4297 "TARGET_32BIT"
3ef90e77 4298 "mvns%?\\t%0, %1%S3"
344495ea 4299 [(set_attr "conds" "set")
331beb1a 4300 (set_attr "shift" "1")
d5d4dc8d 4301 (set_attr "arch" "32,a")
1aed5204 4302 (set_attr "type" "mvn_shift,mvn_shift_reg")])
9c08d1fa 4303
d5d4dc8d 4304(define_insn "*not_shiftsi_compare0_scratch"
bd5b4116 4305 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 4306 (compare:CC_NOOV
4307 (not:SI (match_operator:SI 3 "shift_operator"
4308 [(match_operand:SI 1 "s_register_operand" "r,r")
4309 (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
4310 (const_int 0)))
4311 (clobber (match_scratch:SI 0 "=r,r"))]
4312 "TARGET_32BIT"
3ef90e77 4313 "mvns%?\\t%0, %1%S3"
344495ea 4314 [(set_attr "conds" "set")
331beb1a 4315 (set_attr "shift" "1")
d5d4dc8d 4316 (set_attr "arch" "32,a")
1aed5204 4317 (set_attr "type" "mvn_shift,mvn_shift_reg")])
9c08d1fa 4318
cffb2a26 4319;; We don't really have extzv, but defining this using shifts helps
4320;; to reduce register pressure later on.
4321
4322(define_expand "extzv"
eb04cafb 4323 [(set (match_operand 0 "s_register_operand" "")
4324 (zero_extract (match_operand 1 "nonimmediate_operand" "")
4325 (match_operand 2 "const_int_operand" "")
4326 (match_operand 3 "const_int_operand" "")))]
8b054d5a 4327 "TARGET_THUMB1 || arm_arch_thumb2"
cffb2a26 4328 "
4329 {
4330 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
4331 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
4332
8b054d5a 4333 if (arm_arch_thumb2)
4334 {
eb04cafb 4335 HOST_WIDE_INT width = INTVAL (operands[2]);
4336 HOST_WIDE_INT bitpos = INTVAL (operands[3]);
4337
4338 if (unaligned_access && MEM_P (operands[1])
4339 && (width == 16 || width == 32) && (bitpos % BITS_PER_UNIT) == 0)
4340 {
4341 rtx base_addr;
4342
4343 if (BYTES_BIG_ENDIAN)
4344 bitpos = GET_MODE_BITSIZE (GET_MODE (operands[0])) - width
4345 - bitpos;
4346
4347 if (width == 32)
4348 {
4349 base_addr = adjust_address (operands[1], SImode,
4350 bitpos / BITS_PER_UNIT);
4351 emit_insn (gen_unaligned_loadsi (operands[0], base_addr));
4352 }
4353 else
4354 {
4355 rtx dest = operands[0];
4356 rtx tmp = gen_reg_rtx (SImode);
4357
4358 /* We may get a paradoxical subreg here. Strip it off. */
4359 if (GET_CODE (dest) == SUBREG
4360 && GET_MODE (dest) == SImode
4361 && GET_MODE (SUBREG_REG (dest)) == HImode)
4362 dest = SUBREG_REG (dest);
4363
4364 if (GET_MODE_BITSIZE (GET_MODE (dest)) != width)
4365 FAIL;
4366
4367 base_addr = adjust_address (operands[1], HImode,
4368 bitpos / BITS_PER_UNIT);
4369 emit_insn (gen_unaligned_loadhiu (tmp, base_addr));
4370 emit_move_insn (gen_lowpart (SImode, dest), tmp);
4371 }
4372 DONE;
4373 }
4374 else if (s_register_operand (operands[1], GET_MODE (operands[1])))
4375 {
4376 emit_insn (gen_extzv_t2 (operands[0], operands[1], operands[2],
4377 operands[3]));
4378 DONE;
4379 }
4380 else
4381 FAIL;
8b054d5a 4382 }
eb04cafb 4383
4384 if (!s_register_operand (operands[1], GET_MODE (operands[1])))
4385 FAIL;
8b054d5a 4386
cffb2a26 4387 operands[3] = GEN_INT (rshift);
4388
4389 if (lshift == 0)
4390 {
4391 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
4392 DONE;
4393 }
4394
eb04cafb 4395 emit_insn (gen_extzv_t1 (operands[0], operands[1], GEN_INT (lshift),
4396 operands[3], gen_reg_rtx (SImode)));
4397 DONE;
215b30b3 4398 }"
cffb2a26 4399)
4400
eb04cafb 4401;; Helper for extzv, for the Thumb-1 register-shifts case.
4402
4403(define_expand "extzv_t1"
4404 [(set (match_operand:SI 4 "s_register_operand" "")
4405 (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "")
4406 (match_operand:SI 2 "const_int_operand" "")))
4407 (set (match_operand:SI 0 "s_register_operand" "")
4408 (lshiftrt:SI (match_dup 4)
4409 (match_operand:SI 3 "const_int_operand" "")))]
4410 "TARGET_THUMB1"
4411 "")
4412
4413(define_expand "extv"
4414 [(set (match_operand 0 "s_register_operand" "")
4415 (sign_extract (match_operand 1 "nonimmediate_operand" "")
4416 (match_operand 2 "const_int_operand" "")
4417 (match_operand 3 "const_int_operand" "")))]
4418 "arm_arch_thumb2"
4419{
4420 HOST_WIDE_INT width = INTVAL (operands[2]);
4421 HOST_WIDE_INT bitpos = INTVAL (operands[3]);
4422
4423 if (unaligned_access && MEM_P (operands[1]) && (width == 16 || width == 32)
4424 && (bitpos % BITS_PER_UNIT) == 0)
4425 {
4426 rtx base_addr;
4427
4428 if (BYTES_BIG_ENDIAN)
4429 bitpos = GET_MODE_BITSIZE (GET_MODE (operands[0])) - width - bitpos;
4430
4431 if (width == 32)
4432 {
4433 base_addr = adjust_address (operands[1], SImode,
4434 bitpos / BITS_PER_UNIT);
4435 emit_insn (gen_unaligned_loadsi (operands[0], base_addr));
4436 }
4437 else
4438 {
4439 rtx dest = operands[0];
4440 rtx tmp = gen_reg_rtx (SImode);
4441
4442 /* We may get a paradoxical subreg here. Strip it off. */
4443 if (GET_CODE (dest) == SUBREG
4444 && GET_MODE (dest) == SImode
4445 && GET_MODE (SUBREG_REG (dest)) == HImode)
4446 dest = SUBREG_REG (dest);
4447
4448 if (GET_MODE_BITSIZE (GET_MODE (dest)) != width)
4449 FAIL;
4450
4451 base_addr = adjust_address (operands[1], HImode,
4452 bitpos / BITS_PER_UNIT);
4453 emit_insn (gen_unaligned_loadhis (tmp, base_addr));
4454 emit_move_insn (gen_lowpart (SImode, dest), tmp);
4455 }
4456
4457 DONE;
4458 }
4459 else if (!s_register_operand (operands[1], GET_MODE (operands[1])))
4460 FAIL;
4461 else if (GET_MODE (operands[0]) == SImode
4462 && GET_MODE (operands[1]) == SImode)
4463 {
4464 emit_insn (gen_extv_regsi (operands[0], operands[1], operands[2],
4465 operands[3]));
4466 DONE;
4467 }
4468
4469 FAIL;
4470})
4471
4472; Helper to expand register forms of extv with the proper modes.
4473
4474(define_expand "extv_regsi"
4475 [(set (match_operand:SI 0 "s_register_operand" "")
4476 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
4477 (match_operand 2 "const_int_operand" "")
4478 (match_operand 3 "const_int_operand" "")))]
4479 ""
4480{
4481})
4482
4483; ARMv6+ unaligned load/store instructions (used for packed structure accesses).
4484
4485(define_insn "unaligned_loadsi"
4486 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4487 (unspec:SI [(match_operand:SI 1 "memory_operand" "Uw,m")]
4488 UNSPEC_UNALIGNED_LOAD))]
8fe38eb2 4489 "unaligned_access"
eb04cafb 4490 "ldr%?\t%0, %1\t@ unaligned"
4491 [(set_attr "arch" "t2,any")
4492 (set_attr "length" "2,4")
4493 (set_attr "predicable" "yes")
d952d547 4494 (set_attr "predicable_short_it" "yes,no")
eb04cafb 4495 (set_attr "type" "load1")])
4496
4497(define_insn "unaligned_loadhis"
4498 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4499 (sign_extend:SI
e3f4ccee 4500 (unspec:HI [(match_operand:HI 1 "memory_operand" "Uw,Uh")]
eb04cafb 4501 UNSPEC_UNALIGNED_LOAD)))]
8fe38eb2 4502 "unaligned_access"
3ef90e77 4503 "ldrsh%?\t%0, %1\t@ unaligned"
eb04cafb 4504 [(set_attr "arch" "t2,any")
4505 (set_attr "length" "2,4")
4506 (set_attr "predicable" "yes")
d952d547 4507 (set_attr "predicable_short_it" "yes,no")
eb04cafb 4508 (set_attr "type" "load_byte")])
4509
4510(define_insn "unaligned_loadhiu"
4511 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4512 (zero_extend:SI
4513 (unspec:HI [(match_operand:HI 1 "memory_operand" "Uw,m")]
4514 UNSPEC_UNALIGNED_LOAD)))]
8fe38eb2 4515 "unaligned_access"
3ef90e77 4516 "ldrh%?\t%0, %1\t@ unaligned"
eb04cafb 4517 [(set_attr "arch" "t2,any")
4518 (set_attr "length" "2,4")
4519 (set_attr "predicable" "yes")
d952d547 4520 (set_attr "predicable_short_it" "yes,no")
eb04cafb 4521 (set_attr "type" "load_byte")])
4522
4523(define_insn "unaligned_storesi"
4524 [(set (match_operand:SI 0 "memory_operand" "=Uw,m")
4525 (unspec:SI [(match_operand:SI 1 "s_register_operand" "l,r")]
4526 UNSPEC_UNALIGNED_STORE))]
8fe38eb2 4527 "unaligned_access"
eb04cafb 4528 "str%?\t%1, %0\t@ unaligned"
4529 [(set_attr "arch" "t2,any")
4530 (set_attr "length" "2,4")
4531 (set_attr "predicable" "yes")
d952d547 4532 (set_attr "predicable_short_it" "yes,no")
eb04cafb 4533 (set_attr "type" "store1")])
4534
4535(define_insn "unaligned_storehi"
4536 [(set (match_operand:HI 0 "memory_operand" "=Uw,m")
4537 (unspec:HI [(match_operand:HI 1 "s_register_operand" "l,r")]
4538 UNSPEC_UNALIGNED_STORE))]
8fe38eb2 4539 "unaligned_access"
3ef90e77 4540 "strh%?\t%1, %0\t@ unaligned"
eb04cafb 4541 [(set_attr "arch" "t2,any")
4542 (set_attr "length" "2,4")
4543 (set_attr "predicable" "yes")
d952d547 4544 (set_attr "predicable_short_it" "yes,no")
eb04cafb 4545 (set_attr "type" "store1")])
4546
ae51a965 4547
eb04cafb 4548(define_insn "*extv_reg"
8b054d5a 4549 [(set (match_operand:SI 0 "s_register_operand" "=r")
4550 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
13051f13 4551 (match_operand:SI 2 "const_int_operand" "n")
4552 (match_operand:SI 3 "const_int_operand" "n")))]
4553 "arm_arch_thumb2
4554 && IN_RANGE (INTVAL (operands[3]), 0, 31)
4555 && IN_RANGE (INTVAL (operands[2]), 1, 32 - INTVAL (operands[3]))"
8b054d5a 4556 "sbfx%?\t%0, %1, %3, %2"
4557 [(set_attr "length" "4")
d952d547 4558 (set_attr "predicable" "yes")
d82e788e 4559 (set_attr "predicable_short_it" "no")
4560 (set_attr "type" "bfm")]
8b054d5a 4561)
4562
4563(define_insn "extzv_t2"
4564 [(set (match_operand:SI 0 "s_register_operand" "=r")
4565 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "r")
13051f13 4566 (match_operand:SI 2 "const_int_operand" "n")
4567 (match_operand:SI 3 "const_int_operand" "n")))]
4568 "arm_arch_thumb2
4569 && IN_RANGE (INTVAL (operands[3]), 0, 31)
4570 && IN_RANGE (INTVAL (operands[2]), 1, 32 - INTVAL (operands[3]))"
8b054d5a 4571 "ubfx%?\t%0, %1, %3, %2"
4572 [(set_attr "length" "4")
d952d547 4573 (set_attr "predicable" "yes")
d82e788e 4574 (set_attr "predicable_short_it" "no")
4575 (set_attr "type" "bfm")]
8b054d5a 4576)
4577
7d3cda8c 4578
4579;; Division instructions
4580(define_insn "divsi3"
8f5f2788 4581 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4582 (div:SI (match_operand:SI 1 "s_register_operand" "r,r")
4583 (match_operand:SI 2 "s_register_operand" "r,r")))]
7d3cda8c 4584 "TARGET_IDIV"
8f5f2788 4585 "@
4586 sdiv%?\t%0, %1, %2
4587 sdiv\t%0, %1, %2"
4588 [(set_attr "arch" "32,v8mb")
4589 (set_attr "predicable" "yes")
d952d547 4590 (set_attr "predicable_short_it" "no")
9da0ec36 4591 (set_attr "type" "sdiv")]
7d3cda8c 4592)
4593
4594(define_insn "udivsi3"
8f5f2788 4595 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4596 (udiv:SI (match_operand:SI 1 "s_register_operand" "r,r")
4597 (match_operand:SI 2 "s_register_operand" "r,r")))]
7d3cda8c 4598 "TARGET_IDIV"
8f5f2788 4599 "@
4600 udiv%?\t%0, %1, %2
4601 udiv\t%0, %1, %2"
4602 [(set_attr "arch" "32,v8mb")
4603 (set_attr "predicable" "yes")
d952d547 4604 (set_attr "predicable_short_it" "no")
9da0ec36 4605 (set_attr "type" "udiv")]
7d3cda8c 4606)
4607
b11cae9e 4608\f
4609;; Unary arithmetic insns
4610
f6c98a9a 4611(define_expand "negvsi3"
4612 [(match_operand:SI 0 "register_operand")
4613 (match_operand:SI 1 "register_operand")
4614 (match_operand 2 "")]
4615 "TARGET_32BIT"
4616{
4617 emit_insn (gen_subsi3_compare (operands[0], const0_rtx, operands[1]));
4618 arm_gen_unlikely_cbranch (NE, CC_Vmode, operands[2]);
4619
4620 DONE;
4621})
4622
4623(define_expand "negvdi3"
4624 [(match_operand:DI 0 "register_operand")
4625 (match_operand:DI 1 "register_operand")
4626 (match_operand 2 "")]
4627 "TARGET_ARM"
4628{
4629 emit_insn (gen_negdi2_compare (operands[0], operands[1]));
4630 arm_gen_unlikely_cbranch (NE, CC_Vmode, operands[2]);
4631
4632 DONE;
4633})
4634
4635
4636(define_insn_and_split "negdi2_compare"
4637 [(set (reg:CC CC_REGNUM)
4638 (compare:CC
4639 (const_int 0)
4640 (match_operand:DI 1 "register_operand" "0,r")))
4641 (set (match_operand:DI 0 "register_operand" "=r,&r")
4642 (minus:DI (const_int 0) (match_dup 1)))]
4643 "TARGET_ARM"
4644 "#"
4645 "&& reload_completed"
4646 [(parallel [(set (reg:CC CC_REGNUM)
4647 (compare:CC (const_int 0) (match_dup 1)))
4648 (set (match_dup 0) (minus:SI (const_int 0)
4649 (match_dup 1)))])
4650 (parallel [(set (reg:CC CC_REGNUM)
4651 (compare:CC (const_int 0) (match_dup 3)))
4652 (set (match_dup 2)
4653 (minus:SI
4654 (minus:SI (const_int 0) (match_dup 3))
4655 (ltu:SI (reg:CC_C CC_REGNUM)
4656 (const_int 0))))])]
4657 {
4658 operands[2] = gen_highpart (SImode, operands[0]);
4659 operands[0] = gen_lowpart (SImode, operands[0]);
4660 operands[3] = gen_highpart (SImode, operands[1]);
4661 operands[1] = gen_lowpart (SImode, operands[1]);
4662 }
4663 [(set_attr "conds" "set")
4664 (set_attr "length" "8")
4665 (set_attr "type" "multiple")]
4666)
4667
cffb2a26 4668(define_expand "negdi2"
4669 [(parallel
8135a42b 4670 [(set (match_operand:DI 0 "s_register_operand" "")
4671 (neg:DI (match_operand:DI 1 "s_register_operand" "")))
bd5b4116 4672 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 4673 "TARGET_EITHER"
774d2fbb 4674 {
4675 if (TARGET_NEON)
4676 {
4677 emit_insn (gen_negdi2_neon (operands[0], operands[1]));
4678 DONE;
4679 }
4680 }
cffb2a26 4681)
4682
4683;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
e5fea38e 4684;; The first alternative allows the common case of a *full* overlap.
d5bf2b53 4685(define_insn_and_split "*negdi2_insn"
458a8706 4686 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 4687 (neg:DI (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 4688 (clobber (reg:CC CC_REGNUM))]
d5bf2b53 4689 "TARGET_32BIT"
4690 "#" ; rsbs %Q0, %Q1, #0; rsc %R0, %R1, #0 (ARM)
4691 ; negs %Q0, %Q1 ; sbc %R0, %R1, %R1, lsl #1 (Thumb-2)
ba6a3b2f 4692 "&& reload_completed"
4693 [(parallel [(set (reg:CC CC_REGNUM)
4694 (compare:CC (const_int 0) (match_dup 1)))
4695 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 1)))])
4696 (set (match_dup 2) (minus:SI (minus:SI (const_int 0) (match_dup 3))
4697 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
4698 {
4699 operands[2] = gen_highpart (SImode, operands[0]);
4700 operands[0] = gen_lowpart (SImode, operands[0]);
4701 operands[3] = gen_highpart (SImode, operands[1]);
4702 operands[1] = gen_lowpart (SImode, operands[1]);
4703 }
cffb2a26 4704 [(set_attr "conds" "clob")
1b7da4ac 4705 (set_attr "length" "8")
4706 (set_attr "type" "multiple")]
cffb2a26 4707)
b11cae9e 4708
f6c98a9a 4709(define_insn "*negsi2_carryin_compare"
4710 [(set (reg:CC CC_REGNUM)
4711 (compare:CC (const_int 0)
4712 (match_operand:SI 1 "s_register_operand" "r")))
4713 (set (match_operand:SI 0 "s_register_operand" "=r")
4714 (minus:SI (minus:SI (const_int 0)
4715 (match_dup 1))
4716 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
4717 "TARGET_ARM"
4718 "rscs\\t%0, %1, #0"
4719 [(set_attr "conds" "set")
4720 (set_attr "type" "alus_imm")]
4721)
4722
cffb2a26 4723(define_expand "negsi2"
4724 [(set (match_operand:SI 0 "s_register_operand" "")
4725 (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
4726 "TARGET_EITHER"
b11cae9e 4727 ""
cffb2a26 4728)
4729
4730(define_insn "*arm_negsi2"
d952d547 4731 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4732 (neg:SI (match_operand:SI 1 "s_register_operand" "l,r")))]
25f905c2 4733 "TARGET_32BIT"
cffb2a26 4734 "rsb%?\\t%0, %1, #0"
d952d547 4735 [(set_attr "predicable" "yes")
4736 (set_attr "predicable_short_it" "yes,no")
4737 (set_attr "arch" "t2,*")
1b7da4ac 4738 (set_attr "length" "4")
112eda6f 4739 (set_attr "type" "alu_sreg")]
cffb2a26 4740)
4741
604f3a0a 4742(define_expand "negsf2"
4743 [(set (match_operand:SF 0 "s_register_operand" "")
4744 (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
d7216193 4745 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 4746 ""
4747)
4748
4749(define_expand "negdf2"
4750 [(set (match_operand:DF 0 "s_register_operand" "")
4751 (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
994606f8 4752 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
604f3a0a 4753 "")
4754
7eaf2be0 4755(define_insn_and_split "*zextendsidi_negsi"
4756 [(set (match_operand:DI 0 "s_register_operand" "=r")
4757 (zero_extend:DI (neg:SI (match_operand:SI 1 "s_register_operand" "r"))))]
4758 "TARGET_32BIT"
4759 "#"
4760 ""
4761 [(set (match_dup 2)
4762 (neg:SI (match_dup 1)))
4763 (set (match_dup 3)
4764 (const_int 0))]
4765 {
4766 operands[2] = gen_lowpart (SImode, operands[0]);
4767 operands[3] = gen_highpart (SImode, operands[0]);
4768 }
4769 [(set_attr "length" "8")
4770 (set_attr "type" "multiple")]
4771)
4772
83e2b922 4773;; Negate an extended 32-bit value.
4774(define_insn_and_split "*negdi_extendsidi"
61fa8ff2 4775 [(set (match_operand:DI 0 "s_register_operand" "=l,r")
4776 (neg:DI (sign_extend:DI
4777 (match_operand:SI 1 "s_register_operand" "l,r"))))
83e2b922 4778 (clobber (reg:CC CC_REGNUM))]
4779 "TARGET_32BIT"
61fa8ff2 4780 "#"
83e2b922 4781 "&& reload_completed"
4782 [(const_int 0)]
4783 {
61fa8ff2 4784 rtx low = gen_lowpart (SImode, operands[0]);
4785 rtx high = gen_highpart (SImode, operands[0]);
4786
4787 if (reg_overlap_mentioned_p (low, operands[1]))
4788 {
4789 /* Input overlaps the low word of the output. Use:
4790 asr Rhi, Rin, #31
4791 rsbs Rlo, Rin, #0
4792 rsc Rhi, Rhi, #0 (thumb2: sbc Rhi, Rhi, Rhi, lsl #1). */
4793 rtx cc_reg = gen_rtx_REG (CC_Cmode, CC_REGNUM);
4794
d1f9b275 4795 emit_insn (gen_rtx_SET (high,
61fa8ff2 4796 gen_rtx_ASHIFTRT (SImode, operands[1],
4797 GEN_INT (31))));
4798
4799 emit_insn (gen_subsi3_compare (low, const0_rtx, operands[1]));
4800 if (TARGET_ARM)
d1f9b275 4801 emit_insn (gen_rtx_SET (high,
61fa8ff2 4802 gen_rtx_MINUS (SImode,
4803 gen_rtx_MINUS (SImode,
4804 const0_rtx,
4805 high),
4806 gen_rtx_LTU (SImode,
4807 cc_reg,
4808 const0_rtx))));
4809 else
4810 {
4811 rtx two_x = gen_rtx_ASHIFT (SImode, high, GEN_INT (1));
d1f9b275 4812 emit_insn (gen_rtx_SET (high,
61fa8ff2 4813 gen_rtx_MINUS (SImode,
4814 gen_rtx_MINUS (SImode,
4815 high,
4816 two_x),
4817 gen_rtx_LTU (SImode,
4818 cc_reg,
4819 const0_rtx))));
4820 }
4821 }
4822 else
4823 {
4824 /* No overlap, or overlap on high word. Use:
4825 rsb Rlo, Rin, #0
4826 bic Rhi, Rlo, Rin
4827 asr Rhi, Rhi, #31
4828 Flags not needed for this sequence. */
d1f9b275 4829 emit_insn (gen_rtx_SET (low, gen_rtx_NEG (SImode, operands[1])));
4830 emit_insn (gen_rtx_SET (high,
61fa8ff2 4831 gen_rtx_AND (SImode,
4832 gen_rtx_NOT (SImode, operands[1]),
4833 low)));
d1f9b275 4834 emit_insn (gen_rtx_SET (high,
61fa8ff2 4835 gen_rtx_ASHIFTRT (SImode, high,
4836 GEN_INT (31))));
4837 }
4838 DONE;
83e2b922 4839 }
61fa8ff2 4840 [(set_attr "length" "12")
4841 (set_attr "arch" "t2,*")
1b7da4ac 4842 (set_attr "type" "multiple")]
83e2b922 4843)
4844
4845(define_insn_and_split "*negdi_zero_extendsidi"
4846 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
4847 (neg:DI (zero_extend:DI (match_operand:SI 1 "s_register_operand" "0,r"))))
4848 (clobber (reg:CC CC_REGNUM))]
4849 "TARGET_32BIT"
4850 "#" ; "rsbs\\t%Q0, %1, #0\;sbc\\t%R0,%R0,%R0"
4851 ;; Don't care what register is input to sbc,
47ae02b7 4852 ;; since we just need to propagate the carry.
83e2b922 4853 "&& reload_completed"
4854 [(parallel [(set (reg:CC CC_REGNUM)
4855 (compare:CC (const_int 0) (match_dup 1)))
4856 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 1)))])
4857 (set (match_dup 2) (minus:SI (minus:SI (match_dup 2) (match_dup 2))
4858 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
4859 {
4860 operands[2] = gen_highpart (SImode, operands[0]);
4861 operands[0] = gen_lowpart (SImode, operands[0]);
4862 }
4863 [(set_attr "conds" "clob")
1b7da4ac 4864 (set_attr "length" "8")
4865 (set_attr "type" "multiple")] ;; length in thumb is 4
83e2b922 4866)
4867
9c08d1fa 4868;; abssi2 doesn't really clobber the condition codes if a different register
4869;; is being set. To keep things simple, assume during rtl manipulations that
4870;; it does, but tell the final scan operator the truth. Similarly for
4871;; (neg (abs...))
4872
604f3a0a 4873(define_expand "abssi2"
4874 [(parallel
4875 [(set (match_operand:SI 0 "s_register_operand" "")
4876 (abs:SI (match_operand:SI 1 "s_register_operand" "")))
ba156559 4877 (clobber (match_dup 2))])]
4878 "TARGET_EITHER"
4879 "
25f905c2 4880 if (TARGET_THUMB1)
ba156559 4881 operands[2] = gen_rtx_SCRATCH (SImode);
4882 else
4883 operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
4884")
604f3a0a 4885
ba6a3b2f 4886(define_insn_and_split "*arm_abssi2"
ba156559 4887 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
9c08d1fa 4888 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
bd5b4116 4889 (clobber (reg:CC CC_REGNUM))]
cffb2a26 4890 "TARGET_ARM"
ba6a3b2f 4891 "#"
4892 "&& reload_completed"
4893 [(const_int 0)]
4894 {
4895 /* if (which_alternative == 0) */
4896 if (REGNO(operands[0]) == REGNO(operands[1]))
4897 {
4898 /* Emit the pattern:
4899 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
4900 [(set (reg:CC CC_REGNUM)
4901 (compare:CC (match_dup 0) (const_int 0)))
4902 (cond_exec (lt:CC (reg:CC CC_REGNUM) (const_int 0))
4903 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 1))))]
4904 */
d1f9b275 4905 emit_insn (gen_rtx_SET (gen_rtx_REG (CCmode, CC_REGNUM),
ba6a3b2f 4906 gen_rtx_COMPARE (CCmode, operands[0], const0_rtx)));
4907 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
4908 (gen_rtx_LT (SImode,
4909 gen_rtx_REG (CCmode, CC_REGNUM),
4910 const0_rtx)),
d1f9b275 4911 (gen_rtx_SET (operands[0],
ba6a3b2f 4912 (gen_rtx_MINUS (SImode,
4913 const0_rtx,
4914 operands[1]))))));
4915 DONE;
4916 }
4917 else
4918 {
4919 /* Emit the pattern:
4920 alt1: eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31
4921 [(set (match_dup 0)
4922 (xor:SI (match_dup 1)
4923 (ashiftrt:SI (match_dup 1) (const_int 31))))
4924 (set (match_dup 0)
4925 (minus:SI (match_dup 0)
4926 (ashiftrt:SI (match_dup 1) (const_int 31))))]
4927 */
d1f9b275 4928 emit_insn (gen_rtx_SET (operands[0],
ba6a3b2f 4929 gen_rtx_XOR (SImode,
4930 gen_rtx_ASHIFTRT (SImode,
4931 operands[1],
4932 GEN_INT (31)),
4933 operands[1])));
d1f9b275 4934 emit_insn (gen_rtx_SET (operands[0],
ba6a3b2f 4935 gen_rtx_MINUS (SImode,
4936 operands[0],
4937 gen_rtx_ASHIFTRT (SImode,
4938 operands[1],
4939 GEN_INT (31)))));
4940 DONE;
4941 }
4942 }
cffb2a26 4943 [(set_attr "conds" "clob,*")
331beb1a 4944 (set_attr "shift" "1")
2ad08b65 4945 (set_attr "predicable" "no, yes")
1b7da4ac 4946 (set_attr "length" "8")
4947 (set_attr "type" "multiple")]
cffb2a26 4948)
9c08d1fa 4949
ba6a3b2f 4950(define_insn_and_split "*arm_neg_abssi2"
9c08d1fa 4951 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
4952 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
bd5b4116 4953 (clobber (reg:CC CC_REGNUM))]
cffb2a26 4954 "TARGET_ARM"
ba6a3b2f 4955 "#"
4956 "&& reload_completed"
4957 [(const_int 0)]
4958 {
4959 /* if (which_alternative == 0) */
4960 if (REGNO (operands[0]) == REGNO (operands[1]))
4961 {
4962 /* Emit the pattern:
4963 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
4964 */
d1f9b275 4965 emit_insn (gen_rtx_SET (gen_rtx_REG (CCmode, CC_REGNUM),
ba6a3b2f 4966 gen_rtx_COMPARE (CCmode, operands[0], const0_rtx)));
4967 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
4968 gen_rtx_GT (SImode,
4969 gen_rtx_REG (CCmode, CC_REGNUM),
4970 const0_rtx),
d1f9b275 4971 gen_rtx_SET (operands[0],
ba6a3b2f 4972 (gen_rtx_MINUS (SImode,
4973 const0_rtx,
4974 operands[1])))));
4975 }
4976 else
4977 {
4978 /* Emit the pattern:
4979 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31
4980 */
d1f9b275 4981 emit_insn (gen_rtx_SET (operands[0],
ba6a3b2f 4982 gen_rtx_XOR (SImode,
4983 gen_rtx_ASHIFTRT (SImode,
4984 operands[1],
4985 GEN_INT (31)),
4986 operands[1])));
d1f9b275 4987 emit_insn (gen_rtx_SET (operands[0],
ba6a3b2f 4988 gen_rtx_MINUS (SImode,
4989 gen_rtx_ASHIFTRT (SImode,
4990 operands[1],
4991 GEN_INT (31)),
4992 operands[0])));
4993 }
4994 DONE;
4995 }
cffb2a26 4996 [(set_attr "conds" "clob,*")
331beb1a 4997 (set_attr "shift" "1")
2ad08b65 4998 (set_attr "predicable" "no, yes")
1b7da4ac 4999 (set_attr "length" "8")
5000 (set_attr "type" "multiple")]
cffb2a26 5001)
b11cae9e 5002
604f3a0a 5003(define_expand "abssf2"
5004 [(set (match_operand:SF 0 "s_register_operand" "")
5005 (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
25f905c2 5006 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 5007 "")
5008
604f3a0a 5009(define_expand "absdf2"
5010 [(set (match_operand:DF 0 "s_register_operand" "")
5011 (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 5012 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 5013 "")
5014
7db9af5d 5015(define_expand "sqrtsf2"
5016 [(set (match_operand:SF 0 "s_register_operand" "")
5017 (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
d7216193 5018 "TARGET_32BIT && TARGET_HARD_FLOAT"
7db9af5d 5019 "")
9c08d1fa 5020
7db9af5d 5021(define_expand "sqrtdf2"
5022 [(set (match_operand:DF 0 "s_register_operand" "")
5023 (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
994606f8 5024 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
7db9af5d 5025 "")
9c08d1fa 5026
a0f94409 5027(define_insn_and_split "one_cmpldi2"
10efb95f 5028 [(set (match_operand:DI 0 "s_register_operand" "=w,&r,&r,?w")
5029 (not:DI (match_operand:DI 1 "s_register_operand" " w, 0, r, w")))]
25f905c2 5030 "TARGET_32BIT"
10efb95f 5031 "@
5032 vmvn\t%P0, %P1
5033 #
5034 #
5035 vmvn\t%P0, %P1"
5036 "TARGET_32BIT && reload_completed
5037 && arm_general_register_operand (operands[0], DImode)"
a0f94409 5038 [(set (match_dup 0) (not:SI (match_dup 1)))
5039 (set (match_dup 2) (not:SI (match_dup 3)))]
5040 "
5041 {
5042 operands[2] = gen_highpart (SImode, operands[0]);
5043 operands[0] = gen_lowpart (SImode, operands[0]);
5044 operands[3] = gen_highpart (SImode, operands[1]);
5045 operands[1] = gen_lowpart (SImode, operands[1]);
5046 }"
10efb95f 5047 [(set_attr "length" "*,8,8,*")
5048 (set_attr "predicable" "no,yes,yes,no")
32093010 5049 (set_attr "type" "neon_move,multiple,multiple,neon_move")
b6779ddc 5050 (set_attr "arch" "neon_for_64bits,*,*,avoid_neon_for_64bits")]
cffb2a26 5051)
b11cae9e 5052
cffb2a26 5053(define_expand "one_cmplsi2"
5054 [(set (match_operand:SI 0 "s_register_operand" "")
5055 (not:SI (match_operand:SI 1 "s_register_operand" "")))]
5056 "TARGET_EITHER"
b11cae9e 5057 ""
cffb2a26 5058)
5059
5060(define_insn "*arm_one_cmplsi2"
d952d547 5061 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
5062 (not:SI (match_operand:SI 1 "s_register_operand" "l,r")))]
25f905c2 5063 "TARGET_32BIT"
cffb2a26 5064 "mvn%?\\t%0, %1"
d2a518d1 5065 [(set_attr "predicable" "yes")
d952d547 5066 (set_attr "predicable_short_it" "yes,no")
5067 (set_attr "arch" "t2,*")
5068 (set_attr "length" "4")
1aed5204 5069 (set_attr "type" "mvn_reg")]
cffb2a26 5070)
5071
f7fbdd4a 5072(define_insn "*notsi_compare0"
bd5b4116 5073 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 5074 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5075 (const_int 0)))
5076 (set (match_operand:SI 0 "s_register_operand" "=r")
5077 (not:SI (match_dup 1)))]
25f905c2 5078 "TARGET_32BIT"
3ef90e77 5079 "mvns%?\\t%0, %1"
d2a518d1 5080 [(set_attr "conds" "set")
1aed5204 5081 (set_attr "type" "mvn_reg")]
cffb2a26 5082)
9c08d1fa 5083
f7fbdd4a 5084(define_insn "*notsi_compare0_scratch"
bd5b4116 5085 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 5086 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5087 (const_int 0)))
5088 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 5089 "TARGET_32BIT"
3ef90e77 5090 "mvns%?\\t%0, %1"
d2a518d1 5091 [(set_attr "conds" "set")
1aed5204 5092 (set_attr "type" "mvn_reg")]
cffb2a26 5093)
b11cae9e 5094\f
5095;; Fixed <--> Floating conversion insns
5096
9b8516be 5097(define_expand "floatsihf2"
5098 [(set (match_operand:HF 0 "general_operand" "")
5099 (float:HF (match_operand:SI 1 "general_operand" "")))]
5100 "TARGET_EITHER"
5101 "
5102 {
5103 rtx op1 = gen_reg_rtx (SFmode);
5104 expand_float (op1, operands[1], 0);
5105 op1 = convert_to_mode (HFmode, op1, 0);
5106 emit_move_insn (operands[0], op1);
5107 DONE;
5108 }"
5109)
5110
5111(define_expand "floatdihf2"
5112 [(set (match_operand:HF 0 "general_operand" "")
5113 (float:HF (match_operand:DI 1 "general_operand" "")))]
5114 "TARGET_EITHER"
5115 "
5116 {
5117 rtx op1 = gen_reg_rtx (SFmode);
5118 expand_float (op1, operands[1], 0);
5119 op1 = convert_to_mode (HFmode, op1, 0);
5120 emit_move_insn (operands[0], op1);
5121 DONE;
5122 }"
5123)
5124
604f3a0a 5125(define_expand "floatsisf2"
5126 [(set (match_operand:SF 0 "s_register_operand" "")
5127 (float:SF (match_operand:SI 1 "s_register_operand" "")))]
25f905c2 5128 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 5129 "
604f3a0a 5130")
5131
604f3a0a 5132(define_expand "floatsidf2"
5133 [(set (match_operand:DF 0 "s_register_operand" "")
5134 (float:DF (match_operand:SI 1 "s_register_operand" "")))]
a50d7267 5135 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 5136 "
604f3a0a 5137")
5138
9b8516be 5139(define_expand "fix_trunchfsi2"
5140 [(set (match_operand:SI 0 "general_operand" "")
5141 (fix:SI (fix:HF (match_operand:HF 1 "general_operand" ""))))]
5142 "TARGET_EITHER"
5143 "
5144 {
5145 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
5146 expand_fix (operands[0], op1, 0);
5147 DONE;
5148 }"
5149)
5150
5151(define_expand "fix_trunchfdi2"
5152 [(set (match_operand:DI 0 "general_operand" "")
5153 (fix:DI (fix:HF (match_operand:HF 1 "general_operand" ""))))]
5154 "TARGET_EITHER"
5155 "
5156 {
5157 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
5158 expand_fix (operands[0], op1, 0);
5159 DONE;
5160 }"
5161)
5162
604f3a0a 5163(define_expand "fix_truncsfsi2"
5164 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 5165 (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" ""))))]
25f905c2 5166 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 5167 "
604f3a0a 5168")
5169
604f3a0a 5170(define_expand "fix_truncdfsi2"
5171 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 5172 (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" ""))))]
a50d7267 5173 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 5174 "
604f3a0a 5175")
5176
f544c6d2 5177;; Truncation insns
b11cae9e 5178
604f3a0a 5179(define_expand "truncdfsf2"
5180 [(set (match_operand:SF 0 "s_register_operand" "")
5181 (float_truncate:SF
5182 (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 5183 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 5184 ""
5185)
9b8516be 5186
539b44ee 5187;; DFmode to HFmode conversions on targets without a single-step hardware
5188;; instruction for it would have to go through SFmode. This is dangerous
5189;; as it introduces double rounding.
5190;;
5191;; Disable this pattern unless we are in an unsafe math mode, or we have
5192;; a single-step instruction.
5193
9b8516be 5194(define_expand "truncdfhf2"
539b44ee 5195 [(set (match_operand:HF 0 "s_register_operand" "")
9b8516be 5196 (float_truncate:HF
539b44ee 5197 (match_operand:DF 1 "s_register_operand" "")))]
5198 "(TARGET_EITHER && flag_unsafe_math_optimizations)
5199 || (TARGET_32BIT && TARGET_FP16_TO_DOUBLE)"
5200{
5201 /* We don't have a direct instruction for this, so we must be in
5202 an unsafe math mode, and going via SFmode. */
5203
5204 if (!(TARGET_32BIT && TARGET_FP16_TO_DOUBLE))
5205 {
5206 rtx op1;
5207 op1 = convert_to_mode (SFmode, operands[1], 0);
5208 op1 = convert_to_mode (HFmode, op1, 0);
5209 emit_move_insn (operands[0], op1);
5210 DONE;
5211 }
5212 /* Otherwise, we will pick this up as a single instruction with
5213 no intermediary rounding. */
5214}
9b8516be 5215)
b11cae9e 5216\f
9c08d1fa 5217;; Zero and sign extension instructions.
b11cae9e 5218
848e66ac 5219(define_insn "zero_extend<mode>di2"
6aa689e8 5220 [(set (match_operand:DI 0 "s_register_operand" "=w,r,?r,w")
6d97728e 5221 (zero_extend:DI (match_operand:QHSI 1 "<qhs_zextenddi_op>"
5222 "<qhs_zextenddi_cstr>")))]
848e66ac 5223 "TARGET_32BIT <qhs_zextenddi_cond>"
5224 "#"
6aa689e8 5225 [(set_attr "length" "8,4,8,8")
b6779ddc 5226 (set_attr "arch" "neon_for_64bits,*,*,avoid_neon_for_64bits")
848e66ac 5227 (set_attr "ce_count" "2")
efbb5e19 5228 (set_attr "predicable" "yes")
5229 (set_attr "type" "multiple,mov_reg,multiple,multiple")]
25f905c2 5230)
5231
848e66ac 5232(define_insn "extend<mode>di2"
6aa689e8 5233 [(set (match_operand:DI 0 "s_register_operand" "=w,r,?r,?r,w")
63d204a8 5234 (sign_extend:DI (match_operand:QHSI 1 "<qhs_extenddi_op>"
5235 "<qhs_extenddi_cstr>")))]
848e66ac 5236 "TARGET_32BIT <qhs_sextenddi_cond>"
5237 "#"
6aa689e8 5238 [(set_attr "length" "8,4,8,8,8")
848e66ac 5239 (set_attr "ce_count" "2")
5240 (set_attr "shift" "1")
8012d2c2 5241 (set_attr "predicable" "yes")
1b7da4ac 5242 (set_attr "arch" "neon_for_64bits,*,a,t,avoid_neon_for_64bits")
5243 (set_attr "type" "multiple,mov_reg,multiple,multiple,multiple")]
0d66636f 5244)
9c08d1fa 5245
848e66ac 5246;; Splits for all extensions to DImode
5247(define_split
5248 [(set (match_operand:DI 0 "s_register_operand" "")
5249 (zero_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
6aa689e8 5250 "TARGET_32BIT && reload_completed && !IS_VFP_REGNUM (REGNO (operands[0]))"
848e66ac 5251 [(set (match_dup 0) (match_dup 1))]
5252{
848e66ac 5253 rtx lo_part = gen_lowpart (SImode, operands[0]);
3754d046 5254 machine_mode src_mode = GET_MODE (operands[1]);
848e66ac 5255
5256 if (REG_P (operands[0])
5257 && !reg_overlap_mentioned_p (operands[0], operands[1]))
5258 emit_clobber (operands[0]);
5259 if (!REG_P (lo_part) || src_mode != SImode
5260 || !rtx_equal_p (lo_part, operands[1]))
5261 {
5262 if (src_mode == SImode)
5263 emit_move_insn (lo_part, operands[1]);
5264 else
d1f9b275 5265 emit_insn (gen_rtx_SET (lo_part,
848e66ac 5266 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
5267 operands[1] = lo_part;
5268 }
5269 operands[0] = gen_highpart (SImode, operands[0]);
5270 operands[1] = const0_rtx;
5271})
9c08d1fa 5272
848e66ac 5273(define_split
25f905c2 5274 [(set (match_operand:DI 0 "s_register_operand" "")
848e66ac 5275 (sign_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
6aa689e8 5276 "TARGET_32BIT && reload_completed && !IS_VFP_REGNUM (REGNO (operands[0]))"
848e66ac 5277 [(set (match_dup 0) (ashiftrt:SI (match_dup 1) (const_int 31)))]
5278{
5279 rtx lo_part = gen_lowpart (SImode, operands[0]);
3754d046 5280 machine_mode src_mode = GET_MODE (operands[1]);
25f905c2 5281
848e66ac 5282 if (REG_P (operands[0])
5283 && !reg_overlap_mentioned_p (operands[0], operands[1]))
5284 emit_clobber (operands[0]);
5285
5286 if (!REG_P (lo_part) || src_mode != SImode
5287 || !rtx_equal_p (lo_part, operands[1]))
5288 {
5289 if (src_mode == SImode)
5290 emit_move_insn (lo_part, operands[1]);
5291 else
d1f9b275 5292 emit_insn (gen_rtx_SET (lo_part,
848e66ac 5293 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
5294 operands[1] = lo_part;
5295 }
5296 operands[0] = gen_highpart (SImode, operands[0]);
5297})
9c08d1fa 5298
5299(define_expand "zero_extendhisi2"
ef51b8e1 5300 [(set (match_operand:SI 0 "s_register_operand" "")
5301 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
cffb2a26 5302 "TARGET_EITHER"
ef51b8e1 5303{
5304 if (TARGET_ARM && !arm_arch4 && MEM_P (operands[1]))
f7fbdd4a 5305 {
ef51b8e1 5306 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
5307 DONE;
25f7a26e 5308 }
ef51b8e1 5309 if (!arm_arch6 && !MEM_P (operands[1]))
5310 {
5311 rtx t = gen_lowpart (SImode, operands[1]);
5312 rtx tmp = gen_reg_rtx (SImode);
5313 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
5314 emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (16)));
5315 DONE;
5316 }
5317})
9c08d1fa 5318
ef51b8e1 5319(define_split
b146458f 5320 [(set (match_operand:SI 0 "s_register_operand" "")
5321 (zero_extend:SI (match_operand:HI 1 "s_register_operand" "")))]
ef51b8e1 5322 "!TARGET_THUMB2 && !arm_arch6"
5323 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
5324 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 16)))]
5325{
5326 operands[2] = gen_lowpart (SImode, operands[1]);
5327})
5328
cffb2a26 5329(define_insn "*arm_zero_extendhisi2"
ef51b8e1 5330 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5331 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 5332 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 5333 "@
5334 #
3ef90e77 5335 ldrh%?\\t%0, %1"
d82e788e 5336 [(set_attr "type" "alu_shift_reg,load_byte")
848e66ac 5337 (set_attr "predicable" "yes")]
cffb2a26 5338)
f7fbdd4a 5339
a2cd141b 5340(define_insn "*arm_zero_extendhisi2_v6"
5341 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
e3f4ccee 5342 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,Uh")))]
a2cd141b 5343 "TARGET_ARM && arm_arch6"
5344 "@
5345 uxth%?\\t%0, %1
3ef90e77 5346 ldrh%?\\t%0, %1"
65f68e55 5347 [(set_attr "predicable" "yes")
6b6abc9c 5348 (set_attr "type" "extend,load_byte")]
a2cd141b 5349)
5350
5351(define_insn "*arm_zero_extendhisi2addsi"
5352 [(set (match_operand:SI 0 "s_register_operand" "=r")
5353 (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
5354 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 5355 "TARGET_INT_SIMD"
a2cd141b 5356 "uxtah%?\\t%0, %2, %1"
d82e788e 5357 [(set_attr "type" "alu_shift_reg")
d952d547 5358 (set_attr "predicable" "yes")
5359 (set_attr "predicable_short_it" "no")]
a2cd141b 5360)
5361
87b22bf7 5362(define_expand "zero_extendqisi2"
cffb2a26 5363 [(set (match_operand:SI 0 "s_register_operand" "")
5364 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
5365 "TARGET_EITHER"
ef51b8e1 5366{
0438d37f 5367 if (TARGET_ARM && !arm_arch6 && !MEM_P (operands[1]))
87b22bf7 5368 {
ef51b8e1 5369 emit_insn (gen_andsi3 (operands[0],
5370 gen_lowpart (SImode, operands[1]),
5371 GEN_INT (255)));
5372 DONE;
5373 }
5374 if (!arm_arch6 && !MEM_P (operands[1]))
5375 {
5376 rtx t = gen_lowpart (SImode, operands[1]);
5377 rtx tmp = gen_reg_rtx (SImode);
5378 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
5379 emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (24)));
5380 DONE;
5381 }
5382})
cffb2a26 5383
ef51b8e1 5384(define_split
b146458f 5385 [(set (match_operand:SI 0 "s_register_operand" "")
5386 (zero_extend:SI (match_operand:QI 1 "s_register_operand" "")))]
ef51b8e1 5387 "!arm_arch6"
5388 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
5389 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 24)))]
5390{
5391 operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
5392 if (TARGET_ARM)
5393 {
5394 emit_insn (gen_andsi3 (operands[0], operands[2], GEN_INT (255)));
87b22bf7 5395 DONE;
5396 }
ef51b8e1 5397})
9c08d1fa 5398
cffb2a26 5399(define_insn "*arm_zero_extendqisi2"
ef51b8e1 5400 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5401 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 5402 "TARGET_ARM && !arm_arch6"
ef51b8e1 5403 "@
5404 #
3ef90e77 5405 ldrb%?\\t%0, %1\\t%@ zero_extendqisi2"
ef51b8e1 5406 [(set_attr "length" "8,4")
d82e788e 5407 (set_attr "type" "alu_shift_reg,load_byte")
848e66ac 5408 (set_attr "predicable" "yes")]
cffb2a26 5409)
87b22bf7 5410
a2cd141b 5411(define_insn "*arm_zero_extendqisi2_v6"
5412 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
e3f4ccee 5413 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,Uh")))]
a2cd141b 5414 "TARGET_ARM && arm_arch6"
5415 "@
3ef90e77 5416 uxtb%?\\t%0, %1
5417 ldrb%?\\t%0, %1\\t%@ zero_extendqisi2"
6b6abc9c 5418 [(set_attr "type" "extend,load_byte")
848e66ac 5419 (set_attr "predicable" "yes")]
a2cd141b 5420)
5421
5422(define_insn "*arm_zero_extendqisi2addsi"
5423 [(set (match_operand:SI 0 "s_register_operand" "=r")
5424 (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
5425 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 5426 "TARGET_INT_SIMD"
a2cd141b 5427 "uxtab%?\\t%0, %2, %1"
5428 [(set_attr "predicable" "yes")
d952d547 5429 (set_attr "predicable_short_it" "no")
d82e788e 5430 (set_attr "type" "alu_shift_reg")]
a2cd141b 5431)
5432
87b22bf7 5433(define_split
5434 [(set (match_operand:SI 0 "s_register_operand" "")
5435 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
5436 (clobber (match_operand:SI 2 "s_register_operand" ""))]
0438d37f 5437 "TARGET_32BIT && (!MEM_P (operands[1])) && ! BYTES_BIG_ENDIAN"
87b22bf7 5438 [(set (match_dup 2) (match_dup 1))
5439 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
cffb2a26 5440 ""
5441)
9c08d1fa 5442
8a4d25d6 5443(define_split
5444 [(set (match_operand:SI 0 "s_register_operand" "")
5445 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 3)))
5446 (clobber (match_operand:SI 2 "s_register_operand" ""))]
0438d37f 5447 "TARGET_32BIT && (!MEM_P (operands[1])) && BYTES_BIG_ENDIAN"
8a4d25d6 5448 [(set (match_dup 2) (match_dup 1))
5449 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
5450 ""
5451)
5452
1c274529 5453
5454(define_split
5455 [(set (match_operand:SI 0 "s_register_operand" "")
9b23f0a7 5456 (IOR_XOR:SI (and:SI (ashift:SI
1c274529 5457 (match_operand:SI 1 "s_register_operand" "")
5458 (match_operand:SI 2 "const_int_operand" ""))
5459 (match_operand:SI 3 "const_int_operand" ""))
5460 (zero_extend:SI
5461 (match_operator 5 "subreg_lowpart_operator"
5462 [(match_operand:SI 4 "s_register_operand" "")]))))]
5463 "TARGET_32BIT
8c4e8755 5464 && (UINTVAL (operands[3])
1c274529 5465 == (GET_MODE_MASK (GET_MODE (operands[5]))
5466 & (GET_MODE_MASK (GET_MODE (operands[5]))
5467 << (INTVAL (operands[2])))))"
9b23f0a7 5468 [(set (match_dup 0) (IOR_XOR:SI (ashift:SI (match_dup 1) (match_dup 2))
1c274529 5469 (match_dup 4)))
5470 (set (match_dup 0) (zero_extend:SI (match_dup 5)))]
5471 "operands[5] = gen_lowpart (GET_MODE (operands[5]), operands[0]);"
5472)
5473
f7fbdd4a 5474(define_insn "*compareqi_eq0"
bd5b4116 5475 [(set (reg:CC_Z CC_REGNUM)
206ee9a2 5476 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
87b22bf7 5477 (const_int 0)))]
25f905c2 5478 "TARGET_32BIT"
596e5e8f 5479 "tst%?\\t%0, #255"
5480 [(set_attr "conds" "set")
d952d547 5481 (set_attr "predicable" "yes")
1b7da4ac 5482 (set_attr "predicable_short_it" "no")
5483 (set_attr "type" "logic_imm")]
cffb2a26 5484)
b11cae9e 5485
b11cae9e 5486(define_expand "extendhisi2"
ef51b8e1 5487 [(set (match_operand:SI 0 "s_register_operand" "")
5488 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
cffb2a26 5489 "TARGET_EITHER"
ef51b8e1 5490{
5491 if (TARGET_THUMB1)
5492 {
5493 emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1]));
5494 DONE;
5495 }
5496 if (MEM_P (operands[1]) && TARGET_ARM && !arm_arch4)
5497 {
5498 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
5499 DONE;
5500 }
ed29c566 5501
ef51b8e1 5502 if (!arm_arch6 && !MEM_P (operands[1]))
5503 {
5504 rtx t = gen_lowpart (SImode, operands[1]);
5505 rtx tmp = gen_reg_rtx (SImode);
5506 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
5507 emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (16)));
5508 DONE;
5509 }
5510})
cffb2a26 5511
ef51b8e1 5512(define_split
5513 [(parallel
5514 [(set (match_operand:SI 0 "register_operand" "")
5515 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))
5516 (clobber (match_scratch:SI 2 ""))])]
5517 "!arm_arch6"
5518 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
5519 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
5520{
5521 operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
5522})
25f7a26e 5523
25f905c2 5524;; This pattern will only be used when ldsh is not available
25f7a26e 5525(define_expand "extendhisi2_mem"
eab14235 5526 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 5527 (set (match_dup 3)
eab14235 5528 (zero_extend:SI (match_dup 7)))
25f7a26e 5529 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
5530 (set (match_operand:SI 0 "" "")
5531 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
cffb2a26 5532 "TARGET_ARM"
25f7a26e 5533 "
215b30b3 5534 {
5535 rtx mem1, mem2;
5536 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
5537
788fcce0 5538 mem1 = change_address (operands[1], QImode, addr);
29c05e22 5539 mem2 = change_address (operands[1], QImode,
5540 plus_constant (Pmode, addr, 1));
215b30b3 5541 operands[0] = gen_lowpart (SImode, operands[0]);
5542 operands[1] = mem1;
5543 operands[2] = gen_reg_rtx (SImode);
5544 operands[3] = gen_reg_rtx (SImode);
5545 operands[6] = gen_reg_rtx (SImode);
5546 operands[7] = mem2;
25f7a26e 5547
215b30b3 5548 if (BYTES_BIG_ENDIAN)
5549 {
5550 operands[4] = operands[2];
5551 operands[5] = operands[3];
5552 }
5553 else
5554 {
5555 operands[4] = operands[3];
5556 operands[5] = operands[2];
5557 }
5558 }"
5559)
b11cae9e 5560
ef51b8e1 5561(define_split
5562 [(set (match_operand:SI 0 "register_operand" "")
5563 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
5564 "!arm_arch6"
5565 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
5566 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
5567{
5568 operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
5569})
5570
a2cd141b 5571(define_insn "*arm_extendhisi2"
ef51b8e1 5572 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
e3f4ccee 5573 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,Uh")))]
a2cd141b 5574 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 5575 "@
5576 #
3ef90e77 5577 ldrsh%?\\t%0, %1"
ef51b8e1 5578 [(set_attr "length" "8,4")
d82e788e 5579 (set_attr "type" "alu_shift_reg,load_byte")
e3f4ccee 5580 (set_attr "predicable" "yes")]
cffb2a26 5581)
f7fbdd4a 5582
25f905c2 5583;; ??? Check Thumb-2 pool range
a2cd141b 5584(define_insn "*arm_extendhisi2_v6"
5585 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
e3f4ccee 5586 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,Uh")))]
25f905c2 5587 "TARGET_32BIT && arm_arch6"
a2cd141b 5588 "@
5589 sxth%?\\t%0, %1
3ef90e77 5590 ldrsh%?\\t%0, %1"
6b6abc9c 5591 [(set_attr "type" "extend,load_byte")
a2cd141b 5592 (set_attr "predicable" "yes")
e3f4ccee 5593 (set_attr "predicable_short_it" "no")]
a2cd141b 5594)
5595
5596(define_insn "*arm_extendhisi2addsi"
5597 [(set (match_operand:SI 0 "s_register_operand" "=r")
5598 (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
5599 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 5600 "TARGET_INT_SIMD"
a2cd141b 5601 "sxtah%?\\t%0, %2, %1"
1b7da4ac 5602 [(set_attr "type" "alu_shift_reg")]
a2cd141b 5603)
5604
c8f69309 5605(define_expand "extendqihi2"
5606 [(set (match_dup 2)
bed7d9a5 5607 (ashift:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")
c8f69309 5608 (const_int 24)))
9c08d1fa 5609 (set (match_operand:HI 0 "s_register_operand" "")
c8f69309 5610 (ashiftrt:SI (match_dup 2)
5611 (const_int 24)))]
cffb2a26 5612 "TARGET_ARM"
c8f69309 5613 "
215b30b3 5614 {
0438d37f 5615 if (arm_arch4 && MEM_P (operands[1]))
215b30b3 5616 {
d1f9b275 5617 emit_insn (gen_rtx_SET (operands[0],
215b30b3 5618 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
5619 DONE;
5620 }
5621 if (!s_register_operand (operands[1], QImode))
5622 operands[1] = copy_to_mode_reg (QImode, operands[1]);
5623 operands[0] = gen_lowpart (SImode, operands[0]);
5624 operands[1] = gen_lowpart (SImode, operands[1]);
5625 operands[2] = gen_reg_rtx (SImode);
5626 }"
5627)
f7fbdd4a 5628
25f905c2 5629(define_insn "*arm_extendqihi_insn"
b4e8a300 5630 [(set (match_operand:HI 0 "s_register_operand" "=r")
bed7d9a5 5631 (sign_extend:HI (match_operand:QI 1 "arm_extendqisi_mem_op" "Uq")))]
cffb2a26 5632 "TARGET_ARM && arm_arch4"
3ef90e77 5633 "ldrsb%?\\t%0, %1"
a2cd141b 5634 [(set_attr "type" "load_byte")
e3f4ccee 5635 (set_attr "predicable" "yes")]
cffb2a26 5636)
3fc2009e 5637
b11cae9e 5638(define_expand "extendqisi2"
ef51b8e1 5639 [(set (match_operand:SI 0 "s_register_operand" "")
5640 (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")))]
cffb2a26 5641 "TARGET_EITHER"
ef51b8e1 5642{
5643 if (!arm_arch4 && MEM_P (operands[1]))
5644 operands[1] = copy_to_mode_reg (QImode, operands[1]);
a2cd141b 5645
ef51b8e1 5646 if (!arm_arch6 && !MEM_P (operands[1]))
5647 {
5648 rtx t = gen_lowpart (SImode, operands[1]);
5649 rtx tmp = gen_reg_rtx (SImode);
5650 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
5651 emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (24)));
5652 DONE;
5653 }
5654})
a2cd141b 5655
ef51b8e1 5656(define_split
5657 [(set (match_operand:SI 0 "register_operand" "")
5658 (sign_extend:SI (match_operand:QI 1 "register_operand" "")))]
5659 "!arm_arch6"
5660 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
5661 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))]
5662{
5663 operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
5664})
f7fbdd4a 5665
a2cd141b 5666(define_insn "*arm_extendqisi"
ef51b8e1 5667 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5668 (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
a2cd141b 5669 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 5670 "@
5671 #
3ef90e77 5672 ldrsb%?\\t%0, %1"
ef51b8e1 5673 [(set_attr "length" "8,4")
d82e788e 5674 (set_attr "type" "alu_shift_reg,load_byte")
e3f4ccee 5675 (set_attr "predicable" "yes")]
cffb2a26 5676)
3fc2009e 5677
a2cd141b 5678(define_insn "*arm_extendqisi_v6"
5679 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
bed7d9a5 5680 (sign_extend:SI
5681 (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
a2cd141b 5682 "TARGET_ARM && arm_arch6"
b4e8a300 5683 "@
5684 sxtb%?\\t%0, %1
3ef90e77 5685 ldrsb%?\\t%0, %1"
6b6abc9c 5686 [(set_attr "type" "extend,load_byte")
e3f4ccee 5687 (set_attr "predicable" "yes")]
a2cd141b 5688)
5689
5690(define_insn "*arm_extendqisi2addsi"
5691 [(set (match_operand:SI 0 "s_register_operand" "=r")
5692 (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
5693 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 5694 "TARGET_INT_SIMD"
a2cd141b 5695 "sxtab%?\\t%0, %2, %1"
d82e788e 5696 [(set_attr "type" "alu_shift_reg")
d952d547 5697 (set_attr "predicable" "yes")
5698 (set_attr "predicable_short_it" "no")]
a2cd141b 5699)
5700
caedf871 5701(define_expand "extendsfdf2"
5702 [(set (match_operand:DF 0 "s_register_operand" "")
5703 (float_extend:DF (match_operand:SF 1 "s_register_operand" "")))]
a50d7267 5704 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
caedf871 5705 ""
5706)
9b8516be 5707
539b44ee 5708;; HFmode -> DFmode conversions where we don't have an instruction for it
5709;; must go through SFmode.
5710;;
5711;; This is always safe for an extend.
5712
9b8516be 5713(define_expand "extendhfdf2"
539b44ee 5714 [(set (match_operand:DF 0 "s_register_operand" "")
5715 (float_extend:DF (match_operand:HF 1 "s_register_operand" "")))]
9b8516be 5716 "TARGET_EITHER"
539b44ee 5717{
5718 /* We don't have a direct instruction for this, so go via SFmode. */
5719 if (!(TARGET_32BIT && TARGET_FP16_TO_DOUBLE))
5720 {
5721 rtx op1;
5722 op1 = convert_to_mode (SFmode, operands[1], 0);
5723 op1 = convert_to_mode (DFmode, op1, 0);
5724 emit_insn (gen_movdf (operands[0], op1));
5725 DONE;
5726 }
5727 /* Otherwise, we're done producing RTL and will pick up the correct
5728 pattern to do this with one rounding-step in a single instruction. */
5729}
9b8516be 5730)
b11cae9e 5731\f
5732;; Move insns (including loads and stores)
5733
5734;; XXX Just some ideas about movti.
9c08d1fa 5735;; I don't think these are a good idea on the arm, there just aren't enough
5736;; registers
b11cae9e 5737;;(define_expand "loadti"
9c08d1fa 5738;; [(set (match_operand:TI 0 "s_register_operand" "")
b11cae9e 5739;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
5740;; "" "")
5741
5742;;(define_expand "storeti"
5743;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
9c08d1fa 5744;; (match_operand:TI 1 "s_register_operand" ""))]
b11cae9e 5745;; "" "")
5746
5747;;(define_expand "movti"
5748;; [(set (match_operand:TI 0 "general_operand" "")
5749;; (match_operand:TI 1 "general_operand" ""))]
5750;; ""
5751;; "
5752;;{
5753;; rtx insn;
5754;;
0438d37f 5755;; if (MEM_P (operands[0]) && MEM_P (operands[1]))
b11cae9e 5756;; operands[1] = copy_to_reg (operands[1]);
0438d37f 5757;; if (MEM_P (operands[0]))
b11cae9e 5758;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
0438d37f 5759;; else if (MEM_P (operands[1]))
b11cae9e 5760;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
5761;; else
5762;; FAIL;
5763;;
5764;; emit_insn (insn);
5765;; DONE;
5766;;}")
5767
a2f10574 5768;; Recognize garbage generated above.
b11cae9e 5769
5770;;(define_insn ""
5771;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
5772;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
5773;; ""
5774;; "*
5775;; {
5776;; register mem = (which_alternative < 3);
0d66636f 5777;; register const char *template;
b11cae9e 5778;;
5779;; operands[mem] = XEXP (operands[mem], 0);
5780;; switch (which_alternative)
5781;; {
5782;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
5783;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
5784;; case 2: template = \"ldmia\\t%1, %M0\"; break;
5785;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
5786;; case 4: template = \"stmia\\t%0!, %M1\"; break;
5787;; case 5: template = \"stmia\\t%0, %M1\"; break;
5788;; }
e2348bcb 5789;; output_asm_insn (template, operands);
5790;; return \"\";
b11cae9e 5791;; }")
5792
cffb2a26 5793(define_expand "movdi"
5794 [(set (match_operand:DI 0 "general_operand" "")
5795 (match_operand:DI 1 "general_operand" ""))]
5796 "TARGET_EITHER"
5797 "
e1ba4a27 5798 if (can_create_pseudo_p ())
cffb2a26 5799 {
0438d37f 5800 if (!REG_P (operands[0]))
b2778788 5801 operands[1] = force_reg (DImode, operands[1]);
cffb2a26 5802 }
6b97fdcc 5803 if (REG_P (operands[0]) && REGNO (operands[0]) <= LAST_ARM_REGNUM
4f0e25ca 5804 && !HARD_REGNO_MODE_OK (REGNO (operands[0]), DImode))
5805 {
5806 /* Avoid LDRD's into an odd-numbered register pair in ARM state
5807 when expanding function calls. */
5808 gcc_assert (can_create_pseudo_p ());
5809 if (MEM_P (operands[1]) && MEM_VOLATILE_P (operands[1]))
5810 {
5811 /* Perform load into legal reg pair first, then move. */
5812 rtx reg = gen_reg_rtx (DImode);
5813 emit_insn (gen_movdi (reg, operands[1]));
5814 operands[1] = reg;
5815 }
5816 emit_move_insn (gen_lowpart (SImode, operands[0]),
5817 gen_lowpart (SImode, operands[1]));
5818 emit_move_insn (gen_highpart (SImode, operands[0]),
5819 gen_highpart (SImode, operands[1]));
5820 DONE;
5821 }
6b97fdcc 5822 else if (REG_P (operands[1]) && REGNO (operands[1]) <= LAST_ARM_REGNUM
4f0e25ca 5823 && !HARD_REGNO_MODE_OK (REGNO (operands[1]), DImode))
5824 {
5825 /* Avoid STRD's from an odd-numbered register pair in ARM state
5826 when expanding function prologue. */
5827 gcc_assert (can_create_pseudo_p ());
5828 rtx split_dest = (MEM_P (operands[0]) && MEM_VOLATILE_P (operands[0]))
5829 ? gen_reg_rtx (DImode)
5830 : operands[0];
5831 emit_move_insn (gen_lowpart (SImode, split_dest),
5832 gen_lowpart (SImode, operands[1]));
5833 emit_move_insn (gen_highpart (SImode, split_dest),
5834 gen_highpart (SImode, operands[1]));
5835 if (split_dest != operands[0])
5836 emit_insn (gen_movdi (operands[0], split_dest));
5837 DONE;
5838 }
cffb2a26 5839 "
5840)
b11cae9e 5841
cffb2a26 5842(define_insn "*arm_movdi"
353cf59a 5843 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, q, m")
5844 (match_operand:DI 1 "di_operand" "rDa,Db,Dc,mi,q"))]
cde1623a 5845 "TARGET_32BIT
d7216193 5846 && !(TARGET_HARD_FLOAT)
b2778788 5847 && !TARGET_IWMMXT
5848 && ( register_operand (operands[0], DImode)
5849 || register_operand (operands[1], DImode))"
b11cae9e 5850 "*
d51f92df 5851 switch (which_alternative)
5852 {
5853 case 0:
5854 case 1:
5855 case 2:
5856 return \"#\";
5857 default:
26ff80c0 5858 return output_move_double (operands, true, NULL);
d51f92df 5859 }
cffb2a26 5860 "
359a6e9f 5861 [(set_attr "length" "8,12,16,8,8")
1b7da4ac 5862 (set_attr "type" "multiple,multiple,multiple,load2,store2")
cde1623a 5863 (set_attr "arm_pool_range" "*,*,*,1020,*")
8848d797 5864 (set_attr "arm_neg_pool_range" "*,*,*,1004,*")
42e1de19 5865 (set_attr "thumb2_pool_range" "*,*,*,4094,*")
cde1623a 5866 (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
cffb2a26 5867)
5868
d51f92df 5869(define_split
5870 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
e6dd3afa 5871 (match_operand:ANY64 1 "immediate_operand" ""))]
25f905c2 5872 "TARGET_32BIT
d51f92df 5873 && reload_completed
5874 && (arm_const_double_inline_cost (operands[1])
861033d5 5875 <= arm_max_const_double_inline_cost ())"
d51f92df 5876 [(const_int 0)]
5877 "
5878 arm_split_constant (SET, SImode, curr_insn,
5879 INTVAL (gen_lowpart (SImode, operands[1])),
5880 gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
5881 arm_split_constant (SET, SImode, curr_insn,
5882 INTVAL (gen_highpart_mode (SImode,
5883 GET_MODE (operands[0]),
5884 operands[1])),
5885 gen_highpart (SImode, operands[0]), NULL_RTX, 0);
5886 DONE;
5887 "
5888)
5889
e5ba9289 5890; If optimizing for size, or if we have load delay slots, then
5891; we want to split the constant into two separate operations.
5892; In both cases this may split a trivial part into a single data op
5893; leaving a single complex constant to load. We can also get longer
5894; offsets in a LDR which means we get better chances of sharing the pool
5895; entries. Finally, we can normally do a better job of scheduling
5896; LDR instructions than we can with LDM.
5897; This pattern will only match if the one above did not.
5898(define_split
5899 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
5900 (match_operand:ANY64 1 "const_double_operand" ""))]
5901 "TARGET_ARM && reload_completed
5902 && arm_const_double_by_parts (operands[1])"
5903 [(set (match_dup 0) (match_dup 1))
5904 (set (match_dup 2) (match_dup 3))]
5905 "
5906 operands[2] = gen_highpart (SImode, operands[0]);
5907 operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
5908 operands[1]);
5909 operands[0] = gen_lowpart (SImode, operands[0]);
5910 operands[1] = gen_lowpart (SImode, operands[1]);
5911 "
5912)
5913
d51f92df 5914(define_split
5915 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
5916 (match_operand:ANY64 1 "arm_general_register_operand" ""))]
5917 "TARGET_EITHER && reload_completed"
5918 [(set (match_dup 0) (match_dup 1))
5919 (set (match_dup 2) (match_dup 3))]
5920 "
5921 operands[2] = gen_highpart (SImode, operands[0]);
5922 operands[3] = gen_highpart (SImode, operands[1]);
5923 operands[0] = gen_lowpart (SImode, operands[0]);
5924 operands[1] = gen_lowpart (SImode, operands[1]);
5925
5926 /* Handle a partial overlap. */
5927 if (rtx_equal_p (operands[0], operands[3]))
5928 {
5929 rtx tmp0 = operands[0];
5930 rtx tmp1 = operands[1];
5931
5932 operands[0] = operands[2];
5933 operands[1] = operands[3];
5934 operands[2] = tmp0;
5935 operands[3] = tmp1;
5936 }
5937 "
5938)
5939
a8a3b539 5940;; We can't actually do base+index doubleword loads if the index and
5941;; destination overlap. Split here so that we at least have chance to
5942;; schedule.
5943(define_split
5944 [(set (match_operand:DI 0 "s_register_operand" "")
5945 (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
5946 (match_operand:SI 2 "s_register_operand" ""))))]
5947 "TARGET_LDRD
5948 && reg_overlap_mentioned_p (operands[0], operands[1])
5949 && reg_overlap_mentioned_p (operands[0], operands[2])"
5950 [(set (match_dup 4)
5951 (plus:SI (match_dup 1)
5952 (match_dup 2)))
5953 (set (match_dup 0)
5954 (mem:DI (match_dup 4)))]
5955 "
5956 operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
5957 "
5958)
5959
9c08d1fa 5960(define_expand "movsi"
5961 [(set (match_operand:SI 0 "general_operand" "")
5962 (match_operand:SI 1 "general_operand" ""))]
cffb2a26 5963 "TARGET_EITHER"
9c08d1fa 5964 "
befb0bac 5965 {
e348ff3e 5966 rtx base, offset, tmp;
5967
25f905c2 5968 if (TARGET_32BIT)
9c08d1fa 5969 {
674a8f0b 5970 /* Everything except mem = const or mem = mem can be done easily. */
0438d37f 5971 if (MEM_P (operands[0]))
cffb2a26 5972 operands[1] = force_reg (SImode, operands[1]);
a2cd141b 5973 if (arm_general_register_operand (operands[0], SImode)
0438d37f 5974 && CONST_INT_P (operands[1])
cffb2a26 5975 && !(const_ok_for_arm (INTVAL (operands[1]))
5976 || const_ok_for_arm (~INTVAL (operands[1]))))
5977 {
17202aa5 5978 if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[1]), SET))
5979 {
5980 emit_insn (gen_rtx_SET (operands[0], operands[1]));
5981 DONE;
5982 }
5983 else
5984 {
5985 arm_split_constant (SET, SImode, NULL_RTX,
5986 INTVAL (operands[1]), operands[0], NULL_RTX,
5987 optimize && can_create_pseudo_p ());
5988 DONE;
5989 }
cffb2a26 5990 }
5991 }
25f905c2 5992 else /* TARGET_THUMB1... */
cffb2a26 5993 {
e1ba4a27 5994 if (can_create_pseudo_p ())
cffb2a26 5995 {
0438d37f 5996 if (!REG_P (operands[0]))
cffb2a26 5997 operands[1] = force_reg (SImode, operands[1]);
5998 }
9c08d1fa 5999 }
f655717d 6000
e348ff3e 6001 if (ARM_OFFSETS_MUST_BE_WITHIN_SECTIONS_P)
6002 {
6003 split_const (operands[1], &base, &offset);
6004 if (GET_CODE (base) == SYMBOL_REF
6005 && !offset_within_block_p (base, INTVAL (offset)))
6006 {
b308ddcf 6007 tmp = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
e348ff3e 6008 emit_move_insn (tmp, base);
6009 emit_insn (gen_addsi3 (operands[0], tmp, offset));
6010 DONE;
6011 }
6012 }
6013
f655717d 6014 /* Recognize the case where operand[1] is a reference to thread-local
6015 data and load its address to a register. */
6016 if (arm_tls_referenced_p (operands[1]))
6017 {
6018 rtx tmp = operands[1];
6019 rtx addend = NULL;
6020
6021 if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
6022 {
6023 addend = XEXP (XEXP (tmp, 0), 1);
6024 tmp = XEXP (XEXP (tmp, 0), 0);
6025 }
6026
6027 gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
6028 gcc_assert (SYMBOL_REF_TLS_MODEL (tmp) != 0);
6029
e1ba4a27 6030 tmp = legitimize_tls_address (tmp,
6031 !can_create_pseudo_p () ? operands[0] : 0);
f655717d 6032 if (addend)
6033 {
6034 tmp = gen_rtx_PLUS (SImode, tmp, addend);
6035 tmp = force_operand (tmp, operands[0]);
6036 }
6037 operands[1] = tmp;
6038 }
6039 else if (flag_pic
6040 && (CONSTANT_P (operands[1])
6041 || symbol_mentioned_p (operands[1])
6042 || label_mentioned_p (operands[1])))
6043 operands[1] = legitimize_pic_address (operands[1], SImode,
e1ba4a27 6044 (!can_create_pseudo_p ()
6045 ? operands[0]
6046 : 0));
befb0bac 6047 }
215b30b3 6048 "
6049)
9c08d1fa 6050
d0e6a121 6051;; The ARM LO_SUM and HIGH are backwards - HIGH sets the low bits, and
6052;; LO_SUM adds in the high bits. Fortunately these are opaque operations
6053;; so this does not matter.
6054(define_insn "*arm_movt"
417e5cc5 6055 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r")
6056 (lo_sum:SI (match_operand:SI 1 "nonimmediate_operand" "0,0")
6057 (match_operand:SI 2 "general_operand" "i,i")))]
60a48e7d 6058 "TARGET_HAVE_MOVT && arm_valid_symbolic_address_p (operands[2])"
417e5cc5 6059 "@
6060 movt%?\t%0, #:upper16:%c2
6061 movt\t%0, #:upper16:%c2"
6062 [(set_attr "arch" "32,v8mb")
6063 (set_attr "predicable" "yes")
d952d547 6064 (set_attr "predicable_short_it" "no")
1b7da4ac 6065 (set_attr "length" "4")
282b4c75 6066 (set_attr "type" "alu_sreg")]
d0e6a121 6067)
6068
cffb2a26 6069(define_insn "*arm_movsi_insn"
aaa37ad6 6070 [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,rk,m")
110eae03 6071 (match_operand:SI 1 "general_operand" "rk, I,K,j,mi,rk"))]
d7216193 6072 "TARGET_ARM && !TARGET_IWMMXT && !TARGET_HARD_FLOAT
cffb2a26 6073 && ( register_operand (operands[0], SImode)
6074 || register_operand (operands[1], SImode))"
f7fbdd4a 6075 "@
aaa37ad6 6076 mov%?\\t%0, %1
f7fbdd4a 6077 mov%?\\t%0, %1
6078 mvn%?\\t%0, #%B1
25f905c2 6079 movw%?\\t%0, %1
f7fbdd4a 6080 ldr%?\\t%0, %1
6081 str%?\\t%1, %0"
1aed5204 6082 [(set_attr "type" "mov_reg,mov_imm,mvn_imm,mov_imm,load1,store1")
0d66636f 6083 (set_attr "predicable" "yes")
100cd063 6084 (set_attr "arch" "*,*,*,v6t2,*,*")
aaa37ad6 6085 (set_attr "pool_range" "*,*,*,*,4096,*")
6086 (set_attr "neg_pool_range" "*,*,*,*,4084,*")]
cffb2a26 6087)
87b22bf7 6088
6089(define_split
a2cd141b 6090 [(set (match_operand:SI 0 "arm_general_register_operand" "")
87b22bf7 6091 (match_operand:SI 1 "const_int_operand" ""))]
25f905c2 6092 "TARGET_32BIT
215b30b3 6093 && (!(const_ok_for_arm (INTVAL (operands[1]))
6094 || const_ok_for_arm (~INTVAL (operands[1]))))"
87b22bf7 6095 [(clobber (const_int 0))]
6096 "
96f57e36 6097 arm_split_constant (SET, SImode, NULL_RTX,
6098 INTVAL (operands[1]), operands[0], NULL_RTX, 0);
87b22bf7 6099 DONE;
215b30b3 6100 "
6101)
9c08d1fa 6102
861033d5 6103;; A normal way to do (symbol + offset) requires three instructions at least
6104;; (depends on how big the offset is) as below:
6105;; movw r0, #:lower16:g
6106;; movw r0, #:upper16:g
6107;; adds r0, #4
6108;;
6109;; A better way would be:
6110;; movw r0, #:lower16:g+4
6111;; movw r0, #:upper16:g+4
6112;;
6113;; The limitation of this way is that the length of offset should be a 16-bit
6114;; signed value, because current assembler only supports REL type relocation for
6115;; such case. If the more powerful RELA type is supported in future, we should
6116;; update this pattern to go with better way.
6117(define_split
6118 [(set (match_operand:SI 0 "arm_general_register_operand" "")
6119 (const:SI (plus:SI (match_operand:SI 1 "general_operand" "")
6120 (match_operand:SI 2 "const_int_operand" ""))))]
60a48e7d 6121 "TARGET_THUMB
6122 && TARGET_HAVE_MOVT
861033d5 6123 && arm_disable_literal_pool
6124 && reload_completed
6125 && GET_CODE (operands[1]) == SYMBOL_REF"
6126 [(clobber (const_int 0))]
6127 "
6128 int offset = INTVAL (operands[2]);
6129
6130 if (offset < -0x8000 || offset > 0x7fff)
6131 {
6132 arm_emit_movpair (operands[0], operands[1]);
d1f9b275 6133 emit_insn (gen_rtx_SET (operands[0],
861033d5 6134 gen_rtx_PLUS (SImode, operands[0], operands[2])));
6135 }
6136 else
6137 {
6138 rtx op = gen_rtx_CONST (SImode,
6139 gen_rtx_PLUS (SImode, operands[1], operands[2]));
6140 arm_emit_movpair (operands[0], op);
6141 }
6142 "
6143)
6144
b8d5d078 6145;; Split symbol_refs at the later stage (after cprop), instead of generating
6146;; movt/movw pair directly at expand. Otherwise corresponding high_sum
6147;; and lo_sum would be merged back into memory load at cprop. However,
6148;; if the default is to prefer movt/movw rather than a load from the constant
6149;; pool, the performance is better.
6150(define_split
6151 [(set (match_operand:SI 0 "arm_general_register_operand" "")
6152 (match_operand:SI 1 "general_operand" ""))]
60a48e7d 6153 "TARGET_USE_MOVT && GET_CODE (operands[1]) == SYMBOL_REF
b8d5d078 6154 && !flag_pic && !target_word_relocations
6155 && !arm_tls_referenced_p (operands[1])"
6156 [(clobber (const_int 0))]
6157{
6158 arm_emit_movpair (operands[0], operands[1]);
6159 DONE;
6160})
6161
bc360af8 6162;; When generating pic, we need to load the symbol offset into a register.
6163;; So that the optimizer does not confuse this with a normal symbol load
6164;; we use an unspec. The offset will be loaded from a constant pool entry,
6165;; since that is the only type of relocation we can use.
cffb2a26 6166
bc360af8 6167;; Wrap calculation of the whole PIC address in a single pattern for the
6168;; benefit of optimizers, particularly, PRE and HOIST. Calculation of
6169;; a PIC address involves two loads from memory, so we want to CSE it
6170;; as often as possible.
6171;; This pattern will be split into one of the pic_load_addr_* patterns
6172;; and a move after GCSE optimizations.
6173;;
6174;; Note: Update arm.c: legitimize_pic_address() when changing this pattern.
6175(define_expand "calculate_pic_address"
94f8caca 6176 [(set (match_operand:SI 0 "register_operand" "")
6177 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "")
6178 (unspec:SI [(match_operand:SI 2 "" "")]
6179 UNSPEC_PIC_SYM))))]
6180 "flag_pic"
6181)
6182
6183;; Split calculate_pic_address into pic_load_addr_* and a move.
6184(define_split
6185 [(set (match_operand:SI 0 "register_operand" "")
6186 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "")
6187 (unspec:SI [(match_operand:SI 2 "" "")]
6188 UNSPEC_PIC_SYM))))]
6189 "flag_pic"
6190 [(set (match_dup 3) (unspec:SI [(match_dup 2)] UNSPEC_PIC_SYM))
6191 (set (match_dup 0) (mem:SI (plus:SI (match_dup 1) (match_dup 3))))]
6192 "operands[3] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];"
6193)
6194
350ccca5 6195;; operand1 is the memory address to go into
6196;; pic_load_addr_32bit.
6197;; operand2 is the PIC label to be emitted
6198;; from pic_add_dot_plus_eight.
6199;; We do this to allow hoisting of the entire insn.
6200(define_insn_and_split "pic_load_addr_unified"
6201 [(set (match_operand:SI 0 "s_register_operand" "=r,r,l")
6202 (unspec:SI [(match_operand:SI 1 "" "mX,mX,mX")
6203 (match_operand:SI 2 "" "")]
6204 UNSPEC_PIC_UNIFIED))]
6205 "flag_pic"
6206 "#"
6207 "&& reload_completed"
6208 [(set (match_dup 0) (unspec:SI [(match_dup 1)] UNSPEC_PIC_SYM))
6209 (set (match_dup 0) (unspec:SI [(match_dup 0) (match_dup 3)
6210 (match_dup 2)] UNSPEC_PIC_BASE))]
6211 "operands[3] = TARGET_THUMB ? GEN_INT (4) : GEN_INT (8);"
6212 [(set_attr "type" "load1,load1,load1")
42e1de19 6213 (set_attr "pool_range" "4096,4094,1022")
350ccca5 6214 (set_attr "neg_pool_range" "4084,0,0")
6215 (set_attr "arch" "a,t2,t1")
6216 (set_attr "length" "8,6,4")]
6217)
6218
67336bcf 6219;; The rather odd constraints on the following are to force reload to leave
6220;; the insn alone, and to force the minipool generation pass to then move
6221;; the GOT symbol to memory.
849170fd 6222
b3cd5f55 6223(define_insn "pic_load_addr_32bit"
849170fd 6224 [(set (match_operand:SI 0 "s_register_operand" "=r")
e1159bbe 6225 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
b3cd5f55 6226 "TARGET_32BIT && flag_pic"
67336bcf 6227 "ldr%?\\t%0, %1"
a2cd141b 6228 [(set_attr "type" "load1")
42e1de19 6229 (set (attr "pool_range")
6230 (if_then_else (eq_attr "is_thumb" "no")
6231 (const_int 4096)
6232 (const_int 4094)))
b3cd5f55 6233 (set (attr "neg_pool_range")
6234 (if_then_else (eq_attr "is_thumb" "no")
6235 (const_int 4084)
6236 (const_int 0)))]
8c4d8060 6237)
6238
25f905c2 6239(define_insn "pic_load_addr_thumb1"
8c4d8060 6240 [(set (match_operand:SI 0 "s_register_operand" "=l")
e1159bbe 6241 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
25f905c2 6242 "TARGET_THUMB1 && flag_pic"
8c4d8060 6243 "ldr\\t%0, %1"
a2cd141b 6244 [(set_attr "type" "load1")
42e1de19 6245 (set (attr "pool_range") (const_int 1018))]
cffb2a26 6246)
849170fd 6247
cffb2a26 6248(define_insn "pic_add_dot_plus_four"
15d5d060 6249 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 6250 (unspec:SI [(match_operand:SI 1 "register_operand" "0")
6251 (const_int 4)
beef0fb5 6252 (match_operand 2 "" "")]
6253 UNSPEC_PIC_BASE))]
b3cd5f55 6254 "TARGET_THUMB"
cffb2a26 6255 "*
6cdcb15c 6256 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
6257 INTVAL (operands[2]));
cffb2a26 6258 return \"add\\t%0, %|pc\";
6259 "
1b7da4ac 6260 [(set_attr "length" "2")
112eda6f 6261 (set_attr "type" "alu_sreg")]
cffb2a26 6262)
849170fd 6263
6264(define_insn "pic_add_dot_plus_eight"
15d5d060 6265 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 6266 (unspec:SI [(match_operand:SI 1 "register_operand" "r")
6267 (const_int 8)
beef0fb5 6268 (match_operand 2 "" "")]
6269 UNSPEC_PIC_BASE))]
f655717d 6270 "TARGET_ARM"
c4034607 6271 "*
6cdcb15c 6272 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
6273 INTVAL (operands[2]));
15d5d060 6274 return \"add%?\\t%0, %|pc, %1\";
cffb2a26 6275 "
1b7da4ac 6276 [(set_attr "predicable" "yes")
112eda6f 6277 (set_attr "type" "alu_sreg")]
cffb2a26 6278)
849170fd 6279
f655717d 6280(define_insn "tls_load_dot_plus_eight"
cc071db6 6281 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 6282 (mem:SI (unspec:SI [(match_operand:SI 1 "register_operand" "r")
6283 (const_int 8)
beef0fb5 6284 (match_operand 2 "" "")]
6285 UNSPEC_PIC_BASE)))]
f655717d 6286 "TARGET_ARM"
6287 "*
6cdcb15c 6288 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
6289 INTVAL (operands[2]));
f655717d 6290 return \"ldr%?\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_eight\";
6291 "
1b7da4ac 6292 [(set_attr "predicable" "yes")
6293 (set_attr "type" "load1")]
f655717d 6294)
6295
6296;; PIC references to local variables can generate pic_add_dot_plus_eight
6297;; followed by a load. These sequences can be crunched down to
6298;; tls_load_dot_plus_eight by a peephole.
6299
6300(define_peephole2
c0c1fba5 6301 [(set (match_operand:SI 0 "register_operand" "")
6302 (unspec:SI [(match_operand:SI 3 "register_operand" "")
6303 (const_int 8)
6304 (match_operand 1 "" "")]
6305 UNSPEC_PIC_BASE))
2d05dfad 6306 (set (match_operand:SI 2 "arm_general_register_operand" "")
6307 (mem:SI (match_dup 0)))]
f655717d 6308 "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
c0c1fba5 6309 [(set (match_dup 2)
6310 (mem:SI (unspec:SI [(match_dup 3)
6311 (const_int 8)
6312 (match_dup 1)]
6313 UNSPEC_PIC_BASE)))]
f655717d 6314 ""
6315)
6316
bac7fc85 6317(define_insn "pic_offset_arm"
6318 [(set (match_operand:SI 0 "register_operand" "=r")
6319 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
6320 (unspec:SI [(match_operand:SI 2 "" "X")]
6321 UNSPEC_PIC_OFFSET))))]
6322 "TARGET_VXWORKS_RTP && TARGET_ARM && flag_pic"
6323 "ldr%?\\t%0, [%1,%2]"
6324 [(set_attr "type" "load1")]
6325)
6326
95373f08 6327(define_expand "builtin_setjmp_receiver"
6328 [(label_ref (match_operand 0 "" ""))]
6329 "flag_pic"
6330 "
6331{
b935b306 6332 /* r3 is clobbered by set/longjmp, so we can use it as a scratch
6333 register. */
2cb7d577 6334 if (arm_pic_register != INVALID_REGNUM)
6335 arm_load_pic_register (1UL << 3);
95373f08 6336 DONE;
6337}")
6338
9c08d1fa 6339;; If copying one reg to another we can set the condition codes according to
6340;; its value. Such a move is common after a return from subroutine and the
6341;; result is being tested against zero.
6342
f7fbdd4a 6343(define_insn "*movsi_compare0"
bd5b4116 6344 [(set (reg:CC CC_REGNUM)
cffb2a26 6345 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
6346 (const_int 0)))
6347 (set (match_operand:SI 0 "s_register_operand" "=r,r")
6348 (match_dup 1))]
25f905c2 6349 "TARGET_32BIT"
e2348bcb 6350 "@
40dbec34 6351 cmp%?\\t%0, #0
3ef90e77 6352 subs%?\\t%0, %1, #0"
65f68e55 6353 [(set_attr "conds" "set")
d82e788e 6354 (set_attr "type" "alus_imm,alus_imm")]
cffb2a26 6355)
b11cae9e 6356
b11cae9e 6357;; Subroutine to store a half word from a register into memory.
6358;; Operand 0 is the source register (HImode)
c8f69309 6359;; Operand 1 is the destination address in a register (SImode)
b11cae9e 6360
9c08d1fa 6361;; In both this routine and the next, we must be careful not to spill
01cc3b75 6362;; a memory address of reg+large_const into a separate PLUS insn, since this
9c08d1fa 6363;; can generate unrecognizable rtl.
6364
b11cae9e 6365(define_expand "storehi"
c8f69309 6366 [;; store the low byte
f082f1c4 6367 (set (match_operand 1 "" "") (match_dup 3))
b11cae9e 6368 ;; extract the high byte
c8f69309 6369 (set (match_dup 2)
6370 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
b11cae9e 6371 ;; store the high byte
787f8210 6372 (set (match_dup 4) (match_dup 5))]
cffb2a26 6373 "TARGET_ARM"
b11cae9e 6374 "
215b30b3 6375 {
537ffcfc 6376 rtx op1 = operands[1];
6377 rtx addr = XEXP (op1, 0);
215b30b3 6378 enum rtx_code code = GET_CODE (addr);
6379
0438d37f 6380 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
215b30b3 6381 || code == MINUS)
537ffcfc 6382 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
215b30b3 6383
537ffcfc 6384 operands[4] = adjust_address (op1, QImode, 1);
e513d163 6385 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 6386 operands[3] = gen_lowpart (QImode, operands[0]);
6387 operands[0] = gen_lowpart (SImode, operands[0]);
787f8210 6388 operands[2] = gen_reg_rtx (SImode);
6389 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 6390 }"
6391)
b11cae9e 6392
c7597b5d 6393(define_expand "storehi_bigend"
f082f1c4 6394 [(set (match_dup 4) (match_dup 3))
c7597b5d 6395 (set (match_dup 2)
6396 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
787f8210 6397 (set (match_operand 1 "" "") (match_dup 5))]
cffb2a26 6398 "TARGET_ARM"
b11cae9e 6399 "
215b30b3 6400 {
537ffcfc 6401 rtx op1 = operands[1];
6402 rtx addr = XEXP (op1, 0);
215b30b3 6403 enum rtx_code code = GET_CODE (addr);
6404
0438d37f 6405 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
215b30b3 6406 || code == MINUS)
537ffcfc 6407 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
215b30b3 6408
537ffcfc 6409 operands[4] = adjust_address (op1, QImode, 1);
e513d163 6410 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 6411 operands[3] = gen_lowpart (QImode, operands[0]);
6412 operands[0] = gen_lowpart (SImode, operands[0]);
6413 operands[2] = gen_reg_rtx (SImode);
787f8210 6414 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 6415 }"
6416)
c7597b5d 6417
6418;; Subroutine to store a half word integer constant into memory.
6419(define_expand "storeinthi"
f082f1c4 6420 [(set (match_operand 0 "" "")
787f8210 6421 (match_operand 1 "" ""))
9e8503e6 6422 (set (match_dup 3) (match_dup 2))]
cffb2a26 6423 "TARGET_ARM"
c7597b5d 6424 "
215b30b3 6425 {
6426 HOST_WIDE_INT value = INTVAL (operands[1]);
6427 rtx addr = XEXP (operands[0], 0);
537ffcfc 6428 rtx op0 = operands[0];
215b30b3 6429 enum rtx_code code = GET_CODE (addr);
c7597b5d 6430
0438d37f 6431 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
215b30b3 6432 || code == MINUS)
537ffcfc 6433 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
c7597b5d 6434
215b30b3 6435 operands[1] = gen_reg_rtx (SImode);
6436 if (BYTES_BIG_ENDIAN)
6437 {
6438 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
6439 if ((value & 255) == ((value >> 8) & 255))
6440 operands[2] = operands[1];
6441 else
6442 {
6443 operands[2] = gen_reg_rtx (SImode);
6444 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
6445 }
6446 }
6447 else
6448 {
6449 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
6450 if ((value & 255) == ((value >> 8) & 255))
6451 operands[2] = operands[1];
6452 else
6453 {
6454 operands[2] = gen_reg_rtx (SImode);
6455 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
6456 }
6457 }
c7597b5d 6458
537ffcfc 6459 operands[3] = adjust_address (op0, QImode, 1);
e513d163 6460 operands[0] = adjust_address (operands[0], QImode, 0);
9e8503e6 6461 operands[2] = gen_lowpart (QImode, operands[2]);
787f8210 6462 operands[1] = gen_lowpart (QImode, operands[1]);
215b30b3 6463 }"
6464)
b11cae9e 6465
f7fbdd4a 6466(define_expand "storehi_single_op"
6467 [(set (match_operand:HI 0 "memory_operand" "")
6468 (match_operand:HI 1 "general_operand" ""))]
25f905c2 6469 "TARGET_32BIT && arm_arch4"
f7fbdd4a 6470 "
215b30b3 6471 if (!s_register_operand (operands[1], HImode))
f7fbdd4a 6472 operands[1] = copy_to_mode_reg (HImode, operands[1]);
215b30b3 6473 "
6474)
f7fbdd4a 6475
b11cae9e 6476(define_expand "movhi"
6477 [(set (match_operand:HI 0 "general_operand" "")
c8f69309 6478 (match_operand:HI 1 "general_operand" ""))]
cffb2a26 6479 "TARGET_EITHER"
b11cae9e 6480 "
cffb2a26 6481 if (TARGET_ARM)
b11cae9e 6482 {
e1ba4a27 6483 if (can_create_pseudo_p ())
cffb2a26 6484 {
0438d37f 6485 if (MEM_P (operands[0]))
b11cae9e 6486 {
cffb2a26 6487 if (arm_arch4)
6488 {
6489 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
6490 DONE;
6491 }
0438d37f 6492 if (CONST_INT_P (operands[1]))
cffb2a26 6493 emit_insn (gen_storeinthi (operands[0], operands[1]));
c7597b5d 6494 else
cffb2a26 6495 {
0438d37f 6496 if (MEM_P (operands[1]))
cffb2a26 6497 operands[1] = force_reg (HImode, operands[1]);
6498 if (BYTES_BIG_ENDIAN)
6499 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
6500 else
6501 emit_insn (gen_storehi (operands[1], operands[0]));
6502 }
6503 DONE;
b11cae9e 6504 }
cffb2a26 6505 /* Sign extend a constant, and keep it in an SImode reg. */
0438d37f 6506 else if (CONST_INT_P (operands[1]))
9c08d1fa 6507 {
cffb2a26 6508 rtx reg = gen_reg_rtx (SImode);
6509 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
6510
6511 /* If the constant is already valid, leave it alone. */
215b30b3 6512 if (!const_ok_for_arm (val))
cffb2a26 6513 {
6514 /* If setting all the top bits will make the constant
6515 loadable in a single instruction, then set them.
6516 Otherwise, sign extend the number. */
6517
215b30b3 6518 if (const_ok_for_arm (~(val | ~0xffff)))
cffb2a26 6519 val |= ~0xffff;
6520 else if (val & 0x8000)
6521 val |= ~0xffff;
6522 }
6523
6524 emit_insn (gen_movsi (reg, GEN_INT (val)));
9e8503e6 6525 operands[1] = gen_lowpart (HImode, reg);
9c08d1fa 6526 }
e1ba4a27 6527 else if (arm_arch4 && optimize && can_create_pseudo_p ()
0438d37f 6528 && MEM_P (operands[1]))
0045890a 6529 {
6530 rtx reg = gen_reg_rtx (SImode);
6531
6532 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
6533 operands[1] = gen_lowpart (HImode, reg);
6534 }
215b30b3 6535 else if (!arm_arch4)
f7fbdd4a 6536 {
0438d37f 6537 if (MEM_P (operands[1]))
cffb2a26 6538 {
c1a66faf 6539 rtx base;
6540 rtx offset = const0_rtx;
6541 rtx reg = gen_reg_rtx (SImode);
6542
0438d37f 6543 if ((REG_P (base = XEXP (operands[1], 0))
c1a66faf 6544 || (GET_CODE (base) == PLUS
0438d37f 6545 && (CONST_INT_P (offset = XEXP (base, 1)))
c1a66faf 6546 && ((INTVAL(offset) & 1) != 1)
0438d37f 6547 && REG_P (base = XEXP (base, 0))))
c1a66faf 6548 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
206ee9a2 6549 {
8deb3959 6550 rtx new_rtx;
c1a66faf 6551
8deb3959 6552 new_rtx = widen_memory_access (operands[1], SImode,
6553 ((INTVAL (offset) & ~3)
6554 - INTVAL (offset)));
6555 emit_insn (gen_movsi (reg, new_rtx));
c1a66faf 6556 if (((INTVAL (offset) & 2) != 0)
6557 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
6558 {
6559 rtx reg2 = gen_reg_rtx (SImode);
6560
6561 emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
6562 reg = reg2;
6563 }
206ee9a2 6564 }
c1a66faf 6565 else
6566 emit_insn (gen_movhi_bytes (reg, operands[1]));
6567
6568 operands[1] = gen_lowpart (HImode, reg);
cffb2a26 6569 }
6570 }
6571 }
674a8f0b 6572 /* Handle loading a large integer during reload. */
0438d37f 6573 else if (CONST_INT_P (operands[1])
215b30b3 6574 && !const_ok_for_arm (INTVAL (operands[1]))
6575 && !const_ok_for_arm (~INTVAL (operands[1])))
cffb2a26 6576 {
6577 /* Writing a constant to memory needs a scratch, which should
6578 be handled with SECONDARY_RELOADs. */
0438d37f 6579 gcc_assert (REG_P (operands[0]));
cffb2a26 6580
6581 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
6582 emit_insn (gen_movsi (operands[0], operands[1]));
6583 DONE;
6584 }
6585 }
25f905c2 6586 else if (TARGET_THUMB2)
6587 {
6588 /* Thumb-2 can do everything except mem=mem and mem=const easily. */
e1ba4a27 6589 if (can_create_pseudo_p ())
25f905c2 6590 {
0438d37f 6591 if (!REG_P (operands[0]))
25f905c2 6592 operands[1] = force_reg (HImode, operands[1]);
6593 /* Zero extend a constant, and keep it in an SImode reg. */
0438d37f 6594 else if (CONST_INT_P (operands[1]))
25f905c2 6595 {
6596 rtx reg = gen_reg_rtx (SImode);
6597 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
6598
6599 emit_insn (gen_movsi (reg, GEN_INT (val)));
6600 operands[1] = gen_lowpart (HImode, reg);
6601 }
6602 }
6603 }
6604 else /* TARGET_THUMB1 */
cffb2a26 6605 {
e1ba4a27 6606 if (can_create_pseudo_p ())
cffb2a26 6607 {
0438d37f 6608 if (CONST_INT_P (operands[1]))
6cffc037 6609 {
6610 rtx reg = gen_reg_rtx (SImode);
6611
6612 emit_insn (gen_movsi (reg, operands[1]));
6613 operands[1] = gen_lowpart (HImode, reg);
6614 }
cffb2a26 6615
6616 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 6617 happen if we are passed a SP (never OK for HImode/QImode) or
bc409cb4 6618 virtual register (also rejected as illegitimate for HImode/QImode)
6619 relative address. */
cffb2a26 6620 /* ??? This should perhaps be fixed elsewhere, for instance, in
6621 fixup_stack_1, by checking for other kinds of invalid addresses,
6622 e.g. a bare reference to a virtual register. This may confuse the
6623 alpha though, which must handle this case differently. */
0438d37f 6624 if (MEM_P (operands[0])
215b30b3 6625 && !memory_address_p (GET_MODE (operands[0]),
6626 XEXP (operands[0], 0)))
537ffcfc 6627 operands[0]
6628 = replace_equiv_address (operands[0],
6629 copy_to_reg (XEXP (operands[0], 0)));
cffb2a26 6630
0438d37f 6631 if (MEM_P (operands[1])
215b30b3 6632 && !memory_address_p (GET_MODE (operands[1]),
6633 XEXP (operands[1], 0)))
537ffcfc 6634 operands[1]
6635 = replace_equiv_address (operands[1],
6636 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 6637
0438d37f 6638 if (MEM_P (operands[1]) && optimize > 0)
6cffc037 6639 {
6640 rtx reg = gen_reg_rtx (SImode);
6641
6642 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
6643 operands[1] = gen_lowpart (HImode, reg);
6644 }
6645
0438d37f 6646 if (MEM_P (operands[0]))
6cffc037 6647 operands[1] = force_reg (HImode, operands[1]);
cffb2a26 6648 }
0438d37f 6649 else if (CONST_INT_P (operands[1])
234f6557 6650 && !satisfies_constraint_I (operands[1]))
cffb2a26 6651 {
6cffc037 6652 /* Handle loading a large integer during reload. */
6653
cffb2a26 6654 /* Writing a constant to memory needs a scratch, which should
6655 be handled with SECONDARY_RELOADs. */
0438d37f 6656 gcc_assert (REG_P (operands[0]));
cffb2a26 6657
1a83b3ff 6658 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
cffb2a26 6659 emit_insn (gen_movsi (operands[0], operands[1]));
6660 DONE;
6661 }
b11cae9e 6662 }
cffb2a26 6663 "
6664)
6665
25f7a26e 6666(define_expand "movhi_bytes"
eab14235 6667 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 6668 (set (match_dup 3)
eab14235 6669 (zero_extend:SI (match_dup 6)))
25f7a26e 6670 (set (match_operand:SI 0 "" "")
6671 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
cffb2a26 6672 "TARGET_ARM"
25f7a26e 6673 "
215b30b3 6674 {
6675 rtx mem1, mem2;
6676 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
6677
788fcce0 6678 mem1 = change_address (operands[1], QImode, addr);
29c05e22 6679 mem2 = change_address (operands[1], QImode,
6680 plus_constant (Pmode, addr, 1));
215b30b3 6681 operands[0] = gen_lowpart (SImode, operands[0]);
6682 operands[1] = mem1;
6683 operands[2] = gen_reg_rtx (SImode);
6684 operands[3] = gen_reg_rtx (SImode);
6685 operands[6] = mem2;
25f7a26e 6686
215b30b3 6687 if (BYTES_BIG_ENDIAN)
6688 {
6689 operands[4] = operands[2];
6690 operands[5] = operands[3];
6691 }
6692 else
6693 {
6694 operands[4] = operands[3];
6695 operands[5] = operands[2];
6696 }
6697 }"
6698)
25f7a26e 6699
c7597b5d 6700(define_expand "movhi_bigend"
6701 [(set (match_dup 2)
6702 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
6703 (const_int 16)))
6704 (set (match_dup 3)
6705 (ashiftrt:SI (match_dup 2) (const_int 16)))
6706 (set (match_operand:HI 0 "s_register_operand" "")
787f8210 6707 (match_dup 4))]
cffb2a26 6708 "TARGET_ARM"
c7597b5d 6709 "
6710 operands[2] = gen_reg_rtx (SImode);
6711 operands[3] = gen_reg_rtx (SImode);
787f8210 6712 operands[4] = gen_lowpart (HImode, operands[3]);
215b30b3 6713 "
6714)
b11cae9e 6715
a2f10574 6716;; Pattern to recognize insn generated default case above
f7fbdd4a 6717(define_insn "*movhi_insn_arch4"
e4585731 6718 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r,m,r")
6719 (match_operand:HI 1 "general_operand" "rIk,K,n,r,mi"))]
cffb2a26 6720 "TARGET_ARM
d7216193 6721 && arm_arch4 && !TARGET_HARD_FLOAT
85e02ccb 6722 && (register_operand (operands[0], HImode)
6723 || register_operand (operands[1], HImode))"
f7fbdd4a 6724 "@
6725 mov%?\\t%0, %1\\t%@ movhi
6726 mvn%?\\t%0, #%B1\\t%@ movhi
b1c1a101 6727 movw%?\\t%0, %L1\\t%@ movhi
3ef90e77 6728 strh%?\\t%1, %0\\t%@ movhi
6729 ldrh%?\\t%0, %1\\t%@ movhi"
65f68e55 6730 [(set_attr "predicable" "yes")
e4585731 6731 (set_attr "pool_range" "*,*,*,*,256")
6732 (set_attr "neg_pool_range" "*,*,*,*,244")
6733 (set_attr "arch" "*,*,v6t2,*,*")
65f68e55 6734 (set_attr_alternative "type"
6735 [(if_then_else (match_operand 1 "const_int_operand" "")
1aed5204 6736 (const_string "mov_imm" )
6737 (const_string "mov_reg"))
6738 (const_string "mvn_imm")
e4585731 6739 (const_string "mov_imm")
65f68e55 6740 (const_string "store1")
6741 (const_string "load1")])]
cffb2a26 6742)
f7fbdd4a 6743
f7fbdd4a 6744(define_insn "*movhi_bytes"
65f68e55 6745 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
5fd254ed 6746 (match_operand:HI 1 "arm_rhs_operand" "I,rk,K"))]
d7216193 6747 "TARGET_ARM && !TARGET_HARD_FLOAT"
25f7a26e 6748 "@
65f68e55 6749 mov%?\\t%0, %1\\t%@ movhi
25f7a26e 6750 mov%?\\t%0, %1\\t%@ movhi
0d66636f 6751 mvn%?\\t%0, #%B1\\t%@ movhi"
d2a518d1 6752 [(set_attr "predicable" "yes")
1aed5204 6753 (set_attr "type" "mov_imm,mov_reg,mvn_imm")]
0d66636f 6754)
837bb76e 6755
bc5c7e08 6756;; We use a DImode scratch because we may occasionally need an additional
6757;; temporary if the address isn't offsettable -- push_reload doesn't seem
6758;; to take any notice of the "o" constraints on reload_memory_operand operand.
d3373b54 6759(define_expand "reload_outhi"
cffb2a26 6760 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
215b30b3 6761 (match_operand:HI 1 "s_register_operand" "r")
6762 (match_operand:DI 2 "s_register_operand" "=&l")])]
cffb2a26 6763 "TARGET_EITHER"
6764 "if (TARGET_ARM)
6765 arm_reload_out_hi (operands);
6766 else
6767 thumb_reload_out_hi (operands);
d3373b54 6768 DONE;
cffb2a26 6769 "
6770)
d3373b54 6771
25f7a26e 6772(define_expand "reload_inhi"
6773 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
cffb2a26 6774 (match_operand:HI 1 "arm_reload_memory_operand" "o")
bc5c7e08 6775 (match_operand:DI 2 "s_register_operand" "=&r")])]
c1a66faf 6776 "TARGET_EITHER"
25f7a26e 6777 "
cffb2a26 6778 if (TARGET_ARM)
6779 arm_reload_in_hi (operands);
6780 else
6781 thumb_reload_out_hi (operands);
25f7a26e 6782 DONE;
6783")
6784
9c08d1fa 6785(define_expand "movqi"
6786 [(set (match_operand:QI 0 "general_operand" "")
6787 (match_operand:QI 1 "general_operand" ""))]
cffb2a26 6788 "TARGET_EITHER"
9c08d1fa 6789 "
6cffc037 6790 /* Everything except mem = const or mem = mem can be done easily */
0045890a 6791
e1ba4a27 6792 if (can_create_pseudo_p ())
cffb2a26 6793 {
0438d37f 6794 if (CONST_INT_P (operands[1]))
6cffc037 6795 {
6796 rtx reg = gen_reg_rtx (SImode);
6797
03770691 6798 /* For thumb we want an unsigned immediate, then we are more likely
6799 to be able to use a movs insn. */
6800 if (TARGET_THUMB)
6801 operands[1] = GEN_INT (INTVAL (operands[1]) & 255);
6802
6cffc037 6803 emit_insn (gen_movsi (reg, operands[1]));
6804 operands[1] = gen_lowpart (QImode, reg);
6805 }
cffb2a26 6806
6cffc037 6807 if (TARGET_THUMB)
6808 {
cffb2a26 6809 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 6810 happen if we are passed a SP (never OK for HImode/QImode) or
bc409cb4 6811 virtual register (also rejected as illegitimate for HImode/QImode)
6812 relative address. */
cffb2a26 6813 /* ??? This should perhaps be fixed elsewhere, for instance, in
6814 fixup_stack_1, by checking for other kinds of invalid addresses,
6815 e.g. a bare reference to a virtual register. This may confuse the
6816 alpha though, which must handle this case differently. */
0438d37f 6817 if (MEM_P (operands[0])
215b30b3 6818 && !memory_address_p (GET_MODE (operands[0]),
cffb2a26 6819 XEXP (operands[0], 0)))
537ffcfc 6820 operands[0]
6821 = replace_equiv_address (operands[0],
6822 copy_to_reg (XEXP (operands[0], 0)));
0438d37f 6823 if (MEM_P (operands[1])
215b30b3 6824 && !memory_address_p (GET_MODE (operands[1]),
cffb2a26 6825 XEXP (operands[1], 0)))
537ffcfc 6826 operands[1]
6827 = replace_equiv_address (operands[1],
6828 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 6829 }
6830
0438d37f 6831 if (MEM_P (operands[1]) && optimize > 0)
6cffc037 6832 {
6833 rtx reg = gen_reg_rtx (SImode);
6834
6835 emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
6836 operands[1] = gen_lowpart (QImode, reg);
6837 }
6838
0438d37f 6839 if (MEM_P (operands[0]))
6cffc037 6840 operands[1] = force_reg (QImode, operands[1]);
6841 }
6842 else if (TARGET_THUMB
0438d37f 6843 && CONST_INT_P (operands[1])
234f6557 6844 && !satisfies_constraint_I (operands[1]))
6cffc037 6845 {
674a8f0b 6846 /* Handle loading a large integer during reload. */
cffb2a26 6847
6cffc037 6848 /* Writing a constant to memory needs a scratch, which should
6849 be handled with SECONDARY_RELOADs. */
0438d37f 6850 gcc_assert (REG_P (operands[0]));
6cffc037 6851
6852 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
6853 emit_insn (gen_movsi (operands[0], operands[1]));
6854 DONE;
cffb2a26 6855 }
6856 "
6857)
b11cae9e 6858
cffb2a26 6859(define_insn "*arm_movqi_insn"
fd711051 6860 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,l,r,l,Uu,r,m")
490f62ca 6861 (match_operand:QI 1 "general_operand" "rk,rk,I,Py,K,Uu,l,Uh,r"))]
25f905c2 6862 "TARGET_32BIT
cffb2a26 6863 && ( register_operand (operands[0], QImode)
6864 || register_operand (operands[1], QImode))"
5565501b 6865 "@
fd711051 6866 mov%?\\t%0, %1
6867 mov%?\\t%0, %1
65f68e55 6868 mov%?\\t%0, %1
5565501b 6869 mov%?\\t%0, %1
6870 mvn%?\\t%0, #%B1
3ef90e77 6871 ldrb%?\\t%0, %1
6872 strb%?\\t%1, %0
6873 ldrb%?\\t%0, %1
6874 strb%?\\t%1, %0"
1aed5204 6875 [(set_attr "type" "mov_reg,mov_reg,mov_imm,mov_imm,mvn_imm,load1,store1,load1,store1")
a54e3e7b 6876 (set_attr "predicable" "yes")
5233bf6a 6877 (set_attr "predicable_short_it" "yes,yes,no,yes,no,no,no,no,no")
fd711051 6878 (set_attr "arch" "t2,any,any,t2,any,t2,t2,any,any")
6879 (set_attr "length" "2,4,4,2,4,2,2,4,4")]
cffb2a26 6880)
6881
9b8516be 6882;; HFmode moves
6883(define_expand "movhf"
6884 [(set (match_operand:HF 0 "general_operand" "")
6885 (match_operand:HF 1 "general_operand" ""))]
6886 "TARGET_EITHER"
6887 "
6888 if (TARGET_32BIT)
6889 {
0438d37f 6890 if (MEM_P (operands[0]))
9b8516be 6891 operands[1] = force_reg (HFmode, operands[1]);
6892 }
6893 else /* TARGET_THUMB1 */
6894 {
6895 if (can_create_pseudo_p ())
6896 {
0438d37f 6897 if (!REG_P (operands[0]))
9b8516be 6898 operands[1] = force_reg (HFmode, operands[1]);
6899 }
6900 }
6901 "
6902)
6903
6904(define_insn "*arm32_movhf"
6905 [(set (match_operand:HF 0 "nonimmediate_operand" "=r,m,r,r")
6906 (match_operand:HF 1 "general_operand" " m,r,r,F"))]
d7216193 6907 "TARGET_32BIT && !TARGET_HARD_FLOAT
9b8516be 6908 && ( s_register_operand (operands[0], HFmode)
6909 || s_register_operand (operands[1], HFmode))"
6910 "*
6911 switch (which_alternative)
6912 {
6913 case 0: /* ARM register from memory */
3ef90e77 6914 return \"ldrh%?\\t%0, %1\\t%@ __fp16\";
9b8516be 6915 case 1: /* memory from ARM register */
3ef90e77 6916 return \"strh%?\\t%1, %0\\t%@ __fp16\";
9b8516be 6917 case 2: /* ARM register from ARM register */
6918 return \"mov%?\\t%0, %1\\t%@ __fp16\";
6919 case 3: /* ARM register from constant */
6920 {
9b8516be 6921 long bits;
6922 rtx ops[4];
6923
945f7b03 6924 bits = real_to_target (NULL, CONST_DOUBLE_REAL_VALUE (operands[1]),
6925 HFmode);
9b8516be 6926 ops[0] = operands[0];
6927 ops[1] = GEN_INT (bits);
6928 ops[2] = GEN_INT (bits & 0xff00);
6929 ops[3] = GEN_INT (bits & 0x00ff);
6930
6931 if (arm_arch_thumb2)
6932 output_asm_insn (\"movw%?\\t%0, %1\", ops);
6933 else
6934 output_asm_insn (\"mov%?\\t%0, %2\;orr%?\\t%0, %0, %3\", ops);
6935 return \"\";
6936 }
6937 default:
6938 gcc_unreachable ();
6939 }
6940 "
6941 [(set_attr "conds" "unconditional")
ad4fc3c0 6942 (set_attr "type" "load1,store1,mov_reg,multiple")
9b8516be 6943 (set_attr "length" "4,4,4,8")
ea501323 6944 (set_attr "predicable" "yes")
6945 (set_attr "predicable_short_it" "no")]
9b8516be 6946)
6947
87b22bf7 6948(define_expand "movsf"
6949 [(set (match_operand:SF 0 "general_operand" "")
6950 (match_operand:SF 1 "general_operand" ""))]
cffb2a26 6951 "TARGET_EITHER"
87b22bf7 6952 "
25f905c2 6953 if (TARGET_32BIT)
cffb2a26 6954 {
0438d37f 6955 if (MEM_P (operands[0]))
cffb2a26 6956 operands[1] = force_reg (SFmode, operands[1]);
6957 }
25f905c2 6958 else /* TARGET_THUMB1 */
cffb2a26 6959 {
e1ba4a27 6960 if (can_create_pseudo_p ())
cffb2a26 6961 {
0438d37f 6962 if (!REG_P (operands[0]))
cffb2a26 6963 operands[1] = force_reg (SFmode, operands[1]);
6964 }
6965 }
6966 "
6967)
6968
03d440a6 6969;; Transform a floating-point move of a constant into a core register into
6970;; an SImode operation.
cffb2a26 6971(define_split
03d440a6 6972 [(set (match_operand:SF 0 "arm_general_register_operand" "")
cffb2a26 6973 (match_operand:SF 1 "immediate_operand" ""))]
339034d0 6974 "TARGET_EITHER
cffb2a26 6975 && reload_completed
0438d37f 6976 && CONST_DOUBLE_P (operands[1])"
cffb2a26 6977 [(set (match_dup 2) (match_dup 3))]
6978 "
6979 operands[2] = gen_lowpart (SImode, operands[0]);
6980 operands[3] = gen_lowpart (SImode, operands[1]);
6981 if (operands[2] == 0 || operands[3] == 0)
6982 FAIL;
215b30b3 6983 "
6984)
87b22bf7 6985
cffb2a26 6986(define_insn "*arm_movsf_soft_insn"
6987 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
6988 (match_operand:SF 1 "general_operand" "r,mE,r"))]
cde1623a 6989 "TARGET_32BIT
cffb2a26 6990 && TARGET_SOFT_FLOAT
0438d37f 6991 && (!MEM_P (operands[0])
215b30b3 6992 || register_operand (operands[1], SFmode))"
9a1112d7 6993 "@
6994 mov%?\\t%0, %1
6995 ldr%?\\t%0, %1\\t%@ float
6996 str%?\\t%1, %0\\t%@ float"
cde1623a 6997 [(set_attr "predicable" "yes")
7c36fe71 6998 (set_attr "predicable_short_it" "no")
1aed5204 6999 (set_attr "type" "mov_reg,load1,store1")
42e1de19 7000 (set_attr "arm_pool_range" "*,4096,*")
7001 (set_attr "thumb2_pool_range" "*,4094,*")
cde1623a 7002 (set_attr "arm_neg_pool_range" "*,4084,*")
7003 (set_attr "thumb2_neg_pool_range" "*,0,*")]
cffb2a26 7004)
7005
9c08d1fa 7006(define_expand "movdf"
87b22bf7 7007 [(set (match_operand:DF 0 "general_operand" "")
7008 (match_operand:DF 1 "general_operand" ""))]
cffb2a26 7009 "TARGET_EITHER"
9c08d1fa 7010 "
25f905c2 7011 if (TARGET_32BIT)
cffb2a26 7012 {
0438d37f 7013 if (MEM_P (operands[0]))
cffb2a26 7014 operands[1] = force_reg (DFmode, operands[1]);
7015 }
7016 else /* TARGET_THUMB */
7017 {
e1ba4a27 7018 if (can_create_pseudo_p ())
cffb2a26 7019 {
0438d37f 7020 if (!REG_P (operands[0]))
cffb2a26 7021 operands[1] = force_reg (DFmode, operands[1]);
7022 }
7023 }
7024 "
7025)
b11cae9e 7026
9c08d1fa 7027;; Reloading a df mode value stored in integer regs to memory can require a
7028;; scratch reg.
7029(define_expand "reload_outdf"
cffb2a26 7030 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
87b22bf7 7031 (match_operand:DF 1 "s_register_operand" "r")
7032 (match_operand:SI 2 "s_register_operand" "=&r")]
06adefdc 7033 "TARGET_THUMB2"
87b22bf7 7034 "
215b30b3 7035 {
7036 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
f7fbdd4a 7037
215b30b3 7038 if (code == REG)
7039 operands[2] = XEXP (operands[0], 0);
7040 else if (code == POST_INC || code == PRE_DEC)
7041 {
7042 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
7043 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
7044 emit_insn (gen_movdi (operands[0], operands[1]));
7045 DONE;
7046 }
7047 else if (code == PRE_INC)
7048 {
7049 rtx reg = XEXP (XEXP (operands[0], 0), 0);
f7fbdd4a 7050
215b30b3 7051 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
7052 operands[2] = reg;
7053 }
7054 else if (code == POST_DEC)
7055 operands[2] = XEXP (XEXP (operands[0], 0), 0);
7056 else
7057 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
7058 XEXP (XEXP (operands[0], 0), 1)));
f7fbdd4a 7059
d1f9b275 7060 emit_insn (gen_rtx_SET (replace_equiv_address (operands[0], operands[2]),
215b30b3 7061 operands[1]));
f7fbdd4a 7062
215b30b3 7063 if (code == POST_DEC)
7064 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
7065
7066 DONE;
7067 }"
7068)
9c08d1fa 7069
9a1112d7 7070(define_insn "*movdf_soft_insn"
353cf59a 7071 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,q,m")
7072 (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,q"))]
cde1623a 7073 "TARGET_32BIT && TARGET_SOFT_FLOAT
b2778788 7074 && ( register_operand (operands[0], DFmode)
7075 || register_operand (operands[1], DFmode))"
d51f92df 7076 "*
7077 switch (which_alternative)
7078 {
7079 case 0:
7080 case 1:
7081 case 2:
7082 return \"#\";
7083 default:
26ff80c0 7084 return output_move_double (operands, true, NULL);
d51f92df 7085 }
7086 "
359a6e9f 7087 [(set_attr "length" "8,12,16,8,8")
1b7da4ac 7088 (set_attr "type" "multiple,multiple,multiple,load2,store2")
42e1de19 7089 (set_attr "arm_pool_range" "*,*,*,1020,*")
7090 (set_attr "thumb2_pool_range" "*,*,*,1018,*")
8848d797 7091 (set_attr "arm_neg_pool_range" "*,*,*,1004,*")
cde1623a 7092 (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
cffb2a26 7093)
b11cae9e 7094\f
b11cae9e 7095
9c08d1fa 7096;; load- and store-multiple insns
7097;; The arm can load/store any set of registers, provided that they are in
320ea44d 7098;; ascending order, but these expanders assume a contiguous set.
b11cae9e 7099
9c08d1fa 7100(define_expand "load_multiple"
7101 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
7102 (match_operand:SI 1 "" ""))
7103 (use (match_operand:SI 2 "" ""))])]
25f905c2 7104 "TARGET_32BIT"
9580c25f 7105{
7106 HOST_WIDE_INT offset = 0;
7107
bd5b4116 7108 /* Support only fixed point registers. */
0438d37f 7109 if (!CONST_INT_P (operands[2])
6e628811 7110 || INTVAL (operands[2]) > MAX_LDM_STM_OPS
9c08d1fa 7111 || INTVAL (operands[2]) < 2
0438d37f 7112 || !MEM_P (operands[1])
7113 || !REG_P (operands[0])
bd5b4116 7114 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
7115 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 7116 FAIL;
7117
7118 operands[3]
320ea44d 7119 = arm_gen_load_multiple (arm_regs_in_sequence + REGNO (operands[0]),
7120 INTVAL (operands[2]),
f082f1c4 7121 force_reg (SImode, XEXP (operands[1], 0)),
320ea44d 7122 FALSE, operands[1], &offset);
9580c25f 7123})
b11cae9e 7124
9c08d1fa 7125(define_expand "store_multiple"
7126 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
7127 (match_operand:SI 1 "" ""))
7128 (use (match_operand:SI 2 "" ""))])]
25f905c2 7129 "TARGET_32BIT"
9580c25f 7130{
7131 HOST_WIDE_INT offset = 0;
7132
674a8f0b 7133 /* Support only fixed point registers. */
0438d37f 7134 if (!CONST_INT_P (operands[2])
6e628811 7135 || INTVAL (operands[2]) > MAX_LDM_STM_OPS
9c08d1fa 7136 || INTVAL (operands[2]) < 2
0438d37f 7137 || !REG_P (operands[1])
7138 || !MEM_P (operands[0])
bd5b4116 7139 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
7140 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 7141 FAIL;
7142
7143 operands[3]
320ea44d 7144 = arm_gen_store_multiple (arm_regs_in_sequence + REGNO (operands[1]),
7145 INTVAL (operands[2]),
f082f1c4 7146 force_reg (SImode, XEXP (operands[0], 0)),
320ea44d 7147 FALSE, operands[0], &offset);
9580c25f 7148})
b11cae9e 7149
9c08d1fa 7150
e34ebfca 7151(define_expand "setmemsi"
7152 [(match_operand:BLK 0 "general_operand" "")
7153 (match_operand:SI 1 "const_int_operand" "")
7154 (match_operand:SI 2 "const_int_operand" "")
7155 (match_operand:SI 3 "const_int_operand" "")]
7156 "TARGET_32BIT"
7157{
7158 if (arm_gen_setmem (operands))
7159 DONE;
7160
7161 FAIL;
7162})
7163
7164
9c08d1fa 7165;; Move a block of memory if it is word aligned and MORE than 2 words long.
7166;; We could let this apply for blocks of less than this, but it clobbers so
7167;; many registers that there is then probably a better way.
7168
008c057d 7169(define_expand "movmemqi"
34191dd1 7170 [(match_operand:BLK 0 "general_operand" "")
7171 (match_operand:BLK 1 "general_operand" "")
7172 (match_operand:SI 2 "const_int_operand" "")
7173 (match_operand:SI 3 "const_int_operand" "")]
ae51a965 7174 ""
9c08d1fa 7175 "
25f905c2 7176 if (TARGET_32BIT)
cffb2a26 7177 {
ae51a965 7178 if (TARGET_LDRD && current_tune->prefer_ldrd_strd
7179 && !optimize_function_for_size_p (cfun))
7180 {
7181 if (gen_movmem_ldrd_strd (operands))
7182 DONE;
7183 FAIL;
7184 }
7185
008c057d 7186 if (arm_gen_movmemqi (operands))
cffb2a26 7187 DONE;
7188 FAIL;
7189 }
25f905c2 7190 else /* TARGET_THUMB1 */
cffb2a26 7191 {
7192 if ( INTVAL (operands[3]) != 4
7193 || INTVAL (operands[2]) > 48)
7194 FAIL;
7195
008c057d 7196 thumb_expand_movmemqi (operands);
cffb2a26 7197 DONE;
7198 }
7199 "
7200)
9c08d1fa 7201\f
b11cae9e 7202
341940e8 7203;; Compare & branch insns
8d232dc7 7204;; The range calculations are based as follows:
341940e8 7205;; For forward branches, the address calculation returns the address of
7206;; the next instruction. This is 2 beyond the branch instruction.
7207;; For backward branches, the address calculation returns the address of
7208;; the first instruction in this pattern (cmp). This is 2 before the branch
7209;; instruction for the shortest sequence, and 4 before the branch instruction
7210;; if we have to jump around an unconditional branch.
7211;; To the basic branch range the PC offset must be added (this is +4).
7212;; So for forward branches we have
7213;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
7214;; And for backward branches we have
7215;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
7216;;
7217;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
7218;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
cffb2a26 7219
aeac46d4 7220(define_expand "cbranchsi4"
7221 [(set (pc) (if_then_else
aa06947a 7222 (match_operator 0 "expandable_comparison_operator"
aeac46d4 7223 [(match_operand:SI 1 "s_register_operand" "")
7224 (match_operand:SI 2 "nonmemory_operand" "")])
7225 (label_ref (match_operand 3 "" ""))
7226 (pc)))]
f9aa4160 7227 "TARGET_EITHER"
aeac46d4 7228 "
74f4459c 7229 if (!TARGET_THUMB1)
7230 {
f9aa4160 7231 if (!arm_validize_comparison (&operands[0], &operands[1], &operands[2]))
7232 FAIL;
74f4459c 7233 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
7234 operands[3]));
7235 DONE;
7236 }
25f905c2 7237 if (thumb1_cmpneg_operand (operands[2], SImode))
aeac46d4 7238 {
7239 emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
7240 operands[3], operands[0]));
7241 DONE;
7242 }
25f905c2 7243 if (!thumb1_cmp_operand (operands[2], SImode))
aeac46d4 7244 operands[2] = force_reg (SImode, operands[2]);
7245 ")
7246
74f4459c 7247(define_expand "cbranchsf4"
7248 [(set (pc) (if_then_else
aa06947a 7249 (match_operator 0 "expandable_comparison_operator"
74f4459c 7250 [(match_operand:SF 1 "s_register_operand" "")
d7216193 7251 (match_operand:SF 2 "vfp_compare_operand" "")])
74f4459c 7252 (label_ref (match_operand 3 "" ""))
7253 (pc)))]
7254 "TARGET_32BIT && TARGET_HARD_FLOAT"
7255 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
7256 operands[3])); DONE;"
7257)
7258
7259(define_expand "cbranchdf4"
7260 [(set (pc) (if_then_else
aa06947a 7261 (match_operator 0 "expandable_comparison_operator"
74f4459c 7262 [(match_operand:DF 1 "s_register_operand" "")
d7216193 7263 (match_operand:DF 2 "vfp_compare_operand" "")])
74f4459c 7264 (label_ref (match_operand 3 "" ""))
7265 (pc)))]
a50d7267 7266 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
74f4459c 7267 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
7268 operands[3])); DONE;"
7269)
7270
74f4459c 7271(define_expand "cbranchdi4"
7272 [(set (pc) (if_then_else
aa06947a 7273 (match_operator 0 "expandable_comparison_operator"
b8eae306 7274 [(match_operand:DI 1 "s_register_operand" "")
a8045a4f 7275 (match_operand:DI 2 "cmpdi_operand" "")])
74f4459c 7276 (label_ref (match_operand 3 "" ""))
7277 (pc)))]
a8045a4f 7278 "TARGET_32BIT"
7279 "{
0438d37f 7280 if (!arm_validize_comparison (&operands[0], &operands[1], &operands[2]))
f9aa4160 7281 FAIL;
7282 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
a8045a4f 7283 operands[3]));
7284 DONE;
7285 }"
74f4459c 7286)
7287
9c08d1fa 7288;; Comparison and test insns
7289
cffb2a26 7290(define_insn "*arm_cmpsi_insn"
bd5b4116 7291 [(set (reg:CC CC_REGNUM)
f9f234ec 7292 (compare:CC (match_operand:SI 0 "s_register_operand" "l,r,r,r,r")
7293 (match_operand:SI 1 "arm_add_operand" "Py,r,r,I,L")))]
25f905c2 7294 "TARGET_32BIT"
5565501b 7295 "@
a6864a24 7296 cmp%?\\t%0, %1
7297 cmp%?\\t%0, %1
aea4c774 7298 cmp%?\\t%0, %1
f9f234ec 7299 cmp%?\\t%0, %1
aea4c774 7300 cmn%?\\t%0, #%n1"
a6864a24 7301 [(set_attr "conds" "set")
f9f234ec 7302 (set_attr "arch" "t2,t2,any,any,any")
7303 (set_attr "length" "2,2,4,4,4")
65f68e55 7304 (set_attr "predicable" "yes")
f9f234ec 7305 (set_attr "predicable_short_it" "yes,yes,yes,no,no")
112eda6f 7306 (set_attr "type" "alus_imm,alus_sreg,alus_sreg,alus_imm,alus_imm")]
cffb2a26 7307)
b11cae9e 7308
d5d4dc8d 7309(define_insn "*cmpsi_shiftsi"
bd5b4116 7310 [(set (reg:CC CC_REGNUM)
d82e788e 7311 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r,r")
cffb2a26 7312 (match_operator:SI 3 "shift_operator"
d82e788e 7313 [(match_operand:SI 1 "s_register_operand" "r,r,r")
7314 (match_operand:SI 2 "shift_amount_operand" "M,r,M")])))]
d5d4dc8d 7315 "TARGET_32BIT"
f9f234ec 7316 "cmp\\t%0, %1%S3"
344495ea 7317 [(set_attr "conds" "set")
331beb1a 7318 (set_attr "shift" "1")
d82e788e 7319 (set_attr "arch" "32,a,a")
282b4c75 7320 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
b11cae9e 7321
d5d4dc8d 7322(define_insn "*cmpsi_shiftsi_swp"
bd5b4116 7323 [(set (reg:CC_SWP CC_REGNUM)
aea4c774 7324 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
d82e788e 7325 [(match_operand:SI 1 "s_register_operand" "r,r,r")
7326 (match_operand:SI 2 "shift_amount_operand" "M,r,M")])
7327 (match_operand:SI 0 "s_register_operand" "r,r,r")))]
d5d4dc8d 7328 "TARGET_32BIT"
aea4c774 7329 "cmp%?\\t%0, %1%S3"
344495ea 7330 [(set_attr "conds" "set")
331beb1a 7331 (set_attr "shift" "1")
d82e788e 7332 (set_attr "arch" "32,a,a")
282b4c75 7333 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
b11cae9e 7334
25f905c2 7335(define_insn "*arm_cmpsi_negshiftsi_si"
aed179ae 7336 [(set (reg:CC_Z CC_REGNUM)
7337 (compare:CC_Z
7338 (neg:SI (match_operator:SI 1 "shift_operator"
7339 [(match_operand:SI 2 "s_register_operand" "r")
7340 (match_operand:SI 3 "reg_or_int_operand" "rM")]))
7341 (match_operand:SI 0 "s_register_operand" "r")))]
cffb2a26 7342 "TARGET_ARM"
aed179ae 7343 "cmn%?\\t%0, %2%S1"
344495ea 7344 [(set_attr "conds" "set")
aed179ae 7345 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
d82e788e 7346 (const_string "alus_shift_imm")
7347 (const_string "alus_shift_reg")))
596e5e8f 7348 (set_attr "predicable" "yes")]
0d66636f 7349)
b11cae9e 7350
a8045a4f 7351;; DImode comparisons. The generic code generates branches that
7352;; if-conversion can not reduce to a conditional compare, so we do
7353;; that directly.
7354
ba6a3b2f 7355(define_insn_and_split "*arm_cmpdi_insn"
a8045a4f 7356 [(set (reg:CC_NCV CC_REGNUM)
7357 (compare:CC_NCV (match_operand:DI 0 "s_register_operand" "r")
7358 (match_operand:DI 1 "arm_di_operand" "rDi")))
7359 (clobber (match_scratch:SI 2 "=r"))]
b805622c 7360 "TARGET_32BIT"
ba6a3b2f 7361 "#" ; "cmp\\t%Q0, %Q1\;sbcs\\t%2, %R0, %R1"
7362 "&& reload_completed"
7363 [(set (reg:CC CC_REGNUM)
7364 (compare:CC (match_dup 0) (match_dup 1)))
7365 (parallel [(set (reg:CC CC_REGNUM)
7366 (compare:CC (match_dup 3) (match_dup 4)))
7367 (set (match_dup 2)
7368 (minus:SI (match_dup 5)
7369 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))])]
7370 {
7371 operands[3] = gen_highpart (SImode, operands[0]);
7372 operands[0] = gen_lowpart (SImode, operands[0]);
7373 if (CONST_INT_P (operands[1]))
7374 {
7375 operands[4] = GEN_INT (~INTVAL (gen_highpart_mode (SImode,
7376 DImode,
7377 operands[1])));
7378 operands[5] = gen_rtx_PLUS (SImode, operands[3], operands[4]);
7379 }
7380 else
7381 {
7382 operands[4] = gen_highpart (SImode, operands[1]);
7383 operands[5] = gen_rtx_MINUS (SImode, operands[3], operands[4]);
7384 }
7385 operands[1] = gen_lowpart (SImode, operands[1]);
7386 operands[2] = gen_lowpart (SImode, operands[2]);
7387 }
a8045a4f 7388 [(set_attr "conds" "set")
1b7da4ac 7389 (set_attr "length" "8")
7390 (set_attr "type" "multiple")]
a8045a4f 7391)
7392
ba6a3b2f 7393(define_insn_and_split "*arm_cmpdi_unsigned"
a8045a4f 7394 [(set (reg:CC_CZ CC_REGNUM)
1a86364b 7395 (compare:CC_CZ (match_operand:DI 0 "s_register_operand" "l,r,r,r")
7396 (match_operand:DI 1 "arm_di_operand" "Py,r,Di,rDi")))]
7c36fe71 7397
48a98053 7398 "TARGET_32BIT"
ba6a3b2f 7399 "#" ; "cmp\\t%R0, %R1\;it eq\;cmpeq\\t%Q0, %Q1"
7400 "&& reload_completed"
7401 [(set (reg:CC CC_REGNUM)
7402 (compare:CC (match_dup 2) (match_dup 3)))
7403 (cond_exec (eq:SI (reg:CC CC_REGNUM) (const_int 0))
7404 (set (reg:CC CC_REGNUM)
7405 (compare:CC (match_dup 0) (match_dup 1))))]
7406 {
7407 operands[2] = gen_highpart (SImode, operands[0]);
7408 operands[0] = gen_lowpart (SImode, operands[0]);
7409 if (CONST_INT_P (operands[1]))
7410 operands[3] = gen_highpart_mode (SImode, DImode, operands[1]);
7411 else
7412 operands[3] = gen_highpart (SImode, operands[1]);
7413 operands[1] = gen_lowpart (SImode, operands[1]);
7414 }
a8045a4f 7415 [(set_attr "conds" "set")
1a86364b 7416 (set_attr "enabled_for_depr_it" "yes,yes,no,*")
7417 (set_attr "arch" "t2,t2,t2,a")
7418 (set_attr "length" "6,6,10,8")
1b7da4ac 7419 (set_attr "type" "multiple")]
a8045a4f 7420)
7421
7422(define_insn "*arm_cmpdi_zero"
7423 [(set (reg:CC_Z CC_REGNUM)
7424 (compare:CC_Z (match_operand:DI 0 "s_register_operand" "r")
7425 (const_int 0)))
7426 (clobber (match_scratch:SI 1 "=r"))]
7427 "TARGET_32BIT"
3ef90e77 7428 "orrs%?\\t%1, %Q0, %R0"
1b7da4ac 7429 [(set_attr "conds" "set")
7430 (set_attr "type" "logics_reg")]
a8045a4f 7431)
7432
9c08d1fa 7433; This insn allows redundant compares to be removed by cse, nothing should
7434; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
7435; is deleted later on. The match_dup will match the mode here, so that
7436; mode changes of the condition codes aren't lost by this even though we don't
7437; specify what they are.
7438
8a18b90c 7439(define_insn "*deleted_compare"
9c08d1fa 7440 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
25f905c2 7441 "TARGET_32BIT"
40dbec34 7442 "\\t%@ deleted compare"
cffb2a26 7443 [(set_attr "conds" "set")
1b7da4ac 7444 (set_attr "length" "0")
7445 (set_attr "type" "no_insn")]
cffb2a26 7446)
9c08d1fa 7447
7448\f
7449;; Conditional branch insns
7450
74f4459c 7451(define_expand "cbranch_cc"
9c08d1fa 7452 [(set (pc)
74f4459c 7453 (if_then_else (match_operator 0 "" [(match_operand 1 "" "")
7454 (match_operand 2 "" "")])
7455 (label_ref (match_operand 3 "" ""))
9c08d1fa 7456 (pc)))]
25f905c2 7457 "TARGET_32BIT"
74f4459c 7458 "operands[1] = arm_gen_compare_reg (GET_CODE (operands[0]),
e1b93706 7459 operands[1], operands[2], NULL_RTX);
74f4459c 7460 operands[2] = const0_rtx;"
8fa3ba89 7461)
7462
7463;;
7464;; Patterns to match conditional branch insns.
7465;;
7466
ffcc986d 7467(define_insn "arm_cond_branch"
9c08d1fa 7468 [(set (pc)
8fa3ba89 7469 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 7470 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 7471 (label_ref (match_operand 0 "" ""))
7472 (pc)))]
25f905c2 7473 "TARGET_32BIT"
d75350ce 7474 "*
9c08d1fa 7475 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 7476 {
7477 arm_ccfsm_state += 2;
7478 return \"\";
7479 }
e2348bcb 7480 return \"b%d1\\t%l0\";
cffb2a26 7481 "
a2cd141b 7482 [(set_attr "conds" "use")
a6864a24 7483 (set_attr "type" "branch")
7484 (set (attr "length")
7485 (if_then_else
0bf497f5 7486 (and (match_test "TARGET_THUMB2")
a6864a24 7487 (and (ge (minus (match_dup 0) (pc)) (const_int -250))
7488 (le (minus (match_dup 0) (pc)) (const_int 256))))
7489 (const_int 2)
7490 (const_int 4)))]
cffb2a26 7491)
d75350ce 7492
cffb2a26 7493(define_insn "*arm_cond_branch_reversed"
9c08d1fa 7494 [(set (pc)
8fa3ba89 7495 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 7496 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 7497 (pc)
7498 (label_ref (match_operand 0 "" ""))))]
25f905c2 7499 "TARGET_32BIT"
d75350ce 7500 "*
9c08d1fa 7501 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 7502 {
7503 arm_ccfsm_state += 2;
7504 return \"\";
7505 }
e2348bcb 7506 return \"b%D1\\t%l0\";
cffb2a26 7507 "
a2cd141b 7508 [(set_attr "conds" "use")
a6864a24 7509 (set_attr "type" "branch")
7510 (set (attr "length")
7511 (if_then_else
0bf497f5 7512 (and (match_test "TARGET_THUMB2")
a6864a24 7513 (and (ge (minus (match_dup 0) (pc)) (const_int -250))
7514 (le (minus (match_dup 0) (pc)) (const_int 256))))
7515 (const_int 2)
7516 (const_int 4)))]
cffb2a26 7517)
7518
b11cae9e 7519\f
9c08d1fa 7520
7521; scc insns
7522
74f4459c 7523(define_expand "cstore_cc"
7db9af5d 7524 [(set (match_operand:SI 0 "s_register_operand" "")
74f4459c 7525 (match_operator:SI 1 "" [(match_operand 2 "" "")
7526 (match_operand 3 "" "")]))]
25f905c2 7527 "TARGET_32BIT"
74f4459c 7528 "operands[2] = arm_gen_compare_reg (GET_CODE (operands[1]),
e1b93706 7529 operands[2], operands[3], NULL_RTX);
74f4459c 7530 operands[3] = const0_rtx;"
8fa3ba89 7531)
7532
a3b84066 7533(define_insn_and_split "*mov_scc"
9c08d1fa 7534 [(set (match_operand:SI 0 "s_register_operand" "=r")
ff74dd54 7535 (match_operator:SI 1 "arm_comparison_operator_mode"
8a18b90c 7536 [(match_operand 2 "cc_register" "") (const_int 0)]))]
cffb2a26 7537 "TARGET_ARM"
a3b84066 7538 "#" ; "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
7539 "TARGET_ARM"
7540 [(set (match_dup 0)
7541 (if_then_else:SI (match_dup 1)
7542 (const_int 1)
7543 (const_int 0)))]
7544 ""
cffb2a26 7545 [(set_attr "conds" "use")
1b7da4ac 7546 (set_attr "length" "8")
7547 (set_attr "type" "multiple")]
cffb2a26 7548)
9c08d1fa 7549
a3b84066 7550(define_insn_and_split "*mov_negscc"
9c08d1fa 7551 [(set (match_operand:SI 0 "s_register_operand" "=r")
ff74dd54 7552 (neg:SI (match_operator:SI 1 "arm_comparison_operator_mode"
8a18b90c 7553 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 7554 "TARGET_ARM"
a3b84066 7555 "#" ; "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
7556 "TARGET_ARM"
7557 [(set (match_dup 0)
7558 (if_then_else:SI (match_dup 1)
7559 (match_dup 3)
7560 (const_int 0)))]
7561 {
7562 operands[3] = GEN_INT (~0);
7563 }
cffb2a26 7564 [(set_attr "conds" "use")
1b7da4ac 7565 (set_attr "length" "8")
7566 (set_attr "type" "multiple")]
cffb2a26 7567)
9c08d1fa 7568
a3b84066 7569(define_insn_and_split "*mov_notscc"
9c08d1fa 7570 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7571 (not:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7572 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 7573 "TARGET_ARM"
a3b84066 7574 "#" ; "mvn%D1\\t%0, #0\;mvn%d1\\t%0, #1"
7575 "TARGET_ARM"
7576 [(set (match_dup 0)
7577 (if_then_else:SI (match_dup 1)
7578 (match_dup 3)
7579 (match_dup 4)))]
7580 {
7581 operands[3] = GEN_INT (~1);
7582 operands[4] = GEN_INT (~0);
7583 }
cffb2a26 7584 [(set_attr "conds" "use")
1b7da4ac 7585 (set_attr "length" "8")
7586 (set_attr "type" "multiple")]
cffb2a26 7587)
9c08d1fa 7588
595d88b5 7589(define_expand "cstoresi4"
7590 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 7591 (match_operator:SI 1 "expandable_comparison_operator"
595d88b5 7592 [(match_operand:SI 2 "s_register_operand" "")
7593 (match_operand:SI 3 "reg_or_int_operand" "")]))]
74f4459c 7594 "TARGET_32BIT || TARGET_THUMB1"
595d88b5 7595 "{
7596 rtx op3, scratch, scratch2;
7597
74f4459c 7598 if (!TARGET_THUMB1)
7599 {
7600 if (!arm_add_operand (operands[3], SImode))
7601 operands[3] = force_reg (SImode, operands[3]);
7602 emit_insn (gen_cstore_cc (operands[0], operands[1],
7603 operands[2], operands[3]));
7604 DONE;
7605 }
7606
595d88b5 7607 if (operands[3] == const0_rtx)
7608 {
7609 switch (GET_CODE (operands[1]))
7610 {
7611 case EQ:
25f905c2 7612 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], operands[2]));
595d88b5 7613 break;
7614
7615 case NE:
25f905c2 7616 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], operands[2]));
595d88b5 7617 break;
7618
7619 case LE:
7620 scratch = expand_binop (SImode, add_optab, operands[2], constm1_rtx,
7621 NULL_RTX, 0, OPTAB_WIDEN);
7622 scratch = expand_binop (SImode, ior_optab, operands[2], scratch,
7623 NULL_RTX, 0, OPTAB_WIDEN);
7624 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7625 operands[0], 1, OPTAB_WIDEN);
7626 break;
7627
7628 case GE:
7629 scratch = expand_unop (SImode, one_cmpl_optab, operands[2],
7630 NULL_RTX, 1);
7631 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7632 NULL_RTX, 1, OPTAB_WIDEN);
7633 break;
7634
7635 case GT:
7636 scratch = expand_binop (SImode, ashr_optab, operands[2],
7637 GEN_INT (31), NULL_RTX, 0, OPTAB_WIDEN);
7638 scratch = expand_binop (SImode, sub_optab, scratch, operands[2],
7639 NULL_RTX, 0, OPTAB_WIDEN);
7640 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31), operands[0],
7641 0, OPTAB_WIDEN);
7642 break;
7643
7644 /* LT is handled by generic code. No need for unsigned with 0. */
7645 default:
7646 FAIL;
7647 }
7648 DONE;
7649 }
7650
7651 switch (GET_CODE (operands[1]))
7652 {
7653 case EQ:
7654 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7655 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7656 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], scratch));
595d88b5 7657 break;
7658
7659 case NE:
7660 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7661 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7662 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], scratch));
595d88b5 7663 break;
7664
7665 case LE:
7666 op3 = force_reg (SImode, operands[3]);
7667
7668 scratch = expand_binop (SImode, lshr_optab, operands[2], GEN_INT (31),
7669 NULL_RTX, 1, OPTAB_WIDEN);
7670 scratch2 = expand_binop (SImode, ashr_optab, op3, GEN_INT (31),
7671 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7672 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
595d88b5 7673 op3, operands[2]));
7674 break;
7675
7676 case GE:
7677 op3 = operands[3];
25f905c2 7678 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7679 op3 = force_reg (SImode, op3);
7680 scratch = expand_binop (SImode, ashr_optab, operands[2], GEN_INT (31),
7681 NULL_RTX, 0, OPTAB_WIDEN);
7682 scratch2 = expand_binop (SImode, lshr_optab, op3, GEN_INT (31),
7683 NULL_RTX, 1, OPTAB_WIDEN);
25f905c2 7684 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
595d88b5 7685 operands[2], op3));
7686 break;
7687
7688 case LEU:
7689 op3 = force_reg (SImode, operands[3]);
7690 scratch = force_reg (SImode, const0_rtx);
25f905c2 7691 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
595d88b5 7692 op3, operands[2]));
7693 break;
7694
7695 case GEU:
7696 op3 = operands[3];
25f905c2 7697 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7698 op3 = force_reg (SImode, op3);
7699 scratch = force_reg (SImode, const0_rtx);
25f905c2 7700 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
595d88b5 7701 operands[2], op3));
7702 break;
7703
7704 case LTU:
7705 op3 = operands[3];
25f905c2 7706 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7707 op3 = force_reg (SImode, op3);
7708 scratch = gen_reg_rtx (SImode);
408b7ae5 7709 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], operands[2], op3));
595d88b5 7710 break;
7711
7712 case GTU:
7713 op3 = force_reg (SImode, operands[3]);
7714 scratch = gen_reg_rtx (SImode);
408b7ae5 7715 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], op3, operands[2]));
595d88b5 7716 break;
7717
7718 /* No good sequences for GT, LT. */
7719 default:
7720 FAIL;
7721 }
7722 DONE;
7723}")
7724
9854d864 7725(define_expand "cstorehf4"
7726 [(set (match_operand:SI 0 "s_register_operand")
7727 (match_operator:SI 1 "expandable_comparison_operator"
7728 [(match_operand:HF 2 "s_register_operand")
d7216193 7729 (match_operand:HF 3 "vfp_compare_operand")]))]
9854d864 7730 "TARGET_VFP_FP16INST"
7731 {
7732 if (!arm_validize_comparison (&operands[1],
7733 &operands[2],
7734 &operands[3]))
7735 FAIL;
7736
7737 emit_insn (gen_cstore_cc (operands[0], operands[1],
7738 operands[2], operands[3]));
7739 DONE;
7740 }
7741)
7742
74f4459c 7743(define_expand "cstoresf4"
7744 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 7745 (match_operator:SI 1 "expandable_comparison_operator"
74f4459c 7746 [(match_operand:SF 2 "s_register_operand" "")
d7216193 7747 (match_operand:SF 3 "vfp_compare_operand" "")]))]
74f4459c 7748 "TARGET_32BIT && TARGET_HARD_FLOAT"
7749 "emit_insn (gen_cstore_cc (operands[0], operands[1],
7750 operands[2], operands[3])); DONE;"
7751)
7752
7753(define_expand "cstoredf4"
7754 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 7755 (match_operator:SI 1 "expandable_comparison_operator"
74f4459c 7756 [(match_operand:DF 2 "s_register_operand" "")
d7216193 7757 (match_operand:DF 3 "vfp_compare_operand" "")]))]
d63ed457 7758 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
74f4459c 7759 "emit_insn (gen_cstore_cc (operands[0], operands[1],
7760 operands[2], operands[3])); DONE;"
7761)
7762
74f4459c 7763(define_expand "cstoredi4"
7764 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 7765 (match_operator:SI 1 "expandable_comparison_operator"
b8eae306 7766 [(match_operand:DI 2 "s_register_operand" "")
a8045a4f 7767 (match_operand:DI 3 "cmpdi_operand" "")]))]
7768 "TARGET_32BIT"
7769 "{
f9aa4160 7770 if (!arm_validize_comparison (&operands[1],
7771 &operands[2],
7772 &operands[3]))
7773 FAIL;
7774 emit_insn (gen_cstore_cc (operands[0], operands[1], operands[2],
a8045a4f 7775 operands[3]));
7776 DONE;
7777 }"
74f4459c 7778)
7779
9c08d1fa 7780\f
39b5e676 7781;; Conditional move insns
7782
7783(define_expand "movsicc"
8a18b90c 7784 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 7785 (if_then_else:SI (match_operand 1 "expandable_comparison_operator" "")
aea4c774 7786 (match_operand:SI 2 "arm_not_operand" "")
8a18b90c 7787 (match_operand:SI 3 "arm_not_operand" "")))]
25f905c2 7788 "TARGET_32BIT"
39b5e676 7789 "
215b30b3 7790 {
f9aa4160 7791 enum rtx_code code;
278b301d 7792 rtx ccreg;
7793
f9aa4160 7794 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
9854d864 7795 &XEXP (operands[1], 1)))
278b301d 7796 FAIL;
9854d864 7797
7798 code = GET_CODE (operands[1]);
7799 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
7800 XEXP (operands[1], 1), NULL_RTX);
7801 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7802 }"
7803)
7804
7805(define_expand "movhfcc"
7806 [(set (match_operand:HF 0 "s_register_operand")
7807 (if_then_else:HF (match_operand 1 "arm_cond_move_operator")
7808 (match_operand:HF 2 "s_register_operand")
7809 (match_operand:HF 3 "s_register_operand")))]
7810 "TARGET_VFP_FP16INST"
7811 "
7812 {
7813 enum rtx_code code = GET_CODE (operands[1]);
7814 rtx ccreg;
7815
7816 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
7817 &XEXP (operands[1], 1)))
7818 FAIL;
7819
f9aa4160 7820 code = GET_CODE (operands[1]);
74f4459c 7821 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
e1b93706 7822 XEXP (operands[1], 1), NULL_RTX);
29bb088d 7823 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7824 }"
7825)
39b5e676 7826
7827(define_expand "movsfcc"
8a18b90c 7828 [(set (match_operand:SF 0 "s_register_operand" "")
4df97ffc 7829 (if_then_else:SF (match_operand 1 "arm_cond_move_operator" "")
8a18b90c 7830 (match_operand:SF 2 "s_register_operand" "")
d86c91f6 7831 (match_operand:SF 3 "s_register_operand" "")))]
19f6bf8d 7832 "TARGET_32BIT && TARGET_HARD_FLOAT"
39b5e676 7833 "
215b30b3 7834 {
7835 enum rtx_code code = GET_CODE (operands[1]);
7836 rtx ccreg;
f082f1c4 7837
9854d864 7838 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
f9aa4160 7839 &XEXP (operands[1], 1)))
7840 FAIL;
39b5e676 7841
f9aa4160 7842 code = GET_CODE (operands[1]);
74f4459c 7843 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
e1b93706 7844 XEXP (operands[1], 1), NULL_RTX);
29bb088d 7845 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7846 }"
7847)
39b5e676 7848
7849(define_expand "movdfcc"
8a18b90c 7850 [(set (match_operand:DF 0 "s_register_operand" "")
4df97ffc 7851 (if_then_else:DF (match_operand 1 "arm_cond_move_operator" "")
8a18b90c 7852 (match_operand:DF 2 "s_register_operand" "")
d86c91f6 7853 (match_operand:DF 3 "s_register_operand" "")))]
994606f8 7854 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
39b5e676 7855 "
215b30b3 7856 {
7857 enum rtx_code code = GET_CODE (operands[1]);
278b301d 7858 rtx ccreg;
39b5e676 7859
f9aa4160 7860 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
7861 &XEXP (operands[1], 1)))
7862 FAIL;
7863 code = GET_CODE (operands[1]);
74f4459c 7864 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
e1b93706 7865 XEXP (operands[1], 1), NULL_RTX);
29bb088d 7866 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7867 }"
7868)
39b5e676 7869
91cb50d2 7870(define_insn "*cmov<mode>"
7871 [(set (match_operand:SDF 0 "s_register_operand" "=<F_constraint>")
7872 (if_then_else:SDF (match_operator 1 "arm_vsel_comparison_operator"
7873 [(match_operand 2 "cc_register" "") (const_int 0)])
7874 (match_operand:SDF 3 "s_register_operand"
7875 "<F_constraint>")
7876 (match_operand:SDF 4 "s_register_operand"
7877 "<F_constraint>")))]
7878 "TARGET_HARD_FLOAT && TARGET_FPU_ARMV8 <vfp_double_cond>"
7879 "*
7880 {
7881 enum arm_cond_code code = maybe_get_arm_condition_code (operands[1]);
7882 switch (code)
7883 {
7884 case ARM_GE:
7885 case ARM_GT:
7886 case ARM_EQ:
7887 case ARM_VS:
7888 return \"vsel%d1.<V_if_elem>\\t%<V_reg>0, %<V_reg>3, %<V_reg>4\";
7889 case ARM_LT:
7890 case ARM_LE:
7891 case ARM_NE:
7892 case ARM_VC:
7893 return \"vsel%D1.<V_if_elem>\\t%<V_reg>0, %<V_reg>4, %<V_reg>3\";
7894 default:
7895 gcc_unreachable ();
7896 }
7897 return \"\";
7898 }"
7899 [(set_attr "conds" "use")
6664d308 7900 (set_attr "type" "fcsel")]
91cb50d2 7901)
7902
9854d864 7903(define_insn "*cmovhf"
7904 [(set (match_operand:HF 0 "s_register_operand" "=t")
7905 (if_then_else:HF (match_operator 1 "arm_vsel_comparison_operator"
7906 [(match_operand 2 "cc_register" "") (const_int 0)])
7907 (match_operand:HF 3 "s_register_operand" "t")
7908 (match_operand:HF 4 "s_register_operand" "t")))]
7909 "TARGET_VFP_FP16INST"
7910 "*
7911 {
7912 enum arm_cond_code code = maybe_get_arm_condition_code (operands[1]);
7913 switch (code)
7914 {
7915 case ARM_GE:
7916 case ARM_GT:
7917 case ARM_EQ:
7918 case ARM_VS:
7919 return \"vsel%d1.f16\\t%0, %3, %4\";
7920 case ARM_LT:
7921 case ARM_LE:
7922 case ARM_NE:
7923 case ARM_VC:
7924 return \"vsel%D1.f16\\t%0, %4, %3\";
7925 default:
7926 gcc_unreachable ();
7927 }
7928 return \"\";
7929 }"
7930 [(set_attr "conds" "use")
7931 (set_attr "type" "fcsel")]
7932)
7933
190efb17 7934(define_insn_and_split "*movsicc_insn"
f082f1c4 7935 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
8a18b90c 7936 (if_then_else:SI
8fa3ba89 7937 (match_operator 3 "arm_comparison_operator"
8a18b90c 7938 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 7939 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
7940 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
cffb2a26 7941 "TARGET_ARM"
39b5e676 7942 "@
8a18b90c 7943 mov%D3\\t%0, %2
7944 mvn%D3\\t%0, #%B2
f082f1c4 7945 mov%d3\\t%0, %1
7946 mvn%d3\\t%0, #%B1
190efb17 7947 #
7948 #
7949 #
7950 #"
7951 ; alt4: mov%d3\\t%0, %1\;mov%D3\\t%0, %2
7952 ; alt5: mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
7953 ; alt6: mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
7954 ; alt7: mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
7955 "&& reload_completed"
7956 [(const_int 0)]
7957 {
7958 enum rtx_code rev_code;
3754d046 7959 machine_mode mode;
190efb17 7960 rtx rev_cond;
7961
7962 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
7963 operands[3],
d1f9b275 7964 gen_rtx_SET (operands[0], operands[1])));
190efb17 7965
7966 rev_code = GET_CODE (operands[3]);
7967 mode = GET_MODE (operands[4]);
7968 if (mode == CCFPmode || mode == CCFPEmode)
7969 rev_code = reverse_condition_maybe_unordered (rev_code);
7970 else
7971 rev_code = reverse_condition (rev_code);
7972
7973 rev_cond = gen_rtx_fmt_ee (rev_code,
7974 VOIDmode,
7975 operands[4],
7976 const0_rtx);
7977 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
7978 rev_cond,
d1f9b275 7979 gen_rtx_SET (operands[0], operands[2])));
190efb17 7980 DONE;
7981 }
f082f1c4 7982 [(set_attr "length" "4,4,4,4,8,8,8,8")
d2a518d1 7983 (set_attr "conds" "use")
65f68e55 7984 (set_attr_alternative "type"
7985 [(if_then_else (match_operand 2 "const_int_operand" "")
1aed5204 7986 (const_string "mov_imm")
7987 (const_string "mov_reg"))
7988 (const_string "mvn_imm")
65f68e55 7989 (if_then_else (match_operand 1 "const_int_operand" "")
1aed5204 7990 (const_string "mov_imm")
7991 (const_string "mov_reg"))
7992 (const_string "mvn_imm")
282b4c75 7993 (const_string "multiple")
7994 (const_string "multiple")
7995 (const_string "multiple")
7996 (const_string "multiple")])]
215b30b3 7997)
39b5e676 7998
39b5e676 7999(define_insn "*movsfcc_soft_insn"
f082f1c4 8000 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
8fa3ba89 8001 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
8a18b90c 8002 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 8003 (match_operand:SF 1 "s_register_operand" "0,r")
8004 (match_operand:SF 2 "s_register_operand" "r,0")))]
cffb2a26 8005 "TARGET_ARM && TARGET_SOFT_FLOAT"
f082f1c4 8006 "@
8007 mov%D3\\t%0, %2
8008 mov%d3\\t%0, %1"
d2a518d1 8009 [(set_attr "conds" "use")
1aed5204 8010 (set_attr "type" "mov_reg")]
8fa3ba89 8011)
39b5e676 8012
39b5e676 8013\f
9c08d1fa 8014;; Jump and linkage insns
8015
cffb2a26 8016(define_expand "jump"
9c08d1fa 8017 [(set (pc)
8018 (label_ref (match_operand 0 "" "")))]
cffb2a26 8019 "TARGET_EITHER"
9c08d1fa 8020 ""
cffb2a26 8021)
8022
8023(define_insn "*arm_jump"
8024 [(set (pc)
8025 (label_ref (match_operand 0 "" "")))]
25f905c2 8026 "TARGET_32BIT"
9c08d1fa 8027 "*
0d66636f 8028 {
8029 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
8030 {
8031 arm_ccfsm_state += 2;
8032 return \"\";
8033 }
8034 return \"b%?\\t%l0\";
8035 }
8036 "
a6864a24 8037 [(set_attr "predicable" "yes")
8038 (set (attr "length")
8039 (if_then_else
0bf497f5 8040 (and (match_test "TARGET_THUMB2")
a6864a24 8041 (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
8042 (le (minus (match_dup 0) (pc)) (const_int 2048))))
8043 (const_int 2)
1b7da4ac 8044 (const_int 4)))
8045 (set_attr "type" "branch")]
0d66636f 8046)
9c08d1fa 8047
d3373b54 8048(define_expand "call"
8049 [(parallel [(call (match_operand 0 "memory_operand" "")
8050 (match_operand 1 "general_operand" ""))
cffb2a26 8051 (use (match_operand 2 "" ""))
bd5b4116 8052 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 8053 "TARGET_EITHER"
6c4c2133 8054 "
8055 {
bac7fc85 8056 rtx callee, pat;
2d3a01a7 8057 tree addr = MEM_EXPR (operands[0]);
bbe777ea 8058
bbe777ea 8059 /* In an untyped call, we can get NULL for operand 2. */
8060 if (operands[2] == NULL_RTX)
8061 operands[2] = const0_rtx;
8062
de55252a 8063 /* Decide if we should generate indirect calls by loading the
85c36fd1 8064 32-bit address of the callee into a register before performing the
de55252a 8065 branch and link. */
8066 callee = XEXP (operands[0], 0);
8067 if (GET_CODE (callee) == SYMBOL_REF
8068 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
8069 : !REG_P (callee))
bbe777ea 8070 XEXP (operands[0], 0) = force_reg (Pmode, callee);
bac7fc85 8071
2d3a01a7 8072 if (detect_cmse_nonsecure_call (addr))
8073 {
8074 pat = gen_nonsecure_call_internal (operands[0], operands[1],
8075 operands[2]);
8076 emit_call_insn (pat);
8077 }
8078 else
8079 {
8080 pat = gen_call_internal (operands[0], operands[1], operands[2]);
8081 arm_emit_call_insn (pat, XEXP (operands[0], 0), false);
8082 }
bac7fc85 8083 DONE;
6c4c2133 8084 }"
8085)
d3373b54 8086
bac7fc85 8087(define_expand "call_internal"
8088 [(parallel [(call (match_operand 0 "memory_operand" "")
8089 (match_operand 1 "general_operand" ""))
8090 (use (match_operand 2 "" ""))
8091 (clobber (reg:SI LR_REGNUM))])])
8092
2d3a01a7 8093(define_expand "nonsecure_call_internal"
8094 [(parallel [(call (unspec:SI [(match_operand 0 "memory_operand" "")]
8095 UNSPEC_NONSECURE_MEM)
8096 (match_operand 1 "general_operand" ""))
8097 (use (match_operand 2 "" ""))
8098 (clobber (reg:SI LR_REGNUM))
8099 (clobber (reg:SI 4))])]
8100 "use_cmse"
8101 "
8102 {
8103 rtx tmp;
8104 tmp = copy_to_suggested_reg (XEXP (operands[0], 0),
8105 gen_rtx_REG (SImode, 4),
8106 SImode);
8107
8108 operands[0] = replace_equiv_address (operands[0], tmp);
8109 }")
8110
f1039640 8111(define_insn "*call_reg_armv5"
d3373b54 8112 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
cffb2a26 8113 (match_operand 1 "" ""))
8114 (use (match_operand 2 "" ""))
bd5b4116 8115 (clobber (reg:SI LR_REGNUM))]
33ae7c4b 8116 "TARGET_ARM && arm_arch5 && !SIBLING_CALL_P (insn)"
f1039640 8117 "blx%?\\t%0"
8118 [(set_attr "type" "call")]
8119)
8120
8121(define_insn "*call_reg_arm"
8122 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
8123 (match_operand 1 "" ""))
8124 (use (match_operand 2 "" ""))
8125 (clobber (reg:SI LR_REGNUM))]
33ae7c4b 8126 "TARGET_ARM && !arm_arch5 && !SIBLING_CALL_P (insn)"
9c08d1fa 8127 "*
5565501b 8128 return output_call (operands);
cffb2a26 8129 "
8130 ;; length is worst case, normally it is only two
8131 [(set_attr "length" "12")
8132 (set_attr "type" "call")]
8133)
9c08d1fa 8134
89504fc1 8135
d3373b54 8136(define_expand "call_value"
e0698af7 8137 [(parallel [(set (match_operand 0 "" "")
8138 (call (match_operand 1 "memory_operand" "")
8139 (match_operand 2 "general_operand" "")))
cffb2a26 8140 (use (match_operand 3 "" ""))
bd5b4116 8141 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 8142 "TARGET_EITHER"
6c4c2133 8143 "
8144 {
bac7fc85 8145 rtx pat, callee;
2d3a01a7 8146 tree addr = MEM_EXPR (operands[1]);
bbe777ea 8147
8148 /* In an untyped call, we can get NULL for operand 2. */
8149 if (operands[3] == 0)
8150 operands[3] = const0_rtx;
8151
de55252a 8152 /* Decide if we should generate indirect calls by loading the
8153 32-bit address of the callee into a register before performing the
8154 branch and link. */
8155 callee = XEXP (operands[1], 0);
8156 if (GET_CODE (callee) == SYMBOL_REF
8157 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
8158 : !REG_P (callee))
78fe751b 8159 XEXP (operands[1], 0) = force_reg (Pmode, callee);
bac7fc85 8160
2d3a01a7 8161 if (detect_cmse_nonsecure_call (addr))
8162 {
8163 pat = gen_nonsecure_call_value_internal (operands[0], operands[1],
8164 operands[2], operands[3]);
8165 emit_call_insn (pat);
8166 }
8167 else
8168 {
8169 pat = gen_call_value_internal (operands[0], operands[1],
8170 operands[2], operands[3]);
8171 arm_emit_call_insn (pat, XEXP (operands[1], 0), false);
8172 }
bac7fc85 8173 DONE;
6c4c2133 8174 }"
8175)
d3373b54 8176
bac7fc85 8177(define_expand "call_value_internal"
8178 [(parallel [(set (match_operand 0 "" "")
8179 (call (match_operand 1 "memory_operand" "")
8180 (match_operand 2 "general_operand" "")))
8181 (use (match_operand 3 "" ""))
8182 (clobber (reg:SI LR_REGNUM))])])
8183
2d3a01a7 8184(define_expand "nonsecure_call_value_internal"
8185 [(parallel [(set (match_operand 0 "" "")
8186 (call (unspec:SI [(match_operand 1 "memory_operand" "")]
8187 UNSPEC_NONSECURE_MEM)
8188 (match_operand 2 "general_operand" "")))
8189 (use (match_operand 3 "" ""))
8190 (clobber (reg:SI LR_REGNUM))
8191 (clobber (reg:SI 4))])]
8192 "use_cmse"
8193 "
8194 {
8195 rtx tmp;
8196 tmp = copy_to_suggested_reg (XEXP (operands[1], 0),
8197 gen_rtx_REG (SImode, 4),
8198 SImode);
8199
8200 operands[1] = replace_equiv_address (operands[1], tmp);
8201 }")
8202
f1039640 8203(define_insn "*call_value_reg_armv5"
27ed6835 8204 [(set (match_operand 0 "" "")
755eb2b4 8205 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
cffb2a26 8206 (match_operand 2 "" "")))
bbe777ea 8207 (use (match_operand 3 "" ""))
bd5b4116 8208 (clobber (reg:SI LR_REGNUM))]
33ae7c4b 8209 "TARGET_ARM && arm_arch5 && !SIBLING_CALL_P (insn)"
f1039640 8210 "blx%?\\t%1"
8211 [(set_attr "type" "call")]
8212)
8213
8214(define_insn "*call_value_reg_arm"
8215 [(set (match_operand 0 "" "")
8216 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
8217 (match_operand 2 "" "")))
8218 (use (match_operand 3 "" ""))
8219 (clobber (reg:SI LR_REGNUM))]
33ae7c4b 8220 "TARGET_ARM && !arm_arch5 && !SIBLING_CALL_P (insn)"
9c08d1fa 8221 "*
215b30b3 8222 return output_call (&operands[1]);
cffb2a26 8223 "
8224 [(set_attr "length" "12")
8225 (set_attr "type" "call")]
8226)
9c08d1fa 8227
9c08d1fa 8228;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
8229;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
8230
f7fbdd4a 8231(define_insn "*call_symbol"
27ed6835 8232 [(call (mem:SI (match_operand:SI 0 "" ""))
cffb2a26 8233 (match_operand 1 "" ""))
bbe777ea 8234 (use (match_operand 2 "" ""))
bd5b4116 8235 (clobber (reg:SI LR_REGNUM))]
d68c2c10 8236 "TARGET_32BIT
33ae7c4b 8237 && !SIBLING_CALL_P (insn)
cffb2a26 8238 && (GET_CODE (operands[0]) == SYMBOL_REF)
de55252a 8239 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
6ebaa29d 8240 "*
8241 {
95f1e0d1 8242 rtx op = operands[0];
8243
8244 /* Switch mode now when possible. */
8245 if (SYMBOL_REF_DECL (op) && !TREE_PUBLIC (SYMBOL_REF_DECL (op))
8246 && arm_arch5 && arm_change_mode_p (SYMBOL_REF_DECL (op)))
8247 return NEED_PLT_RELOC ? \"blx%?\\t%a0(PLT)\" : \"blx%?\\t(%a0)\";
8248
55c1e470 8249 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
6ebaa29d 8250 }"
cffb2a26 8251 [(set_attr "type" "call")]
8252)
9c08d1fa 8253
f7fbdd4a 8254(define_insn "*call_value_symbol"
ccd90aaa 8255 [(set (match_operand 0 "" "")
27ed6835 8256 (call (mem:SI (match_operand:SI 1 "" ""))
dd6d7504 8257 (match_operand:SI 2 "" "")))
bbe777ea 8258 (use (match_operand 3 "" ""))
bd5b4116 8259 (clobber (reg:SI LR_REGNUM))]
d68c2c10 8260 "TARGET_32BIT
33ae7c4b 8261 && !SIBLING_CALL_P (insn)
cffb2a26 8262 && (GET_CODE (operands[1]) == SYMBOL_REF)
de55252a 8263 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
6ebaa29d 8264 "*
8265 {
95f1e0d1 8266 rtx op = operands[1];
8267
8268 /* Switch mode now when possible. */
8269 if (SYMBOL_REF_DECL (op) && !TREE_PUBLIC (SYMBOL_REF_DECL (op))
8270 && arm_arch5 && arm_change_mode_p (SYMBOL_REF_DECL (op)))
3f6b66fa 8271 return NEED_PLT_RELOC ? \"blx%?\\t%a1(PLT)\" : \"blx%?\\t(%a1)\";
95f1e0d1 8272
55c1e470 8273 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
6ebaa29d 8274 }"
cffb2a26 8275 [(set_attr "type" "call")]
8276)
8277
ca373797 8278(define_expand "sibcall_internal"
8279 [(parallel [(call (match_operand 0 "memory_operand" "")
8280 (match_operand 1 "general_operand" ""))
8281 (return)
8282 (use (match_operand 2 "" ""))])])
8283
1c494086 8284;; We may also be able to do sibcalls for Thumb, but it's much harder...
8285(define_expand "sibcall"
8286 [(parallel [(call (match_operand 0 "memory_operand" "")
8287 (match_operand 1 "general_operand" ""))
2ba80634 8288 (return)
8289 (use (match_operand 2 "" ""))])]
d68c2c10 8290 "TARGET_32BIT"
1c494086 8291 "
8292 {
ca373797 8293 rtx pat;
8294
3112c3f7 8295 if ((!REG_P (XEXP (operands[0], 0))
8296 && GET_CODE (XEXP (operands[0], 0)) != SYMBOL_REF)
8297 || (GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
8298 && arm_is_long_call_p (SYMBOL_REF_DECL (XEXP (operands[0], 0)))))
33ae7c4b 8299 XEXP (operands[0], 0) = force_reg (SImode, XEXP (operands[0], 0));
8300
1c494086 8301 if (operands[2] == NULL_RTX)
8302 operands[2] = const0_rtx;
ca373797 8303
8304 pat = gen_sibcall_internal (operands[0], operands[1], operands[2]);
8305 arm_emit_call_insn (pat, operands[0], true);
8306 DONE;
1c494086 8307 }"
8308)
8309
ca373797 8310(define_expand "sibcall_value_internal"
8311 [(parallel [(set (match_operand 0 "" "")
8312 (call (match_operand 1 "memory_operand" "")
8313 (match_operand 2 "general_operand" "")))
8314 (return)
8315 (use (match_operand 3 "" ""))])])
8316
1c494086 8317(define_expand "sibcall_value"
ccd90aaa 8318 [(parallel [(set (match_operand 0 "" "")
1c494086 8319 (call (match_operand 1 "memory_operand" "")
8320 (match_operand 2 "general_operand" "")))
2ba80634 8321 (return)
8322 (use (match_operand 3 "" ""))])]
d68c2c10 8323 "TARGET_32BIT"
1c494086 8324 "
8325 {
ca373797 8326 rtx pat;
8327
3112c3f7 8328 if ((!REG_P (XEXP (operands[1], 0))
8329 && GET_CODE (XEXP (operands[1], 0)) != SYMBOL_REF)
8330 || (GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
8331 && arm_is_long_call_p (SYMBOL_REF_DECL (XEXP (operands[1], 0)))))
33ae7c4b 8332 XEXP (operands[1], 0) = force_reg (SImode, XEXP (operands[1], 0));
8333
1c494086 8334 if (operands[3] == NULL_RTX)
8335 operands[3] = const0_rtx;
ca373797 8336
8337 pat = gen_sibcall_value_internal (operands[0], operands[1],
8338 operands[2], operands[3]);
8339 arm_emit_call_insn (pat, operands[1], true);
8340 DONE;
1c494086 8341 }"
8342)
8343
8344(define_insn "*sibcall_insn"
84ce8e5c 8345 [(call (mem:SI (match_operand:SI 0 "call_insn_operand" "Cs, US"))
1c494086 8346 (match_operand 1 "" ""))
2ba80634 8347 (return)
8348 (use (match_operand 2 "" ""))]
33ae7c4b 8349 "TARGET_32BIT && SIBLING_CALL_P (insn)"
1c494086 8350 "*
33ae7c4b 8351 if (which_alternative == 1)
8352 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
8353 else
8354 {
8355 if (arm_arch5 || arm_arch4t)
947d113e 8356 return \"bx%?\\t%0\\t%@ indirect register sibling call\";
33ae7c4b 8357 else
8358 return \"mov%?\\t%|pc, %0\\t%@ indirect register sibling call\";
8359 }
1c494086 8360 "
8361 [(set_attr "type" "call")]
8362)
8363
8364(define_insn "*sibcall_value_insn"
84ce8e5c 8365 [(set (match_operand 0 "" "")
8366 (call (mem:SI (match_operand:SI 1 "call_insn_operand" "Cs,US"))
1c494086 8367 (match_operand 2 "" "")))
2ba80634 8368 (return)
8369 (use (match_operand 3 "" ""))]
33ae7c4b 8370 "TARGET_32BIT && SIBLING_CALL_P (insn)"
1c494086 8371 "*
33ae7c4b 8372 if (which_alternative == 1)
8373 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
8374 else
8375 {
8376 if (arm_arch5 || arm_arch4t)
84ce8e5c 8377 return \"bx%?\\t%1\";
33ae7c4b 8378 else
8379 return \"mov%?\\t%|pc, %1\\t@ indirect sibling call \";
8380 }
1c494086 8381 "
8382 [(set_attr "type" "call")]
8383)
8384
0686440e 8385(define_expand "<return_str>return"
9b23f0a7 8386 [(RETURNS)]
8cba51a5 8387 "(TARGET_ARM || (TARGET_THUMB2
8388 && ARM_FUNC_TYPE (arm_current_func_type ()) == ARM_FT_NORMAL
8389 && !IS_STACKALIGN (arm_current_func_type ())))
0686440e 8390 <return_cond_false>"
8cba51a5 8391 "
8392 {
8393 if (TARGET_THUMB2)
8394 {
0686440e 8395 thumb2_expand_return (<return_simple_p>);
8cba51a5 8396 DONE;
8397 }
8398 }
8399 "
8400)
d68c2c10 8401
9c08d1fa 8402;; Often the return insn will be the same as loading from memory, so set attr
d68c2c10 8403(define_insn "*arm_return"
9c08d1fa 8404 [(return)]
cffb2a26 8405 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
9c08d1fa 8406 "*
9c08d1fa 8407 {
cffb2a26 8408 if (arm_ccfsm_state == 2)
8409 {
8410 arm_ccfsm_state += 2;
8411 return \"\";
8412 }
e2549f81 8413 return output_return_instruction (const_true_rtx, true, false, false);
cffb2a26 8414 }"
a2cd141b 8415 [(set_attr "type" "load1")
755eb2b4 8416 (set_attr "length" "12")
0d66636f 8417 (set_attr "predicable" "yes")]
cffb2a26 8418)
9c08d1fa 8419
0686440e 8420(define_insn "*cond_<return_str>return"
9c08d1fa 8421 [(set (pc)
8fa3ba89 8422 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 8423 [(match_operand 1 "cc_register" "") (const_int 0)])
9b23f0a7 8424 (RETURNS)
9c08d1fa 8425 (pc)))]
0686440e 8426 "TARGET_ARM <return_cond_true>"
9c08d1fa 8427 "*
8fa3ba89 8428 {
8429 if (arm_ccfsm_state == 2)
8430 {
8431 arm_ccfsm_state += 2;
8432 return \"\";
8433 }
0686440e 8434 return output_return_instruction (operands[0], true, false,
8435 <return_simple_p>);
8fa3ba89 8436 }"
8437 [(set_attr "conds" "use")
755eb2b4 8438 (set_attr "length" "12")
a2cd141b 8439 (set_attr "type" "load1")]
8fa3ba89 8440)
9c08d1fa 8441
0686440e 8442(define_insn "*cond_<return_str>return_inverted"
9c08d1fa 8443 [(set (pc)
8fa3ba89 8444 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 8445 [(match_operand 1 "cc_register" "") (const_int 0)])
9c08d1fa 8446 (pc)
9b23f0a7 8447 (RETURNS)))]
0686440e 8448 "TARGET_ARM <return_cond_true>"
9c08d1fa 8449 "*
8fa3ba89 8450 {
8451 if (arm_ccfsm_state == 2)
8452 {
8453 arm_ccfsm_state += 2;
8454 return \"\";
8455 }
0686440e 8456 return output_return_instruction (operands[0], true, true,
8457 <return_simple_p>);
8fa3ba89 8458 }"
8459 [(set_attr "conds" "use")
37a1317b 8460 (set_attr "length" "12")
a2cd141b 8461 (set_attr "type" "load1")]
8fa3ba89 8462)
9c08d1fa 8463
e2549f81 8464(define_insn "*arm_simple_return"
8465 [(simple_return)]
8466 "TARGET_ARM"
8467 "*
8468 {
8469 if (arm_ccfsm_state == 2)
8470 {
8471 arm_ccfsm_state += 2;
8472 return \"\";
8473 }
8474 return output_return_instruction (const_true_rtx, true, false, true);
8475 }"
8476 [(set_attr "type" "branch")
8477 (set_attr "length" "4")
8478 (set_attr "predicable" "yes")]
8479)
8480
68121397 8481;; Generate a sequence of instructions to determine if the processor is
8482;; in 26-bit or 32-bit mode, and return the appropriate return address
8483;; mask.
8484
8485(define_expand "return_addr_mask"
8486 [(set (match_dup 1)
8487 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8488 (const_int 0)))
8489 (set (match_operand:SI 0 "s_register_operand" "")
8490 (if_then_else:SI (eq (match_dup 1) (const_int 0))
8491 (const_int -1)
8492 (const_int 67108860)))] ; 0x03fffffc
8493 "TARGET_ARM"
8494 "
62eddbd4 8495 operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
68121397 8496 ")
8497
8498(define_insn "*check_arch2"
8499 [(set (match_operand:CC_NOOV 0 "cc_register" "")
8500 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8501 (const_int 0)))]
8502 "TARGET_ARM"
8503 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
8504 [(set_attr "length" "8")
1b7da4ac 8505 (set_attr "conds" "set")
8506 (set_attr "type" "multiple")]
68121397 8507)
8508
9c08d1fa 8509;; Call subroutine returning any type.
8510
8511(define_expand "untyped_call"
8512 [(parallel [(call (match_operand 0 "" "")
8513 (const_int 0))
8514 (match_operand 1 "" "")
8515 (match_operand 2 "" "")])]
ccd90aaa 8516 "TARGET_EITHER"
9c08d1fa 8517 "
215b30b3 8518 {
8519 int i;
ccd90aaa 8520 rtx par = gen_rtx_PARALLEL (VOIDmode,
8521 rtvec_alloc (XVECLEN (operands[2], 0)));
8522 rtx addr = gen_reg_rtx (Pmode);
8523 rtx mem;
8524 int size = 0;
9c08d1fa 8525
ccd90aaa 8526 emit_move_insn (addr, XEXP (operands[1], 0));
8527 mem = change_address (operands[1], BLKmode, addr);
9c08d1fa 8528
215b30b3 8529 for (i = 0; i < XVECLEN (operands[2], 0); i++)
8530 {
ccd90aaa 8531 rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
9c08d1fa 8532
ccd90aaa 8533 /* Default code only uses r0 as a return value, but we could
8534 be using anything up to 4 registers. */
8535 if (REGNO (src) == R0_REGNUM)
8536 src = gen_rtx_REG (TImode, R0_REGNUM);
8537
8538 XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
8539 GEN_INT (size));
8540 size += GET_MODE_SIZE (GET_MODE (src));
8541 }
8542
7f265a08 8543 emit_call_insn (gen_call_value (par, operands[0], const0_rtx, NULL));
ccd90aaa 8544
8545 size = 0;
8546
8547 for (i = 0; i < XVECLEN (par, 0); i++)
8548 {
8549 HOST_WIDE_INT offset = 0;
8550 rtx reg = XEXP (XVECEXP (par, 0, i), 0);
8551
8552 if (size != 0)
29c05e22 8553 emit_move_insn (addr, plus_constant (Pmode, addr, size));
ccd90aaa 8554
8555 mem = change_address (mem, GET_MODE (reg), NULL);
8556 if (REGNO (reg) == R0_REGNUM)
8557 {
8558 /* On thumb we have to use a write-back instruction. */
320ea44d 8559 emit_insn (arm_gen_store_multiple (arm_regs_in_sequence, 4, addr,
8560 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
ccd90aaa 8561 size = TARGET_ARM ? 16 : 0;
8562 }
8563 else
8564 {
8565 emit_move_insn (mem, reg);
8566 size = GET_MODE_SIZE (GET_MODE (reg));
8567 }
215b30b3 8568 }
9c08d1fa 8569
215b30b3 8570 /* The optimizer does not know that the call sets the function value
8571 registers we stored in the result block. We avoid problems by
8572 claiming that all hard registers are used and clobbered at this
8573 point. */
8574 emit_insn (gen_blockage ());
8575
8576 DONE;
8577 }"
8578)
9c08d1fa 8579
ccd90aaa 8580(define_expand "untyped_return"
8581 [(match_operand:BLK 0 "memory_operand" "")
8582 (match_operand 1 "" "")]
8583 "TARGET_EITHER"
8584 "
8585 {
8586 int i;
8587 rtx addr = gen_reg_rtx (Pmode);
8588 rtx mem;
8589 int size = 0;
8590
8591 emit_move_insn (addr, XEXP (operands[0], 0));
8592 mem = change_address (operands[0], BLKmode, addr);
8593
8594 for (i = 0; i < XVECLEN (operands[1], 0); i++)
8595 {
8596 HOST_WIDE_INT offset = 0;
8597 rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
8598
8599 if (size != 0)
29c05e22 8600 emit_move_insn (addr, plus_constant (Pmode, addr, size));
ccd90aaa 8601
8602 mem = change_address (mem, GET_MODE (reg), NULL);
8603 if (REGNO (reg) == R0_REGNUM)
8604 {
8605 /* On thumb we have to use a write-back instruction. */
320ea44d 8606 emit_insn (arm_gen_load_multiple (arm_regs_in_sequence, 4, addr,
8607 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
ccd90aaa 8608 size = TARGET_ARM ? 16 : 0;
8609 }
8610 else
8611 {
8612 emit_move_insn (reg, mem);
8613 size = GET_MODE_SIZE (GET_MODE (reg));
8614 }
8615 }
8616
8617 /* Emit USE insns before the return. */
8618 for (i = 0; i < XVECLEN (operands[1], 0); i++)
18b42941 8619 emit_use (SET_DEST (XVECEXP (operands[1], 0, i)));
ccd90aaa 8620
8621 /* Construct the return. */
8622 expand_naked_return ();
8623
8624 DONE;
8625 }"
8626)
8627
9c08d1fa 8628;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
8629;; all of memory. This blocks insns from being moved across this point.
8630
8631(define_insn "blockage"
e1159bbe 8632 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
cffb2a26 8633 "TARGET_EITHER"
9c08d1fa 8634 ""
cffb2a26 8635 [(set_attr "length" "0")
8636 (set_attr "type" "block")]
8637)
9c08d1fa 8638
706dca65 8639(define_insn "probe_stack"
f8570abe 8640 [(set (match_operand:SI 0 "memory_operand" "=m")
8641 (unspec:SI [(const_int 0)] UNSPEC_PROBE_STACK))]
706dca65 8642 "TARGET_32BIT"
154ae8e6 8643 "str%?\\tr0, %0"
706dca65 8644 [(set_attr "type" "store1")
8645 (set_attr "predicable" "yes")]
8646)
8647
8648(define_insn "probe_stack_range"
8649 [(set (match_operand:SI 0 "register_operand" "=r")
8650 (unspec_volatile:SI [(match_operand:SI 1 "register_operand" "0")
8651 (match_operand:SI 2 "register_operand" "r")]
dd8aabc9 8652 VUNSPEC_PROBE_STACK_RANGE))]
706dca65 8653 "TARGET_32BIT"
8654{
8655 return output_probe_stack_range (operands[0], operands[2]);
8656}
8657 [(set_attr "type" "multiple")
8658 (set_attr "conds" "clob")]
8659)
8660
f7fbdd4a 8661(define_expand "casesi"
8662 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
aea4c774 8663 (match_operand:SI 1 "const_int_operand" "") ; lower bound
8664 (match_operand:SI 2 "const_int_operand" "") ; total range
f7fbdd4a 8665 (match_operand:SI 3 "" "") ; table label
8666 (match_operand:SI 4 "" "")] ; Out of range label
9753b549 8667 "(TARGET_32BIT || optimize_size || flag_pic) && !target_pure_code"
f7fbdd4a 8668 "
215b30b3 8669 {
e6ac8414 8670 enum insn_code code;
215b30b3 8671 if (operands[1] != const0_rtx)
8672 {
e6ac8414 8673 rtx reg = gen_reg_rtx (SImode);
f7fbdd4a 8674
215b30b3 8675 emit_insn (gen_addsi3 (reg, operands[0],
d022fa24 8676 gen_int_mode (-INTVAL (operands[1]),
8677 SImode)));
215b30b3 8678 operands[0] = reg;
8679 }
9c08d1fa 8680
25f905c2 8681 if (TARGET_ARM)
e6ac8414 8682 code = CODE_FOR_arm_casesi_internal;
3db2019b 8683 else if (TARGET_THUMB1)
e6ac8414 8684 code = CODE_FOR_thumb1_casesi_internal_pic;
25f905c2 8685 else if (flag_pic)
e6ac8414 8686 code = CODE_FOR_thumb2_casesi_internal_pic;
25f905c2 8687 else
e6ac8414 8688 code = CODE_FOR_thumb2_casesi_internal;
8689
8690 if (!insn_data[(int) code].operand[1].predicate(operands[2], SImode))
8691 operands[2] = force_reg (SImode, operands[2]);
8692
8693 emit_jump_insn (GEN_FCN ((int) code) (operands[0], operands[2],
8694 operands[3], operands[4]));
215b30b3 8695 DONE;
8696 }"
8697)
f7fbdd4a 8698
f082f1c4 8699;; The USE in this pattern is needed to tell flow analysis that this is
8700;; a CASESI insn. It has no other purpose.
25f905c2 8701(define_insn "arm_casesi_internal"
f082f1c4 8702 [(parallel [(set (pc)
8703 (if_then_else
8704 (leu (match_operand:SI 0 "s_register_operand" "r")
8705 (match_operand:SI 1 "arm_rhs_operand" "rI"))
8706 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
8707 (label_ref (match_operand 2 "" ""))))
8708 (label_ref (match_operand 3 "" ""))))
bd5b4116 8709 (clobber (reg:CC CC_REGNUM))
f082f1c4 8710 (use (label_ref (match_dup 2)))])]
cffb2a26 8711 "TARGET_ARM"
f7fbdd4a 8712 "*
0d66636f 8713 if (flag_pic)
8714 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
8715 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
8716 "
8717 [(set_attr "conds" "clob")
1b7da4ac 8718 (set_attr "length" "12")
8719 (set_attr "type" "multiple")]
0d66636f 8720)
9c08d1fa 8721
cffb2a26 8722(define_expand "indirect_jump"
9c08d1fa 8723 [(set (pc)
cffb2a26 8724 (match_operand:SI 0 "s_register_operand" ""))]
8725 "TARGET_EITHER"
25f905c2 8726 "
8727 /* Thumb-2 doesn't have mov pc, reg. Explicitly set the low bit of the
8728 address and use bx. */
8729 if (TARGET_THUMB2)
8730 {
8731 rtx tmp;
8732 tmp = gen_reg_rtx (SImode);
8733 emit_insn (gen_iorsi3 (tmp, operands[0], GEN_INT(1)));
8734 operands[0] = tmp;
8735 }
8736 "
cffb2a26 8737)
8738
f1039640 8739;; NB Never uses BX.
cffb2a26 8740(define_insn "*arm_indirect_jump"
8741 [(set (pc)
8742 (match_operand:SI 0 "s_register_operand" "r"))]
8743 "TARGET_ARM"
8744 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
1b7da4ac 8745 [(set_attr "predicable" "yes")
8746 (set_attr "type" "branch")]
cffb2a26 8747)
9c08d1fa 8748
f7fbdd4a 8749(define_insn "*load_indirect_jump"
9c08d1fa 8750 [(set (pc)
8751 (match_operand:SI 0 "memory_operand" "m"))]
cffb2a26 8752 "TARGET_ARM"
8753 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
a2cd141b 8754 [(set_attr "type" "load1")
61a2d04c 8755 (set_attr "pool_range" "4096")
8756 (set_attr "neg_pool_range" "4084")
0d66636f 8757 (set_attr "predicable" "yes")]
cffb2a26 8758)
8759
9c08d1fa 8760\f
8761;; Misc insns
8762
8763(define_insn "nop"
8764 [(const_int 0)]
cffb2a26 8765 "TARGET_EITHER"
3ef90e77 8766 "nop"
cffb2a26 8767 [(set (attr "length")
8768 (if_then_else (eq_attr "is_thumb" "yes")
8769 (const_int 2)
1b7da4ac 8770 (const_int 4)))
8771 (set_attr "type" "mov_reg")]
cffb2a26 8772)
8773
ad9d4399 8774(define_insn "trap"
8775 [(trap_if (const_int 1) (const_int 0))]
8776 ""
8777 "*
8778 if (TARGET_ARM)
8779 return \".inst\\t0xe7f000f0\";
8780 else
8781 return \".inst\\t0xdeff\";
8782 "
8783 [(set (attr "length")
8784 (if_then_else (eq_attr "is_thumb" "yes")
8785 (const_int 2)
8786 (const_int 4)))
8787 (set_attr "type" "trap")
8788 (set_attr "conds" "unconditional")]
8789)
8790
9c08d1fa 8791\f
8792;; Patterns to allow combination of arithmetic, cond code and shifts
8793
0abea32c 8794(define_insn "*<arith_shift_insn>_multsi"
8795 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9b23f0a7 8796 (SHIFTABLE_OPS:SI
0abea32c 8797 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
8798 (match_operand:SI 3 "power_of_two_operand" ""))
8799 (match_operand:SI 1 "s_register_operand" "rk,<t2_binop0>")))]
d5d4dc8d 8800 "TARGET_32BIT"
0abea32c 8801 "<arith_shift_insn>%?\\t%0, %1, %2, lsl %b3"
8802 [(set_attr "predicable" "yes")
8803 (set_attr "predicable_short_it" "no")
753d9835 8804 (set_attr "shift" "2")
0abea32c 8805 (set_attr "arch" "a,t2")
8806 (set_attr "type" "alu_shift_imm")])
8807
8808(define_insn "*<arith_shift_insn>_shiftsi"
8809 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9b23f0a7 8810 (SHIFTABLE_OPS:SI
0abea32c 8811 (match_operator:SI 2 "shift_nomul_operator"
8812 [(match_operand:SI 3 "s_register_operand" "r,r,r")
8813 (match_operand:SI 4 "shift_amount_operand" "M,M,r")])
8814 (match_operand:SI 1 "s_register_operand" "rk,<t2_binop0>,rk")))]
a021b821 8815 "TARGET_32BIT && GET_CODE (operands[2]) != MULT"
0abea32c 8816 "<arith_shift_insn>%?\\t%0, %1, %3%S2"
344495ea 8817 [(set_attr "predicable" "yes")
74ef923b 8818 (set_attr "predicable_short_it" "no")
753d9835 8819 (set_attr "shift" "3")
0abea32c 8820 (set_attr "arch" "a,t2,a")
8821 (set_attr "type" "alu_shift_imm,alu_shift_imm,alu_shift_reg")])
9c08d1fa 8822
d7863cfe 8823(define_split
8824 [(set (match_operand:SI 0 "s_register_operand" "")
8825 (match_operator:SI 1 "shiftable_operator"
8826 [(match_operator:SI 2 "shiftable_operator"
8827 [(match_operator:SI 3 "shift_operator"
8828 [(match_operand:SI 4 "s_register_operand" "")
8829 (match_operand:SI 5 "reg_or_int_operand" "")])
8830 (match_operand:SI 6 "s_register_operand" "")])
8831 (match_operand:SI 7 "arm_rhs_operand" "")]))
8832 (clobber (match_operand:SI 8 "s_register_operand" ""))]
d5d4dc8d 8833 "TARGET_32BIT"
d7863cfe 8834 [(set (match_dup 8)
8835 (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8836 (match_dup 6)]))
8837 (set (match_dup 0)
8838 (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
8839 "")
8840
f7fbdd4a 8841(define_insn "*arith_shiftsi_compare0"
bd5b4116 8842 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 8843 (compare:CC_NOOV
8844 (match_operator:SI 1 "shiftable_operator"
8845 [(match_operator:SI 3 "shift_operator"
8846 [(match_operand:SI 4 "s_register_operand" "r,r")
8847 (match_operand:SI 5 "shift_amount_operand" "M,r")])
8848 (match_operand:SI 2 "s_register_operand" "r,r")])
8849 (const_int 0)))
8850 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 8851 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8852 (match_dup 2)]))]
d5d4dc8d 8853 "TARGET_32BIT"
3ef90e77 8854 "%i1s%?\\t%0, %2, %4%S3"
344495ea 8855 [(set_attr "conds" "set")
331beb1a 8856 (set_attr "shift" "4")
d5d4dc8d 8857 (set_attr "arch" "32,a")
d82e788e 8858 (set_attr "type" "alus_shift_imm,alus_shift_reg")])
9c08d1fa 8859
f7fbdd4a 8860(define_insn "*arith_shiftsi_compare0_scratch"
bd5b4116 8861 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 8862 (compare:CC_NOOV
8863 (match_operator:SI 1 "shiftable_operator"
8864 [(match_operator:SI 3 "shift_operator"
8865 [(match_operand:SI 4 "s_register_operand" "r,r")
8866 (match_operand:SI 5 "shift_amount_operand" "M,r")])
8867 (match_operand:SI 2 "s_register_operand" "r,r")])
8868 (const_int 0)))
8869 (clobber (match_scratch:SI 0 "=r,r"))]
8870 "TARGET_32BIT"
3ef90e77 8871 "%i1s%?\\t%0, %2, %4%S3"
344495ea 8872 [(set_attr "conds" "set")
331beb1a 8873 (set_attr "shift" "4")
d5d4dc8d 8874 (set_attr "arch" "32,a")
d82e788e 8875 (set_attr "type" "alus_shift_imm,alus_shift_reg")])
9c08d1fa 8876
f7fbdd4a 8877(define_insn "*sub_shiftsi"
d5d4dc8d 8878 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8879 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
9c08d1fa 8880 (match_operator:SI 2 "shift_operator"
d5d4dc8d 8881 [(match_operand:SI 3 "s_register_operand" "r,r")
8882 (match_operand:SI 4 "shift_amount_operand" "M,r")])))]
8883 "TARGET_32BIT"
6c4c2133 8884 "sub%?\\t%0, %1, %3%S2"
344495ea 8885 [(set_attr "predicable" "yes")
331beb1a 8886 (set_attr "shift" "3")
d5d4dc8d 8887 (set_attr "arch" "32,a")
d82e788e 8888 (set_attr "type" "alus_shift_imm,alus_shift_reg")])
9c08d1fa 8889
f7fbdd4a 8890(define_insn "*sub_shiftsi_compare0"
bd5b4116 8891 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 8892 (compare:CC_NOOV
d82e788e 8893 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
40dbec34 8894 (match_operator:SI 2 "shift_operator"
d82e788e 8895 [(match_operand:SI 3 "s_register_operand" "r,r,r")
8896 (match_operand:SI 4 "shift_amount_operand" "M,r,M")]))
40dbec34 8897 (const_int 0)))
d82e788e 8898 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
d5d4dc8d 8899 (minus:SI (match_dup 1)
8900 (match_op_dup 2 [(match_dup 3) (match_dup 4)])))]
8901 "TARGET_32BIT"
3ef90e77 8902 "subs%?\\t%0, %1, %3%S2"
344495ea 8903 [(set_attr "conds" "set")
a2cd141b 8904 (set_attr "shift" "3")
d82e788e 8905 (set_attr "arch" "32,a,a")
8906 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
9c08d1fa 8907
f7fbdd4a 8908(define_insn "*sub_shiftsi_compare0_scratch"
bd5b4116 8909 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 8910 (compare:CC_NOOV
d82e788e 8911 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
40dbec34 8912 (match_operator:SI 2 "shift_operator"
d82e788e 8913 [(match_operand:SI 3 "s_register_operand" "r,r,r")
8914 (match_operand:SI 4 "shift_amount_operand" "M,r,M")]))
40dbec34 8915 (const_int 0)))
d82e788e 8916 (clobber (match_scratch:SI 0 "=r,r,r"))]
d5d4dc8d 8917 "TARGET_32BIT"
3ef90e77 8918 "subs%?\\t%0, %1, %3%S2"
344495ea 8919 [(set_attr "conds" "set")
a2cd141b 8920 (set_attr "shift" "3")
d82e788e 8921 (set_attr "arch" "32,a,a")
8922 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
9c08d1fa 8923\f
8924
190efb17 8925(define_insn_and_split "*and_scc"
9c08d1fa 8926 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 8927 (and:SI (match_operator:SI 1 "arm_comparison_operator"
190efb17 8928 [(match_operand 2 "cc_register" "") (const_int 0)])
8929 (match_operand:SI 3 "s_register_operand" "r")))]
cffb2a26 8930 "TARGET_ARM"
190efb17 8931 "#" ; "mov%D1\\t%0, #0\;and%d1\\t%0, %3, #1"
8932 "&& reload_completed"
8933 [(cond_exec (match_dup 5) (set (match_dup 0) (const_int 0)))
8934 (cond_exec (match_dup 4) (set (match_dup 0)
8935 (and:SI (match_dup 3) (const_int 1))))]
8936 {
3754d046 8937 machine_mode mode = GET_MODE (operands[2]);
190efb17 8938 enum rtx_code rc = GET_CODE (operands[1]);
8939
8940 /* Note that operands[4] is the same as operands[1],
8941 but with VOIDmode as the result. */
8942 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
8943 if (mode == CCFPmode || mode == CCFPEmode)
8944 rc = reverse_condition_maybe_unordered (rc);
8945 else
8946 rc = reverse_condition (rc);
8947 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
8948 }
8fa3ba89 8949 [(set_attr "conds" "use")
1b7da4ac 8950 (set_attr "type" "multiple")
8fa3ba89 8951 (set_attr "length" "8")]
8952)
9c08d1fa 8953
190efb17 8954(define_insn_and_split "*ior_scc"
9c08d1fa 8955 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
190efb17 8956 (ior:SI (match_operator:SI 1 "arm_comparison_operator"
8957 [(match_operand 2 "cc_register" "") (const_int 0)])
8958 (match_operand:SI 3 "s_register_operand" "0,?r")))]
cffb2a26 8959 "TARGET_ARM"
e2348bcb 8960 "@
190efb17 8961 orr%d1\\t%0, %3, #1
8962 #"
8963 "&& reload_completed
8964 && REGNO (operands [0]) != REGNO (operands[3])"
8965 ;; && which_alternative == 1
8966 ; mov%D1\\t%0, %3\;orr%d1\\t%0, %3, #1
8967 [(cond_exec (match_dup 5) (set (match_dup 0) (match_dup 3)))
8968 (cond_exec (match_dup 4) (set (match_dup 0)
8969 (ior:SI (match_dup 3) (const_int 1))))]
8970 {
3754d046 8971 machine_mode mode = GET_MODE (operands[2]);
190efb17 8972 enum rtx_code rc = GET_CODE (operands[1]);
8973
8974 /* Note that operands[4] is the same as operands[1],
8975 but with VOIDmode as the result. */
8976 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
8977 if (mode == CCFPmode || mode == CCFPEmode)
8978 rc = reverse_condition_maybe_unordered (rc);
8979 else
8980 rc = reverse_condition (rc);
8981 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
8982 }
8fa3ba89 8983 [(set_attr "conds" "use")
1b7da4ac 8984 (set_attr "length" "4,8")
8985 (set_attr "type" "logic_imm,multiple")]
8fa3ba89 8986)
9c08d1fa 8987
2df9477b 8988; A series of splitters for the compare_scc pattern below. Note that
8989; order is important.
8990(define_split
8991 [(set (match_operand:SI 0 "s_register_operand" "")
8992 (lt:SI (match_operand:SI 1 "s_register_operand" "")
8993 (const_int 0)))
8994 (clobber (reg:CC CC_REGNUM))]
8995 "TARGET_32BIT && reload_completed"
8996 [(set (match_dup 0) (lshiftrt:SI (match_dup 1) (const_int 31)))])
8997
8998(define_split
8999 [(set (match_operand:SI 0 "s_register_operand" "")
9000 (ge:SI (match_operand:SI 1 "s_register_operand" "")
9001 (const_int 0)))
9002 (clobber (reg:CC CC_REGNUM))]
9003 "TARGET_32BIT && reload_completed"
9004 [(set (match_dup 0) (not:SI (match_dup 1)))
9005 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 31)))])
9006
98562479 9007(define_split
9008 [(set (match_operand:SI 0 "s_register_operand" "")
9009 (eq:SI (match_operand:SI 1 "s_register_operand" "")
9010 (const_int 0)))
9011 (clobber (reg:CC CC_REGNUM))]
9012 "arm_arch5 && TARGET_32BIT"
9013 [(set (match_dup 0) (clz:SI (match_dup 1)))
9014 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 5)))]
9015)
9016
2df9477b 9017(define_split
9018 [(set (match_operand:SI 0 "s_register_operand" "")
9019 (eq:SI (match_operand:SI 1 "s_register_operand" "")
9020 (const_int 0)))
9021 (clobber (reg:CC CC_REGNUM))]
9022 "TARGET_32BIT && reload_completed"
9023 [(parallel
080c0b9a 9024 [(set (reg:CC CC_REGNUM)
9025 (compare:CC (const_int 1) (match_dup 1)))
2df9477b 9026 (set (match_dup 0)
9027 (minus:SI (const_int 1) (match_dup 1)))])
080c0b9a 9028 (cond_exec (ltu:CC (reg:CC CC_REGNUM) (const_int 0))
2df9477b 9029 (set (match_dup 0) (const_int 0)))])
9030
9031(define_split
9032 [(set (match_operand:SI 0 "s_register_operand" "")
9033 (ne:SI (match_operand:SI 1 "s_register_operand" "")
9034 (match_operand:SI 2 "const_int_operand" "")))
9035 (clobber (reg:CC CC_REGNUM))]
9036 "TARGET_32BIT && reload_completed"
9037 [(parallel
9038 [(set (reg:CC CC_REGNUM)
9039 (compare:CC (match_dup 1) (match_dup 2)))
9040 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))])
9041 (cond_exec (ne:CC (reg:CC CC_REGNUM) (const_int 0))
9042 (set (match_dup 0) (const_int 1)))]
9043{
9044 operands[3] = GEN_INT (-INTVAL (operands[2]));
9045})
9046
9047(define_split
9048 [(set (match_operand:SI 0 "s_register_operand" "")
9049 (ne:SI (match_operand:SI 1 "s_register_operand" "")
9050 (match_operand:SI 2 "arm_add_operand" "")))
9051 (clobber (reg:CC CC_REGNUM))]
9052 "TARGET_32BIT && reload_completed"
9053 [(parallel
9054 [(set (reg:CC_NOOV CC_REGNUM)
9055 (compare:CC_NOOV (minus:SI (match_dup 1) (match_dup 2))
9056 (const_int 0)))
9057 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
9058 (cond_exec (ne:CC_NOOV (reg:CC_NOOV CC_REGNUM) (const_int 0))
9059 (set (match_dup 0) (const_int 1)))])
9060
9061(define_insn_and_split "*compare_scc"
fd711051 9062 [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts")
8fa3ba89 9063 (match_operator:SI 1 "arm_comparison_operator"
5565501b 9064 [(match_operand:SI 2 "s_register_operand" "r,r")
9065 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
bd5b4116 9066 (clobber (reg:CC CC_REGNUM))]
2df9477b 9067 "TARGET_32BIT"
9068 "#"
9069 "&& reload_completed"
9070 [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 3)))
9071 (cond_exec (match_dup 4) (set (match_dup 0) (const_int 0)))
9072 (cond_exec (match_dup 5) (set (match_dup 0) (const_int 1)))]
9073{
9074 rtx tmp1;
3754d046 9075 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
2df9477b 9076 operands[2], operands[3]);
9077 enum rtx_code rc = GET_CODE (operands[1]);
e2348bcb 9078
2df9477b 9079 tmp1 = gen_rtx_REG (mode, CC_REGNUM);
080c0b9a 9080
2df9477b 9081 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
9082 if (mode == CCFPmode || mode == CCFPEmode)
9083 rc = reverse_condition_maybe_unordered (rc);
9084 else
9085 rc = reverse_condition (rc);
9086 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
1b7da4ac 9087}
9088 [(set_attr "type" "multiple")]
9089)
9c08d1fa 9090
080c0b9a 9091;; Attempt to improve the sequence generated by the compare_scc splitters
9092;; not to use conditional execution.
98562479 9093
9094;; Rd = (eq (reg1) (const_int0)) // ARMv5
9095;; clz Rd, reg1
9096;; lsr Rd, Rd, #5
080c0b9a 9097(define_peephole2
9098 [(set (reg:CC CC_REGNUM)
9099 (compare:CC (match_operand:SI 1 "register_operand" "")
98562479 9100 (const_int 0)))
9101 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
9102 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
9103 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
9104 (set (match_dup 0) (const_int 1)))]
9105 "arm_arch5 && TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)"
9106 [(set (match_dup 0) (clz:SI (match_dup 1)))
9107 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 5)))]
9108)
9109
9110;; Rd = (eq (reg1) (const_int0)) // !ARMv5
9111;; negs Rd, reg1
9112;; adc Rd, Rd, reg1
9113(define_peephole2
9114 [(set (reg:CC CC_REGNUM)
9115 (compare:CC (match_operand:SI 1 "register_operand" "")
9116 (const_int 0)))
080c0b9a 9117 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
9118 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
9119 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
9120 (set (match_dup 0) (const_int 1)))
98562479 9121 (match_scratch:SI 2 "r")]
9122 "TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)"
922b6913 9123 [(parallel
9124 [(set (reg:CC CC_REGNUM)
98562479 9125 (compare:CC (const_int 0) (match_dup 1)))
9126 (set (match_dup 2) (minus:SI (const_int 0) (match_dup 1)))])
9127 (set (match_dup 0)
9128 (plus:SI (plus:SI (match_dup 1) (match_dup 2))
9129 (geu:SI (reg:CC CC_REGNUM) (const_int 0))))]
9130)
9131
31991287 9132;; Rd = (eq (reg1) (reg2/imm)) // ARMv5 and optimising for speed.
98562479 9133;; sub Rd, Reg1, reg2
9134;; clz Rd, Rd
9135;; lsr Rd, Rd, #5
9136(define_peephole2
9137 [(set (reg:CC CC_REGNUM)
9138 (compare:CC (match_operand:SI 1 "register_operand" "")
9139 (match_operand:SI 2 "arm_rhs_operand" "")))
9140 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
9141 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
9142 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
9143 (set (match_dup 0) (const_int 1)))]
31991287 9144 "arm_arch5 && TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)
9145 && !(TARGET_THUMB2 && optimize_insn_for_size_p ())"
98562479 9146 [(set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))
9147 (set (match_dup 0) (clz:SI (match_dup 0)))
9148 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 5)))]
9149)
9150
9151
31991287 9152;; Rd = (eq (reg1) (reg2)) // ! ARMv5 or optimising for size.
98562479 9153;; sub T1, Reg1, reg2
9154;; negs Rd, T1
9155;; adc Rd, Rd, T1
9156(define_peephole2
9157 [(set (reg:CC CC_REGNUM)
9158 (compare:CC (match_operand:SI 1 "register_operand" "")
9159 (match_operand:SI 2 "arm_rhs_operand" "")))
9160 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
9161 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
9162 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
9163 (set (match_dup 0) (const_int 1)))
9164 (match_scratch:SI 3 "r")]
9165 "TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)"
31991287 9166 [(set (match_dup 3) (match_dup 4))
080c0b9a 9167 (parallel
9168 [(set (reg:CC CC_REGNUM)
9169 (compare:CC (const_int 0) (match_dup 3)))
9170 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 3)))])
98562479 9171 (set (match_dup 0)
9172 (plus:SI (plus:SI (match_dup 0) (match_dup 3))
9173 (geu:SI (reg:CC CC_REGNUM) (const_int 0))))]
31991287 9174 "
9175 if (CONST_INT_P (operands[2]))
9176 operands[4] = plus_constant (SImode, operands[1], -INTVAL (operands[2]));
9177 else
9178 operands[4] = gen_rtx_MINUS (SImode, operands[1], operands[2]);
9179 ")
080c0b9a 9180
f7fbdd4a 9181(define_insn "*cond_move"
9c08d1fa 9182 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
aea4c774 9183 (if_then_else:SI (match_operator 3 "equality_operator"
8fa3ba89 9184 [(match_operator 4 "arm_comparison_operator"
8a18b90c 9185 [(match_operand 5 "cc_register" "") (const_int 0)])
aea4c774 9186 (const_int 0)])
9187 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9188 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
cffb2a26 9189 "TARGET_ARM"
9c08d1fa 9190 "*
8fa3ba89 9191 if (GET_CODE (operands[3]) == NE)
9192 {
9193 if (which_alternative != 1)
9194 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
9195 if (which_alternative != 0)
9196 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
9197 return \"\";
9198 }
9199 if (which_alternative != 0)
9200 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9201 if (which_alternative != 1)
9202 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
9203 return \"\";
9204 "
9205 [(set_attr "conds" "use")
282b4c75 9206 (set_attr_alternative "type"
9207 [(if_then_else (match_operand 2 "const_int_operand" "")
9208 (const_string "mov_imm")
9209 (const_string "mov_reg"))
9210 (if_then_else (match_operand 1 "const_int_operand" "")
9211 (const_string "mov_imm")
9212 (const_string "mov_reg"))
9213 (const_string "multiple")])
8fa3ba89 9214 (set_attr "length" "4,4,8")]
9215)
9c08d1fa 9216
f7fbdd4a 9217(define_insn "*cond_arith"
9c08d1fa 9218 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9219 (match_operator:SI 5 "shiftable_operator"
8fa3ba89 9220 [(match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 9221 [(match_operand:SI 2 "s_register_operand" "r,r")
9222 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
9223 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 9224 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9225 "TARGET_ARM"
9c08d1fa 9226 "*
8fa3ba89 9227 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
9228 return \"%i5\\t%0, %1, %2, lsr #31\";
40dbec34 9229
8fa3ba89 9230 output_asm_insn (\"cmp\\t%2, %3\", operands);
9231 if (GET_CODE (operands[5]) == AND)
9232 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
9233 else if (GET_CODE (operands[5]) == MINUS)
9234 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
9235 else if (which_alternative != 0)
9236 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9237 return \"%i5%d4\\t%0, %1, #1\";
9238 "
9239 [(set_attr "conds" "clob")
1b7da4ac 9240 (set_attr "length" "12")
9241 (set_attr "type" "multiple")]
8fa3ba89 9242)
9c08d1fa 9243
f7fbdd4a 9244(define_insn "*cond_sub"
9c08d1fa 9245 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9246 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8fa3ba89 9247 (match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 9248 [(match_operand:SI 2 "s_register_operand" "r,r")
9249 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 9250 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9251 "TARGET_ARM"
9c08d1fa 9252 "*
8fa3ba89 9253 output_asm_insn (\"cmp\\t%2, %3\", operands);
9254 if (which_alternative != 0)
9255 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9256 return \"sub%d4\\t%0, %1, #1\";
9257 "
9258 [(set_attr "conds" "clob")
1b7da4ac 9259 (set_attr "length" "8,12")
9260 (set_attr "type" "multiple")]
8fa3ba89 9261)
9c08d1fa 9262
aea4c774 9263(define_insn "*cmp_ite0"
cffb2a26 9264 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 9265 (compare
9266 (if_then_else:SI
8fa3ba89 9267 (match_operator 4 "arm_comparison_operator"
2ff91fec 9268 [(match_operand:SI 0 "s_register_operand"
9269 "l,l,l,r,r,r,r,r,r")
9270 (match_operand:SI 1 "arm_add_operand"
9271 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
8fa3ba89 9272 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 9273 [(match_operand:SI 2 "s_register_operand"
9274 "l,r,r,l,l,r,r,r,r")
9275 (match_operand:SI 3 "arm_add_operand"
9276 "lPy,rI,L,lPy,lPy,rI,rI,L,L")])
aea4c774 9277 (const_int 0))
9278 (const_int 0)))]
2ff91fec 9279 "TARGET_32BIT"
9c08d1fa 9280 "*
aea4c774 9281 {
2ff91fec 9282 static const char * const cmp1[NUM_OF_COND_CMP][2] =
9283 {
9284 {\"cmp%d5\\t%0, %1\",
9285 \"cmp%d4\\t%2, %3\"},
9286 {\"cmn%d5\\t%0, #%n1\",
9287 \"cmp%d4\\t%2, %3\"},
9288 {\"cmp%d5\\t%0, %1\",
9289 \"cmn%d4\\t%2, #%n3\"},
9290 {\"cmn%d5\\t%0, #%n1\",
9291 \"cmn%d4\\t%2, #%n3\"}
9292 };
9293 static const char * const cmp2[NUM_OF_COND_CMP][2] =
9294 {
9295 {\"cmp\\t%2, %3\",
9296 \"cmp\\t%0, %1\"},
9297 {\"cmp\\t%2, %3\",
9298 \"cmn\\t%0, #%n1\"},
9299 {\"cmn\\t%2, #%n3\",
9300 \"cmp\\t%0, %1\"},
9301 {\"cmn\\t%2, #%n3\",
9302 \"cmn\\t%0, #%n1\"}
9303 };
9304 static const char * const ite[2] =
8fa3ba89 9305 {
2ff91fec 9306 \"it\\t%d5\",
9307 \"it\\t%d4\"
8fa3ba89 9308 };
2ff91fec 9309 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
9310 CMP_CMP, CMN_CMP, CMP_CMP,
9311 CMN_CMP, CMP_CMN, CMN_CMN};
8fa3ba89 9312 int swap =
9313 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9314
2ff91fec 9315 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9316 if (TARGET_THUMB2) {
9317 output_asm_insn (ite[swap], operands);
9318 }
9319 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9320 return \"\";
8fa3ba89 9321 }"
9322 [(set_attr "conds" "set")
2ff91fec 9323 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
1b7da4ac 9324 (set_attr "type" "multiple")
2ff91fec 9325 (set_attr_alternative "length"
9326 [(const_int 6)
9327 (const_int 8)
9328 (const_int 8)
9329 (const_int 8)
9330 (const_int 8)
9331 (if_then_else (eq_attr "is_thumb" "no")
9332 (const_int 8)
9333 (const_int 10))
9334 (if_then_else (eq_attr "is_thumb" "no")
9335 (const_int 8)
9336 (const_int 10))
9337 (if_then_else (eq_attr "is_thumb" "no")
9338 (const_int 8)
9339 (const_int 10))
9340 (if_then_else (eq_attr "is_thumb" "no")
9341 (const_int 8)
9342 (const_int 10))])]
8fa3ba89 9343)
9c08d1fa 9344
aea4c774 9345(define_insn "*cmp_ite1"
cffb2a26 9346 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 9347 (compare
9348 (if_then_else:SI
8fa3ba89 9349 (match_operator 4 "arm_comparison_operator"
2ff91fec 9350 [(match_operand:SI 0 "s_register_operand"
9351 "l,l,l,r,r,r,r,r,r")
9352 (match_operand:SI 1 "arm_add_operand"
9353 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
8fa3ba89 9354 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 9355 [(match_operand:SI 2 "s_register_operand"
9356 "l,r,r,l,l,r,r,r,r")
9357 (match_operand:SI 3 "arm_add_operand"
9358 "lPy,rI,L,lPy,lPy,rI,rI,L,L")])
aea4c774 9359 (const_int 1))
9360 (const_int 0)))]
2ff91fec 9361 "TARGET_32BIT"
9c08d1fa 9362 "*
9c08d1fa 9363 {
2ff91fec 9364 static const char * const cmp1[NUM_OF_COND_CMP][2] =
9365 {
9366 {\"cmp\\t%0, %1\",
9367 \"cmp\\t%2, %3\"},
9368 {\"cmn\\t%0, #%n1\",
9369 \"cmp\\t%2, %3\"},
9370 {\"cmp\\t%0, %1\",
9371 \"cmn\\t%2, #%n3\"},
9372 {\"cmn\\t%0, #%n1\",
9373 \"cmn\\t%2, #%n3\"}
9374 };
9375 static const char * const cmp2[NUM_OF_COND_CMP][2] =
215b30b3 9376 {
2ff91fec 9377 {\"cmp%d4\\t%2, %3\",
9378 \"cmp%D5\\t%0, %1\"},
9379 {\"cmp%d4\\t%2, %3\",
9380 \"cmn%D5\\t%0, #%n1\"},
9381 {\"cmn%d4\\t%2, #%n3\",
9382 \"cmp%D5\\t%0, %1\"},
9383 {\"cmn%d4\\t%2, #%n3\",
9384 \"cmn%D5\\t%0, #%n1\"}
215b30b3 9385 };
2ff91fec 9386 static const char * const ite[2] =
9387 {
9388 \"it\\t%d4\",
9389 \"it\\t%D5\"
9390 };
9391 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
9392 CMP_CMP, CMN_CMP, CMP_CMP,
9393 CMN_CMP, CMP_CMN, CMN_CMN};
215b30b3 9394 int swap =
9395 comparison_dominates_p (GET_CODE (operands[5]),
9396 reverse_condition (GET_CODE (operands[4])));
9397
2ff91fec 9398 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9399 if (TARGET_THUMB2) {
9400 output_asm_insn (ite[swap], operands);
9401 }
9402 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9403 return \"\";
215b30b3 9404 }"
8fa3ba89 9405 [(set_attr "conds" "set")
2ff91fec 9406 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
9407 (set_attr_alternative "length"
9408 [(const_int 6)
9409 (const_int 8)
9410 (const_int 8)
9411 (const_int 8)
9412 (const_int 8)
9413 (if_then_else (eq_attr "is_thumb" "no")
9414 (const_int 8)
9415 (const_int 10))
9416 (if_then_else (eq_attr "is_thumb" "no")
9417 (const_int 8)
9418 (const_int 10))
9419 (if_then_else (eq_attr "is_thumb" "no")
9420 (const_int 8)
9421 (const_int 10))
9422 (if_then_else (eq_attr "is_thumb" "no")
9423 (const_int 8)
1b7da4ac 9424 (const_int 10))])
9425 (set_attr "type" "multiple")]
8fa3ba89 9426)
9c08d1fa 9427
f6c53574 9428(define_insn "*cmp_and"
9429 [(set (match_operand 6 "dominant_cc_register" "")
9430 (compare
9431 (and:SI
9432 (match_operator 4 "arm_comparison_operator"
2ff91fec 9433 [(match_operand:SI 0 "s_register_operand"
9434 "l,l,l,r,r,r,r,r,r")
9435 (match_operand:SI 1 "arm_add_operand"
9436 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
f6c53574 9437 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 9438 [(match_operand:SI 2 "s_register_operand"
9439 "l,r,r,l,l,r,r,r,r")
9440 (match_operand:SI 3 "arm_add_operand"
9441 "lPy,rI,L,lPy,lPy,rI,rI,L,L")]))
f6c53574 9442 (const_int 0)))]
2ff91fec 9443 "TARGET_32BIT"
f6c53574 9444 "*
9445 {
2ff91fec 9446 static const char *const cmp1[NUM_OF_COND_CMP][2] =
f6c53574 9447 {
2ff91fec 9448 {\"cmp%d5\\t%0, %1\",
9449 \"cmp%d4\\t%2, %3\"},
9450 {\"cmn%d5\\t%0, #%n1\",
9451 \"cmp%d4\\t%2, %3\"},
9452 {\"cmp%d5\\t%0, %1\",
9453 \"cmn%d4\\t%2, #%n3\"},
9454 {\"cmn%d5\\t%0, #%n1\",
9455 \"cmn%d4\\t%2, #%n3\"}
f6c53574 9456 };
2ff91fec 9457 static const char *const cmp2[NUM_OF_COND_CMP][2] =
9458 {
9459 {\"cmp\\t%2, %3\",
9460 \"cmp\\t%0, %1\"},
9461 {\"cmp\\t%2, %3\",
9462 \"cmn\\t%0, #%n1\"},
9463 {\"cmn\\t%2, #%n3\",
9464 \"cmp\\t%0, %1\"},
9465 {\"cmn\\t%2, #%n3\",
9466 \"cmn\\t%0, #%n1\"}
9467 };
9468 static const char *const ite[2] =
9469 {
9470 \"it\\t%d5\",
9471 \"it\\t%d4\"
9472 };
9473 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
9474 CMP_CMP, CMN_CMP, CMP_CMP,
9475 CMN_CMP, CMP_CMN, CMN_CMN};
f6c53574 9476 int swap =
9477 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9478
2ff91fec 9479 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9480 if (TARGET_THUMB2) {
9481 output_asm_insn (ite[swap], operands);
9482 }
9483 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9484 return \"\";
f6c53574 9485 }"
9486 [(set_attr "conds" "set")
9487 (set_attr "predicable" "no")
2ff91fec 9488 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
9489 (set_attr_alternative "length"
9490 [(const_int 6)
9491 (const_int 8)
9492 (const_int 8)
9493 (const_int 8)
9494 (const_int 8)
9495 (if_then_else (eq_attr "is_thumb" "no")
9496 (const_int 8)
9497 (const_int 10))
9498 (if_then_else (eq_attr "is_thumb" "no")
9499 (const_int 8)
9500 (const_int 10))
9501 (if_then_else (eq_attr "is_thumb" "no")
9502 (const_int 8)
9503 (const_int 10))
9504 (if_then_else (eq_attr "is_thumb" "no")
9505 (const_int 8)
1b7da4ac 9506 (const_int 10))])
9507 (set_attr "type" "multiple")]
f6c53574 9508)
9509
9510(define_insn "*cmp_ior"
9511 [(set (match_operand 6 "dominant_cc_register" "")
9512 (compare
9513 (ior:SI
9514 (match_operator 4 "arm_comparison_operator"
2ff91fec 9515 [(match_operand:SI 0 "s_register_operand"
9516 "l,l,l,r,r,r,r,r,r")
9517 (match_operand:SI 1 "arm_add_operand"
9518 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
f6c53574 9519 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 9520 [(match_operand:SI 2 "s_register_operand"
9521 "l,r,r,l,l,r,r,r,r")
9522 (match_operand:SI 3 "arm_add_operand"
9523 "lPy,rI,L,lPy,lPy,rI,rI,L,L")]))
f6c53574 9524 (const_int 0)))]
2ff91fec 9525 "TARGET_32BIT"
f6c53574 9526 "*
f6c53574 9527 {
2ff91fec 9528 static const char *const cmp1[NUM_OF_COND_CMP][2] =
9529 {
9530 {\"cmp\\t%0, %1\",
9531 \"cmp\\t%2, %3\"},
9532 {\"cmn\\t%0, #%n1\",
9533 \"cmp\\t%2, %3\"},
9534 {\"cmp\\t%0, %1\",
9535 \"cmn\\t%2, #%n3\"},
9536 {\"cmn\\t%0, #%n1\",
9537 \"cmn\\t%2, #%n3\"}
9538 };
9539 static const char *const cmp2[NUM_OF_COND_CMP][2] =
9540 {
9541 {\"cmp%D4\\t%2, %3\",
9542 \"cmp%D5\\t%0, %1\"},
9543 {\"cmp%D4\\t%2, %3\",
9544 \"cmn%D5\\t%0, #%n1\"},
9545 {\"cmn%D4\\t%2, #%n3\",
9546 \"cmp%D5\\t%0, %1\"},
9547 {\"cmn%D4\\t%2, #%n3\",
9548 \"cmn%D5\\t%0, #%n1\"}
9549 };
9550 static const char *const ite[2] =
9551 {
9552 \"it\\t%D4\",
9553 \"it\\t%D5\"
9554 };
9555 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
9556 CMP_CMP, CMN_CMP, CMP_CMP,
9557 CMN_CMP, CMP_CMN, CMN_CMN};
9558 int swap =
9559 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9560
9561 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9562 if (TARGET_THUMB2) {
9563 output_asm_insn (ite[swap], operands);
9564 }
9565 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9566 return \"\";
9567 }
9568 "
f6c53574 9569 [(set_attr "conds" "set")
2ff91fec 9570 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
9571 (set_attr_alternative "length"
9572 [(const_int 6)
9573 (const_int 8)
9574 (const_int 8)
9575 (const_int 8)
9576 (const_int 8)
9577 (if_then_else (eq_attr "is_thumb" "no")
9578 (const_int 8)
9579 (const_int 10))
9580 (if_then_else (eq_attr "is_thumb" "no")
9581 (const_int 8)
9582 (const_int 10))
9583 (if_then_else (eq_attr "is_thumb" "no")
9584 (const_int 8)
9585 (const_int 10))
9586 (if_then_else (eq_attr "is_thumb" "no")
9587 (const_int 8)
1b7da4ac 9588 (const_int 10))])
9589 (set_attr "type" "multiple")]
f6c53574 9590)
9591
3c5afce6 9592(define_insn_and_split "*ior_scc_scc"
fd711051 9593 [(set (match_operand:SI 0 "s_register_operand" "=Ts")
3c5afce6 9594 (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9595 [(match_operand:SI 1 "s_register_operand" "r")
9596 (match_operand:SI 2 "arm_add_operand" "rIL")])
9597 (match_operator:SI 6 "arm_comparison_operator"
9598 [(match_operand:SI 4 "s_register_operand" "r")
9599 (match_operand:SI 5 "arm_add_operand" "rIL")])))
9600 (clobber (reg:CC CC_REGNUM))]
2ff91fec 9601 "TARGET_32BIT
3c5afce6 9602 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
9603 != CCmode)"
9604 "#"
2ff91fec 9605 "TARGET_32BIT && reload_completed"
3c5afce6 9606 [(set (match_dup 7)
9607 (compare
9608 (ior:SI
9609 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9610 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9611 (const_int 0)))
9612 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9613 "operands[7]
9614 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9615 DOM_CC_X_OR_Y),
601f584c 9616 CC_REGNUM);"
9617 [(set_attr "conds" "clob")
1b7da4ac 9618 (set_attr "length" "16")
9619 (set_attr "type" "multiple")]
9620)
601f584c 9621
9622; If the above pattern is followed by a CMP insn, then the compare is
9623; redundant, since we can rework the conditional instruction that follows.
9624(define_insn_and_split "*ior_scc_scc_cmp"
9625 [(set (match_operand 0 "dominant_cc_register" "")
9626 (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9627 [(match_operand:SI 1 "s_register_operand" "r")
9628 (match_operand:SI 2 "arm_add_operand" "rIL")])
9629 (match_operator:SI 6 "arm_comparison_operator"
9630 [(match_operand:SI 4 "s_register_operand" "r")
9631 (match_operand:SI 5 "arm_add_operand" "rIL")]))
9632 (const_int 0)))
fd711051 9633 (set (match_operand:SI 7 "s_register_operand" "=Ts")
601f584c 9634 (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9635 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
2ff91fec 9636 "TARGET_32BIT"
601f584c 9637 "#"
2ff91fec 9638 "TARGET_32BIT && reload_completed"
601f584c 9639 [(set (match_dup 0)
9640 (compare
9641 (ior:SI
9642 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9643 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9644 (const_int 0)))
9645 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9646 ""
9647 [(set_attr "conds" "set")
1b7da4ac 9648 (set_attr "length" "16")
9649 (set_attr "type" "multiple")]
9650)
3c5afce6 9651
9652(define_insn_and_split "*and_scc_scc"
fd711051 9653 [(set (match_operand:SI 0 "s_register_operand" "=Ts")
3c5afce6 9654 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9655 [(match_operand:SI 1 "s_register_operand" "r")
9656 (match_operand:SI 2 "arm_add_operand" "rIL")])
9657 (match_operator:SI 6 "arm_comparison_operator"
9658 [(match_operand:SI 4 "s_register_operand" "r")
9659 (match_operand:SI 5 "arm_add_operand" "rIL")])))
9660 (clobber (reg:CC CC_REGNUM))]
2ff91fec 9661 "TARGET_32BIT
3c5afce6 9662 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9663 != CCmode)"
9664 "#"
2ff91fec 9665 "TARGET_32BIT && reload_completed
601f584c 9666 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9667 != CCmode)"
3c5afce6 9668 [(set (match_dup 7)
9669 (compare
9670 (and:SI
9671 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9672 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9673 (const_int 0)))
9674 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9675 "operands[7]
9676 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9677 DOM_CC_X_AND_Y),
601f584c 9678 CC_REGNUM);"
9679 [(set_attr "conds" "clob")
1b7da4ac 9680 (set_attr "length" "16")
9681 (set_attr "type" "multiple")]
9682)
601f584c 9683
9684; If the above pattern is followed by a CMP insn, then the compare is
9685; redundant, since we can rework the conditional instruction that follows.
9686(define_insn_and_split "*and_scc_scc_cmp"
9687 [(set (match_operand 0 "dominant_cc_register" "")
9688 (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
9689 [(match_operand:SI 1 "s_register_operand" "r")
9690 (match_operand:SI 2 "arm_add_operand" "rIL")])
9691 (match_operator:SI 6 "arm_comparison_operator"
9692 [(match_operand:SI 4 "s_register_operand" "r")
9693 (match_operand:SI 5 "arm_add_operand" "rIL")]))
9694 (const_int 0)))
fd711051 9695 (set (match_operand:SI 7 "s_register_operand" "=Ts")
601f584c 9696 (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9697 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
2ff91fec 9698 "TARGET_32BIT"
601f584c 9699 "#"
2ff91fec 9700 "TARGET_32BIT && reload_completed"
601f584c 9701 [(set (match_dup 0)
9702 (compare
9703 (and:SI
9704 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9705 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9706 (const_int 0)))
9707 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9708 ""
9709 [(set_attr "conds" "set")
1b7da4ac 9710 (set_attr "length" "16")
9711 (set_attr "type" "multiple")]
9712)
601f584c 9713
9714;; If there is no dominance in the comparison, then we can still save an
9715;; instruction in the AND case, since we can know that the second compare
9716;; need only zero the value if false (if true, then the value is already
9717;; correct).
9718(define_insn_and_split "*and_scc_scc_nodom"
fd711051 9719 [(set (match_operand:SI 0 "s_register_operand" "=&Ts,&Ts,&Ts")
601f584c 9720 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9721 [(match_operand:SI 1 "s_register_operand" "r,r,0")
9722 (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
9723 (match_operator:SI 6 "arm_comparison_operator"
9724 [(match_operand:SI 4 "s_register_operand" "r,r,r")
9725 (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
9726 (clobber (reg:CC CC_REGNUM))]
2ff91fec 9727 "TARGET_32BIT
601f584c 9728 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9729 == CCmode)"
9730 "#"
2ff91fec 9731 "TARGET_32BIT && reload_completed"
601f584c 9732 [(parallel [(set (match_dup 0)
9733 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
9734 (clobber (reg:CC CC_REGNUM))])
9735 (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
9736 (set (match_dup 0)
9737 (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
9738 (match_dup 0)
9739 (const_int 0)))]
9740 "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
9741 operands[4], operands[5]),
9742 CC_REGNUM);
9743 operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
9744 operands[5]);"
9745 [(set_attr "conds" "clob")
1b7da4ac 9746 (set_attr "length" "20")
9747 (set_attr "type" "multiple")]
9748)
3c5afce6 9749
3a0bdee0 9750(define_split
9751 [(set (reg:CC_NOOV CC_REGNUM)
9752 (compare:CC_NOOV (ior:SI
9753 (and:SI (match_operand:SI 0 "s_register_operand" "")
9754 (const_int 1))
b0694be0 9755 (match_operator:SI 1 "arm_comparison_operator"
3a0bdee0 9756 [(match_operand:SI 2 "s_register_operand" "")
9757 (match_operand:SI 3 "arm_add_operand" "")]))
9758 (const_int 0)))
9759 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9760 "TARGET_ARM"
9761 [(set (match_dup 4)
9762 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9763 (match_dup 0)))
9764 (set (reg:CC_NOOV CC_REGNUM)
9765 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9766 (const_int 0)))]
9767 "")
9768
9769(define_split
9770 [(set (reg:CC_NOOV CC_REGNUM)
9771 (compare:CC_NOOV (ior:SI
b0694be0 9772 (match_operator:SI 1 "arm_comparison_operator"
3a0bdee0 9773 [(match_operand:SI 2 "s_register_operand" "")
9774 (match_operand:SI 3 "arm_add_operand" "")])
9775 (and:SI (match_operand:SI 0 "s_register_operand" "")
9776 (const_int 1)))
9777 (const_int 0)))
9778 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9779 "TARGET_ARM"
9780 [(set (match_dup 4)
9781 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9782 (match_dup 0)))
9783 (set (reg:CC_NOOV CC_REGNUM)
9784 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9785 (const_int 0)))]
9786 "")
25f905c2 9787;; ??? The conditional patterns above need checking for Thumb-2 usefulness
3a0bdee0 9788
190efb17 9789(define_insn_and_split "*negscc"
9c08d1fa 9790 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9791 (neg:SI (match_operator 3 "arm_comparison_operator"
9c08d1fa 9792 [(match_operand:SI 1 "s_register_operand" "r")
9793 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
bd5b4116 9794 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9795 "TARGET_ARM"
190efb17 9796 "#"
9797 "&& reload_completed"
9798 [(const_int 0)]
9799 {
9800 rtx cc_reg = gen_rtx_REG (CCmode, CC_REGNUM);
e2348bcb 9801
190efb17 9802 if (GET_CODE (operands[3]) == LT && operands[2] == const0_rtx)
9803 {
9804 /* Emit mov\\t%0, %1, asr #31 */
d1f9b275 9805 emit_insn (gen_rtx_SET (operands[0],
190efb17 9806 gen_rtx_ASHIFTRT (SImode,
9807 operands[1],
9808 GEN_INT (31))));
9809 DONE;
9810 }
9811 else if (GET_CODE (operands[3]) == NE)
9812 {
9813 /* Emit subs\\t%0, %1, %2\;mvnne\\t%0, #0 */
9814 if (CONST_INT_P (operands[2]))
9815 emit_insn (gen_cmpsi2_addneg (operands[0], operands[1], operands[2],
9816 GEN_INT (- INTVAL (operands[2]))));
9817 else
9818 emit_insn (gen_subsi3_compare (operands[0], operands[1], operands[2]));
9819
9820 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
9821 gen_rtx_NE (SImode,
9822 cc_reg,
9823 const0_rtx),
d1f9b275 9824 gen_rtx_SET (operands[0],
190efb17 9825 GEN_INT (~0))));
9826 DONE;
9827 }
9828 else
9829 {
9830 /* Emit: cmp\\t%1, %2\;mov%D3\\t%0, #0\;mvn%d3\\t%0, #0 */
d1f9b275 9831 emit_insn (gen_rtx_SET (cc_reg,
190efb17 9832 gen_rtx_COMPARE (CCmode, operands[1], operands[2])));
9833 enum rtx_code rc = GET_CODE (operands[3]);
9834
9835 rc = reverse_condition (rc);
9836 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
9837 gen_rtx_fmt_ee (rc,
9838 VOIDmode,
9839 cc_reg,
9840 const0_rtx),
d1f9b275 9841 gen_rtx_SET (operands[0], const0_rtx)));
190efb17 9842 rc = GET_CODE (operands[3]);
9843 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
9844 gen_rtx_fmt_ee (rc,
9845 VOIDmode,
9846 cc_reg,
9847 const0_rtx),
d1f9b275 9848 gen_rtx_SET (operands[0],
190efb17 9849 GEN_INT (~0))));
9850 DONE;
9851 }
9852 FAIL;
9853 }
8fa3ba89 9854 [(set_attr "conds" "clob")
1b7da4ac 9855 (set_attr "length" "12")
9856 (set_attr "type" "multiple")]
8fa3ba89 9857)
9c08d1fa 9858
90404b57 9859(define_insn_and_split "movcond_addsi"
9860 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r")
9861 (if_then_else:SI
9862 (match_operator 5 "comparison_operator"
9863 [(plus:SI (match_operand:SI 3 "s_register_operand" "r,r,r")
9864 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL"))
9865 (const_int 0)])
9866 (match_operand:SI 1 "arm_rhs_operand" "rI,rPy,r")
9867 (match_operand:SI 2 "arm_rhs_operand" "rI,rPy,r")))
9868 (clobber (reg:CC CC_REGNUM))]
9869 "TARGET_32BIT"
9870 "#"
9871 "&& reload_completed"
9872 [(set (reg:CC_NOOV CC_REGNUM)
9873 (compare:CC_NOOV
9874 (plus:SI (match_dup 3)
9875 (match_dup 4))
9876 (const_int 0)))
9877 (set (match_dup 0) (match_dup 1))
9878 (cond_exec (match_dup 6)
9879 (set (match_dup 0) (match_dup 2)))]
9880 "
9881 {
3754d046 9882 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[5]),
90404b57 9883 operands[3], operands[4]);
9884 enum rtx_code rc = GET_CODE (operands[5]);
90404b57 9885 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9886 gcc_assert (!(mode == CCFPmode || mode == CCFPEmode));
22440aeb 9887 if (!REG_P (operands[2]) || REGNO (operands[2]) != REGNO (operands[0]))
4d01ce2f 9888 rc = reverse_condition (rc);
f145bcba 9889 else
9890 std::swap (operands[1], operands[2]);
90404b57 9891
9892 operands[6] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9893 }
9894 "
9895 [(set_attr "conds" "clob")
1b7da4ac 9896 (set_attr "enabled_for_depr_it" "no,yes,yes")
9897 (set_attr "type" "multiple")]
90404b57 9898)
9899
9c08d1fa 9900(define_insn "movcond"
9901 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 9902 (if_then_else:SI
8fa3ba89 9903 (match_operator 5 "arm_comparison_operator"
5565501b 9904 [(match_operand:SI 3 "s_register_operand" "r,r,r")
9905 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
9906 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9907 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 9908 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9909 "TARGET_ARM"
9c08d1fa 9910 "*
9911 if (GET_CODE (operands[5]) == LT
9912 && (operands[4] == const0_rtx))
9913 {
0438d37f 9914 if (which_alternative != 1 && REG_P (operands[1]))
9c08d1fa 9915 {
9c08d1fa 9916 if (operands[2] == const0_rtx)
e2348bcb 9917 return \"and\\t%0, %1, %3, asr #31\";
9918 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
9c08d1fa 9919 }
0438d37f 9920 else if (which_alternative != 0 && REG_P (operands[2]))
9c08d1fa 9921 {
9c08d1fa 9922 if (operands[1] == const0_rtx)
e2348bcb 9923 return \"bic\\t%0, %2, %3, asr #31\";
9924 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
9c08d1fa 9925 }
9926 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 9927 are constants. */
9c08d1fa 9928 }
e2348bcb 9929
9c08d1fa 9930 if (GET_CODE (operands[5]) == GE
9931 && (operands[4] == const0_rtx))
9932 {
0438d37f 9933 if (which_alternative != 1 && REG_P (operands[1]))
9c08d1fa 9934 {
9c08d1fa 9935 if (operands[2] == const0_rtx)
e2348bcb 9936 return \"bic\\t%0, %1, %3, asr #31\";
9937 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
9c08d1fa 9938 }
0438d37f 9939 else if (which_alternative != 0 && REG_P (operands[2]))
9c08d1fa 9940 {
9c08d1fa 9941 if (operands[1] == const0_rtx)
e2348bcb 9942 return \"and\\t%0, %2, %3, asr #31\";
9943 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
9c08d1fa 9944 }
9945 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 9946 are constants. */
9c08d1fa 9947 }
0438d37f 9948 if (CONST_INT_P (operands[4])
9c08d1fa 9949 && !const_ok_for_arm (INTVAL (operands[4])))
e2348bcb 9950 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
9c08d1fa 9951 else
e2348bcb 9952 output_asm_insn (\"cmp\\t%3, %4\", operands);
9c08d1fa 9953 if (which_alternative != 0)
e2348bcb 9954 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
9c08d1fa 9955 if (which_alternative != 1)
e2348bcb 9956 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
9c08d1fa 9957 return \"\";
215b30b3 9958 "
8fa3ba89 9959 [(set_attr "conds" "clob")
1b7da4ac 9960 (set_attr "length" "8,8,12")
9961 (set_attr "type" "multiple")]
8fa3ba89 9962)
9c08d1fa 9963
25f905c2 9964;; ??? The patterns below need checking for Thumb-2 usefulness.
9965
8a18b90c 9966(define_insn "*ifcompare_plus_move"
9967 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9968 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 9969 [(match_operand:SI 4 "s_register_operand" "r,r")
9970 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9971 (plus:SI
9972 (match_operand:SI 2 "s_register_operand" "r,r")
9973 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
129a2fe4 9974 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 9975 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9976 "TARGET_ARM"
8a18b90c 9977 "#"
8fa3ba89 9978 [(set_attr "conds" "clob")
1b7da4ac 9979 (set_attr "length" "8,12")
9980 (set_attr "type" "multiple")]
8fa3ba89 9981)
8a18b90c 9982
9983(define_insn "*if_plus_move"
129a2fe4 9984 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 9985 (if_then_else:SI
8fa3ba89 9986 (match_operator 4 "arm_comparison_operator"
8a18b90c 9987 [(match_operand 5 "cc_register" "") (const_int 0)])
9988 (plus:SI
129a2fe4 9989 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9990 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
9991 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
cffb2a26 9992 "TARGET_ARM"
8a18b90c 9993 "@
9994 add%d4\\t%0, %2, %3
9995 sub%d4\\t%0, %2, #%n3
9996 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
129a2fe4 9997 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8fa3ba89 9998 [(set_attr "conds" "use")
9999 (set_attr "length" "4,4,8,8")
65f68e55 10000 (set_attr_alternative "type"
10001 [(if_then_else (match_operand 3 "const_int_operand" "")
d82e788e 10002 (const_string "alu_imm" )
112eda6f 10003 (const_string "alu_sreg"))
d82e788e 10004 (const_string "alu_imm")
282b4c75 10005 (const_string "multiple")
10006 (const_string "multiple")])]
8fa3ba89 10007)
8a18b90c 10008
10009(define_insn "*ifcompare_move_plus"
5565501b 10010 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10011 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 10012 [(match_operand:SI 4 "s_register_operand" "r,r")
10013 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 10014 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 10015 (plus:SI
10016 (match_operand:SI 2 "s_register_operand" "r,r")
10017 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
bd5b4116 10018 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10019 "TARGET_ARM"
8a18b90c 10020 "#"
8fa3ba89 10021 [(set_attr "conds" "clob")
1b7da4ac 10022 (set_attr "length" "8,12")
10023 (set_attr "type" "multiple")]
8fa3ba89 10024)
8a18b90c 10025
10026(define_insn "*if_move_plus"
129a2fe4 10027 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 10028 (if_then_else:SI
8fa3ba89 10029 (match_operator 4 "arm_comparison_operator"
8a18b90c 10030 [(match_operand 5 "cc_register" "") (const_int 0)])
129a2fe4 10031 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8a18b90c 10032 (plus:SI
129a2fe4 10033 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
10034 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
cffb2a26 10035 "TARGET_ARM"
8a18b90c 10036 "@
10037 add%D4\\t%0, %2, %3
10038 sub%D4\\t%0, %2, #%n3
10039 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
129a2fe4 10040 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8fa3ba89 10041 [(set_attr "conds" "use")
10042 (set_attr "length" "4,4,8,8")
282b4c75 10043 (set_attr_alternative "type"
10044 [(if_then_else (match_operand 3 "const_int_operand" "")
10045 (const_string "alu_imm" )
10046 (const_string "alu_sreg"))
10047 (const_string "alu_imm")
10048 (const_string "multiple")
10049 (const_string "multiple")])]
8fa3ba89 10050)
8a18b90c 10051
10052(define_insn "*ifcompare_arith_arith"
10053 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 10054 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8a18b90c 10055 [(match_operand:SI 5 "s_register_operand" "r")
10056 (match_operand:SI 6 "arm_add_operand" "rIL")])
9c08d1fa 10057 (match_operator:SI 8 "shiftable_operator"
8a18b90c 10058 [(match_operand:SI 1 "s_register_operand" "r")
10059 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9c08d1fa 10060 (match_operator:SI 7 "shiftable_operator"
8a18b90c 10061 [(match_operand:SI 3 "s_register_operand" "r")
10062 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
bd5b4116 10063 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10064 "TARGET_ARM"
8a18b90c 10065 "#"
8fa3ba89 10066 [(set_attr "conds" "clob")
1b7da4ac 10067 (set_attr "length" "12")
10068 (set_attr "type" "multiple")]
8fa3ba89 10069)
9c08d1fa 10070
8a18b90c 10071(define_insn "*if_arith_arith"
10072 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 10073 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8a18b90c 10074 [(match_operand 8 "cc_register" "") (const_int 0)])
10075 (match_operator:SI 6 "shiftable_operator"
10076 [(match_operand:SI 1 "s_register_operand" "r")
10077 (match_operand:SI 2 "arm_rhs_operand" "rI")])
10078 (match_operator:SI 7 "shiftable_operator"
10079 [(match_operand:SI 3 "s_register_operand" "r")
10080 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
cffb2a26 10081 "TARGET_ARM"
8a18b90c 10082 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8fa3ba89 10083 [(set_attr "conds" "use")
1b7da4ac 10084 (set_attr "length" "8")
10085 (set_attr "type" "multiple")]
8fa3ba89 10086)
8a18b90c 10087
f7fbdd4a 10088(define_insn "*ifcompare_arith_move"
9c08d1fa 10089 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10090 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 10091 [(match_operand:SI 2 "s_register_operand" "r,r")
5565501b 10092 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
9c08d1fa 10093 (match_operator:SI 7 "shiftable_operator"
10094 [(match_operand:SI 4 "s_register_operand" "r,r")
10095 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
129a2fe4 10096 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 10097 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10098 "TARGET_ARM"
9c08d1fa 10099 "*
9c08d1fa 10100 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 10101 the conditional operator is LT or GE and we are comparing against zero and
674a8f0b 10102 everything is in registers then we can do this in two instructions. */
9c08d1fa 10103 if (operands[3] == const0_rtx
10104 && GET_CODE (operands[7]) != AND
0438d37f 10105 && REG_P (operands[5])
10106 && REG_P (operands[1])
9c08d1fa 10107 && REGNO (operands[1]) == REGNO (operands[4])
10108 && REGNO (operands[4]) != REGNO (operands[0]))
10109 {
10110 if (GET_CODE (operands[6]) == LT)
40dbec34 10111 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 10112 else if (GET_CODE (operands[6]) == GE)
40dbec34 10113 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 10114 }
0438d37f 10115 if (CONST_INT_P (operands[3])
9c08d1fa 10116 && !const_ok_for_arm (INTVAL (operands[3])))
e2348bcb 10117 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
9c08d1fa 10118 else
e2348bcb 10119 output_asm_insn (\"cmp\\t%2, %3\", operands);
40dbec34 10120 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
9c08d1fa 10121 if (which_alternative != 0)
129a2fe4 10122 return \"mov%D6\\t%0, %1\";
9c08d1fa 10123 return \"\";
215b30b3 10124 "
8fa3ba89 10125 [(set_attr "conds" "clob")
1b7da4ac 10126 (set_attr "length" "8,12")
10127 (set_attr "type" "multiple")]
8fa3ba89 10128)
9c08d1fa 10129
8a18b90c 10130(define_insn "*if_arith_move"
129a2fe4 10131 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10132 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8a18b90c 10133 [(match_operand 6 "cc_register" "") (const_int 0)])
10134 (match_operator:SI 5 "shiftable_operator"
129a2fe4 10135 [(match_operand:SI 2 "s_register_operand" "r,r")
10136 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
10137 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
cffb2a26 10138 "TARGET_ARM"
8a18b90c 10139 "@
10140 %I5%d4\\t%0, %2, %3
129a2fe4 10141 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8fa3ba89 10142 [(set_attr "conds" "use")
10143 (set_attr "length" "4,8")
282b4c75 10144 (set_attr_alternative "type"
10145 [(if_then_else (match_operand 3 "const_int_operand" "")
10146 (const_string "alu_shift_imm" )
10147 (const_string "alu_shift_reg"))
10148 (const_string "multiple")])]
8fa3ba89 10149)
8a18b90c 10150
f7fbdd4a 10151(define_insn "*ifcompare_move_arith"
9c08d1fa 10152 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10153 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 10154 [(match_operand:SI 4 "s_register_operand" "r,r")
5565501b 10155 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 10156 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9c08d1fa 10157 (match_operator:SI 7 "shiftable_operator"
10158 [(match_operand:SI 2 "s_register_operand" "r,r")
10159 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 10160 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10161 "TARGET_ARM"
9c08d1fa 10162 "*
9c08d1fa 10163 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 10164 the conditional operator is LT or GE and we are comparing against zero and
9c08d1fa 10165 everything is in registers then we can do this in two instructions */
10166 if (operands[5] == const0_rtx
10167 && GET_CODE (operands[7]) != AND
0438d37f 10168 && REG_P (operands[3])
10169 && REG_P (operands[1])
9c08d1fa 10170 && REGNO (operands[1]) == REGNO (operands[2])
10171 && REGNO (operands[2]) != REGNO (operands[0]))
10172 {
10173 if (GET_CODE (operands[6]) == GE)
40dbec34 10174 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 10175 else if (GET_CODE (operands[6]) == LT)
40dbec34 10176 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 10177 }
40dbec34 10178
0438d37f 10179 if (CONST_INT_P (operands[5])
9c08d1fa 10180 && !const_ok_for_arm (INTVAL (operands[5])))
e2348bcb 10181 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
9c08d1fa 10182 else
e2348bcb 10183 output_asm_insn (\"cmp\\t%4, %5\", operands);
40dbec34 10184
9c08d1fa 10185 if (which_alternative != 0)
129a2fe4 10186 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
40dbec34 10187 return \"%I7%D6\\t%0, %2, %3\";
215b30b3 10188 "
8fa3ba89 10189 [(set_attr "conds" "clob")
1b7da4ac 10190 (set_attr "length" "8,12")
10191 (set_attr "type" "multiple")]
8fa3ba89 10192)
9c08d1fa 10193
8a18b90c 10194(define_insn "*if_move_arith"
129a2fe4 10195 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 10196 (if_then_else:SI
8fa3ba89 10197 (match_operator 4 "arm_comparison_operator"
8a18b90c 10198 [(match_operand 6 "cc_register" "") (const_int 0)])
129a2fe4 10199 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 10200 (match_operator:SI 5 "shiftable_operator"
129a2fe4 10201 [(match_operand:SI 2 "s_register_operand" "r,r")
10202 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
cffb2a26 10203 "TARGET_ARM"
8a18b90c 10204 "@
10205 %I5%D4\\t%0, %2, %3
129a2fe4 10206 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
8fa3ba89 10207 [(set_attr "conds" "use")
10208 (set_attr "length" "4,8")
282b4c75 10209 (set_attr_alternative "type"
10210 [(if_then_else (match_operand 3 "const_int_operand" "")
10211 (const_string "alu_shift_imm" )
10212 (const_string "alu_shift_reg"))
10213 (const_string "multiple")])]
8fa3ba89 10214)
8a18b90c 10215
10216(define_insn "*ifcompare_move_not"
9c08d1fa 10217 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 10218 (if_then_else:SI
8fa3ba89 10219 (match_operator 5 "arm_comparison_operator"
8a18b90c 10220 [(match_operand:SI 3 "s_register_operand" "r,r")
10221 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10222 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
10223 (not:SI
10224 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 10225 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10226 "TARGET_ARM"
8a18b90c 10227 "#"
8fa3ba89 10228 [(set_attr "conds" "clob")
1b7da4ac 10229 (set_attr "length" "8,12")
10230 (set_attr "type" "multiple")]
8fa3ba89 10231)
9c08d1fa 10232
8a18b90c 10233(define_insn "*if_move_not"
10234 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10235 (if_then_else:SI
8fa3ba89 10236 (match_operator 4 "arm_comparison_operator"
8a18b90c 10237 [(match_operand 3 "cc_register" "") (const_int 0)])
10238 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
10239 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
cffb2a26 10240 "TARGET_ARM"
8a18b90c 10241 "@
10242 mvn%D4\\t%0, %2
10243 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
10244 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
8fa3ba89 10245 [(set_attr "conds" "use")
1aed5204 10246 (set_attr "type" "mvn_reg")
1b7da4ac 10247 (set_attr "length" "4,8,8")
10248 (set_attr "type" "mvn_reg,multiple,multiple")]
8fa3ba89 10249)
8a18b90c 10250
10251(define_insn "*ifcompare_not_move"
9c08d1fa 10252 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 10253 (if_then_else:SI
8fa3ba89 10254 (match_operator 5 "arm_comparison_operator"
8a18b90c 10255 [(match_operand:SI 3 "s_register_operand" "r,r")
10256 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10257 (not:SI
10258 (match_operand:SI 2 "s_register_operand" "r,r"))
10259 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 10260 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10261 "TARGET_ARM"
8a18b90c 10262 "#"
8fa3ba89 10263 [(set_attr "conds" "clob")
1b7da4ac 10264 (set_attr "length" "8,12")
10265 (set_attr "type" "multiple")]
8fa3ba89 10266)
9c08d1fa 10267
8a18b90c 10268(define_insn "*if_not_move"
10269 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10270 (if_then_else:SI
8fa3ba89 10271 (match_operator 4 "arm_comparison_operator"
8a18b90c 10272 [(match_operand 3 "cc_register" "") (const_int 0)])
10273 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
10274 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 10275 "TARGET_ARM"
8a18b90c 10276 "@
10277 mvn%d4\\t%0, %2
10278 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
10279 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
8fa3ba89 10280 [(set_attr "conds" "use")
1b7da4ac 10281 (set_attr "type" "mvn_reg,multiple,multiple")
8fa3ba89 10282 (set_attr "length" "4,8,8")]
10283)
8a18b90c 10284
10285(define_insn "*ifcompare_shift_move"
9c08d1fa 10286 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 10287 (if_then_else:SI
8fa3ba89 10288 (match_operator 6 "arm_comparison_operator"
8a18b90c 10289 [(match_operand:SI 4 "s_register_operand" "r,r")
10290 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
10291 (match_operator:SI 7 "shift_operator"
10292 [(match_operand:SI 2 "s_register_operand" "r,r")
10293 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
10294 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 10295 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10296 "TARGET_ARM"
9c08d1fa 10297 "#"
8fa3ba89 10298 [(set_attr "conds" "clob")
1b7da4ac 10299 (set_attr "length" "8,12")
10300 (set_attr "type" "multiple")]
8fa3ba89 10301)
9c08d1fa 10302
8a18b90c 10303(define_insn "*if_shift_move"
10304 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10305 (if_then_else:SI
8fa3ba89 10306 (match_operator 5 "arm_comparison_operator"
8a18b90c 10307 [(match_operand 6 "cc_register" "") (const_int 0)])
10308 (match_operator:SI 4 "shift_operator"
10309 [(match_operand:SI 2 "s_register_operand" "r,r,r")
10310 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
10311 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 10312 "TARGET_ARM"
5565501b 10313 "@
8a18b90c 10314 mov%d5\\t%0, %2%S4
10315 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
10316 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
8fa3ba89 10317 [(set_attr "conds" "use")
331beb1a 10318 (set_attr "shift" "2")
a2cd141b 10319 (set_attr "length" "4,8,8")
282b4c75 10320 (set_attr_alternative "type"
10321 [(if_then_else (match_operand 3 "const_int_operand" "")
10322 (const_string "mov_shift" )
10323 (const_string "mov_shift_reg"))
10324 (const_string "multiple")
10325 (const_string "multiple")])]
8fa3ba89 10326)
5565501b 10327
8a18b90c 10328(define_insn "*ifcompare_move_shift"
10329 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 10330 (if_then_else:SI
8fa3ba89 10331 (match_operator 6 "arm_comparison_operator"
8a18b90c 10332 [(match_operand:SI 4 "s_register_operand" "r,r")
10333 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
10334 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
5565501b 10335 (match_operator:SI 7 "shift_operator"
8a18b90c 10336 [(match_operand:SI 2 "s_register_operand" "r,r")
10337 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
bd5b4116 10338 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10339 "TARGET_ARM"
8a18b90c 10340 "#"
8fa3ba89 10341 [(set_attr "conds" "clob")
1b7da4ac 10342 (set_attr "length" "8,12")
10343 (set_attr "type" "multiple")]
8fa3ba89 10344)
5565501b 10345
8a18b90c 10346(define_insn "*if_move_shift"
10347 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 10348 (if_then_else:SI
8fa3ba89 10349 (match_operator 5 "arm_comparison_operator"
8a18b90c 10350 [(match_operand 6 "cc_register" "") (const_int 0)])
10351 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
10352 (match_operator:SI 4 "shift_operator"
10353 [(match_operand:SI 2 "s_register_operand" "r,r,r")
10354 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
cffb2a26 10355 "TARGET_ARM"
5565501b 10356 "@
8a18b90c 10357 mov%D5\\t%0, %2%S4
10358 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
10359 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
8fa3ba89 10360 [(set_attr "conds" "use")
331beb1a 10361 (set_attr "shift" "2")
a2cd141b 10362 (set_attr "length" "4,8,8")
282b4c75 10363 (set_attr_alternative "type"
10364 [(if_then_else (match_operand 3 "const_int_operand" "")
10365 (const_string "mov_shift" )
10366 (const_string "mov_shift_reg"))
10367 (const_string "multiple")
10368 (const_string "multiple")])]
8fa3ba89 10369)
9c08d1fa 10370
f7fbdd4a 10371(define_insn "*ifcompare_shift_shift"
8a18b90c 10372 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 10373 (if_then_else:SI
8fa3ba89 10374 (match_operator 7 "arm_comparison_operator"
8a18b90c 10375 [(match_operand:SI 5 "s_register_operand" "r")
10376 (match_operand:SI 6 "arm_add_operand" "rIL")])
5565501b 10377 (match_operator:SI 8 "shift_operator"
8a18b90c 10378 [(match_operand:SI 1 "s_register_operand" "r")
10379 (match_operand:SI 2 "arm_rhs_operand" "rM")])
5565501b 10380 (match_operator:SI 9 "shift_operator"
8a18b90c 10381 [(match_operand:SI 3 "s_register_operand" "r")
10382 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
bd5b4116 10383 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10384 "TARGET_ARM"
8a18b90c 10385 "#"
8fa3ba89 10386 [(set_attr "conds" "clob")
1b7da4ac 10387 (set_attr "length" "12")
10388 (set_attr "type" "multiple")]
8fa3ba89 10389)
9c08d1fa 10390
8a18b90c 10391(define_insn "*if_shift_shift"
10392 [(set (match_operand:SI 0 "s_register_operand" "=r")
10393 (if_then_else:SI
8fa3ba89 10394 (match_operator 5 "arm_comparison_operator"
8a18b90c 10395 [(match_operand 8 "cc_register" "") (const_int 0)])
10396 (match_operator:SI 6 "shift_operator"
10397 [(match_operand:SI 1 "s_register_operand" "r")
10398 (match_operand:SI 2 "arm_rhs_operand" "rM")])
10399 (match_operator:SI 7 "shift_operator"
10400 [(match_operand:SI 3 "s_register_operand" "r")
10401 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
cffb2a26 10402 "TARGET_ARM"
8a18b90c 10403 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
8fa3ba89 10404 [(set_attr "conds" "use")
331beb1a 10405 (set_attr "shift" "1")
a2cd141b 10406 (set_attr "length" "8")
10407 (set (attr "type") (if_then_else
10408 (and (match_operand 2 "const_int_operand" "")
10409 (match_operand 4 "const_int_operand" ""))
1aed5204 10410 (const_string "mov_shift")
10411 (const_string "mov_shift_reg")))]
8fa3ba89 10412)
8a18b90c 10413
f7fbdd4a 10414(define_insn "*ifcompare_not_arith"
8a18b90c 10415 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 10416 (if_then_else:SI
8fa3ba89 10417 (match_operator 6 "arm_comparison_operator"
8a18b90c 10418 [(match_operand:SI 4 "s_register_operand" "r")
10419 (match_operand:SI 5 "arm_add_operand" "rIL")])
10420 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5565501b 10421 (match_operator:SI 7 "shiftable_operator"
8a18b90c 10422 [(match_operand:SI 2 "s_register_operand" "r")
10423 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
bd5b4116 10424 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10425 "TARGET_ARM"
8a18b90c 10426 "#"
8fa3ba89 10427 [(set_attr "conds" "clob")
1b7da4ac 10428 (set_attr "length" "12")
10429 (set_attr "type" "multiple")]
8fa3ba89 10430)
9c08d1fa 10431
8a18b90c 10432(define_insn "*if_not_arith"
10433 [(set (match_operand:SI 0 "s_register_operand" "=r")
10434 (if_then_else:SI
8fa3ba89 10435 (match_operator 5 "arm_comparison_operator"
8a18b90c 10436 [(match_operand 4 "cc_register" "") (const_int 0)])
10437 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
10438 (match_operator:SI 6 "shiftable_operator"
10439 [(match_operand:SI 2 "s_register_operand" "r")
10440 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
cffb2a26 10441 "TARGET_ARM"
8a18b90c 10442 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
8fa3ba89 10443 [(set_attr "conds" "use")
1aed5204 10444 (set_attr "type" "mvn_reg")
8fa3ba89 10445 (set_attr "length" "8")]
10446)
8a18b90c 10447
10448(define_insn "*ifcompare_arith_not"
10449 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 10450 (if_then_else:SI
8fa3ba89 10451 (match_operator 6 "arm_comparison_operator"
8a18b90c 10452 [(match_operand:SI 4 "s_register_operand" "r")
10453 (match_operand:SI 5 "arm_add_operand" "rIL")])
5565501b 10454 (match_operator:SI 7 "shiftable_operator"
8a18b90c 10455 [(match_operand:SI 2 "s_register_operand" "r")
10456 (match_operand:SI 3 "arm_rhs_operand" "rI")])
10457 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
bd5b4116 10458 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10459 "TARGET_ARM"
8a18b90c 10460 "#"
8fa3ba89 10461 [(set_attr "conds" "clob")
1b7da4ac 10462 (set_attr "length" "12")
10463 (set_attr "type" "multiple")]
8fa3ba89 10464)
9c08d1fa 10465
8a18b90c 10466(define_insn "*if_arith_not"
10467 [(set (match_operand:SI 0 "s_register_operand" "=r")
10468 (if_then_else:SI
8fa3ba89 10469 (match_operator 5 "arm_comparison_operator"
8a18b90c 10470 [(match_operand 4 "cc_register" "") (const_int 0)])
10471 (match_operator:SI 6 "shiftable_operator"
10472 [(match_operand:SI 2 "s_register_operand" "r")
10473 (match_operand:SI 3 "arm_rhs_operand" "rI")])
10474 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
cffb2a26 10475 "TARGET_ARM"
8a18b90c 10476 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
8fa3ba89 10477 [(set_attr "conds" "use")
1b7da4ac 10478 (set_attr "type" "multiple")
8fa3ba89 10479 (set_attr "length" "8")]
10480)
8a18b90c 10481
f7fbdd4a 10482(define_insn "*ifcompare_neg_move"
8a18b90c 10483 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 10484 (if_then_else:SI
8fa3ba89 10485 (match_operator 5 "arm_comparison_operator"
8a18b90c 10486 [(match_operand:SI 3 "s_register_operand" "r,r")
10487 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10488 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
10489 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 10490 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10491 "TARGET_ARM"
8a18b90c 10492 "#"
8fa3ba89 10493 [(set_attr "conds" "clob")
1b7da4ac 10494 (set_attr "length" "8,12")
10495 (set_attr "type" "multiple")]
8fa3ba89 10496)
8a18b90c 10497
530bb693 10498(define_insn_and_split "*if_neg_move"
10499 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
8a18b90c 10500 (if_then_else:SI
8fa3ba89 10501 (match_operator 4 "arm_comparison_operator"
8a18b90c 10502 [(match_operand 3 "cc_register" "") (const_int 0)])
530bb693 10503 (neg:SI (match_operand:SI 2 "s_register_operand" "l,r"))
10504 (match_operand:SI 1 "s_register_operand" "0,0")))]
10505 "TARGET_32BIT"
10506 "#"
10507 "&& reload_completed"
10508 [(cond_exec (match_op_dup 4 [(match_dup 3) (const_int 0)])
10509 (set (match_dup 0) (neg:SI (match_dup 2))))]
10510 ""
8fa3ba89 10511 [(set_attr "conds" "use")
530bb693 10512 (set_attr "length" "4")
10513 (set_attr "arch" "t2,32")
10514 (set_attr "enabled_for_depr_it" "yes,no")
10515 (set_attr "type" "logic_shift_imm")]
8fa3ba89 10516)
9c08d1fa 10517
f7fbdd4a 10518(define_insn "*ifcompare_move_neg"
8a18b90c 10519 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 10520 (if_then_else:SI
8fa3ba89 10521 (match_operator 5 "arm_comparison_operator"
8a18b90c 10522 [(match_operand:SI 3 "s_register_operand" "r,r")
10523 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10524 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
10525 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 10526 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10527 "TARGET_ARM"
8a18b90c 10528 "#"
8fa3ba89 10529 [(set_attr "conds" "clob")
1b7da4ac 10530 (set_attr "length" "8,12")
10531 (set_attr "type" "multiple")]
8fa3ba89 10532)
8a18b90c 10533
530bb693 10534(define_insn_and_split "*if_move_neg"
10535 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
8a18b90c 10536 (if_then_else:SI
8fa3ba89 10537 (match_operator 4 "arm_comparison_operator"
8a18b90c 10538 [(match_operand 3 "cc_register" "") (const_int 0)])
530bb693 10539 (match_operand:SI 1 "s_register_operand" "0,0")
10540 (neg:SI (match_operand:SI 2 "s_register_operand" "l,r"))))]
10541 "TARGET_32BIT"
10542 "#"
10543 "&& reload_completed"
10544 [(cond_exec (match_dup 5)
10545 (set (match_dup 0) (neg:SI (match_dup 2))))]
10546 {
10547 machine_mode mode = GET_MODE (operands[3]);
10548 rtx_code rc = GET_CODE (operands[4]);
10549
10550 if (mode == CCFPmode || mode == CCFPEmode)
10551 rc = reverse_condition_maybe_unordered (rc);
10552 else
10553 rc = reverse_condition (rc);
10554
10555 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[3], const0_rtx);
10556 }
0d66636f 10557 [(set_attr "conds" "use")
530bb693 10558 (set_attr "length" "4")
10559 (set_attr "arch" "t2,32")
10560 (set_attr "enabled_for_depr_it" "yes,no")
10561 (set_attr "type" "logic_shift_imm")]
0d66636f 10562)
9c08d1fa 10563
f7fbdd4a 10564(define_insn "*arith_adjacentmem"
9c08d1fa 10565 [(set (match_operand:SI 0 "s_register_operand" "=r")
10566 (match_operator:SI 1 "shiftable_operator"
10567 [(match_operand:SI 2 "memory_operand" "m")
10568 (match_operand:SI 3 "memory_operand" "m")]))
10569 (clobber (match_scratch:SI 4 "=r"))]
cffb2a26 10570 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9c08d1fa 10571 "*
215b30b3 10572 {
10573 rtx ldm[3];
10574 rtx arith[4];
94dee231 10575 rtx base_reg;
10576 HOST_WIDE_INT val1 = 0, val2 = 0;
9c08d1fa 10577
215b30b3 10578 if (REGNO (operands[0]) > REGNO (operands[4]))
10579 {
10580 ldm[1] = operands[4];
10581 ldm[2] = operands[0];
10582 }
10583 else
10584 {
10585 ldm[1] = operands[0];
10586 ldm[2] = operands[4];
10587 }
94dee231 10588
10589 base_reg = XEXP (operands[2], 0);
10590
10591 if (!REG_P (base_reg))
10592 {
10593 val1 = INTVAL (XEXP (base_reg, 1));
10594 base_reg = XEXP (base_reg, 0);
10595 }
10596
10597 if (!REG_P (XEXP (operands[3], 0)))
215b30b3 10598 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
94dee231 10599
215b30b3 10600 arith[0] = operands[0];
10601 arith[3] = operands[1];
94dee231 10602
215b30b3 10603 if (val1 < val2)
10604 {
10605 arith[1] = ldm[1];
10606 arith[2] = ldm[2];
10607 }
10608 else
10609 {
10610 arith[1] = ldm[2];
10611 arith[2] = ldm[1];
10612 }
94dee231 10613
10614 ldm[0] = base_reg;
10615 if (val1 !=0 && val2 != 0)
215b30b3 10616 {
cdb1295a 10617 rtx ops[3];
10618
94dee231 10619 if (val1 == 4 || val2 == 4)
10620 /* Other val must be 8, since we know they are adjacent and neither
10621 is zero. */
3ef90e77 10622 output_asm_insn (\"ldmib%?\\t%0, {%1, %2}\", ldm);
cdb1295a 10623 else if (const_ok_for_arm (val1) || const_ok_for_arm (-val1))
94dee231 10624 {
94dee231 10625 ldm[0] = ops[0] = operands[4];
10626 ops[1] = base_reg;
10627 ops[2] = GEN_INT (val1);
10628 output_add_immediate (ops);
10629 if (val1 < val2)
3ef90e77 10630 output_asm_insn (\"ldmia%?\\t%0, {%1, %2}\", ldm);
94dee231 10631 else
3ef90e77 10632 output_asm_insn (\"ldmda%?\\t%0, {%1, %2}\", ldm);
94dee231 10633 }
cdb1295a 10634 else
10635 {
10636 /* Offset is out of range for a single add, so use two ldr. */
10637 ops[0] = ldm[1];
10638 ops[1] = base_reg;
10639 ops[2] = GEN_INT (val1);
10640 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10641 ops[0] = ldm[2];
10642 ops[2] = GEN_INT (val2);
10643 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10644 }
215b30b3 10645 }
94dee231 10646 else if (val1 != 0)
215b30b3 10647 {
215b30b3 10648 if (val1 < val2)
3ef90e77 10649 output_asm_insn (\"ldmda%?\\t%0, {%1, %2}\", ldm);
215b30b3 10650 else
3ef90e77 10651 output_asm_insn (\"ldmia%?\\t%0, {%1, %2}\", ldm);
215b30b3 10652 }
10653 else
10654 {
215b30b3 10655 if (val1 < val2)
3ef90e77 10656 output_asm_insn (\"ldmia%?\\t%0, {%1, %2}\", ldm);
215b30b3 10657 else
3ef90e77 10658 output_asm_insn (\"ldmda%?\\t%0, {%1, %2}\", ldm);
215b30b3 10659 }
10660 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
10661 return \"\";
10662 }"
10663 [(set_attr "length" "12")
10664 (set_attr "predicable" "yes")
a2cd141b 10665 (set_attr "type" "load1")]
215b30b3 10666)
9c08d1fa 10667
9c08d1fa 10668; This pattern is never tried by combine, so do it as a peephole
10669
a0f94409 10670(define_peephole2
372575c7 10671 [(set (match_operand:SI 0 "arm_general_register_operand" "")
10672 (match_operand:SI 1 "arm_general_register_operand" ""))
bd5b4116 10673 (set (reg:CC CC_REGNUM)
aea4c774 10674 (compare:CC (match_dup 1) (const_int 0)))]
372575c7 10675 "TARGET_ARM"
a0f94409 10676 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
10677 (set (match_dup 0) (match_dup 1))])]
10678 ""
0d66636f 10679)
9c08d1fa 10680
9c08d1fa 10681(define_split
10682 [(set (match_operand:SI 0 "s_register_operand" "")
10683 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
10684 (const_int 0))
8fa3ba89 10685 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9c08d1fa 10686 [(match_operand:SI 3 "s_register_operand" "")
10687 (match_operand:SI 4 "arm_rhs_operand" "")]))))
10688 (clobber (match_operand:SI 5 "s_register_operand" ""))]
cffb2a26 10689 "TARGET_ARM"
9c08d1fa 10690 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
10691 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
10692 (match_dup 5)))]
215b30b3 10693 ""
10694)
9c08d1fa 10695
aea4c774 10696;; This split can be used because CC_Z mode implies that the following
10697;; branch will be an equality, or an unsigned inequality, so the sign
10698;; extension is not needed.
9c08d1fa 10699
aea4c774 10700(define_split
bd5b4116 10701 [(set (reg:CC_Z CC_REGNUM)
aea4c774 10702 (compare:CC_Z
10703 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9c08d1fa 10704 (const_int 24))
aea4c774 10705 (match_operand 1 "const_int_operand" "")))
10706 (clobber (match_scratch:SI 2 ""))]
cffb2a26 10707 "TARGET_ARM
8c4e8755 10708 && ((UINTVAL (operands[1]))
10709 == ((UINTVAL (operands[1])) >> 24) << 24)"
aea4c774 10710 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
bd5b4116 10711 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
aea4c774 10712 "
9c08d1fa 10713 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
215b30b3 10714 "
10715)
25f905c2 10716;; ??? Check the patterns above for Thumb-2 usefulness
9c08d1fa 10717
87b22bf7 10718(define_expand "prologue"
10719 [(clobber (const_int 0))]
cffb2a26 10720 "TARGET_EITHER"
25f905c2 10721 "if (TARGET_32BIT)
cffb2a26 10722 arm_expand_prologue ();
10723 else
25f905c2 10724 thumb1_expand_prologue ();
87b22bf7 10725 DONE;
cffb2a26 10726 "
10727)
87b22bf7 10728
56d27660 10729(define_expand "epilogue"
4c44712e 10730 [(clobber (const_int 0))]
cffb2a26 10731 "TARGET_EITHER"
56d27660 10732 "
18d50ae6 10733 if (crtl->calls_eh_return)
fb94f18b 10734 emit_insn (gen_force_register_use (gen_rtx_REG (Pmode, 2)));
25f905c2 10735 if (TARGET_THUMB1)
c3635784 10736 {
10737 thumb1_expand_epilogue ();
10738 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
10739 gen_rtvec (1, ret_rtx), VUNSPEC_EPILOGUE));
10740 }
10741 else if (HAVE_return)
10742 {
10743 /* HAVE_return is testing for USE_RETURN_INSN (FALSE). Hence,
10744 no need for explicit testing again. */
10745 emit_jump_insn (gen_return ());
10746 }
10747 else if (TARGET_32BIT)
10748 {
10749 arm_expand_epilogue (true);
10750 }
cffb2a26 10751 DONE;
10752 "
10753)
56d27660 10754
ef5651d0 10755;; Note - although unspec_volatile's USE all hard registers,
10756;; USEs are ignored after relaod has completed. Thus we need
10757;; to add an unspec of the link register to ensure that flow
10758;; does not think that it is unused by the sibcall branch that
10759;; will replace the standard function epilogue.
c3635784 10760(define_expand "sibcall_epilogue"
fb94f18b 10761 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_REGISTER_USE)
c3635784 10762 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
10763 "TARGET_32BIT"
10764 "
10765 arm_expand_epilogue (false);
10766 DONE;
10767 "
1c494086 10768)
10769
cffb2a26 10770(define_expand "eh_epilogue"
7db9af5d 10771 [(use (match_operand:SI 0 "register_operand" ""))
10772 (use (match_operand:SI 1 "register_operand" ""))
10773 (use (match_operand:SI 2 "register_operand" ""))]
cffb2a26 10774 "TARGET_EITHER"
10775 "
215b30b3 10776 {
10777 cfun->machine->eh_epilogue_sp_ofs = operands[1];
0438d37f 10778 if (!REG_P (operands[2]) || REGNO (operands[2]) != 2)
215b30b3 10779 {
10780 rtx ra = gen_rtx_REG (Pmode, 2);
10781
10782 emit_move_insn (ra, operands[2]);
10783 operands[2] = ra;
10784 }
5cf3595a 10785 /* This is a hack -- we may have crystalized the function type too
10786 early. */
10787 cfun->machine->func_type = 0;
215b30b3 10788 }"
10789)
56d27660 10790
9c08d1fa 10791;; This split is only used during output to reduce the number of patterns
10792;; that need assembler instructions adding to them. We allowed the setting
10793;; of the conditions to be implicit during rtl generation so that
10794;; the conditional compare patterns would work. However this conflicts to
8a18b90c 10795;; some extent with the conditional data operations, so we have to split them
9c08d1fa 10796;; up again here.
10797
25f905c2 10798;; ??? Need to audit these splitters for Thumb-2. Why isn't normal
10799;; conditional execution sufficient?
10800
9c08d1fa 10801(define_split
10802 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 10803 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10804 [(match_operand 2 "" "") (match_operand 3 "" "")])
10805 (match_dup 0)
10806 (match_operand 4 "" "")))
bd5b4116 10807 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10808 "TARGET_ARM && reload_completed"
8fa3ba89 10809 [(set (match_dup 5) (match_dup 6))
10810 (cond_exec (match_dup 7)
10811 (set (match_dup 0) (match_dup 4)))]
10812 "
10813 {
3754d046 10814 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8fa3ba89 10815 operands[2], operands[3]);
10816 enum rtx_code rc = GET_CODE (operands[1]);
10817
bd5b4116 10818 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10819 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10820 if (mode == CCFPmode || mode == CCFPEmode)
10821 rc = reverse_condition_maybe_unordered (rc);
10822 else
10823 rc = reverse_condition (rc);
10824
10825 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
10826 }"
10827)
10828
10829(define_split
10830 [(set (match_operand:SI 0 "s_register_operand" "")
10831 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10832 [(match_operand 2 "" "") (match_operand 3 "" "")])
10833 (match_operand 4 "" "")
10834 (match_dup 0)))
bd5b4116 10835 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10836 "TARGET_ARM && reload_completed"
8fa3ba89 10837 [(set (match_dup 5) (match_dup 6))
10838 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
10839 (set (match_dup 0) (match_dup 4)))]
10840 "
10841 {
3754d046 10842 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8fa3ba89 10843 operands[2], operands[3]);
10844
bd5b4116 10845 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10846 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10847 }"
10848)
10849
10850(define_split
10851 [(set (match_operand:SI 0 "s_register_operand" "")
10852 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9c08d1fa 10853 [(match_operand 2 "" "") (match_operand 3 "" "")])
10854 (match_operand 4 "" "")
10855 (match_operand 5 "" "")))
bd5b4116 10856 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10857 "TARGET_ARM && reload_completed"
8fa3ba89 10858 [(set (match_dup 6) (match_dup 7))
10859 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10860 (set (match_dup 0) (match_dup 4)))
10861 (cond_exec (match_dup 8)
10862 (set (match_dup 0) (match_dup 5)))]
10863 "
10864 {
3754d046 10865 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8fa3ba89 10866 operands[2], operands[3]);
10867 enum rtx_code rc = GET_CODE (operands[1]);
10868
bd5b4116 10869 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10870 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10871 if (mode == CCFPmode || mode == CCFPEmode)
10872 rc = reverse_condition_maybe_unordered (rc);
10873 else
10874 rc = reverse_condition (rc);
10875
10876 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10877 }"
10878)
10879
cffb2a26 10880(define_split
10881 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 10882 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
cffb2a26 10883 [(match_operand:SI 2 "s_register_operand" "")
10884 (match_operand:SI 3 "arm_add_operand" "")])
10885 (match_operand:SI 4 "arm_rhs_operand" "")
10886 (not:SI
10887 (match_operand:SI 5 "s_register_operand" ""))))
bd5b4116 10888 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10889 "TARGET_ARM && reload_completed"
cffb2a26 10890 [(set (match_dup 6) (match_dup 7))
f6c53574 10891 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10892 (set (match_dup 0) (match_dup 4)))
10893 (cond_exec (match_dup 8)
10894 (set (match_dup 0) (not:SI (match_dup 5))))]
cffb2a26 10895 "
215b30b3 10896 {
3754d046 10897 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
215b30b3 10898 operands[2], operands[3]);
f6c53574 10899 enum rtx_code rc = GET_CODE (operands[1]);
cffb2a26 10900
bd5b4116 10901 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
1a83b3ff 10902 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
f6c53574 10903 if (mode == CCFPmode || mode == CCFPEmode)
10904 rc = reverse_condition_maybe_unordered (rc);
10905 else
10906 rc = reverse_condition (rc);
10907
10908 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
215b30b3 10909 }"
10910)
cffb2a26 10911
10912(define_insn "*cond_move_not"
10913 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10914 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
cffb2a26 10915 [(match_operand 3 "cc_register" "") (const_int 0)])
10916 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10917 (not:SI
10918 (match_operand:SI 2 "s_register_operand" "r,r"))))]
10919 "TARGET_ARM"
10920 "@
10921 mvn%D4\\t%0, %2
10922 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
0d66636f 10923 [(set_attr "conds" "use")
1b7da4ac 10924 (set_attr "type" "mvn_reg,multiple")
0d66636f 10925 (set_attr "length" "4,8")]
10926)
cffb2a26 10927
9c08d1fa 10928;; The next two patterns occur when an AND operation is followed by a
10929;; scc insn sequence
10930
f7fbdd4a 10931(define_insn "*sign_extract_onebit"
9c08d1fa 10932 [(set (match_operand:SI 0 "s_register_operand" "=r")
10933 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10934 (const_int 1)
ed750274 10935 (match_operand:SI 2 "const_int_operand" "n")))
10936 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10937 "TARGET_ARM"
9c08d1fa 10938 "*
0d66636f 10939 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10940 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
10941 return \"mvnne\\t%0, #0\";
10942 "
10943 [(set_attr "conds" "clob")
1b7da4ac 10944 (set_attr "length" "8")
10945 (set_attr "type" "multiple")]
0d66636f 10946)
9c08d1fa 10947
f7fbdd4a 10948(define_insn "*not_signextract_onebit"
9c08d1fa 10949 [(set (match_operand:SI 0 "s_register_operand" "=r")
10950 (not:SI
10951 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10952 (const_int 1)
ed750274 10953 (match_operand:SI 2 "const_int_operand" "n"))))
10954 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10955 "TARGET_ARM"
9c08d1fa 10956 "*
0d66636f 10957 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10958 output_asm_insn (\"tst\\t%1, %2\", operands);
10959 output_asm_insn (\"mvneq\\t%0, #0\", operands);
10960 return \"movne\\t%0, #0\";
10961 "
10962 [(set_attr "conds" "clob")
1b7da4ac 10963 (set_attr "length" "12")
10964 (set_attr "type" "multiple")]
0d66636f 10965)
25f905c2 10966;; ??? The above patterns need auditing for Thumb-2
87b22bf7 10967
0d66636f 10968;; Push multiple registers to the stack. Registers are in parallel (use ...)
10969;; expressions. For simplicity, the first register is also in the unspec
10970;; part.
08508cbf 10971;; To avoid the usage of GNU extension, the length attribute is computed
10972;; in a C function arm_attr_length_push_multi.
f7fbdd4a 10973(define_insn "*push_multi"
87b22bf7 10974 [(match_parallel 2 "multi_register_push"
7571d3f7 10975 [(set (match_operand:BLK 0 "push_mult_memory_operand" "")
3cc80a30 10976 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "")]
e1159bbe 10977 UNSPEC_PUSH_MULT))])]
7571d3f7 10978 ""
87b22bf7 10979 "*
215b30b3 10980 {
10981 int num_saves = XVECLEN (operands[2], 0);
ed593f11 10982
215b30b3 10983 /* For the StrongARM at least it is faster to
25f905c2 10984 use STR to store only a single register.
542d5028 10985 In Thumb mode always use push, and the assembler will pick
10986 something appropriate. */
25f905c2 10987 if (num_saves == 1 && TARGET_ARM)
61309563 10988 output_asm_insn (\"str%?\\t%1, [%m0, #-4]!\", operands);
215b30b3 10989 else
10990 {
10991 int i;
10992 char pattern[100];
ed593f11 10993
3ef90e77 10994 if (TARGET_32BIT)
61309563 10995 strcpy (pattern, \"push%?\\t{%1\");
25f905c2 10996 else
10997 strcpy (pattern, \"push\\t{%1\");
215b30b3 10998
6079f055 10999 for (i = 1; i < num_saves; i++)
215b30b3 11000 {
11001 strcat (pattern, \", %|\");
11002 strcat (pattern,
11003 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
11004 }
11005
11006 strcat (pattern, \"}\");
11007 output_asm_insn (pattern, operands);
11008 }
11009
11010 return \"\";
11011 }"
a6864a24 11012 [(set_attr "type" "store4")
11013 (set (attr "length")
08508cbf 11014 (symbol_ref "arm_attr_length_push_multi (operands[2], operands[1])"))]
215b30b3 11015)
f7fbdd4a 11016
4c58c898 11017(define_insn "stack_tie"
11018 [(set (mem:BLK (scratch))
aaa37ad6 11019 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "rk")
11020 (match_operand:SI 1 "s_register_operand" "rk")]
4c58c898 11021 UNSPEC_PRLG_STK))]
11022 ""
11023 ""
1b7da4ac 11024 [(set_attr "length" "0")
11025 (set_attr "type" "block")]
4c58c898 11026)
11027
426be8c5 11028;; Pop (as used in epilogue RTL)
11029;;
11030(define_insn "*load_multiple_with_writeback"
11031 [(match_parallel 0 "load_multiple_operation"
11032 [(set (match_operand:SI 1 "s_register_operand" "+rk")
11033 (plus:SI (match_dup 1)
809003b3 11034 (match_operand:SI 2 "const_int_I_operand" "I")))
426be8c5 11035 (set (match_operand:SI 3 "s_register_operand" "=rk")
11036 (mem:SI (match_dup 1)))
11037 ])]
11038 "TARGET_32BIT && (reload_in_progress || reload_completed)"
11039 "*
11040 {
11041 arm_output_multireg_pop (operands, /*return_pc=*/false,
11042 /*cond=*/const_true_rtx,
11043 /*reverse=*/false,
11044 /*update=*/true);
11045 return \"\";
11046 }
11047 "
11048 [(set_attr "type" "load4")
5431c9c9 11049 (set_attr "predicable" "yes")
11050 (set (attr "length")
11051 (symbol_ref "arm_attr_length_pop_multi (operands,
11052 /*return_pc=*/false,
11053 /*write_back_p=*/true)"))]
426be8c5 11054)
11055
11056;; Pop with return (as used in epilogue RTL)
11057;;
11058;; This instruction is generated when the registers are popped at the end of
11059;; epilogue. Here, instead of popping the value into LR and then generating
11060;; jump to LR, value is popped into PC directly. Hence, the pattern is combined
11061;; with (return).
11062(define_insn "*pop_multiple_with_writeback_and_return"
11063 [(match_parallel 0 "pop_multiple_return"
11064 [(return)
11065 (set (match_operand:SI 1 "s_register_operand" "+rk")
11066 (plus:SI (match_dup 1)
809003b3 11067 (match_operand:SI 2 "const_int_I_operand" "I")))
426be8c5 11068 (set (match_operand:SI 3 "s_register_operand" "=rk")
11069 (mem:SI (match_dup 1)))
11070 ])]
11071 "TARGET_32BIT && (reload_in_progress || reload_completed)"
11072 "*
11073 {
11074 arm_output_multireg_pop (operands, /*return_pc=*/true,
11075 /*cond=*/const_true_rtx,
11076 /*reverse=*/false,
11077 /*update=*/true);
11078 return \"\";
11079 }
11080 "
11081 [(set_attr "type" "load4")
5431c9c9 11082 (set_attr "predicable" "yes")
11083 (set (attr "length")
11084 (symbol_ref "arm_attr_length_pop_multi (operands, /*return_pc=*/true,
11085 /*write_back_p=*/true)"))]
426be8c5 11086)
11087
11088(define_insn "*pop_multiple_with_return"
11089 [(match_parallel 0 "pop_multiple_return"
11090 [(return)
11091 (set (match_operand:SI 2 "s_register_operand" "=rk")
11092 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
11093 ])]
11094 "TARGET_32BIT && (reload_in_progress || reload_completed)"
11095 "*
11096 {
11097 arm_output_multireg_pop (operands, /*return_pc=*/true,
11098 /*cond=*/const_true_rtx,
11099 /*reverse=*/false,
11100 /*update=*/false);
11101 return \"\";
11102 }
11103 "
11104 [(set_attr "type" "load4")
5431c9c9 11105 (set_attr "predicable" "yes")
11106 (set (attr "length")
11107 (symbol_ref "arm_attr_length_pop_multi (operands, /*return_pc=*/true,
11108 /*write_back_p=*/false)"))]
426be8c5 11109)
11110
11111;; Load into PC and return
11112(define_insn "*ldr_with_return"
11113 [(return)
11114 (set (reg:SI PC_REGNUM)
11115 (mem:SI (post_inc:SI (match_operand:SI 0 "s_register_operand" "+rk"))))]
11116 "TARGET_32BIT && (reload_in_progress || reload_completed)"
11117 "ldr%?\t%|pc, [%0], #4"
11118 [(set_attr "type" "load1")
11119 (set_attr "predicable" "yes")]
11120)
1a0b0f12 11121;; Pop for floating point registers (as used in epilogue RTL)
11122(define_insn "*vfp_pop_multiple_with_writeback"
11123 [(match_parallel 0 "pop_multiple_fp"
11124 [(set (match_operand:SI 1 "s_register_operand" "+rk")
11125 (plus:SI (match_dup 1)
809003b3 11126 (match_operand:SI 2 "const_int_I_operand" "I")))
2f2163a4 11127 (set (match_operand:DF 3 "vfp_hard_register_operand" "")
1a0b0f12 11128 (mem:DF (match_dup 1)))])]
d7216193 11129 "TARGET_32BIT && TARGET_HARD_FLOAT"
1a0b0f12 11130 "*
11131 {
11132 int num_regs = XVECLEN (operands[0], 0);
11133 char pattern[100];
11134 rtx op_list[2];
b34d8dac 11135 strcpy (pattern, \"vldm\\t\");
1a0b0f12 11136 strcat (pattern, reg_names[REGNO (SET_DEST (XVECEXP (operands[0], 0, 0)))]);
11137 strcat (pattern, \"!, {\");
11138 op_list[0] = XEXP (XVECEXP (operands[0], 0, 1), 0);
11139 strcat (pattern, \"%P0\");
11140 if ((num_regs - 1) > 1)
11141 {
11142 strcat (pattern, \"-%P1\");
11143 op_list [1] = XEXP (XVECEXP (operands[0], 0, num_regs - 1), 0);
11144 }
11145
11146 strcat (pattern, \"}\");
11147 output_asm_insn (pattern, op_list);
11148 return \"\";
11149 }
11150 "
11151 [(set_attr "type" "load4")
11152 (set_attr "conds" "unconditional")
11153 (set_attr "predicable" "no")]
11154)
11155
f7fbdd4a 11156;; Special patterns for dealing with the constant pool
11157
cffb2a26 11158(define_insn "align_4"
e1159bbe 11159 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
cffb2a26 11160 "TARGET_EITHER"
f7fbdd4a 11161 "*
cffb2a26 11162 assemble_align (32);
f7fbdd4a 11163 return \"\";
cffb2a26 11164 "
1b7da4ac 11165 [(set_attr "type" "no_insn")]
cffb2a26 11166)
f7fbdd4a 11167
755eb2b4 11168(define_insn "align_8"
11169 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
f9273c43 11170 "TARGET_EITHER"
755eb2b4 11171 "*
11172 assemble_align (64);
11173 return \"\";
11174 "
1b7da4ac 11175 [(set_attr "type" "no_insn")]
755eb2b4 11176)
11177
cffb2a26 11178(define_insn "consttable_end"
e1159bbe 11179 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
cffb2a26 11180 "TARGET_EITHER"
f7fbdd4a 11181 "*
cffb2a26 11182 making_const_table = FALSE;
f7fbdd4a 11183 return \"\";
cffb2a26 11184 "
1b7da4ac 11185 [(set_attr "type" "no_insn")]
cffb2a26 11186)
f7fbdd4a 11187
0e207eb8 11188(define_insn "consttable_1"
11189 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
11190 "TARGET_EITHER"
11191 "*
11192 making_const_table = TRUE;
11193 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
11194 assemble_zeros (3);
11195 return \"\";
11196 "
11197 [(set_attr "length" "4")
11198 (set_attr "type" "no_insn")]
11199)
11200
11201(define_insn "consttable_2"
11202 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
11203 "TARGET_EITHER"
11204 "*
11205 {
11206 rtx x = operands[0];
11207 making_const_table = TRUE;
11208 switch (GET_MODE_CLASS (GET_MODE (x)))
11209 {
11210 case MODE_FLOAT:
11211 arm_emit_fp16_const (x);
11212 break;
11213 default:
11214 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
11215 assemble_zeros (2);
11216 break;
11217 }
11218 return \"\";
11219 }"
11220 [(set_attr "length" "4")
11221 (set_attr "type" "no_insn")]
11222)
11223
cffb2a26 11224(define_insn "consttable_4"
e1159bbe 11225 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
cffb2a26 11226 "TARGET_EITHER"
11227 "*
11228 {
9b8516be 11229 rtx x = operands[0];
cffb2a26 11230 making_const_table = TRUE;
9b8516be 11231 switch (GET_MODE_CLASS (GET_MODE (x)))
cffb2a26 11232 {
11233 case MODE_FLOAT:
945f7b03 11234 assemble_real (*CONST_DOUBLE_REAL_VALUE (x), GET_MODE (x),
11235 BITS_PER_WORD);
11236 break;
cffb2a26 11237 default:
7b04c5d5 11238 /* XXX: Sometimes gcc does something really dumb and ends up with
11239 a HIGH in a constant pool entry, usually because it's trying to
11240 load into a VFP register. We know this will always be used in
11241 combination with a LO_SUM which ignores the high bits, so just
11242 strip off the HIGH. */
11243 if (GET_CODE (x) == HIGH)
11244 x = XEXP (x, 0);
9b8516be 11245 assemble_integer (x, 4, BITS_PER_WORD, 1);
11246 mark_symbol_refs_as_used (x);
cffb2a26 11247 break;
11248 }
11249 return \"\";
11250 }"
1b7da4ac 11251 [(set_attr "length" "4")
11252 (set_attr "type" "no_insn")]
cffb2a26 11253)
11254
11255(define_insn "consttable_8"
e1159bbe 11256 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
cffb2a26 11257 "TARGET_EITHER"
11258 "*
11259 {
11260 making_const_table = TRUE;
11261 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
11262 {
945f7b03 11263 case MODE_FLOAT:
11264 assemble_real (*CONST_DOUBLE_REAL_VALUE (operands[0]),
11265 GET_MODE (operands[0]), BITS_PER_WORD);
11266 break;
cffb2a26 11267 default:
09d688ff 11268 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
cffb2a26 11269 break;
11270 }
11271 return \"\";
11272 }"
1b7da4ac 11273 [(set_attr "length" "8")
11274 (set_attr "type" "no_insn")]
cffb2a26 11275)
11276
d98a3884 11277(define_insn "consttable_16"
11278 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_16)]
11279 "TARGET_EITHER"
11280 "*
11281 {
11282 making_const_table = TRUE;
11283 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
11284 {
945f7b03 11285 case MODE_FLOAT:
11286 assemble_real (*CONST_DOUBLE_REAL_VALUE (operands[0]),
11287 GET_MODE (operands[0]), BITS_PER_WORD);
11288 break;
d98a3884 11289 default:
11290 assemble_integer (operands[0], 16, BITS_PER_WORD, 1);
11291 break;
11292 }
11293 return \"\";
11294 }"
1b7da4ac 11295 [(set_attr "length" "16")
11296 (set_attr "type" "no_insn")]
d98a3884 11297)
11298
331beb1a 11299;; V5 Instructions,
11300
8f4be2be 11301(define_insn "clzsi2"
11302 [(set (match_operand:SI 0 "s_register_operand" "=r")
11303 (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 11304 "TARGET_32BIT && arm_arch5"
ee7cbe0e 11305 "clz%?\\t%0, %1"
bcaec148 11306 [(set_attr "predicable" "yes")
4a510717 11307 (set_attr "predicable_short_it" "no")
bebe9bbb 11308 (set_attr "type" "clz")])
331beb1a 11309
099ad98b 11310(define_insn "rbitsi2"
11311 [(set (match_operand:SI 0 "s_register_operand" "=r")
11312 (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")] UNSPEC_RBIT))]
11313 "TARGET_32BIT && arm_arch_thumb2"
11314 "rbit%?\\t%0, %1"
11315 [(set_attr "predicable" "yes")
4a510717 11316 (set_attr "predicable_short_it" "no")
bebe9bbb 11317 (set_attr "type" "clz")])
099ad98b 11318
99ffa689 11319;; Keep this as a CTZ expression until after reload and then split
11320;; into RBIT + CLZ. Since RBIT is represented as an UNSPEC it is unlikely
11321;; to fold with any other expression.
11322
11323(define_insn_and_split "ctzsi2"
11324 [(set (match_operand:SI 0 "s_register_operand" "=r")
11325 (ctz:SI (match_operand:SI 1 "s_register_operand" "r")))]
099ad98b 11326 "TARGET_32BIT && arm_arch_thumb2"
99ffa689 11327 "#"
11328 "&& reload_completed"
11329 [(const_int 0)]
099ad98b 11330 "
99ffa689 11331 emit_insn (gen_rbitsi2 (operands[0], operands[1]));
11332 emit_insn (gen_clzsi2 (operands[0], operands[0]));
11333 DONE;
11334")
099ad98b 11335
e1159bbe 11336;; V5E instructions.
331beb1a 11337
11338(define_insn "prefetch"
f4e79814 11339 [(prefetch (match_operand:SI 0 "address_operand" "p")
11340 (match_operand:SI 1 "" "")
11341 (match_operand:SI 2 "" ""))]
25f905c2 11342 "TARGET_32BIT && arm_arch5e"
1b7da4ac 11343 "pld\\t%a0"
11344 [(set_attr "type" "load1")]
11345)
331beb1a 11346
0d66636f 11347;; General predication pattern
11348
11349(define_cond_exec
11350 [(match_operator 0 "arm_comparison_operator"
11351 [(match_operand 1 "cc_register" "")
11352 (const_int 0)])]
580f4c48 11353 "TARGET_32BIT
11354 && (!TARGET_NO_VOLATILE_CE || !volatile_refs_p (PATTERN (insn)))"
0d66636f 11355 ""
c7a58118 11356[(set_attr "predicated" "yes")]
0d66636f 11357)
11358
fb94f18b 11359(define_insn "force_register_use"
11360 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_REGISTER_USE)]
063a05c7 11361 ""
fb94f18b 11362 "%@ %0 needed"
1b7da4ac 11363 [(set_attr "length" "0")
11364 (set_attr "type" "no_insn")]
063a05c7 11365)
7db9af5d 11366
4c44712e 11367
11368;; Patterns for exception handling
11369
11370(define_expand "eh_return"
11371 [(use (match_operand 0 "general_operand" ""))]
11372 "TARGET_EITHER"
11373 "
11374 {
25f905c2 11375 if (TARGET_32BIT)
4c44712e 11376 emit_insn (gen_arm_eh_return (operands[0]));
11377 else
11378 emit_insn (gen_thumb_eh_return (operands[0]));
11379 DONE;
11380 }"
11381)
11382
11383;; We can't expand this before we know where the link register is stored.
11384(define_insn_and_split "arm_eh_return"
11385 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
11386 VUNSPEC_EH_RETURN)
11387 (clobber (match_scratch:SI 1 "=&r"))]
11388 "TARGET_ARM"
11389 "#"
11390 "&& reload_completed"
11391 [(const_int 0)]
11392 "
11393 {
11394 arm_set_return_address (operands[0], operands[1]);
11395 DONE;
11396 }"
11397)
11398
f655717d 11399\f
11400;; TLS support
11401
11402(define_insn "load_tp_hard"
11403 [(set (match_operand:SI 0 "register_operand" "=r")
11404 (unspec:SI [(const_int 0)] UNSPEC_TLS))]
11405 "TARGET_HARD_TP"
11406 "mrc%?\\tp15, 0, %0, c13, c0, 3\\t@ load_tp_hard"
1b7da4ac 11407 [(set_attr "predicable" "yes")
4b5d7374 11408 (set_attr "type" "mrs")]
f655717d 11409)
11410
11411;; Doesn't clobber R1-R3. Must use r0 for the first operand.
11412(define_insn "load_tp_soft"
11413 [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
11414 (clobber (reg:SI LR_REGNUM))
11415 (clobber (reg:SI IP_REGNUM))
11416 (clobber (reg:CC CC_REGNUM))]
11417 "TARGET_SOFT_TP"
11418 "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
1b7da4ac 11419 [(set_attr "conds" "clob")
11420 (set_attr "type" "branch")]
f655717d 11421)
11422
f41e4452 11423;; tls descriptor call
11424(define_insn "tlscall"
11425 [(set (reg:SI R0_REGNUM)
11426 (unspec:SI [(reg:SI R0_REGNUM)
11427 (match_operand:SI 0 "" "X")
11428 (match_operand 1 "" "")] UNSPEC_TLS))
11429 (clobber (reg:SI R1_REGNUM))
11430 (clobber (reg:SI LR_REGNUM))
11431 (clobber (reg:SI CC_REGNUM))]
11432 "TARGET_GNU2_TLS"
11433 {
11434 targetm.asm_out.internal_label (asm_out_file, "LPIC",
11435 INTVAL (operands[1]));
11436 return "bl\\t%c0(tlscall)";
11437 }
11438 [(set_attr "conds" "clob")
1b7da4ac 11439 (set_attr "length" "4")
11440 (set_attr "type" "branch")]
f41e4452 11441)
11442
1fe0edab 11443;; For thread pointer builtin
11444(define_expand "get_thread_pointersi"
11445 [(match_operand:SI 0 "s_register_operand" "=r")]
11446 ""
11447 "
11448 {
11449 arm_load_tp (operands[0]);
11450 DONE;
11451 }")
11452
f41e4452 11453;;
11454
aabe09ac 11455;; We only care about the lower 16 bits of the constant
11456;; being inserted into the upper 16 bits of the register.
eca5c984 11457(define_insn "*arm_movtas_ze"
417e5cc5 11458 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r,r")
eca5c984 11459 (const_int 16)
11460 (const_int 16))
11461 (match_operand:SI 1 "const_int_operand" ""))]
60a48e7d 11462 "TARGET_HAVE_MOVT"
417e5cc5 11463 "@
11464 movt%?\t%0, %L1
11465 movt\t%0, %L1"
11466 [(set_attr "arch" "32,v8mb")
11467 (set_attr "predicable" "yes")
7c36fe71 11468 (set_attr "predicable_short_it" "no")
1b7da4ac 11469 (set_attr "length" "4")
282b4c75 11470 (set_attr "type" "alu_sreg")]
eca5c984 11471)
11472
c0fc3696 11473(define_insn "*arm_rev"
a486b499 11474 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
11475 (bswap:SI (match_operand:SI 1 "s_register_operand" "l,l,r")))]
11476 "arm_arch6"
11477 "@
11478 rev\t%0, %1
11479 rev%?\t%0, %1
11480 rev%?\t%0, %1"
11481 [(set_attr "arch" "t1,t2,32")
1b7da4ac 11482 (set_attr "length" "2,2,4")
4a510717 11483 (set_attr "predicable" "no,yes,yes")
11484 (set_attr "predicable_short_it" "no")
1b7da4ac 11485 (set_attr "type" "rev")]
ff82f757 11486)
11487
11488(define_expand "arm_legacy_rev"
11489 [(set (match_operand:SI 2 "s_register_operand" "")
11490 (xor:SI (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
11491 (const_int 16))
11492 (match_dup 1)))
11493 (set (match_dup 2)
11494 (lshiftrt:SI (match_dup 2)
11495 (const_int 8)))
11496 (set (match_operand:SI 3 "s_register_operand" "")
11497 (rotatert:SI (match_dup 1)
11498 (const_int 8)))
11499 (set (match_dup 2)
11500 (and:SI (match_dup 2)
11501 (const_int -65281)))
11502 (set (match_operand:SI 0 "s_register_operand" "")
11503 (xor:SI (match_dup 3)
11504 (match_dup 2)))]
11505 "TARGET_32BIT"
11506 ""
11507)
11508
11509;; Reuse temporaries to keep register pressure down.
11510(define_expand "thumb_legacy_rev"
11511 [(set (match_operand:SI 2 "s_register_operand" "")
11512 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
11513 (const_int 24)))
11514 (set (match_operand:SI 3 "s_register_operand" "")
11515 (lshiftrt:SI (match_dup 1)
11516 (const_int 24)))
11517 (set (match_dup 3)
11518 (ior:SI (match_dup 3)
11519 (match_dup 2)))
11520 (set (match_operand:SI 4 "s_register_operand" "")
11521 (const_int 16))
11522 (set (match_operand:SI 5 "s_register_operand" "")
11523 (rotatert:SI (match_dup 1)
11524 (match_dup 4)))
11525 (set (match_dup 2)
11526 (ashift:SI (match_dup 5)
11527 (const_int 24)))
11528 (set (match_dup 5)
11529 (lshiftrt:SI (match_dup 5)
11530 (const_int 24)))
11531 (set (match_dup 5)
11532 (ior:SI (match_dup 5)
11533 (match_dup 2)))
11534 (set (match_dup 5)
11535 (rotatert:SI (match_dup 5)
11536 (match_dup 4)))
11537 (set (match_operand:SI 0 "s_register_operand" "")
11538 (ior:SI (match_dup 5)
11539 (match_dup 3)))]
11540 "TARGET_THUMB"
11541 ""
11542)
11543
62e39b06 11544;; ARM-specific expansion of signed mod by power of 2
11545;; using conditional negate.
11546;; For r0 % n where n is a power of 2 produce:
11547;; rsbs r1, r0, #0
11548;; and r0, r0, #(n - 1)
11549;; and r1, r1, #(n - 1)
11550;; rsbpl r0, r1, #0
11551
11552(define_expand "modsi3"
11553 [(match_operand:SI 0 "register_operand" "")
11554 (match_operand:SI 1 "register_operand" "")
11555 (match_operand:SI 2 "const_int_operand" "")]
11556 "TARGET_32BIT"
11557 {
11558 HOST_WIDE_INT val = INTVAL (operands[2]);
11559
11560 if (val <= 0
11561 || exact_log2 (val) <= 0)
11562 FAIL;
11563
11564 rtx mask = GEN_INT (val - 1);
11565
11566 /* In the special case of x0 % 2 we can do the even shorter:
11567 cmp r0, #0
11568 and r0, r0, #1
11569 rsblt r0, r0, #0. */
11570
11571 if (val == 2)
11572 {
11573 rtx cc_reg = arm_gen_compare_reg (LT,
11574 operands[1], const0_rtx, NULL_RTX);
11575 rtx cond = gen_rtx_LT (SImode, cc_reg, const0_rtx);
11576 rtx masked = gen_reg_rtx (SImode);
11577
11578 emit_insn (gen_andsi3 (masked, operands[1], mask));
11579 emit_move_insn (operands[0],
11580 gen_rtx_IF_THEN_ELSE (SImode, cond,
11581 gen_rtx_NEG (SImode,
11582 masked),
11583 masked));
11584 DONE;
11585 }
11586
11587 rtx neg_op = gen_reg_rtx (SImode);
11588 rtx_insn *insn = emit_insn (gen_subsi3_compare0 (neg_op, const0_rtx,
11589 operands[1]));
11590
11591 /* Extract the condition register and mode. */
11592 rtx cmp = XVECEXP (PATTERN (insn), 0, 0);
11593 rtx cc_reg = SET_DEST (cmp);
11594 rtx cond = gen_rtx_GE (SImode, cc_reg, const0_rtx);
11595
11596 emit_insn (gen_andsi3 (operands[0], operands[1], mask));
11597
11598 rtx masked_neg = gen_reg_rtx (SImode);
11599 emit_insn (gen_andsi3 (masked_neg, neg_op, mask));
11600
11601 /* We want a conditional negate here, but emitting COND_EXEC rtxes
11602 during expand does not always work. Do an IF_THEN_ELSE instead. */
11603 emit_move_insn (operands[0],
11604 gen_rtx_IF_THEN_ELSE (SImode, cond,
11605 gen_rtx_NEG (SImode, masked_neg),
11606 operands[0]));
11607
11608
11609 DONE;
11610 }
11611)
11612
ff82f757 11613(define_expand "bswapsi2"
11614 [(set (match_operand:SI 0 "s_register_operand" "=r")
11615 (bswap:SI (match_operand:SI 1 "s_register_operand" "r")))]
8d1af482 11616"TARGET_EITHER && (arm_arch6 || !optimize_size)"
ff82f757 11617"
8d1af482 11618 if (!arm_arch6)
11619 {
11620 rtx op2 = gen_reg_rtx (SImode);
11621 rtx op3 = gen_reg_rtx (SImode);
ff82f757 11622
8d1af482 11623 if (TARGET_THUMB)
11624 {
11625 rtx op4 = gen_reg_rtx (SImode);
11626 rtx op5 = gen_reg_rtx (SImode);
ff82f757 11627
8d1af482 11628 emit_insn (gen_thumb_legacy_rev (operands[0], operands[1],
11629 op2, op3, op4, op5));
11630 }
11631 else
11632 {
11633 emit_insn (gen_arm_legacy_rev (operands[0], operands[1],
11634 op2, op3));
11635 }
ff82f757 11636
8d1af482 11637 DONE;
11638 }
ff82f757 11639 "
11640)
11641
a486b499 11642;; bswap16 patterns: use revsh and rev16 instructions for the signed
11643;; and unsigned variants, respectively. For rev16, expose
11644;; byte-swapping in the lower 16 bits only.
11645(define_insn "*arm_revsh"
11646 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
11647 (sign_extend:SI (bswap:HI (match_operand:HI 1 "s_register_operand" "l,l,r"))))]
11648 "arm_arch6"
11649 "@
11650 revsh\t%0, %1
11651 revsh%?\t%0, %1
11652 revsh%?\t%0, %1"
11653 [(set_attr "arch" "t1,t2,32")
1b7da4ac 11654 (set_attr "length" "2,2,4")
11655 (set_attr "type" "rev")]
a486b499 11656)
11657
11658(define_insn "*arm_rev16"
11659 [(set (match_operand:HI 0 "s_register_operand" "=l,l,r")
11660 (bswap:HI (match_operand:HI 1 "s_register_operand" "l,l,r")))]
11661 "arm_arch6"
11662 "@
11663 rev16\t%0, %1
11664 rev16%?\t%0, %1
11665 rev16%?\t%0, %1"
11666 [(set_attr "arch" "t1,t2,32")
1b7da4ac 11667 (set_attr "length" "2,2,4")
11668 (set_attr "type" "rev")]
09f69e55 11669)
11670
11671;; There are no canonicalisation rules for the position of the lshiftrt, ashift
11672;; operations within an IOR/AND RTX, therefore we have two patterns matching
11673;; each valid permutation.
11674
11675(define_insn "arm_rev16si2"
11676 [(set (match_operand:SI 0 "register_operand" "=l,l,r")
11677 (ior:SI (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "l,l,r")
11678 (const_int 8))
11679 (match_operand:SI 3 "const_int_operand" "n,n,n"))
11680 (and:SI (lshiftrt:SI (match_dup 1)
11681 (const_int 8))
11682 (match_operand:SI 2 "const_int_operand" "n,n,n"))))]
11683 "arm_arch6
11684 && aarch_rev16_shleft_mask_imm_p (operands[3], SImode)
11685 && aarch_rev16_shright_mask_imm_p (operands[2], SImode)"
11686 "rev16\\t%0, %1"
11687 [(set_attr "arch" "t1,t2,32")
11688 (set_attr "length" "2,2,4")
11689 (set_attr "type" "rev")]
11690)
11691
11692(define_insn "arm_rev16si2_alt"
11693 [(set (match_operand:SI 0 "register_operand" "=l,l,r")
11694 (ior:SI (and:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,l,r")
11695 (const_int 8))
11696 (match_operand:SI 2 "const_int_operand" "n,n,n"))
11697 (and:SI (ashift:SI (match_dup 1)
11698 (const_int 8))
11699 (match_operand:SI 3 "const_int_operand" "n,n,n"))))]
11700 "arm_arch6
11701 && aarch_rev16_shleft_mask_imm_p (operands[3], SImode)
11702 && aarch_rev16_shright_mask_imm_p (operands[2], SImode)"
11703 "rev16\\t%0, %1"
11704 [(set_attr "arch" "t1,t2,32")
11705 (set_attr "length" "2,2,4")
11706 (set_attr "type" "rev")]
a486b499 11707)
11708
11709(define_expand "bswaphi2"
11710 [(set (match_operand:HI 0 "s_register_operand" "=r")
11711 (bswap:HI (match_operand:HI 1 "s_register_operand" "r")))]
11712"arm_arch6"
11713""
11714)
11715
1653cf17 11716;; Patterns for LDRD/STRD in Thumb2 mode
11717
11718(define_insn "*thumb2_ldrd"
11719 [(set (match_operand:SI 0 "s_register_operand" "=r")
11720 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
11721 (match_operand:SI 2 "ldrd_strd_offset_operand" "Do"))))
11722 (set (match_operand:SI 3 "s_register_operand" "=r")
11723 (mem:SI (plus:SI (match_dup 1)
11724 (match_operand:SI 4 "const_int_operand" ""))))]
11725 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
1653cf17 11726 && ((INTVAL (operands[2]) + 4) == INTVAL (operands[4]))
11727 && (operands_ok_ldrd_strd (operands[0], operands[3],
11728 operands[1], INTVAL (operands[2]),
11729 false, true))"
11730 "ldrd%?\t%0, %3, [%1, %2]"
11731 [(set_attr "type" "load2")
d952d547 11732 (set_attr "predicable" "yes")
11733 (set_attr "predicable_short_it" "no")])
1653cf17 11734
11735(define_insn "*thumb2_ldrd_base"
11736 [(set (match_operand:SI 0 "s_register_operand" "=r")
11737 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
11738 (set (match_operand:SI 2 "s_register_operand" "=r")
11739 (mem:SI (plus:SI (match_dup 1)
11740 (const_int 4))))]
11741 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
1653cf17 11742 && (operands_ok_ldrd_strd (operands[0], operands[2],
11743 operands[1], 0, false, true))"
11744 "ldrd%?\t%0, %2, [%1]"
11745 [(set_attr "type" "load2")
d952d547 11746 (set_attr "predicable" "yes")
11747 (set_attr "predicable_short_it" "no")])
1653cf17 11748
11749(define_insn "*thumb2_ldrd_base_neg"
11750 [(set (match_operand:SI 0 "s_register_operand" "=r")
11751 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
11752 (const_int -4))))
11753 (set (match_operand:SI 2 "s_register_operand" "=r")
11754 (mem:SI (match_dup 1)))]
11755 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
1653cf17 11756 && (operands_ok_ldrd_strd (operands[0], operands[2],
11757 operands[1], -4, false, true))"
11758 "ldrd%?\t%0, %2, [%1, #-4]"
11759 [(set_attr "type" "load2")
d952d547 11760 (set_attr "predicable" "yes")
11761 (set_attr "predicable_short_it" "no")])
1653cf17 11762
11763(define_insn "*thumb2_strd"
11764 [(set (mem:SI (plus:SI (match_operand:SI 0 "s_register_operand" "rk")
11765 (match_operand:SI 1 "ldrd_strd_offset_operand" "Do")))
11766 (match_operand:SI 2 "s_register_operand" "r"))
11767 (set (mem:SI (plus:SI (match_dup 0)
11768 (match_operand:SI 3 "const_int_operand" "")))
11769 (match_operand:SI 4 "s_register_operand" "r"))]
11770 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
1653cf17 11771 && ((INTVAL (operands[1]) + 4) == INTVAL (operands[3]))
11772 && (operands_ok_ldrd_strd (operands[2], operands[4],
11773 operands[0], INTVAL (operands[1]),
11774 false, false))"
11775 "strd%?\t%2, %4, [%0, %1]"
11776 [(set_attr "type" "store2")
d952d547 11777 (set_attr "predicable" "yes")
11778 (set_attr "predicable_short_it" "no")])
1653cf17 11779
11780(define_insn "*thumb2_strd_base"
11781 [(set (mem:SI (match_operand:SI 0 "s_register_operand" "rk"))
11782 (match_operand:SI 1 "s_register_operand" "r"))
11783 (set (mem:SI (plus:SI (match_dup 0)
11784 (const_int 4)))
11785 (match_operand:SI 2 "s_register_operand" "r"))]
11786 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
1653cf17 11787 && (operands_ok_ldrd_strd (operands[1], operands[2],
11788 operands[0], 0, false, false))"
11789 "strd%?\t%1, %2, [%0]"
11790 [(set_attr "type" "store2")
d952d547 11791 (set_attr "predicable" "yes")
11792 (set_attr "predicable_short_it" "no")])
1653cf17 11793
11794(define_insn "*thumb2_strd_base_neg"
11795 [(set (mem:SI (plus:SI (match_operand:SI 0 "s_register_operand" "rk")
11796 (const_int -4)))
11797 (match_operand:SI 1 "s_register_operand" "r"))
11798 (set (mem:SI (match_dup 0))
11799 (match_operand:SI 2 "s_register_operand" "r"))]
11800 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
1653cf17 11801 && (operands_ok_ldrd_strd (operands[1], operands[2],
11802 operands[0], -4, false, false))"
11803 "strd%?\t%1, %2, [%0, #-4]"
11804 [(set_attr "type" "store2")
d952d547 11805 (set_attr "predicable" "yes")
11806 (set_attr "predicable_short_it" "no")])
1653cf17 11807
2a0c73f2 11808;; ARMv8 CRC32 instructions.
11809(define_insn "<crc_variant>"
11810 [(set (match_operand:SI 0 "s_register_operand" "=r")
11811 (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")
11812 (match_operand:<crc_mode> 2 "s_register_operand" "r")]
11813 CRC))]
11814 "TARGET_CRC32"
11815 "<crc_variant>\\t%0, %1, %2"
11816 [(set_attr "type" "crc")
11817 (set_attr "conds" "unconditional")]
11818)
1653cf17 11819
353cf59a 11820;; Load the load/store double peephole optimizations.
11821(include "ldrdstrd.md")
11822
320ea44d 11823;; Load the load/store multiple patterns
11824(include "ldmstm.md")
426be8c5 11825
11826;; Patterns in ldmstm.md don't cover more than 4 registers. This pattern covers
11827;; large lists without explicit writeback generated for APCS_FRAME epilogue.
11828(define_insn "*load_multiple"
11829 [(match_parallel 0 "load_multiple_operation"
11830 [(set (match_operand:SI 2 "s_register_operand" "=rk")
11831 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
11832 ])]
11833 "TARGET_32BIT"
11834 "*
11835 {
11836 arm_output_multireg_pop (operands, /*return_pc=*/false,
11837 /*cond=*/const_true_rtx,
11838 /*reverse=*/false,
11839 /*update=*/false);
11840 return \"\";
11841 }
11842 "
11843 [(set_attr "predicable" "yes")]
11844)
11845
84450ddc 11846(define_expand "copysignsf3"
11847 [(match_operand:SF 0 "register_operand")
11848 (match_operand:SF 1 "register_operand")
11849 (match_operand:SF 2 "register_operand")]
11850 "TARGET_SOFT_FLOAT && arm_arch_thumb2"
11851 "{
11852 emit_move_insn (operands[0], operands[2]);
11853 emit_insn (gen_insv_t2 (simplify_gen_subreg (SImode, operands[0], SFmode, 0),
11854 GEN_INT (31), GEN_INT (0),
11855 simplify_gen_subreg (SImode, operands[1], SFmode, 0)));
11856 DONE;
11857 }"
11858)
11859
11860(define_expand "copysigndf3"
11861 [(match_operand:DF 0 "register_operand")
11862 (match_operand:DF 1 "register_operand")
11863 (match_operand:DF 2 "register_operand")]
11864 "TARGET_SOFT_FLOAT && arm_arch_thumb2"
11865 "{
11866 rtx op0_low = gen_lowpart (SImode, operands[0]);
11867 rtx op0_high = gen_highpart (SImode, operands[0]);
11868 rtx op1_low = gen_lowpart (SImode, operands[1]);
11869 rtx op1_high = gen_highpart (SImode, operands[1]);
11870 rtx op2_high = gen_highpart (SImode, operands[2]);
11871
11872 rtx scratch1 = gen_reg_rtx (SImode);
11873 rtx scratch2 = gen_reg_rtx (SImode);
11874 emit_move_insn (scratch1, op2_high);
11875 emit_move_insn (scratch2, op1_high);
11876
d1f9b275 11877 emit_insn(gen_rtx_SET(scratch1,
84450ddc 11878 gen_rtx_LSHIFTRT (SImode, op2_high, GEN_INT(31))));
11879 emit_insn(gen_insv_t2(scratch2, GEN_INT(1), GEN_INT(31), scratch1));
11880 emit_move_insn (op0_low, op1_low);
11881 emit_move_insn (op0_high, scratch2);
11882
11883 DONE;
11884 }"
11885)
11886
115857ef 11887;; movmisalign patterns for HImode and SImode.
11888(define_expand "movmisalign<mode>"
11889 [(match_operand:HSI 0 "general_operand")
11890 (match_operand:HSI 1 "general_operand")]
11891 "unaligned_access"
11892{
11893 /* This pattern is not permitted to fail during expansion: if both arguments
11894 are non-registers (e.g. memory := constant), force operand 1 into a
11895 register. */
11896 rtx (* gen_unaligned_load)(rtx, rtx);
11897 rtx tmp_dest = operands[0];
11898 if (!s_register_operand (operands[0], <MODE>mode)
11899 && !s_register_operand (operands[1], <MODE>mode))
11900 operands[1] = force_reg (<MODE>mode, operands[1]);
11901
11902 if (<MODE>mode == HImode)
11903 {
11904 gen_unaligned_load = gen_unaligned_loadhiu;
11905 tmp_dest = gen_reg_rtx (SImode);
11906 }
11907 else
11908 gen_unaligned_load = gen_unaligned_loadsi;
11909
11910 if (MEM_P (operands[1]))
11911 {
11912 emit_insn (gen_unaligned_load (tmp_dest, operands[1]));
11913 if (<MODE>mode == HImode)
11914 emit_move_insn (operands[0], gen_lowpart (HImode, tmp_dest));
11915 }
11916 else
11917 emit_insn (gen_unaligned_store<mode> (operands[0], operands[1]));
11918
11919 DONE;
11920})
11921
1be6395a 11922(define_insn "<cdp>"
11923 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "n")
11924 (match_operand:SI 1 "immediate_operand" "n")
11925 (match_operand:SI 2 "immediate_operand" "n")
11926 (match_operand:SI 3 "immediate_operand" "n")
11927 (match_operand:SI 4 "immediate_operand" "n")
11928 (match_operand:SI 5 "immediate_operand" "n")] CDPI)]
11929 "arm_coproc_builtin_available (VUNSPEC_<CDP>)"
11930{
11931 arm_const_bounds (operands[0], 0, 16);
11932 arm_const_bounds (operands[1], 0, 16);
11933 arm_const_bounds (operands[2], 0, (1 << 5));
11934 arm_const_bounds (operands[3], 0, (1 << 5));
11935 arm_const_bounds (operands[4], 0, (1 << 5));
11936 arm_const_bounds (operands[5], 0, 8);
11937 return "<cdp>\\tp%c0, %1, CR%c2, CR%c3, CR%c4, %5";
11938}
11939 [(set_attr "length" "4")
11940 (set_attr "type" "coproc")])
11941
638b44bd 11942(define_insn "*ldc"
11943 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "n")
11944 (match_operand:SI 1 "immediate_operand" "n")
11945 (match_operand:SI 2 "memory_operand" "Uz")] LDCI)]
11946 "arm_coproc_builtin_available (VUNSPEC_<LDC>)"
11947{
11948 arm_const_bounds (operands[0], 0, 16);
11949 arm_const_bounds (operands[1], 0, (1 << 5));
11950 return "<ldc>\\tp%c0, CR%c1, %2";
11951}
11952 [(set_attr "length" "4")
11953 (set_attr "type" "coproc")])
11954
11955(define_insn "*stc"
11956 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "n")
11957 (match_operand:SI 1 "immediate_operand" "n")
11958 (match_operand:SI 2 "memory_operand" "=Uz")] STCI)]
11959 "arm_coproc_builtin_available (VUNSPEC_<STC>)"
11960{
11961 arm_const_bounds (operands[0], 0, 16);
11962 arm_const_bounds (operands[1], 0, (1 << 5));
11963 return "<stc>\\tp%c0, CR%c1, %2";
11964}
11965 [(set_attr "length" "4")
11966 (set_attr "type" "coproc")])
11967
11968(define_expand "<ldc>"
11969 [(unspec_volatile [(match_operand:SI 0 "immediate_operand")
11970 (match_operand:SI 1 "immediate_operand")
11971 (mem:SI (match_operand:SI 2 "s_register_operand"))] LDCI)]
11972 "arm_coproc_builtin_available (VUNSPEC_<LDC>)")
11973
11974(define_expand "<stc>"
11975 [(unspec_volatile [(match_operand:SI 0 "immediate_operand")
11976 (match_operand:SI 1 "immediate_operand")
11977 (mem:SI (match_operand:SI 2 "s_register_operand"))] STCI)]
11978 "arm_coproc_builtin_available (VUNSPEC_<STC>)")
11979
415e9b1f 11980(define_insn "<mcr>"
11981 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "n")
11982 (match_operand:SI 1 "immediate_operand" "n")
11983 (match_operand:SI 2 "s_register_operand" "r")
11984 (match_operand:SI 3 "immediate_operand" "n")
11985 (match_operand:SI 4 "immediate_operand" "n")
11986 (match_operand:SI 5 "immediate_operand" "n")] MCRI)
11987 (use (match_dup 2))]
11988 "arm_coproc_builtin_available (VUNSPEC_<MCR>)"
11989{
11990 arm_const_bounds (operands[0], 0, 16);
11991 arm_const_bounds (operands[1], 0, 8);
11992 arm_const_bounds (operands[3], 0, (1 << 5));
11993 arm_const_bounds (operands[4], 0, (1 << 5));
11994 arm_const_bounds (operands[5], 0, 8);
11995 return "<mcr>\\tp%c0, %1, %2, CR%c3, CR%c4, %5";
11996}
11997 [(set_attr "length" "4")
11998 (set_attr "type" "coproc")])
11999
12000(define_insn "<mrc>"
12001 [(set (match_operand:SI 0 "s_register_operand" "=r")
12002 (unspec_volatile [(match_operand:SI 1 "immediate_operand" "n")
12003 (match_operand:SI 2 "immediate_operand" "n")
12004 (match_operand:SI 3 "immediate_operand" "n")
12005 (match_operand:SI 4 "immediate_operand" "n")
12006 (match_operand:SI 5 "immediate_operand" "n")] MRCI))]
12007 "arm_coproc_builtin_available (VUNSPEC_<MRC>)"
12008{
12009 arm_const_bounds (operands[1], 0, 16);
12010 arm_const_bounds (operands[2], 0, 8);
12011 arm_const_bounds (operands[3], 0, (1 << 5));
12012 arm_const_bounds (operands[4], 0, (1 << 5));
12013 arm_const_bounds (operands[5], 0, 8);
12014 return "<mrc>\\tp%c1, %2, %0, CR%c3, CR%c4, %5";
12015}
12016 [(set_attr "length" "4")
12017 (set_attr "type" "coproc")])
12018
d98a3884 12019;; Vector bits common to IWMMXT and Neon
12020(include "vec-common.md")
755eb2b4 12021;; Load the Intel Wireless Multimedia Extension patterns
12022(include "iwmmxt.md")
a2cd141b 12023;; Load the VFP co-processor patterns
12024(include "vfp.md")
bc360af8 12025;; Thumb-1 patterns
12026(include "thumb1.md")
25f905c2 12027;; Thumb-2 patterns
12028(include "thumb2.md")
d98a3884 12029;; Neon patterns
12030(include "neon.md")
e84fdf6e 12031;; Crypto patterns
12032(include "crypto.md")
06df6b17 12033;; Synchronization Primitives
12034(include "sync.md")
bbbe4599 12035;; Fixed-point patterns
12036(include "arm-fixed.md")