]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/arm/arm.md
PR target/89434
[thirdparty/gcc.git] / gcc / config / arm / arm.md
CommitLineData
129a2fe4 1;;- Machine description for ARM for GNU compiler
fbd26352 2;; Copyright (C) 1991-2019 Free Software Foundation, Inc.
b11cae9e 3;; Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
f082f1c4 4;; and Martin Simmons (@harleqn.co.uk).
129a2fe4 5;; More major hacks by Richard Earnshaw (rearnsha@arm.com).
b11cae9e 6
acf6ed70 7;; This file is part of GCC.
b11cae9e 8
acf6ed70 9;; GCC is free software; you can redistribute it and/or modify it
10;; under the terms of the GNU General Public License as published
038d1e19 11;; by the Free Software Foundation; either version 3, or (at your
acf6ed70 12;; option) any later version.
b11cae9e 13
acf6ed70 14;; GCC is distributed in the hope that it will be useful, but WITHOUT
15;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
17;; License for more details.
b11cae9e 18
19;; You should have received a copy of the GNU General Public License
038d1e19 20;; along with GCC; see the file COPYING3. If not see
21;; <http://www.gnu.org/licenses/>.
b11cae9e 22
23;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
24
9c08d1fa 25\f
e1159bbe 26;;---------------------------------------------------------------------------
27;; Constants
28
bffbb863 29;; Register numbers -- All machine registers should be defined here
e1159bbe 30(define_constants
bffbb863 31 [(R0_REGNUM 0) ; First CORE register
32 (R1_REGNUM 1) ; Second CORE register
e27c5a70 33 (R4_REGNUM 4) ; Fifth CORE register
bffbb863 34 (IP_REGNUM 12) ; Scratch register
35 (SP_REGNUM 13) ; Stack pointer
36 (LR_REGNUM 14) ; Return address register
37 (PC_REGNUM 15) ; Program counter
38 (LAST_ARM_REGNUM 15) ;
39 (CC_REGNUM 100) ; Condition code pseudo register
40 (VFPCC_REGNUM 101) ; VFP Condition code pseudo register
e1159bbe 41 ]
42)
3c5afce6 43;; 3rd operand to select_dominance_cc_mode
44(define_constants
45 [(DOM_CC_X_AND_Y 0)
46 (DOM_CC_NX_OR_Y 1)
47 (DOM_CC_X_OR_Y 2)
48 ]
49)
2ff91fec 50;; conditional compare combination
51(define_constants
52 [(CMP_CMP 0)
53 (CMN_CMP 1)
54 (CMP_CMN 2)
55 (CMN_CMN 3)
56 (NUM_OF_COND_CMP 4)
57 ]
58)
e1159bbe 59
b11cae9e 60\f
e1159bbe 61;;---------------------------------------------------------------------------
9c08d1fa 62;; Attributes
63
a651f34d 64;; Processor type. This is created automatically from arm-cores.def.
65(include "arm-tune.md")
66
861033d5 67;; Instruction classification types
68(include "types.md")
69
215b30b3 70; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
71; generating ARM code. This is used to control the length of some insn
72; patterns that share the same RTL in both ARM and Thumb code.
8724f216 73(define_attr "is_thumb" "yes,no"
74 (const (if_then_else (symbol_ref "TARGET_THUMB")
75 (const_string "yes") (const_string "no"))))
cffb2a26 76
ef51b8e1 77; IS_ARCH6 is set to 'yes' when we are generating code form ARMv6.
78(define_attr "is_arch6" "no,yes" (const (symbol_ref "arm_arch6")))
79
747b7458 80; IS_THUMB1 is set to 'yes' iff we are generating Thumb-1 code.
8724f216 81(define_attr "is_thumb1" "yes,no"
82 (const (if_then_else (symbol_ref "TARGET_THUMB1")
83 (const_string "yes") (const_string "no"))))
747b7458 84
8bdfd6ed 85; Mark an instruction as suitable for "short IT" blocks in Thumb-2.
86; The arm_restrict_it flag enables the "short IT" feature which
87; restricts IT blocks to a single 16-bit instruction.
88; This attribute should only be used on 16-bit Thumb-2 instructions
89; which may be predicated (the "predicable" attribute must be set).
90(define_attr "predicable_short_it" "no,yes" (const_string "no"))
91
92; Mark an instruction as suitable for "short IT" blocks in Thumb-2.
93; This attribute should only be used on instructions which may emit
94; an IT block in their expansion which is not a short IT.
95(define_attr "enabled_for_short_it" "no,yes" (const_string "yes"))
c7a58118 96
331beb1a 97;; Operand number of an input operand that is shifted. Zero if the
98;; given instruction does not shift one of its input operands.
331beb1a 99(define_attr "shift" "" (const_int 0))
100
55a94dda 101;; [For compatibility with AArch64 in pipeline models]
102;; Attribute that specifies whether or not the instruction touches fp
103;; registers.
104(define_attr "fp" "no,yes" (const_string "no"))
105
3d91c5d6 106; Floating Point Unit. If we only have floating point emulation, then there
107; is no point in scheduling the floating point insns. (Well, for best
108; performance we should try and group them together).
bffbb863 109(define_attr "fpu" "none,vfp"
c7f506fd 110 (const (symbol_ref "arm_fpu_attr")))
3d91c5d6 111
b2bcff19 112; Predicated means that the insn form is conditionally executed based on a
113; predicate. We default to 'no' because no Thumb patterns match this rule
114; and not all ARM insns do.
c7a58118 115(define_attr "predicated" "yes,no" (const_string "no"))
116
094e994f 117; LENGTH of an instruction (in bytes)
06df6b17 118(define_attr "length" ""
e1b93706 119 (const_int 4))
9c08d1fa 120
d5d4dc8d 121; The architecture which supports the instruction (or alternative).
122; This can be "a" for ARM, "t" for either of the Thumbs, "32" for
123; TARGET_32BIT, "t1" or "t2" to specify a specific Thumb mode. "v6"
124; for ARM or Thumb-2 with arm_arch6, and nov6 for ARM without
417e5cc5 125; arm_arch6. "v6t2" for Thumb-2 with arm_arch6 and "v8mb" for ARMv8-M
126; Baseline. This attribute is used to compute attribute "enabled",
127; use type "any" to enable an alternative in all cases.
128(define_attr "arch" "any,a,t,32,t1,t2,v6,nov6,v6t2,v8mb,neon_for_64bits,avoid_neon_for_64bits,iwmmxt,iwmmxt2,armv6_or_vfpv3,neon"
d5d4dc8d 129 (const_string "any"))
130
131(define_attr "arch_enabled" "no,yes"
132 (cond [(eq_attr "arch" "any")
133 (const_string "yes")
134
135 (and (eq_attr "arch" "a")
0bf497f5 136 (match_test "TARGET_ARM"))
d5d4dc8d 137 (const_string "yes")
138
139 (and (eq_attr "arch" "t")
0bf497f5 140 (match_test "TARGET_THUMB"))
d5d4dc8d 141 (const_string "yes")
142
143 (and (eq_attr "arch" "t1")
0bf497f5 144 (match_test "TARGET_THUMB1"))
d5d4dc8d 145 (const_string "yes")
146
147 (and (eq_attr "arch" "t2")
0bf497f5 148 (match_test "TARGET_THUMB2"))
d5d4dc8d 149 (const_string "yes")
150
151 (and (eq_attr "arch" "32")
0bf497f5 152 (match_test "TARGET_32BIT"))
d5d4dc8d 153 (const_string "yes")
154
155 (and (eq_attr "arch" "v6")
0bf497f5 156 (match_test "TARGET_32BIT && arm_arch6"))
d5d4dc8d 157 (const_string "yes")
158
159 (and (eq_attr "arch" "nov6")
0bf497f5 160 (match_test "TARGET_32BIT && !arm_arch6"))
a651f34d 161 (const_string "yes")
162
e4585731 163 (and (eq_attr "arch" "v6t2")
164 (match_test "TARGET_32BIT && arm_arch6 && arm_arch_thumb2"))
165 (const_string "yes")
166
417e5cc5 167 (and (eq_attr "arch" "v8mb")
168 (match_test "TARGET_THUMB1 && arm_arch8"))
169 (const_string "yes")
170
b6779ddc 171 (and (eq_attr "arch" "avoid_neon_for_64bits")
172 (match_test "TARGET_NEON")
173 (not (match_test "TARGET_PREFER_NEON_64BITS")))
a651f34d 174 (const_string "yes")
175
b6779ddc 176 (and (eq_attr "arch" "neon_for_64bits")
177 (match_test "TARGET_NEON")
178 (match_test "TARGET_PREFER_NEON_64BITS"))
6b8f7c28 179 (const_string "yes")
180
181 (and (eq_attr "arch" "iwmmxt2")
182 (match_test "TARGET_REALLY_IWMMXT2"))
21cc9773 183 (const_string "yes")
184
185 (and (eq_attr "arch" "armv6_or_vfpv3")
186 (match_test "arm_arch6 || TARGET_VFP3"))
187 (const_string "yes")
ac876af5 188
189 (and (eq_attr "arch" "neon")
190 (match_test "TARGET_NEON"))
191 (const_string "yes")
21cc9773 192 ]
6b8f7c28 193
d5d4dc8d 194 (const_string "no")))
195
aa06c51c 196(define_attr "opt" "any,speed,size"
197 (const_string "any"))
198
199(define_attr "opt_enabled" "no,yes"
200 (cond [(eq_attr "opt" "any")
201 (const_string "yes")
202
203 (and (eq_attr "opt" "speed")
204 (match_test "optimize_function_for_speed_p (cfun)"))
205 (const_string "yes")
206
207 (and (eq_attr "opt" "size")
208 (match_test "optimize_function_for_size_p (cfun)"))
209 (const_string "yes")]
210 (const_string "no")))
211
861033d5 212(define_attr "use_literal_pool" "no,yes"
213 (cond [(and (eq_attr "type" "f_loads,f_loadd")
214 (match_test "CONSTANT_P (operands[1])"))
215 (const_string "yes")]
216 (const_string "no")))
217
d5d4dc8d 218; Enable all alternatives that are both arch_enabled and insn_enabled.
951a3f72 219; FIXME:: opt_enabled has been temporarily removed till the time we have
220; an attribute that allows the use of such alternatives.
221; This depends on caching of speed_p, size_p on a per
222; alternative basis. The problem is that the enabled attribute
223; cannot depend on any state that is not cached or is not constant
224; for a compilation unit. We probably need a generic "hot/cold"
225; alternative which if implemented can help with this. We disable this
226; until such a time as this is implemented and / or the improvements or
227; regressions with removing this attribute are double checked.
228; See ashldi3_neon and <shift>di3_neon in neon.md.
229
93b431d9 230 (define_attr "enabled" "no,yes"
0abea32c 231 (cond [(and (eq_attr "predicable_short_it" "no")
c7a58118 232 (and (eq_attr "predicated" "yes")
233 (match_test "arm_restrict_it")))
234 (const_string "no")
235
8bdfd6ed 236 (and (eq_attr "enabled_for_short_it" "no")
c7a58118 237 (match_test "arm_restrict_it"))
238 (const_string "no")
239
aa06c51c 240 (eq_attr "arch_enabled" "no")
aa06c51c 241 (const_string "no")]
242 (const_string "yes")))
d5d4dc8d 243
56d27660 244; POOL_RANGE is how far away from a constant pool entry that this insn
245; can be placed. If the distance is zero, then this insn will never
246; reference the pool.
42e1de19 247; Note that for Thumb constant pools the PC value is rounded down to the
248; nearest multiple of four. Therefore, THUMB2_POOL_RANGE (and POOL_RANGE for
249; Thumb insns) should be set to <max_range> - 2.
cffb2a26 250; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
8848d797 251; before its address. It is set to <max_range> - (8 + <data_size>).
cde1623a 252(define_attr "arm_pool_range" "" (const_int 0))
253(define_attr "thumb2_pool_range" "" (const_int 0))
254(define_attr "arm_neg_pool_range" "" (const_int 0))
255(define_attr "thumb2_neg_pool_range" "" (const_int 0))
256
257(define_attr "pool_range" ""
258 (cond [(eq_attr "is_thumb" "yes") (attr "thumb2_pool_range")]
259 (attr "arm_pool_range")))
260(define_attr "neg_pool_range" ""
261 (cond [(eq_attr "is_thumb" "yes") (attr "thumb2_neg_pool_range")]
262 (attr "arm_neg_pool_range")))
56d27660 263
215b30b3 264; An assembler sequence may clobber the condition codes without us knowing.
4d7a8451 265; If such an insn references the pool, then we have no way of knowing how,
266; so use the most conservative value for pool_range.
9c08d1fa 267(define_asm_attributes
4d7a8451 268 [(set_attr "conds" "clob")
269 (set_attr "length" "4")
270 (set_attr "pool_range" "250")])
9c08d1fa 271
9888ad6d 272; Load scheduling, set from the arm_ld_sched variable
4c834714 273; initialized by arm_option_override()
9888ad6d 274(define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
849170fd 275
f7fbdd4a 276; condition codes: this one is used by final_prescan_insn to speed up
277; conditionalizing instructions. It saves having to scan the rtl to see if
278; it uses or alters the condition codes.
215b30b3 279;
f7fbdd4a 280; USE means that the condition codes are used by the insn in the process of
215b30b3 281; outputting code, this means (at present) that we can't use the insn in
282; inlined branches
283;
f7fbdd4a 284; SET means that the purpose of the insn is to set the condition codes in a
215b30b3 285; well defined manner.
286;
f7fbdd4a 287; CLOB means that the condition codes are altered in an undefined manner, if
215b30b3 288; they are altered at all
289;
f4d3c071 290; UNCONDITIONAL means the instruction cannot be conditionally executed and
ad6d3e2a 291; that the instruction does not use or alter the condition codes.
c52acdd2 292;
ad6d3e2a 293; NOCOND means that the instruction does not use or alter the condition
294; codes but can be converted into a conditionally exectuted instruction.
f7fbdd4a 295
b0694be0 296(define_attr "conds" "use,set,clob,unconditional,nocond"
747b7458 297 (if_then_else
298 (ior (eq_attr "is_thumb1" "yes")
299 (eq_attr "type" "call"))
c1a66faf 300 (const_string "clob")
32093010 301 (if_then_else (eq_attr "is_neon_type" "no")
52432540 302 (const_string "nocond")
303 (const_string "unconditional"))))
f7fbdd4a 304
215b30b3 305; Predicable means that the insn can be conditionally executed based on
306; an automatically added predicate (additional patterns are generated by
307; gen...). We default to 'no' because no Thumb patterns match this rule
308; and not all ARM patterns do.
0d66636f 309(define_attr "predicable" "no,yes" (const_string "no"))
310
129a2fe4 311; Only model the write buffer for ARM6 and ARM7. Earlier processors don't
312; have one. Later ones, such as StrongARM, have write-back caches, so don't
8d232dc7 313; suffer blockages enough to warrant modelling this (and it can adversely
129a2fe4 314; affect the schedule).
74a71f7d 315(define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_tune_wbuf")))
129a2fe4 316
215b30b3 317; WRITE_CONFLICT implies that a read following an unrelated write is likely
318; to stall the processor. Used with model_wbuf above.
9c08d1fa 319(define_attr "write_conflict" "no,yes"
320 (if_then_else (eq_attr "type"
9f2c2a36 321 "block,call,load_4")
9c08d1fa 322 (const_string "yes")
323 (const_string "no")))
324
215b30b3 325; Classify the insns into those that take one cycle and those that take more
326; than one on the main cpu execution unit.
f7fbdd4a 327(define_attr "core_cycles" "single,multi"
328 (if_then_else (eq_attr "type"
112eda6f 329 "adc_imm, adc_reg, adcs_imm, adcs_reg, adr, alu_ext, alu_imm, alu_sreg,\
330 alu_shift_imm, alu_shift_reg, alu_dsp_reg, alus_ext, alus_imm, alus_sreg,\
d82e788e 331 alus_shift_imm, alus_shift_reg, bfm, csel, rev, logic_imm, logic_reg,\
332 logic_shift_imm, logic_shift_reg, logics_imm, logics_reg,\
333 logics_shift_imm, logics_shift_reg, extend, shift_imm, float, fcsel,\
7cb6c048 334 wmmx_wor, wmmx_wxor, wmmx_wand, wmmx_wandn, wmmx_wmov, wmmx_tmcrr,\
335 wmmx_tmrrc, wmmx_wldr, wmmx_wstr, wmmx_tmcr, wmmx_tmrc, wmmx_wadd,\
336 wmmx_wsub, wmmx_wmul, wmmx_wmac, wmmx_wavg2, wmmx_tinsr, wmmx_textrm,\
337 wmmx_wshufh, wmmx_wcmpeq, wmmx_wcmpgt, wmmx_wmax, wmmx_wmin, wmmx_wpack,\
338 wmmx_wunpckih, wmmx_wunpckil, wmmx_wunpckeh, wmmx_wunpckel, wmmx_wror,\
339 wmmx_wsra, wmmx_wsrl, wmmx_wsll, wmmx_wmadd, wmmx_tmia, wmmx_tmiaph,\
340 wmmx_tmiaxy, wmmx_tbcst, wmmx_tmovmsk, wmmx_wacc, wmmx_waligni,\
341 wmmx_walignr, wmmx_tandc, wmmx_textrc, wmmx_torc, wmmx_torvsc, wmmx_wsad,\
342 wmmx_wabs, wmmx_wabsdiff, wmmx_waddsubhx, wmmx_wsubaddhx, wmmx_wavg4,\
343 wmmx_wmulw, wmmx_wqmulm, wmmx_wqmulwm, wmmx_waddbhus, wmmx_wqmiaxy,\
344 wmmx_wmiaxy, wmmx_wmiawxy, wmmx_wmerge")
f7fbdd4a 345 (const_string "single")
346 (const_string "multi")))
347
cffb2a26 348;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
215b30b3 349;; distant label. Only applicable to Thumb code.
cffb2a26 350(define_attr "far_jump" "yes,no" (const_string "no"))
351
d51f92df 352
25f905c2 353;; The number of machine instructions this pattern expands to.
354;; Used for Thumb-2 conditional execution.
355(define_attr "ce_count" "" (const_int 1))
356
4182b724 357;;---------------------------------------------------------------------------
358;; Unspecs
359
360(include "unspecs.md")
361
d51f92df 362;;---------------------------------------------------------------------------
fd781bb2 363;; Mode iterators
d51f92df 364
3de0dec6 365(include "iterators.md")
03770691 366
d51f92df 367;;---------------------------------------------------------------------------
368;; Predicates
369
9c9db025 370(include "predicates.md")
234f6557 371(include "constraints.md")
9c9db025 372
a2cd141b 373;;---------------------------------------------------------------------------
374;; Pipeline descriptions
215b30b3 375
e3879fd0 376(define_attr "tune_cortexr4" "yes,no"
377 (const (if_then_else
7d3cda8c 378 (eq_attr "tune" "cortexr4,cortexr4f,cortexr5")
e3879fd0 379 (const_string "yes")
380 (const_string "no"))))
381
a2cd141b 382;; True if the generic scheduling description should be used.
383
384(define_attr "generic_sched" "yes,no"
2546d93a 385 (const (if_then_else
e18862f3 386 (ior (eq_attr "tune" "fa526,fa626,fa606te,fa626te,fmp626,fa726te,\
1efe0507 387 arm926ejs,arm10e,arm1026ejs,arm1136js,\
e18862f3 388 arm1136jfs,cortexa5,cortexa7,cortexa8,\
42e7b263 389 cortexa9,cortexa12,cortexa15,cortexa17,\
b1099bfd 390 cortexa53,cortexa57,cortexm4,cortexm7,\
802e6377 391 exynosm1,marvell_pj4,xgene1")
2546d93a 392 (eq_attr "tune_cortexr4" "yes"))
4d5cb40d 393 (const_string "no")
394 (const_string "yes"))))
395
c0e1af52 396(define_attr "generic_vfp" "yes,no"
397 (const (if_then_else
398 (and (eq_attr "fpu" "vfp")
1efe0507 399 (eq_attr "tune" "!arm10e,cortexa5,cortexa7,\
e18862f3 400 cortexa8,cortexa9,cortexa53,cortexm4,\
55a94dda 401 cortexm7,marvell_pj4,xgene1")
e3879fd0 402 (eq_attr "tune_cortexr4" "no"))
c0e1af52 403 (const_string "yes")
404 (const_string "no"))))
405
6b8f7c28 406(include "marvell-f-iwmmxt.md")
a2cd141b 407(include "arm-generic.md")
408(include "arm926ejs.md")
c0e1af52 409(include "arm1020e.md")
a2cd141b 410(include "arm1026ejs.md")
411(include "arm1136jfs.md")
0e266d06 412(include "fa526.md")
413(include "fa606te.md")
414(include "fa626te.md")
415(include "fmp626.md")
416(include "fa726te.md")
3f1e069f 417(include "cortex-a5.md")
d6b7f019 418(include "cortex-a7.md")
bcaec148 419(include "cortex-a8.md")
036068af 420(include "cortex-a9.md")
65f2f758 421(include "cortex-a15.md")
42e7b263 422(include "cortex-a17.md")
da10bc87 423(include "cortex-a53.md")
b1099bfd 424(include "cortex-a57.md")
934a1e72 425(include "cortex-r4.md")
e3879fd0 426(include "cortex-r4f.md")
e18862f3 427(include "cortex-m7.md")
2546d93a 428(include "cortex-m4.md")
429(include "cortex-m4-fpu.md")
802e6377 430(include "exynos-m1.md")
55e3ada8 431(include "vfp11.md")
ea7d210b 432(include "marvell-pj4.md")
55a94dda 433(include "xgene1.md")
3586df96 434
9c08d1fa 435\f
215b30b3 436;;---------------------------------------------------------------------------
e1159bbe 437;; Insn patterns
438;;
a0f94409 439;; Addition insns.
215b30b3 440
9c08d1fa 441;; Note: For DImode insns, there is normally no reason why operands should
442;; not be in the same register, what we don't want is for something being
443;; written to partially overlap something that is an input.
444
cffb2a26 445(define_expand "adddi3"
446 [(parallel
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"
206f0a3f 464 [(set (match_operand:DI 0 "arm_general_register_operand" "=&r,&r,&r,&r,&r")
465 (plus:DI (match_operand:DI 1 "arm_general_register_operand" "%0, 0, r, 0, r")
466 (match_operand:DI 2 "arm_general_adddi_operand" "r, 0, r, Dd, Dd")))
bd5b4116 467 (clobber (reg:CC CC_REGNUM))]
b805622c 468 "TARGET_32BIT && !TARGET_NEON"
33782ec7 469 "#"
206f0a3f 470 "TARGET_32BIT && ((!TARGET_NEON && !TARGET_IWMMXT) || reload_completed)"
a0f94409 471 [(parallel [(set (reg:CC_C CC_REGNUM)
472 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
473 (match_dup 1)))
474 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 475 (set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (match_dup 5))
476 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
a0f94409 477 "
478 {
479 operands[3] = gen_highpart (SImode, operands[0]);
480 operands[0] = gen_lowpart (SImode, operands[0]);
481 operands[4] = gen_highpart (SImode, operands[1]);
482 operands[1] = gen_lowpart (SImode, operands[1]);
10e5ccd5 483 operands[5] = gen_highpart_mode (SImode, DImode, operands[2]);
a0f94409 484 operands[2] = gen_lowpart (SImode, operands[2]);
485 }"
cffb2a26 486 [(set_attr "conds" "clob")
1b7da4ac 487 (set_attr "length" "8")
488 (set_attr "type" "multiple")]
cffb2a26 489)
9c08d1fa 490
a0f94409 491(define_insn_and_split "*adddi_sesidi_di"
9c08d1fa 492 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
493 (plus:DI (sign_extend:DI
97499065 494 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 495 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 496 (clobber (reg:CC CC_REGNUM))]
b805622c 497 "TARGET_32BIT"
33782ec7 498 "#"
25f905c2 499 "TARGET_32BIT && reload_completed"
a0f94409 500 [(parallel [(set (reg:CC_C CC_REGNUM)
501 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
502 (match_dup 1)))
503 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 504 (set (match_dup 3) (plus:SI (plus:SI (ashiftrt:SI (match_dup 2)
a0f94409 505 (const_int 31))
080c0b9a 506 (match_dup 4))
507 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
a0f94409 508 "
509 {
510 operands[3] = gen_highpart (SImode, operands[0]);
511 operands[0] = gen_lowpart (SImode, operands[0]);
512 operands[4] = gen_highpart (SImode, operands[1]);
513 operands[1] = gen_lowpart (SImode, operands[1]);
514 operands[2] = gen_lowpart (SImode, operands[2]);
515 }"
215b30b3 516 [(set_attr "conds" "clob")
1b7da4ac 517 (set_attr "length" "8")
518 (set_attr "type" "multiple")]
215b30b3 519)
9c08d1fa 520
a0f94409 521(define_insn_and_split "*adddi_zesidi_di"
9c08d1fa 522 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
523 (plus:DI (zero_extend:DI
97499065 524 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 525 (match_operand:DI 1 "s_register_operand" "0,r")))
a0f94409 526 (clobber (reg:CC CC_REGNUM))]
b805622c 527 "TARGET_32BIT"
33782ec7 528 "#"
25f905c2 529 "TARGET_32BIT && reload_completed"
a0f94409 530 [(parallel [(set (reg:CC_C CC_REGNUM)
531 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
532 (match_dup 1)))
533 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 534 (set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (const_int 0))
535 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
a0f94409 536 "
537 {
538 operands[3] = gen_highpart (SImode, operands[0]);
539 operands[0] = gen_lowpart (SImode, operands[0]);
540 operands[4] = gen_highpart (SImode, operands[1]);
541 operands[1] = gen_lowpart (SImode, operands[1]);
542 operands[2] = gen_lowpart (SImode, operands[2]);
543 }"
cffb2a26 544 [(set_attr "conds" "clob")
1b7da4ac 545 (set_attr "length" "8")
546 (set_attr "type" "multiple")]
cffb2a26 547)
b11cae9e 548
f6c98a9a 549(define_expand "addv<mode>4"
550 [(match_operand:SIDI 0 "register_operand")
551 (match_operand:SIDI 1 "register_operand")
552 (match_operand:SIDI 2 "register_operand")
553 (match_operand 3 "")]
554 "TARGET_32BIT"
555{
556 emit_insn (gen_add<mode>3_compareV (operands[0], operands[1], operands[2]));
557 arm_gen_unlikely_cbranch (NE, CC_Vmode, operands[3]);
558
559 DONE;
560})
561
562(define_expand "uaddv<mode>4"
563 [(match_operand:SIDI 0 "register_operand")
564 (match_operand:SIDI 1 "register_operand")
565 (match_operand:SIDI 2 "register_operand")
566 (match_operand 3 "")]
567 "TARGET_32BIT"
568{
569 emit_insn (gen_add<mode>3_compareC (operands[0], operands[1], operands[2]));
570 arm_gen_unlikely_cbranch (NE, CC_Cmode, operands[3]);
571
572 DONE;
573})
574
87b22bf7 575(define_expand "addsi3"
cffb2a26 576 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 577 (plus:SI (match_operand:SI 1 "s_register_operand" "")
578 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 579 "TARGET_EITHER"
87b22bf7 580 "
0438d37f 581 if (TARGET_32BIT && CONST_INT_P (operands[2]))
87b22bf7 582 {
96f57e36 583 arm_split_constant (PLUS, SImode, NULL_RTX,
584 INTVAL (operands[2]), operands[0], operands[1],
e1ba4a27 585 optimize && can_create_pseudo_p ());
87b22bf7 586 DONE;
587 }
cffb2a26 588 "
589)
87b22bf7 590
5bd751ff 591; If there is a scratch available, this will be faster than synthesizing the
a0f94409 592; addition.
593(define_peephole2
594 [(match_scratch:SI 3 "r")
372575c7 595 (set (match_operand:SI 0 "arm_general_register_operand" "")
596 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
cffb2a26 597 (match_operand:SI 2 "const_int_operand" "")))]
25f905c2 598 "TARGET_32BIT &&
a0f94409 599 !(const_ok_for_arm (INTVAL (operands[2]))
600 || const_ok_for_arm (-INTVAL (operands[2])))
601 && const_ok_for_arm (~INTVAL (operands[2]))"
602 [(set (match_dup 3) (match_dup 2))
603 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
604 ""
605)
87b22bf7 606
2f02c19f 607;; The r/r/k alternative is required when reloading the address
608;; (plus (reg rN) (reg sp)) into (reg rN). In this case reload will
609;; put the duplicated register first, and not try the commutative version.
a0f94409 610(define_insn_and_split "*arm_addsi3"
fa1f9c9e 611 [(set (match_operand:SI 0 "s_register_operand" "=rk,l,l ,l ,r ,k ,r,k ,r ,k ,r ,k,k,r ,k ,r")
612 (plus:SI (match_operand:SI 1 "s_register_operand" "%0 ,l,0 ,l ,rk,k ,r,r ,rk,k ,rk,k,r,rk,k ,rk")
613 (match_operand:SI 2 "reg_or_int_operand" "rk ,l,Py,Pd,rI,rI,k,rI,Pj,Pj,L ,L,L,PJ,PJ,?n")))]
25f905c2 614 "TARGET_32BIT"
5565501b 615 "@
c24d855d 616 add%?\\t%0, %0, %2
5565501b 617 add%?\\t%0, %1, %2
a0b3420a 618 add%?\\t%0, %1, %2
7c36fe71 619 add%?\\t%0, %1, %2
620 add%?\\t%0, %1, %2
aaa37ad6 621 add%?\\t%0, %1, %2
2f02c19f 622 add%?\\t%0, %2, %1
fa1f9c9e 623 add%?\\t%0, %1, %2
d5cbae34 624 addw%?\\t%0, %1, %2
625 addw%?\\t%0, %1, %2
aaa37ad6 626 sub%?\\t%0, %1, #%n2
87b22bf7 627 sub%?\\t%0, %1, #%n2
d7757711 628 sub%?\\t%0, %1, #%n2
d5cbae34 629 subw%?\\t%0, %1, #%n2
630 subw%?\\t%0, %1, #%n2
87b22bf7 631 #"
a3ffc315 632 "TARGET_32BIT
0438d37f 633 && CONST_INT_P (operands[2])
d5cbae34 634 && !const_ok_for_op (INTVAL (operands[2]), PLUS)
a3ffc315 635 && (reload_completed || !arm_eliminable_register (operands[1]))"
a0f94409 636 [(clobber (const_int 0))]
637 "
96f57e36 638 arm_split_constant (PLUS, SImode, curr_insn,
639 INTVAL (operands[2]), operands[0],
a0f94409 640 operands[1], 0);
641 DONE;
642 "
fa1f9c9e 643 [(set_attr "length" "2,4,4,4,4,4,4,4,4,4,4,4,4,4,4,16")
d5cbae34 644 (set_attr "predicable" "yes")
fa1f9c9e 645 (set_attr "predicable_short_it" "yes,yes,yes,yes,no,no,no,no,no,no,no,no,no,no,no,no")
646 (set_attr "arch" "t2,t2,t2,t2,*,*,*,a,t2,t2,*,*,a,t2,t2,*")
65f68e55 647 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
d82e788e 648 (const_string "alu_imm")
112eda6f 649 (const_string "alu_sreg")))
65f68e55 650 ]
cffb2a26 651)
652
f6c98a9a 653(define_insn_and_split "adddi3_compareV"
654 [(set (reg:CC_V CC_REGNUM)
655 (ne:CC_V
656 (plus:TI
657 (sign_extend:TI (match_operand:DI 1 "register_operand" "r"))
658 (sign_extend:TI (match_operand:DI 2 "register_operand" "r")))
659 (sign_extend:TI (plus:DI (match_dup 1) (match_dup 2)))))
660 (set (match_operand:DI 0 "register_operand" "=&r")
661 (plus:DI (match_dup 1) (match_dup 2)))]
662 "TARGET_32BIT"
663 "#"
664 "&& reload_completed"
665 [(parallel [(set (reg:CC_C CC_REGNUM)
666 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
667 (match_dup 1)))
668 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
669 (parallel [(set (reg:CC_V CC_REGNUM)
670 (ne:CC_V
671 (plus:DI (plus:DI
672 (sign_extend:DI (match_dup 4))
673 (sign_extend:DI (match_dup 5)))
674 (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0)))
675 (plus:DI (sign_extend:DI
676 (plus:SI (match_dup 4) (match_dup 5)))
677 (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0)))))
678 (set (match_dup 3) (plus:SI (plus:SI
679 (match_dup 4) (match_dup 5))
680 (ltu:SI (reg:CC_C CC_REGNUM)
681 (const_int 0))))])]
682 "
683 {
684 operands[3] = gen_highpart (SImode, operands[0]);
685 operands[0] = gen_lowpart (SImode, operands[0]);
686 operands[4] = gen_highpart (SImode, operands[1]);
687 operands[1] = gen_lowpart (SImode, operands[1]);
688 operands[5] = gen_highpart (SImode, operands[2]);
689 operands[2] = gen_lowpart (SImode, operands[2]);
690 }"
691 [(set_attr "conds" "set")
692 (set_attr "length" "8")
693 (set_attr "type" "multiple")]
694)
695
696(define_insn "addsi3_compareV"
697 [(set (reg:CC_V CC_REGNUM)
698 (ne:CC_V
699 (plus:DI
700 (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
701 (sign_extend:DI (match_operand:SI 2 "register_operand" "r")))
702 (sign_extend:DI (plus:SI (match_dup 1) (match_dup 2)))))
703 (set (match_operand:SI 0 "register_operand" "=r")
704 (plus:SI (match_dup 1) (match_dup 2)))]
705 "TARGET_32BIT"
706 "adds%?\\t%0, %1, %2"
707 [(set_attr "conds" "set")
708 (set_attr "type" "alus_sreg")]
709)
710
711(define_insn "*addsi3_compareV_upper"
712 [(set (reg:CC_V CC_REGNUM)
713 (ne:CC_V
714 (plus:DI
715 (plus:DI
716 (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
717 (sign_extend:DI (match_operand:SI 2 "register_operand" "r")))
718 (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0)))
719 (plus:DI (sign_extend:DI
720 (plus:SI (match_dup 1) (match_dup 2)))
721 (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0)))))
722 (set (match_operand:SI 0 "register_operand" "=r")
723 (plus:SI
724 (plus:SI (match_dup 1) (match_dup 2))
725 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
726 "TARGET_32BIT"
727 "adcs%?\\t%0, %1, %2"
728 [(set_attr "conds" "set")
729 (set_attr "type" "adcs_reg")]
730)
731
732(define_insn_and_split "adddi3_compareC"
733 [(set (reg:CC_C CC_REGNUM)
734 (ne:CC_C
735 (plus:TI
736 (zero_extend:TI (match_operand:DI 1 "register_operand" "r"))
737 (zero_extend:TI (match_operand:DI 2 "register_operand" "r")))
738 (zero_extend:TI (plus:DI (match_dup 1) (match_dup 2)))))
739 (set (match_operand:DI 0 "register_operand" "=&r")
740 (plus:DI (match_dup 1) (match_dup 2)))]
741 "TARGET_32BIT"
742 "#"
743 "&& reload_completed"
744 [(parallel [(set (reg:CC_C CC_REGNUM)
745 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
746 (match_dup 1)))
747 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
748 (parallel [(set (reg:CC_C CC_REGNUM)
749 (ne:CC_C
750 (plus:DI (plus:DI
751 (zero_extend:DI (match_dup 4))
752 (zero_extend:DI (match_dup 5)))
753 (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0)))
754 (plus:DI (zero_extend:DI
755 (plus:SI (match_dup 4) (match_dup 5)))
756 (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0)))))
757 (set (match_dup 3) (plus:SI
758 (plus:SI (match_dup 4) (match_dup 5))
759 (ltu:SI (reg:CC_C CC_REGNUM)
760 (const_int 0))))])]
761 "
762 {
763 operands[3] = gen_highpart (SImode, operands[0]);
764 operands[0] = gen_lowpart (SImode, operands[0]);
765 operands[4] = gen_highpart (SImode, operands[1]);
766 operands[5] = gen_highpart (SImode, operands[2]);
767 operands[1] = gen_lowpart (SImode, operands[1]);
768 operands[2] = gen_lowpart (SImode, operands[2]);
769 }"
770 [(set_attr "conds" "set")
771 (set_attr "length" "8")
772 (set_attr "type" "multiple")]
773)
774
775(define_insn "*addsi3_compareC_upper"
776 [(set (reg:CC_C CC_REGNUM)
777 (ne:CC_C
778 (plus:DI
779 (plus:DI
780 (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
781 (zero_extend:DI (match_operand:SI 2 "register_operand" "r")))
782 (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0)))
783 (plus:DI (zero_extend:DI
784 (plus:SI (match_dup 1) (match_dup 2)))
785 (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0)))))
786 (set (match_operand:SI 0 "register_operand" "=r")
787 (plus:SI
788 (plus:SI (match_dup 1) (match_dup 2))
789 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
790 "TARGET_32BIT"
791 "adcs%?\\t%0, %1, %2"
792 [(set_attr "conds" "set")
793 (set_attr "type" "adcs_reg")]
794)
795
796(define_insn "addsi3_compareC"
797 [(set (reg:CC_C CC_REGNUM)
798 (ne:CC_C
799 (plus:DI
800 (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
801 (zero_extend:DI (match_operand:SI 2 "register_operand" "r")))
802 (zero_extend:DI
803 (plus:SI (match_dup 1) (match_dup 2)))))
804 (set (match_operand:SI 0 "register_operand" "=r")
805 (plus:SI (match_dup 1) (match_dup 2)))]
806 "TARGET_32BIT"
807 "adds%?\\t%0, %1, %2"
808 [(set_attr "conds" "set")
809 (set_attr "type" "alus_sreg")]
810)
811
90c2bcf0 812(define_insn "addsi3_compare0"
bd5b4116 813 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 814 (compare:CC_NOOV
65f68e55 815 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r,r")
816 (match_operand:SI 2 "arm_add_operand" "I,L,r"))
5565501b 817 (const_int 0)))
65f68e55 818 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9c08d1fa 819 (plus:SI (match_dup 1) (match_dup 2)))]
ec792a7b 820 "TARGET_ARM"
5565501b 821 "@
3ef90e77 822 adds%?\\t%0, %1, %2
823 subs%?\\t%0, %1, #%n2
824 adds%?\\t%0, %1, %2"
65f68e55 825 [(set_attr "conds" "set")
112eda6f 826 (set_attr "type" "alus_imm,alus_imm,alus_sreg")]
cffb2a26 827)
9c08d1fa 828
aea4c774 829(define_insn "*addsi3_compare0_scratch"
bd5b4116 830 [(set (reg:CC_NOOV CC_REGNUM)
aea4c774 831 (compare:CC_NOOV
65f68e55 832 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r, r")
833 (match_operand:SI 1 "arm_add_operand" "I,L, r"))
aea4c774 834 (const_int 0)))]
ec792a7b 835 "TARGET_ARM"
cffb2a26 836 "@
837 cmn%?\\t%0, %1
65f68e55 838 cmp%?\\t%0, #%n1
839 cmn%?\\t%0, %1"
596e5e8f 840 [(set_attr "conds" "set")
65f68e55 841 (set_attr "predicable" "yes")
112eda6f 842 (set_attr "type" "alus_imm,alus_imm,alus_sreg")]
0d66636f 843)
cffb2a26 844
aed179ae 845(define_insn "*compare_negsi_si"
846 [(set (reg:CC_Z CC_REGNUM)
847 (compare:CC_Z
7c36fe71 848 (neg:SI (match_operand:SI 0 "s_register_operand" "l,r"))
849 (match_operand:SI 1 "s_register_operand" "l,r")))]
25f905c2 850 "TARGET_32BIT"
aed179ae 851 "cmn%?\\t%1, %0"
596e5e8f 852 [(set_attr "conds" "set")
7c36fe71 853 (set_attr "predicable" "yes")
854 (set_attr "arch" "t2,*")
855 (set_attr "length" "2,4")
1b7da4ac 856 (set_attr "predicable_short_it" "yes,no")
112eda6f 857 (set_attr "type" "alus_sreg")]
0d66636f 858)
aea4c774 859
203c488f 860;; This is the canonicalization of addsi3_compare0_for_combiner when the
861;; addend is a constant.
190efb17 862(define_insn "cmpsi2_addneg"
203c488f 863 [(set (reg:CC CC_REGNUM)
864 (compare:CC
865 (match_operand:SI 1 "s_register_operand" "r,r")
2a977b78 866 (match_operand:SI 2 "arm_addimm_operand" "L,I")))
203c488f 867 (set (match_operand:SI 0 "s_register_operand" "=r,r")
868 (plus:SI (match_dup 1)
2a977b78 869 (match_operand:SI 3 "arm_addimm_operand" "I,L")))]
25f905c2 870 "TARGET_32BIT && INTVAL (operands[2]) == -INTVAL (operands[3])"
203c488f 871 "@
3ef90e77 872 adds%?\\t%0, %1, %3
873 subs%?\\t%0, %1, #%n3"
1b7da4ac 874 [(set_attr "conds" "set")
112eda6f 875 (set_attr "type" "alus_sreg")]
203c488f 876)
877
878;; Convert the sequence
879;; sub rd, rn, #1
880;; cmn rd, #1 (equivalent to cmp rd, #-1)
881;; bne dest
882;; into
883;; subs rd, rn, #1
884;; bcs dest ((unsigned)rn >= 1)
885;; similarly for the beq variant using bcc.
886;; This is a common looping idiom (while (n--))
887(define_peephole2
372575c7 888 [(set (match_operand:SI 0 "arm_general_register_operand" "")
889 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
203c488f 890 (const_int -1)))
891 (set (match_operand 2 "cc_register" "")
892 (compare (match_dup 0) (const_int -1)))
893 (set (pc)
894 (if_then_else (match_operator 3 "equality_operator"
895 [(match_dup 2) (const_int 0)])
896 (match_operand 4 "" "")
897 (match_operand 5 "" "")))]
25f905c2 898 "TARGET_32BIT && peep2_reg_dead_p (3, operands[2])"
203c488f 899 [(parallel[
900 (set (match_dup 2)
901 (compare:CC
902 (match_dup 1) (const_int 1)))
903 (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
904 (set (pc)
905 (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
906 (match_dup 4)
907 (match_dup 5)))]
908 "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
909 operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
910 ? GEU : LTU),
911 VOIDmode,
912 operands[2], const0_rtx);"
913)
914
ebcc79bc 915;; The next four insns work because they compare the result with one of
916;; the operands, and we know that the use of the condition code is
917;; either GEU or LTU, so we can use the carry flag from the addition
918;; instead of doing the compare a second time.
919(define_insn "*addsi3_compare_op1"
bd5b4116 920 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 921 (compare:CC_C
65f68e55 922 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
923 (match_operand:SI 2 "arm_add_operand" "I,L,r"))
ebcc79bc 924 (match_dup 1)))
65f68e55 925 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
ebcc79bc 926 (plus:SI (match_dup 1) (match_dup 2)))]
25f905c2 927 "TARGET_32BIT"
ebcc79bc 928 "@
3ef90e77 929 adds%?\\t%0, %1, %2
930 subs%?\\t%0, %1, #%n2
931 adds%?\\t%0, %1, %2"
65f68e55 932 [(set_attr "conds" "set")
112eda6f 933 (set_attr "type" "alus_imm,alus_imm,alus_sreg")]
0d66636f 934)
ebcc79bc 935
936(define_insn "*addsi3_compare_op2"
bd5b4116 937 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 938 (compare:CC_C
65f68e55 939 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
940 (match_operand:SI 2 "arm_add_operand" "I,L,r"))
ebcc79bc 941 (match_dup 2)))
65f68e55 942 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9c08d1fa 943 (plus:SI (match_dup 1) (match_dup 2)))]
25f905c2 944 "TARGET_32BIT"
5565501b 945 "@
3ef90e77 946 adds%?\\t%0, %1, %2
38128b57 947 subs%?\\t%0, %1, #%n2
948 adds%?\\t%0, %1, %2"
65f68e55 949 [(set_attr "conds" "set")
112eda6f 950 (set_attr "type" "alus_imm,alus_imm,alus_sreg")]
0d66636f 951)
9c08d1fa 952
ebcc79bc 953(define_insn "*compare_addsi2_op0"
bd5b4116 954 [(set (reg:CC_C CC_REGNUM)
7c36fe71 955 (compare:CC_C
956 (plus:SI (match_operand:SI 0 "s_register_operand" "l,l,r,r,r")
957 (match_operand:SI 1 "arm_add_operand" "Pv,l,I,L,r"))
958 (match_dup 0)))]
25f905c2 959 "TARGET_32BIT"
ebcc79bc 960 "@
7c36fe71 961 cmp%?\\t%0, #%n1
962 cmn%?\\t%0, %1
ebcc79bc 963 cmn%?\\t%0, %1
65f68e55 964 cmp%?\\t%0, #%n1
965 cmn%?\\t%0, %1"
596e5e8f 966 [(set_attr "conds" "set")
65f68e55 967 (set_attr "predicable" "yes")
7c36fe71 968 (set_attr "arch" "t2,t2,*,*,*")
969 (set_attr "predicable_short_it" "yes,yes,no,no,no")
970 (set_attr "length" "2,2,4,4,4")
112eda6f 971 (set_attr "type" "alus_imm,alus_sreg,alus_imm,alus_imm,alus_sreg")]
0d66636f 972)
ebcc79bc 973
974(define_insn "*compare_addsi2_op1"
bd5b4116 975 [(set (reg:CC_C CC_REGNUM)
7c36fe71 976 (compare:CC_C
977 (plus:SI (match_operand:SI 0 "s_register_operand" "l,l,r,r,r")
978 (match_operand:SI 1 "arm_add_operand" "Pv,l,I,L,r"))
979 (match_dup 1)))]
25f905c2 980 "TARGET_32BIT"
ebcc79bc 981 "@
7c36fe71 982 cmp%?\\t%0, #%n1
983 cmn%?\\t%0, %1
ebcc79bc 984 cmn%?\\t%0, %1
65f68e55 985 cmp%?\\t%0, #%n1
986 cmn%?\\t%0, %1"
596e5e8f 987 [(set_attr "conds" "set")
65f68e55 988 (set_attr "predicable" "yes")
7c36fe71 989 (set_attr "arch" "t2,t2,*,*,*")
990 (set_attr "predicable_short_it" "yes,yes,no,no,no")
991 (set_attr "length" "2,2,4,4,4")
112eda6f 992 (set_attr "type" "alus_imm,alus_sreg,alus_imm,alus_imm,alus_sreg")]
7c36fe71 993 )
ebcc79bc 994
080c0b9a 995(define_insn "*addsi3_carryin_<optab>"
7c36fe71 996 [(set (match_operand:SI 0 "s_register_operand" "=l,r,r")
997 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%l,r,r")
998 (match_operand:SI 2 "arm_not_operand" "0,rI,K"))
999 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))]
25f905c2 1000 "TARGET_32BIT"
10e5ccd5 1001 "@
a0b3420a 1002 adc%?\\t%0, %1, %2
10e5ccd5 1003 adc%?\\t%0, %1, %2
1004 sbc%?\\t%0, %1, #%B2"
a7de272d 1005 [(set_attr "conds" "use")
7c36fe71 1006 (set_attr "predicable" "yes")
1007 (set_attr "arch" "t2,*,*")
1008 (set_attr "length" "4")
1b7da4ac 1009 (set_attr "predicable_short_it" "yes,no,no")
1010 (set_attr "type" "adc_reg,adc_reg,adc_imm")]
cffb2a26 1011)
ebcc79bc 1012
080c0b9a 1013(define_insn "*addsi3_carryin_alt2_<optab>"
7c36fe71 1014 [(set (match_operand:SI 0 "s_register_operand" "=l,r,r")
1015 (plus:SI (plus:SI (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))
1016 (match_operand:SI 1 "s_register_operand" "%l,r,r"))
1017 (match_operand:SI 2 "arm_rhs_operand" "l,rI,K")))]
25f905c2 1018 "TARGET_32BIT"
10e5ccd5 1019 "@
a0b3420a 1020 adc%?\\t%0, %1, %2
10e5ccd5 1021 adc%?\\t%0, %1, %2
1022 sbc%?\\t%0, %1, #%B2"
a7de272d 1023 [(set_attr "conds" "use")
7c36fe71 1024 (set_attr "predicable" "yes")
1025 (set_attr "arch" "t2,*,*")
1026 (set_attr "length" "4")
1b7da4ac 1027 (set_attr "predicable_short_it" "yes,no,no")
1028 (set_attr "type" "adc_reg,adc_reg,adc_imm")]
0d66636f 1029)
ebcc79bc 1030
080c0b9a 1031(define_insn "*addsi3_carryin_shift_<optab>"
ebcc79bc 1032 [(set (match_operand:SI 0 "s_register_operand" "=r")
080c0b9a 1033 (plus:SI (plus:SI
1034 (match_operator:SI 2 "shift_operator"
1035 [(match_operand:SI 3 "s_register_operand" "r")
1036 (match_operand:SI 4 "reg_or_int_operand" "rM")])
1037 (match_operand:SI 1 "s_register_operand" "r"))
1038 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))]
25f905c2 1039 "TARGET_32BIT"
080c0b9a 1040 "adc%?\\t%0, %1, %3%S2"
1041 [(set_attr "conds" "use")
a7de272d 1042 (set_attr "predicable" "yes")
080c0b9a 1043 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
d82e788e 1044 (const_string "alu_shift_imm")
1045 (const_string "alu_shift_reg")))]
cffb2a26 1046)
ebcc79bc 1047
922b6913 1048(define_insn "*addsi3_carryin_clobercc_<optab>"
1049 [(set (match_operand:SI 0 "s_register_operand" "=r")
1050 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%r")
1051 (match_operand:SI 2 "arm_rhs_operand" "rI"))
1052 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))
1053 (clobber (reg:CC CC_REGNUM))]
1054 "TARGET_32BIT"
3ef90e77 1055 "adcs%?\\t%0, %1, %2"
1b7da4ac 1056 [(set_attr "conds" "set")
1057 (set_attr "type" "adcs_reg")]
922b6913 1058)
1059
f6c98a9a 1060(define_expand "subv<mode>4"
1061 [(match_operand:SIDI 0 "register_operand")
1062 (match_operand:SIDI 1 "register_operand")
1063 (match_operand:SIDI 2 "register_operand")
1064 (match_operand 3 "")]
1065 "TARGET_32BIT"
1066{
1067 emit_insn (gen_sub<mode>3_compare1 (operands[0], operands[1], operands[2]));
1068 arm_gen_unlikely_cbranch (NE, CC_Vmode, operands[3]);
1069
1070 DONE;
1071})
1072
1073(define_expand "usubv<mode>4"
1074 [(match_operand:SIDI 0 "register_operand")
1075 (match_operand:SIDI 1 "register_operand")
1076 (match_operand:SIDI 2 "register_operand")
1077 (match_operand 3 "")]
1078 "TARGET_32BIT"
1079{
1080 emit_insn (gen_sub<mode>3_compare1 (operands[0], operands[1], operands[2]));
1081 arm_gen_unlikely_cbranch (LTU, CCmode, operands[3]);
1082
1083 DONE;
1084})
1085
1086(define_insn_and_split "subdi3_compare1"
1087 [(set (reg:CC CC_REGNUM)
1088 (compare:CC
1089 (match_operand:DI 1 "register_operand" "r")
1090 (match_operand:DI 2 "register_operand" "r")))
1091 (set (match_operand:DI 0 "register_operand" "=&r")
1092 (minus:DI (match_dup 1) (match_dup 2)))]
1093 "TARGET_32BIT"
1094 "#"
1095 "&& reload_completed"
1096 [(parallel [(set (reg:CC CC_REGNUM)
1097 (compare:CC (match_dup 1) (match_dup 2)))
1098 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1099 (parallel [(set (reg:CC CC_REGNUM)
1100 (compare:CC (match_dup 4) (match_dup 5)))
1101 (set (match_dup 3) (minus:SI (minus:SI (match_dup 4) (match_dup 5))
1102 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))])]
1103 {
1104 operands[3] = gen_highpart (SImode, operands[0]);
1105 operands[0] = gen_lowpart (SImode, operands[0]);
1106 operands[4] = gen_highpart (SImode, operands[1]);
1107 operands[1] = gen_lowpart (SImode, operands[1]);
1108 operands[5] = gen_highpart (SImode, operands[2]);
1109 operands[2] = gen_lowpart (SImode, operands[2]);
1110 }
1111 [(set_attr "conds" "set")
1112 (set_attr "length" "8")
1113 (set_attr "type" "multiple")]
1114)
1115
1116(define_insn "subsi3_compare1"
1117 [(set (reg:CC CC_REGNUM)
1118 (compare:CC
1119 (match_operand:SI 1 "register_operand" "r")
1120 (match_operand:SI 2 "register_operand" "r")))
1121 (set (match_operand:SI 0 "register_operand" "=r")
1122 (minus:SI (match_dup 1) (match_dup 2)))]
1123 "TARGET_32BIT"
1124 "subs%?\\t%0, %1, %2"
1125 [(set_attr "conds" "set")
1126 (set_attr "type" "alus_sreg")]
1127)
1128
9154bd82 1129(define_insn "*subsi3_carryin"
d5bf2b53 1130 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1131 (minus:SI (minus:SI (match_operand:SI 1 "reg_or_int_operand" "r,I,Pz")
1132 (match_operand:SI 2 "s_register_operand" "r,r,r"))
1133 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
9154bd82 1134 "TARGET_32BIT"
1135 "@
1136 sbc%?\\t%0, %1, %2
d5bf2b53 1137 rsc%?\\t%0, %2, %1
1138 sbc%?\\t%0, %2, %2, lsl #1"
9154bd82 1139 [(set_attr "conds" "use")
d5bf2b53 1140 (set_attr "arch" "*,a,t2")
7c36fe71 1141 (set_attr "predicable" "yes")
d5bf2b53 1142 (set_attr "type" "adc_reg,adc_imm,alu_shift_imm")]
9154bd82 1143)
1144
1145(define_insn "*subsi3_carryin_const"
1146 [(set (match_operand:SI 0 "s_register_operand" "=r")
df46fd5e 1147 (minus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
16a3cf9c 1148 (match_operand:SI 2 "arm_neg_immediate_operand" "L"))
9154bd82 1149 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1150 "TARGET_32BIT"
16a3cf9c 1151 "sbc\\t%0, %1, #%n2"
1152 [(set_attr "conds" "use")
1153 (set_attr "type" "adc_imm")]
1154)
1155
1156(define_insn "*subsi3_carryin_const0"
1157 [(set (match_operand:SI 0 "s_register_operand" "=r")
1158 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
1159 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1160 "TARGET_32BIT"
1161 "sbc\\t%0, %1, #0"
1b7da4ac 1162 [(set_attr "conds" "use")
1163 (set_attr "type" "adc_imm")]
9154bd82 1164)
1165
1166(define_insn "*subsi3_carryin_compare"
1167 [(set (reg:CC CC_REGNUM)
1168 (compare:CC (match_operand:SI 1 "s_register_operand" "r")
1169 (match_operand:SI 2 "s_register_operand" "r")))
1170 (set (match_operand:SI 0 "s_register_operand" "=r")
1171 (minus:SI (minus:SI (match_dup 1)
1172 (match_dup 2))
1173 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1174 "TARGET_32BIT"
1175 "sbcs\\t%0, %1, %2"
1b7da4ac 1176 [(set_attr "conds" "set")
1177 (set_attr "type" "adcs_reg")]
9154bd82 1178)
1179
1180(define_insn "*subsi3_carryin_compare_const"
1181 [(set (reg:CC CC_REGNUM)
1182 (compare:CC (match_operand:SI 1 "reg_or_int_operand" "r")
16a3cf9c 1183 (match_operand:SI 2 "const_int_I_operand" "I")))
9154bd82 1184 (set (match_operand:SI 0 "s_register_operand" "=r")
1185 (minus:SI (plus:SI (match_dup 1)
16a3cf9c 1186 (match_operand:SI 3 "arm_neg_immediate_operand" "L"))
1187 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
2b363585 1188 "TARGET_32BIT
1189 && (INTVAL (operands[2])
1190 == trunc_int_for_mode (-INTVAL (operands[3]), SImode))"
16a3cf9c 1191 "sbcs\\t%0, %1, #%n3"
1192 [(set_attr "conds" "set")
1193 (set_attr "type" "adcs_imm")]
1194)
1195
1196(define_insn "*subsi3_carryin_compare_const0"
1197 [(set (reg:CC CC_REGNUM)
1198 (compare:CC (match_operand:SI 1 "reg_or_int_operand" "r")
1199 (const_int 0)))
1200 (set (match_operand:SI 0 "s_register_operand" "=r")
1201 (minus:SI (match_dup 1)
9154bd82 1202 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1203 "TARGET_32BIT"
16a3cf9c 1204 "sbcs\\t%0, %1, #0"
1b7da4ac 1205 [(set_attr "conds" "set")
1206 (set_attr "type" "adcs_imm")]
9154bd82 1207)
1208
1209(define_insn "*subsi3_carryin_shift"
1210 [(set (match_operand:SI 0 "s_register_operand" "=r")
1211 (minus:SI (minus:SI
1212 (match_operand:SI 1 "s_register_operand" "r")
1213 (match_operator:SI 2 "shift_operator"
1214 [(match_operand:SI 3 "s_register_operand" "r")
1215 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
1216 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1217 "TARGET_32BIT"
1218 "sbc%?\\t%0, %1, %3%S2"
1219 [(set_attr "conds" "use")
1220 (set_attr "predicable" "yes")
1221 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
d82e788e 1222 (const_string "alu_shift_imm")
1223 (const_string "alu_shift_reg")))]
9154bd82 1224)
1225
1226(define_insn "*rsbsi3_carryin_shift"
1227 [(set (match_operand:SI 0 "s_register_operand" "=r")
1228 (minus:SI (minus:SI
1229 (match_operator:SI 2 "shift_operator"
1230 [(match_operand:SI 3 "s_register_operand" "r")
1231 (match_operand:SI 4 "reg_or_int_operand" "rM")])
1232 (match_operand:SI 1 "s_register_operand" "r"))
1233 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1234 "TARGET_ARM"
1235 "rsc%?\\t%0, %1, %3%S2"
1236 [(set_attr "conds" "use")
1237 (set_attr "predicable" "yes")
1238 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
d82e788e 1239 (const_string "alu_shift_imm")
1240 (const_string "alu_shift_reg")))]
9154bd82 1241)
1242
d795fb69 1243; transform ((x << y) - 1) to ~(~(x-1) << y) Where X is a constant.
1244(define_split
1245 [(set (match_operand:SI 0 "s_register_operand" "")
1246 (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
1247 (match_operand:SI 2 "s_register_operand" ""))
1248 (const_int -1)))
1249 (clobber (match_operand:SI 3 "s_register_operand" ""))]
25f905c2 1250 "TARGET_32BIT"
d795fb69 1251 [(set (match_dup 3) (match_dup 1))
1252 (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
1253 "
1254 operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
1255")
1256
604f3a0a 1257(define_expand "addsf3"
1258 [(set (match_operand:SF 0 "s_register_operand" "")
1259 (plus:SF (match_operand:SF 1 "s_register_operand" "")
d86c91f6 1260 (match_operand:SF 2 "s_register_operand" "")))]
25f905c2 1261 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1262 "
604f3a0a 1263")
1264
604f3a0a 1265(define_expand "adddf3"
1266 [(set (match_operand:DF 0 "s_register_operand" "")
1267 (plus:DF (match_operand:DF 1 "s_register_operand" "")
d86c91f6 1268 (match_operand:DF 2 "s_register_operand" "")))]
a50d7267 1269 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 1270 "
604f3a0a 1271")
1272
cffb2a26 1273(define_expand "subdi3"
1274 [(parallel
1275 [(set (match_operand:DI 0 "s_register_operand" "")
1276 (minus:DI (match_operand:DI 1 "s_register_operand" "")
1277 (match_operand:DI 2 "s_register_operand" "")))
bd5b4116 1278 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 1279 "TARGET_EITHER"
1280 "
25f905c2 1281 if (TARGET_THUMB1)
cffb2a26 1282 {
0438d37f 1283 if (!REG_P (operands[1]))
5aa8c5f0 1284 operands[1] = force_reg (DImode, operands[1]);
0438d37f 1285 if (!REG_P (operands[2]))
5aa8c5f0 1286 operands[2] = force_reg (DImode, operands[2]);
cffb2a26 1287 }
1288 "
1289)
1290
2f9b23e3 1291(define_insn_and_split "*arm_subdi3"
206f0a3f 1292 [(set (match_operand:DI 0 "arm_general_register_operand" "=&r,&r,&r")
1293 (minus:DI (match_operand:DI 1 "arm_general_register_operand" "0,r,0")
1294 (match_operand:DI 2 "arm_general_register_operand" "r,0,0")))
bd5b4116 1295 (clobber (reg:CC CC_REGNUM))]
94829feb 1296 "TARGET_32BIT && !TARGET_NEON"
2f9b23e3 1297 "#" ; "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
0d84c6e5 1298 "&& (!TARGET_IWMMXT || reload_completed)"
2f9b23e3 1299 [(parallel [(set (reg:CC CC_REGNUM)
1300 (compare:CC (match_dup 1) (match_dup 2)))
1301 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1302 (set (match_dup 3) (minus:SI (minus:SI (match_dup 4) (match_dup 5))
1303 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1304 {
1305 operands[3] = gen_highpart (SImode, operands[0]);
1306 operands[0] = gen_lowpart (SImode, operands[0]);
1307 operands[4] = gen_highpart (SImode, operands[1]);
1308 operands[1] = gen_lowpart (SImode, operands[1]);
1309 operands[5] = gen_highpart (SImode, operands[2]);
1310 operands[2] = gen_lowpart (SImode, operands[2]);
1311 }
cffb2a26 1312 [(set_attr "conds" "clob")
1b7da4ac 1313 (set_attr "length" "8")
1314 (set_attr "type" "multiple")]
cffb2a26 1315)
1316
2f9b23e3 1317(define_insn_and_split "*subdi_di_zesidi"
cffb2a26 1318 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 1319 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r")
9c08d1fa 1320 (zero_extend:DI
cffb2a26 1321 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 1322 (clobber (reg:CC CC_REGNUM))]
25f905c2 1323 "TARGET_32BIT"
2f9b23e3 1324 "#" ; "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
1325 "&& reload_completed"
1326 [(parallel [(set (reg:CC CC_REGNUM)
1327 (compare:CC (match_dup 1) (match_dup 2)))
1328 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
16a3cf9c 1329 (set (match_dup 3) (minus:SI (match_dup 4)
2f9b23e3 1330 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1331 {
1332 operands[3] = gen_highpart (SImode, operands[0]);
1333 operands[0] = gen_lowpart (SImode, operands[0]);
1334 operands[4] = gen_highpart (SImode, operands[1]);
1335 operands[1] = gen_lowpart (SImode, operands[1]);
2f9b23e3 1336 }
cffb2a26 1337 [(set_attr "conds" "clob")
1b7da4ac 1338 (set_attr "length" "8")
1339 (set_attr "type" "multiple")]
cffb2a26 1340)
9c08d1fa 1341
2f9b23e3 1342(define_insn_and_split "*subdi_di_sesidi"
cffb2a26 1343 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 1344 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r")
9c08d1fa 1345 (sign_extend:DI
cffb2a26 1346 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 1347 (clobber (reg:CC CC_REGNUM))]
25f905c2 1348 "TARGET_32BIT"
2f9b23e3 1349 "#" ; "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
1350 "&& reload_completed"
1351 [(parallel [(set (reg:CC CC_REGNUM)
1352 (compare:CC (match_dup 1) (match_dup 2)))
1353 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1354 (set (match_dup 3) (minus:SI (minus:SI (match_dup 4)
1355 (ashiftrt:SI (match_dup 2)
1356 (const_int 31)))
1357 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1358 {
1359 operands[3] = gen_highpart (SImode, operands[0]);
1360 operands[0] = gen_lowpart (SImode, operands[0]);
1361 operands[4] = gen_highpart (SImode, operands[1]);
1362 operands[1] = gen_lowpart (SImode, operands[1]);
1363 }
cffb2a26 1364 [(set_attr "conds" "clob")
1b7da4ac 1365 (set_attr "length" "8")
1366 (set_attr "type" "multiple")]
cffb2a26 1367)
9c08d1fa 1368
2f9b23e3 1369(define_insn_and_split "*subdi_zesidi_di"
cffb2a26 1370 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1371 (minus:DI (zero_extend:DI
cffb2a26 1372 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 1373 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 1374 (clobber (reg:CC CC_REGNUM))]
cffb2a26 1375 "TARGET_ARM"
2f9b23e3 1376 "#" ; "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
1377 ; is equivalent to:
1378 ; "subs\\t%Q0, %2, %Q1\;rsc\\t%R0, %R1, #0"
1379 "&& reload_completed"
1380 [(parallel [(set (reg:CC CC_REGNUM)
1381 (compare:CC (match_dup 2) (match_dup 1)))
1382 (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))])
1383 (set (match_dup 3) (minus:SI (minus:SI (const_int 0) (match_dup 4))
1384 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1385 {
1386 operands[3] = gen_highpart (SImode, operands[0]);
1387 operands[0] = gen_lowpart (SImode, operands[0]);
1388 operands[4] = gen_highpart (SImode, operands[1]);
1389 operands[1] = gen_lowpart (SImode, operands[1]);
1390 }
cffb2a26 1391 [(set_attr "conds" "clob")
1b7da4ac 1392 (set_attr "length" "8")
1393 (set_attr "type" "multiple")]
cffb2a26 1394)
9c08d1fa 1395
2f9b23e3 1396(define_insn_and_split "*subdi_sesidi_di"
cffb2a26 1397 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1398 (minus:DI (sign_extend:DI
cffb2a26 1399 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 1400 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 1401 (clobber (reg:CC CC_REGNUM))]
cffb2a26 1402 "TARGET_ARM"
2f9b23e3 1403 "#" ; "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
1404 ; is equivalent to:
1405 ; "subs\\t%Q0, %2, %Q1\;rsc\\t%R0, %R1, %2, asr #31"
1406 "&& reload_completed"
1407 [(parallel [(set (reg:CC CC_REGNUM)
1408 (compare:CC (match_dup 2) (match_dup 1)))
1409 (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))])
1410 (set (match_dup 3) (minus:SI (minus:SI
1411 (ashiftrt:SI (match_dup 2)
1412 (const_int 31))
1413 (match_dup 4))
1414 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1415 {
1416 operands[3] = gen_highpart (SImode, operands[0]);
1417 operands[0] = gen_lowpart (SImode, operands[0]);
1418 operands[4] = gen_highpart (SImode, operands[1]);
1419 operands[1] = gen_lowpart (SImode, operands[1]);
1420 }
cffb2a26 1421 [(set_attr "conds" "clob")
1b7da4ac 1422 (set_attr "length" "8")
1423 (set_attr "type" "multiple")]
cffb2a26 1424)
9c08d1fa 1425
2f9b23e3 1426(define_insn_and_split "*subdi_zesidi_zesidi"
cffb2a26 1427 [(set (match_operand:DI 0 "s_register_operand" "=r")
9c08d1fa 1428 (minus:DI (zero_extend:DI
cffb2a26 1429 (match_operand:SI 1 "s_register_operand" "r"))
9c08d1fa 1430 (zero_extend:DI
cffb2a26 1431 (match_operand:SI 2 "s_register_operand" "r"))))
bd5b4116 1432 (clobber (reg:CC CC_REGNUM))]
25f905c2 1433 "TARGET_32BIT"
2f9b23e3 1434 "#" ; "subs\\t%Q0, %1, %2\;sbc\\t%R0, %1, %1"
1435 "&& reload_completed"
1436 [(parallel [(set (reg:CC CC_REGNUM)
1437 (compare:CC (match_dup 1) (match_dup 2)))
1438 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1439 (set (match_dup 3) (minus:SI (minus:SI (match_dup 1) (match_dup 1))
1440 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1441 {
1442 operands[3] = gen_highpart (SImode, operands[0]);
1443 operands[0] = gen_lowpart (SImode, operands[0]);
1444 }
cffb2a26 1445 [(set_attr "conds" "clob")
1b7da4ac 1446 (set_attr "length" "8")
1447 (set_attr "type" "multiple")]
cffb2a26 1448)
b11cae9e 1449
87b22bf7 1450(define_expand "subsi3"
cffb2a26 1451 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 1452 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
1453 (match_operand:SI 2 "s_register_operand" "")))]
cffb2a26 1454 "TARGET_EITHER"
87b22bf7 1455 "
0438d37f 1456 if (CONST_INT_P (operands[1]))
87b22bf7 1457 {
25f905c2 1458 if (TARGET_32BIT)
cffb2a26 1459 {
17202aa5 1460 if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[1]), MINUS))
1461 operands[1] = force_reg (SImode, operands[1]);
1462 else
1463 {
1464 arm_split_constant (MINUS, SImode, NULL_RTX,
1465 INTVAL (operands[1]), operands[0],
1466 operands[2],
1467 optimize && can_create_pseudo_p ());
1468 DONE;
1469 }
cffb2a26 1470 }
25f905c2 1471 else /* TARGET_THUMB1 */
cffb2a26 1472 operands[1] = force_reg (SImode, operands[1]);
87b22bf7 1473 }
cffb2a26 1474 "
1475)
87b22bf7 1476
25f905c2 1477; ??? Check Thumb-2 split length
a0f94409 1478(define_insn_and_split "*arm_subsi3_insn"
3a44c5a9 1479 [(set (match_operand:SI 0 "s_register_operand" "=l,l ,l ,l ,r,r,r,rk,r")
1480 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "l ,0 ,l ,Pz,I,r,r,k ,?n")
1481 (match_operand:SI 2 "reg_or_int_operand" "l ,Py,Pd,l ,r,I,r,r ,r")))]
25f905c2 1482 "TARGET_32BIT"
e2348bcb 1483 "@
7c36fe71 1484 sub%?\\t%0, %1, %2
1485 sub%?\\t%0, %2
1486 sub%?\\t%0, %1, %2
1487 rsb%?\\t%0, %2, %1
87b22bf7 1488 rsb%?\\t%0, %2, %1
aaa37ad6 1489 sub%?\\t%0, %1, %2
080c0b9a 1490 sub%?\\t%0, %1, %2
65f68e55 1491 sub%?\\t%0, %1, %2
87b22bf7 1492 #"
0438d37f 1493 "&& (CONST_INT_P (operands[1])
91a5e339 1494 && !const_ok_for_arm (INTVAL (operands[1])))"
87b22bf7 1495 [(clobber (const_int 0))]
1496 "
96f57e36 1497 arm_split_constant (MINUS, SImode, curr_insn,
1498 INTVAL (operands[1]), operands[0], operands[2], 0);
87b22bf7 1499 DONE;
cffb2a26 1500 "
7c36fe71 1501 [(set_attr "length" "4,4,4,4,4,4,4,4,16")
1502 (set_attr "arch" "t2,t2,t2,t2,*,*,*,*,*")
65f68e55 1503 (set_attr "predicable" "yes")
7c36fe71 1504 (set_attr "predicable_short_it" "yes,yes,yes,yes,no,no,no,no,no")
112eda6f 1505 (set_attr "type" "alu_sreg,alu_sreg,alu_sreg,alu_sreg,alu_imm,alu_imm,alu_sreg,alu_sreg,multiple")]
a0f94409 1506)
1507
1508(define_peephole2
1509 [(match_scratch:SI 3 "r")
372575c7 1510 (set (match_operand:SI 0 "arm_general_register_operand" "")
a0f94409 1511 (minus:SI (match_operand:SI 1 "const_int_operand" "")
372575c7 1512 (match_operand:SI 2 "arm_general_register_operand" "")))]
25f905c2 1513 "TARGET_32BIT
a0f94409 1514 && !const_ok_for_arm (INTVAL (operands[1]))
1515 && const_ok_for_arm (~INTVAL (operands[1]))"
1516 [(set (match_dup 3) (match_dup 1))
1517 (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1518 ""
cffb2a26 1519)
b11cae9e 1520
62e39b06 1521(define_insn "subsi3_compare0"
bd5b4116 1522 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1523 (compare:CC_NOOV
65f68e55 1524 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,r,I")
1525 (match_operand:SI 2 "arm_rhs_operand" "I,r,r"))
215b30b3 1526 (const_int 0)))
65f68e55 1527 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9c08d1fa 1528 (minus:SI (match_dup 1) (match_dup 2)))]
25f905c2 1529 "TARGET_32BIT"
e2348bcb 1530 "@
3ef90e77 1531 subs%?\\t%0, %1, %2
1532 subs%?\\t%0, %1, %2
1533 rsbs%?\\t%0, %2, %1"
65f68e55 1534 [(set_attr "conds" "set")
112eda6f 1535 (set_attr "type" "alus_imm,alus_sreg,alus_sreg")]
cffb2a26 1536)
9c08d1fa 1537
190efb17 1538(define_insn "subsi3_compare"
080c0b9a 1539 [(set (reg:CC CC_REGNUM)
65f68e55 1540 (compare:CC (match_operand:SI 1 "arm_rhs_operand" "r,r,I")
1541 (match_operand:SI 2 "arm_rhs_operand" "I,r,r")))
1542 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2df9477b 1543 (minus:SI (match_dup 1) (match_dup 2)))]
1544 "TARGET_32BIT"
1545 "@
3ef90e77 1546 subs%?\\t%0, %1, %2
1547 subs%?\\t%0, %1, %2
1548 rsbs%?\\t%0, %2, %1"
65f68e55 1549 [(set_attr "conds" "set")
112eda6f 1550 (set_attr "type" "alus_imm,alus_sreg,alus_sreg")]
2df9477b 1551)
1552
604f3a0a 1553(define_expand "subsf3"
1554 [(set (match_operand:SF 0 "s_register_operand" "")
d86c91f6 1555 (minus:SF (match_operand:SF 1 "s_register_operand" "")
1556 (match_operand:SF 2 "s_register_operand" "")))]
25f905c2 1557 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1558 "
604f3a0a 1559")
1560
604f3a0a 1561(define_expand "subdf3"
1562 [(set (match_operand:DF 0 "s_register_operand" "")
d86c91f6 1563 (minus:DF (match_operand:DF 1 "s_register_operand" "")
1564 (match_operand:DF 2 "s_register_operand" "")))]
a50d7267 1565 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 1566 "
604f3a0a 1567")
1568
b11cae9e 1569\f
1570;; Multiplication insns
1571
4422d91f 1572(define_expand "mulhi3"
1573 [(set (match_operand:HI 0 "s_register_operand" "")
1574 (mult:HI (match_operand:HI 1 "s_register_operand" "")
1575 (match_operand:HI 2 "s_register_operand" "")))]
1576 "TARGET_DSP_MULTIPLY"
1577 "
1578 {
1579 rtx result = gen_reg_rtx (SImode);
1580 emit_insn (gen_mulhisi3 (result, operands[1], operands[2]));
1581 emit_move_insn (operands[0], gen_lowpart (HImode, result));
1582 DONE;
1583 }"
1584)
1585
cffb2a26 1586(define_expand "mulsi3"
1587 [(set (match_operand:SI 0 "s_register_operand" "")
1588 (mult:SI (match_operand:SI 2 "s_register_operand" "")
1589 (match_operand:SI 1 "s_register_operand" "")))]
1590 "TARGET_EITHER"
1591 ""
1592)
1593
9c08d1fa 1594;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
cffb2a26 1595(define_insn "*arm_mulsi3"
1596 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1597 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1598 (match_operand:SI 1 "s_register_operand" "%0,r")))]
58d7d654 1599 "TARGET_32BIT && !arm_arch6"
f7fbdd4a 1600 "mul%?\\t%0, %2, %1"
9da0ec36 1601 [(set_attr "type" "mul")
0d66636f 1602 (set_attr "predicable" "yes")]
cffb2a26 1603)
1604
58d7d654 1605(define_insn "*arm_mulsi3_v6"
d952d547 1606 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
1607 (mult:SI (match_operand:SI 1 "s_register_operand" "0,l,r")
1608 (match_operand:SI 2 "s_register_operand" "l,0,r")))]
58d7d654 1609 "TARGET_32BIT && arm_arch6"
1610 "mul%?\\t%0, %1, %2"
9da0ec36 1611 [(set_attr "type" "mul")
d952d547 1612 (set_attr "predicable" "yes")
1613 (set_attr "arch" "t2,t2,*")
1614 (set_attr "length" "4")
1615 (set_attr "predicable_short_it" "yes,yes,no")]
58d7d654 1616)
1617
f7fbdd4a 1618(define_insn "*mulsi3_compare0"
bd5b4116 1619 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1620 (compare:CC_NOOV (mult:SI
1621 (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1622 (match_operand:SI 1 "s_register_operand" "%0,r"))
9c08d1fa 1623 (const_int 0)))
1624 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1625 (mult:SI (match_dup 2) (match_dup 1)))]
58d7d654 1626 "TARGET_ARM && !arm_arch6"
3ef90e77 1627 "muls%?\\t%0, %2, %1"
58d7d654 1628 [(set_attr "conds" "set")
9da0ec36 1629 (set_attr "type" "muls")]
58d7d654 1630)
1631
1632(define_insn "*mulsi3_compare0_v6"
1633 [(set (reg:CC_NOOV CC_REGNUM)
1634 (compare:CC_NOOV (mult:SI
1635 (match_operand:SI 2 "s_register_operand" "r")
1636 (match_operand:SI 1 "s_register_operand" "r"))
1637 (const_int 0)))
1638 (set (match_operand:SI 0 "s_register_operand" "=r")
1639 (mult:SI (match_dup 2) (match_dup 1)))]
1640 "TARGET_ARM && arm_arch6 && optimize_size"
3ef90e77 1641 "muls%?\\t%0, %2, %1"
cffb2a26 1642 [(set_attr "conds" "set")
9da0ec36 1643 (set_attr "type" "muls")]
cffb2a26 1644)
9c08d1fa 1645
f7fbdd4a 1646(define_insn "*mulsi_compare0_scratch"
bd5b4116 1647 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1648 (compare:CC_NOOV (mult:SI
1649 (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1650 (match_operand:SI 1 "s_register_operand" "%0,r"))
9c08d1fa 1651 (const_int 0)))
1652 (clobber (match_scratch:SI 0 "=&r,&r"))]
58d7d654 1653 "TARGET_ARM && !arm_arch6"
3ef90e77 1654 "muls%?\\t%0, %2, %1"
58d7d654 1655 [(set_attr "conds" "set")
9da0ec36 1656 (set_attr "type" "muls")]
58d7d654 1657)
1658
1659(define_insn "*mulsi_compare0_scratch_v6"
1660 [(set (reg:CC_NOOV CC_REGNUM)
1661 (compare:CC_NOOV (mult:SI
1662 (match_operand:SI 2 "s_register_operand" "r")
1663 (match_operand:SI 1 "s_register_operand" "r"))
1664 (const_int 0)))
1665 (clobber (match_scratch:SI 0 "=r"))]
1666 "TARGET_ARM && arm_arch6 && optimize_size"
3ef90e77 1667 "muls%?\\t%0, %2, %1"
cffb2a26 1668 [(set_attr "conds" "set")
9da0ec36 1669 (set_attr "type" "muls")]
cffb2a26 1670)
9c08d1fa 1671
b11cae9e 1672;; Unnamed templates to match MLA instruction.
1673
f7fbdd4a 1674(define_insn "*mulsi3addsi"
9c08d1fa 1675 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
c8f69309 1676 (plus:SI
9c08d1fa 1677 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1678 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1679 (match_operand:SI 3 "s_register_operand" "r,r,0,0")))]
58d7d654 1680 "TARGET_32BIT && !arm_arch6"
1681 "mla%?\\t%0, %2, %1, %3"
9da0ec36 1682 [(set_attr "type" "mla")
58d7d654 1683 (set_attr "predicable" "yes")]
1684)
1685
1686(define_insn "*mulsi3addsi_v6"
1687 [(set (match_operand:SI 0 "s_register_operand" "=r")
1688 (plus:SI
1689 (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1690 (match_operand:SI 1 "s_register_operand" "r"))
1691 (match_operand:SI 3 "s_register_operand" "r")))]
1692 "TARGET_32BIT && arm_arch6"
f7fbdd4a 1693 "mla%?\\t%0, %2, %1, %3"
9da0ec36 1694 [(set_attr "type" "mla")
8bdfd6ed 1695 (set_attr "predicable" "yes")]
0d66636f 1696)
b11cae9e 1697
f7fbdd4a 1698(define_insn "*mulsi3addsi_compare0"
bd5b4116 1699 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1700 (compare:CC_NOOV
1701 (plus:SI (mult:SI
1702 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1703 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1704 (match_operand:SI 3 "s_register_operand" "r,r,0,0"))
215b30b3 1705 (const_int 0)))
9c08d1fa 1706 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1707 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1708 (match_dup 3)))]
58d7d654 1709 "TARGET_ARM && arm_arch6"
3ef90e77 1710 "mlas%?\\t%0, %2, %1, %3"
58d7d654 1711 [(set_attr "conds" "set")
9da0ec36 1712 (set_attr "type" "mlas")]
58d7d654 1713)
1714
1715(define_insn "*mulsi3addsi_compare0_v6"
1716 [(set (reg:CC_NOOV CC_REGNUM)
1717 (compare:CC_NOOV
1718 (plus:SI (mult:SI
1719 (match_operand:SI 2 "s_register_operand" "r")
1720 (match_operand:SI 1 "s_register_operand" "r"))
1721 (match_operand:SI 3 "s_register_operand" "r"))
1722 (const_int 0)))
1723 (set (match_operand:SI 0 "s_register_operand" "=r")
1724 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1725 (match_dup 3)))]
1726 "TARGET_ARM && arm_arch6 && optimize_size"
3ef90e77 1727 "mlas%?\\t%0, %2, %1, %3"
0d66636f 1728 [(set_attr "conds" "set")
9da0ec36 1729 (set_attr "type" "mlas")]
0d66636f 1730)
9c08d1fa 1731
f7fbdd4a 1732(define_insn "*mulsi3addsi_compare0_scratch"
bd5b4116 1733 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1734 (compare:CC_NOOV
1735 (plus:SI (mult:SI
1736 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1737 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
215b30b3 1738 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1739 (const_int 0)))
9c08d1fa 1740 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
58d7d654 1741 "TARGET_ARM && !arm_arch6"
3ef90e77 1742 "mlas%?\\t%0, %2, %1, %3"
58d7d654 1743 [(set_attr "conds" "set")
9da0ec36 1744 (set_attr "type" "mlas")]
58d7d654 1745)
1746
1747(define_insn "*mulsi3addsi_compare0_scratch_v6"
1748 [(set (reg:CC_NOOV CC_REGNUM)
1749 (compare:CC_NOOV
1750 (plus:SI (mult:SI
1751 (match_operand:SI 2 "s_register_operand" "r")
1752 (match_operand:SI 1 "s_register_operand" "r"))
1753 (match_operand:SI 3 "s_register_operand" "r"))
1754 (const_int 0)))
1755 (clobber (match_scratch:SI 0 "=r"))]
1756 "TARGET_ARM && arm_arch6 && optimize_size"
3ef90e77 1757 "mlas%?\\t%0, %2, %1, %3"
cffb2a26 1758 [(set_attr "conds" "set")
9da0ec36 1759 (set_attr "type" "mlas")]
cffb2a26 1760)
f7fbdd4a 1761
89545238 1762(define_insn "*mulsi3subsi"
1763 [(set (match_operand:SI 0 "s_register_operand" "=r")
1764 (minus:SI
1765 (match_operand:SI 3 "s_register_operand" "r")
1766 (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1767 (match_operand:SI 1 "s_register_operand" "r"))))]
1768 "TARGET_32BIT && arm_arch_thumb2"
1769 "mls%?\\t%0, %2, %1, %3"
9da0ec36 1770 [(set_attr "type" "mla")
8bdfd6ed 1771 (set_attr "predicable" "yes")]
89545238 1772)
1773
5cdca009 1774(define_expand "maddsidi4"
1775 [(set (match_operand:DI 0 "s_register_operand" "")
1776 (plus:DI
1777 (mult:DI
1778 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1779 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1780 (match_operand:DI 3 "s_register_operand" "")))]
1930b04c 1781 "TARGET_32BIT"
5cdca009 1782 "")
82b85d08 1783
1784(define_insn "*mulsidi3adddi"
fe8dbf85 1785 [(set (match_operand:DI 0 "s_register_operand" "=&r")
82b85d08 1786 (plus:DI
215b30b3 1787 (mult:DI
fe8dbf85 1788 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1789 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1790 (match_operand:DI 1 "s_register_operand" "0")))]
1930b04c 1791 "TARGET_32BIT && !arm_arch6"
58d7d654 1792 "smlal%?\\t%Q0, %R0, %3, %2"
9da0ec36 1793 [(set_attr "type" "smlal")
58d7d654 1794 (set_attr "predicable" "yes")]
1795)
1796
1797(define_insn "*mulsidi3adddi_v6"
1798 [(set (match_operand:DI 0 "s_register_operand" "=r")
1799 (plus:DI
1800 (mult:DI
1801 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1802 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1803 (match_operand:DI 1 "s_register_operand" "0")))]
1804 "TARGET_32BIT && arm_arch6"
fe8dbf85 1805 "smlal%?\\t%Q0, %R0, %3, %2"
9da0ec36 1806 [(set_attr "type" "smlal")
8bdfd6ed 1807 (set_attr "predicable" "yes")]
0d66636f 1808)
82b85d08 1809
957788b0 1810;; 32x32->64 widening multiply.
1811;; As with mulsi3, the only difference between the v3-5 and v6+
1812;; versions of these patterns is the requirement that the output not
1813;; overlap the inputs, but that still means we have to have a named
1814;; expander and two different starred insns.
1815
1816(define_expand "mulsidi3"
1817 [(set (match_operand:DI 0 "s_register_operand" "")
1818 (mult:DI
1819 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1820 (sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1930b04c 1821 "TARGET_32BIT"
957788b0 1822 ""
1823)
1824
1825(define_insn "*mulsidi3_nov6"
f7fbdd4a 1826 [(set (match_operand:DI 0 "s_register_operand" "=&r")
215b30b3 1827 (mult:DI
1828 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1829 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1930b04c 1830 "TARGET_32BIT && !arm_arch6"
58d7d654 1831 "smull%?\\t%Q0, %R0, %1, %2"
9da0ec36 1832 [(set_attr "type" "smull")
58d7d654 1833 (set_attr "predicable" "yes")]
1834)
1835
957788b0 1836(define_insn "*mulsidi3_v6"
58d7d654 1837 [(set (match_operand:DI 0 "s_register_operand" "=r")
1838 (mult:DI
1839 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1840 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1841 "TARGET_32BIT && arm_arch6"
97499065 1842 "smull%?\\t%Q0, %R0, %1, %2"
9da0ec36 1843 [(set_attr "type" "smull")
8bdfd6ed 1844 (set_attr "predicable" "yes")]
0d66636f 1845)
f7fbdd4a 1846
957788b0 1847(define_expand "umulsidi3"
1848 [(set (match_operand:DI 0 "s_register_operand" "")
1849 (mult:DI
1850 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1851 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1930b04c 1852 "TARGET_32BIT"
957788b0 1853 ""
1854)
1855
1856(define_insn "*umulsidi3_nov6"
f7fbdd4a 1857 [(set (match_operand:DI 0 "s_register_operand" "=&r")
215b30b3 1858 (mult:DI
1859 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1860 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1930b04c 1861 "TARGET_32BIT && !arm_arch6"
58d7d654 1862 "umull%?\\t%Q0, %R0, %1, %2"
9da0ec36 1863 [(set_attr "type" "umull")
58d7d654 1864 (set_attr "predicable" "yes")]
1865)
1866
957788b0 1867(define_insn "*umulsidi3_v6"
58d7d654 1868 [(set (match_operand:DI 0 "s_register_operand" "=r")
1869 (mult:DI
1870 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1871 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1872 "TARGET_32BIT && arm_arch6"
97499065 1873 "umull%?\\t%Q0, %R0, %1, %2"
9da0ec36 1874 [(set_attr "type" "umull")
8bdfd6ed 1875 (set_attr "predicable" "yes")]
0d66636f 1876)
b11cae9e 1877
5cdca009 1878(define_expand "umaddsidi4"
1879 [(set (match_operand:DI 0 "s_register_operand" "")
1880 (plus:DI
1881 (mult:DI
1882 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1883 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1884 (match_operand:DI 3 "s_register_operand" "")))]
1930b04c 1885 "TARGET_32BIT"
5cdca009 1886 "")
82b85d08 1887
1888(define_insn "*umulsidi3adddi"
8ead09f9 1889 [(set (match_operand:DI 0 "s_register_operand" "=&r")
82b85d08 1890 (plus:DI
215b30b3 1891 (mult:DI
fe8dbf85 1892 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1893 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1894 (match_operand:DI 1 "s_register_operand" "0")))]
1930b04c 1895 "TARGET_32BIT && !arm_arch6"
58d7d654 1896 "umlal%?\\t%Q0, %R0, %3, %2"
9da0ec36 1897 [(set_attr "type" "umlal")
58d7d654 1898 (set_attr "predicable" "yes")]
1899)
1900
1901(define_insn "*umulsidi3adddi_v6"
1902 [(set (match_operand:DI 0 "s_register_operand" "=r")
1903 (plus:DI
1904 (mult:DI
1905 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1906 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1907 (match_operand:DI 1 "s_register_operand" "0")))]
1908 "TARGET_32BIT && arm_arch6"
fe8dbf85 1909 "umlal%?\\t%Q0, %R0, %3, %2"
9da0ec36 1910 [(set_attr "type" "umlal")
8bdfd6ed 1911 (set_attr "predicable" "yes")]
0d66636f 1912)
82b85d08 1913
957788b0 1914(define_expand "smulsi3_highpart"
1915 [(parallel
1916 [(set (match_operand:SI 0 "s_register_operand" "")
1917 (truncate:SI
1918 (lshiftrt:DI
1919 (mult:DI
1920 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1921 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1922 (const_int 32))))
1923 (clobber (match_scratch:SI 3 ""))])]
1930b04c 1924 "TARGET_32BIT"
957788b0 1925 ""
1926)
1927
1928(define_insn "*smulsi3_highpart_nov6"
f082f1c4 1929 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1930 (truncate:SI
1931 (lshiftrt:DI
215b30b3 1932 (mult:DI
e5fea38e 1933 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
215b30b3 1934 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
f082f1c4 1935 (const_int 32))))
1936 (clobber (match_scratch:SI 3 "=&r,&r"))]
1930b04c 1937 "TARGET_32BIT && !arm_arch6"
58d7d654 1938 "smull%?\\t%3, %0, %2, %1"
9da0ec36 1939 [(set_attr "type" "smull")
58d7d654 1940 (set_attr "predicable" "yes")]
1941)
1942
957788b0 1943(define_insn "*smulsi3_highpart_v6"
58d7d654 1944 [(set (match_operand:SI 0 "s_register_operand" "=r")
1945 (truncate:SI
1946 (lshiftrt:DI
1947 (mult:DI
1948 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1949 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1950 (const_int 32))))
1951 (clobber (match_scratch:SI 3 "=r"))]
1952 "TARGET_32BIT && arm_arch6"
f082f1c4 1953 "smull%?\\t%3, %0, %2, %1"
9da0ec36 1954 [(set_attr "type" "smull")
8bdfd6ed 1955 (set_attr "predicable" "yes")]
cffb2a26 1956)
f082f1c4 1957
957788b0 1958(define_expand "umulsi3_highpart"
1959 [(parallel
1960 [(set (match_operand:SI 0 "s_register_operand" "")
1961 (truncate:SI
1962 (lshiftrt:DI
1963 (mult:DI
1964 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1965 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1966 (const_int 32))))
1967 (clobber (match_scratch:SI 3 ""))])]
1930b04c 1968 "TARGET_32BIT"
957788b0 1969 ""
1970)
1971
1972(define_insn "*umulsi3_highpart_nov6"
f082f1c4 1973 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1974 (truncate:SI
1975 (lshiftrt:DI
215b30b3 1976 (mult:DI
e5fea38e 1977 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
215b30b3 1978 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
f082f1c4 1979 (const_int 32))))
1980 (clobber (match_scratch:SI 3 "=&r,&r"))]
1930b04c 1981 "TARGET_32BIT && !arm_arch6"
58d7d654 1982 "umull%?\\t%3, %0, %2, %1"
9da0ec36 1983 [(set_attr "type" "umull")
58d7d654 1984 (set_attr "predicable" "yes")]
1985)
1986
957788b0 1987(define_insn "*umulsi3_highpart_v6"
58d7d654 1988 [(set (match_operand:SI 0 "s_register_operand" "=r")
1989 (truncate:SI
1990 (lshiftrt:DI
1991 (mult:DI
1992 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1993 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1994 (const_int 32))))
1995 (clobber (match_scratch:SI 3 "=r"))]
1996 "TARGET_32BIT && arm_arch6"
f082f1c4 1997 "umull%?\\t%3, %0, %2, %1"
9da0ec36 1998 [(set_attr "type" "umull")
8bdfd6ed 1999 (set_attr "predicable" "yes")]
cffb2a26 2000)
f082f1c4 2001
331beb1a 2002(define_insn "mulhisi3"
2003 [(set (match_operand:SI 0 "s_register_operand" "=r")
2004 (mult:SI (sign_extend:SI
2005 (match_operand:HI 1 "s_register_operand" "%r"))
2006 (sign_extend:SI
2007 (match_operand:HI 2 "s_register_operand" "r"))))]
25f905c2 2008 "TARGET_DSP_MULTIPLY"
61a2d04c 2009 "smulbb%?\\t%0, %1, %2"
9da0ec36 2010 [(set_attr "type" "smulxy")
fec538d9 2011 (set_attr "predicable" "yes")]
2012)
2013
2014(define_insn "*mulhisi3tb"
2015 [(set (match_operand:SI 0 "s_register_operand" "=r")
2016 (mult:SI (ashiftrt:SI
2017 (match_operand:SI 1 "s_register_operand" "r")
2018 (const_int 16))
2019 (sign_extend:SI
2020 (match_operand:HI 2 "s_register_operand" "r"))))]
25f905c2 2021 "TARGET_DSP_MULTIPLY"
fec538d9 2022 "smultb%?\\t%0, %1, %2"
9da0ec36 2023 [(set_attr "type" "smulxy")
8bdfd6ed 2024 (set_attr "predicable" "yes")]
fec538d9 2025)
2026
2027(define_insn "*mulhisi3bt"
2028 [(set (match_operand:SI 0 "s_register_operand" "=r")
2029 (mult:SI (sign_extend:SI
2030 (match_operand:HI 1 "s_register_operand" "r"))
2031 (ashiftrt:SI
2032 (match_operand:SI 2 "s_register_operand" "r")
2033 (const_int 16))))]
25f905c2 2034 "TARGET_DSP_MULTIPLY"
fec538d9 2035 "smulbt%?\\t%0, %1, %2"
9da0ec36 2036 [(set_attr "type" "smulxy")
8bdfd6ed 2037 (set_attr "predicable" "yes")]
fec538d9 2038)
2039
2040(define_insn "*mulhisi3tt"
2041 [(set (match_operand:SI 0 "s_register_operand" "=r")
2042 (mult:SI (ashiftrt:SI
2043 (match_operand:SI 1 "s_register_operand" "r")
2044 (const_int 16))
2045 (ashiftrt:SI
2046 (match_operand:SI 2 "s_register_operand" "r")
2047 (const_int 16))))]
25f905c2 2048 "TARGET_DSP_MULTIPLY"
fec538d9 2049 "smultt%?\\t%0, %1, %2"
9da0ec36 2050 [(set_attr "type" "smulxy")
8bdfd6ed 2051 (set_attr "predicable" "yes")]
331beb1a 2052)
2053
5cdca009 2054(define_insn "maddhisi4"
331beb1a 2055 [(set (match_operand:SI 0 "s_register_operand" "=r")
cfa6c608 2056 (plus:SI (mult:SI (sign_extend:SI
2057 (match_operand:HI 1 "s_register_operand" "r"))
331beb1a 2058 (sign_extend:SI
cfa6c608 2059 (match_operand:HI 2 "s_register_operand" "r")))
2060 (match_operand:SI 3 "s_register_operand" "r")))]
25f905c2 2061 "TARGET_DSP_MULTIPLY"
5cdca009 2062 "smlabb%?\\t%0, %1, %2, %3"
9da0ec36 2063 [(set_attr "type" "smlaxy")
8bdfd6ed 2064 (set_attr "predicable" "yes")]
331beb1a 2065)
2066
9a92f368 2067;; Note: there is no maddhisi4ibt because this one is canonical form
2068(define_insn "*maddhisi4tb"
2069 [(set (match_operand:SI 0 "s_register_operand" "=r")
2070 (plus:SI (mult:SI (ashiftrt:SI
2071 (match_operand:SI 1 "s_register_operand" "r")
2072 (const_int 16))
2073 (sign_extend:SI
2074 (match_operand:HI 2 "s_register_operand" "r")))
2075 (match_operand:SI 3 "s_register_operand" "r")))]
2076 "TARGET_DSP_MULTIPLY"
2077 "smlatb%?\\t%0, %1, %2, %3"
9da0ec36 2078 [(set_attr "type" "smlaxy")
8bdfd6ed 2079 (set_attr "predicable" "yes")]
9a92f368 2080)
2081
2082(define_insn "*maddhisi4tt"
2083 [(set (match_operand:SI 0 "s_register_operand" "=r")
2084 (plus:SI (mult:SI (ashiftrt:SI
2085 (match_operand:SI 1 "s_register_operand" "r")
2086 (const_int 16))
2087 (ashiftrt:SI
2088 (match_operand:SI 2 "s_register_operand" "r")
2089 (const_int 16)))
2090 (match_operand:SI 3 "s_register_operand" "r")))]
2091 "TARGET_DSP_MULTIPLY"
2092 "smlatt%?\\t%0, %1, %2, %3"
9da0ec36 2093 [(set_attr "type" "smlaxy")
8bdfd6ed 2094 (set_attr "predicable" "yes")]
9a92f368 2095)
2096
aff5fb4d 2097(define_insn "maddhidi4"
331beb1a 2098 [(set (match_operand:DI 0 "s_register_operand" "=r")
2099 (plus:DI
331beb1a 2100 (mult:DI (sign_extend:DI
d952d547 2101 (match_operand:HI 1 "s_register_operand" "r"))
331beb1a 2102 (sign_extend:DI
cfa6c608 2103 (match_operand:HI 2 "s_register_operand" "r")))
2104 (match_operand:DI 3 "s_register_operand" "0")))]
25f905c2 2105 "TARGET_DSP_MULTIPLY"
5cdca009 2106 "smlalbb%?\\t%Q0, %R0, %1, %2"
9da0ec36 2107 [(set_attr "type" "smlalxy")
8bdfd6ed 2108 (set_attr "predicable" "yes")])
331beb1a 2109
9a92f368 2110;; Note: there is no maddhidi4ibt because this one is canonical form
2111(define_insn "*maddhidi4tb"
2112 [(set (match_operand:DI 0 "s_register_operand" "=r")
2113 (plus:DI
2114 (mult:DI (sign_extend:DI
2115 (ashiftrt:SI
2116 (match_operand:SI 1 "s_register_operand" "r")
2117 (const_int 16)))
2118 (sign_extend:DI
2119 (match_operand:HI 2 "s_register_operand" "r")))
2120 (match_operand:DI 3 "s_register_operand" "0")))]
2121 "TARGET_DSP_MULTIPLY"
2122 "smlaltb%?\\t%Q0, %R0, %1, %2"
9da0ec36 2123 [(set_attr "type" "smlalxy")
8bdfd6ed 2124 (set_attr "predicable" "yes")])
9a92f368 2125
2126(define_insn "*maddhidi4tt"
2127 [(set (match_operand:DI 0 "s_register_operand" "=r")
2128 (plus:DI
2129 (mult:DI (sign_extend:DI
2130 (ashiftrt:SI
2131 (match_operand:SI 1 "s_register_operand" "r")
2132 (const_int 16)))
2133 (sign_extend:DI
2134 (ashiftrt:SI
2135 (match_operand:SI 2 "s_register_operand" "r")
2136 (const_int 16))))
2137 (match_operand:DI 3 "s_register_operand" "0")))]
2138 "TARGET_DSP_MULTIPLY"
2139 "smlaltt%?\\t%Q0, %R0, %1, %2"
9da0ec36 2140 [(set_attr "type" "smlalxy")
8bdfd6ed 2141 (set_attr "predicable" "yes")])
9a92f368 2142
604f3a0a 2143(define_expand "mulsf3"
2144 [(set (match_operand:SF 0 "s_register_operand" "")
2145 (mult:SF (match_operand:SF 1 "s_register_operand" "")
d86c91f6 2146 (match_operand:SF 2 "s_register_operand" "")))]
25f905c2 2147 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 2148 "
604f3a0a 2149")
2150
604f3a0a 2151(define_expand "muldf3"
2152 [(set (match_operand:DF 0 "s_register_operand" "")
2153 (mult:DF (match_operand:DF 1 "s_register_operand" "")
d86c91f6 2154 (match_operand:DF 2 "s_register_operand" "")))]
a50d7267 2155 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 2156 "
604f3a0a 2157")
b11cae9e 2158\f
2159;; Division insns
2160
7db9af5d 2161(define_expand "divsf3"
2162 [(set (match_operand:SF 0 "s_register_operand" "")
d86c91f6 2163 (div:SF (match_operand:SF 1 "s_register_operand" "")
2164 (match_operand:SF 2 "s_register_operand" "")))]
d7216193 2165 "TARGET_32BIT && TARGET_HARD_FLOAT"
7db9af5d 2166 "")
9c08d1fa 2167
7db9af5d 2168(define_expand "divdf3"
2169 [(set (match_operand:DF 0 "s_register_operand" "")
d86c91f6 2170 (div:DF (match_operand:DF 1 "s_register_operand" "")
2171 (match_operand:DF 2 "s_register_operand" "")))]
994606f8 2172 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
7db9af5d 2173 "")
b11cae9e 2174\f
2175;; Boolean and,ior,xor insns
2176
f6ebffac 2177;; Split up double word logical operations
2178
2179;; Split up simple DImode logical operations. Simply perform the logical
2180;; operation on the upper and lower halves of the registers.
2181(define_split
2182 [(set (match_operand:DI 0 "s_register_operand" "")
2183 (match_operator:DI 6 "logical_binary_operator"
2184 [(match_operand:DI 1 "s_register_operand" "")
2185 (match_operand:DI 2 "s_register_operand" "")]))]
25f905c2 2186 "TARGET_32BIT && reload_completed
e2669ea7 2187 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))
25f905c2 2188 && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
f6ebffac 2189 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
2190 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
2191 "
215b30b3 2192 {
2193 operands[3] = gen_highpart (SImode, operands[0]);
2194 operands[0] = gen_lowpart (SImode, operands[0]);
2195 operands[4] = gen_highpart (SImode, operands[1]);
2196 operands[1] = gen_lowpart (SImode, operands[1]);
2197 operands[5] = gen_highpart (SImode, operands[2]);
2198 operands[2] = gen_lowpart (SImode, operands[2]);
2199 }"
2200)
f6ebffac 2201
f6ebffac 2202(define_split
2203 [(set (match_operand:DI 0 "s_register_operand" "")
2204 (match_operator:DI 6 "logical_binary_operator"
2205 [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
2206 (match_operand:DI 1 "s_register_operand" "")]))]
25f905c2 2207 "TARGET_32BIT && reload_completed"
f6ebffac 2208 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
2209 (set (match_dup 3) (match_op_dup:SI 6
2210 [(ashiftrt:SI (match_dup 2) (const_int 31))
2211 (match_dup 4)]))]
2212 "
215b30b3 2213 {
2214 operands[3] = gen_highpart (SImode, operands[0]);
2215 operands[0] = gen_lowpart (SImode, operands[0]);
2216 operands[4] = gen_highpart (SImode, operands[1]);
2217 operands[1] = gen_lowpart (SImode, operands[1]);
2218 operands[5] = gen_highpart (SImode, operands[2]);
2219 operands[2] = gen_lowpart (SImode, operands[2]);
2220 }"
2221)
f6ebffac 2222
f6ebffac 2223;; The zero extend of operand 2 means we can just copy the high part of
2224;; operand1 into operand0.
2225(define_split
2226 [(set (match_operand:DI 0 "s_register_operand" "")
2227 (ior:DI
2228 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
2229 (match_operand:DI 1 "s_register_operand" "")))]
25f905c2 2230 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
f6ebffac 2231 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
2232 (set (match_dup 3) (match_dup 4))]
2233 "
215b30b3 2234 {
2235 operands[4] = gen_highpart (SImode, operands[1]);
2236 operands[3] = gen_highpart (SImode, operands[0]);
2237 operands[0] = gen_lowpart (SImode, operands[0]);
2238 operands[1] = gen_lowpart (SImode, operands[1]);
2239 }"
2240)
f6ebffac 2241
2242;; The zero extend of operand 2 means we can just copy the high part of
2243;; operand1 into operand0.
2244(define_split
2245 [(set (match_operand:DI 0 "s_register_operand" "")
2246 (xor:DI
2247 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
2248 (match_operand:DI 1 "s_register_operand" "")))]
25f905c2 2249 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
f6ebffac 2250 [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
2251 (set (match_dup 3) (match_dup 4))]
2252 "
215b30b3 2253 {
2254 operands[4] = gen_highpart (SImode, operands[1]);
2255 operands[3] = gen_highpart (SImode, operands[0]);
2256 operands[0] = gen_lowpart (SImode, operands[0]);
2257 operands[1] = gen_lowpart (SImode, operands[1]);
2258 }"
2259)
f6ebffac 2260
e2669ea7 2261(define_expand "anddi3"
2262 [(set (match_operand:DI 0 "s_register_operand" "")
2263 (and:DI (match_operand:DI 1 "s_register_operand" "")
2264 (match_operand:DI 2 "neon_inv_logic_op2" "")))]
2265 "TARGET_32BIT"
0d84c6e5 2266 "
2267 if (!TARGET_NEON && !TARGET_IWMMXT)
2268 {
2269 rtx low = simplify_gen_binary (AND, SImode,
2270 gen_lowpart (SImode, operands[1]),
2271 gen_lowpart (SImode, operands[2]));
2272 rtx high = simplify_gen_binary (AND, SImode,
2273 gen_highpart (SImode, operands[1]),
2274 gen_highpart_mode (SImode, DImode,
2275 operands[2]));
2276
2277 emit_insn (gen_rtx_SET (gen_lowpart (SImode, operands[0]), low));
2278 emit_insn (gen_rtx_SET (gen_highpart (SImode, operands[0]), high));
2279
2280 DONE;
2281 }
2282 /* Otherwise expand pattern as above. */
2283 "
e2669ea7 2284)
2285
f6bbdcf6 2286(define_insn_and_split "*anddi3_insn"
0a314dcd 2287 [(set (match_operand:DI 0 "s_register_operand" "=w,w ,&r,&r,&r,&r,?w,?w")
2288 (and:DI (match_operand:DI 1 "s_register_operand" "%w,0 ,0 ,r ,0 ,r ,w ,0")
2289 (match_operand:DI 2 "arm_anddi_operand_neon" "w ,DL,r ,r ,De,De,w ,DL")))]
f6bbdcf6 2290 "TARGET_32BIT && !TARGET_IWMMXT"
2291{
2292 switch (which_alternative)
2293 {
0a314dcd 2294 case 0: /* fall through */
2295 case 6: return "vand\t%P0, %P1, %P2";
2296 case 1: /* fall through */
2297 case 7: return neon_output_logic_immediate ("vand", &operands[2],
2298 DImode, 1, VALID_NEON_QREG_MODE (DImode));
f6bbdcf6 2299 case 2:
0a314dcd 2300 case 3:
2301 case 4:
f6bbdcf6 2302 case 5: /* fall through */
0a314dcd 2303 return "#";
f6bbdcf6 2304 default: gcc_unreachable ();
2305 }
2306}
0a314dcd 2307 "TARGET_32BIT && !TARGET_IWMMXT && reload_completed
2308 && !(IS_VFP_REGNUM (REGNO (operands[0])))"
f6bbdcf6 2309 [(set (match_dup 3) (match_dup 4))
2310 (set (match_dup 5) (match_dup 6))]
2311 "
2312 {
2313 operands[3] = gen_lowpart (SImode, operands[0]);
2314 operands[5] = gen_highpart (SImode, operands[0]);
2315
2316 operands[4] = simplify_gen_binary (AND, SImode,
2317 gen_lowpart (SImode, operands[1]),
2318 gen_lowpart (SImode, operands[2]));
2319 operands[6] = simplify_gen_binary (AND, SImode,
2320 gen_highpart (SImode, operands[1]),
2321 gen_highpart_mode (SImode, DImode, operands[2]));
2322
2323 }"
32093010 2324 [(set_attr "type" "neon_logic,neon_logic,multiple,multiple,\
2325 multiple,multiple,neon_logic,neon_logic")
0a314dcd 2326 (set_attr "arch" "neon_for_64bits,neon_for_64bits,*,*,*,*,
f6bbdcf6 2327 avoid_neon_for_64bits,avoid_neon_for_64bits")
0a314dcd 2328 (set_attr "length" "*,*,8,8,8,8,*,*")
2329 ]
215b30b3 2330)
b11cae9e 2331
a0f94409 2332(define_insn_and_split "*anddi_zesidi_di"
9c08d1fa 2333 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2334 (and:DI (zero_extend:DI
2335 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 2336 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2337 "TARGET_32BIT"
f6ebffac 2338 "#"
25f905c2 2339 "TARGET_32BIT && reload_completed"
a0f94409 2340 ; The zero extend of operand 2 clears the high word of the output
2341 ; operand.
2342 [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
2343 (set (match_dup 3) (const_int 0))]
2344 "
2345 {
2346 operands[3] = gen_highpart (SImode, operands[0]);
2347 operands[0] = gen_lowpart (SImode, operands[0]);
2348 operands[1] = gen_lowpart (SImode, operands[1]);
2349 }"
1b7da4ac 2350 [(set_attr "length" "8")
2351 (set_attr "type" "multiple")]
215b30b3 2352)
b11cae9e 2353
f7fbdd4a 2354(define_insn "*anddi_sesdi_di"
cffb2a26 2355 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 2356 (and:DI (sign_extend:DI
2357 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 2358 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2359 "TARGET_32BIT"
f6ebffac 2360 "#"
1b7da4ac 2361 [(set_attr "length" "8")
2362 (set_attr "type" "multiple")]
cffb2a26 2363)
b11cae9e 2364
87b22bf7 2365(define_expand "andsi3"
cffb2a26 2366 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2367 (and:SI (match_operand:SI 1 "s_register_operand" "")
2368 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 2369 "TARGET_EITHER"
87b22bf7 2370 "
25f905c2 2371 if (TARGET_32BIT)
87b22bf7 2372 {
0438d37f 2373 if (CONST_INT_P (operands[2]))
cffb2a26 2374 {
47b5b27b 2375 if (INTVAL (operands[2]) == 255 && arm_arch6)
2376 {
2377 operands[1] = convert_to_mode (QImode, operands[1], 1);
2378 emit_insn (gen_thumb2_zero_extendqisi2_v6 (operands[0],
2379 operands[1]));
17202aa5 2380 DONE;
47b5b27b 2381 }
17202aa5 2382 else if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[2]), AND))
2383 operands[2] = force_reg (SImode, operands[2]);
47b5b27b 2384 else
17202aa5 2385 {
2386 arm_split_constant (AND, SImode, NULL_RTX,
2387 INTVAL (operands[2]), operands[0],
2388 operands[1],
2389 optimize && can_create_pseudo_p ());
615caa51 2390
17202aa5 2391 DONE;
2392 }
cffb2a26 2393 }
87b22bf7 2394 }
25f905c2 2395 else /* TARGET_THUMB1 */
cffb2a26 2396 {
0438d37f 2397 if (!CONST_INT_P (operands[2]))
923ffadb 2398 {
2399 rtx tmp = force_reg (SImode, operands[2]);
2400 if (rtx_equal_p (operands[0], operands[1]))
2401 operands[2] = tmp;
2402 else
2403 {
2404 operands[2] = operands[1];
2405 operands[1] = tmp;
2406 }
2407 }
cffb2a26 2408 else
2409 {
2410 int i;
2411
215b30b3 2412 if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
cffb2a26 2413 {
215b30b3 2414 operands[2] = force_reg (SImode,
2415 GEN_INT (~INTVAL (operands[2])));
cffb2a26 2416
747b7458 2417 emit_insn (gen_thumb1_bicsi3 (operands[0], operands[2], operands[1]));
cffb2a26 2418
2419 DONE;
2420 }
87b22bf7 2421
cffb2a26 2422 for (i = 9; i <= 31; i++)
2423 {
db2faf44 2424 if ((HOST_WIDE_INT_1 << i) - 1 == INTVAL (operands[2]))
cffb2a26 2425 {
2426 emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
2427 const0_rtx));
2428 DONE;
2429 }
db2faf44 2430 else if ((HOST_WIDE_INT_1 << i) - 1
215b30b3 2431 == ~INTVAL (operands[2]))
cffb2a26 2432 {
2433 rtx shift = GEN_INT (i);
2434 rtx reg = gen_reg_rtx (SImode);
2435
2436 emit_insn (gen_lshrsi3 (reg, operands[1], shift));
2437 emit_insn (gen_ashlsi3 (operands[0], reg, shift));
2438
2439 DONE;
2440 }
2441 }
2442
2443 operands[2] = force_reg (SImode, operands[2]);
2444 }
215b30b3 2445 }
2446 "
cffb2a26 2447)
2448
25f905c2 2449; ??? Check split length for Thumb-2
a0f94409 2450(define_insn_and_split "*arm_andsi3_insn"
29e234a3 2451 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r,r,r")
2452 (and:SI (match_operand:SI 1 "s_register_operand" "%r,0,r,r,r")
2453 (match_operand:SI 2 "reg_or_int_operand" "I,l,K,r,?n")))]
25f905c2 2454 "TARGET_32BIT"
5565501b 2455 "@
29e234a3 2456 and%?\\t%0, %1, %2
5565501b 2457 and%?\\t%0, %1, %2
87b22bf7 2458 bic%?\\t%0, %1, #%B2
65f68e55 2459 and%?\\t%0, %1, %2
87b22bf7 2460 #"
25f905c2 2461 "TARGET_32BIT
0438d37f 2462 && CONST_INT_P (operands[2])
a0f94409 2463 && !(const_ok_for_arm (INTVAL (operands[2]))
2464 || const_ok_for_arm (~INTVAL (operands[2])))"
2465 [(clobber (const_int 0))]
2466 "
96f57e36 2467 arm_split_constant (AND, SImode, curr_insn,
2468 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 2469 DONE;
2470 "
29e234a3 2471 [(set_attr "length" "4,4,4,4,16")
65f68e55 2472 (set_attr "predicable" "yes")
29e234a3 2473 (set_attr "predicable_short_it" "no,yes,no,no,no")
d82e788e 2474 (set_attr "type" "logic_imm,logic_imm,logic_reg,logic_reg,logic_imm")]
cffb2a26 2475)
2476
f7fbdd4a 2477(define_insn "*andsi3_compare0"
bd5b4116 2478 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 2479 (compare:CC_NOOV
65f68e55 2480 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
2481 (match_operand:SI 2 "arm_not_operand" "I,K,r"))
5565501b 2482 (const_int 0)))
65f68e55 2483 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9c08d1fa 2484 (and:SI (match_dup 1) (match_dup 2)))]
25f905c2 2485 "TARGET_32BIT"
5565501b 2486 "@
3ef90e77 2487 ands%?\\t%0, %1, %2
2488 bics%?\\t%0, %1, #%B2
2489 ands%?\\t%0, %1, %2"
65f68e55 2490 [(set_attr "conds" "set")
d82e788e 2491 (set_attr "type" "logics_imm,logics_imm,logics_reg")]
cffb2a26 2492)
9c08d1fa 2493
f7fbdd4a 2494(define_insn "*andsi3_compare0_scratch"
bd5b4116 2495 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 2496 (compare:CC_NOOV
65f68e55 2497 (and:SI (match_operand:SI 0 "s_register_operand" "r,r,r")
2498 (match_operand:SI 1 "arm_not_operand" "I,K,r"))
5565501b 2499 (const_int 0)))
65f68e55 2500 (clobber (match_scratch:SI 2 "=X,r,X"))]
25f905c2 2501 "TARGET_32BIT"
5565501b 2502 "@
2503 tst%?\\t%0, %1
3ef90e77 2504 bics%?\\t%2, %0, #%B1
65f68e55 2505 tst%?\\t%0, %1"
2506 [(set_attr "conds" "set")
d82e788e 2507 (set_attr "type" "logics_imm,logics_imm,logics_reg")]
0d66636f 2508)
9c08d1fa 2509
f7fbdd4a 2510(define_insn "*zeroextractsi_compare0_scratch"
bd5b4116 2511 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2512 (compare:CC_NOOV (zero_extract:SI
2513 (match_operand:SI 0 "s_register_operand" "r")
d952d547 2514 (match_operand 1 "const_int_operand" "n")
206ee9a2 2515 (match_operand 2 "const_int_operand" "n"))
9c08d1fa 2516 (const_int 0)))]
25f905c2 2517 "TARGET_32BIT
cffb2a26 2518 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
2519 && INTVAL (operands[1]) > 0
2520 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
2521 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
9c08d1fa 2522 "*
5c49a439 2523 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
2524 << INTVAL (operands[2]));
40dbec34 2525 output_asm_insn (\"tst%?\\t%0, %1\", operands);
e2348bcb 2526 return \"\";
0d66636f 2527 "
596e5e8f 2528 [(set_attr "conds" "set")
65f68e55 2529 (set_attr "predicable" "yes")
d82e788e 2530 (set_attr "type" "logics_imm")]
0d66636f 2531)
9c08d1fa 2532
f4462328 2533(define_insn_and_split "*ne_zeroextractsi"
c4034607 2534 [(set (match_operand:SI 0 "s_register_operand" "=r")
2535 (ne:SI (zero_extract:SI
2536 (match_operand:SI 1 "s_register_operand" "r")
2537 (match_operand:SI 2 "const_int_operand" "n")
2538 (match_operand:SI 3 "const_int_operand" "n"))
3b8c7f7a 2539 (const_int 0)))
2540 (clobber (reg:CC CC_REGNUM))]
25f905c2 2541 "TARGET_32BIT
cffb2a26 2542 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2543 && INTVAL (operands[2]) > 0
2544 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2545 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
f4462328 2546 "#"
25f905c2 2547 "TARGET_32BIT
f4462328 2548 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2549 && INTVAL (operands[2]) > 0
2550 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2551 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
2552 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2553 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2554 (const_int 0)))
2555 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2556 (set (match_dup 0)
2557 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2558 (match_dup 0) (const_int 1)))]
2559 "
2560 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
2561 << INTVAL (operands[3]));
2562 "
2563 [(set_attr "conds" "clob")
25f905c2 2564 (set (attr "length")
2565 (if_then_else (eq_attr "is_thumb" "yes")
2566 (const_int 12)
1b7da4ac 2567 (const_int 8)))
2568 (set_attr "type" "multiple")]
f4462328 2569)
2570
2571(define_insn_and_split "*ne_zeroextractsi_shifted"
2572 [(set (match_operand:SI 0 "s_register_operand" "=r")
2573 (ne:SI (zero_extract:SI
2574 (match_operand:SI 1 "s_register_operand" "r")
2575 (match_operand:SI 2 "const_int_operand" "n")
2576 (const_int 0))
2577 (const_int 0)))
2578 (clobber (reg:CC CC_REGNUM))]
2579 "TARGET_ARM"
2580 "#"
2581 "TARGET_ARM"
2582 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2583 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2584 (const_int 0)))
2585 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2586 (set (match_dup 0)
2587 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2588 (match_dup 0) (const_int 1)))]
2589 "
2590 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
2591 "
2592 [(set_attr "conds" "clob")
1b7da4ac 2593 (set_attr "length" "8")
2594 (set_attr "type" "multiple")]
f4462328 2595)
2596
2597(define_insn_and_split "*ite_ne_zeroextractsi"
2598 [(set (match_operand:SI 0 "s_register_operand" "=r")
2599 (if_then_else:SI (ne (zero_extract:SI
2600 (match_operand:SI 1 "s_register_operand" "r")
2601 (match_operand:SI 2 "const_int_operand" "n")
2602 (match_operand:SI 3 "const_int_operand" "n"))
2603 (const_int 0))
2604 (match_operand:SI 4 "arm_not_operand" "rIK")
2605 (const_int 0)))
2606 (clobber (reg:CC CC_REGNUM))]
2607 "TARGET_ARM
2608 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2609 && INTVAL (operands[2]) > 0
2610 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 2611 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2612 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 2613 "#"
2614 "TARGET_ARM
2615 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2616 && INTVAL (operands[2]) > 0
2617 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 2618 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2619 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 2620 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2621 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2622 (const_int 0)))
2623 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2624 (set (match_dup 0)
2625 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2626 (match_dup 0) (match_dup 4)))]
2627 "
c4034607 2628 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
f4462328 2629 << INTVAL (operands[3]));
2630 "
2631 [(set_attr "conds" "clob")
1b7da4ac 2632 (set_attr "length" "8")
2633 (set_attr "type" "multiple")]
f4462328 2634)
2635
2636(define_insn_and_split "*ite_ne_zeroextractsi_shifted"
2637 [(set (match_operand:SI 0 "s_register_operand" "=r")
2638 (if_then_else:SI (ne (zero_extract:SI
2639 (match_operand:SI 1 "s_register_operand" "r")
2640 (match_operand:SI 2 "const_int_operand" "n")
2641 (const_int 0))
2642 (const_int 0))
2643 (match_operand:SI 3 "arm_not_operand" "rIK")
2644 (const_int 0)))
2645 (clobber (reg:CC CC_REGNUM))]
f8d7bf2f 2646 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 2647 "#"
f8d7bf2f 2648 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 2649 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2650 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2651 (const_int 0)))
2652 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2653 (set (match_dup 0)
2654 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2655 (match_dup 0) (match_dup 3)))]
2656 "
2657 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
0d66636f 2658 "
2659 [(set_attr "conds" "clob")
1b7da4ac 2660 (set_attr "length" "8")
2661 (set_attr "type" "multiple")]
215b30b3 2662)
9c08d1fa 2663
25f905c2 2664;; ??? Use Thumb-2 has bitfield insert/extract instructions.
d7863cfe 2665(define_split
2666 [(set (match_operand:SI 0 "s_register_operand" "")
2667 (match_operator:SI 1 "shiftable_operator"
2668 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2669 (match_operand:SI 3 "const_int_operand" "")
2670 (match_operand:SI 4 "const_int_operand" ""))
2671 (match_operand:SI 5 "s_register_operand" "")]))
2672 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2673 "TARGET_ARM"
2674 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2675 (set (match_dup 0)
2676 (match_op_dup 1
2677 [(lshiftrt:SI (match_dup 6) (match_dup 4))
2678 (match_dup 5)]))]
2679 "{
2680 HOST_WIDE_INT temp = INTVAL (operands[3]);
2681
2682 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2683 operands[4] = GEN_INT (32 - temp);
2684 }"
2685)
2686
d7863cfe 2687(define_split
2688 [(set (match_operand:SI 0 "s_register_operand" "")
2689 (match_operator:SI 1 "shiftable_operator"
2690 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2691 (match_operand:SI 3 "const_int_operand" "")
2692 (match_operand:SI 4 "const_int_operand" ""))
2693 (match_operand:SI 5 "s_register_operand" "")]))
2694 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2695 "TARGET_ARM"
2696 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2697 (set (match_dup 0)
2698 (match_op_dup 1
2699 [(ashiftrt:SI (match_dup 6) (match_dup 4))
2700 (match_dup 5)]))]
2701 "{
2702 HOST_WIDE_INT temp = INTVAL (operands[3]);
2703
2704 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2705 operands[4] = GEN_INT (32 - temp);
2706 }"
2707)
2708
a42059fd 2709;;; ??? This pattern is bogus. If operand3 has bits outside the range
2710;;; represented by the bitfield, then this will produce incorrect results.
2711;;; Somewhere, the value needs to be truncated. On targets like the m68k,
ceb2fe0f 2712;;; which have a real bit-field insert instruction, the truncation happens
2713;;; in the bit-field insert instruction itself. Since arm does not have a
2714;;; bit-field insert instruction, we would have to emit code here to truncate
a42059fd 2715;;; the value before we insert. This loses some of the advantage of having
2716;;; this insv pattern, so this pattern needs to be reevalutated.
2717
8a18b90c 2718(define_expand "insv"
eb04cafb 2719 [(set (zero_extract (match_operand 0 "nonimmediate_operand" "")
2720 (match_operand 1 "general_operand" "")
2721 (match_operand 2 "general_operand" ""))
2722 (match_operand 3 "reg_or_int_operand" ""))]
8b054d5a 2723 "TARGET_ARM || arm_arch_thumb2"
8a18b90c 2724 "
215b30b3 2725 {
2726 int start_bit = INTVAL (operands[2]);
2727 int width = INTVAL (operands[1]);
db2faf44 2728 HOST_WIDE_INT mask = (HOST_WIDE_INT_1 << width) - 1;
215b30b3 2729 rtx target, subtarget;
2730
8b054d5a 2731 if (arm_arch_thumb2)
2732 {
eb04cafb 2733 if (unaligned_access && MEM_P (operands[0])
2734 && s_register_operand (operands[3], GET_MODE (operands[3]))
2735 && (width == 16 || width == 32) && (start_bit % BITS_PER_UNIT) == 0)
8b054d5a 2736 {
eb04cafb 2737 rtx base_addr;
2738
2739 if (BYTES_BIG_ENDIAN)
2740 start_bit = GET_MODE_BITSIZE (GET_MODE (operands[3])) - width
2741 - start_bit;
8b054d5a 2742
eb04cafb 2743 if (width == 32)
8b054d5a 2744 {
eb04cafb 2745 base_addr = adjust_address (operands[0], SImode,
2746 start_bit / BITS_PER_UNIT);
2747 emit_insn (gen_unaligned_storesi (base_addr, operands[3]));
8b054d5a 2748 }
eb04cafb 2749 else
2750 {
2751 rtx tmp = gen_reg_rtx (HImode);
8b054d5a 2752
eb04cafb 2753 base_addr = adjust_address (operands[0], HImode,
2754 start_bit / BITS_PER_UNIT);
2755 emit_move_insn (tmp, gen_lowpart (HImode, operands[3]));
2756 emit_insn (gen_unaligned_storehi (base_addr, tmp));
2757 }
2758 DONE;
8b054d5a 2759 }
eb04cafb 2760 else if (s_register_operand (operands[0], GET_MODE (operands[0])))
8b054d5a 2761 {
eb04cafb 2762 bool use_bfi = TRUE;
8b054d5a 2763
0438d37f 2764 if (CONST_INT_P (operands[3]))
eb04cafb 2765 {
2766 HOST_WIDE_INT val = INTVAL (operands[3]) & mask;
2767
2768 if (val == 0)
2769 {
2770 emit_insn (gen_insv_zero (operands[0], operands[1],
2771 operands[2]));
2772 DONE;
2773 }
2774
2775 /* See if the set can be done with a single orr instruction. */
2776 if (val == mask && const_ok_for_arm (val << start_bit))
2777 use_bfi = FALSE;
2778 }
2779
2780 if (use_bfi)
2781 {
0438d37f 2782 if (!REG_P (operands[3]))
eb04cafb 2783 operands[3] = force_reg (SImode, operands[3]);
2784
2785 emit_insn (gen_insv_t2 (operands[0], operands[1], operands[2],
2786 operands[3]));
2787 DONE;
2788 }
8b054d5a 2789 }
eb04cafb 2790 else
2791 FAIL;
8b054d5a 2792 }
2793
eb04cafb 2794 if (!s_register_operand (operands[0], GET_MODE (operands[0])))
2795 FAIL;
2796
3f8fde42 2797 target = copy_rtx (operands[0]);
215b30b3 2798 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
2799 subreg as the final target. */
2800 if (GET_CODE (target) == SUBREG)
2801 {
2802 subtarget = gen_reg_rtx (SImode);
2803 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
2804 < GET_MODE_SIZE (SImode))
2805 target = SUBREG_REG (target);
2806 }
2807 else
2808 subtarget = target;
8a18b90c 2809
0438d37f 2810 if (CONST_INT_P (operands[3]))
215b30b3 2811 {
2812 /* Since we are inserting a known constant, we may be able to
2813 reduce the number of bits that we have to clear so that
2814 the mask becomes simple. */
2815 /* ??? This code does not check to see if the new mask is actually
2816 simpler. It may not be. */
2817 rtx op1 = gen_reg_rtx (SImode);
2818 /* ??? Truncate operand3 to fit in the bitfield. See comment before
2819 start of this pattern. */
2820 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
2821 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
2822
c5b3a71b 2823 emit_insn (gen_andsi3 (op1, operands[0],
2824 gen_int_mode (~mask2, SImode)));
215b30b3 2825 emit_insn (gen_iorsi3 (subtarget, op1,
4292ca6b 2826 gen_int_mode (op3_value << start_bit, SImode)));
215b30b3 2827 }
2828 else if (start_bit == 0
2829 && !(const_ok_for_arm (mask)
2830 || const_ok_for_arm (~mask)))
2831 {
2832 /* A Trick, since we are setting the bottom bits in the word,
2833 we can shift operand[3] up, operand[0] down, OR them together
2834 and rotate the result back again. This takes 3 insns, and
5910bb95 2835 the third might be mergeable into another op. */
215b30b3 2836 /* The shift up copes with the possibility that operand[3] is
2837 wider than the bitfield. */
2838 rtx op0 = gen_reg_rtx (SImode);
2839 rtx op1 = gen_reg_rtx (SImode);
2840
2841 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2842 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
2843 emit_insn (gen_iorsi3 (op1, op1, op0));
2844 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
2845 }
2846 else if ((width + start_bit == 32)
2847 && !(const_ok_for_arm (mask)
2848 || const_ok_for_arm (~mask)))
2849 {
2850 /* Similar trick, but slightly less efficient. */
8a18b90c 2851
215b30b3 2852 rtx op0 = gen_reg_rtx (SImode);
2853 rtx op1 = gen_reg_rtx (SImode);
8a18b90c 2854
215b30b3 2855 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2856 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
2857 emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
2858 emit_insn (gen_iorsi3 (subtarget, op1, op0));
2859 }
2860 else
2861 {
c5b3a71b 2862 rtx op0 = gen_int_mode (mask, SImode);
215b30b3 2863 rtx op1 = gen_reg_rtx (SImode);
2864 rtx op2 = gen_reg_rtx (SImode);
8a18b90c 2865
215b30b3 2866 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
2867 {
2868 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 2869
215b30b3 2870 emit_insn (gen_movsi (tmp, op0));
2871 op0 = tmp;
2872 }
8a18b90c 2873
215b30b3 2874 /* Mask out any bits in operand[3] that are not needed. */
2875 emit_insn (gen_andsi3 (op1, operands[3], op0));
8a18b90c 2876
0438d37f 2877 if (CONST_INT_P (op0)
215b30b3 2878 && (const_ok_for_arm (mask << start_bit)
2879 || const_ok_for_arm (~(mask << start_bit))))
2880 {
c5b3a71b 2881 op0 = gen_int_mode (~(mask << start_bit), SImode);
215b30b3 2882 emit_insn (gen_andsi3 (op2, operands[0], op0));
2883 }
2884 else
2885 {
0438d37f 2886 if (CONST_INT_P (op0))
215b30b3 2887 {
2888 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 2889
215b30b3 2890 emit_insn (gen_movsi (tmp, op0));
2891 op0 = tmp;
2892 }
2893
2894 if (start_bit != 0)
2895 emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
a42059fd 2896
215b30b3 2897 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
2898 }
8a18b90c 2899
215b30b3 2900 if (start_bit != 0)
2901 emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
8a18b90c 2902
215b30b3 2903 emit_insn (gen_iorsi3 (subtarget, op1, op2));
2904 }
f082f1c4 2905
215b30b3 2906 if (subtarget != target)
2907 {
2908 /* If TARGET is still a SUBREG, then it must be wider than a word,
2909 so we must be careful only to set the subword we were asked to. */
2910 if (GET_CODE (target) == SUBREG)
2911 emit_move_insn (target, subtarget);
2912 else
2913 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
2914 }
8a18b90c 2915
215b30b3 2916 DONE;
2917 }"
2918)
8a18b90c 2919
8b054d5a 2920(define_insn "insv_zero"
2921 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
809003b3 2922 (match_operand:SI 1 "const_int_M_operand" "M")
2923 (match_operand:SI 2 "const_int_M_operand" "M"))
8b054d5a 2924 (const_int 0))]
2925 "arm_arch_thumb2"
2926 "bfc%?\t%0, %2, %1"
2927 [(set_attr "length" "4")
d952d547 2928 (set_attr "predicable" "yes")
d82e788e 2929 (set_attr "type" "bfm")]
8b054d5a 2930)
2931
2932(define_insn "insv_t2"
2933 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
809003b3 2934 (match_operand:SI 1 "const_int_M_operand" "M")
2935 (match_operand:SI 2 "const_int_M_operand" "M"))
8b054d5a 2936 (match_operand:SI 3 "s_register_operand" "r"))]
2937 "arm_arch_thumb2"
2938 "bfi%?\t%0, %3, %2, %1"
2939 [(set_attr "length" "4")
d952d547 2940 (set_attr "predicable" "yes")
d82e788e 2941 (set_attr "type" "bfm")]
8b054d5a 2942)
2943
215b30b3 2944; constants for op 2 will never be given to these patterns.
a0f94409 2945(define_insn_and_split "*anddi_notdi_di"
9c08d1fa 2946 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 2947 (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "0,r"))
2948 (match_operand:DI 2 "s_register_operand" "r,0")))]
25f905c2 2949 "TARGET_32BIT"
f6ebffac 2950 "#"
e2669ea7 2951 "TARGET_32BIT && reload_completed
2952 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))
2953 && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
a0f94409 2954 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2955 (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2956 "
2957 {
2958 operands[3] = gen_highpart (SImode, operands[0]);
2959 operands[0] = gen_lowpart (SImode, operands[0]);
2960 operands[4] = gen_highpart (SImode, operands[1]);
2961 operands[1] = gen_lowpart (SImode, operands[1]);
2962 operands[5] = gen_highpart (SImode, operands[2]);
2963 operands[2] = gen_lowpart (SImode, operands[2]);
2964 }"
0d66636f 2965 [(set_attr "length" "8")
1b7da4ac 2966 (set_attr "predicable" "yes")
2967 (set_attr "type" "multiple")]
0d66636f 2968)
d952d547 2969
a0f94409 2970(define_insn_and_split "*anddi_notzesidi_di"
9c08d1fa 2971 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2972 (and:DI (not:DI (zero_extend:DI
2973 (match_operand:SI 2 "s_register_operand" "r,r")))
e2348bcb 2974 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 2975 "TARGET_32BIT"
e2348bcb 2976 "@
97499065 2977 bic%?\\t%Q0, %Q1, %2
f6ebffac 2978 #"
a0f94409 2979 ; (not (zero_extend ...)) allows us to just copy the high word from
2980 ; operand1 to operand0.
25f905c2 2981 "TARGET_32BIT
a0f94409 2982 && reload_completed
2983 && operands[0] != operands[1]"
5a097f7d 2984 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
a0f94409 2985 (set (match_dup 3) (match_dup 4))]
2986 "
2987 {
2988 operands[3] = gen_highpart (SImode, operands[0]);
2989 operands[0] = gen_lowpart (SImode, operands[0]);
2990 operands[4] = gen_highpart (SImode, operands[1]);
2991 operands[1] = gen_lowpart (SImode, operands[1]);
2992 }"
0d66636f 2993 [(set_attr "length" "4,8")
d952d547 2994 (set_attr "predicable" "yes")
1b7da4ac 2995 (set_attr "type" "multiple")]
0d66636f 2996)
d952d547 2997
d8cd5fa0 2998(define_insn_and_split "*anddi_notdi_zesidi"
2999 [(set (match_operand:DI 0 "s_register_operand" "=r")
3000 (and:DI (not:DI (match_operand:DI 2 "s_register_operand" "r"))
3001 (zero_extend:DI
3002 (match_operand:SI 1 "s_register_operand" "r"))))]
3003 "TARGET_32BIT"
3004 "#"
3005 "TARGET_32BIT && reload_completed"
3006 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
3007 (set (match_dup 3) (const_int 0))]
3008 "
3009 {
3010 operands[3] = gen_highpart (SImode, operands[0]);
3011 operands[0] = gen_lowpart (SImode, operands[0]);
3012 operands[2] = gen_lowpart (SImode, operands[2]);
3013 }"
3014 [(set_attr "length" "8")
3015 (set_attr "predicable" "yes")
d8cd5fa0 3016 (set_attr "type" "multiple")]
3017)
3018
a0f94409 3019(define_insn_and_split "*anddi_notsesidi_di"
9c08d1fa 3020 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3021 (and:DI (not:DI (sign_extend:DI
3022 (match_operand:SI 2 "s_register_operand" "r,r")))
5a097f7d 3023 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 3024 "TARGET_32BIT"
f6ebffac 3025 "#"
25f905c2 3026 "TARGET_32BIT && reload_completed"
5a097f7d 3027 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
a0f94409 3028 (set (match_dup 3) (and:SI (not:SI
3029 (ashiftrt:SI (match_dup 2) (const_int 31)))
3030 (match_dup 4)))]
3031 "
3032 {
3033 operands[3] = gen_highpart (SImode, operands[0]);
3034 operands[0] = gen_lowpart (SImode, operands[0]);
3035 operands[4] = gen_highpart (SImode, operands[1]);
3036 operands[1] = gen_lowpart (SImode, operands[1]);
3037 }"
0d66636f 3038 [(set_attr "length" "8")
d952d547 3039 (set_attr "predicable" "yes")
1b7da4ac 3040 (set_attr "type" "multiple")]
0d66636f 3041)
d952d547 3042
8a18b90c 3043(define_insn "andsi_notsi_si"
9c08d1fa 3044 [(set (match_operand:SI 0 "s_register_operand" "=r")
3045 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
3046 (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 3047 "TARGET_32BIT"
0d66636f 3048 "bic%?\\t%0, %1, %2"
d952d547 3049 [(set_attr "predicable" "yes")
1b7da4ac 3050 (set_attr "type" "logic_reg")]
0d66636f 3051)
b11cae9e 3052
8a18b90c 3053(define_insn "andsi_not_shiftsi_si"
a2cd141b 3054 [(set (match_operand:SI 0 "s_register_operand" "=r")
3055 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
3056 [(match_operand:SI 2 "s_register_operand" "r")
3057 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
3058 (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 3059 "TARGET_ARM"
6c4c2133 3060 "bic%?\\t%0, %1, %2%S4"
344495ea 3061 [(set_attr "predicable" "yes")
331beb1a 3062 (set_attr "shift" "2")
a2cd141b 3063 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
d82e788e 3064 (const_string "logic_shift_imm")
3065 (const_string "logic_shift_reg")))]
6c4c2133 3066)
8a18b90c 3067
9ed784d8 3068;; Shifted bics pattern used to set up CC status register and not reusing
3069;; bics output. Pattern restricts Thumb2 shift operand as bics for Thumb2
3070;; does not support shift by register.
3071(define_insn "andsi_not_shiftsi_si_scc_no_reuse"
3072 [(set (reg:CC_NOOV CC_REGNUM)
3073 (compare:CC_NOOV
3074 (and:SI (not:SI (match_operator:SI 0 "shift_operator"
3075 [(match_operand:SI 1 "s_register_operand" "r")
3076 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
3077 (match_operand:SI 3 "s_register_operand" "r"))
3078 (const_int 0)))
3079 (clobber (match_scratch:SI 4 "=r"))]
3080 "TARGET_ARM || (TARGET_THUMB2 && CONST_INT_P (operands[2]))"
3ef90e77 3081 "bics%?\\t%4, %3, %1%S0"
9ed784d8 3082 [(set_attr "predicable" "yes")
9ed784d8 3083 (set_attr "conds" "set")
3084 (set_attr "shift" "1")
3085 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3086 (const_string "logic_shift_imm")
3087 (const_string "logic_shift_reg")))]
3088)
3089
3090;; Same as andsi_not_shiftsi_si_scc_no_reuse, but the bics result is also
3091;; getting reused later.
3092(define_insn "andsi_not_shiftsi_si_scc"
3093 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
3094 (compare:CC_NOOV
3095 (and:SI (not:SI (match_operator:SI 0 "shift_operator"
3096 [(match_operand:SI 1 "s_register_operand" "r")
3097 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
3098 (match_operand:SI 3 "s_register_operand" "r"))
3099 (const_int 0)))
3100 (set (match_operand:SI 4 "s_register_operand" "=r")
3101 (and:SI (not:SI (match_op_dup 0
3102 [(match_dup 1)
3103 (match_dup 2)]))
3104 (match_dup 3)))])]
3105 "TARGET_ARM || (TARGET_THUMB2 && CONST_INT_P (operands[2]))"
3ef90e77 3106 "bics%?\\t%4, %3, %1%S0"
9ed784d8 3107 [(set_attr "predicable" "yes")
9ed784d8 3108 (set_attr "conds" "set")
3109 (set_attr "shift" "1")
3110 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3111 (const_string "logic_shift_imm")
3112 (const_string "logic_shift_reg")))]
3113)
3114
f7fbdd4a 3115(define_insn "*andsi_notsi_si_compare0"
bd5b4116 3116 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 3117 (compare:CC_NOOV
3118 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
3119 (match_operand:SI 1 "s_register_operand" "r"))
3120 (const_int 0)))
9c08d1fa 3121 (set (match_operand:SI 0 "s_register_operand" "=r")
3122 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
25f905c2 3123 "TARGET_32BIT"
3ef90e77 3124 "bics\\t%0, %1, %2"
d82e788e 3125 [(set_attr "conds" "set")
3126 (set_attr "type" "logics_shift_reg")]
0d66636f 3127)
9c08d1fa 3128
f7fbdd4a 3129(define_insn "*andsi_notsi_si_compare0_scratch"
bd5b4116 3130 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 3131 (compare:CC_NOOV
3132 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
3133 (match_operand:SI 1 "s_register_operand" "r"))
3134 (const_int 0)))
9c08d1fa 3135 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 3136 "TARGET_32BIT"
3ef90e77 3137 "bics\\t%0, %1, %2"
d82e788e 3138 [(set_attr "conds" "set")
3139 (set_attr "type" "logics_shift_reg")]
0d66636f 3140)
9c08d1fa 3141
e2669ea7 3142(define_expand "iordi3"
3143 [(set (match_operand:DI 0 "s_register_operand" "")
3144 (ior:DI (match_operand:DI 1 "s_register_operand" "")
3145 (match_operand:DI 2 "neon_logic_op2" "")))]
3146 "TARGET_32BIT"
0d84c6e5 3147 "
3148 if (!TARGET_NEON && !TARGET_IWMMXT)
3149 {
3150 rtx low = simplify_gen_binary (IOR, SImode,
3151 gen_lowpart (SImode, operands[1]),
3152 gen_lowpart (SImode, operands[2]));
3153 rtx high = simplify_gen_binary (IOR, SImode,
3154 gen_highpart (SImode, operands[1]),
3155 gen_highpart_mode (SImode, DImode,
3156 operands[2]));
3157
3158 emit_insn (gen_rtx_SET (gen_lowpart (SImode, operands[0]), low));
3159 emit_insn (gen_rtx_SET (gen_highpart (SImode, operands[0]), high));
3160
3161 DONE;
3162 }
3163 /* Otherwise expand pattern as above. */
3164 "
e2669ea7 3165)
3166
74d6113f 3167(define_insn_and_split "*iordi3_insn"
3168 [(set (match_operand:DI 0 "s_register_operand" "=w,w ,&r,&r,&r,&r,?w,?w")
3169 (ior:DI (match_operand:DI 1 "s_register_operand" "%w,0 ,0 ,r ,0 ,r ,w ,0")
e0fe6977 3170 (match_operand:DI 2 "arm_iordi_operand_neon" "w ,Dl,r ,r ,Df,Df,w ,Dl")))]
74d6113f 3171 "TARGET_32BIT && !TARGET_IWMMXT"
3172 {
3173 switch (which_alternative)
3174 {
3175 case 0: /* fall through */
3176 case 6: return "vorr\t%P0, %P1, %P2";
3177 case 1: /* fall through */
3178 case 7: return neon_output_logic_immediate ("vorr", &operands[2],
3179 DImode, 0, VALID_NEON_QREG_MODE (DImode));
3180 case 2:
3181 case 3:
3182 case 4:
3183 case 5:
3184 return "#";
3185 default: gcc_unreachable ();
3186 }
3187 }
3188 "TARGET_32BIT && !TARGET_IWMMXT && reload_completed
3189 && !(IS_VFP_REGNUM (REGNO (operands[0])))"
3190 [(set (match_dup 3) (match_dup 4))
3191 (set (match_dup 5) (match_dup 6))]
3192 "
3193 {
3194 operands[3] = gen_lowpart (SImode, operands[0]);
3195 operands[5] = gen_highpart (SImode, operands[0]);
3196
3197 operands[4] = simplify_gen_binary (IOR, SImode,
3198 gen_lowpart (SImode, operands[1]),
3199 gen_lowpart (SImode, operands[2]));
3200 operands[6] = simplify_gen_binary (IOR, SImode,
3201 gen_highpart (SImode, operands[1]),
3202 gen_highpart_mode (SImode, DImode, operands[2]));
3203
3204 }"
32093010 3205 [(set_attr "type" "neon_logic,neon_logic,multiple,multiple,multiple,\
3206 multiple,neon_logic,neon_logic")
e0fe6977 3207 (set_attr "length" "*,*,8,8,8,8,*,*")
74d6113f 3208 (set_attr "arch" "neon_for_64bits,neon_for_64bits,*,*,*,*,avoid_neon_for_64bits,avoid_neon_for_64bits")]
cffb2a26 3209)
9c08d1fa 3210
f7fbdd4a 3211(define_insn "*iordi_zesidi_di"
9c08d1fa 3212 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3213 (ior:DI (zero_extend:DI
3214 (match_operand:SI 2 "s_register_operand" "r,r"))
e2348bcb 3215 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 3216 "TARGET_32BIT"
e2348bcb 3217 "@
97499065 3218 orr%?\\t%Q0, %Q1, %2
f6ebffac 3219 #"
0d66636f 3220 [(set_attr "length" "4,8")
d952d547 3221 (set_attr "predicable" "yes")
1b7da4ac 3222 (set_attr "type" "logic_reg,multiple")]
cffb2a26 3223)
9c08d1fa 3224
f7fbdd4a 3225(define_insn "*iordi_sesidi_di"
9c08d1fa 3226 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3227 (ior:DI (sign_extend:DI
3228 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 3229 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 3230 "TARGET_32BIT"
f6ebffac 3231 "#"
0d66636f 3232 [(set_attr "length" "8")
1b7da4ac 3233 (set_attr "predicable" "yes")
3234 (set_attr "type" "multiple")]
cffb2a26 3235)
9c08d1fa 3236
87b22bf7 3237(define_expand "iorsi3"
cffb2a26 3238 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3239 (ior:SI (match_operand:SI 1 "s_register_operand" "")
3240 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 3241 "TARGET_EITHER"
87b22bf7 3242 "
0438d37f 3243 if (CONST_INT_P (operands[2]))
87b22bf7 3244 {
25f905c2 3245 if (TARGET_32BIT)
cffb2a26 3246 {
17202aa5 3247 if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[2]), IOR))
3248 operands[2] = force_reg (SImode, operands[2]);
3249 else
3250 {
3251 arm_split_constant (IOR, SImode, NULL_RTX,
3252 INTVAL (operands[2]), operands[0],
3253 operands[1],
3254 optimize && can_create_pseudo_p ());
3255 DONE;
3256 }
cffb2a26 3257 }
25f905c2 3258 else /* TARGET_THUMB1 */
923ffadb 3259 {
3260 rtx tmp = force_reg (SImode, operands[2]);
3261 if (rtx_equal_p (operands[0], operands[1]))
3262 operands[2] = tmp;
3263 else
3264 {
3265 operands[2] = operands[1];
3266 operands[1] = tmp;
3267 }
3268 }
87b22bf7 3269 }
cffb2a26 3270 "
3271)
87b22bf7 3272
d5d4dc8d 3273(define_insn_and_split "*iorsi3_insn"
29e234a3 3274 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r,r,r")
3275 (ior:SI (match_operand:SI 1 "s_register_operand" "%r,0,r,r,r")
3276 (match_operand:SI 2 "reg_or_int_operand" "I,l,K,r,?n")))]
d5d4dc8d 3277 "TARGET_32BIT"
87b22bf7 3278 "@
29e234a3 3279 orr%?\\t%0, %1, %2
87b22bf7 3280 orr%?\\t%0, %1, %2
d5d4dc8d 3281 orn%?\\t%0, %1, #%B2
65f68e55 3282 orr%?\\t%0, %1, %2
87b22bf7 3283 #"
d5d4dc8d 3284 "TARGET_32BIT
0438d37f 3285 && CONST_INT_P (operands[2])
d5d4dc8d 3286 && !(const_ok_for_arm (INTVAL (operands[2]))
3287 || (TARGET_THUMB2 && const_ok_for_arm (~INTVAL (operands[2]))))"
a0f94409 3288 [(clobber (const_int 0))]
d5d4dc8d 3289{
29e234a3 3290 arm_split_constant (IOR, SImode, curr_insn,
96f57e36 3291 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 3292 DONE;
d5d4dc8d 3293}
29e234a3 3294 [(set_attr "length" "4,4,4,4,16")
3295 (set_attr "arch" "32,t2,t2,32,32")
65f68e55 3296 (set_attr "predicable" "yes")
29e234a3 3297 (set_attr "predicable_short_it" "no,yes,no,no,no")
d82e788e 3298 (set_attr "type" "logic_imm,logic_reg,logic_imm,logic_reg,logic_reg")]
65f68e55 3299)
cffb2a26 3300
a0f94409 3301(define_peephole2
3302 [(match_scratch:SI 3 "r")
372575c7 3303 (set (match_operand:SI 0 "arm_general_register_operand" "")
3304 (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
87b22bf7 3305 (match_operand:SI 2 "const_int_operand" "")))]
90560cad 3306 "TARGET_ARM
a0f94409 3307 && !const_ok_for_arm (INTVAL (operands[2]))
3308 && const_ok_for_arm (~INTVAL (operands[2]))"
3309 [(set (match_dup 3) (match_dup 2))
3310 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
3311 ""
215b30b3 3312)
a0f94409 3313
f7fbdd4a 3314(define_insn "*iorsi3_compare0"
bd5b4116 3315 [(set (reg:CC_NOOV CC_REGNUM)
65f68e55 3316 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r,r")
3317 (match_operand:SI 2 "arm_rhs_operand" "I,r"))
9c08d1fa 3318 (const_int 0)))
65f68e55 3319 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 3320 (ior:SI (match_dup 1) (match_dup 2)))]
25f905c2 3321 "TARGET_32BIT"
3ef90e77 3322 "orrs%?\\t%0, %1, %2"
65f68e55 3323 [(set_attr "conds" "set")
d82e788e 3324 (set_attr "type" "logics_imm,logics_reg")]
cffb2a26 3325)
9c08d1fa 3326
f7fbdd4a 3327(define_insn "*iorsi3_compare0_scratch"
bd5b4116 3328 [(set (reg:CC_NOOV CC_REGNUM)
65f68e55 3329 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r,r")
3330 (match_operand:SI 2 "arm_rhs_operand" "I,r"))
9c08d1fa 3331 (const_int 0)))
65f68e55 3332 (clobber (match_scratch:SI 0 "=r,r"))]
25f905c2 3333 "TARGET_32BIT"
3ef90e77 3334 "orrs%?\\t%0, %1, %2"
65f68e55 3335 [(set_attr "conds" "set")
d82e788e 3336 (set_attr "type" "logics_imm,logics_reg")]
0d66636f 3337)
9c08d1fa 3338
e2669ea7 3339(define_expand "xordi3"
3340 [(set (match_operand:DI 0 "s_register_operand" "")
3341 (xor:DI (match_operand:DI 1 "s_register_operand" "")
8ee7dc6f 3342 (match_operand:DI 2 "arm_xordi_operand" "")))]
e2669ea7 3343 "TARGET_32BIT"
8df5e205 3344 {
3345 /* The iWMMXt pattern for xordi3 accepts only register operands but we want
3346 to reuse this expander for all TARGET_32BIT targets so just force the
3347 constants into a register. Unlike for the anddi3 and iordi3 there are
3348 no NEON instructions that take an immediate. */
3349 if (TARGET_IWMMXT && !REG_P (operands[2]))
3350 operands[2] = force_reg (DImode, operands[2]);
0d84c6e5 3351 if (!TARGET_NEON && !TARGET_IWMMXT)
3352 {
3353 rtx low = simplify_gen_binary (XOR, SImode,
3354 gen_lowpart (SImode, operands[1]),
3355 gen_lowpart (SImode, operands[2]));
3356 rtx high = simplify_gen_binary (XOR, SImode,
3357 gen_highpart (SImode, operands[1]),
3358 gen_highpart_mode (SImode, DImode,
3359 operands[2]));
3360
3361 emit_insn (gen_rtx_SET (gen_lowpart (SImode, operands[0]), low));
3362 emit_insn (gen_rtx_SET (gen_highpart (SImode, operands[0]), high));
3363
3364 DONE;
3365 }
3366 /* Otherwise expand pattern as above. */
8df5e205 3367 }
e2669ea7 3368)
3369
8ee7dc6f 3370(define_insn_and_split "*xordi3_insn"
3371 [(set (match_operand:DI 0 "s_register_operand" "=w,&r,&r,&r,&r,?w")
205c3b0a 3372 (xor:DI (match_operand:DI 1 "s_register_operand" "%w ,0,r ,0 ,r ,w")
8ee7dc6f 3373 (match_operand:DI 2 "arm_xordi_operand" "w ,r ,r ,Dg,Dg,w")))]
3374 "TARGET_32BIT && !TARGET_IWMMXT"
3375{
3376 switch (which_alternative)
3377 {
3378 case 1:
3379 case 2:
3380 case 3:
3381 case 4: /* fall through */
3382 return "#";
3383 case 0: /* fall through */
3384 case 5: return "veor\t%P0, %P1, %P2";
3385 default: gcc_unreachable ();
3386 }
3387}
3388 "TARGET_32BIT && !TARGET_IWMMXT && reload_completed
3389 && !(IS_VFP_REGNUM (REGNO (operands[0])))"
3390 [(set (match_dup 3) (match_dup 4))
3391 (set (match_dup 5) (match_dup 6))]
3392 "
3393 {
3394 operands[3] = gen_lowpart (SImode, operands[0]);
3395 operands[5] = gen_highpart (SImode, operands[0]);
3396
3397 operands[4] = simplify_gen_binary (XOR, SImode,
3398 gen_lowpart (SImode, operands[1]),
3399 gen_lowpart (SImode, operands[2]));
3400 operands[6] = simplify_gen_binary (XOR, SImode,
3401 gen_highpart (SImode, operands[1]),
3402 gen_highpart_mode (SImode, DImode, operands[2]));
3403
3404 }"
3405 [(set_attr "length" "*,8,8,8,8,*")
32093010 3406 (set_attr "type" "neon_logic,multiple,multiple,multiple,multiple,neon_logic")
8ee7dc6f 3407 (set_attr "arch" "neon_for_64bits,*,*,*,*,avoid_neon_for_64bits")]
cffb2a26 3408)
9c08d1fa 3409
f7fbdd4a 3410(define_insn "*xordi_zesidi_di"
9c08d1fa 3411 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3412 (xor:DI (zero_extend:DI
3413 (match_operand:SI 2 "s_register_operand" "r,r"))
e2348bcb 3414 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 3415 "TARGET_32BIT"
e2348bcb 3416 "@
97499065 3417 eor%?\\t%Q0, %Q1, %2
f6ebffac 3418 #"
0d66636f 3419 [(set_attr "length" "4,8")
d952d547 3420 (set_attr "predicable" "yes")
1b7da4ac 3421 (set_attr "type" "logic_reg")]
cffb2a26 3422)
9c08d1fa 3423
f7fbdd4a 3424(define_insn "*xordi_sesidi_di"
9c08d1fa 3425 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3426 (xor:DI (sign_extend:DI
3427 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 3428 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 3429 "TARGET_32BIT"
f6ebffac 3430 "#"
0d66636f 3431 [(set_attr "length" "8")
1b7da4ac 3432 (set_attr "predicable" "yes")
3433 (set_attr "type" "multiple")]
cffb2a26 3434)
9c08d1fa 3435
cffb2a26 3436(define_expand "xorsi3"
3437 [(set (match_operand:SI 0 "s_register_operand" "")
3438 (xor:SI (match_operand:SI 1 "s_register_operand" "")
923ffadb 3439 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 3440 "TARGET_EITHER"
0438d37f 3441 "if (CONST_INT_P (operands[2]))
923ffadb 3442 {
3443 if (TARGET_32BIT)
3444 {
17202aa5 3445 if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[2]), XOR))
3446 operands[2] = force_reg (SImode, operands[2]);
3447 else
3448 {
3449 arm_split_constant (XOR, SImode, NULL_RTX,
3450 INTVAL (operands[2]), operands[0],
3451 operands[1],
3452 optimize && can_create_pseudo_p ());
3453 DONE;
3454 }
923ffadb 3455 }
3456 else /* TARGET_THUMB1 */
3457 {
3458 rtx tmp = force_reg (SImode, operands[2]);
3459 if (rtx_equal_p (operands[0], operands[1]))
3460 operands[2] = tmp;
3461 else
3462 {
3463 operands[2] = operands[1];
3464 operands[1] = tmp;
3465 }
3466 }
3467 }"
cffb2a26 3468)
3469
5dcb35d9 3470(define_insn_and_split "*arm_xorsi3"
29e234a3 3471 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r,r")
3472 (xor:SI (match_operand:SI 1 "s_register_operand" "%r,0,r,r")
3473 (match_operand:SI 2 "reg_or_int_operand" "I,l,r,?n")))]
25f905c2 3474 "TARGET_32BIT"
5dcb35d9 3475 "@
29e234a3 3476 eor%?\\t%0, %1, %2
65f68e55 3477 eor%?\\t%0, %1, %2
5dcb35d9 3478 eor%?\\t%0, %1, %2
3479 #"
3480 "TARGET_32BIT
0438d37f 3481 && CONST_INT_P (operands[2])
5dcb35d9 3482 && !const_ok_for_arm (INTVAL (operands[2]))"
3483 [(clobber (const_int 0))]
3484{
3485 arm_split_constant (XOR, SImode, curr_insn,
3486 INTVAL (operands[2]), operands[0], operands[1], 0);
3487 DONE;
3488}
29e234a3 3489 [(set_attr "length" "4,4,4,16")
65f68e55 3490 (set_attr "predicable" "yes")
29e234a3 3491 (set_attr "predicable_short_it" "no,yes,no,no")
1b7da4ac 3492 (set_attr "type" "logic_imm,logic_reg,logic_reg,multiple")]
cffb2a26 3493)
3494
f7fbdd4a 3495(define_insn "*xorsi3_compare0"
bd5b4116 3496 [(set (reg:CC_NOOV CC_REGNUM)
65f68e55 3497 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r,r")
3498 (match_operand:SI 2 "arm_rhs_operand" "I,r"))
9c08d1fa 3499 (const_int 0)))
65f68e55 3500 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 3501 (xor:SI (match_dup 1) (match_dup 2)))]
25f905c2 3502 "TARGET_32BIT"
3ef90e77 3503 "eors%?\\t%0, %1, %2"
65f68e55 3504 [(set_attr "conds" "set")
d82e788e 3505 (set_attr "type" "logics_imm,logics_reg")]
0d66636f 3506)
9c08d1fa 3507
f7fbdd4a 3508(define_insn "*xorsi3_compare0_scratch"
bd5b4116 3509 [(set (reg:CC_NOOV CC_REGNUM)
65f68e55 3510 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r,r")
3511 (match_operand:SI 1 "arm_rhs_operand" "I,r"))
9c08d1fa 3512 (const_int 0)))]
25f905c2 3513 "TARGET_32BIT"
40dbec34 3514 "teq%?\\t%0, %1"
65f68e55 3515 [(set_attr "conds" "set")
d82e788e 3516 (set_attr "type" "logics_imm,logics_reg")]
cffb2a26 3517)
9c08d1fa 3518
215b30b3 3519; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
3520; (NOT D) we can sometimes merge the final NOT into one of the following
3521; insns.
9c08d1fa 3522
3523(define_split
a058e94a 3524 [(set (match_operand:SI 0 "s_register_operand" "")
3525 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
3526 (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
3527 (match_operand:SI 3 "arm_rhs_operand" "")))
3528 (clobber (match_operand:SI 4 "s_register_operand" ""))]
25f905c2 3529 "TARGET_32BIT"
9c08d1fa 3530 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
3531 (not:SI (match_dup 3))))
3532 (set (match_dup 0) (not:SI (match_dup 4)))]
3533 ""
3534)
3535
ba6a3b2f 3536(define_insn_and_split "*andsi_iorsi3_notsi"
9c08d1fa 3537 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
e5fea38e 3538 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "%0,r,r")
9c08d1fa 3539 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
3540 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
25f905c2 3541 "TARGET_32BIT"
ba6a3b2f 3542 "#" ; "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
3543 "&& reload_completed"
3544 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
054fd237 3545 (set (match_dup 0) (and:SI (match_dup 4) (match_dup 5)))]
3546 {
3547 /* If operands[3] is a constant make sure to fold the NOT into it
3548 to avoid creating a NOT of a CONST_INT. */
3549 rtx not_rtx = simplify_gen_unary (NOT, SImode, operands[3], SImode);
3550 if (CONST_INT_P (not_rtx))
3551 {
3552 operands[4] = operands[0];
3553 operands[5] = not_rtx;
3554 }
3555 else
3556 {
3557 operands[5] = operands[0];
3558 operands[4] = not_rtx;
3559 }
3560 }
0d66636f 3561 [(set_attr "length" "8")
25f905c2 3562 (set_attr "ce_count" "2")
d952d547 3563 (set_attr "predicable" "yes")
1b7da4ac 3564 (set_attr "type" "multiple")]
cffb2a26 3565)
9c08d1fa 3566
25f905c2 3567; ??? Are these four splitters still beneficial when the Thumb-2 bitfield
3568; insns are available?
d7863cfe 3569(define_split
3570 [(set (match_operand:SI 0 "s_register_operand" "")
3571 (match_operator:SI 1 "logical_binary_operator"
3572 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
3573 (match_operand:SI 3 "const_int_operand" "")
3574 (match_operand:SI 4 "const_int_operand" ""))
3575 (match_operator:SI 9 "logical_binary_operator"
3576 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3577 (match_operand:SI 6 "const_int_operand" ""))
3578 (match_operand:SI 7 "s_register_operand" "")])]))
3579 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3580 "TARGET_32BIT
d7863cfe 3581 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3582 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3583 [(set (match_dup 8)
3584 (match_op_dup 1
3585 [(ashift:SI (match_dup 2) (match_dup 4))
3586 (match_dup 5)]))
3587 (set (match_dup 0)
3588 (match_op_dup 1
3589 [(lshiftrt:SI (match_dup 8) (match_dup 6))
3590 (match_dup 7)]))]
3591 "
3592 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3593")
3594
3595(define_split
3596 [(set (match_operand:SI 0 "s_register_operand" "")
3597 (match_operator:SI 1 "logical_binary_operator"
3598 [(match_operator:SI 9 "logical_binary_operator"
3599 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3600 (match_operand:SI 6 "const_int_operand" ""))
3601 (match_operand:SI 7 "s_register_operand" "")])
3602 (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
3603 (match_operand:SI 3 "const_int_operand" "")
3604 (match_operand:SI 4 "const_int_operand" ""))]))
3605 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3606 "TARGET_32BIT
d7863cfe 3607 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3608 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3609 [(set (match_dup 8)
3610 (match_op_dup 1
3611 [(ashift:SI (match_dup 2) (match_dup 4))
3612 (match_dup 5)]))
3613 (set (match_dup 0)
3614 (match_op_dup 1
3615 [(lshiftrt:SI (match_dup 8) (match_dup 6))
3616 (match_dup 7)]))]
3617 "
3618 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3619")
3620
3621(define_split
3622 [(set (match_operand:SI 0 "s_register_operand" "")
3623 (match_operator:SI 1 "logical_binary_operator"
3624 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
3625 (match_operand:SI 3 "const_int_operand" "")
3626 (match_operand:SI 4 "const_int_operand" ""))
3627 (match_operator:SI 9 "logical_binary_operator"
3628 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3629 (match_operand:SI 6 "const_int_operand" ""))
3630 (match_operand:SI 7 "s_register_operand" "")])]))
3631 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3632 "TARGET_32BIT
d7863cfe 3633 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3634 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3635 [(set (match_dup 8)
3636 (match_op_dup 1
3637 [(ashift:SI (match_dup 2) (match_dup 4))
3638 (match_dup 5)]))
3639 (set (match_dup 0)
3640 (match_op_dup 1
3641 [(ashiftrt:SI (match_dup 8) (match_dup 6))
3642 (match_dup 7)]))]
3643 "
3644 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3645")
3646
3647(define_split
3648 [(set (match_operand:SI 0 "s_register_operand" "")
3649 (match_operator:SI 1 "logical_binary_operator"
3650 [(match_operator:SI 9 "logical_binary_operator"
3651 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3652 (match_operand:SI 6 "const_int_operand" ""))
3653 (match_operand:SI 7 "s_register_operand" "")])
3654 (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
3655 (match_operand:SI 3 "const_int_operand" "")
3656 (match_operand:SI 4 "const_int_operand" ""))]))
3657 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3658 "TARGET_32BIT
d7863cfe 3659 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3660 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3661 [(set (match_dup 8)
3662 (match_op_dup 1
3663 [(ashift:SI (match_dup 2) (match_dup 4))
3664 (match_dup 5)]))
3665 (set (match_dup 0)
3666 (match_op_dup 1
3667 [(ashiftrt:SI (match_dup 8) (match_dup 6))
3668 (match_dup 7)]))]
3669 "
3670 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3671")
9c08d1fa 3672\f
3673
3674;; Minimum and maximum insns
3675
8b9dc177 3676(define_expand "smaxsi3"
3677 [(parallel [
3678 (set (match_operand:SI 0 "s_register_operand" "")
3679 (smax:SI (match_operand:SI 1 "s_register_operand" "")
3680 (match_operand:SI 2 "arm_rhs_operand" "")))
3681 (clobber (reg:CC CC_REGNUM))])]
25f905c2 3682 "TARGET_32BIT"
8b9dc177 3683 "
8774928b 3684 if (operands[2] == const0_rtx || operands[2] == constm1_rtx)
8b9dc177 3685 {
3686 /* No need for a clobber of the condition code register here. */
d1f9b275 3687 emit_insn (gen_rtx_SET (operands[0],
8b9dc177 3688 gen_rtx_SMAX (SImode, operands[1],
3689 operands[2])));
3690 DONE;
3691 }
3692")
3693
3694(define_insn "*smax_0"
3695 [(set (match_operand:SI 0 "s_register_operand" "=r")
3696 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3697 (const_int 0)))]
25f905c2 3698 "TARGET_32BIT"
8b9dc177 3699 "bic%?\\t%0, %1, %1, asr #31"
d952d547 3700 [(set_attr "predicable" "yes")
1b7da4ac 3701 (set_attr "type" "logic_shift_reg")]
8b9dc177 3702)
3703
8774928b 3704(define_insn "*smax_m1"
3705 [(set (match_operand:SI 0 "s_register_operand" "=r")
3706 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3707 (const_int -1)))]
25f905c2 3708 "TARGET_32BIT"
8774928b 3709 "orr%?\\t%0, %1, %1, asr #31"
d952d547 3710 [(set_attr "predicable" "yes")
1b7da4ac 3711 (set_attr "type" "logic_shift_reg")]
8774928b 3712)
3713
3dc953f2 3714(define_insn_and_split "*arm_smax_insn"
8b9dc177 3715 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3716 (smax:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3717 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
bd5b4116 3718 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3719 "TARGET_ARM"
3dc953f2 3720 "#"
3721 ; cmp\\t%1, %2\;movlt\\t%0, %2
3722 ; cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
3723 "TARGET_ARM"
3724 [(set (reg:CC CC_REGNUM)
3725 (compare:CC (match_dup 1) (match_dup 2)))
3726 (set (match_dup 0)
3727 (if_then_else:SI (ge:SI (reg:CC CC_REGNUM) (const_int 0))
3728 (match_dup 1)
3729 (match_dup 2)))]
3730 ""
cffb2a26 3731 [(set_attr "conds" "clob")
1b7da4ac 3732 (set_attr "length" "8,12")
3733 (set_attr "type" "multiple")]
cffb2a26 3734)
9c08d1fa 3735
8b9dc177 3736(define_expand "sminsi3"
3737 [(parallel [
3738 (set (match_operand:SI 0 "s_register_operand" "")
3739 (smin:SI (match_operand:SI 1 "s_register_operand" "")
3740 (match_operand:SI 2 "arm_rhs_operand" "")))
3741 (clobber (reg:CC CC_REGNUM))])]
25f905c2 3742 "TARGET_32BIT"
8b9dc177 3743 "
3744 if (operands[2] == const0_rtx)
3745 {
3746 /* No need for a clobber of the condition code register here. */
d1f9b275 3747 emit_insn (gen_rtx_SET (operands[0],
8b9dc177 3748 gen_rtx_SMIN (SImode, operands[1],
3749 operands[2])));
3750 DONE;
3751 }
3752")
3753
3754(define_insn "*smin_0"
3755 [(set (match_operand:SI 0 "s_register_operand" "=r")
3756 (smin:SI (match_operand:SI 1 "s_register_operand" "r")
3757 (const_int 0)))]
25f905c2 3758 "TARGET_32BIT"
8b9dc177 3759 "and%?\\t%0, %1, %1, asr #31"
d952d547 3760 [(set_attr "predicable" "yes")
1b7da4ac 3761 (set_attr "type" "logic_shift_reg")]
8b9dc177 3762)
3763
3dc953f2 3764(define_insn_and_split "*arm_smin_insn"
8b9dc177 3765 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3766 (smin:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3767 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
bd5b4116 3768 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3769 "TARGET_ARM"
3dc953f2 3770 "#"
3771 ; cmp\\t%1, %2\;movge\\t%0, %2
3772 ; cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
3773 "TARGET_ARM"
3774 [(set (reg:CC CC_REGNUM)
3775 (compare:CC (match_dup 1) (match_dup 2)))
3776 (set (match_dup 0)
3777 (if_then_else:SI (lt:SI (reg:CC CC_REGNUM) (const_int 0))
3778 (match_dup 1)
3779 (match_dup 2)))]
3780 ""
0d66636f 3781 [(set_attr "conds" "clob")
1b7da4ac 3782 (set_attr "length" "8,12")
3783 (set_attr "type" "multiple,multiple")]
0d66636f 3784)
9c08d1fa 3785
25f905c2 3786(define_expand "umaxsi3"
3787 [(parallel [
3788 (set (match_operand:SI 0 "s_register_operand" "")
3789 (umax:SI (match_operand:SI 1 "s_register_operand" "")
3790 (match_operand:SI 2 "arm_rhs_operand" "")))
3791 (clobber (reg:CC CC_REGNUM))])]
3792 "TARGET_32BIT"
3793 ""
3794)
3795
3dc953f2 3796(define_insn_and_split "*arm_umaxsi3"
9c08d1fa 3797 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3798 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3799 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 3800 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3801 "TARGET_ARM"
3dc953f2 3802 "#"
3803 ; cmp\\t%1, %2\;movcc\\t%0, %2
3804 ; cmp\\t%1, %2\;movcs\\t%0, %1
3805 ; cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
3806 "TARGET_ARM"
3807 [(set (reg:CC CC_REGNUM)
3808 (compare:CC (match_dup 1) (match_dup 2)))
3809 (set (match_dup 0)
3810 (if_then_else:SI (geu:SI (reg:CC CC_REGNUM) (const_int 0))
3811 (match_dup 1)
3812 (match_dup 2)))]
3813 ""
0d66636f 3814 [(set_attr "conds" "clob")
1b7da4ac 3815 (set_attr "length" "8,8,12")
9f2c2a36 3816 (set_attr "type" "store_4")]
0d66636f 3817)
9c08d1fa 3818
25f905c2 3819(define_expand "uminsi3"
3820 [(parallel [
3821 (set (match_operand:SI 0 "s_register_operand" "")
3822 (umin:SI (match_operand:SI 1 "s_register_operand" "")
3823 (match_operand:SI 2 "arm_rhs_operand" "")))
3824 (clobber (reg:CC CC_REGNUM))])]
3825 "TARGET_32BIT"
3826 ""
3827)
3828
3dc953f2 3829(define_insn_and_split "*arm_uminsi3"
9c08d1fa 3830 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3831 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3832 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 3833 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3834 "TARGET_ARM"
3dc953f2 3835 "#"
3836 ; cmp\\t%1, %2\;movcs\\t%0, %2
3837 ; cmp\\t%1, %2\;movcc\\t%0, %1
3838 ; cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
3839 "TARGET_ARM"
3840 [(set (reg:CC CC_REGNUM)
3841 (compare:CC (match_dup 1) (match_dup 2)))
3842 (set (match_dup 0)
3843 (if_then_else:SI (ltu:SI (reg:CC CC_REGNUM) (const_int 0))
3844 (match_dup 1)
3845 (match_dup 2)))]
3846 ""
0d66636f 3847 [(set_attr "conds" "clob")
1b7da4ac 3848 (set_attr "length" "8,8,12")
9f2c2a36 3849 (set_attr "type" "store_4")]
0d66636f 3850)
9c08d1fa 3851
8a18b90c 3852(define_insn "*store_minmaxsi"
9c08d1fa 3853 [(set (match_operand:SI 0 "memory_operand" "=m")
3854 (match_operator:SI 3 "minmax_operator"
3855 [(match_operand:SI 1 "s_register_operand" "r")
3856 (match_operand:SI 2 "s_register_operand" "r")]))
bd5b4116 3857 (clobber (reg:CC CC_REGNUM))]
b207d152 3858 "TARGET_32BIT && optimize_function_for_size_p (cfun) && !arm_restrict_it"
9c08d1fa 3859 "*
dc55b8a9 3860 operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
3861 operands[1], operands[2]);
e2348bcb 3862 output_asm_insn (\"cmp\\t%1, %2\", operands);
25f905c2 3863 if (TARGET_THUMB2)
3864 output_asm_insn (\"ite\t%d3\", operands);
e2348bcb 3865 output_asm_insn (\"str%d3\\t%1, %0\", operands);
3866 output_asm_insn (\"str%D3\\t%2, %0\", operands);
3867 return \"\";
0d66636f 3868 "
3869 [(set_attr "conds" "clob")
25f905c2 3870 (set (attr "length")
3871 (if_then_else (eq_attr "is_thumb" "yes")
3872 (const_int 14)
3873 (const_int 12)))
9f2c2a36 3874 (set_attr "type" "store_4")]
0d66636f 3875)
9c08d1fa 3876
8a18b90c 3877; Reject the frame pointer in operand[1], since reloading this after
3878; it has been eliminated can cause carnage.
f7fbdd4a 3879(define_insn "*minmax_arithsi"
9c08d1fa 3880 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3881 (match_operator:SI 4 "shiftable_operator"
3882 [(match_operator:SI 5 "minmax_operator"
3883 [(match_operand:SI 2 "s_register_operand" "r,r")
3884 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
3885 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 3886 (clobber (reg:CC CC_REGNUM))]
7c36fe71 3887 "TARGET_32BIT && !arm_eliminable_register (operands[1]) && !arm_restrict_it"
9c08d1fa 3888 "*
0d66636f 3889 {
3890 enum rtx_code code = GET_CODE (operands[4]);
25f905c2 3891 bool need_else;
3892
3893 if (which_alternative != 0 || operands[3] != const0_rtx
ca0fc5a2 3894 || (code != PLUS && code != IOR && code != XOR))
25f905c2 3895 need_else = true;
3896 else
3897 need_else = false;
0d66636f 3898
dc55b8a9 3899 operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
3900 operands[2], operands[3]);
0d66636f 3901 output_asm_insn (\"cmp\\t%2, %3\", operands);
25f905c2 3902 if (TARGET_THUMB2)
3903 {
3904 if (need_else)
3905 output_asm_insn (\"ite\\t%d5\", operands);
3906 else
3907 output_asm_insn (\"it\\t%d5\", operands);
3908 }
0d66636f 3909 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
25f905c2 3910 if (need_else)
0d66636f 3911 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
3912 return \"\";
215b30b3 3913 }"
0d66636f 3914 [(set_attr "conds" "clob")
25f905c2 3915 (set (attr "length")
3916 (if_then_else (eq_attr "is_thumb" "yes")
3917 (const_int 14)
1b7da4ac 3918 (const_int 12)))
3919 (set_attr "type" "multiple")]
0d66636f 3920)
9c08d1fa 3921
4164bca1 3922; Reject the frame pointer in operand[1], since reloading this after
3923; it has been eliminated can cause carnage.
3924(define_insn_and_split "*minmax_arithsi_non_canon"
7c36fe71 3925 [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts")
4164bca1 3926 (minus:SI
7c36fe71 3927 (match_operand:SI 1 "s_register_operand" "0,?Ts")
4164bca1 3928 (match_operator:SI 4 "minmax_operator"
7c36fe71 3929 [(match_operand:SI 2 "s_register_operand" "Ts,Ts")
3930 (match_operand:SI 3 "arm_rhs_operand" "TsI,TsI")])))
4164bca1 3931 (clobber (reg:CC CC_REGNUM))]
7c36fe71 3932 "TARGET_32BIT && !arm_eliminable_register (operands[1])
3933 && !(arm_restrict_it && CONST_INT_P (operands[3]))"
4164bca1 3934 "#"
3935 "TARGET_32BIT && !arm_eliminable_register (operands[1]) && reload_completed"
3936 [(set (reg:CC CC_REGNUM)
3937 (compare:CC (match_dup 2) (match_dup 3)))
3938
3939 (cond_exec (match_op_dup 4 [(reg:CC CC_REGNUM) (const_int 0)])
3940 (set (match_dup 0)
3941 (minus:SI (match_dup 1)
3942 (match_dup 2))))
3943 (cond_exec (match_op_dup 5 [(reg:CC CC_REGNUM) (const_int 0)])
3944 (set (match_dup 0)
36ee0cde 3945 (match_dup 6)))]
4164bca1 3946 {
3754d046 3947 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
4164bca1 3948 operands[2], operands[3]);
3949 enum rtx_code rc = minmax_code (operands[4]);
3950 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode,
3951 operands[2], operands[3]);
3952
3953 if (mode == CCFPmode || mode == CCFPEmode)
3954 rc = reverse_condition_maybe_unordered (rc);
3955 else
3956 rc = reverse_condition (rc);
3957 operands[5] = gen_rtx_fmt_ee (rc, SImode, operands[2], operands[3]);
36ee0cde 3958 if (CONST_INT_P (operands[3]))
3959 operands[6] = plus_constant (SImode, operands[1], -INTVAL (operands[3]));
3960 else
3961 operands[6] = gen_rtx_MINUS (SImode, operands[1], operands[3]);
4164bca1 3962 }
3963 [(set_attr "conds" "clob")
3964 (set (attr "length")
3965 (if_then_else (eq_attr "is_thumb" "yes")
3966 (const_int 14)
1b7da4ac 3967 (const_int 12)))
3968 (set_attr "type" "multiple")]
4164bca1 3969)
3970
b49e3742 3971(define_code_iterator SAT [smin smax])
3972(define_code_iterator SATrev [smin smax])
3973(define_code_attr SATlo [(smin "1") (smax "2")])
3974(define_code_attr SAThi [(smin "2") (smax "1")])
3975
3976(define_insn "*satsi_<SAT:code>"
3977 [(set (match_operand:SI 0 "s_register_operand" "=r")
3978 (SAT:SI (SATrev:SI (match_operand:SI 3 "s_register_operand" "r")
3979 (match_operand:SI 1 "const_int_operand" "i"))
3980 (match_operand:SI 2 "const_int_operand" "i")))]
3981 "TARGET_32BIT && arm_arch6 && <SAT:CODE> != <SATrev:CODE>
3982 && arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>], NULL, NULL)"
3983{
3984 int mask;
3985 bool signed_sat;
3986 if (!arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>],
3987 &mask, &signed_sat))
3988 gcc_unreachable ();
3989
3990 operands[1] = GEN_INT (mask);
3991 if (signed_sat)
3992 return "ssat%?\t%0, %1, %3";
3993 else
3994 return "usat%?\t%0, %1, %3";
3995}
7c36fe71 3996 [(set_attr "predicable" "yes")
1b7da4ac 3997 (set_attr "type" "alus_imm")]
bebe9bbb 3998)
b49e3742 3999
4000(define_insn "*satsi_<SAT:code>_shift"
4001 [(set (match_operand:SI 0 "s_register_operand" "=r")
4002 (SAT:SI (SATrev:SI (match_operator:SI 3 "sat_shift_operator"
4003 [(match_operand:SI 4 "s_register_operand" "r")
4004 (match_operand:SI 5 "const_int_operand" "i")])
4005 (match_operand:SI 1 "const_int_operand" "i"))
4006 (match_operand:SI 2 "const_int_operand" "i")))]
4007 "TARGET_32BIT && arm_arch6 && <SAT:CODE> != <SATrev:CODE>
4008 && arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>], NULL, NULL)"
4009{
4010 int mask;
4011 bool signed_sat;
4012 if (!arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>],
4013 &mask, &signed_sat))
4014 gcc_unreachable ();
4015
4016 operands[1] = GEN_INT (mask);
4017 if (signed_sat)
4018 return "ssat%?\t%0, %1, %4%S3";
4019 else
4020 return "usat%?\t%0, %1, %4%S3";
4021}
4022 [(set_attr "predicable" "yes")
b49e3742 4023 (set_attr "shift" "3")
d82e788e 4024 (set_attr "type" "logic_shift_reg")])
b11cae9e 4025\f
4026;; Shift and rotation insns
4027
a2cd141b 4028(define_expand "ashldi3"
4029 [(set (match_operand:DI 0 "s_register_operand" "")
4030 (ashift:DI (match_operand:DI 1 "s_register_operand" "")
aa06c51c 4031 (match_operand:SI 2 "general_operand" "")))]
25f905c2 4032 "TARGET_32BIT"
a2cd141b 4033 "
aa06c51c 4034 if (TARGET_NEON)
4035 {
4036 /* Delay the decision whether to use NEON or core-regs until
4037 register allocation. */
4038 emit_insn (gen_ashldi3_neon (operands[0], operands[1], operands[2]));
4039 DONE;
4040 }
4041 else
4042 {
4043 /* Only the NEON case can handle in-memory shift counts. */
4044 if (!reg_or_int_operand (operands[2], SImode))
4045 operands[2] = force_reg (SImode, operands[2]);
4046 }
4047
b805622c 4048 if (!CONST_INT_P (operands[2]) && TARGET_REALLY_IWMMXT)
ffcc986d 4049 ; /* No special preparation statements; expand pattern as above. */
4050 else
a2cd141b 4051 {
ffcc986d 4052 rtx scratch1, scratch2;
4053
ffcc986d 4054 /* Ideally we should use iwmmxt here if we could know that operands[1]
4055 ends up already living in an iwmmxt register. Otherwise it's
4056 cheaper to have the alternate code being generated than moving
4057 values to iwmmxt regs and back. */
4058
ffcc986d 4059 /* Expand operation using core-registers.
4060 'FAIL' would achieve the same thing, but this is a bit smarter. */
4061 scratch1 = gen_reg_rtx (SImode);
4062 scratch2 = gen_reg_rtx (SImode);
4063 arm_emit_coreregs_64bit_shift (ASHIFT, operands[0], operands[1],
4064 operands[2], scratch1, scratch2);
4065 DONE;
a2cd141b 4066 }
a2cd141b 4067 "
4068)
4069
87b22bf7 4070(define_expand "ashlsi3"
cffb2a26 4071 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 4072 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
4073 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 4074 "TARGET_EITHER"
87b22bf7 4075 "
0438d37f 4076 if (CONST_INT_P (operands[2])
8c4e8755 4077 && (UINTVAL (operands[2])) > 31)
87b22bf7 4078 {
4079 emit_insn (gen_movsi (operands[0], const0_rtx));
4080 DONE;
4081 }
cffb2a26 4082 "
4083)
4084
a2cd141b 4085(define_expand "ashrdi3"
4086 [(set (match_operand:DI 0 "s_register_operand" "")
4087 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
4088 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 4089 "TARGET_32BIT"
a2cd141b 4090 "
aa06c51c 4091 if (TARGET_NEON)
4092 {
4093 /* Delay the decision whether to use NEON or core-regs until
4094 register allocation. */
4095 emit_insn (gen_ashrdi3_neon (operands[0], operands[1], operands[2]));
4096 DONE;
4097 }
4098
b805622c 4099 if (!CONST_INT_P (operands[2]) && TARGET_REALLY_IWMMXT)
ffcc986d 4100 ; /* No special preparation statements; expand pattern as above. */
4101 else
a2cd141b 4102 {
ffcc986d 4103 rtx scratch1, scratch2;
4104
ffcc986d 4105 /* Ideally we should use iwmmxt here if we could know that operands[1]
4106 ends up already living in an iwmmxt register. Otherwise it's
4107 cheaper to have the alternate code being generated than moving
4108 values to iwmmxt regs and back. */
4109
ffcc986d 4110 /* Expand operation using core-registers.
4111 'FAIL' would achieve the same thing, but this is a bit smarter. */
4112 scratch1 = gen_reg_rtx (SImode);
4113 scratch2 = gen_reg_rtx (SImode);
4114 arm_emit_coreregs_64bit_shift (ASHIFTRT, operands[0], operands[1],
4115 operands[2], scratch1, scratch2);
4116 DONE;
a2cd141b 4117 }
a2cd141b 4118 "
4119)
4120
87b22bf7 4121(define_expand "ashrsi3"
cffb2a26 4122 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 4123 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
4124 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 4125 "TARGET_EITHER"
87b22bf7 4126 "
0438d37f 4127 if (CONST_INT_P (operands[2])
8c4e8755 4128 && UINTVAL (operands[2]) > 31)
87b22bf7 4129 operands[2] = GEN_INT (31);
cffb2a26 4130 "
4131)
4132
a2cd141b 4133(define_expand "lshrdi3"
4134 [(set (match_operand:DI 0 "s_register_operand" "")
4135 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
4136 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 4137 "TARGET_32BIT"
a2cd141b 4138 "
aa06c51c 4139 if (TARGET_NEON)
4140 {
4141 /* Delay the decision whether to use NEON or core-regs until
4142 register allocation. */
4143 emit_insn (gen_lshrdi3_neon (operands[0], operands[1], operands[2]));
4144 DONE;
4145 }
4146
b805622c 4147 if (!CONST_INT_P (operands[2]) && TARGET_REALLY_IWMMXT)
ffcc986d 4148 ; /* No special preparation statements; expand pattern as above. */
4149 else
a2cd141b 4150 {
ffcc986d 4151 rtx scratch1, scratch2;
4152
ffcc986d 4153 /* Ideally we should use iwmmxt here if we could know that operands[1]
4154 ends up already living in an iwmmxt register. Otherwise it's
4155 cheaper to have the alternate code being generated than moving
4156 values to iwmmxt regs and back. */
4157
ffcc986d 4158 /* Expand operation using core-registers.
4159 'FAIL' would achieve the same thing, but this is a bit smarter. */
4160 scratch1 = gen_reg_rtx (SImode);
4161 scratch2 = gen_reg_rtx (SImode);
4162 arm_emit_coreregs_64bit_shift (LSHIFTRT, operands[0], operands[1],
4163 operands[2], scratch1, scratch2);
4164 DONE;
a2cd141b 4165 }
a2cd141b 4166 "
4167)
4168
87b22bf7 4169(define_expand "lshrsi3"
cffb2a26 4170 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 4171 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
4172 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 4173 "TARGET_EITHER"
87b22bf7 4174 "
0438d37f 4175 if (CONST_INT_P (operands[2])
8c4e8755 4176 && (UINTVAL (operands[2])) > 31)
87b22bf7 4177 {
4178 emit_insn (gen_movsi (operands[0], const0_rtx));
4179 DONE;
4180 }
cffb2a26 4181 "
4182)
4183
87b22bf7 4184(define_expand "rotlsi3"
cffb2a26 4185 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 4186 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
4187 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 4188 "TARGET_32BIT"
87b22bf7 4189 "
0438d37f 4190 if (CONST_INT_P (operands[2]))
87b22bf7 4191 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
4192 else
b11cae9e 4193 {
87b22bf7 4194 rtx reg = gen_reg_rtx (SImode);
4195 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
4196 operands[2] = reg;
b11cae9e 4197 }
cffb2a26 4198 "
4199)
9c08d1fa 4200
87b22bf7 4201(define_expand "rotrsi3"
cffb2a26 4202 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 4203 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
4204 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 4205 "TARGET_EITHER"
87b22bf7 4206 "
25f905c2 4207 if (TARGET_32BIT)
cffb2a26 4208 {
0438d37f 4209 if (CONST_INT_P (operands[2])
8c4e8755 4210 && UINTVAL (operands[2]) > 31)
cffb2a26 4211 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
4212 }
25f905c2 4213 else /* TARGET_THUMB1 */
cffb2a26 4214 {
0438d37f 4215 if (CONST_INT_P (operands [2]))
cffb2a26 4216 operands [2] = force_reg (SImode, operands[2]);
4217 }
4218 "
4219)
87b22bf7 4220
cffb2a26 4221(define_insn "*arm_shiftsi3"
88c29385 4222 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r,r")
cffb2a26 4223 (match_operator:SI 3 "shift_operator"
88c29385 4224 [(match_operand:SI 1 "s_register_operand" "0,l,r,r")
4225 (match_operand:SI 2 "reg_or_int_operand" "l,M,M,r")]))]
25f905c2 4226 "TARGET_32BIT"
4227 "* return arm_output_shift(operands, 0);"
344495ea 4228 [(set_attr "predicable" "yes")
88c29385 4229 (set_attr "arch" "t2,t2,*,*")
4230 (set_attr "predicable_short_it" "yes,yes,no,no")
7c36fe71 4231 (set_attr "length" "4")
331beb1a 4232 (set_attr "shift" "1")
88c29385 4233 (set_attr "type" "alu_shift_reg,alu_shift_imm,alu_shift_imm,alu_shift_reg")]
6c4c2133 4234)
87b22bf7 4235
f7fbdd4a 4236(define_insn "*shiftsi3_compare0"
bd5b4116 4237 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 4238 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
6b6abc9c 4239 [(match_operand:SI 1 "s_register_operand" "r,r")
4240 (match_operand:SI 2 "arm_rhs_operand" "M,r")])
9c08d1fa 4241 (const_int 0)))
6b6abc9c 4242 (set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 4243 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
25f905c2 4244 "TARGET_32BIT"
4245 "* return arm_output_shift(operands, 1);"
344495ea 4246 [(set_attr "conds" "set")
331beb1a 4247 (set_attr "shift" "1")
d82e788e 4248 (set_attr "type" "alus_shift_imm,alus_shift_reg")]
0d66636f 4249)
9c08d1fa 4250
f7fbdd4a 4251(define_insn "*shiftsi3_compare0_scratch"
bd5b4116 4252 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 4253 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
6b6abc9c 4254 [(match_operand:SI 1 "s_register_operand" "r,r")
4255 (match_operand:SI 2 "arm_rhs_operand" "M,r")])
9c08d1fa 4256 (const_int 0)))
6b6abc9c 4257 (clobber (match_scratch:SI 0 "=r,r"))]
25f905c2 4258 "TARGET_32BIT"
4259 "* return arm_output_shift(operands, 1);"
344495ea 4260 [(set_attr "conds" "set")
6b6abc9c 4261 (set_attr "shift" "1")
d82e788e 4262 (set_attr "type" "shift_imm,shift_reg")]
0d66636f 4263)
9c08d1fa 4264
d5d4dc8d 4265(define_insn "*not_shiftsi"
4266 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 4267 (not:SI (match_operator:SI 3 "shift_operator"
d5d4dc8d 4268 [(match_operand:SI 1 "s_register_operand" "r,r")
4269 (match_operand:SI 2 "shift_amount_operand" "M,rM")])))]
4270 "TARGET_32BIT"
6c4c2133 4271 "mvn%?\\t%0, %1%S3"
344495ea 4272 [(set_attr "predicable" "yes")
331beb1a 4273 (set_attr "shift" "1")
d5d4dc8d 4274 (set_attr "arch" "32,a")
1aed5204 4275 (set_attr "type" "mvn_shift,mvn_shift_reg")])
9c08d1fa 4276
d5d4dc8d 4277(define_insn "*not_shiftsi_compare0"
bd5b4116 4278 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 4279 (compare:CC_NOOV
4280 (not:SI (match_operator:SI 3 "shift_operator"
4281 [(match_operand:SI 1 "s_register_operand" "r,r")
4282 (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
4283 (const_int 0)))
4284 (set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 4285 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
d5d4dc8d 4286 "TARGET_32BIT"
3ef90e77 4287 "mvns%?\\t%0, %1%S3"
344495ea 4288 [(set_attr "conds" "set")
331beb1a 4289 (set_attr "shift" "1")
d5d4dc8d 4290 (set_attr "arch" "32,a")
1aed5204 4291 (set_attr "type" "mvn_shift,mvn_shift_reg")])
9c08d1fa 4292
d5d4dc8d 4293(define_insn "*not_shiftsi_compare0_scratch"
bd5b4116 4294 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 4295 (compare:CC_NOOV
4296 (not:SI (match_operator:SI 3 "shift_operator"
4297 [(match_operand:SI 1 "s_register_operand" "r,r")
4298 (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
4299 (const_int 0)))
4300 (clobber (match_scratch:SI 0 "=r,r"))]
4301 "TARGET_32BIT"
3ef90e77 4302 "mvns%?\\t%0, %1%S3"
344495ea 4303 [(set_attr "conds" "set")
331beb1a 4304 (set_attr "shift" "1")
d5d4dc8d 4305 (set_attr "arch" "32,a")
1aed5204 4306 (set_attr "type" "mvn_shift,mvn_shift_reg")])
9c08d1fa 4307
cffb2a26 4308;; We don't really have extzv, but defining this using shifts helps
4309;; to reduce register pressure later on.
4310
4311(define_expand "extzv"
eb04cafb 4312 [(set (match_operand 0 "s_register_operand" "")
4313 (zero_extract (match_operand 1 "nonimmediate_operand" "")
4314 (match_operand 2 "const_int_operand" "")
4315 (match_operand 3 "const_int_operand" "")))]
8b054d5a 4316 "TARGET_THUMB1 || arm_arch_thumb2"
cffb2a26 4317 "
4318 {
4319 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
4320 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
4321
8b054d5a 4322 if (arm_arch_thumb2)
4323 {
eb04cafb 4324 HOST_WIDE_INT width = INTVAL (operands[2]);
4325 HOST_WIDE_INT bitpos = INTVAL (operands[3]);
4326
4327 if (unaligned_access && MEM_P (operands[1])
4328 && (width == 16 || width == 32) && (bitpos % BITS_PER_UNIT) == 0)
4329 {
4330 rtx base_addr;
4331
4332 if (BYTES_BIG_ENDIAN)
4333 bitpos = GET_MODE_BITSIZE (GET_MODE (operands[0])) - width
4334 - bitpos;
4335
4336 if (width == 32)
4337 {
4338 base_addr = adjust_address (operands[1], SImode,
4339 bitpos / BITS_PER_UNIT);
4340 emit_insn (gen_unaligned_loadsi (operands[0], base_addr));
4341 }
4342 else
4343 {
4344 rtx dest = operands[0];
4345 rtx tmp = gen_reg_rtx (SImode);
4346
4347 /* We may get a paradoxical subreg here. Strip it off. */
4348 if (GET_CODE (dest) == SUBREG
4349 && GET_MODE (dest) == SImode
4350 && GET_MODE (SUBREG_REG (dest)) == HImode)
4351 dest = SUBREG_REG (dest);
4352
4353 if (GET_MODE_BITSIZE (GET_MODE (dest)) != width)
4354 FAIL;
4355
4356 base_addr = adjust_address (operands[1], HImode,
4357 bitpos / BITS_PER_UNIT);
4358 emit_insn (gen_unaligned_loadhiu (tmp, base_addr));
4359 emit_move_insn (gen_lowpart (SImode, dest), tmp);
4360 }
4361 DONE;
4362 }
4363 else if (s_register_operand (operands[1], GET_MODE (operands[1])))
4364 {
4365 emit_insn (gen_extzv_t2 (operands[0], operands[1], operands[2],
4366 operands[3]));
4367 DONE;
4368 }
4369 else
4370 FAIL;
8b054d5a 4371 }
eb04cafb 4372
4373 if (!s_register_operand (operands[1], GET_MODE (operands[1])))
4374 FAIL;
8b054d5a 4375
cffb2a26 4376 operands[3] = GEN_INT (rshift);
4377
4378 if (lshift == 0)
4379 {
4380 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
4381 DONE;
4382 }
4383
eb04cafb 4384 emit_insn (gen_extzv_t1 (operands[0], operands[1], GEN_INT (lshift),
4385 operands[3], gen_reg_rtx (SImode)));
4386 DONE;
215b30b3 4387 }"
cffb2a26 4388)
4389
eb04cafb 4390;; Helper for extzv, for the Thumb-1 register-shifts case.
4391
4392(define_expand "extzv_t1"
4393 [(set (match_operand:SI 4 "s_register_operand" "")
4394 (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "")
4395 (match_operand:SI 2 "const_int_operand" "")))
4396 (set (match_operand:SI 0 "s_register_operand" "")
4397 (lshiftrt:SI (match_dup 4)
4398 (match_operand:SI 3 "const_int_operand" "")))]
4399 "TARGET_THUMB1"
4400 "")
4401
4402(define_expand "extv"
4403 [(set (match_operand 0 "s_register_operand" "")
4404 (sign_extract (match_operand 1 "nonimmediate_operand" "")
4405 (match_operand 2 "const_int_operand" "")
4406 (match_operand 3 "const_int_operand" "")))]
4407 "arm_arch_thumb2"
4408{
4409 HOST_WIDE_INT width = INTVAL (operands[2]);
4410 HOST_WIDE_INT bitpos = INTVAL (operands[3]);
4411
4412 if (unaligned_access && MEM_P (operands[1]) && (width == 16 || width == 32)
4413 && (bitpos % BITS_PER_UNIT) == 0)
4414 {
4415 rtx base_addr;
4416
4417 if (BYTES_BIG_ENDIAN)
4418 bitpos = GET_MODE_BITSIZE (GET_MODE (operands[0])) - width - bitpos;
4419
4420 if (width == 32)
4421 {
4422 base_addr = adjust_address (operands[1], SImode,
4423 bitpos / BITS_PER_UNIT);
4424 emit_insn (gen_unaligned_loadsi (operands[0], base_addr));
4425 }
4426 else
4427 {
4428 rtx dest = operands[0];
4429 rtx tmp = gen_reg_rtx (SImode);
4430
4431 /* We may get a paradoxical subreg here. Strip it off. */
4432 if (GET_CODE (dest) == SUBREG
4433 && GET_MODE (dest) == SImode
4434 && GET_MODE (SUBREG_REG (dest)) == HImode)
4435 dest = SUBREG_REG (dest);
4436
4437 if (GET_MODE_BITSIZE (GET_MODE (dest)) != width)
4438 FAIL;
4439
4440 base_addr = adjust_address (operands[1], HImode,
4441 bitpos / BITS_PER_UNIT);
4442 emit_insn (gen_unaligned_loadhis (tmp, base_addr));
4443 emit_move_insn (gen_lowpart (SImode, dest), tmp);
4444 }
4445
4446 DONE;
4447 }
4448 else if (!s_register_operand (operands[1], GET_MODE (operands[1])))
4449 FAIL;
4450 else if (GET_MODE (operands[0]) == SImode
4451 && GET_MODE (operands[1]) == SImode)
4452 {
4453 emit_insn (gen_extv_regsi (operands[0], operands[1], operands[2],
4454 operands[3]));
4455 DONE;
4456 }
4457
4458 FAIL;
4459})
4460
4461; Helper to expand register forms of extv with the proper modes.
4462
4463(define_expand "extv_regsi"
4464 [(set (match_operand:SI 0 "s_register_operand" "")
4465 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
4466 (match_operand 2 "const_int_operand" "")
4467 (match_operand 3 "const_int_operand" "")))]
4468 ""
4469{
4470})
4471
4472; ARMv6+ unaligned load/store instructions (used for packed structure accesses).
4473
4474(define_insn "unaligned_loadsi"
4475 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4476 (unspec:SI [(match_operand:SI 1 "memory_operand" "Uw,m")]
4477 UNSPEC_UNALIGNED_LOAD))]
8fe38eb2 4478 "unaligned_access"
eb04cafb 4479 "ldr%?\t%0, %1\t@ unaligned"
4480 [(set_attr "arch" "t2,any")
4481 (set_attr "length" "2,4")
4482 (set_attr "predicable" "yes")
d952d547 4483 (set_attr "predicable_short_it" "yes,no")
9f2c2a36 4484 (set_attr "type" "load_4")])
eb04cafb 4485
4486(define_insn "unaligned_loadhis"
5d79b75e 4487 [(set (match_operand:SI 0 "s_register_operand" "=r")
eb04cafb 4488 (sign_extend:SI
5d79b75e 4489 (unspec:HI [(match_operand:HI 1 "memory_operand" "Uh")]
eb04cafb 4490 UNSPEC_UNALIGNED_LOAD)))]
8fe38eb2 4491 "unaligned_access"
3ef90e77 4492 "ldrsh%?\t%0, %1\t@ unaligned"
5d79b75e 4493 [(set_attr "predicable" "yes")
eb04cafb 4494 (set_attr "type" "load_byte")])
4495
4496(define_insn "unaligned_loadhiu"
4497 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4498 (zero_extend:SI
4499 (unspec:HI [(match_operand:HI 1 "memory_operand" "Uw,m")]
4500 UNSPEC_UNALIGNED_LOAD)))]
8fe38eb2 4501 "unaligned_access"
3ef90e77 4502 "ldrh%?\t%0, %1\t@ unaligned"
eb04cafb 4503 [(set_attr "arch" "t2,any")
4504 (set_attr "length" "2,4")
4505 (set_attr "predicable" "yes")
d952d547 4506 (set_attr "predicable_short_it" "yes,no")
eb04cafb 4507 (set_attr "type" "load_byte")])
4508
4509(define_insn "unaligned_storesi"
4510 [(set (match_operand:SI 0 "memory_operand" "=Uw,m")
4511 (unspec:SI [(match_operand:SI 1 "s_register_operand" "l,r")]
4512 UNSPEC_UNALIGNED_STORE))]
8fe38eb2 4513 "unaligned_access"
eb04cafb 4514 "str%?\t%1, %0\t@ unaligned"
4515 [(set_attr "arch" "t2,any")
4516 (set_attr "length" "2,4")
4517 (set_attr "predicable" "yes")
d952d547 4518 (set_attr "predicable_short_it" "yes,no")
9f2c2a36 4519 (set_attr "type" "store_4")])
eb04cafb 4520
4521(define_insn "unaligned_storehi"
4522 [(set (match_operand:HI 0 "memory_operand" "=Uw,m")
4523 (unspec:HI [(match_operand:HI 1 "s_register_operand" "l,r")]
4524 UNSPEC_UNALIGNED_STORE))]
8fe38eb2 4525 "unaligned_access"
3ef90e77 4526 "strh%?\t%1, %0\t@ unaligned"
eb04cafb 4527 [(set_attr "arch" "t2,any")
4528 (set_attr "length" "2,4")
4529 (set_attr "predicable" "yes")
d952d547 4530 (set_attr "predicable_short_it" "yes,no")
9f2c2a36 4531 (set_attr "type" "store_4")])
eb04cafb 4532
ae51a965 4533
eb04cafb 4534(define_insn "*extv_reg"
8b054d5a 4535 [(set (match_operand:SI 0 "s_register_operand" "=r")
4536 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
13051f13 4537 (match_operand:SI 2 "const_int_operand" "n")
4538 (match_operand:SI 3 "const_int_operand" "n")))]
4539 "arm_arch_thumb2
4540 && IN_RANGE (INTVAL (operands[3]), 0, 31)
4541 && IN_RANGE (INTVAL (operands[2]), 1, 32 - INTVAL (operands[3]))"
8b054d5a 4542 "sbfx%?\t%0, %1, %3, %2"
4543 [(set_attr "length" "4")
d952d547 4544 (set_attr "predicable" "yes")
d82e788e 4545 (set_attr "type" "bfm")]
8b054d5a 4546)
4547
4548(define_insn "extzv_t2"
4549 [(set (match_operand:SI 0 "s_register_operand" "=r")
4550 (zero_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 "ubfx%?\t%0, %1, %3, %2"
4557 [(set_attr "length" "4")
d952d547 4558 (set_attr "predicable" "yes")
d82e788e 4559 (set_attr "type" "bfm")]
8b054d5a 4560)
4561
7d3cda8c 4562
4563;; Division instructions
4564(define_insn "divsi3"
8f5f2788 4565 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4566 (div:SI (match_operand:SI 1 "s_register_operand" "r,r")
4567 (match_operand:SI 2 "s_register_operand" "r,r")))]
7d3cda8c 4568 "TARGET_IDIV"
8f5f2788 4569 "@
4570 sdiv%?\t%0, %1, %2
4571 sdiv\t%0, %1, %2"
4572 [(set_attr "arch" "32,v8mb")
4573 (set_attr "predicable" "yes")
9da0ec36 4574 (set_attr "type" "sdiv")]
7d3cda8c 4575)
4576
4577(define_insn "udivsi3"
8f5f2788 4578 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4579 (udiv:SI (match_operand:SI 1 "s_register_operand" "r,r")
4580 (match_operand:SI 2 "s_register_operand" "r,r")))]
7d3cda8c 4581 "TARGET_IDIV"
8f5f2788 4582 "@
4583 udiv%?\t%0, %1, %2
4584 udiv\t%0, %1, %2"
4585 [(set_attr "arch" "32,v8mb")
4586 (set_attr "predicable" "yes")
9da0ec36 4587 (set_attr "type" "udiv")]
7d3cda8c 4588)
4589
b11cae9e 4590\f
4591;; Unary arithmetic insns
4592
f6c98a9a 4593(define_expand "negvsi3"
4594 [(match_operand:SI 0 "register_operand")
4595 (match_operand:SI 1 "register_operand")
4596 (match_operand 2 "")]
4597 "TARGET_32BIT"
4598{
4599 emit_insn (gen_subsi3_compare (operands[0], const0_rtx, operands[1]));
4600 arm_gen_unlikely_cbranch (NE, CC_Vmode, operands[2]);
4601
4602 DONE;
4603})
4604
4605(define_expand "negvdi3"
4606 [(match_operand:DI 0 "register_operand")
4607 (match_operand:DI 1 "register_operand")
4608 (match_operand 2 "")]
4609 "TARGET_ARM"
4610{
4611 emit_insn (gen_negdi2_compare (operands[0], operands[1]));
4612 arm_gen_unlikely_cbranch (NE, CC_Vmode, operands[2]);
4613
4614 DONE;
4615})
4616
4617
4618(define_insn_and_split "negdi2_compare"
4619 [(set (reg:CC CC_REGNUM)
4620 (compare:CC
4621 (const_int 0)
4622 (match_operand:DI 1 "register_operand" "0,r")))
4623 (set (match_operand:DI 0 "register_operand" "=r,&r")
4624 (minus:DI (const_int 0) (match_dup 1)))]
4625 "TARGET_ARM"
4626 "#"
4627 "&& reload_completed"
4628 [(parallel [(set (reg:CC CC_REGNUM)
4629 (compare:CC (const_int 0) (match_dup 1)))
4630 (set (match_dup 0) (minus:SI (const_int 0)
4631 (match_dup 1)))])
4632 (parallel [(set (reg:CC CC_REGNUM)
4633 (compare:CC (const_int 0) (match_dup 3)))
4634 (set (match_dup 2)
4635 (minus:SI
4636 (minus:SI (const_int 0) (match_dup 3))
4637 (ltu:SI (reg:CC_C CC_REGNUM)
4638 (const_int 0))))])]
4639 {
4640 operands[2] = gen_highpart (SImode, operands[0]);
4641 operands[0] = gen_lowpart (SImode, operands[0]);
4642 operands[3] = gen_highpart (SImode, operands[1]);
4643 operands[1] = gen_lowpart (SImode, operands[1]);
4644 }
4645 [(set_attr "conds" "set")
4646 (set_attr "length" "8")
4647 (set_attr "type" "multiple")]
4648)
4649
cffb2a26 4650(define_expand "negdi2"
4651 [(parallel
8135a42b 4652 [(set (match_operand:DI 0 "s_register_operand" "")
4653 (neg:DI (match_operand:DI 1 "s_register_operand" "")))
bd5b4116 4654 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 4655 "TARGET_EITHER"
774d2fbb 4656 {
4657 if (TARGET_NEON)
4658 {
4659 emit_insn (gen_negdi2_neon (operands[0], operands[1]));
4660 DONE;
4661 }
4662 }
cffb2a26 4663)
4664
4665;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
e5fea38e 4666;; The first alternative allows the common case of a *full* overlap.
d5bf2b53 4667(define_insn_and_split "*negdi2_insn"
458a8706 4668 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 4669 (neg:DI (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 4670 (clobber (reg:CC CC_REGNUM))]
d5bf2b53 4671 "TARGET_32BIT"
4672 "#" ; rsbs %Q0, %Q1, #0; rsc %R0, %R1, #0 (ARM)
4673 ; negs %Q0, %Q1 ; sbc %R0, %R1, %R1, lsl #1 (Thumb-2)
ba6a3b2f 4674 "&& reload_completed"
4675 [(parallel [(set (reg:CC CC_REGNUM)
4676 (compare:CC (const_int 0) (match_dup 1)))
4677 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 1)))])
4678 (set (match_dup 2) (minus:SI (minus:SI (const_int 0) (match_dup 3))
4679 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
4680 {
4681 operands[2] = gen_highpart (SImode, operands[0]);
4682 operands[0] = gen_lowpart (SImode, operands[0]);
4683 operands[3] = gen_highpart (SImode, operands[1]);
4684 operands[1] = gen_lowpart (SImode, operands[1]);
4685 }
cffb2a26 4686 [(set_attr "conds" "clob")
1b7da4ac 4687 (set_attr "length" "8")
4688 (set_attr "type" "multiple")]
cffb2a26 4689)
b11cae9e 4690
f6c98a9a 4691(define_insn "*negsi2_carryin_compare"
4692 [(set (reg:CC CC_REGNUM)
4693 (compare:CC (const_int 0)
4694 (match_operand:SI 1 "s_register_operand" "r")))
4695 (set (match_operand:SI 0 "s_register_operand" "=r")
4696 (minus:SI (minus:SI (const_int 0)
4697 (match_dup 1))
4698 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
4699 "TARGET_ARM"
4700 "rscs\\t%0, %1, #0"
4701 [(set_attr "conds" "set")
4702 (set_attr "type" "alus_imm")]
4703)
4704
cffb2a26 4705(define_expand "negsi2"
4706 [(set (match_operand:SI 0 "s_register_operand" "")
4707 (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
4708 "TARGET_EITHER"
b11cae9e 4709 ""
cffb2a26 4710)
4711
4712(define_insn "*arm_negsi2"
d952d547 4713 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4714 (neg:SI (match_operand:SI 1 "s_register_operand" "l,r")))]
25f905c2 4715 "TARGET_32BIT"
cffb2a26 4716 "rsb%?\\t%0, %1, #0"
d952d547 4717 [(set_attr "predicable" "yes")
4718 (set_attr "predicable_short_it" "yes,no")
4719 (set_attr "arch" "t2,*")
1b7da4ac 4720 (set_attr "length" "4")
112eda6f 4721 (set_attr "type" "alu_sreg")]
cffb2a26 4722)
4723
604f3a0a 4724(define_expand "negsf2"
4725 [(set (match_operand:SF 0 "s_register_operand" "")
4726 (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
d7216193 4727 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 4728 ""
4729)
4730
4731(define_expand "negdf2"
4732 [(set (match_operand:DF 0 "s_register_operand" "")
4733 (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
994606f8 4734 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
604f3a0a 4735 "")
4736
7eaf2be0 4737(define_insn_and_split "*zextendsidi_negsi"
4738 [(set (match_operand:DI 0 "s_register_operand" "=r")
4739 (zero_extend:DI (neg:SI (match_operand:SI 1 "s_register_operand" "r"))))]
4740 "TARGET_32BIT"
4741 "#"
4742 ""
4743 [(set (match_dup 2)
4744 (neg:SI (match_dup 1)))
4745 (set (match_dup 3)
4746 (const_int 0))]
4747 {
4748 operands[2] = gen_lowpart (SImode, operands[0]);
4749 operands[3] = gen_highpart (SImode, operands[0]);
4750 }
4751 [(set_attr "length" "8")
4752 (set_attr "type" "multiple")]
4753)
4754
83e2b922 4755;; Negate an extended 32-bit value.
4756(define_insn_and_split "*negdi_extendsidi"
61fa8ff2 4757 [(set (match_operand:DI 0 "s_register_operand" "=l,r")
4758 (neg:DI (sign_extend:DI
4759 (match_operand:SI 1 "s_register_operand" "l,r"))))
83e2b922 4760 (clobber (reg:CC CC_REGNUM))]
4761 "TARGET_32BIT"
61fa8ff2 4762 "#"
83e2b922 4763 "&& reload_completed"
4764 [(const_int 0)]
4765 {
61fa8ff2 4766 rtx low = gen_lowpart (SImode, operands[0]);
4767 rtx high = gen_highpart (SImode, operands[0]);
4768
4769 if (reg_overlap_mentioned_p (low, operands[1]))
4770 {
4771 /* Input overlaps the low word of the output. Use:
4772 asr Rhi, Rin, #31
4773 rsbs Rlo, Rin, #0
4774 rsc Rhi, Rhi, #0 (thumb2: sbc Rhi, Rhi, Rhi, lsl #1). */
4775 rtx cc_reg = gen_rtx_REG (CC_Cmode, CC_REGNUM);
4776
d1f9b275 4777 emit_insn (gen_rtx_SET (high,
61fa8ff2 4778 gen_rtx_ASHIFTRT (SImode, operands[1],
4779 GEN_INT (31))));
4780
4781 emit_insn (gen_subsi3_compare (low, const0_rtx, operands[1]));
4782 if (TARGET_ARM)
d1f9b275 4783 emit_insn (gen_rtx_SET (high,
61fa8ff2 4784 gen_rtx_MINUS (SImode,
4785 gen_rtx_MINUS (SImode,
4786 const0_rtx,
4787 high),
4788 gen_rtx_LTU (SImode,
4789 cc_reg,
4790 const0_rtx))));
4791 else
4792 {
4793 rtx two_x = gen_rtx_ASHIFT (SImode, high, GEN_INT (1));
d1f9b275 4794 emit_insn (gen_rtx_SET (high,
61fa8ff2 4795 gen_rtx_MINUS (SImode,
4796 gen_rtx_MINUS (SImode,
4797 high,
4798 two_x),
4799 gen_rtx_LTU (SImode,
4800 cc_reg,
4801 const0_rtx))));
4802 }
4803 }
4804 else
4805 {
4806 /* No overlap, or overlap on high word. Use:
4807 rsb Rlo, Rin, #0
4808 bic Rhi, Rlo, Rin
4809 asr Rhi, Rhi, #31
4810 Flags not needed for this sequence. */
d1f9b275 4811 emit_insn (gen_rtx_SET (low, gen_rtx_NEG (SImode, operands[1])));
4812 emit_insn (gen_rtx_SET (high,
61fa8ff2 4813 gen_rtx_AND (SImode,
4814 gen_rtx_NOT (SImode, operands[1]),
4815 low)));
d1f9b275 4816 emit_insn (gen_rtx_SET (high,
61fa8ff2 4817 gen_rtx_ASHIFTRT (SImode, high,
4818 GEN_INT (31))));
4819 }
4820 DONE;
83e2b922 4821 }
61fa8ff2 4822 [(set_attr "length" "12")
4823 (set_attr "arch" "t2,*")
1b7da4ac 4824 (set_attr "type" "multiple")]
83e2b922 4825)
4826
4827(define_insn_and_split "*negdi_zero_extendsidi"
4828 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
4829 (neg:DI (zero_extend:DI (match_operand:SI 1 "s_register_operand" "0,r"))))
4830 (clobber (reg:CC CC_REGNUM))]
4831 "TARGET_32BIT"
4832 "#" ; "rsbs\\t%Q0, %1, #0\;sbc\\t%R0,%R0,%R0"
4833 ;; Don't care what register is input to sbc,
47ae02b7 4834 ;; since we just need to propagate the carry.
83e2b922 4835 "&& reload_completed"
4836 [(parallel [(set (reg:CC CC_REGNUM)
4837 (compare:CC (const_int 0) (match_dup 1)))
4838 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 1)))])
4839 (set (match_dup 2) (minus:SI (minus:SI (match_dup 2) (match_dup 2))
4840 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
4841 {
4842 operands[2] = gen_highpart (SImode, operands[0]);
4843 operands[0] = gen_lowpart (SImode, operands[0]);
4844 }
4845 [(set_attr "conds" "clob")
1b7da4ac 4846 (set_attr "length" "8")
4847 (set_attr "type" "multiple")] ;; length in thumb is 4
83e2b922 4848)
4849
9c08d1fa 4850;; abssi2 doesn't really clobber the condition codes if a different register
4851;; is being set. To keep things simple, assume during rtl manipulations that
4852;; it does, but tell the final scan operator the truth. Similarly for
4853;; (neg (abs...))
4854
604f3a0a 4855(define_expand "abssi2"
4856 [(parallel
4857 [(set (match_operand:SI 0 "s_register_operand" "")
4858 (abs:SI (match_operand:SI 1 "s_register_operand" "")))
ba156559 4859 (clobber (match_dup 2))])]
4860 "TARGET_EITHER"
4861 "
25f905c2 4862 if (TARGET_THUMB1)
ba156559 4863 operands[2] = gen_rtx_SCRATCH (SImode);
4864 else
4865 operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
4866")
604f3a0a 4867
ba6a3b2f 4868(define_insn_and_split "*arm_abssi2"
ba156559 4869 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
9c08d1fa 4870 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
bd5b4116 4871 (clobber (reg:CC CC_REGNUM))]
cffb2a26 4872 "TARGET_ARM"
ba6a3b2f 4873 "#"
4874 "&& reload_completed"
4875 [(const_int 0)]
4876 {
4877 /* if (which_alternative == 0) */
4878 if (REGNO(operands[0]) == REGNO(operands[1]))
4879 {
4880 /* Emit the pattern:
4881 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
4882 [(set (reg:CC CC_REGNUM)
4883 (compare:CC (match_dup 0) (const_int 0)))
4884 (cond_exec (lt:CC (reg:CC CC_REGNUM) (const_int 0))
4885 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 1))))]
4886 */
d1f9b275 4887 emit_insn (gen_rtx_SET (gen_rtx_REG (CCmode, CC_REGNUM),
ba6a3b2f 4888 gen_rtx_COMPARE (CCmode, operands[0], const0_rtx)));
4889 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
4890 (gen_rtx_LT (SImode,
4891 gen_rtx_REG (CCmode, CC_REGNUM),
4892 const0_rtx)),
d1f9b275 4893 (gen_rtx_SET (operands[0],
ba6a3b2f 4894 (gen_rtx_MINUS (SImode,
4895 const0_rtx,
4896 operands[1]))))));
4897 DONE;
4898 }
4899 else
4900 {
4901 /* Emit the pattern:
4902 alt1: eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31
4903 [(set (match_dup 0)
4904 (xor:SI (match_dup 1)
4905 (ashiftrt:SI (match_dup 1) (const_int 31))))
4906 (set (match_dup 0)
4907 (minus:SI (match_dup 0)
4908 (ashiftrt:SI (match_dup 1) (const_int 31))))]
4909 */
d1f9b275 4910 emit_insn (gen_rtx_SET (operands[0],
ba6a3b2f 4911 gen_rtx_XOR (SImode,
4912 gen_rtx_ASHIFTRT (SImode,
4913 operands[1],
4914 GEN_INT (31)),
4915 operands[1])));
d1f9b275 4916 emit_insn (gen_rtx_SET (operands[0],
ba6a3b2f 4917 gen_rtx_MINUS (SImode,
4918 operands[0],
4919 gen_rtx_ASHIFTRT (SImode,
4920 operands[1],
4921 GEN_INT (31)))));
4922 DONE;
4923 }
4924 }
cffb2a26 4925 [(set_attr "conds" "clob,*")
331beb1a 4926 (set_attr "shift" "1")
2ad08b65 4927 (set_attr "predicable" "no, yes")
1b7da4ac 4928 (set_attr "length" "8")
4929 (set_attr "type" "multiple")]
cffb2a26 4930)
9c08d1fa 4931
ba6a3b2f 4932(define_insn_and_split "*arm_neg_abssi2"
9c08d1fa 4933 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
4934 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
bd5b4116 4935 (clobber (reg:CC CC_REGNUM))]
cffb2a26 4936 "TARGET_ARM"
ba6a3b2f 4937 "#"
4938 "&& reload_completed"
4939 [(const_int 0)]
4940 {
4941 /* if (which_alternative == 0) */
4942 if (REGNO (operands[0]) == REGNO (operands[1]))
4943 {
4944 /* Emit the pattern:
4945 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
4946 */
d1f9b275 4947 emit_insn (gen_rtx_SET (gen_rtx_REG (CCmode, CC_REGNUM),
ba6a3b2f 4948 gen_rtx_COMPARE (CCmode, operands[0], const0_rtx)));
4949 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
4950 gen_rtx_GT (SImode,
4951 gen_rtx_REG (CCmode, CC_REGNUM),
4952 const0_rtx),
d1f9b275 4953 gen_rtx_SET (operands[0],
ba6a3b2f 4954 (gen_rtx_MINUS (SImode,
4955 const0_rtx,
4956 operands[1])))));
4957 }
4958 else
4959 {
4960 /* Emit the pattern:
4961 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31
4962 */
d1f9b275 4963 emit_insn (gen_rtx_SET (operands[0],
ba6a3b2f 4964 gen_rtx_XOR (SImode,
4965 gen_rtx_ASHIFTRT (SImode,
4966 operands[1],
4967 GEN_INT (31)),
4968 operands[1])));
d1f9b275 4969 emit_insn (gen_rtx_SET (operands[0],
ba6a3b2f 4970 gen_rtx_MINUS (SImode,
4971 gen_rtx_ASHIFTRT (SImode,
4972 operands[1],
4973 GEN_INT (31)),
4974 operands[0])));
4975 }
4976 DONE;
4977 }
cffb2a26 4978 [(set_attr "conds" "clob,*")
331beb1a 4979 (set_attr "shift" "1")
2ad08b65 4980 (set_attr "predicable" "no, yes")
1b7da4ac 4981 (set_attr "length" "8")
4982 (set_attr "type" "multiple")]
cffb2a26 4983)
b11cae9e 4984
604f3a0a 4985(define_expand "abssf2"
4986 [(set (match_operand:SF 0 "s_register_operand" "")
4987 (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
25f905c2 4988 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 4989 "")
4990
604f3a0a 4991(define_expand "absdf2"
4992 [(set (match_operand:DF 0 "s_register_operand" "")
4993 (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 4994 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 4995 "")
4996
7db9af5d 4997(define_expand "sqrtsf2"
4998 [(set (match_operand:SF 0 "s_register_operand" "")
4999 (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
d7216193 5000 "TARGET_32BIT && TARGET_HARD_FLOAT"
7db9af5d 5001 "")
9c08d1fa 5002
7db9af5d 5003(define_expand "sqrtdf2"
5004 [(set (match_operand:DF 0 "s_register_operand" "")
5005 (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
994606f8 5006 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
7db9af5d 5007 "")
9c08d1fa 5008
0d84c6e5 5009(define_expand "one_cmpldi2"
5010 [(set (match_operand:DI 0 "s_register_operand" "")
5011 (not:DI (match_operand:DI 1 "s_register_operand" "")))]
5012 "TARGET_32BIT"
5013 "
5014 if (!TARGET_NEON && !TARGET_IWMMXT)
5015 {
5016 rtx low = simplify_gen_unary (NOT, SImode,
5017 gen_lowpart (SImode, operands[1]),
5018 SImode);
5019 rtx high = simplify_gen_unary (NOT, SImode,
5020 gen_highpart_mode (SImode, DImode,
5021 operands[1]),
5022 SImode);
5023
5024 emit_insn (gen_rtx_SET (gen_lowpart (SImode, operands[0]), low));
5025 emit_insn (gen_rtx_SET (gen_highpart (SImode, operands[0]), high));
5026
5027 DONE;
5028 }
5029 /* Otherwise expand pattern as above. */
5030 "
5031)
5032
5033(define_insn_and_split "*one_cmpldi2_insn"
10efb95f 5034 [(set (match_operand:DI 0 "s_register_operand" "=w,&r,&r,?w")
5035 (not:DI (match_operand:DI 1 "s_register_operand" " w, 0, r, w")))]
25f905c2 5036 "TARGET_32BIT"
10efb95f 5037 "@
5038 vmvn\t%P0, %P1
5039 #
5040 #
5041 vmvn\t%P0, %P1"
5042 "TARGET_32BIT && reload_completed
5043 && arm_general_register_operand (operands[0], DImode)"
a0f94409 5044 [(set (match_dup 0) (not:SI (match_dup 1)))
5045 (set (match_dup 2) (not:SI (match_dup 3)))]
5046 "
5047 {
5048 operands[2] = gen_highpart (SImode, operands[0]);
5049 operands[0] = gen_lowpart (SImode, operands[0]);
5050 operands[3] = gen_highpart (SImode, operands[1]);
5051 operands[1] = gen_lowpart (SImode, operands[1]);
5052 }"
10efb95f 5053 [(set_attr "length" "*,8,8,*")
5054 (set_attr "predicable" "no,yes,yes,no")
32093010 5055 (set_attr "type" "neon_move,multiple,multiple,neon_move")
b6779ddc 5056 (set_attr "arch" "neon_for_64bits,*,*,avoid_neon_for_64bits")]
cffb2a26 5057)
b11cae9e 5058
cffb2a26 5059(define_expand "one_cmplsi2"
5060 [(set (match_operand:SI 0 "s_register_operand" "")
5061 (not:SI (match_operand:SI 1 "s_register_operand" "")))]
5062 "TARGET_EITHER"
b11cae9e 5063 ""
cffb2a26 5064)
5065
5066(define_insn "*arm_one_cmplsi2"
d952d547 5067 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
5068 (not:SI (match_operand:SI 1 "s_register_operand" "l,r")))]
25f905c2 5069 "TARGET_32BIT"
cffb2a26 5070 "mvn%?\\t%0, %1"
d2a518d1 5071 [(set_attr "predicable" "yes")
d952d547 5072 (set_attr "predicable_short_it" "yes,no")
5073 (set_attr "arch" "t2,*")
5074 (set_attr "length" "4")
1aed5204 5075 (set_attr "type" "mvn_reg")]
cffb2a26 5076)
5077
f7fbdd4a 5078(define_insn "*notsi_compare0"
bd5b4116 5079 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 5080 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5081 (const_int 0)))
5082 (set (match_operand:SI 0 "s_register_operand" "=r")
5083 (not:SI (match_dup 1)))]
25f905c2 5084 "TARGET_32BIT"
3ef90e77 5085 "mvns%?\\t%0, %1"
d2a518d1 5086 [(set_attr "conds" "set")
1aed5204 5087 (set_attr "type" "mvn_reg")]
cffb2a26 5088)
9c08d1fa 5089
f7fbdd4a 5090(define_insn "*notsi_compare0_scratch"
bd5b4116 5091 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 5092 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5093 (const_int 0)))
5094 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 5095 "TARGET_32BIT"
3ef90e77 5096 "mvns%?\\t%0, %1"
d2a518d1 5097 [(set_attr "conds" "set")
1aed5204 5098 (set_attr "type" "mvn_reg")]
cffb2a26 5099)
b11cae9e 5100\f
5101;; Fixed <--> Floating conversion insns
5102
9b8516be 5103(define_expand "floatsihf2"
5104 [(set (match_operand:HF 0 "general_operand" "")
5105 (float:HF (match_operand:SI 1 "general_operand" "")))]
5106 "TARGET_EITHER"
5107 "
5108 {
5109 rtx op1 = gen_reg_rtx (SFmode);
5110 expand_float (op1, operands[1], 0);
5111 op1 = convert_to_mode (HFmode, op1, 0);
5112 emit_move_insn (operands[0], op1);
5113 DONE;
5114 }"
5115)
5116
5117(define_expand "floatdihf2"
5118 [(set (match_operand:HF 0 "general_operand" "")
5119 (float:HF (match_operand:DI 1 "general_operand" "")))]
5120 "TARGET_EITHER"
5121 "
5122 {
5123 rtx op1 = gen_reg_rtx (SFmode);
5124 expand_float (op1, operands[1], 0);
5125 op1 = convert_to_mode (HFmode, op1, 0);
5126 emit_move_insn (operands[0], op1);
5127 DONE;
5128 }"
5129)
5130
604f3a0a 5131(define_expand "floatsisf2"
5132 [(set (match_operand:SF 0 "s_register_operand" "")
5133 (float:SF (match_operand:SI 1 "s_register_operand" "")))]
25f905c2 5134 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 5135 "
604f3a0a 5136")
5137
604f3a0a 5138(define_expand "floatsidf2"
5139 [(set (match_operand:DF 0 "s_register_operand" "")
5140 (float:DF (match_operand:SI 1 "s_register_operand" "")))]
a50d7267 5141 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 5142 "
604f3a0a 5143")
5144
9b8516be 5145(define_expand "fix_trunchfsi2"
5146 [(set (match_operand:SI 0 "general_operand" "")
5147 (fix:SI (fix:HF (match_operand:HF 1 "general_operand" ""))))]
5148 "TARGET_EITHER"
5149 "
5150 {
5151 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
5152 expand_fix (operands[0], op1, 0);
5153 DONE;
5154 }"
5155)
5156
5157(define_expand "fix_trunchfdi2"
5158 [(set (match_operand:DI 0 "general_operand" "")
5159 (fix:DI (fix:HF (match_operand:HF 1 "general_operand" ""))))]
5160 "TARGET_EITHER"
5161 "
5162 {
5163 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
5164 expand_fix (operands[0], op1, 0);
5165 DONE;
5166 }"
5167)
5168
604f3a0a 5169(define_expand "fix_truncsfsi2"
5170 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 5171 (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" ""))))]
25f905c2 5172 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 5173 "
604f3a0a 5174")
5175
604f3a0a 5176(define_expand "fix_truncdfsi2"
5177 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 5178 (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" ""))))]
a50d7267 5179 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 5180 "
604f3a0a 5181")
5182
f544c6d2 5183;; Truncation insns
b11cae9e 5184
604f3a0a 5185(define_expand "truncdfsf2"
5186 [(set (match_operand:SF 0 "s_register_operand" "")
5187 (float_truncate:SF
5188 (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 5189 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 5190 ""
5191)
9b8516be 5192
539b44ee 5193;; DFmode to HFmode conversions on targets without a single-step hardware
5194;; instruction for it would have to go through SFmode. This is dangerous
5195;; as it introduces double rounding.
5196;;
5197;; Disable this pattern unless we are in an unsafe math mode, or we have
5198;; a single-step instruction.
5199
9b8516be 5200(define_expand "truncdfhf2"
539b44ee 5201 [(set (match_operand:HF 0 "s_register_operand" "")
9b8516be 5202 (float_truncate:HF
539b44ee 5203 (match_operand:DF 1 "s_register_operand" "")))]
5204 "(TARGET_EITHER && flag_unsafe_math_optimizations)
5205 || (TARGET_32BIT && TARGET_FP16_TO_DOUBLE)"
5206{
5207 /* We don't have a direct instruction for this, so we must be in
5208 an unsafe math mode, and going via SFmode. */
5209
5210 if (!(TARGET_32BIT && TARGET_FP16_TO_DOUBLE))
5211 {
5212 rtx op1;
5213 op1 = convert_to_mode (SFmode, operands[1], 0);
5214 op1 = convert_to_mode (HFmode, op1, 0);
5215 emit_move_insn (operands[0], op1);
5216 DONE;
5217 }
5218 /* Otherwise, we will pick this up as a single instruction with
5219 no intermediary rounding. */
5220}
9b8516be 5221)
b11cae9e 5222\f
9c08d1fa 5223;; Zero and sign extension instructions.
b11cae9e 5224
848e66ac 5225(define_insn "zero_extend<mode>di2"
6aa689e8 5226 [(set (match_operand:DI 0 "s_register_operand" "=w,r,?r,w")
6d97728e 5227 (zero_extend:DI (match_operand:QHSI 1 "<qhs_zextenddi_op>"
5228 "<qhs_zextenddi_cstr>")))]
848e66ac 5229 "TARGET_32BIT <qhs_zextenddi_cond>"
5230 "#"
6aa689e8 5231 [(set_attr "length" "8,4,8,8")
b6779ddc 5232 (set_attr "arch" "neon_for_64bits,*,*,avoid_neon_for_64bits")
848e66ac 5233 (set_attr "ce_count" "2")
efbb5e19 5234 (set_attr "predicable" "yes")
5235 (set_attr "type" "multiple,mov_reg,multiple,multiple")]
25f905c2 5236)
5237
848e66ac 5238(define_insn "extend<mode>di2"
6aa689e8 5239 [(set (match_operand:DI 0 "s_register_operand" "=w,r,?r,?r,w")
63d204a8 5240 (sign_extend:DI (match_operand:QHSI 1 "<qhs_extenddi_op>"
5241 "<qhs_extenddi_cstr>")))]
848e66ac 5242 "TARGET_32BIT <qhs_sextenddi_cond>"
5243 "#"
6aa689e8 5244 [(set_attr "length" "8,4,8,8,8")
848e66ac 5245 (set_attr "ce_count" "2")
5246 (set_attr "shift" "1")
8012d2c2 5247 (set_attr "predicable" "yes")
1b7da4ac 5248 (set_attr "arch" "neon_for_64bits,*,a,t,avoid_neon_for_64bits")
5249 (set_attr "type" "multiple,mov_reg,multiple,multiple,multiple")]
0d66636f 5250)
9c08d1fa 5251
848e66ac 5252;; Splits for all extensions to DImode
5253(define_split
5254 [(set (match_operand:DI 0 "s_register_operand" "")
5255 (zero_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
6aa689e8 5256 "TARGET_32BIT && reload_completed && !IS_VFP_REGNUM (REGNO (operands[0]))"
848e66ac 5257 [(set (match_dup 0) (match_dup 1))]
5258{
848e66ac 5259 rtx lo_part = gen_lowpart (SImode, operands[0]);
3754d046 5260 machine_mode src_mode = GET_MODE (operands[1]);
848e66ac 5261
5262 if (REG_P (operands[0])
5263 && !reg_overlap_mentioned_p (operands[0], operands[1]))
5264 emit_clobber (operands[0]);
5265 if (!REG_P (lo_part) || src_mode != SImode
5266 || !rtx_equal_p (lo_part, operands[1]))
5267 {
5268 if (src_mode == SImode)
5269 emit_move_insn (lo_part, operands[1]);
5270 else
d1f9b275 5271 emit_insn (gen_rtx_SET (lo_part,
848e66ac 5272 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
5273 operands[1] = lo_part;
5274 }
5275 operands[0] = gen_highpart (SImode, operands[0]);
5276 operands[1] = const0_rtx;
5277})
9c08d1fa 5278
848e66ac 5279(define_split
25f905c2 5280 [(set (match_operand:DI 0 "s_register_operand" "")
848e66ac 5281 (sign_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
6aa689e8 5282 "TARGET_32BIT && reload_completed && !IS_VFP_REGNUM (REGNO (operands[0]))"
848e66ac 5283 [(set (match_dup 0) (ashiftrt:SI (match_dup 1) (const_int 31)))]
5284{
5285 rtx lo_part = gen_lowpart (SImode, operands[0]);
3754d046 5286 machine_mode src_mode = GET_MODE (operands[1]);
25f905c2 5287
848e66ac 5288 if (REG_P (operands[0])
5289 && !reg_overlap_mentioned_p (operands[0], operands[1]))
5290 emit_clobber (operands[0]);
5291
5292 if (!REG_P (lo_part) || src_mode != SImode
5293 || !rtx_equal_p (lo_part, operands[1]))
5294 {
5295 if (src_mode == SImode)
5296 emit_move_insn (lo_part, operands[1]);
5297 else
d1f9b275 5298 emit_insn (gen_rtx_SET (lo_part,
848e66ac 5299 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
5300 operands[1] = lo_part;
5301 }
5302 operands[0] = gen_highpart (SImode, operands[0]);
5303})
9c08d1fa 5304
5305(define_expand "zero_extendhisi2"
ef51b8e1 5306 [(set (match_operand:SI 0 "s_register_operand" "")
5307 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
cffb2a26 5308 "TARGET_EITHER"
ef51b8e1 5309{
5310 if (TARGET_ARM && !arm_arch4 && MEM_P (operands[1]))
f7fbdd4a 5311 {
ef51b8e1 5312 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
5313 DONE;
25f7a26e 5314 }
ef51b8e1 5315 if (!arm_arch6 && !MEM_P (operands[1]))
5316 {
5317 rtx t = gen_lowpart (SImode, operands[1]);
5318 rtx tmp = gen_reg_rtx (SImode);
5319 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
5320 emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (16)));
5321 DONE;
5322 }
5323})
9c08d1fa 5324
ef51b8e1 5325(define_split
b146458f 5326 [(set (match_operand:SI 0 "s_register_operand" "")
5327 (zero_extend:SI (match_operand:HI 1 "s_register_operand" "")))]
ef51b8e1 5328 "!TARGET_THUMB2 && !arm_arch6"
5329 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
5330 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 16)))]
5331{
5332 operands[2] = gen_lowpart (SImode, operands[1]);
5333})
5334
cffb2a26 5335(define_insn "*arm_zero_extendhisi2"
ef51b8e1 5336 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5337 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 5338 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 5339 "@
5340 #
3ef90e77 5341 ldrh%?\\t%0, %1"
d82e788e 5342 [(set_attr "type" "alu_shift_reg,load_byte")
848e66ac 5343 (set_attr "predicable" "yes")]
cffb2a26 5344)
f7fbdd4a 5345
a2cd141b 5346(define_insn "*arm_zero_extendhisi2_v6"
5347 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
e3f4ccee 5348 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,Uh")))]
a2cd141b 5349 "TARGET_ARM && arm_arch6"
5350 "@
5351 uxth%?\\t%0, %1
3ef90e77 5352 ldrh%?\\t%0, %1"
65f68e55 5353 [(set_attr "predicable" "yes")
6b6abc9c 5354 (set_attr "type" "extend,load_byte")]
a2cd141b 5355)
5356
5357(define_insn "*arm_zero_extendhisi2addsi"
5358 [(set (match_operand:SI 0 "s_register_operand" "=r")
5359 (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
5360 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 5361 "TARGET_INT_SIMD"
a2cd141b 5362 "uxtah%?\\t%0, %2, %1"
d82e788e 5363 [(set_attr "type" "alu_shift_reg")
8bdfd6ed 5364 (set_attr "predicable" "yes")]
a2cd141b 5365)
5366
87b22bf7 5367(define_expand "zero_extendqisi2"
cffb2a26 5368 [(set (match_operand:SI 0 "s_register_operand" "")
5369 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
5370 "TARGET_EITHER"
ef51b8e1 5371{
0438d37f 5372 if (TARGET_ARM && !arm_arch6 && !MEM_P (operands[1]))
87b22bf7 5373 {
ef51b8e1 5374 emit_insn (gen_andsi3 (operands[0],
5375 gen_lowpart (SImode, operands[1]),
5376 GEN_INT (255)));
5377 DONE;
5378 }
5379 if (!arm_arch6 && !MEM_P (operands[1]))
5380 {
5381 rtx t = gen_lowpart (SImode, operands[1]);
5382 rtx tmp = gen_reg_rtx (SImode);
5383 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
5384 emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (24)));
5385 DONE;
5386 }
5387})
cffb2a26 5388
ef51b8e1 5389(define_split
b146458f 5390 [(set (match_operand:SI 0 "s_register_operand" "")
5391 (zero_extend:SI (match_operand:QI 1 "s_register_operand" "")))]
ef51b8e1 5392 "!arm_arch6"
5393 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
5394 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 24)))]
5395{
5396 operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
5397 if (TARGET_ARM)
5398 {
5399 emit_insn (gen_andsi3 (operands[0], operands[2], GEN_INT (255)));
87b22bf7 5400 DONE;
5401 }
ef51b8e1 5402})
9c08d1fa 5403
cffb2a26 5404(define_insn "*arm_zero_extendqisi2"
ef51b8e1 5405 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5406 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 5407 "TARGET_ARM && !arm_arch6"
ef51b8e1 5408 "@
5409 #
3ef90e77 5410 ldrb%?\\t%0, %1\\t%@ zero_extendqisi2"
ef51b8e1 5411 [(set_attr "length" "8,4")
d82e788e 5412 (set_attr "type" "alu_shift_reg,load_byte")
848e66ac 5413 (set_attr "predicable" "yes")]
cffb2a26 5414)
87b22bf7 5415
a2cd141b 5416(define_insn "*arm_zero_extendqisi2_v6"
5417 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
e3f4ccee 5418 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,Uh")))]
a2cd141b 5419 "TARGET_ARM && arm_arch6"
5420 "@
3ef90e77 5421 uxtb%?\\t%0, %1
5422 ldrb%?\\t%0, %1\\t%@ zero_extendqisi2"
6b6abc9c 5423 [(set_attr "type" "extend,load_byte")
848e66ac 5424 (set_attr "predicable" "yes")]
a2cd141b 5425)
5426
5427(define_insn "*arm_zero_extendqisi2addsi"
5428 [(set (match_operand:SI 0 "s_register_operand" "=r")
5429 (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
5430 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 5431 "TARGET_INT_SIMD"
a2cd141b 5432 "uxtab%?\\t%0, %2, %1"
5433 [(set_attr "predicable" "yes")
d82e788e 5434 (set_attr "type" "alu_shift_reg")]
a2cd141b 5435)
5436
87b22bf7 5437(define_split
5438 [(set (match_operand:SI 0 "s_register_operand" "")
5439 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
5440 (clobber (match_operand:SI 2 "s_register_operand" ""))]
0438d37f 5441 "TARGET_32BIT && (!MEM_P (operands[1])) && ! BYTES_BIG_ENDIAN"
87b22bf7 5442 [(set (match_dup 2) (match_dup 1))
5443 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
cffb2a26 5444 ""
5445)
9c08d1fa 5446
8a4d25d6 5447(define_split
5448 [(set (match_operand:SI 0 "s_register_operand" "")
5449 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 3)))
5450 (clobber (match_operand:SI 2 "s_register_operand" ""))]
0438d37f 5451 "TARGET_32BIT && (!MEM_P (operands[1])) && BYTES_BIG_ENDIAN"
8a4d25d6 5452 [(set (match_dup 2) (match_dup 1))
5453 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
5454 ""
5455)
5456
1c274529 5457
5458(define_split
5459 [(set (match_operand:SI 0 "s_register_operand" "")
9b23f0a7 5460 (IOR_XOR:SI (and:SI (ashift:SI
1c274529 5461 (match_operand:SI 1 "s_register_operand" "")
5462 (match_operand:SI 2 "const_int_operand" ""))
5463 (match_operand:SI 3 "const_int_operand" ""))
5464 (zero_extend:SI
5465 (match_operator 5 "subreg_lowpart_operator"
5466 [(match_operand:SI 4 "s_register_operand" "")]))))]
5467 "TARGET_32BIT
8c4e8755 5468 && (UINTVAL (operands[3])
1c274529 5469 == (GET_MODE_MASK (GET_MODE (operands[5]))
5470 & (GET_MODE_MASK (GET_MODE (operands[5]))
5471 << (INTVAL (operands[2])))))"
9b23f0a7 5472 [(set (match_dup 0) (IOR_XOR:SI (ashift:SI (match_dup 1) (match_dup 2))
1c274529 5473 (match_dup 4)))
5474 (set (match_dup 0) (zero_extend:SI (match_dup 5)))]
5475 "operands[5] = gen_lowpart (GET_MODE (operands[5]), operands[0]);"
5476)
5477
f7fbdd4a 5478(define_insn "*compareqi_eq0"
bd5b4116 5479 [(set (reg:CC_Z CC_REGNUM)
206ee9a2 5480 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
87b22bf7 5481 (const_int 0)))]
25f905c2 5482 "TARGET_32BIT"
596e5e8f 5483 "tst%?\\t%0, #255"
5484 [(set_attr "conds" "set")
d952d547 5485 (set_attr "predicable" "yes")
1b7da4ac 5486 (set_attr "type" "logic_imm")]
cffb2a26 5487)
b11cae9e 5488
b11cae9e 5489(define_expand "extendhisi2"
ef51b8e1 5490 [(set (match_operand:SI 0 "s_register_operand" "")
5491 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
cffb2a26 5492 "TARGET_EITHER"
ef51b8e1 5493{
5494 if (TARGET_THUMB1)
5495 {
5496 emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1]));
5497 DONE;
5498 }
5499 if (MEM_P (operands[1]) && TARGET_ARM && !arm_arch4)
5500 {
5501 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
5502 DONE;
5503 }
ed29c566 5504
ef51b8e1 5505 if (!arm_arch6 && !MEM_P (operands[1]))
5506 {
5507 rtx t = gen_lowpart (SImode, operands[1]);
5508 rtx tmp = gen_reg_rtx (SImode);
5509 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
5510 emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (16)));
5511 DONE;
5512 }
5513})
cffb2a26 5514
ef51b8e1 5515(define_split
5516 [(parallel
5517 [(set (match_operand:SI 0 "register_operand" "")
5518 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))
5519 (clobber (match_scratch:SI 2 ""))])]
5520 "!arm_arch6"
5521 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
5522 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
5523{
5524 operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
5525})
25f7a26e 5526
25f905c2 5527;; This pattern will only be used when ldsh is not available
25f7a26e 5528(define_expand "extendhisi2_mem"
eab14235 5529 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 5530 (set (match_dup 3)
eab14235 5531 (zero_extend:SI (match_dup 7)))
25f7a26e 5532 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
5533 (set (match_operand:SI 0 "" "")
5534 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
cffb2a26 5535 "TARGET_ARM"
25f7a26e 5536 "
215b30b3 5537 {
5538 rtx mem1, mem2;
5539 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
5540
788fcce0 5541 mem1 = change_address (operands[1], QImode, addr);
29c05e22 5542 mem2 = change_address (operands[1], QImode,
5543 plus_constant (Pmode, addr, 1));
215b30b3 5544 operands[0] = gen_lowpart (SImode, operands[0]);
5545 operands[1] = mem1;
5546 operands[2] = gen_reg_rtx (SImode);
5547 operands[3] = gen_reg_rtx (SImode);
5548 operands[6] = gen_reg_rtx (SImode);
5549 operands[7] = mem2;
25f7a26e 5550
215b30b3 5551 if (BYTES_BIG_ENDIAN)
5552 {
5553 operands[4] = operands[2];
5554 operands[5] = operands[3];
5555 }
5556 else
5557 {
5558 operands[4] = operands[3];
5559 operands[5] = operands[2];
5560 }
5561 }"
5562)
b11cae9e 5563
ef51b8e1 5564(define_split
5565 [(set (match_operand:SI 0 "register_operand" "")
5566 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
5567 "!arm_arch6"
5568 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
5569 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
5570{
5571 operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
5572})
5573
a2cd141b 5574(define_insn "*arm_extendhisi2"
ef51b8e1 5575 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
e3f4ccee 5576 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,Uh")))]
a2cd141b 5577 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 5578 "@
5579 #
3ef90e77 5580 ldrsh%?\\t%0, %1"
ef51b8e1 5581 [(set_attr "length" "8,4")
d82e788e 5582 (set_attr "type" "alu_shift_reg,load_byte")
e3f4ccee 5583 (set_attr "predicable" "yes")]
cffb2a26 5584)
f7fbdd4a 5585
25f905c2 5586;; ??? Check Thumb-2 pool range
a2cd141b 5587(define_insn "*arm_extendhisi2_v6"
5588 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
e3f4ccee 5589 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,Uh")))]
25f905c2 5590 "TARGET_32BIT && arm_arch6"
a2cd141b 5591 "@
5592 sxth%?\\t%0, %1
3ef90e77 5593 ldrsh%?\\t%0, %1"
6b6abc9c 5594 [(set_attr "type" "extend,load_byte")
8bdfd6ed 5595 (set_attr "predicable" "yes")]
a2cd141b 5596)
5597
5598(define_insn "*arm_extendhisi2addsi"
5599 [(set (match_operand:SI 0 "s_register_operand" "=r")
5600 (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
5601 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 5602 "TARGET_INT_SIMD"
a2cd141b 5603 "sxtah%?\\t%0, %2, %1"
1b7da4ac 5604 [(set_attr "type" "alu_shift_reg")]
a2cd141b 5605)
5606
c8f69309 5607(define_expand "extendqihi2"
5608 [(set (match_dup 2)
bed7d9a5 5609 (ashift:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")
c8f69309 5610 (const_int 24)))
9c08d1fa 5611 (set (match_operand:HI 0 "s_register_operand" "")
c8f69309 5612 (ashiftrt:SI (match_dup 2)
5613 (const_int 24)))]
cffb2a26 5614 "TARGET_ARM"
c8f69309 5615 "
215b30b3 5616 {
0438d37f 5617 if (arm_arch4 && MEM_P (operands[1]))
215b30b3 5618 {
d1f9b275 5619 emit_insn (gen_rtx_SET (operands[0],
215b30b3 5620 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
5621 DONE;
5622 }
5623 if (!s_register_operand (operands[1], QImode))
5624 operands[1] = copy_to_mode_reg (QImode, operands[1]);
5625 operands[0] = gen_lowpart (SImode, operands[0]);
5626 operands[1] = gen_lowpart (SImode, operands[1]);
5627 operands[2] = gen_reg_rtx (SImode);
5628 }"
5629)
f7fbdd4a 5630
25f905c2 5631(define_insn "*arm_extendqihi_insn"
b4e8a300 5632 [(set (match_operand:HI 0 "s_register_operand" "=r")
bed7d9a5 5633 (sign_extend:HI (match_operand:QI 1 "arm_extendqisi_mem_op" "Uq")))]
cffb2a26 5634 "TARGET_ARM && arm_arch4"
3ef90e77 5635 "ldrsb%?\\t%0, %1"
a2cd141b 5636 [(set_attr "type" "load_byte")
e3f4ccee 5637 (set_attr "predicable" "yes")]
cffb2a26 5638)
3fc2009e 5639
b11cae9e 5640(define_expand "extendqisi2"
ef51b8e1 5641 [(set (match_operand:SI 0 "s_register_operand" "")
5642 (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")))]
cffb2a26 5643 "TARGET_EITHER"
ef51b8e1 5644{
5645 if (!arm_arch4 && MEM_P (operands[1]))
5646 operands[1] = copy_to_mode_reg (QImode, operands[1]);
a2cd141b 5647
ef51b8e1 5648 if (!arm_arch6 && !MEM_P (operands[1]))
5649 {
5650 rtx t = gen_lowpart (SImode, operands[1]);
5651 rtx tmp = gen_reg_rtx (SImode);
5652 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
5653 emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (24)));
5654 DONE;
5655 }
5656})
a2cd141b 5657
ef51b8e1 5658(define_split
5659 [(set (match_operand:SI 0 "register_operand" "")
5660 (sign_extend:SI (match_operand:QI 1 "register_operand" "")))]
5661 "!arm_arch6"
5662 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
5663 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))]
5664{
5665 operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
5666})
f7fbdd4a 5667
a2cd141b 5668(define_insn "*arm_extendqisi"
ef51b8e1 5669 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5670 (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
a2cd141b 5671 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 5672 "@
5673 #
3ef90e77 5674 ldrsb%?\\t%0, %1"
ef51b8e1 5675 [(set_attr "length" "8,4")
d82e788e 5676 (set_attr "type" "alu_shift_reg,load_byte")
e3f4ccee 5677 (set_attr "predicable" "yes")]
cffb2a26 5678)
3fc2009e 5679
a2cd141b 5680(define_insn "*arm_extendqisi_v6"
5681 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
bed7d9a5 5682 (sign_extend:SI
5683 (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
a2cd141b 5684 "TARGET_ARM && arm_arch6"
b4e8a300 5685 "@
5686 sxtb%?\\t%0, %1
3ef90e77 5687 ldrsb%?\\t%0, %1"
6b6abc9c 5688 [(set_attr "type" "extend,load_byte")
e3f4ccee 5689 (set_attr "predicable" "yes")]
a2cd141b 5690)
5691
5692(define_insn "*arm_extendqisi2addsi"
5693 [(set (match_operand:SI 0 "s_register_operand" "=r")
5694 (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
5695 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 5696 "TARGET_INT_SIMD"
a2cd141b 5697 "sxtab%?\\t%0, %2, %1"
d82e788e 5698 [(set_attr "type" "alu_shift_reg")
8bdfd6ed 5699 (set_attr "predicable" "yes")]
a2cd141b 5700)
5701
caedf871 5702(define_expand "extendsfdf2"
5703 [(set (match_operand:DF 0 "s_register_operand" "")
5704 (float_extend:DF (match_operand:SF 1 "s_register_operand" "")))]
a50d7267 5705 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
caedf871 5706 ""
5707)
9b8516be 5708
539b44ee 5709;; HFmode -> DFmode conversions where we don't have an instruction for it
5710;; must go through SFmode.
5711;;
5712;; This is always safe for an extend.
5713
9b8516be 5714(define_expand "extendhfdf2"
539b44ee 5715 [(set (match_operand:DF 0 "s_register_operand" "")
5716 (float_extend:DF (match_operand:HF 1 "s_register_operand" "")))]
9b8516be 5717 "TARGET_EITHER"
539b44ee 5718{
5719 /* We don't have a direct instruction for this, so go via SFmode. */
5720 if (!(TARGET_32BIT && TARGET_FP16_TO_DOUBLE))
5721 {
5722 rtx op1;
5723 op1 = convert_to_mode (SFmode, operands[1], 0);
5724 op1 = convert_to_mode (DFmode, op1, 0);
5725 emit_insn (gen_movdf (operands[0], op1));
5726 DONE;
5727 }
5728 /* Otherwise, we're done producing RTL and will pick up the correct
5729 pattern to do this with one rounding-step in a single instruction. */
5730}
9b8516be 5731)
b11cae9e 5732\f
5733;; Move insns (including loads and stores)
5734
5735;; XXX Just some ideas about movti.
9c08d1fa 5736;; I don't think these are a good idea on the arm, there just aren't enough
5737;; registers
b11cae9e 5738;;(define_expand "loadti"
9c08d1fa 5739;; [(set (match_operand:TI 0 "s_register_operand" "")
b11cae9e 5740;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
5741;; "" "")
5742
5743;;(define_expand "storeti"
5744;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
9c08d1fa 5745;; (match_operand:TI 1 "s_register_operand" ""))]
b11cae9e 5746;; "" "")
5747
5748;;(define_expand "movti"
5749;; [(set (match_operand:TI 0 "general_operand" "")
5750;; (match_operand:TI 1 "general_operand" ""))]
5751;; ""
5752;; "
5753;;{
5754;; rtx insn;
5755;;
0438d37f 5756;; if (MEM_P (operands[0]) && MEM_P (operands[1]))
b11cae9e 5757;; operands[1] = copy_to_reg (operands[1]);
0438d37f 5758;; if (MEM_P (operands[0]))
b11cae9e 5759;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
0438d37f 5760;; else if (MEM_P (operands[1]))
b11cae9e 5761;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
5762;; else
5763;; FAIL;
5764;;
5765;; emit_insn (insn);
5766;; DONE;
5767;;}")
5768
a2f10574 5769;; Recognize garbage generated above.
b11cae9e 5770
5771;;(define_insn ""
5772;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
5773;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
5774;; ""
5775;; "*
5776;; {
5777;; register mem = (which_alternative < 3);
0d66636f 5778;; register const char *template;
b11cae9e 5779;;
5780;; operands[mem] = XEXP (operands[mem], 0);
5781;; switch (which_alternative)
5782;; {
5783;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
5784;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
5785;; case 2: template = \"ldmia\\t%1, %M0\"; break;
5786;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
5787;; case 4: template = \"stmia\\t%0!, %M1\"; break;
5788;; case 5: template = \"stmia\\t%0, %M1\"; break;
5789;; }
e2348bcb 5790;; output_asm_insn (template, operands);
5791;; return \"\";
b11cae9e 5792;; }")
5793
cffb2a26 5794(define_expand "movdi"
5795 [(set (match_operand:DI 0 "general_operand" "")
5796 (match_operand:DI 1 "general_operand" ""))]
5797 "TARGET_EITHER"
5798 "
e1ba4a27 5799 if (can_create_pseudo_p ())
cffb2a26 5800 {
0438d37f 5801 if (!REG_P (operands[0]))
b2778788 5802 operands[1] = force_reg (DImode, operands[1]);
cffb2a26 5803 }
6b97fdcc 5804 if (REG_P (operands[0]) && REGNO (operands[0]) <= LAST_ARM_REGNUM
b395382f 5805 && !targetm.hard_regno_mode_ok (REGNO (operands[0]), DImode))
4f0e25ca 5806 {
5807 /* Avoid LDRD's into an odd-numbered register pair in ARM state
5808 when expanding function calls. */
5809 gcc_assert (can_create_pseudo_p ());
5810 if (MEM_P (operands[1]) && MEM_VOLATILE_P (operands[1]))
5811 {
5812 /* Perform load into legal reg pair first, then move. */
5813 rtx reg = gen_reg_rtx (DImode);
5814 emit_insn (gen_movdi (reg, operands[1]));
5815 operands[1] = reg;
5816 }
5817 emit_move_insn (gen_lowpart (SImode, operands[0]),
5818 gen_lowpart (SImode, operands[1]));
5819 emit_move_insn (gen_highpart (SImode, operands[0]),
5820 gen_highpart (SImode, operands[1]));
5821 DONE;
5822 }
6b97fdcc 5823 else if (REG_P (operands[1]) && REGNO (operands[1]) <= LAST_ARM_REGNUM
b395382f 5824 && !targetm.hard_regno_mode_ok (REGNO (operands[1]), DImode))
4f0e25ca 5825 {
5826 /* Avoid STRD's from an odd-numbered register pair in ARM state
5827 when expanding function prologue. */
5828 gcc_assert (can_create_pseudo_p ());
5829 rtx split_dest = (MEM_P (operands[0]) && MEM_VOLATILE_P (operands[0]))
5830 ? gen_reg_rtx (DImode)
5831 : operands[0];
5832 emit_move_insn (gen_lowpart (SImode, split_dest),
5833 gen_lowpart (SImode, operands[1]));
5834 emit_move_insn (gen_highpart (SImode, split_dest),
5835 gen_highpart (SImode, operands[1]));
5836 if (split_dest != operands[0])
5837 emit_insn (gen_movdi (operands[0], split_dest));
5838 DONE;
5839 }
cffb2a26 5840 "
5841)
b11cae9e 5842
cffb2a26 5843(define_insn "*arm_movdi"
8f1c7041 5844 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, r, m")
5845 (match_operand:DI 1 "di_operand" "rDa,Db,Dc,mi,r"))]
cde1623a 5846 "TARGET_32BIT
d7216193 5847 && !(TARGET_HARD_FLOAT)
b2778788 5848 && !TARGET_IWMMXT
5849 && ( register_operand (operands[0], DImode)
5850 || register_operand (operands[1], DImode))"
b11cae9e 5851 "*
d51f92df 5852 switch (which_alternative)
5853 {
5854 case 0:
5855 case 1:
5856 case 2:
5857 return \"#\";
581f16e5 5858 case 3:
5859 /* Cannot load it directly, split to load it via MOV / MOVT. */
5860 if (!MEM_P (operands[1]) && arm_disable_literal_pool)
5861 return \"#\";
5862 /* Fall through. */
d51f92df 5863 default:
26ff80c0 5864 return output_move_double (operands, true, NULL);
d51f92df 5865 }
cffb2a26 5866 "
359a6e9f 5867 [(set_attr "length" "8,12,16,8,8")
9f2c2a36 5868 (set_attr "type" "multiple,multiple,multiple,load_8,store_8")
cde1623a 5869 (set_attr "arm_pool_range" "*,*,*,1020,*")
8848d797 5870 (set_attr "arm_neg_pool_range" "*,*,*,1004,*")
42e1de19 5871 (set_attr "thumb2_pool_range" "*,*,*,4094,*")
cde1623a 5872 (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
cffb2a26 5873)
5874
d51f92df 5875(define_split
5876 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
e6dd3afa 5877 (match_operand:ANY64 1 "immediate_operand" ""))]
25f905c2 5878 "TARGET_32BIT
d51f92df 5879 && reload_completed
a869c476 5880 && (arm_disable_literal_pool
5881 || (arm_const_double_inline_cost (operands[1])
5882 <= arm_max_const_double_inline_cost ()))"
d51f92df 5883 [(const_int 0)]
5884 "
5885 arm_split_constant (SET, SImode, curr_insn,
5886 INTVAL (gen_lowpart (SImode, operands[1])),
5887 gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
5888 arm_split_constant (SET, SImode, curr_insn,
5889 INTVAL (gen_highpart_mode (SImode,
5890 GET_MODE (operands[0]),
5891 operands[1])),
5892 gen_highpart (SImode, operands[0]), NULL_RTX, 0);
5893 DONE;
5894 "
5895)
5896
e5ba9289 5897; If optimizing for size, or if we have load delay slots, then
5898; we want to split the constant into two separate operations.
5899; In both cases this may split a trivial part into a single data op
5900; leaving a single complex constant to load. We can also get longer
5901; offsets in a LDR which means we get better chances of sharing the pool
5902; entries. Finally, we can normally do a better job of scheduling
5903; LDR instructions than we can with LDM.
5904; This pattern will only match if the one above did not.
5905(define_split
5906 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
5907 (match_operand:ANY64 1 "const_double_operand" ""))]
5908 "TARGET_ARM && reload_completed
5909 && arm_const_double_by_parts (operands[1])"
5910 [(set (match_dup 0) (match_dup 1))
5911 (set (match_dup 2) (match_dup 3))]
5912 "
5913 operands[2] = gen_highpart (SImode, operands[0]);
5914 operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
5915 operands[1]);
5916 operands[0] = gen_lowpart (SImode, operands[0]);
5917 operands[1] = gen_lowpart (SImode, operands[1]);
5918 "
5919)
5920
d51f92df 5921(define_split
5922 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
5923 (match_operand:ANY64 1 "arm_general_register_operand" ""))]
5924 "TARGET_EITHER && reload_completed"
5925 [(set (match_dup 0) (match_dup 1))
5926 (set (match_dup 2) (match_dup 3))]
5927 "
5928 operands[2] = gen_highpart (SImode, operands[0]);
5929 operands[3] = gen_highpart (SImode, operands[1]);
5930 operands[0] = gen_lowpart (SImode, operands[0]);
5931 operands[1] = gen_lowpart (SImode, operands[1]);
5932
5933 /* Handle a partial overlap. */
5934 if (rtx_equal_p (operands[0], operands[3]))
5935 {
5936 rtx tmp0 = operands[0];
5937 rtx tmp1 = operands[1];
5938
5939 operands[0] = operands[2];
5940 operands[1] = operands[3];
5941 operands[2] = tmp0;
5942 operands[3] = tmp1;
5943 }
5944 "
5945)
5946
a8a3b539 5947;; We can't actually do base+index doubleword loads if the index and
5948;; destination overlap. Split here so that we at least have chance to
5949;; schedule.
5950(define_split
5951 [(set (match_operand:DI 0 "s_register_operand" "")
5952 (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
5953 (match_operand:SI 2 "s_register_operand" ""))))]
5954 "TARGET_LDRD
5955 && reg_overlap_mentioned_p (operands[0], operands[1])
5956 && reg_overlap_mentioned_p (operands[0], operands[2])"
5957 [(set (match_dup 4)
5958 (plus:SI (match_dup 1)
5959 (match_dup 2)))
5960 (set (match_dup 0)
5961 (mem:DI (match_dup 4)))]
5962 "
5963 operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
5964 "
5965)
5966
9c08d1fa 5967(define_expand "movsi"
5968 [(set (match_operand:SI 0 "general_operand" "")
5969 (match_operand:SI 1 "general_operand" ""))]
cffb2a26 5970 "TARGET_EITHER"
9c08d1fa 5971 "
befb0bac 5972 {
e348ff3e 5973 rtx base, offset, tmp;
5974
6e291830 5975 if (TARGET_32BIT || TARGET_HAVE_MOVT)
9c08d1fa 5976 {
674a8f0b 5977 /* Everything except mem = const or mem = mem can be done easily. */
0438d37f 5978 if (MEM_P (operands[0]))
cffb2a26 5979 operands[1] = force_reg (SImode, operands[1]);
a2cd141b 5980 if (arm_general_register_operand (operands[0], SImode)
0438d37f 5981 && CONST_INT_P (operands[1])
cffb2a26 5982 && !(const_ok_for_arm (INTVAL (operands[1]))
5983 || const_ok_for_arm (~INTVAL (operands[1]))))
5984 {
17202aa5 5985 if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[1]), SET))
5986 {
5987 emit_insn (gen_rtx_SET (operands[0], operands[1]));
5988 DONE;
5989 }
5990 else
5991 {
5992 arm_split_constant (SET, SImode, NULL_RTX,
5993 INTVAL (operands[1]), operands[0], NULL_RTX,
5994 optimize && can_create_pseudo_p ());
5995 DONE;
5996 }
cffb2a26 5997 }
5998 }
75612252 5999 else /* Target doesn't have MOVT... */
cffb2a26 6000 {
e1ba4a27 6001 if (can_create_pseudo_p ())
cffb2a26 6002 {
0438d37f 6003 if (!REG_P (operands[0]))
cffb2a26 6004 operands[1] = force_reg (SImode, operands[1]);
6005 }
9c08d1fa 6006 }
f655717d 6007
e348ff3e 6008 if (ARM_OFFSETS_MUST_BE_WITHIN_SECTIONS_P)
6009 {
6010 split_const (operands[1], &base, &offset);
6011 if (GET_CODE (base) == SYMBOL_REF
6012 && !offset_within_block_p (base, INTVAL (offset)))
6013 {
b308ddcf 6014 tmp = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
e348ff3e 6015 emit_move_insn (tmp, base);
6016 emit_insn (gen_addsi3 (operands[0], tmp, offset));
6017 DONE;
6018 }
6019 }
6020
f655717d 6021 /* Recognize the case where operand[1] is a reference to thread-local
6022 data and load its address to a register. */
6023 if (arm_tls_referenced_p (operands[1]))
6024 {
6025 rtx tmp = operands[1];
6026 rtx addend = NULL;
6027
6028 if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
6029 {
6030 addend = XEXP (XEXP (tmp, 0), 1);
6031 tmp = XEXP (XEXP (tmp, 0), 0);
6032 }
6033
6034 gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
6035 gcc_assert (SYMBOL_REF_TLS_MODEL (tmp) != 0);
6036
e1ba4a27 6037 tmp = legitimize_tls_address (tmp,
6038 !can_create_pseudo_p () ? operands[0] : 0);
f655717d 6039 if (addend)
6040 {
6041 tmp = gen_rtx_PLUS (SImode, tmp, addend);
6042 tmp = force_operand (tmp, operands[0]);
6043 }
6044 operands[1] = tmp;
6045 }
6046 else if (flag_pic
6047 && (CONSTANT_P (operands[1])
6048 || symbol_mentioned_p (operands[1])
6049 || label_mentioned_p (operands[1])))
6050 operands[1] = legitimize_pic_address (operands[1], SImode,
e1ba4a27 6051 (!can_create_pseudo_p ()
6052 ? operands[0]
f98495d9 6053 : NULL_RTX), NULL_RTX,
6054 false /*compute_now*/);
befb0bac 6055 }
215b30b3 6056 "
6057)
9c08d1fa 6058
d0e6a121 6059;; The ARM LO_SUM and HIGH are backwards - HIGH sets the low bits, and
6060;; LO_SUM adds in the high bits. Fortunately these are opaque operations
6061;; so this does not matter.
6062(define_insn "*arm_movt"
417e5cc5 6063 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r")
6064 (lo_sum:SI (match_operand:SI 1 "nonimmediate_operand" "0,0")
6065 (match_operand:SI 2 "general_operand" "i,i")))]
60a48e7d 6066 "TARGET_HAVE_MOVT && arm_valid_symbolic_address_p (operands[2])"
417e5cc5 6067 "@
6068 movt%?\t%0, #:upper16:%c2
6069 movt\t%0, #:upper16:%c2"
6070 [(set_attr "arch" "32,v8mb")
6071 (set_attr "predicable" "yes")
1b7da4ac 6072 (set_attr "length" "4")
282b4c75 6073 (set_attr "type" "alu_sreg")]
d0e6a121 6074)
6075
cffb2a26 6076(define_insn "*arm_movsi_insn"
aaa37ad6 6077 [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,rk,m")
110eae03 6078 (match_operand:SI 1 "general_operand" "rk, I,K,j,mi,rk"))]
d7216193 6079 "TARGET_ARM && !TARGET_IWMMXT && !TARGET_HARD_FLOAT
cffb2a26 6080 && ( register_operand (operands[0], SImode)
6081 || register_operand (operands[1], SImode))"
f7fbdd4a 6082 "@
aaa37ad6 6083 mov%?\\t%0, %1
f7fbdd4a 6084 mov%?\\t%0, %1
6085 mvn%?\\t%0, #%B1
25f905c2 6086 movw%?\\t%0, %1
f7fbdd4a 6087 ldr%?\\t%0, %1
6088 str%?\\t%1, %0"
9f2c2a36 6089 [(set_attr "type" "mov_reg,mov_imm,mvn_imm,mov_imm,load_4,store_4")
0d66636f 6090 (set_attr "predicable" "yes")
100cd063 6091 (set_attr "arch" "*,*,*,v6t2,*,*")
aaa37ad6 6092 (set_attr "pool_range" "*,*,*,*,4096,*")
6093 (set_attr "neg_pool_range" "*,*,*,*,4084,*")]
cffb2a26 6094)
87b22bf7 6095
6096(define_split
a2cd141b 6097 [(set (match_operand:SI 0 "arm_general_register_operand" "")
87b22bf7 6098 (match_operand:SI 1 "const_int_operand" ""))]
6e291830 6099 "(TARGET_32BIT || TARGET_HAVE_MOVT)
215b30b3 6100 && (!(const_ok_for_arm (INTVAL (operands[1]))
6101 || const_ok_for_arm (~INTVAL (operands[1]))))"
87b22bf7 6102 [(clobber (const_int 0))]
6103 "
96f57e36 6104 arm_split_constant (SET, SImode, NULL_RTX,
6105 INTVAL (operands[1]), operands[0], NULL_RTX, 0);
87b22bf7 6106 DONE;
215b30b3 6107 "
6108)
9c08d1fa 6109
861033d5 6110;; A normal way to do (symbol + offset) requires three instructions at least
6111;; (depends on how big the offset is) as below:
6112;; movw r0, #:lower16:g
6113;; movw r0, #:upper16:g
6114;; adds r0, #4
6115;;
6116;; A better way would be:
6117;; movw r0, #:lower16:g+4
6118;; movw r0, #:upper16:g+4
6119;;
6120;; The limitation of this way is that the length of offset should be a 16-bit
6121;; signed value, because current assembler only supports REL type relocation for
6122;; such case. If the more powerful RELA type is supported in future, we should
6123;; update this pattern to go with better way.
6124(define_split
6125 [(set (match_operand:SI 0 "arm_general_register_operand" "")
6126 (const:SI (plus:SI (match_operand:SI 1 "general_operand" "")
6127 (match_operand:SI 2 "const_int_operand" ""))))]
60a48e7d 6128 "TARGET_THUMB
6129 && TARGET_HAVE_MOVT
861033d5 6130 && arm_disable_literal_pool
6131 && reload_completed
6132 && GET_CODE (operands[1]) == SYMBOL_REF"
6133 [(clobber (const_int 0))]
6134 "
6135 int offset = INTVAL (operands[2]);
6136
6137 if (offset < -0x8000 || offset > 0x7fff)
6138 {
6139 arm_emit_movpair (operands[0], operands[1]);
d1f9b275 6140 emit_insn (gen_rtx_SET (operands[0],
861033d5 6141 gen_rtx_PLUS (SImode, operands[0], operands[2])));
6142 }
6143 else
6144 {
6145 rtx op = gen_rtx_CONST (SImode,
6146 gen_rtx_PLUS (SImode, operands[1], operands[2]));
6147 arm_emit_movpair (operands[0], op);
6148 }
6149 "
6150)
6151
b8d5d078 6152;; Split symbol_refs at the later stage (after cprop), instead of generating
6153;; movt/movw pair directly at expand. Otherwise corresponding high_sum
6154;; and lo_sum would be merged back into memory load at cprop. However,
6155;; if the default is to prefer movt/movw rather than a load from the constant
6156;; pool, the performance is better.
6157(define_split
6158 [(set (match_operand:SI 0 "arm_general_register_operand" "")
6159 (match_operand:SI 1 "general_operand" ""))]
60a48e7d 6160 "TARGET_USE_MOVT && GET_CODE (operands[1]) == SYMBOL_REF
d022aaf3 6161 && !target_word_relocations
b8d5d078 6162 && !arm_tls_referenced_p (operands[1])"
6163 [(clobber (const_int 0))]
6164{
6165 arm_emit_movpair (operands[0], operands[1]);
6166 DONE;
6167})
6168
bc360af8 6169;; When generating pic, we need to load the symbol offset into a register.
6170;; So that the optimizer does not confuse this with a normal symbol load
6171;; we use an unspec. The offset will be loaded from a constant pool entry,
6172;; since that is the only type of relocation we can use.
cffb2a26 6173
bc360af8 6174;; Wrap calculation of the whole PIC address in a single pattern for the
6175;; benefit of optimizers, particularly, PRE and HOIST. Calculation of
6176;; a PIC address involves two loads from memory, so we want to CSE it
6177;; as often as possible.
6178;; This pattern will be split into one of the pic_load_addr_* patterns
6179;; and a move after GCSE optimizations.
6180;;
6181;; Note: Update arm.c: legitimize_pic_address() when changing this pattern.
6182(define_expand "calculate_pic_address"
94f8caca 6183 [(set (match_operand:SI 0 "register_operand" "")
6184 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "")
6185 (unspec:SI [(match_operand:SI 2 "" "")]
6186 UNSPEC_PIC_SYM))))]
6187 "flag_pic"
6188)
6189
6190;; Split calculate_pic_address into pic_load_addr_* and a move.
6191(define_split
6192 [(set (match_operand:SI 0 "register_operand" "")
6193 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "")
6194 (unspec:SI [(match_operand:SI 2 "" "")]
6195 UNSPEC_PIC_SYM))))]
6196 "flag_pic"
6197 [(set (match_dup 3) (unspec:SI [(match_dup 2)] UNSPEC_PIC_SYM))
6198 (set (match_dup 0) (mem:SI (plus:SI (match_dup 1) (match_dup 3))))]
6199 "operands[3] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];"
6200)
6201
350ccca5 6202;; operand1 is the memory address to go into
6203;; pic_load_addr_32bit.
6204;; operand2 is the PIC label to be emitted
6205;; from pic_add_dot_plus_eight.
6206;; We do this to allow hoisting of the entire insn.
6207(define_insn_and_split "pic_load_addr_unified"
6208 [(set (match_operand:SI 0 "s_register_operand" "=r,r,l")
6209 (unspec:SI [(match_operand:SI 1 "" "mX,mX,mX")
6210 (match_operand:SI 2 "" "")]
6211 UNSPEC_PIC_UNIFIED))]
6212 "flag_pic"
6213 "#"
6214 "&& reload_completed"
6215 [(set (match_dup 0) (unspec:SI [(match_dup 1)] UNSPEC_PIC_SYM))
6216 (set (match_dup 0) (unspec:SI [(match_dup 0) (match_dup 3)
6217 (match_dup 2)] UNSPEC_PIC_BASE))]
6218 "operands[3] = TARGET_THUMB ? GEN_INT (4) : GEN_INT (8);"
9f2c2a36 6219 [(set_attr "type" "load_4,load_4,load_4")
42e1de19 6220 (set_attr "pool_range" "4096,4094,1022")
350ccca5 6221 (set_attr "neg_pool_range" "4084,0,0")
6222 (set_attr "arch" "a,t2,t1")
6223 (set_attr "length" "8,6,4")]
6224)
6225
67336bcf 6226;; The rather odd constraints on the following are to force reload to leave
6227;; the insn alone, and to force the minipool generation pass to then move
6228;; the GOT symbol to memory.
849170fd 6229
b3cd5f55 6230(define_insn "pic_load_addr_32bit"
849170fd 6231 [(set (match_operand:SI 0 "s_register_operand" "=r")
e1159bbe 6232 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
b3cd5f55 6233 "TARGET_32BIT && flag_pic"
67336bcf 6234 "ldr%?\\t%0, %1"
9f2c2a36 6235 [(set_attr "type" "load_4")
42e1de19 6236 (set (attr "pool_range")
6237 (if_then_else (eq_attr "is_thumb" "no")
6238 (const_int 4096)
6239 (const_int 4094)))
b3cd5f55 6240 (set (attr "neg_pool_range")
6241 (if_then_else (eq_attr "is_thumb" "no")
6242 (const_int 4084)
6243 (const_int 0)))]
8c4d8060 6244)
6245
25f905c2 6246(define_insn "pic_load_addr_thumb1"
8c4d8060 6247 [(set (match_operand:SI 0 "s_register_operand" "=l")
e1159bbe 6248 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
25f905c2 6249 "TARGET_THUMB1 && flag_pic"
8c4d8060 6250 "ldr\\t%0, %1"
9f2c2a36 6251 [(set_attr "type" "load_4")
42e1de19 6252 (set (attr "pool_range") (const_int 1018))]
cffb2a26 6253)
849170fd 6254
cffb2a26 6255(define_insn "pic_add_dot_plus_four"
15d5d060 6256 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 6257 (unspec:SI [(match_operand:SI 1 "register_operand" "0")
6258 (const_int 4)
beef0fb5 6259 (match_operand 2 "" "")]
6260 UNSPEC_PIC_BASE))]
b3cd5f55 6261 "TARGET_THUMB"
cffb2a26 6262 "*
6cdcb15c 6263 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
6264 INTVAL (operands[2]));
cffb2a26 6265 return \"add\\t%0, %|pc\";
6266 "
1b7da4ac 6267 [(set_attr "length" "2")
112eda6f 6268 (set_attr "type" "alu_sreg")]
cffb2a26 6269)
849170fd 6270
6271(define_insn "pic_add_dot_plus_eight"
15d5d060 6272 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 6273 (unspec:SI [(match_operand:SI 1 "register_operand" "r")
6274 (const_int 8)
beef0fb5 6275 (match_operand 2 "" "")]
6276 UNSPEC_PIC_BASE))]
f655717d 6277 "TARGET_ARM"
c4034607 6278 "*
6cdcb15c 6279 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
6280 INTVAL (operands[2]));
15d5d060 6281 return \"add%?\\t%0, %|pc, %1\";
cffb2a26 6282 "
1b7da4ac 6283 [(set_attr "predicable" "yes")
112eda6f 6284 (set_attr "type" "alu_sreg")]
cffb2a26 6285)
849170fd 6286
f655717d 6287(define_insn "tls_load_dot_plus_eight"
cc071db6 6288 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 6289 (mem:SI (unspec:SI [(match_operand:SI 1 "register_operand" "r")
6290 (const_int 8)
beef0fb5 6291 (match_operand 2 "" "")]
6292 UNSPEC_PIC_BASE)))]
f655717d 6293 "TARGET_ARM"
6294 "*
6cdcb15c 6295 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
6296 INTVAL (operands[2]));
f655717d 6297 return \"ldr%?\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_eight\";
6298 "
1b7da4ac 6299 [(set_attr "predicable" "yes")
9f2c2a36 6300 (set_attr "type" "load_4")]
f655717d 6301)
6302
6303;; PIC references to local variables can generate pic_add_dot_plus_eight
6304;; followed by a load. These sequences can be crunched down to
6305;; tls_load_dot_plus_eight by a peephole.
6306
6307(define_peephole2
c0c1fba5 6308 [(set (match_operand:SI 0 "register_operand" "")
6309 (unspec:SI [(match_operand:SI 3 "register_operand" "")
6310 (const_int 8)
6311 (match_operand 1 "" "")]
6312 UNSPEC_PIC_BASE))
2d05dfad 6313 (set (match_operand:SI 2 "arm_general_register_operand" "")
6314 (mem:SI (match_dup 0)))]
f655717d 6315 "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
c0c1fba5 6316 [(set (match_dup 2)
6317 (mem:SI (unspec:SI [(match_dup 3)
6318 (const_int 8)
6319 (match_dup 1)]
6320 UNSPEC_PIC_BASE)))]
f655717d 6321 ""
6322)
6323
bac7fc85 6324(define_insn "pic_offset_arm"
6325 [(set (match_operand:SI 0 "register_operand" "=r")
6326 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
6327 (unspec:SI [(match_operand:SI 2 "" "X")]
6328 UNSPEC_PIC_OFFSET))))]
6329 "TARGET_VXWORKS_RTP && TARGET_ARM && flag_pic"
6330 "ldr%?\\t%0, [%1,%2]"
9f2c2a36 6331 [(set_attr "type" "load_4")]
bac7fc85 6332)
6333
95373f08 6334(define_expand "builtin_setjmp_receiver"
6335 [(label_ref (match_operand 0 "" ""))]
6336 "flag_pic"
6337 "
6338{
b935b306 6339 /* r3 is clobbered by set/longjmp, so we can use it as a scratch
6340 register. */
2cb7d577 6341 if (arm_pic_register != INVALID_REGNUM)
f98495d9 6342 arm_load_pic_register (1UL << 3, NULL_RTX);
95373f08 6343 DONE;
6344}")
6345
9c08d1fa 6346;; If copying one reg to another we can set the condition codes according to
6347;; its value. Such a move is common after a return from subroutine and the
6348;; result is being tested against zero.
6349
f7fbdd4a 6350(define_insn "*movsi_compare0"
bd5b4116 6351 [(set (reg:CC CC_REGNUM)
cffb2a26 6352 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
6353 (const_int 0)))
6354 (set (match_operand:SI 0 "s_register_operand" "=r,r")
6355 (match_dup 1))]
25f905c2 6356 "TARGET_32BIT"
e2348bcb 6357 "@
40dbec34 6358 cmp%?\\t%0, #0
3ef90e77 6359 subs%?\\t%0, %1, #0"
65f68e55 6360 [(set_attr "conds" "set")
d82e788e 6361 (set_attr "type" "alus_imm,alus_imm")]
cffb2a26 6362)
b11cae9e 6363
b11cae9e 6364;; Subroutine to store a half word from a register into memory.
6365;; Operand 0 is the source register (HImode)
c8f69309 6366;; Operand 1 is the destination address in a register (SImode)
b11cae9e 6367
9c08d1fa 6368;; In both this routine and the next, we must be careful not to spill
01cc3b75 6369;; a memory address of reg+large_const into a separate PLUS insn, since this
9c08d1fa 6370;; can generate unrecognizable rtl.
6371
b11cae9e 6372(define_expand "storehi"
c8f69309 6373 [;; store the low byte
f082f1c4 6374 (set (match_operand 1 "" "") (match_dup 3))
b11cae9e 6375 ;; extract the high byte
c8f69309 6376 (set (match_dup 2)
6377 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
b11cae9e 6378 ;; store the high byte
787f8210 6379 (set (match_dup 4) (match_dup 5))]
cffb2a26 6380 "TARGET_ARM"
b11cae9e 6381 "
215b30b3 6382 {
537ffcfc 6383 rtx op1 = operands[1];
6384 rtx addr = XEXP (op1, 0);
215b30b3 6385 enum rtx_code code = GET_CODE (addr);
6386
0438d37f 6387 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
215b30b3 6388 || code == MINUS)
537ffcfc 6389 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
215b30b3 6390
537ffcfc 6391 operands[4] = adjust_address (op1, QImode, 1);
e513d163 6392 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 6393 operands[3] = gen_lowpart (QImode, operands[0]);
6394 operands[0] = gen_lowpart (SImode, operands[0]);
787f8210 6395 operands[2] = gen_reg_rtx (SImode);
6396 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 6397 }"
6398)
b11cae9e 6399
c7597b5d 6400(define_expand "storehi_bigend"
f082f1c4 6401 [(set (match_dup 4) (match_dup 3))
c7597b5d 6402 (set (match_dup 2)
6403 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
787f8210 6404 (set (match_operand 1 "" "") (match_dup 5))]
cffb2a26 6405 "TARGET_ARM"
b11cae9e 6406 "
215b30b3 6407 {
537ffcfc 6408 rtx op1 = operands[1];
6409 rtx addr = XEXP (op1, 0);
215b30b3 6410 enum rtx_code code = GET_CODE (addr);
6411
0438d37f 6412 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
215b30b3 6413 || code == MINUS)
537ffcfc 6414 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
215b30b3 6415
537ffcfc 6416 operands[4] = adjust_address (op1, QImode, 1);
e513d163 6417 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 6418 operands[3] = gen_lowpart (QImode, operands[0]);
6419 operands[0] = gen_lowpart (SImode, operands[0]);
6420 operands[2] = gen_reg_rtx (SImode);
787f8210 6421 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 6422 }"
6423)
c7597b5d 6424
6425;; Subroutine to store a half word integer constant into memory.
6426(define_expand "storeinthi"
f082f1c4 6427 [(set (match_operand 0 "" "")
787f8210 6428 (match_operand 1 "" ""))
9e8503e6 6429 (set (match_dup 3) (match_dup 2))]
cffb2a26 6430 "TARGET_ARM"
c7597b5d 6431 "
215b30b3 6432 {
6433 HOST_WIDE_INT value = INTVAL (operands[1]);
6434 rtx addr = XEXP (operands[0], 0);
537ffcfc 6435 rtx op0 = operands[0];
215b30b3 6436 enum rtx_code code = GET_CODE (addr);
c7597b5d 6437
0438d37f 6438 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
215b30b3 6439 || code == MINUS)
537ffcfc 6440 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
c7597b5d 6441
215b30b3 6442 operands[1] = gen_reg_rtx (SImode);
6443 if (BYTES_BIG_ENDIAN)
6444 {
6445 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
6446 if ((value & 255) == ((value >> 8) & 255))
6447 operands[2] = operands[1];
6448 else
6449 {
6450 operands[2] = gen_reg_rtx (SImode);
6451 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
6452 }
6453 }
6454 else
6455 {
6456 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
6457 if ((value & 255) == ((value >> 8) & 255))
6458 operands[2] = operands[1];
6459 else
6460 {
6461 operands[2] = gen_reg_rtx (SImode);
6462 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
6463 }
6464 }
c7597b5d 6465
537ffcfc 6466 operands[3] = adjust_address (op0, QImode, 1);
e513d163 6467 operands[0] = adjust_address (operands[0], QImode, 0);
9e8503e6 6468 operands[2] = gen_lowpart (QImode, operands[2]);
787f8210 6469 operands[1] = gen_lowpart (QImode, operands[1]);
215b30b3 6470 }"
6471)
b11cae9e 6472
f7fbdd4a 6473(define_expand "storehi_single_op"
6474 [(set (match_operand:HI 0 "memory_operand" "")
6475 (match_operand:HI 1 "general_operand" ""))]
25f905c2 6476 "TARGET_32BIT && arm_arch4"
f7fbdd4a 6477 "
215b30b3 6478 if (!s_register_operand (operands[1], HImode))
f7fbdd4a 6479 operands[1] = copy_to_mode_reg (HImode, operands[1]);
215b30b3 6480 "
6481)
f7fbdd4a 6482
b11cae9e 6483(define_expand "movhi"
6484 [(set (match_operand:HI 0 "general_operand" "")
c8f69309 6485 (match_operand:HI 1 "general_operand" ""))]
cffb2a26 6486 "TARGET_EITHER"
b11cae9e 6487 "
cffb2a26 6488 if (TARGET_ARM)
b11cae9e 6489 {
e1ba4a27 6490 if (can_create_pseudo_p ())
cffb2a26 6491 {
0438d37f 6492 if (MEM_P (operands[0]))
b11cae9e 6493 {
cffb2a26 6494 if (arm_arch4)
6495 {
6496 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
6497 DONE;
6498 }
0438d37f 6499 if (CONST_INT_P (operands[1]))
cffb2a26 6500 emit_insn (gen_storeinthi (operands[0], operands[1]));
c7597b5d 6501 else
cffb2a26 6502 {
0438d37f 6503 if (MEM_P (operands[1]))
cffb2a26 6504 operands[1] = force_reg (HImode, operands[1]);
6505 if (BYTES_BIG_ENDIAN)
6506 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
6507 else
6508 emit_insn (gen_storehi (operands[1], operands[0]));
6509 }
6510 DONE;
b11cae9e 6511 }
cffb2a26 6512 /* Sign extend a constant, and keep it in an SImode reg. */
0438d37f 6513 else if (CONST_INT_P (operands[1]))
9c08d1fa 6514 {
cffb2a26 6515 rtx reg = gen_reg_rtx (SImode);
6516 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
6517
6518 /* If the constant is already valid, leave it alone. */
215b30b3 6519 if (!const_ok_for_arm (val))
cffb2a26 6520 {
6521 /* If setting all the top bits will make the constant
6522 loadable in a single instruction, then set them.
6523 Otherwise, sign extend the number. */
6524
215b30b3 6525 if (const_ok_for_arm (~(val | ~0xffff)))
cffb2a26 6526 val |= ~0xffff;
6527 else if (val & 0x8000)
6528 val |= ~0xffff;
6529 }
6530
6531 emit_insn (gen_movsi (reg, GEN_INT (val)));
9e8503e6 6532 operands[1] = gen_lowpart (HImode, reg);
9c08d1fa 6533 }
e1ba4a27 6534 else if (arm_arch4 && optimize && can_create_pseudo_p ()
0438d37f 6535 && MEM_P (operands[1]))
0045890a 6536 {
6537 rtx reg = gen_reg_rtx (SImode);
6538
6539 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
6540 operands[1] = gen_lowpart (HImode, reg);
6541 }
215b30b3 6542 else if (!arm_arch4)
f7fbdd4a 6543 {
0438d37f 6544 if (MEM_P (operands[1]))
cffb2a26 6545 {
c1a66faf 6546 rtx base;
6547 rtx offset = const0_rtx;
6548 rtx reg = gen_reg_rtx (SImode);
6549
0438d37f 6550 if ((REG_P (base = XEXP (operands[1], 0))
c1a66faf 6551 || (GET_CODE (base) == PLUS
0438d37f 6552 && (CONST_INT_P (offset = XEXP (base, 1)))
c1a66faf 6553 && ((INTVAL(offset) & 1) != 1)
0438d37f 6554 && REG_P (base = XEXP (base, 0))))
c1a66faf 6555 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
206ee9a2 6556 {
8deb3959 6557 rtx new_rtx;
c1a66faf 6558
8deb3959 6559 new_rtx = widen_memory_access (operands[1], SImode,
6560 ((INTVAL (offset) & ~3)
6561 - INTVAL (offset)));
6562 emit_insn (gen_movsi (reg, new_rtx));
c1a66faf 6563 if (((INTVAL (offset) & 2) != 0)
6564 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
6565 {
6566 rtx reg2 = gen_reg_rtx (SImode);
6567
6568 emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
6569 reg = reg2;
6570 }
206ee9a2 6571 }
c1a66faf 6572 else
6573 emit_insn (gen_movhi_bytes (reg, operands[1]));
6574
6575 operands[1] = gen_lowpart (HImode, reg);
cffb2a26 6576 }
6577 }
6578 }
674a8f0b 6579 /* Handle loading a large integer during reload. */
0438d37f 6580 else if (CONST_INT_P (operands[1])
215b30b3 6581 && !const_ok_for_arm (INTVAL (operands[1]))
6582 && !const_ok_for_arm (~INTVAL (operands[1])))
cffb2a26 6583 {
6584 /* Writing a constant to memory needs a scratch, which should
6585 be handled with SECONDARY_RELOADs. */
0438d37f 6586 gcc_assert (REG_P (operands[0]));
cffb2a26 6587
6588 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
6589 emit_insn (gen_movsi (operands[0], operands[1]));
6590 DONE;
6591 }
6592 }
25f905c2 6593 else if (TARGET_THUMB2)
6594 {
6595 /* Thumb-2 can do everything except mem=mem and mem=const easily. */
e1ba4a27 6596 if (can_create_pseudo_p ())
25f905c2 6597 {
0438d37f 6598 if (!REG_P (operands[0]))
25f905c2 6599 operands[1] = force_reg (HImode, operands[1]);
6600 /* Zero extend a constant, and keep it in an SImode reg. */
0438d37f 6601 else if (CONST_INT_P (operands[1]))
25f905c2 6602 {
6603 rtx reg = gen_reg_rtx (SImode);
6604 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
6605
6606 emit_insn (gen_movsi (reg, GEN_INT (val)));
6607 operands[1] = gen_lowpart (HImode, reg);
6608 }
6609 }
6610 }
6611 else /* TARGET_THUMB1 */
cffb2a26 6612 {
e1ba4a27 6613 if (can_create_pseudo_p ())
cffb2a26 6614 {
0438d37f 6615 if (CONST_INT_P (operands[1]))
6cffc037 6616 {
6617 rtx reg = gen_reg_rtx (SImode);
6618
6619 emit_insn (gen_movsi (reg, operands[1]));
6620 operands[1] = gen_lowpart (HImode, reg);
6621 }
cffb2a26 6622
6623 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 6624 happen if we are passed a SP (never OK for HImode/QImode) or
bc409cb4 6625 virtual register (also rejected as illegitimate for HImode/QImode)
6626 relative address. */
cffb2a26 6627 /* ??? This should perhaps be fixed elsewhere, for instance, in
6628 fixup_stack_1, by checking for other kinds of invalid addresses,
6629 e.g. a bare reference to a virtual register. This may confuse the
6630 alpha though, which must handle this case differently. */
0438d37f 6631 if (MEM_P (operands[0])
215b30b3 6632 && !memory_address_p (GET_MODE (operands[0]),
6633 XEXP (operands[0], 0)))
537ffcfc 6634 operands[0]
6635 = replace_equiv_address (operands[0],
6636 copy_to_reg (XEXP (operands[0], 0)));
cffb2a26 6637
0438d37f 6638 if (MEM_P (operands[1])
215b30b3 6639 && !memory_address_p (GET_MODE (operands[1]),
6640 XEXP (operands[1], 0)))
537ffcfc 6641 operands[1]
6642 = replace_equiv_address (operands[1],
6643 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 6644
0438d37f 6645 if (MEM_P (operands[1]) && optimize > 0)
6cffc037 6646 {
6647 rtx reg = gen_reg_rtx (SImode);
6648
6649 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
6650 operands[1] = gen_lowpart (HImode, reg);
6651 }
6652
0438d37f 6653 if (MEM_P (operands[0]))
6cffc037 6654 operands[1] = force_reg (HImode, operands[1]);
cffb2a26 6655 }
0438d37f 6656 else if (CONST_INT_P (operands[1])
234f6557 6657 && !satisfies_constraint_I (operands[1]))
cffb2a26 6658 {
6cffc037 6659 /* Handle loading a large integer during reload. */
6660
cffb2a26 6661 /* Writing a constant to memory needs a scratch, which should
6662 be handled with SECONDARY_RELOADs. */
0438d37f 6663 gcc_assert (REG_P (operands[0]));
cffb2a26 6664
1a83b3ff 6665 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
cffb2a26 6666 emit_insn (gen_movsi (operands[0], operands[1]));
6667 DONE;
6668 }
b11cae9e 6669 }
cffb2a26 6670 "
6671)
6672
25f7a26e 6673(define_expand "movhi_bytes"
eab14235 6674 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 6675 (set (match_dup 3)
eab14235 6676 (zero_extend:SI (match_dup 6)))
25f7a26e 6677 (set (match_operand:SI 0 "" "")
6678 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
cffb2a26 6679 "TARGET_ARM"
25f7a26e 6680 "
215b30b3 6681 {
6682 rtx mem1, mem2;
6683 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
6684
788fcce0 6685 mem1 = change_address (operands[1], QImode, addr);
29c05e22 6686 mem2 = change_address (operands[1], QImode,
6687 plus_constant (Pmode, addr, 1));
215b30b3 6688 operands[0] = gen_lowpart (SImode, operands[0]);
6689 operands[1] = mem1;
6690 operands[2] = gen_reg_rtx (SImode);
6691 operands[3] = gen_reg_rtx (SImode);
6692 operands[6] = mem2;
25f7a26e 6693
215b30b3 6694 if (BYTES_BIG_ENDIAN)
6695 {
6696 operands[4] = operands[2];
6697 operands[5] = operands[3];
6698 }
6699 else
6700 {
6701 operands[4] = operands[3];
6702 operands[5] = operands[2];
6703 }
6704 }"
6705)
25f7a26e 6706
c7597b5d 6707(define_expand "movhi_bigend"
6708 [(set (match_dup 2)
6709 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
6710 (const_int 16)))
6711 (set (match_dup 3)
6712 (ashiftrt:SI (match_dup 2) (const_int 16)))
6713 (set (match_operand:HI 0 "s_register_operand" "")
787f8210 6714 (match_dup 4))]
cffb2a26 6715 "TARGET_ARM"
c7597b5d 6716 "
6717 operands[2] = gen_reg_rtx (SImode);
6718 operands[3] = gen_reg_rtx (SImode);
787f8210 6719 operands[4] = gen_lowpart (HImode, operands[3]);
215b30b3 6720 "
6721)
b11cae9e 6722
a2f10574 6723;; Pattern to recognize insn generated default case above
f7fbdd4a 6724(define_insn "*movhi_insn_arch4"
e4585731 6725 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r,m,r")
6726 (match_operand:HI 1 "general_operand" "rIk,K,n,r,mi"))]
cffb2a26 6727 "TARGET_ARM
d7216193 6728 && arm_arch4 && !TARGET_HARD_FLOAT
85e02ccb 6729 && (register_operand (operands[0], HImode)
6730 || register_operand (operands[1], HImode))"
f7fbdd4a 6731 "@
6732 mov%?\\t%0, %1\\t%@ movhi
6733 mvn%?\\t%0, #%B1\\t%@ movhi
b1c1a101 6734 movw%?\\t%0, %L1\\t%@ movhi
3ef90e77 6735 strh%?\\t%1, %0\\t%@ movhi
6736 ldrh%?\\t%0, %1\\t%@ movhi"
65f68e55 6737 [(set_attr "predicable" "yes")
e4585731 6738 (set_attr "pool_range" "*,*,*,*,256")
6739 (set_attr "neg_pool_range" "*,*,*,*,244")
6740 (set_attr "arch" "*,*,v6t2,*,*")
65f68e55 6741 (set_attr_alternative "type"
6742 [(if_then_else (match_operand 1 "const_int_operand" "")
1aed5204 6743 (const_string "mov_imm" )
6744 (const_string "mov_reg"))
6745 (const_string "mvn_imm")
e4585731 6746 (const_string "mov_imm")
9f2c2a36 6747 (const_string "store_4")
6748 (const_string "load_4")])]
cffb2a26 6749)
f7fbdd4a 6750
f7fbdd4a 6751(define_insn "*movhi_bytes"
65f68e55 6752 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
5fd254ed 6753 (match_operand:HI 1 "arm_rhs_operand" "I,rk,K"))]
d7216193 6754 "TARGET_ARM && !TARGET_HARD_FLOAT"
25f7a26e 6755 "@
65f68e55 6756 mov%?\\t%0, %1\\t%@ movhi
25f7a26e 6757 mov%?\\t%0, %1\\t%@ movhi
0d66636f 6758 mvn%?\\t%0, #%B1\\t%@ movhi"
d2a518d1 6759 [(set_attr "predicable" "yes")
1aed5204 6760 (set_attr "type" "mov_imm,mov_reg,mvn_imm")]
0d66636f 6761)
837bb76e 6762
bc5c7e08 6763;; We use a DImode scratch because we may occasionally need an additional
6764;; temporary if the address isn't offsettable -- push_reload doesn't seem
6765;; to take any notice of the "o" constraints on reload_memory_operand operand.
d3373b54 6766(define_expand "reload_outhi"
cffb2a26 6767 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
215b30b3 6768 (match_operand:HI 1 "s_register_operand" "r")
6769 (match_operand:DI 2 "s_register_operand" "=&l")])]
cffb2a26 6770 "TARGET_EITHER"
6771 "if (TARGET_ARM)
6772 arm_reload_out_hi (operands);
6773 else
6774 thumb_reload_out_hi (operands);
d3373b54 6775 DONE;
cffb2a26 6776 "
6777)
d3373b54 6778
25f7a26e 6779(define_expand "reload_inhi"
6780 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
cffb2a26 6781 (match_operand:HI 1 "arm_reload_memory_operand" "o")
bc5c7e08 6782 (match_operand:DI 2 "s_register_operand" "=&r")])]
c1a66faf 6783 "TARGET_EITHER"
25f7a26e 6784 "
cffb2a26 6785 if (TARGET_ARM)
6786 arm_reload_in_hi (operands);
6787 else
6788 thumb_reload_out_hi (operands);
25f7a26e 6789 DONE;
6790")
6791
9c08d1fa 6792(define_expand "movqi"
6793 [(set (match_operand:QI 0 "general_operand" "")
6794 (match_operand:QI 1 "general_operand" ""))]
cffb2a26 6795 "TARGET_EITHER"
9c08d1fa 6796 "
6cffc037 6797 /* Everything except mem = const or mem = mem can be done easily */
0045890a 6798
e1ba4a27 6799 if (can_create_pseudo_p ())
cffb2a26 6800 {
0438d37f 6801 if (CONST_INT_P (operands[1]))
6cffc037 6802 {
6803 rtx reg = gen_reg_rtx (SImode);
6804
03770691 6805 /* For thumb we want an unsigned immediate, then we are more likely
6806 to be able to use a movs insn. */
6807 if (TARGET_THUMB)
6808 operands[1] = GEN_INT (INTVAL (operands[1]) & 255);
6809
6cffc037 6810 emit_insn (gen_movsi (reg, operands[1]));
6811 operands[1] = gen_lowpart (QImode, reg);
6812 }
cffb2a26 6813
6cffc037 6814 if (TARGET_THUMB)
6815 {
cffb2a26 6816 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 6817 happen if we are passed a SP (never OK for HImode/QImode) or
bc409cb4 6818 virtual register (also rejected as illegitimate for HImode/QImode)
6819 relative address. */
cffb2a26 6820 /* ??? This should perhaps be fixed elsewhere, for instance, in
6821 fixup_stack_1, by checking for other kinds of invalid addresses,
6822 e.g. a bare reference to a virtual register. This may confuse the
6823 alpha though, which must handle this case differently. */
0438d37f 6824 if (MEM_P (operands[0])
215b30b3 6825 && !memory_address_p (GET_MODE (operands[0]),
cffb2a26 6826 XEXP (operands[0], 0)))
537ffcfc 6827 operands[0]
6828 = replace_equiv_address (operands[0],
6829 copy_to_reg (XEXP (operands[0], 0)));
0438d37f 6830 if (MEM_P (operands[1])
215b30b3 6831 && !memory_address_p (GET_MODE (operands[1]),
cffb2a26 6832 XEXP (operands[1], 0)))
537ffcfc 6833 operands[1]
6834 = replace_equiv_address (operands[1],
6835 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 6836 }
6837
0438d37f 6838 if (MEM_P (operands[1]) && optimize > 0)
6cffc037 6839 {
6840 rtx reg = gen_reg_rtx (SImode);
6841
6842 emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
6843 operands[1] = gen_lowpart (QImode, reg);
6844 }
6845
0438d37f 6846 if (MEM_P (operands[0]))
6cffc037 6847 operands[1] = force_reg (QImode, operands[1]);
6848 }
6849 else if (TARGET_THUMB
0438d37f 6850 && CONST_INT_P (operands[1])
234f6557 6851 && !satisfies_constraint_I (operands[1]))
6cffc037 6852 {
674a8f0b 6853 /* Handle loading a large integer during reload. */
cffb2a26 6854
6cffc037 6855 /* Writing a constant to memory needs a scratch, which should
6856 be handled with SECONDARY_RELOADs. */
0438d37f 6857 gcc_assert (REG_P (operands[0]));
6cffc037 6858
6859 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
6860 emit_insn (gen_movsi (operands[0], operands[1]));
6861 DONE;
cffb2a26 6862 }
6863 "
6864)
b11cae9e 6865
cffb2a26 6866(define_insn "*arm_movqi_insn"
fd711051 6867 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,l,r,l,Uu,r,m")
490f62ca 6868 (match_operand:QI 1 "general_operand" "rk,rk,I,Py,K,Uu,l,Uh,r"))]
25f905c2 6869 "TARGET_32BIT
cffb2a26 6870 && ( register_operand (operands[0], QImode)
6871 || register_operand (operands[1], QImode))"
5565501b 6872 "@
fd711051 6873 mov%?\\t%0, %1
6874 mov%?\\t%0, %1
65f68e55 6875 mov%?\\t%0, %1
5565501b 6876 mov%?\\t%0, %1
6877 mvn%?\\t%0, #%B1
3ef90e77 6878 ldrb%?\\t%0, %1
6879 strb%?\\t%1, %0
6880 ldrb%?\\t%0, %1
6881 strb%?\\t%1, %0"
9f2c2a36 6882 [(set_attr "type" "mov_reg,mov_reg,mov_imm,mov_imm,mvn_imm,load_4,store_4,load_4,store_4")
a54e3e7b 6883 (set_attr "predicable" "yes")
5233bf6a 6884 (set_attr "predicable_short_it" "yes,yes,no,yes,no,no,no,no,no")
fd711051 6885 (set_attr "arch" "t2,any,any,t2,any,t2,t2,any,any")
6886 (set_attr "length" "2,4,4,2,4,2,2,4,4")]
cffb2a26 6887)
6888
9b8516be 6889;; HFmode moves
6890(define_expand "movhf"
6891 [(set (match_operand:HF 0 "general_operand" "")
6892 (match_operand:HF 1 "general_operand" ""))]
6893 "TARGET_EITHER"
6894 "
6895 if (TARGET_32BIT)
6896 {
0438d37f 6897 if (MEM_P (operands[0]))
9b8516be 6898 operands[1] = force_reg (HFmode, operands[1]);
6899 }
6900 else /* TARGET_THUMB1 */
6901 {
6902 if (can_create_pseudo_p ())
6903 {
0438d37f 6904 if (!REG_P (operands[0]))
9b8516be 6905 operands[1] = force_reg (HFmode, operands[1]);
6906 }
6907 }
6908 "
6909)
6910
6911(define_insn "*arm32_movhf"
6912 [(set (match_operand:HF 0 "nonimmediate_operand" "=r,m,r,r")
6913 (match_operand:HF 1 "general_operand" " m,r,r,F"))]
d7216193 6914 "TARGET_32BIT && !TARGET_HARD_FLOAT
9b8516be 6915 && ( s_register_operand (operands[0], HFmode)
6916 || s_register_operand (operands[1], HFmode))"
6917 "*
6918 switch (which_alternative)
6919 {
6920 case 0: /* ARM register from memory */
3ef90e77 6921 return \"ldrh%?\\t%0, %1\\t%@ __fp16\";
9b8516be 6922 case 1: /* memory from ARM register */
3ef90e77 6923 return \"strh%?\\t%1, %0\\t%@ __fp16\";
9b8516be 6924 case 2: /* ARM register from ARM register */
6925 return \"mov%?\\t%0, %1\\t%@ __fp16\";
6926 case 3: /* ARM register from constant */
6927 {
9b8516be 6928 long bits;
6929 rtx ops[4];
6930
945f7b03 6931 bits = real_to_target (NULL, CONST_DOUBLE_REAL_VALUE (operands[1]),
6932 HFmode);
9b8516be 6933 ops[0] = operands[0];
6934 ops[1] = GEN_INT (bits);
6935 ops[2] = GEN_INT (bits & 0xff00);
6936 ops[3] = GEN_INT (bits & 0x00ff);
6937
6938 if (arm_arch_thumb2)
6939 output_asm_insn (\"movw%?\\t%0, %1\", ops);
6940 else
6941 output_asm_insn (\"mov%?\\t%0, %2\;orr%?\\t%0, %0, %3\", ops);
6942 return \"\";
6943 }
6944 default:
6945 gcc_unreachable ();
6946 }
6947 "
6948 [(set_attr "conds" "unconditional")
9f2c2a36 6949 (set_attr "type" "load_4,store_4,mov_reg,multiple")
9b8516be 6950 (set_attr "length" "4,4,4,8")
8bdfd6ed 6951 (set_attr "predicable" "yes")]
9b8516be 6952)
6953
87b22bf7 6954(define_expand "movsf"
6955 [(set (match_operand:SF 0 "general_operand" "")
6956 (match_operand:SF 1 "general_operand" ""))]
cffb2a26 6957 "TARGET_EITHER"
87b22bf7 6958 "
25f905c2 6959 if (TARGET_32BIT)
cffb2a26 6960 {
0438d37f 6961 if (MEM_P (operands[0]))
cffb2a26 6962 operands[1] = force_reg (SFmode, operands[1]);
6963 }
25f905c2 6964 else /* TARGET_THUMB1 */
cffb2a26 6965 {
e1ba4a27 6966 if (can_create_pseudo_p ())
cffb2a26 6967 {
0438d37f 6968 if (!REG_P (operands[0]))
cffb2a26 6969 operands[1] = force_reg (SFmode, operands[1]);
6970 }
6971 }
581f16e5 6972
6973 /* Cannot load it directly, generate a load with clobber so that it can be
6974 loaded via GPR with MOV / MOVT. */
6975 if (arm_disable_literal_pool
6976 && (REG_P (operands[0]) || SUBREG_P (operands[0]))
6977 && CONST_DOUBLE_P (operands[1])
6978 && TARGET_HARD_FLOAT
6979 && !vfp3_const_double_rtx (operands[1]))
6980 {
6981 rtx clobreg = gen_reg_rtx (SFmode);
6982 emit_insn (gen_no_literal_pool_sf_immediate (operands[0], operands[1],
6983 clobreg));
6984 DONE;
6985 }
cffb2a26 6986 "
6987)
6988
03d440a6 6989;; Transform a floating-point move of a constant into a core register into
6990;; an SImode operation.
cffb2a26 6991(define_split
03d440a6 6992 [(set (match_operand:SF 0 "arm_general_register_operand" "")
cffb2a26 6993 (match_operand:SF 1 "immediate_operand" ""))]
339034d0 6994 "TARGET_EITHER
cffb2a26 6995 && reload_completed
0438d37f 6996 && CONST_DOUBLE_P (operands[1])"
cffb2a26 6997 [(set (match_dup 2) (match_dup 3))]
6998 "
6999 operands[2] = gen_lowpart (SImode, operands[0]);
7000 operands[3] = gen_lowpart (SImode, operands[1]);
7001 if (operands[2] == 0 || operands[3] == 0)
7002 FAIL;
215b30b3 7003 "
7004)
87b22bf7 7005
cffb2a26 7006(define_insn "*arm_movsf_soft_insn"
7007 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
7008 (match_operand:SF 1 "general_operand" "r,mE,r"))]
cde1623a 7009 "TARGET_32BIT
cffb2a26 7010 && TARGET_SOFT_FLOAT
0438d37f 7011 && (!MEM_P (operands[0])
215b30b3 7012 || register_operand (operands[1], SFmode))"
581f16e5 7013{
7014 switch (which_alternative)
7015 {
7016 case 0: return \"mov%?\\t%0, %1\";
7017 case 1:
7018 /* Cannot load it directly, split to load it via MOV / MOVT. */
7019 if (!MEM_P (operands[1]) && arm_disable_literal_pool)
7020 return \"#\";
7021 return \"ldr%?\\t%0, %1\\t%@ float\";
7022 case 2: return \"str%?\\t%1, %0\\t%@ float\";
7023 default: gcc_unreachable ();
7024 }
7025}
cde1623a 7026 [(set_attr "predicable" "yes")
9f2c2a36 7027 (set_attr "type" "mov_reg,load_4,store_4")
42e1de19 7028 (set_attr "arm_pool_range" "*,4096,*")
7029 (set_attr "thumb2_pool_range" "*,4094,*")
cde1623a 7030 (set_attr "arm_neg_pool_range" "*,4084,*")
7031 (set_attr "thumb2_neg_pool_range" "*,0,*")]
cffb2a26 7032)
7033
581f16e5 7034;; Splitter for the above.
7035(define_split
7036 [(set (match_operand:SF 0 "s_register_operand")
7037 (match_operand:SF 1 "const_double_operand"))]
7038 "arm_disable_literal_pool && TARGET_SOFT_FLOAT"
7039 [(const_int 0)]
7040{
7041 long buf;
7042 real_to_target (&buf, CONST_DOUBLE_REAL_VALUE (operands[1]), SFmode);
7043 rtx cst = gen_int_mode (buf, SImode);
7044 emit_move_insn (simplify_gen_subreg (SImode, operands[0], SFmode, 0), cst);
7045 DONE;
7046}
7047)
7048
9c08d1fa 7049(define_expand "movdf"
87b22bf7 7050 [(set (match_operand:DF 0 "general_operand" "")
7051 (match_operand:DF 1 "general_operand" ""))]
cffb2a26 7052 "TARGET_EITHER"
9c08d1fa 7053 "
25f905c2 7054 if (TARGET_32BIT)
cffb2a26 7055 {
0438d37f 7056 if (MEM_P (operands[0]))
cffb2a26 7057 operands[1] = force_reg (DFmode, operands[1]);
7058 }
7059 else /* TARGET_THUMB */
7060 {
e1ba4a27 7061 if (can_create_pseudo_p ())
cffb2a26 7062 {
0438d37f 7063 if (!REG_P (operands[0]))
cffb2a26 7064 operands[1] = force_reg (DFmode, operands[1]);
7065 }
7066 }
581f16e5 7067
7068 /* Cannot load it directly, generate a load with clobber so that it can be
7069 loaded via GPR with MOV / MOVT. */
7070 if (arm_disable_literal_pool
7071 && (REG_P (operands[0]) || SUBREG_P (operands[0]))
7072 && CONSTANT_P (operands[1])
7073 && TARGET_HARD_FLOAT
7074 && !arm_const_double_rtx (operands[1])
7075 && !(TARGET_VFP_DOUBLE && vfp3_const_double_rtx (operands[1])))
7076 {
7077 rtx clobreg = gen_reg_rtx (DFmode);
7078 emit_insn (gen_no_literal_pool_df_immediate (operands[0], operands[1],
7079 clobreg));
7080 DONE;
7081 }
cffb2a26 7082 "
7083)
b11cae9e 7084
9c08d1fa 7085;; Reloading a df mode value stored in integer regs to memory can require a
7086;; scratch reg.
7087(define_expand "reload_outdf"
cffb2a26 7088 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
87b22bf7 7089 (match_operand:DF 1 "s_register_operand" "r")
7090 (match_operand:SI 2 "s_register_operand" "=&r")]
06adefdc 7091 "TARGET_THUMB2"
87b22bf7 7092 "
215b30b3 7093 {
7094 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
f7fbdd4a 7095
215b30b3 7096 if (code == REG)
7097 operands[2] = XEXP (operands[0], 0);
7098 else if (code == POST_INC || code == PRE_DEC)
7099 {
7100 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
7101 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
7102 emit_insn (gen_movdi (operands[0], operands[1]));
7103 DONE;
7104 }
7105 else if (code == PRE_INC)
7106 {
7107 rtx reg = XEXP (XEXP (operands[0], 0), 0);
f7fbdd4a 7108
215b30b3 7109 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
7110 operands[2] = reg;
7111 }
7112 else if (code == POST_DEC)
7113 operands[2] = XEXP (XEXP (operands[0], 0), 0);
7114 else
7115 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
7116 XEXP (XEXP (operands[0], 0), 1)));
f7fbdd4a 7117
d1f9b275 7118 emit_insn (gen_rtx_SET (replace_equiv_address (operands[0], operands[2]),
215b30b3 7119 operands[1]));
f7fbdd4a 7120
215b30b3 7121 if (code == POST_DEC)
7122 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
7123
7124 DONE;
7125 }"
7126)
9c08d1fa 7127
9a1112d7 7128(define_insn "*movdf_soft_insn"
8f1c7041 7129 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,r,m")
7130 (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))]
cde1623a 7131 "TARGET_32BIT && TARGET_SOFT_FLOAT
b2778788 7132 && ( register_operand (operands[0], DFmode)
7133 || register_operand (operands[1], DFmode))"
d51f92df 7134 "*
7135 switch (which_alternative)
7136 {
7137 case 0:
7138 case 1:
7139 case 2:
7140 return \"#\";
581f16e5 7141 case 3:
7142 /* Cannot load it directly, split to load it via MOV / MOVT. */
7143 if (!MEM_P (operands[1]) && arm_disable_literal_pool)
7144 return \"#\";
7145 /* Fall through. */
d51f92df 7146 default:
26ff80c0 7147 return output_move_double (operands, true, NULL);
d51f92df 7148 }
7149 "
359a6e9f 7150 [(set_attr "length" "8,12,16,8,8")
9f2c2a36 7151 (set_attr "type" "multiple,multiple,multiple,load_8,store_8")
42e1de19 7152 (set_attr "arm_pool_range" "*,*,*,1020,*")
7153 (set_attr "thumb2_pool_range" "*,*,*,1018,*")
8848d797 7154 (set_attr "arm_neg_pool_range" "*,*,*,1004,*")
cde1623a 7155 (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
cffb2a26 7156)
581f16e5 7157
7158;; Splitter for the above.
7159(define_split
7160 [(set (match_operand:DF 0 "s_register_operand")
7161 (match_operand:DF 1 "const_double_operand"))]
7162 "arm_disable_literal_pool && TARGET_SOFT_FLOAT"
7163 [(const_int 0)]
7164{
7165 long buf[2];
7166 int order = BYTES_BIG_ENDIAN ? 1 : 0;
7167 real_to_target (buf, CONST_DOUBLE_REAL_VALUE (operands[1]), DFmode);
7168 unsigned HOST_WIDE_INT ival = zext_hwi (buf[order], 32);
7169 ival |= (zext_hwi (buf[1 - order], 32) << 32);
7170 rtx cst = gen_int_mode (ival, DImode);
7171 emit_move_insn (simplify_gen_subreg (DImode, operands[0], DFmode, 0), cst);
7172 DONE;
7173}
7174)
b11cae9e 7175\f
b11cae9e 7176
9c08d1fa 7177;; load- and store-multiple insns
7178;; The arm can load/store any set of registers, provided that they are in
320ea44d 7179;; ascending order, but these expanders assume a contiguous set.
b11cae9e 7180
9c08d1fa 7181(define_expand "load_multiple"
7182 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
7183 (match_operand:SI 1 "" ""))
7184 (use (match_operand:SI 2 "" ""))])]
25f905c2 7185 "TARGET_32BIT"
9580c25f 7186{
7187 HOST_WIDE_INT offset = 0;
7188
bd5b4116 7189 /* Support only fixed point registers. */
0438d37f 7190 if (!CONST_INT_P (operands[2])
6e628811 7191 || INTVAL (operands[2]) > MAX_LDM_STM_OPS
9c08d1fa 7192 || INTVAL (operands[2]) < 2
0438d37f 7193 || !MEM_P (operands[1])
7194 || !REG_P (operands[0])
bd5b4116 7195 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
7196 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 7197 FAIL;
7198
7199 operands[3]
320ea44d 7200 = arm_gen_load_multiple (arm_regs_in_sequence + REGNO (operands[0]),
7201 INTVAL (operands[2]),
f082f1c4 7202 force_reg (SImode, XEXP (operands[1], 0)),
320ea44d 7203 FALSE, operands[1], &offset);
9580c25f 7204})
b11cae9e 7205
9c08d1fa 7206(define_expand "store_multiple"
7207 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
7208 (match_operand:SI 1 "" ""))
7209 (use (match_operand:SI 2 "" ""))])]
25f905c2 7210 "TARGET_32BIT"
9580c25f 7211{
7212 HOST_WIDE_INT offset = 0;
7213
674a8f0b 7214 /* Support only fixed point registers. */
0438d37f 7215 if (!CONST_INT_P (operands[2])
6e628811 7216 || INTVAL (operands[2]) > MAX_LDM_STM_OPS
9c08d1fa 7217 || INTVAL (operands[2]) < 2
0438d37f 7218 || !REG_P (operands[1])
7219 || !MEM_P (operands[0])
bd5b4116 7220 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
7221 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 7222 FAIL;
7223
7224 operands[3]
320ea44d 7225 = arm_gen_store_multiple (arm_regs_in_sequence + REGNO (operands[1]),
7226 INTVAL (operands[2]),
f082f1c4 7227 force_reg (SImode, XEXP (operands[0], 0)),
320ea44d 7228 FALSE, operands[0], &offset);
9580c25f 7229})
b11cae9e 7230
9c08d1fa 7231
e34ebfca 7232(define_expand "setmemsi"
7233 [(match_operand:BLK 0 "general_operand" "")
7234 (match_operand:SI 1 "const_int_operand" "")
7235 (match_operand:SI 2 "const_int_operand" "")
7236 (match_operand:SI 3 "const_int_operand" "")]
7237 "TARGET_32BIT"
7238{
7239 if (arm_gen_setmem (operands))
7240 DONE;
7241
7242 FAIL;
7243})
7244
7245
9c08d1fa 7246;; Move a block of memory if it is word aligned and MORE than 2 words long.
7247;; We could let this apply for blocks of less than this, but it clobbers so
7248;; many registers that there is then probably a better way.
7249
008c057d 7250(define_expand "movmemqi"
34191dd1 7251 [(match_operand:BLK 0 "general_operand" "")
7252 (match_operand:BLK 1 "general_operand" "")
7253 (match_operand:SI 2 "const_int_operand" "")
7254 (match_operand:SI 3 "const_int_operand" "")]
ae51a965 7255 ""
9c08d1fa 7256 "
25f905c2 7257 if (TARGET_32BIT)
cffb2a26 7258 {
ae51a965 7259 if (TARGET_LDRD && current_tune->prefer_ldrd_strd
7260 && !optimize_function_for_size_p (cfun))
7261 {
7262 if (gen_movmem_ldrd_strd (operands))
7263 DONE;
7264 FAIL;
7265 }
7266
008c057d 7267 if (arm_gen_movmemqi (operands))
cffb2a26 7268 DONE;
7269 FAIL;
7270 }
25f905c2 7271 else /* TARGET_THUMB1 */
cffb2a26 7272 {
7273 if ( INTVAL (operands[3]) != 4
7274 || INTVAL (operands[2]) > 48)
7275 FAIL;
7276
008c057d 7277 thumb_expand_movmemqi (operands);
cffb2a26 7278 DONE;
7279 }
7280 "
7281)
9c08d1fa 7282\f
b11cae9e 7283
341940e8 7284;; Compare & branch insns
8d232dc7 7285;; The range calculations are based as follows:
341940e8 7286;; For forward branches, the address calculation returns the address of
7287;; the next instruction. This is 2 beyond the branch instruction.
7288;; For backward branches, the address calculation returns the address of
7289;; the first instruction in this pattern (cmp). This is 2 before the branch
7290;; instruction for the shortest sequence, and 4 before the branch instruction
7291;; if we have to jump around an unconditional branch.
7292;; To the basic branch range the PC offset must be added (this is +4).
7293;; So for forward branches we have
7294;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
7295;; And for backward branches we have
7296;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
7297;;
7298;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
7299;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
cffb2a26 7300
aeac46d4 7301(define_expand "cbranchsi4"
7302 [(set (pc) (if_then_else
aa06947a 7303 (match_operator 0 "expandable_comparison_operator"
aeac46d4 7304 [(match_operand:SI 1 "s_register_operand" "")
7305 (match_operand:SI 2 "nonmemory_operand" "")])
7306 (label_ref (match_operand 3 "" ""))
7307 (pc)))]
f9aa4160 7308 "TARGET_EITHER"
aeac46d4 7309 "
74f4459c 7310 if (!TARGET_THUMB1)
7311 {
f9aa4160 7312 if (!arm_validize_comparison (&operands[0], &operands[1], &operands[2]))
7313 FAIL;
74f4459c 7314 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
7315 operands[3]));
7316 DONE;
7317 }
25f905c2 7318 if (thumb1_cmpneg_operand (operands[2], SImode))
aeac46d4 7319 {
7320 emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
7321 operands[3], operands[0]));
7322 DONE;
7323 }
25f905c2 7324 if (!thumb1_cmp_operand (operands[2], SImode))
aeac46d4 7325 operands[2] = force_reg (SImode, operands[2]);
7326 ")
7327
74f4459c 7328(define_expand "cbranchsf4"
7329 [(set (pc) (if_then_else
aa06947a 7330 (match_operator 0 "expandable_comparison_operator"
74f4459c 7331 [(match_operand:SF 1 "s_register_operand" "")
d7216193 7332 (match_operand:SF 2 "vfp_compare_operand" "")])
74f4459c 7333 (label_ref (match_operand 3 "" ""))
7334 (pc)))]
7335 "TARGET_32BIT && TARGET_HARD_FLOAT"
7336 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
7337 operands[3])); DONE;"
7338)
7339
7340(define_expand "cbranchdf4"
7341 [(set (pc) (if_then_else
aa06947a 7342 (match_operator 0 "expandable_comparison_operator"
74f4459c 7343 [(match_operand:DF 1 "s_register_operand" "")
d7216193 7344 (match_operand:DF 2 "vfp_compare_operand" "")])
74f4459c 7345 (label_ref (match_operand 3 "" ""))
7346 (pc)))]
a50d7267 7347 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
74f4459c 7348 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
7349 operands[3])); DONE;"
7350)
7351
74f4459c 7352(define_expand "cbranchdi4"
7353 [(set (pc) (if_then_else
aa06947a 7354 (match_operator 0 "expandable_comparison_operator"
b8eae306 7355 [(match_operand:DI 1 "s_register_operand" "")
a8045a4f 7356 (match_operand:DI 2 "cmpdi_operand" "")])
74f4459c 7357 (label_ref (match_operand 3 "" ""))
7358 (pc)))]
a8045a4f 7359 "TARGET_32BIT"
7360 "{
0438d37f 7361 if (!arm_validize_comparison (&operands[0], &operands[1], &operands[2]))
f9aa4160 7362 FAIL;
7363 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
a8045a4f 7364 operands[3]));
7365 DONE;
7366 }"
74f4459c 7367)
7368
9c08d1fa 7369;; Comparison and test insns
7370
cffb2a26 7371(define_insn "*arm_cmpsi_insn"
bd5b4116 7372 [(set (reg:CC CC_REGNUM)
f9f234ec 7373 (compare:CC (match_operand:SI 0 "s_register_operand" "l,r,r,r,r")
7374 (match_operand:SI 1 "arm_add_operand" "Py,r,r,I,L")))]
25f905c2 7375 "TARGET_32BIT"
5565501b 7376 "@
a6864a24 7377 cmp%?\\t%0, %1
7378 cmp%?\\t%0, %1
aea4c774 7379 cmp%?\\t%0, %1
f9f234ec 7380 cmp%?\\t%0, %1
aea4c774 7381 cmn%?\\t%0, #%n1"
a6864a24 7382 [(set_attr "conds" "set")
f9f234ec 7383 (set_attr "arch" "t2,t2,any,any,any")
7384 (set_attr "length" "2,2,4,4,4")
65f68e55 7385 (set_attr "predicable" "yes")
f9f234ec 7386 (set_attr "predicable_short_it" "yes,yes,yes,no,no")
112eda6f 7387 (set_attr "type" "alus_imm,alus_sreg,alus_sreg,alus_imm,alus_imm")]
cffb2a26 7388)
b11cae9e 7389
d5d4dc8d 7390(define_insn "*cmpsi_shiftsi"
bd5b4116 7391 [(set (reg:CC CC_REGNUM)
d82e788e 7392 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r,r")
cffb2a26 7393 (match_operator:SI 3 "shift_operator"
d82e788e 7394 [(match_operand:SI 1 "s_register_operand" "r,r,r")
7395 (match_operand:SI 2 "shift_amount_operand" "M,r,M")])))]
d5d4dc8d 7396 "TARGET_32BIT"
f9f234ec 7397 "cmp\\t%0, %1%S3"
344495ea 7398 [(set_attr "conds" "set")
331beb1a 7399 (set_attr "shift" "1")
d82e788e 7400 (set_attr "arch" "32,a,a")
282b4c75 7401 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
b11cae9e 7402
d5d4dc8d 7403(define_insn "*cmpsi_shiftsi_swp"
bd5b4116 7404 [(set (reg:CC_SWP CC_REGNUM)
aea4c774 7405 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
d82e788e 7406 [(match_operand:SI 1 "s_register_operand" "r,r,r")
7407 (match_operand:SI 2 "shift_amount_operand" "M,r,M")])
7408 (match_operand:SI 0 "s_register_operand" "r,r,r")))]
d5d4dc8d 7409 "TARGET_32BIT"
aea4c774 7410 "cmp%?\\t%0, %1%S3"
344495ea 7411 [(set_attr "conds" "set")
331beb1a 7412 (set_attr "shift" "1")
d82e788e 7413 (set_attr "arch" "32,a,a")
282b4c75 7414 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
b11cae9e 7415
25f905c2 7416(define_insn "*arm_cmpsi_negshiftsi_si"
aed179ae 7417 [(set (reg:CC_Z CC_REGNUM)
7418 (compare:CC_Z
7419 (neg:SI (match_operator:SI 1 "shift_operator"
7420 [(match_operand:SI 2 "s_register_operand" "r")
7421 (match_operand:SI 3 "reg_or_int_operand" "rM")]))
7422 (match_operand:SI 0 "s_register_operand" "r")))]
cffb2a26 7423 "TARGET_ARM"
aed179ae 7424 "cmn%?\\t%0, %2%S1"
344495ea 7425 [(set_attr "conds" "set")
aed179ae 7426 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
d82e788e 7427 (const_string "alus_shift_imm")
7428 (const_string "alus_shift_reg")))
596e5e8f 7429 (set_attr "predicable" "yes")]
0d66636f 7430)
b11cae9e 7431
a8045a4f 7432;; DImode comparisons. The generic code generates branches that
f4d3c071 7433;; if-conversion cannot reduce to a conditional compare, so we do
a8045a4f 7434;; that directly.
7435
ba6a3b2f 7436(define_insn_and_split "*arm_cmpdi_insn"
a8045a4f 7437 [(set (reg:CC_NCV CC_REGNUM)
7438 (compare:CC_NCV (match_operand:DI 0 "s_register_operand" "r")
7439 (match_operand:DI 1 "arm_di_operand" "rDi")))
7440 (clobber (match_scratch:SI 2 "=r"))]
b805622c 7441 "TARGET_32BIT"
ba6a3b2f 7442 "#" ; "cmp\\t%Q0, %Q1\;sbcs\\t%2, %R0, %R1"
7443 "&& reload_completed"
7444 [(set (reg:CC CC_REGNUM)
7445 (compare:CC (match_dup 0) (match_dup 1)))
7446 (parallel [(set (reg:CC CC_REGNUM)
7447 (compare:CC (match_dup 3) (match_dup 4)))
7448 (set (match_dup 2)
7449 (minus:SI (match_dup 5)
16a3cf9c 7450 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))])]
ba6a3b2f 7451 {
7452 operands[3] = gen_highpart (SImode, operands[0]);
7453 operands[0] = gen_lowpart (SImode, operands[0]);
7454 if (CONST_INT_P (operands[1]))
7455 {
16a3cf9c 7456 operands[4] = gen_highpart_mode (SImode, DImode, operands[1]);
7457 if (operands[4] == const0_rtx)
7458 operands[5] = operands[3];
7459 else
7460 operands[5] = gen_rtx_PLUS (SImode, operands[3],
7461 gen_int_mode (-UINTVAL (operands[4]),
7462 SImode));
ba6a3b2f 7463 }
7464 else
7465 {
7466 operands[4] = gen_highpart (SImode, operands[1]);
7467 operands[5] = gen_rtx_MINUS (SImode, operands[3], operands[4]);
7468 }
7469 operands[1] = gen_lowpart (SImode, operands[1]);
7470 operands[2] = gen_lowpart (SImode, operands[2]);
7471 }
a8045a4f 7472 [(set_attr "conds" "set")
1b7da4ac 7473 (set_attr "length" "8")
7474 (set_attr "type" "multiple")]
a8045a4f 7475)
7476
ba6a3b2f 7477(define_insn_and_split "*arm_cmpdi_unsigned"
a8045a4f 7478 [(set (reg:CC_CZ CC_REGNUM)
1a86364b 7479 (compare:CC_CZ (match_operand:DI 0 "s_register_operand" "l,r,r,r")
7480 (match_operand:DI 1 "arm_di_operand" "Py,r,Di,rDi")))]
7c36fe71 7481
48a98053 7482 "TARGET_32BIT"
ba6a3b2f 7483 "#" ; "cmp\\t%R0, %R1\;it eq\;cmpeq\\t%Q0, %Q1"
7484 "&& reload_completed"
7485 [(set (reg:CC CC_REGNUM)
7486 (compare:CC (match_dup 2) (match_dup 3)))
7487 (cond_exec (eq:SI (reg:CC CC_REGNUM) (const_int 0))
7488 (set (reg:CC CC_REGNUM)
7489 (compare:CC (match_dup 0) (match_dup 1))))]
7490 {
7491 operands[2] = gen_highpart (SImode, operands[0]);
7492 operands[0] = gen_lowpart (SImode, operands[0]);
7493 if (CONST_INT_P (operands[1]))
7494 operands[3] = gen_highpart_mode (SImode, DImode, operands[1]);
7495 else
7496 operands[3] = gen_highpart (SImode, operands[1]);
7497 operands[1] = gen_lowpart (SImode, operands[1]);
7498 }
a8045a4f 7499 [(set_attr "conds" "set")
8bdfd6ed 7500 (set_attr "enabled_for_short_it" "yes,yes,no,*")
1a86364b 7501 (set_attr "arch" "t2,t2,t2,a")
7502 (set_attr "length" "6,6,10,8")
1b7da4ac 7503 (set_attr "type" "multiple")]
a8045a4f 7504)
7505
7506(define_insn "*arm_cmpdi_zero"
7507 [(set (reg:CC_Z CC_REGNUM)
7508 (compare:CC_Z (match_operand:DI 0 "s_register_operand" "r")
7509 (const_int 0)))
7510 (clobber (match_scratch:SI 1 "=r"))]
7511 "TARGET_32BIT"
3ef90e77 7512 "orrs%?\\t%1, %Q0, %R0"
1b7da4ac 7513 [(set_attr "conds" "set")
7514 (set_attr "type" "logics_reg")]
a8045a4f 7515)
7516
9c08d1fa 7517; This insn allows redundant compares to be removed by cse, nothing should
7518; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
7519; is deleted later on. The match_dup will match the mode here, so that
7520; mode changes of the condition codes aren't lost by this even though we don't
7521; specify what they are.
7522
8a18b90c 7523(define_insn "*deleted_compare"
9c08d1fa 7524 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
25f905c2 7525 "TARGET_32BIT"
40dbec34 7526 "\\t%@ deleted compare"
cffb2a26 7527 [(set_attr "conds" "set")
1b7da4ac 7528 (set_attr "length" "0")
7529 (set_attr "type" "no_insn")]
cffb2a26 7530)
9c08d1fa 7531
7532\f
7533;; Conditional branch insns
7534
74f4459c 7535(define_expand "cbranch_cc"
9c08d1fa 7536 [(set (pc)
74f4459c 7537 (if_then_else (match_operator 0 "" [(match_operand 1 "" "")
7538 (match_operand 2 "" "")])
7539 (label_ref (match_operand 3 "" ""))
9c08d1fa 7540 (pc)))]
25f905c2 7541 "TARGET_32BIT"
74f4459c 7542 "operands[1] = arm_gen_compare_reg (GET_CODE (operands[0]),
e1b93706 7543 operands[1], operands[2], NULL_RTX);
74f4459c 7544 operands[2] = const0_rtx;"
8fa3ba89 7545)
7546
7547;;
7548;; Patterns to match conditional branch insns.
7549;;
7550
ffcc986d 7551(define_insn "arm_cond_branch"
9c08d1fa 7552 [(set (pc)
8fa3ba89 7553 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 7554 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 7555 (label_ref (match_operand 0 "" ""))
7556 (pc)))]
25f905c2 7557 "TARGET_32BIT"
d75350ce 7558 "*
9c08d1fa 7559 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 7560 {
7561 arm_ccfsm_state += 2;
7562 return \"\";
7563 }
e2348bcb 7564 return \"b%d1\\t%l0\";
cffb2a26 7565 "
a2cd141b 7566 [(set_attr "conds" "use")
a6864a24 7567 (set_attr "type" "branch")
7568 (set (attr "length")
7569 (if_then_else
0bf497f5 7570 (and (match_test "TARGET_THUMB2")
a6864a24 7571 (and (ge (minus (match_dup 0) (pc)) (const_int -250))
7572 (le (minus (match_dup 0) (pc)) (const_int 256))))
7573 (const_int 2)
7574 (const_int 4)))]
cffb2a26 7575)
d75350ce 7576
cffb2a26 7577(define_insn "*arm_cond_branch_reversed"
9c08d1fa 7578 [(set (pc)
8fa3ba89 7579 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 7580 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 7581 (pc)
7582 (label_ref (match_operand 0 "" ""))))]
25f905c2 7583 "TARGET_32BIT"
d75350ce 7584 "*
9c08d1fa 7585 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 7586 {
7587 arm_ccfsm_state += 2;
7588 return \"\";
7589 }
e2348bcb 7590 return \"b%D1\\t%l0\";
cffb2a26 7591 "
a2cd141b 7592 [(set_attr "conds" "use")
a6864a24 7593 (set_attr "type" "branch")
7594 (set (attr "length")
7595 (if_then_else
0bf497f5 7596 (and (match_test "TARGET_THUMB2")
a6864a24 7597 (and (ge (minus (match_dup 0) (pc)) (const_int -250))
7598 (le (minus (match_dup 0) (pc)) (const_int 256))))
7599 (const_int 2)
7600 (const_int 4)))]
cffb2a26 7601)
7602
b11cae9e 7603\f
9c08d1fa 7604
7605; scc insns
7606
74f4459c 7607(define_expand "cstore_cc"
7db9af5d 7608 [(set (match_operand:SI 0 "s_register_operand" "")
74f4459c 7609 (match_operator:SI 1 "" [(match_operand 2 "" "")
7610 (match_operand 3 "" "")]))]
25f905c2 7611 "TARGET_32BIT"
74f4459c 7612 "operands[2] = arm_gen_compare_reg (GET_CODE (operands[1]),
e1b93706 7613 operands[2], operands[3], NULL_RTX);
74f4459c 7614 operands[3] = const0_rtx;"
8fa3ba89 7615)
7616
a3b84066 7617(define_insn_and_split "*mov_scc"
9c08d1fa 7618 [(set (match_operand:SI 0 "s_register_operand" "=r")
ff74dd54 7619 (match_operator:SI 1 "arm_comparison_operator_mode"
8a18b90c 7620 [(match_operand 2 "cc_register" "") (const_int 0)]))]
cffb2a26 7621 "TARGET_ARM"
a3b84066 7622 "#" ; "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
7623 "TARGET_ARM"
7624 [(set (match_dup 0)
7625 (if_then_else:SI (match_dup 1)
7626 (const_int 1)
7627 (const_int 0)))]
7628 ""
cffb2a26 7629 [(set_attr "conds" "use")
1b7da4ac 7630 (set_attr "length" "8")
7631 (set_attr "type" "multiple")]
cffb2a26 7632)
9c08d1fa 7633
a3b84066 7634(define_insn_and_split "*mov_negscc"
9c08d1fa 7635 [(set (match_operand:SI 0 "s_register_operand" "=r")
ff74dd54 7636 (neg:SI (match_operator:SI 1 "arm_comparison_operator_mode"
8a18b90c 7637 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 7638 "TARGET_ARM"
a3b84066 7639 "#" ; "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
7640 "TARGET_ARM"
7641 [(set (match_dup 0)
7642 (if_then_else:SI (match_dup 1)
7643 (match_dup 3)
7644 (const_int 0)))]
7645 {
7646 operands[3] = GEN_INT (~0);
7647 }
cffb2a26 7648 [(set_attr "conds" "use")
1b7da4ac 7649 (set_attr "length" "8")
7650 (set_attr "type" "multiple")]
cffb2a26 7651)
9c08d1fa 7652
a3b84066 7653(define_insn_and_split "*mov_notscc"
9c08d1fa 7654 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7655 (not:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7656 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 7657 "TARGET_ARM"
a3b84066 7658 "#" ; "mvn%D1\\t%0, #0\;mvn%d1\\t%0, #1"
7659 "TARGET_ARM"
7660 [(set (match_dup 0)
7661 (if_then_else:SI (match_dup 1)
7662 (match_dup 3)
7663 (match_dup 4)))]
7664 {
7665 operands[3] = GEN_INT (~1);
7666 operands[4] = GEN_INT (~0);
7667 }
cffb2a26 7668 [(set_attr "conds" "use")
1b7da4ac 7669 (set_attr "length" "8")
7670 (set_attr "type" "multiple")]
cffb2a26 7671)
9c08d1fa 7672
595d88b5 7673(define_expand "cstoresi4"
7674 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 7675 (match_operator:SI 1 "expandable_comparison_operator"
595d88b5 7676 [(match_operand:SI 2 "s_register_operand" "")
7677 (match_operand:SI 3 "reg_or_int_operand" "")]))]
74f4459c 7678 "TARGET_32BIT || TARGET_THUMB1"
595d88b5 7679 "{
7680 rtx op3, scratch, scratch2;
7681
74f4459c 7682 if (!TARGET_THUMB1)
7683 {
7684 if (!arm_add_operand (operands[3], SImode))
7685 operands[3] = force_reg (SImode, operands[3]);
7686 emit_insn (gen_cstore_cc (operands[0], operands[1],
7687 operands[2], operands[3]));
7688 DONE;
7689 }
7690
595d88b5 7691 if (operands[3] == const0_rtx)
7692 {
7693 switch (GET_CODE (operands[1]))
7694 {
7695 case EQ:
25f905c2 7696 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], operands[2]));
595d88b5 7697 break;
7698
7699 case NE:
25f905c2 7700 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], operands[2]));
595d88b5 7701 break;
7702
7703 case LE:
7704 scratch = expand_binop (SImode, add_optab, operands[2], constm1_rtx,
7705 NULL_RTX, 0, OPTAB_WIDEN);
7706 scratch = expand_binop (SImode, ior_optab, operands[2], scratch,
7707 NULL_RTX, 0, OPTAB_WIDEN);
7708 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7709 operands[0], 1, OPTAB_WIDEN);
7710 break;
7711
7712 case GE:
7713 scratch = expand_unop (SImode, one_cmpl_optab, operands[2],
7714 NULL_RTX, 1);
7715 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7716 NULL_RTX, 1, OPTAB_WIDEN);
7717 break;
7718
7719 case GT:
7720 scratch = expand_binop (SImode, ashr_optab, operands[2],
7721 GEN_INT (31), NULL_RTX, 0, OPTAB_WIDEN);
7722 scratch = expand_binop (SImode, sub_optab, scratch, operands[2],
7723 NULL_RTX, 0, OPTAB_WIDEN);
7724 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31), operands[0],
7725 0, OPTAB_WIDEN);
7726 break;
7727
7728 /* LT is handled by generic code. No need for unsigned with 0. */
7729 default:
7730 FAIL;
7731 }
7732 DONE;
7733 }
7734
7735 switch (GET_CODE (operands[1]))
7736 {
7737 case EQ:
7738 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7739 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7740 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], scratch));
595d88b5 7741 break;
7742
7743 case NE:
7744 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7745 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7746 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], scratch));
595d88b5 7747 break;
7748
7749 case LE:
7750 op3 = force_reg (SImode, operands[3]);
7751
7752 scratch = expand_binop (SImode, lshr_optab, operands[2], GEN_INT (31),
7753 NULL_RTX, 1, OPTAB_WIDEN);
7754 scratch2 = expand_binop (SImode, ashr_optab, op3, GEN_INT (31),
7755 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7756 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
595d88b5 7757 op3, operands[2]));
7758 break;
7759
7760 case GE:
7761 op3 = operands[3];
25f905c2 7762 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7763 op3 = force_reg (SImode, op3);
7764 scratch = expand_binop (SImode, ashr_optab, operands[2], GEN_INT (31),
7765 NULL_RTX, 0, OPTAB_WIDEN);
7766 scratch2 = expand_binop (SImode, lshr_optab, op3, GEN_INT (31),
7767 NULL_RTX, 1, OPTAB_WIDEN);
25f905c2 7768 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
595d88b5 7769 operands[2], op3));
7770 break;
7771
7772 case LEU:
7773 op3 = force_reg (SImode, operands[3]);
7774 scratch = force_reg (SImode, const0_rtx);
25f905c2 7775 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
595d88b5 7776 op3, operands[2]));
7777 break;
7778
7779 case GEU:
7780 op3 = operands[3];
25f905c2 7781 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7782 op3 = force_reg (SImode, op3);
7783 scratch = force_reg (SImode, const0_rtx);
25f905c2 7784 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
595d88b5 7785 operands[2], op3));
7786 break;
7787
7788 case LTU:
7789 op3 = operands[3];
25f905c2 7790 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7791 op3 = force_reg (SImode, op3);
7792 scratch = gen_reg_rtx (SImode);
408b7ae5 7793 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], operands[2], op3));
595d88b5 7794 break;
7795
7796 case GTU:
7797 op3 = force_reg (SImode, operands[3]);
7798 scratch = gen_reg_rtx (SImode);
408b7ae5 7799 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], op3, operands[2]));
595d88b5 7800 break;
7801
7802 /* No good sequences for GT, LT. */
7803 default:
7804 FAIL;
7805 }
7806 DONE;
7807}")
7808
9854d864 7809(define_expand "cstorehf4"
7810 [(set (match_operand:SI 0 "s_register_operand")
7811 (match_operator:SI 1 "expandable_comparison_operator"
7812 [(match_operand:HF 2 "s_register_operand")
d7216193 7813 (match_operand:HF 3 "vfp_compare_operand")]))]
9854d864 7814 "TARGET_VFP_FP16INST"
7815 {
7816 if (!arm_validize_comparison (&operands[1],
7817 &operands[2],
7818 &operands[3]))
7819 FAIL;
7820
7821 emit_insn (gen_cstore_cc (operands[0], operands[1],
7822 operands[2], operands[3]));
7823 DONE;
7824 }
7825)
7826
74f4459c 7827(define_expand "cstoresf4"
7828 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 7829 (match_operator:SI 1 "expandable_comparison_operator"
74f4459c 7830 [(match_operand:SF 2 "s_register_operand" "")
d7216193 7831 (match_operand:SF 3 "vfp_compare_operand" "")]))]
74f4459c 7832 "TARGET_32BIT && TARGET_HARD_FLOAT"
7833 "emit_insn (gen_cstore_cc (operands[0], operands[1],
7834 operands[2], operands[3])); DONE;"
7835)
7836
7837(define_expand "cstoredf4"
7838 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 7839 (match_operator:SI 1 "expandable_comparison_operator"
74f4459c 7840 [(match_operand:DF 2 "s_register_operand" "")
d7216193 7841 (match_operand:DF 3 "vfp_compare_operand" "")]))]
d63ed457 7842 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
74f4459c 7843 "emit_insn (gen_cstore_cc (operands[0], operands[1],
7844 operands[2], operands[3])); DONE;"
7845)
7846
74f4459c 7847(define_expand "cstoredi4"
7848 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 7849 (match_operator:SI 1 "expandable_comparison_operator"
b8eae306 7850 [(match_operand:DI 2 "s_register_operand" "")
a8045a4f 7851 (match_operand:DI 3 "cmpdi_operand" "")]))]
7852 "TARGET_32BIT"
7853 "{
f9aa4160 7854 if (!arm_validize_comparison (&operands[1],
7855 &operands[2],
7856 &operands[3]))
7857 FAIL;
7858 emit_insn (gen_cstore_cc (operands[0], operands[1], operands[2],
a8045a4f 7859 operands[3]));
7860 DONE;
7861 }"
74f4459c 7862)
7863
9c08d1fa 7864\f
39b5e676 7865;; Conditional move insns
7866
7867(define_expand "movsicc"
8a18b90c 7868 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 7869 (if_then_else:SI (match_operand 1 "expandable_comparison_operator" "")
aea4c774 7870 (match_operand:SI 2 "arm_not_operand" "")
8a18b90c 7871 (match_operand:SI 3 "arm_not_operand" "")))]
25f905c2 7872 "TARGET_32BIT"
39b5e676 7873 "
215b30b3 7874 {
f9aa4160 7875 enum rtx_code code;
278b301d 7876 rtx ccreg;
7877
f9aa4160 7878 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
9854d864 7879 &XEXP (operands[1], 1)))
278b301d 7880 FAIL;
9854d864 7881
7882 code = GET_CODE (operands[1]);
7883 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
7884 XEXP (operands[1], 1), NULL_RTX);
7885 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7886 }"
7887)
7888
7889(define_expand "movhfcc"
7890 [(set (match_operand:HF 0 "s_register_operand")
7891 (if_then_else:HF (match_operand 1 "arm_cond_move_operator")
7892 (match_operand:HF 2 "s_register_operand")
7893 (match_operand:HF 3 "s_register_operand")))]
7894 "TARGET_VFP_FP16INST"
7895 "
7896 {
7897 enum rtx_code code = GET_CODE (operands[1]);
7898 rtx ccreg;
7899
7900 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
7901 &XEXP (operands[1], 1)))
7902 FAIL;
7903
f9aa4160 7904 code = GET_CODE (operands[1]);
74f4459c 7905 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
e1b93706 7906 XEXP (operands[1], 1), NULL_RTX);
29bb088d 7907 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7908 }"
7909)
39b5e676 7910
7911(define_expand "movsfcc"
8a18b90c 7912 [(set (match_operand:SF 0 "s_register_operand" "")
4df97ffc 7913 (if_then_else:SF (match_operand 1 "arm_cond_move_operator" "")
8a18b90c 7914 (match_operand:SF 2 "s_register_operand" "")
d86c91f6 7915 (match_operand:SF 3 "s_register_operand" "")))]
19f6bf8d 7916 "TARGET_32BIT && TARGET_HARD_FLOAT"
39b5e676 7917 "
215b30b3 7918 {
7919 enum rtx_code code = GET_CODE (operands[1]);
7920 rtx ccreg;
f082f1c4 7921
9854d864 7922 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
f9aa4160 7923 &XEXP (operands[1], 1)))
7924 FAIL;
39b5e676 7925
f9aa4160 7926 code = GET_CODE (operands[1]);
74f4459c 7927 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
e1b93706 7928 XEXP (operands[1], 1), NULL_RTX);
29bb088d 7929 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7930 }"
7931)
39b5e676 7932
7933(define_expand "movdfcc"
8a18b90c 7934 [(set (match_operand:DF 0 "s_register_operand" "")
4df97ffc 7935 (if_then_else:DF (match_operand 1 "arm_cond_move_operator" "")
8a18b90c 7936 (match_operand:DF 2 "s_register_operand" "")
d86c91f6 7937 (match_operand:DF 3 "s_register_operand" "")))]
994606f8 7938 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
39b5e676 7939 "
215b30b3 7940 {
7941 enum rtx_code code = GET_CODE (operands[1]);
278b301d 7942 rtx ccreg;
39b5e676 7943
f9aa4160 7944 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
7945 &XEXP (operands[1], 1)))
7946 FAIL;
7947 code = GET_CODE (operands[1]);
74f4459c 7948 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
e1b93706 7949 XEXP (operands[1], 1), NULL_RTX);
29bb088d 7950 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7951 }"
7952)
39b5e676 7953
91cb50d2 7954(define_insn "*cmov<mode>"
7955 [(set (match_operand:SDF 0 "s_register_operand" "=<F_constraint>")
7956 (if_then_else:SDF (match_operator 1 "arm_vsel_comparison_operator"
7957 [(match_operand 2 "cc_register" "") (const_int 0)])
7958 (match_operand:SDF 3 "s_register_operand"
7959 "<F_constraint>")
7960 (match_operand:SDF 4 "s_register_operand"
7961 "<F_constraint>")))]
c79c1b1b 7962 "TARGET_HARD_FLOAT && TARGET_VFP5 <vfp_double_cond>"
91cb50d2 7963 "*
7964 {
7965 enum arm_cond_code code = maybe_get_arm_condition_code (operands[1]);
7966 switch (code)
7967 {
7968 case ARM_GE:
7969 case ARM_GT:
7970 case ARM_EQ:
7971 case ARM_VS:
7972 return \"vsel%d1.<V_if_elem>\\t%<V_reg>0, %<V_reg>3, %<V_reg>4\";
7973 case ARM_LT:
7974 case ARM_LE:
7975 case ARM_NE:
7976 case ARM_VC:
7977 return \"vsel%D1.<V_if_elem>\\t%<V_reg>0, %<V_reg>4, %<V_reg>3\";
7978 default:
7979 gcc_unreachable ();
7980 }
7981 return \"\";
7982 }"
7983 [(set_attr "conds" "use")
6664d308 7984 (set_attr "type" "fcsel")]
91cb50d2 7985)
7986
9854d864 7987(define_insn "*cmovhf"
7988 [(set (match_operand:HF 0 "s_register_operand" "=t")
7989 (if_then_else:HF (match_operator 1 "arm_vsel_comparison_operator"
7990 [(match_operand 2 "cc_register" "") (const_int 0)])
7991 (match_operand:HF 3 "s_register_operand" "t")
7992 (match_operand:HF 4 "s_register_operand" "t")))]
7993 "TARGET_VFP_FP16INST"
7994 "*
7995 {
7996 enum arm_cond_code code = maybe_get_arm_condition_code (operands[1]);
7997 switch (code)
7998 {
7999 case ARM_GE:
8000 case ARM_GT:
8001 case ARM_EQ:
8002 case ARM_VS:
8003 return \"vsel%d1.f16\\t%0, %3, %4\";
8004 case ARM_LT:
8005 case ARM_LE:
8006 case ARM_NE:
8007 case ARM_VC:
8008 return \"vsel%D1.f16\\t%0, %4, %3\";
8009 default:
8010 gcc_unreachable ();
8011 }
8012 return \"\";
8013 }"
8014 [(set_attr "conds" "use")
8015 (set_attr "type" "fcsel")]
8016)
8017
190efb17 8018(define_insn_and_split "*movsicc_insn"
f082f1c4 8019 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
8a18b90c 8020 (if_then_else:SI
8fa3ba89 8021 (match_operator 3 "arm_comparison_operator"
8a18b90c 8022 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 8023 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
8024 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
cffb2a26 8025 "TARGET_ARM"
39b5e676 8026 "@
8a18b90c 8027 mov%D3\\t%0, %2
8028 mvn%D3\\t%0, #%B2
f082f1c4 8029 mov%d3\\t%0, %1
8030 mvn%d3\\t%0, #%B1
190efb17 8031 #
8032 #
8033 #
8034 #"
8035 ; alt4: mov%d3\\t%0, %1\;mov%D3\\t%0, %2
8036 ; alt5: mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
8037 ; alt6: mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
8038 ; alt7: mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
8039 "&& reload_completed"
8040 [(const_int 0)]
8041 {
8042 enum rtx_code rev_code;
3754d046 8043 machine_mode mode;
190efb17 8044 rtx rev_cond;
8045
8046 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
8047 operands[3],
d1f9b275 8048 gen_rtx_SET (operands[0], operands[1])));
190efb17 8049
8050 rev_code = GET_CODE (operands[3]);
8051 mode = GET_MODE (operands[4]);
8052 if (mode == CCFPmode || mode == CCFPEmode)
8053 rev_code = reverse_condition_maybe_unordered (rev_code);
8054 else
8055 rev_code = reverse_condition (rev_code);
8056
8057 rev_cond = gen_rtx_fmt_ee (rev_code,
8058 VOIDmode,
8059 operands[4],
8060 const0_rtx);
8061 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
8062 rev_cond,
d1f9b275 8063 gen_rtx_SET (operands[0], operands[2])));
190efb17 8064 DONE;
8065 }
f082f1c4 8066 [(set_attr "length" "4,4,4,4,8,8,8,8")
d2a518d1 8067 (set_attr "conds" "use")
65f68e55 8068 (set_attr_alternative "type"
8069 [(if_then_else (match_operand 2 "const_int_operand" "")
1aed5204 8070 (const_string "mov_imm")
8071 (const_string "mov_reg"))
8072 (const_string "mvn_imm")
65f68e55 8073 (if_then_else (match_operand 1 "const_int_operand" "")
1aed5204 8074 (const_string "mov_imm")
8075 (const_string "mov_reg"))
8076 (const_string "mvn_imm")
282b4c75 8077 (const_string "multiple")
8078 (const_string "multiple")
8079 (const_string "multiple")
8080 (const_string "multiple")])]
215b30b3 8081)
39b5e676 8082
39b5e676 8083(define_insn "*movsfcc_soft_insn"
f082f1c4 8084 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
8fa3ba89 8085 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
8a18b90c 8086 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 8087 (match_operand:SF 1 "s_register_operand" "0,r")
8088 (match_operand:SF 2 "s_register_operand" "r,0")))]
cffb2a26 8089 "TARGET_ARM && TARGET_SOFT_FLOAT"
f082f1c4 8090 "@
8091 mov%D3\\t%0, %2
8092 mov%d3\\t%0, %1"
d2a518d1 8093 [(set_attr "conds" "use")
1aed5204 8094 (set_attr "type" "mov_reg")]
8fa3ba89 8095)
39b5e676 8096
39b5e676 8097\f
9c08d1fa 8098;; Jump and linkage insns
8099
cffb2a26 8100(define_expand "jump"
9c08d1fa 8101 [(set (pc)
8102 (label_ref (match_operand 0 "" "")))]
cffb2a26 8103 "TARGET_EITHER"
9c08d1fa 8104 ""
cffb2a26 8105)
8106
8107(define_insn "*arm_jump"
8108 [(set (pc)
8109 (label_ref (match_operand 0 "" "")))]
25f905c2 8110 "TARGET_32BIT"
9c08d1fa 8111 "*
0d66636f 8112 {
8113 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
8114 {
8115 arm_ccfsm_state += 2;
8116 return \"\";
8117 }
8118 return \"b%?\\t%l0\";
8119 }
8120 "
a6864a24 8121 [(set_attr "predicable" "yes")
8122 (set (attr "length")
8123 (if_then_else
0bf497f5 8124 (and (match_test "TARGET_THUMB2")
a6864a24 8125 (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
8126 (le (minus (match_dup 0) (pc)) (const_int 2048))))
8127 (const_int 2)
1b7da4ac 8128 (const_int 4)))
8129 (set_attr "type" "branch")]
0d66636f 8130)
9c08d1fa 8131
d3373b54 8132(define_expand "call"
8133 [(parallel [(call (match_operand 0 "memory_operand" "")
8134 (match_operand 1 "general_operand" ""))
cffb2a26 8135 (use (match_operand 2 "" ""))
bd5b4116 8136 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 8137 "TARGET_EITHER"
6c4c2133 8138 "
8139 {
bac7fc85 8140 rtx callee, pat;
2d3a01a7 8141 tree addr = MEM_EXPR (operands[0]);
bbe777ea 8142
bbe777ea 8143 /* In an untyped call, we can get NULL for operand 2. */
8144 if (operands[2] == NULL_RTX)
8145 operands[2] = const0_rtx;
8146
de55252a 8147 /* Decide if we should generate indirect calls by loading the
85c36fd1 8148 32-bit address of the callee into a register before performing the
de55252a 8149 branch and link. */
8150 callee = XEXP (operands[0], 0);
8151 if (GET_CODE (callee) == SYMBOL_REF
8152 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
8153 : !REG_P (callee))
bbe777ea 8154 XEXP (operands[0], 0) = force_reg (Pmode, callee);
bac7fc85 8155
2d3a01a7 8156 if (detect_cmse_nonsecure_call (addr))
8157 {
8158 pat = gen_nonsecure_call_internal (operands[0], operands[1],
8159 operands[2]);
8160 emit_call_insn (pat);
8161 }
8162 else
8163 {
8164 pat = gen_call_internal (operands[0], operands[1], operands[2]);
8165 arm_emit_call_insn (pat, XEXP (operands[0], 0), false);
8166 }
bac7fc85 8167 DONE;
6c4c2133 8168 }"
8169)
d3373b54 8170
bac7fc85 8171(define_expand "call_internal"
8172 [(parallel [(call (match_operand 0 "memory_operand" "")
8173 (match_operand 1 "general_operand" ""))
8174 (use (match_operand 2 "" ""))
8175 (clobber (reg:SI LR_REGNUM))])])
8176
2d3a01a7 8177(define_expand "nonsecure_call_internal"
8178 [(parallel [(call (unspec:SI [(match_operand 0 "memory_operand" "")]
8179 UNSPEC_NONSECURE_MEM)
8180 (match_operand 1 "general_operand" ""))
8181 (use (match_operand 2 "" ""))
e27c5a70 8182 (clobber (reg:SI LR_REGNUM))])]
2d3a01a7 8183 "use_cmse"
8184 "
8185 {
8186 rtx tmp;
8187 tmp = copy_to_suggested_reg (XEXP (operands[0], 0),
e27c5a70 8188 gen_rtx_REG (SImode, R4_REGNUM),
2d3a01a7 8189 SImode);
8190
8191 operands[0] = replace_equiv_address (operands[0], tmp);
8192 }")
8193
f1039640 8194(define_insn "*call_reg_armv5"
d3373b54 8195 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
cffb2a26 8196 (match_operand 1 "" ""))
8197 (use (match_operand 2 "" ""))
bd5b4116 8198 (clobber (reg:SI LR_REGNUM))]
b232e6b5 8199 "TARGET_ARM && arm_arch5t && !SIBLING_CALL_P (insn)"
f1039640 8200 "blx%?\\t%0"
8201 [(set_attr "type" "call")]
8202)
8203
8204(define_insn "*call_reg_arm"
8205 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
8206 (match_operand 1 "" ""))
8207 (use (match_operand 2 "" ""))
8208 (clobber (reg:SI LR_REGNUM))]
b232e6b5 8209 "TARGET_ARM && !arm_arch5t && !SIBLING_CALL_P (insn)"
9c08d1fa 8210 "*
5565501b 8211 return output_call (operands);
cffb2a26 8212 "
8213 ;; length is worst case, normally it is only two
8214 [(set_attr "length" "12")
8215 (set_attr "type" "call")]
8216)
9c08d1fa 8217
89504fc1 8218
d3373b54 8219(define_expand "call_value"
e0698af7 8220 [(parallel [(set (match_operand 0 "" "")
8221 (call (match_operand 1 "memory_operand" "")
8222 (match_operand 2 "general_operand" "")))
cffb2a26 8223 (use (match_operand 3 "" ""))
bd5b4116 8224 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 8225 "TARGET_EITHER"
6c4c2133 8226 "
8227 {
bac7fc85 8228 rtx pat, callee;
2d3a01a7 8229 tree addr = MEM_EXPR (operands[1]);
bbe777ea 8230
8231 /* In an untyped call, we can get NULL for operand 2. */
8232 if (operands[3] == 0)
8233 operands[3] = const0_rtx;
8234
de55252a 8235 /* Decide if we should generate indirect calls by loading the
8236 32-bit address of the callee into a register before performing the
8237 branch and link. */
8238 callee = XEXP (operands[1], 0);
8239 if (GET_CODE (callee) == SYMBOL_REF
8240 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
8241 : !REG_P (callee))
78fe751b 8242 XEXP (operands[1], 0) = force_reg (Pmode, callee);
bac7fc85 8243
2d3a01a7 8244 if (detect_cmse_nonsecure_call (addr))
8245 {
8246 pat = gen_nonsecure_call_value_internal (operands[0], operands[1],
8247 operands[2], operands[3]);
8248 emit_call_insn (pat);
8249 }
8250 else
8251 {
8252 pat = gen_call_value_internal (operands[0], operands[1],
8253 operands[2], operands[3]);
8254 arm_emit_call_insn (pat, XEXP (operands[1], 0), false);
8255 }
bac7fc85 8256 DONE;
6c4c2133 8257 }"
8258)
d3373b54 8259
bac7fc85 8260(define_expand "call_value_internal"
8261 [(parallel [(set (match_operand 0 "" "")
8262 (call (match_operand 1 "memory_operand" "")
8263 (match_operand 2 "general_operand" "")))
8264 (use (match_operand 3 "" ""))
8265 (clobber (reg:SI LR_REGNUM))])])
8266
2d3a01a7 8267(define_expand "nonsecure_call_value_internal"
8268 [(parallel [(set (match_operand 0 "" "")
8269 (call (unspec:SI [(match_operand 1 "memory_operand" "")]
8270 UNSPEC_NONSECURE_MEM)
8271 (match_operand 2 "general_operand" "")))
8272 (use (match_operand 3 "" ""))
e27c5a70 8273 (clobber (reg:SI LR_REGNUM))])]
2d3a01a7 8274 "use_cmse"
8275 "
8276 {
8277 rtx tmp;
8278 tmp = copy_to_suggested_reg (XEXP (operands[1], 0),
e27c5a70 8279 gen_rtx_REG (SImode, R4_REGNUM),
2d3a01a7 8280 SImode);
8281
8282 operands[1] = replace_equiv_address (operands[1], tmp);
8283 }")
8284
f1039640 8285(define_insn "*call_value_reg_armv5"
27ed6835 8286 [(set (match_operand 0 "" "")
755eb2b4 8287 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
cffb2a26 8288 (match_operand 2 "" "")))
bbe777ea 8289 (use (match_operand 3 "" ""))
bd5b4116 8290 (clobber (reg:SI LR_REGNUM))]
b232e6b5 8291 "TARGET_ARM && arm_arch5t && !SIBLING_CALL_P (insn)"
f1039640 8292 "blx%?\\t%1"
8293 [(set_attr "type" "call")]
8294)
8295
8296(define_insn "*call_value_reg_arm"
8297 [(set (match_operand 0 "" "")
8298 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
8299 (match_operand 2 "" "")))
8300 (use (match_operand 3 "" ""))
8301 (clobber (reg:SI LR_REGNUM))]
b232e6b5 8302 "TARGET_ARM && !arm_arch5t && !SIBLING_CALL_P (insn)"
9c08d1fa 8303 "*
215b30b3 8304 return output_call (&operands[1]);
cffb2a26 8305 "
8306 [(set_attr "length" "12")
8307 (set_attr "type" "call")]
8308)
9c08d1fa 8309
9c08d1fa 8310;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
8311;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
8312
f7fbdd4a 8313(define_insn "*call_symbol"
27ed6835 8314 [(call (mem:SI (match_operand:SI 0 "" ""))
cffb2a26 8315 (match_operand 1 "" ""))
bbe777ea 8316 (use (match_operand 2 "" ""))
bd5b4116 8317 (clobber (reg:SI LR_REGNUM))]
d68c2c10 8318 "TARGET_32BIT
33ae7c4b 8319 && !SIBLING_CALL_P (insn)
cffb2a26 8320 && (GET_CODE (operands[0]) == SYMBOL_REF)
de55252a 8321 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
6ebaa29d 8322 "*
8323 {
95f1e0d1 8324 rtx op = operands[0];
8325
8326 /* Switch mode now when possible. */
8327 if (SYMBOL_REF_DECL (op) && !TREE_PUBLIC (SYMBOL_REF_DECL (op))
b232e6b5 8328 && arm_arch5t && arm_change_mode_p (SYMBOL_REF_DECL (op)))
95f1e0d1 8329 return NEED_PLT_RELOC ? \"blx%?\\t%a0(PLT)\" : \"blx%?\\t(%a0)\";
8330
55c1e470 8331 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
6ebaa29d 8332 }"
cffb2a26 8333 [(set_attr "type" "call")]
8334)
9c08d1fa 8335
f7fbdd4a 8336(define_insn "*call_value_symbol"
ccd90aaa 8337 [(set (match_operand 0 "" "")
27ed6835 8338 (call (mem:SI (match_operand:SI 1 "" ""))
dd6d7504 8339 (match_operand:SI 2 "" "")))
bbe777ea 8340 (use (match_operand 3 "" ""))
bd5b4116 8341 (clobber (reg:SI LR_REGNUM))]
d68c2c10 8342 "TARGET_32BIT
33ae7c4b 8343 && !SIBLING_CALL_P (insn)
cffb2a26 8344 && (GET_CODE (operands[1]) == SYMBOL_REF)
de55252a 8345 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
6ebaa29d 8346 "*
8347 {
95f1e0d1 8348 rtx op = operands[1];
8349
8350 /* Switch mode now when possible. */
8351 if (SYMBOL_REF_DECL (op) && !TREE_PUBLIC (SYMBOL_REF_DECL (op))
b232e6b5 8352 && arm_arch5t && arm_change_mode_p (SYMBOL_REF_DECL (op)))
3f6b66fa 8353 return NEED_PLT_RELOC ? \"blx%?\\t%a1(PLT)\" : \"blx%?\\t(%a1)\";
95f1e0d1 8354
55c1e470 8355 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
6ebaa29d 8356 }"
cffb2a26 8357 [(set_attr "type" "call")]
8358)
8359
ca373797 8360(define_expand "sibcall_internal"
8361 [(parallel [(call (match_operand 0 "memory_operand" "")
8362 (match_operand 1 "general_operand" ""))
8363 (return)
8364 (use (match_operand 2 "" ""))])])
8365
1c494086 8366;; We may also be able to do sibcalls for Thumb, but it's much harder...
8367(define_expand "sibcall"
8368 [(parallel [(call (match_operand 0 "memory_operand" "")
8369 (match_operand 1 "general_operand" ""))
2ba80634 8370 (return)
8371 (use (match_operand 2 "" ""))])]
d68c2c10 8372 "TARGET_32BIT"
1c494086 8373 "
8374 {
ca373797 8375 rtx pat;
8376
3112c3f7 8377 if ((!REG_P (XEXP (operands[0], 0))
8378 && GET_CODE (XEXP (operands[0], 0)) != SYMBOL_REF)
8379 || (GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
8380 && arm_is_long_call_p (SYMBOL_REF_DECL (XEXP (operands[0], 0)))))
33ae7c4b 8381 XEXP (operands[0], 0) = force_reg (SImode, XEXP (operands[0], 0));
8382
1c494086 8383 if (operands[2] == NULL_RTX)
8384 operands[2] = const0_rtx;
ca373797 8385
8386 pat = gen_sibcall_internal (operands[0], operands[1], operands[2]);
8387 arm_emit_call_insn (pat, operands[0], true);
8388 DONE;
1c494086 8389 }"
8390)
8391
ca373797 8392(define_expand "sibcall_value_internal"
8393 [(parallel [(set (match_operand 0 "" "")
8394 (call (match_operand 1 "memory_operand" "")
8395 (match_operand 2 "general_operand" "")))
8396 (return)
8397 (use (match_operand 3 "" ""))])])
8398
1c494086 8399(define_expand "sibcall_value"
ccd90aaa 8400 [(parallel [(set (match_operand 0 "" "")
1c494086 8401 (call (match_operand 1 "memory_operand" "")
8402 (match_operand 2 "general_operand" "")))
2ba80634 8403 (return)
8404 (use (match_operand 3 "" ""))])]
d68c2c10 8405 "TARGET_32BIT"
1c494086 8406 "
8407 {
ca373797 8408 rtx pat;
8409
3112c3f7 8410 if ((!REG_P (XEXP (operands[1], 0))
8411 && GET_CODE (XEXP (operands[1], 0)) != SYMBOL_REF)
8412 || (GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
8413 && arm_is_long_call_p (SYMBOL_REF_DECL (XEXP (operands[1], 0)))))
33ae7c4b 8414 XEXP (operands[1], 0) = force_reg (SImode, XEXP (operands[1], 0));
8415
1c494086 8416 if (operands[3] == NULL_RTX)
8417 operands[3] = const0_rtx;
ca373797 8418
8419 pat = gen_sibcall_value_internal (operands[0], operands[1],
8420 operands[2], operands[3]);
8421 arm_emit_call_insn (pat, operands[1], true);
8422 DONE;
1c494086 8423 }"
8424)
8425
8426(define_insn "*sibcall_insn"
84ce8e5c 8427 [(call (mem:SI (match_operand:SI 0 "call_insn_operand" "Cs, US"))
1c494086 8428 (match_operand 1 "" ""))
2ba80634 8429 (return)
8430 (use (match_operand 2 "" ""))]
33ae7c4b 8431 "TARGET_32BIT && SIBLING_CALL_P (insn)"
1c494086 8432 "*
33ae7c4b 8433 if (which_alternative == 1)
8434 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
8435 else
8436 {
b232e6b5 8437 if (arm_arch5t || arm_arch4t)
947d113e 8438 return \"bx%?\\t%0\\t%@ indirect register sibling call\";
33ae7c4b 8439 else
8440 return \"mov%?\\t%|pc, %0\\t%@ indirect register sibling call\";
8441 }
1c494086 8442 "
8443 [(set_attr "type" "call")]
8444)
8445
8446(define_insn "*sibcall_value_insn"
84ce8e5c 8447 [(set (match_operand 0 "" "")
8448 (call (mem:SI (match_operand:SI 1 "call_insn_operand" "Cs,US"))
1c494086 8449 (match_operand 2 "" "")))
2ba80634 8450 (return)
8451 (use (match_operand 3 "" ""))]
33ae7c4b 8452 "TARGET_32BIT && SIBLING_CALL_P (insn)"
1c494086 8453 "*
33ae7c4b 8454 if (which_alternative == 1)
8455 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
8456 else
8457 {
b232e6b5 8458 if (arm_arch5t || arm_arch4t)
84ce8e5c 8459 return \"bx%?\\t%1\";
33ae7c4b 8460 else
8461 return \"mov%?\\t%|pc, %1\\t@ indirect sibling call \";
8462 }
1c494086 8463 "
8464 [(set_attr "type" "call")]
8465)
8466
0686440e 8467(define_expand "<return_str>return"
9b23f0a7 8468 [(RETURNS)]
8cba51a5 8469 "(TARGET_ARM || (TARGET_THUMB2
8470 && ARM_FUNC_TYPE (arm_current_func_type ()) == ARM_FT_NORMAL
8471 && !IS_STACKALIGN (arm_current_func_type ())))
0686440e 8472 <return_cond_false>"
8cba51a5 8473 "
8474 {
8475 if (TARGET_THUMB2)
8476 {
0686440e 8477 thumb2_expand_return (<return_simple_p>);
8cba51a5 8478 DONE;
8479 }
8480 }
8481 "
8482)
d68c2c10 8483
9c08d1fa 8484;; Often the return insn will be the same as loading from memory, so set attr
d68c2c10 8485(define_insn "*arm_return"
9c08d1fa 8486 [(return)]
cffb2a26 8487 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
9c08d1fa 8488 "*
9c08d1fa 8489 {
cffb2a26 8490 if (arm_ccfsm_state == 2)
8491 {
8492 arm_ccfsm_state += 2;
8493 return \"\";
8494 }
e2549f81 8495 return output_return_instruction (const_true_rtx, true, false, false);
cffb2a26 8496 }"
9f2c2a36 8497 [(set_attr "type" "load_4")
755eb2b4 8498 (set_attr "length" "12")
0d66636f 8499 (set_attr "predicable" "yes")]
cffb2a26 8500)
9c08d1fa 8501
0686440e 8502(define_insn "*cond_<return_str>return"
9c08d1fa 8503 [(set (pc)
8fa3ba89 8504 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 8505 [(match_operand 1 "cc_register" "") (const_int 0)])
9b23f0a7 8506 (RETURNS)
9c08d1fa 8507 (pc)))]
0686440e 8508 "TARGET_ARM <return_cond_true>"
9c08d1fa 8509 "*
8fa3ba89 8510 {
8511 if (arm_ccfsm_state == 2)
8512 {
8513 arm_ccfsm_state += 2;
8514 return \"\";
8515 }
0686440e 8516 return output_return_instruction (operands[0], true, false,
8517 <return_simple_p>);
8fa3ba89 8518 }"
8519 [(set_attr "conds" "use")
755eb2b4 8520 (set_attr "length" "12")
9f2c2a36 8521 (set_attr "type" "load_4")]
8fa3ba89 8522)
9c08d1fa 8523
0686440e 8524(define_insn "*cond_<return_str>return_inverted"
9c08d1fa 8525 [(set (pc)
8fa3ba89 8526 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 8527 [(match_operand 1 "cc_register" "") (const_int 0)])
9c08d1fa 8528 (pc)
9b23f0a7 8529 (RETURNS)))]
0686440e 8530 "TARGET_ARM <return_cond_true>"
9c08d1fa 8531 "*
8fa3ba89 8532 {
8533 if (arm_ccfsm_state == 2)
8534 {
8535 arm_ccfsm_state += 2;
8536 return \"\";
8537 }
0686440e 8538 return output_return_instruction (operands[0], true, true,
8539 <return_simple_p>);
8fa3ba89 8540 }"
8541 [(set_attr "conds" "use")
37a1317b 8542 (set_attr "length" "12")
9f2c2a36 8543 (set_attr "type" "load_4")]
8fa3ba89 8544)
9c08d1fa 8545
e2549f81 8546(define_insn "*arm_simple_return"
8547 [(simple_return)]
8548 "TARGET_ARM"
8549 "*
8550 {
8551 if (arm_ccfsm_state == 2)
8552 {
8553 arm_ccfsm_state += 2;
8554 return \"\";
8555 }
8556 return output_return_instruction (const_true_rtx, true, false, true);
8557 }"
8558 [(set_attr "type" "branch")
8559 (set_attr "length" "4")
8560 (set_attr "predicable" "yes")]
8561)
8562
68121397 8563;; Generate a sequence of instructions to determine if the processor is
8564;; in 26-bit or 32-bit mode, and return the appropriate return address
8565;; mask.
8566
8567(define_expand "return_addr_mask"
8568 [(set (match_dup 1)
8569 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8570 (const_int 0)))
8571 (set (match_operand:SI 0 "s_register_operand" "")
8572 (if_then_else:SI (eq (match_dup 1) (const_int 0))
8573 (const_int -1)
8574 (const_int 67108860)))] ; 0x03fffffc
8575 "TARGET_ARM"
8576 "
62eddbd4 8577 operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
68121397 8578 ")
8579
8580(define_insn "*check_arch2"
8581 [(set (match_operand:CC_NOOV 0 "cc_register" "")
8582 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8583 (const_int 0)))]
8584 "TARGET_ARM"
8585 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
8586 [(set_attr "length" "8")
1b7da4ac 8587 (set_attr "conds" "set")
8588 (set_attr "type" "multiple")]
68121397 8589)
8590
9c08d1fa 8591;; Call subroutine returning any type.
8592
8593(define_expand "untyped_call"
8594 [(parallel [(call (match_operand 0 "" "")
8595 (const_int 0))
8596 (match_operand 1 "" "")
8597 (match_operand 2 "" "")])]
ccd90aaa 8598 "TARGET_EITHER"
9c08d1fa 8599 "
215b30b3 8600 {
8601 int i;
ccd90aaa 8602 rtx par = gen_rtx_PARALLEL (VOIDmode,
8603 rtvec_alloc (XVECLEN (operands[2], 0)));
8604 rtx addr = gen_reg_rtx (Pmode);
8605 rtx mem;
8606 int size = 0;
9c08d1fa 8607
ccd90aaa 8608 emit_move_insn (addr, XEXP (operands[1], 0));
8609 mem = change_address (operands[1], BLKmode, addr);
9c08d1fa 8610
215b30b3 8611 for (i = 0; i < XVECLEN (operands[2], 0); i++)
8612 {
ccd90aaa 8613 rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
9c08d1fa 8614
ccd90aaa 8615 /* Default code only uses r0 as a return value, but we could
8616 be using anything up to 4 registers. */
8617 if (REGNO (src) == R0_REGNUM)
8618 src = gen_rtx_REG (TImode, R0_REGNUM);
8619
8620 XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
8621 GEN_INT (size));
8622 size += GET_MODE_SIZE (GET_MODE (src));
8623 }
8624
7f265a08 8625 emit_call_insn (gen_call_value (par, operands[0], const0_rtx, NULL));
ccd90aaa 8626
8627 size = 0;
8628
8629 for (i = 0; i < XVECLEN (par, 0); i++)
8630 {
8631 HOST_WIDE_INT offset = 0;
8632 rtx reg = XEXP (XVECEXP (par, 0, i), 0);
8633
8634 if (size != 0)
29c05e22 8635 emit_move_insn (addr, plus_constant (Pmode, addr, size));
ccd90aaa 8636
8637 mem = change_address (mem, GET_MODE (reg), NULL);
8638 if (REGNO (reg) == R0_REGNUM)
8639 {
8640 /* On thumb we have to use a write-back instruction. */
320ea44d 8641 emit_insn (arm_gen_store_multiple (arm_regs_in_sequence, 4, addr,
8642 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
ccd90aaa 8643 size = TARGET_ARM ? 16 : 0;
8644 }
8645 else
8646 {
8647 emit_move_insn (mem, reg);
8648 size = GET_MODE_SIZE (GET_MODE (reg));
8649 }
215b30b3 8650 }
9c08d1fa 8651
215b30b3 8652 /* The optimizer does not know that the call sets the function value
8653 registers we stored in the result block. We avoid problems by
8654 claiming that all hard registers are used and clobbered at this
8655 point. */
8656 emit_insn (gen_blockage ());
8657
8658 DONE;
8659 }"
8660)
9c08d1fa 8661
ccd90aaa 8662(define_expand "untyped_return"
8663 [(match_operand:BLK 0 "memory_operand" "")
8664 (match_operand 1 "" "")]
8665 "TARGET_EITHER"
8666 "
8667 {
8668 int i;
8669 rtx addr = gen_reg_rtx (Pmode);
8670 rtx mem;
8671 int size = 0;
8672
8673 emit_move_insn (addr, XEXP (operands[0], 0));
8674 mem = change_address (operands[0], BLKmode, addr);
8675
8676 for (i = 0; i < XVECLEN (operands[1], 0); i++)
8677 {
8678 HOST_WIDE_INT offset = 0;
8679 rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
8680
8681 if (size != 0)
29c05e22 8682 emit_move_insn (addr, plus_constant (Pmode, addr, size));
ccd90aaa 8683
8684 mem = change_address (mem, GET_MODE (reg), NULL);
8685 if (REGNO (reg) == R0_REGNUM)
8686 {
8687 /* On thumb we have to use a write-back instruction. */
320ea44d 8688 emit_insn (arm_gen_load_multiple (arm_regs_in_sequence, 4, addr,
8689 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
ccd90aaa 8690 size = TARGET_ARM ? 16 : 0;
8691 }
8692 else
8693 {
8694 emit_move_insn (reg, mem);
8695 size = GET_MODE_SIZE (GET_MODE (reg));
8696 }
8697 }
8698
8699 /* Emit USE insns before the return. */
8700 for (i = 0; i < XVECLEN (operands[1], 0); i++)
18b42941 8701 emit_use (SET_DEST (XVECEXP (operands[1], 0, i)));
ccd90aaa 8702
8703 /* Construct the return. */
8704 expand_naked_return ();
8705
8706 DONE;
8707 }"
8708)
8709
9c08d1fa 8710;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
8711;; all of memory. This blocks insns from being moved across this point.
8712
8713(define_insn "blockage"
e1159bbe 8714 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
cffb2a26 8715 "TARGET_EITHER"
9c08d1fa 8716 ""
cffb2a26 8717 [(set_attr "length" "0")
8718 (set_attr "type" "block")]
8719)
9c08d1fa 8720
80c63fc3 8721;; Since we hard code r0 here use the 'o' constraint to prevent
8722;; provoking undefined behaviour in the hardware with putting out
8723;; auto-increment operations with potentially r0 as the base register.
706dca65 8724(define_insn "probe_stack"
80c63fc3 8725 [(set (match_operand:SI 0 "memory_operand" "=o")
f8570abe 8726 (unspec:SI [(const_int 0)] UNSPEC_PROBE_STACK))]
706dca65 8727 "TARGET_32BIT"
154ae8e6 8728 "str%?\\tr0, %0"
9f2c2a36 8729 [(set_attr "type" "store_4")
706dca65 8730 (set_attr "predicable" "yes")]
8731)
8732
8733(define_insn "probe_stack_range"
8734 [(set (match_operand:SI 0 "register_operand" "=r")
8735 (unspec_volatile:SI [(match_operand:SI 1 "register_operand" "0")
8736 (match_operand:SI 2 "register_operand" "r")]
dd8aabc9 8737 VUNSPEC_PROBE_STACK_RANGE))]
706dca65 8738 "TARGET_32BIT"
8739{
8740 return output_probe_stack_range (operands[0], operands[2]);
8741}
8742 [(set_attr "type" "multiple")
8743 (set_attr "conds" "clob")]
8744)
8745
f98495d9 8746;; Named patterns for stack smashing protection.
8747(define_expand "stack_protect_combined_set"
8748 [(parallel
8749 [(set (match_operand:SI 0 "memory_operand" "")
8750 (unspec:SI [(match_operand:SI 1 "guard_operand" "")]
8751 UNSPEC_SP_SET))
8752 (clobber (match_scratch:SI 2 ""))
8753 (clobber (match_scratch:SI 3 ""))])]
8754 ""
8755 ""
8756)
8757
8758;; Use a separate insn from the above expand to be able to have the mem outside
8759;; the operand #1 when register allocation comes. This is needed to avoid LRA
8760;; try to reload the guard since we need to control how PIC access is done in
8761;; the -fpic/-fPIC case (see COMPUTE_NOW parameter when calling
8762;; legitimize_pic_address ()).
8763(define_insn_and_split "*stack_protect_combined_set_insn"
8764 [(set (match_operand:SI 0 "memory_operand" "=m,m")
8765 (unspec:SI [(mem:SI (match_operand:SI 1 "guard_addr_operand" "X,X"))]
8766 UNSPEC_SP_SET))
8767 (clobber (match_scratch:SI 2 "=&l,&r"))
8768 (clobber (match_scratch:SI 3 "=&l,&r"))]
8769 ""
8770 "#"
8771 "reload_completed"
8772 [(parallel [(set (match_dup 0) (unspec:SI [(mem:SI (match_dup 2))]
8773 UNSPEC_SP_SET))
8774 (clobber (match_dup 2))])]
8775 "
8776{
8777 if (flag_pic)
8778 {
8779 /* Forces recomputing of GOT base now. */
8780 legitimize_pic_address (operands[1], SImode, operands[2], operands[3],
8781 true /*compute_now*/);
8782 }
8783 else
8784 {
8785 if (address_operand (operands[1], SImode))
8786 operands[2] = operands[1];
8787 else
8788 {
8789 rtx mem = XEXP (force_const_mem (SImode, operands[1]), 0);
8790 emit_move_insn (operands[2], mem);
8791 }
8792 }
8793}"
8794 [(set_attr "arch" "t1,32")]
8795)
8796
8797(define_insn "*stack_protect_set_insn"
8798 [(set (match_operand:SI 0 "memory_operand" "=m,m")
8799 (unspec:SI [(mem:SI (match_operand:SI 1 "register_operand" "+&l,&r"))]
8800 UNSPEC_SP_SET))
8801 (clobber (match_dup 1))]
8802 ""
8803 "@
8804 ldr\\t%1, [%1]\;str\\t%1, %0\;movs\t%1,#0
8805 ldr\\t%1, [%1]\;str\\t%1, %0\;mov\t%1,#0"
8806 [(set_attr "length" "8,12")
8807 (set_attr "conds" "clob,nocond")
8808 (set_attr "type" "multiple")
8809 (set_attr "arch" "t1,32")]
8810)
8811
8812(define_expand "stack_protect_combined_test"
8813 [(parallel
8814 [(set (pc)
8815 (if_then_else
8816 (eq (match_operand:SI 0 "memory_operand" "")
8817 (unspec:SI [(match_operand:SI 1 "guard_operand" "")]
8818 UNSPEC_SP_TEST))
8819 (label_ref (match_operand 2))
8820 (pc)))
8821 (clobber (match_scratch:SI 3 ""))
8822 (clobber (match_scratch:SI 4 ""))
8823 (clobber (reg:CC CC_REGNUM))])]
8824 ""
8825 ""
8826)
8827
8828;; Use a separate insn from the above expand to be able to have the mem outside
8829;; the operand #1 when register allocation comes. This is needed to avoid LRA
8830;; try to reload the guard since we need to control how PIC access is done in
8831;; the -fpic/-fPIC case (see COMPUTE_NOW parameter when calling
8832;; legitimize_pic_address ()).
8833(define_insn_and_split "*stack_protect_combined_test_insn"
8834 [(set (pc)
8835 (if_then_else
8836 (eq (match_operand:SI 0 "memory_operand" "m,m")
8837 (unspec:SI [(mem:SI (match_operand:SI 1 "guard_addr_operand" "X,X"))]
8838 UNSPEC_SP_TEST))
8839 (label_ref (match_operand 2))
8840 (pc)))
8841 (clobber (match_scratch:SI 3 "=&l,&r"))
8842 (clobber (match_scratch:SI 4 "=&l,&r"))
8843 (clobber (reg:CC CC_REGNUM))]
8844 ""
8845 "#"
8846 "reload_completed"
8847 [(const_int 0)]
8848{
8849 rtx eq;
8850
8851 if (flag_pic)
8852 {
8853 /* Forces recomputing of GOT base now. */
8854 legitimize_pic_address (operands[1], SImode, operands[3], operands[4],
8855 true /*compute_now*/);
8856 }
8857 else
8858 {
8859 if (address_operand (operands[1], SImode))
8860 operands[3] = operands[1];
8861 else
8862 {
8863 rtx mem = XEXP (force_const_mem (SImode, operands[1]), 0);
8864 emit_move_insn (operands[3], mem);
8865 }
8866 }
8867 if (TARGET_32BIT)
8868 {
8869 emit_insn (gen_arm_stack_protect_test_insn (operands[4], operands[0],
8870 operands[3]));
8871 rtx cc_reg = gen_rtx_REG (CC_Zmode, CC_REGNUM);
8872 eq = gen_rtx_EQ (CC_Zmode, cc_reg, const0_rtx);
8873 emit_jump_insn (gen_arm_cond_branch (operands[2], eq, cc_reg));
8874 }
8875 else
8876 {
8877 emit_insn (gen_thumb1_stack_protect_test_insn (operands[4], operands[0],
8878 operands[3]));
8879 eq = gen_rtx_EQ (VOIDmode, operands[4], const0_rtx);
8880 emit_jump_insn (gen_cbranchsi4 (eq, operands[4], const0_rtx,
8881 operands[2]));
8882 }
8883 DONE;
8884}
8885 [(set_attr "arch" "t1,32")]
8886)
8887
8888(define_insn "arm_stack_protect_test_insn"
8889 [(set (reg:CC_Z CC_REGNUM)
8890 (compare:CC_Z (unspec:SI [(match_operand:SI 1 "memory_operand" "m,m")
8891 (mem:SI (match_operand:SI 2 "register_operand" "+l,r"))]
8892 UNSPEC_SP_TEST)
8893 (const_int 0)))
8894 (clobber (match_operand:SI 0 "register_operand" "=&l,&r"))
8895 (clobber (match_dup 2))]
8896 "TARGET_32BIT"
8897 "ldr\t%0, [%2]\;ldr\t%2, %1\;eors\t%0, %2, %0"
8898 [(set_attr "length" "8,12")
8899 (set_attr "conds" "set")
8900 (set_attr "type" "multiple")
8901 (set_attr "arch" "t,32")]
8902)
8903
f7fbdd4a 8904(define_expand "casesi"
8905 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
aea4c774 8906 (match_operand:SI 1 "const_int_operand" "") ; lower bound
8907 (match_operand:SI 2 "const_int_operand" "") ; total range
f7fbdd4a 8908 (match_operand:SI 3 "" "") ; table label
8909 (match_operand:SI 4 "" "")] ; Out of range label
9753b549 8910 "(TARGET_32BIT || optimize_size || flag_pic) && !target_pure_code"
f7fbdd4a 8911 "
215b30b3 8912 {
e6ac8414 8913 enum insn_code code;
215b30b3 8914 if (operands[1] != const0_rtx)
8915 {
e6ac8414 8916 rtx reg = gen_reg_rtx (SImode);
f7fbdd4a 8917
215b30b3 8918 emit_insn (gen_addsi3 (reg, operands[0],
d022fa24 8919 gen_int_mode (-INTVAL (operands[1]),
8920 SImode)));
215b30b3 8921 operands[0] = reg;
8922 }
9c08d1fa 8923
25f905c2 8924 if (TARGET_ARM)
e6ac8414 8925 code = CODE_FOR_arm_casesi_internal;
3db2019b 8926 else if (TARGET_THUMB1)
e6ac8414 8927 code = CODE_FOR_thumb1_casesi_internal_pic;
25f905c2 8928 else if (flag_pic)
e6ac8414 8929 code = CODE_FOR_thumb2_casesi_internal_pic;
25f905c2 8930 else
e6ac8414 8931 code = CODE_FOR_thumb2_casesi_internal;
8932
8933 if (!insn_data[(int) code].operand[1].predicate(operands[2], SImode))
8934 operands[2] = force_reg (SImode, operands[2]);
8935
8936 emit_jump_insn (GEN_FCN ((int) code) (operands[0], operands[2],
8937 operands[3], operands[4]));
215b30b3 8938 DONE;
8939 }"
8940)
f7fbdd4a 8941
f082f1c4 8942;; The USE in this pattern is needed to tell flow analysis that this is
8943;; a CASESI insn. It has no other purpose.
b634d96a 8944(define_expand "arm_casesi_internal"
8945 [(parallel [(set (pc)
8946 (if_then_else
8947 (leu (match_operand:SI 0 "s_register_operand")
8948 (match_operand:SI 1 "arm_rhs_operand"))
8949 (match_dup 4)
8950 (label_ref:SI (match_operand 3 ""))))
8951 (clobber (reg:CC CC_REGNUM))
8952 (use (label_ref:SI (match_operand 2 "")))])]
8953 "TARGET_ARM"
8954{
8955 operands[4] = gen_rtx_MULT (SImode, operands[0], GEN_INT (4));
8956 operands[4] = gen_rtx_PLUS (SImode, operands[4],
8957 gen_rtx_LABEL_REF (SImode, operands[2]));
8958 operands[4] = gen_rtx_MEM (SImode, operands[4]);
8959 MEM_READONLY_P (operands[4]) = 1;
8960 MEM_NOTRAP_P (operands[4]) = 1;
8961})
8962
8963(define_insn "*arm_casesi_internal"
f082f1c4 8964 [(parallel [(set (pc)
8965 (if_then_else
8966 (leu (match_operand:SI 0 "s_register_operand" "r")
8967 (match_operand:SI 1 "arm_rhs_operand" "rI"))
8968 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
b634d96a 8969 (label_ref:SI (match_operand 2 "" ""))))
8970 (label_ref:SI (match_operand 3 "" ""))))
bd5b4116 8971 (clobber (reg:CC CC_REGNUM))
b634d96a 8972 (use (label_ref:SI (match_dup 2)))])]
cffb2a26 8973 "TARGET_ARM"
f7fbdd4a 8974 "*
0d66636f 8975 if (flag_pic)
8976 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
8977 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
8978 "
8979 [(set_attr "conds" "clob")
1b7da4ac 8980 (set_attr "length" "12")
8981 (set_attr "type" "multiple")]
0d66636f 8982)
9c08d1fa 8983
cffb2a26 8984(define_expand "indirect_jump"
9c08d1fa 8985 [(set (pc)
cffb2a26 8986 (match_operand:SI 0 "s_register_operand" ""))]
8987 "TARGET_EITHER"
25f905c2 8988 "
8989 /* Thumb-2 doesn't have mov pc, reg. Explicitly set the low bit of the
8990 address and use bx. */
8991 if (TARGET_THUMB2)
8992 {
8993 rtx tmp;
8994 tmp = gen_reg_rtx (SImode);
8995 emit_insn (gen_iorsi3 (tmp, operands[0], GEN_INT(1)));
8996 operands[0] = tmp;
8997 }
8998 "
cffb2a26 8999)
9000
f1039640 9001;; NB Never uses BX.
cffb2a26 9002(define_insn "*arm_indirect_jump"
9003 [(set (pc)
9004 (match_operand:SI 0 "s_register_operand" "r"))]
9005 "TARGET_ARM"
9006 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
1b7da4ac 9007 [(set_attr "predicable" "yes")
9008 (set_attr "type" "branch")]
cffb2a26 9009)
9c08d1fa 9010
f7fbdd4a 9011(define_insn "*load_indirect_jump"
9c08d1fa 9012 [(set (pc)
9013 (match_operand:SI 0 "memory_operand" "m"))]
cffb2a26 9014 "TARGET_ARM"
9015 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
9f2c2a36 9016 [(set_attr "type" "load_4")
61a2d04c 9017 (set_attr "pool_range" "4096")
9018 (set_attr "neg_pool_range" "4084")
0d66636f 9019 (set_attr "predicable" "yes")]
cffb2a26 9020)
9021
9c08d1fa 9022\f
9023;; Misc insns
9024
9025(define_insn "nop"
9026 [(const_int 0)]
cffb2a26 9027 "TARGET_EITHER"
3ef90e77 9028 "nop"
cffb2a26 9029 [(set (attr "length")
9030 (if_then_else (eq_attr "is_thumb" "yes")
9031 (const_int 2)
1b7da4ac 9032 (const_int 4)))
9033 (set_attr "type" "mov_reg")]
cffb2a26 9034)
9035
ad9d4399 9036(define_insn "trap"
9037 [(trap_if (const_int 1) (const_int 0))]
9038 ""
9039 "*
9040 if (TARGET_ARM)
9041 return \".inst\\t0xe7f000f0\";
9042 else
9043 return \".inst\\t0xdeff\";
9044 "
9045 [(set (attr "length")
9046 (if_then_else (eq_attr "is_thumb" "yes")
9047 (const_int 2)
9048 (const_int 4)))
9049 (set_attr "type" "trap")
9050 (set_attr "conds" "unconditional")]
9051)
9052
9c08d1fa 9053\f
9054;; Patterns to allow combination of arithmetic, cond code and shifts
9055
0abea32c 9056(define_insn "*<arith_shift_insn>_multsi"
9057 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9b23f0a7 9058 (SHIFTABLE_OPS:SI
0abea32c 9059 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
9060 (match_operand:SI 3 "power_of_two_operand" ""))
9061 (match_operand:SI 1 "s_register_operand" "rk,<t2_binop0>")))]
d5d4dc8d 9062 "TARGET_32BIT"
0abea32c 9063 "<arith_shift_insn>%?\\t%0, %1, %2, lsl %b3"
9064 [(set_attr "predicable" "yes")
753d9835 9065 (set_attr "shift" "2")
0abea32c 9066 (set_attr "arch" "a,t2")
9067 (set_attr "type" "alu_shift_imm")])
9068
9069(define_insn "*<arith_shift_insn>_shiftsi"
9070 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9b23f0a7 9071 (SHIFTABLE_OPS:SI
0abea32c 9072 (match_operator:SI 2 "shift_nomul_operator"
9073 [(match_operand:SI 3 "s_register_operand" "r,r,r")
9074 (match_operand:SI 4 "shift_amount_operand" "M,M,r")])
9075 (match_operand:SI 1 "s_register_operand" "rk,<t2_binop0>,rk")))]
a021b821 9076 "TARGET_32BIT && GET_CODE (operands[2]) != MULT"
0abea32c 9077 "<arith_shift_insn>%?\\t%0, %1, %3%S2"
344495ea 9078 [(set_attr "predicable" "yes")
753d9835 9079 (set_attr "shift" "3")
0abea32c 9080 (set_attr "arch" "a,t2,a")
9081 (set_attr "type" "alu_shift_imm,alu_shift_imm,alu_shift_reg")])
9c08d1fa 9082
d7863cfe 9083(define_split
9084 [(set (match_operand:SI 0 "s_register_operand" "")
9085 (match_operator:SI 1 "shiftable_operator"
9086 [(match_operator:SI 2 "shiftable_operator"
9087 [(match_operator:SI 3 "shift_operator"
9088 [(match_operand:SI 4 "s_register_operand" "")
9089 (match_operand:SI 5 "reg_or_int_operand" "")])
9090 (match_operand:SI 6 "s_register_operand" "")])
9091 (match_operand:SI 7 "arm_rhs_operand" "")]))
9092 (clobber (match_operand:SI 8 "s_register_operand" ""))]
d5d4dc8d 9093 "TARGET_32BIT"
d7863cfe 9094 [(set (match_dup 8)
9095 (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
9096 (match_dup 6)]))
9097 (set (match_dup 0)
9098 (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
9099 "")
9100
f7fbdd4a 9101(define_insn "*arith_shiftsi_compare0"
bd5b4116 9102 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 9103 (compare:CC_NOOV
9104 (match_operator:SI 1 "shiftable_operator"
9105 [(match_operator:SI 3 "shift_operator"
9106 [(match_operand:SI 4 "s_register_operand" "r,r")
9107 (match_operand:SI 5 "shift_amount_operand" "M,r")])
9108 (match_operand:SI 2 "s_register_operand" "r,r")])
9109 (const_int 0)))
9110 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 9111 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
9112 (match_dup 2)]))]
d5d4dc8d 9113 "TARGET_32BIT"
3ef90e77 9114 "%i1s%?\\t%0, %2, %4%S3"
344495ea 9115 [(set_attr "conds" "set")
331beb1a 9116 (set_attr "shift" "4")
d5d4dc8d 9117 (set_attr "arch" "32,a")
d82e788e 9118 (set_attr "type" "alus_shift_imm,alus_shift_reg")])
9c08d1fa 9119
f7fbdd4a 9120(define_insn "*arith_shiftsi_compare0_scratch"
bd5b4116 9121 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 9122 (compare:CC_NOOV
9123 (match_operator:SI 1 "shiftable_operator"
9124 [(match_operator:SI 3 "shift_operator"
9125 [(match_operand:SI 4 "s_register_operand" "r,r")
9126 (match_operand:SI 5 "shift_amount_operand" "M,r")])
9127 (match_operand:SI 2 "s_register_operand" "r,r")])
9128 (const_int 0)))
9129 (clobber (match_scratch:SI 0 "=r,r"))]
9130 "TARGET_32BIT"
3ef90e77 9131 "%i1s%?\\t%0, %2, %4%S3"
344495ea 9132 [(set_attr "conds" "set")
331beb1a 9133 (set_attr "shift" "4")
d5d4dc8d 9134 (set_attr "arch" "32,a")
d82e788e 9135 (set_attr "type" "alus_shift_imm,alus_shift_reg")])
9c08d1fa 9136
f7fbdd4a 9137(define_insn "*sub_shiftsi"
d5d4dc8d 9138 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9139 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
9c08d1fa 9140 (match_operator:SI 2 "shift_operator"
d5d4dc8d 9141 [(match_operand:SI 3 "s_register_operand" "r,r")
9142 (match_operand:SI 4 "shift_amount_operand" "M,r")])))]
9143 "TARGET_32BIT"
6c4c2133 9144 "sub%?\\t%0, %1, %3%S2"
344495ea 9145 [(set_attr "predicable" "yes")
2df5a382 9146 (set_attr "predicable_short_it" "no")
331beb1a 9147 (set_attr "shift" "3")
d5d4dc8d 9148 (set_attr "arch" "32,a")
d82e788e 9149 (set_attr "type" "alus_shift_imm,alus_shift_reg")])
9c08d1fa 9150
f7fbdd4a 9151(define_insn "*sub_shiftsi_compare0"
bd5b4116 9152 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 9153 (compare:CC_NOOV
d82e788e 9154 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
40dbec34 9155 (match_operator:SI 2 "shift_operator"
d82e788e 9156 [(match_operand:SI 3 "s_register_operand" "r,r,r")
9157 (match_operand:SI 4 "shift_amount_operand" "M,r,M")]))
40dbec34 9158 (const_int 0)))
d82e788e 9159 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
d5d4dc8d 9160 (minus:SI (match_dup 1)
9161 (match_op_dup 2 [(match_dup 3) (match_dup 4)])))]
9162 "TARGET_32BIT"
3ef90e77 9163 "subs%?\\t%0, %1, %3%S2"
344495ea 9164 [(set_attr "conds" "set")
a2cd141b 9165 (set_attr "shift" "3")
d82e788e 9166 (set_attr "arch" "32,a,a")
9167 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
9c08d1fa 9168
f7fbdd4a 9169(define_insn "*sub_shiftsi_compare0_scratch"
bd5b4116 9170 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 9171 (compare:CC_NOOV
d82e788e 9172 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
40dbec34 9173 (match_operator:SI 2 "shift_operator"
d82e788e 9174 [(match_operand:SI 3 "s_register_operand" "r,r,r")
9175 (match_operand:SI 4 "shift_amount_operand" "M,r,M")]))
40dbec34 9176 (const_int 0)))
d82e788e 9177 (clobber (match_scratch:SI 0 "=r,r,r"))]
d5d4dc8d 9178 "TARGET_32BIT"
3ef90e77 9179 "subs%?\\t%0, %1, %3%S2"
344495ea 9180 [(set_attr "conds" "set")
a2cd141b 9181 (set_attr "shift" "3")
d82e788e 9182 (set_attr "arch" "32,a,a")
9183 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
9c08d1fa 9184\f
9185
190efb17 9186(define_insn_and_split "*and_scc"
9c08d1fa 9187 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9188 (and:SI (match_operator:SI 1 "arm_comparison_operator"
190efb17 9189 [(match_operand 2 "cc_register" "") (const_int 0)])
9190 (match_operand:SI 3 "s_register_operand" "r")))]
cffb2a26 9191 "TARGET_ARM"
190efb17 9192 "#" ; "mov%D1\\t%0, #0\;and%d1\\t%0, %3, #1"
9193 "&& reload_completed"
9194 [(cond_exec (match_dup 5) (set (match_dup 0) (const_int 0)))
9195 (cond_exec (match_dup 4) (set (match_dup 0)
9196 (and:SI (match_dup 3) (const_int 1))))]
9197 {
3754d046 9198 machine_mode mode = GET_MODE (operands[2]);
190efb17 9199 enum rtx_code rc = GET_CODE (operands[1]);
9200
9201 /* Note that operands[4] is the same as operands[1],
9202 but with VOIDmode as the result. */
9203 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
9204 if (mode == CCFPmode || mode == CCFPEmode)
9205 rc = reverse_condition_maybe_unordered (rc);
9206 else
9207 rc = reverse_condition (rc);
9208 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
9209 }
8fa3ba89 9210 [(set_attr "conds" "use")
1b7da4ac 9211 (set_attr "type" "multiple")
8fa3ba89 9212 (set_attr "length" "8")]
9213)
9c08d1fa 9214
190efb17 9215(define_insn_and_split "*ior_scc"
9c08d1fa 9216 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
190efb17 9217 (ior:SI (match_operator:SI 1 "arm_comparison_operator"
9218 [(match_operand 2 "cc_register" "") (const_int 0)])
9219 (match_operand:SI 3 "s_register_operand" "0,?r")))]
cffb2a26 9220 "TARGET_ARM"
e2348bcb 9221 "@
190efb17 9222 orr%d1\\t%0, %3, #1
9223 #"
9224 "&& reload_completed
9225 && REGNO (operands [0]) != REGNO (operands[3])"
9226 ;; && which_alternative == 1
9227 ; mov%D1\\t%0, %3\;orr%d1\\t%0, %3, #1
9228 [(cond_exec (match_dup 5) (set (match_dup 0) (match_dup 3)))
9229 (cond_exec (match_dup 4) (set (match_dup 0)
9230 (ior:SI (match_dup 3) (const_int 1))))]
9231 {
3754d046 9232 machine_mode mode = GET_MODE (operands[2]);
190efb17 9233 enum rtx_code rc = GET_CODE (operands[1]);
9234
9235 /* Note that operands[4] is the same as operands[1],
9236 but with VOIDmode as the result. */
9237 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
9238 if (mode == CCFPmode || mode == CCFPEmode)
9239 rc = reverse_condition_maybe_unordered (rc);
9240 else
9241 rc = reverse_condition (rc);
9242 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
9243 }
8fa3ba89 9244 [(set_attr "conds" "use")
1b7da4ac 9245 (set_attr "length" "4,8")
9246 (set_attr "type" "logic_imm,multiple")]
8fa3ba89 9247)
9c08d1fa 9248
2df9477b 9249; A series of splitters for the compare_scc pattern below. Note that
9250; order is important.
9251(define_split
9252 [(set (match_operand:SI 0 "s_register_operand" "")
9253 (lt:SI (match_operand:SI 1 "s_register_operand" "")
9254 (const_int 0)))
9255 (clobber (reg:CC CC_REGNUM))]
9256 "TARGET_32BIT && reload_completed"
9257 [(set (match_dup 0) (lshiftrt:SI (match_dup 1) (const_int 31)))])
9258
9259(define_split
9260 [(set (match_operand:SI 0 "s_register_operand" "")
9261 (ge:SI (match_operand:SI 1 "s_register_operand" "")
9262 (const_int 0)))
9263 (clobber (reg:CC CC_REGNUM))]
9264 "TARGET_32BIT && reload_completed"
9265 [(set (match_dup 0) (not:SI (match_dup 1)))
9266 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 31)))])
9267
98562479 9268(define_split
9269 [(set (match_operand:SI 0 "s_register_operand" "")
9270 (eq:SI (match_operand:SI 1 "s_register_operand" "")
9271 (const_int 0)))
9272 (clobber (reg:CC CC_REGNUM))]
b232e6b5 9273 "arm_arch5t && TARGET_32BIT"
98562479 9274 [(set (match_dup 0) (clz:SI (match_dup 1)))
9275 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 5)))]
9276)
9277
2df9477b 9278(define_split
9279 [(set (match_operand:SI 0 "s_register_operand" "")
9280 (eq:SI (match_operand:SI 1 "s_register_operand" "")
9281 (const_int 0)))
9282 (clobber (reg:CC CC_REGNUM))]
9283 "TARGET_32BIT && reload_completed"
9284 [(parallel
080c0b9a 9285 [(set (reg:CC CC_REGNUM)
9286 (compare:CC (const_int 1) (match_dup 1)))
2df9477b 9287 (set (match_dup 0)
9288 (minus:SI (const_int 1) (match_dup 1)))])
080c0b9a 9289 (cond_exec (ltu:CC (reg:CC CC_REGNUM) (const_int 0))
2df9477b 9290 (set (match_dup 0) (const_int 0)))])
9291
9292(define_split
9293 [(set (match_operand:SI 0 "s_register_operand" "")
9294 (ne:SI (match_operand:SI 1 "s_register_operand" "")
9295 (match_operand:SI 2 "const_int_operand" "")))
9296 (clobber (reg:CC CC_REGNUM))]
9297 "TARGET_32BIT && reload_completed"
9298 [(parallel
9299 [(set (reg:CC CC_REGNUM)
9300 (compare:CC (match_dup 1) (match_dup 2)))
9301 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))])
9302 (cond_exec (ne:CC (reg:CC CC_REGNUM) (const_int 0))
9303 (set (match_dup 0) (const_int 1)))]
9304{
9305 operands[3] = GEN_INT (-INTVAL (operands[2]));
9306})
9307
9308(define_split
9309 [(set (match_operand:SI 0 "s_register_operand" "")
9310 (ne:SI (match_operand:SI 1 "s_register_operand" "")
9311 (match_operand:SI 2 "arm_add_operand" "")))
9312 (clobber (reg:CC CC_REGNUM))]
9313 "TARGET_32BIT && reload_completed"
9314 [(parallel
9315 [(set (reg:CC_NOOV CC_REGNUM)
9316 (compare:CC_NOOV (minus:SI (match_dup 1) (match_dup 2))
9317 (const_int 0)))
9318 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
9319 (cond_exec (ne:CC_NOOV (reg:CC_NOOV CC_REGNUM) (const_int 0))
9320 (set (match_dup 0) (const_int 1)))])
9321
9322(define_insn_and_split "*compare_scc"
fd711051 9323 [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts")
8fa3ba89 9324 (match_operator:SI 1 "arm_comparison_operator"
5565501b 9325 [(match_operand:SI 2 "s_register_operand" "r,r")
9326 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
bd5b4116 9327 (clobber (reg:CC CC_REGNUM))]
2df9477b 9328 "TARGET_32BIT"
9329 "#"
9330 "&& reload_completed"
9331 [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 3)))
9332 (cond_exec (match_dup 4) (set (match_dup 0) (const_int 0)))
9333 (cond_exec (match_dup 5) (set (match_dup 0) (const_int 1)))]
9334{
9335 rtx tmp1;
3754d046 9336 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
2df9477b 9337 operands[2], operands[3]);
9338 enum rtx_code rc = GET_CODE (operands[1]);
e2348bcb 9339
2df9477b 9340 tmp1 = gen_rtx_REG (mode, CC_REGNUM);
080c0b9a 9341
2df9477b 9342 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
9343 if (mode == CCFPmode || mode == CCFPEmode)
9344 rc = reverse_condition_maybe_unordered (rc);
9345 else
9346 rc = reverse_condition (rc);
9347 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
1b7da4ac 9348}
9349 [(set_attr "type" "multiple")]
9350)
9c08d1fa 9351
080c0b9a 9352;; Attempt to improve the sequence generated by the compare_scc splitters
9353;; not to use conditional execution.
98562479 9354
9355;; Rd = (eq (reg1) (const_int0)) // ARMv5
9356;; clz Rd, reg1
9357;; lsr Rd, Rd, #5
080c0b9a 9358(define_peephole2
9359 [(set (reg:CC CC_REGNUM)
9360 (compare:CC (match_operand:SI 1 "register_operand" "")
98562479 9361 (const_int 0)))
9362 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
9363 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
9364 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
9365 (set (match_dup 0) (const_int 1)))]
b232e6b5 9366 "arm_arch5t && TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)"
98562479 9367 [(set (match_dup 0) (clz:SI (match_dup 1)))
9368 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 5)))]
9369)
9370
9371;; Rd = (eq (reg1) (const_int0)) // !ARMv5
9372;; negs Rd, reg1
9373;; adc Rd, Rd, reg1
9374(define_peephole2
9375 [(set (reg:CC CC_REGNUM)
9376 (compare:CC (match_operand:SI 1 "register_operand" "")
9377 (const_int 0)))
080c0b9a 9378 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
9379 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
9380 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
9381 (set (match_dup 0) (const_int 1)))
98562479 9382 (match_scratch:SI 2 "r")]
9383 "TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)"
922b6913 9384 [(parallel
9385 [(set (reg:CC CC_REGNUM)
98562479 9386 (compare:CC (const_int 0) (match_dup 1)))
9387 (set (match_dup 2) (minus:SI (const_int 0) (match_dup 1)))])
9388 (set (match_dup 0)
9389 (plus:SI (plus:SI (match_dup 1) (match_dup 2))
9390 (geu:SI (reg:CC CC_REGNUM) (const_int 0))))]
9391)
9392
31991287 9393;; Rd = (eq (reg1) (reg2/imm)) // ARMv5 and optimising for speed.
98562479 9394;; sub Rd, Reg1, reg2
9395;; clz Rd, Rd
9396;; lsr Rd, Rd, #5
9397(define_peephole2
9398 [(set (reg:CC CC_REGNUM)
9399 (compare:CC (match_operand:SI 1 "register_operand" "")
9400 (match_operand:SI 2 "arm_rhs_operand" "")))
9401 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
9402 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
9403 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
9404 (set (match_dup 0) (const_int 1)))]
b232e6b5 9405 "arm_arch5t && TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)
31991287 9406 && !(TARGET_THUMB2 && optimize_insn_for_size_p ())"
98562479 9407 [(set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))
9408 (set (match_dup 0) (clz:SI (match_dup 0)))
9409 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 5)))]
9410)
9411
9412
31991287 9413;; Rd = (eq (reg1) (reg2)) // ! ARMv5 or optimising for size.
98562479 9414;; sub T1, Reg1, reg2
9415;; negs Rd, T1
9416;; adc Rd, Rd, T1
9417(define_peephole2
9418 [(set (reg:CC CC_REGNUM)
9419 (compare:CC (match_operand:SI 1 "register_operand" "")
9420 (match_operand:SI 2 "arm_rhs_operand" "")))
9421 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
9422 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
9423 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
9424 (set (match_dup 0) (const_int 1)))
9425 (match_scratch:SI 3 "r")]
9426 "TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)"
31991287 9427 [(set (match_dup 3) (match_dup 4))
080c0b9a 9428 (parallel
9429 [(set (reg:CC CC_REGNUM)
9430 (compare:CC (const_int 0) (match_dup 3)))
9431 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 3)))])
98562479 9432 (set (match_dup 0)
9433 (plus:SI (plus:SI (match_dup 0) (match_dup 3))
9434 (geu:SI (reg:CC CC_REGNUM) (const_int 0))))]
31991287 9435 "
9436 if (CONST_INT_P (operands[2]))
9437 operands[4] = plus_constant (SImode, operands[1], -INTVAL (operands[2]));
9438 else
9439 operands[4] = gen_rtx_MINUS (SImode, operands[1], operands[2]);
9440 ")
080c0b9a 9441
f7fbdd4a 9442(define_insn "*cond_move"
9c08d1fa 9443 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
aea4c774 9444 (if_then_else:SI (match_operator 3 "equality_operator"
8fa3ba89 9445 [(match_operator 4 "arm_comparison_operator"
8a18b90c 9446 [(match_operand 5 "cc_register" "") (const_int 0)])
aea4c774 9447 (const_int 0)])
9448 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9449 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
cffb2a26 9450 "TARGET_ARM"
9c08d1fa 9451 "*
8fa3ba89 9452 if (GET_CODE (operands[3]) == NE)
9453 {
9454 if (which_alternative != 1)
9455 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
9456 if (which_alternative != 0)
9457 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
9458 return \"\";
9459 }
9460 if (which_alternative != 0)
9461 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9462 if (which_alternative != 1)
9463 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
9464 return \"\";
9465 "
9466 [(set_attr "conds" "use")
282b4c75 9467 (set_attr_alternative "type"
9468 [(if_then_else (match_operand 2 "const_int_operand" "")
9469 (const_string "mov_imm")
9470 (const_string "mov_reg"))
9471 (if_then_else (match_operand 1 "const_int_operand" "")
9472 (const_string "mov_imm")
9473 (const_string "mov_reg"))
9474 (const_string "multiple")])
8fa3ba89 9475 (set_attr "length" "4,4,8")]
9476)
9c08d1fa 9477
f7fbdd4a 9478(define_insn "*cond_arith"
9c08d1fa 9479 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9480 (match_operator:SI 5 "shiftable_operator"
8fa3ba89 9481 [(match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 9482 [(match_operand:SI 2 "s_register_operand" "r,r")
9483 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
9484 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 9485 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9486 "TARGET_ARM"
9c08d1fa 9487 "*
8fa3ba89 9488 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
9489 return \"%i5\\t%0, %1, %2, lsr #31\";
40dbec34 9490
8fa3ba89 9491 output_asm_insn (\"cmp\\t%2, %3\", operands);
9492 if (GET_CODE (operands[5]) == AND)
9493 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
9494 else if (GET_CODE (operands[5]) == MINUS)
9495 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
9496 else if (which_alternative != 0)
9497 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9498 return \"%i5%d4\\t%0, %1, #1\";
9499 "
9500 [(set_attr "conds" "clob")
1b7da4ac 9501 (set_attr "length" "12")
9502 (set_attr "type" "multiple")]
8fa3ba89 9503)
9c08d1fa 9504
f7fbdd4a 9505(define_insn "*cond_sub"
9c08d1fa 9506 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9507 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8fa3ba89 9508 (match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 9509 [(match_operand:SI 2 "s_register_operand" "r,r")
9510 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 9511 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9512 "TARGET_ARM"
9c08d1fa 9513 "*
8fa3ba89 9514 output_asm_insn (\"cmp\\t%2, %3\", operands);
9515 if (which_alternative != 0)
9516 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9517 return \"sub%d4\\t%0, %1, #1\";
9518 "
9519 [(set_attr "conds" "clob")
1b7da4ac 9520 (set_attr "length" "8,12")
9521 (set_attr "type" "multiple")]
8fa3ba89 9522)
9c08d1fa 9523
aea4c774 9524(define_insn "*cmp_ite0"
cffb2a26 9525 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 9526 (compare
9527 (if_then_else:SI
8fa3ba89 9528 (match_operator 4 "arm_comparison_operator"
2ff91fec 9529 [(match_operand:SI 0 "s_register_operand"
9530 "l,l,l,r,r,r,r,r,r")
9531 (match_operand:SI 1 "arm_add_operand"
9532 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
8fa3ba89 9533 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 9534 [(match_operand:SI 2 "s_register_operand"
9535 "l,r,r,l,l,r,r,r,r")
9536 (match_operand:SI 3 "arm_add_operand"
9537 "lPy,rI,L,lPy,lPy,rI,rI,L,L")])
aea4c774 9538 (const_int 0))
9539 (const_int 0)))]
2ff91fec 9540 "TARGET_32BIT"
9c08d1fa 9541 "*
aea4c774 9542 {
2ff91fec 9543 static const char * const cmp1[NUM_OF_COND_CMP][2] =
9544 {
9545 {\"cmp%d5\\t%0, %1\",
9546 \"cmp%d4\\t%2, %3\"},
9547 {\"cmn%d5\\t%0, #%n1\",
9548 \"cmp%d4\\t%2, %3\"},
9549 {\"cmp%d5\\t%0, %1\",
9550 \"cmn%d4\\t%2, #%n3\"},
9551 {\"cmn%d5\\t%0, #%n1\",
9552 \"cmn%d4\\t%2, #%n3\"}
9553 };
9554 static const char * const cmp2[NUM_OF_COND_CMP][2] =
9555 {
9556 {\"cmp\\t%2, %3\",
9557 \"cmp\\t%0, %1\"},
9558 {\"cmp\\t%2, %3\",
9559 \"cmn\\t%0, #%n1\"},
9560 {\"cmn\\t%2, #%n3\",
9561 \"cmp\\t%0, %1\"},
9562 {\"cmn\\t%2, #%n3\",
9563 \"cmn\\t%0, #%n1\"}
9564 };
9565 static const char * const ite[2] =
8fa3ba89 9566 {
2ff91fec 9567 \"it\\t%d5\",
9568 \"it\\t%d4\"
8fa3ba89 9569 };
2ff91fec 9570 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
9571 CMP_CMP, CMN_CMP, CMP_CMP,
9572 CMN_CMP, CMP_CMN, CMN_CMN};
8fa3ba89 9573 int swap =
9574 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9575
2ff91fec 9576 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9577 if (TARGET_THUMB2) {
9578 output_asm_insn (ite[swap], operands);
9579 }
9580 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9581 return \"\";
8fa3ba89 9582 }"
9583 [(set_attr "conds" "set")
2ff91fec 9584 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
8bdfd6ed 9585 (set_attr "enabled_for_short_it" "yes,no,no,no,no,no,no,no,no")
1b7da4ac 9586 (set_attr "type" "multiple")
2ff91fec 9587 (set_attr_alternative "length"
9588 [(const_int 6)
9589 (const_int 8)
9590 (const_int 8)
9591 (const_int 8)
9592 (const_int 8)
9593 (if_then_else (eq_attr "is_thumb" "no")
9594 (const_int 8)
9595 (const_int 10))
9596 (if_then_else (eq_attr "is_thumb" "no")
9597 (const_int 8)
9598 (const_int 10))
9599 (if_then_else (eq_attr "is_thumb" "no")
9600 (const_int 8)
9601 (const_int 10))
9602 (if_then_else (eq_attr "is_thumb" "no")
9603 (const_int 8)
9604 (const_int 10))])]
8fa3ba89 9605)
9c08d1fa 9606
aea4c774 9607(define_insn "*cmp_ite1"
cffb2a26 9608 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 9609 (compare
9610 (if_then_else:SI
8fa3ba89 9611 (match_operator 4 "arm_comparison_operator"
2ff91fec 9612 [(match_operand:SI 0 "s_register_operand"
9613 "l,l,l,r,r,r,r,r,r")
9614 (match_operand:SI 1 "arm_add_operand"
9615 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
8fa3ba89 9616 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 9617 [(match_operand:SI 2 "s_register_operand"
9618 "l,r,r,l,l,r,r,r,r")
9619 (match_operand:SI 3 "arm_add_operand"
9620 "lPy,rI,L,lPy,lPy,rI,rI,L,L")])
aea4c774 9621 (const_int 1))
9622 (const_int 0)))]
2ff91fec 9623 "TARGET_32BIT"
9c08d1fa 9624 "*
9c08d1fa 9625 {
2ff91fec 9626 static const char * const cmp1[NUM_OF_COND_CMP][2] =
9627 {
9628 {\"cmp\\t%0, %1\",
9629 \"cmp\\t%2, %3\"},
9630 {\"cmn\\t%0, #%n1\",
9631 \"cmp\\t%2, %3\"},
9632 {\"cmp\\t%0, %1\",
9633 \"cmn\\t%2, #%n3\"},
9634 {\"cmn\\t%0, #%n1\",
9635 \"cmn\\t%2, #%n3\"}
9636 };
9637 static const char * const cmp2[NUM_OF_COND_CMP][2] =
215b30b3 9638 {
2ff91fec 9639 {\"cmp%d4\\t%2, %3\",
9640 \"cmp%D5\\t%0, %1\"},
9641 {\"cmp%d4\\t%2, %3\",
9642 \"cmn%D5\\t%0, #%n1\"},
9643 {\"cmn%d4\\t%2, #%n3\",
9644 \"cmp%D5\\t%0, %1\"},
9645 {\"cmn%d4\\t%2, #%n3\",
9646 \"cmn%D5\\t%0, #%n1\"}
215b30b3 9647 };
2ff91fec 9648 static const char * const ite[2] =
9649 {
9650 \"it\\t%d4\",
9651 \"it\\t%D5\"
9652 };
9653 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
9654 CMP_CMP, CMN_CMP, CMP_CMP,
9655 CMN_CMP, CMP_CMN, CMN_CMN};
215b30b3 9656 int swap =
9657 comparison_dominates_p (GET_CODE (operands[5]),
9658 reverse_condition (GET_CODE (operands[4])));
9659
2ff91fec 9660 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9661 if (TARGET_THUMB2) {
9662 output_asm_insn (ite[swap], operands);
9663 }
9664 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9665 return \"\";
215b30b3 9666 }"
8fa3ba89 9667 [(set_attr "conds" "set")
2ff91fec 9668 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
8bdfd6ed 9669 (set_attr "enabled_for_short_it" "yes,no,no,no,no,no,no,no,no")
2ff91fec 9670 (set_attr_alternative "length"
9671 [(const_int 6)
9672 (const_int 8)
9673 (const_int 8)
9674 (const_int 8)
9675 (const_int 8)
9676 (if_then_else (eq_attr "is_thumb" "no")
9677 (const_int 8)
9678 (const_int 10))
9679 (if_then_else (eq_attr "is_thumb" "no")
9680 (const_int 8)
9681 (const_int 10))
9682 (if_then_else (eq_attr "is_thumb" "no")
9683 (const_int 8)
9684 (const_int 10))
9685 (if_then_else (eq_attr "is_thumb" "no")
9686 (const_int 8)
1b7da4ac 9687 (const_int 10))])
9688 (set_attr "type" "multiple")]
8fa3ba89 9689)
9c08d1fa 9690
f6c53574 9691(define_insn "*cmp_and"
9692 [(set (match_operand 6 "dominant_cc_register" "")
9693 (compare
9694 (and:SI
9695 (match_operator 4 "arm_comparison_operator"
2ff91fec 9696 [(match_operand:SI 0 "s_register_operand"
9697 "l,l,l,r,r,r,r,r,r")
9698 (match_operand:SI 1 "arm_add_operand"
9699 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
f6c53574 9700 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 9701 [(match_operand:SI 2 "s_register_operand"
9702 "l,r,r,l,l,r,r,r,r")
9703 (match_operand:SI 3 "arm_add_operand"
9704 "lPy,rI,L,lPy,lPy,rI,rI,L,L")]))
f6c53574 9705 (const_int 0)))]
2ff91fec 9706 "TARGET_32BIT"
f6c53574 9707 "*
9708 {
2ff91fec 9709 static const char *const cmp1[NUM_OF_COND_CMP][2] =
f6c53574 9710 {
2ff91fec 9711 {\"cmp%d5\\t%0, %1\",
9712 \"cmp%d4\\t%2, %3\"},
9713 {\"cmn%d5\\t%0, #%n1\",
9714 \"cmp%d4\\t%2, %3\"},
9715 {\"cmp%d5\\t%0, %1\",
9716 \"cmn%d4\\t%2, #%n3\"},
9717 {\"cmn%d5\\t%0, #%n1\",
9718 \"cmn%d4\\t%2, #%n3\"}
f6c53574 9719 };
2ff91fec 9720 static const char *const cmp2[NUM_OF_COND_CMP][2] =
9721 {
9722 {\"cmp\\t%2, %3\",
9723 \"cmp\\t%0, %1\"},
9724 {\"cmp\\t%2, %3\",
9725 \"cmn\\t%0, #%n1\"},
9726 {\"cmn\\t%2, #%n3\",
9727 \"cmp\\t%0, %1\"},
9728 {\"cmn\\t%2, #%n3\",
9729 \"cmn\\t%0, #%n1\"}
9730 };
9731 static const char *const ite[2] =
9732 {
9733 \"it\\t%d5\",
9734 \"it\\t%d4\"
9735 };
9736 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
9737 CMP_CMP, CMN_CMP, CMP_CMP,
9738 CMN_CMP, CMP_CMN, CMN_CMN};
f6c53574 9739 int swap =
9740 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9741
2ff91fec 9742 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9743 if (TARGET_THUMB2) {
9744 output_asm_insn (ite[swap], operands);
9745 }
9746 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9747 return \"\";
f6c53574 9748 }"
9749 [(set_attr "conds" "set")
9750 (set_attr "predicable" "no")
2ff91fec 9751 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
8bdfd6ed 9752 (set_attr "enabled_for_short_it" "yes,no,no,no,no,no,no,no,no")
2ff91fec 9753 (set_attr_alternative "length"
9754 [(const_int 6)
9755 (const_int 8)
9756 (const_int 8)
9757 (const_int 8)
9758 (const_int 8)
9759 (if_then_else (eq_attr "is_thumb" "no")
9760 (const_int 8)
9761 (const_int 10))
9762 (if_then_else (eq_attr "is_thumb" "no")
9763 (const_int 8)
9764 (const_int 10))
9765 (if_then_else (eq_attr "is_thumb" "no")
9766 (const_int 8)
9767 (const_int 10))
9768 (if_then_else (eq_attr "is_thumb" "no")
9769 (const_int 8)
1b7da4ac 9770 (const_int 10))])
9771 (set_attr "type" "multiple")]
f6c53574 9772)
9773
9774(define_insn "*cmp_ior"
9775 [(set (match_operand 6 "dominant_cc_register" "")
9776 (compare
9777 (ior:SI
9778 (match_operator 4 "arm_comparison_operator"
2ff91fec 9779 [(match_operand:SI 0 "s_register_operand"
9780 "l,l,l,r,r,r,r,r,r")
9781 (match_operand:SI 1 "arm_add_operand"
9782 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
f6c53574 9783 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 9784 [(match_operand:SI 2 "s_register_operand"
9785 "l,r,r,l,l,r,r,r,r")
9786 (match_operand:SI 3 "arm_add_operand"
9787 "lPy,rI,L,lPy,lPy,rI,rI,L,L")]))
f6c53574 9788 (const_int 0)))]
2ff91fec 9789 "TARGET_32BIT"
f6c53574 9790 "*
f6c53574 9791 {
2ff91fec 9792 static const char *const cmp1[NUM_OF_COND_CMP][2] =
9793 {
9794 {\"cmp\\t%0, %1\",
9795 \"cmp\\t%2, %3\"},
9796 {\"cmn\\t%0, #%n1\",
9797 \"cmp\\t%2, %3\"},
9798 {\"cmp\\t%0, %1\",
9799 \"cmn\\t%2, #%n3\"},
9800 {\"cmn\\t%0, #%n1\",
9801 \"cmn\\t%2, #%n3\"}
9802 };
9803 static const char *const cmp2[NUM_OF_COND_CMP][2] =
9804 {
9805 {\"cmp%D4\\t%2, %3\",
9806 \"cmp%D5\\t%0, %1\"},
9807 {\"cmp%D4\\t%2, %3\",
9808 \"cmn%D5\\t%0, #%n1\"},
9809 {\"cmn%D4\\t%2, #%n3\",
9810 \"cmp%D5\\t%0, %1\"},
9811 {\"cmn%D4\\t%2, #%n3\",
9812 \"cmn%D5\\t%0, #%n1\"}
9813 };
9814 static const char *const ite[2] =
9815 {
9816 \"it\\t%D4\",
9817 \"it\\t%D5\"
9818 };
9819 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
9820 CMP_CMP, CMN_CMP, CMP_CMP,
9821 CMN_CMP, CMP_CMN, CMN_CMN};
9822 int swap =
9823 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9824
9825 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9826 if (TARGET_THUMB2) {
9827 output_asm_insn (ite[swap], operands);
9828 }
9829 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9830 return \"\";
9831 }
9832 "
f6c53574 9833 [(set_attr "conds" "set")
2ff91fec 9834 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
8bdfd6ed 9835 (set_attr "enabled_for_short_it" "yes,no,no,no,no,no,no,no,no")
2ff91fec 9836 (set_attr_alternative "length"
9837 [(const_int 6)
9838 (const_int 8)
9839 (const_int 8)
9840 (const_int 8)
9841 (const_int 8)
9842 (if_then_else (eq_attr "is_thumb" "no")
9843 (const_int 8)
9844 (const_int 10))
9845 (if_then_else (eq_attr "is_thumb" "no")
9846 (const_int 8)
9847 (const_int 10))
9848 (if_then_else (eq_attr "is_thumb" "no")
9849 (const_int 8)
9850 (const_int 10))
9851 (if_then_else (eq_attr "is_thumb" "no")
9852 (const_int 8)
1b7da4ac 9853 (const_int 10))])
9854 (set_attr "type" "multiple")]
f6c53574 9855)
9856
3c5afce6 9857(define_insn_and_split "*ior_scc_scc"
f9d240a0 9858 [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts")
3c5afce6 9859 (ior:SI (match_operator:SI 3 "arm_comparison_operator"
f9d240a0 9860 [(match_operand:SI 1 "s_register_operand" "l,r")
9861 (match_operand:SI 2 "arm_add_operand" "lPy,rIL")])
3c5afce6 9862 (match_operator:SI 6 "arm_comparison_operator"
f9d240a0 9863 [(match_operand:SI 4 "s_register_operand" "l,r")
9864 (match_operand:SI 5 "arm_add_operand" "lPy,rIL")])))
3c5afce6 9865 (clobber (reg:CC CC_REGNUM))]
2ff91fec 9866 "TARGET_32BIT
3c5afce6 9867 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
9868 != CCmode)"
9869 "#"
2ff91fec 9870 "TARGET_32BIT && reload_completed"
3c5afce6 9871 [(set (match_dup 7)
9872 (compare
9873 (ior:SI
9874 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9875 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9876 (const_int 0)))
9877 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9878 "operands[7]
9879 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9880 DOM_CC_X_OR_Y),
601f584c 9881 CC_REGNUM);"
9882 [(set_attr "conds" "clob")
8bdfd6ed 9883 (set_attr "enabled_for_short_it" "yes,no")
1b7da4ac 9884 (set_attr "length" "16")
9885 (set_attr "type" "multiple")]
9886)
601f584c 9887
9888; If the above pattern is followed by a CMP insn, then the compare is
9889; redundant, since we can rework the conditional instruction that follows.
9890(define_insn_and_split "*ior_scc_scc_cmp"
9891 [(set (match_operand 0 "dominant_cc_register" "")
9892 (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
f9d240a0 9893 [(match_operand:SI 1 "s_register_operand" "l,r")
9894 (match_operand:SI 2 "arm_add_operand" "lPy,rIL")])
601f584c 9895 (match_operator:SI 6 "arm_comparison_operator"
f9d240a0 9896 [(match_operand:SI 4 "s_register_operand" "l,r")
9897 (match_operand:SI 5 "arm_add_operand" "lPy,rIL")]))
601f584c 9898 (const_int 0)))
f9d240a0 9899 (set (match_operand:SI 7 "s_register_operand" "=Ts,Ts")
601f584c 9900 (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9901 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
2ff91fec 9902 "TARGET_32BIT"
601f584c 9903 "#"
2ff91fec 9904 "TARGET_32BIT && reload_completed"
601f584c 9905 [(set (match_dup 0)
9906 (compare
9907 (ior:SI
9908 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9909 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9910 (const_int 0)))
9911 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9912 ""
9913 [(set_attr "conds" "set")
8bdfd6ed 9914 (set_attr "enabled_for_short_it" "yes,no")
1b7da4ac 9915 (set_attr "length" "16")
9916 (set_attr "type" "multiple")]
9917)
3c5afce6 9918
9919(define_insn_and_split "*and_scc_scc"
f9d240a0 9920 [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts")
3c5afce6 9921 (and:SI (match_operator:SI 3 "arm_comparison_operator"
f9d240a0 9922 [(match_operand:SI 1 "s_register_operand" "l,r")
9923 (match_operand:SI 2 "arm_add_operand" "lPy,rIL")])
3c5afce6 9924 (match_operator:SI 6 "arm_comparison_operator"
f9d240a0 9925 [(match_operand:SI 4 "s_register_operand" "l,r")
9926 (match_operand:SI 5 "arm_add_operand" "lPy,rIL")])))
3c5afce6 9927 (clobber (reg:CC CC_REGNUM))]
2ff91fec 9928 "TARGET_32BIT
3c5afce6 9929 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9930 != CCmode)"
9931 "#"
2ff91fec 9932 "TARGET_32BIT && reload_completed
601f584c 9933 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9934 != CCmode)"
3c5afce6 9935 [(set (match_dup 7)
9936 (compare
9937 (and:SI
9938 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9939 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9940 (const_int 0)))
9941 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9942 "operands[7]
9943 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9944 DOM_CC_X_AND_Y),
601f584c 9945 CC_REGNUM);"
9946 [(set_attr "conds" "clob")
8bdfd6ed 9947 (set_attr "enabled_for_short_it" "yes,no")
1b7da4ac 9948 (set_attr "length" "16")
9949 (set_attr "type" "multiple")]
9950)
601f584c 9951
9952; If the above pattern is followed by a CMP insn, then the compare is
9953; redundant, since we can rework the conditional instruction that follows.
9954(define_insn_and_split "*and_scc_scc_cmp"
9955 [(set (match_operand 0 "dominant_cc_register" "")
9956 (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
f9d240a0 9957 [(match_operand:SI 1 "s_register_operand" "l,r")
9958 (match_operand:SI 2 "arm_add_operand" "lPy,rIL")])
601f584c 9959 (match_operator:SI 6 "arm_comparison_operator"
f9d240a0 9960 [(match_operand:SI 4 "s_register_operand" "l,r")
9961 (match_operand:SI 5 "arm_add_operand" "lPy,rIL")]))
601f584c 9962 (const_int 0)))
f9d240a0 9963 (set (match_operand:SI 7 "s_register_operand" "=Ts,Ts")
601f584c 9964 (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9965 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
2ff91fec 9966 "TARGET_32BIT"
601f584c 9967 "#"
2ff91fec 9968 "TARGET_32BIT && reload_completed"
601f584c 9969 [(set (match_dup 0)
9970 (compare
9971 (and:SI
9972 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9973 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9974 (const_int 0)))
9975 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9976 ""
9977 [(set_attr "conds" "set")
8bdfd6ed 9978 (set_attr "enabled_for_short_it" "yes,no")
1b7da4ac 9979 (set_attr "length" "16")
9980 (set_attr "type" "multiple")]
9981)
601f584c 9982
9983;; If there is no dominance in the comparison, then we can still save an
9984;; instruction in the AND case, since we can know that the second compare
9985;; need only zero the value if false (if true, then the value is already
9986;; correct).
9987(define_insn_and_split "*and_scc_scc_nodom"
fd711051 9988 [(set (match_operand:SI 0 "s_register_operand" "=&Ts,&Ts,&Ts")
601f584c 9989 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9990 [(match_operand:SI 1 "s_register_operand" "r,r,0")
9991 (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
9992 (match_operator:SI 6 "arm_comparison_operator"
9993 [(match_operand:SI 4 "s_register_operand" "r,r,r")
9994 (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
9995 (clobber (reg:CC CC_REGNUM))]
2ff91fec 9996 "TARGET_32BIT
601f584c 9997 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9998 == CCmode)"
9999 "#"
2ff91fec 10000 "TARGET_32BIT && reload_completed"
601f584c 10001 [(parallel [(set (match_dup 0)
10002 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
10003 (clobber (reg:CC CC_REGNUM))])
10004 (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
10005 (set (match_dup 0)
10006 (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
10007 (match_dup 0)
10008 (const_int 0)))]
10009 "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
10010 operands[4], operands[5]),
10011 CC_REGNUM);
10012 operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
10013 operands[5]);"
10014 [(set_attr "conds" "clob")
1b7da4ac 10015 (set_attr "length" "20")
10016 (set_attr "type" "multiple")]
10017)
3c5afce6 10018
3a0bdee0 10019(define_split
10020 [(set (reg:CC_NOOV CC_REGNUM)
10021 (compare:CC_NOOV (ior:SI
10022 (and:SI (match_operand:SI 0 "s_register_operand" "")
10023 (const_int 1))
b0694be0 10024 (match_operator:SI 1 "arm_comparison_operator"
3a0bdee0 10025 [(match_operand:SI 2 "s_register_operand" "")
10026 (match_operand:SI 3 "arm_add_operand" "")]))
10027 (const_int 0)))
10028 (clobber (match_operand:SI 4 "s_register_operand" ""))]
10029 "TARGET_ARM"
10030 [(set (match_dup 4)
10031 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
10032 (match_dup 0)))
10033 (set (reg:CC_NOOV CC_REGNUM)
10034 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
10035 (const_int 0)))]
10036 "")
10037
10038(define_split
10039 [(set (reg:CC_NOOV CC_REGNUM)
10040 (compare:CC_NOOV (ior:SI
b0694be0 10041 (match_operator:SI 1 "arm_comparison_operator"
3a0bdee0 10042 [(match_operand:SI 2 "s_register_operand" "")
10043 (match_operand:SI 3 "arm_add_operand" "")])
10044 (and:SI (match_operand:SI 0 "s_register_operand" "")
10045 (const_int 1)))
10046 (const_int 0)))
10047 (clobber (match_operand:SI 4 "s_register_operand" ""))]
10048 "TARGET_ARM"
10049 [(set (match_dup 4)
10050 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
10051 (match_dup 0)))
10052 (set (reg:CC_NOOV CC_REGNUM)
10053 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
10054 (const_int 0)))]
10055 "")
25f905c2 10056;; ??? The conditional patterns above need checking for Thumb-2 usefulness
3a0bdee0 10057
190efb17 10058(define_insn_and_split "*negscc"
9c08d1fa 10059 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 10060 (neg:SI (match_operator 3 "arm_comparison_operator"
9c08d1fa 10061 [(match_operand:SI 1 "s_register_operand" "r")
10062 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
bd5b4116 10063 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10064 "TARGET_ARM"
190efb17 10065 "#"
10066 "&& reload_completed"
10067 [(const_int 0)]
10068 {
10069 rtx cc_reg = gen_rtx_REG (CCmode, CC_REGNUM);
e2348bcb 10070
190efb17 10071 if (GET_CODE (operands[3]) == LT && operands[2] == const0_rtx)
10072 {
10073 /* Emit mov\\t%0, %1, asr #31 */
d1f9b275 10074 emit_insn (gen_rtx_SET (operands[0],
190efb17 10075 gen_rtx_ASHIFTRT (SImode,
10076 operands[1],
10077 GEN_INT (31))));
10078 DONE;
10079 }
10080 else if (GET_CODE (operands[3]) == NE)
10081 {
10082 /* Emit subs\\t%0, %1, %2\;mvnne\\t%0, #0 */
10083 if (CONST_INT_P (operands[2]))
10084 emit_insn (gen_cmpsi2_addneg (operands[0], operands[1], operands[2],
10085 GEN_INT (- INTVAL (operands[2]))));
10086 else
10087 emit_insn (gen_subsi3_compare (operands[0], operands[1], operands[2]));
10088
10089 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
10090 gen_rtx_NE (SImode,
10091 cc_reg,
10092 const0_rtx),
d1f9b275 10093 gen_rtx_SET (operands[0],
190efb17 10094 GEN_INT (~0))));
10095 DONE;
10096 }
10097 else
10098 {
10099 /* Emit: cmp\\t%1, %2\;mov%D3\\t%0, #0\;mvn%d3\\t%0, #0 */
d1f9b275 10100 emit_insn (gen_rtx_SET (cc_reg,
190efb17 10101 gen_rtx_COMPARE (CCmode, operands[1], operands[2])));
10102 enum rtx_code rc = GET_CODE (operands[3]);
10103
10104 rc = reverse_condition (rc);
10105 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
10106 gen_rtx_fmt_ee (rc,
10107 VOIDmode,
10108 cc_reg,
10109 const0_rtx),
d1f9b275 10110 gen_rtx_SET (operands[0], const0_rtx)));
190efb17 10111 rc = GET_CODE (operands[3]);
10112 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
10113 gen_rtx_fmt_ee (rc,
10114 VOIDmode,
10115 cc_reg,
10116 const0_rtx),
d1f9b275 10117 gen_rtx_SET (operands[0],
190efb17 10118 GEN_INT (~0))));
10119 DONE;
10120 }
10121 FAIL;
10122 }
8fa3ba89 10123 [(set_attr "conds" "clob")
1b7da4ac 10124 (set_attr "length" "12")
10125 (set_attr "type" "multiple")]
8fa3ba89 10126)
9c08d1fa 10127
90404b57 10128(define_insn_and_split "movcond_addsi"
10129 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r")
10130 (if_then_else:SI
10131 (match_operator 5 "comparison_operator"
10132 [(plus:SI (match_operand:SI 3 "s_register_operand" "r,r,r")
10133 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL"))
10134 (const_int 0)])
10135 (match_operand:SI 1 "arm_rhs_operand" "rI,rPy,r")
10136 (match_operand:SI 2 "arm_rhs_operand" "rI,rPy,r")))
10137 (clobber (reg:CC CC_REGNUM))]
10138 "TARGET_32BIT"
10139 "#"
10140 "&& reload_completed"
10141 [(set (reg:CC_NOOV CC_REGNUM)
10142 (compare:CC_NOOV
10143 (plus:SI (match_dup 3)
10144 (match_dup 4))
10145 (const_int 0)))
10146 (set (match_dup 0) (match_dup 1))
10147 (cond_exec (match_dup 6)
10148 (set (match_dup 0) (match_dup 2)))]
10149 "
10150 {
3754d046 10151 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[5]),
90404b57 10152 operands[3], operands[4]);
10153 enum rtx_code rc = GET_CODE (operands[5]);
90404b57 10154 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
10155 gcc_assert (!(mode == CCFPmode || mode == CCFPEmode));
22440aeb 10156 if (!REG_P (operands[2]) || REGNO (operands[2]) != REGNO (operands[0]))
4d01ce2f 10157 rc = reverse_condition (rc);
f145bcba 10158 else
10159 std::swap (operands[1], operands[2]);
90404b57 10160
10161 operands[6] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10162 }
10163 "
10164 [(set_attr "conds" "clob")
8bdfd6ed 10165 (set_attr "enabled_for_short_it" "no,yes,yes")
1b7da4ac 10166 (set_attr "type" "multiple")]
90404b57 10167)
10168
9c08d1fa 10169(define_insn "movcond"
10170 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 10171 (if_then_else:SI
8fa3ba89 10172 (match_operator 5 "arm_comparison_operator"
5565501b 10173 [(match_operand:SI 3 "s_register_operand" "r,r,r")
10174 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
10175 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
10176 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 10177 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10178 "TARGET_ARM"
9c08d1fa 10179 "*
10180 if (GET_CODE (operands[5]) == LT
10181 && (operands[4] == const0_rtx))
10182 {
0438d37f 10183 if (which_alternative != 1 && REG_P (operands[1]))
9c08d1fa 10184 {
9c08d1fa 10185 if (operands[2] == const0_rtx)
e2348bcb 10186 return \"and\\t%0, %1, %3, asr #31\";
10187 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
9c08d1fa 10188 }
0438d37f 10189 else if (which_alternative != 0 && REG_P (operands[2]))
9c08d1fa 10190 {
9c08d1fa 10191 if (operands[1] == const0_rtx)
e2348bcb 10192 return \"bic\\t%0, %2, %3, asr #31\";
10193 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
9c08d1fa 10194 }
10195 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 10196 are constants. */
9c08d1fa 10197 }
e2348bcb 10198
9c08d1fa 10199 if (GET_CODE (operands[5]) == GE
10200 && (operands[4] == const0_rtx))
10201 {
0438d37f 10202 if (which_alternative != 1 && REG_P (operands[1]))
9c08d1fa 10203 {
9c08d1fa 10204 if (operands[2] == const0_rtx)
e2348bcb 10205 return \"bic\\t%0, %1, %3, asr #31\";
10206 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
9c08d1fa 10207 }
0438d37f 10208 else if (which_alternative != 0 && REG_P (operands[2]))
9c08d1fa 10209 {
9c08d1fa 10210 if (operands[1] == const0_rtx)
e2348bcb 10211 return \"and\\t%0, %2, %3, asr #31\";
10212 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
9c08d1fa 10213 }
10214 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 10215 are constants. */
9c08d1fa 10216 }
0438d37f 10217 if (CONST_INT_P (operands[4])
9c08d1fa 10218 && !const_ok_for_arm (INTVAL (operands[4])))
e2348bcb 10219 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
9c08d1fa 10220 else
e2348bcb 10221 output_asm_insn (\"cmp\\t%3, %4\", operands);
9c08d1fa 10222 if (which_alternative != 0)
e2348bcb 10223 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
9c08d1fa 10224 if (which_alternative != 1)
e2348bcb 10225 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
9c08d1fa 10226 return \"\";
215b30b3 10227 "
8fa3ba89 10228 [(set_attr "conds" "clob")
1b7da4ac 10229 (set_attr "length" "8,8,12")
10230 (set_attr "type" "multiple")]
8fa3ba89 10231)
9c08d1fa 10232
25f905c2 10233;; ??? The patterns below need checking for Thumb-2 usefulness.
10234
8a18b90c 10235(define_insn "*ifcompare_plus_move"
10236 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10237 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 10238 [(match_operand:SI 4 "s_register_operand" "r,r")
10239 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
10240 (plus:SI
10241 (match_operand:SI 2 "s_register_operand" "r,r")
10242 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
129a2fe4 10243 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 10244 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10245 "TARGET_ARM"
8a18b90c 10246 "#"
8fa3ba89 10247 [(set_attr "conds" "clob")
1b7da4ac 10248 (set_attr "length" "8,12")
10249 (set_attr "type" "multiple")]
8fa3ba89 10250)
8a18b90c 10251
10252(define_insn "*if_plus_move"
129a2fe4 10253 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 10254 (if_then_else:SI
8fa3ba89 10255 (match_operator 4 "arm_comparison_operator"
8a18b90c 10256 [(match_operand 5 "cc_register" "") (const_int 0)])
10257 (plus:SI
129a2fe4 10258 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
10259 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
10260 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
cffb2a26 10261 "TARGET_ARM"
8a18b90c 10262 "@
10263 add%d4\\t%0, %2, %3
10264 sub%d4\\t%0, %2, #%n3
10265 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
129a2fe4 10266 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8fa3ba89 10267 [(set_attr "conds" "use")
10268 (set_attr "length" "4,4,8,8")
65f68e55 10269 (set_attr_alternative "type"
10270 [(if_then_else (match_operand 3 "const_int_operand" "")
d82e788e 10271 (const_string "alu_imm" )
112eda6f 10272 (const_string "alu_sreg"))
d82e788e 10273 (const_string "alu_imm")
282b4c75 10274 (const_string "multiple")
10275 (const_string "multiple")])]
8fa3ba89 10276)
8a18b90c 10277
10278(define_insn "*ifcompare_move_plus"
5565501b 10279 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10280 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 10281 [(match_operand:SI 4 "s_register_operand" "r,r")
10282 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 10283 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 10284 (plus:SI
10285 (match_operand:SI 2 "s_register_operand" "r,r")
10286 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
bd5b4116 10287 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10288 "TARGET_ARM"
8a18b90c 10289 "#"
8fa3ba89 10290 [(set_attr "conds" "clob")
1b7da4ac 10291 (set_attr "length" "8,12")
10292 (set_attr "type" "multiple")]
8fa3ba89 10293)
8a18b90c 10294
10295(define_insn "*if_move_plus"
129a2fe4 10296 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 10297 (if_then_else:SI
8fa3ba89 10298 (match_operator 4 "arm_comparison_operator"
8a18b90c 10299 [(match_operand 5 "cc_register" "") (const_int 0)])
129a2fe4 10300 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8a18b90c 10301 (plus:SI
129a2fe4 10302 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
10303 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
cffb2a26 10304 "TARGET_ARM"
8a18b90c 10305 "@
10306 add%D4\\t%0, %2, %3
10307 sub%D4\\t%0, %2, #%n3
10308 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
129a2fe4 10309 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8fa3ba89 10310 [(set_attr "conds" "use")
10311 (set_attr "length" "4,4,8,8")
282b4c75 10312 (set_attr_alternative "type"
10313 [(if_then_else (match_operand 3 "const_int_operand" "")
10314 (const_string "alu_imm" )
10315 (const_string "alu_sreg"))
10316 (const_string "alu_imm")
10317 (const_string "multiple")
10318 (const_string "multiple")])]
8fa3ba89 10319)
8a18b90c 10320
10321(define_insn "*ifcompare_arith_arith"
10322 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 10323 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8a18b90c 10324 [(match_operand:SI 5 "s_register_operand" "r")
10325 (match_operand:SI 6 "arm_add_operand" "rIL")])
9c08d1fa 10326 (match_operator:SI 8 "shiftable_operator"
8a18b90c 10327 [(match_operand:SI 1 "s_register_operand" "r")
10328 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9c08d1fa 10329 (match_operator:SI 7 "shiftable_operator"
8a18b90c 10330 [(match_operand:SI 3 "s_register_operand" "r")
10331 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
bd5b4116 10332 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10333 "TARGET_ARM"
8a18b90c 10334 "#"
8fa3ba89 10335 [(set_attr "conds" "clob")
1b7da4ac 10336 (set_attr "length" "12")
10337 (set_attr "type" "multiple")]
8fa3ba89 10338)
9c08d1fa 10339
8a18b90c 10340(define_insn "*if_arith_arith"
10341 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 10342 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8a18b90c 10343 [(match_operand 8 "cc_register" "") (const_int 0)])
10344 (match_operator:SI 6 "shiftable_operator"
10345 [(match_operand:SI 1 "s_register_operand" "r")
10346 (match_operand:SI 2 "arm_rhs_operand" "rI")])
10347 (match_operator:SI 7 "shiftable_operator"
10348 [(match_operand:SI 3 "s_register_operand" "r")
10349 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
cffb2a26 10350 "TARGET_ARM"
8a18b90c 10351 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8fa3ba89 10352 [(set_attr "conds" "use")
1b7da4ac 10353 (set_attr "length" "8")
10354 (set_attr "type" "multiple")]
8fa3ba89 10355)
8a18b90c 10356
f7fbdd4a 10357(define_insn "*ifcompare_arith_move"
9c08d1fa 10358 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10359 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 10360 [(match_operand:SI 2 "s_register_operand" "r,r")
5565501b 10361 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
9c08d1fa 10362 (match_operator:SI 7 "shiftable_operator"
10363 [(match_operand:SI 4 "s_register_operand" "r,r")
10364 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
129a2fe4 10365 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 10366 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10367 "TARGET_ARM"
9c08d1fa 10368 "*
9c08d1fa 10369 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 10370 the conditional operator is LT or GE and we are comparing against zero and
674a8f0b 10371 everything is in registers then we can do this in two instructions. */
9c08d1fa 10372 if (operands[3] == const0_rtx
10373 && GET_CODE (operands[7]) != AND
0438d37f 10374 && REG_P (operands[5])
10375 && REG_P (operands[1])
9c08d1fa 10376 && REGNO (operands[1]) == REGNO (operands[4])
10377 && REGNO (operands[4]) != REGNO (operands[0]))
10378 {
10379 if (GET_CODE (operands[6]) == LT)
40dbec34 10380 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 10381 else if (GET_CODE (operands[6]) == GE)
40dbec34 10382 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 10383 }
0438d37f 10384 if (CONST_INT_P (operands[3])
9c08d1fa 10385 && !const_ok_for_arm (INTVAL (operands[3])))
e2348bcb 10386 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
9c08d1fa 10387 else
e2348bcb 10388 output_asm_insn (\"cmp\\t%2, %3\", operands);
40dbec34 10389 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
9c08d1fa 10390 if (which_alternative != 0)
129a2fe4 10391 return \"mov%D6\\t%0, %1\";
9c08d1fa 10392 return \"\";
215b30b3 10393 "
8fa3ba89 10394 [(set_attr "conds" "clob")
1b7da4ac 10395 (set_attr "length" "8,12")
10396 (set_attr "type" "multiple")]
8fa3ba89 10397)
9c08d1fa 10398
8a18b90c 10399(define_insn "*if_arith_move"
129a2fe4 10400 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10401 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8a18b90c 10402 [(match_operand 6 "cc_register" "") (const_int 0)])
10403 (match_operator:SI 5 "shiftable_operator"
129a2fe4 10404 [(match_operand:SI 2 "s_register_operand" "r,r")
10405 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
10406 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
cffb2a26 10407 "TARGET_ARM"
8a18b90c 10408 "@
10409 %I5%d4\\t%0, %2, %3
129a2fe4 10410 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8fa3ba89 10411 [(set_attr "conds" "use")
10412 (set_attr "length" "4,8")
282b4c75 10413 (set_attr_alternative "type"
10414 [(if_then_else (match_operand 3 "const_int_operand" "")
10415 (const_string "alu_shift_imm" )
10416 (const_string "alu_shift_reg"))
10417 (const_string "multiple")])]
8fa3ba89 10418)
8a18b90c 10419
f7fbdd4a 10420(define_insn "*ifcompare_move_arith"
9c08d1fa 10421 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10422 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 10423 [(match_operand:SI 4 "s_register_operand" "r,r")
5565501b 10424 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 10425 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9c08d1fa 10426 (match_operator:SI 7 "shiftable_operator"
10427 [(match_operand:SI 2 "s_register_operand" "r,r")
10428 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 10429 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10430 "TARGET_ARM"
9c08d1fa 10431 "*
9c08d1fa 10432 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 10433 the conditional operator is LT or GE and we are comparing against zero and
9c08d1fa 10434 everything is in registers then we can do this in two instructions */
10435 if (operands[5] == const0_rtx
10436 && GET_CODE (operands[7]) != AND
0438d37f 10437 && REG_P (operands[3])
10438 && REG_P (operands[1])
9c08d1fa 10439 && REGNO (operands[1]) == REGNO (operands[2])
10440 && REGNO (operands[2]) != REGNO (operands[0]))
10441 {
10442 if (GET_CODE (operands[6]) == GE)
40dbec34 10443 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 10444 else if (GET_CODE (operands[6]) == LT)
40dbec34 10445 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 10446 }
40dbec34 10447
0438d37f 10448 if (CONST_INT_P (operands[5])
9c08d1fa 10449 && !const_ok_for_arm (INTVAL (operands[5])))
e2348bcb 10450 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
9c08d1fa 10451 else
e2348bcb 10452 output_asm_insn (\"cmp\\t%4, %5\", operands);
40dbec34 10453
9c08d1fa 10454 if (which_alternative != 0)
129a2fe4 10455 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
40dbec34 10456 return \"%I7%D6\\t%0, %2, %3\";
215b30b3 10457 "
8fa3ba89 10458 [(set_attr "conds" "clob")
1b7da4ac 10459 (set_attr "length" "8,12")
10460 (set_attr "type" "multiple")]
8fa3ba89 10461)
9c08d1fa 10462
8a18b90c 10463(define_insn "*if_move_arith"
129a2fe4 10464 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 10465 (if_then_else:SI
8fa3ba89 10466 (match_operator 4 "arm_comparison_operator"
8a18b90c 10467 [(match_operand 6 "cc_register" "") (const_int 0)])
129a2fe4 10468 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 10469 (match_operator:SI 5 "shiftable_operator"
129a2fe4 10470 [(match_operand:SI 2 "s_register_operand" "r,r")
10471 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
cffb2a26 10472 "TARGET_ARM"
8a18b90c 10473 "@
10474 %I5%D4\\t%0, %2, %3
129a2fe4 10475 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
8fa3ba89 10476 [(set_attr "conds" "use")
10477 (set_attr "length" "4,8")
282b4c75 10478 (set_attr_alternative "type"
10479 [(if_then_else (match_operand 3 "const_int_operand" "")
10480 (const_string "alu_shift_imm" )
10481 (const_string "alu_shift_reg"))
10482 (const_string "multiple")])]
8fa3ba89 10483)
8a18b90c 10484
10485(define_insn "*ifcompare_move_not"
9c08d1fa 10486 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 10487 (if_then_else:SI
8fa3ba89 10488 (match_operator 5 "arm_comparison_operator"
8a18b90c 10489 [(match_operand:SI 3 "s_register_operand" "r,r")
10490 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10491 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
10492 (not:SI
10493 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 10494 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10495 "TARGET_ARM"
8a18b90c 10496 "#"
8fa3ba89 10497 [(set_attr "conds" "clob")
1b7da4ac 10498 (set_attr "length" "8,12")
10499 (set_attr "type" "multiple")]
8fa3ba89 10500)
9c08d1fa 10501
8a18b90c 10502(define_insn "*if_move_not"
10503 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10504 (if_then_else:SI
8fa3ba89 10505 (match_operator 4 "arm_comparison_operator"
8a18b90c 10506 [(match_operand 3 "cc_register" "") (const_int 0)])
10507 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
10508 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
cffb2a26 10509 "TARGET_ARM"
8a18b90c 10510 "@
10511 mvn%D4\\t%0, %2
10512 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
10513 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
8fa3ba89 10514 [(set_attr "conds" "use")
1aed5204 10515 (set_attr "type" "mvn_reg")
1b7da4ac 10516 (set_attr "length" "4,8,8")
10517 (set_attr "type" "mvn_reg,multiple,multiple")]
8fa3ba89 10518)
8a18b90c 10519
10520(define_insn "*ifcompare_not_move"
9c08d1fa 10521 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 10522 (if_then_else:SI
8fa3ba89 10523 (match_operator 5 "arm_comparison_operator"
8a18b90c 10524 [(match_operand:SI 3 "s_register_operand" "r,r")
10525 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10526 (not:SI
10527 (match_operand:SI 2 "s_register_operand" "r,r"))
10528 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 10529 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10530 "TARGET_ARM"
8a18b90c 10531 "#"
8fa3ba89 10532 [(set_attr "conds" "clob")
1b7da4ac 10533 (set_attr "length" "8,12")
10534 (set_attr "type" "multiple")]
8fa3ba89 10535)
9c08d1fa 10536
8a18b90c 10537(define_insn "*if_not_move"
10538 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10539 (if_then_else:SI
8fa3ba89 10540 (match_operator 4 "arm_comparison_operator"
8a18b90c 10541 [(match_operand 3 "cc_register" "") (const_int 0)])
10542 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
10543 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 10544 "TARGET_ARM"
8a18b90c 10545 "@
10546 mvn%d4\\t%0, %2
10547 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
10548 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
8fa3ba89 10549 [(set_attr "conds" "use")
1b7da4ac 10550 (set_attr "type" "mvn_reg,multiple,multiple")
8fa3ba89 10551 (set_attr "length" "4,8,8")]
10552)
8a18b90c 10553
10554(define_insn "*ifcompare_shift_move"
9c08d1fa 10555 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 10556 (if_then_else:SI
8fa3ba89 10557 (match_operator 6 "arm_comparison_operator"
8a18b90c 10558 [(match_operand:SI 4 "s_register_operand" "r,r")
10559 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
10560 (match_operator:SI 7 "shift_operator"
10561 [(match_operand:SI 2 "s_register_operand" "r,r")
10562 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
10563 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 10564 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10565 "TARGET_ARM"
9c08d1fa 10566 "#"
8fa3ba89 10567 [(set_attr "conds" "clob")
1b7da4ac 10568 (set_attr "length" "8,12")
10569 (set_attr "type" "multiple")]
8fa3ba89 10570)
9c08d1fa 10571
8a18b90c 10572(define_insn "*if_shift_move"
10573 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10574 (if_then_else:SI
8fa3ba89 10575 (match_operator 5 "arm_comparison_operator"
8a18b90c 10576 [(match_operand 6 "cc_register" "") (const_int 0)])
10577 (match_operator:SI 4 "shift_operator"
10578 [(match_operand:SI 2 "s_register_operand" "r,r,r")
10579 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
10580 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 10581 "TARGET_ARM"
5565501b 10582 "@
8a18b90c 10583 mov%d5\\t%0, %2%S4
10584 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
10585 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
8fa3ba89 10586 [(set_attr "conds" "use")
331beb1a 10587 (set_attr "shift" "2")
a2cd141b 10588 (set_attr "length" "4,8,8")
282b4c75 10589 (set_attr_alternative "type"
10590 [(if_then_else (match_operand 3 "const_int_operand" "")
10591 (const_string "mov_shift" )
10592 (const_string "mov_shift_reg"))
10593 (const_string "multiple")
10594 (const_string "multiple")])]
8fa3ba89 10595)
5565501b 10596
8a18b90c 10597(define_insn "*ifcompare_move_shift"
10598 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 10599 (if_then_else:SI
8fa3ba89 10600 (match_operator 6 "arm_comparison_operator"
8a18b90c 10601 [(match_operand:SI 4 "s_register_operand" "r,r")
10602 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
10603 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
5565501b 10604 (match_operator:SI 7 "shift_operator"
8a18b90c 10605 [(match_operand:SI 2 "s_register_operand" "r,r")
10606 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
bd5b4116 10607 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10608 "TARGET_ARM"
8a18b90c 10609 "#"
8fa3ba89 10610 [(set_attr "conds" "clob")
1b7da4ac 10611 (set_attr "length" "8,12")
10612 (set_attr "type" "multiple")]
8fa3ba89 10613)
5565501b 10614
8a18b90c 10615(define_insn "*if_move_shift"
10616 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 10617 (if_then_else:SI
8fa3ba89 10618 (match_operator 5 "arm_comparison_operator"
8a18b90c 10619 [(match_operand 6 "cc_register" "") (const_int 0)])
10620 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
10621 (match_operator:SI 4 "shift_operator"
10622 [(match_operand:SI 2 "s_register_operand" "r,r,r")
10623 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
cffb2a26 10624 "TARGET_ARM"
5565501b 10625 "@
8a18b90c 10626 mov%D5\\t%0, %2%S4
10627 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
10628 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
8fa3ba89 10629 [(set_attr "conds" "use")
331beb1a 10630 (set_attr "shift" "2")
a2cd141b 10631 (set_attr "length" "4,8,8")
282b4c75 10632 (set_attr_alternative "type"
10633 [(if_then_else (match_operand 3 "const_int_operand" "")
10634 (const_string "mov_shift" )
10635 (const_string "mov_shift_reg"))
10636 (const_string "multiple")
10637 (const_string "multiple")])]
8fa3ba89 10638)
9c08d1fa 10639
f7fbdd4a 10640(define_insn "*ifcompare_shift_shift"
8a18b90c 10641 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 10642 (if_then_else:SI
8fa3ba89 10643 (match_operator 7 "arm_comparison_operator"
8a18b90c 10644 [(match_operand:SI 5 "s_register_operand" "r")
10645 (match_operand:SI 6 "arm_add_operand" "rIL")])
5565501b 10646 (match_operator:SI 8 "shift_operator"
8a18b90c 10647 [(match_operand:SI 1 "s_register_operand" "r")
10648 (match_operand:SI 2 "arm_rhs_operand" "rM")])
5565501b 10649 (match_operator:SI 9 "shift_operator"
8a18b90c 10650 [(match_operand:SI 3 "s_register_operand" "r")
10651 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
bd5b4116 10652 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10653 "TARGET_ARM"
8a18b90c 10654 "#"
8fa3ba89 10655 [(set_attr "conds" "clob")
1b7da4ac 10656 (set_attr "length" "12")
10657 (set_attr "type" "multiple")]
8fa3ba89 10658)
9c08d1fa 10659
8a18b90c 10660(define_insn "*if_shift_shift"
10661 [(set (match_operand:SI 0 "s_register_operand" "=r")
10662 (if_then_else:SI
8fa3ba89 10663 (match_operator 5 "arm_comparison_operator"
8a18b90c 10664 [(match_operand 8 "cc_register" "") (const_int 0)])
10665 (match_operator:SI 6 "shift_operator"
10666 [(match_operand:SI 1 "s_register_operand" "r")
10667 (match_operand:SI 2 "arm_rhs_operand" "rM")])
10668 (match_operator:SI 7 "shift_operator"
10669 [(match_operand:SI 3 "s_register_operand" "r")
10670 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
cffb2a26 10671 "TARGET_ARM"
8a18b90c 10672 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
8fa3ba89 10673 [(set_attr "conds" "use")
331beb1a 10674 (set_attr "shift" "1")
a2cd141b 10675 (set_attr "length" "8")
10676 (set (attr "type") (if_then_else
10677 (and (match_operand 2 "const_int_operand" "")
10678 (match_operand 4 "const_int_operand" ""))
1aed5204 10679 (const_string "mov_shift")
10680 (const_string "mov_shift_reg")))]
8fa3ba89 10681)
8a18b90c 10682
f7fbdd4a 10683(define_insn "*ifcompare_not_arith"
8a18b90c 10684 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 10685 (if_then_else:SI
8fa3ba89 10686 (match_operator 6 "arm_comparison_operator"
8a18b90c 10687 [(match_operand:SI 4 "s_register_operand" "r")
10688 (match_operand:SI 5 "arm_add_operand" "rIL")])
10689 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5565501b 10690 (match_operator:SI 7 "shiftable_operator"
8a18b90c 10691 [(match_operand:SI 2 "s_register_operand" "r")
10692 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
bd5b4116 10693 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10694 "TARGET_ARM"
8a18b90c 10695 "#"
8fa3ba89 10696 [(set_attr "conds" "clob")
1b7da4ac 10697 (set_attr "length" "12")
10698 (set_attr "type" "multiple")]
8fa3ba89 10699)
9c08d1fa 10700
8a18b90c 10701(define_insn "*if_not_arith"
10702 [(set (match_operand:SI 0 "s_register_operand" "=r")
10703 (if_then_else:SI
8fa3ba89 10704 (match_operator 5 "arm_comparison_operator"
8a18b90c 10705 [(match_operand 4 "cc_register" "") (const_int 0)])
10706 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
10707 (match_operator:SI 6 "shiftable_operator"
10708 [(match_operand:SI 2 "s_register_operand" "r")
10709 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
cffb2a26 10710 "TARGET_ARM"
8a18b90c 10711 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
8fa3ba89 10712 [(set_attr "conds" "use")
1aed5204 10713 (set_attr "type" "mvn_reg")
8fa3ba89 10714 (set_attr "length" "8")]
10715)
8a18b90c 10716
10717(define_insn "*ifcompare_arith_not"
10718 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 10719 (if_then_else:SI
8fa3ba89 10720 (match_operator 6 "arm_comparison_operator"
8a18b90c 10721 [(match_operand:SI 4 "s_register_operand" "r")
10722 (match_operand:SI 5 "arm_add_operand" "rIL")])
5565501b 10723 (match_operator:SI 7 "shiftable_operator"
8a18b90c 10724 [(match_operand:SI 2 "s_register_operand" "r")
10725 (match_operand:SI 3 "arm_rhs_operand" "rI")])
10726 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
bd5b4116 10727 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10728 "TARGET_ARM"
8a18b90c 10729 "#"
8fa3ba89 10730 [(set_attr "conds" "clob")
1b7da4ac 10731 (set_attr "length" "12")
10732 (set_attr "type" "multiple")]
8fa3ba89 10733)
9c08d1fa 10734
8a18b90c 10735(define_insn "*if_arith_not"
10736 [(set (match_operand:SI 0 "s_register_operand" "=r")
10737 (if_then_else:SI
8fa3ba89 10738 (match_operator 5 "arm_comparison_operator"
8a18b90c 10739 [(match_operand 4 "cc_register" "") (const_int 0)])
10740 (match_operator:SI 6 "shiftable_operator"
10741 [(match_operand:SI 2 "s_register_operand" "r")
10742 (match_operand:SI 3 "arm_rhs_operand" "rI")])
10743 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
cffb2a26 10744 "TARGET_ARM"
8a18b90c 10745 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
8fa3ba89 10746 [(set_attr "conds" "use")
1b7da4ac 10747 (set_attr "type" "multiple")
8fa3ba89 10748 (set_attr "length" "8")]
10749)
8a18b90c 10750
f7fbdd4a 10751(define_insn "*ifcompare_neg_move"
8a18b90c 10752 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 10753 (if_then_else:SI
8fa3ba89 10754 (match_operator 5 "arm_comparison_operator"
8a18b90c 10755 [(match_operand:SI 3 "s_register_operand" "r,r")
10756 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10757 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
10758 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 10759 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10760 "TARGET_ARM"
8a18b90c 10761 "#"
8fa3ba89 10762 [(set_attr "conds" "clob")
1b7da4ac 10763 (set_attr "length" "8,12")
10764 (set_attr "type" "multiple")]
8fa3ba89 10765)
8a18b90c 10766
530bb693 10767(define_insn_and_split "*if_neg_move"
10768 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
8a18b90c 10769 (if_then_else:SI
8fa3ba89 10770 (match_operator 4 "arm_comparison_operator"
8a18b90c 10771 [(match_operand 3 "cc_register" "") (const_int 0)])
530bb693 10772 (neg:SI (match_operand:SI 2 "s_register_operand" "l,r"))
10773 (match_operand:SI 1 "s_register_operand" "0,0")))]
10774 "TARGET_32BIT"
10775 "#"
10776 "&& reload_completed"
10777 [(cond_exec (match_op_dup 4 [(match_dup 3) (const_int 0)])
10778 (set (match_dup 0) (neg:SI (match_dup 2))))]
10779 ""
8fa3ba89 10780 [(set_attr "conds" "use")
530bb693 10781 (set_attr "length" "4")
10782 (set_attr "arch" "t2,32")
8bdfd6ed 10783 (set_attr "enabled_for_short_it" "yes,no")
530bb693 10784 (set_attr "type" "logic_shift_imm")]
8fa3ba89 10785)
9c08d1fa 10786
f7fbdd4a 10787(define_insn "*ifcompare_move_neg"
8a18b90c 10788 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 10789 (if_then_else:SI
8fa3ba89 10790 (match_operator 5 "arm_comparison_operator"
8a18b90c 10791 [(match_operand:SI 3 "s_register_operand" "r,r")
10792 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10793 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
10794 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 10795 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10796 "TARGET_ARM"
8a18b90c 10797 "#"
8fa3ba89 10798 [(set_attr "conds" "clob")
1b7da4ac 10799 (set_attr "length" "8,12")
10800 (set_attr "type" "multiple")]
8fa3ba89 10801)
8a18b90c 10802
530bb693 10803(define_insn_and_split "*if_move_neg"
10804 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
8a18b90c 10805 (if_then_else:SI
8fa3ba89 10806 (match_operator 4 "arm_comparison_operator"
8a18b90c 10807 [(match_operand 3 "cc_register" "") (const_int 0)])
530bb693 10808 (match_operand:SI 1 "s_register_operand" "0,0")
10809 (neg:SI (match_operand:SI 2 "s_register_operand" "l,r"))))]
10810 "TARGET_32BIT"
10811 "#"
10812 "&& reload_completed"
10813 [(cond_exec (match_dup 5)
10814 (set (match_dup 0) (neg:SI (match_dup 2))))]
10815 {
10816 machine_mode mode = GET_MODE (operands[3]);
10817 rtx_code rc = GET_CODE (operands[4]);
10818
10819 if (mode == CCFPmode || mode == CCFPEmode)
10820 rc = reverse_condition_maybe_unordered (rc);
10821 else
10822 rc = reverse_condition (rc);
10823
10824 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[3], const0_rtx);
10825 }
0d66636f 10826 [(set_attr "conds" "use")
530bb693 10827 (set_attr "length" "4")
10828 (set_attr "arch" "t2,32")
8bdfd6ed 10829 (set_attr "enabled_for_short_it" "yes,no")
530bb693 10830 (set_attr "type" "logic_shift_imm")]
0d66636f 10831)
9c08d1fa 10832
f7fbdd4a 10833(define_insn "*arith_adjacentmem"
9c08d1fa 10834 [(set (match_operand:SI 0 "s_register_operand" "=r")
10835 (match_operator:SI 1 "shiftable_operator"
10836 [(match_operand:SI 2 "memory_operand" "m")
10837 (match_operand:SI 3 "memory_operand" "m")]))
10838 (clobber (match_scratch:SI 4 "=r"))]
cffb2a26 10839 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9c08d1fa 10840 "*
215b30b3 10841 {
10842 rtx ldm[3];
10843 rtx arith[4];
94dee231 10844 rtx base_reg;
10845 HOST_WIDE_INT val1 = 0, val2 = 0;
9c08d1fa 10846
215b30b3 10847 if (REGNO (operands[0]) > REGNO (operands[4]))
10848 {
10849 ldm[1] = operands[4];
10850 ldm[2] = operands[0];
10851 }
10852 else
10853 {
10854 ldm[1] = operands[0];
10855 ldm[2] = operands[4];
10856 }
94dee231 10857
10858 base_reg = XEXP (operands[2], 0);
10859
10860 if (!REG_P (base_reg))
10861 {
10862 val1 = INTVAL (XEXP (base_reg, 1));
10863 base_reg = XEXP (base_reg, 0);
10864 }
10865
10866 if (!REG_P (XEXP (operands[3], 0)))
215b30b3 10867 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
94dee231 10868
215b30b3 10869 arith[0] = operands[0];
10870 arith[3] = operands[1];
94dee231 10871
215b30b3 10872 if (val1 < val2)
10873 {
10874 arith[1] = ldm[1];
10875 arith[2] = ldm[2];
10876 }
10877 else
10878 {
10879 arith[1] = ldm[2];
10880 arith[2] = ldm[1];
10881 }
94dee231 10882
10883 ldm[0] = base_reg;
10884 if (val1 !=0 && val2 != 0)
215b30b3 10885 {
cdb1295a 10886 rtx ops[3];
10887
94dee231 10888 if (val1 == 4 || val2 == 4)
10889 /* Other val must be 8, since we know they are adjacent and neither
10890 is zero. */
3ef90e77 10891 output_asm_insn (\"ldmib%?\\t%0, {%1, %2}\", ldm);
cdb1295a 10892 else if (const_ok_for_arm (val1) || const_ok_for_arm (-val1))
94dee231 10893 {
94dee231 10894 ldm[0] = ops[0] = operands[4];
10895 ops[1] = base_reg;
10896 ops[2] = GEN_INT (val1);
10897 output_add_immediate (ops);
10898 if (val1 < val2)
3ef90e77 10899 output_asm_insn (\"ldmia%?\\t%0, {%1, %2}\", ldm);
94dee231 10900 else
3ef90e77 10901 output_asm_insn (\"ldmda%?\\t%0, {%1, %2}\", ldm);
94dee231 10902 }
cdb1295a 10903 else
10904 {
10905 /* Offset is out of range for a single add, so use two ldr. */
10906 ops[0] = ldm[1];
10907 ops[1] = base_reg;
10908 ops[2] = GEN_INT (val1);
10909 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10910 ops[0] = ldm[2];
10911 ops[2] = GEN_INT (val2);
10912 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10913 }
215b30b3 10914 }
94dee231 10915 else if (val1 != 0)
215b30b3 10916 {
215b30b3 10917 if (val1 < val2)
3ef90e77 10918 output_asm_insn (\"ldmda%?\\t%0, {%1, %2}\", ldm);
215b30b3 10919 else
3ef90e77 10920 output_asm_insn (\"ldmia%?\\t%0, {%1, %2}\", ldm);
215b30b3 10921 }
10922 else
10923 {
215b30b3 10924 if (val1 < val2)
3ef90e77 10925 output_asm_insn (\"ldmia%?\\t%0, {%1, %2}\", ldm);
215b30b3 10926 else
3ef90e77 10927 output_asm_insn (\"ldmda%?\\t%0, {%1, %2}\", ldm);
215b30b3 10928 }
10929 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
10930 return \"\";
10931 }"
10932 [(set_attr "length" "12")
10933 (set_attr "predicable" "yes")
9f2c2a36 10934 (set_attr "type" "load_4")]
215b30b3 10935)
9c08d1fa 10936
9c08d1fa 10937; This pattern is never tried by combine, so do it as a peephole
10938
a0f94409 10939(define_peephole2
372575c7 10940 [(set (match_operand:SI 0 "arm_general_register_operand" "")
10941 (match_operand:SI 1 "arm_general_register_operand" ""))
bd5b4116 10942 (set (reg:CC CC_REGNUM)
aea4c774 10943 (compare:CC (match_dup 1) (const_int 0)))]
372575c7 10944 "TARGET_ARM"
a0f94409 10945 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
10946 (set (match_dup 0) (match_dup 1))])]
10947 ""
0d66636f 10948)
9c08d1fa 10949
9c08d1fa 10950(define_split
10951 [(set (match_operand:SI 0 "s_register_operand" "")
10952 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
10953 (const_int 0))
8fa3ba89 10954 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9c08d1fa 10955 [(match_operand:SI 3 "s_register_operand" "")
10956 (match_operand:SI 4 "arm_rhs_operand" "")]))))
10957 (clobber (match_operand:SI 5 "s_register_operand" ""))]
cffb2a26 10958 "TARGET_ARM"
9c08d1fa 10959 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
10960 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
10961 (match_dup 5)))]
215b30b3 10962 ""
10963)
9c08d1fa 10964
aea4c774 10965;; This split can be used because CC_Z mode implies that the following
10966;; branch will be an equality, or an unsigned inequality, so the sign
10967;; extension is not needed.
9c08d1fa 10968
aea4c774 10969(define_split
bd5b4116 10970 [(set (reg:CC_Z CC_REGNUM)
aea4c774 10971 (compare:CC_Z
10972 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9c08d1fa 10973 (const_int 24))
aea4c774 10974 (match_operand 1 "const_int_operand" "")))
10975 (clobber (match_scratch:SI 2 ""))]
cffb2a26 10976 "TARGET_ARM
8c4e8755 10977 && ((UINTVAL (operands[1]))
10978 == ((UINTVAL (operands[1])) >> 24) << 24)"
aea4c774 10979 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
bd5b4116 10980 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
aea4c774 10981 "
9c08d1fa 10982 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
215b30b3 10983 "
10984)
25f905c2 10985;; ??? Check the patterns above for Thumb-2 usefulness
9c08d1fa 10986
87b22bf7 10987(define_expand "prologue"
10988 [(clobber (const_int 0))]
cffb2a26 10989 "TARGET_EITHER"
25f905c2 10990 "if (TARGET_32BIT)
cffb2a26 10991 arm_expand_prologue ();
10992 else
25f905c2 10993 thumb1_expand_prologue ();
87b22bf7 10994 DONE;
cffb2a26 10995 "
10996)
87b22bf7 10997
56d27660 10998(define_expand "epilogue"
4c44712e 10999 [(clobber (const_int 0))]
cffb2a26 11000 "TARGET_EITHER"
56d27660 11001 "
18d50ae6 11002 if (crtl->calls_eh_return)
fb94f18b 11003 emit_insn (gen_force_register_use (gen_rtx_REG (Pmode, 2)));
25f905c2 11004 if (TARGET_THUMB1)
c3635784 11005 {
11006 thumb1_expand_epilogue ();
11007 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
11008 gen_rtvec (1, ret_rtx), VUNSPEC_EPILOGUE));
11009 }
11010 else if (HAVE_return)
11011 {
11012 /* HAVE_return is testing for USE_RETURN_INSN (FALSE). Hence,
11013 no need for explicit testing again. */
11014 emit_jump_insn (gen_return ());
11015 }
11016 else if (TARGET_32BIT)
11017 {
11018 arm_expand_epilogue (true);
11019 }
cffb2a26 11020 DONE;
11021 "
11022)
56d27660 11023
ef5651d0 11024;; Note - although unspec_volatile's USE all hard registers,
11025;; USEs are ignored after relaod has completed. Thus we need
11026;; to add an unspec of the link register to ensure that flow
11027;; does not think that it is unused by the sibcall branch that
11028;; will replace the standard function epilogue.
c3635784 11029(define_expand "sibcall_epilogue"
fb94f18b 11030 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_REGISTER_USE)
c3635784 11031 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
11032 "TARGET_32BIT"
11033 "
11034 arm_expand_epilogue (false);
11035 DONE;
11036 "
1c494086 11037)
11038
cffb2a26 11039(define_expand "eh_epilogue"
7db9af5d 11040 [(use (match_operand:SI 0 "register_operand" ""))
11041 (use (match_operand:SI 1 "register_operand" ""))
11042 (use (match_operand:SI 2 "register_operand" ""))]
cffb2a26 11043 "TARGET_EITHER"
11044 "
215b30b3 11045 {
11046 cfun->machine->eh_epilogue_sp_ofs = operands[1];
0438d37f 11047 if (!REG_P (operands[2]) || REGNO (operands[2]) != 2)
215b30b3 11048 {
11049 rtx ra = gen_rtx_REG (Pmode, 2);
11050
11051 emit_move_insn (ra, operands[2]);
11052 operands[2] = ra;
11053 }
5cf3595a 11054 /* This is a hack -- we may have crystalized the function type too
11055 early. */
11056 cfun->machine->func_type = 0;
215b30b3 11057 }"
11058)
56d27660 11059
9c08d1fa 11060;; This split is only used during output to reduce the number of patterns
11061;; that need assembler instructions adding to them. We allowed the setting
11062;; of the conditions to be implicit during rtl generation so that
11063;; the conditional compare patterns would work. However this conflicts to
8a18b90c 11064;; some extent with the conditional data operations, so we have to split them
9c08d1fa 11065;; up again here.
11066
25f905c2 11067;; ??? Need to audit these splitters for Thumb-2. Why isn't normal
11068;; conditional execution sufficient?
11069
9c08d1fa 11070(define_split
11071 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 11072 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
11073 [(match_operand 2 "" "") (match_operand 3 "" "")])
11074 (match_dup 0)
11075 (match_operand 4 "" "")))
bd5b4116 11076 (clobber (reg:CC CC_REGNUM))]
ac8b093b 11077 "TARGET_ARM && reload_completed"
8fa3ba89 11078 [(set (match_dup 5) (match_dup 6))
11079 (cond_exec (match_dup 7)
11080 (set (match_dup 0) (match_dup 4)))]
11081 "
11082 {
3754d046 11083 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8fa3ba89 11084 operands[2], operands[3]);
11085 enum rtx_code rc = GET_CODE (operands[1]);
11086
bd5b4116 11087 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 11088 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
11089 if (mode == CCFPmode || mode == CCFPEmode)
11090 rc = reverse_condition_maybe_unordered (rc);
11091 else
11092 rc = reverse_condition (rc);
11093
11094 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
11095 }"
11096)
11097
11098(define_split
11099 [(set (match_operand:SI 0 "s_register_operand" "")
11100 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
11101 [(match_operand 2 "" "") (match_operand 3 "" "")])
11102 (match_operand 4 "" "")
11103 (match_dup 0)))
bd5b4116 11104 (clobber (reg:CC CC_REGNUM))]
ac8b093b 11105 "TARGET_ARM && reload_completed"
8fa3ba89 11106 [(set (match_dup 5) (match_dup 6))
11107 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
11108 (set (match_dup 0) (match_dup 4)))]
11109 "
11110 {
3754d046 11111 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8fa3ba89 11112 operands[2], operands[3]);
11113
bd5b4116 11114 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 11115 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
11116 }"
11117)
11118
11119(define_split
11120 [(set (match_operand:SI 0 "s_register_operand" "")
11121 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9c08d1fa 11122 [(match_operand 2 "" "") (match_operand 3 "" "")])
11123 (match_operand 4 "" "")
11124 (match_operand 5 "" "")))
bd5b4116 11125 (clobber (reg:CC CC_REGNUM))]
ac8b093b 11126 "TARGET_ARM && reload_completed"
8fa3ba89 11127 [(set (match_dup 6) (match_dup 7))
11128 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
11129 (set (match_dup 0) (match_dup 4)))
11130 (cond_exec (match_dup 8)
11131 (set (match_dup 0) (match_dup 5)))]
11132 "
11133 {
3754d046 11134 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8fa3ba89 11135 operands[2], operands[3]);
11136 enum rtx_code rc = GET_CODE (operands[1]);
11137
bd5b4116 11138 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 11139 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
11140 if (mode == CCFPmode || mode == CCFPEmode)
11141 rc = reverse_condition_maybe_unordered (rc);
11142 else
11143 rc = reverse_condition (rc);
11144
11145 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
11146 }"
11147)
11148
cffb2a26 11149(define_split
11150 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 11151 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
cffb2a26 11152 [(match_operand:SI 2 "s_register_operand" "")
11153 (match_operand:SI 3 "arm_add_operand" "")])
11154 (match_operand:SI 4 "arm_rhs_operand" "")
11155 (not:SI
11156 (match_operand:SI 5 "s_register_operand" ""))))
bd5b4116 11157 (clobber (reg:CC CC_REGNUM))]
ac8b093b 11158 "TARGET_ARM && reload_completed"
cffb2a26 11159 [(set (match_dup 6) (match_dup 7))
f6c53574 11160 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
11161 (set (match_dup 0) (match_dup 4)))
11162 (cond_exec (match_dup 8)
11163 (set (match_dup 0) (not:SI (match_dup 5))))]
cffb2a26 11164 "
215b30b3 11165 {
3754d046 11166 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
215b30b3 11167 operands[2], operands[3]);
f6c53574 11168 enum rtx_code rc = GET_CODE (operands[1]);
cffb2a26 11169
bd5b4116 11170 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
1a83b3ff 11171 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
f6c53574 11172 if (mode == CCFPmode || mode == CCFPEmode)
11173 rc = reverse_condition_maybe_unordered (rc);
11174 else
11175 rc = reverse_condition (rc);
11176
11177 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
215b30b3 11178 }"
11179)
cffb2a26 11180
11181(define_insn "*cond_move_not"
11182 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 11183 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
cffb2a26 11184 [(match_operand 3 "cc_register" "") (const_int 0)])
11185 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
11186 (not:SI
11187 (match_operand:SI 2 "s_register_operand" "r,r"))))]
11188 "TARGET_ARM"
11189 "@
11190 mvn%D4\\t%0, %2
11191 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
0d66636f 11192 [(set_attr "conds" "use")
1b7da4ac 11193 (set_attr "type" "mvn_reg,multiple")
0d66636f 11194 (set_attr "length" "4,8")]
11195)
cffb2a26 11196
9c08d1fa 11197;; The next two patterns occur when an AND operation is followed by a
11198;; scc insn sequence
11199
f7fbdd4a 11200(define_insn "*sign_extract_onebit"
9c08d1fa 11201 [(set (match_operand:SI 0 "s_register_operand" "=r")
11202 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
11203 (const_int 1)
ed750274 11204 (match_operand:SI 2 "const_int_operand" "n")))
11205 (clobber (reg:CC CC_REGNUM))]
cffb2a26 11206 "TARGET_ARM"
9c08d1fa 11207 "*
0d66636f 11208 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
11209 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
11210 return \"mvnne\\t%0, #0\";
11211 "
11212 [(set_attr "conds" "clob")
1b7da4ac 11213 (set_attr "length" "8")
11214 (set_attr "type" "multiple")]
0d66636f 11215)
9c08d1fa 11216
f7fbdd4a 11217(define_insn "*not_signextract_onebit"
9c08d1fa 11218 [(set (match_operand:SI 0 "s_register_operand" "=r")
11219 (not:SI
11220 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
11221 (const_int 1)
ed750274 11222 (match_operand:SI 2 "const_int_operand" "n"))))
11223 (clobber (reg:CC CC_REGNUM))]
cffb2a26 11224 "TARGET_ARM"
9c08d1fa 11225 "*
0d66636f 11226 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
11227 output_asm_insn (\"tst\\t%1, %2\", operands);
11228 output_asm_insn (\"mvneq\\t%0, #0\", operands);
11229 return \"movne\\t%0, #0\";
11230 "
11231 [(set_attr "conds" "clob")
1b7da4ac 11232 (set_attr "length" "12")
11233 (set_attr "type" "multiple")]
0d66636f 11234)
25f905c2 11235;; ??? The above patterns need auditing for Thumb-2
87b22bf7 11236
0d66636f 11237;; Push multiple registers to the stack. Registers are in parallel (use ...)
11238;; expressions. For simplicity, the first register is also in the unspec
11239;; part.
08508cbf 11240;; To avoid the usage of GNU extension, the length attribute is computed
11241;; in a C function arm_attr_length_push_multi.
f7fbdd4a 11242(define_insn "*push_multi"
87b22bf7 11243 [(match_parallel 2 "multi_register_push"
7571d3f7 11244 [(set (match_operand:BLK 0 "push_mult_memory_operand" "")
3cc80a30 11245 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "")]
e1159bbe 11246 UNSPEC_PUSH_MULT))])]
7571d3f7 11247 ""
87b22bf7 11248 "*
215b30b3 11249 {
11250 int num_saves = XVECLEN (operands[2], 0);
ed593f11 11251
215b30b3 11252 /* For the StrongARM at least it is faster to
25f905c2 11253 use STR to store only a single register.
542d5028 11254 In Thumb mode always use push, and the assembler will pick
11255 something appropriate. */
25f905c2 11256 if (num_saves == 1 && TARGET_ARM)
61309563 11257 output_asm_insn (\"str%?\\t%1, [%m0, #-4]!\", operands);
215b30b3 11258 else
11259 {
11260 int i;
11261 char pattern[100];
ed593f11 11262
3ef90e77 11263 if (TARGET_32BIT)
61309563 11264 strcpy (pattern, \"push%?\\t{%1\");
25f905c2 11265 else
11266 strcpy (pattern, \"push\\t{%1\");
215b30b3 11267
6079f055 11268 for (i = 1; i < num_saves; i++)
215b30b3 11269 {
11270 strcat (pattern, \", %|\");
11271 strcat (pattern,
11272 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
11273 }
11274
11275 strcat (pattern, \"}\");
11276 output_asm_insn (pattern, operands);
11277 }
11278
11279 return \"\";
11280 }"
9f2c2a36 11281 [(set_attr "type" "store_16")
a6864a24 11282 (set (attr "length")
08508cbf 11283 (symbol_ref "arm_attr_length_push_multi (operands[2], operands[1])"))]
215b30b3 11284)
f7fbdd4a 11285
4c58c898 11286(define_insn "stack_tie"
11287 [(set (mem:BLK (scratch))
aaa37ad6 11288 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "rk")
11289 (match_operand:SI 1 "s_register_operand" "rk")]
4c58c898 11290 UNSPEC_PRLG_STK))]
11291 ""
11292 ""
1b7da4ac 11293 [(set_attr "length" "0")
11294 (set_attr "type" "block")]
4c58c898 11295)
11296
426be8c5 11297;; Pop (as used in epilogue RTL)
11298;;
11299(define_insn "*load_multiple_with_writeback"
11300 [(match_parallel 0 "load_multiple_operation"
11301 [(set (match_operand:SI 1 "s_register_operand" "+rk")
11302 (plus:SI (match_dup 1)
809003b3 11303 (match_operand:SI 2 "const_int_I_operand" "I")))
426be8c5 11304 (set (match_operand:SI 3 "s_register_operand" "=rk")
11305 (mem:SI (match_dup 1)))
11306 ])]
11307 "TARGET_32BIT && (reload_in_progress || reload_completed)"
11308 "*
11309 {
11310 arm_output_multireg_pop (operands, /*return_pc=*/false,
11311 /*cond=*/const_true_rtx,
11312 /*reverse=*/false,
11313 /*update=*/true);
11314 return \"\";
11315 }
11316 "
9f2c2a36 11317 [(set_attr "type" "load_16")
5431c9c9 11318 (set_attr "predicable" "yes")
11319 (set (attr "length")
11320 (symbol_ref "arm_attr_length_pop_multi (operands,
11321 /*return_pc=*/false,
11322 /*write_back_p=*/true)"))]
426be8c5 11323)
11324
11325;; Pop with return (as used in epilogue RTL)
11326;;
11327;; This instruction is generated when the registers are popped at the end of
11328;; epilogue. Here, instead of popping the value into LR and then generating
11329;; jump to LR, value is popped into PC directly. Hence, the pattern is combined
11330;; with (return).
11331(define_insn "*pop_multiple_with_writeback_and_return"
11332 [(match_parallel 0 "pop_multiple_return"
11333 [(return)
11334 (set (match_operand:SI 1 "s_register_operand" "+rk")
11335 (plus:SI (match_dup 1)
809003b3 11336 (match_operand:SI 2 "const_int_I_operand" "I")))
426be8c5 11337 (set (match_operand:SI 3 "s_register_operand" "=rk")
11338 (mem:SI (match_dup 1)))
11339 ])]
11340 "TARGET_32BIT && (reload_in_progress || reload_completed)"
11341 "*
11342 {
11343 arm_output_multireg_pop (operands, /*return_pc=*/true,
11344 /*cond=*/const_true_rtx,
11345 /*reverse=*/false,
11346 /*update=*/true);
11347 return \"\";
11348 }
11349 "
9f2c2a36 11350 [(set_attr "type" "load_16")
5431c9c9 11351 (set_attr "predicable" "yes")
11352 (set (attr "length")
11353 (symbol_ref "arm_attr_length_pop_multi (operands, /*return_pc=*/true,
11354 /*write_back_p=*/true)"))]
426be8c5 11355)
11356
11357(define_insn "*pop_multiple_with_return"
11358 [(match_parallel 0 "pop_multiple_return"
11359 [(return)
11360 (set (match_operand:SI 2 "s_register_operand" "=rk")
11361 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
11362 ])]
11363 "TARGET_32BIT && (reload_in_progress || reload_completed)"
11364 "*
11365 {
11366 arm_output_multireg_pop (operands, /*return_pc=*/true,
11367 /*cond=*/const_true_rtx,
11368 /*reverse=*/false,
11369 /*update=*/false);
11370 return \"\";
11371 }
11372 "
9f2c2a36 11373 [(set_attr "type" "load_16")
5431c9c9 11374 (set_attr "predicable" "yes")
11375 (set (attr "length")
11376 (symbol_ref "arm_attr_length_pop_multi (operands, /*return_pc=*/true,
11377 /*write_back_p=*/false)"))]
426be8c5 11378)
11379
11380;; Load into PC and return
11381(define_insn "*ldr_with_return"
11382 [(return)
11383 (set (reg:SI PC_REGNUM)
11384 (mem:SI (post_inc:SI (match_operand:SI 0 "s_register_operand" "+rk"))))]
11385 "TARGET_32BIT && (reload_in_progress || reload_completed)"
11386 "ldr%?\t%|pc, [%0], #4"
9f2c2a36 11387 [(set_attr "type" "load_4")
426be8c5 11388 (set_attr "predicable" "yes")]
11389)
1a0b0f12 11390;; Pop for floating point registers (as used in epilogue RTL)
11391(define_insn "*vfp_pop_multiple_with_writeback"
11392 [(match_parallel 0 "pop_multiple_fp"
11393 [(set (match_operand:SI 1 "s_register_operand" "+rk")
11394 (plus:SI (match_dup 1)
809003b3 11395 (match_operand:SI 2 "const_int_I_operand" "I")))
2f2163a4 11396 (set (match_operand:DF 3 "vfp_hard_register_operand" "")
1a0b0f12 11397 (mem:DF (match_dup 1)))])]
d7216193 11398 "TARGET_32BIT && TARGET_HARD_FLOAT"
1a0b0f12 11399 "*
11400 {
11401 int num_regs = XVECLEN (operands[0], 0);
11402 char pattern[100];
11403 rtx op_list[2];
b34d8dac 11404 strcpy (pattern, \"vldm\\t\");
1a0b0f12 11405 strcat (pattern, reg_names[REGNO (SET_DEST (XVECEXP (operands[0], 0, 0)))]);
11406 strcat (pattern, \"!, {\");
11407 op_list[0] = XEXP (XVECEXP (operands[0], 0, 1), 0);
11408 strcat (pattern, \"%P0\");
11409 if ((num_regs - 1) > 1)
11410 {
11411 strcat (pattern, \"-%P1\");
11412 op_list [1] = XEXP (XVECEXP (operands[0], 0, num_regs - 1), 0);
11413 }
11414
11415 strcat (pattern, \"}\");
11416 output_asm_insn (pattern, op_list);
11417 return \"\";
11418 }
11419 "
9f2c2a36 11420 [(set_attr "type" "load_16")
1a0b0f12 11421 (set_attr "conds" "unconditional")
11422 (set_attr "predicable" "no")]
11423)
11424
f7fbdd4a 11425;; Special patterns for dealing with the constant pool
11426
cffb2a26 11427(define_insn "align_4"
e1159bbe 11428 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
cffb2a26 11429 "TARGET_EITHER"
f7fbdd4a 11430 "*
cffb2a26 11431 assemble_align (32);
f7fbdd4a 11432 return \"\";
cffb2a26 11433 "
1b7da4ac 11434 [(set_attr "type" "no_insn")]
cffb2a26 11435)
f7fbdd4a 11436
755eb2b4 11437(define_insn "align_8"
11438 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
f9273c43 11439 "TARGET_EITHER"
755eb2b4 11440 "*
11441 assemble_align (64);
11442 return \"\";
11443 "
1b7da4ac 11444 [(set_attr "type" "no_insn")]
755eb2b4 11445)
11446
cffb2a26 11447(define_insn "consttable_end"
e1159bbe 11448 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
cffb2a26 11449 "TARGET_EITHER"
f7fbdd4a 11450 "*
cffb2a26 11451 making_const_table = FALSE;
f7fbdd4a 11452 return \"\";
cffb2a26 11453 "
1b7da4ac 11454 [(set_attr "type" "no_insn")]
cffb2a26 11455)
f7fbdd4a 11456
0e207eb8 11457(define_insn "consttable_1"
11458 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
11459 "TARGET_EITHER"
11460 "*
11461 making_const_table = TRUE;
11462 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
11463 assemble_zeros (3);
11464 return \"\";
11465 "
11466 [(set_attr "length" "4")
11467 (set_attr "type" "no_insn")]
11468)
11469
11470(define_insn "consttable_2"
11471 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
11472 "TARGET_EITHER"
11473 "*
11474 {
11475 rtx x = operands[0];
11476 making_const_table = TRUE;
11477 switch (GET_MODE_CLASS (GET_MODE (x)))
11478 {
11479 case MODE_FLOAT:
11480 arm_emit_fp16_const (x);
11481 break;
11482 default:
11483 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
11484 assemble_zeros (2);
11485 break;
11486 }
11487 return \"\";
11488 }"
11489 [(set_attr "length" "4")
11490 (set_attr "type" "no_insn")]
11491)
11492
cffb2a26 11493(define_insn "consttable_4"
e1159bbe 11494 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
cffb2a26 11495 "TARGET_EITHER"
11496 "*
11497 {
9b8516be 11498 rtx x = operands[0];
cffb2a26 11499 making_const_table = TRUE;
0f97e0f5 11500 scalar_float_mode float_mode;
11501 if (is_a <scalar_float_mode> (GET_MODE (x), &float_mode))
11502 assemble_real (*CONST_DOUBLE_REAL_VALUE (x), float_mode, BITS_PER_WORD);
11503 else
cffb2a26 11504 {
7b04c5d5 11505 /* XXX: Sometimes gcc does something really dumb and ends up with
11506 a HIGH in a constant pool entry, usually because it's trying to
11507 load into a VFP register. We know this will always be used in
11508 combination with a LO_SUM which ignores the high bits, so just
11509 strip off the HIGH. */
11510 if (GET_CODE (x) == HIGH)
11511 x = XEXP (x, 0);
9b8516be 11512 assemble_integer (x, 4, BITS_PER_WORD, 1);
11513 mark_symbol_refs_as_used (x);
cffb2a26 11514 }
11515 return \"\";
11516 }"
1b7da4ac 11517 [(set_attr "length" "4")
11518 (set_attr "type" "no_insn")]
cffb2a26 11519)
11520
11521(define_insn "consttable_8"
e1159bbe 11522 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
cffb2a26 11523 "TARGET_EITHER"
11524 "*
11525 {
11526 making_const_table = TRUE;
0f97e0f5 11527 scalar_float_mode float_mode;
11528 if (is_a <scalar_float_mode> (GET_MODE (operands[0]), &float_mode))
11529 assemble_real (*CONST_DOUBLE_REAL_VALUE (operands[0]),
11530 float_mode, BITS_PER_WORD);
11531 else
11532 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
cffb2a26 11533 return \"\";
11534 }"
1b7da4ac 11535 [(set_attr "length" "8")
11536 (set_attr "type" "no_insn")]
cffb2a26 11537)
11538
d98a3884 11539(define_insn "consttable_16"
11540 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_16)]
11541 "TARGET_EITHER"
11542 "*
11543 {
11544 making_const_table = TRUE;
0f97e0f5 11545 scalar_float_mode float_mode;
11546 if (is_a <scalar_float_mode> (GET_MODE (operands[0]), &float_mode))
11547 assemble_real (*CONST_DOUBLE_REAL_VALUE (operands[0]),
11548 float_mode, BITS_PER_WORD);
11549 else
11550 assemble_integer (operands[0], 16, BITS_PER_WORD, 1);
d98a3884 11551 return \"\";
11552 }"
1b7da4ac 11553 [(set_attr "length" "16")
11554 (set_attr "type" "no_insn")]
d98a3884 11555)
11556
331beb1a 11557;; V5 Instructions,
11558
8f4be2be 11559(define_insn "clzsi2"
11560 [(set (match_operand:SI 0 "s_register_operand" "=r")
11561 (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
b232e6b5 11562 "TARGET_32BIT && arm_arch5t"
ee7cbe0e 11563 "clz%?\\t%0, %1"
bcaec148 11564 [(set_attr "predicable" "yes")
bebe9bbb 11565 (set_attr "type" "clz")])
331beb1a 11566
099ad98b 11567(define_insn "rbitsi2"
11568 [(set (match_operand:SI 0 "s_register_operand" "=r")
11569 (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")] UNSPEC_RBIT))]
11570 "TARGET_32BIT && arm_arch_thumb2"
11571 "rbit%?\\t%0, %1"
11572 [(set_attr "predicable" "yes")
bebe9bbb 11573 (set_attr "type" "clz")])
099ad98b 11574
99ffa689 11575;; Keep this as a CTZ expression until after reload and then split
11576;; into RBIT + CLZ. Since RBIT is represented as an UNSPEC it is unlikely
11577;; to fold with any other expression.
11578
11579(define_insn_and_split "ctzsi2"
11580 [(set (match_operand:SI 0 "s_register_operand" "=r")
11581 (ctz:SI (match_operand:SI 1 "s_register_operand" "r")))]
099ad98b 11582 "TARGET_32BIT && arm_arch_thumb2"
99ffa689 11583 "#"
11584 "&& reload_completed"
11585 [(const_int 0)]
099ad98b 11586 "
99ffa689 11587 emit_insn (gen_rbitsi2 (operands[0], operands[1]));
11588 emit_insn (gen_clzsi2 (operands[0], operands[0]));
11589 DONE;
11590")
099ad98b 11591
e1159bbe 11592;; V5E instructions.
331beb1a 11593
11594(define_insn "prefetch"
f4e79814 11595 [(prefetch (match_operand:SI 0 "address_operand" "p")
11596 (match_operand:SI 1 "" "")
11597 (match_operand:SI 2 "" ""))]
b232e6b5 11598 "TARGET_32BIT && arm_arch5te"
1b7da4ac 11599 "pld\\t%a0"
9f2c2a36 11600 [(set_attr "type" "load_4")]
1b7da4ac 11601)
331beb1a 11602
0d66636f 11603;; General predication pattern
11604
11605(define_cond_exec
11606 [(match_operator 0 "arm_comparison_operator"
11607 [(match_operand 1 "cc_register" "")
11608 (const_int 0)])]
580f4c48 11609 "TARGET_32BIT
11610 && (!TARGET_NO_VOLATILE_CE || !volatile_refs_p (PATTERN (insn)))"
0d66636f 11611 ""
c7a58118 11612[(set_attr "predicated" "yes")]
0d66636f 11613)
11614
fb94f18b 11615(define_insn "force_register_use"
11616 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_REGISTER_USE)]
063a05c7 11617 ""
fb94f18b 11618 "%@ %0 needed"
1b7da4ac 11619 [(set_attr "length" "0")
11620 (set_attr "type" "no_insn")]
063a05c7 11621)
7db9af5d 11622
4c44712e 11623
11624;; Patterns for exception handling
11625
11626(define_expand "eh_return"
11627 [(use (match_operand 0 "general_operand" ""))]
11628 "TARGET_EITHER"
11629 "
11630 {
25f905c2 11631 if (TARGET_32BIT)
4c44712e 11632 emit_insn (gen_arm_eh_return (operands[0]));
11633 else
11634 emit_insn (gen_thumb_eh_return (operands[0]));
11635 DONE;
11636 }"
11637)
11638
11639;; We can't expand this before we know where the link register is stored.
11640(define_insn_and_split "arm_eh_return"
11641 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
11642 VUNSPEC_EH_RETURN)
11643 (clobber (match_scratch:SI 1 "=&r"))]
11644 "TARGET_ARM"
11645 "#"
11646 "&& reload_completed"
11647 [(const_int 0)]
11648 "
11649 {
11650 arm_set_return_address (operands[0], operands[1]);
11651 DONE;
11652 }"
11653)
11654
f655717d 11655\f
11656;; TLS support
11657
11658(define_insn "load_tp_hard"
11659 [(set (match_operand:SI 0 "register_operand" "=r")
11660 (unspec:SI [(const_int 0)] UNSPEC_TLS))]
11661 "TARGET_HARD_TP"
11662 "mrc%?\\tp15, 0, %0, c13, c0, 3\\t@ load_tp_hard"
1b7da4ac 11663 [(set_attr "predicable" "yes")
4b5d7374 11664 (set_attr "type" "mrs")]
f655717d 11665)
11666
11667;; Doesn't clobber R1-R3. Must use r0 for the first operand.
11668(define_insn "load_tp_soft"
11669 [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
11670 (clobber (reg:SI LR_REGNUM))
11671 (clobber (reg:SI IP_REGNUM))
11672 (clobber (reg:CC CC_REGNUM))]
11673 "TARGET_SOFT_TP"
11674 "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
1b7da4ac 11675 [(set_attr "conds" "clob")
11676 (set_attr "type" "branch")]
f655717d 11677)
11678
f41e4452 11679;; tls descriptor call
11680(define_insn "tlscall"
11681 [(set (reg:SI R0_REGNUM)
11682 (unspec:SI [(reg:SI R0_REGNUM)
11683 (match_operand:SI 0 "" "X")
11684 (match_operand 1 "" "")] UNSPEC_TLS))
11685 (clobber (reg:SI R1_REGNUM))
11686 (clobber (reg:SI LR_REGNUM))
11687 (clobber (reg:SI CC_REGNUM))]
11688 "TARGET_GNU2_TLS"
11689 {
11690 targetm.asm_out.internal_label (asm_out_file, "LPIC",
11691 INTVAL (operands[1]));
11692 return "bl\\t%c0(tlscall)";
11693 }
11694 [(set_attr "conds" "clob")
1b7da4ac 11695 (set_attr "length" "4")
11696 (set_attr "type" "branch")]
f41e4452 11697)
11698
1fe0edab 11699;; For thread pointer builtin
11700(define_expand "get_thread_pointersi"
11701 [(match_operand:SI 0 "s_register_operand" "=r")]
11702 ""
11703 "
11704 {
11705 arm_load_tp (operands[0]);
11706 DONE;
11707 }")
11708
f41e4452 11709;;
11710
aabe09ac 11711;; We only care about the lower 16 bits of the constant
11712;; being inserted into the upper 16 bits of the register.
eca5c984 11713(define_insn "*arm_movtas_ze"
417e5cc5 11714 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r,r")
eca5c984 11715 (const_int 16)
11716 (const_int 16))
11717 (match_operand:SI 1 "const_int_operand" ""))]
60a48e7d 11718 "TARGET_HAVE_MOVT"
417e5cc5 11719 "@
11720 movt%?\t%0, %L1
11721 movt\t%0, %L1"
11722 [(set_attr "arch" "32,v8mb")
11723 (set_attr "predicable" "yes")
1b7da4ac 11724 (set_attr "length" "4")
282b4c75 11725 (set_attr "type" "alu_sreg")]
eca5c984 11726)
11727
c0fc3696 11728(define_insn "*arm_rev"
a486b499 11729 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
11730 (bswap:SI (match_operand:SI 1 "s_register_operand" "l,l,r")))]
11731 "arm_arch6"
11732 "@
11733 rev\t%0, %1
11734 rev%?\t%0, %1
11735 rev%?\t%0, %1"
11736 [(set_attr "arch" "t1,t2,32")
1b7da4ac 11737 (set_attr "length" "2,2,4")
4a510717 11738 (set_attr "predicable" "no,yes,yes")
1b7da4ac 11739 (set_attr "type" "rev")]
ff82f757 11740)
11741
11742(define_expand "arm_legacy_rev"
11743 [(set (match_operand:SI 2 "s_register_operand" "")
11744 (xor:SI (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
11745 (const_int 16))
11746 (match_dup 1)))
11747 (set (match_dup 2)
11748 (lshiftrt:SI (match_dup 2)
11749 (const_int 8)))
11750 (set (match_operand:SI 3 "s_register_operand" "")
11751 (rotatert:SI (match_dup 1)
11752 (const_int 8)))
11753 (set (match_dup 2)
11754 (and:SI (match_dup 2)
11755 (const_int -65281)))
11756 (set (match_operand:SI 0 "s_register_operand" "")
11757 (xor:SI (match_dup 3)
11758 (match_dup 2)))]
11759 "TARGET_32BIT"
11760 ""
11761)
11762
11763;; Reuse temporaries to keep register pressure down.
11764(define_expand "thumb_legacy_rev"
11765 [(set (match_operand:SI 2 "s_register_operand" "")
11766 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
11767 (const_int 24)))
11768 (set (match_operand:SI 3 "s_register_operand" "")
11769 (lshiftrt:SI (match_dup 1)
11770 (const_int 24)))
11771 (set (match_dup 3)
11772 (ior:SI (match_dup 3)
11773 (match_dup 2)))
11774 (set (match_operand:SI 4 "s_register_operand" "")
11775 (const_int 16))
11776 (set (match_operand:SI 5 "s_register_operand" "")
11777 (rotatert:SI (match_dup 1)
11778 (match_dup 4)))
11779 (set (match_dup 2)
11780 (ashift:SI (match_dup 5)
11781 (const_int 24)))
11782 (set (match_dup 5)
11783 (lshiftrt:SI (match_dup 5)
11784 (const_int 24)))
11785 (set (match_dup 5)
11786 (ior:SI (match_dup 5)
11787 (match_dup 2)))
11788 (set (match_dup 5)
11789 (rotatert:SI (match_dup 5)
11790 (match_dup 4)))
11791 (set (match_operand:SI 0 "s_register_operand" "")
11792 (ior:SI (match_dup 5)
11793 (match_dup 3)))]
11794 "TARGET_THUMB"
11795 ""
11796)
11797
62e39b06 11798;; ARM-specific expansion of signed mod by power of 2
11799;; using conditional negate.
11800;; For r0 % n where n is a power of 2 produce:
11801;; rsbs r1, r0, #0
11802;; and r0, r0, #(n - 1)
11803;; and r1, r1, #(n - 1)
11804;; rsbpl r0, r1, #0
11805
11806(define_expand "modsi3"
11807 [(match_operand:SI 0 "register_operand" "")
11808 (match_operand:SI 1 "register_operand" "")
11809 (match_operand:SI 2 "const_int_operand" "")]
11810 "TARGET_32BIT"
11811 {
11812 HOST_WIDE_INT val = INTVAL (operands[2]);
11813
11814 if (val <= 0
11815 || exact_log2 (val) <= 0)
11816 FAIL;
11817
11818 rtx mask = GEN_INT (val - 1);
11819
11820 /* In the special case of x0 % 2 we can do the even shorter:
11821 cmp r0, #0
11822 and r0, r0, #1
11823 rsblt r0, r0, #0. */
11824
11825 if (val == 2)
11826 {
11827 rtx cc_reg = arm_gen_compare_reg (LT,
11828 operands[1], const0_rtx, NULL_RTX);
11829 rtx cond = gen_rtx_LT (SImode, cc_reg, const0_rtx);
11830 rtx masked = gen_reg_rtx (SImode);
11831
11832 emit_insn (gen_andsi3 (masked, operands[1], mask));
11833 emit_move_insn (operands[0],
11834 gen_rtx_IF_THEN_ELSE (SImode, cond,
11835 gen_rtx_NEG (SImode,
11836 masked),
11837 masked));
11838 DONE;
11839 }
11840
11841 rtx neg_op = gen_reg_rtx (SImode);
11842 rtx_insn *insn = emit_insn (gen_subsi3_compare0 (neg_op, const0_rtx,
11843 operands[1]));
11844
11845 /* Extract the condition register and mode. */
11846 rtx cmp = XVECEXP (PATTERN (insn), 0, 0);
11847 rtx cc_reg = SET_DEST (cmp);
11848 rtx cond = gen_rtx_GE (SImode, cc_reg, const0_rtx);
11849
11850 emit_insn (gen_andsi3 (operands[0], operands[1], mask));
11851
11852 rtx masked_neg = gen_reg_rtx (SImode);
11853 emit_insn (gen_andsi3 (masked_neg, neg_op, mask));
11854
11855 /* We want a conditional negate here, but emitting COND_EXEC rtxes
11856 during expand does not always work. Do an IF_THEN_ELSE instead. */
11857 emit_move_insn (operands[0],
11858 gen_rtx_IF_THEN_ELSE (SImode, cond,
11859 gen_rtx_NEG (SImode, masked_neg),
11860 operands[0]));
11861
11862
11863 DONE;
11864 }
11865)
11866
ff82f757 11867(define_expand "bswapsi2"
11868 [(set (match_operand:SI 0 "s_register_operand" "=r")
11869 (bswap:SI (match_operand:SI 1 "s_register_operand" "r")))]
8d1af482 11870"TARGET_EITHER && (arm_arch6 || !optimize_size)"
ff82f757 11871"
8d1af482 11872 if (!arm_arch6)
11873 {
11874 rtx op2 = gen_reg_rtx (SImode);
11875 rtx op3 = gen_reg_rtx (SImode);
ff82f757 11876
8d1af482 11877 if (TARGET_THUMB)
11878 {
11879 rtx op4 = gen_reg_rtx (SImode);
11880 rtx op5 = gen_reg_rtx (SImode);
ff82f757 11881
8d1af482 11882 emit_insn (gen_thumb_legacy_rev (operands[0], operands[1],
11883 op2, op3, op4, op5));
11884 }
11885 else
11886 {
11887 emit_insn (gen_arm_legacy_rev (operands[0], operands[1],
11888 op2, op3));
11889 }
ff82f757 11890
8d1af482 11891 DONE;
11892 }
ff82f757 11893 "
11894)
11895
a486b499 11896;; bswap16 patterns: use revsh and rev16 instructions for the signed
11897;; and unsigned variants, respectively. For rev16, expose
11898;; byte-swapping in the lower 16 bits only.
11899(define_insn "*arm_revsh"
11900 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
11901 (sign_extend:SI (bswap:HI (match_operand:HI 1 "s_register_operand" "l,l,r"))))]
11902 "arm_arch6"
11903 "@
11904 revsh\t%0, %1
11905 revsh%?\t%0, %1
11906 revsh%?\t%0, %1"
11907 [(set_attr "arch" "t1,t2,32")
1b7da4ac 11908 (set_attr "length" "2,2,4")
11909 (set_attr "type" "rev")]
a486b499 11910)
11911
11912(define_insn "*arm_rev16"
11913 [(set (match_operand:HI 0 "s_register_operand" "=l,l,r")
11914 (bswap:HI (match_operand:HI 1 "s_register_operand" "l,l,r")))]
11915 "arm_arch6"
11916 "@
11917 rev16\t%0, %1
11918 rev16%?\t%0, %1
11919 rev16%?\t%0, %1"
11920 [(set_attr "arch" "t1,t2,32")
1b7da4ac 11921 (set_attr "length" "2,2,4")
11922 (set_attr "type" "rev")]
09f69e55 11923)
11924
11925;; There are no canonicalisation rules for the position of the lshiftrt, ashift
11926;; operations within an IOR/AND RTX, therefore we have two patterns matching
11927;; each valid permutation.
11928
11929(define_insn "arm_rev16si2"
11930 [(set (match_operand:SI 0 "register_operand" "=l,l,r")
11931 (ior:SI (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "l,l,r")
11932 (const_int 8))
11933 (match_operand:SI 3 "const_int_operand" "n,n,n"))
11934 (and:SI (lshiftrt:SI (match_dup 1)
11935 (const_int 8))
11936 (match_operand:SI 2 "const_int_operand" "n,n,n"))))]
11937 "arm_arch6
11938 && aarch_rev16_shleft_mask_imm_p (operands[3], SImode)
11939 && aarch_rev16_shright_mask_imm_p (operands[2], SImode)"
11940 "rev16\\t%0, %1"
11941 [(set_attr "arch" "t1,t2,32")
11942 (set_attr "length" "2,2,4")
11943 (set_attr "type" "rev")]
11944)
11945
11946(define_insn "arm_rev16si2_alt"
11947 [(set (match_operand:SI 0 "register_operand" "=l,l,r")
11948 (ior:SI (and:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,l,r")
11949 (const_int 8))
11950 (match_operand:SI 2 "const_int_operand" "n,n,n"))
11951 (and:SI (ashift:SI (match_dup 1)
11952 (const_int 8))
11953 (match_operand:SI 3 "const_int_operand" "n,n,n"))))]
11954 "arm_arch6
11955 && aarch_rev16_shleft_mask_imm_p (operands[3], SImode)
11956 && aarch_rev16_shright_mask_imm_p (operands[2], SImode)"
11957 "rev16\\t%0, %1"
11958 [(set_attr "arch" "t1,t2,32")
11959 (set_attr "length" "2,2,4")
11960 (set_attr "type" "rev")]
a486b499 11961)
11962
11963(define_expand "bswaphi2"
11964 [(set (match_operand:HI 0 "s_register_operand" "=r")
11965 (bswap:HI (match_operand:HI 1 "s_register_operand" "r")))]
11966"arm_arch6"
11967""
11968)
11969
1653cf17 11970;; Patterns for LDRD/STRD in Thumb2 mode
11971
11972(define_insn "*thumb2_ldrd"
11973 [(set (match_operand:SI 0 "s_register_operand" "=r")
11974 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
11975 (match_operand:SI 2 "ldrd_strd_offset_operand" "Do"))))
11976 (set (match_operand:SI 3 "s_register_operand" "=r")
11977 (mem:SI (plus:SI (match_dup 1)
11978 (match_operand:SI 4 "const_int_operand" ""))))]
11979 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
1653cf17 11980 && ((INTVAL (operands[2]) + 4) == INTVAL (operands[4]))
11981 && (operands_ok_ldrd_strd (operands[0], operands[3],
11982 operands[1], INTVAL (operands[2]),
11983 false, true))"
11984 "ldrd%?\t%0, %3, [%1, %2]"
9f2c2a36 11985 [(set_attr "type" "load_8")
8bdfd6ed 11986 (set_attr "predicable" "yes")])
1653cf17 11987
11988(define_insn "*thumb2_ldrd_base"
11989 [(set (match_operand:SI 0 "s_register_operand" "=r")
11990 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
11991 (set (match_operand:SI 2 "s_register_operand" "=r")
11992 (mem:SI (plus:SI (match_dup 1)
11993 (const_int 4))))]
11994 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
1653cf17 11995 && (operands_ok_ldrd_strd (operands[0], operands[2],
11996 operands[1], 0, false, true))"
11997 "ldrd%?\t%0, %2, [%1]"
9f2c2a36 11998 [(set_attr "type" "load_8")
8bdfd6ed 11999 (set_attr "predicable" "yes")])
1653cf17 12000
12001(define_insn "*thumb2_ldrd_base_neg"
12002 [(set (match_operand:SI 0 "s_register_operand" "=r")
12003 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
12004 (const_int -4))))
12005 (set (match_operand:SI 2 "s_register_operand" "=r")
12006 (mem:SI (match_dup 1)))]
12007 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
1653cf17 12008 && (operands_ok_ldrd_strd (operands[0], operands[2],
12009 operands[1], -4, false, true))"
12010 "ldrd%?\t%0, %2, [%1, #-4]"
9f2c2a36 12011 [(set_attr "type" "load_8")
8bdfd6ed 12012 (set_attr "predicable" "yes")])
1653cf17 12013
12014(define_insn "*thumb2_strd"
12015 [(set (mem:SI (plus:SI (match_operand:SI 0 "s_register_operand" "rk")
12016 (match_operand:SI 1 "ldrd_strd_offset_operand" "Do")))
12017 (match_operand:SI 2 "s_register_operand" "r"))
12018 (set (mem:SI (plus:SI (match_dup 0)
12019 (match_operand:SI 3 "const_int_operand" "")))
12020 (match_operand:SI 4 "s_register_operand" "r"))]
12021 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
1653cf17 12022 && ((INTVAL (operands[1]) + 4) == INTVAL (operands[3]))
12023 && (operands_ok_ldrd_strd (operands[2], operands[4],
12024 operands[0], INTVAL (operands[1]),
12025 false, false))"
12026 "strd%?\t%2, %4, [%0, %1]"
9f2c2a36 12027 [(set_attr "type" "store_8")
8bdfd6ed 12028 (set_attr "predicable" "yes")])
1653cf17 12029
12030(define_insn "*thumb2_strd_base"
12031 [(set (mem:SI (match_operand:SI 0 "s_register_operand" "rk"))
12032 (match_operand:SI 1 "s_register_operand" "r"))
12033 (set (mem:SI (plus:SI (match_dup 0)
12034 (const_int 4)))
12035 (match_operand:SI 2 "s_register_operand" "r"))]
12036 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
1653cf17 12037 && (operands_ok_ldrd_strd (operands[1], operands[2],
12038 operands[0], 0, false, false))"
12039 "strd%?\t%1, %2, [%0]"
9f2c2a36 12040 [(set_attr "type" "store_8")
8bdfd6ed 12041 (set_attr "predicable" "yes")])
1653cf17 12042
12043(define_insn "*thumb2_strd_base_neg"
12044 [(set (mem:SI (plus:SI (match_operand:SI 0 "s_register_operand" "rk")
12045 (const_int -4)))
12046 (match_operand:SI 1 "s_register_operand" "r"))
12047 (set (mem:SI (match_dup 0))
12048 (match_operand:SI 2 "s_register_operand" "r"))]
12049 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
1653cf17 12050 && (operands_ok_ldrd_strd (operands[1], operands[2],
12051 operands[0], -4, false, false))"
12052 "strd%?\t%1, %2, [%0, #-4]"
9f2c2a36 12053 [(set_attr "type" "store_8")
8bdfd6ed 12054 (set_attr "predicable" "yes")])
1653cf17 12055
2a0c73f2 12056;; ARMv8 CRC32 instructions.
12057(define_insn "<crc_variant>"
12058 [(set (match_operand:SI 0 "s_register_operand" "=r")
12059 (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")
12060 (match_operand:<crc_mode> 2 "s_register_operand" "r")]
12061 CRC))]
12062 "TARGET_CRC32"
12063 "<crc_variant>\\t%0, %1, %2"
12064 [(set_attr "type" "crc")
12065 (set_attr "conds" "unconditional")]
12066)
1653cf17 12067
353cf59a 12068;; Load the load/store double peephole optimizations.
12069(include "ldrdstrd.md")
12070
320ea44d 12071;; Load the load/store multiple patterns
12072(include "ldmstm.md")
426be8c5 12073
12074;; Patterns in ldmstm.md don't cover more than 4 registers. This pattern covers
12075;; large lists without explicit writeback generated for APCS_FRAME epilogue.
3873efff 12076;; The operands are validated through the load_multiple_operation
12077;; match_parallel predicate rather than through constraints so enable it only
12078;; after reload.
426be8c5 12079(define_insn "*load_multiple"
12080 [(match_parallel 0 "load_multiple_operation"
12081 [(set (match_operand:SI 2 "s_register_operand" "=rk")
12082 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
12083 ])]
3873efff 12084 "TARGET_32BIT && reload_completed"
426be8c5 12085 "*
12086 {
12087 arm_output_multireg_pop (operands, /*return_pc=*/false,
12088 /*cond=*/const_true_rtx,
12089 /*reverse=*/false,
12090 /*update=*/false);
12091 return \"\";
12092 }
12093 "
12094 [(set_attr "predicable" "yes")]
12095)
12096
84450ddc 12097(define_expand "copysignsf3"
12098 [(match_operand:SF 0 "register_operand")
12099 (match_operand:SF 1 "register_operand")
12100 (match_operand:SF 2 "register_operand")]
12101 "TARGET_SOFT_FLOAT && arm_arch_thumb2"
12102 "{
12103 emit_move_insn (operands[0], operands[2]);
12104 emit_insn (gen_insv_t2 (simplify_gen_subreg (SImode, operands[0], SFmode, 0),
12105 GEN_INT (31), GEN_INT (0),
12106 simplify_gen_subreg (SImode, operands[1], SFmode, 0)));
12107 DONE;
12108 }"
12109)
12110
12111(define_expand "copysigndf3"
12112 [(match_operand:DF 0 "register_operand")
12113 (match_operand:DF 1 "register_operand")
12114 (match_operand:DF 2 "register_operand")]
12115 "TARGET_SOFT_FLOAT && arm_arch_thumb2"
12116 "{
12117 rtx op0_low = gen_lowpart (SImode, operands[0]);
12118 rtx op0_high = gen_highpart (SImode, operands[0]);
12119 rtx op1_low = gen_lowpart (SImode, operands[1]);
12120 rtx op1_high = gen_highpart (SImode, operands[1]);
12121 rtx op2_high = gen_highpart (SImode, operands[2]);
12122
12123 rtx scratch1 = gen_reg_rtx (SImode);
12124 rtx scratch2 = gen_reg_rtx (SImode);
12125 emit_move_insn (scratch1, op2_high);
12126 emit_move_insn (scratch2, op1_high);
12127
d1f9b275 12128 emit_insn(gen_rtx_SET(scratch1,
84450ddc 12129 gen_rtx_LSHIFTRT (SImode, op2_high, GEN_INT(31))));
12130 emit_insn(gen_insv_t2(scratch2, GEN_INT(1), GEN_INT(31), scratch1));
12131 emit_move_insn (op0_low, op1_low);
12132 emit_move_insn (op0_high, scratch2);
12133
12134 DONE;
12135 }"
12136)
12137
115857ef 12138;; movmisalign patterns for HImode and SImode.
12139(define_expand "movmisalign<mode>"
12140 [(match_operand:HSI 0 "general_operand")
12141 (match_operand:HSI 1 "general_operand")]
12142 "unaligned_access"
12143{
12144 /* This pattern is not permitted to fail during expansion: if both arguments
12145 are non-registers (e.g. memory := constant), force operand 1 into a
12146 register. */
12147 rtx (* gen_unaligned_load)(rtx, rtx);
12148 rtx tmp_dest = operands[0];
12149 if (!s_register_operand (operands[0], <MODE>mode)
12150 && !s_register_operand (operands[1], <MODE>mode))
12151 operands[1] = force_reg (<MODE>mode, operands[1]);
12152
12153 if (<MODE>mode == HImode)
12154 {
12155 gen_unaligned_load = gen_unaligned_loadhiu;
12156 tmp_dest = gen_reg_rtx (SImode);
12157 }
12158 else
12159 gen_unaligned_load = gen_unaligned_loadsi;
12160
12161 if (MEM_P (operands[1]))
12162 {
12163 emit_insn (gen_unaligned_load (tmp_dest, operands[1]));
12164 if (<MODE>mode == HImode)
12165 emit_move_insn (operands[0], gen_lowpart (HImode, tmp_dest));
12166 }
12167 else
12168 emit_insn (gen_unaligned_store<mode> (operands[0], operands[1]));
12169
12170 DONE;
12171})
12172
1be6395a 12173(define_insn "<cdp>"
12174 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "n")
12175 (match_operand:SI 1 "immediate_operand" "n")
12176 (match_operand:SI 2 "immediate_operand" "n")
12177 (match_operand:SI 3 "immediate_operand" "n")
12178 (match_operand:SI 4 "immediate_operand" "n")
12179 (match_operand:SI 5 "immediate_operand" "n")] CDPI)]
12180 "arm_coproc_builtin_available (VUNSPEC_<CDP>)"
12181{
12182 arm_const_bounds (operands[0], 0, 16);
12183 arm_const_bounds (operands[1], 0, 16);
12184 arm_const_bounds (operands[2], 0, (1 << 5));
12185 arm_const_bounds (operands[3], 0, (1 << 5));
12186 arm_const_bounds (operands[4], 0, (1 << 5));
12187 arm_const_bounds (operands[5], 0, 8);
12188 return "<cdp>\\tp%c0, %1, CR%c2, CR%c3, CR%c4, %5";
12189}
12190 [(set_attr "length" "4")
12191 (set_attr "type" "coproc")])
12192
638b44bd 12193(define_insn "*ldc"
12194 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "n")
12195 (match_operand:SI 1 "immediate_operand" "n")
12196 (match_operand:SI 2 "memory_operand" "Uz")] LDCI)]
12197 "arm_coproc_builtin_available (VUNSPEC_<LDC>)"
12198{
12199 arm_const_bounds (operands[0], 0, 16);
12200 arm_const_bounds (operands[1], 0, (1 << 5));
12201 return "<ldc>\\tp%c0, CR%c1, %2";
12202}
12203 [(set_attr "length" "4")
12204 (set_attr "type" "coproc")])
12205
12206(define_insn "*stc"
12207 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "n")
12208 (match_operand:SI 1 "immediate_operand" "n")
12209 (match_operand:SI 2 "memory_operand" "=Uz")] STCI)]
12210 "arm_coproc_builtin_available (VUNSPEC_<STC>)"
12211{
12212 arm_const_bounds (operands[0], 0, 16);
12213 arm_const_bounds (operands[1], 0, (1 << 5));
12214 return "<stc>\\tp%c0, CR%c1, %2";
12215}
12216 [(set_attr "length" "4")
12217 (set_attr "type" "coproc")])
12218
12219(define_expand "<ldc>"
12220 [(unspec_volatile [(match_operand:SI 0 "immediate_operand")
12221 (match_operand:SI 1 "immediate_operand")
12222 (mem:SI (match_operand:SI 2 "s_register_operand"))] LDCI)]
12223 "arm_coproc_builtin_available (VUNSPEC_<LDC>)")
12224
12225(define_expand "<stc>"
12226 [(unspec_volatile [(match_operand:SI 0 "immediate_operand")
12227 (match_operand:SI 1 "immediate_operand")
12228 (mem:SI (match_operand:SI 2 "s_register_operand"))] STCI)]
12229 "arm_coproc_builtin_available (VUNSPEC_<STC>)")
12230
415e9b1f 12231(define_insn "<mcr>"
12232 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "n")
12233 (match_operand:SI 1 "immediate_operand" "n")
12234 (match_operand:SI 2 "s_register_operand" "r")
12235 (match_operand:SI 3 "immediate_operand" "n")
12236 (match_operand:SI 4 "immediate_operand" "n")
12237 (match_operand:SI 5 "immediate_operand" "n")] MCRI)
12238 (use (match_dup 2))]
12239 "arm_coproc_builtin_available (VUNSPEC_<MCR>)"
12240{
12241 arm_const_bounds (operands[0], 0, 16);
12242 arm_const_bounds (operands[1], 0, 8);
12243 arm_const_bounds (operands[3], 0, (1 << 5));
12244 arm_const_bounds (operands[4], 0, (1 << 5));
12245 arm_const_bounds (operands[5], 0, 8);
12246 return "<mcr>\\tp%c0, %1, %2, CR%c3, CR%c4, %5";
12247}
12248 [(set_attr "length" "4")
12249 (set_attr "type" "coproc")])
12250
12251(define_insn "<mrc>"
12252 [(set (match_operand:SI 0 "s_register_operand" "=r")
6f8d7784 12253 (unspec_volatile:SI [(match_operand:SI 1 "immediate_operand" "n")
415e9b1f 12254 (match_operand:SI 2 "immediate_operand" "n")
12255 (match_operand:SI 3 "immediate_operand" "n")
12256 (match_operand:SI 4 "immediate_operand" "n")
12257 (match_operand:SI 5 "immediate_operand" "n")] MRCI))]
12258 "arm_coproc_builtin_available (VUNSPEC_<MRC>)"
12259{
12260 arm_const_bounds (operands[1], 0, 16);
12261 arm_const_bounds (operands[2], 0, 8);
12262 arm_const_bounds (operands[3], 0, (1 << 5));
12263 arm_const_bounds (operands[4], 0, (1 << 5));
12264 arm_const_bounds (operands[5], 0, 8);
12265 return "<mrc>\\tp%c1, %2, %0, CR%c3, CR%c4, %5";
12266}
12267 [(set_attr "length" "4")
12268 (set_attr "type" "coproc")])
12269
cabfd710 12270(define_insn "<mcrr>"
12271 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "n")
12272 (match_operand:SI 1 "immediate_operand" "n")
12273 (match_operand:DI 2 "s_register_operand" "r")
12274 (match_operand:SI 3 "immediate_operand" "n")] MCRRI)
12275 (use (match_dup 2))]
12276 "arm_coproc_builtin_available (VUNSPEC_<MCRR>)"
12277{
12278 arm_const_bounds (operands[0], 0, 16);
12279 arm_const_bounds (operands[1], 0, 8);
12280 arm_const_bounds (operands[3], 0, (1 << 5));
12281 return "<mcrr>\\tp%c0, %1, %Q2, %R2, CR%c3";
12282}
12283 [(set_attr "length" "4")
12284 (set_attr "type" "coproc")])
12285
12286(define_insn "<mrrc>"
12287 [(set (match_operand:DI 0 "s_register_operand" "=r")
6f8d7784 12288 (unspec_volatile:DI [(match_operand:SI 1 "immediate_operand" "n")
cabfd710 12289 (match_operand:SI 2 "immediate_operand" "n")
12290 (match_operand:SI 3 "immediate_operand" "n")] MRRCI))]
12291 "arm_coproc_builtin_available (VUNSPEC_<MRRC>)"
12292{
12293 arm_const_bounds (operands[1], 0, 16);
12294 arm_const_bounds (operands[2], 0, 8);
12295 arm_const_bounds (operands[3], 0, (1 << 5));
12296 return "<mrrc>\\tp%c1, %2, %Q0, %R0, CR%c3";
12297}
12298 [(set_attr "length" "4")
12299 (set_attr "type" "coproc")])
12300
be626997 12301(define_expand "speculation_barrier"
12302 [(unspec_volatile [(const_int 0)] VUNSPEC_SPECULATION_BARRIER)]
12303 "TARGET_EITHER"
12304 "
a7852b35 12305 /* For thumb1 (except Armv8 derivatives), and for pre-Armv7 we don't
12306 have a usable barrier (and probably don't need one in practice).
12307 But to be safe if such code is run on later architectures, call a
12308 helper function in libgcc that will do the thing for the active
12309 system. */
12310 if (!(arm_arch7 || arm_arch8))
12311 {
12312 arm_emit_speculation_barrier_function ();
12313 DONE;
12314 }
be626997 12315 "
12316)
12317
12318;; Generate a hard speculation barrier when we have not enabled speculation
12319;; tracking.
12320(define_insn "*speculation_barrier_insn"
12321 [(unspec_volatile [(const_int 0)] VUNSPEC_SPECULATION_BARRIER)]
a7852b35 12322 "arm_arch7 || arm_arch8"
be626997 12323 "isb\;dsb\\tsy"
12324 [(set_attr "type" "block")
12325 (set_attr "length" "8")]
12326)
12327
d98a3884 12328;; Vector bits common to IWMMXT and Neon
12329(include "vec-common.md")
755eb2b4 12330;; Load the Intel Wireless Multimedia Extension patterns
12331(include "iwmmxt.md")
a2cd141b 12332;; Load the VFP co-processor patterns
12333(include "vfp.md")
bc360af8 12334;; Thumb-1 patterns
12335(include "thumb1.md")
25f905c2 12336;; Thumb-2 patterns
12337(include "thumb2.md")
d98a3884 12338;; Neon patterns
12339(include "neon.md")
e84fdf6e 12340;; Crypto patterns
12341(include "crypto.md")
06df6b17 12342;; Synchronization Primitives
12343(include "sync.md")
bbbe4599 12344;; Fixed-point patterns
12345(include "arm-fixed.md")