]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/arm/arm.md
[arm] Allow the summation result of signed add-with-overflow to be discarded.
[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
85fc66a7 34 (FDPIC_REGNUM 9) ; FDPIC register
bffbb863 35 (IP_REGNUM 12) ; Scratch register
36 (SP_REGNUM 13) ; Stack pointer
37 (LR_REGNUM 14) ; Return address register
38 (PC_REGNUM 15) ; Program counter
39 (LAST_ARM_REGNUM 15) ;
40 (CC_REGNUM 100) ; Condition code pseudo register
41 (VFPCC_REGNUM 101) ; VFP Condition code pseudo register
e1159bbe 42 ]
43)
3c5afce6 44;; 3rd operand to select_dominance_cc_mode
45(define_constants
46 [(DOM_CC_X_AND_Y 0)
47 (DOM_CC_NX_OR_Y 1)
48 (DOM_CC_X_OR_Y 2)
49 ]
50)
2ff91fec 51;; conditional compare combination
52(define_constants
53 [(CMP_CMP 0)
54 (CMN_CMP 1)
55 (CMP_CMN 2)
56 (CMN_CMN 3)
57 (NUM_OF_COND_CMP 4)
58 ]
59)
e1159bbe 60
b11cae9e 61\f
e1159bbe 62;;---------------------------------------------------------------------------
9c08d1fa 63;; Attributes
64
a651f34d 65;; Processor type. This is created automatically from arm-cores.def.
66(include "arm-tune.md")
67
861033d5 68;; Instruction classification types
69(include "types.md")
70
215b30b3 71; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
72; generating ARM code. This is used to control the length of some insn
73; patterns that share the same RTL in both ARM and Thumb code.
8724f216 74(define_attr "is_thumb" "yes,no"
75 (const (if_then_else (symbol_ref "TARGET_THUMB")
76 (const_string "yes") (const_string "no"))))
cffb2a26 77
ef51b8e1 78; IS_ARCH6 is set to 'yes' when we are generating code form ARMv6.
79(define_attr "is_arch6" "no,yes" (const (symbol_ref "arm_arch6")))
80
747b7458 81; IS_THUMB1 is set to 'yes' iff we are generating Thumb-1 code.
8724f216 82(define_attr "is_thumb1" "yes,no"
83 (const (if_then_else (symbol_ref "TARGET_THUMB1")
84 (const_string "yes") (const_string "no"))))
747b7458 85
8bdfd6ed 86; Mark an instruction as suitable for "short IT" blocks in Thumb-2.
87; The arm_restrict_it flag enables the "short IT" feature which
88; restricts IT blocks to a single 16-bit instruction.
89; This attribute should only be used on 16-bit Thumb-2 instructions
90; which may be predicated (the "predicable" attribute must be set).
91(define_attr "predicable_short_it" "no,yes" (const_string "no"))
92
93; Mark an instruction as suitable for "short IT" blocks in Thumb-2.
94; This attribute should only be used on instructions which may emit
95; an IT block in their expansion which is not a short IT.
96(define_attr "enabled_for_short_it" "no,yes" (const_string "yes"))
c7a58118 97
331beb1a 98;; Operand number of an input operand that is shifted. Zero if the
99;; given instruction does not shift one of its input operands.
331beb1a 100(define_attr "shift" "" (const_int 0))
101
55a94dda 102;; [For compatibility with AArch64 in pipeline models]
103;; Attribute that specifies whether or not the instruction touches fp
104;; registers.
105(define_attr "fp" "no,yes" (const_string "no"))
106
3d91c5d6 107; Floating Point Unit. If we only have floating point emulation, then there
108; is no point in scheduling the floating point insns. (Well, for best
109; performance we should try and group them together).
bffbb863 110(define_attr "fpu" "none,vfp"
c7f506fd 111 (const (symbol_ref "arm_fpu_attr")))
3d91c5d6 112
b2bcff19 113; Predicated means that the insn form is conditionally executed based on a
114; predicate. We default to 'no' because no Thumb patterns match this rule
115; and not all ARM insns do.
c7a58118 116(define_attr "predicated" "yes,no" (const_string "no"))
117
094e994f 118; LENGTH of an instruction (in bytes)
06df6b17 119(define_attr "length" ""
e1b93706 120 (const_int 4))
9c08d1fa 121
d5d4dc8d 122; The architecture which supports the instruction (or alternative).
123; This can be "a" for ARM, "t" for either of the Thumbs, "32" for
124; TARGET_32BIT, "t1" or "t2" to specify a specific Thumb mode. "v6"
125; for ARM or Thumb-2 with arm_arch6, and nov6 for ARM without
417e5cc5 126; arm_arch6. "v6t2" for Thumb-2 with arm_arch6 and "v8mb" for ARMv8-M
127; Baseline. This attribute is used to compute attribute "enabled",
128; use type "any" to enable an alternative in all cases.
def2e672 129(define_attr "arch" "any,a,t,32,t1,t2,v6,nov6,v6t2,v8mb,iwmmxt,iwmmxt2,armv6_or_vfpv3,neon"
d5d4dc8d 130 (const_string "any"))
131
132(define_attr "arch_enabled" "no,yes"
133 (cond [(eq_attr "arch" "any")
134 (const_string "yes")
135
136 (and (eq_attr "arch" "a")
0bf497f5 137 (match_test "TARGET_ARM"))
d5d4dc8d 138 (const_string "yes")
139
140 (and (eq_attr "arch" "t")
0bf497f5 141 (match_test "TARGET_THUMB"))
d5d4dc8d 142 (const_string "yes")
143
144 (and (eq_attr "arch" "t1")
0bf497f5 145 (match_test "TARGET_THUMB1"))
d5d4dc8d 146 (const_string "yes")
147
148 (and (eq_attr "arch" "t2")
0bf497f5 149 (match_test "TARGET_THUMB2"))
d5d4dc8d 150 (const_string "yes")
151
152 (and (eq_attr "arch" "32")
0bf497f5 153 (match_test "TARGET_32BIT"))
d5d4dc8d 154 (const_string "yes")
155
156 (and (eq_attr "arch" "v6")
0bf497f5 157 (match_test "TARGET_32BIT && arm_arch6"))
d5d4dc8d 158 (const_string "yes")
159
160 (and (eq_attr "arch" "nov6")
0bf497f5 161 (match_test "TARGET_32BIT && !arm_arch6"))
a651f34d 162 (const_string "yes")
163
e4585731 164 (and (eq_attr "arch" "v6t2")
165 (match_test "TARGET_32BIT && arm_arch6 && arm_arch_thumb2"))
166 (const_string "yes")
167
417e5cc5 168 (and (eq_attr "arch" "v8mb")
169 (match_test "TARGET_THUMB1 && arm_arch8"))
170 (const_string "yes")
171
6b8f7c28 172 (and (eq_attr "arch" "iwmmxt2")
173 (match_test "TARGET_REALLY_IWMMXT2"))
21cc9773 174 (const_string "yes")
175
176 (and (eq_attr "arch" "armv6_or_vfpv3")
177 (match_test "arm_arch6 || TARGET_VFP3"))
178 (const_string "yes")
ac876af5 179
180 (and (eq_attr "arch" "neon")
181 (match_test "TARGET_NEON"))
182 (const_string "yes")
21cc9773 183 ]
6b8f7c28 184
d5d4dc8d 185 (const_string "no")))
186
aa06c51c 187(define_attr "opt" "any,speed,size"
188 (const_string "any"))
189
190(define_attr "opt_enabled" "no,yes"
191 (cond [(eq_attr "opt" "any")
192 (const_string "yes")
193
194 (and (eq_attr "opt" "speed")
195 (match_test "optimize_function_for_speed_p (cfun)"))
196 (const_string "yes")
197
198 (and (eq_attr "opt" "size")
199 (match_test "optimize_function_for_size_p (cfun)"))
200 (const_string "yes")]
201 (const_string "no")))
202
861033d5 203(define_attr "use_literal_pool" "no,yes"
204 (cond [(and (eq_attr "type" "f_loads,f_loadd")
205 (match_test "CONSTANT_P (operands[1])"))
206 (const_string "yes")]
207 (const_string "no")))
208
d5d4dc8d 209; Enable all alternatives that are both arch_enabled and insn_enabled.
951a3f72 210; FIXME:: opt_enabled has been temporarily removed till the time we have
211; an attribute that allows the use of such alternatives.
212; This depends on caching of speed_p, size_p on a per
213; alternative basis. The problem is that the enabled attribute
214; cannot depend on any state that is not cached or is not constant
215; for a compilation unit. We probably need a generic "hot/cold"
216; alternative which if implemented can help with this. We disable this
217; until such a time as this is implemented and / or the improvements or
218; regressions with removing this attribute are double checked.
219; See ashldi3_neon and <shift>di3_neon in neon.md.
220
93b431d9 221 (define_attr "enabled" "no,yes"
0abea32c 222 (cond [(and (eq_attr "predicable_short_it" "no")
c7a58118 223 (and (eq_attr "predicated" "yes")
224 (match_test "arm_restrict_it")))
225 (const_string "no")
226
8bdfd6ed 227 (and (eq_attr "enabled_for_short_it" "no")
c7a58118 228 (match_test "arm_restrict_it"))
229 (const_string "no")
230
aa06c51c 231 (eq_attr "arch_enabled" "no")
aa06c51c 232 (const_string "no")]
233 (const_string "yes")))
d5d4dc8d 234
56d27660 235; POOL_RANGE is how far away from a constant pool entry that this insn
236; can be placed. If the distance is zero, then this insn will never
237; reference the pool.
42e1de19 238; Note that for Thumb constant pools the PC value is rounded down to the
239; nearest multiple of four. Therefore, THUMB2_POOL_RANGE (and POOL_RANGE for
240; Thumb insns) should be set to <max_range> - 2.
cffb2a26 241; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
8848d797 242; before its address. It is set to <max_range> - (8 + <data_size>).
cde1623a 243(define_attr "arm_pool_range" "" (const_int 0))
244(define_attr "thumb2_pool_range" "" (const_int 0))
245(define_attr "arm_neg_pool_range" "" (const_int 0))
246(define_attr "thumb2_neg_pool_range" "" (const_int 0))
247
248(define_attr "pool_range" ""
249 (cond [(eq_attr "is_thumb" "yes") (attr "thumb2_pool_range")]
250 (attr "arm_pool_range")))
251(define_attr "neg_pool_range" ""
252 (cond [(eq_attr "is_thumb" "yes") (attr "thumb2_neg_pool_range")]
253 (attr "arm_neg_pool_range")))
56d27660 254
215b30b3 255; An assembler sequence may clobber the condition codes without us knowing.
4d7a8451 256; If such an insn references the pool, then we have no way of knowing how,
257; so use the most conservative value for pool_range.
9c08d1fa 258(define_asm_attributes
4d7a8451 259 [(set_attr "conds" "clob")
260 (set_attr "length" "4")
261 (set_attr "pool_range" "250")])
9c08d1fa 262
9888ad6d 263; Load scheduling, set from the arm_ld_sched variable
4c834714 264; initialized by arm_option_override()
9888ad6d 265(define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
849170fd 266
f7fbdd4a 267; condition codes: this one is used by final_prescan_insn to speed up
268; conditionalizing instructions. It saves having to scan the rtl to see if
269; it uses or alters the condition codes.
215b30b3 270;
f7fbdd4a 271; USE means that the condition codes are used by the insn in the process of
215b30b3 272; outputting code, this means (at present) that we can't use the insn in
273; inlined branches
274;
f7fbdd4a 275; SET means that the purpose of the insn is to set the condition codes in a
215b30b3 276; well defined manner.
277;
f7fbdd4a 278; CLOB means that the condition codes are altered in an undefined manner, if
215b30b3 279; they are altered at all
280;
f4d3c071 281; UNCONDITIONAL means the instruction cannot be conditionally executed and
ad6d3e2a 282; that the instruction does not use or alter the condition codes.
c52acdd2 283;
ad6d3e2a 284; NOCOND means that the instruction does not use or alter the condition
285; codes but can be converted into a conditionally exectuted instruction.
f7fbdd4a 286
b0694be0 287(define_attr "conds" "use,set,clob,unconditional,nocond"
747b7458 288 (if_then_else
289 (ior (eq_attr "is_thumb1" "yes")
290 (eq_attr "type" "call"))
c1a66faf 291 (const_string "clob")
32093010 292 (if_then_else (eq_attr "is_neon_type" "no")
52432540 293 (const_string "nocond")
294 (const_string "unconditional"))))
f7fbdd4a 295
215b30b3 296; Predicable means that the insn can be conditionally executed based on
297; an automatically added predicate (additional patterns are generated by
298; gen...). We default to 'no' because no Thumb patterns match this rule
299; and not all ARM patterns do.
0d66636f 300(define_attr "predicable" "no,yes" (const_string "no"))
301
129a2fe4 302; Only model the write buffer for ARM6 and ARM7. Earlier processors don't
303; have one. Later ones, such as StrongARM, have write-back caches, so don't
8d232dc7 304; suffer blockages enough to warrant modelling this (and it can adversely
129a2fe4 305; affect the schedule).
74a71f7d 306(define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_tune_wbuf")))
129a2fe4 307
215b30b3 308; WRITE_CONFLICT implies that a read following an unrelated write is likely
309; to stall the processor. Used with model_wbuf above.
9c08d1fa 310(define_attr "write_conflict" "no,yes"
311 (if_then_else (eq_attr "type"
9f2c2a36 312 "block,call,load_4")
9c08d1fa 313 (const_string "yes")
314 (const_string "no")))
315
215b30b3 316; Classify the insns into those that take one cycle and those that take more
317; than one on the main cpu execution unit.
f7fbdd4a 318(define_attr "core_cycles" "single,multi"
319 (if_then_else (eq_attr "type"
112eda6f 320 "adc_imm, adc_reg, adcs_imm, adcs_reg, adr, alu_ext, alu_imm, alu_sreg,\
321 alu_shift_imm, alu_shift_reg, alu_dsp_reg, alus_ext, alus_imm, alus_sreg,\
d82e788e 322 alus_shift_imm, alus_shift_reg, bfm, csel, rev, logic_imm, logic_reg,\
323 logic_shift_imm, logic_shift_reg, logics_imm, logics_reg,\
324 logics_shift_imm, logics_shift_reg, extend, shift_imm, float, fcsel,\
7cb6c048 325 wmmx_wor, wmmx_wxor, wmmx_wand, wmmx_wandn, wmmx_wmov, wmmx_tmcrr,\
326 wmmx_tmrrc, wmmx_wldr, wmmx_wstr, wmmx_tmcr, wmmx_tmrc, wmmx_wadd,\
327 wmmx_wsub, wmmx_wmul, wmmx_wmac, wmmx_wavg2, wmmx_tinsr, wmmx_textrm,\
328 wmmx_wshufh, wmmx_wcmpeq, wmmx_wcmpgt, wmmx_wmax, wmmx_wmin, wmmx_wpack,\
329 wmmx_wunpckih, wmmx_wunpckil, wmmx_wunpckeh, wmmx_wunpckel, wmmx_wror,\
330 wmmx_wsra, wmmx_wsrl, wmmx_wsll, wmmx_wmadd, wmmx_tmia, wmmx_tmiaph,\
331 wmmx_tmiaxy, wmmx_tbcst, wmmx_tmovmsk, wmmx_wacc, wmmx_waligni,\
332 wmmx_walignr, wmmx_tandc, wmmx_textrc, wmmx_torc, wmmx_torvsc, wmmx_wsad,\
333 wmmx_wabs, wmmx_wabsdiff, wmmx_waddsubhx, wmmx_wsubaddhx, wmmx_wavg4,\
334 wmmx_wmulw, wmmx_wqmulm, wmmx_wqmulwm, wmmx_waddbhus, wmmx_wqmiaxy,\
335 wmmx_wmiaxy, wmmx_wmiawxy, wmmx_wmerge")
f7fbdd4a 336 (const_string "single")
337 (const_string "multi")))
338
cffb2a26 339;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
215b30b3 340;; distant label. Only applicable to Thumb code.
cffb2a26 341(define_attr "far_jump" "yes,no" (const_string "no"))
342
d51f92df 343
25f905c2 344;; The number of machine instructions this pattern expands to.
345;; Used for Thumb-2 conditional execution.
346(define_attr "ce_count" "" (const_int 1))
347
4182b724 348;;---------------------------------------------------------------------------
349;; Unspecs
350
351(include "unspecs.md")
352
d51f92df 353;;---------------------------------------------------------------------------
fd781bb2 354;; Mode iterators
d51f92df 355
3de0dec6 356(include "iterators.md")
03770691 357
d51f92df 358;;---------------------------------------------------------------------------
359;; Predicates
360
9c9db025 361(include "predicates.md")
234f6557 362(include "constraints.md")
9c9db025 363
a2cd141b 364;;---------------------------------------------------------------------------
365;; Pipeline descriptions
215b30b3 366
e3879fd0 367(define_attr "tune_cortexr4" "yes,no"
368 (const (if_then_else
7d3cda8c 369 (eq_attr "tune" "cortexr4,cortexr4f,cortexr5")
e3879fd0 370 (const_string "yes")
371 (const_string "no"))))
372
a2cd141b 373;; True if the generic scheduling description should be used.
374
375(define_attr "generic_sched" "yes,no"
2546d93a 376 (const (if_then_else
e18862f3 377 (ior (eq_attr "tune" "fa526,fa626,fa606te,fa626te,fmp626,fa726te,\
1efe0507 378 arm926ejs,arm10e,arm1026ejs,arm1136js,\
e18862f3 379 arm1136jfs,cortexa5,cortexa7,cortexa8,\
42e7b263 380 cortexa9,cortexa12,cortexa15,cortexa17,\
b1099bfd 381 cortexa53,cortexa57,cortexm4,cortexm7,\
802e6377 382 exynosm1,marvell_pj4,xgene1")
2546d93a 383 (eq_attr "tune_cortexr4" "yes"))
4d5cb40d 384 (const_string "no")
385 (const_string "yes"))))
386
c0e1af52 387(define_attr "generic_vfp" "yes,no"
388 (const (if_then_else
389 (and (eq_attr "fpu" "vfp")
1efe0507 390 (eq_attr "tune" "!arm10e,cortexa5,cortexa7,\
e18862f3 391 cortexa8,cortexa9,cortexa53,cortexm4,\
55a94dda 392 cortexm7,marvell_pj4,xgene1")
e3879fd0 393 (eq_attr "tune_cortexr4" "no"))
c0e1af52 394 (const_string "yes")
395 (const_string "no"))))
396
6b8f7c28 397(include "marvell-f-iwmmxt.md")
a2cd141b 398(include "arm-generic.md")
399(include "arm926ejs.md")
c0e1af52 400(include "arm1020e.md")
a2cd141b 401(include "arm1026ejs.md")
402(include "arm1136jfs.md")
0e266d06 403(include "fa526.md")
404(include "fa606te.md")
405(include "fa626te.md")
406(include "fmp626.md")
407(include "fa726te.md")
3f1e069f 408(include "cortex-a5.md")
d6b7f019 409(include "cortex-a7.md")
bcaec148 410(include "cortex-a8.md")
036068af 411(include "cortex-a9.md")
65f2f758 412(include "cortex-a15.md")
42e7b263 413(include "cortex-a17.md")
da10bc87 414(include "cortex-a53.md")
b1099bfd 415(include "cortex-a57.md")
934a1e72 416(include "cortex-r4.md")
e3879fd0 417(include "cortex-r4f.md")
e18862f3 418(include "cortex-m7.md")
2546d93a 419(include "cortex-m4.md")
420(include "cortex-m4-fpu.md")
802e6377 421(include "exynos-m1.md")
55e3ada8 422(include "vfp11.md")
ea7d210b 423(include "marvell-pj4.md")
55a94dda 424(include "xgene1.md")
3586df96 425
9c08d1fa 426\f
215b30b3 427;;---------------------------------------------------------------------------
e1159bbe 428;; Insn patterns
429;;
a0f94409 430;; Addition insns.
215b30b3 431
9c08d1fa 432;; Note: For DImode insns, there is normally no reason why operands should
433;; not be in the same register, what we don't want is for something being
434;; written to partially overlap something that is an input.
435
cffb2a26 436(define_expand "adddi3"
437 [(parallel
3934ae0e 438 [(set (match_operand:DI 0 "s_register_operand")
439 (plus:DI (match_operand:DI 1 "s_register_operand")
6cc8c27c 440 (match_operand:DI 2 "reg_or_int_operand")))
bd5b4116 441 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 442 "TARGET_EITHER"
443 "
6cc8c27c 444 if (TARGET_THUMB1)
445 {
446 if (!REG_P (operands[2]))
447 operands[2] = force_reg (DImode, operands[2]);
448 }
449 else
450 {
451 rtx lo_result, hi_result, lo_dest, hi_dest;
452 rtx lo_op1, hi_op1, lo_op2, hi_op2;
453 arm_decompose_di_binop (operands[1], operands[2], &lo_op1, &hi_op1,
454 &lo_op2, &hi_op2);
455 lo_result = lo_dest = gen_lowpart (SImode, operands[0]);
456 hi_result = hi_dest = gen_highpart (SImode, operands[0]);
457
458 if (lo_op2 == const0_rtx)
459 {
460 lo_dest = lo_op1;
461 if (!arm_add_operand (hi_op2, SImode))
462 hi_op2 = force_reg (SImode, hi_op2);
463 /* Assume hi_op2 won't also be zero. */
464 emit_insn (gen_addsi3 (hi_dest, hi_op1, hi_op2));
465 }
466 else
467 {
468 if (!arm_add_operand (lo_op2, SImode))
469 lo_op2 = force_reg (SImode, lo_op2);
470 if (!arm_not_operand (hi_op2, SImode))
471 hi_op2 = force_reg (SImode, hi_op2);
472
eaddabc8 473 emit_insn (gen_addsi3_compare_op1 (lo_dest, lo_op1, lo_op2));
40155e19 474 rtx carry = gen_rtx_LTU (SImode, gen_rtx_REG (CC_Cmode, CC_REGNUM),
475 const0_rtx);
6cc8c27c 476 if (hi_op2 == const0_rtx)
40155e19 477 emit_insn (gen_add0si3_carryin (hi_dest, hi_op1, carry));
6cc8c27c 478 else
40155e19 479 emit_insn (gen_addsi3_carryin (hi_dest, hi_op1, hi_op2, carry));
6cc8c27c 480 }
481
482 if (lo_result != lo_dest)
483 emit_move_insn (lo_result, lo_dest);
484 if (hi_result != hi_dest)
485 emit_move_insn (gen_highpart (SImode, operands[0]), hi_dest);
486 DONE;
487 }
cffb2a26 488 "
489)
490
d302ef3a 491(define_expand "addvsi4"
492 [(match_operand:SI 0 "s_register_operand")
493 (match_operand:SI 1 "s_register_operand")
494 (match_operand:SI 2 "arm_add_operand")
495 (match_operand 3 "")]
496 "TARGET_32BIT"
497{
498 if (CONST_INT_P (operands[2]))
499 emit_insn (gen_addsi3_compareV_imm (operands[0], operands[1], operands[2]));
500 else
501 emit_insn (gen_addsi3_compareV_reg (operands[0], operands[1], operands[2]));
502 arm_gen_unlikely_cbranch (NE, CC_Vmode, operands[3]);
503
504 DONE;
505})
506
507(define_expand "addvdi4"
508 [(match_operand:DI 0 "register_operand")
509 (match_operand:DI 1 "register_operand")
510 (match_operand:DI 2 "register_operand")
f6c98a9a 511 (match_operand 3 "")]
512 "TARGET_32BIT"
513{
d302ef3a 514 emit_insn (gen_adddi3_compareV (operands[0], operands[1], operands[2]));
f6c98a9a 515 arm_gen_unlikely_cbranch (NE, CC_Vmode, operands[3]);
516
517 DONE;
518})
519
eaddabc8 520(define_expand "uaddvsi4"
521 [(match_operand:SI 0 "s_register_operand")
522 (match_operand:SI 1 "s_register_operand")
523 (match_operand:SI 2 "arm_add_operand")
f6c98a9a 524 (match_operand 3 "")]
525 "TARGET_32BIT"
526{
eaddabc8 527 emit_insn (gen_addsi3_compare_op1 (operands[0], operands[1], operands[2]));
528 arm_gen_unlikely_cbranch (LTU, CC_Cmode, operands[3]);
529
530 DONE;
531})
532
533(define_expand "uaddvdi4"
534 [(match_operand:DI 0 "s_register_operand")
535 (match_operand:DI 1 "s_register_operand")
58087a96 536 (match_operand:DI 2 "reg_or_int_operand")
eaddabc8 537 (match_operand 3 "")]
538 "TARGET_32BIT"
539{
58087a96 540 rtx lo_result, hi_result;
541 rtx lo_op1, hi_op1, lo_op2, hi_op2;
542 arm_decompose_di_binop (operands[1], operands[2], &lo_op1, &hi_op1,
543 &lo_op2, &hi_op2);
544 lo_result = gen_lowpart (SImode, operands[0]);
545 hi_result = gen_highpart (SImode, operands[0]);
546
547 if (lo_op2 == const0_rtx)
548 {
549 emit_move_insn (lo_result, lo_op1);
550 if (!arm_add_operand (hi_op2, SImode))
551 hi_op2 = force_reg (SImode, hi_op2);
552
553 gen_uaddvsi4 (hi_result, hi_op1, hi_op2, operands[3]);
554 }
555 else
556 {
557 if (!arm_add_operand (lo_op2, SImode))
558 lo_op2 = force_reg (SImode, lo_op2);
559 if (!arm_not_operand (hi_op2, SImode))
560 hi_op2 = force_reg (SImode, hi_op2);
561
562 emit_insn (gen_addsi3_compare_op1 (lo_result, lo_op1, lo_op2));
563
564 if (hi_op2 == const0_rtx)
565 emit_insn (gen_addsi3_cin_cout_0 (hi_result, hi_op1));
566 else if (CONST_INT_P (hi_op2))
567 emit_insn (gen_addsi3_cin_cout_imm (hi_result, hi_op1, hi_op2));
568 else
569 emit_insn (gen_addsi3_cin_cout_reg (hi_result, hi_op1, hi_op2));
570
571 arm_gen_unlikely_cbranch (GEU, CC_ADCmode, operands[3]);
572 }
f6c98a9a 573
574 DONE;
575})
576
58087a96 577(define_expand "addsi3_cin_cout_reg"
578 [(parallel
579 [(set (match_dup 3)
580 (compare:CC_ADC
581 (plus:DI
582 (plus:DI (match_dup 4)
583 (zero_extend:DI (match_operand:SI 1 "s_register_operand")))
584 (zero_extend:DI (match_operand:SI 2 "s_register_operand")))
585 (const_int 4294967296)))
586 (set (match_operand:SI 0 "s_register_operand")
587 (plus:SI (plus:SI (match_dup 5) (match_dup 1))
588 (match_dup 2)))])]
589 "TARGET_32BIT"
590 {
591 operands[3] = gen_rtx_REG (CC_ADCmode, CC_REGNUM);
592 rtx ccin = gen_rtx_REG (CC_Cmode, CC_REGNUM);
593 operands[4] = gen_rtx_LTU (DImode, ccin, const0_rtx);
594 operands[5] = gen_rtx_LTU (SImode, ccin, const0_rtx);
595 }
596)
597
598(define_insn "*addsi3_cin_cout_reg_insn"
599 [(set (reg:CC_ADC CC_REGNUM)
600 (compare:CC_ADC
601 (plus:DI
602 (plus:DI
603 (match_operand:DI 3 "arm_carry_operation" "")
604 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r")))
605 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "l,r")))
606 (const_int 4294967296)))
607 (set (match_operand:SI 0 "s_register_operand" "=l,r")
608 (plus:SI (plus:SI (match_operand:SI 4 "arm_carry_operation" "")
609 (match_dup 1))
610 (match_dup 2)))]
611 "TARGET_32BIT"
612 "@
613 adcs%?\\t%0, %0, %2
614 adcs%?\\t%0, %1, %2"
615 [(set_attr "type" "alus_sreg")
616 (set_attr "arch" "t2,*")
617 (set_attr "length" "2,4")]
618)
619
620(define_expand "addsi3_cin_cout_imm"
621 [(parallel
622 [(set (match_dup 3)
623 (compare:CC_ADC
624 (plus:DI
625 (plus:DI (match_dup 4)
626 (zero_extend:DI (match_operand:SI 1 "s_register_operand")))
627 (match_dup 6))
628 (const_int 4294967296)))
629 (set (match_operand:SI 0 "s_register_operand")
630 (plus:SI (plus:SI (match_dup 5) (match_dup 1))
631 (match_operand:SI 2 "arm_adcimm_operand")))])]
632 "TARGET_32BIT"
633 {
634 operands[3] = gen_rtx_REG (CC_ADCmode, CC_REGNUM);
635 rtx ccin = gen_rtx_REG (CC_Cmode, CC_REGNUM);
636 operands[4] = gen_rtx_LTU (DImode, ccin, const0_rtx);
637 operands[5] = gen_rtx_LTU (SImode, ccin, const0_rtx);
638 operands[6] = GEN_INT (UINTVAL (operands[2]) & 0xffffffff);
639 }
640)
641
642(define_insn "*addsi3_cin_cout_imm_insn"
643 [(set (reg:CC_ADC CC_REGNUM)
644 (compare:CC_ADC
645 (plus:DI
646 (plus:DI
647 (match_operand:DI 3 "arm_carry_operation" "")
648 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r,r")))
649 (match_operand:DI 5 "const_int_operand" "n,n"))
650 (const_int 4294967296)))
651 (set (match_operand:SI 0 "s_register_operand" "=r,r")
652 (plus:SI (plus:SI (match_operand:SI 4 "arm_carry_operation" "")
653 (match_dup 1))
654 (match_operand:SI 2 "arm_adcimm_operand" "I,K")))]
655 "TARGET_32BIT
656 && (UINTVAL (operands[2]) & 0xffffffff) == UINTVAL (operands[5])"
657 "@
658 adcs%?\\t%0, %1, %2
659 sbcs%?\\t%0, %1, #%B2"
660 [(set_attr "type" "alus_imm")]
661)
662
663(define_expand "addsi3_cin_cout_0"
664 [(parallel
665 [(set (match_dup 2)
666 (compare:CC_ADC
667 (plus:DI (match_dup 3)
668 (zero_extend:DI (match_operand:SI 1 "s_register_operand")))
669 (const_int 4294967296)))
670 (set (match_operand:SI 0 "s_register_operand")
671 (plus:SI (match_dup 4) (match_dup 1)))])]
672 "TARGET_32BIT"
673 {
674 operands[2] = gen_rtx_REG (CC_ADCmode, CC_REGNUM);
675 rtx ccin = gen_rtx_REG (CC_Cmode, CC_REGNUM);
676 operands[3] = gen_rtx_LTU (DImode, ccin, const0_rtx);
677 operands[4] = gen_rtx_LTU (SImode, ccin, const0_rtx);
678 }
679)
680
681(define_insn "*addsi3_cin_cout_0_insn"
682 [(set (reg:CC_ADC CC_REGNUM)
683 (compare:CC_ADC
684 (plus:DI
685 (match_operand:DI 2 "arm_carry_operation" "")
686 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))
687 (const_int 4294967296)))
688 (set (match_operand:SI 0 "s_register_operand" "=r")
689 (plus:SI (match_operand:SI 3 "arm_carry_operation" "") (match_dup 1)))]
690 "TARGET_32BIT"
691 "adcs%?\\t%0, %1, #0"
692 [(set_attr "type" "alus_imm")]
693)
694
87b22bf7 695(define_expand "addsi3"
3934ae0e 696 [(set (match_operand:SI 0 "s_register_operand")
697 (plus:SI (match_operand:SI 1 "s_register_operand")
698 (match_operand:SI 2 "reg_or_int_operand")))]
cffb2a26 699 "TARGET_EITHER"
87b22bf7 700 "
0438d37f 701 if (TARGET_32BIT && CONST_INT_P (operands[2]))
87b22bf7 702 {
96f57e36 703 arm_split_constant (PLUS, SImode, NULL_RTX,
704 INTVAL (operands[2]), operands[0], operands[1],
e1ba4a27 705 optimize && can_create_pseudo_p ());
87b22bf7 706 DONE;
707 }
cffb2a26 708 "
709)
87b22bf7 710
5bd751ff 711; If there is a scratch available, this will be faster than synthesizing the
a0f94409 712; addition.
713(define_peephole2
714 [(match_scratch:SI 3 "r")
372575c7 715 (set (match_operand:SI 0 "arm_general_register_operand" "")
716 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
cffb2a26 717 (match_operand:SI 2 "const_int_operand" "")))]
25f905c2 718 "TARGET_32BIT &&
a0f94409 719 !(const_ok_for_arm (INTVAL (operands[2]))
720 || const_ok_for_arm (-INTVAL (operands[2])))
721 && const_ok_for_arm (~INTVAL (operands[2]))"
722 [(set (match_dup 3) (match_dup 2))
723 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
724 ""
725)
87b22bf7 726
2f02c19f 727;; The r/r/k alternative is required when reloading the address
728;; (plus (reg rN) (reg sp)) into (reg rN). In this case reload will
729;; put the duplicated register first, and not try the commutative version.
a0f94409 730(define_insn_and_split "*arm_addsi3"
fa1f9c9e 731 [(set (match_operand:SI 0 "s_register_operand" "=rk,l,l ,l ,r ,k ,r,k ,r ,k ,r ,k,k,r ,k ,r")
732 (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")
733 (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 734 "TARGET_32BIT"
5565501b 735 "@
c24d855d 736 add%?\\t%0, %0, %2
5565501b 737 add%?\\t%0, %1, %2
a0b3420a 738 add%?\\t%0, %1, %2
7c36fe71 739 add%?\\t%0, %1, %2
740 add%?\\t%0, %1, %2
aaa37ad6 741 add%?\\t%0, %1, %2
2f02c19f 742 add%?\\t%0, %2, %1
fa1f9c9e 743 add%?\\t%0, %1, %2
d5cbae34 744 addw%?\\t%0, %1, %2
745 addw%?\\t%0, %1, %2
aaa37ad6 746 sub%?\\t%0, %1, #%n2
87b22bf7 747 sub%?\\t%0, %1, #%n2
d7757711 748 sub%?\\t%0, %1, #%n2
d5cbae34 749 subw%?\\t%0, %1, #%n2
750 subw%?\\t%0, %1, #%n2
87b22bf7 751 #"
a3ffc315 752 "TARGET_32BIT
0438d37f 753 && CONST_INT_P (operands[2])
d5cbae34 754 && !const_ok_for_op (INTVAL (operands[2]), PLUS)
a3ffc315 755 && (reload_completed || !arm_eliminable_register (operands[1]))"
a0f94409 756 [(clobber (const_int 0))]
757 "
96f57e36 758 arm_split_constant (PLUS, SImode, curr_insn,
759 INTVAL (operands[2]), operands[0],
a0f94409 760 operands[1], 0);
761 DONE;
762 "
fa1f9c9e 763 [(set_attr "length" "2,4,4,4,4,4,4,4,4,4,4,4,4,4,4,16")
d5cbae34 764 (set_attr "predicable" "yes")
fa1f9c9e 765 (set_attr "predicable_short_it" "yes,yes,yes,yes,no,no,no,no,no,no,no,no,no,no,no,no")
766 (set_attr "arch" "t2,t2,t2,t2,*,*,*,a,t2,t2,*,*,a,t2,t2,*")
65f68e55 767 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
d82e788e 768 (const_string "alu_imm")
112eda6f 769 (const_string "alu_sreg")))
65f68e55 770 ]
cffb2a26 771)
772
e62551fd 773(define_insn "adddi3_compareV"
f6c98a9a 774 [(set (reg:CC_V CC_REGNUM)
775 (ne:CC_V
776 (plus:TI
e62551fd 777 (sign_extend:TI (match_operand:DI 1 "s_register_operand" "r"))
778 (sign_extend:TI (match_operand:DI 2 "s_register_operand" "r")))
f6c98a9a 779 (sign_extend:TI (plus:DI (match_dup 1) (match_dup 2)))))
e62551fd 780 (set (match_operand:DI 0 "s_register_operand" "=&r")
f6c98a9a 781 (plus:DI (match_dup 1) (match_dup 2)))]
782 "TARGET_32BIT"
e62551fd 783 "adds\\t%Q0, %Q1, %Q2;adcs\\t%R0, %R1, %R2"
f6c98a9a 784 [(set_attr "conds" "set")
785 (set_attr "length" "8")
786 (set_attr "type" "multiple")]
787)
788
d302ef3a 789(define_insn "addsi3_compareV_reg"
f6c98a9a 790 [(set (reg:CC_V CC_REGNUM)
d302ef3a 791 (compare:CC_V
f6c98a9a 792 (plus:DI
d302ef3a 793 (sign_extend:DI (match_operand:SI 1 "register_operand" "%l,0,r"))
794 (sign_extend:DI (match_operand:SI 2 "register_operand" "l,r,r")))
f6c98a9a 795 (sign_extend:DI (plus:SI (match_dup 1) (match_dup 2)))))
d302ef3a 796 (set (match_operand:SI 0 "register_operand" "=l,r,r")
f6c98a9a 797 (plus:SI (match_dup 1) (match_dup 2)))]
798 "TARGET_32BIT"
799 "adds%?\\t%0, %1, %2"
800 [(set_attr "conds" "set")
d302ef3a 801 (set_attr "arch" "t2,t2,*")
802 (set_attr "length" "2,2,4")
f6c98a9a 803 (set_attr "type" "alus_sreg")]
804)
805
8aefed8a 806(define_insn "*addsi3_compareV_reg_nosum"
807 [(set (reg:CC_V CC_REGNUM)
808 (compare:CC_V
809 (plus:DI
810 (sign_extend:DI (match_operand:SI 0 "register_operand" "%l,r"))
811 (sign_extend:DI (match_operand:SI 1 "register_operand" "l,r")))
812 (sign_extend:DI (plus:SI (match_dup 0) (match_dup 1)))))]
813 "TARGET_32BIT"
814 "cmn%?\\t%0, %1"
815 [(set_attr "conds" "set")
816 (set_attr "arch" "t2,*")
817 (set_attr "length" "2,4")
818 (set_attr "type" "alus_sreg")]
819)
820
d302ef3a 821(define_insn "addsi3_compareV_imm"
822 [(set (reg:CC_V CC_REGNUM)
823 (compare:CC_V
824 (plus:DI
825 (sign_extend:DI
826 (match_operand:SI 1 "register_operand" "l,0,l,0,r,r"))
827 (match_operand 2 "arm_addimm_operand" "Pd,Py,Px,Pw,I,L"))
828 (sign_extend:DI (plus:SI (match_dup 1) (match_dup 2)))))
829 (set (match_operand:SI 0 "register_operand" "=l,l,l,l,r,r")
830 (plus:SI (match_dup 1) (match_dup 2)))]
831 "TARGET_32BIT
832 && INTVAL (operands[2]) == ARM_SIGN_EXTEND (INTVAL (operands[2]))"
833 "@
834 adds%?\\t%0, %1, %2
835 adds%?\\t%0, %0, %2
836 subs%?\\t%0, %1, #%n2
837 subs%?\\t%0, %0, #%n2
838 adds%?\\t%0, %1, %2
839 subs%?\\t%0, %1, #%n2"
840 [(set_attr "conds" "set")
841 (set_attr "arch" "t2,t2,t2,t2,*,*")
842 (set_attr "length" "2,2,2,2,4,4")
843 (set_attr "type" "alus_imm")]
844)
845
8aefed8a 846(define_insn "addsi3_compareV_imm_nosum"
847 [(set (reg:CC_V CC_REGNUM)
848 (compare:CC_V
849 (plus:DI
850 (sign_extend:DI
851 (match_operand:SI 0 "register_operand" "l,r,r"))
852 (match_operand 1 "arm_addimm_operand" "Pw,I,L"))
853 (sign_extend:DI (plus:SI (match_dup 0) (match_dup 1)))))]
854 "TARGET_32BIT
855 && INTVAL (operands[1]) == ARM_SIGN_EXTEND (INTVAL (operands[1]))"
856 "@
857 cmp%?\\t%0, #%n1
858 cmn%?\\t%0, %1
859 cmp%?\\t%0, #%n1"
860 [(set_attr "conds" "set")
861 (set_attr "arch" "t2,*,*")
862 (set_attr "length" "2,4,4")
863 (set_attr "type" "alus_imm")]
864)
865
866;; We can handle more constants efficently if we can clobber either a scratch
867;; or the other source operand. We deliberately leave this late as in
868;; high register pressure situations it's not worth forcing any reloads.
869(define_peephole2
870 [(match_scratch:SI 2 "l")
871 (set (reg:CC_V CC_REGNUM)
872 (compare:CC_V
873 (plus:DI
874 (sign_extend:DI
875 (match_operand:SI 0 "low_register_operand"))
876 (match_operand 1 "const_int_operand"))
877 (sign_extend:DI (plus:SI (match_dup 0) (match_dup 1)))))]
878 "TARGET_THUMB2
879 && satisfies_constraint_Pd (operands[1])"
880 [(parallel[
881 (set (reg:CC_V CC_REGNUM)
882 (compare:CC_V
883 (plus:DI (sign_extend:DI (match_dup 0))
884 (sign_extend:DI (match_dup 1)))
885 (sign_extend:DI (plus:SI (match_dup 0) (match_dup 1)))))
886 (set (match_dup 2) (plus:SI (match_dup 0) (match_dup 1)))])]
887)
888
889(define_peephole2
890 [(set (reg:CC_V CC_REGNUM)
891 (compare:CC_V
892 (plus:DI
893 (sign_extend:DI
894 (match_operand:SI 0 "low_register_operand"))
895 (match_operand 1 "const_int_operand"))
896 (sign_extend:DI (plus:SI (match_dup 0) (match_dup 1)))))]
897 "TARGET_THUMB2
898 && dead_or_set_p (peep2_next_insn (0), operands[0])
899 && satisfies_constraint_Py (operands[1])"
900 [(parallel[
901 (set (reg:CC_V CC_REGNUM)
902 (compare:CC_V
903 (plus:DI (sign_extend:DI (match_dup 0))
904 (sign_extend:DI (match_dup 1)))
905 (sign_extend:DI (plus:SI (match_dup 0) (match_dup 1)))))
906 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))])]
907)
908
90c2bcf0 909(define_insn "addsi3_compare0"
bd5b4116 910 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 911 (compare:CC_NOOV
65f68e55 912 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r,r")
913 (match_operand:SI 2 "arm_add_operand" "I,L,r"))
5565501b 914 (const_int 0)))
65f68e55 915 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9c08d1fa 916 (plus:SI (match_dup 1) (match_dup 2)))]
ec792a7b 917 "TARGET_ARM"
5565501b 918 "@
3ef90e77 919 adds%?\\t%0, %1, %2
920 subs%?\\t%0, %1, #%n2
921 adds%?\\t%0, %1, %2"
65f68e55 922 [(set_attr "conds" "set")
112eda6f 923 (set_attr "type" "alus_imm,alus_imm,alus_sreg")]
cffb2a26 924)
9c08d1fa 925
aea4c774 926(define_insn "*addsi3_compare0_scratch"
bd5b4116 927 [(set (reg:CC_NOOV CC_REGNUM)
aea4c774 928 (compare:CC_NOOV
65f68e55 929 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r, r")
930 (match_operand:SI 1 "arm_add_operand" "I,L, r"))
aea4c774 931 (const_int 0)))]
ec792a7b 932 "TARGET_ARM"
cffb2a26 933 "@
934 cmn%?\\t%0, %1
65f68e55 935 cmp%?\\t%0, #%n1
936 cmn%?\\t%0, %1"
596e5e8f 937 [(set_attr "conds" "set")
65f68e55 938 (set_attr "predicable" "yes")
112eda6f 939 (set_attr "type" "alus_imm,alus_imm,alus_sreg")]
0d66636f 940)
cffb2a26 941
aed179ae 942(define_insn "*compare_negsi_si"
943 [(set (reg:CC_Z CC_REGNUM)
944 (compare:CC_Z
7c36fe71 945 (neg:SI (match_operand:SI 0 "s_register_operand" "l,r"))
946 (match_operand:SI 1 "s_register_operand" "l,r")))]
25f905c2 947 "TARGET_32BIT"
aed179ae 948 "cmn%?\\t%1, %0"
596e5e8f 949 [(set_attr "conds" "set")
7c36fe71 950 (set_attr "predicable" "yes")
951 (set_attr "arch" "t2,*")
952 (set_attr "length" "2,4")
1b7da4ac 953 (set_attr "predicable_short_it" "yes,no")
112eda6f 954 (set_attr "type" "alus_sreg")]
0d66636f 955)
aea4c774 956
7f100343 957;; This is the canonicalization of subsi3_compare when the
203c488f 958;; addend is a constant.
190efb17 959(define_insn "cmpsi2_addneg"
203c488f 960 [(set (reg:CC CC_REGNUM)
961 (compare:CC
962 (match_operand:SI 1 "s_register_operand" "r,r")
7f100343 963 (match_operand:SI 2 "arm_addimm_operand" "I,L")))
203c488f 964 (set (match_operand:SI 0 "s_register_operand" "=r,r")
965 (plus:SI (match_dup 1)
7f100343 966 (match_operand:SI 3 "arm_addimm_operand" "L,I")))]
e3dcfc16 967 "TARGET_32BIT
968 && (INTVAL (operands[2])
969 == trunc_int_for_mode (-INTVAL (operands[3]), SImode))"
970{
7f100343 971 /* For 0 and INT_MIN it is essential that we use subs, as adds will result
972 in different condition codes (like cmn rather than like cmp), so that
973 alternative comes first. Both alternatives can match for any 0x??000000
974 where except for 0 and INT_MIN it doesn't matter what we choose, and also
975 for -1 and 1 with TARGET_THUMB2, in that case prefer instruction with #1
976 as it is shorter. */
977 if (which_alternative == 0 && operands[3] != const1_rtx)
e3dcfc16 978 return "subs%?\\t%0, %1, #%n3";
979 else
980 return "adds%?\\t%0, %1, %3";
981}
1b7da4ac 982 [(set_attr "conds" "set")
112eda6f 983 (set_attr "type" "alus_sreg")]
203c488f 984)
985
986;; Convert the sequence
987;; sub rd, rn, #1
988;; cmn rd, #1 (equivalent to cmp rd, #-1)
989;; bne dest
990;; into
991;; subs rd, rn, #1
992;; bcs dest ((unsigned)rn >= 1)
993;; similarly for the beq variant using bcc.
994;; This is a common looping idiom (while (n--))
995(define_peephole2
372575c7 996 [(set (match_operand:SI 0 "arm_general_register_operand" "")
997 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
203c488f 998 (const_int -1)))
999 (set (match_operand 2 "cc_register" "")
1000 (compare (match_dup 0) (const_int -1)))
1001 (set (pc)
1002 (if_then_else (match_operator 3 "equality_operator"
1003 [(match_dup 2) (const_int 0)])
1004 (match_operand 4 "" "")
1005 (match_operand 5 "" "")))]
25f905c2 1006 "TARGET_32BIT && peep2_reg_dead_p (3, operands[2])"
203c488f 1007 [(parallel[
1008 (set (match_dup 2)
1009 (compare:CC
1010 (match_dup 1) (const_int 1)))
1011 (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
1012 (set (pc)
1013 (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
1014 (match_dup 4)
1015 (match_dup 5)))]
1016 "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
1017 operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
1018 ? GEU : LTU),
1019 VOIDmode,
1020 operands[2], const0_rtx);"
1021)
1022
ebcc79bc 1023;; The next four insns work because they compare the result with one of
1024;; the operands, and we know that the use of the condition code is
1025;; either GEU or LTU, so we can use the carry flag from the addition
1026;; instead of doing the compare a second time.
eaddabc8 1027(define_insn "addsi3_compare_op1"
bd5b4116 1028 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 1029 (compare:CC_C
eaddabc8 1030 (plus:SI (match_operand:SI 1 "s_register_operand" "l,0,l,0,rk,rk")
1031 (match_operand:SI 2 "arm_add_operand" "lPd,Py,lPx,Pw,rkI,L"))
ebcc79bc 1032 (match_dup 1)))
eaddabc8 1033 (set (match_operand:SI 0 "s_register_operand" "=l,l,l,l,rk,rk")
ebcc79bc 1034 (plus:SI (match_dup 1) (match_dup 2)))]
25f905c2 1035 "TARGET_32BIT"
ebcc79bc 1036 "@
4fe655e9 1037 adds%?\\t%0, %1, %2
1038 adds%?\\t%0, %0, %2
1039 subs%?\\t%0, %1, #%n2
1040 subs%?\\t%0, %0, #%n2
3ef90e77 1041 adds%?\\t%0, %1, %2
eaddabc8 1042 subs%?\\t%0, %1, #%n2"
65f68e55 1043 [(set_attr "conds" "set")
eaddabc8 1044 (set_attr "arch" "t2,t2,t2,t2,*,*")
1045 (set_attr "length" "2,2,2,2,4,4")
1046 (set (attr "type")
1047 (if_then_else (match_operand 2 "const_int_operand")
1048 (const_string "alu_imm")
1049 (const_string "alu_sreg")))]
0d66636f 1050)
ebcc79bc 1051
1052(define_insn "*addsi3_compare_op2"
bd5b4116 1053 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 1054 (compare:CC_C
eaddabc8 1055 (plus:SI (match_operand:SI 1 "s_register_operand" "l,0,l,0,r,r")
1056 (match_operand:SI 2 "arm_add_operand" "lPd,Py,lPx,Pw,rI,L"))
ebcc79bc 1057 (match_dup 2)))
eaddabc8 1058 (set (match_operand:SI 0 "s_register_operand" "=l,l,l,l,r,r")
9c08d1fa 1059 (plus:SI (match_dup 1) (match_dup 2)))]
25f905c2 1060 "TARGET_32BIT"
5565501b 1061 "@
4fe655e9 1062 adds%?\\t%0, %1, %2
1063 adds%?\\t%0, %0, %2
1064 subs%?\\t%0, %1, #%n2
1065 subs%?\\t%0, %0, #%n2
3ef90e77 1066 adds%?\\t%0, %1, %2
eaddabc8 1067 subs%?\\t%0, %1, #%n2"
65f68e55 1068 [(set_attr "conds" "set")
eaddabc8 1069 (set_attr "arch" "t2,t2,t2,t2,*,*")
1070 (set_attr "length" "2,2,2,2,4,4")
1071 (set (attr "type")
1072 (if_then_else (match_operand 2 "const_int_operand")
1073 (const_string "alu_imm")
1074 (const_string "alu_sreg")))]
0d66636f 1075)
9c08d1fa 1076
ebcc79bc 1077(define_insn "*compare_addsi2_op0"
bd5b4116 1078 [(set (reg:CC_C CC_REGNUM)
7c36fe71 1079 (compare:CC_C
eaddabc8 1080 (plus:SI (match_operand:SI 0 "s_register_operand" "l,l,r,r")
1081 (match_operand:SI 1 "arm_add_operand" "l,Pw,rI,L"))
7c36fe71 1082 (match_dup 0)))]
25f905c2 1083 "TARGET_32BIT"
ebcc79bc 1084 "@
1085 cmn%?\\t%0, %1
65f68e55 1086 cmp%?\\t%0, #%n1
eaddabc8 1087 cmn%?\\t%0, %1
1088 cmp%?\\t%0, #%n1"
596e5e8f 1089 [(set_attr "conds" "set")
65f68e55 1090 (set_attr "predicable" "yes")
eaddabc8 1091 (set_attr "arch" "t2,t2,*,*")
1092 (set_attr "predicable_short_it" "yes,yes,no,no")
1093 (set_attr "length" "2,2,4,4")
1094 (set (attr "type")
1095 (if_then_else (match_operand 1 "const_int_operand")
1096 (const_string "alu_imm")
1097 (const_string "alu_sreg")))]
0d66636f 1098)
ebcc79bc 1099
1100(define_insn "*compare_addsi2_op1"
bd5b4116 1101 [(set (reg:CC_C CC_REGNUM)
7c36fe71 1102 (compare:CC_C
eaddabc8 1103 (plus:SI (match_operand:SI 0 "s_register_operand" "l,l,r,r")
1104 (match_operand:SI 1 "arm_add_operand" "l,Pw,rI,L"))
7c36fe71 1105 (match_dup 1)))]
25f905c2 1106 "TARGET_32BIT"
ebcc79bc 1107 "@
1108 cmn%?\\t%0, %1
65f68e55 1109 cmp%?\\t%0, #%n1
eaddabc8 1110 cmn%?\\t%0, %1
1111 cmp%?\\t%0, #%n1"
596e5e8f 1112 [(set_attr "conds" "set")
65f68e55 1113 (set_attr "predicable" "yes")
eaddabc8 1114 (set_attr "arch" "t2,t2,*,*")
1115 (set_attr "predicable_short_it" "yes,yes,no,no")
1116 (set_attr "length" "2,2,4,4")
1117 (set (attr "type")
1118 (if_then_else (match_operand 1 "const_int_operand")
1119 (const_string "alu_imm")
1120 (const_string "alu_sreg")))]
7c36fe71 1121 )
ebcc79bc 1122
40155e19 1123(define_insn "addsi3_carryin"
7c36fe71 1124 [(set (match_operand:SI 0 "s_register_operand" "=l,r,r")
1125 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%l,r,r")
1126 (match_operand:SI 2 "arm_not_operand" "0,rI,K"))
40155e19 1127 (match_operand:SI 3 "arm_carry_operation" "")))]
25f905c2 1128 "TARGET_32BIT"
10e5ccd5 1129 "@
a0b3420a 1130 adc%?\\t%0, %1, %2
10e5ccd5 1131 adc%?\\t%0, %1, %2
1132 sbc%?\\t%0, %1, #%B2"
a7de272d 1133 [(set_attr "conds" "use")
7c36fe71 1134 (set_attr "predicable" "yes")
1135 (set_attr "arch" "t2,*,*")
1136 (set_attr "length" "4")
1b7da4ac 1137 (set_attr "predicable_short_it" "yes,no,no")
1138 (set_attr "type" "adc_reg,adc_reg,adc_imm")]
cffb2a26 1139)
ebcc79bc 1140
6cc8c27c 1141;; Canonicalization of the above when the immediate is zero.
40155e19 1142(define_insn "add0si3_carryin"
6cc8c27c 1143 [(set (match_operand:SI 0 "s_register_operand" "=r")
40155e19 1144 (plus:SI (match_operand:SI 2 "arm_carry_operation" "")
6cc8c27c 1145 (match_operand:SI 1 "arm_not_operand" "r")))]
1146 "TARGET_32BIT"
1147 "adc%?\\t%0, %1, #0"
1148 [(set_attr "conds" "use")
1149 (set_attr "predicable" "yes")
1150 (set_attr "length" "4")
1151 (set_attr "type" "adc_imm")]
1152)
1153
40155e19 1154(define_insn "*addsi3_carryin_alt2"
7c36fe71 1155 [(set (match_operand:SI 0 "s_register_operand" "=l,r,r")
40155e19 1156 (plus:SI (plus:SI (match_operand:SI 3 "arm_carry_operation" "")
7c36fe71 1157 (match_operand:SI 1 "s_register_operand" "%l,r,r"))
3f095d09 1158 (match_operand:SI 2 "arm_not_operand" "l,rI,K")))]
25f905c2 1159 "TARGET_32BIT"
10e5ccd5 1160 "@
a0b3420a 1161 adc%?\\t%0, %1, %2
10e5ccd5 1162 adc%?\\t%0, %1, %2
1163 sbc%?\\t%0, %1, #%B2"
a7de272d 1164 [(set_attr "conds" "use")
7c36fe71 1165 (set_attr "predicable" "yes")
1166 (set_attr "arch" "t2,*,*")
1167 (set_attr "length" "4")
1b7da4ac 1168 (set_attr "predicable_short_it" "yes,no,no")
1169 (set_attr "type" "adc_reg,adc_reg,adc_imm")]
0d66636f 1170)
ebcc79bc 1171
40155e19 1172(define_insn "*addsi3_carryin_shift"
1173 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
080c0b9a 1174 (plus:SI (plus:SI
1175 (match_operator:SI 2 "shift_operator"
40155e19 1176 [(match_operand:SI 3 "s_register_operand" "r,r")
1177 (match_operand:SI 4 "shift_amount_operand" "M,r")])
1178 (match_operand:SI 5 "arm_carry_operation" ""))
1179 (match_operand:SI 1 "s_register_operand" "r,r")))]
25f905c2 1180 "TARGET_32BIT"
080c0b9a 1181 "adc%?\\t%0, %1, %3%S2"
1182 [(set_attr "conds" "use")
40155e19 1183 (set_attr "arch" "32,a")
1184 (set_attr "shift" "3")
a7de272d 1185 (set_attr "predicable" "yes")
080c0b9a 1186 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
d82e788e 1187 (const_string "alu_shift_imm")
1188 (const_string "alu_shift_reg")))]
cffb2a26 1189)
ebcc79bc 1190
40155e19 1191(define_insn "*addsi3_carryin_clobercc"
922b6913 1192 [(set (match_operand:SI 0 "s_register_operand" "=r")
1193 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%r")
1194 (match_operand:SI 2 "arm_rhs_operand" "rI"))
40155e19 1195 (match_operand:SI 3 "arm_carry_operation" "")))
922b6913 1196 (clobber (reg:CC CC_REGNUM))]
1197 "TARGET_32BIT"
3ef90e77 1198 "adcs%?\\t%0, %1, %2"
1b7da4ac 1199 [(set_attr "conds" "set")
1200 (set_attr "type" "adcs_reg")]
922b6913 1201)
1202
f6c98a9a 1203(define_expand "subv<mode>4"
1204 [(match_operand:SIDI 0 "register_operand")
1205 (match_operand:SIDI 1 "register_operand")
1206 (match_operand:SIDI 2 "register_operand")
1207 (match_operand 3 "")]
1208 "TARGET_32BIT"
1209{
1210 emit_insn (gen_sub<mode>3_compare1 (operands[0], operands[1], operands[2]));
1211 arm_gen_unlikely_cbranch (NE, CC_Vmode, operands[3]);
1212
1213 DONE;
1214})
1215
1216(define_expand "usubv<mode>4"
1217 [(match_operand:SIDI 0 "register_operand")
1218 (match_operand:SIDI 1 "register_operand")
1219 (match_operand:SIDI 2 "register_operand")
1220 (match_operand 3 "")]
1221 "TARGET_32BIT"
1222{
1223 emit_insn (gen_sub<mode>3_compare1 (operands[0], operands[1], operands[2]));
1224 arm_gen_unlikely_cbranch (LTU, CCmode, operands[3]);
1225
1226 DONE;
1227})
1228
e62551fd 1229(define_insn "subdi3_compare1"
f6c98a9a 1230 [(set (reg:CC CC_REGNUM)
1231 (compare:CC
e62551fd 1232 (match_operand:DI 1 "s_register_operand" "r")
1233 (match_operand:DI 2 "s_register_operand" "r")))
1234 (set (match_operand:DI 0 "s_register_operand" "=&r")
f6c98a9a 1235 (minus:DI (match_dup 1) (match_dup 2)))]
1236 "TARGET_32BIT"
e62551fd 1237 "subs\\t%Q0, %Q1, %Q2;sbcs\\t%R0, %R1, %R2"
f6c98a9a 1238 [(set_attr "conds" "set")
1239 (set_attr "length" "8")
1240 (set_attr "type" "multiple")]
1241)
1242
1243(define_insn "subsi3_compare1"
1244 [(set (reg:CC CC_REGNUM)
1245 (compare:CC
1246 (match_operand:SI 1 "register_operand" "r")
1247 (match_operand:SI 2 "register_operand" "r")))
1248 (set (match_operand:SI 0 "register_operand" "=r")
1249 (minus:SI (match_dup 1) (match_dup 2)))]
1250 "TARGET_32BIT"
1251 "subs%?\\t%0, %1, %2"
1252 [(set_attr "conds" "set")
1253 (set_attr "type" "alus_sreg")]
1254)
1255
7724f74b 1256(define_insn "subsi3_carryin"
d5bf2b53 1257 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1258 (minus:SI (minus:SI (match_operand:SI 1 "reg_or_int_operand" "r,I,Pz")
1259 (match_operand:SI 2 "s_register_operand" "r,r,r"))
3b0dcaf2 1260 (match_operand:SI 3 "arm_borrow_operation" "")))]
9154bd82 1261 "TARGET_32BIT"
1262 "@
1263 sbc%?\\t%0, %1, %2
d5bf2b53 1264 rsc%?\\t%0, %2, %1
1265 sbc%?\\t%0, %2, %2, lsl #1"
9154bd82 1266 [(set_attr "conds" "use")
d5bf2b53 1267 (set_attr "arch" "*,a,t2")
7c36fe71 1268 (set_attr "predicable" "yes")
d5bf2b53 1269 (set_attr "type" "adc_reg,adc_imm,alu_shift_imm")]
9154bd82 1270)
1271
060a96ad 1272(define_insn "cmpsi3_carryin_<CC_EXTEND>out"
1273 [(set (reg:<CC_EXTEND> CC_REGNUM)
1274 (compare:<CC_EXTEND>
1275 (SE:DI (match_operand:SI 1 "s_register_operand" "0,r"))
1276 (plus:DI (match_operand:DI 3 "arm_borrow_operation" "")
1277 (SE:DI (match_operand:SI 2 "s_register_operand" "l,r")))))
1278 (clobber (match_scratch:SI 0 "=l,r"))]
1279 "TARGET_32BIT"
1280 "sbcs\\t%0, %1, %2"
1281 [(set_attr "conds" "set")
1282 (set_attr "arch" "t2,*")
1283 (set_attr "length" "2,4")
1284 (set_attr "type" "adc_reg")]
1285)
1286
1287;; Similar to the above, but handling a constant which has a different
1288;; canonicalization.
1289(define_insn "cmpsi3_imm_carryin_<CC_EXTEND>out"
1290 [(set (reg:<CC_EXTEND> CC_REGNUM)
1291 (compare:<CC_EXTEND>
1292 (SE:DI (match_operand:SI 1 "s_register_operand" "r,r"))
1293 (plus:DI (match_operand:DI 3 "arm_borrow_operation" "")
1294 (match_operand:DI 2 "arm_adcimm_operand" "I,K"))))
1295 (clobber (match_scratch:SI 0 "=l,r"))]
1296 "TARGET_32BIT"
1297 "@
1298 sbcs\\t%0, %1, %2
1299 adcs\\t%0, %1, #%B2"
1300 [(set_attr "conds" "set")
1301 (set_attr "type" "adc_imm")]
1302)
1303
1304;; Further canonicalization when the constant is zero.
1305(define_insn "cmpsi3_0_carryin_<CC_EXTEND>out"
1306 [(set (reg:<CC_EXTEND> CC_REGNUM)
1307 (compare:<CC_EXTEND>
1308 (SE:DI (match_operand:SI 1 "s_register_operand" "r,r"))
1309 (match_operand:DI 2 "arm_borrow_operation" "")))
1310 (clobber (match_scratch:SI 0 "=l,r"))]
1311 "TARGET_32BIT"
1312 "sbcs\\t%0, %1, #0"
1313 [(set_attr "conds" "set")
1314 (set_attr "type" "adc_imm")]
1315)
1316
9154bd82 1317(define_insn "*subsi3_carryin_const"
1318 [(set (match_operand:SI 0 "s_register_operand" "=r")
3b0dcaf2 1319 (minus:SI (plus:SI
1320 (match_operand:SI 1 "s_register_operand" "r")
1321 (match_operand:SI 2 "arm_neg_immediate_operand" "L"))
1322 (match_operand:SI 3 "arm_borrow_operation" "")))]
9154bd82 1323 "TARGET_32BIT"
16a3cf9c 1324 "sbc\\t%0, %1, #%n2"
1325 [(set_attr "conds" "use")
1326 (set_attr "type" "adc_imm")]
1327)
1328
1329(define_insn "*subsi3_carryin_const0"
1330 [(set (match_operand:SI 0 "s_register_operand" "=r")
3b0dcaf2 1331 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
1332 (match_operand:SI 2 "arm_borrow_operation" "")))]
16a3cf9c 1333 "TARGET_32BIT"
1334 "sbc\\t%0, %1, #0"
1b7da4ac 1335 [(set_attr "conds" "use")
1336 (set_attr "type" "adc_imm")]
9154bd82 1337)
1338
9154bd82 1339(define_insn "*subsi3_carryin_shift"
1340 [(set (match_operand:SI 0 "s_register_operand" "=r")
1341 (minus:SI (minus:SI
3b0dcaf2 1342 (match_operand:SI 1 "s_register_operand" "r")
1343 (match_operator:SI 2 "shift_operator"
1344 [(match_operand:SI 3 "s_register_operand" "r")
1345 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
1346 (match_operand:SI 5 "arm_borrow_operation" "")))]
9154bd82 1347 "TARGET_32BIT"
1348 "sbc%?\\t%0, %1, %3%S2"
1349 [(set_attr "conds" "use")
1350 (set_attr "predicable" "yes")
1351 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
3b0dcaf2 1352 (const_string "alu_shift_imm")
1353 (const_string "alu_shift_reg")))]
9154bd82 1354)
1355
263f9e4d 1356(define_insn "*subsi3_carryin_shift_alt"
1357 [(set (match_operand:SI 0 "s_register_operand" "=r")
1358 (minus:SI (minus:SI
1359 (match_operand:SI 1 "s_register_operand" "r")
1360 (match_operand:SI 5 "arm_borrow_operation" ""))
1361 (match_operator:SI 2 "shift_operator"
1362 [(match_operand:SI 3 "s_register_operand" "r")
1363 (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
1364 "TARGET_32BIT"
1365 "sbc%?\\t%0, %1, %3%S2"
1366 [(set_attr "conds" "use")
1367 (set_attr "predicable" "yes")
1368 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
1369 (const_string "alu_shift_imm")
1370 (const_string "alu_shift_reg")))]
1371)
1372
9154bd82 1373(define_insn "*rsbsi3_carryin_shift"
1374 [(set (match_operand:SI 0 "s_register_operand" "=r")
1375 (minus:SI (minus:SI
3b0dcaf2 1376 (match_operator:SI 2 "shift_operator"
1377 [(match_operand:SI 3 "s_register_operand" "r")
1378 (match_operand:SI 4 "reg_or_int_operand" "rM")])
9154bd82 1379 (match_operand:SI 1 "s_register_operand" "r"))
3b0dcaf2 1380 (match_operand:SI 5 "arm_borrow_operation" "")))]
9154bd82 1381 "TARGET_ARM"
1382 "rsc%?\\t%0, %1, %3%S2"
1383 [(set_attr "conds" "use")
1384 (set_attr "predicable" "yes")
1385 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
d82e788e 1386 (const_string "alu_shift_imm")
1387 (const_string "alu_shift_reg")))]
9154bd82 1388)
1389
263f9e4d 1390(define_insn "*rsbsi3_carryin_shift_alt"
1391 [(set (match_operand:SI 0 "s_register_operand" "=r")
1392 (minus:SI (minus:SI
1393 (match_operator:SI 2 "shift_operator"
1394 [(match_operand:SI 3 "s_register_operand" "r")
1395 (match_operand:SI 4 "reg_or_int_operand" "rM")])
1396 (match_operand:SI 5 "arm_borrow_operation" ""))
1397 (match_operand:SI 1 "s_register_operand" "r")))]
1398 "TARGET_ARM"
1399 "rsc%?\\t%0, %1, %3%S2"
1400 [(set_attr "conds" "use")
1401 (set_attr "predicable" "yes")
1402 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
1403 (const_string "alu_shift_imm")
1404 (const_string "alu_shift_reg")))]
1405)
1406
d795fb69 1407; transform ((x << y) - 1) to ~(~(x-1) << y) Where X is a constant.
1408(define_split
1409 [(set (match_operand:SI 0 "s_register_operand" "")
1410 (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
1411 (match_operand:SI 2 "s_register_operand" ""))
1412 (const_int -1)))
1413 (clobber (match_operand:SI 3 "s_register_operand" ""))]
25f905c2 1414 "TARGET_32BIT"
d795fb69 1415 [(set (match_dup 3) (match_dup 1))
1416 (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
1417 "
1418 operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
1419")
1420
604f3a0a 1421(define_expand "addsf3"
3934ae0e 1422 [(set (match_operand:SF 0 "s_register_operand")
1423 (plus:SF (match_operand:SF 1 "s_register_operand")
1424 (match_operand:SF 2 "s_register_operand")))]
25f905c2 1425 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1426 "
604f3a0a 1427")
1428
604f3a0a 1429(define_expand "adddf3"
3934ae0e 1430 [(set (match_operand:DF 0 "s_register_operand")
1431 (plus:DF (match_operand:DF 1 "s_register_operand")
1432 (match_operand:DF 2 "s_register_operand")))]
a50d7267 1433 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 1434 "
604f3a0a 1435")
1436
cffb2a26 1437(define_expand "subdi3"
1438 [(parallel
3934ae0e 1439 [(set (match_operand:DI 0 "s_register_operand")
7724f74b 1440 (minus:DI (match_operand:DI 1 "reg_or_int_operand")
e62551fd 1441 (match_operand:DI 2 "s_register_operand")))
bd5b4116 1442 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 1443 "TARGET_EITHER"
1444 "
7724f74b 1445 if (TARGET_THUMB1)
1446 {
1447 if (!REG_P (operands[1]))
1448 operands[1] = force_reg (DImode, operands[1]);
1449 }
1450 else
1451 {
1452 rtx lo_result, hi_result, lo_dest, hi_dest;
1453 rtx lo_op1, hi_op1, lo_op2, hi_op2;
1454 rtx condition;
1455
1456 /* Since operands[1] may be an integer, pass it second, so that
1457 any necessary simplifications will be done on the decomposed
1458 constant. */
1459 arm_decompose_di_binop (operands[2], operands[1], &lo_op2, &hi_op2,
1460 &lo_op1, &hi_op1);
1461 lo_result = lo_dest = gen_lowpart (SImode, operands[0]);
1462 hi_result = hi_dest = gen_highpart (SImode, operands[0]);
1463
1464 if (!arm_rhs_operand (lo_op1, SImode))
1465 lo_op1 = force_reg (SImode, lo_op1);
1466
1467 if ((TARGET_THUMB2 && ! s_register_operand (hi_op1, SImode))
1468 || !arm_rhs_operand (hi_op1, SImode))
1469 hi_op1 = force_reg (SImode, hi_op1);
1470
1471 rtx cc_reg;
1472 if (lo_op1 == const0_rtx)
1473 {
1474 cc_reg = gen_rtx_REG (CC_RSBmode, CC_REGNUM);
1475 emit_insn (gen_negsi2_0compare (lo_dest, lo_op2));
1476 }
1477 else if (CONST_INT_P (lo_op1))
1478 {
1479 cc_reg = gen_rtx_REG (CC_RSBmode, CC_REGNUM);
1480 emit_insn (gen_rsb_imm_compare (lo_dest, lo_op1, lo_op2,
1481 GEN_INT (~UINTVAL (lo_op1))));
1482 }
1483 else
1484 {
1485 cc_reg = gen_rtx_REG (CCmode, CC_REGNUM);
1486 emit_insn (gen_subsi3_compare (lo_dest, lo_op1, lo_op2));
1487 }
1488
1489 condition = gen_rtx_LTU (SImode, cc_reg, const0_rtx);
1490
1491 if (hi_op1 == const0_rtx)
1492 emit_insn (gen_negsi2_carryin (hi_dest, hi_op2, condition));
1493 else
1494 emit_insn (gen_subsi3_carryin (hi_dest, hi_op1, hi_op2, condition));
1495
1496 if (lo_result != lo_dest)
1497 emit_move_insn (lo_result, lo_dest);
1498
1499 if (hi_result != hi_dest)
1500 emit_move_insn (hi_result, hi_dest);
1501
1502 DONE;
1503 }
1504 "
1505)
cffb2a26 1506
87b22bf7 1507(define_expand "subsi3"
3934ae0e 1508 [(set (match_operand:SI 0 "s_register_operand")
1509 (minus:SI (match_operand:SI 1 "reg_or_int_operand")
1510 (match_operand:SI 2 "s_register_operand")))]
cffb2a26 1511 "TARGET_EITHER"
87b22bf7 1512 "
0438d37f 1513 if (CONST_INT_P (operands[1]))
87b22bf7 1514 {
25f905c2 1515 if (TARGET_32BIT)
cffb2a26 1516 {
17202aa5 1517 if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[1]), MINUS))
1518 operands[1] = force_reg (SImode, operands[1]);
1519 else
1520 {
1521 arm_split_constant (MINUS, SImode, NULL_RTX,
1522 INTVAL (operands[1]), operands[0],
1523 operands[2],
1524 optimize && can_create_pseudo_p ());
1525 DONE;
1526 }
cffb2a26 1527 }
25f905c2 1528 else /* TARGET_THUMB1 */
cffb2a26 1529 operands[1] = force_reg (SImode, operands[1]);
87b22bf7 1530 }
cffb2a26 1531 "
1532)
87b22bf7 1533
25f905c2 1534; ??? Check Thumb-2 split length
a0f94409 1535(define_insn_and_split "*arm_subsi3_insn"
3a44c5a9 1536 [(set (match_operand:SI 0 "s_register_operand" "=l,l ,l ,l ,r,r,r,rk,r")
1537 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "l ,0 ,l ,Pz,I,r,r,k ,?n")
1538 (match_operand:SI 2 "reg_or_int_operand" "l ,Py,Pd,l ,r,I,r,r ,r")))]
25f905c2 1539 "TARGET_32BIT"
e2348bcb 1540 "@
7c36fe71 1541 sub%?\\t%0, %1, %2
1542 sub%?\\t%0, %2
1543 sub%?\\t%0, %1, %2
1544 rsb%?\\t%0, %2, %1
87b22bf7 1545 rsb%?\\t%0, %2, %1
aaa37ad6 1546 sub%?\\t%0, %1, %2
080c0b9a 1547 sub%?\\t%0, %1, %2
65f68e55 1548 sub%?\\t%0, %1, %2
87b22bf7 1549 #"
0438d37f 1550 "&& (CONST_INT_P (operands[1])
91a5e339 1551 && !const_ok_for_arm (INTVAL (operands[1])))"
87b22bf7 1552 [(clobber (const_int 0))]
1553 "
96f57e36 1554 arm_split_constant (MINUS, SImode, curr_insn,
1555 INTVAL (operands[1]), operands[0], operands[2], 0);
87b22bf7 1556 DONE;
cffb2a26 1557 "
7c36fe71 1558 [(set_attr "length" "4,4,4,4,4,4,4,4,16")
1559 (set_attr "arch" "t2,t2,t2,t2,*,*,*,*,*")
65f68e55 1560 (set_attr "predicable" "yes")
7c36fe71 1561 (set_attr "predicable_short_it" "yes,yes,yes,yes,no,no,no,no,no")
112eda6f 1562 (set_attr "type" "alu_sreg,alu_sreg,alu_sreg,alu_sreg,alu_imm,alu_imm,alu_sreg,alu_sreg,multiple")]
a0f94409 1563)
1564
1565(define_peephole2
1566 [(match_scratch:SI 3 "r")
372575c7 1567 (set (match_operand:SI 0 "arm_general_register_operand" "")
a0f94409 1568 (minus:SI (match_operand:SI 1 "const_int_operand" "")
372575c7 1569 (match_operand:SI 2 "arm_general_register_operand" "")))]
25f905c2 1570 "TARGET_32BIT
a0f94409 1571 && !const_ok_for_arm (INTVAL (operands[1]))
1572 && const_ok_for_arm (~INTVAL (operands[1]))"
1573 [(set (match_dup 3) (match_dup 1))
1574 (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1575 ""
cffb2a26 1576)
b11cae9e 1577
62e39b06 1578(define_insn "subsi3_compare0"
bd5b4116 1579 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1580 (compare:CC_NOOV
65f68e55 1581 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,r,I")
1582 (match_operand:SI 2 "arm_rhs_operand" "I,r,r"))
215b30b3 1583 (const_int 0)))
65f68e55 1584 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9c08d1fa 1585 (minus:SI (match_dup 1) (match_dup 2)))]
25f905c2 1586 "TARGET_32BIT"
e2348bcb 1587 "@
3ef90e77 1588 subs%?\\t%0, %1, %2
1589 subs%?\\t%0, %1, %2
1590 rsbs%?\\t%0, %2, %1"
65f68e55 1591 [(set_attr "conds" "set")
112eda6f 1592 (set_attr "type" "alus_imm,alus_sreg,alus_sreg")]
cffb2a26 1593)
9c08d1fa 1594
190efb17 1595(define_insn "subsi3_compare"
080c0b9a 1596 [(set (reg:CC CC_REGNUM)
65f68e55 1597 (compare:CC (match_operand:SI 1 "arm_rhs_operand" "r,r,I")
1598 (match_operand:SI 2 "arm_rhs_operand" "I,r,r")))
1599 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2df9477b 1600 (minus:SI (match_dup 1) (match_dup 2)))]
1601 "TARGET_32BIT"
1602 "@
3ef90e77 1603 subs%?\\t%0, %1, %2
1604 subs%?\\t%0, %1, %2
1605 rsbs%?\\t%0, %2, %1"
65f68e55 1606 [(set_attr "conds" "set")
7724f74b 1607 (set_attr "type" "alus_imm,alus_sreg,alus_imm")]
1608)
1609
1610;; To keep the comparison in canonical form we express it as (~reg cmp ~0)
1611;; rather than (0 cmp reg). This gives the same results for unsigned
1612;; and equality compares which is what we mostly need here.
1613(define_insn "rsb_imm_compare"
1614 [(set (reg:CC_RSB CC_REGNUM)
1615 (compare:CC_RSB (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1616 (match_operand 3 "const_int_operand" "")))
1617 (set (match_operand:SI 0 "s_register_operand" "=r")
1618 (minus:SI (match_operand 1 "arm_immediate_operand" "I")
1619 (match_dup 2)))]
1620 "TARGET_32BIT && ~UINTVAL (operands[1]) == UINTVAL (operands[3])"
1621 "rsbs\\t%0, %2, %1"
1622 [(set_attr "conds" "set")
1623 (set_attr "type" "alus_imm")]
2df9477b 1624)
1625
efaa33f9 1626;; Similarly, but the result is unused.
1627(define_insn "rsb_imm_compare_scratch"
1628 [(set (reg:CC_RSB CC_REGNUM)
1629 (compare:CC_RSB (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1630 (match_operand 1 "arm_not_immediate_operand" "K")))
1631 (clobber (match_scratch:SI 0 "=r"))]
1632 "TARGET_32BIT"
1633 "rsbs\\t%0, %2, #%B1"
1634 [(set_attr "conds" "set")
1635 (set_attr "type" "alus_imm")]
1636)
1637
1638;; Compare the sum of a value plus a carry against a constant. Uses
1639;; RSC, so the result is swapped. Only available on Arm
1640(define_insn "rscsi3_<CC_EXTEND>out_scratch"
1641 [(set (reg:CC_SWP CC_REGNUM)
1642 (compare:CC_SWP
1643 (plus:DI (SE:DI (match_operand:SI 2 "s_register_operand" "r"))
1644 (match_operand:DI 3 "arm_borrow_operation" ""))
1645 (match_operand 1 "arm_immediate_operand" "I")))
1646 (clobber (match_scratch:SI 0 "=r"))]
1647 "TARGET_ARM"
1648 "rscs\\t%0, %2, %1"
1649 [(set_attr "conds" "set")
1650 (set_attr "type" "alus_imm")]
1651)
1652
604f3a0a 1653(define_expand "subsf3"
3934ae0e 1654 [(set (match_operand:SF 0 "s_register_operand")
1655 (minus:SF (match_operand:SF 1 "s_register_operand")
1656 (match_operand:SF 2 "s_register_operand")))]
25f905c2 1657 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1658 "
604f3a0a 1659")
1660
604f3a0a 1661(define_expand "subdf3"
3934ae0e 1662 [(set (match_operand:DF 0 "s_register_operand")
1663 (minus:DF (match_operand:DF 1 "s_register_operand")
1664 (match_operand:DF 2 "s_register_operand")))]
a50d7267 1665 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 1666 "
604f3a0a 1667")
1668
b11cae9e 1669\f
1670;; Multiplication insns
1671
4422d91f 1672(define_expand "mulhi3"
3934ae0e 1673 [(set (match_operand:HI 0 "s_register_operand")
1674 (mult:HI (match_operand:HI 1 "s_register_operand")
1675 (match_operand:HI 2 "s_register_operand")))]
4422d91f 1676 "TARGET_DSP_MULTIPLY"
1677 "
1678 {
1679 rtx result = gen_reg_rtx (SImode);
1680 emit_insn (gen_mulhisi3 (result, operands[1], operands[2]));
1681 emit_move_insn (operands[0], gen_lowpart (HImode, result));
1682 DONE;
1683 }"
1684)
1685
cffb2a26 1686(define_expand "mulsi3"
3934ae0e 1687 [(set (match_operand:SI 0 "s_register_operand")
1688 (mult:SI (match_operand:SI 2 "s_register_operand")
1689 (match_operand:SI 1 "s_register_operand")))]
cffb2a26 1690 "TARGET_EITHER"
1691 ""
1692)
1693
40ac65c8 1694;; Use `&' and then `0' to prevent operands 0 and 2 being the same
1695(define_insn "*mul"
1696 [(set (match_operand:SI 0 "s_register_operand" "=l,r,&r,&r")
1697 (mult:SI (match_operand:SI 2 "s_register_operand" "l,r,r,r")
1698 (match_operand:SI 1 "s_register_operand" "%0,r,0,r")))]
1699 "TARGET_32BIT"
f7fbdd4a 1700 "mul%?\\t%0, %2, %1"
9da0ec36 1701 [(set_attr "type" "mul")
40ac65c8 1702 (set_attr "predicable" "yes")
1703 (set_attr "arch" "t2,v6,nov6,nov6")
1704 (set_attr "length" "4")
1705 (set_attr "predicable_short_it" "yes,no,*,*")]
cffb2a26 1706)
1707
40ac65c8 1708;; MLA and MLS instruction. Use operand 1 for the accumulator to prefer
1709;; reusing the same register.
1710
1711(define_insn "*mla"
1712 [(set (match_operand:SI 0 "s_register_operand" "=r,&r,&r,&r")
1713 (plus:SI
1714 (mult:SI (match_operand:SI 3 "s_register_operand" "r,r,r,r")
1715 (match_operand:SI 2 "s_register_operand" "%r,r,0,r"))
1716 (match_operand:SI 1 "s_register_operand" "r,0,r,r")))]
1717 "TARGET_32BIT"
1718 "mla%?\\t%0, %3, %2, %1"
1719 [(set_attr "type" "mla")
d952d547 1720 (set_attr "predicable" "yes")
40ac65c8 1721 (set_attr "arch" "v6,nov6,nov6,nov6")]
1722)
1723
1724(define_insn "*mls"
1725 [(set (match_operand:SI 0 "s_register_operand" "=r")
1726 (minus:SI
1727 (match_operand:SI 1 "s_register_operand" "r")
1728 (mult:SI (match_operand:SI 3 "s_register_operand" "r")
1729 (match_operand:SI 2 "s_register_operand" "r"))))]
1730 "TARGET_32BIT && arm_arch_thumb2"
1731 "mls%?\\t%0, %3, %2, %1"
1732 [(set_attr "type" "mla")
1733 (set_attr "predicable" "yes")]
58d7d654 1734)
1735
f7fbdd4a 1736(define_insn "*mulsi3_compare0"
bd5b4116 1737 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1738 (compare:CC_NOOV (mult:SI
1739 (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1740 (match_operand:SI 1 "s_register_operand" "%0,r"))
9c08d1fa 1741 (const_int 0)))
1742 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1743 (mult:SI (match_dup 2) (match_dup 1)))]
58d7d654 1744 "TARGET_ARM && !arm_arch6"
3ef90e77 1745 "muls%?\\t%0, %2, %1"
58d7d654 1746 [(set_attr "conds" "set")
9da0ec36 1747 (set_attr "type" "muls")]
58d7d654 1748)
1749
1750(define_insn "*mulsi3_compare0_v6"
1751 [(set (reg:CC_NOOV CC_REGNUM)
1752 (compare:CC_NOOV (mult:SI
1753 (match_operand:SI 2 "s_register_operand" "r")
1754 (match_operand:SI 1 "s_register_operand" "r"))
1755 (const_int 0)))
1756 (set (match_operand:SI 0 "s_register_operand" "=r")
1757 (mult:SI (match_dup 2) (match_dup 1)))]
1758 "TARGET_ARM && arm_arch6 && optimize_size"
3ef90e77 1759 "muls%?\\t%0, %2, %1"
cffb2a26 1760 [(set_attr "conds" "set")
9da0ec36 1761 (set_attr "type" "muls")]
cffb2a26 1762)
9c08d1fa 1763
f7fbdd4a 1764(define_insn "*mulsi_compare0_scratch"
bd5b4116 1765 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1766 (compare:CC_NOOV (mult:SI
1767 (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1768 (match_operand:SI 1 "s_register_operand" "%0,r"))
9c08d1fa 1769 (const_int 0)))
1770 (clobber (match_scratch:SI 0 "=&r,&r"))]
58d7d654 1771 "TARGET_ARM && !arm_arch6"
3ef90e77 1772 "muls%?\\t%0, %2, %1"
58d7d654 1773 [(set_attr "conds" "set")
9da0ec36 1774 (set_attr "type" "muls")]
58d7d654 1775)
1776
1777(define_insn "*mulsi_compare0_scratch_v6"
1778 [(set (reg:CC_NOOV CC_REGNUM)
1779 (compare:CC_NOOV (mult:SI
1780 (match_operand:SI 2 "s_register_operand" "r")
1781 (match_operand:SI 1 "s_register_operand" "r"))
1782 (const_int 0)))
1783 (clobber (match_scratch:SI 0 "=r"))]
1784 "TARGET_ARM && arm_arch6 && optimize_size"
3ef90e77 1785 "muls%?\\t%0, %2, %1"
cffb2a26 1786 [(set_attr "conds" "set")
9da0ec36 1787 (set_attr "type" "muls")]
cffb2a26 1788)
9c08d1fa 1789
f7fbdd4a 1790(define_insn "*mulsi3addsi_compare0"
bd5b4116 1791 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1792 (compare:CC_NOOV
1793 (plus:SI (mult:SI
1794 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1795 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1796 (match_operand:SI 3 "s_register_operand" "r,r,0,0"))
215b30b3 1797 (const_int 0)))
9c08d1fa 1798 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1799 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1800 (match_dup 3)))]
58d7d654 1801 "TARGET_ARM && arm_arch6"
3ef90e77 1802 "mlas%?\\t%0, %2, %1, %3"
58d7d654 1803 [(set_attr "conds" "set")
9da0ec36 1804 (set_attr "type" "mlas")]
58d7d654 1805)
1806
1807(define_insn "*mulsi3addsi_compare0_v6"
1808 [(set (reg:CC_NOOV CC_REGNUM)
1809 (compare:CC_NOOV
1810 (plus:SI (mult:SI
1811 (match_operand:SI 2 "s_register_operand" "r")
1812 (match_operand:SI 1 "s_register_operand" "r"))
1813 (match_operand:SI 3 "s_register_operand" "r"))
1814 (const_int 0)))
1815 (set (match_operand:SI 0 "s_register_operand" "=r")
1816 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1817 (match_dup 3)))]
1818 "TARGET_ARM && arm_arch6 && optimize_size"
3ef90e77 1819 "mlas%?\\t%0, %2, %1, %3"
0d66636f 1820 [(set_attr "conds" "set")
9da0ec36 1821 (set_attr "type" "mlas")]
0d66636f 1822)
9c08d1fa 1823
f7fbdd4a 1824(define_insn "*mulsi3addsi_compare0_scratch"
bd5b4116 1825 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1826 (compare:CC_NOOV
1827 (plus:SI (mult:SI
1828 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1829 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
215b30b3 1830 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1831 (const_int 0)))
9c08d1fa 1832 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
58d7d654 1833 "TARGET_ARM && !arm_arch6"
3ef90e77 1834 "mlas%?\\t%0, %2, %1, %3"
58d7d654 1835 [(set_attr "conds" "set")
9da0ec36 1836 (set_attr "type" "mlas")]
58d7d654 1837)
1838
1839(define_insn "*mulsi3addsi_compare0_scratch_v6"
1840 [(set (reg:CC_NOOV CC_REGNUM)
1841 (compare:CC_NOOV
1842 (plus:SI (mult:SI
1843 (match_operand:SI 2 "s_register_operand" "r")
1844 (match_operand:SI 1 "s_register_operand" "r"))
1845 (match_operand:SI 3 "s_register_operand" "r"))
1846 (const_int 0)))
1847 (clobber (match_scratch:SI 0 "=r"))]
1848 "TARGET_ARM && arm_arch6 && optimize_size"
3ef90e77 1849 "mlas%?\\t%0, %2, %1, %3"
cffb2a26 1850 [(set_attr "conds" "set")
9da0ec36 1851 (set_attr "type" "mlas")]
cffb2a26 1852)
f7fbdd4a 1853
957788b0 1854;; 32x32->64 widening multiply.
fa761b10 1855;; The only difference between the v3-5 and v6+ versions is the requirement
1856;; that the output does not overlap with either input.
957788b0 1857
fa761b10 1858(define_expand "<Us>mulsidi3"
3934ae0e 1859 [(set (match_operand:DI 0 "s_register_operand")
957788b0 1860 (mult:DI
fa761b10 1861 (SE:DI (match_operand:SI 1 "s_register_operand"))
1862 (SE:DI (match_operand:SI 2 "s_register_operand"))))]
1930b04c 1863 "TARGET_32BIT"
fa761b10 1864 {
1865 emit_insn (gen_<US>mull (gen_lowpart (SImode, operands[0]),
1866 gen_highpart (SImode, operands[0]),
1867 operands[1], operands[2]));
1868 DONE;
1869 }
0d66636f 1870)
f7fbdd4a 1871
fa761b10 1872(define_insn "<US>mull"
1873 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
1874 (mult:SI
1875 (match_operand:SI 2 "s_register_operand" "%r,r")
1876 (match_operand:SI 3 "s_register_operand" "r,r")))
1877 (set (match_operand:SI 1 "s_register_operand" "=r,&r")
1878 (truncate:SI
1879 (lshiftrt:DI
1880 (mult:DI (SE:DI (match_dup 2)) (SE:DI (match_dup 3)))
1881 (const_int 32))))]
1930b04c 1882 "TARGET_32BIT"
fa761b10 1883 "<US>mull%?\\t%0, %1, %2, %3"
9da0ec36 1884 [(set_attr "type" "umull")
fa761b10 1885 (set_attr "predicable" "yes")
1886 (set_attr "arch" "v6,nov6")]
0d66636f 1887)
b11cae9e 1888
fa761b10 1889(define_expand "<Us>maddsidi4"
3934ae0e 1890 [(set (match_operand:DI 0 "s_register_operand")
5cdca009 1891 (plus:DI
1892 (mult:DI
fa761b10 1893 (SE:DI (match_operand:SI 1 "s_register_operand"))
1894 (SE:DI (match_operand:SI 2 "s_register_operand")))
3934ae0e 1895 (match_operand:DI 3 "s_register_operand")))]
1930b04c 1896 "TARGET_32BIT"
fa761b10 1897 {
1898 emit_insn (gen_<US>mlal (gen_lowpart (SImode, operands[0]),
1899 gen_lowpart (SImode, operands[3]),
1900 gen_highpart (SImode, operands[0]),
1901 gen_highpart (SImode, operands[3]),
1902 operands[1], operands[2]));
1903 DONE;
1904 }
58d7d654 1905)
1906
fa761b10 1907(define_insn "<US>mlal"
1908 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
1909 (plus:SI
1910 (mult:SI
49833aa2 1911 (match_operand:SI 4 "s_register_operand" "%r,r")
1912 (match_operand:SI 5 "s_register_operand" "r,r"))
fa761b10 1913 (match_operand:SI 1 "s_register_operand" "0,0")))
1914 (set (match_operand:SI 2 "s_register_operand" "=r,&r")
1915 (plus:SI
1916 (truncate:SI
1917 (lshiftrt:DI
1918 (plus:DI
1919 (mult:DI (SE:DI (match_dup 4)) (SE:DI (match_dup 5)))
1920 (zero_extend:DI (match_dup 1)))
1921 (const_int 32)))
1922 (match_operand:SI 3 "s_register_operand" "2,2")))]
1923 "TARGET_32BIT"
1924 "<US>mlal%?\\t%0, %2, %4, %5"
9da0ec36 1925 [(set_attr "type" "umlal")
fa761b10 1926 (set_attr "predicable" "yes")
1927 (set_attr "arch" "v6,nov6")]
0d66636f 1928)
82b85d08 1929
662cc42a 1930(define_expand "<US>mulsi3_highpart"
957788b0 1931 [(parallel
3934ae0e 1932 [(set (match_operand:SI 0 "s_register_operand")
957788b0 1933 (truncate:SI
1934 (lshiftrt:DI
1935 (mult:DI
662cc42a 1936 (SE:DI (match_operand:SI 1 "s_register_operand"))
1937 (SE:DI (match_operand:SI 2 "s_register_operand")))
957788b0 1938 (const_int 32))))
1939 (clobber (match_scratch:SI 3 ""))])]
1930b04c 1940 "TARGET_32BIT"
957788b0 1941 ""
1942)
1943
662cc42a 1944(define_insn "*<US>mull_high"
1945 [(set (match_operand:SI 0 "s_register_operand" "=r,&r,&r")
f082f1c4 1946 (truncate:SI
1947 (lshiftrt:DI
215b30b3 1948 (mult:DI
662cc42a 1949 (SE:DI (match_operand:SI 1 "s_register_operand" "%r,0,r"))
1950 (SE:DI (match_operand:SI 2 "s_register_operand" "r,r,r")))
f082f1c4 1951 (const_int 32))))
662cc42a 1952 (clobber (match_scratch:SI 3 "=r,&r,&r"))]
1930b04c 1953 "TARGET_32BIT"
662cc42a 1954 "<US>mull%?\\t%3, %0, %2, %1"
9da0ec36 1955 [(set_attr "type" "umull")
662cc42a 1956 (set_attr "predicable" "yes")
1957 (set_attr "arch" "v6,nov6,nov6")]
cffb2a26 1958)
f082f1c4 1959
331beb1a 1960(define_insn "mulhisi3"
1961 [(set (match_operand:SI 0 "s_register_operand" "=r")
1962 (mult:SI (sign_extend:SI
1963 (match_operand:HI 1 "s_register_operand" "%r"))
1964 (sign_extend:SI
1965 (match_operand:HI 2 "s_register_operand" "r"))))]
25f905c2 1966 "TARGET_DSP_MULTIPLY"
61a2d04c 1967 "smulbb%?\\t%0, %1, %2"
9da0ec36 1968 [(set_attr "type" "smulxy")
fec538d9 1969 (set_attr "predicable" "yes")]
1970)
1971
1972(define_insn "*mulhisi3tb"
1973 [(set (match_operand:SI 0 "s_register_operand" "=r")
1974 (mult:SI (ashiftrt:SI
1975 (match_operand:SI 1 "s_register_operand" "r")
1976 (const_int 16))
1977 (sign_extend:SI
1978 (match_operand:HI 2 "s_register_operand" "r"))))]
25f905c2 1979 "TARGET_DSP_MULTIPLY"
fec538d9 1980 "smultb%?\\t%0, %1, %2"
9da0ec36 1981 [(set_attr "type" "smulxy")
8bdfd6ed 1982 (set_attr "predicable" "yes")]
fec538d9 1983)
1984
1985(define_insn "*mulhisi3bt"
1986 [(set (match_operand:SI 0 "s_register_operand" "=r")
1987 (mult:SI (sign_extend:SI
1988 (match_operand:HI 1 "s_register_operand" "r"))
1989 (ashiftrt:SI
1990 (match_operand:SI 2 "s_register_operand" "r")
1991 (const_int 16))))]
25f905c2 1992 "TARGET_DSP_MULTIPLY"
fec538d9 1993 "smulbt%?\\t%0, %1, %2"
9da0ec36 1994 [(set_attr "type" "smulxy")
8bdfd6ed 1995 (set_attr "predicable" "yes")]
fec538d9 1996)
1997
1998(define_insn "*mulhisi3tt"
1999 [(set (match_operand:SI 0 "s_register_operand" "=r")
2000 (mult:SI (ashiftrt:SI
2001 (match_operand:SI 1 "s_register_operand" "r")
2002 (const_int 16))
2003 (ashiftrt:SI
2004 (match_operand:SI 2 "s_register_operand" "r")
2005 (const_int 16))))]
25f905c2 2006 "TARGET_DSP_MULTIPLY"
fec538d9 2007 "smultt%?\\t%0, %1, %2"
9da0ec36 2008 [(set_attr "type" "smulxy")
8bdfd6ed 2009 (set_attr "predicable" "yes")]
331beb1a 2010)
2011
5cdca009 2012(define_insn "maddhisi4"
331beb1a 2013 [(set (match_operand:SI 0 "s_register_operand" "=r")
cfa6c608 2014 (plus:SI (mult:SI (sign_extend:SI
2015 (match_operand:HI 1 "s_register_operand" "r"))
331beb1a 2016 (sign_extend:SI
cfa6c608 2017 (match_operand:HI 2 "s_register_operand" "r")))
2018 (match_operand:SI 3 "s_register_operand" "r")))]
25f905c2 2019 "TARGET_DSP_MULTIPLY"
5cdca009 2020 "smlabb%?\\t%0, %1, %2, %3"
9da0ec36 2021 [(set_attr "type" "smlaxy")
8bdfd6ed 2022 (set_attr "predicable" "yes")]
331beb1a 2023)
2024
9a92f368 2025;; Note: there is no maddhisi4ibt because this one is canonical form
2026(define_insn "*maddhisi4tb"
2027 [(set (match_operand:SI 0 "s_register_operand" "=r")
2028 (plus:SI (mult:SI (ashiftrt:SI
2029 (match_operand:SI 1 "s_register_operand" "r")
2030 (const_int 16))
2031 (sign_extend:SI
2032 (match_operand:HI 2 "s_register_operand" "r")))
2033 (match_operand:SI 3 "s_register_operand" "r")))]
2034 "TARGET_DSP_MULTIPLY"
2035 "smlatb%?\\t%0, %1, %2, %3"
9da0ec36 2036 [(set_attr "type" "smlaxy")
8bdfd6ed 2037 (set_attr "predicable" "yes")]
9a92f368 2038)
2039
2040(define_insn "*maddhisi4tt"
2041 [(set (match_operand:SI 0 "s_register_operand" "=r")
2042 (plus:SI (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)))
2048 (match_operand:SI 3 "s_register_operand" "r")))]
2049 "TARGET_DSP_MULTIPLY"
2050 "smlatt%?\\t%0, %1, %2, %3"
9da0ec36 2051 [(set_attr "type" "smlaxy")
8bdfd6ed 2052 (set_attr "predicable" "yes")]
9a92f368 2053)
2054
aff5fb4d 2055(define_insn "maddhidi4"
331beb1a 2056 [(set (match_operand:DI 0 "s_register_operand" "=r")
2057 (plus:DI
331beb1a 2058 (mult:DI (sign_extend:DI
d952d547 2059 (match_operand:HI 1 "s_register_operand" "r"))
331beb1a 2060 (sign_extend:DI
cfa6c608 2061 (match_operand:HI 2 "s_register_operand" "r")))
2062 (match_operand:DI 3 "s_register_operand" "0")))]
25f905c2 2063 "TARGET_DSP_MULTIPLY"
5cdca009 2064 "smlalbb%?\\t%Q0, %R0, %1, %2"
9da0ec36 2065 [(set_attr "type" "smlalxy")
8bdfd6ed 2066 (set_attr "predicable" "yes")])
331beb1a 2067
9a92f368 2068;; Note: there is no maddhidi4ibt because this one is canonical form
2069(define_insn "*maddhidi4tb"
2070 [(set (match_operand:DI 0 "s_register_operand" "=r")
2071 (plus:DI
2072 (mult:DI (sign_extend:DI
2073 (ashiftrt:SI
2074 (match_operand:SI 1 "s_register_operand" "r")
2075 (const_int 16)))
2076 (sign_extend:DI
2077 (match_operand:HI 2 "s_register_operand" "r")))
2078 (match_operand:DI 3 "s_register_operand" "0")))]
2079 "TARGET_DSP_MULTIPLY"
2080 "smlaltb%?\\t%Q0, %R0, %1, %2"
9da0ec36 2081 [(set_attr "type" "smlalxy")
8bdfd6ed 2082 (set_attr "predicable" "yes")])
9a92f368 2083
2084(define_insn "*maddhidi4tt"
2085 [(set (match_operand:DI 0 "s_register_operand" "=r")
2086 (plus:DI
2087 (mult:DI (sign_extend:DI
2088 (ashiftrt:SI
2089 (match_operand:SI 1 "s_register_operand" "r")
2090 (const_int 16)))
2091 (sign_extend:DI
2092 (ashiftrt:SI
2093 (match_operand:SI 2 "s_register_operand" "r")
2094 (const_int 16))))
2095 (match_operand:DI 3 "s_register_operand" "0")))]
2096 "TARGET_DSP_MULTIPLY"
2097 "smlaltt%?\\t%Q0, %R0, %1, %2"
9da0ec36 2098 [(set_attr "type" "smlalxy")
8bdfd6ed 2099 (set_attr "predicable" "yes")])
9a92f368 2100
604f3a0a 2101(define_expand "mulsf3"
3934ae0e 2102 [(set (match_operand:SF 0 "s_register_operand")
2103 (mult:SF (match_operand:SF 1 "s_register_operand")
2104 (match_operand:SF 2 "s_register_operand")))]
25f905c2 2105 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 2106 "
604f3a0a 2107")
2108
604f3a0a 2109(define_expand "muldf3"
3934ae0e 2110 [(set (match_operand:DF 0 "s_register_operand")
2111 (mult:DF (match_operand:DF 1 "s_register_operand")
2112 (match_operand:DF 2 "s_register_operand")))]
a50d7267 2113 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 2114 "
604f3a0a 2115")
b11cae9e 2116\f
2117;; Division insns
2118
7db9af5d 2119(define_expand "divsf3"
3934ae0e 2120 [(set (match_operand:SF 0 "s_register_operand")
2121 (div:SF (match_operand:SF 1 "s_register_operand")
2122 (match_operand:SF 2 "s_register_operand")))]
d7216193 2123 "TARGET_32BIT && TARGET_HARD_FLOAT"
7db9af5d 2124 "")
9c08d1fa 2125
7db9af5d 2126(define_expand "divdf3"
3934ae0e 2127 [(set (match_operand:DF 0 "s_register_operand")
2128 (div:DF (match_operand:DF 1 "s_register_operand")
2129 (match_operand:DF 2 "s_register_operand")))]
994606f8 2130 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
7db9af5d 2131 "")
b11cae9e 2132\f
b11cae9e 2133
9a7e877f 2134; Expand logical operations. The mid-end expander does not split off memory
2135; operands or complex immediates, which leads to fewer LDRD/STRD instructions.
2136; So an explicit expander is needed to generate better code.
2137
c9ad5cc4 2138(define_expand "<LOGICAL:optab>di3"
9a7e877f 2139 [(set (match_operand:DI 0 "s_register_operand")
2140 (LOGICAL:DI (match_operand:DI 1 "s_register_operand")
c9ad5cc4 2141 (match_operand:DI 2 "arm_<optab>di_operand")))]
9a7e877f 2142 "TARGET_32BIT"
2143 {
c9ad5cc4 2144 rtx low = simplify_gen_binary (<CODE>, SImode,
9a7e877f 2145 gen_lowpart (SImode, operands[1]),
2146 gen_lowpart (SImode, operands[2]));
c9ad5cc4 2147 rtx high = simplify_gen_binary (<CODE>, SImode,
9a7e877f 2148 gen_highpart (SImode, operands[1]),
2149 gen_highpart_mode (SImode, DImode,
2150 operands[2]));
2151
2152 emit_insn (gen_rtx_SET (gen_lowpart (SImode, operands[0]), low));
2153 emit_insn (gen_rtx_SET (gen_highpart (SImode, operands[0]), high));
2154 DONE;
2155 }
2156)
2157
2158(define_expand "one_cmpldi2"
2159 [(set (match_operand:DI 0 "s_register_operand")
2160 (not:DI (match_operand:DI 1 "s_register_operand")))]
2161 "TARGET_32BIT"
2162 {
2163 rtx low = simplify_gen_unary (NOT, SImode,
2164 gen_lowpart (SImode, operands[1]),
2165 SImode);
2166 rtx high = simplify_gen_unary (NOT, SImode,
2167 gen_highpart_mode (SImode, DImode,
2168 operands[1]),
2169 SImode);
2170
2171 emit_insn (gen_rtx_SET (gen_lowpart (SImode, operands[0]), low));
2172 emit_insn (gen_rtx_SET (gen_highpart (SImode, operands[0]), high));
2173 DONE;
2174 }
2175)
2176
5eddd275 2177;; Split DImode and, ior, xor operations. Simply perform the logical
f6ebffac 2178;; operation on the upper and lower halves of the registers.
5eddd275 2179;; This is needed for atomic operations in arm_split_atomic_op.
2180;; Avoid splitting IWMMXT instructions.
f6ebffac 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
2187 && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
f6ebffac 2188 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
2189 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
2190 "
215b30b3 2191 {
2192 operands[3] = gen_highpart (SImode, operands[0]);
2193 operands[0] = gen_lowpart (SImode, operands[0]);
2194 operands[4] = gen_highpart (SImode, operands[1]);
2195 operands[1] = gen_lowpart (SImode, operands[1]);
2196 operands[5] = gen_highpart (SImode, operands[2]);
2197 operands[2] = gen_lowpart (SImode, operands[2]);
2198 }"
2199)
f6ebffac 2200
5eddd275 2201;; Split DImode not (needed for atomic operations in arm_split_atomic_op).
2202;; Unconditionally split since there is no SIMD DImode NOT pattern.
f6ebffac 2203(define_split
5eddd275 2204 [(set (match_operand:DI 0 "s_register_operand")
2205 (not:DI (match_operand:DI 1 "s_register_operand")))]
25f905c2 2206 "TARGET_32BIT"
5eddd275 2207 [(set (match_dup 0) (not:SI (match_dup 1)))
2208 (set (match_dup 2) (not:SI (match_dup 3)))]
a0f94409 2209 "
2210 {
5eddd275 2211 operands[2] = gen_highpart (SImode, operands[0]);
a0f94409 2212 operands[0] = gen_lowpart (SImode, operands[0]);
5eddd275 2213 operands[3] = gen_highpart (SImode, operands[1]);
a0f94409 2214 operands[1] = gen_lowpart (SImode, operands[1]);
2215 }"
cffb2a26 2216)
b11cae9e 2217
87b22bf7 2218(define_expand "andsi3"
3934ae0e 2219 [(set (match_operand:SI 0 "s_register_operand")
2220 (and:SI (match_operand:SI 1 "s_register_operand")
2221 (match_operand:SI 2 "reg_or_int_operand")))]
cffb2a26 2222 "TARGET_EITHER"
87b22bf7 2223 "
25f905c2 2224 if (TARGET_32BIT)
87b22bf7 2225 {
0438d37f 2226 if (CONST_INT_P (operands[2]))
cffb2a26 2227 {
47b5b27b 2228 if (INTVAL (operands[2]) == 255 && arm_arch6)
2229 {
2230 operands[1] = convert_to_mode (QImode, operands[1], 1);
2231 emit_insn (gen_thumb2_zero_extendqisi2_v6 (operands[0],
2232 operands[1]));
17202aa5 2233 DONE;
47b5b27b 2234 }
17202aa5 2235 else if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[2]), AND))
2236 operands[2] = force_reg (SImode, operands[2]);
47b5b27b 2237 else
17202aa5 2238 {
2239 arm_split_constant (AND, SImode, NULL_RTX,
2240 INTVAL (operands[2]), operands[0],
2241 operands[1],
2242 optimize && can_create_pseudo_p ());
615caa51 2243
17202aa5 2244 DONE;
2245 }
cffb2a26 2246 }
87b22bf7 2247 }
25f905c2 2248 else /* TARGET_THUMB1 */
cffb2a26 2249 {
0438d37f 2250 if (!CONST_INT_P (operands[2]))
923ffadb 2251 {
2252 rtx tmp = force_reg (SImode, operands[2]);
2253 if (rtx_equal_p (operands[0], operands[1]))
2254 operands[2] = tmp;
2255 else
2256 {
2257 operands[2] = operands[1];
2258 operands[1] = tmp;
2259 }
2260 }
cffb2a26 2261 else
2262 {
2263 int i;
2264
215b30b3 2265 if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
cffb2a26 2266 {
215b30b3 2267 operands[2] = force_reg (SImode,
2268 GEN_INT (~INTVAL (operands[2])));
cffb2a26 2269
747b7458 2270 emit_insn (gen_thumb1_bicsi3 (operands[0], operands[2], operands[1]));
cffb2a26 2271
2272 DONE;
2273 }
87b22bf7 2274
cffb2a26 2275 for (i = 9; i <= 31; i++)
2276 {
db2faf44 2277 if ((HOST_WIDE_INT_1 << i) - 1 == INTVAL (operands[2]))
cffb2a26 2278 {
2279 emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
2280 const0_rtx));
2281 DONE;
2282 }
db2faf44 2283 else if ((HOST_WIDE_INT_1 << i) - 1
215b30b3 2284 == ~INTVAL (operands[2]))
cffb2a26 2285 {
2286 rtx shift = GEN_INT (i);
2287 rtx reg = gen_reg_rtx (SImode);
2288
2289 emit_insn (gen_lshrsi3 (reg, operands[1], shift));
2290 emit_insn (gen_ashlsi3 (operands[0], reg, shift));
2291
2292 DONE;
2293 }
2294 }
2295
2296 operands[2] = force_reg (SImode, operands[2]);
2297 }
215b30b3 2298 }
2299 "
cffb2a26 2300)
2301
25f905c2 2302; ??? Check split length for Thumb-2
a0f94409 2303(define_insn_and_split "*arm_andsi3_insn"
29e234a3 2304 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r,r,r")
2305 (and:SI (match_operand:SI 1 "s_register_operand" "%r,0,r,r,r")
2306 (match_operand:SI 2 "reg_or_int_operand" "I,l,K,r,?n")))]
25f905c2 2307 "TARGET_32BIT"
5565501b 2308 "@
29e234a3 2309 and%?\\t%0, %1, %2
5565501b 2310 and%?\\t%0, %1, %2
87b22bf7 2311 bic%?\\t%0, %1, #%B2
65f68e55 2312 and%?\\t%0, %1, %2
87b22bf7 2313 #"
25f905c2 2314 "TARGET_32BIT
0438d37f 2315 && CONST_INT_P (operands[2])
a0f94409 2316 && !(const_ok_for_arm (INTVAL (operands[2]))
2317 || const_ok_for_arm (~INTVAL (operands[2])))"
2318 [(clobber (const_int 0))]
2319 "
96f57e36 2320 arm_split_constant (AND, SImode, curr_insn,
2321 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 2322 DONE;
2323 "
29e234a3 2324 [(set_attr "length" "4,4,4,4,16")
65f68e55 2325 (set_attr "predicable" "yes")
29e234a3 2326 (set_attr "predicable_short_it" "no,yes,no,no,no")
d82e788e 2327 (set_attr "type" "logic_imm,logic_imm,logic_reg,logic_reg,logic_imm")]
cffb2a26 2328)
2329
f7fbdd4a 2330(define_insn "*andsi3_compare0"
bd5b4116 2331 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 2332 (compare:CC_NOOV
65f68e55 2333 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
2334 (match_operand:SI 2 "arm_not_operand" "I,K,r"))
5565501b 2335 (const_int 0)))
65f68e55 2336 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9c08d1fa 2337 (and:SI (match_dup 1) (match_dup 2)))]
25f905c2 2338 "TARGET_32BIT"
5565501b 2339 "@
3ef90e77 2340 ands%?\\t%0, %1, %2
2341 bics%?\\t%0, %1, #%B2
2342 ands%?\\t%0, %1, %2"
65f68e55 2343 [(set_attr "conds" "set")
d82e788e 2344 (set_attr "type" "logics_imm,logics_imm,logics_reg")]
cffb2a26 2345)
9c08d1fa 2346
f7fbdd4a 2347(define_insn "*andsi3_compare0_scratch"
bd5b4116 2348 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 2349 (compare:CC_NOOV
65f68e55 2350 (and:SI (match_operand:SI 0 "s_register_operand" "r,r,r")
2351 (match_operand:SI 1 "arm_not_operand" "I,K,r"))
5565501b 2352 (const_int 0)))
65f68e55 2353 (clobber (match_scratch:SI 2 "=X,r,X"))]
25f905c2 2354 "TARGET_32BIT"
5565501b 2355 "@
2356 tst%?\\t%0, %1
3ef90e77 2357 bics%?\\t%2, %0, #%B1
65f68e55 2358 tst%?\\t%0, %1"
2359 [(set_attr "conds" "set")
d82e788e 2360 (set_attr "type" "logics_imm,logics_imm,logics_reg")]
0d66636f 2361)
9c08d1fa 2362
f7fbdd4a 2363(define_insn "*zeroextractsi_compare0_scratch"
bd5b4116 2364 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2365 (compare:CC_NOOV (zero_extract:SI
2366 (match_operand:SI 0 "s_register_operand" "r")
d952d547 2367 (match_operand 1 "const_int_operand" "n")
206ee9a2 2368 (match_operand 2 "const_int_operand" "n"))
9c08d1fa 2369 (const_int 0)))]
25f905c2 2370 "TARGET_32BIT
cffb2a26 2371 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
2372 && INTVAL (operands[1]) > 0
2373 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
2374 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
9c08d1fa 2375 "*
5c49a439 2376 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
2377 << INTVAL (operands[2]));
40dbec34 2378 output_asm_insn (\"tst%?\\t%0, %1\", operands);
e2348bcb 2379 return \"\";
0d66636f 2380 "
596e5e8f 2381 [(set_attr "conds" "set")
65f68e55 2382 (set_attr "predicable" "yes")
d82e788e 2383 (set_attr "type" "logics_imm")]
0d66636f 2384)
9c08d1fa 2385
f4462328 2386(define_insn_and_split "*ne_zeroextractsi"
c4034607 2387 [(set (match_operand:SI 0 "s_register_operand" "=r")
2388 (ne:SI (zero_extract:SI
2389 (match_operand:SI 1 "s_register_operand" "r")
2390 (match_operand:SI 2 "const_int_operand" "n")
2391 (match_operand:SI 3 "const_int_operand" "n"))
3b8c7f7a 2392 (const_int 0)))
2393 (clobber (reg:CC CC_REGNUM))]
25f905c2 2394 "TARGET_32BIT
cffb2a26 2395 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2396 && INTVAL (operands[2]) > 0
2397 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2398 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
f4462328 2399 "#"
25f905c2 2400 "TARGET_32BIT
f4462328 2401 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2402 && INTVAL (operands[2]) > 0
2403 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2404 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
2405 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2406 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2407 (const_int 0)))
2408 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2409 (set (match_dup 0)
2410 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2411 (match_dup 0) (const_int 1)))]
2412 "
2413 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
2414 << INTVAL (operands[3]));
2415 "
2416 [(set_attr "conds" "clob")
25f905c2 2417 (set (attr "length")
2418 (if_then_else (eq_attr "is_thumb" "yes")
2419 (const_int 12)
1b7da4ac 2420 (const_int 8)))
2421 (set_attr "type" "multiple")]
f4462328 2422)
2423
2424(define_insn_and_split "*ne_zeroextractsi_shifted"
2425 [(set (match_operand:SI 0 "s_register_operand" "=r")
2426 (ne:SI (zero_extract:SI
2427 (match_operand:SI 1 "s_register_operand" "r")
2428 (match_operand:SI 2 "const_int_operand" "n")
2429 (const_int 0))
2430 (const_int 0)))
2431 (clobber (reg:CC CC_REGNUM))]
2432 "TARGET_ARM"
2433 "#"
2434 "TARGET_ARM"
2435 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2436 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2437 (const_int 0)))
2438 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2439 (set (match_dup 0)
2440 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2441 (match_dup 0) (const_int 1)))]
2442 "
2443 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
2444 "
2445 [(set_attr "conds" "clob")
1b7da4ac 2446 (set_attr "length" "8")
2447 (set_attr "type" "multiple")]
f4462328 2448)
2449
2450(define_insn_and_split "*ite_ne_zeroextractsi"
2451 [(set (match_operand:SI 0 "s_register_operand" "=r")
2452 (if_then_else:SI (ne (zero_extract:SI
2453 (match_operand:SI 1 "s_register_operand" "r")
2454 (match_operand:SI 2 "const_int_operand" "n")
2455 (match_operand:SI 3 "const_int_operand" "n"))
2456 (const_int 0))
2457 (match_operand:SI 4 "arm_not_operand" "rIK")
2458 (const_int 0)))
2459 (clobber (reg:CC CC_REGNUM))]
2460 "TARGET_ARM
2461 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2462 && INTVAL (operands[2]) > 0
2463 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 2464 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2465 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 2466 "#"
2467 "TARGET_ARM
2468 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2469 && INTVAL (operands[2]) > 0
2470 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 2471 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2472 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 2473 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2474 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2475 (const_int 0)))
2476 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2477 (set (match_dup 0)
2478 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2479 (match_dup 0) (match_dup 4)))]
2480 "
c4034607 2481 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
f4462328 2482 << INTVAL (operands[3]));
2483 "
2484 [(set_attr "conds" "clob")
1b7da4ac 2485 (set_attr "length" "8")
2486 (set_attr "type" "multiple")]
f4462328 2487)
2488
2489(define_insn_and_split "*ite_ne_zeroextractsi_shifted"
2490 [(set (match_operand:SI 0 "s_register_operand" "=r")
2491 (if_then_else:SI (ne (zero_extract:SI
2492 (match_operand:SI 1 "s_register_operand" "r")
2493 (match_operand:SI 2 "const_int_operand" "n")
2494 (const_int 0))
2495 (const_int 0))
2496 (match_operand:SI 3 "arm_not_operand" "rIK")
2497 (const_int 0)))
2498 (clobber (reg:CC CC_REGNUM))]
f8d7bf2f 2499 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 2500 "#"
f8d7bf2f 2501 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 2502 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2503 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2504 (const_int 0)))
2505 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2506 (set (match_dup 0)
2507 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2508 (match_dup 0) (match_dup 3)))]
2509 "
2510 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
0d66636f 2511 "
2512 [(set_attr "conds" "clob")
1b7da4ac 2513 (set_attr "length" "8")
2514 (set_attr "type" "multiple")]
215b30b3 2515)
9c08d1fa 2516
25f905c2 2517;; ??? Use Thumb-2 has bitfield insert/extract instructions.
d7863cfe 2518(define_split
2519 [(set (match_operand:SI 0 "s_register_operand" "")
2520 (match_operator:SI 1 "shiftable_operator"
2521 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2522 (match_operand:SI 3 "const_int_operand" "")
2523 (match_operand:SI 4 "const_int_operand" ""))
2524 (match_operand:SI 5 "s_register_operand" "")]))
2525 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2526 "TARGET_ARM"
2527 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2528 (set (match_dup 0)
2529 (match_op_dup 1
2530 [(lshiftrt:SI (match_dup 6) (match_dup 4))
2531 (match_dup 5)]))]
2532 "{
2533 HOST_WIDE_INT temp = INTVAL (operands[3]);
2534
2535 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2536 operands[4] = GEN_INT (32 - temp);
2537 }"
2538)
2539
d7863cfe 2540(define_split
2541 [(set (match_operand:SI 0 "s_register_operand" "")
2542 (match_operator:SI 1 "shiftable_operator"
2543 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2544 (match_operand:SI 3 "const_int_operand" "")
2545 (match_operand:SI 4 "const_int_operand" ""))
2546 (match_operand:SI 5 "s_register_operand" "")]))
2547 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2548 "TARGET_ARM"
2549 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2550 (set (match_dup 0)
2551 (match_op_dup 1
2552 [(ashiftrt:SI (match_dup 6) (match_dup 4))
2553 (match_dup 5)]))]
2554 "{
2555 HOST_WIDE_INT temp = INTVAL (operands[3]);
2556
2557 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2558 operands[4] = GEN_INT (32 - temp);
2559 }"
2560)
2561
a42059fd 2562;;; ??? This pattern is bogus. If operand3 has bits outside the range
2563;;; represented by the bitfield, then this will produce incorrect results.
2564;;; Somewhere, the value needs to be truncated. On targets like the m68k,
ceb2fe0f 2565;;; which have a real bit-field insert instruction, the truncation happens
2566;;; in the bit-field insert instruction itself. Since arm does not have a
2567;;; bit-field insert instruction, we would have to emit code here to truncate
a42059fd 2568;;; the value before we insert. This loses some of the advantage of having
2569;;; this insv pattern, so this pattern needs to be reevalutated.
2570
8a18b90c 2571(define_expand "insv"
3934ae0e 2572 [(set (zero_extract (match_operand 0 "nonimmediate_operand")
2573 (match_operand 1 "general_operand")
2574 (match_operand 2 "general_operand"))
2575 (match_operand 3 "reg_or_int_operand"))]
8b054d5a 2576 "TARGET_ARM || arm_arch_thumb2"
8a18b90c 2577 "
215b30b3 2578 {
2579 int start_bit = INTVAL (operands[2]);
2580 int width = INTVAL (operands[1]);
db2faf44 2581 HOST_WIDE_INT mask = (HOST_WIDE_INT_1 << width) - 1;
215b30b3 2582 rtx target, subtarget;
2583
8b054d5a 2584 if (arm_arch_thumb2)
2585 {
eb04cafb 2586 if (unaligned_access && MEM_P (operands[0])
2587 && s_register_operand (operands[3], GET_MODE (operands[3]))
2588 && (width == 16 || width == 32) && (start_bit % BITS_PER_UNIT) == 0)
8b054d5a 2589 {
eb04cafb 2590 rtx base_addr;
2591
2592 if (BYTES_BIG_ENDIAN)
2593 start_bit = GET_MODE_BITSIZE (GET_MODE (operands[3])) - width
2594 - start_bit;
8b054d5a 2595
eb04cafb 2596 if (width == 32)
8b054d5a 2597 {
eb04cafb 2598 base_addr = adjust_address (operands[0], SImode,
2599 start_bit / BITS_PER_UNIT);
2600 emit_insn (gen_unaligned_storesi (base_addr, operands[3]));
8b054d5a 2601 }
eb04cafb 2602 else
2603 {
2604 rtx tmp = gen_reg_rtx (HImode);
8b054d5a 2605
eb04cafb 2606 base_addr = adjust_address (operands[0], HImode,
2607 start_bit / BITS_PER_UNIT);
2608 emit_move_insn (tmp, gen_lowpart (HImode, operands[3]));
2609 emit_insn (gen_unaligned_storehi (base_addr, tmp));
2610 }
2611 DONE;
8b054d5a 2612 }
eb04cafb 2613 else if (s_register_operand (operands[0], GET_MODE (operands[0])))
8b054d5a 2614 {
eb04cafb 2615 bool use_bfi = TRUE;
8b054d5a 2616
0438d37f 2617 if (CONST_INT_P (operands[3]))
eb04cafb 2618 {
2619 HOST_WIDE_INT val = INTVAL (operands[3]) & mask;
2620
2621 if (val == 0)
2622 {
2623 emit_insn (gen_insv_zero (operands[0], operands[1],
2624 operands[2]));
2625 DONE;
2626 }
2627
2628 /* See if the set can be done with a single orr instruction. */
2629 if (val == mask && const_ok_for_arm (val << start_bit))
2630 use_bfi = FALSE;
2631 }
2632
2633 if (use_bfi)
2634 {
0438d37f 2635 if (!REG_P (operands[3]))
eb04cafb 2636 operands[3] = force_reg (SImode, operands[3]);
2637
2638 emit_insn (gen_insv_t2 (operands[0], operands[1], operands[2],
2639 operands[3]));
2640 DONE;
2641 }
8b054d5a 2642 }
eb04cafb 2643 else
2644 FAIL;
8b054d5a 2645 }
2646
eb04cafb 2647 if (!s_register_operand (operands[0], GET_MODE (operands[0])))
2648 FAIL;
2649
3f8fde42 2650 target = copy_rtx (operands[0]);
215b30b3 2651 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
2652 subreg as the final target. */
2653 if (GET_CODE (target) == SUBREG)
2654 {
2655 subtarget = gen_reg_rtx (SImode);
2656 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
2657 < GET_MODE_SIZE (SImode))
2658 target = SUBREG_REG (target);
2659 }
2660 else
2661 subtarget = target;
8a18b90c 2662
0438d37f 2663 if (CONST_INT_P (operands[3]))
215b30b3 2664 {
2665 /* Since we are inserting a known constant, we may be able to
2666 reduce the number of bits that we have to clear so that
2667 the mask becomes simple. */
2668 /* ??? This code does not check to see if the new mask is actually
2669 simpler. It may not be. */
2670 rtx op1 = gen_reg_rtx (SImode);
2671 /* ??? Truncate operand3 to fit in the bitfield. See comment before
2672 start of this pattern. */
2673 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
2674 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
2675
c5b3a71b 2676 emit_insn (gen_andsi3 (op1, operands[0],
2677 gen_int_mode (~mask2, SImode)));
215b30b3 2678 emit_insn (gen_iorsi3 (subtarget, op1,
4292ca6b 2679 gen_int_mode (op3_value << start_bit, SImode)));
215b30b3 2680 }
2681 else if (start_bit == 0
2682 && !(const_ok_for_arm (mask)
2683 || const_ok_for_arm (~mask)))
2684 {
2685 /* A Trick, since we are setting the bottom bits in the word,
2686 we can shift operand[3] up, operand[0] down, OR them together
2687 and rotate the result back again. This takes 3 insns, and
5910bb95 2688 the third might be mergeable into another op. */
215b30b3 2689 /* The shift up copes with the possibility that operand[3] is
2690 wider than the bitfield. */
2691 rtx op0 = gen_reg_rtx (SImode);
2692 rtx op1 = gen_reg_rtx (SImode);
2693
2694 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2695 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
2696 emit_insn (gen_iorsi3 (op1, op1, op0));
2697 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
2698 }
2699 else if ((width + start_bit == 32)
2700 && !(const_ok_for_arm (mask)
2701 || const_ok_for_arm (~mask)))
2702 {
2703 /* Similar trick, but slightly less efficient. */
8a18b90c 2704
215b30b3 2705 rtx op0 = gen_reg_rtx (SImode);
2706 rtx op1 = gen_reg_rtx (SImode);
8a18b90c 2707
215b30b3 2708 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2709 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
2710 emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
2711 emit_insn (gen_iorsi3 (subtarget, op1, op0));
2712 }
2713 else
2714 {
c5b3a71b 2715 rtx op0 = gen_int_mode (mask, SImode);
215b30b3 2716 rtx op1 = gen_reg_rtx (SImode);
2717 rtx op2 = gen_reg_rtx (SImode);
8a18b90c 2718
215b30b3 2719 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
2720 {
2721 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 2722
215b30b3 2723 emit_insn (gen_movsi (tmp, op0));
2724 op0 = tmp;
2725 }
8a18b90c 2726
215b30b3 2727 /* Mask out any bits in operand[3] that are not needed. */
2728 emit_insn (gen_andsi3 (op1, operands[3], op0));
8a18b90c 2729
0438d37f 2730 if (CONST_INT_P (op0)
215b30b3 2731 && (const_ok_for_arm (mask << start_bit)
2732 || const_ok_for_arm (~(mask << start_bit))))
2733 {
c5b3a71b 2734 op0 = gen_int_mode (~(mask << start_bit), SImode);
215b30b3 2735 emit_insn (gen_andsi3 (op2, operands[0], op0));
2736 }
2737 else
2738 {
0438d37f 2739 if (CONST_INT_P (op0))
215b30b3 2740 {
2741 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 2742
215b30b3 2743 emit_insn (gen_movsi (tmp, op0));
2744 op0 = tmp;
2745 }
2746
2747 if (start_bit != 0)
2748 emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
a42059fd 2749
215b30b3 2750 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
2751 }
8a18b90c 2752
215b30b3 2753 if (start_bit != 0)
2754 emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
8a18b90c 2755
215b30b3 2756 emit_insn (gen_iorsi3 (subtarget, op1, op2));
2757 }
f082f1c4 2758
215b30b3 2759 if (subtarget != target)
2760 {
2761 /* If TARGET is still a SUBREG, then it must be wider than a word,
2762 so we must be careful only to set the subword we were asked to. */
2763 if (GET_CODE (target) == SUBREG)
2764 emit_move_insn (target, subtarget);
2765 else
2766 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
2767 }
8a18b90c 2768
215b30b3 2769 DONE;
2770 }"
2771)
8a18b90c 2772
8b054d5a 2773(define_insn "insv_zero"
2774 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
809003b3 2775 (match_operand:SI 1 "const_int_M_operand" "M")
2776 (match_operand:SI 2 "const_int_M_operand" "M"))
8b054d5a 2777 (const_int 0))]
2778 "arm_arch_thumb2"
2779 "bfc%?\t%0, %2, %1"
2780 [(set_attr "length" "4")
d952d547 2781 (set_attr "predicable" "yes")
d82e788e 2782 (set_attr "type" "bfm")]
8b054d5a 2783)
2784
2785(define_insn "insv_t2"
2786 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
809003b3 2787 (match_operand:SI 1 "const_int_M_operand" "M")
2788 (match_operand:SI 2 "const_int_M_operand" "M"))
8b054d5a 2789 (match_operand:SI 3 "s_register_operand" "r"))]
2790 "arm_arch_thumb2"
2791 "bfi%?\t%0, %3, %2, %1"
2792 [(set_attr "length" "4")
d952d547 2793 (set_attr "predicable" "yes")
d82e788e 2794 (set_attr "type" "bfm")]
8b054d5a 2795)
2796
8a18b90c 2797(define_insn "andsi_notsi_si"
9c08d1fa 2798 [(set (match_operand:SI 0 "s_register_operand" "=r")
2799 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2800 (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 2801 "TARGET_32BIT"
0d66636f 2802 "bic%?\\t%0, %1, %2"
d952d547 2803 [(set_attr "predicable" "yes")
1b7da4ac 2804 (set_attr "type" "logic_reg")]
0d66636f 2805)
b11cae9e 2806
8a18b90c 2807(define_insn "andsi_not_shiftsi_si"
a2cd141b 2808 [(set (match_operand:SI 0 "s_register_operand" "=r")
2809 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2810 [(match_operand:SI 2 "s_register_operand" "r")
2811 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2812 (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 2813 "TARGET_ARM"
6c4c2133 2814 "bic%?\\t%0, %1, %2%S4"
344495ea 2815 [(set_attr "predicable" "yes")
331beb1a 2816 (set_attr "shift" "2")
a2cd141b 2817 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
d82e788e 2818 (const_string "logic_shift_imm")
2819 (const_string "logic_shift_reg")))]
6c4c2133 2820)
8a18b90c 2821
9ed784d8 2822;; Shifted bics pattern used to set up CC status register and not reusing
2823;; bics output. Pattern restricts Thumb2 shift operand as bics for Thumb2
2824;; does not support shift by register.
2825(define_insn "andsi_not_shiftsi_si_scc_no_reuse"
2826 [(set (reg:CC_NOOV CC_REGNUM)
2827 (compare:CC_NOOV
2828 (and:SI (not:SI (match_operator:SI 0 "shift_operator"
2829 [(match_operand:SI 1 "s_register_operand" "r")
2830 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2831 (match_operand:SI 3 "s_register_operand" "r"))
2832 (const_int 0)))
2833 (clobber (match_scratch:SI 4 "=r"))]
2834 "TARGET_ARM || (TARGET_THUMB2 && CONST_INT_P (operands[2]))"
3ef90e77 2835 "bics%?\\t%4, %3, %1%S0"
9ed784d8 2836 [(set_attr "predicable" "yes")
9ed784d8 2837 (set_attr "conds" "set")
2838 (set_attr "shift" "1")
2839 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2840 (const_string "logic_shift_imm")
2841 (const_string "logic_shift_reg")))]
2842)
2843
2844;; Same as andsi_not_shiftsi_si_scc_no_reuse, but the bics result is also
2845;; getting reused later.
2846(define_insn "andsi_not_shiftsi_si_scc"
2847 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2848 (compare:CC_NOOV
2849 (and:SI (not:SI (match_operator:SI 0 "shift_operator"
2850 [(match_operand:SI 1 "s_register_operand" "r")
2851 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2852 (match_operand:SI 3 "s_register_operand" "r"))
2853 (const_int 0)))
2854 (set (match_operand:SI 4 "s_register_operand" "=r")
2855 (and:SI (not:SI (match_op_dup 0
2856 [(match_dup 1)
2857 (match_dup 2)]))
2858 (match_dup 3)))])]
2859 "TARGET_ARM || (TARGET_THUMB2 && CONST_INT_P (operands[2]))"
3ef90e77 2860 "bics%?\\t%4, %3, %1%S0"
9ed784d8 2861 [(set_attr "predicable" "yes")
9ed784d8 2862 (set_attr "conds" "set")
2863 (set_attr "shift" "1")
2864 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2865 (const_string "logic_shift_imm")
2866 (const_string "logic_shift_reg")))]
2867)
2868
f7fbdd4a 2869(define_insn "*andsi_notsi_si_compare0"
bd5b4116 2870 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 2871 (compare:CC_NOOV
2872 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2873 (match_operand:SI 1 "s_register_operand" "r"))
2874 (const_int 0)))
9c08d1fa 2875 (set (match_operand:SI 0 "s_register_operand" "=r")
2876 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
25f905c2 2877 "TARGET_32BIT"
3ef90e77 2878 "bics\\t%0, %1, %2"
d82e788e 2879 [(set_attr "conds" "set")
2880 (set_attr "type" "logics_shift_reg")]
0d66636f 2881)
9c08d1fa 2882
f7fbdd4a 2883(define_insn "*andsi_notsi_si_compare0_scratch"
bd5b4116 2884 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 2885 (compare:CC_NOOV
2886 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2887 (match_operand:SI 1 "s_register_operand" "r"))
2888 (const_int 0)))
9c08d1fa 2889 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 2890 "TARGET_32BIT"
3ef90e77 2891 "bics\\t%0, %1, %2"
d82e788e 2892 [(set_attr "conds" "set")
2893 (set_attr "type" "logics_shift_reg")]
0d66636f 2894)
9c08d1fa 2895
87b22bf7 2896(define_expand "iorsi3"
3934ae0e 2897 [(set (match_operand:SI 0 "s_register_operand")
2898 (ior:SI (match_operand:SI 1 "s_register_operand")
2899 (match_operand:SI 2 "reg_or_int_operand")))]
cffb2a26 2900 "TARGET_EITHER"
87b22bf7 2901 "
0438d37f 2902 if (CONST_INT_P (operands[2]))
87b22bf7 2903 {
25f905c2 2904 if (TARGET_32BIT)
cffb2a26 2905 {
17202aa5 2906 if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[2]), IOR))
2907 operands[2] = force_reg (SImode, operands[2]);
2908 else
2909 {
2910 arm_split_constant (IOR, SImode, NULL_RTX,
2911 INTVAL (operands[2]), operands[0],
2912 operands[1],
2913 optimize && can_create_pseudo_p ());
2914 DONE;
2915 }
cffb2a26 2916 }
25f905c2 2917 else /* TARGET_THUMB1 */
923ffadb 2918 {
2919 rtx tmp = force_reg (SImode, operands[2]);
2920 if (rtx_equal_p (operands[0], operands[1]))
2921 operands[2] = tmp;
2922 else
2923 {
2924 operands[2] = operands[1];
2925 operands[1] = tmp;
2926 }
2927 }
87b22bf7 2928 }
cffb2a26 2929 "
2930)
87b22bf7 2931
d5d4dc8d 2932(define_insn_and_split "*iorsi3_insn"
29e234a3 2933 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r,r,r")
2934 (ior:SI (match_operand:SI 1 "s_register_operand" "%r,0,r,r,r")
2935 (match_operand:SI 2 "reg_or_int_operand" "I,l,K,r,?n")))]
d5d4dc8d 2936 "TARGET_32BIT"
87b22bf7 2937 "@
29e234a3 2938 orr%?\\t%0, %1, %2
87b22bf7 2939 orr%?\\t%0, %1, %2
d5d4dc8d 2940 orn%?\\t%0, %1, #%B2
65f68e55 2941 orr%?\\t%0, %1, %2
87b22bf7 2942 #"
d5d4dc8d 2943 "TARGET_32BIT
0438d37f 2944 && CONST_INT_P (operands[2])
d5d4dc8d 2945 && !(const_ok_for_arm (INTVAL (operands[2]))
2946 || (TARGET_THUMB2 && const_ok_for_arm (~INTVAL (operands[2]))))"
a0f94409 2947 [(clobber (const_int 0))]
d5d4dc8d 2948{
29e234a3 2949 arm_split_constant (IOR, SImode, curr_insn,
96f57e36 2950 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 2951 DONE;
d5d4dc8d 2952}
29e234a3 2953 [(set_attr "length" "4,4,4,4,16")
2954 (set_attr "arch" "32,t2,t2,32,32")
65f68e55 2955 (set_attr "predicable" "yes")
29e234a3 2956 (set_attr "predicable_short_it" "no,yes,no,no,no")
d82e788e 2957 (set_attr "type" "logic_imm,logic_reg,logic_imm,logic_reg,logic_reg")]
65f68e55 2958)
cffb2a26 2959
a0f94409 2960(define_peephole2
2961 [(match_scratch:SI 3 "r")
372575c7 2962 (set (match_operand:SI 0 "arm_general_register_operand" "")
2963 (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
87b22bf7 2964 (match_operand:SI 2 "const_int_operand" "")))]
90560cad 2965 "TARGET_ARM
a0f94409 2966 && !const_ok_for_arm (INTVAL (operands[2]))
2967 && const_ok_for_arm (~INTVAL (operands[2]))"
2968 [(set (match_dup 3) (match_dup 2))
2969 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2970 ""
215b30b3 2971)
a0f94409 2972
f7fbdd4a 2973(define_insn "*iorsi3_compare0"
bd5b4116 2974 [(set (reg:CC_NOOV CC_REGNUM)
a02b858e 2975 (compare:CC_NOOV
2976 (ior:SI (match_operand:SI 1 "s_register_operand" "%r,0,r")
2977 (match_operand:SI 2 "arm_rhs_operand" "I,l,r"))
2978 (const_int 0)))
2979 (set (match_operand:SI 0 "s_register_operand" "=r,l,r")
9c08d1fa 2980 (ior:SI (match_dup 1) (match_dup 2)))]
25f905c2 2981 "TARGET_32BIT"
3ef90e77 2982 "orrs%?\\t%0, %1, %2"
65f68e55 2983 [(set_attr "conds" "set")
a02b858e 2984 (set_attr "arch" "*,t2,*")
2985 (set_attr "length" "4,2,4")
2986 (set_attr "type" "logics_imm,logics_reg,logics_reg")]
cffb2a26 2987)
9c08d1fa 2988
f7fbdd4a 2989(define_insn "*iorsi3_compare0_scratch"
bd5b4116 2990 [(set (reg:CC_NOOV CC_REGNUM)
a02b858e 2991 (compare:CC_NOOV
2992 (ior:SI (match_operand:SI 1 "s_register_operand" "%r,0,r")
2993 (match_operand:SI 2 "arm_rhs_operand" "I,l,r"))
2994 (const_int 0)))
2995 (clobber (match_scratch:SI 0 "=r,l,r"))]
25f905c2 2996 "TARGET_32BIT"
3ef90e77 2997 "orrs%?\\t%0, %1, %2"
65f68e55 2998 [(set_attr "conds" "set")
a02b858e 2999 (set_attr "arch" "*,t2,*")
3000 (set_attr "length" "4,2,4")
3001 (set_attr "type" "logics_imm,logics_reg,logics_reg")]
0d66636f 3002)
9c08d1fa 3003
cffb2a26 3004(define_expand "xorsi3"
3934ae0e 3005 [(set (match_operand:SI 0 "s_register_operand")
3006 (xor:SI (match_operand:SI 1 "s_register_operand")
3007 (match_operand:SI 2 "reg_or_int_operand")))]
cffb2a26 3008 "TARGET_EITHER"
0438d37f 3009 "if (CONST_INT_P (operands[2]))
923ffadb 3010 {
3011 if (TARGET_32BIT)
3012 {
17202aa5 3013 if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[2]), XOR))
3014 operands[2] = force_reg (SImode, operands[2]);
3015 else
3016 {
3017 arm_split_constant (XOR, SImode, NULL_RTX,
3018 INTVAL (operands[2]), operands[0],
3019 operands[1],
3020 optimize && can_create_pseudo_p ());
3021 DONE;
3022 }
923ffadb 3023 }
3024 else /* TARGET_THUMB1 */
3025 {
3026 rtx tmp = force_reg (SImode, operands[2]);
3027 if (rtx_equal_p (operands[0], operands[1]))
3028 operands[2] = tmp;
3029 else
3030 {
3031 operands[2] = operands[1];
3032 operands[1] = tmp;
3033 }
3034 }
3035 }"
cffb2a26 3036)
3037
5dcb35d9 3038(define_insn_and_split "*arm_xorsi3"
29e234a3 3039 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r,r")
3040 (xor:SI (match_operand:SI 1 "s_register_operand" "%r,0,r,r")
3041 (match_operand:SI 2 "reg_or_int_operand" "I,l,r,?n")))]
25f905c2 3042 "TARGET_32BIT"
5dcb35d9 3043 "@
29e234a3 3044 eor%?\\t%0, %1, %2
65f68e55 3045 eor%?\\t%0, %1, %2
5dcb35d9 3046 eor%?\\t%0, %1, %2
3047 #"
3048 "TARGET_32BIT
0438d37f 3049 && CONST_INT_P (operands[2])
5dcb35d9 3050 && !const_ok_for_arm (INTVAL (operands[2]))"
3051 [(clobber (const_int 0))]
3052{
3053 arm_split_constant (XOR, SImode, curr_insn,
3054 INTVAL (operands[2]), operands[0], operands[1], 0);
3055 DONE;
3056}
29e234a3 3057 [(set_attr "length" "4,4,4,16")
65f68e55 3058 (set_attr "predicable" "yes")
29e234a3 3059 (set_attr "predicable_short_it" "no,yes,no,no")
1b7da4ac 3060 (set_attr "type" "logic_imm,logic_reg,logic_reg,multiple")]
cffb2a26 3061)
3062
f7fbdd4a 3063(define_insn "*xorsi3_compare0"
bd5b4116 3064 [(set (reg:CC_NOOV CC_REGNUM)
65f68e55 3065 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r,r")
3066 (match_operand:SI 2 "arm_rhs_operand" "I,r"))
9c08d1fa 3067 (const_int 0)))
65f68e55 3068 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 3069 (xor:SI (match_dup 1) (match_dup 2)))]
25f905c2 3070 "TARGET_32BIT"
3ef90e77 3071 "eors%?\\t%0, %1, %2"
65f68e55 3072 [(set_attr "conds" "set")
d82e788e 3073 (set_attr "type" "logics_imm,logics_reg")]
0d66636f 3074)
9c08d1fa 3075
f7fbdd4a 3076(define_insn "*xorsi3_compare0_scratch"
bd5b4116 3077 [(set (reg:CC_NOOV CC_REGNUM)
65f68e55 3078 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r,r")
3079 (match_operand:SI 1 "arm_rhs_operand" "I,r"))
9c08d1fa 3080 (const_int 0)))]
25f905c2 3081 "TARGET_32BIT"
40dbec34 3082 "teq%?\\t%0, %1"
65f68e55 3083 [(set_attr "conds" "set")
d82e788e 3084 (set_attr "type" "logics_imm,logics_reg")]
cffb2a26 3085)
9c08d1fa 3086
215b30b3 3087; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
3088; (NOT D) we can sometimes merge the final NOT into one of the following
3089; insns.
9c08d1fa 3090
3091(define_split
a058e94a 3092 [(set (match_operand:SI 0 "s_register_operand" "")
3093 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
3094 (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
3095 (match_operand:SI 3 "arm_rhs_operand" "")))
3096 (clobber (match_operand:SI 4 "s_register_operand" ""))]
25f905c2 3097 "TARGET_32BIT"
9c08d1fa 3098 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
3099 (not:SI (match_dup 3))))
3100 (set (match_dup 0) (not:SI (match_dup 4)))]
3101 ""
3102)
3103
ba6a3b2f 3104(define_insn_and_split "*andsi_iorsi3_notsi"
9c08d1fa 3105 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
e5fea38e 3106 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "%0,r,r")
9c08d1fa 3107 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
3108 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
25f905c2 3109 "TARGET_32BIT"
ba6a3b2f 3110 "#" ; "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
3111 "&& reload_completed"
3112 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
054fd237 3113 (set (match_dup 0) (and:SI (match_dup 4) (match_dup 5)))]
3114 {
3115 /* If operands[3] is a constant make sure to fold the NOT into it
3116 to avoid creating a NOT of a CONST_INT. */
3117 rtx not_rtx = simplify_gen_unary (NOT, SImode, operands[3], SImode);
3118 if (CONST_INT_P (not_rtx))
3119 {
3120 operands[4] = operands[0];
3121 operands[5] = not_rtx;
3122 }
3123 else
3124 {
3125 operands[5] = operands[0];
3126 operands[4] = not_rtx;
3127 }
3128 }
0d66636f 3129 [(set_attr "length" "8")
25f905c2 3130 (set_attr "ce_count" "2")
d952d547 3131 (set_attr "predicable" "yes")
1b7da4ac 3132 (set_attr "type" "multiple")]
cffb2a26 3133)
9c08d1fa 3134
25f905c2 3135; ??? Are these four splitters still beneficial when the Thumb-2 bitfield
3136; insns are available?
d7863cfe 3137(define_split
3138 [(set (match_operand:SI 0 "s_register_operand" "")
3139 (match_operator:SI 1 "logical_binary_operator"
3140 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
3141 (match_operand:SI 3 "const_int_operand" "")
3142 (match_operand:SI 4 "const_int_operand" ""))
3143 (match_operator:SI 9 "logical_binary_operator"
3144 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3145 (match_operand:SI 6 "const_int_operand" ""))
3146 (match_operand:SI 7 "s_register_operand" "")])]))
3147 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3148 "TARGET_32BIT
d7863cfe 3149 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3150 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3151 [(set (match_dup 8)
3152 (match_op_dup 1
3153 [(ashift:SI (match_dup 2) (match_dup 4))
3154 (match_dup 5)]))
3155 (set (match_dup 0)
3156 (match_op_dup 1
3157 [(lshiftrt:SI (match_dup 8) (match_dup 6))
3158 (match_dup 7)]))]
3159 "
3160 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3161")
3162
3163(define_split
3164 [(set (match_operand:SI 0 "s_register_operand" "")
3165 (match_operator:SI 1 "logical_binary_operator"
3166 [(match_operator:SI 9 "logical_binary_operator"
3167 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3168 (match_operand:SI 6 "const_int_operand" ""))
3169 (match_operand:SI 7 "s_register_operand" "")])
3170 (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
3171 (match_operand:SI 3 "const_int_operand" "")
3172 (match_operand:SI 4 "const_int_operand" ""))]))
3173 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3174 "TARGET_32BIT
d7863cfe 3175 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3176 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3177 [(set (match_dup 8)
3178 (match_op_dup 1
3179 [(ashift:SI (match_dup 2) (match_dup 4))
3180 (match_dup 5)]))
3181 (set (match_dup 0)
3182 (match_op_dup 1
3183 [(lshiftrt:SI (match_dup 8) (match_dup 6))
3184 (match_dup 7)]))]
3185 "
3186 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3187")
3188
3189(define_split
3190 [(set (match_operand:SI 0 "s_register_operand" "")
3191 (match_operator:SI 1 "logical_binary_operator"
3192 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
3193 (match_operand:SI 3 "const_int_operand" "")
3194 (match_operand:SI 4 "const_int_operand" ""))
3195 (match_operator:SI 9 "logical_binary_operator"
3196 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3197 (match_operand:SI 6 "const_int_operand" ""))
3198 (match_operand:SI 7 "s_register_operand" "")])]))
3199 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3200 "TARGET_32BIT
d7863cfe 3201 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3202 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3203 [(set (match_dup 8)
3204 (match_op_dup 1
3205 [(ashift:SI (match_dup 2) (match_dup 4))
3206 (match_dup 5)]))
3207 (set (match_dup 0)
3208 (match_op_dup 1
3209 [(ashiftrt:SI (match_dup 8) (match_dup 6))
3210 (match_dup 7)]))]
3211 "
3212 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3213")
3214
3215(define_split
3216 [(set (match_operand:SI 0 "s_register_operand" "")
3217 (match_operator:SI 1 "logical_binary_operator"
3218 [(match_operator:SI 9 "logical_binary_operator"
3219 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3220 (match_operand:SI 6 "const_int_operand" ""))
3221 (match_operand:SI 7 "s_register_operand" "")])
3222 (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
3223 (match_operand:SI 3 "const_int_operand" "")
3224 (match_operand:SI 4 "const_int_operand" ""))]))
3225 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3226 "TARGET_32BIT
d7863cfe 3227 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3228 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3229 [(set (match_dup 8)
3230 (match_op_dup 1
3231 [(ashift:SI (match_dup 2) (match_dup 4))
3232 (match_dup 5)]))
3233 (set (match_dup 0)
3234 (match_op_dup 1
3235 [(ashiftrt:SI (match_dup 8) (match_dup 6))
3236 (match_dup 7)]))]
3237 "
3238 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3239")
9c08d1fa 3240\f
3241
3242;; Minimum and maximum insns
3243
8b9dc177 3244(define_expand "smaxsi3"
3245 [(parallel [
3934ae0e 3246 (set (match_operand:SI 0 "s_register_operand")
3247 (smax:SI (match_operand:SI 1 "s_register_operand")
3248 (match_operand:SI 2 "arm_rhs_operand")))
8b9dc177 3249 (clobber (reg:CC CC_REGNUM))])]
25f905c2 3250 "TARGET_32BIT"
8b9dc177 3251 "
8774928b 3252 if (operands[2] == const0_rtx || operands[2] == constm1_rtx)
8b9dc177 3253 {
3254 /* No need for a clobber of the condition code register here. */
d1f9b275 3255 emit_insn (gen_rtx_SET (operands[0],
8b9dc177 3256 gen_rtx_SMAX (SImode, operands[1],
3257 operands[2])));
3258 DONE;
3259 }
3260")
3261
3262(define_insn "*smax_0"
3263 [(set (match_operand:SI 0 "s_register_operand" "=r")
3264 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3265 (const_int 0)))]
25f905c2 3266 "TARGET_32BIT"
8b9dc177 3267 "bic%?\\t%0, %1, %1, asr #31"
d952d547 3268 [(set_attr "predicable" "yes")
1b7da4ac 3269 (set_attr "type" "logic_shift_reg")]
8b9dc177 3270)
3271
8774928b 3272(define_insn "*smax_m1"
3273 [(set (match_operand:SI 0 "s_register_operand" "=r")
3274 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3275 (const_int -1)))]
25f905c2 3276 "TARGET_32BIT"
8774928b 3277 "orr%?\\t%0, %1, %1, asr #31"
d952d547 3278 [(set_attr "predicable" "yes")
1b7da4ac 3279 (set_attr "type" "logic_shift_reg")]
8774928b 3280)
3281
3dc953f2 3282(define_insn_and_split "*arm_smax_insn"
8b9dc177 3283 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3284 (smax:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3285 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
bd5b4116 3286 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3287 "TARGET_ARM"
3dc953f2 3288 "#"
3289 ; cmp\\t%1, %2\;movlt\\t%0, %2
3290 ; cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
3291 "TARGET_ARM"
3292 [(set (reg:CC CC_REGNUM)
3293 (compare:CC (match_dup 1) (match_dup 2)))
3294 (set (match_dup 0)
3295 (if_then_else:SI (ge:SI (reg:CC CC_REGNUM) (const_int 0))
3296 (match_dup 1)
3297 (match_dup 2)))]
3298 ""
cffb2a26 3299 [(set_attr "conds" "clob")
1b7da4ac 3300 (set_attr "length" "8,12")
3301 (set_attr "type" "multiple")]
cffb2a26 3302)
9c08d1fa 3303
8b9dc177 3304(define_expand "sminsi3"
3305 [(parallel [
3934ae0e 3306 (set (match_operand:SI 0 "s_register_operand")
3307 (smin:SI (match_operand:SI 1 "s_register_operand")
3308 (match_operand:SI 2 "arm_rhs_operand")))
8b9dc177 3309 (clobber (reg:CC CC_REGNUM))])]
25f905c2 3310 "TARGET_32BIT"
8b9dc177 3311 "
3312 if (operands[2] == const0_rtx)
3313 {
3314 /* No need for a clobber of the condition code register here. */
d1f9b275 3315 emit_insn (gen_rtx_SET (operands[0],
8b9dc177 3316 gen_rtx_SMIN (SImode, operands[1],
3317 operands[2])));
3318 DONE;
3319 }
3320")
3321
3322(define_insn "*smin_0"
3323 [(set (match_operand:SI 0 "s_register_operand" "=r")
3324 (smin:SI (match_operand:SI 1 "s_register_operand" "r")
3325 (const_int 0)))]
25f905c2 3326 "TARGET_32BIT"
8b9dc177 3327 "and%?\\t%0, %1, %1, asr #31"
d952d547 3328 [(set_attr "predicable" "yes")
1b7da4ac 3329 (set_attr "type" "logic_shift_reg")]
8b9dc177 3330)
3331
3dc953f2 3332(define_insn_and_split "*arm_smin_insn"
8b9dc177 3333 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3334 (smin:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3335 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
bd5b4116 3336 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3337 "TARGET_ARM"
3dc953f2 3338 "#"
3339 ; cmp\\t%1, %2\;movge\\t%0, %2
3340 ; cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
3341 "TARGET_ARM"
3342 [(set (reg:CC CC_REGNUM)
3343 (compare:CC (match_dup 1) (match_dup 2)))
3344 (set (match_dup 0)
3345 (if_then_else:SI (lt:SI (reg:CC CC_REGNUM) (const_int 0))
3346 (match_dup 1)
3347 (match_dup 2)))]
3348 ""
0d66636f 3349 [(set_attr "conds" "clob")
1b7da4ac 3350 (set_attr "length" "8,12")
3351 (set_attr "type" "multiple,multiple")]
0d66636f 3352)
9c08d1fa 3353
25f905c2 3354(define_expand "umaxsi3"
3355 [(parallel [
3934ae0e 3356 (set (match_operand:SI 0 "s_register_operand")
3357 (umax:SI (match_operand:SI 1 "s_register_operand")
3358 (match_operand:SI 2 "arm_rhs_operand")))
25f905c2 3359 (clobber (reg:CC CC_REGNUM))])]
3360 "TARGET_32BIT"
3361 ""
3362)
3363
3dc953f2 3364(define_insn_and_split "*arm_umaxsi3"
9c08d1fa 3365 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3366 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3367 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 3368 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3369 "TARGET_ARM"
3dc953f2 3370 "#"
3371 ; cmp\\t%1, %2\;movcc\\t%0, %2
3372 ; cmp\\t%1, %2\;movcs\\t%0, %1
3373 ; cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
3374 "TARGET_ARM"
3375 [(set (reg:CC CC_REGNUM)
3376 (compare:CC (match_dup 1) (match_dup 2)))
3377 (set (match_dup 0)
3378 (if_then_else:SI (geu:SI (reg:CC CC_REGNUM) (const_int 0))
3379 (match_dup 1)
3380 (match_dup 2)))]
3381 ""
0d66636f 3382 [(set_attr "conds" "clob")
1b7da4ac 3383 (set_attr "length" "8,8,12")
9f2c2a36 3384 (set_attr "type" "store_4")]
0d66636f 3385)
9c08d1fa 3386
25f905c2 3387(define_expand "uminsi3"
3388 [(parallel [
3934ae0e 3389 (set (match_operand:SI 0 "s_register_operand")
3390 (umin:SI (match_operand:SI 1 "s_register_operand")
3391 (match_operand:SI 2 "arm_rhs_operand")))
25f905c2 3392 (clobber (reg:CC CC_REGNUM))])]
3393 "TARGET_32BIT"
3394 ""
3395)
3396
3dc953f2 3397(define_insn_and_split "*arm_uminsi3"
9c08d1fa 3398 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3399 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3400 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 3401 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3402 "TARGET_ARM"
3dc953f2 3403 "#"
3404 ; cmp\\t%1, %2\;movcs\\t%0, %2
3405 ; cmp\\t%1, %2\;movcc\\t%0, %1
3406 ; cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
3407 "TARGET_ARM"
3408 [(set (reg:CC CC_REGNUM)
3409 (compare:CC (match_dup 1) (match_dup 2)))
3410 (set (match_dup 0)
3411 (if_then_else:SI (ltu:SI (reg:CC CC_REGNUM) (const_int 0))
3412 (match_dup 1)
3413 (match_dup 2)))]
3414 ""
0d66636f 3415 [(set_attr "conds" "clob")
1b7da4ac 3416 (set_attr "length" "8,8,12")
9f2c2a36 3417 (set_attr "type" "store_4")]
0d66636f 3418)
9c08d1fa 3419
8a18b90c 3420(define_insn "*store_minmaxsi"
9c08d1fa 3421 [(set (match_operand:SI 0 "memory_operand" "=m")
3422 (match_operator:SI 3 "minmax_operator"
3423 [(match_operand:SI 1 "s_register_operand" "r")
3424 (match_operand:SI 2 "s_register_operand" "r")]))
bd5b4116 3425 (clobber (reg:CC CC_REGNUM))]
b207d152 3426 "TARGET_32BIT && optimize_function_for_size_p (cfun) && !arm_restrict_it"
9c08d1fa 3427 "*
dc55b8a9 3428 operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
3429 operands[1], operands[2]);
e2348bcb 3430 output_asm_insn (\"cmp\\t%1, %2\", operands);
25f905c2 3431 if (TARGET_THUMB2)
3432 output_asm_insn (\"ite\t%d3\", operands);
e2348bcb 3433 output_asm_insn (\"str%d3\\t%1, %0\", operands);
3434 output_asm_insn (\"str%D3\\t%2, %0\", operands);
3435 return \"\";
0d66636f 3436 "
3437 [(set_attr "conds" "clob")
25f905c2 3438 (set (attr "length")
3439 (if_then_else (eq_attr "is_thumb" "yes")
3440 (const_int 14)
3441 (const_int 12)))
9f2c2a36 3442 (set_attr "type" "store_4")]
0d66636f 3443)
9c08d1fa 3444
8a18b90c 3445; Reject the frame pointer in operand[1], since reloading this after
3446; it has been eliminated can cause carnage.
f7fbdd4a 3447(define_insn "*minmax_arithsi"
9c08d1fa 3448 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3449 (match_operator:SI 4 "shiftable_operator"
3450 [(match_operator:SI 5 "minmax_operator"
3451 [(match_operand:SI 2 "s_register_operand" "r,r")
3452 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
3453 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 3454 (clobber (reg:CC CC_REGNUM))]
7c36fe71 3455 "TARGET_32BIT && !arm_eliminable_register (operands[1]) && !arm_restrict_it"
9c08d1fa 3456 "*
0d66636f 3457 {
3458 enum rtx_code code = GET_CODE (operands[4]);
25f905c2 3459 bool need_else;
3460
3461 if (which_alternative != 0 || operands[3] != const0_rtx
ca0fc5a2 3462 || (code != PLUS && code != IOR && code != XOR))
25f905c2 3463 need_else = true;
3464 else
3465 need_else = false;
0d66636f 3466
dc55b8a9 3467 operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
3468 operands[2], operands[3]);
0d66636f 3469 output_asm_insn (\"cmp\\t%2, %3\", operands);
25f905c2 3470 if (TARGET_THUMB2)
3471 {
3472 if (need_else)
3473 output_asm_insn (\"ite\\t%d5\", operands);
3474 else
3475 output_asm_insn (\"it\\t%d5\", operands);
3476 }
0d66636f 3477 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
25f905c2 3478 if (need_else)
0d66636f 3479 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
3480 return \"\";
215b30b3 3481 }"
0d66636f 3482 [(set_attr "conds" "clob")
25f905c2 3483 (set (attr "length")
3484 (if_then_else (eq_attr "is_thumb" "yes")
3485 (const_int 14)
1b7da4ac 3486 (const_int 12)))
3487 (set_attr "type" "multiple")]
0d66636f 3488)
9c08d1fa 3489
4164bca1 3490; Reject the frame pointer in operand[1], since reloading this after
3491; it has been eliminated can cause carnage.
3492(define_insn_and_split "*minmax_arithsi_non_canon"
7c36fe71 3493 [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts")
4164bca1 3494 (minus:SI
7c36fe71 3495 (match_operand:SI 1 "s_register_operand" "0,?Ts")
4164bca1 3496 (match_operator:SI 4 "minmax_operator"
7c36fe71 3497 [(match_operand:SI 2 "s_register_operand" "Ts,Ts")
3498 (match_operand:SI 3 "arm_rhs_operand" "TsI,TsI")])))
4164bca1 3499 (clobber (reg:CC CC_REGNUM))]
7c36fe71 3500 "TARGET_32BIT && !arm_eliminable_register (operands[1])
3501 && !(arm_restrict_it && CONST_INT_P (operands[3]))"
4164bca1 3502 "#"
3503 "TARGET_32BIT && !arm_eliminable_register (operands[1]) && reload_completed"
3504 [(set (reg:CC CC_REGNUM)
3505 (compare:CC (match_dup 2) (match_dup 3)))
3506
3507 (cond_exec (match_op_dup 4 [(reg:CC CC_REGNUM) (const_int 0)])
3508 (set (match_dup 0)
3509 (minus:SI (match_dup 1)
3510 (match_dup 2))))
3511 (cond_exec (match_op_dup 5 [(reg:CC CC_REGNUM) (const_int 0)])
3512 (set (match_dup 0)
36ee0cde 3513 (match_dup 6)))]
4164bca1 3514 {
3754d046 3515 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
4164bca1 3516 operands[2], operands[3]);
3517 enum rtx_code rc = minmax_code (operands[4]);
3518 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode,
3519 operands[2], operands[3]);
3520
3521 if (mode == CCFPmode || mode == CCFPEmode)
3522 rc = reverse_condition_maybe_unordered (rc);
3523 else
3524 rc = reverse_condition (rc);
3525 operands[5] = gen_rtx_fmt_ee (rc, SImode, operands[2], operands[3]);
36ee0cde 3526 if (CONST_INT_P (operands[3]))
3527 operands[6] = plus_constant (SImode, operands[1], -INTVAL (operands[3]));
3528 else
3529 operands[6] = gen_rtx_MINUS (SImode, operands[1], operands[3]);
4164bca1 3530 }
3531 [(set_attr "conds" "clob")
3532 (set (attr "length")
3533 (if_then_else (eq_attr "is_thumb" "yes")
3534 (const_int 14)
1b7da4ac 3535 (const_int 12)))
3536 (set_attr "type" "multiple")]
4164bca1 3537)
3538
b49e3742 3539(define_code_iterator SAT [smin smax])
f0038cf3 3540(define_code_attr SATrev [(smin "smax") (smax "smin")])
b49e3742 3541(define_code_attr SATlo [(smin "1") (smax "2")])
3542(define_code_attr SAThi [(smin "2") (smax "1")])
3543
3544(define_insn "*satsi_<SAT:code>"
3545 [(set (match_operand:SI 0 "s_register_operand" "=r")
f0038cf3 3546 (SAT:SI (<SATrev>:SI (match_operand:SI 3 "s_register_operand" "r")
b49e3742 3547 (match_operand:SI 1 "const_int_operand" "i"))
3548 (match_operand:SI 2 "const_int_operand" "i")))]
f0038cf3 3549 "TARGET_32BIT && arm_arch6
b49e3742 3550 && arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>], NULL, NULL)"
3551{
3552 int mask;
3553 bool signed_sat;
3554 if (!arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>],
3555 &mask, &signed_sat))
3556 gcc_unreachable ();
3557
3558 operands[1] = GEN_INT (mask);
3559 if (signed_sat)
3560 return "ssat%?\t%0, %1, %3";
3561 else
3562 return "usat%?\t%0, %1, %3";
3563}
7c36fe71 3564 [(set_attr "predicable" "yes")
1b7da4ac 3565 (set_attr "type" "alus_imm")]
bebe9bbb 3566)
b49e3742 3567
3568(define_insn "*satsi_<SAT:code>_shift"
3569 [(set (match_operand:SI 0 "s_register_operand" "=r")
f0038cf3 3570 (SAT:SI (<SATrev>:SI (match_operator:SI 3 "sat_shift_operator"
b49e3742 3571 [(match_operand:SI 4 "s_register_operand" "r")
3572 (match_operand:SI 5 "const_int_operand" "i")])
3573 (match_operand:SI 1 "const_int_operand" "i"))
3574 (match_operand:SI 2 "const_int_operand" "i")))]
f0038cf3 3575 "TARGET_32BIT && arm_arch6
b49e3742 3576 && arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>], NULL, NULL)"
3577{
3578 int mask;
3579 bool signed_sat;
3580 if (!arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>],
3581 &mask, &signed_sat))
3582 gcc_unreachable ();
3583
3584 operands[1] = GEN_INT (mask);
3585 if (signed_sat)
3586 return "ssat%?\t%0, %1, %4%S3";
3587 else
3588 return "usat%?\t%0, %1, %4%S3";
3589}
3590 [(set_attr "predicable" "yes")
b49e3742 3591 (set_attr "shift" "3")
d82e788e 3592 (set_attr "type" "logic_shift_reg")])
b11cae9e 3593\f
3594;; Shift and rotation insns
3595
a2cd141b 3596(define_expand "ashldi3"
3934ae0e 3597 [(set (match_operand:DI 0 "s_register_operand")
3598 (ashift:DI (match_operand:DI 1 "s_register_operand")
8baabb36 3599 (match_operand:SI 2 "reg_or_int_operand")))]
25f905c2 3600 "TARGET_32BIT"
a2cd141b 3601 "
8baabb36 3602 arm_emit_coreregs_64bit_shift (ASHIFT, operands[0], operands[1],
3603 operands[2], gen_reg_rtx (SImode),
3604 gen_reg_rtx (SImode));
3605 DONE;
3606")
a2cd141b 3607
87b22bf7 3608(define_expand "ashlsi3"
3934ae0e 3609 [(set (match_operand:SI 0 "s_register_operand")
3610 (ashift:SI (match_operand:SI 1 "s_register_operand")
3611 (match_operand:SI 2 "arm_rhs_operand")))]
cffb2a26 3612 "TARGET_EITHER"
87b22bf7 3613 "
0438d37f 3614 if (CONST_INT_P (operands[2])
8c4e8755 3615 && (UINTVAL (operands[2])) > 31)
87b22bf7 3616 {
3617 emit_insn (gen_movsi (operands[0], const0_rtx));
3618 DONE;
3619 }
cffb2a26 3620 "
3621)
3622
a2cd141b 3623(define_expand "ashrdi3"
3934ae0e 3624 [(set (match_operand:DI 0 "s_register_operand")
3625 (ashiftrt:DI (match_operand:DI 1 "s_register_operand")
3626 (match_operand:SI 2 "reg_or_int_operand")))]
25f905c2 3627 "TARGET_32BIT"
a2cd141b 3628 "
8baabb36 3629 arm_emit_coreregs_64bit_shift (ASHIFTRT, operands[0], operands[1],
3630 operands[2], gen_reg_rtx (SImode),
3631 gen_reg_rtx (SImode));
3632 DONE;
3633")
a2cd141b 3634
87b22bf7 3635(define_expand "ashrsi3"
3934ae0e 3636 [(set (match_operand:SI 0 "s_register_operand")
3637 (ashiftrt:SI (match_operand:SI 1 "s_register_operand")
3638 (match_operand:SI 2 "arm_rhs_operand")))]
cffb2a26 3639 "TARGET_EITHER"
87b22bf7 3640 "
0438d37f 3641 if (CONST_INT_P (operands[2])
8c4e8755 3642 && UINTVAL (operands[2]) > 31)
87b22bf7 3643 operands[2] = GEN_INT (31);
cffb2a26 3644 "
3645)
3646
a2cd141b 3647(define_expand "lshrdi3"
3934ae0e 3648 [(set (match_operand:DI 0 "s_register_operand")
3649 (lshiftrt:DI (match_operand:DI 1 "s_register_operand")
3650 (match_operand:SI 2 "reg_or_int_operand")))]
25f905c2 3651 "TARGET_32BIT"
a2cd141b 3652 "
8baabb36 3653 arm_emit_coreregs_64bit_shift (LSHIFTRT, operands[0], operands[1],
3654 operands[2], gen_reg_rtx (SImode),
3655 gen_reg_rtx (SImode));
3656 DONE;
3657")
a2cd141b 3658
87b22bf7 3659(define_expand "lshrsi3"
3934ae0e 3660 [(set (match_operand:SI 0 "s_register_operand")
3661 (lshiftrt:SI (match_operand:SI 1 "s_register_operand")
3662 (match_operand:SI 2 "arm_rhs_operand")))]
cffb2a26 3663 "TARGET_EITHER"
87b22bf7 3664 "
0438d37f 3665 if (CONST_INT_P (operands[2])
8c4e8755 3666 && (UINTVAL (operands[2])) > 31)
87b22bf7 3667 {
3668 emit_insn (gen_movsi (operands[0], const0_rtx));
3669 DONE;
3670 }
cffb2a26 3671 "
3672)
3673
87b22bf7 3674(define_expand "rotlsi3"
3934ae0e 3675 [(set (match_operand:SI 0 "s_register_operand")
3676 (rotatert:SI (match_operand:SI 1 "s_register_operand")
3677 (match_operand:SI 2 "reg_or_int_operand")))]
25f905c2 3678 "TARGET_32BIT"
87b22bf7 3679 "
0438d37f 3680 if (CONST_INT_P (operands[2]))
87b22bf7 3681 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
3682 else
b11cae9e 3683 {
87b22bf7 3684 rtx reg = gen_reg_rtx (SImode);
3685 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
3686 operands[2] = reg;
b11cae9e 3687 }
cffb2a26 3688 "
3689)
9c08d1fa 3690
87b22bf7 3691(define_expand "rotrsi3"
3934ae0e 3692 [(set (match_operand:SI 0 "s_register_operand")
3693 (rotatert:SI (match_operand:SI 1 "s_register_operand")
3694 (match_operand:SI 2 "arm_rhs_operand")))]
cffb2a26 3695 "TARGET_EITHER"
87b22bf7 3696 "
25f905c2 3697 if (TARGET_32BIT)
cffb2a26 3698 {
0438d37f 3699 if (CONST_INT_P (operands[2])
8c4e8755 3700 && UINTVAL (operands[2]) > 31)
cffb2a26 3701 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
3702 }
25f905c2 3703 else /* TARGET_THUMB1 */
cffb2a26 3704 {
0438d37f 3705 if (CONST_INT_P (operands [2]))
cffb2a26 3706 operands [2] = force_reg (SImode, operands[2]);
3707 }
3708 "
3709)
87b22bf7 3710
cffb2a26 3711(define_insn "*arm_shiftsi3"
88c29385 3712 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r,r")
cffb2a26 3713 (match_operator:SI 3 "shift_operator"
88c29385 3714 [(match_operand:SI 1 "s_register_operand" "0,l,r,r")
3715 (match_operand:SI 2 "reg_or_int_operand" "l,M,M,r")]))]
25f905c2 3716 "TARGET_32BIT"
3717 "* return arm_output_shift(operands, 0);"
344495ea 3718 [(set_attr "predicable" "yes")
88c29385 3719 (set_attr "arch" "t2,t2,*,*")
3720 (set_attr "predicable_short_it" "yes,yes,no,no")
7c36fe71 3721 (set_attr "length" "4")
331beb1a 3722 (set_attr "shift" "1")
88c29385 3723 (set_attr "type" "alu_shift_reg,alu_shift_imm,alu_shift_imm,alu_shift_reg")]
6c4c2133 3724)
87b22bf7 3725
f7fbdd4a 3726(define_insn "*shiftsi3_compare0"
bd5b4116 3727 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 3728 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
6b6abc9c 3729 [(match_operand:SI 1 "s_register_operand" "r,r")
3730 (match_operand:SI 2 "arm_rhs_operand" "M,r")])
9c08d1fa 3731 (const_int 0)))
6b6abc9c 3732 (set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 3733 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
25f905c2 3734 "TARGET_32BIT"
3735 "* return arm_output_shift(operands, 1);"
344495ea 3736 [(set_attr "conds" "set")
331beb1a 3737 (set_attr "shift" "1")
d82e788e 3738 (set_attr "type" "alus_shift_imm,alus_shift_reg")]
0d66636f 3739)
9c08d1fa 3740
f7fbdd4a 3741(define_insn "*shiftsi3_compare0_scratch"
bd5b4116 3742 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 3743 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
6b6abc9c 3744 [(match_operand:SI 1 "s_register_operand" "r,r")
3745 (match_operand:SI 2 "arm_rhs_operand" "M,r")])
9c08d1fa 3746 (const_int 0)))
6b6abc9c 3747 (clobber (match_scratch:SI 0 "=r,r"))]
25f905c2 3748 "TARGET_32BIT"
3749 "* return arm_output_shift(operands, 1);"
344495ea 3750 [(set_attr "conds" "set")
6b6abc9c 3751 (set_attr "shift" "1")
d82e788e 3752 (set_attr "type" "shift_imm,shift_reg")]
0d66636f 3753)
9c08d1fa 3754
d5d4dc8d 3755(define_insn "*not_shiftsi"
3756 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 3757 (not:SI (match_operator:SI 3 "shift_operator"
d5d4dc8d 3758 [(match_operand:SI 1 "s_register_operand" "r,r")
3759 (match_operand:SI 2 "shift_amount_operand" "M,rM")])))]
3760 "TARGET_32BIT"
6c4c2133 3761 "mvn%?\\t%0, %1%S3"
344495ea 3762 [(set_attr "predicable" "yes")
331beb1a 3763 (set_attr "shift" "1")
d5d4dc8d 3764 (set_attr "arch" "32,a")
1aed5204 3765 (set_attr "type" "mvn_shift,mvn_shift_reg")])
9c08d1fa 3766
d5d4dc8d 3767(define_insn "*not_shiftsi_compare0"
bd5b4116 3768 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 3769 (compare:CC_NOOV
3770 (not:SI (match_operator:SI 3 "shift_operator"
3771 [(match_operand:SI 1 "s_register_operand" "r,r")
3772 (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
3773 (const_int 0)))
3774 (set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 3775 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
d5d4dc8d 3776 "TARGET_32BIT"
3ef90e77 3777 "mvns%?\\t%0, %1%S3"
344495ea 3778 [(set_attr "conds" "set")
331beb1a 3779 (set_attr "shift" "1")
d5d4dc8d 3780 (set_attr "arch" "32,a")
1aed5204 3781 (set_attr "type" "mvn_shift,mvn_shift_reg")])
9c08d1fa 3782
d5d4dc8d 3783(define_insn "*not_shiftsi_compare0_scratch"
bd5b4116 3784 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 3785 (compare:CC_NOOV
3786 (not:SI (match_operator:SI 3 "shift_operator"
3787 [(match_operand:SI 1 "s_register_operand" "r,r")
3788 (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
3789 (const_int 0)))
3790 (clobber (match_scratch:SI 0 "=r,r"))]
3791 "TARGET_32BIT"
3ef90e77 3792 "mvns%?\\t%0, %1%S3"
344495ea 3793 [(set_attr "conds" "set")
331beb1a 3794 (set_attr "shift" "1")
d5d4dc8d 3795 (set_attr "arch" "32,a")
1aed5204 3796 (set_attr "type" "mvn_shift,mvn_shift_reg")])
9c08d1fa 3797
cffb2a26 3798;; We don't really have extzv, but defining this using shifts helps
3799;; to reduce register pressure later on.
3800
3801(define_expand "extzv"
3934ae0e 3802 [(set (match_operand 0 "s_register_operand")
3803 (zero_extract (match_operand 1 "nonimmediate_operand")
3804 (match_operand 2 "const_int_operand")
3805 (match_operand 3 "const_int_operand")))]
8b054d5a 3806 "TARGET_THUMB1 || arm_arch_thumb2"
cffb2a26 3807 "
3808 {
3809 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
3810 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
3811
8b054d5a 3812 if (arm_arch_thumb2)
3813 {
eb04cafb 3814 HOST_WIDE_INT width = INTVAL (operands[2]);
3815 HOST_WIDE_INT bitpos = INTVAL (operands[3]);
3816
3817 if (unaligned_access && MEM_P (operands[1])
3818 && (width == 16 || width == 32) && (bitpos % BITS_PER_UNIT) == 0)
3819 {
3820 rtx base_addr;
3821
3822 if (BYTES_BIG_ENDIAN)
3823 bitpos = GET_MODE_BITSIZE (GET_MODE (operands[0])) - width
3824 - bitpos;
3825
3826 if (width == 32)
3827 {
3828 base_addr = adjust_address (operands[1], SImode,
3829 bitpos / BITS_PER_UNIT);
3830 emit_insn (gen_unaligned_loadsi (operands[0], base_addr));
3831 }
3832 else
3833 {
3834 rtx dest = operands[0];
3835 rtx tmp = gen_reg_rtx (SImode);
3836
3837 /* We may get a paradoxical subreg here. Strip it off. */
3838 if (GET_CODE (dest) == SUBREG
3839 && GET_MODE (dest) == SImode
3840 && GET_MODE (SUBREG_REG (dest)) == HImode)
3841 dest = SUBREG_REG (dest);
3842
3843 if (GET_MODE_BITSIZE (GET_MODE (dest)) != width)
3844 FAIL;
3845
3846 base_addr = adjust_address (operands[1], HImode,
3847 bitpos / BITS_PER_UNIT);
3848 emit_insn (gen_unaligned_loadhiu (tmp, base_addr));
3849 emit_move_insn (gen_lowpart (SImode, dest), tmp);
3850 }
3851 DONE;
3852 }
3853 else if (s_register_operand (operands[1], GET_MODE (operands[1])))
3854 {
3855 emit_insn (gen_extzv_t2 (operands[0], operands[1], operands[2],
3856 operands[3]));
3857 DONE;
3858 }
3859 else
3860 FAIL;
8b054d5a 3861 }
eb04cafb 3862
3863 if (!s_register_operand (operands[1], GET_MODE (operands[1])))
3864 FAIL;
8b054d5a 3865
cffb2a26 3866 operands[3] = GEN_INT (rshift);
3867
3868 if (lshift == 0)
3869 {
3870 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
3871 DONE;
3872 }
3873
eb04cafb 3874 emit_insn (gen_extzv_t1 (operands[0], operands[1], GEN_INT (lshift),
3875 operands[3], gen_reg_rtx (SImode)));
3876 DONE;
215b30b3 3877 }"
cffb2a26 3878)
3879
eb04cafb 3880;; Helper for extzv, for the Thumb-1 register-shifts case.
3881
3882(define_expand "extzv_t1"
3934ae0e 3883 [(set (match_operand:SI 4 "s_register_operand")
3884 (ashift:SI (match_operand:SI 1 "nonimmediate_operand")
3885 (match_operand:SI 2 "const_int_operand")))
3886 (set (match_operand:SI 0 "s_register_operand")
eb04cafb 3887 (lshiftrt:SI (match_dup 4)
3934ae0e 3888 (match_operand:SI 3 "const_int_operand")))]
eb04cafb 3889 "TARGET_THUMB1"
3890 "")
3891
3892(define_expand "extv"
3934ae0e 3893 [(set (match_operand 0 "s_register_operand")
3894 (sign_extract (match_operand 1 "nonimmediate_operand")
3895 (match_operand 2 "const_int_operand")
3896 (match_operand 3 "const_int_operand")))]
eb04cafb 3897 "arm_arch_thumb2"
3898{
3899 HOST_WIDE_INT width = INTVAL (operands[2]);
3900 HOST_WIDE_INT bitpos = INTVAL (operands[3]);
3901
3902 if (unaligned_access && MEM_P (operands[1]) && (width == 16 || width == 32)
3903 && (bitpos % BITS_PER_UNIT) == 0)
3904 {
3905 rtx base_addr;
3906
3907 if (BYTES_BIG_ENDIAN)
3908 bitpos = GET_MODE_BITSIZE (GET_MODE (operands[0])) - width - bitpos;
3909
3910 if (width == 32)
3911 {
3912 base_addr = adjust_address (operands[1], SImode,
3913 bitpos / BITS_PER_UNIT);
3914 emit_insn (gen_unaligned_loadsi (operands[0], base_addr));
3915 }
3916 else
3917 {
3918 rtx dest = operands[0];
3919 rtx tmp = gen_reg_rtx (SImode);
3920
3921 /* We may get a paradoxical subreg here. Strip it off. */
3922 if (GET_CODE (dest) == SUBREG
3923 && GET_MODE (dest) == SImode
3924 && GET_MODE (SUBREG_REG (dest)) == HImode)
3925 dest = SUBREG_REG (dest);
3926
3927 if (GET_MODE_BITSIZE (GET_MODE (dest)) != width)
3928 FAIL;
3929
3930 base_addr = adjust_address (operands[1], HImode,
3931 bitpos / BITS_PER_UNIT);
3932 emit_insn (gen_unaligned_loadhis (tmp, base_addr));
3933 emit_move_insn (gen_lowpart (SImode, dest), tmp);
3934 }
3935
3936 DONE;
3937 }
3938 else if (!s_register_operand (operands[1], GET_MODE (operands[1])))
3939 FAIL;
3940 else if (GET_MODE (operands[0]) == SImode
3941 && GET_MODE (operands[1]) == SImode)
3942 {
3943 emit_insn (gen_extv_regsi (operands[0], operands[1], operands[2],
3944 operands[3]));
3945 DONE;
3946 }
3947
3948 FAIL;
3949})
3950
3951; Helper to expand register forms of extv with the proper modes.
3952
3953(define_expand "extv_regsi"
3934ae0e 3954 [(set (match_operand:SI 0 "s_register_operand")
3955 (sign_extract:SI (match_operand:SI 1 "s_register_operand")
3956 (match_operand 2 "const_int_operand")
3957 (match_operand 3 "const_int_operand")))]
eb04cafb 3958 ""
3959{
3960})
3961
3962; ARMv6+ unaligned load/store instructions (used for packed structure accesses).
3963
122f262a 3964(define_insn "unaligned_loaddi"
3965 [(set (match_operand:DI 0 "s_register_operand" "=r")
3966 (unspec:DI [(match_operand:DI 1 "memory_operand" "m")]
3967 UNSPEC_UNALIGNED_LOAD))]
3968 "TARGET_32BIT && TARGET_LDRD"
3969 "*
3970 return output_move_double (operands, true, NULL);
3971 "
3972 [(set_attr "length" "8")
3973 (set_attr "type" "load_8")])
3974
eb04cafb 3975(define_insn "unaligned_loadsi"
70ce330a 3976 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
3977 (unspec:SI [(match_operand:SI 1 "memory_operand" "m,Uw,m")]
eb04cafb 3978 UNSPEC_UNALIGNED_LOAD))]
8fe38eb2 3979 "unaligned_access"
70ce330a 3980 "@
3981 ldr\t%0, %1\t@ unaligned
3982 ldr%?\t%0, %1\t@ unaligned
3983 ldr%?\t%0, %1\t@ unaligned"
3984 [(set_attr "arch" "t1,t2,32")
3985 (set_attr "length" "2,2,4")
3986 (set_attr "predicable" "no,yes,yes")
3987 (set_attr "predicable_short_it" "no,yes,no")
9f2c2a36 3988 (set_attr "type" "load_4")])
eb04cafb 3989
70ce330a 3990;; The 16-bit Thumb1 variant of ldrsh requires two registers in the
3991;; address (there's no immediate format). That's tricky to support
3992;; here and we don't really need this pattern for that case, so only
3993;; enable for 32-bit ISAs.
eb04cafb 3994(define_insn "unaligned_loadhis"
5d79b75e 3995 [(set (match_operand:SI 0 "s_register_operand" "=r")
eb04cafb 3996 (sign_extend:SI
5d79b75e 3997 (unspec:HI [(match_operand:HI 1 "memory_operand" "Uh")]
eb04cafb 3998 UNSPEC_UNALIGNED_LOAD)))]
70ce330a 3999 "unaligned_access && TARGET_32BIT"
3ef90e77 4000 "ldrsh%?\t%0, %1\t@ unaligned"
5d79b75e 4001 [(set_attr "predicable" "yes")
eb04cafb 4002 (set_attr "type" "load_byte")])
4003
4004(define_insn "unaligned_loadhiu"
70ce330a 4005 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
eb04cafb 4006 (zero_extend:SI
70ce330a 4007 (unspec:HI [(match_operand:HI 1 "memory_operand" "m,Uw,m")]
eb04cafb 4008 UNSPEC_UNALIGNED_LOAD)))]
8fe38eb2 4009 "unaligned_access"
70ce330a 4010 "@
4011 ldrh\t%0, %1\t@ unaligned
4012 ldrh%?\t%0, %1\t@ unaligned
4013 ldrh%?\t%0, %1\t@ unaligned"
4014 [(set_attr "arch" "t1,t2,32")
4015 (set_attr "length" "2,2,4")
4016 (set_attr "predicable" "no,yes,yes")
4017 (set_attr "predicable_short_it" "no,yes,no")
eb04cafb 4018 (set_attr "type" "load_byte")])
4019
122f262a 4020(define_insn "unaligned_storedi"
4021 [(set (match_operand:DI 0 "memory_operand" "=m")
4022 (unspec:DI [(match_operand:DI 1 "s_register_operand" "r")]
4023 UNSPEC_UNALIGNED_STORE))]
4024 "TARGET_32BIT && TARGET_LDRD"
4025 "*
4026 return output_move_double (operands, true, NULL);
4027 "
4028 [(set_attr "length" "8")
4029 (set_attr "type" "store_8")])
4030
eb04cafb 4031(define_insn "unaligned_storesi"
70ce330a 4032 [(set (match_operand:SI 0 "memory_operand" "=m,Uw,m")
4033 (unspec:SI [(match_operand:SI 1 "s_register_operand" "l,l,r")]
eb04cafb 4034 UNSPEC_UNALIGNED_STORE))]
8fe38eb2 4035 "unaligned_access"
70ce330a 4036 "@
4037 str\t%1, %0\t@ unaligned
4038 str%?\t%1, %0\t@ unaligned
4039 str%?\t%1, %0\t@ unaligned"
4040 [(set_attr "arch" "t1,t2,32")
4041 (set_attr "length" "2,2,4")
4042 (set_attr "predicable" "no,yes,yes")
4043 (set_attr "predicable_short_it" "no,yes,no")
9f2c2a36 4044 (set_attr "type" "store_4")])
eb04cafb 4045
4046(define_insn "unaligned_storehi"
70ce330a 4047 [(set (match_operand:HI 0 "memory_operand" "=m,Uw,m")
4048 (unspec:HI [(match_operand:HI 1 "s_register_operand" "l,l,r")]
eb04cafb 4049 UNSPEC_UNALIGNED_STORE))]
8fe38eb2 4050 "unaligned_access"
70ce330a 4051 "@
4052 strh\t%1, %0\t@ unaligned
4053 strh%?\t%1, %0\t@ unaligned
4054 strh%?\t%1, %0\t@ unaligned"
4055 [(set_attr "arch" "t1,t2,32")
4056 (set_attr "length" "2,2,4")
4057 (set_attr "predicable" "no,yes,yes")
4058 (set_attr "predicable_short_it" "no,yes,no")
9f2c2a36 4059 (set_attr "type" "store_4")])
eb04cafb 4060
ae51a965 4061
eb04cafb 4062(define_insn "*extv_reg"
8b054d5a 4063 [(set (match_operand:SI 0 "s_register_operand" "=r")
4064 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
13051f13 4065 (match_operand:SI 2 "const_int_operand" "n")
4066 (match_operand:SI 3 "const_int_operand" "n")))]
4067 "arm_arch_thumb2
4068 && IN_RANGE (INTVAL (operands[3]), 0, 31)
4069 && IN_RANGE (INTVAL (operands[2]), 1, 32 - INTVAL (operands[3]))"
8b054d5a 4070 "sbfx%?\t%0, %1, %3, %2"
4071 [(set_attr "length" "4")
d952d547 4072 (set_attr "predicable" "yes")
d82e788e 4073 (set_attr "type" "bfm")]
8b054d5a 4074)
4075
4076(define_insn "extzv_t2"
4077 [(set (match_operand:SI 0 "s_register_operand" "=r")
4078 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "r")
13051f13 4079 (match_operand:SI 2 "const_int_operand" "n")
4080 (match_operand:SI 3 "const_int_operand" "n")))]
4081 "arm_arch_thumb2
4082 && IN_RANGE (INTVAL (operands[3]), 0, 31)
4083 && IN_RANGE (INTVAL (operands[2]), 1, 32 - INTVAL (operands[3]))"
8b054d5a 4084 "ubfx%?\t%0, %1, %3, %2"
4085 [(set_attr "length" "4")
d952d547 4086 (set_attr "predicable" "yes")
d82e788e 4087 (set_attr "type" "bfm")]
8b054d5a 4088)
4089
7d3cda8c 4090
4091;; Division instructions
4092(define_insn "divsi3"
8f5f2788 4093 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4094 (div:SI (match_operand:SI 1 "s_register_operand" "r,r")
4095 (match_operand:SI 2 "s_register_operand" "r,r")))]
7d3cda8c 4096 "TARGET_IDIV"
8f5f2788 4097 "@
4098 sdiv%?\t%0, %1, %2
4099 sdiv\t%0, %1, %2"
4100 [(set_attr "arch" "32,v8mb")
4101 (set_attr "predicable" "yes")
9da0ec36 4102 (set_attr "type" "sdiv")]
7d3cda8c 4103)
4104
4105(define_insn "udivsi3"
8f5f2788 4106 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4107 (udiv:SI (match_operand:SI 1 "s_register_operand" "r,r")
4108 (match_operand:SI 2 "s_register_operand" "r,r")))]
7d3cda8c 4109 "TARGET_IDIV"
8f5f2788 4110 "@
4111 udiv%?\t%0, %1, %2
4112 udiv\t%0, %1, %2"
4113 [(set_attr "arch" "32,v8mb")
4114 (set_attr "predicable" "yes")
9da0ec36 4115 (set_attr "type" "udiv")]
7d3cda8c 4116)
4117
b11cae9e 4118\f
4119;; Unary arithmetic insns
4120
f6c98a9a 4121(define_expand "negvsi3"
4122 [(match_operand:SI 0 "register_operand")
4123 (match_operand:SI 1 "register_operand")
4124 (match_operand 2 "")]
4125 "TARGET_32BIT"
4126{
4127 emit_insn (gen_subsi3_compare (operands[0], const0_rtx, operands[1]));
4128 arm_gen_unlikely_cbranch (NE, CC_Vmode, operands[2]);
4129
4130 DONE;
4131})
4132
4133(define_expand "negvdi3"
e62551fd 4134 [(match_operand:DI 0 "s_register_operand")
4135 (match_operand:DI 1 "s_register_operand")
f6c98a9a 4136 (match_operand 2 "")]
4137 "TARGET_ARM"
4138{
4139 emit_insn (gen_negdi2_compare (operands[0], operands[1]));
4140 arm_gen_unlikely_cbranch (NE, CC_Vmode, operands[2]);
4141
4142 DONE;
4143})
4144
4145
e62551fd 4146(define_insn "negdi2_compare"
f6c98a9a 4147 [(set (reg:CC CC_REGNUM)
4148 (compare:CC
4149 (const_int 0)
e62551fd 4150 (match_operand:DI 1 "register_operand" "r,r")))
4151 (set (match_operand:DI 0 "register_operand" "=&r,&r")
f6c98a9a 4152 (minus:DI (const_int 0) (match_dup 1)))]
4153 "TARGET_ARM"
e62551fd 4154 "@
4155 rsbs\\t%Q0, %Q1, #0;rscs\\t%R0, %R1, #0
4156 rsbs\\t%Q0, %Q1, #0;sbcs\\t%R0, %R1, %R1, lsl #1"
f6c98a9a 4157 [(set_attr "conds" "set")
e62551fd 4158 (set_attr "arch" "a,t2")
f6c98a9a 4159 (set_attr "length" "8")
4160 (set_attr "type" "multiple")]
4161)
4162
cffb2a26 4163(define_expand "negsi2"
3934ae0e 4164 [(set (match_operand:SI 0 "s_register_operand")
4165 (neg:SI (match_operand:SI 1 "s_register_operand")))]
cffb2a26 4166 "TARGET_EITHER"
b11cae9e 4167 ""
cffb2a26 4168)
4169
4170(define_insn "*arm_negsi2"
d952d547 4171 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4172 (neg:SI (match_operand:SI 1 "s_register_operand" "l,r")))]
25f905c2 4173 "TARGET_32BIT"
cffb2a26 4174 "rsb%?\\t%0, %1, #0"
d952d547 4175 [(set_attr "predicable" "yes")
4176 (set_attr "predicable_short_it" "yes,no")
4177 (set_attr "arch" "t2,*")
1b7da4ac 4178 (set_attr "length" "4")
7724f74b 4179 (set_attr "type" "alu_imm")]
4180)
4181
4182;; To keep the comparison in canonical form we express it as (~reg cmp ~0)
4183;; rather than (0 cmp reg). This gives the same results for unsigned
4184;; and equality compares which is what we mostly need here.
4185(define_insn "negsi2_0compare"
4186 [(set (reg:CC_RSB CC_REGNUM)
4187 (compare:CC_RSB (not:SI (match_operand:SI 1 "s_register_operand" "l,r"))
4188 (const_int -1)))
4189 (set (match_operand:SI 0 "s_register_operand" "=l,r")
4190 (neg:SI (match_dup 1)))]
4191 "TARGET_32BIT"
4192 "@
4193 negs\\t%0, %1
4194 rsbs\\t%0, %1, #0"
4195 [(set_attr "conds" "set")
4196 (set_attr "arch" "t2,*")
4197 (set_attr "length" "2,*")
4198 (set_attr "type" "alus_imm")]
4199)
4200
4201(define_insn "negsi2_carryin"
4202 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4203 (minus:SI (neg:SI (match_operand:SI 1 "s_register_operand" "r,r"))
4204 (match_operand:SI 2 "arm_borrow_operation" "")))]
4205 "TARGET_32BIT"
4206 "@
4207 rsc\\t%0, %1, #0
4208 sbc\\t%0, %1, %1, lsl #1"
4209 [(set_attr "conds" "use")
4210 (set_attr "arch" "a,t2")
4211 (set_attr "type" "adc_imm,adc_reg")]
cffb2a26 4212)
4213
604f3a0a 4214(define_expand "negsf2"
3934ae0e 4215 [(set (match_operand:SF 0 "s_register_operand")
4216 (neg:SF (match_operand:SF 1 "s_register_operand")))]
d7216193 4217 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 4218 ""
4219)
4220
4221(define_expand "negdf2"
3934ae0e 4222 [(set (match_operand:DF 0 "s_register_operand")
4223 (neg:DF (match_operand:DF 1 "s_register_operand")))]
994606f8 4224 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
604f3a0a 4225 "")
4226
9c08d1fa 4227;; abssi2 doesn't really clobber the condition codes if a different register
4228;; is being set. To keep things simple, assume during rtl manipulations that
4229;; it does, but tell the final scan operator the truth. Similarly for
4230;; (neg (abs...))
4231
604f3a0a 4232(define_expand "abssi2"
4233 [(parallel
3934ae0e 4234 [(set (match_operand:SI 0 "s_register_operand")
4235 (abs:SI (match_operand:SI 1 "s_register_operand")))
ba156559 4236 (clobber (match_dup 2))])]
4237 "TARGET_EITHER"
4238 "
25f905c2 4239 if (TARGET_THUMB1)
ba156559 4240 operands[2] = gen_rtx_SCRATCH (SImode);
4241 else
4242 operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
4243")
604f3a0a 4244
ba6a3b2f 4245(define_insn_and_split "*arm_abssi2"
ba156559 4246 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
9c08d1fa 4247 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
bd5b4116 4248 (clobber (reg:CC CC_REGNUM))]
cffb2a26 4249 "TARGET_ARM"
ba6a3b2f 4250 "#"
4251 "&& reload_completed"
4252 [(const_int 0)]
4253 {
4254 /* if (which_alternative == 0) */
4255 if (REGNO(operands[0]) == REGNO(operands[1]))
4256 {
4257 /* Emit the pattern:
4258 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
4259 [(set (reg:CC CC_REGNUM)
4260 (compare:CC (match_dup 0) (const_int 0)))
4261 (cond_exec (lt:CC (reg:CC CC_REGNUM) (const_int 0))
4262 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 1))))]
4263 */
d1f9b275 4264 emit_insn (gen_rtx_SET (gen_rtx_REG (CCmode, CC_REGNUM),
ba6a3b2f 4265 gen_rtx_COMPARE (CCmode, operands[0], const0_rtx)));
4266 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
4267 (gen_rtx_LT (SImode,
4268 gen_rtx_REG (CCmode, CC_REGNUM),
4269 const0_rtx)),
d1f9b275 4270 (gen_rtx_SET (operands[0],
ba6a3b2f 4271 (gen_rtx_MINUS (SImode,
4272 const0_rtx,
4273 operands[1]))))));
4274 DONE;
4275 }
4276 else
4277 {
4278 /* Emit the pattern:
4279 alt1: eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31
4280 [(set (match_dup 0)
4281 (xor:SI (match_dup 1)
4282 (ashiftrt:SI (match_dup 1) (const_int 31))))
4283 (set (match_dup 0)
4284 (minus:SI (match_dup 0)
4285 (ashiftrt:SI (match_dup 1) (const_int 31))))]
4286 */
d1f9b275 4287 emit_insn (gen_rtx_SET (operands[0],
ba6a3b2f 4288 gen_rtx_XOR (SImode,
4289 gen_rtx_ASHIFTRT (SImode,
4290 operands[1],
4291 GEN_INT (31)),
4292 operands[1])));
d1f9b275 4293 emit_insn (gen_rtx_SET (operands[0],
ba6a3b2f 4294 gen_rtx_MINUS (SImode,
4295 operands[0],
4296 gen_rtx_ASHIFTRT (SImode,
4297 operands[1],
4298 GEN_INT (31)))));
4299 DONE;
4300 }
4301 }
cffb2a26 4302 [(set_attr "conds" "clob,*")
331beb1a 4303 (set_attr "shift" "1")
2ad08b65 4304 (set_attr "predicable" "no, yes")
1b7da4ac 4305 (set_attr "length" "8")
4306 (set_attr "type" "multiple")]
cffb2a26 4307)
9c08d1fa 4308
ba6a3b2f 4309(define_insn_and_split "*arm_neg_abssi2"
9c08d1fa 4310 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
4311 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
bd5b4116 4312 (clobber (reg:CC CC_REGNUM))]
cffb2a26 4313 "TARGET_ARM"
ba6a3b2f 4314 "#"
4315 "&& reload_completed"
4316 [(const_int 0)]
4317 {
4318 /* if (which_alternative == 0) */
4319 if (REGNO (operands[0]) == REGNO (operands[1]))
4320 {
4321 /* Emit the pattern:
4322 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
4323 */
d1f9b275 4324 emit_insn (gen_rtx_SET (gen_rtx_REG (CCmode, CC_REGNUM),
ba6a3b2f 4325 gen_rtx_COMPARE (CCmode, operands[0], const0_rtx)));
4326 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
4327 gen_rtx_GT (SImode,
4328 gen_rtx_REG (CCmode, CC_REGNUM),
4329 const0_rtx),
d1f9b275 4330 gen_rtx_SET (operands[0],
ba6a3b2f 4331 (gen_rtx_MINUS (SImode,
4332 const0_rtx,
4333 operands[1])))));
4334 }
4335 else
4336 {
4337 /* Emit the pattern:
4338 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31
4339 */
d1f9b275 4340 emit_insn (gen_rtx_SET (operands[0],
ba6a3b2f 4341 gen_rtx_XOR (SImode,
4342 gen_rtx_ASHIFTRT (SImode,
4343 operands[1],
4344 GEN_INT (31)),
4345 operands[1])));
d1f9b275 4346 emit_insn (gen_rtx_SET (operands[0],
ba6a3b2f 4347 gen_rtx_MINUS (SImode,
4348 gen_rtx_ASHIFTRT (SImode,
4349 operands[1],
4350 GEN_INT (31)),
4351 operands[0])));
4352 }
4353 DONE;
4354 }
cffb2a26 4355 [(set_attr "conds" "clob,*")
331beb1a 4356 (set_attr "shift" "1")
2ad08b65 4357 (set_attr "predicable" "no, yes")
1b7da4ac 4358 (set_attr "length" "8")
4359 (set_attr "type" "multiple")]
cffb2a26 4360)
b11cae9e 4361
604f3a0a 4362(define_expand "abssf2"
3934ae0e 4363 [(set (match_operand:SF 0 "s_register_operand")
4364 (abs:SF (match_operand:SF 1 "s_register_operand")))]
25f905c2 4365 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 4366 "")
4367
604f3a0a 4368(define_expand "absdf2"
3934ae0e 4369 [(set (match_operand:DF 0 "s_register_operand")
4370 (abs:DF (match_operand:DF 1 "s_register_operand")))]
a50d7267 4371 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 4372 "")
4373
7db9af5d 4374(define_expand "sqrtsf2"
3934ae0e 4375 [(set (match_operand:SF 0 "s_register_operand")
4376 (sqrt:SF (match_operand:SF 1 "s_register_operand")))]
d7216193 4377 "TARGET_32BIT && TARGET_HARD_FLOAT"
7db9af5d 4378 "")
9c08d1fa 4379
7db9af5d 4380(define_expand "sqrtdf2"
3934ae0e 4381 [(set (match_operand:DF 0 "s_register_operand")
4382 (sqrt:DF (match_operand:DF 1 "s_register_operand")))]
994606f8 4383 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
7db9af5d 4384 "")
9c08d1fa 4385
cffb2a26 4386(define_expand "one_cmplsi2"
3934ae0e 4387 [(set (match_operand:SI 0 "s_register_operand")
4388 (not:SI (match_operand:SI 1 "s_register_operand")))]
cffb2a26 4389 "TARGET_EITHER"
b11cae9e 4390 ""
cffb2a26 4391)
4392
4393(define_insn "*arm_one_cmplsi2"
d952d547 4394 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4395 (not:SI (match_operand:SI 1 "s_register_operand" "l,r")))]
25f905c2 4396 "TARGET_32BIT"
cffb2a26 4397 "mvn%?\\t%0, %1"
d2a518d1 4398 [(set_attr "predicable" "yes")
d952d547 4399 (set_attr "predicable_short_it" "yes,no")
4400 (set_attr "arch" "t2,*")
4401 (set_attr "length" "4")
1aed5204 4402 (set_attr "type" "mvn_reg")]
cffb2a26 4403)
4404
f7fbdd4a 4405(define_insn "*notsi_compare0"
bd5b4116 4406 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 4407 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
4408 (const_int 0)))
4409 (set (match_operand:SI 0 "s_register_operand" "=r")
4410 (not:SI (match_dup 1)))]
25f905c2 4411 "TARGET_32BIT"
3ef90e77 4412 "mvns%?\\t%0, %1"
d2a518d1 4413 [(set_attr "conds" "set")
1aed5204 4414 (set_attr "type" "mvn_reg")]
cffb2a26 4415)
9c08d1fa 4416
f7fbdd4a 4417(define_insn "*notsi_compare0_scratch"
bd5b4116 4418 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 4419 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
4420 (const_int 0)))
4421 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 4422 "TARGET_32BIT"
3ef90e77 4423 "mvns%?\\t%0, %1"
d2a518d1 4424 [(set_attr "conds" "set")
1aed5204 4425 (set_attr "type" "mvn_reg")]
cffb2a26 4426)
b11cae9e 4427\f
4428;; Fixed <--> Floating conversion insns
4429
9b8516be 4430(define_expand "floatsihf2"
3934ae0e 4431 [(set (match_operand:HF 0 "general_operand")
4432 (float:HF (match_operand:SI 1 "general_operand")))]
9b8516be 4433 "TARGET_EITHER"
4434 "
4435 {
4436 rtx op1 = gen_reg_rtx (SFmode);
4437 expand_float (op1, operands[1], 0);
4438 op1 = convert_to_mode (HFmode, op1, 0);
4439 emit_move_insn (operands[0], op1);
4440 DONE;
4441 }"
4442)
4443
4444(define_expand "floatdihf2"
3934ae0e 4445 [(set (match_operand:HF 0 "general_operand")
4446 (float:HF (match_operand:DI 1 "general_operand")))]
9b8516be 4447 "TARGET_EITHER"
4448 "
4449 {
4450 rtx op1 = gen_reg_rtx (SFmode);
4451 expand_float (op1, operands[1], 0);
4452 op1 = convert_to_mode (HFmode, op1, 0);
4453 emit_move_insn (operands[0], op1);
4454 DONE;
4455 }"
4456)
4457
604f3a0a 4458(define_expand "floatsisf2"
3934ae0e 4459 [(set (match_operand:SF 0 "s_register_operand")
4460 (float:SF (match_operand:SI 1 "s_register_operand")))]
25f905c2 4461 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 4462 "
604f3a0a 4463")
4464
604f3a0a 4465(define_expand "floatsidf2"
3934ae0e 4466 [(set (match_operand:DF 0 "s_register_operand")
4467 (float:DF (match_operand:SI 1 "s_register_operand")))]
a50d7267 4468 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 4469 "
604f3a0a 4470")
4471
9b8516be 4472(define_expand "fix_trunchfsi2"
3934ae0e 4473 [(set (match_operand:SI 0 "general_operand")
4474 (fix:SI (fix:HF (match_operand:HF 1 "general_operand"))))]
9b8516be 4475 "TARGET_EITHER"
4476 "
4477 {
4478 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
4479 expand_fix (operands[0], op1, 0);
4480 DONE;
4481 }"
4482)
4483
4484(define_expand "fix_trunchfdi2"
3934ae0e 4485 [(set (match_operand:DI 0 "general_operand")
4486 (fix:DI (fix:HF (match_operand:HF 1 "general_operand"))))]
9b8516be 4487 "TARGET_EITHER"
4488 "
4489 {
4490 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
4491 expand_fix (operands[0], op1, 0);
4492 DONE;
4493 }"
4494)
4495
604f3a0a 4496(define_expand "fix_truncsfsi2"
3934ae0e 4497 [(set (match_operand:SI 0 "s_register_operand")
4498 (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand"))))]
25f905c2 4499 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 4500 "
604f3a0a 4501")
4502
604f3a0a 4503(define_expand "fix_truncdfsi2"
3934ae0e 4504 [(set (match_operand:SI 0 "s_register_operand")
4505 (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand"))))]
a50d7267 4506 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 4507 "
604f3a0a 4508")
4509
f544c6d2 4510;; Truncation insns
b11cae9e 4511
604f3a0a 4512(define_expand "truncdfsf2"
3934ae0e 4513 [(set (match_operand:SF 0 "s_register_operand")
604f3a0a 4514 (float_truncate:SF
3934ae0e 4515 (match_operand:DF 1 "s_register_operand")))]
a50d7267 4516 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 4517 ""
4518)
9b8516be 4519
539b44ee 4520;; DFmode to HFmode conversions on targets without a single-step hardware
4521;; instruction for it would have to go through SFmode. This is dangerous
4522;; as it introduces double rounding.
4523;;
4524;; Disable this pattern unless we are in an unsafe math mode, or we have
4525;; a single-step instruction.
4526
9b8516be 4527(define_expand "truncdfhf2"
3934ae0e 4528 [(set (match_operand:HF 0 "s_register_operand")
9b8516be 4529 (float_truncate:HF
3934ae0e 4530 (match_operand:DF 1 "s_register_operand")))]
539b44ee 4531 "(TARGET_EITHER && flag_unsafe_math_optimizations)
4532 || (TARGET_32BIT && TARGET_FP16_TO_DOUBLE)"
4533{
4534 /* We don't have a direct instruction for this, so we must be in
4535 an unsafe math mode, and going via SFmode. */
4536
4537 if (!(TARGET_32BIT && TARGET_FP16_TO_DOUBLE))
4538 {
4539 rtx op1;
4540 op1 = convert_to_mode (SFmode, operands[1], 0);
4541 op1 = convert_to_mode (HFmode, op1, 0);
4542 emit_move_insn (operands[0], op1);
4543 DONE;
4544 }
4545 /* Otherwise, we will pick this up as a single instruction with
4546 no intermediary rounding. */
4547}
9b8516be 4548)
b11cae9e 4549\f
9c08d1fa 4550;; Zero and sign extension instructions.
b11cae9e 4551
2e55c7de 4552(define_expand "zero_extend<mode>di2"
4553 [(set (match_operand:DI 0 "s_register_operand" "")
4554 (zero_extend:DI (match_operand:QHSI 1 "<qhs_zextenddi_op>" "")))]
848e66ac 4555 "TARGET_32BIT <qhs_zextenddi_cond>"
2e55c7de 4556 {
4557 rtx res_lo, res_hi, op0_lo, op0_hi;
4558 res_lo = gen_lowpart (SImode, operands[0]);
4559 res_hi = gen_highpart (SImode, operands[0]);
4560 if (can_create_pseudo_p ())
4561 {
4562 op0_lo = <MODE>mode == SImode ? operands[1] : gen_reg_rtx (SImode);
4563 op0_hi = gen_reg_rtx (SImode);
4564 }
4565 else
4566 {
4567 op0_lo = <MODE>mode == SImode ? operands[1] : res_lo;
4568 op0_hi = res_hi;
4569 }
4570 if (<MODE>mode != SImode)
4571 emit_insn (gen_rtx_SET (op0_lo,
4572 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
4573 emit_insn (gen_movsi (op0_hi, const0_rtx));
4574 if (res_lo != op0_lo)
4575 emit_move_insn (res_lo, op0_lo);
4576 if (res_hi != op0_hi)
4577 emit_move_insn (res_hi, op0_hi);
4578 DONE;
4579 }
25f905c2 4580)
4581
2e55c7de 4582(define_expand "extend<mode>di2"
4583 [(set (match_operand:DI 0 "s_register_operand" "")
4584 (sign_extend:DI (match_operand:QHSI 1 "<qhs_extenddi_op>" "")))]
848e66ac 4585 "TARGET_32BIT <qhs_sextenddi_cond>"
2e55c7de 4586 {
4587 rtx res_lo, res_hi, op0_lo, op0_hi;
4588 res_lo = gen_lowpart (SImode, operands[0]);
4589 res_hi = gen_highpart (SImode, operands[0]);
4590 if (can_create_pseudo_p ())
4591 {
4592 op0_lo = <MODE>mode == SImode ? operands[1] : gen_reg_rtx (SImode);
4593 op0_hi = gen_reg_rtx (SImode);
4594 }
4595 else
4596 {
4597 op0_lo = <MODE>mode == SImode ? operands[1] : res_lo;
4598 op0_hi = res_hi;
4599 }
4600 if (<MODE>mode != SImode)
4601 emit_insn (gen_rtx_SET (op0_lo,
4602 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
4603 emit_insn (gen_ashrsi3 (op0_hi, op0_lo, GEN_INT (31)));
4604 if (res_lo != op0_lo)
4605 emit_move_insn (res_lo, op0_lo);
4606 if (res_hi != op0_hi)
4607 emit_move_insn (res_hi, op0_hi);
4608 DONE;
4609 }
0d66636f 4610)
9c08d1fa 4611
848e66ac 4612;; Splits for all extensions to DImode
4613(define_split
4614 [(set (match_operand:DI 0 "s_register_operand" "")
4615 (zero_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
def2e672 4616 "TARGET_32BIT"
848e66ac 4617 [(set (match_dup 0) (match_dup 1))]
4618{
848e66ac 4619 rtx lo_part = gen_lowpart (SImode, operands[0]);
3754d046 4620 machine_mode src_mode = GET_MODE (operands[1]);
848e66ac 4621
def2e672 4622 if (src_mode == SImode)
4623 emit_move_insn (lo_part, operands[1]);
4624 else
4625 emit_insn (gen_rtx_SET (lo_part,
4626 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
848e66ac 4627 operands[0] = gen_highpart (SImode, operands[0]);
4628 operands[1] = const0_rtx;
4629})
9c08d1fa 4630
848e66ac 4631(define_split
25f905c2 4632 [(set (match_operand:DI 0 "s_register_operand" "")
848e66ac 4633 (sign_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
def2e672 4634 "TARGET_32BIT"
848e66ac 4635 [(set (match_dup 0) (ashiftrt:SI (match_dup 1) (const_int 31)))]
4636{
4637 rtx lo_part = gen_lowpart (SImode, operands[0]);
3754d046 4638 machine_mode src_mode = GET_MODE (operands[1]);
25f905c2 4639
def2e672 4640 if (src_mode == SImode)
4641 emit_move_insn (lo_part, operands[1]);
4642 else
4643 emit_insn (gen_rtx_SET (lo_part,
4644 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
4645 operands[1] = lo_part;
848e66ac 4646 operands[0] = gen_highpart (SImode, operands[0]);
4647})
9c08d1fa 4648
4649(define_expand "zero_extendhisi2"
3934ae0e 4650 [(set (match_operand:SI 0 "s_register_operand")
4651 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand")))]
cffb2a26 4652 "TARGET_EITHER"
ef51b8e1 4653{
4654 if (TARGET_ARM && !arm_arch4 && MEM_P (operands[1]))
f7fbdd4a 4655 {
ef51b8e1 4656 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
4657 DONE;
25f7a26e 4658 }
ef51b8e1 4659 if (!arm_arch6 && !MEM_P (operands[1]))
4660 {
4661 rtx t = gen_lowpart (SImode, operands[1]);
4662 rtx tmp = gen_reg_rtx (SImode);
4663 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
4664 emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (16)));
4665 DONE;
4666 }
4667})
9c08d1fa 4668
ef51b8e1 4669(define_split
b146458f 4670 [(set (match_operand:SI 0 "s_register_operand" "")
4671 (zero_extend:SI (match_operand:HI 1 "s_register_operand" "")))]
ef51b8e1 4672 "!TARGET_THUMB2 && !arm_arch6"
4673 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4674 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 16)))]
4675{
4676 operands[2] = gen_lowpart (SImode, operands[1]);
4677})
4678
cffb2a26 4679(define_insn "*arm_zero_extendhisi2"
ef51b8e1 4680 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4681 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 4682 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 4683 "@
4684 #
3ef90e77 4685 ldrh%?\\t%0, %1"
d82e788e 4686 [(set_attr "type" "alu_shift_reg,load_byte")
848e66ac 4687 (set_attr "predicable" "yes")]
cffb2a26 4688)
f7fbdd4a 4689
a2cd141b 4690(define_insn "*arm_zero_extendhisi2_v6"
4691 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
e3f4ccee 4692 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,Uh")))]
a2cd141b 4693 "TARGET_ARM && arm_arch6"
4694 "@
4695 uxth%?\\t%0, %1
3ef90e77 4696 ldrh%?\\t%0, %1"
65f68e55 4697 [(set_attr "predicable" "yes")
6b6abc9c 4698 (set_attr "type" "extend,load_byte")]
a2cd141b 4699)
4700
4701(define_insn "*arm_zero_extendhisi2addsi"
4702 [(set (match_operand:SI 0 "s_register_operand" "=r")
4703 (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
4704 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4705 "TARGET_INT_SIMD"
a2cd141b 4706 "uxtah%?\\t%0, %2, %1"
d82e788e 4707 [(set_attr "type" "alu_shift_reg")
8bdfd6ed 4708 (set_attr "predicable" "yes")]
a2cd141b 4709)
4710
87b22bf7 4711(define_expand "zero_extendqisi2"
3934ae0e 4712 [(set (match_operand:SI 0 "s_register_operand")
4713 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand")))]
cffb2a26 4714 "TARGET_EITHER"
ef51b8e1 4715{
0438d37f 4716 if (TARGET_ARM && !arm_arch6 && !MEM_P (operands[1]))
87b22bf7 4717 {
ef51b8e1 4718 emit_insn (gen_andsi3 (operands[0],
4719 gen_lowpart (SImode, operands[1]),
4720 GEN_INT (255)));
4721 DONE;
4722 }
4723 if (!arm_arch6 && !MEM_P (operands[1]))
4724 {
4725 rtx t = gen_lowpart (SImode, operands[1]);
4726 rtx tmp = gen_reg_rtx (SImode);
4727 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
4728 emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (24)));
4729 DONE;
4730 }
4731})
cffb2a26 4732
ef51b8e1 4733(define_split
b146458f 4734 [(set (match_operand:SI 0 "s_register_operand" "")
4735 (zero_extend:SI (match_operand:QI 1 "s_register_operand" "")))]
ef51b8e1 4736 "!arm_arch6"
4737 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
4738 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 24)))]
4739{
4740 operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
4741 if (TARGET_ARM)
4742 {
4743 emit_insn (gen_andsi3 (operands[0], operands[2], GEN_INT (255)));
87b22bf7 4744 DONE;
4745 }
ef51b8e1 4746})
9c08d1fa 4747
cffb2a26 4748(define_insn "*arm_zero_extendqisi2"
ef51b8e1 4749 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4750 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 4751 "TARGET_ARM && !arm_arch6"
ef51b8e1 4752 "@
4753 #
3ef90e77 4754 ldrb%?\\t%0, %1\\t%@ zero_extendqisi2"
ef51b8e1 4755 [(set_attr "length" "8,4")
d82e788e 4756 (set_attr "type" "alu_shift_reg,load_byte")
848e66ac 4757 (set_attr "predicable" "yes")]
cffb2a26 4758)
87b22bf7 4759
a2cd141b 4760(define_insn "*arm_zero_extendqisi2_v6"
4761 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
e3f4ccee 4762 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,Uh")))]
a2cd141b 4763 "TARGET_ARM && arm_arch6"
4764 "@
3ef90e77 4765 uxtb%?\\t%0, %1
4766 ldrb%?\\t%0, %1\\t%@ zero_extendqisi2"
6b6abc9c 4767 [(set_attr "type" "extend,load_byte")
848e66ac 4768 (set_attr "predicable" "yes")]
a2cd141b 4769)
4770
4771(define_insn "*arm_zero_extendqisi2addsi"
4772 [(set (match_operand:SI 0 "s_register_operand" "=r")
4773 (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
4774 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4775 "TARGET_INT_SIMD"
a2cd141b 4776 "uxtab%?\\t%0, %2, %1"
4777 [(set_attr "predicable" "yes")
d82e788e 4778 (set_attr "type" "alu_shift_reg")]
a2cd141b 4779)
4780
87b22bf7 4781(define_split
4782 [(set (match_operand:SI 0 "s_register_operand" "")
4783 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
4784 (clobber (match_operand:SI 2 "s_register_operand" ""))]
0438d37f 4785 "TARGET_32BIT && (!MEM_P (operands[1])) && ! BYTES_BIG_ENDIAN"
87b22bf7 4786 [(set (match_dup 2) (match_dup 1))
4787 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
cffb2a26 4788 ""
4789)
9c08d1fa 4790
8a4d25d6 4791(define_split
4792 [(set (match_operand:SI 0 "s_register_operand" "")
4793 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 3)))
4794 (clobber (match_operand:SI 2 "s_register_operand" ""))]
0438d37f 4795 "TARGET_32BIT && (!MEM_P (operands[1])) && BYTES_BIG_ENDIAN"
8a4d25d6 4796 [(set (match_dup 2) (match_dup 1))
4797 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
4798 ""
4799)
4800
1c274529 4801
4802(define_split
4803 [(set (match_operand:SI 0 "s_register_operand" "")
9b23f0a7 4804 (IOR_XOR:SI (and:SI (ashift:SI
1c274529 4805 (match_operand:SI 1 "s_register_operand" "")
4806 (match_operand:SI 2 "const_int_operand" ""))
4807 (match_operand:SI 3 "const_int_operand" ""))
4808 (zero_extend:SI
4809 (match_operator 5 "subreg_lowpart_operator"
4810 [(match_operand:SI 4 "s_register_operand" "")]))))]
4811 "TARGET_32BIT
8c4e8755 4812 && (UINTVAL (operands[3])
1c274529 4813 == (GET_MODE_MASK (GET_MODE (operands[5]))
4814 & (GET_MODE_MASK (GET_MODE (operands[5]))
4815 << (INTVAL (operands[2])))))"
9b23f0a7 4816 [(set (match_dup 0) (IOR_XOR:SI (ashift:SI (match_dup 1) (match_dup 2))
1c274529 4817 (match_dup 4)))
4818 (set (match_dup 0) (zero_extend:SI (match_dup 5)))]
4819 "operands[5] = gen_lowpart (GET_MODE (operands[5]), operands[0]);"
4820)
4821
f7fbdd4a 4822(define_insn "*compareqi_eq0"
bd5b4116 4823 [(set (reg:CC_Z CC_REGNUM)
206ee9a2 4824 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
87b22bf7 4825 (const_int 0)))]
25f905c2 4826 "TARGET_32BIT"
596e5e8f 4827 "tst%?\\t%0, #255"
4828 [(set_attr "conds" "set")
d952d547 4829 (set_attr "predicable" "yes")
1b7da4ac 4830 (set_attr "type" "logic_imm")]
cffb2a26 4831)
b11cae9e 4832
b11cae9e 4833(define_expand "extendhisi2"
3934ae0e 4834 [(set (match_operand:SI 0 "s_register_operand")
4835 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand")))]
cffb2a26 4836 "TARGET_EITHER"
ef51b8e1 4837{
4838 if (TARGET_THUMB1)
4839 {
4840 emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1]));
4841 DONE;
4842 }
4843 if (MEM_P (operands[1]) && TARGET_ARM && !arm_arch4)
4844 {
4845 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
4846 DONE;
4847 }
ed29c566 4848
ef51b8e1 4849 if (!arm_arch6 && !MEM_P (operands[1]))
4850 {
4851 rtx t = gen_lowpart (SImode, operands[1]);
4852 rtx tmp = gen_reg_rtx (SImode);
4853 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
4854 emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (16)));
4855 DONE;
4856 }
4857})
cffb2a26 4858
ef51b8e1 4859(define_split
4860 [(parallel
4861 [(set (match_operand:SI 0 "register_operand" "")
4862 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))
4863 (clobber (match_scratch:SI 2 ""))])]
4864 "!arm_arch6"
4865 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4866 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
4867{
4868 operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
4869})
25f7a26e 4870
25f905c2 4871;; This pattern will only be used when ldsh is not available
25f7a26e 4872(define_expand "extendhisi2_mem"
eab14235 4873 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 4874 (set (match_dup 3)
eab14235 4875 (zero_extend:SI (match_dup 7)))
25f7a26e 4876 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
4877 (set (match_operand:SI 0 "" "")
4878 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
cffb2a26 4879 "TARGET_ARM"
25f7a26e 4880 "
215b30b3 4881 {
4882 rtx mem1, mem2;
4883 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4884
788fcce0 4885 mem1 = change_address (operands[1], QImode, addr);
29c05e22 4886 mem2 = change_address (operands[1], QImode,
4887 plus_constant (Pmode, addr, 1));
215b30b3 4888 operands[0] = gen_lowpart (SImode, operands[0]);
4889 operands[1] = mem1;
4890 operands[2] = gen_reg_rtx (SImode);
4891 operands[3] = gen_reg_rtx (SImode);
4892 operands[6] = gen_reg_rtx (SImode);
4893 operands[7] = mem2;
25f7a26e 4894
215b30b3 4895 if (BYTES_BIG_ENDIAN)
4896 {
4897 operands[4] = operands[2];
4898 operands[5] = operands[3];
4899 }
4900 else
4901 {
4902 operands[4] = operands[3];
4903 operands[5] = operands[2];
4904 }
4905 }"
4906)
b11cae9e 4907
ef51b8e1 4908(define_split
4909 [(set (match_operand:SI 0 "register_operand" "")
4910 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
4911 "!arm_arch6"
4912 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4913 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
4914{
4915 operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
4916})
4917
a2cd141b 4918(define_insn "*arm_extendhisi2"
ef51b8e1 4919 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
e3f4ccee 4920 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,Uh")))]
a2cd141b 4921 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 4922 "@
4923 #
3ef90e77 4924 ldrsh%?\\t%0, %1"
ef51b8e1 4925 [(set_attr "length" "8,4")
d82e788e 4926 (set_attr "type" "alu_shift_reg,load_byte")
e3f4ccee 4927 (set_attr "predicable" "yes")]
cffb2a26 4928)
f7fbdd4a 4929
25f905c2 4930;; ??? Check Thumb-2 pool range
a2cd141b 4931(define_insn "*arm_extendhisi2_v6"
4932 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
e3f4ccee 4933 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,Uh")))]
25f905c2 4934 "TARGET_32BIT && arm_arch6"
a2cd141b 4935 "@
4936 sxth%?\\t%0, %1
3ef90e77 4937 ldrsh%?\\t%0, %1"
6b6abc9c 4938 [(set_attr "type" "extend,load_byte")
8bdfd6ed 4939 (set_attr "predicable" "yes")]
a2cd141b 4940)
4941
4942(define_insn "*arm_extendhisi2addsi"
4943 [(set (match_operand:SI 0 "s_register_operand" "=r")
4944 (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
4945 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4946 "TARGET_INT_SIMD"
a2cd141b 4947 "sxtah%?\\t%0, %2, %1"
1b7da4ac 4948 [(set_attr "type" "alu_shift_reg")]
a2cd141b 4949)
4950
c8f69309 4951(define_expand "extendqihi2"
4952 [(set (match_dup 2)
3934ae0e 4953 (ashift:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op")
c8f69309 4954 (const_int 24)))
3934ae0e 4955 (set (match_operand:HI 0 "s_register_operand")
c8f69309 4956 (ashiftrt:SI (match_dup 2)
4957 (const_int 24)))]
cffb2a26 4958 "TARGET_ARM"
c8f69309 4959 "
215b30b3 4960 {
0438d37f 4961 if (arm_arch4 && MEM_P (operands[1]))
215b30b3 4962 {
d1f9b275 4963 emit_insn (gen_rtx_SET (operands[0],
215b30b3 4964 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
4965 DONE;
4966 }
4967 if (!s_register_operand (operands[1], QImode))
4968 operands[1] = copy_to_mode_reg (QImode, operands[1]);
4969 operands[0] = gen_lowpart (SImode, operands[0]);
4970 operands[1] = gen_lowpart (SImode, operands[1]);
4971 operands[2] = gen_reg_rtx (SImode);
4972 }"
4973)
f7fbdd4a 4974
25f905c2 4975(define_insn "*arm_extendqihi_insn"
b4e8a300 4976 [(set (match_operand:HI 0 "s_register_operand" "=r")
bed7d9a5 4977 (sign_extend:HI (match_operand:QI 1 "arm_extendqisi_mem_op" "Uq")))]
cffb2a26 4978 "TARGET_ARM && arm_arch4"
3ef90e77 4979 "ldrsb%?\\t%0, %1"
a2cd141b 4980 [(set_attr "type" "load_byte")
e3f4ccee 4981 (set_attr "predicable" "yes")]
cffb2a26 4982)
3fc2009e 4983
b11cae9e 4984(define_expand "extendqisi2"
3934ae0e 4985 [(set (match_operand:SI 0 "s_register_operand")
4986 (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op")))]
cffb2a26 4987 "TARGET_EITHER"
ef51b8e1 4988{
4989 if (!arm_arch4 && MEM_P (operands[1]))
4990 operands[1] = copy_to_mode_reg (QImode, operands[1]);
a2cd141b 4991
ef51b8e1 4992 if (!arm_arch6 && !MEM_P (operands[1]))
4993 {
4994 rtx t = gen_lowpart (SImode, operands[1]);
4995 rtx tmp = gen_reg_rtx (SImode);
4996 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
4997 emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (24)));
4998 DONE;
4999 }
5000})
a2cd141b 5001
ef51b8e1 5002(define_split
5003 [(set (match_operand:SI 0 "register_operand" "")
5004 (sign_extend:SI (match_operand:QI 1 "register_operand" "")))]
5005 "!arm_arch6"
5006 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
5007 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))]
5008{
5009 operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
5010})
f7fbdd4a 5011
a2cd141b 5012(define_insn "*arm_extendqisi"
ef51b8e1 5013 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5014 (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
a2cd141b 5015 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 5016 "@
5017 #
3ef90e77 5018 ldrsb%?\\t%0, %1"
ef51b8e1 5019 [(set_attr "length" "8,4")
d82e788e 5020 (set_attr "type" "alu_shift_reg,load_byte")
e3f4ccee 5021 (set_attr "predicable" "yes")]
cffb2a26 5022)
3fc2009e 5023
a2cd141b 5024(define_insn "*arm_extendqisi_v6"
5025 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
bed7d9a5 5026 (sign_extend:SI
5027 (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
a2cd141b 5028 "TARGET_ARM && arm_arch6"
b4e8a300 5029 "@
5030 sxtb%?\\t%0, %1
3ef90e77 5031 ldrsb%?\\t%0, %1"
6b6abc9c 5032 [(set_attr "type" "extend,load_byte")
e3f4ccee 5033 (set_attr "predicable" "yes")]
a2cd141b 5034)
5035
5036(define_insn "*arm_extendqisi2addsi"
5037 [(set (match_operand:SI 0 "s_register_operand" "=r")
5038 (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
5039 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 5040 "TARGET_INT_SIMD"
a2cd141b 5041 "sxtab%?\\t%0, %2, %1"
d82e788e 5042 [(set_attr "type" "alu_shift_reg")
8bdfd6ed 5043 (set_attr "predicable" "yes")]
a2cd141b 5044)
5045
856adc5d 5046(define_insn "arm_<sup>xtb16"
5047 [(set (match_operand:SI 0 "s_register_operand" "=r")
5048 (unspec:SI
5049 [(match_operand:SI 1 "s_register_operand" "r")] USXTB16))]
5050 "TARGET_INT_SIMD"
5051 "<sup>xtb16%?\\t%0, %1"
5052 [(set_attr "predicable" "yes")
5053 (set_attr "type" "alu_dsp_reg")])
5054
5055(define_insn "arm_<simd32_op>"
5056 [(set (match_operand:SI 0 "s_register_operand" "=r")
5057 (unspec:SI
5058 [(match_operand:SI 1 "s_register_operand" "r")
5059 (match_operand:SI 2 "s_register_operand" "r")] SIMD32_NOGE_BINOP))]
5060 "TARGET_INT_SIMD"
5061 "<simd32_op>%?\\t%0, %1, %2"
5062 [(set_attr "predicable" "yes")
5063 (set_attr "type" "alu_dsp_reg")])
5064
5065(define_insn "arm_usada8"
5066 [(set (match_operand:SI 0 "s_register_operand" "=r")
5067 (unspec:SI
5068 [(match_operand:SI 1 "s_register_operand" "r")
5069 (match_operand:SI 2 "s_register_operand" "r")
5070 (match_operand:SI 3 "s_register_operand" "r")] UNSPEC_USADA8))]
5071 "TARGET_INT_SIMD"
5072 "usada8%?\\t%0, %1, %2, %3"
5073 [(set_attr "predicable" "yes")
5074 (set_attr "type" "alu_dsp_reg")])
5075
433c7595 5076(define_insn "arm_<simd32_op>"
5077 [(set (match_operand:DI 0 "s_register_operand" "=r")
5078 (unspec:DI
5079 [(match_operand:SI 1 "s_register_operand" "r")
5080 (match_operand:SI 2 "s_register_operand" "r")
5081 (match_operand:DI 3 "s_register_operand" "0")] SIMD32_DIMODE))]
5082 "TARGET_INT_SIMD"
5083 "<simd32_op>%?\\t%Q0, %R0, %1, %2"
5084 [(set_attr "predicable" "yes")
5085 (set_attr "type" "smlald")])
5086
caedf871 5087(define_expand "extendsfdf2"
3934ae0e 5088 [(set (match_operand:DF 0 "s_register_operand")
5089 (float_extend:DF (match_operand:SF 1 "s_register_operand")))]
a50d7267 5090 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
caedf871 5091 ""
5092)
9b8516be 5093
539b44ee 5094;; HFmode -> DFmode conversions where we don't have an instruction for it
5095;; must go through SFmode.
5096;;
5097;; This is always safe for an extend.
5098
9b8516be 5099(define_expand "extendhfdf2"
3934ae0e 5100 [(set (match_operand:DF 0 "s_register_operand")
5101 (float_extend:DF (match_operand:HF 1 "s_register_operand")))]
9b8516be 5102 "TARGET_EITHER"
539b44ee 5103{
5104 /* We don't have a direct instruction for this, so go via SFmode. */
5105 if (!(TARGET_32BIT && TARGET_FP16_TO_DOUBLE))
5106 {
5107 rtx op1;
5108 op1 = convert_to_mode (SFmode, operands[1], 0);
5109 op1 = convert_to_mode (DFmode, op1, 0);
5110 emit_insn (gen_movdf (operands[0], op1));
5111 DONE;
5112 }
5113 /* Otherwise, we're done producing RTL and will pick up the correct
5114 pattern to do this with one rounding-step in a single instruction. */
5115}
9b8516be 5116)
b11cae9e 5117\f
5118;; Move insns (including loads and stores)
5119
5120;; XXX Just some ideas about movti.
9c08d1fa 5121;; I don't think these are a good idea on the arm, there just aren't enough
5122;; registers
b11cae9e 5123;;(define_expand "loadti"
3934ae0e 5124;; [(set (match_operand:TI 0 "s_register_operand")
5125;; (mem:TI (match_operand:SI 1 "address_operand")))]
b11cae9e 5126;; "" "")
5127
5128;;(define_expand "storeti"
3934ae0e 5129;; [(set (mem:TI (match_operand:TI 0 "address_operand"))
5130;; (match_operand:TI 1 "s_register_operand"))]
b11cae9e 5131;; "" "")
5132
5133;;(define_expand "movti"
3934ae0e 5134;; [(set (match_operand:TI 0 "general_operand")
5135;; (match_operand:TI 1 "general_operand"))]
b11cae9e 5136;; ""
5137;; "
5138;;{
5139;; rtx insn;
5140;;
0438d37f 5141;; if (MEM_P (operands[0]) && MEM_P (operands[1]))
b11cae9e 5142;; operands[1] = copy_to_reg (operands[1]);
0438d37f 5143;; if (MEM_P (operands[0]))
b11cae9e 5144;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
0438d37f 5145;; else if (MEM_P (operands[1]))
b11cae9e 5146;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
5147;; else
5148;; FAIL;
5149;;
5150;; emit_insn (insn);
5151;; DONE;
5152;;}")
5153
a2f10574 5154;; Recognize garbage generated above.
b11cae9e 5155
5156;;(define_insn ""
5157;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
5158;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
5159;; ""
5160;; "*
5161;; {
5162;; register mem = (which_alternative < 3);
0d66636f 5163;; register const char *template;
b11cae9e 5164;;
5165;; operands[mem] = XEXP (operands[mem], 0);
5166;; switch (which_alternative)
5167;; {
5168;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
5169;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
5170;; case 2: template = \"ldmia\\t%1, %M0\"; break;
5171;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
5172;; case 4: template = \"stmia\\t%0!, %M1\"; break;
5173;; case 5: template = \"stmia\\t%0, %M1\"; break;
5174;; }
e2348bcb 5175;; output_asm_insn (template, operands);
5176;; return \"\";
b11cae9e 5177;; }")
5178
cffb2a26 5179(define_expand "movdi"
3934ae0e 5180 [(set (match_operand:DI 0 "general_operand")
5181 (match_operand:DI 1 "general_operand"))]
cffb2a26 5182 "TARGET_EITHER"
5183 "
e723310d 5184 gcc_checking_assert (aligned_operand (operands[0], DImode));
5185 gcc_checking_assert (aligned_operand (operands[1], DImode));
e1ba4a27 5186 if (can_create_pseudo_p ())
cffb2a26 5187 {
0438d37f 5188 if (!REG_P (operands[0]))
b2778788 5189 operands[1] = force_reg (DImode, operands[1]);
cffb2a26 5190 }
6b97fdcc 5191 if (REG_P (operands[0]) && REGNO (operands[0]) <= LAST_ARM_REGNUM
b395382f 5192 && !targetm.hard_regno_mode_ok (REGNO (operands[0]), DImode))
4f0e25ca 5193 {
5194 /* Avoid LDRD's into an odd-numbered register pair in ARM state
5195 when expanding function calls. */
5196 gcc_assert (can_create_pseudo_p ());
5197 if (MEM_P (operands[1]) && MEM_VOLATILE_P (operands[1]))
5198 {
5199 /* Perform load into legal reg pair first, then move. */
5200 rtx reg = gen_reg_rtx (DImode);
5201 emit_insn (gen_movdi (reg, operands[1]));
5202 operands[1] = reg;
5203 }
5204 emit_move_insn (gen_lowpart (SImode, operands[0]),
5205 gen_lowpart (SImode, operands[1]));
5206 emit_move_insn (gen_highpart (SImode, operands[0]),
5207 gen_highpart (SImode, operands[1]));
5208 DONE;
5209 }
6b97fdcc 5210 else if (REG_P (operands[1]) && REGNO (operands[1]) <= LAST_ARM_REGNUM
b395382f 5211 && !targetm.hard_regno_mode_ok (REGNO (operands[1]), DImode))
4f0e25ca 5212 {
5213 /* Avoid STRD's from an odd-numbered register pair in ARM state
5214 when expanding function prologue. */
5215 gcc_assert (can_create_pseudo_p ());
5216 rtx split_dest = (MEM_P (operands[0]) && MEM_VOLATILE_P (operands[0]))
5217 ? gen_reg_rtx (DImode)
5218 : operands[0];
5219 emit_move_insn (gen_lowpart (SImode, split_dest),
5220 gen_lowpart (SImode, operands[1]));
5221 emit_move_insn (gen_highpart (SImode, split_dest),
5222 gen_highpart (SImode, operands[1]));
5223 if (split_dest != operands[0])
5224 emit_insn (gen_movdi (operands[0], split_dest));
5225 DONE;
5226 }
cffb2a26 5227 "
5228)
b11cae9e 5229
cffb2a26 5230(define_insn "*arm_movdi"
8f1c7041 5231 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, r, m")
5232 (match_operand:DI 1 "di_operand" "rDa,Db,Dc,mi,r"))]
cde1623a 5233 "TARGET_32BIT
d7216193 5234 && !(TARGET_HARD_FLOAT)
b2778788 5235 && !TARGET_IWMMXT
5236 && ( register_operand (operands[0], DImode)
5237 || register_operand (operands[1], DImode))"
b11cae9e 5238 "*
d51f92df 5239 switch (which_alternative)
5240 {
5241 case 0:
5242 case 1:
5243 case 2:
5244 return \"#\";
581f16e5 5245 case 3:
5246 /* Cannot load it directly, split to load it via MOV / MOVT. */
5247 if (!MEM_P (operands[1]) && arm_disable_literal_pool)
5248 return \"#\";
5249 /* Fall through. */
d51f92df 5250 default:
26ff80c0 5251 return output_move_double (operands, true, NULL);
d51f92df 5252 }
cffb2a26 5253 "
359a6e9f 5254 [(set_attr "length" "8,12,16,8,8")
9f2c2a36 5255 (set_attr "type" "multiple,multiple,multiple,load_8,store_8")
cde1623a 5256 (set_attr "arm_pool_range" "*,*,*,1020,*")
8848d797 5257 (set_attr "arm_neg_pool_range" "*,*,*,1004,*")
42e1de19 5258 (set_attr "thumb2_pool_range" "*,*,*,4094,*")
cde1623a 5259 (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
cffb2a26 5260)
5261
d51f92df 5262(define_split
5263 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
e6dd3afa 5264 (match_operand:ANY64 1 "immediate_operand" ""))]
25f905c2 5265 "TARGET_32BIT
d51f92df 5266 && reload_completed
a869c476 5267 && (arm_disable_literal_pool
5268 || (arm_const_double_inline_cost (operands[1])
5269 <= arm_max_const_double_inline_cost ()))"
d51f92df 5270 [(const_int 0)]
5271 "
5272 arm_split_constant (SET, SImode, curr_insn,
5273 INTVAL (gen_lowpart (SImode, operands[1])),
5274 gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
5275 arm_split_constant (SET, SImode, curr_insn,
5276 INTVAL (gen_highpart_mode (SImode,
5277 GET_MODE (operands[0]),
5278 operands[1])),
5279 gen_highpart (SImode, operands[0]), NULL_RTX, 0);
5280 DONE;
5281 "
5282)
5283
e5ba9289 5284; If optimizing for size, or if we have load delay slots, then
5285; we want to split the constant into two separate operations.
5286; In both cases this may split a trivial part into a single data op
5287; leaving a single complex constant to load. We can also get longer
5288; offsets in a LDR which means we get better chances of sharing the pool
5289; entries. Finally, we can normally do a better job of scheduling
5290; LDR instructions than we can with LDM.
5291; This pattern will only match if the one above did not.
5292(define_split
5293 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
5294 (match_operand:ANY64 1 "const_double_operand" ""))]
5295 "TARGET_ARM && reload_completed
5296 && arm_const_double_by_parts (operands[1])"
5297 [(set (match_dup 0) (match_dup 1))
5298 (set (match_dup 2) (match_dup 3))]
5299 "
5300 operands[2] = gen_highpart (SImode, operands[0]);
5301 operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
5302 operands[1]);
5303 operands[0] = gen_lowpart (SImode, operands[0]);
5304 operands[1] = gen_lowpart (SImode, operands[1]);
5305 "
5306)
5307
d51f92df 5308(define_split
5309 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
5310 (match_operand:ANY64 1 "arm_general_register_operand" ""))]
5311 "TARGET_EITHER && reload_completed"
5312 [(set (match_dup 0) (match_dup 1))
5313 (set (match_dup 2) (match_dup 3))]
5314 "
5315 operands[2] = gen_highpart (SImode, operands[0]);
5316 operands[3] = gen_highpart (SImode, operands[1]);
5317 operands[0] = gen_lowpart (SImode, operands[0]);
5318 operands[1] = gen_lowpart (SImode, operands[1]);
5319
5320 /* Handle a partial overlap. */
5321 if (rtx_equal_p (operands[0], operands[3]))
5322 {
5323 rtx tmp0 = operands[0];
5324 rtx tmp1 = operands[1];
5325
5326 operands[0] = operands[2];
5327 operands[1] = operands[3];
5328 operands[2] = tmp0;
5329 operands[3] = tmp1;
5330 }
5331 "
5332)
5333
a8a3b539 5334;; We can't actually do base+index doubleword loads if the index and
5335;; destination overlap. Split here so that we at least have chance to
5336;; schedule.
5337(define_split
5338 [(set (match_operand:DI 0 "s_register_operand" "")
5339 (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
5340 (match_operand:SI 2 "s_register_operand" ""))))]
5341 "TARGET_LDRD
5342 && reg_overlap_mentioned_p (operands[0], operands[1])
5343 && reg_overlap_mentioned_p (operands[0], operands[2])"
5344 [(set (match_dup 4)
5345 (plus:SI (match_dup 1)
5346 (match_dup 2)))
5347 (set (match_dup 0)
5348 (mem:DI (match_dup 4)))]
5349 "
5350 operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
5351 "
5352)
5353
9c08d1fa 5354(define_expand "movsi"
3934ae0e 5355 [(set (match_operand:SI 0 "general_operand")
5356 (match_operand:SI 1 "general_operand"))]
cffb2a26 5357 "TARGET_EITHER"
9c08d1fa 5358 "
befb0bac 5359 {
e348ff3e 5360 rtx base, offset, tmp;
5361
e723310d 5362 gcc_checking_assert (aligned_operand (operands[0], SImode));
5363 gcc_checking_assert (aligned_operand (operands[1], SImode));
6e291830 5364 if (TARGET_32BIT || TARGET_HAVE_MOVT)
9c08d1fa 5365 {
674a8f0b 5366 /* Everything except mem = const or mem = mem can be done easily. */
0438d37f 5367 if (MEM_P (operands[0]))
cffb2a26 5368 operands[1] = force_reg (SImode, operands[1]);
a2cd141b 5369 if (arm_general_register_operand (operands[0], SImode)
0438d37f 5370 && CONST_INT_P (operands[1])
cffb2a26 5371 && !(const_ok_for_arm (INTVAL (operands[1]))
5372 || const_ok_for_arm (~INTVAL (operands[1]))))
5373 {
17202aa5 5374 if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[1]), SET))
5375 {
5376 emit_insn (gen_rtx_SET (operands[0], operands[1]));
5377 DONE;
5378 }
5379 else
5380 {
5381 arm_split_constant (SET, SImode, NULL_RTX,
5382 INTVAL (operands[1]), operands[0], NULL_RTX,
5383 optimize && can_create_pseudo_p ());
5384 DONE;
5385 }
cffb2a26 5386 }
5387 }
75612252 5388 else /* Target doesn't have MOVT... */
cffb2a26 5389 {
e1ba4a27 5390 if (can_create_pseudo_p ())
cffb2a26 5391 {
0438d37f 5392 if (!REG_P (operands[0]))
cffb2a26 5393 operands[1] = force_reg (SImode, operands[1]);
5394 }
9c08d1fa 5395 }
f655717d 5396
eeb22b66 5397 split_const (operands[1], &base, &offset);
5398 if (INTVAL (offset) != 0
5399 && targetm.cannot_force_const_mem (SImode, operands[1]))
e348ff3e 5400 {
eeb22b66 5401 tmp = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
5402 emit_move_insn (tmp, base);
5403 emit_insn (gen_addsi3 (operands[0], tmp, offset));
5404 DONE;
e348ff3e 5405 }
5406
eeb22b66 5407 tmp = can_create_pseudo_p () ? NULL_RTX : operands[0];
5408
f655717d 5409 /* Recognize the case where operand[1] is a reference to thread-local
eeb22b66 5410 data and load its address to a register. Offsets have been split off
5411 already. */
f655717d 5412 if (arm_tls_referenced_p (operands[1]))
eeb22b66 5413 operands[1] = legitimize_tls_address (operands[1], tmp);
f655717d 5414 else if (flag_pic
5415 && (CONSTANT_P (operands[1])
5416 || symbol_mentioned_p (operands[1])
5417 || label_mentioned_p (operands[1])))
eeb22b66 5418 operands[1] =
5419 legitimize_pic_address (operands[1], SImode, tmp, NULL_RTX, false);
befb0bac 5420 }
215b30b3 5421 "
5422)
9c08d1fa 5423
d0e6a121 5424;; The ARM LO_SUM and HIGH are backwards - HIGH sets the low bits, and
5425;; LO_SUM adds in the high bits. Fortunately these are opaque operations
5426;; so this does not matter.
5427(define_insn "*arm_movt"
417e5cc5 5428 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r")
5429 (lo_sum:SI (match_operand:SI 1 "nonimmediate_operand" "0,0")
5430 (match_operand:SI 2 "general_operand" "i,i")))]
60a48e7d 5431 "TARGET_HAVE_MOVT && arm_valid_symbolic_address_p (operands[2])"
417e5cc5 5432 "@
5433 movt%?\t%0, #:upper16:%c2
5434 movt\t%0, #:upper16:%c2"
5435 [(set_attr "arch" "32,v8mb")
5436 (set_attr "predicable" "yes")
1b7da4ac 5437 (set_attr "length" "4")
282b4c75 5438 (set_attr "type" "alu_sreg")]
d0e6a121 5439)
5440
cffb2a26 5441(define_insn "*arm_movsi_insn"
aaa37ad6 5442 [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,rk,m")
110eae03 5443 (match_operand:SI 1 "general_operand" "rk, I,K,j,mi,rk"))]
d7216193 5444 "TARGET_ARM && !TARGET_IWMMXT && !TARGET_HARD_FLOAT
cffb2a26 5445 && ( register_operand (operands[0], SImode)
5446 || register_operand (operands[1], SImode))"
f7fbdd4a 5447 "@
aaa37ad6 5448 mov%?\\t%0, %1
f7fbdd4a 5449 mov%?\\t%0, %1
5450 mvn%?\\t%0, #%B1
25f905c2 5451 movw%?\\t%0, %1
f7fbdd4a 5452 ldr%?\\t%0, %1
5453 str%?\\t%1, %0"
9f2c2a36 5454 [(set_attr "type" "mov_reg,mov_imm,mvn_imm,mov_imm,load_4,store_4")
0d66636f 5455 (set_attr "predicable" "yes")
100cd063 5456 (set_attr "arch" "*,*,*,v6t2,*,*")
aaa37ad6 5457 (set_attr "pool_range" "*,*,*,*,4096,*")
5458 (set_attr "neg_pool_range" "*,*,*,*,4084,*")]
cffb2a26 5459)
87b22bf7 5460
5461(define_split
a2cd141b 5462 [(set (match_operand:SI 0 "arm_general_register_operand" "")
87b22bf7 5463 (match_operand:SI 1 "const_int_operand" ""))]
6e291830 5464 "(TARGET_32BIT || TARGET_HAVE_MOVT)
215b30b3 5465 && (!(const_ok_for_arm (INTVAL (operands[1]))
5466 || const_ok_for_arm (~INTVAL (operands[1]))))"
87b22bf7 5467 [(clobber (const_int 0))]
5468 "
96f57e36 5469 arm_split_constant (SET, SImode, NULL_RTX,
5470 INTVAL (operands[1]), operands[0], NULL_RTX, 0);
87b22bf7 5471 DONE;
215b30b3 5472 "
5473)
9c08d1fa 5474
861033d5 5475;; A normal way to do (symbol + offset) requires three instructions at least
5476;; (depends on how big the offset is) as below:
5477;; movw r0, #:lower16:g
5478;; movw r0, #:upper16:g
5479;; adds r0, #4
5480;;
5481;; A better way would be:
5482;; movw r0, #:lower16:g+4
5483;; movw r0, #:upper16:g+4
5484;;
5485;; The limitation of this way is that the length of offset should be a 16-bit
5486;; signed value, because current assembler only supports REL type relocation for
5487;; such case. If the more powerful RELA type is supported in future, we should
5488;; update this pattern to go with better way.
5489(define_split
5490 [(set (match_operand:SI 0 "arm_general_register_operand" "")
5491 (const:SI (plus:SI (match_operand:SI 1 "general_operand" "")
5492 (match_operand:SI 2 "const_int_operand" ""))))]
60a48e7d 5493 "TARGET_THUMB
5494 && TARGET_HAVE_MOVT
861033d5 5495 && arm_disable_literal_pool
5496 && reload_completed
5497 && GET_CODE (operands[1]) == SYMBOL_REF"
5498 [(clobber (const_int 0))]
5499 "
5500 int offset = INTVAL (operands[2]);
5501
5502 if (offset < -0x8000 || offset > 0x7fff)
5503 {
5504 arm_emit_movpair (operands[0], operands[1]);
d1f9b275 5505 emit_insn (gen_rtx_SET (operands[0],
861033d5 5506 gen_rtx_PLUS (SImode, operands[0], operands[2])));
5507 }
5508 else
5509 {
5510 rtx op = gen_rtx_CONST (SImode,
5511 gen_rtx_PLUS (SImode, operands[1], operands[2]));
5512 arm_emit_movpair (operands[0], op);
5513 }
5514 "
5515)
5516
b8d5d078 5517;; Split symbol_refs at the later stage (after cprop), instead of generating
5518;; movt/movw pair directly at expand. Otherwise corresponding high_sum
5519;; and lo_sum would be merged back into memory load at cprop. However,
5520;; if the default is to prefer movt/movw rather than a load from the constant
5521;; pool, the performance is better.
5522(define_split
5523 [(set (match_operand:SI 0 "arm_general_register_operand" "")
5524 (match_operand:SI 1 "general_operand" ""))]
60a48e7d 5525 "TARGET_USE_MOVT && GET_CODE (operands[1]) == SYMBOL_REF
d022aaf3 5526 && !target_word_relocations
b8d5d078 5527 && !arm_tls_referenced_p (operands[1])"
5528 [(clobber (const_int 0))]
5529{
5530 arm_emit_movpair (operands[0], operands[1]);
5531 DONE;
5532})
5533
bc360af8 5534;; When generating pic, we need to load the symbol offset into a register.
5535;; So that the optimizer does not confuse this with a normal symbol load
5536;; we use an unspec. The offset will be loaded from a constant pool entry,
5537;; since that is the only type of relocation we can use.
cffb2a26 5538
bc360af8 5539;; Wrap calculation of the whole PIC address in a single pattern for the
5540;; benefit of optimizers, particularly, PRE and HOIST. Calculation of
5541;; a PIC address involves two loads from memory, so we want to CSE it
5542;; as often as possible.
5543;; This pattern will be split into one of the pic_load_addr_* patterns
5544;; and a move after GCSE optimizations.
5545;;
5546;; Note: Update arm.c: legitimize_pic_address() when changing this pattern.
5547(define_expand "calculate_pic_address"
3934ae0e 5548 [(set (match_operand:SI 0 "register_operand")
5549 (mem:SI (plus:SI (match_operand:SI 1 "register_operand")
94f8caca 5550 (unspec:SI [(match_operand:SI 2 "" "")]
5551 UNSPEC_PIC_SYM))))]
5552 "flag_pic"
5553)
5554
5555;; Split calculate_pic_address into pic_load_addr_* and a move.
5556(define_split
5557 [(set (match_operand:SI 0 "register_operand" "")
5558 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "")
5559 (unspec:SI [(match_operand:SI 2 "" "")]
5560 UNSPEC_PIC_SYM))))]
5561 "flag_pic"
5562 [(set (match_dup 3) (unspec:SI [(match_dup 2)] UNSPEC_PIC_SYM))
5563 (set (match_dup 0) (mem:SI (plus:SI (match_dup 1) (match_dup 3))))]
5564 "operands[3] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];"
5565)
5566
350ccca5 5567;; operand1 is the memory address to go into
5568;; pic_load_addr_32bit.
5569;; operand2 is the PIC label to be emitted
5570;; from pic_add_dot_plus_eight.
5571;; We do this to allow hoisting of the entire insn.
5572(define_insn_and_split "pic_load_addr_unified"
5573 [(set (match_operand:SI 0 "s_register_operand" "=r,r,l")
5574 (unspec:SI [(match_operand:SI 1 "" "mX,mX,mX")
5575 (match_operand:SI 2 "" "")]
5576 UNSPEC_PIC_UNIFIED))]
5577 "flag_pic"
5578 "#"
5579 "&& reload_completed"
5580 [(set (match_dup 0) (unspec:SI [(match_dup 1)] UNSPEC_PIC_SYM))
5581 (set (match_dup 0) (unspec:SI [(match_dup 0) (match_dup 3)
5582 (match_dup 2)] UNSPEC_PIC_BASE))]
5583 "operands[3] = TARGET_THUMB ? GEN_INT (4) : GEN_INT (8);"
9f2c2a36 5584 [(set_attr "type" "load_4,load_4,load_4")
42e1de19 5585 (set_attr "pool_range" "4096,4094,1022")
350ccca5 5586 (set_attr "neg_pool_range" "4084,0,0")
5587 (set_attr "arch" "a,t2,t1")
5588 (set_attr "length" "8,6,4")]
5589)
5590
67336bcf 5591;; The rather odd constraints on the following are to force reload to leave
5592;; the insn alone, and to force the minipool generation pass to then move
5593;; the GOT symbol to memory.
849170fd 5594
b3cd5f55 5595(define_insn "pic_load_addr_32bit"
849170fd 5596 [(set (match_operand:SI 0 "s_register_operand" "=r")
e1159bbe 5597 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
b3cd5f55 5598 "TARGET_32BIT && flag_pic"
67336bcf 5599 "ldr%?\\t%0, %1"
9f2c2a36 5600 [(set_attr "type" "load_4")
42e1de19 5601 (set (attr "pool_range")
5602 (if_then_else (eq_attr "is_thumb" "no")
5603 (const_int 4096)
5604 (const_int 4094)))
b3cd5f55 5605 (set (attr "neg_pool_range")
5606 (if_then_else (eq_attr "is_thumb" "no")
5607 (const_int 4084)
5608 (const_int 0)))]
8c4d8060 5609)
5610
25f905c2 5611(define_insn "pic_load_addr_thumb1"
8c4d8060 5612 [(set (match_operand:SI 0 "s_register_operand" "=l")
e1159bbe 5613 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
25f905c2 5614 "TARGET_THUMB1 && flag_pic"
8c4d8060 5615 "ldr\\t%0, %1"
9f2c2a36 5616 [(set_attr "type" "load_4")
42e1de19 5617 (set (attr "pool_range") (const_int 1018))]
cffb2a26 5618)
849170fd 5619
cffb2a26 5620(define_insn "pic_add_dot_plus_four"
15d5d060 5621 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5622 (unspec:SI [(match_operand:SI 1 "register_operand" "0")
5623 (const_int 4)
beef0fb5 5624 (match_operand 2 "" "")]
5625 UNSPEC_PIC_BASE))]
b3cd5f55 5626 "TARGET_THUMB"
cffb2a26 5627 "*
6cdcb15c 5628 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5629 INTVAL (operands[2]));
cffb2a26 5630 return \"add\\t%0, %|pc\";
5631 "
1b7da4ac 5632 [(set_attr "length" "2")
112eda6f 5633 (set_attr "type" "alu_sreg")]
cffb2a26 5634)
849170fd 5635
5636(define_insn "pic_add_dot_plus_eight"
15d5d060 5637 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5638 (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5639 (const_int 8)
beef0fb5 5640 (match_operand 2 "" "")]
5641 UNSPEC_PIC_BASE))]
f655717d 5642 "TARGET_ARM"
c4034607 5643 "*
6cdcb15c 5644 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5645 INTVAL (operands[2]));
15d5d060 5646 return \"add%?\\t%0, %|pc, %1\";
cffb2a26 5647 "
1b7da4ac 5648 [(set_attr "predicable" "yes")
112eda6f 5649 (set_attr "type" "alu_sreg")]
cffb2a26 5650)
849170fd 5651
f655717d 5652(define_insn "tls_load_dot_plus_eight"
cc071db6 5653 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5654 (mem:SI (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5655 (const_int 8)
beef0fb5 5656 (match_operand 2 "" "")]
5657 UNSPEC_PIC_BASE)))]
f655717d 5658 "TARGET_ARM"
5659 "*
6cdcb15c 5660 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5661 INTVAL (operands[2]));
f655717d 5662 return \"ldr%?\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_eight\";
5663 "
1b7da4ac 5664 [(set_attr "predicable" "yes")
9f2c2a36 5665 (set_attr "type" "load_4")]
f655717d 5666)
5667
5668;; PIC references to local variables can generate pic_add_dot_plus_eight
5669;; followed by a load. These sequences can be crunched down to
5670;; tls_load_dot_plus_eight by a peephole.
5671
5672(define_peephole2
c0c1fba5 5673 [(set (match_operand:SI 0 "register_operand" "")
5674 (unspec:SI [(match_operand:SI 3 "register_operand" "")
5675 (const_int 8)
5676 (match_operand 1 "" "")]
5677 UNSPEC_PIC_BASE))
2d05dfad 5678 (set (match_operand:SI 2 "arm_general_register_operand" "")
5679 (mem:SI (match_dup 0)))]
f655717d 5680 "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
c0c1fba5 5681 [(set (match_dup 2)
5682 (mem:SI (unspec:SI [(match_dup 3)
5683 (const_int 8)
5684 (match_dup 1)]
5685 UNSPEC_PIC_BASE)))]
f655717d 5686 ""
5687)
5688
bac7fc85 5689(define_insn "pic_offset_arm"
5690 [(set (match_operand:SI 0 "register_operand" "=r")
5691 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
5692 (unspec:SI [(match_operand:SI 2 "" "X")]
5693 UNSPEC_PIC_OFFSET))))]
5694 "TARGET_VXWORKS_RTP && TARGET_ARM && flag_pic"
5695 "ldr%?\\t%0, [%1,%2]"
9f2c2a36 5696 [(set_attr "type" "load_4")]
bac7fc85 5697)
5698
95373f08 5699(define_expand "builtin_setjmp_receiver"
5700 [(label_ref (match_operand 0 "" ""))]
5701 "flag_pic"
5702 "
5703{
b935b306 5704 /* r3 is clobbered by set/longjmp, so we can use it as a scratch
5705 register. */
2cb7d577 5706 if (arm_pic_register != INVALID_REGNUM)
f98495d9 5707 arm_load_pic_register (1UL << 3, NULL_RTX);
95373f08 5708 DONE;
5709}")
5710
9c08d1fa 5711;; If copying one reg to another we can set the condition codes according to
5712;; its value. Such a move is common after a return from subroutine and the
5713;; result is being tested against zero.
5714
f7fbdd4a 5715(define_insn "*movsi_compare0"
bd5b4116 5716 [(set (reg:CC CC_REGNUM)
cffb2a26 5717 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
5718 (const_int 0)))
5719 (set (match_operand:SI 0 "s_register_operand" "=r,r")
5720 (match_dup 1))]
25f905c2 5721 "TARGET_32BIT"
e2348bcb 5722 "@
40dbec34 5723 cmp%?\\t%0, #0
3ef90e77 5724 subs%?\\t%0, %1, #0"
65f68e55 5725 [(set_attr "conds" "set")
d82e788e 5726 (set_attr "type" "alus_imm,alus_imm")]
cffb2a26 5727)
b11cae9e 5728
b11cae9e 5729;; Subroutine to store a half word from a register into memory.
5730;; Operand 0 is the source register (HImode)
c8f69309 5731;; Operand 1 is the destination address in a register (SImode)
b11cae9e 5732
9c08d1fa 5733;; In both this routine and the next, we must be careful not to spill
01cc3b75 5734;; a memory address of reg+large_const into a separate PLUS insn, since this
9c08d1fa 5735;; can generate unrecognizable rtl.
5736
b11cae9e 5737(define_expand "storehi"
c8f69309 5738 [;; store the low byte
f082f1c4 5739 (set (match_operand 1 "" "") (match_dup 3))
b11cae9e 5740 ;; extract the high byte
c8f69309 5741 (set (match_dup 2)
5742 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
b11cae9e 5743 ;; store the high byte
787f8210 5744 (set (match_dup 4) (match_dup 5))]
cffb2a26 5745 "TARGET_ARM"
b11cae9e 5746 "
215b30b3 5747 {
537ffcfc 5748 rtx op1 = operands[1];
5749 rtx addr = XEXP (op1, 0);
215b30b3 5750 enum rtx_code code = GET_CODE (addr);
5751
0438d37f 5752 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
215b30b3 5753 || code == MINUS)
537ffcfc 5754 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
215b30b3 5755
537ffcfc 5756 operands[4] = adjust_address (op1, QImode, 1);
e513d163 5757 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 5758 operands[3] = gen_lowpart (QImode, operands[0]);
5759 operands[0] = gen_lowpart (SImode, operands[0]);
787f8210 5760 operands[2] = gen_reg_rtx (SImode);
5761 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 5762 }"
5763)
b11cae9e 5764
c7597b5d 5765(define_expand "storehi_bigend"
f082f1c4 5766 [(set (match_dup 4) (match_dup 3))
c7597b5d 5767 (set (match_dup 2)
5768 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
787f8210 5769 (set (match_operand 1 "" "") (match_dup 5))]
cffb2a26 5770 "TARGET_ARM"
b11cae9e 5771 "
215b30b3 5772 {
537ffcfc 5773 rtx op1 = operands[1];
5774 rtx addr = XEXP (op1, 0);
215b30b3 5775 enum rtx_code code = GET_CODE (addr);
5776
0438d37f 5777 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
215b30b3 5778 || code == MINUS)
537ffcfc 5779 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
215b30b3 5780
537ffcfc 5781 operands[4] = adjust_address (op1, QImode, 1);
e513d163 5782 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 5783 operands[3] = gen_lowpart (QImode, operands[0]);
5784 operands[0] = gen_lowpart (SImode, operands[0]);
5785 operands[2] = gen_reg_rtx (SImode);
787f8210 5786 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 5787 }"
5788)
c7597b5d 5789
5790;; Subroutine to store a half word integer constant into memory.
5791(define_expand "storeinthi"
f082f1c4 5792 [(set (match_operand 0 "" "")
787f8210 5793 (match_operand 1 "" ""))
9e8503e6 5794 (set (match_dup 3) (match_dup 2))]
cffb2a26 5795 "TARGET_ARM"
c7597b5d 5796 "
215b30b3 5797 {
5798 HOST_WIDE_INT value = INTVAL (operands[1]);
5799 rtx addr = XEXP (operands[0], 0);
537ffcfc 5800 rtx op0 = operands[0];
215b30b3 5801 enum rtx_code code = GET_CODE (addr);
c7597b5d 5802
0438d37f 5803 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
215b30b3 5804 || code == MINUS)
537ffcfc 5805 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
c7597b5d 5806
215b30b3 5807 operands[1] = gen_reg_rtx (SImode);
5808 if (BYTES_BIG_ENDIAN)
5809 {
5810 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
5811 if ((value & 255) == ((value >> 8) & 255))
5812 operands[2] = operands[1];
5813 else
5814 {
5815 operands[2] = gen_reg_rtx (SImode);
5816 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
5817 }
5818 }
5819 else
5820 {
5821 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
5822 if ((value & 255) == ((value >> 8) & 255))
5823 operands[2] = operands[1];
5824 else
5825 {
5826 operands[2] = gen_reg_rtx (SImode);
5827 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
5828 }
5829 }
c7597b5d 5830
537ffcfc 5831 operands[3] = adjust_address (op0, QImode, 1);
e513d163 5832 operands[0] = adjust_address (operands[0], QImode, 0);
9e8503e6 5833 operands[2] = gen_lowpart (QImode, operands[2]);
787f8210 5834 operands[1] = gen_lowpart (QImode, operands[1]);
215b30b3 5835 }"
5836)
b11cae9e 5837
f7fbdd4a 5838(define_expand "storehi_single_op"
3934ae0e 5839 [(set (match_operand:HI 0 "memory_operand")
5840 (match_operand:HI 1 "general_operand"))]
25f905c2 5841 "TARGET_32BIT && arm_arch4"
f7fbdd4a 5842 "
215b30b3 5843 if (!s_register_operand (operands[1], HImode))
f7fbdd4a 5844 operands[1] = copy_to_mode_reg (HImode, operands[1]);
215b30b3 5845 "
5846)
f7fbdd4a 5847
b11cae9e 5848(define_expand "movhi"
3934ae0e 5849 [(set (match_operand:HI 0 "general_operand")
5850 (match_operand:HI 1 "general_operand"))]
cffb2a26 5851 "TARGET_EITHER"
b11cae9e 5852 "
e723310d 5853 gcc_checking_assert (aligned_operand (operands[0], HImode));
5854 gcc_checking_assert (aligned_operand (operands[1], HImode));
cffb2a26 5855 if (TARGET_ARM)
b11cae9e 5856 {
e1ba4a27 5857 if (can_create_pseudo_p ())
cffb2a26 5858 {
0438d37f 5859 if (MEM_P (operands[0]))
b11cae9e 5860 {
cffb2a26 5861 if (arm_arch4)
5862 {
5863 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
5864 DONE;
5865 }
0438d37f 5866 if (CONST_INT_P (operands[1]))
cffb2a26 5867 emit_insn (gen_storeinthi (operands[0], operands[1]));
c7597b5d 5868 else
cffb2a26 5869 {
0438d37f 5870 if (MEM_P (operands[1]))
cffb2a26 5871 operands[1] = force_reg (HImode, operands[1]);
5872 if (BYTES_BIG_ENDIAN)
5873 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
5874 else
5875 emit_insn (gen_storehi (operands[1], operands[0]));
5876 }
5877 DONE;
b11cae9e 5878 }
cffb2a26 5879 /* Sign extend a constant, and keep it in an SImode reg. */
0438d37f 5880 else if (CONST_INT_P (operands[1]))
9c08d1fa 5881 {
cffb2a26 5882 rtx reg = gen_reg_rtx (SImode);
5883 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
5884
5885 /* If the constant is already valid, leave it alone. */
215b30b3 5886 if (!const_ok_for_arm (val))
cffb2a26 5887 {
5888 /* If setting all the top bits will make the constant
5889 loadable in a single instruction, then set them.
5890 Otherwise, sign extend the number. */
5891
215b30b3 5892 if (const_ok_for_arm (~(val | ~0xffff)))
cffb2a26 5893 val |= ~0xffff;
5894 else if (val & 0x8000)
5895 val |= ~0xffff;
5896 }
5897
5898 emit_insn (gen_movsi (reg, GEN_INT (val)));
9e8503e6 5899 operands[1] = gen_lowpart (HImode, reg);
9c08d1fa 5900 }
e1ba4a27 5901 else if (arm_arch4 && optimize && can_create_pseudo_p ()
0438d37f 5902 && MEM_P (operands[1]))
0045890a 5903 {
5904 rtx reg = gen_reg_rtx (SImode);
5905
5906 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
5907 operands[1] = gen_lowpart (HImode, reg);
5908 }
215b30b3 5909 else if (!arm_arch4)
f7fbdd4a 5910 {
0438d37f 5911 if (MEM_P (operands[1]))
cffb2a26 5912 {
c1a66faf 5913 rtx base;
5914 rtx offset = const0_rtx;
5915 rtx reg = gen_reg_rtx (SImode);
5916
0438d37f 5917 if ((REG_P (base = XEXP (operands[1], 0))
c1a66faf 5918 || (GET_CODE (base) == PLUS
0438d37f 5919 && (CONST_INT_P (offset = XEXP (base, 1)))
c1a66faf 5920 && ((INTVAL(offset) & 1) != 1)
0438d37f 5921 && REG_P (base = XEXP (base, 0))))
c1a66faf 5922 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
206ee9a2 5923 {
8deb3959 5924 rtx new_rtx;
c1a66faf 5925
8deb3959 5926 new_rtx = widen_memory_access (operands[1], SImode,
5927 ((INTVAL (offset) & ~3)
5928 - INTVAL (offset)));
5929 emit_insn (gen_movsi (reg, new_rtx));
c1a66faf 5930 if (((INTVAL (offset) & 2) != 0)
5931 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
5932 {
5933 rtx reg2 = gen_reg_rtx (SImode);
5934
5935 emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
5936 reg = reg2;
5937 }
206ee9a2 5938 }
c1a66faf 5939 else
5940 emit_insn (gen_movhi_bytes (reg, operands[1]));
5941
5942 operands[1] = gen_lowpart (HImode, reg);
cffb2a26 5943 }
5944 }
5945 }
674a8f0b 5946 /* Handle loading a large integer during reload. */
0438d37f 5947 else if (CONST_INT_P (operands[1])
215b30b3 5948 && !const_ok_for_arm (INTVAL (operands[1]))
5949 && !const_ok_for_arm (~INTVAL (operands[1])))
cffb2a26 5950 {
5951 /* Writing a constant to memory needs a scratch, which should
5952 be handled with SECONDARY_RELOADs. */
0438d37f 5953 gcc_assert (REG_P (operands[0]));
cffb2a26 5954
5955 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5956 emit_insn (gen_movsi (operands[0], operands[1]));
5957 DONE;
5958 }
5959 }
25f905c2 5960 else if (TARGET_THUMB2)
5961 {
5962 /* Thumb-2 can do everything except mem=mem and mem=const easily. */
e1ba4a27 5963 if (can_create_pseudo_p ())
25f905c2 5964 {
0438d37f 5965 if (!REG_P (operands[0]))
25f905c2 5966 operands[1] = force_reg (HImode, operands[1]);
5967 /* Zero extend a constant, and keep it in an SImode reg. */
0438d37f 5968 else if (CONST_INT_P (operands[1]))
25f905c2 5969 {
5970 rtx reg = gen_reg_rtx (SImode);
5971 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
5972
5973 emit_insn (gen_movsi (reg, GEN_INT (val)));
5974 operands[1] = gen_lowpart (HImode, reg);
5975 }
5976 }
5977 }
5978 else /* TARGET_THUMB1 */
cffb2a26 5979 {
e1ba4a27 5980 if (can_create_pseudo_p ())
cffb2a26 5981 {
0438d37f 5982 if (CONST_INT_P (operands[1]))
6cffc037 5983 {
5984 rtx reg = gen_reg_rtx (SImode);
5985
5986 emit_insn (gen_movsi (reg, operands[1]));
5987 operands[1] = gen_lowpart (HImode, reg);
5988 }
cffb2a26 5989
5990 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 5991 happen if we are passed a SP (never OK for HImode/QImode) or
bc409cb4 5992 virtual register (also rejected as illegitimate for HImode/QImode)
5993 relative address. */
cffb2a26 5994 /* ??? This should perhaps be fixed elsewhere, for instance, in
5995 fixup_stack_1, by checking for other kinds of invalid addresses,
5996 e.g. a bare reference to a virtual register. This may confuse the
5997 alpha though, which must handle this case differently. */
0438d37f 5998 if (MEM_P (operands[0])
215b30b3 5999 && !memory_address_p (GET_MODE (operands[0]),
6000 XEXP (operands[0], 0)))
537ffcfc 6001 operands[0]
6002 = replace_equiv_address (operands[0],
6003 copy_to_reg (XEXP (operands[0], 0)));
cffb2a26 6004
0438d37f 6005 if (MEM_P (operands[1])
215b30b3 6006 && !memory_address_p (GET_MODE (operands[1]),
6007 XEXP (operands[1], 0)))
537ffcfc 6008 operands[1]
6009 = replace_equiv_address (operands[1],
6010 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 6011
0438d37f 6012 if (MEM_P (operands[1]) && optimize > 0)
6cffc037 6013 {
6014 rtx reg = gen_reg_rtx (SImode);
6015
6016 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
6017 operands[1] = gen_lowpart (HImode, reg);
6018 }
6019
0438d37f 6020 if (MEM_P (operands[0]))
6cffc037 6021 operands[1] = force_reg (HImode, operands[1]);
cffb2a26 6022 }
0438d37f 6023 else if (CONST_INT_P (operands[1])
234f6557 6024 && !satisfies_constraint_I (operands[1]))
cffb2a26 6025 {
6cffc037 6026 /* Handle loading a large integer during reload. */
6027
cffb2a26 6028 /* Writing a constant to memory needs a scratch, which should
6029 be handled with SECONDARY_RELOADs. */
0438d37f 6030 gcc_assert (REG_P (operands[0]));
cffb2a26 6031
1a83b3ff 6032 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
cffb2a26 6033 emit_insn (gen_movsi (operands[0], operands[1]));
6034 DONE;
6035 }
b11cae9e 6036 }
cffb2a26 6037 "
6038)
6039
25f7a26e 6040(define_expand "movhi_bytes"
eab14235 6041 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 6042 (set (match_dup 3)
eab14235 6043 (zero_extend:SI (match_dup 6)))
25f7a26e 6044 (set (match_operand:SI 0 "" "")
6045 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
cffb2a26 6046 "TARGET_ARM"
25f7a26e 6047 "
215b30b3 6048 {
6049 rtx mem1, mem2;
6050 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
6051
788fcce0 6052 mem1 = change_address (operands[1], QImode, addr);
29c05e22 6053 mem2 = change_address (operands[1], QImode,
6054 plus_constant (Pmode, addr, 1));
215b30b3 6055 operands[0] = gen_lowpart (SImode, operands[0]);
6056 operands[1] = mem1;
6057 operands[2] = gen_reg_rtx (SImode);
6058 operands[3] = gen_reg_rtx (SImode);
6059 operands[6] = mem2;
25f7a26e 6060
215b30b3 6061 if (BYTES_BIG_ENDIAN)
6062 {
6063 operands[4] = operands[2];
6064 operands[5] = operands[3];
6065 }
6066 else
6067 {
6068 operands[4] = operands[3];
6069 operands[5] = operands[2];
6070 }
6071 }"
6072)
25f7a26e 6073
c7597b5d 6074(define_expand "movhi_bigend"
6075 [(set (match_dup 2)
3934ae0e 6076 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand") 0)
c7597b5d 6077 (const_int 16)))
6078 (set (match_dup 3)
6079 (ashiftrt:SI (match_dup 2) (const_int 16)))
3934ae0e 6080 (set (match_operand:HI 0 "s_register_operand")
787f8210 6081 (match_dup 4))]
cffb2a26 6082 "TARGET_ARM"
c7597b5d 6083 "
6084 operands[2] = gen_reg_rtx (SImode);
6085 operands[3] = gen_reg_rtx (SImode);
787f8210 6086 operands[4] = gen_lowpart (HImode, operands[3]);
215b30b3 6087 "
6088)
b11cae9e 6089
a2f10574 6090;; Pattern to recognize insn generated default case above
f7fbdd4a 6091(define_insn "*movhi_insn_arch4"
e4585731 6092 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r,m,r")
6093 (match_operand:HI 1 "general_operand" "rIk,K,n,r,mi"))]
cffb2a26 6094 "TARGET_ARM
d7216193 6095 && arm_arch4 && !TARGET_HARD_FLOAT
85e02ccb 6096 && (register_operand (operands[0], HImode)
6097 || register_operand (operands[1], HImode))"
f7fbdd4a 6098 "@
6099 mov%?\\t%0, %1\\t%@ movhi
6100 mvn%?\\t%0, #%B1\\t%@ movhi
b1c1a101 6101 movw%?\\t%0, %L1\\t%@ movhi
3ef90e77 6102 strh%?\\t%1, %0\\t%@ movhi
6103 ldrh%?\\t%0, %1\\t%@ movhi"
65f68e55 6104 [(set_attr "predicable" "yes")
e4585731 6105 (set_attr "pool_range" "*,*,*,*,256")
6106 (set_attr "neg_pool_range" "*,*,*,*,244")
6107 (set_attr "arch" "*,*,v6t2,*,*")
65f68e55 6108 (set_attr_alternative "type"
6109 [(if_then_else (match_operand 1 "const_int_operand" "")
1aed5204 6110 (const_string "mov_imm" )
6111 (const_string "mov_reg"))
6112 (const_string "mvn_imm")
e4585731 6113 (const_string "mov_imm")
9f2c2a36 6114 (const_string "store_4")
6115 (const_string "load_4")])]
cffb2a26 6116)
f7fbdd4a 6117
f7fbdd4a 6118(define_insn "*movhi_bytes"
65f68e55 6119 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
5fd254ed 6120 (match_operand:HI 1 "arm_rhs_operand" "I,rk,K"))]
d7216193 6121 "TARGET_ARM && !TARGET_HARD_FLOAT"
25f7a26e 6122 "@
65f68e55 6123 mov%?\\t%0, %1\\t%@ movhi
25f7a26e 6124 mov%?\\t%0, %1\\t%@ movhi
0d66636f 6125 mvn%?\\t%0, #%B1\\t%@ movhi"
d2a518d1 6126 [(set_attr "predicable" "yes")
1aed5204 6127 (set_attr "type" "mov_imm,mov_reg,mvn_imm")]
0d66636f 6128)
837bb76e 6129
bc5c7e08 6130;; We use a DImode scratch because we may occasionally need an additional
6131;; temporary if the address isn't offsettable -- push_reload doesn't seem
6132;; to take any notice of the "o" constraints on reload_memory_operand operand.
3934ae0e 6133;; The reload_in<m> and reload_out<m> patterns require special constraints
6134;; to be correctly handled in default_secondary_reload function.
d3373b54 6135(define_expand "reload_outhi"
cffb2a26 6136 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
215b30b3 6137 (match_operand:HI 1 "s_register_operand" "r")
6138 (match_operand:DI 2 "s_register_operand" "=&l")])]
cffb2a26 6139 "TARGET_EITHER"
6140 "if (TARGET_ARM)
6141 arm_reload_out_hi (operands);
6142 else
6143 thumb_reload_out_hi (operands);
d3373b54 6144 DONE;
cffb2a26 6145 "
6146)
d3373b54 6147
25f7a26e 6148(define_expand "reload_inhi"
6149 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
cffb2a26 6150 (match_operand:HI 1 "arm_reload_memory_operand" "o")
bc5c7e08 6151 (match_operand:DI 2 "s_register_operand" "=&r")])]
c1a66faf 6152 "TARGET_EITHER"
25f7a26e 6153 "
cffb2a26 6154 if (TARGET_ARM)
6155 arm_reload_in_hi (operands);
6156 else
6157 thumb_reload_out_hi (operands);
25f7a26e 6158 DONE;
6159")
6160
9c08d1fa 6161(define_expand "movqi"
3934ae0e 6162 [(set (match_operand:QI 0 "general_operand")
6163 (match_operand:QI 1 "general_operand"))]
cffb2a26 6164 "TARGET_EITHER"
9c08d1fa 6165 "
6cffc037 6166 /* Everything except mem = const or mem = mem can be done easily */
0045890a 6167
e1ba4a27 6168 if (can_create_pseudo_p ())
cffb2a26 6169 {
0438d37f 6170 if (CONST_INT_P (operands[1]))
6cffc037 6171 {
6172 rtx reg = gen_reg_rtx (SImode);
6173
03770691 6174 /* For thumb we want an unsigned immediate, then we are more likely
6175 to be able to use a movs insn. */
6176 if (TARGET_THUMB)
6177 operands[1] = GEN_INT (INTVAL (operands[1]) & 255);
6178
6cffc037 6179 emit_insn (gen_movsi (reg, operands[1]));
6180 operands[1] = gen_lowpart (QImode, reg);
6181 }
cffb2a26 6182
6cffc037 6183 if (TARGET_THUMB)
6184 {
cffb2a26 6185 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 6186 happen if we are passed a SP (never OK for HImode/QImode) or
bc409cb4 6187 virtual register (also rejected as illegitimate for HImode/QImode)
6188 relative address. */
cffb2a26 6189 /* ??? This should perhaps be fixed elsewhere, for instance, in
6190 fixup_stack_1, by checking for other kinds of invalid addresses,
6191 e.g. a bare reference to a virtual register. This may confuse the
6192 alpha though, which must handle this case differently. */
0438d37f 6193 if (MEM_P (operands[0])
215b30b3 6194 && !memory_address_p (GET_MODE (operands[0]),
cffb2a26 6195 XEXP (operands[0], 0)))
537ffcfc 6196 operands[0]
6197 = replace_equiv_address (operands[0],
6198 copy_to_reg (XEXP (operands[0], 0)));
0438d37f 6199 if (MEM_P (operands[1])
215b30b3 6200 && !memory_address_p (GET_MODE (operands[1]),
cffb2a26 6201 XEXP (operands[1], 0)))
537ffcfc 6202 operands[1]
6203 = replace_equiv_address (operands[1],
6204 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 6205 }
6206
0438d37f 6207 if (MEM_P (operands[1]) && optimize > 0)
6cffc037 6208 {
6209 rtx reg = gen_reg_rtx (SImode);
6210
6211 emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
6212 operands[1] = gen_lowpart (QImode, reg);
6213 }
6214
0438d37f 6215 if (MEM_P (operands[0]))
6cffc037 6216 operands[1] = force_reg (QImode, operands[1]);
6217 }
6218 else if (TARGET_THUMB
0438d37f 6219 && CONST_INT_P (operands[1])
234f6557 6220 && !satisfies_constraint_I (operands[1]))
6cffc037 6221 {
674a8f0b 6222 /* Handle loading a large integer during reload. */
cffb2a26 6223
6cffc037 6224 /* Writing a constant to memory needs a scratch, which should
6225 be handled with SECONDARY_RELOADs. */
0438d37f 6226 gcc_assert (REG_P (operands[0]));
6cffc037 6227
6228 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
6229 emit_insn (gen_movsi (operands[0], operands[1]));
6230 DONE;
cffb2a26 6231 }
6232 "
6233)
b11cae9e 6234
cffb2a26 6235(define_insn "*arm_movqi_insn"
fd711051 6236 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,l,r,l,Uu,r,m")
490f62ca 6237 (match_operand:QI 1 "general_operand" "rk,rk,I,Py,K,Uu,l,Uh,r"))]
25f905c2 6238 "TARGET_32BIT
cffb2a26 6239 && ( register_operand (operands[0], QImode)
6240 || register_operand (operands[1], QImode))"
5565501b 6241 "@
fd711051 6242 mov%?\\t%0, %1
6243 mov%?\\t%0, %1
65f68e55 6244 mov%?\\t%0, %1
5565501b 6245 mov%?\\t%0, %1
6246 mvn%?\\t%0, #%B1
3ef90e77 6247 ldrb%?\\t%0, %1
6248 strb%?\\t%1, %0
6249 ldrb%?\\t%0, %1
6250 strb%?\\t%1, %0"
9f2c2a36 6251 [(set_attr "type" "mov_reg,mov_reg,mov_imm,mov_imm,mvn_imm,load_4,store_4,load_4,store_4")
a54e3e7b 6252 (set_attr "predicable" "yes")
5233bf6a 6253 (set_attr "predicable_short_it" "yes,yes,no,yes,no,no,no,no,no")
fd711051 6254 (set_attr "arch" "t2,any,any,t2,any,t2,t2,any,any")
6255 (set_attr "length" "2,4,4,2,4,2,2,4,4")]
cffb2a26 6256)
6257
9b8516be 6258;; HFmode moves
6259(define_expand "movhf"
3934ae0e 6260 [(set (match_operand:HF 0 "general_operand")
6261 (match_operand:HF 1 "general_operand"))]
9b8516be 6262 "TARGET_EITHER"
6263 "
e723310d 6264 gcc_checking_assert (aligned_operand (operands[0], HFmode));
6265 gcc_checking_assert (aligned_operand (operands[1], HFmode));
9b8516be 6266 if (TARGET_32BIT)
6267 {
0438d37f 6268 if (MEM_P (operands[0]))
9b8516be 6269 operands[1] = force_reg (HFmode, operands[1]);
6270 }
6271 else /* TARGET_THUMB1 */
6272 {
6273 if (can_create_pseudo_p ())
6274 {
0438d37f 6275 if (!REG_P (operands[0]))
9b8516be 6276 operands[1] = force_reg (HFmode, operands[1]);
6277 }
6278 }
6279 "
6280)
6281
6282(define_insn "*arm32_movhf"
6283 [(set (match_operand:HF 0 "nonimmediate_operand" "=r,m,r,r")
6284 (match_operand:HF 1 "general_operand" " m,r,r,F"))]
d7216193 6285 "TARGET_32BIT && !TARGET_HARD_FLOAT
9b8516be 6286 && ( s_register_operand (operands[0], HFmode)
6287 || s_register_operand (operands[1], HFmode))"
6288 "*
6289 switch (which_alternative)
6290 {
6291 case 0: /* ARM register from memory */
3ef90e77 6292 return \"ldrh%?\\t%0, %1\\t%@ __fp16\";
9b8516be 6293 case 1: /* memory from ARM register */
3ef90e77 6294 return \"strh%?\\t%1, %0\\t%@ __fp16\";
9b8516be 6295 case 2: /* ARM register from ARM register */
6296 return \"mov%?\\t%0, %1\\t%@ __fp16\";
6297 case 3: /* ARM register from constant */
6298 {
9b8516be 6299 long bits;
6300 rtx ops[4];
6301
945f7b03 6302 bits = real_to_target (NULL, CONST_DOUBLE_REAL_VALUE (operands[1]),
6303 HFmode);
9b8516be 6304 ops[0] = operands[0];
6305 ops[1] = GEN_INT (bits);
6306 ops[2] = GEN_INT (bits & 0xff00);
6307 ops[3] = GEN_INT (bits & 0x00ff);
6308
6309 if (arm_arch_thumb2)
6310 output_asm_insn (\"movw%?\\t%0, %1\", ops);
6311 else
6312 output_asm_insn (\"mov%?\\t%0, %2\;orr%?\\t%0, %0, %3\", ops);
6313 return \"\";
6314 }
6315 default:
6316 gcc_unreachable ();
6317 }
6318 "
6319 [(set_attr "conds" "unconditional")
9f2c2a36 6320 (set_attr "type" "load_4,store_4,mov_reg,multiple")
9b8516be 6321 (set_attr "length" "4,4,4,8")
8bdfd6ed 6322 (set_attr "predicable" "yes")]
9b8516be 6323)
6324
87b22bf7 6325(define_expand "movsf"
3934ae0e 6326 [(set (match_operand:SF 0 "general_operand")
6327 (match_operand:SF 1 "general_operand"))]
cffb2a26 6328 "TARGET_EITHER"
87b22bf7 6329 "
e723310d 6330 gcc_checking_assert (aligned_operand (operands[0], SFmode));
6331 gcc_checking_assert (aligned_operand (operands[1], SFmode));
25f905c2 6332 if (TARGET_32BIT)
cffb2a26 6333 {
0438d37f 6334 if (MEM_P (operands[0]))
cffb2a26 6335 operands[1] = force_reg (SFmode, operands[1]);
6336 }
25f905c2 6337 else /* TARGET_THUMB1 */
cffb2a26 6338 {
e1ba4a27 6339 if (can_create_pseudo_p ())
cffb2a26 6340 {
0438d37f 6341 if (!REG_P (operands[0]))
cffb2a26 6342 operands[1] = force_reg (SFmode, operands[1]);
6343 }
6344 }
581f16e5 6345
6346 /* Cannot load it directly, generate a load with clobber so that it can be
6347 loaded via GPR with MOV / MOVT. */
6348 if (arm_disable_literal_pool
6349 && (REG_P (operands[0]) || SUBREG_P (operands[0]))
6350 && CONST_DOUBLE_P (operands[1])
6351 && TARGET_HARD_FLOAT
6352 && !vfp3_const_double_rtx (operands[1]))
6353 {
6354 rtx clobreg = gen_reg_rtx (SFmode);
6355 emit_insn (gen_no_literal_pool_sf_immediate (operands[0], operands[1],
6356 clobreg));
6357 DONE;
6358 }
cffb2a26 6359 "
6360)
6361
03d440a6 6362;; Transform a floating-point move of a constant into a core register into
6363;; an SImode operation.
cffb2a26 6364(define_split
03d440a6 6365 [(set (match_operand:SF 0 "arm_general_register_operand" "")
cffb2a26 6366 (match_operand:SF 1 "immediate_operand" ""))]
339034d0 6367 "TARGET_EITHER
cffb2a26 6368 && reload_completed
0438d37f 6369 && CONST_DOUBLE_P (operands[1])"
cffb2a26 6370 [(set (match_dup 2) (match_dup 3))]
6371 "
6372 operands[2] = gen_lowpart (SImode, operands[0]);
6373 operands[3] = gen_lowpart (SImode, operands[1]);
6374 if (operands[2] == 0 || operands[3] == 0)
6375 FAIL;
215b30b3 6376 "
6377)
87b22bf7 6378
cffb2a26 6379(define_insn "*arm_movsf_soft_insn"
6380 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
6381 (match_operand:SF 1 "general_operand" "r,mE,r"))]
cde1623a 6382 "TARGET_32BIT
cffb2a26 6383 && TARGET_SOFT_FLOAT
0438d37f 6384 && (!MEM_P (operands[0])
215b30b3 6385 || register_operand (operands[1], SFmode))"
581f16e5 6386{
6387 switch (which_alternative)
6388 {
6389 case 0: return \"mov%?\\t%0, %1\";
6390 case 1:
6391 /* Cannot load it directly, split to load it via MOV / MOVT. */
6392 if (!MEM_P (operands[1]) && arm_disable_literal_pool)
6393 return \"#\";
6394 return \"ldr%?\\t%0, %1\\t%@ float\";
6395 case 2: return \"str%?\\t%1, %0\\t%@ float\";
6396 default: gcc_unreachable ();
6397 }
6398}
cde1623a 6399 [(set_attr "predicable" "yes")
9f2c2a36 6400 (set_attr "type" "mov_reg,load_4,store_4")
42e1de19 6401 (set_attr "arm_pool_range" "*,4096,*")
6402 (set_attr "thumb2_pool_range" "*,4094,*")
cde1623a 6403 (set_attr "arm_neg_pool_range" "*,4084,*")
6404 (set_attr "thumb2_neg_pool_range" "*,0,*")]
cffb2a26 6405)
6406
581f16e5 6407;; Splitter for the above.
6408(define_split
6409 [(set (match_operand:SF 0 "s_register_operand")
6410 (match_operand:SF 1 "const_double_operand"))]
6411 "arm_disable_literal_pool && TARGET_SOFT_FLOAT"
6412 [(const_int 0)]
6413{
6414 long buf;
6415 real_to_target (&buf, CONST_DOUBLE_REAL_VALUE (operands[1]), SFmode);
6416 rtx cst = gen_int_mode (buf, SImode);
6417 emit_move_insn (simplify_gen_subreg (SImode, operands[0], SFmode, 0), cst);
6418 DONE;
6419}
6420)
6421
9c08d1fa 6422(define_expand "movdf"
3934ae0e 6423 [(set (match_operand:DF 0 "general_operand")
6424 (match_operand:DF 1 "general_operand"))]
cffb2a26 6425 "TARGET_EITHER"
9c08d1fa 6426 "
e723310d 6427 gcc_checking_assert (aligned_operand (operands[0], DFmode));
6428 gcc_checking_assert (aligned_operand (operands[1], DFmode));
25f905c2 6429 if (TARGET_32BIT)
cffb2a26 6430 {
0438d37f 6431 if (MEM_P (operands[0]))
cffb2a26 6432 operands[1] = force_reg (DFmode, operands[1]);
6433 }
6434 else /* TARGET_THUMB */
6435 {
e1ba4a27 6436 if (can_create_pseudo_p ())
cffb2a26 6437 {
0438d37f 6438 if (!REG_P (operands[0]))
cffb2a26 6439 operands[1] = force_reg (DFmode, operands[1]);
6440 }
6441 }
581f16e5 6442
6443 /* Cannot load it directly, generate a load with clobber so that it can be
6444 loaded via GPR with MOV / MOVT. */
6445 if (arm_disable_literal_pool
6446 && (REG_P (operands[0]) || SUBREG_P (operands[0]))
6447 && CONSTANT_P (operands[1])
6448 && TARGET_HARD_FLOAT
6449 && !arm_const_double_rtx (operands[1])
6450 && !(TARGET_VFP_DOUBLE && vfp3_const_double_rtx (operands[1])))
6451 {
6452 rtx clobreg = gen_reg_rtx (DFmode);
6453 emit_insn (gen_no_literal_pool_df_immediate (operands[0], operands[1],
6454 clobreg));
6455 DONE;
6456 }
cffb2a26 6457 "
6458)
b11cae9e 6459
9c08d1fa 6460;; Reloading a df mode value stored in integer regs to memory can require a
6461;; scratch reg.
3934ae0e 6462;; Another reload_out<m> pattern that requires special constraints.
9c08d1fa 6463(define_expand "reload_outdf"
cffb2a26 6464 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
87b22bf7 6465 (match_operand:DF 1 "s_register_operand" "r")
6466 (match_operand:SI 2 "s_register_operand" "=&r")]
06adefdc 6467 "TARGET_THUMB2"
87b22bf7 6468 "
215b30b3 6469 {
6470 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
f7fbdd4a 6471
215b30b3 6472 if (code == REG)
6473 operands[2] = XEXP (operands[0], 0);
6474 else if (code == POST_INC || code == PRE_DEC)
6475 {
6476 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
6477 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
6478 emit_insn (gen_movdi (operands[0], operands[1]));
6479 DONE;
6480 }
6481 else if (code == PRE_INC)
6482 {
6483 rtx reg = XEXP (XEXP (operands[0], 0), 0);
f7fbdd4a 6484
215b30b3 6485 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
6486 operands[2] = reg;
6487 }
6488 else if (code == POST_DEC)
6489 operands[2] = XEXP (XEXP (operands[0], 0), 0);
6490 else
6491 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
6492 XEXP (XEXP (operands[0], 0), 1)));
f7fbdd4a 6493
d1f9b275 6494 emit_insn (gen_rtx_SET (replace_equiv_address (operands[0], operands[2]),
215b30b3 6495 operands[1]));
f7fbdd4a 6496
215b30b3 6497 if (code == POST_DEC)
6498 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
6499
6500 DONE;
6501 }"
6502)
9c08d1fa 6503
9a1112d7 6504(define_insn "*movdf_soft_insn"
8f1c7041 6505 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,r,m")
6506 (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))]
cde1623a 6507 "TARGET_32BIT && TARGET_SOFT_FLOAT
b2778788 6508 && ( register_operand (operands[0], DFmode)
6509 || register_operand (operands[1], DFmode))"
d51f92df 6510 "*
6511 switch (which_alternative)
6512 {
6513 case 0:
6514 case 1:
6515 case 2:
6516 return \"#\";
581f16e5 6517 case 3:
6518 /* Cannot load it directly, split to load it via MOV / MOVT. */
6519 if (!MEM_P (operands[1]) && arm_disable_literal_pool)
6520 return \"#\";
6521 /* Fall through. */
d51f92df 6522 default:
26ff80c0 6523 return output_move_double (operands, true, NULL);
d51f92df 6524 }
6525 "
359a6e9f 6526 [(set_attr "length" "8,12,16,8,8")
9f2c2a36 6527 (set_attr "type" "multiple,multiple,multiple,load_8,store_8")
42e1de19 6528 (set_attr "arm_pool_range" "*,*,*,1020,*")
6529 (set_attr "thumb2_pool_range" "*,*,*,1018,*")
8848d797 6530 (set_attr "arm_neg_pool_range" "*,*,*,1004,*")
cde1623a 6531 (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
cffb2a26 6532)
581f16e5 6533
6534;; Splitter for the above.
6535(define_split
6536 [(set (match_operand:DF 0 "s_register_operand")
6537 (match_operand:DF 1 "const_double_operand"))]
6538 "arm_disable_literal_pool && TARGET_SOFT_FLOAT"
6539 [(const_int 0)]
6540{
6541 long buf[2];
6542 int order = BYTES_BIG_ENDIAN ? 1 : 0;
6543 real_to_target (buf, CONST_DOUBLE_REAL_VALUE (operands[1]), DFmode);
6544 unsigned HOST_WIDE_INT ival = zext_hwi (buf[order], 32);
6545 ival |= (zext_hwi (buf[1 - order], 32) << 32);
6546 rtx cst = gen_int_mode (ival, DImode);
6547 emit_move_insn (simplify_gen_subreg (DImode, operands[0], DFmode, 0), cst);
6548 DONE;
6549}
6550)
b11cae9e 6551\f
b11cae9e 6552
9c08d1fa 6553;; load- and store-multiple insns
6554;; The arm can load/store any set of registers, provided that they are in
320ea44d 6555;; ascending order, but these expanders assume a contiguous set.
b11cae9e 6556
9c08d1fa 6557(define_expand "load_multiple"
6558 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6559 (match_operand:SI 1 "" ""))
6560 (use (match_operand:SI 2 "" ""))])]
25f905c2 6561 "TARGET_32BIT"
9580c25f 6562{
6563 HOST_WIDE_INT offset = 0;
6564
bd5b4116 6565 /* Support only fixed point registers. */
0438d37f 6566 if (!CONST_INT_P (operands[2])
6e628811 6567 || INTVAL (operands[2]) > MAX_LDM_STM_OPS
9c08d1fa 6568 || INTVAL (operands[2]) < 2
0438d37f 6569 || !MEM_P (operands[1])
6570 || !REG_P (operands[0])
bd5b4116 6571 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
6572 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 6573 FAIL;
6574
6575 operands[3]
320ea44d 6576 = arm_gen_load_multiple (arm_regs_in_sequence + REGNO (operands[0]),
6577 INTVAL (operands[2]),
f082f1c4 6578 force_reg (SImode, XEXP (operands[1], 0)),
320ea44d 6579 FALSE, operands[1], &offset);
9580c25f 6580})
b11cae9e 6581
9c08d1fa 6582(define_expand "store_multiple"
6583 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6584 (match_operand:SI 1 "" ""))
6585 (use (match_operand:SI 2 "" ""))])]
25f905c2 6586 "TARGET_32BIT"
9580c25f 6587{
6588 HOST_WIDE_INT offset = 0;
6589
674a8f0b 6590 /* Support only fixed point registers. */
0438d37f 6591 if (!CONST_INT_P (operands[2])
6e628811 6592 || INTVAL (operands[2]) > MAX_LDM_STM_OPS
9c08d1fa 6593 || INTVAL (operands[2]) < 2
0438d37f 6594 || !REG_P (operands[1])
6595 || !MEM_P (operands[0])
bd5b4116 6596 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
6597 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 6598 FAIL;
6599
6600 operands[3]
320ea44d 6601 = arm_gen_store_multiple (arm_regs_in_sequence + REGNO (operands[1]),
6602 INTVAL (operands[2]),
f082f1c4 6603 force_reg (SImode, XEXP (operands[0], 0)),
320ea44d 6604 FALSE, operands[0], &offset);
9580c25f 6605})
b11cae9e 6606
9c08d1fa 6607
e34ebfca 6608(define_expand "setmemsi"
3934ae0e 6609 [(match_operand:BLK 0 "general_operand")
6610 (match_operand:SI 1 "const_int_operand")
6611 (match_operand:SI 2 "const_int_operand")
6612 (match_operand:SI 3 "const_int_operand")]
e34ebfca 6613 "TARGET_32BIT"
6614{
6615 if (arm_gen_setmem (operands))
6616 DONE;
6617
6618 FAIL;
6619})
6620
6621
9c08d1fa 6622;; Move a block of memory if it is word aligned and MORE than 2 words long.
6623;; We could let this apply for blocks of less than this, but it clobbers so
6624;; many registers that there is then probably a better way.
6625
f135a8d4 6626(define_expand "cpymemqi"
3934ae0e 6627 [(match_operand:BLK 0 "general_operand")
6628 (match_operand:BLK 1 "general_operand")
6629 (match_operand:SI 2 "const_int_operand")
6630 (match_operand:SI 3 "const_int_operand")]
ae51a965 6631 ""
9c08d1fa 6632 "
25f905c2 6633 if (TARGET_32BIT)
cffb2a26 6634 {
ae51a965 6635 if (TARGET_LDRD && current_tune->prefer_ldrd_strd
6636 && !optimize_function_for_size_p (cfun))
6637 {
f135a8d4 6638 if (gen_cpymem_ldrd_strd (operands))
ae51a965 6639 DONE;
6640 FAIL;
6641 }
6642
f135a8d4 6643 if (arm_gen_cpymemqi (operands))
cffb2a26 6644 DONE;
6645 FAIL;
6646 }
25f905c2 6647 else /* TARGET_THUMB1 */
cffb2a26 6648 {
6649 if ( INTVAL (operands[3]) != 4
6650 || INTVAL (operands[2]) > 48)
6651 FAIL;
6652
f135a8d4 6653 thumb_expand_cpymemqi (operands);
cffb2a26 6654 DONE;
6655 }
6656 "
6657)
9c08d1fa 6658\f
b11cae9e 6659
341940e8 6660;; Compare & branch insns
8d232dc7 6661;; The range calculations are based as follows:
341940e8 6662;; For forward branches, the address calculation returns the address of
6663;; the next instruction. This is 2 beyond the branch instruction.
6664;; For backward branches, the address calculation returns the address of
6665;; the first instruction in this pattern (cmp). This is 2 before the branch
6666;; instruction for the shortest sequence, and 4 before the branch instruction
6667;; if we have to jump around an unconditional branch.
6668;; To the basic branch range the PC offset must be added (this is +4).
6669;; So for forward branches we have
6670;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
6671;; And for backward branches we have
6672;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
6673;;
6674;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
6675;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
cffb2a26 6676
aeac46d4 6677(define_expand "cbranchsi4"
6678 [(set (pc) (if_then_else
aa06947a 6679 (match_operator 0 "expandable_comparison_operator"
3934ae0e 6680 [(match_operand:SI 1 "s_register_operand")
6681 (match_operand:SI 2 "nonmemory_operand")])
aeac46d4 6682 (label_ref (match_operand 3 "" ""))
6683 (pc)))]
f9aa4160 6684 "TARGET_EITHER"
aeac46d4 6685 "
74f4459c 6686 if (!TARGET_THUMB1)
6687 {
f9aa4160 6688 if (!arm_validize_comparison (&operands[0], &operands[1], &operands[2]))
6689 FAIL;
74f4459c 6690 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6691 operands[3]));
6692 DONE;
6693 }
25f905c2 6694 if (thumb1_cmpneg_operand (operands[2], SImode))
aeac46d4 6695 {
6696 emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
6697 operands[3], operands[0]));
6698 DONE;
6699 }
25f905c2 6700 if (!thumb1_cmp_operand (operands[2], SImode))
aeac46d4 6701 operands[2] = force_reg (SImode, operands[2]);
6702 ")
6703
74f4459c 6704(define_expand "cbranchsf4"
6705 [(set (pc) (if_then_else
aa06947a 6706 (match_operator 0 "expandable_comparison_operator"
3934ae0e 6707 [(match_operand:SF 1 "s_register_operand")
6708 (match_operand:SF 2 "vfp_compare_operand")])
74f4459c 6709 (label_ref (match_operand 3 "" ""))
6710 (pc)))]
6711 "TARGET_32BIT && TARGET_HARD_FLOAT"
6712 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6713 operands[3])); DONE;"
6714)
6715
6716(define_expand "cbranchdf4"
6717 [(set (pc) (if_then_else
aa06947a 6718 (match_operator 0 "expandable_comparison_operator"
3934ae0e 6719 [(match_operand:DF 1 "s_register_operand")
6720 (match_operand:DF 2 "vfp_compare_operand")])
74f4459c 6721 (label_ref (match_operand 3 "" ""))
6722 (pc)))]
a50d7267 6723 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
74f4459c 6724 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6725 operands[3])); DONE;"
6726)
6727
74f4459c 6728(define_expand "cbranchdi4"
6729 [(set (pc) (if_then_else
aa06947a 6730 (match_operator 0 "expandable_comparison_operator"
3934ae0e 6731 [(match_operand:DI 1 "s_register_operand")
d6852b47 6732 (match_operand:DI 2 "reg_or_int_operand")])
74f4459c 6733 (label_ref (match_operand 3 "" ""))
6734 (pc)))]
a8045a4f 6735 "TARGET_32BIT"
6736 "{
0438d37f 6737 if (!arm_validize_comparison (&operands[0], &operands[1], &operands[2]))
f9aa4160 6738 FAIL;
6739 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
a8045a4f 6740 operands[3]));
6741 DONE;
6742 }"
74f4459c 6743)
6744
9c08d1fa 6745;; Comparison and test insns
6746
cffb2a26 6747(define_insn "*arm_cmpsi_insn"
bd5b4116 6748 [(set (reg:CC CC_REGNUM)
f9f234ec 6749 (compare:CC (match_operand:SI 0 "s_register_operand" "l,r,r,r,r")
6750 (match_operand:SI 1 "arm_add_operand" "Py,r,r,I,L")))]
25f905c2 6751 "TARGET_32BIT"
5565501b 6752 "@
a6864a24 6753 cmp%?\\t%0, %1
6754 cmp%?\\t%0, %1
aea4c774 6755 cmp%?\\t%0, %1
f9f234ec 6756 cmp%?\\t%0, %1
aea4c774 6757 cmn%?\\t%0, #%n1"
a6864a24 6758 [(set_attr "conds" "set")
f9f234ec 6759 (set_attr "arch" "t2,t2,any,any,any")
6760 (set_attr "length" "2,2,4,4,4")
65f68e55 6761 (set_attr "predicable" "yes")
f9f234ec 6762 (set_attr "predicable_short_it" "yes,yes,yes,no,no")
112eda6f 6763 (set_attr "type" "alus_imm,alus_sreg,alus_sreg,alus_imm,alus_imm")]
cffb2a26 6764)
b11cae9e 6765
d5d4dc8d 6766(define_insn "*cmpsi_shiftsi"
bd5b4116 6767 [(set (reg:CC CC_REGNUM)
d82e788e 6768 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r,r")
cffb2a26 6769 (match_operator:SI 3 "shift_operator"
d82e788e 6770 [(match_operand:SI 1 "s_register_operand" "r,r,r")
6771 (match_operand:SI 2 "shift_amount_operand" "M,r,M")])))]
d5d4dc8d 6772 "TARGET_32BIT"
f9f234ec 6773 "cmp\\t%0, %1%S3"
344495ea 6774 [(set_attr "conds" "set")
331beb1a 6775 (set_attr "shift" "1")
d82e788e 6776 (set_attr "arch" "32,a,a")
282b4c75 6777 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
b11cae9e 6778
d5d4dc8d 6779(define_insn "*cmpsi_shiftsi_swp"
bd5b4116 6780 [(set (reg:CC_SWP CC_REGNUM)
aea4c774 6781 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
d82e788e 6782 [(match_operand:SI 1 "s_register_operand" "r,r,r")
6783 (match_operand:SI 2 "shift_amount_operand" "M,r,M")])
6784 (match_operand:SI 0 "s_register_operand" "r,r,r")))]
d5d4dc8d 6785 "TARGET_32BIT"
aea4c774 6786 "cmp%?\\t%0, %1%S3"
344495ea 6787 [(set_attr "conds" "set")
331beb1a 6788 (set_attr "shift" "1")
d82e788e 6789 (set_attr "arch" "32,a,a")
282b4c75 6790 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
b11cae9e 6791
25f905c2 6792(define_insn "*arm_cmpsi_negshiftsi_si"
aed179ae 6793 [(set (reg:CC_Z CC_REGNUM)
6794 (compare:CC_Z
6795 (neg:SI (match_operator:SI 1 "shift_operator"
6796 [(match_operand:SI 2 "s_register_operand" "r")
6797 (match_operand:SI 3 "reg_or_int_operand" "rM")]))
6798 (match_operand:SI 0 "s_register_operand" "r")))]
cffb2a26 6799 "TARGET_ARM"
aed179ae 6800 "cmn%?\\t%0, %2%S1"
344495ea 6801 [(set_attr "conds" "set")
aed179ae 6802 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
d82e788e 6803 (const_string "alus_shift_imm")
6804 (const_string "alus_shift_reg")))
596e5e8f 6805 (set_attr "predicable" "yes")]
0d66636f 6806)
b11cae9e 6807
9c08d1fa 6808; This insn allows redundant compares to be removed by cse, nothing should
6809; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
6810; is deleted later on. The match_dup will match the mode here, so that
6811; mode changes of the condition codes aren't lost by this even though we don't
6812; specify what they are.
6813
8a18b90c 6814(define_insn "*deleted_compare"
9c08d1fa 6815 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
25f905c2 6816 "TARGET_32BIT"
40dbec34 6817 "\\t%@ deleted compare"
cffb2a26 6818 [(set_attr "conds" "set")
1b7da4ac 6819 (set_attr "length" "0")
6820 (set_attr "type" "no_insn")]
cffb2a26 6821)
9c08d1fa 6822
6823\f
6824;; Conditional branch insns
6825
74f4459c 6826(define_expand "cbranch_cc"
9c08d1fa 6827 [(set (pc)
74f4459c 6828 (if_then_else (match_operator 0 "" [(match_operand 1 "" "")
6829 (match_operand 2 "" "")])
6830 (label_ref (match_operand 3 "" ""))
9c08d1fa 6831 (pc)))]
25f905c2 6832 "TARGET_32BIT"
74f4459c 6833 "operands[1] = arm_gen_compare_reg (GET_CODE (operands[0]),
e1b93706 6834 operands[1], operands[2], NULL_RTX);
74f4459c 6835 operands[2] = const0_rtx;"
8fa3ba89 6836)
6837
6838;;
6839;; Patterns to match conditional branch insns.
6840;;
6841
ffcc986d 6842(define_insn "arm_cond_branch"
9c08d1fa 6843 [(set (pc)
8fa3ba89 6844 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 6845 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 6846 (label_ref (match_operand 0 "" ""))
6847 (pc)))]
25f905c2 6848 "TARGET_32BIT"
d75350ce 6849 "*
9c08d1fa 6850 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 6851 {
6852 arm_ccfsm_state += 2;
6853 return \"\";
6854 }
e2348bcb 6855 return \"b%d1\\t%l0\";
cffb2a26 6856 "
a2cd141b 6857 [(set_attr "conds" "use")
a6864a24 6858 (set_attr "type" "branch")
6859 (set (attr "length")
6860 (if_then_else
0bf497f5 6861 (and (match_test "TARGET_THUMB2")
a6864a24 6862 (and (ge (minus (match_dup 0) (pc)) (const_int -250))
6863 (le (minus (match_dup 0) (pc)) (const_int 256))))
6864 (const_int 2)
6865 (const_int 4)))]
cffb2a26 6866)
d75350ce 6867
cffb2a26 6868(define_insn "*arm_cond_branch_reversed"
9c08d1fa 6869 [(set (pc)
8fa3ba89 6870 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 6871 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 6872 (pc)
6873 (label_ref (match_operand 0 "" ""))))]
25f905c2 6874 "TARGET_32BIT"
d75350ce 6875 "*
9c08d1fa 6876 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 6877 {
6878 arm_ccfsm_state += 2;
6879 return \"\";
6880 }
e2348bcb 6881 return \"b%D1\\t%l0\";
cffb2a26 6882 "
a2cd141b 6883 [(set_attr "conds" "use")
a6864a24 6884 (set_attr "type" "branch")
6885 (set (attr "length")
6886 (if_then_else
0bf497f5 6887 (and (match_test "TARGET_THUMB2")
a6864a24 6888 (and (ge (minus (match_dup 0) (pc)) (const_int -250))
6889 (le (minus (match_dup 0) (pc)) (const_int 256))))
6890 (const_int 2)
6891 (const_int 4)))]
cffb2a26 6892)
6893
b11cae9e 6894\f
9c08d1fa 6895
6896; scc insns
6897
74f4459c 6898(define_expand "cstore_cc"
3934ae0e 6899 [(set (match_operand:SI 0 "s_register_operand")
74f4459c 6900 (match_operator:SI 1 "" [(match_operand 2 "" "")
6901 (match_operand 3 "" "")]))]
25f905c2 6902 "TARGET_32BIT"
74f4459c 6903 "operands[2] = arm_gen_compare_reg (GET_CODE (operands[1]),
e1b93706 6904 operands[2], operands[3], NULL_RTX);
74f4459c 6905 operands[3] = const0_rtx;"
8fa3ba89 6906)
6907
a3b84066 6908(define_insn_and_split "*mov_scc"
9c08d1fa 6909 [(set (match_operand:SI 0 "s_register_operand" "=r")
ff74dd54 6910 (match_operator:SI 1 "arm_comparison_operator_mode"
8a18b90c 6911 [(match_operand 2 "cc_register" "") (const_int 0)]))]
cffb2a26 6912 "TARGET_ARM"
a3b84066 6913 "#" ; "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
6914 "TARGET_ARM"
6915 [(set (match_dup 0)
6916 (if_then_else:SI (match_dup 1)
6917 (const_int 1)
6918 (const_int 0)))]
6919 ""
cffb2a26 6920 [(set_attr "conds" "use")
1b7da4ac 6921 (set_attr "length" "8")
6922 (set_attr "type" "multiple")]
cffb2a26 6923)
9c08d1fa 6924
01089cc7 6925(define_insn "*negscc_borrow"
6926 [(set (match_operand:SI 0 "s_register_operand" "=r")
6927 (neg:SI (match_operand:SI 1 "arm_borrow_operation" "")))]
6928 "TARGET_32BIT"
6929 "sbc\\t%0, %0, %0"
6930 [(set_attr "conds" "use")
6931 (set_attr "length" "4")
6932 (set_attr "type" "adc_reg")]
6933)
6934
a3b84066 6935(define_insn_and_split "*mov_negscc"
9c08d1fa 6936 [(set (match_operand:SI 0 "s_register_operand" "=r")
ff74dd54 6937 (neg:SI (match_operator:SI 1 "arm_comparison_operator_mode"
8a18b90c 6938 [(match_operand 2 "cc_register" "") (const_int 0)])))]
01089cc7 6939 "TARGET_ARM && !arm_borrow_operation (operands[1], SImode)"
a3b84066 6940 "#" ; "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
01089cc7 6941 "&& true"
a3b84066 6942 [(set (match_dup 0)
6943 (if_then_else:SI (match_dup 1)
6944 (match_dup 3)
6945 (const_int 0)))]
6946 {
6947 operands[3] = GEN_INT (~0);
6948 }
cffb2a26 6949 [(set_attr "conds" "use")
1b7da4ac 6950 (set_attr "length" "8")
6951 (set_attr "type" "multiple")]
cffb2a26 6952)
9c08d1fa 6953
a3b84066 6954(define_insn_and_split "*mov_notscc"
9c08d1fa 6955 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 6956 (not:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 6957 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 6958 "TARGET_ARM"
a3b84066 6959 "#" ; "mvn%D1\\t%0, #0\;mvn%d1\\t%0, #1"
6960 "TARGET_ARM"
6961 [(set (match_dup 0)
6962 (if_then_else:SI (match_dup 1)
6963 (match_dup 3)
6964 (match_dup 4)))]
6965 {
6966 operands[3] = GEN_INT (~1);
6967 operands[4] = GEN_INT (~0);
6968 }
cffb2a26 6969 [(set_attr "conds" "use")
1b7da4ac 6970 (set_attr "length" "8")
6971 (set_attr "type" "multiple")]
cffb2a26 6972)
9c08d1fa 6973
595d88b5 6974(define_expand "cstoresi4"
3934ae0e 6975 [(set (match_operand:SI 0 "s_register_operand")
aa06947a 6976 (match_operator:SI 1 "expandable_comparison_operator"
3934ae0e 6977 [(match_operand:SI 2 "s_register_operand")
6978 (match_operand:SI 3 "reg_or_int_operand")]))]
74f4459c 6979 "TARGET_32BIT || TARGET_THUMB1"
595d88b5 6980 "{
6981 rtx op3, scratch, scratch2;
6982
74f4459c 6983 if (!TARGET_THUMB1)
6984 {
6985 if (!arm_add_operand (operands[3], SImode))
6986 operands[3] = force_reg (SImode, operands[3]);
6987 emit_insn (gen_cstore_cc (operands[0], operands[1],
6988 operands[2], operands[3]));
6989 DONE;
6990 }
6991
595d88b5 6992 if (operands[3] == const0_rtx)
6993 {
6994 switch (GET_CODE (operands[1]))
6995 {
6996 case EQ:
25f905c2 6997 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], operands[2]));
595d88b5 6998 break;
6999
7000 case NE:
25f905c2 7001 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], operands[2]));
595d88b5 7002 break;
7003
7004 case LE:
7005 scratch = expand_binop (SImode, add_optab, operands[2], constm1_rtx,
7006 NULL_RTX, 0, OPTAB_WIDEN);
7007 scratch = expand_binop (SImode, ior_optab, operands[2], scratch,
7008 NULL_RTX, 0, OPTAB_WIDEN);
7009 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7010 operands[0], 1, OPTAB_WIDEN);
7011 break;
7012
7013 case GE:
7014 scratch = expand_unop (SImode, one_cmpl_optab, operands[2],
7015 NULL_RTX, 1);
7016 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7017 NULL_RTX, 1, OPTAB_WIDEN);
7018 break;
7019
7020 case GT:
7021 scratch = expand_binop (SImode, ashr_optab, operands[2],
7022 GEN_INT (31), NULL_RTX, 0, OPTAB_WIDEN);
7023 scratch = expand_binop (SImode, sub_optab, scratch, operands[2],
7024 NULL_RTX, 0, OPTAB_WIDEN);
7025 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31), operands[0],
7026 0, OPTAB_WIDEN);
7027 break;
7028
7029 /* LT is handled by generic code. No need for unsigned with 0. */
7030 default:
7031 FAIL;
7032 }
7033 DONE;
7034 }
7035
7036 switch (GET_CODE (operands[1]))
7037 {
7038 case EQ:
7039 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7040 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7041 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], scratch));
595d88b5 7042 break;
7043
7044 case NE:
7045 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7046 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7047 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], scratch));
595d88b5 7048 break;
7049
7050 case LE:
7051 op3 = force_reg (SImode, operands[3]);
7052
7053 scratch = expand_binop (SImode, lshr_optab, operands[2], GEN_INT (31),
7054 NULL_RTX, 1, OPTAB_WIDEN);
7055 scratch2 = expand_binop (SImode, ashr_optab, op3, GEN_INT (31),
7056 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7057 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
595d88b5 7058 op3, operands[2]));
7059 break;
7060
7061 case GE:
7062 op3 = operands[3];
25f905c2 7063 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7064 op3 = force_reg (SImode, op3);
7065 scratch = expand_binop (SImode, ashr_optab, operands[2], GEN_INT (31),
7066 NULL_RTX, 0, OPTAB_WIDEN);
7067 scratch2 = expand_binop (SImode, lshr_optab, op3, GEN_INT (31),
7068 NULL_RTX, 1, OPTAB_WIDEN);
25f905c2 7069 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
595d88b5 7070 operands[2], op3));
7071 break;
7072
7073 case LEU:
7074 op3 = force_reg (SImode, operands[3]);
7075 scratch = force_reg (SImode, const0_rtx);
25f905c2 7076 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
595d88b5 7077 op3, operands[2]));
7078 break;
7079
7080 case GEU:
7081 op3 = operands[3];
25f905c2 7082 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7083 op3 = force_reg (SImode, op3);
7084 scratch = force_reg (SImode, const0_rtx);
25f905c2 7085 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
595d88b5 7086 operands[2], op3));
7087 break;
7088
7089 case LTU:
7090 op3 = operands[3];
25f905c2 7091 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7092 op3 = force_reg (SImode, op3);
7093 scratch = gen_reg_rtx (SImode);
408b7ae5 7094 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], operands[2], op3));
595d88b5 7095 break;
7096
7097 case GTU:
7098 op3 = force_reg (SImode, operands[3]);
7099 scratch = gen_reg_rtx (SImode);
408b7ae5 7100 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], op3, operands[2]));
595d88b5 7101 break;
7102
7103 /* No good sequences for GT, LT. */
7104 default:
7105 FAIL;
7106 }
7107 DONE;
7108}")
7109
9854d864 7110(define_expand "cstorehf4"
7111 [(set (match_operand:SI 0 "s_register_operand")
7112 (match_operator:SI 1 "expandable_comparison_operator"
7113 [(match_operand:HF 2 "s_register_operand")
d7216193 7114 (match_operand:HF 3 "vfp_compare_operand")]))]
9854d864 7115 "TARGET_VFP_FP16INST"
7116 {
7117 if (!arm_validize_comparison (&operands[1],
7118 &operands[2],
7119 &operands[3]))
7120 FAIL;
7121
7122 emit_insn (gen_cstore_cc (operands[0], operands[1],
7123 operands[2], operands[3]));
7124 DONE;
7125 }
7126)
7127
74f4459c 7128(define_expand "cstoresf4"
3934ae0e 7129 [(set (match_operand:SI 0 "s_register_operand")
aa06947a 7130 (match_operator:SI 1 "expandable_comparison_operator"
3934ae0e 7131 [(match_operand:SF 2 "s_register_operand")
7132 (match_operand:SF 3 "vfp_compare_operand")]))]
74f4459c 7133 "TARGET_32BIT && TARGET_HARD_FLOAT"
7134 "emit_insn (gen_cstore_cc (operands[0], operands[1],
7135 operands[2], operands[3])); DONE;"
7136)
7137
7138(define_expand "cstoredf4"
3934ae0e 7139 [(set (match_operand:SI 0 "s_register_operand")
aa06947a 7140 (match_operator:SI 1 "expandable_comparison_operator"
3934ae0e 7141 [(match_operand:DF 2 "s_register_operand")
7142 (match_operand:DF 3 "vfp_compare_operand")]))]
d63ed457 7143 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
74f4459c 7144 "emit_insn (gen_cstore_cc (operands[0], operands[1],
7145 operands[2], operands[3])); DONE;"
7146)
7147
74f4459c 7148(define_expand "cstoredi4"
3934ae0e 7149 [(set (match_operand:SI 0 "s_register_operand")
aa06947a 7150 (match_operator:SI 1 "expandable_comparison_operator"
3934ae0e 7151 [(match_operand:DI 2 "s_register_operand")
d6852b47 7152 (match_operand:DI 3 "reg_or_int_operand")]))]
a8045a4f 7153 "TARGET_32BIT"
7154 "{
f9aa4160 7155 if (!arm_validize_comparison (&operands[1],
7156 &operands[2],
7157 &operands[3]))
7158 FAIL;
7159 emit_insn (gen_cstore_cc (operands[0], operands[1], operands[2],
a8045a4f 7160 operands[3]));
7161 DONE;
7162 }"
74f4459c 7163)
7164
9c08d1fa 7165\f
39b5e676 7166;; Conditional move insns
7167
7168(define_expand "movsicc"
3934ae0e 7169 [(set (match_operand:SI 0 "s_register_operand")
7170 (if_then_else:SI (match_operand 1 "expandable_comparison_operator")
7171 (match_operand:SI 2 "arm_not_operand")
7172 (match_operand:SI 3 "arm_not_operand")))]
25f905c2 7173 "TARGET_32BIT"
39b5e676 7174 "
215b30b3 7175 {
f9aa4160 7176 enum rtx_code code;
278b301d 7177 rtx ccreg;
7178
f9aa4160 7179 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
9854d864 7180 &XEXP (operands[1], 1)))
278b301d 7181 FAIL;
9854d864 7182
7183 code = GET_CODE (operands[1]);
7184 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
7185 XEXP (operands[1], 1), NULL_RTX);
7186 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7187 }"
7188)
7189
7190(define_expand "movhfcc"
7191 [(set (match_operand:HF 0 "s_register_operand")
7192 (if_then_else:HF (match_operand 1 "arm_cond_move_operator")
7193 (match_operand:HF 2 "s_register_operand")
7194 (match_operand:HF 3 "s_register_operand")))]
7195 "TARGET_VFP_FP16INST"
7196 "
7197 {
7198 enum rtx_code code = GET_CODE (operands[1]);
7199 rtx ccreg;
7200
7201 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
7202 &XEXP (operands[1], 1)))
7203 FAIL;
7204
f9aa4160 7205 code = GET_CODE (operands[1]);
74f4459c 7206 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
e1b93706 7207 XEXP (operands[1], 1), NULL_RTX);
29bb088d 7208 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7209 }"
7210)
39b5e676 7211
7212(define_expand "movsfcc"
3934ae0e 7213 [(set (match_operand:SF 0 "s_register_operand")
7214 (if_then_else:SF (match_operand 1 "arm_cond_move_operator")
7215 (match_operand:SF 2 "s_register_operand")
7216 (match_operand:SF 3 "s_register_operand")))]
19f6bf8d 7217 "TARGET_32BIT && TARGET_HARD_FLOAT"
39b5e676 7218 "
215b30b3 7219 {
7220 enum rtx_code code = GET_CODE (operands[1]);
7221 rtx ccreg;
f082f1c4 7222
9854d864 7223 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
f9aa4160 7224 &XEXP (operands[1], 1)))
7225 FAIL;
39b5e676 7226
f9aa4160 7227 code = GET_CODE (operands[1]);
74f4459c 7228 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
e1b93706 7229 XEXP (operands[1], 1), NULL_RTX);
29bb088d 7230 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7231 }"
7232)
39b5e676 7233
7234(define_expand "movdfcc"
3934ae0e 7235 [(set (match_operand:DF 0 "s_register_operand")
7236 (if_then_else:DF (match_operand 1 "arm_cond_move_operator")
7237 (match_operand:DF 2 "s_register_operand")
7238 (match_operand:DF 3 "s_register_operand")))]
994606f8 7239 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
39b5e676 7240 "
215b30b3 7241 {
7242 enum rtx_code code = GET_CODE (operands[1]);
278b301d 7243 rtx ccreg;
39b5e676 7244
f9aa4160 7245 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
7246 &XEXP (operands[1], 1)))
7247 FAIL;
7248 code = GET_CODE (operands[1]);
74f4459c 7249 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
e1b93706 7250 XEXP (operands[1], 1), NULL_RTX);
29bb088d 7251 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7252 }"
7253)
39b5e676 7254
91cb50d2 7255(define_insn "*cmov<mode>"
7256 [(set (match_operand:SDF 0 "s_register_operand" "=<F_constraint>")
7257 (if_then_else:SDF (match_operator 1 "arm_vsel_comparison_operator"
7258 [(match_operand 2 "cc_register" "") (const_int 0)])
7259 (match_operand:SDF 3 "s_register_operand"
7260 "<F_constraint>")
7261 (match_operand:SDF 4 "s_register_operand"
7262 "<F_constraint>")))]
c79c1b1b 7263 "TARGET_HARD_FLOAT && TARGET_VFP5 <vfp_double_cond>"
91cb50d2 7264 "*
7265 {
7266 enum arm_cond_code code = maybe_get_arm_condition_code (operands[1]);
7267 switch (code)
7268 {
7269 case ARM_GE:
7270 case ARM_GT:
7271 case ARM_EQ:
7272 case ARM_VS:
7273 return \"vsel%d1.<V_if_elem>\\t%<V_reg>0, %<V_reg>3, %<V_reg>4\";
7274 case ARM_LT:
7275 case ARM_LE:
7276 case ARM_NE:
7277 case ARM_VC:
7278 return \"vsel%D1.<V_if_elem>\\t%<V_reg>0, %<V_reg>4, %<V_reg>3\";
7279 default:
7280 gcc_unreachable ();
7281 }
7282 return \"\";
7283 }"
7284 [(set_attr "conds" "use")
6664d308 7285 (set_attr "type" "fcsel")]
91cb50d2 7286)
7287
9854d864 7288(define_insn "*cmovhf"
7289 [(set (match_operand:HF 0 "s_register_operand" "=t")
7290 (if_then_else:HF (match_operator 1 "arm_vsel_comparison_operator"
7291 [(match_operand 2 "cc_register" "") (const_int 0)])
7292 (match_operand:HF 3 "s_register_operand" "t")
7293 (match_operand:HF 4 "s_register_operand" "t")))]
7294 "TARGET_VFP_FP16INST"
7295 "*
7296 {
7297 enum arm_cond_code code = maybe_get_arm_condition_code (operands[1]);
7298 switch (code)
7299 {
7300 case ARM_GE:
7301 case ARM_GT:
7302 case ARM_EQ:
7303 case ARM_VS:
7304 return \"vsel%d1.f16\\t%0, %3, %4\";
7305 case ARM_LT:
7306 case ARM_LE:
7307 case ARM_NE:
7308 case ARM_VC:
7309 return \"vsel%D1.f16\\t%0, %4, %3\";
7310 default:
7311 gcc_unreachable ();
7312 }
7313 return \"\";
7314 }"
7315 [(set_attr "conds" "use")
7316 (set_attr "type" "fcsel")]
7317)
7318
190efb17 7319(define_insn_and_split "*movsicc_insn"
f082f1c4 7320 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
8a18b90c 7321 (if_then_else:SI
8fa3ba89 7322 (match_operator 3 "arm_comparison_operator"
8a18b90c 7323 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 7324 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
7325 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
cffb2a26 7326 "TARGET_ARM"
39b5e676 7327 "@
8a18b90c 7328 mov%D3\\t%0, %2
7329 mvn%D3\\t%0, #%B2
f082f1c4 7330 mov%d3\\t%0, %1
7331 mvn%d3\\t%0, #%B1
190efb17 7332 #
7333 #
7334 #
7335 #"
7336 ; alt4: mov%d3\\t%0, %1\;mov%D3\\t%0, %2
7337 ; alt5: mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
7338 ; alt6: mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
7339 ; alt7: mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
7340 "&& reload_completed"
7341 [(const_int 0)]
7342 {
7343 enum rtx_code rev_code;
3754d046 7344 machine_mode mode;
190efb17 7345 rtx rev_cond;
7346
7347 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
7348 operands[3],
d1f9b275 7349 gen_rtx_SET (operands[0], operands[1])));
190efb17 7350
7351 rev_code = GET_CODE (operands[3]);
7352 mode = GET_MODE (operands[4]);
7353 if (mode == CCFPmode || mode == CCFPEmode)
7354 rev_code = reverse_condition_maybe_unordered (rev_code);
7355 else
7356 rev_code = reverse_condition (rev_code);
7357
7358 rev_cond = gen_rtx_fmt_ee (rev_code,
7359 VOIDmode,
7360 operands[4],
7361 const0_rtx);
7362 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
7363 rev_cond,
d1f9b275 7364 gen_rtx_SET (operands[0], operands[2])));
190efb17 7365 DONE;
7366 }
f082f1c4 7367 [(set_attr "length" "4,4,4,4,8,8,8,8")
d2a518d1 7368 (set_attr "conds" "use")
65f68e55 7369 (set_attr_alternative "type"
7370 [(if_then_else (match_operand 2 "const_int_operand" "")
1aed5204 7371 (const_string "mov_imm")
7372 (const_string "mov_reg"))
7373 (const_string "mvn_imm")
65f68e55 7374 (if_then_else (match_operand 1 "const_int_operand" "")
1aed5204 7375 (const_string "mov_imm")
7376 (const_string "mov_reg"))
7377 (const_string "mvn_imm")
282b4c75 7378 (const_string "multiple")
7379 (const_string "multiple")
7380 (const_string "multiple")
7381 (const_string "multiple")])]
215b30b3 7382)
39b5e676 7383
39b5e676 7384(define_insn "*movsfcc_soft_insn"
f082f1c4 7385 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
8fa3ba89 7386 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
8a18b90c 7387 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 7388 (match_operand:SF 1 "s_register_operand" "0,r")
7389 (match_operand:SF 2 "s_register_operand" "r,0")))]
cffb2a26 7390 "TARGET_ARM && TARGET_SOFT_FLOAT"
f082f1c4 7391 "@
7392 mov%D3\\t%0, %2
7393 mov%d3\\t%0, %1"
d2a518d1 7394 [(set_attr "conds" "use")
1aed5204 7395 (set_attr "type" "mov_reg")]
8fa3ba89 7396)
39b5e676 7397
39b5e676 7398\f
9c08d1fa 7399;; Jump and linkage insns
7400
cffb2a26 7401(define_expand "jump"
9c08d1fa 7402 [(set (pc)
7403 (label_ref (match_operand 0 "" "")))]
cffb2a26 7404 "TARGET_EITHER"
9c08d1fa 7405 ""
cffb2a26 7406)
7407
7408(define_insn "*arm_jump"
7409 [(set (pc)
7410 (label_ref (match_operand 0 "" "")))]
25f905c2 7411 "TARGET_32BIT"
9c08d1fa 7412 "*
0d66636f 7413 {
7414 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7415 {
7416 arm_ccfsm_state += 2;
7417 return \"\";
7418 }
7419 return \"b%?\\t%l0\";
7420 }
7421 "
a6864a24 7422 [(set_attr "predicable" "yes")
7423 (set (attr "length")
7424 (if_then_else
0bf497f5 7425 (and (match_test "TARGET_THUMB2")
a6864a24 7426 (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
7427 (le (minus (match_dup 0) (pc)) (const_int 2048))))
7428 (const_int 2)
1b7da4ac 7429 (const_int 4)))
7430 (set_attr "type" "branch")]
0d66636f 7431)
9c08d1fa 7432
d3373b54 7433(define_expand "call"
3934ae0e 7434 [(parallel [(call (match_operand 0 "memory_operand")
7435 (match_operand 1 "general_operand"))
cffb2a26 7436 (use (match_operand 2 "" ""))
bd5b4116 7437 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 7438 "TARGET_EITHER"
6c4c2133 7439 "
7440 {
bac7fc85 7441 rtx callee, pat;
2d3a01a7 7442 tree addr = MEM_EXPR (operands[0]);
bbe777ea 7443
bbe777ea 7444 /* In an untyped call, we can get NULL for operand 2. */
7445 if (operands[2] == NULL_RTX)
7446 operands[2] = const0_rtx;
7447
de55252a 7448 /* Decide if we should generate indirect calls by loading the
85c36fd1 7449 32-bit address of the callee into a register before performing the
de55252a 7450 branch and link. */
7451 callee = XEXP (operands[0], 0);
7452 if (GET_CODE (callee) == SYMBOL_REF
7453 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
7454 : !REG_P (callee))
bbe777ea 7455 XEXP (operands[0], 0) = force_reg (Pmode, callee);
bac7fc85 7456
2649fa41 7457 if (TARGET_FDPIC && !SYMBOL_REF_P (XEXP (operands[0], 0)))
7458 /* Indirect call: set r9 with FDPIC value of callee. */
7459 XEXP (operands[0], 0)
7460 = arm_load_function_descriptor (XEXP (operands[0], 0));
7461
2d3a01a7 7462 if (detect_cmse_nonsecure_call (addr))
7463 {
7464 pat = gen_nonsecure_call_internal (operands[0], operands[1],
7465 operands[2]);
7466 emit_call_insn (pat);
7467 }
7468 else
7469 {
7470 pat = gen_call_internal (operands[0], operands[1], operands[2]);
7471 arm_emit_call_insn (pat, XEXP (operands[0], 0), false);
7472 }
2649fa41 7473
7474 /* Restore FDPIC register (r9) after call. */
7475 if (TARGET_FDPIC)
7476 {
7477 rtx fdpic_reg = gen_rtx_REG (Pmode, FDPIC_REGNUM);
7478 rtx initial_fdpic_reg
7479 = get_hard_reg_initial_val (Pmode, FDPIC_REGNUM);
7480
7481 emit_insn (gen_restore_pic_register_after_call (fdpic_reg,
7482 initial_fdpic_reg));
7483 }
7484
bac7fc85 7485 DONE;
6c4c2133 7486 }"
7487)
d3373b54 7488
2649fa41 7489(define_insn "restore_pic_register_after_call"
7490 [(set (match_operand:SI 0 "s_register_operand" "+r,r")
7491 (unspec:SI [(match_dup 0)
7492 (match_operand:SI 1 "nonimmediate_operand" "r,m")]
7493 UNSPEC_PIC_RESTORE))]
7494 ""
7495 "@
7496 mov\t%0, %1
7497 ldr\t%0, %1"
7498)
7499
bac7fc85 7500(define_expand "call_internal"
3934ae0e 7501 [(parallel [(call (match_operand 0 "memory_operand")
7502 (match_operand 1 "general_operand"))
bac7fc85 7503 (use (match_operand 2 "" ""))
7504 (clobber (reg:SI LR_REGNUM))])])
7505
2d3a01a7 7506(define_expand "nonsecure_call_internal"
3934ae0e 7507 [(parallel [(call (unspec:SI [(match_operand 0 "memory_operand")]
2d3a01a7 7508 UNSPEC_NONSECURE_MEM)
3934ae0e 7509 (match_operand 1 "general_operand"))
2d3a01a7 7510 (use (match_operand 2 "" ""))
e27c5a70 7511 (clobber (reg:SI LR_REGNUM))])]
2d3a01a7 7512 "use_cmse"
7513 "
7514 {
7515 rtx tmp;
7516 tmp = copy_to_suggested_reg (XEXP (operands[0], 0),
e27c5a70 7517 gen_rtx_REG (SImode, R4_REGNUM),
2d3a01a7 7518 SImode);
7519
7520 operands[0] = replace_equiv_address (operands[0], tmp);
7521 }")
7522
f1039640 7523(define_insn "*call_reg_armv5"
d3373b54 7524 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
cffb2a26 7525 (match_operand 1 "" ""))
7526 (use (match_operand 2 "" ""))
bd5b4116 7527 (clobber (reg:SI LR_REGNUM))]
b232e6b5 7528 "TARGET_ARM && arm_arch5t && !SIBLING_CALL_P (insn)"
f1039640 7529 "blx%?\\t%0"
7530 [(set_attr "type" "call")]
7531)
7532
7533(define_insn "*call_reg_arm"
7534 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7535 (match_operand 1 "" ""))
7536 (use (match_operand 2 "" ""))
7537 (clobber (reg:SI LR_REGNUM))]
b232e6b5 7538 "TARGET_ARM && !arm_arch5t && !SIBLING_CALL_P (insn)"
9c08d1fa 7539 "*
5565501b 7540 return output_call (operands);
cffb2a26 7541 "
7542 ;; length is worst case, normally it is only two
7543 [(set_attr "length" "12")
7544 (set_attr "type" "call")]
7545)
9c08d1fa 7546
89504fc1 7547
d3373b54 7548(define_expand "call_value"
e0698af7 7549 [(parallel [(set (match_operand 0 "" "")
3934ae0e 7550 (call (match_operand 1 "memory_operand")
7551 (match_operand 2 "general_operand")))
cffb2a26 7552 (use (match_operand 3 "" ""))
bd5b4116 7553 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 7554 "TARGET_EITHER"
6c4c2133 7555 "
7556 {
bac7fc85 7557 rtx pat, callee;
2d3a01a7 7558 tree addr = MEM_EXPR (operands[1]);
bbe777ea 7559
7560 /* In an untyped call, we can get NULL for operand 2. */
7561 if (operands[3] == 0)
7562 operands[3] = const0_rtx;
7563
de55252a 7564 /* Decide if we should generate indirect calls by loading the
7565 32-bit address of the callee into a register before performing the
7566 branch and link. */
7567 callee = XEXP (operands[1], 0);
7568 if (GET_CODE (callee) == SYMBOL_REF
7569 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
7570 : !REG_P (callee))
78fe751b 7571 XEXP (operands[1], 0) = force_reg (Pmode, callee);
bac7fc85 7572
2649fa41 7573 if (TARGET_FDPIC && !SYMBOL_REF_P (XEXP (operands[1], 0)))
7574 /* Indirect call: set r9 with FDPIC value of callee. */
7575 XEXP (operands[1], 0)
7576 = arm_load_function_descriptor (XEXP (operands[1], 0));
7577
2d3a01a7 7578 if (detect_cmse_nonsecure_call (addr))
7579 {
7580 pat = gen_nonsecure_call_value_internal (operands[0], operands[1],
7581 operands[2], operands[3]);
7582 emit_call_insn (pat);
7583 }
7584 else
7585 {
7586 pat = gen_call_value_internal (operands[0], operands[1],
7587 operands[2], operands[3]);
7588 arm_emit_call_insn (pat, XEXP (operands[1], 0), false);
7589 }
2649fa41 7590
7591 /* Restore FDPIC register (r9) after call. */
7592 if (TARGET_FDPIC)
7593 {
7594 rtx fdpic_reg = gen_rtx_REG (Pmode, FDPIC_REGNUM);
7595 rtx initial_fdpic_reg
7596 = get_hard_reg_initial_val (Pmode, FDPIC_REGNUM);
7597
7598 emit_insn (gen_restore_pic_register_after_call (fdpic_reg,
7599 initial_fdpic_reg));
7600 }
7601
bac7fc85 7602 DONE;
6c4c2133 7603 }"
7604)
d3373b54 7605
bac7fc85 7606(define_expand "call_value_internal"
7607 [(parallel [(set (match_operand 0 "" "")
3934ae0e 7608 (call (match_operand 1 "memory_operand")
7609 (match_operand 2 "general_operand")))
bac7fc85 7610 (use (match_operand 3 "" ""))
7611 (clobber (reg:SI LR_REGNUM))])])
7612
2d3a01a7 7613(define_expand "nonsecure_call_value_internal"
7614 [(parallel [(set (match_operand 0 "" "")
3934ae0e 7615 (call (unspec:SI [(match_operand 1 "memory_operand")]
2d3a01a7 7616 UNSPEC_NONSECURE_MEM)
3934ae0e 7617 (match_operand 2 "general_operand")))
2d3a01a7 7618 (use (match_operand 3 "" ""))
e27c5a70 7619 (clobber (reg:SI LR_REGNUM))])]
2d3a01a7 7620 "use_cmse"
7621 "
7622 {
7623 rtx tmp;
7624 tmp = copy_to_suggested_reg (XEXP (operands[1], 0),
e27c5a70 7625 gen_rtx_REG (SImode, R4_REGNUM),
2d3a01a7 7626 SImode);
7627
7628 operands[1] = replace_equiv_address (operands[1], tmp);
7629 }")
7630
f1039640 7631(define_insn "*call_value_reg_armv5"
27ed6835 7632 [(set (match_operand 0 "" "")
755eb2b4 7633 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
cffb2a26 7634 (match_operand 2 "" "")))
bbe777ea 7635 (use (match_operand 3 "" ""))
bd5b4116 7636 (clobber (reg:SI LR_REGNUM))]
b232e6b5 7637 "TARGET_ARM && arm_arch5t && !SIBLING_CALL_P (insn)"
f1039640 7638 "blx%?\\t%1"
7639 [(set_attr "type" "call")]
7640)
7641
7642(define_insn "*call_value_reg_arm"
7643 [(set (match_operand 0 "" "")
7644 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7645 (match_operand 2 "" "")))
7646 (use (match_operand 3 "" ""))
7647 (clobber (reg:SI LR_REGNUM))]
b232e6b5 7648 "TARGET_ARM && !arm_arch5t && !SIBLING_CALL_P (insn)"
9c08d1fa 7649 "*
215b30b3 7650 return output_call (&operands[1]);
cffb2a26 7651 "
7652 [(set_attr "length" "12")
7653 (set_attr "type" "call")]
7654)
9c08d1fa 7655
9c08d1fa 7656;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
7657;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
7658
f7fbdd4a 7659(define_insn "*call_symbol"
27ed6835 7660 [(call (mem:SI (match_operand:SI 0 "" ""))
cffb2a26 7661 (match_operand 1 "" ""))
bbe777ea 7662 (use (match_operand 2 "" ""))
bd5b4116 7663 (clobber (reg:SI LR_REGNUM))]
d68c2c10 7664 "TARGET_32BIT
33ae7c4b 7665 && !SIBLING_CALL_P (insn)
cffb2a26 7666 && (GET_CODE (operands[0]) == SYMBOL_REF)
de55252a 7667 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
6ebaa29d 7668 "*
7669 {
95f1e0d1 7670 rtx op = operands[0];
7671
7672 /* Switch mode now when possible. */
7673 if (SYMBOL_REF_DECL (op) && !TREE_PUBLIC (SYMBOL_REF_DECL (op))
b232e6b5 7674 && arm_arch5t && arm_change_mode_p (SYMBOL_REF_DECL (op)))
95f1e0d1 7675 return NEED_PLT_RELOC ? \"blx%?\\t%a0(PLT)\" : \"blx%?\\t(%a0)\";
7676
55c1e470 7677 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
6ebaa29d 7678 }"
cffb2a26 7679 [(set_attr "type" "call")]
7680)
9c08d1fa 7681
f7fbdd4a 7682(define_insn "*call_value_symbol"
ccd90aaa 7683 [(set (match_operand 0 "" "")
27ed6835 7684 (call (mem:SI (match_operand:SI 1 "" ""))
dd6d7504 7685 (match_operand:SI 2 "" "")))
bbe777ea 7686 (use (match_operand 3 "" ""))
bd5b4116 7687 (clobber (reg:SI LR_REGNUM))]
d68c2c10 7688 "TARGET_32BIT
33ae7c4b 7689 && !SIBLING_CALL_P (insn)
cffb2a26 7690 && (GET_CODE (operands[1]) == SYMBOL_REF)
de55252a 7691 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
6ebaa29d 7692 "*
7693 {
95f1e0d1 7694 rtx op = operands[1];
7695
7696 /* Switch mode now when possible. */
7697 if (SYMBOL_REF_DECL (op) && !TREE_PUBLIC (SYMBOL_REF_DECL (op))
b232e6b5 7698 && arm_arch5t && arm_change_mode_p (SYMBOL_REF_DECL (op)))
3f6b66fa 7699 return NEED_PLT_RELOC ? \"blx%?\\t%a1(PLT)\" : \"blx%?\\t(%a1)\";
95f1e0d1 7700
55c1e470 7701 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
6ebaa29d 7702 }"
cffb2a26 7703 [(set_attr "type" "call")]
7704)
7705
ca373797 7706(define_expand "sibcall_internal"
3934ae0e 7707 [(parallel [(call (match_operand 0 "memory_operand")
7708 (match_operand 1 "general_operand"))
ca373797 7709 (return)
7710 (use (match_operand 2 "" ""))])])
7711
1c494086 7712;; We may also be able to do sibcalls for Thumb, but it's much harder...
7713(define_expand "sibcall"
3934ae0e 7714 [(parallel [(call (match_operand 0 "memory_operand")
7715 (match_operand 1 "general_operand"))
2ba80634 7716 (return)
7717 (use (match_operand 2 "" ""))])]
d68c2c10 7718 "TARGET_32BIT"
1c494086 7719 "
7720 {
ca373797 7721 rtx pat;
7722
3112c3f7 7723 if ((!REG_P (XEXP (operands[0], 0))
7724 && GET_CODE (XEXP (operands[0], 0)) != SYMBOL_REF)
7725 || (GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
7726 && arm_is_long_call_p (SYMBOL_REF_DECL (XEXP (operands[0], 0)))))
33ae7c4b 7727 XEXP (operands[0], 0) = force_reg (SImode, XEXP (operands[0], 0));
7728
1c494086 7729 if (operands[2] == NULL_RTX)
7730 operands[2] = const0_rtx;
ca373797 7731
7732 pat = gen_sibcall_internal (operands[0], operands[1], operands[2]);
7733 arm_emit_call_insn (pat, operands[0], true);
7734 DONE;
1c494086 7735 }"
7736)
7737
ca373797 7738(define_expand "sibcall_value_internal"
7739 [(parallel [(set (match_operand 0 "" "")
3934ae0e 7740 (call (match_operand 1 "memory_operand")
7741 (match_operand 2 "general_operand")))
ca373797 7742 (return)
7743 (use (match_operand 3 "" ""))])])
7744
1c494086 7745(define_expand "sibcall_value"
ccd90aaa 7746 [(parallel [(set (match_operand 0 "" "")
3934ae0e 7747 (call (match_operand 1 "memory_operand")
7748 (match_operand 2 "general_operand")))
2ba80634 7749 (return)
7750 (use (match_operand 3 "" ""))])]
d68c2c10 7751 "TARGET_32BIT"
1c494086 7752 "
7753 {
ca373797 7754 rtx pat;
7755
3112c3f7 7756 if ((!REG_P (XEXP (operands[1], 0))
7757 && GET_CODE (XEXP (operands[1], 0)) != SYMBOL_REF)
7758 || (GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
7759 && arm_is_long_call_p (SYMBOL_REF_DECL (XEXP (operands[1], 0)))))
33ae7c4b 7760 XEXP (operands[1], 0) = force_reg (SImode, XEXP (operands[1], 0));
7761
1c494086 7762 if (operands[3] == NULL_RTX)
7763 operands[3] = const0_rtx;
ca373797 7764
7765 pat = gen_sibcall_value_internal (operands[0], operands[1],
7766 operands[2], operands[3]);
7767 arm_emit_call_insn (pat, operands[1], true);
7768 DONE;
1c494086 7769 }"
7770)
7771
7772(define_insn "*sibcall_insn"
84ce8e5c 7773 [(call (mem:SI (match_operand:SI 0 "call_insn_operand" "Cs, US"))
1c494086 7774 (match_operand 1 "" ""))
2ba80634 7775 (return)
7776 (use (match_operand 2 "" ""))]
33ae7c4b 7777 "TARGET_32BIT && SIBLING_CALL_P (insn)"
1c494086 7778 "*
33ae7c4b 7779 if (which_alternative == 1)
7780 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
7781 else
7782 {
b232e6b5 7783 if (arm_arch5t || arm_arch4t)
947d113e 7784 return \"bx%?\\t%0\\t%@ indirect register sibling call\";
33ae7c4b 7785 else
7786 return \"mov%?\\t%|pc, %0\\t%@ indirect register sibling call\";
7787 }
1c494086 7788 "
7789 [(set_attr "type" "call")]
7790)
7791
7792(define_insn "*sibcall_value_insn"
84ce8e5c 7793 [(set (match_operand 0 "" "")
7794 (call (mem:SI (match_operand:SI 1 "call_insn_operand" "Cs,US"))
1c494086 7795 (match_operand 2 "" "")))
2ba80634 7796 (return)
7797 (use (match_operand 3 "" ""))]
33ae7c4b 7798 "TARGET_32BIT && SIBLING_CALL_P (insn)"
1c494086 7799 "*
33ae7c4b 7800 if (which_alternative == 1)
7801 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
7802 else
7803 {
b232e6b5 7804 if (arm_arch5t || arm_arch4t)
84ce8e5c 7805 return \"bx%?\\t%1\";
33ae7c4b 7806 else
7807 return \"mov%?\\t%|pc, %1\\t@ indirect sibling call \";
7808 }
1c494086 7809 "
7810 [(set_attr "type" "call")]
7811)
7812
0686440e 7813(define_expand "<return_str>return"
9b23f0a7 7814 [(RETURNS)]
8cba51a5 7815 "(TARGET_ARM || (TARGET_THUMB2
7816 && ARM_FUNC_TYPE (arm_current_func_type ()) == ARM_FT_NORMAL
7817 && !IS_STACKALIGN (arm_current_func_type ())))
0686440e 7818 <return_cond_false>"
8cba51a5 7819 "
7820 {
7821 if (TARGET_THUMB2)
7822 {
0686440e 7823 thumb2_expand_return (<return_simple_p>);
8cba51a5 7824 DONE;
7825 }
7826 }
7827 "
7828)
d68c2c10 7829
9c08d1fa 7830;; Often the return insn will be the same as loading from memory, so set attr
d68c2c10 7831(define_insn "*arm_return"
9c08d1fa 7832 [(return)]
cffb2a26 7833 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
9c08d1fa 7834 "*
9c08d1fa 7835 {
cffb2a26 7836 if (arm_ccfsm_state == 2)
7837 {
7838 arm_ccfsm_state += 2;
7839 return \"\";
7840 }
e2549f81 7841 return output_return_instruction (const_true_rtx, true, false, false);
cffb2a26 7842 }"
9f2c2a36 7843 [(set_attr "type" "load_4")
755eb2b4 7844 (set_attr "length" "12")
0d66636f 7845 (set_attr "predicable" "yes")]
cffb2a26 7846)
9c08d1fa 7847
0686440e 7848(define_insn "*cond_<return_str>return"
9c08d1fa 7849 [(set (pc)
8fa3ba89 7850 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 7851 [(match_operand 1 "cc_register" "") (const_int 0)])
9b23f0a7 7852 (RETURNS)
9c08d1fa 7853 (pc)))]
0686440e 7854 "TARGET_ARM <return_cond_true>"
9c08d1fa 7855 "*
8fa3ba89 7856 {
7857 if (arm_ccfsm_state == 2)
7858 {
7859 arm_ccfsm_state += 2;
7860 return \"\";
7861 }
0686440e 7862 return output_return_instruction (operands[0], true, false,
7863 <return_simple_p>);
8fa3ba89 7864 }"
7865 [(set_attr "conds" "use")
755eb2b4 7866 (set_attr "length" "12")
9f2c2a36 7867 (set_attr "type" "load_4")]
8fa3ba89 7868)
9c08d1fa 7869
0686440e 7870(define_insn "*cond_<return_str>return_inverted"
9c08d1fa 7871 [(set (pc)
8fa3ba89 7872 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 7873 [(match_operand 1 "cc_register" "") (const_int 0)])
9c08d1fa 7874 (pc)
9b23f0a7 7875 (RETURNS)))]
0686440e 7876 "TARGET_ARM <return_cond_true>"
9c08d1fa 7877 "*
8fa3ba89 7878 {
7879 if (arm_ccfsm_state == 2)
7880 {
7881 arm_ccfsm_state += 2;
7882 return \"\";
7883 }
0686440e 7884 return output_return_instruction (operands[0], true, true,
7885 <return_simple_p>);
8fa3ba89 7886 }"
7887 [(set_attr "conds" "use")
37a1317b 7888 (set_attr "length" "12")
9f2c2a36 7889 (set_attr "type" "load_4")]
8fa3ba89 7890)
9c08d1fa 7891
e2549f81 7892(define_insn "*arm_simple_return"
7893 [(simple_return)]
7894 "TARGET_ARM"
7895 "*
7896 {
7897 if (arm_ccfsm_state == 2)
7898 {
7899 arm_ccfsm_state += 2;
7900 return \"\";
7901 }
7902 return output_return_instruction (const_true_rtx, true, false, true);
7903 }"
7904 [(set_attr "type" "branch")
7905 (set_attr "length" "4")
7906 (set_attr "predicable" "yes")]
7907)
7908
68121397 7909;; Generate a sequence of instructions to determine if the processor is
7910;; in 26-bit or 32-bit mode, and return the appropriate return address
7911;; mask.
7912
7913(define_expand "return_addr_mask"
7914 [(set (match_dup 1)
7915 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7916 (const_int 0)))
3934ae0e 7917 (set (match_operand:SI 0 "s_register_operand")
68121397 7918 (if_then_else:SI (eq (match_dup 1) (const_int 0))
7919 (const_int -1)
7920 (const_int 67108860)))] ; 0x03fffffc
7921 "TARGET_ARM"
7922 "
62eddbd4 7923 operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
68121397 7924 ")
7925
7926(define_insn "*check_arch2"
7927 [(set (match_operand:CC_NOOV 0 "cc_register" "")
7928 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7929 (const_int 0)))]
7930 "TARGET_ARM"
7931 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
7932 [(set_attr "length" "8")
1b7da4ac 7933 (set_attr "conds" "set")
7934 (set_attr "type" "multiple")]
68121397 7935)
7936
9c08d1fa 7937;; Call subroutine returning any type.
7938
7939(define_expand "untyped_call"
7940 [(parallel [(call (match_operand 0 "" "")
7941 (const_int 0))
7942 (match_operand 1 "" "")
7943 (match_operand 2 "" "")])]
2649fa41 7944 "TARGET_EITHER && !TARGET_FDPIC"
9c08d1fa 7945 "
215b30b3 7946 {
7947 int i;
ccd90aaa 7948 rtx par = gen_rtx_PARALLEL (VOIDmode,
7949 rtvec_alloc (XVECLEN (operands[2], 0)));
7950 rtx addr = gen_reg_rtx (Pmode);
7951 rtx mem;
7952 int size = 0;
9c08d1fa 7953
ccd90aaa 7954 emit_move_insn (addr, XEXP (operands[1], 0));
7955 mem = change_address (operands[1], BLKmode, addr);
9c08d1fa 7956
215b30b3 7957 for (i = 0; i < XVECLEN (operands[2], 0); i++)
7958 {
ccd90aaa 7959 rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
9c08d1fa 7960
ccd90aaa 7961 /* Default code only uses r0 as a return value, but we could
7962 be using anything up to 4 registers. */
7963 if (REGNO (src) == R0_REGNUM)
7964 src = gen_rtx_REG (TImode, R0_REGNUM);
7965
7966 XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
7967 GEN_INT (size));
7968 size += GET_MODE_SIZE (GET_MODE (src));
7969 }
7970
7f265a08 7971 emit_call_insn (gen_call_value (par, operands[0], const0_rtx, NULL));
ccd90aaa 7972
7973 size = 0;
7974
7975 for (i = 0; i < XVECLEN (par, 0); i++)
7976 {
7977 HOST_WIDE_INT offset = 0;
7978 rtx reg = XEXP (XVECEXP (par, 0, i), 0);
7979
7980 if (size != 0)
29c05e22 7981 emit_move_insn (addr, plus_constant (Pmode, addr, size));
ccd90aaa 7982
7983 mem = change_address (mem, GET_MODE (reg), NULL);
7984 if (REGNO (reg) == R0_REGNUM)
7985 {
7986 /* On thumb we have to use a write-back instruction. */
320ea44d 7987 emit_insn (arm_gen_store_multiple (arm_regs_in_sequence, 4, addr,
7988 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
ccd90aaa 7989 size = TARGET_ARM ? 16 : 0;
7990 }
7991 else
7992 {
7993 emit_move_insn (mem, reg);
7994 size = GET_MODE_SIZE (GET_MODE (reg));
7995 }
215b30b3 7996 }
9c08d1fa 7997
215b30b3 7998 /* The optimizer does not know that the call sets the function value
7999 registers we stored in the result block. We avoid problems by
8000 claiming that all hard registers are used and clobbered at this
8001 point. */
8002 emit_insn (gen_blockage ());
8003
8004 DONE;
8005 }"
8006)
9c08d1fa 8007
ccd90aaa 8008(define_expand "untyped_return"
3934ae0e 8009 [(match_operand:BLK 0 "memory_operand")
ccd90aaa 8010 (match_operand 1 "" "")]
2649fa41 8011 "TARGET_EITHER && !TARGET_FDPIC"
ccd90aaa 8012 "
8013 {
8014 int i;
8015 rtx addr = gen_reg_rtx (Pmode);
8016 rtx mem;
8017 int size = 0;
8018
8019 emit_move_insn (addr, XEXP (operands[0], 0));
8020 mem = change_address (operands[0], BLKmode, addr);
8021
8022 for (i = 0; i < XVECLEN (operands[1], 0); i++)
8023 {
8024 HOST_WIDE_INT offset = 0;
8025 rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
8026
8027 if (size != 0)
29c05e22 8028 emit_move_insn (addr, plus_constant (Pmode, addr, size));
ccd90aaa 8029
8030 mem = change_address (mem, GET_MODE (reg), NULL);
8031 if (REGNO (reg) == R0_REGNUM)
8032 {
8033 /* On thumb we have to use a write-back instruction. */
320ea44d 8034 emit_insn (arm_gen_load_multiple (arm_regs_in_sequence, 4, addr,
8035 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
ccd90aaa 8036 size = TARGET_ARM ? 16 : 0;
8037 }
8038 else
8039 {
8040 emit_move_insn (reg, mem);
8041 size = GET_MODE_SIZE (GET_MODE (reg));
8042 }
8043 }
8044
8045 /* Emit USE insns before the return. */
8046 for (i = 0; i < XVECLEN (operands[1], 0); i++)
18b42941 8047 emit_use (SET_DEST (XVECEXP (operands[1], 0, i)));
ccd90aaa 8048
8049 /* Construct the return. */
8050 expand_naked_return ();
8051
8052 DONE;
8053 }"
8054)
8055
9c08d1fa 8056;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
8057;; all of memory. This blocks insns from being moved across this point.
8058
8059(define_insn "blockage"
e1159bbe 8060 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
cffb2a26 8061 "TARGET_EITHER"
9c08d1fa 8062 ""
cffb2a26 8063 [(set_attr "length" "0")
8064 (set_attr "type" "block")]
8065)
9c08d1fa 8066
80c63fc3 8067;; Since we hard code r0 here use the 'o' constraint to prevent
8068;; provoking undefined behaviour in the hardware with putting out
8069;; auto-increment operations with potentially r0 as the base register.
706dca65 8070(define_insn "probe_stack"
80c63fc3 8071 [(set (match_operand:SI 0 "memory_operand" "=o")
f8570abe 8072 (unspec:SI [(const_int 0)] UNSPEC_PROBE_STACK))]
706dca65 8073 "TARGET_32BIT"
154ae8e6 8074 "str%?\\tr0, %0"
9f2c2a36 8075 [(set_attr "type" "store_4")
706dca65 8076 (set_attr "predicable" "yes")]
8077)
8078
8079(define_insn "probe_stack_range"
8080 [(set (match_operand:SI 0 "register_operand" "=r")
8081 (unspec_volatile:SI [(match_operand:SI 1 "register_operand" "0")
8082 (match_operand:SI 2 "register_operand" "r")]
dd8aabc9 8083 VUNSPEC_PROBE_STACK_RANGE))]
706dca65 8084 "TARGET_32BIT"
8085{
8086 return output_probe_stack_range (operands[0], operands[2]);
8087}
8088 [(set_attr "type" "multiple")
8089 (set_attr "conds" "clob")]
8090)
8091
f98495d9 8092;; Named patterns for stack smashing protection.
8093(define_expand "stack_protect_combined_set"
8094 [(parallel
3934ae0e 8095 [(set (match_operand:SI 0 "memory_operand")
8096 (unspec:SI [(match_operand:SI 1 "guard_operand")]
f98495d9 8097 UNSPEC_SP_SET))
8098 (clobber (match_scratch:SI 2 ""))
8099 (clobber (match_scratch:SI 3 ""))])]
8100 ""
8101 ""
8102)
8103
8104;; Use a separate insn from the above expand to be able to have the mem outside
8105;; the operand #1 when register allocation comes. This is needed to avoid LRA
8106;; try to reload the guard since we need to control how PIC access is done in
8107;; the -fpic/-fPIC case (see COMPUTE_NOW parameter when calling
8108;; legitimize_pic_address ()).
8109(define_insn_and_split "*stack_protect_combined_set_insn"
8110 [(set (match_operand:SI 0 "memory_operand" "=m,m")
8111 (unspec:SI [(mem:SI (match_operand:SI 1 "guard_addr_operand" "X,X"))]
8112 UNSPEC_SP_SET))
8113 (clobber (match_scratch:SI 2 "=&l,&r"))
8114 (clobber (match_scratch:SI 3 "=&l,&r"))]
8115 ""
8116 "#"
8117 "reload_completed"
8118 [(parallel [(set (match_dup 0) (unspec:SI [(mem:SI (match_dup 2))]
8119 UNSPEC_SP_SET))
8120 (clobber (match_dup 2))])]
8121 "
8122{
8123 if (flag_pic)
8124 {
d89c0749 8125 rtx pic_reg;
8126
8127 if (TARGET_FDPIC)
8128 pic_reg = gen_rtx_REG (Pmode, FDPIC_REGNUM);
8129 else
8130 pic_reg = operands[3];
8131
f98495d9 8132 /* Forces recomputing of GOT base now. */
d89c0749 8133 legitimize_pic_address (operands[1], SImode, operands[2], pic_reg,
f98495d9 8134 true /*compute_now*/);
8135 }
8136 else
8137 {
8138 if (address_operand (operands[1], SImode))
8139 operands[2] = operands[1];
8140 else
8141 {
8142 rtx mem = XEXP (force_const_mem (SImode, operands[1]), 0);
8143 emit_move_insn (operands[2], mem);
8144 }
8145 }
8146}"
8147 [(set_attr "arch" "t1,32")]
8148)
8149
fa66a3db 8150;; DO NOT SPLIT THIS INSN. It's important for security reasons that the
8151;; canary value does not live beyond the life of this sequence.
f98495d9 8152(define_insn "*stack_protect_set_insn"
8153 [(set (match_operand:SI 0 "memory_operand" "=m,m")
8154 (unspec:SI [(mem:SI (match_operand:SI 1 "register_operand" "+&l,&r"))]
8155 UNSPEC_SP_SET))
8156 (clobber (match_dup 1))]
8157 ""
8158 "@
fa66a3db 8159 ldr\\t%1, [%1]\;str\\t%1, %0\;movs\t%1, #0
8160 ldr\\t%1, [%1]\;str\\t%1, %0\;mov\t%1, #0"
f98495d9 8161 [(set_attr "length" "8,12")
8162 (set_attr "conds" "clob,nocond")
8163 (set_attr "type" "multiple")
8164 (set_attr "arch" "t1,32")]
8165)
8166
8167(define_expand "stack_protect_combined_test"
8168 [(parallel
8169 [(set (pc)
8170 (if_then_else
3934ae0e 8171 (eq (match_operand:SI 0 "memory_operand")
8172 (unspec:SI [(match_operand:SI 1 "guard_operand")]
f98495d9 8173 UNSPEC_SP_TEST))
8174 (label_ref (match_operand 2))
8175 (pc)))
8176 (clobber (match_scratch:SI 3 ""))
8177 (clobber (match_scratch:SI 4 ""))
8178 (clobber (reg:CC CC_REGNUM))])]
8179 ""
8180 ""
8181)
8182
8183;; Use a separate insn from the above expand to be able to have the mem outside
8184;; the operand #1 when register allocation comes. This is needed to avoid LRA
8185;; try to reload the guard since we need to control how PIC access is done in
8186;; the -fpic/-fPIC case (see COMPUTE_NOW parameter when calling
8187;; legitimize_pic_address ()).
8188(define_insn_and_split "*stack_protect_combined_test_insn"
8189 [(set (pc)
8190 (if_then_else
8191 (eq (match_operand:SI 0 "memory_operand" "m,m")
8192 (unspec:SI [(mem:SI (match_operand:SI 1 "guard_addr_operand" "X,X"))]
8193 UNSPEC_SP_TEST))
8194 (label_ref (match_operand 2))
8195 (pc)))
8196 (clobber (match_scratch:SI 3 "=&l,&r"))
8197 (clobber (match_scratch:SI 4 "=&l,&r"))
8198 (clobber (reg:CC CC_REGNUM))]
8199 ""
8200 "#"
8201 "reload_completed"
8202 [(const_int 0)]
8203{
8204 rtx eq;
8205
8206 if (flag_pic)
8207 {
d89c0749 8208 rtx pic_reg;
8209
8210 if (TARGET_FDPIC)
8211 pic_reg = gen_rtx_REG (Pmode, FDPIC_REGNUM);
8212 else
8213 pic_reg = operands[4];
8214
f98495d9 8215 /* Forces recomputing of GOT base now. */
d89c0749 8216 legitimize_pic_address (operands[1], SImode, operands[3], pic_reg,
f98495d9 8217 true /*compute_now*/);
8218 }
8219 else
8220 {
8221 if (address_operand (operands[1], SImode))
8222 operands[3] = operands[1];
8223 else
8224 {
8225 rtx mem = XEXP (force_const_mem (SImode, operands[1]), 0);
8226 emit_move_insn (operands[3], mem);
8227 }
8228 }
8229 if (TARGET_32BIT)
8230 {
8231 emit_insn (gen_arm_stack_protect_test_insn (operands[4], operands[0],
8232 operands[3]));
8233 rtx cc_reg = gen_rtx_REG (CC_Zmode, CC_REGNUM);
8234 eq = gen_rtx_EQ (CC_Zmode, cc_reg, const0_rtx);
8235 emit_jump_insn (gen_arm_cond_branch (operands[2], eq, cc_reg));
8236 }
8237 else
8238 {
8239 emit_insn (gen_thumb1_stack_protect_test_insn (operands[4], operands[0],
8240 operands[3]));
8241 eq = gen_rtx_EQ (VOIDmode, operands[4], const0_rtx);
8242 emit_jump_insn (gen_cbranchsi4 (eq, operands[4], const0_rtx,
8243 operands[2]));
8244 }
8245 DONE;
8246}
8247 [(set_attr "arch" "t1,32")]
8248)
8249
8250(define_insn "arm_stack_protect_test_insn"
8251 [(set (reg:CC_Z CC_REGNUM)
8252 (compare:CC_Z (unspec:SI [(match_operand:SI 1 "memory_operand" "m,m")
8253 (mem:SI (match_operand:SI 2 "register_operand" "+l,r"))]
8254 UNSPEC_SP_TEST)
8255 (const_int 0)))
8256 (clobber (match_operand:SI 0 "register_operand" "=&l,&r"))
8257 (clobber (match_dup 2))]
8258 "TARGET_32BIT"
8259 "ldr\t%0, [%2]\;ldr\t%2, %1\;eors\t%0, %2, %0"
8260 [(set_attr "length" "8,12")
8261 (set_attr "conds" "set")
8262 (set_attr "type" "multiple")
8263 (set_attr "arch" "t,32")]
8264)
8265
f7fbdd4a 8266(define_expand "casesi"
3934ae0e 8267 [(match_operand:SI 0 "s_register_operand") ; index to jump on
8268 (match_operand:SI 1 "const_int_operand") ; lower bound
8269 (match_operand:SI 2 "const_int_operand") ; total range
f7fbdd4a 8270 (match_operand:SI 3 "" "") ; table label
8271 (match_operand:SI 4 "" "")] ; Out of range label
9753b549 8272 "(TARGET_32BIT || optimize_size || flag_pic) && !target_pure_code"
f7fbdd4a 8273 "
215b30b3 8274 {
e6ac8414 8275 enum insn_code code;
215b30b3 8276 if (operands[1] != const0_rtx)
8277 {
e6ac8414 8278 rtx reg = gen_reg_rtx (SImode);
f7fbdd4a 8279
215b30b3 8280 emit_insn (gen_addsi3 (reg, operands[0],
d022fa24 8281 gen_int_mode (-INTVAL (operands[1]),
8282 SImode)));
215b30b3 8283 operands[0] = reg;
8284 }
9c08d1fa 8285
25f905c2 8286 if (TARGET_ARM)
e6ac8414 8287 code = CODE_FOR_arm_casesi_internal;
3db2019b 8288 else if (TARGET_THUMB1)
e6ac8414 8289 code = CODE_FOR_thumb1_casesi_internal_pic;
25f905c2 8290 else if (flag_pic)
e6ac8414 8291 code = CODE_FOR_thumb2_casesi_internal_pic;
25f905c2 8292 else
e6ac8414 8293 code = CODE_FOR_thumb2_casesi_internal;
8294
8295 if (!insn_data[(int) code].operand[1].predicate(operands[2], SImode))
8296 operands[2] = force_reg (SImode, operands[2]);
8297
8298 emit_jump_insn (GEN_FCN ((int) code) (operands[0], operands[2],
8299 operands[3], operands[4]));
215b30b3 8300 DONE;
8301 }"
8302)
f7fbdd4a 8303
f082f1c4 8304;; The USE in this pattern is needed to tell flow analysis that this is
8305;; a CASESI insn. It has no other purpose.
b634d96a 8306(define_expand "arm_casesi_internal"
8307 [(parallel [(set (pc)
8308 (if_then_else
8309 (leu (match_operand:SI 0 "s_register_operand")
8310 (match_operand:SI 1 "arm_rhs_operand"))
8311 (match_dup 4)
8312 (label_ref:SI (match_operand 3 ""))))
8313 (clobber (reg:CC CC_REGNUM))
8314 (use (label_ref:SI (match_operand 2 "")))])]
8315 "TARGET_ARM"
8316{
8317 operands[4] = gen_rtx_MULT (SImode, operands[0], GEN_INT (4));
8318 operands[4] = gen_rtx_PLUS (SImode, operands[4],
8319 gen_rtx_LABEL_REF (SImode, operands[2]));
8320 operands[4] = gen_rtx_MEM (SImode, operands[4]);
8321 MEM_READONLY_P (operands[4]) = 1;
8322 MEM_NOTRAP_P (operands[4]) = 1;
8323})
8324
8325(define_insn "*arm_casesi_internal"
f082f1c4 8326 [(parallel [(set (pc)
8327 (if_then_else
8328 (leu (match_operand:SI 0 "s_register_operand" "r")
8329 (match_operand:SI 1 "arm_rhs_operand" "rI"))
8330 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
b634d96a 8331 (label_ref:SI (match_operand 2 "" ""))))
8332 (label_ref:SI (match_operand 3 "" ""))))
bd5b4116 8333 (clobber (reg:CC CC_REGNUM))
b634d96a 8334 (use (label_ref:SI (match_dup 2)))])]
cffb2a26 8335 "TARGET_ARM"
f7fbdd4a 8336 "*
0d66636f 8337 if (flag_pic)
8338 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
8339 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
8340 "
8341 [(set_attr "conds" "clob")
1b7da4ac 8342 (set_attr "length" "12")
8343 (set_attr "type" "multiple")]
0d66636f 8344)
9c08d1fa 8345
cffb2a26 8346(define_expand "indirect_jump"
9c08d1fa 8347 [(set (pc)
3934ae0e 8348 (match_operand:SI 0 "s_register_operand"))]
cffb2a26 8349 "TARGET_EITHER"
25f905c2 8350 "
8351 /* Thumb-2 doesn't have mov pc, reg. Explicitly set the low bit of the
8352 address and use bx. */
8353 if (TARGET_THUMB2)
8354 {
8355 rtx tmp;
8356 tmp = gen_reg_rtx (SImode);
8357 emit_insn (gen_iorsi3 (tmp, operands[0], GEN_INT(1)));
8358 operands[0] = tmp;
8359 }
8360 "
cffb2a26 8361)
8362
f1039640 8363;; NB Never uses BX.
cffb2a26 8364(define_insn "*arm_indirect_jump"
8365 [(set (pc)
8366 (match_operand:SI 0 "s_register_operand" "r"))]
8367 "TARGET_ARM"
8368 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
1b7da4ac 8369 [(set_attr "predicable" "yes")
8370 (set_attr "type" "branch")]
cffb2a26 8371)
9c08d1fa 8372
f7fbdd4a 8373(define_insn "*load_indirect_jump"
9c08d1fa 8374 [(set (pc)
8375 (match_operand:SI 0 "memory_operand" "m"))]
cffb2a26 8376 "TARGET_ARM"
8377 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
9f2c2a36 8378 [(set_attr "type" "load_4")
61a2d04c 8379 (set_attr "pool_range" "4096")
8380 (set_attr "neg_pool_range" "4084")
0d66636f 8381 (set_attr "predicable" "yes")]
cffb2a26 8382)
8383
9c08d1fa 8384\f
8385;; Misc insns
8386
8387(define_insn "nop"
8388 [(const_int 0)]
cffb2a26 8389 "TARGET_EITHER"
3ef90e77 8390 "nop"
cffb2a26 8391 [(set (attr "length")
8392 (if_then_else (eq_attr "is_thumb" "yes")
8393 (const_int 2)
1b7da4ac 8394 (const_int 4)))
8395 (set_attr "type" "mov_reg")]
cffb2a26 8396)
8397
ad9d4399 8398(define_insn "trap"
8399 [(trap_if (const_int 1) (const_int 0))]
8400 ""
8401 "*
8402 if (TARGET_ARM)
8403 return \".inst\\t0xe7f000f0\";
8404 else
8405 return \".inst\\t0xdeff\";
8406 "
8407 [(set (attr "length")
8408 (if_then_else (eq_attr "is_thumb" "yes")
8409 (const_int 2)
8410 (const_int 4)))
8411 (set_attr "type" "trap")
8412 (set_attr "conds" "unconditional")]
8413)
8414
9c08d1fa 8415\f
8416;; Patterns to allow combination of arithmetic, cond code and shifts
8417
0abea32c 8418(define_insn "*<arith_shift_insn>_multsi"
8419 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9b23f0a7 8420 (SHIFTABLE_OPS:SI
0abea32c 8421 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
8422 (match_operand:SI 3 "power_of_two_operand" ""))
8423 (match_operand:SI 1 "s_register_operand" "rk,<t2_binop0>")))]
d5d4dc8d 8424 "TARGET_32BIT"
0abea32c 8425 "<arith_shift_insn>%?\\t%0, %1, %2, lsl %b3"
8426 [(set_attr "predicable" "yes")
753d9835 8427 (set_attr "shift" "2")
0abea32c 8428 (set_attr "arch" "a,t2")
8429 (set_attr "type" "alu_shift_imm")])
8430
8431(define_insn "*<arith_shift_insn>_shiftsi"
8432 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9b23f0a7 8433 (SHIFTABLE_OPS:SI
0abea32c 8434 (match_operator:SI 2 "shift_nomul_operator"
8435 [(match_operand:SI 3 "s_register_operand" "r,r,r")
8436 (match_operand:SI 4 "shift_amount_operand" "M,M,r")])
8437 (match_operand:SI 1 "s_register_operand" "rk,<t2_binop0>,rk")))]
a021b821 8438 "TARGET_32BIT && GET_CODE (operands[2]) != MULT"
0abea32c 8439 "<arith_shift_insn>%?\\t%0, %1, %3%S2"
344495ea 8440 [(set_attr "predicable" "yes")
753d9835 8441 (set_attr "shift" "3")
0abea32c 8442 (set_attr "arch" "a,t2,a")
8443 (set_attr "type" "alu_shift_imm,alu_shift_imm,alu_shift_reg")])
9c08d1fa 8444
d7863cfe 8445(define_split
8446 [(set (match_operand:SI 0 "s_register_operand" "")
8447 (match_operator:SI 1 "shiftable_operator"
8448 [(match_operator:SI 2 "shiftable_operator"
8449 [(match_operator:SI 3 "shift_operator"
8450 [(match_operand:SI 4 "s_register_operand" "")
8451 (match_operand:SI 5 "reg_or_int_operand" "")])
8452 (match_operand:SI 6 "s_register_operand" "")])
8453 (match_operand:SI 7 "arm_rhs_operand" "")]))
8454 (clobber (match_operand:SI 8 "s_register_operand" ""))]
d5d4dc8d 8455 "TARGET_32BIT"
d7863cfe 8456 [(set (match_dup 8)
8457 (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8458 (match_dup 6)]))
8459 (set (match_dup 0)
8460 (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
8461 "")
8462
f7fbdd4a 8463(define_insn "*arith_shiftsi_compare0"
bd5b4116 8464 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 8465 (compare:CC_NOOV
8466 (match_operator:SI 1 "shiftable_operator"
8467 [(match_operator:SI 3 "shift_operator"
8468 [(match_operand:SI 4 "s_register_operand" "r,r")
8469 (match_operand:SI 5 "shift_amount_operand" "M,r")])
8470 (match_operand:SI 2 "s_register_operand" "r,r")])
8471 (const_int 0)))
8472 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 8473 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8474 (match_dup 2)]))]
d5d4dc8d 8475 "TARGET_32BIT"
3ef90e77 8476 "%i1s%?\\t%0, %2, %4%S3"
344495ea 8477 [(set_attr "conds" "set")
331beb1a 8478 (set_attr "shift" "4")
d5d4dc8d 8479 (set_attr "arch" "32,a")
d82e788e 8480 (set_attr "type" "alus_shift_imm,alus_shift_reg")])
9c08d1fa 8481
f7fbdd4a 8482(define_insn "*arith_shiftsi_compare0_scratch"
bd5b4116 8483 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 8484 (compare:CC_NOOV
8485 (match_operator:SI 1 "shiftable_operator"
8486 [(match_operator:SI 3 "shift_operator"
8487 [(match_operand:SI 4 "s_register_operand" "r,r")
8488 (match_operand:SI 5 "shift_amount_operand" "M,r")])
8489 (match_operand:SI 2 "s_register_operand" "r,r")])
8490 (const_int 0)))
8491 (clobber (match_scratch:SI 0 "=r,r"))]
8492 "TARGET_32BIT"
3ef90e77 8493 "%i1s%?\\t%0, %2, %4%S3"
344495ea 8494 [(set_attr "conds" "set")
331beb1a 8495 (set_attr "shift" "4")
d5d4dc8d 8496 (set_attr "arch" "32,a")
d82e788e 8497 (set_attr "type" "alus_shift_imm,alus_shift_reg")])
9c08d1fa 8498
f7fbdd4a 8499(define_insn "*sub_shiftsi"
d5d4dc8d 8500 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8501 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
9c08d1fa 8502 (match_operator:SI 2 "shift_operator"
d5d4dc8d 8503 [(match_operand:SI 3 "s_register_operand" "r,r")
8504 (match_operand:SI 4 "shift_amount_operand" "M,r")])))]
8505 "TARGET_32BIT"
6c4c2133 8506 "sub%?\\t%0, %1, %3%S2"
344495ea 8507 [(set_attr "predicable" "yes")
2df5a382 8508 (set_attr "predicable_short_it" "no")
331beb1a 8509 (set_attr "shift" "3")
d5d4dc8d 8510 (set_attr "arch" "32,a")
d82e788e 8511 (set_attr "type" "alus_shift_imm,alus_shift_reg")])
9c08d1fa 8512
f7fbdd4a 8513(define_insn "*sub_shiftsi_compare0"
bd5b4116 8514 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 8515 (compare:CC_NOOV
d82e788e 8516 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
40dbec34 8517 (match_operator:SI 2 "shift_operator"
d82e788e 8518 [(match_operand:SI 3 "s_register_operand" "r,r,r")
8519 (match_operand:SI 4 "shift_amount_operand" "M,r,M")]))
40dbec34 8520 (const_int 0)))
d82e788e 8521 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
d5d4dc8d 8522 (minus:SI (match_dup 1)
8523 (match_op_dup 2 [(match_dup 3) (match_dup 4)])))]
8524 "TARGET_32BIT"
3ef90e77 8525 "subs%?\\t%0, %1, %3%S2"
344495ea 8526 [(set_attr "conds" "set")
a2cd141b 8527 (set_attr "shift" "3")
d82e788e 8528 (set_attr "arch" "32,a,a")
8529 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
9c08d1fa 8530
f7fbdd4a 8531(define_insn "*sub_shiftsi_compare0_scratch"
bd5b4116 8532 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 8533 (compare:CC_NOOV
d82e788e 8534 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
40dbec34 8535 (match_operator:SI 2 "shift_operator"
d82e788e 8536 [(match_operand:SI 3 "s_register_operand" "r,r,r")
8537 (match_operand:SI 4 "shift_amount_operand" "M,r,M")]))
40dbec34 8538 (const_int 0)))
d82e788e 8539 (clobber (match_scratch:SI 0 "=r,r,r"))]
d5d4dc8d 8540 "TARGET_32BIT"
3ef90e77 8541 "subs%?\\t%0, %1, %3%S2"
344495ea 8542 [(set_attr "conds" "set")
a2cd141b 8543 (set_attr "shift" "3")
d82e788e 8544 (set_attr "arch" "32,a,a")
8545 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
9c08d1fa 8546\f
8547
190efb17 8548(define_insn_and_split "*and_scc"
9c08d1fa 8549 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 8550 (and:SI (match_operator:SI 1 "arm_comparison_operator"
190efb17 8551 [(match_operand 2 "cc_register" "") (const_int 0)])
8552 (match_operand:SI 3 "s_register_operand" "r")))]
cffb2a26 8553 "TARGET_ARM"
190efb17 8554 "#" ; "mov%D1\\t%0, #0\;and%d1\\t%0, %3, #1"
8555 "&& reload_completed"
8556 [(cond_exec (match_dup 5) (set (match_dup 0) (const_int 0)))
8557 (cond_exec (match_dup 4) (set (match_dup 0)
8558 (and:SI (match_dup 3) (const_int 1))))]
8559 {
3754d046 8560 machine_mode mode = GET_MODE (operands[2]);
190efb17 8561 enum rtx_code rc = GET_CODE (operands[1]);
8562
8563 /* Note that operands[4] is the same as operands[1],
8564 but with VOIDmode as the result. */
8565 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
8566 if (mode == CCFPmode || mode == CCFPEmode)
8567 rc = reverse_condition_maybe_unordered (rc);
8568 else
8569 rc = reverse_condition (rc);
8570 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
8571 }
8fa3ba89 8572 [(set_attr "conds" "use")
1b7da4ac 8573 (set_attr "type" "multiple")
8fa3ba89 8574 (set_attr "length" "8")]
8575)
9c08d1fa 8576
190efb17 8577(define_insn_and_split "*ior_scc"
9c08d1fa 8578 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
190efb17 8579 (ior:SI (match_operator:SI 1 "arm_comparison_operator"
8580 [(match_operand 2 "cc_register" "") (const_int 0)])
8581 (match_operand:SI 3 "s_register_operand" "0,?r")))]
cffb2a26 8582 "TARGET_ARM"
e2348bcb 8583 "@
190efb17 8584 orr%d1\\t%0, %3, #1
8585 #"
8586 "&& reload_completed
8587 && REGNO (operands [0]) != REGNO (operands[3])"
8588 ;; && which_alternative == 1
8589 ; mov%D1\\t%0, %3\;orr%d1\\t%0, %3, #1
8590 [(cond_exec (match_dup 5) (set (match_dup 0) (match_dup 3)))
8591 (cond_exec (match_dup 4) (set (match_dup 0)
8592 (ior:SI (match_dup 3) (const_int 1))))]
8593 {
3754d046 8594 machine_mode mode = GET_MODE (operands[2]);
190efb17 8595 enum rtx_code rc = GET_CODE (operands[1]);
8596
8597 /* Note that operands[4] is the same as operands[1],
8598 but with VOIDmode as the result. */
8599 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
8600 if (mode == CCFPmode || mode == CCFPEmode)
8601 rc = reverse_condition_maybe_unordered (rc);
8602 else
8603 rc = reverse_condition (rc);
8604 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
8605 }
8fa3ba89 8606 [(set_attr "conds" "use")
1b7da4ac 8607 (set_attr "length" "4,8")
8608 (set_attr "type" "logic_imm,multiple")]
8fa3ba89 8609)
9c08d1fa 8610
2df9477b 8611; A series of splitters for the compare_scc pattern below. Note that
8612; order is important.
8613(define_split
8614 [(set (match_operand:SI 0 "s_register_operand" "")
8615 (lt:SI (match_operand:SI 1 "s_register_operand" "")
8616 (const_int 0)))
8617 (clobber (reg:CC CC_REGNUM))]
8618 "TARGET_32BIT && reload_completed"
8619 [(set (match_dup 0) (lshiftrt:SI (match_dup 1) (const_int 31)))])
8620
8621(define_split
8622 [(set (match_operand:SI 0 "s_register_operand" "")
8623 (ge:SI (match_operand:SI 1 "s_register_operand" "")
8624 (const_int 0)))
8625 (clobber (reg:CC CC_REGNUM))]
8626 "TARGET_32BIT && reload_completed"
8627 [(set (match_dup 0) (not:SI (match_dup 1)))
8628 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 31)))])
8629
98562479 8630(define_split
8631 [(set (match_operand:SI 0 "s_register_operand" "")
8632 (eq:SI (match_operand:SI 1 "s_register_operand" "")
8633 (const_int 0)))
8634 (clobber (reg:CC CC_REGNUM))]
b232e6b5 8635 "arm_arch5t && TARGET_32BIT"
98562479 8636 [(set (match_dup 0) (clz:SI (match_dup 1)))
8637 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 5)))]
8638)
8639
2df9477b 8640(define_split
8641 [(set (match_operand:SI 0 "s_register_operand" "")
8642 (eq:SI (match_operand:SI 1 "s_register_operand" "")
8643 (const_int 0)))
8644 (clobber (reg:CC CC_REGNUM))]
8645 "TARGET_32BIT && reload_completed"
8646 [(parallel
080c0b9a 8647 [(set (reg:CC CC_REGNUM)
8648 (compare:CC (const_int 1) (match_dup 1)))
2df9477b 8649 (set (match_dup 0)
8650 (minus:SI (const_int 1) (match_dup 1)))])
080c0b9a 8651 (cond_exec (ltu:CC (reg:CC CC_REGNUM) (const_int 0))
2df9477b 8652 (set (match_dup 0) (const_int 0)))])
8653
8654(define_split
8655 [(set (match_operand:SI 0 "s_register_operand" "")
8656 (ne:SI (match_operand:SI 1 "s_register_operand" "")
8657 (match_operand:SI 2 "const_int_operand" "")))
8658 (clobber (reg:CC CC_REGNUM))]
8659 "TARGET_32BIT && reload_completed"
8660 [(parallel
8661 [(set (reg:CC CC_REGNUM)
8662 (compare:CC (match_dup 1) (match_dup 2)))
8663 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))])
8664 (cond_exec (ne:CC (reg:CC CC_REGNUM) (const_int 0))
8665 (set (match_dup 0) (const_int 1)))]
8666{
e3dcfc16 8667 operands[3] = gen_int_mode (-INTVAL (operands[2]), SImode);
2df9477b 8668})
8669
8670(define_split
8671 [(set (match_operand:SI 0 "s_register_operand" "")
8672 (ne:SI (match_operand:SI 1 "s_register_operand" "")
8673 (match_operand:SI 2 "arm_add_operand" "")))
8674 (clobber (reg:CC CC_REGNUM))]
8675 "TARGET_32BIT && reload_completed"
8676 [(parallel
8677 [(set (reg:CC_NOOV CC_REGNUM)
8678 (compare:CC_NOOV (minus:SI (match_dup 1) (match_dup 2))
8679 (const_int 0)))
8680 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
8681 (cond_exec (ne:CC_NOOV (reg:CC_NOOV CC_REGNUM) (const_int 0))
8682 (set (match_dup 0) (const_int 1)))])
8683
8684(define_insn_and_split "*compare_scc"
fd711051 8685 [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts")
8fa3ba89 8686 (match_operator:SI 1 "arm_comparison_operator"
5565501b 8687 [(match_operand:SI 2 "s_register_operand" "r,r")
8688 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
bd5b4116 8689 (clobber (reg:CC CC_REGNUM))]
2df9477b 8690 "TARGET_32BIT"
8691 "#"
8692 "&& reload_completed"
8693 [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 3)))
8694 (cond_exec (match_dup 4) (set (match_dup 0) (const_int 0)))
8695 (cond_exec (match_dup 5) (set (match_dup 0) (const_int 1)))]
8696{
8697 rtx tmp1;
3754d046 8698 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
2df9477b 8699 operands[2], operands[3]);
8700 enum rtx_code rc = GET_CODE (operands[1]);
e2348bcb 8701
2df9477b 8702 tmp1 = gen_rtx_REG (mode, CC_REGNUM);
080c0b9a 8703
2df9477b 8704 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
8705 if (mode == CCFPmode || mode == CCFPEmode)
8706 rc = reverse_condition_maybe_unordered (rc);
8707 else
8708 rc = reverse_condition (rc);
8709 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
1b7da4ac 8710}
8711 [(set_attr "type" "multiple")]
8712)
9c08d1fa 8713
080c0b9a 8714;; Attempt to improve the sequence generated by the compare_scc splitters
8715;; not to use conditional execution.
98562479 8716
8717;; Rd = (eq (reg1) (const_int0)) // ARMv5
8718;; clz Rd, reg1
8719;; lsr Rd, Rd, #5
080c0b9a 8720(define_peephole2
8721 [(set (reg:CC CC_REGNUM)
8722 (compare:CC (match_operand:SI 1 "register_operand" "")
98562479 8723 (const_int 0)))
8724 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
8725 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
8726 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
8727 (set (match_dup 0) (const_int 1)))]
b232e6b5 8728 "arm_arch5t && TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)"
98562479 8729 [(set (match_dup 0) (clz:SI (match_dup 1)))
8730 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 5)))]
8731)
8732
8733;; Rd = (eq (reg1) (const_int0)) // !ARMv5
8734;; negs Rd, reg1
8735;; adc Rd, Rd, reg1
8736(define_peephole2
8737 [(set (reg:CC CC_REGNUM)
8738 (compare:CC (match_operand:SI 1 "register_operand" "")
8739 (const_int 0)))
080c0b9a 8740 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
8741 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
8742 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
8743 (set (match_dup 0) (const_int 1)))
98562479 8744 (match_scratch:SI 2 "r")]
8745 "TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)"
922b6913 8746 [(parallel
8747 [(set (reg:CC CC_REGNUM)
98562479 8748 (compare:CC (const_int 0) (match_dup 1)))
8749 (set (match_dup 2) (minus:SI (const_int 0) (match_dup 1)))])
8750 (set (match_dup 0)
8751 (plus:SI (plus:SI (match_dup 1) (match_dup 2))
8752 (geu:SI (reg:CC CC_REGNUM) (const_int 0))))]
8753)
8754
31991287 8755;; Rd = (eq (reg1) (reg2/imm)) // ARMv5 and optimising for speed.
98562479 8756;; sub Rd, Reg1, reg2
8757;; clz Rd, Rd
8758;; lsr Rd, Rd, #5
8759(define_peephole2
8760 [(set (reg:CC CC_REGNUM)
8761 (compare:CC (match_operand:SI 1 "register_operand" "")
8762 (match_operand:SI 2 "arm_rhs_operand" "")))
8763 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
8764 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
8765 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
8766 (set (match_dup 0) (const_int 1)))]
b232e6b5 8767 "arm_arch5t && TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)
31991287 8768 && !(TARGET_THUMB2 && optimize_insn_for_size_p ())"
98562479 8769 [(set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))
8770 (set (match_dup 0) (clz:SI (match_dup 0)))
8771 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 5)))]
8772)
8773
8774
31991287 8775;; Rd = (eq (reg1) (reg2)) // ! ARMv5 or optimising for size.
98562479 8776;; sub T1, Reg1, reg2
8777;; negs Rd, T1
8778;; adc Rd, Rd, T1
8779(define_peephole2
8780 [(set (reg:CC CC_REGNUM)
8781 (compare:CC (match_operand:SI 1 "register_operand" "")
8782 (match_operand:SI 2 "arm_rhs_operand" "")))
8783 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
8784 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
8785 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
8786 (set (match_dup 0) (const_int 1)))
8787 (match_scratch:SI 3 "r")]
8788 "TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)"
31991287 8789 [(set (match_dup 3) (match_dup 4))
080c0b9a 8790 (parallel
8791 [(set (reg:CC CC_REGNUM)
8792 (compare:CC (const_int 0) (match_dup 3)))
8793 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 3)))])
98562479 8794 (set (match_dup 0)
8795 (plus:SI (plus:SI (match_dup 0) (match_dup 3))
8796 (geu:SI (reg:CC CC_REGNUM) (const_int 0))))]
31991287 8797 "
8798 if (CONST_INT_P (operands[2]))
8799 operands[4] = plus_constant (SImode, operands[1], -INTVAL (operands[2]));
8800 else
8801 operands[4] = gen_rtx_MINUS (SImode, operands[1], operands[2]);
8802 ")
080c0b9a 8803
f7fbdd4a 8804(define_insn "*cond_move"
9c08d1fa 8805 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
aea4c774 8806 (if_then_else:SI (match_operator 3 "equality_operator"
8fa3ba89 8807 [(match_operator 4 "arm_comparison_operator"
8a18b90c 8808 [(match_operand 5 "cc_register" "") (const_int 0)])
aea4c774 8809 (const_int 0)])
8810 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8811 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
cffb2a26 8812 "TARGET_ARM"
9c08d1fa 8813 "*
8fa3ba89 8814 if (GET_CODE (operands[3]) == NE)
8815 {
8816 if (which_alternative != 1)
8817 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
8818 if (which_alternative != 0)
8819 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
8820 return \"\";
8821 }
8822 if (which_alternative != 0)
8823 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8824 if (which_alternative != 1)
8825 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
8826 return \"\";
8827 "
8828 [(set_attr "conds" "use")
282b4c75 8829 (set_attr_alternative "type"
8830 [(if_then_else (match_operand 2 "const_int_operand" "")
8831 (const_string "mov_imm")
8832 (const_string "mov_reg"))
8833 (if_then_else (match_operand 1 "const_int_operand" "")
8834 (const_string "mov_imm")
8835 (const_string "mov_reg"))
8836 (const_string "multiple")])
8fa3ba89 8837 (set_attr "length" "4,4,8")]
8838)
9c08d1fa 8839
f7fbdd4a 8840(define_insn "*cond_arith"
9c08d1fa 8841 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8842 (match_operator:SI 5 "shiftable_operator"
8fa3ba89 8843 [(match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 8844 [(match_operand:SI 2 "s_register_operand" "r,r")
8845 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8846 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 8847 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8848 "TARGET_ARM"
9c08d1fa 8849 "*
8fa3ba89 8850 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
8851 return \"%i5\\t%0, %1, %2, lsr #31\";
40dbec34 8852
8fa3ba89 8853 output_asm_insn (\"cmp\\t%2, %3\", operands);
8854 if (GET_CODE (operands[5]) == AND)
8855 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
8856 else if (GET_CODE (operands[5]) == MINUS)
8857 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
8858 else if (which_alternative != 0)
8859 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8860 return \"%i5%d4\\t%0, %1, #1\";
8861 "
8862 [(set_attr "conds" "clob")
1b7da4ac 8863 (set_attr "length" "12")
8864 (set_attr "type" "multiple")]
8fa3ba89 8865)
9c08d1fa 8866
f7fbdd4a 8867(define_insn "*cond_sub"
9c08d1fa 8868 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8869 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8fa3ba89 8870 (match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 8871 [(match_operand:SI 2 "s_register_operand" "r,r")
8872 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 8873 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8874 "TARGET_ARM"
9c08d1fa 8875 "*
8fa3ba89 8876 output_asm_insn (\"cmp\\t%2, %3\", operands);
8877 if (which_alternative != 0)
8878 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8879 return \"sub%d4\\t%0, %1, #1\";
8880 "
8881 [(set_attr "conds" "clob")
1b7da4ac 8882 (set_attr "length" "8,12")
8883 (set_attr "type" "multiple")]
8fa3ba89 8884)
9c08d1fa 8885
aea4c774 8886(define_insn "*cmp_ite0"
cffb2a26 8887 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 8888 (compare
8889 (if_then_else:SI
8fa3ba89 8890 (match_operator 4 "arm_comparison_operator"
2ff91fec 8891 [(match_operand:SI 0 "s_register_operand"
8892 "l,l,l,r,r,r,r,r,r")
8893 (match_operand:SI 1 "arm_add_operand"
8894 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
8fa3ba89 8895 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 8896 [(match_operand:SI 2 "s_register_operand"
8897 "l,r,r,l,l,r,r,r,r")
8898 (match_operand:SI 3 "arm_add_operand"
8899 "lPy,rI,L,lPy,lPy,rI,rI,L,L")])
aea4c774 8900 (const_int 0))
8901 (const_int 0)))]
2ff91fec 8902 "TARGET_32BIT"
9c08d1fa 8903 "*
aea4c774 8904 {
2ff91fec 8905 static const char * const cmp1[NUM_OF_COND_CMP][2] =
8906 {
8907 {\"cmp%d5\\t%0, %1\",
8908 \"cmp%d4\\t%2, %3\"},
8909 {\"cmn%d5\\t%0, #%n1\",
8910 \"cmp%d4\\t%2, %3\"},
8911 {\"cmp%d5\\t%0, %1\",
8912 \"cmn%d4\\t%2, #%n3\"},
8913 {\"cmn%d5\\t%0, #%n1\",
8914 \"cmn%d4\\t%2, #%n3\"}
8915 };
8916 static const char * const cmp2[NUM_OF_COND_CMP][2] =
8917 {
8918 {\"cmp\\t%2, %3\",
8919 \"cmp\\t%0, %1\"},
8920 {\"cmp\\t%2, %3\",
8921 \"cmn\\t%0, #%n1\"},
8922 {\"cmn\\t%2, #%n3\",
8923 \"cmp\\t%0, %1\"},
8924 {\"cmn\\t%2, #%n3\",
8925 \"cmn\\t%0, #%n1\"}
8926 };
8927 static const char * const ite[2] =
8fa3ba89 8928 {
2ff91fec 8929 \"it\\t%d5\",
8930 \"it\\t%d4\"
8fa3ba89 8931 };
2ff91fec 8932 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
8933 CMP_CMP, CMN_CMP, CMP_CMP,
8934 CMN_CMP, CMP_CMN, CMN_CMN};
8fa3ba89 8935 int swap =
8936 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8937
2ff91fec 8938 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
8939 if (TARGET_THUMB2) {
8940 output_asm_insn (ite[swap], operands);
8941 }
8942 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
8943 return \"\";
8fa3ba89 8944 }"
8945 [(set_attr "conds" "set")
2ff91fec 8946 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
8bdfd6ed 8947 (set_attr "enabled_for_short_it" "yes,no,no,no,no,no,no,no,no")
1b7da4ac 8948 (set_attr "type" "multiple")
2ff91fec 8949 (set_attr_alternative "length"
8950 [(const_int 6)
8951 (const_int 8)
8952 (const_int 8)
8953 (const_int 8)
8954 (const_int 8)
8955 (if_then_else (eq_attr "is_thumb" "no")
8956 (const_int 8)
8957 (const_int 10))
8958 (if_then_else (eq_attr "is_thumb" "no")
8959 (const_int 8)
8960 (const_int 10))
8961 (if_then_else (eq_attr "is_thumb" "no")
8962 (const_int 8)
8963 (const_int 10))
8964 (if_then_else (eq_attr "is_thumb" "no")
8965 (const_int 8)
8966 (const_int 10))])]
8fa3ba89 8967)
9c08d1fa 8968
aea4c774 8969(define_insn "*cmp_ite1"
cffb2a26 8970 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 8971 (compare
8972 (if_then_else:SI
8fa3ba89 8973 (match_operator 4 "arm_comparison_operator"
2ff91fec 8974 [(match_operand:SI 0 "s_register_operand"
8975 "l,l,l,r,r,r,r,r,r")
8976 (match_operand:SI 1 "arm_add_operand"
8977 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
8fa3ba89 8978 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 8979 [(match_operand:SI 2 "s_register_operand"
8980 "l,r,r,l,l,r,r,r,r")
8981 (match_operand:SI 3 "arm_add_operand"
8982 "lPy,rI,L,lPy,lPy,rI,rI,L,L")])
aea4c774 8983 (const_int 1))
8984 (const_int 0)))]
2ff91fec 8985 "TARGET_32BIT"
9c08d1fa 8986 "*
9c08d1fa 8987 {
2ff91fec 8988 static const char * const cmp1[NUM_OF_COND_CMP][2] =
8989 {
8990 {\"cmp\\t%0, %1\",
8991 \"cmp\\t%2, %3\"},
8992 {\"cmn\\t%0, #%n1\",
8993 \"cmp\\t%2, %3\"},
8994 {\"cmp\\t%0, %1\",
8995 \"cmn\\t%2, #%n3\"},
8996 {\"cmn\\t%0, #%n1\",
8997 \"cmn\\t%2, #%n3\"}
8998 };
8999 static const char * const cmp2[NUM_OF_COND_CMP][2] =
215b30b3 9000 {
2ff91fec 9001 {\"cmp%d4\\t%2, %3\",
9002 \"cmp%D5\\t%0, %1\"},
9003 {\"cmp%d4\\t%2, %3\",
9004 \"cmn%D5\\t%0, #%n1\"},
9005 {\"cmn%d4\\t%2, #%n3\",
9006 \"cmp%D5\\t%0, %1\"},
9007 {\"cmn%d4\\t%2, #%n3\",
9008 \"cmn%D5\\t%0, #%n1\"}
215b30b3 9009 };
2ff91fec 9010 static const char * const ite[2] =
9011 {
9012 \"it\\t%d4\",
9013 \"it\\t%D5\"
9014 };
9015 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
9016 CMP_CMP, CMN_CMP, CMP_CMP,
9017 CMN_CMP, CMP_CMN, CMN_CMN};
215b30b3 9018 int swap =
9019 comparison_dominates_p (GET_CODE (operands[5]),
9020 reverse_condition (GET_CODE (operands[4])));
9021
2ff91fec 9022 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9023 if (TARGET_THUMB2) {
9024 output_asm_insn (ite[swap], operands);
9025 }
9026 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9027 return \"\";
215b30b3 9028 }"
8fa3ba89 9029 [(set_attr "conds" "set")
2ff91fec 9030 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
8bdfd6ed 9031 (set_attr "enabled_for_short_it" "yes,no,no,no,no,no,no,no,no")
2ff91fec 9032 (set_attr_alternative "length"
9033 [(const_int 6)
9034 (const_int 8)
9035 (const_int 8)
9036 (const_int 8)
9037 (const_int 8)
9038 (if_then_else (eq_attr "is_thumb" "no")
9039 (const_int 8)
9040 (const_int 10))
9041 (if_then_else (eq_attr "is_thumb" "no")
9042 (const_int 8)
9043 (const_int 10))
9044 (if_then_else (eq_attr "is_thumb" "no")
9045 (const_int 8)
9046 (const_int 10))
9047 (if_then_else (eq_attr "is_thumb" "no")
9048 (const_int 8)
1b7da4ac 9049 (const_int 10))])
9050 (set_attr "type" "multiple")]
8fa3ba89 9051)
9c08d1fa 9052
f6c53574 9053(define_insn "*cmp_and"
9054 [(set (match_operand 6 "dominant_cc_register" "")
9055 (compare
9056 (and:SI
9057 (match_operator 4 "arm_comparison_operator"
db23acf2 9058 [(match_operand:SI 0 "s_register_operand"
9059 "l,l,l,r,r,r,r,r,r,r")
9060 (match_operand:SI 1 "arm_add_operand"
9061 "lPy,lPy,lPy,rI,L,r,rI,L,rI,L")])
f6c53574 9062 (match_operator:SI 5 "arm_comparison_operator"
db23acf2 9063 [(match_operand:SI 2 "s_register_operand"
9064 "l,r,r,l,l,r,r,r,r,r")
9065 (match_operand:SI 3 "arm_add_operand"
9066 "lPy,rI,L,lPy,lPy,r,rI,rI,L,L")]))
f6c53574 9067 (const_int 0)))]
2ff91fec 9068 "TARGET_32BIT"
f6c53574 9069 "*
9070 {
2ff91fec 9071 static const char *const cmp1[NUM_OF_COND_CMP][2] =
f6c53574 9072 {
2ff91fec 9073 {\"cmp%d5\\t%0, %1\",
9074 \"cmp%d4\\t%2, %3\"},
9075 {\"cmn%d5\\t%0, #%n1\",
9076 \"cmp%d4\\t%2, %3\"},
9077 {\"cmp%d5\\t%0, %1\",
9078 \"cmn%d4\\t%2, #%n3\"},
9079 {\"cmn%d5\\t%0, #%n1\",
9080 \"cmn%d4\\t%2, #%n3\"}
f6c53574 9081 };
2ff91fec 9082 static const char *const cmp2[NUM_OF_COND_CMP][2] =
9083 {
9084 {\"cmp\\t%2, %3\",
9085 \"cmp\\t%0, %1\"},
9086 {\"cmp\\t%2, %3\",
9087 \"cmn\\t%0, #%n1\"},
9088 {\"cmn\\t%2, #%n3\",
9089 \"cmp\\t%0, %1\"},
9090 {\"cmn\\t%2, #%n3\",
9091 \"cmn\\t%0, #%n1\"}
9092 };
9093 static const char *const ite[2] =
9094 {
9095 \"it\\t%d5\",
9096 \"it\\t%d4\"
9097 };
db23acf2 9098 static const int cmp_idx[] = {CMP_CMP, CMP_CMP, CMP_CMN,
9099 CMP_CMP, CMN_CMP, CMP_CMP,
9100 CMP_CMP, CMN_CMP, CMP_CMN,
9101 CMN_CMN};
f6c53574 9102 int swap =
9103 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9104
2ff91fec 9105 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9106 if (TARGET_THUMB2) {
9107 output_asm_insn (ite[swap], operands);
9108 }
9109 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9110 return \"\";
f6c53574 9111 }"
9112 [(set_attr "conds" "set")
9113 (set_attr "predicable" "no")
db23acf2 9114 (set_attr "arch" "t2,t2,t2,t2,t2,t2,any,any,any,any")
9115 (set_attr "enabled_for_short_it" "yes,no,no,no,no,yes,no,no,no,no")
2ff91fec 9116 (set_attr_alternative "length"
9117 [(const_int 6)
9118 (const_int 8)
9119 (const_int 8)
9120 (const_int 8)
9121 (const_int 8)
db23acf2 9122 (const_int 6)
2ff91fec 9123 (if_then_else (eq_attr "is_thumb" "no")
9124 (const_int 8)
9125 (const_int 10))
9126 (if_then_else (eq_attr "is_thumb" "no")
9127 (const_int 8)
9128 (const_int 10))
9129 (if_then_else (eq_attr "is_thumb" "no")
9130 (const_int 8)
9131 (const_int 10))
9132 (if_then_else (eq_attr "is_thumb" "no")
9133 (const_int 8)
1b7da4ac 9134 (const_int 10))])
9135 (set_attr "type" "multiple")]
f6c53574 9136)
9137
9138(define_insn "*cmp_ior"
9139 [(set (match_operand 6 "dominant_cc_register" "")
9140 (compare
9141 (ior:SI
9142 (match_operator 4 "arm_comparison_operator"
2ff91fec 9143 [(match_operand:SI 0 "s_register_operand"
db23acf2 9144 "l,l,l,r,r,r,r,r,r,r")
2ff91fec 9145 (match_operand:SI 1 "arm_add_operand"
db23acf2 9146 "lPy,lPy,lPy,rI,L,r,rI,L,rI,L")])
f6c53574 9147 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 9148 [(match_operand:SI 2 "s_register_operand"
db23acf2 9149 "l,r,r,l,l,r,r,r,r,r")
2ff91fec 9150 (match_operand:SI 3 "arm_add_operand"
db23acf2 9151 "lPy,rI,L,lPy,lPy,r,rI,rI,L,L")]))
f6c53574 9152 (const_int 0)))]
2ff91fec 9153 "TARGET_32BIT"
f6c53574 9154 "*
f6c53574 9155 {
2ff91fec 9156 static const char *const cmp1[NUM_OF_COND_CMP][2] =
9157 {
9158 {\"cmp\\t%0, %1\",
9159 \"cmp\\t%2, %3\"},
9160 {\"cmn\\t%0, #%n1\",
9161 \"cmp\\t%2, %3\"},
9162 {\"cmp\\t%0, %1\",
9163 \"cmn\\t%2, #%n3\"},
9164 {\"cmn\\t%0, #%n1\",
9165 \"cmn\\t%2, #%n3\"}
9166 };
9167 static const char *const cmp2[NUM_OF_COND_CMP][2] =
9168 {
9169 {\"cmp%D4\\t%2, %3\",
9170 \"cmp%D5\\t%0, %1\"},
9171 {\"cmp%D4\\t%2, %3\",
9172 \"cmn%D5\\t%0, #%n1\"},
9173 {\"cmn%D4\\t%2, #%n3\",
9174 \"cmp%D5\\t%0, %1\"},
9175 {\"cmn%D4\\t%2, #%n3\",
9176 \"cmn%D5\\t%0, #%n1\"}
9177 };
9178 static const char *const ite[2] =
9179 {
9180 \"it\\t%D4\",
9181 \"it\\t%D5\"
9182 };
db23acf2 9183 static const int cmp_idx[] = {CMP_CMP, CMP_CMP, CMP_CMN,
9184 CMP_CMP, CMN_CMP, CMP_CMP,
9185 CMP_CMP, CMN_CMP, CMP_CMN,
9186 CMN_CMN};
2ff91fec 9187 int swap =
9188 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9189
9190 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9191 if (TARGET_THUMB2) {
9192 output_asm_insn (ite[swap], operands);
9193 }
9194 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9195 return \"\";
9196 }
9197 "
f6c53574 9198 [(set_attr "conds" "set")
db23acf2 9199 (set_attr "arch" "t2,t2,t2,t2,t2,t2,any,any,any,any")
9200 (set_attr "enabled_for_short_it" "yes,no,no,no,no,yes,no,no,no,no")
2ff91fec 9201 (set_attr_alternative "length"
9202 [(const_int 6)
9203 (const_int 8)
9204 (const_int 8)
9205 (const_int 8)
9206 (const_int 8)
db23acf2 9207 (const_int 6)
2ff91fec 9208 (if_then_else (eq_attr "is_thumb" "no")
9209 (const_int 8)
9210 (const_int 10))
9211 (if_then_else (eq_attr "is_thumb" "no")
9212 (const_int 8)
9213 (const_int 10))
9214 (if_then_else (eq_attr "is_thumb" "no")
9215 (const_int 8)
9216 (const_int 10))
9217 (if_then_else (eq_attr "is_thumb" "no")
9218 (const_int 8)
1b7da4ac 9219 (const_int 10))])
9220 (set_attr "type" "multiple")]
f6c53574 9221)
9222
3c5afce6 9223(define_insn_and_split "*ior_scc_scc"
f9d240a0 9224 [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts")
3c5afce6 9225 (ior:SI (match_operator:SI 3 "arm_comparison_operator"
f9d240a0 9226 [(match_operand:SI 1 "s_register_operand" "l,r")
9227 (match_operand:SI 2 "arm_add_operand" "lPy,rIL")])
3c5afce6 9228 (match_operator:SI 6 "arm_comparison_operator"
f9d240a0 9229 [(match_operand:SI 4 "s_register_operand" "l,r")
9230 (match_operand:SI 5 "arm_add_operand" "lPy,rIL")])))
3c5afce6 9231 (clobber (reg:CC CC_REGNUM))]
2ff91fec 9232 "TARGET_32BIT
3c5afce6 9233 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
9234 != CCmode)"
9235 "#"
2ff91fec 9236 "TARGET_32BIT && reload_completed"
3c5afce6 9237 [(set (match_dup 7)
9238 (compare
9239 (ior:SI
9240 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9241 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9242 (const_int 0)))
9243 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9244 "operands[7]
9245 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9246 DOM_CC_X_OR_Y),
601f584c 9247 CC_REGNUM);"
9248 [(set_attr "conds" "clob")
8bdfd6ed 9249 (set_attr "enabled_for_short_it" "yes,no")
1b7da4ac 9250 (set_attr "length" "16")
9251 (set_attr "type" "multiple")]
9252)
601f584c 9253
9254; If the above pattern is followed by a CMP insn, then the compare is
9255; redundant, since we can rework the conditional instruction that follows.
9256(define_insn_and_split "*ior_scc_scc_cmp"
9257 [(set (match_operand 0 "dominant_cc_register" "")
9258 (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
f9d240a0 9259 [(match_operand:SI 1 "s_register_operand" "l,r")
9260 (match_operand:SI 2 "arm_add_operand" "lPy,rIL")])
601f584c 9261 (match_operator:SI 6 "arm_comparison_operator"
f9d240a0 9262 [(match_operand:SI 4 "s_register_operand" "l,r")
9263 (match_operand:SI 5 "arm_add_operand" "lPy,rIL")]))
601f584c 9264 (const_int 0)))
f9d240a0 9265 (set (match_operand:SI 7 "s_register_operand" "=Ts,Ts")
601f584c 9266 (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9267 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
2ff91fec 9268 "TARGET_32BIT"
601f584c 9269 "#"
2ff91fec 9270 "TARGET_32BIT && reload_completed"
601f584c 9271 [(set (match_dup 0)
9272 (compare
9273 (ior:SI
9274 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9275 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9276 (const_int 0)))
9277 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9278 ""
9279 [(set_attr "conds" "set")
8bdfd6ed 9280 (set_attr "enabled_for_short_it" "yes,no")
1b7da4ac 9281 (set_attr "length" "16")
9282 (set_attr "type" "multiple")]
9283)
3c5afce6 9284
9285(define_insn_and_split "*and_scc_scc"
f9d240a0 9286 [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts")
3c5afce6 9287 (and:SI (match_operator:SI 3 "arm_comparison_operator"
f9d240a0 9288 [(match_operand:SI 1 "s_register_operand" "l,r")
9289 (match_operand:SI 2 "arm_add_operand" "lPy,rIL")])
3c5afce6 9290 (match_operator:SI 6 "arm_comparison_operator"
f9d240a0 9291 [(match_operand:SI 4 "s_register_operand" "l,r")
9292 (match_operand:SI 5 "arm_add_operand" "lPy,rIL")])))
3c5afce6 9293 (clobber (reg:CC CC_REGNUM))]
2ff91fec 9294 "TARGET_32BIT
3c5afce6 9295 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9296 != CCmode)"
9297 "#"
2ff91fec 9298 "TARGET_32BIT && reload_completed
601f584c 9299 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9300 != CCmode)"
3c5afce6 9301 [(set (match_dup 7)
9302 (compare
9303 (and:SI
9304 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9305 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9306 (const_int 0)))
9307 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9308 "operands[7]
9309 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9310 DOM_CC_X_AND_Y),
601f584c 9311 CC_REGNUM);"
9312 [(set_attr "conds" "clob")
8bdfd6ed 9313 (set_attr "enabled_for_short_it" "yes,no")
1b7da4ac 9314 (set_attr "length" "16")
9315 (set_attr "type" "multiple")]
9316)
601f584c 9317
9318; If the above pattern is followed by a CMP insn, then the compare is
9319; redundant, since we can rework the conditional instruction that follows.
9320(define_insn_and_split "*and_scc_scc_cmp"
9321 [(set (match_operand 0 "dominant_cc_register" "")
9322 (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
f9d240a0 9323 [(match_operand:SI 1 "s_register_operand" "l,r")
9324 (match_operand:SI 2 "arm_add_operand" "lPy,rIL")])
601f584c 9325 (match_operator:SI 6 "arm_comparison_operator"
f9d240a0 9326 [(match_operand:SI 4 "s_register_operand" "l,r")
9327 (match_operand:SI 5 "arm_add_operand" "lPy,rIL")]))
601f584c 9328 (const_int 0)))
f9d240a0 9329 (set (match_operand:SI 7 "s_register_operand" "=Ts,Ts")
601f584c 9330 (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9331 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
2ff91fec 9332 "TARGET_32BIT"
601f584c 9333 "#"
2ff91fec 9334 "TARGET_32BIT && reload_completed"
601f584c 9335 [(set (match_dup 0)
9336 (compare
9337 (and:SI
9338 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9339 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9340 (const_int 0)))
9341 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9342 ""
9343 [(set_attr "conds" "set")
8bdfd6ed 9344 (set_attr "enabled_for_short_it" "yes,no")
1b7da4ac 9345 (set_attr "length" "16")
9346 (set_attr "type" "multiple")]
9347)
601f584c 9348
9349;; If there is no dominance in the comparison, then we can still save an
9350;; instruction in the AND case, since we can know that the second compare
9351;; need only zero the value if false (if true, then the value is already
9352;; correct).
9353(define_insn_and_split "*and_scc_scc_nodom"
fd711051 9354 [(set (match_operand:SI 0 "s_register_operand" "=&Ts,&Ts,&Ts")
601f584c 9355 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9356 [(match_operand:SI 1 "s_register_operand" "r,r,0")
9357 (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
9358 (match_operator:SI 6 "arm_comparison_operator"
9359 [(match_operand:SI 4 "s_register_operand" "r,r,r")
9360 (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
9361 (clobber (reg:CC CC_REGNUM))]
2ff91fec 9362 "TARGET_32BIT
601f584c 9363 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9364 == CCmode)"
9365 "#"
2ff91fec 9366 "TARGET_32BIT && reload_completed"
601f584c 9367 [(parallel [(set (match_dup 0)
9368 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
9369 (clobber (reg:CC CC_REGNUM))])
9370 (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
9371 (set (match_dup 0)
9372 (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
9373 (match_dup 0)
9374 (const_int 0)))]
9375 "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
9376 operands[4], operands[5]),
9377 CC_REGNUM);
9378 operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
9379 operands[5]);"
9380 [(set_attr "conds" "clob")
1b7da4ac 9381 (set_attr "length" "20")
9382 (set_attr "type" "multiple")]
9383)
3c5afce6 9384
3a0bdee0 9385(define_split
9386 [(set (reg:CC_NOOV CC_REGNUM)
9387 (compare:CC_NOOV (ior:SI
9388 (and:SI (match_operand:SI 0 "s_register_operand" "")
9389 (const_int 1))
b0694be0 9390 (match_operator:SI 1 "arm_comparison_operator"
3a0bdee0 9391 [(match_operand:SI 2 "s_register_operand" "")
9392 (match_operand:SI 3 "arm_add_operand" "")]))
9393 (const_int 0)))
9394 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9395 "TARGET_ARM"
9396 [(set (match_dup 4)
9397 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9398 (match_dup 0)))
9399 (set (reg:CC_NOOV CC_REGNUM)
9400 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9401 (const_int 0)))]
9402 "")
9403
9404(define_split
9405 [(set (reg:CC_NOOV CC_REGNUM)
9406 (compare:CC_NOOV (ior:SI
b0694be0 9407 (match_operator:SI 1 "arm_comparison_operator"
3a0bdee0 9408 [(match_operand:SI 2 "s_register_operand" "")
9409 (match_operand:SI 3 "arm_add_operand" "")])
9410 (and:SI (match_operand:SI 0 "s_register_operand" "")
9411 (const_int 1)))
9412 (const_int 0)))
9413 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9414 "TARGET_ARM"
9415 [(set (match_dup 4)
9416 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9417 (match_dup 0)))
9418 (set (reg:CC_NOOV CC_REGNUM)
9419 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9420 (const_int 0)))]
9421 "")
25f905c2 9422;; ??? The conditional patterns above need checking for Thumb-2 usefulness
3a0bdee0 9423
190efb17 9424(define_insn_and_split "*negscc"
9c08d1fa 9425 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9426 (neg:SI (match_operator 3 "arm_comparison_operator"
9c08d1fa 9427 [(match_operand:SI 1 "s_register_operand" "r")
9428 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
bd5b4116 9429 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9430 "TARGET_ARM"
190efb17 9431 "#"
9432 "&& reload_completed"
9433 [(const_int 0)]
9434 {
9435 rtx cc_reg = gen_rtx_REG (CCmode, CC_REGNUM);
e2348bcb 9436
190efb17 9437 if (GET_CODE (operands[3]) == LT && operands[2] == const0_rtx)
9438 {
9439 /* Emit mov\\t%0, %1, asr #31 */
d1f9b275 9440 emit_insn (gen_rtx_SET (operands[0],
190efb17 9441 gen_rtx_ASHIFTRT (SImode,
9442 operands[1],
9443 GEN_INT (31))));
9444 DONE;
9445 }
9446 else if (GET_CODE (operands[3]) == NE)
9447 {
9448 /* Emit subs\\t%0, %1, %2\;mvnne\\t%0, #0 */
9449 if (CONST_INT_P (operands[2]))
9450 emit_insn (gen_cmpsi2_addneg (operands[0], operands[1], operands[2],
e3dcfc16 9451 gen_int_mode (-INTVAL (operands[2]),
9452 SImode)));
190efb17 9453 else
9454 emit_insn (gen_subsi3_compare (operands[0], operands[1], operands[2]));
9455
9456 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
9457 gen_rtx_NE (SImode,
9458 cc_reg,
9459 const0_rtx),
d1f9b275 9460 gen_rtx_SET (operands[0],
190efb17 9461 GEN_INT (~0))));
9462 DONE;
9463 }
9464 else
9465 {
9466 /* Emit: cmp\\t%1, %2\;mov%D3\\t%0, #0\;mvn%d3\\t%0, #0 */
d1f9b275 9467 emit_insn (gen_rtx_SET (cc_reg,
190efb17 9468 gen_rtx_COMPARE (CCmode, operands[1], operands[2])));
9469 enum rtx_code rc = GET_CODE (operands[3]);
9470
9471 rc = reverse_condition (rc);
9472 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
9473 gen_rtx_fmt_ee (rc,
9474 VOIDmode,
9475 cc_reg,
9476 const0_rtx),
d1f9b275 9477 gen_rtx_SET (operands[0], const0_rtx)));
190efb17 9478 rc = GET_CODE (operands[3]);
9479 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
9480 gen_rtx_fmt_ee (rc,
9481 VOIDmode,
9482 cc_reg,
9483 const0_rtx),
d1f9b275 9484 gen_rtx_SET (operands[0],
190efb17 9485 GEN_INT (~0))));
9486 DONE;
9487 }
9488 FAIL;
9489 }
8fa3ba89 9490 [(set_attr "conds" "clob")
1b7da4ac 9491 (set_attr "length" "12")
9492 (set_attr "type" "multiple")]
8fa3ba89 9493)
9c08d1fa 9494
90404b57 9495(define_insn_and_split "movcond_addsi"
9496 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r")
9497 (if_then_else:SI
9498 (match_operator 5 "comparison_operator"
9499 [(plus:SI (match_operand:SI 3 "s_register_operand" "r,r,r")
9500 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL"))
9501 (const_int 0)])
9502 (match_operand:SI 1 "arm_rhs_operand" "rI,rPy,r")
9503 (match_operand:SI 2 "arm_rhs_operand" "rI,rPy,r")))
9504 (clobber (reg:CC CC_REGNUM))]
9505 "TARGET_32BIT"
9506 "#"
9507 "&& reload_completed"
9508 [(set (reg:CC_NOOV CC_REGNUM)
9509 (compare:CC_NOOV
9510 (plus:SI (match_dup 3)
9511 (match_dup 4))
9512 (const_int 0)))
9513 (set (match_dup 0) (match_dup 1))
9514 (cond_exec (match_dup 6)
9515 (set (match_dup 0) (match_dup 2)))]
9516 "
9517 {
3754d046 9518 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[5]),
90404b57 9519 operands[3], operands[4]);
9520 enum rtx_code rc = GET_CODE (operands[5]);
90404b57 9521 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9522 gcc_assert (!(mode == CCFPmode || mode == CCFPEmode));
22440aeb 9523 if (!REG_P (operands[2]) || REGNO (operands[2]) != REGNO (operands[0]))
4d01ce2f 9524 rc = reverse_condition (rc);
f145bcba 9525 else
9526 std::swap (operands[1], operands[2]);
90404b57 9527
9528 operands[6] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9529 }
9530 "
9531 [(set_attr "conds" "clob")
8bdfd6ed 9532 (set_attr "enabled_for_short_it" "no,yes,yes")
1b7da4ac 9533 (set_attr "type" "multiple")]
90404b57 9534)
9535
9c08d1fa 9536(define_insn "movcond"
9537 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 9538 (if_then_else:SI
8fa3ba89 9539 (match_operator 5 "arm_comparison_operator"
5565501b 9540 [(match_operand:SI 3 "s_register_operand" "r,r,r")
9541 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
9542 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9543 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 9544 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9545 "TARGET_ARM"
9c08d1fa 9546 "*
9547 if (GET_CODE (operands[5]) == LT
9548 && (operands[4] == const0_rtx))
9549 {
0438d37f 9550 if (which_alternative != 1 && REG_P (operands[1]))
9c08d1fa 9551 {
9c08d1fa 9552 if (operands[2] == const0_rtx)
e2348bcb 9553 return \"and\\t%0, %1, %3, asr #31\";
9554 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
9c08d1fa 9555 }
0438d37f 9556 else if (which_alternative != 0 && REG_P (operands[2]))
9c08d1fa 9557 {
9c08d1fa 9558 if (operands[1] == const0_rtx)
e2348bcb 9559 return \"bic\\t%0, %2, %3, asr #31\";
9560 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
9c08d1fa 9561 }
9562 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 9563 are constants. */
9c08d1fa 9564 }
e2348bcb 9565
9c08d1fa 9566 if (GET_CODE (operands[5]) == GE
9567 && (operands[4] == const0_rtx))
9568 {
0438d37f 9569 if (which_alternative != 1 && REG_P (operands[1]))
9c08d1fa 9570 {
9c08d1fa 9571 if (operands[2] == const0_rtx)
e2348bcb 9572 return \"bic\\t%0, %1, %3, asr #31\";
9573 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
9c08d1fa 9574 }
0438d37f 9575 else if (which_alternative != 0 && REG_P (operands[2]))
9c08d1fa 9576 {
9c08d1fa 9577 if (operands[1] == const0_rtx)
e2348bcb 9578 return \"and\\t%0, %2, %3, asr #31\";
9579 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
9c08d1fa 9580 }
9581 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 9582 are constants. */
9c08d1fa 9583 }
0438d37f 9584 if (CONST_INT_P (operands[4])
9c08d1fa 9585 && !const_ok_for_arm (INTVAL (operands[4])))
e2348bcb 9586 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
9c08d1fa 9587 else
e2348bcb 9588 output_asm_insn (\"cmp\\t%3, %4\", operands);
9c08d1fa 9589 if (which_alternative != 0)
e2348bcb 9590 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
9c08d1fa 9591 if (which_alternative != 1)
e2348bcb 9592 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
9c08d1fa 9593 return \"\";
215b30b3 9594 "
8fa3ba89 9595 [(set_attr "conds" "clob")
1b7da4ac 9596 (set_attr "length" "8,8,12")
9597 (set_attr "type" "multiple")]
8fa3ba89 9598)
9c08d1fa 9599
25f905c2 9600;; ??? The patterns below need checking for Thumb-2 usefulness.
9601
8a18b90c 9602(define_insn "*ifcompare_plus_move"
9603 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9604 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 9605 [(match_operand:SI 4 "s_register_operand" "r,r")
9606 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9607 (plus:SI
9608 (match_operand:SI 2 "s_register_operand" "r,r")
9609 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
129a2fe4 9610 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 9611 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9612 "TARGET_ARM"
8a18b90c 9613 "#"
8fa3ba89 9614 [(set_attr "conds" "clob")
1b7da4ac 9615 (set_attr "length" "8,12")
9616 (set_attr "type" "multiple")]
8fa3ba89 9617)
8a18b90c 9618
9619(define_insn "*if_plus_move"
129a2fe4 9620 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 9621 (if_then_else:SI
8fa3ba89 9622 (match_operator 4 "arm_comparison_operator"
8a18b90c 9623 [(match_operand 5 "cc_register" "") (const_int 0)])
9624 (plus:SI
129a2fe4 9625 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9626 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
9627 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
cffb2a26 9628 "TARGET_ARM"
8a18b90c 9629 "@
9630 add%d4\\t%0, %2, %3
9631 sub%d4\\t%0, %2, #%n3
9632 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
129a2fe4 9633 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8fa3ba89 9634 [(set_attr "conds" "use")
9635 (set_attr "length" "4,4,8,8")
65f68e55 9636 (set_attr_alternative "type"
9637 [(if_then_else (match_operand 3 "const_int_operand" "")
d82e788e 9638 (const_string "alu_imm" )
112eda6f 9639 (const_string "alu_sreg"))
d82e788e 9640 (const_string "alu_imm")
282b4c75 9641 (const_string "multiple")
9642 (const_string "multiple")])]
8fa3ba89 9643)
8a18b90c 9644
9645(define_insn "*ifcompare_move_plus"
5565501b 9646 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9647 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 9648 [(match_operand:SI 4 "s_register_operand" "r,r")
9649 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 9650 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 9651 (plus:SI
9652 (match_operand:SI 2 "s_register_operand" "r,r")
9653 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
bd5b4116 9654 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9655 "TARGET_ARM"
8a18b90c 9656 "#"
8fa3ba89 9657 [(set_attr "conds" "clob")
1b7da4ac 9658 (set_attr "length" "8,12")
9659 (set_attr "type" "multiple")]
8fa3ba89 9660)
8a18b90c 9661
9662(define_insn "*if_move_plus"
129a2fe4 9663 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 9664 (if_then_else:SI
8fa3ba89 9665 (match_operator 4 "arm_comparison_operator"
8a18b90c 9666 [(match_operand 5 "cc_register" "") (const_int 0)])
129a2fe4 9667 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8a18b90c 9668 (plus:SI
129a2fe4 9669 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9670 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
cffb2a26 9671 "TARGET_ARM"
8a18b90c 9672 "@
9673 add%D4\\t%0, %2, %3
9674 sub%D4\\t%0, %2, #%n3
9675 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
129a2fe4 9676 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8fa3ba89 9677 [(set_attr "conds" "use")
9678 (set_attr "length" "4,4,8,8")
282b4c75 9679 (set_attr_alternative "type"
9680 [(if_then_else (match_operand 3 "const_int_operand" "")
9681 (const_string "alu_imm" )
9682 (const_string "alu_sreg"))
9683 (const_string "alu_imm")
9684 (const_string "multiple")
9685 (const_string "multiple")])]
8fa3ba89 9686)
8a18b90c 9687
9688(define_insn "*ifcompare_arith_arith"
9689 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9690 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8a18b90c 9691 [(match_operand:SI 5 "s_register_operand" "r")
9692 (match_operand:SI 6 "arm_add_operand" "rIL")])
9c08d1fa 9693 (match_operator:SI 8 "shiftable_operator"
8a18b90c 9694 [(match_operand:SI 1 "s_register_operand" "r")
9695 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9c08d1fa 9696 (match_operator:SI 7 "shiftable_operator"
8a18b90c 9697 [(match_operand:SI 3 "s_register_operand" "r")
9698 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
bd5b4116 9699 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9700 "TARGET_ARM"
8a18b90c 9701 "#"
8fa3ba89 9702 [(set_attr "conds" "clob")
1b7da4ac 9703 (set_attr "length" "12")
9704 (set_attr "type" "multiple")]
8fa3ba89 9705)
9c08d1fa 9706
8a18b90c 9707(define_insn "*if_arith_arith"
9708 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9709 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8a18b90c 9710 [(match_operand 8 "cc_register" "") (const_int 0)])
9711 (match_operator:SI 6 "shiftable_operator"
9712 [(match_operand:SI 1 "s_register_operand" "r")
9713 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9714 (match_operator:SI 7 "shiftable_operator"
9715 [(match_operand:SI 3 "s_register_operand" "r")
9716 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
cffb2a26 9717 "TARGET_ARM"
8a18b90c 9718 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8fa3ba89 9719 [(set_attr "conds" "use")
1b7da4ac 9720 (set_attr "length" "8")
9721 (set_attr "type" "multiple")]
8fa3ba89 9722)
8a18b90c 9723
f7fbdd4a 9724(define_insn "*ifcompare_arith_move"
9c08d1fa 9725 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9726 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 9727 [(match_operand:SI 2 "s_register_operand" "r,r")
5565501b 9728 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
9c08d1fa 9729 (match_operator:SI 7 "shiftable_operator"
9730 [(match_operand:SI 4 "s_register_operand" "r,r")
9731 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
129a2fe4 9732 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 9733 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9734 "TARGET_ARM"
9c08d1fa 9735 "*
9c08d1fa 9736 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 9737 the conditional operator is LT or GE and we are comparing against zero and
674a8f0b 9738 everything is in registers then we can do this in two instructions. */
9c08d1fa 9739 if (operands[3] == const0_rtx
9740 && GET_CODE (operands[7]) != AND
0438d37f 9741 && REG_P (operands[5])
9742 && REG_P (operands[1])
9c08d1fa 9743 && REGNO (operands[1]) == REGNO (operands[4])
9744 && REGNO (operands[4]) != REGNO (operands[0]))
9745 {
9746 if (GET_CODE (operands[6]) == LT)
40dbec34 9747 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 9748 else if (GET_CODE (operands[6]) == GE)
40dbec34 9749 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 9750 }
0438d37f 9751 if (CONST_INT_P (operands[3])
9c08d1fa 9752 && !const_ok_for_arm (INTVAL (operands[3])))
e2348bcb 9753 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
9c08d1fa 9754 else
e2348bcb 9755 output_asm_insn (\"cmp\\t%2, %3\", operands);
40dbec34 9756 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
9c08d1fa 9757 if (which_alternative != 0)
129a2fe4 9758 return \"mov%D6\\t%0, %1\";
9c08d1fa 9759 return \"\";
215b30b3 9760 "
8fa3ba89 9761 [(set_attr "conds" "clob")
1b7da4ac 9762 (set_attr "length" "8,12")
9763 (set_attr "type" "multiple")]
8fa3ba89 9764)
9c08d1fa 9765
8a18b90c 9766(define_insn "*if_arith_move"
129a2fe4 9767 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9768 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8a18b90c 9769 [(match_operand 6 "cc_register" "") (const_int 0)])
9770 (match_operator:SI 5 "shiftable_operator"
129a2fe4 9771 [(match_operand:SI 2 "s_register_operand" "r,r")
9772 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
9773 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
cffb2a26 9774 "TARGET_ARM"
8a18b90c 9775 "@
9776 %I5%d4\\t%0, %2, %3
129a2fe4 9777 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8fa3ba89 9778 [(set_attr "conds" "use")
9779 (set_attr "length" "4,8")
282b4c75 9780 (set_attr_alternative "type"
9781 [(if_then_else (match_operand 3 "const_int_operand" "")
9782 (const_string "alu_shift_imm" )
9783 (const_string "alu_shift_reg"))
9784 (const_string "multiple")])]
8fa3ba89 9785)
8a18b90c 9786
f7fbdd4a 9787(define_insn "*ifcompare_move_arith"
9c08d1fa 9788 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9789 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 9790 [(match_operand:SI 4 "s_register_operand" "r,r")
5565501b 9791 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 9792 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9c08d1fa 9793 (match_operator:SI 7 "shiftable_operator"
9794 [(match_operand:SI 2 "s_register_operand" "r,r")
9795 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 9796 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9797 "TARGET_ARM"
9c08d1fa 9798 "*
9c08d1fa 9799 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 9800 the conditional operator is LT or GE and we are comparing against zero and
9c08d1fa 9801 everything is in registers then we can do this in two instructions */
9802 if (operands[5] == const0_rtx
9803 && GET_CODE (operands[7]) != AND
0438d37f 9804 && REG_P (operands[3])
9805 && REG_P (operands[1])
9c08d1fa 9806 && REGNO (operands[1]) == REGNO (operands[2])
9807 && REGNO (operands[2]) != REGNO (operands[0]))
9808 {
9809 if (GET_CODE (operands[6]) == GE)
40dbec34 9810 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 9811 else if (GET_CODE (operands[6]) == LT)
40dbec34 9812 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 9813 }
40dbec34 9814
0438d37f 9815 if (CONST_INT_P (operands[5])
9c08d1fa 9816 && !const_ok_for_arm (INTVAL (operands[5])))
e2348bcb 9817 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
9c08d1fa 9818 else
e2348bcb 9819 output_asm_insn (\"cmp\\t%4, %5\", operands);
40dbec34 9820
9c08d1fa 9821 if (which_alternative != 0)
129a2fe4 9822 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
40dbec34 9823 return \"%I7%D6\\t%0, %2, %3\";
215b30b3 9824 "
8fa3ba89 9825 [(set_attr "conds" "clob")
1b7da4ac 9826 (set_attr "length" "8,12")
9827 (set_attr "type" "multiple")]
8fa3ba89 9828)
9c08d1fa 9829
8a18b90c 9830(define_insn "*if_move_arith"
129a2fe4 9831 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9832 (if_then_else:SI
8fa3ba89 9833 (match_operator 4 "arm_comparison_operator"
8a18b90c 9834 [(match_operand 6 "cc_register" "") (const_int 0)])
129a2fe4 9835 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 9836 (match_operator:SI 5 "shiftable_operator"
129a2fe4 9837 [(match_operand:SI 2 "s_register_operand" "r,r")
9838 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
cffb2a26 9839 "TARGET_ARM"
8a18b90c 9840 "@
9841 %I5%D4\\t%0, %2, %3
129a2fe4 9842 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
8fa3ba89 9843 [(set_attr "conds" "use")
9844 (set_attr "length" "4,8")
282b4c75 9845 (set_attr_alternative "type"
9846 [(if_then_else (match_operand 3 "const_int_operand" "")
9847 (const_string "alu_shift_imm" )
9848 (const_string "alu_shift_reg"))
9849 (const_string "multiple")])]
8fa3ba89 9850)
8a18b90c 9851
9852(define_insn "*ifcompare_move_not"
9c08d1fa 9853 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9854 (if_then_else:SI
8fa3ba89 9855 (match_operator 5 "arm_comparison_operator"
8a18b90c 9856 [(match_operand:SI 3 "s_register_operand" "r,r")
9857 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9858 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9859 (not:SI
9860 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 9861 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9862 "TARGET_ARM"
8a18b90c 9863 "#"
8fa3ba89 9864 [(set_attr "conds" "clob")
1b7da4ac 9865 (set_attr "length" "8,12")
9866 (set_attr "type" "multiple")]
8fa3ba89 9867)
9c08d1fa 9868
8a18b90c 9869(define_insn "*if_move_not"
9870 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9871 (if_then_else:SI
8fa3ba89 9872 (match_operator 4 "arm_comparison_operator"
8a18b90c 9873 [(match_operand 3 "cc_register" "") (const_int 0)])
9874 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9875 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
cffb2a26 9876 "TARGET_ARM"
8a18b90c 9877 "@
9878 mvn%D4\\t%0, %2
9879 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
9880 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
8fa3ba89 9881 [(set_attr "conds" "use")
1aed5204 9882 (set_attr "type" "mvn_reg")
1b7da4ac 9883 (set_attr "length" "4,8,8")
9884 (set_attr "type" "mvn_reg,multiple,multiple")]
8fa3ba89 9885)
8a18b90c 9886
9887(define_insn "*ifcompare_not_move"
9c08d1fa 9888 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9889 (if_then_else:SI
8fa3ba89 9890 (match_operator 5 "arm_comparison_operator"
8a18b90c 9891 [(match_operand:SI 3 "s_register_operand" "r,r")
9892 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9893 (not:SI
9894 (match_operand:SI 2 "s_register_operand" "r,r"))
9895 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 9896 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9897 "TARGET_ARM"
8a18b90c 9898 "#"
8fa3ba89 9899 [(set_attr "conds" "clob")
1b7da4ac 9900 (set_attr "length" "8,12")
9901 (set_attr "type" "multiple")]
8fa3ba89 9902)
9c08d1fa 9903
8a18b90c 9904(define_insn "*if_not_move"
9905 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9906 (if_then_else:SI
8fa3ba89 9907 (match_operator 4 "arm_comparison_operator"
8a18b90c 9908 [(match_operand 3 "cc_register" "") (const_int 0)])
9909 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9910 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 9911 "TARGET_ARM"
8a18b90c 9912 "@
9913 mvn%d4\\t%0, %2
9914 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
9915 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
8fa3ba89 9916 [(set_attr "conds" "use")
1b7da4ac 9917 (set_attr "type" "mvn_reg,multiple,multiple")
8fa3ba89 9918 (set_attr "length" "4,8,8")]
9919)
8a18b90c 9920
9921(define_insn "*ifcompare_shift_move"
9c08d1fa 9922 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9923 (if_then_else:SI
8fa3ba89 9924 (match_operator 6 "arm_comparison_operator"
8a18b90c 9925 [(match_operand:SI 4 "s_register_operand" "r,r")
9926 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9927 (match_operator:SI 7 "shift_operator"
9928 [(match_operand:SI 2 "s_register_operand" "r,r")
9929 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
9930 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 9931 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9932 "TARGET_ARM"
9c08d1fa 9933 "#"
8fa3ba89 9934 [(set_attr "conds" "clob")
1b7da4ac 9935 (set_attr "length" "8,12")
9936 (set_attr "type" "multiple")]
8fa3ba89 9937)
9c08d1fa 9938
8a18b90c 9939(define_insn "*if_shift_move"
9940 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9941 (if_then_else:SI
8fa3ba89 9942 (match_operator 5 "arm_comparison_operator"
8a18b90c 9943 [(match_operand 6 "cc_register" "") (const_int 0)])
9944 (match_operator:SI 4 "shift_operator"
9945 [(match_operand:SI 2 "s_register_operand" "r,r,r")
9946 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
9947 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 9948 "TARGET_ARM"
5565501b 9949 "@
8a18b90c 9950 mov%d5\\t%0, %2%S4
9951 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
9952 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
8fa3ba89 9953 [(set_attr "conds" "use")
331beb1a 9954 (set_attr "shift" "2")
a2cd141b 9955 (set_attr "length" "4,8,8")
282b4c75 9956 (set_attr_alternative "type"
9957 [(if_then_else (match_operand 3 "const_int_operand" "")
9958 (const_string "mov_shift" )
9959 (const_string "mov_shift_reg"))
9960 (const_string "multiple")
9961 (const_string "multiple")])]
8fa3ba89 9962)
5565501b 9963
8a18b90c 9964(define_insn "*ifcompare_move_shift"
9965 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 9966 (if_then_else:SI
8fa3ba89 9967 (match_operator 6 "arm_comparison_operator"
8a18b90c 9968 [(match_operand:SI 4 "s_register_operand" "r,r")
9969 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9970 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
5565501b 9971 (match_operator:SI 7 "shift_operator"
8a18b90c 9972 [(match_operand:SI 2 "s_register_operand" "r,r")
9973 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
bd5b4116 9974 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9975 "TARGET_ARM"
8a18b90c 9976 "#"
8fa3ba89 9977 [(set_attr "conds" "clob")
1b7da4ac 9978 (set_attr "length" "8,12")
9979 (set_attr "type" "multiple")]
8fa3ba89 9980)
5565501b 9981
8a18b90c 9982(define_insn "*if_move_shift"
9983 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 9984 (if_then_else:SI
8fa3ba89 9985 (match_operator 5 "arm_comparison_operator"
8a18b90c 9986 [(match_operand 6 "cc_register" "") (const_int 0)])
9987 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9988 (match_operator:SI 4 "shift_operator"
9989 [(match_operand:SI 2 "s_register_operand" "r,r,r")
9990 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
cffb2a26 9991 "TARGET_ARM"
5565501b 9992 "@
8a18b90c 9993 mov%D5\\t%0, %2%S4
9994 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
9995 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
8fa3ba89 9996 [(set_attr "conds" "use")
331beb1a 9997 (set_attr "shift" "2")
a2cd141b 9998 (set_attr "length" "4,8,8")
282b4c75 9999 (set_attr_alternative "type"
10000 [(if_then_else (match_operand 3 "const_int_operand" "")
10001 (const_string "mov_shift" )
10002 (const_string "mov_shift_reg"))
10003 (const_string "multiple")
10004 (const_string "multiple")])]
8fa3ba89 10005)
9c08d1fa 10006
f7fbdd4a 10007(define_insn "*ifcompare_shift_shift"
8a18b90c 10008 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 10009 (if_then_else:SI
8fa3ba89 10010 (match_operator 7 "arm_comparison_operator"
8a18b90c 10011 [(match_operand:SI 5 "s_register_operand" "r")
10012 (match_operand:SI 6 "arm_add_operand" "rIL")])
5565501b 10013 (match_operator:SI 8 "shift_operator"
8a18b90c 10014 [(match_operand:SI 1 "s_register_operand" "r")
10015 (match_operand:SI 2 "arm_rhs_operand" "rM")])
5565501b 10016 (match_operator:SI 9 "shift_operator"
8a18b90c 10017 [(match_operand:SI 3 "s_register_operand" "r")
10018 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
bd5b4116 10019 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10020 "TARGET_ARM"
8a18b90c 10021 "#"
8fa3ba89 10022 [(set_attr "conds" "clob")
1b7da4ac 10023 (set_attr "length" "12")
10024 (set_attr "type" "multiple")]
8fa3ba89 10025)
9c08d1fa 10026
8a18b90c 10027(define_insn "*if_shift_shift"
10028 [(set (match_operand:SI 0 "s_register_operand" "=r")
10029 (if_then_else:SI
8fa3ba89 10030 (match_operator 5 "arm_comparison_operator"
8a18b90c 10031 [(match_operand 8 "cc_register" "") (const_int 0)])
10032 (match_operator:SI 6 "shift_operator"
10033 [(match_operand:SI 1 "s_register_operand" "r")
10034 (match_operand:SI 2 "arm_rhs_operand" "rM")])
10035 (match_operator:SI 7 "shift_operator"
10036 [(match_operand:SI 3 "s_register_operand" "r")
10037 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
cffb2a26 10038 "TARGET_ARM"
8a18b90c 10039 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
8fa3ba89 10040 [(set_attr "conds" "use")
331beb1a 10041 (set_attr "shift" "1")
a2cd141b 10042 (set_attr "length" "8")
10043 (set (attr "type") (if_then_else
10044 (and (match_operand 2 "const_int_operand" "")
10045 (match_operand 4 "const_int_operand" ""))
1aed5204 10046 (const_string "mov_shift")
10047 (const_string "mov_shift_reg")))]
8fa3ba89 10048)
8a18b90c 10049
f7fbdd4a 10050(define_insn "*ifcompare_not_arith"
8a18b90c 10051 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 10052 (if_then_else:SI
8fa3ba89 10053 (match_operator 6 "arm_comparison_operator"
8a18b90c 10054 [(match_operand:SI 4 "s_register_operand" "r")
10055 (match_operand:SI 5 "arm_add_operand" "rIL")])
10056 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5565501b 10057 (match_operator:SI 7 "shiftable_operator"
8a18b90c 10058 [(match_operand:SI 2 "s_register_operand" "r")
10059 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
bd5b4116 10060 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10061 "TARGET_ARM"
8a18b90c 10062 "#"
8fa3ba89 10063 [(set_attr "conds" "clob")
1b7da4ac 10064 (set_attr "length" "12")
10065 (set_attr "type" "multiple")]
8fa3ba89 10066)
9c08d1fa 10067
8a18b90c 10068(define_insn "*if_not_arith"
10069 [(set (match_operand:SI 0 "s_register_operand" "=r")
10070 (if_then_else:SI
8fa3ba89 10071 (match_operator 5 "arm_comparison_operator"
8a18b90c 10072 [(match_operand 4 "cc_register" "") (const_int 0)])
10073 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
10074 (match_operator:SI 6 "shiftable_operator"
10075 [(match_operand:SI 2 "s_register_operand" "r")
10076 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
cffb2a26 10077 "TARGET_ARM"
8a18b90c 10078 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
8fa3ba89 10079 [(set_attr "conds" "use")
1aed5204 10080 (set_attr "type" "mvn_reg")
8fa3ba89 10081 (set_attr "length" "8")]
10082)
8a18b90c 10083
10084(define_insn "*ifcompare_arith_not"
10085 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 10086 (if_then_else:SI
8fa3ba89 10087 (match_operator 6 "arm_comparison_operator"
8a18b90c 10088 [(match_operand:SI 4 "s_register_operand" "r")
10089 (match_operand:SI 5 "arm_add_operand" "rIL")])
5565501b 10090 (match_operator:SI 7 "shiftable_operator"
8a18b90c 10091 [(match_operand:SI 2 "s_register_operand" "r")
10092 (match_operand:SI 3 "arm_rhs_operand" "rI")])
10093 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
bd5b4116 10094 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10095 "TARGET_ARM"
8a18b90c 10096 "#"
8fa3ba89 10097 [(set_attr "conds" "clob")
1b7da4ac 10098 (set_attr "length" "12")
10099 (set_attr "type" "multiple")]
8fa3ba89 10100)
9c08d1fa 10101
8a18b90c 10102(define_insn "*if_arith_not"
10103 [(set (match_operand:SI 0 "s_register_operand" "=r")
10104 (if_then_else:SI
8fa3ba89 10105 (match_operator 5 "arm_comparison_operator"
8a18b90c 10106 [(match_operand 4 "cc_register" "") (const_int 0)])
10107 (match_operator:SI 6 "shiftable_operator"
10108 [(match_operand:SI 2 "s_register_operand" "r")
10109 (match_operand:SI 3 "arm_rhs_operand" "rI")])
10110 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
cffb2a26 10111 "TARGET_ARM"
8a18b90c 10112 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
8fa3ba89 10113 [(set_attr "conds" "use")
1b7da4ac 10114 (set_attr "type" "multiple")
8fa3ba89 10115 (set_attr "length" "8")]
10116)
8a18b90c 10117
f7fbdd4a 10118(define_insn "*ifcompare_neg_move"
8a18b90c 10119 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 10120 (if_then_else:SI
8fa3ba89 10121 (match_operator 5 "arm_comparison_operator"
8a18b90c 10122 [(match_operand:SI 3 "s_register_operand" "r,r")
10123 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10124 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
10125 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 10126 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10127 "TARGET_ARM"
8a18b90c 10128 "#"
8fa3ba89 10129 [(set_attr "conds" "clob")
1b7da4ac 10130 (set_attr "length" "8,12")
10131 (set_attr "type" "multiple")]
8fa3ba89 10132)
8a18b90c 10133
530bb693 10134(define_insn_and_split "*if_neg_move"
10135 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
8a18b90c 10136 (if_then_else:SI
8fa3ba89 10137 (match_operator 4 "arm_comparison_operator"
8a18b90c 10138 [(match_operand 3 "cc_register" "") (const_int 0)])
530bb693 10139 (neg:SI (match_operand:SI 2 "s_register_operand" "l,r"))
10140 (match_operand:SI 1 "s_register_operand" "0,0")))]
10141 "TARGET_32BIT"
10142 "#"
10143 "&& reload_completed"
10144 [(cond_exec (match_op_dup 4 [(match_dup 3) (const_int 0)])
10145 (set (match_dup 0) (neg:SI (match_dup 2))))]
10146 ""
8fa3ba89 10147 [(set_attr "conds" "use")
530bb693 10148 (set_attr "length" "4")
10149 (set_attr "arch" "t2,32")
8bdfd6ed 10150 (set_attr "enabled_for_short_it" "yes,no")
530bb693 10151 (set_attr "type" "logic_shift_imm")]
8fa3ba89 10152)
9c08d1fa 10153
f7fbdd4a 10154(define_insn "*ifcompare_move_neg"
8a18b90c 10155 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 10156 (if_then_else:SI
8fa3ba89 10157 (match_operator 5 "arm_comparison_operator"
8a18b90c 10158 [(match_operand:SI 3 "s_register_operand" "r,r")
10159 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10160 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
10161 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 10162 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10163 "TARGET_ARM"
8a18b90c 10164 "#"
8fa3ba89 10165 [(set_attr "conds" "clob")
1b7da4ac 10166 (set_attr "length" "8,12")
10167 (set_attr "type" "multiple")]
8fa3ba89 10168)
8a18b90c 10169
530bb693 10170(define_insn_and_split "*if_move_neg"
10171 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
8a18b90c 10172 (if_then_else:SI
8fa3ba89 10173 (match_operator 4 "arm_comparison_operator"
8a18b90c 10174 [(match_operand 3 "cc_register" "") (const_int 0)])
530bb693 10175 (match_operand:SI 1 "s_register_operand" "0,0")
10176 (neg:SI (match_operand:SI 2 "s_register_operand" "l,r"))))]
10177 "TARGET_32BIT"
10178 "#"
10179 "&& reload_completed"
10180 [(cond_exec (match_dup 5)
10181 (set (match_dup 0) (neg:SI (match_dup 2))))]
10182 {
10183 machine_mode mode = GET_MODE (operands[3]);
10184 rtx_code rc = GET_CODE (operands[4]);
10185
10186 if (mode == CCFPmode || mode == CCFPEmode)
10187 rc = reverse_condition_maybe_unordered (rc);
10188 else
10189 rc = reverse_condition (rc);
10190
10191 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[3], const0_rtx);
10192 }
0d66636f 10193 [(set_attr "conds" "use")
530bb693 10194 (set_attr "length" "4")
10195 (set_attr "arch" "t2,32")
8bdfd6ed 10196 (set_attr "enabled_for_short_it" "yes,no")
530bb693 10197 (set_attr "type" "logic_shift_imm")]
0d66636f 10198)
9c08d1fa 10199
f7fbdd4a 10200(define_insn "*arith_adjacentmem"
9c08d1fa 10201 [(set (match_operand:SI 0 "s_register_operand" "=r")
10202 (match_operator:SI 1 "shiftable_operator"
10203 [(match_operand:SI 2 "memory_operand" "m")
10204 (match_operand:SI 3 "memory_operand" "m")]))
10205 (clobber (match_scratch:SI 4 "=r"))]
cffb2a26 10206 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9c08d1fa 10207 "*
215b30b3 10208 {
10209 rtx ldm[3];
10210 rtx arith[4];
94dee231 10211 rtx base_reg;
10212 HOST_WIDE_INT val1 = 0, val2 = 0;
9c08d1fa 10213
215b30b3 10214 if (REGNO (operands[0]) > REGNO (operands[4]))
10215 {
10216 ldm[1] = operands[4];
10217 ldm[2] = operands[0];
10218 }
10219 else
10220 {
10221 ldm[1] = operands[0];
10222 ldm[2] = operands[4];
10223 }
94dee231 10224
10225 base_reg = XEXP (operands[2], 0);
10226
10227 if (!REG_P (base_reg))
10228 {
10229 val1 = INTVAL (XEXP (base_reg, 1));
10230 base_reg = XEXP (base_reg, 0);
10231 }
10232
10233 if (!REG_P (XEXP (operands[3], 0)))
215b30b3 10234 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
94dee231 10235
215b30b3 10236 arith[0] = operands[0];
10237 arith[3] = operands[1];
94dee231 10238
215b30b3 10239 if (val1 < val2)
10240 {
10241 arith[1] = ldm[1];
10242 arith[2] = ldm[2];
10243 }
10244 else
10245 {
10246 arith[1] = ldm[2];
10247 arith[2] = ldm[1];
10248 }
94dee231 10249
10250 ldm[0] = base_reg;
10251 if (val1 !=0 && val2 != 0)
215b30b3 10252 {
cdb1295a 10253 rtx ops[3];
10254
94dee231 10255 if (val1 == 4 || val2 == 4)
10256 /* Other val must be 8, since we know they are adjacent and neither
10257 is zero. */
3ef90e77 10258 output_asm_insn (\"ldmib%?\\t%0, {%1, %2}\", ldm);
cdb1295a 10259 else if (const_ok_for_arm (val1) || const_ok_for_arm (-val1))
94dee231 10260 {
94dee231 10261 ldm[0] = ops[0] = operands[4];
10262 ops[1] = base_reg;
10263 ops[2] = GEN_INT (val1);
10264 output_add_immediate (ops);
10265 if (val1 < val2)
3ef90e77 10266 output_asm_insn (\"ldmia%?\\t%0, {%1, %2}\", ldm);
94dee231 10267 else
3ef90e77 10268 output_asm_insn (\"ldmda%?\\t%0, {%1, %2}\", ldm);
94dee231 10269 }
cdb1295a 10270 else
10271 {
10272 /* Offset is out of range for a single add, so use two ldr. */
10273 ops[0] = ldm[1];
10274 ops[1] = base_reg;
10275 ops[2] = GEN_INT (val1);
10276 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10277 ops[0] = ldm[2];
10278 ops[2] = GEN_INT (val2);
10279 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10280 }
215b30b3 10281 }
94dee231 10282 else if (val1 != 0)
215b30b3 10283 {
215b30b3 10284 if (val1 < val2)
3ef90e77 10285 output_asm_insn (\"ldmda%?\\t%0, {%1, %2}\", ldm);
215b30b3 10286 else
3ef90e77 10287 output_asm_insn (\"ldmia%?\\t%0, {%1, %2}\", ldm);
215b30b3 10288 }
10289 else
10290 {
215b30b3 10291 if (val1 < val2)
3ef90e77 10292 output_asm_insn (\"ldmia%?\\t%0, {%1, %2}\", ldm);
215b30b3 10293 else
3ef90e77 10294 output_asm_insn (\"ldmda%?\\t%0, {%1, %2}\", ldm);
215b30b3 10295 }
10296 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
10297 return \"\";
10298 }"
10299 [(set_attr "length" "12")
10300 (set_attr "predicable" "yes")
9f2c2a36 10301 (set_attr "type" "load_4")]
215b30b3 10302)
9c08d1fa 10303
9c08d1fa 10304; This pattern is never tried by combine, so do it as a peephole
10305
a0f94409 10306(define_peephole2
372575c7 10307 [(set (match_operand:SI 0 "arm_general_register_operand" "")
10308 (match_operand:SI 1 "arm_general_register_operand" ""))
bd5b4116 10309 (set (reg:CC CC_REGNUM)
aea4c774 10310 (compare:CC (match_dup 1) (const_int 0)))]
372575c7 10311 "TARGET_ARM"
a0f94409 10312 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
10313 (set (match_dup 0) (match_dup 1))])]
10314 ""
0d66636f 10315)
9c08d1fa 10316
9c08d1fa 10317(define_split
10318 [(set (match_operand:SI 0 "s_register_operand" "")
10319 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
10320 (const_int 0))
8fa3ba89 10321 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9c08d1fa 10322 [(match_operand:SI 3 "s_register_operand" "")
10323 (match_operand:SI 4 "arm_rhs_operand" "")]))))
10324 (clobber (match_operand:SI 5 "s_register_operand" ""))]
cffb2a26 10325 "TARGET_ARM"
9c08d1fa 10326 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
10327 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
10328 (match_dup 5)))]
215b30b3 10329 ""
10330)
9c08d1fa 10331
aea4c774 10332;; This split can be used because CC_Z mode implies that the following
10333;; branch will be an equality, or an unsigned inequality, so the sign
10334;; extension is not needed.
9c08d1fa 10335
aea4c774 10336(define_split
bd5b4116 10337 [(set (reg:CC_Z CC_REGNUM)
aea4c774 10338 (compare:CC_Z
10339 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9c08d1fa 10340 (const_int 24))
aea4c774 10341 (match_operand 1 "const_int_operand" "")))
10342 (clobber (match_scratch:SI 2 ""))]
cffb2a26 10343 "TARGET_ARM
8c4e8755 10344 && ((UINTVAL (operands[1]))
10345 == ((UINTVAL (operands[1])) >> 24) << 24)"
aea4c774 10346 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
bd5b4116 10347 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
aea4c774 10348 "
9c08d1fa 10349 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
215b30b3 10350 "
10351)
25f905c2 10352;; ??? Check the patterns above for Thumb-2 usefulness
9c08d1fa 10353
87b22bf7 10354(define_expand "prologue"
10355 [(clobber (const_int 0))]
cffb2a26 10356 "TARGET_EITHER"
25f905c2 10357 "if (TARGET_32BIT)
cffb2a26 10358 arm_expand_prologue ();
10359 else
25f905c2 10360 thumb1_expand_prologue ();
87b22bf7 10361 DONE;
cffb2a26 10362 "
10363)
87b22bf7 10364
56d27660 10365(define_expand "epilogue"
4c44712e 10366 [(clobber (const_int 0))]
cffb2a26 10367 "TARGET_EITHER"
56d27660 10368 "
18d50ae6 10369 if (crtl->calls_eh_return)
fb94f18b 10370 emit_insn (gen_force_register_use (gen_rtx_REG (Pmode, 2)));
25f905c2 10371 if (TARGET_THUMB1)
c3635784 10372 {
10373 thumb1_expand_epilogue ();
10374 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
10375 gen_rtvec (1, ret_rtx), VUNSPEC_EPILOGUE));
10376 }
10377 else if (HAVE_return)
10378 {
10379 /* HAVE_return is testing for USE_RETURN_INSN (FALSE). Hence,
10380 no need for explicit testing again. */
10381 emit_jump_insn (gen_return ());
10382 }
10383 else if (TARGET_32BIT)
10384 {
10385 arm_expand_epilogue (true);
10386 }
cffb2a26 10387 DONE;
10388 "
10389)
56d27660 10390
ef5651d0 10391;; Note - although unspec_volatile's USE all hard registers,
10392;; USEs are ignored after relaod has completed. Thus we need
10393;; to add an unspec of the link register to ensure that flow
10394;; does not think that it is unused by the sibcall branch that
10395;; will replace the standard function epilogue.
c3635784 10396(define_expand "sibcall_epilogue"
fb94f18b 10397 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_REGISTER_USE)
c3635784 10398 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
10399 "TARGET_32BIT"
10400 "
10401 arm_expand_epilogue (false);
10402 DONE;
10403 "
1c494086 10404)
10405
cffb2a26 10406(define_expand "eh_epilogue"
3934ae0e 10407 [(use (match_operand:SI 0 "register_operand"))
10408 (use (match_operand:SI 1 "register_operand"))
10409 (use (match_operand:SI 2 "register_operand"))]
cffb2a26 10410 "TARGET_EITHER"
10411 "
215b30b3 10412 {
10413 cfun->machine->eh_epilogue_sp_ofs = operands[1];
0438d37f 10414 if (!REG_P (operands[2]) || REGNO (operands[2]) != 2)
215b30b3 10415 {
10416 rtx ra = gen_rtx_REG (Pmode, 2);
10417
10418 emit_move_insn (ra, operands[2]);
10419 operands[2] = ra;
10420 }
5cf3595a 10421 /* This is a hack -- we may have crystalized the function type too
10422 early. */
10423 cfun->machine->func_type = 0;
215b30b3 10424 }"
10425)
56d27660 10426
9c08d1fa 10427;; This split is only used during output to reduce the number of patterns
10428;; that need assembler instructions adding to them. We allowed the setting
10429;; of the conditions to be implicit during rtl generation so that
10430;; the conditional compare patterns would work. However this conflicts to
8a18b90c 10431;; some extent with the conditional data operations, so we have to split them
9c08d1fa 10432;; up again here.
10433
25f905c2 10434;; ??? Need to audit these splitters for Thumb-2. Why isn't normal
10435;; conditional execution sufficient?
10436
9c08d1fa 10437(define_split
10438 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 10439 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10440 [(match_operand 2 "" "") (match_operand 3 "" "")])
10441 (match_dup 0)
10442 (match_operand 4 "" "")))
bd5b4116 10443 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10444 "TARGET_ARM && reload_completed"
8fa3ba89 10445 [(set (match_dup 5) (match_dup 6))
10446 (cond_exec (match_dup 7)
10447 (set (match_dup 0) (match_dup 4)))]
10448 "
10449 {
3754d046 10450 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8fa3ba89 10451 operands[2], operands[3]);
10452 enum rtx_code rc = GET_CODE (operands[1]);
10453
bd5b4116 10454 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10455 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10456 if (mode == CCFPmode || mode == CCFPEmode)
10457 rc = reverse_condition_maybe_unordered (rc);
10458 else
10459 rc = reverse_condition (rc);
10460
10461 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
10462 }"
10463)
10464
10465(define_split
10466 [(set (match_operand:SI 0 "s_register_operand" "")
10467 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10468 [(match_operand 2 "" "") (match_operand 3 "" "")])
10469 (match_operand 4 "" "")
10470 (match_dup 0)))
bd5b4116 10471 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10472 "TARGET_ARM && reload_completed"
8fa3ba89 10473 [(set (match_dup 5) (match_dup 6))
10474 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
10475 (set (match_dup 0) (match_dup 4)))]
10476 "
10477 {
3754d046 10478 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8fa3ba89 10479 operands[2], operands[3]);
10480
bd5b4116 10481 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10482 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10483 }"
10484)
10485
10486(define_split
10487 [(set (match_operand:SI 0 "s_register_operand" "")
10488 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9c08d1fa 10489 [(match_operand 2 "" "") (match_operand 3 "" "")])
10490 (match_operand 4 "" "")
10491 (match_operand 5 "" "")))
bd5b4116 10492 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10493 "TARGET_ARM && reload_completed"
8fa3ba89 10494 [(set (match_dup 6) (match_dup 7))
10495 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10496 (set (match_dup 0) (match_dup 4)))
10497 (cond_exec (match_dup 8)
10498 (set (match_dup 0) (match_dup 5)))]
10499 "
10500 {
3754d046 10501 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8fa3ba89 10502 operands[2], operands[3]);
10503 enum rtx_code rc = GET_CODE (operands[1]);
10504
bd5b4116 10505 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10506 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10507 if (mode == CCFPmode || mode == CCFPEmode)
10508 rc = reverse_condition_maybe_unordered (rc);
10509 else
10510 rc = reverse_condition (rc);
10511
10512 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10513 }"
10514)
10515
cffb2a26 10516(define_split
10517 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 10518 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
cffb2a26 10519 [(match_operand:SI 2 "s_register_operand" "")
10520 (match_operand:SI 3 "arm_add_operand" "")])
10521 (match_operand:SI 4 "arm_rhs_operand" "")
10522 (not:SI
10523 (match_operand:SI 5 "s_register_operand" ""))))
bd5b4116 10524 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10525 "TARGET_ARM && reload_completed"
cffb2a26 10526 [(set (match_dup 6) (match_dup 7))
f6c53574 10527 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10528 (set (match_dup 0) (match_dup 4)))
10529 (cond_exec (match_dup 8)
10530 (set (match_dup 0) (not:SI (match_dup 5))))]
cffb2a26 10531 "
215b30b3 10532 {
3754d046 10533 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
215b30b3 10534 operands[2], operands[3]);
f6c53574 10535 enum rtx_code rc = GET_CODE (operands[1]);
cffb2a26 10536
bd5b4116 10537 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
1a83b3ff 10538 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
f6c53574 10539 if (mode == CCFPmode || mode == CCFPEmode)
10540 rc = reverse_condition_maybe_unordered (rc);
10541 else
10542 rc = reverse_condition (rc);
10543
10544 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
215b30b3 10545 }"
10546)
cffb2a26 10547
10548(define_insn "*cond_move_not"
10549 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10550 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
cffb2a26 10551 [(match_operand 3 "cc_register" "") (const_int 0)])
10552 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10553 (not:SI
10554 (match_operand:SI 2 "s_register_operand" "r,r"))))]
10555 "TARGET_ARM"
10556 "@
10557 mvn%D4\\t%0, %2
10558 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
0d66636f 10559 [(set_attr "conds" "use")
1b7da4ac 10560 (set_attr "type" "mvn_reg,multiple")
0d66636f 10561 (set_attr "length" "4,8")]
10562)
cffb2a26 10563
9c08d1fa 10564;; The next two patterns occur when an AND operation is followed by a
10565;; scc insn sequence
10566
f7fbdd4a 10567(define_insn "*sign_extract_onebit"
9c08d1fa 10568 [(set (match_operand:SI 0 "s_register_operand" "=r")
10569 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10570 (const_int 1)
ed750274 10571 (match_operand:SI 2 "const_int_operand" "n")))
10572 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10573 "TARGET_ARM"
9c08d1fa 10574 "*
0d66636f 10575 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10576 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
10577 return \"mvnne\\t%0, #0\";
10578 "
10579 [(set_attr "conds" "clob")
1b7da4ac 10580 (set_attr "length" "8")
10581 (set_attr "type" "multiple")]
0d66636f 10582)
9c08d1fa 10583
f7fbdd4a 10584(define_insn "*not_signextract_onebit"
9c08d1fa 10585 [(set (match_operand:SI 0 "s_register_operand" "=r")
10586 (not:SI
10587 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10588 (const_int 1)
ed750274 10589 (match_operand:SI 2 "const_int_operand" "n"))))
10590 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10591 "TARGET_ARM"
9c08d1fa 10592 "*
0d66636f 10593 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10594 output_asm_insn (\"tst\\t%1, %2\", operands);
10595 output_asm_insn (\"mvneq\\t%0, #0\", operands);
10596 return \"movne\\t%0, #0\";
10597 "
10598 [(set_attr "conds" "clob")
1b7da4ac 10599 (set_attr "length" "12")
10600 (set_attr "type" "multiple")]
0d66636f 10601)
25f905c2 10602;; ??? The above patterns need auditing for Thumb-2
87b22bf7 10603
0d66636f 10604;; Push multiple registers to the stack. Registers are in parallel (use ...)
10605;; expressions. For simplicity, the first register is also in the unspec
10606;; part.
08508cbf 10607;; To avoid the usage of GNU extension, the length attribute is computed
10608;; in a C function arm_attr_length_push_multi.
f7fbdd4a 10609(define_insn "*push_multi"
87b22bf7 10610 [(match_parallel 2 "multi_register_push"
7571d3f7 10611 [(set (match_operand:BLK 0 "push_mult_memory_operand" "")
3cc80a30 10612 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "")]
e1159bbe 10613 UNSPEC_PUSH_MULT))])]
7571d3f7 10614 ""
87b22bf7 10615 "*
215b30b3 10616 {
10617 int num_saves = XVECLEN (operands[2], 0);
ed593f11 10618
215b30b3 10619 /* For the StrongARM at least it is faster to
25f905c2 10620 use STR to store only a single register.
542d5028 10621 In Thumb mode always use push, and the assembler will pick
10622 something appropriate. */
25f905c2 10623 if (num_saves == 1 && TARGET_ARM)
61309563 10624 output_asm_insn (\"str%?\\t%1, [%m0, #-4]!\", operands);
215b30b3 10625 else
10626 {
10627 int i;
10628 char pattern[100];
ed593f11 10629
3ef90e77 10630 if (TARGET_32BIT)
61309563 10631 strcpy (pattern, \"push%?\\t{%1\");
25f905c2 10632 else
10633 strcpy (pattern, \"push\\t{%1\");
215b30b3 10634
6079f055 10635 for (i = 1; i < num_saves; i++)
215b30b3 10636 {
10637 strcat (pattern, \", %|\");
10638 strcat (pattern,
10639 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
10640 }
10641
10642 strcat (pattern, \"}\");
10643 output_asm_insn (pattern, operands);
10644 }
10645
10646 return \"\";
10647 }"
9f2c2a36 10648 [(set_attr "type" "store_16")
a6864a24 10649 (set (attr "length")
08508cbf 10650 (symbol_ref "arm_attr_length_push_multi (operands[2], operands[1])"))]
215b30b3 10651)
f7fbdd4a 10652
4c58c898 10653(define_insn "stack_tie"
10654 [(set (mem:BLK (scratch))
aaa37ad6 10655 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "rk")
10656 (match_operand:SI 1 "s_register_operand" "rk")]
4c58c898 10657 UNSPEC_PRLG_STK))]
10658 ""
10659 ""
1b7da4ac 10660 [(set_attr "length" "0")
10661 (set_attr "type" "block")]
4c58c898 10662)
10663
426be8c5 10664;; Pop (as used in epilogue RTL)
10665;;
10666(define_insn "*load_multiple_with_writeback"
10667 [(match_parallel 0 "load_multiple_operation"
10668 [(set (match_operand:SI 1 "s_register_operand" "+rk")
10669 (plus:SI (match_dup 1)
809003b3 10670 (match_operand:SI 2 "const_int_I_operand" "I")))
426be8c5 10671 (set (match_operand:SI 3 "s_register_operand" "=rk")
10672 (mem:SI (match_dup 1)))
10673 ])]
10674 "TARGET_32BIT && (reload_in_progress || reload_completed)"
10675 "*
10676 {
10677 arm_output_multireg_pop (operands, /*return_pc=*/false,
10678 /*cond=*/const_true_rtx,
10679 /*reverse=*/false,
10680 /*update=*/true);
10681 return \"\";
10682 }
10683 "
9f2c2a36 10684 [(set_attr "type" "load_16")
5431c9c9 10685 (set_attr "predicable" "yes")
10686 (set (attr "length")
10687 (symbol_ref "arm_attr_length_pop_multi (operands,
10688 /*return_pc=*/false,
10689 /*write_back_p=*/true)"))]
426be8c5 10690)
10691
10692;; Pop with return (as used in epilogue RTL)
10693;;
10694;; This instruction is generated when the registers are popped at the end of
10695;; epilogue. Here, instead of popping the value into LR and then generating
10696;; jump to LR, value is popped into PC directly. Hence, the pattern is combined
10697;; with (return).
10698(define_insn "*pop_multiple_with_writeback_and_return"
10699 [(match_parallel 0 "pop_multiple_return"
10700 [(return)
10701 (set (match_operand:SI 1 "s_register_operand" "+rk")
10702 (plus:SI (match_dup 1)
809003b3 10703 (match_operand:SI 2 "const_int_I_operand" "I")))
426be8c5 10704 (set (match_operand:SI 3 "s_register_operand" "=rk")
10705 (mem:SI (match_dup 1)))
10706 ])]
10707 "TARGET_32BIT && (reload_in_progress || reload_completed)"
10708 "*
10709 {
10710 arm_output_multireg_pop (operands, /*return_pc=*/true,
10711 /*cond=*/const_true_rtx,
10712 /*reverse=*/false,
10713 /*update=*/true);
10714 return \"\";
10715 }
10716 "
9f2c2a36 10717 [(set_attr "type" "load_16")
5431c9c9 10718 (set_attr "predicable" "yes")
10719 (set (attr "length")
10720 (symbol_ref "arm_attr_length_pop_multi (operands, /*return_pc=*/true,
10721 /*write_back_p=*/true)"))]
426be8c5 10722)
10723
10724(define_insn "*pop_multiple_with_return"
10725 [(match_parallel 0 "pop_multiple_return"
10726 [(return)
10727 (set (match_operand:SI 2 "s_register_operand" "=rk")
10728 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
10729 ])]
10730 "TARGET_32BIT && (reload_in_progress || reload_completed)"
10731 "*
10732 {
10733 arm_output_multireg_pop (operands, /*return_pc=*/true,
10734 /*cond=*/const_true_rtx,
10735 /*reverse=*/false,
10736 /*update=*/false);
10737 return \"\";
10738 }
10739 "
9f2c2a36 10740 [(set_attr "type" "load_16")
5431c9c9 10741 (set_attr "predicable" "yes")
10742 (set (attr "length")
10743 (symbol_ref "arm_attr_length_pop_multi (operands, /*return_pc=*/true,
10744 /*write_back_p=*/false)"))]
426be8c5 10745)
10746
10747;; Load into PC and return
10748(define_insn "*ldr_with_return"
10749 [(return)
10750 (set (reg:SI PC_REGNUM)
10751 (mem:SI (post_inc:SI (match_operand:SI 0 "s_register_operand" "+rk"))))]
10752 "TARGET_32BIT && (reload_in_progress || reload_completed)"
10753 "ldr%?\t%|pc, [%0], #4"
9f2c2a36 10754 [(set_attr "type" "load_4")
426be8c5 10755 (set_attr "predicable" "yes")]
10756)
1a0b0f12 10757;; Pop for floating point registers (as used in epilogue RTL)
10758(define_insn "*vfp_pop_multiple_with_writeback"
10759 [(match_parallel 0 "pop_multiple_fp"
10760 [(set (match_operand:SI 1 "s_register_operand" "+rk")
10761 (plus:SI (match_dup 1)
809003b3 10762 (match_operand:SI 2 "const_int_I_operand" "I")))
2f2163a4 10763 (set (match_operand:DF 3 "vfp_hard_register_operand" "")
1a0b0f12 10764 (mem:DF (match_dup 1)))])]
d7216193 10765 "TARGET_32BIT && TARGET_HARD_FLOAT"
1a0b0f12 10766 "*
10767 {
10768 int num_regs = XVECLEN (operands[0], 0);
10769 char pattern[100];
10770 rtx op_list[2];
b34d8dac 10771 strcpy (pattern, \"vldm\\t\");
1a0b0f12 10772 strcat (pattern, reg_names[REGNO (SET_DEST (XVECEXP (operands[0], 0, 0)))]);
10773 strcat (pattern, \"!, {\");
10774 op_list[0] = XEXP (XVECEXP (operands[0], 0, 1), 0);
10775 strcat (pattern, \"%P0\");
10776 if ((num_regs - 1) > 1)
10777 {
10778 strcat (pattern, \"-%P1\");
10779 op_list [1] = XEXP (XVECEXP (operands[0], 0, num_regs - 1), 0);
10780 }
10781
10782 strcat (pattern, \"}\");
10783 output_asm_insn (pattern, op_list);
10784 return \"\";
10785 }
10786 "
9f2c2a36 10787 [(set_attr "type" "load_16")
1a0b0f12 10788 (set_attr "conds" "unconditional")
10789 (set_attr "predicable" "no")]
10790)
10791
f7fbdd4a 10792;; Special patterns for dealing with the constant pool
10793
cffb2a26 10794(define_insn "align_4"
e1159bbe 10795 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
cffb2a26 10796 "TARGET_EITHER"
f7fbdd4a 10797 "*
cffb2a26 10798 assemble_align (32);
f7fbdd4a 10799 return \"\";
cffb2a26 10800 "
1b7da4ac 10801 [(set_attr "type" "no_insn")]
cffb2a26 10802)
f7fbdd4a 10803
755eb2b4 10804(define_insn "align_8"
10805 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
f9273c43 10806 "TARGET_EITHER"
755eb2b4 10807 "*
10808 assemble_align (64);
10809 return \"\";
10810 "
1b7da4ac 10811 [(set_attr "type" "no_insn")]
755eb2b4 10812)
10813
cffb2a26 10814(define_insn "consttable_end"
e1159bbe 10815 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
cffb2a26 10816 "TARGET_EITHER"
f7fbdd4a 10817 "*
cffb2a26 10818 making_const_table = FALSE;
f7fbdd4a 10819 return \"\";
cffb2a26 10820 "
1b7da4ac 10821 [(set_attr "type" "no_insn")]
cffb2a26 10822)
f7fbdd4a 10823
0e207eb8 10824(define_insn "consttable_1"
10825 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
10826 "TARGET_EITHER"
10827 "*
10828 making_const_table = TRUE;
10829 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
10830 assemble_zeros (3);
10831 return \"\";
10832 "
10833 [(set_attr "length" "4")
10834 (set_attr "type" "no_insn")]
10835)
10836
10837(define_insn "consttable_2"
10838 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
10839 "TARGET_EITHER"
10840 "*
10841 {
10842 rtx x = operands[0];
10843 making_const_table = TRUE;
10844 switch (GET_MODE_CLASS (GET_MODE (x)))
10845 {
10846 case MODE_FLOAT:
10847 arm_emit_fp16_const (x);
10848 break;
10849 default:
10850 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
10851 assemble_zeros (2);
10852 break;
10853 }
10854 return \"\";
10855 }"
10856 [(set_attr "length" "4")
10857 (set_attr "type" "no_insn")]
10858)
10859
cffb2a26 10860(define_insn "consttable_4"
e1159bbe 10861 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
cffb2a26 10862 "TARGET_EITHER"
10863 "*
10864 {
9b8516be 10865 rtx x = operands[0];
cffb2a26 10866 making_const_table = TRUE;
0f97e0f5 10867 scalar_float_mode float_mode;
10868 if (is_a <scalar_float_mode> (GET_MODE (x), &float_mode))
10869 assemble_real (*CONST_DOUBLE_REAL_VALUE (x), float_mode, BITS_PER_WORD);
10870 else
cffb2a26 10871 {
7b04c5d5 10872 /* XXX: Sometimes gcc does something really dumb and ends up with
10873 a HIGH in a constant pool entry, usually because it's trying to
10874 load into a VFP register. We know this will always be used in
10875 combination with a LO_SUM which ignores the high bits, so just
10876 strip off the HIGH. */
10877 if (GET_CODE (x) == HIGH)
10878 x = XEXP (x, 0);
9b8516be 10879 assemble_integer (x, 4, BITS_PER_WORD, 1);
10880 mark_symbol_refs_as_used (x);
cffb2a26 10881 }
10882 return \"\";
10883 }"
1b7da4ac 10884 [(set_attr "length" "4")
10885 (set_attr "type" "no_insn")]
cffb2a26 10886)
10887
10888(define_insn "consttable_8"
e1159bbe 10889 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
cffb2a26 10890 "TARGET_EITHER"
10891 "*
10892 {
10893 making_const_table = TRUE;
0f97e0f5 10894 scalar_float_mode float_mode;
10895 if (is_a <scalar_float_mode> (GET_MODE (operands[0]), &float_mode))
10896 assemble_real (*CONST_DOUBLE_REAL_VALUE (operands[0]),
10897 float_mode, BITS_PER_WORD);
10898 else
10899 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
cffb2a26 10900 return \"\";
10901 }"
1b7da4ac 10902 [(set_attr "length" "8")
10903 (set_attr "type" "no_insn")]
cffb2a26 10904)
10905
d98a3884 10906(define_insn "consttable_16"
10907 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_16)]
10908 "TARGET_EITHER"
10909 "*
10910 {
10911 making_const_table = TRUE;
0f97e0f5 10912 scalar_float_mode float_mode;
10913 if (is_a <scalar_float_mode> (GET_MODE (operands[0]), &float_mode))
10914 assemble_real (*CONST_DOUBLE_REAL_VALUE (operands[0]),
10915 float_mode, BITS_PER_WORD);
10916 else
10917 assemble_integer (operands[0], 16, BITS_PER_WORD, 1);
d98a3884 10918 return \"\";
10919 }"
1b7da4ac 10920 [(set_attr "length" "16")
10921 (set_attr "type" "no_insn")]
d98a3884 10922)
10923
331beb1a 10924;; V5 Instructions,
10925
8f4be2be 10926(define_insn "clzsi2"
10927 [(set (match_operand:SI 0 "s_register_operand" "=r")
10928 (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
b232e6b5 10929 "TARGET_32BIT && arm_arch5t"
ee7cbe0e 10930 "clz%?\\t%0, %1"
bcaec148 10931 [(set_attr "predicable" "yes")
bebe9bbb 10932 (set_attr "type" "clz")])
331beb1a 10933
099ad98b 10934(define_insn "rbitsi2"
10935 [(set (match_operand:SI 0 "s_register_operand" "=r")
10936 (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")] UNSPEC_RBIT))]
10937 "TARGET_32BIT && arm_arch_thumb2"
10938 "rbit%?\\t%0, %1"
10939 [(set_attr "predicable" "yes")
bebe9bbb 10940 (set_attr "type" "clz")])
099ad98b 10941
99ffa689 10942;; Keep this as a CTZ expression until after reload and then split
10943;; into RBIT + CLZ. Since RBIT is represented as an UNSPEC it is unlikely
10944;; to fold with any other expression.
10945
10946(define_insn_and_split "ctzsi2"
10947 [(set (match_operand:SI 0 "s_register_operand" "=r")
10948 (ctz:SI (match_operand:SI 1 "s_register_operand" "r")))]
099ad98b 10949 "TARGET_32BIT && arm_arch_thumb2"
99ffa689 10950 "#"
10951 "&& reload_completed"
10952 [(const_int 0)]
099ad98b 10953 "
99ffa689 10954 emit_insn (gen_rbitsi2 (operands[0], operands[1]));
10955 emit_insn (gen_clzsi2 (operands[0], operands[0]));
10956 DONE;
10957")
099ad98b 10958
e1159bbe 10959;; V5E instructions.
331beb1a 10960
10961(define_insn "prefetch"
f4e79814 10962 [(prefetch (match_operand:SI 0 "address_operand" "p")
10963 (match_operand:SI 1 "" "")
10964 (match_operand:SI 2 "" ""))]
b232e6b5 10965 "TARGET_32BIT && arm_arch5te"
1b7da4ac 10966 "pld\\t%a0"
9f2c2a36 10967 [(set_attr "type" "load_4")]
1b7da4ac 10968)
331beb1a 10969
0d66636f 10970;; General predication pattern
10971
10972(define_cond_exec
10973 [(match_operator 0 "arm_comparison_operator"
10974 [(match_operand 1 "cc_register" "")
10975 (const_int 0)])]
580f4c48 10976 "TARGET_32BIT
10977 && (!TARGET_NO_VOLATILE_CE || !volatile_refs_p (PATTERN (insn)))"
0d66636f 10978 ""
c7a58118 10979[(set_attr "predicated" "yes")]
0d66636f 10980)
10981
fb94f18b 10982(define_insn "force_register_use"
10983 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_REGISTER_USE)]
063a05c7 10984 ""
fb94f18b 10985 "%@ %0 needed"
1b7da4ac 10986 [(set_attr "length" "0")
10987 (set_attr "type" "no_insn")]
063a05c7 10988)
7db9af5d 10989
4c44712e 10990
10991;; Patterns for exception handling
10992
10993(define_expand "eh_return"
3934ae0e 10994 [(use (match_operand 0 "general_operand"))]
4c44712e 10995 "TARGET_EITHER"
10996 "
10997 {
25f905c2 10998 if (TARGET_32BIT)
4c44712e 10999 emit_insn (gen_arm_eh_return (operands[0]));
11000 else
11001 emit_insn (gen_thumb_eh_return (operands[0]));
11002 DONE;
11003 }"
11004)
11005
11006;; We can't expand this before we know where the link register is stored.
11007(define_insn_and_split "arm_eh_return"
11008 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
11009 VUNSPEC_EH_RETURN)
11010 (clobber (match_scratch:SI 1 "=&r"))]
11011 "TARGET_ARM"
11012 "#"
11013 "&& reload_completed"
11014 [(const_int 0)]
11015 "
11016 {
11017 arm_set_return_address (operands[0], operands[1]);
11018 DONE;
11019 }"
11020)
11021
f655717d 11022\f
11023;; TLS support
11024
11025(define_insn "load_tp_hard"
11026 [(set (match_operand:SI 0 "register_operand" "=r")
11027 (unspec:SI [(const_int 0)] UNSPEC_TLS))]
11028 "TARGET_HARD_TP"
11029 "mrc%?\\tp15, 0, %0, c13, c0, 3\\t@ load_tp_hard"
1b7da4ac 11030 [(set_attr "predicable" "yes")
4b5d7374 11031 (set_attr "type" "mrs")]
f655717d 11032)
11033
85fc66a7 11034;; Doesn't clobber R1-R3. Must use r0 for the first operand.
11035(define_insn "load_tp_soft_fdpic"
11036 [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
11037 (clobber (reg:SI FDPIC_REGNUM))
11038 (clobber (reg:SI LR_REGNUM))
11039 (clobber (reg:SI IP_REGNUM))
11040 (clobber (reg:CC CC_REGNUM))]
11041 "TARGET_SOFT_TP && TARGET_FDPIC"
11042 "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
11043 [(set_attr "conds" "clob")
11044 (set_attr "type" "branch")]
11045)
11046
f655717d 11047;; Doesn't clobber R1-R3. Must use r0 for the first operand.
11048(define_insn "load_tp_soft"
11049 [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
11050 (clobber (reg:SI LR_REGNUM))
11051 (clobber (reg:SI IP_REGNUM))
11052 (clobber (reg:CC CC_REGNUM))]
85fc66a7 11053 "TARGET_SOFT_TP && !TARGET_FDPIC"
f655717d 11054 "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
1b7da4ac 11055 [(set_attr "conds" "clob")
11056 (set_attr "type" "branch")]
f655717d 11057)
11058
f41e4452 11059;; tls descriptor call
11060(define_insn "tlscall"
11061 [(set (reg:SI R0_REGNUM)
11062 (unspec:SI [(reg:SI R0_REGNUM)
11063 (match_operand:SI 0 "" "X")
11064 (match_operand 1 "" "")] UNSPEC_TLS))
11065 (clobber (reg:SI R1_REGNUM))
11066 (clobber (reg:SI LR_REGNUM))
11067 (clobber (reg:SI CC_REGNUM))]
11068 "TARGET_GNU2_TLS"
11069 {
11070 targetm.asm_out.internal_label (asm_out_file, "LPIC",
11071 INTVAL (operands[1]));
11072 return "bl\\t%c0(tlscall)";
11073 }
11074 [(set_attr "conds" "clob")
1b7da4ac 11075 (set_attr "length" "4")
11076 (set_attr "type" "branch")]
f41e4452 11077)
11078
1fe0edab 11079;; For thread pointer builtin
11080(define_expand "get_thread_pointersi"
3934ae0e 11081 [(match_operand:SI 0 "s_register_operand")]
1fe0edab 11082 ""
11083 "
11084 {
11085 arm_load_tp (operands[0]);
11086 DONE;
11087 }")
11088
f41e4452 11089;;
11090
aabe09ac 11091;; We only care about the lower 16 bits of the constant
11092;; being inserted into the upper 16 bits of the register.
eca5c984 11093(define_insn "*arm_movtas_ze"
417e5cc5 11094 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r,r")
eca5c984 11095 (const_int 16)
11096 (const_int 16))
11097 (match_operand:SI 1 "const_int_operand" ""))]
60a48e7d 11098 "TARGET_HAVE_MOVT"
417e5cc5 11099 "@
11100 movt%?\t%0, %L1
11101 movt\t%0, %L1"
11102 [(set_attr "arch" "32,v8mb")
11103 (set_attr "predicable" "yes")
1b7da4ac 11104 (set_attr "length" "4")
282b4c75 11105 (set_attr "type" "alu_sreg")]
eca5c984 11106)
11107
c0fc3696 11108(define_insn "*arm_rev"
a486b499 11109 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
11110 (bswap:SI (match_operand:SI 1 "s_register_operand" "l,l,r")))]
11111 "arm_arch6"
11112 "@
11113 rev\t%0, %1
11114 rev%?\t%0, %1
11115 rev%?\t%0, %1"
11116 [(set_attr "arch" "t1,t2,32")
1b7da4ac 11117 (set_attr "length" "2,2,4")
4a510717 11118 (set_attr "predicable" "no,yes,yes")
1b7da4ac 11119 (set_attr "type" "rev")]
ff82f757 11120)
11121
11122(define_expand "arm_legacy_rev"
3934ae0e 11123 [(set (match_operand:SI 2 "s_register_operand")
11124 (xor:SI (rotatert:SI (match_operand:SI 1 "s_register_operand")
ff82f757 11125 (const_int 16))
11126 (match_dup 1)))
11127 (set (match_dup 2)
11128 (lshiftrt:SI (match_dup 2)
11129 (const_int 8)))
3934ae0e 11130 (set (match_operand:SI 3 "s_register_operand")
ff82f757 11131 (rotatert:SI (match_dup 1)
11132 (const_int 8)))
11133 (set (match_dup 2)
11134 (and:SI (match_dup 2)
11135 (const_int -65281)))
3934ae0e 11136 (set (match_operand:SI 0 "s_register_operand")
ff82f757 11137 (xor:SI (match_dup 3)
11138 (match_dup 2)))]
11139 "TARGET_32BIT"
11140 ""
11141)
11142
11143;; Reuse temporaries to keep register pressure down.
11144(define_expand "thumb_legacy_rev"
3934ae0e 11145 [(set (match_operand:SI 2 "s_register_operand")
11146 (ashift:SI (match_operand:SI 1 "s_register_operand")
ff82f757 11147 (const_int 24)))
3934ae0e 11148 (set (match_operand:SI 3 "s_register_operand")
ff82f757 11149 (lshiftrt:SI (match_dup 1)
11150 (const_int 24)))
11151 (set (match_dup 3)
11152 (ior:SI (match_dup 3)
11153 (match_dup 2)))
3934ae0e 11154 (set (match_operand:SI 4 "s_register_operand")
ff82f757 11155 (const_int 16))
3934ae0e 11156 (set (match_operand:SI 5 "s_register_operand")
ff82f757 11157 (rotatert:SI (match_dup 1)
11158 (match_dup 4)))
11159 (set (match_dup 2)
11160 (ashift:SI (match_dup 5)
11161 (const_int 24)))
11162 (set (match_dup 5)
11163 (lshiftrt:SI (match_dup 5)
11164 (const_int 24)))
11165 (set (match_dup 5)
11166 (ior:SI (match_dup 5)
11167 (match_dup 2)))
11168 (set (match_dup 5)
11169 (rotatert:SI (match_dup 5)
11170 (match_dup 4)))
3934ae0e 11171 (set (match_operand:SI 0 "s_register_operand")
ff82f757 11172 (ior:SI (match_dup 5)
11173 (match_dup 3)))]
11174 "TARGET_THUMB"
11175 ""
11176)
11177
62e39b06 11178;; ARM-specific expansion of signed mod by power of 2
11179;; using conditional negate.
11180;; For r0 % n where n is a power of 2 produce:
11181;; rsbs r1, r0, #0
11182;; and r0, r0, #(n - 1)
11183;; and r1, r1, #(n - 1)
11184;; rsbpl r0, r1, #0
11185
11186(define_expand "modsi3"
3934ae0e 11187 [(match_operand:SI 0 "register_operand")
11188 (match_operand:SI 1 "register_operand")
11189 (match_operand:SI 2 "const_int_operand")]
62e39b06 11190 "TARGET_32BIT"
11191 {
11192 HOST_WIDE_INT val = INTVAL (operands[2]);
11193
11194 if (val <= 0
11195 || exact_log2 (val) <= 0)
11196 FAIL;
11197
11198 rtx mask = GEN_INT (val - 1);
11199
11200 /* In the special case of x0 % 2 we can do the even shorter:
11201 cmp r0, #0
11202 and r0, r0, #1
11203 rsblt r0, r0, #0. */
11204
11205 if (val == 2)
11206 {
11207 rtx cc_reg = arm_gen_compare_reg (LT,
11208 operands[1], const0_rtx, NULL_RTX);
11209 rtx cond = gen_rtx_LT (SImode, cc_reg, const0_rtx);
11210 rtx masked = gen_reg_rtx (SImode);
11211
11212 emit_insn (gen_andsi3 (masked, operands[1], mask));
11213 emit_move_insn (operands[0],
11214 gen_rtx_IF_THEN_ELSE (SImode, cond,
11215 gen_rtx_NEG (SImode,
11216 masked),
11217 masked));
11218 DONE;
11219 }
11220
11221 rtx neg_op = gen_reg_rtx (SImode);
11222 rtx_insn *insn = emit_insn (gen_subsi3_compare0 (neg_op, const0_rtx,
11223 operands[1]));
11224
11225 /* Extract the condition register and mode. */
11226 rtx cmp = XVECEXP (PATTERN (insn), 0, 0);
11227 rtx cc_reg = SET_DEST (cmp);
11228 rtx cond = gen_rtx_GE (SImode, cc_reg, const0_rtx);
11229
11230 emit_insn (gen_andsi3 (operands[0], operands[1], mask));
11231
11232 rtx masked_neg = gen_reg_rtx (SImode);
11233 emit_insn (gen_andsi3 (masked_neg, neg_op, mask));
11234
11235 /* We want a conditional negate here, but emitting COND_EXEC rtxes
11236 during expand does not always work. Do an IF_THEN_ELSE instead. */
11237 emit_move_insn (operands[0],
11238 gen_rtx_IF_THEN_ELSE (SImode, cond,
11239 gen_rtx_NEG (SImode, masked_neg),
11240 operands[0]));
11241
11242
11243 DONE;
11244 }
11245)
11246
ff82f757 11247(define_expand "bswapsi2"
3934ae0e 11248 [(set (match_operand:SI 0 "s_register_operand")
11249 (bswap:SI (match_operand:SI 1 "s_register_operand")))]
8d1af482 11250"TARGET_EITHER && (arm_arch6 || !optimize_size)"
ff82f757 11251"
8d1af482 11252 if (!arm_arch6)
11253 {
11254 rtx op2 = gen_reg_rtx (SImode);
11255 rtx op3 = gen_reg_rtx (SImode);
ff82f757 11256
8d1af482 11257 if (TARGET_THUMB)
11258 {
11259 rtx op4 = gen_reg_rtx (SImode);
11260 rtx op5 = gen_reg_rtx (SImode);
ff82f757 11261
8d1af482 11262 emit_insn (gen_thumb_legacy_rev (operands[0], operands[1],
11263 op2, op3, op4, op5));
11264 }
11265 else
11266 {
11267 emit_insn (gen_arm_legacy_rev (operands[0], operands[1],
11268 op2, op3));
11269 }
ff82f757 11270
8d1af482 11271 DONE;
11272 }
ff82f757 11273 "
11274)
11275
a486b499 11276;; bswap16 patterns: use revsh and rev16 instructions for the signed
11277;; and unsigned variants, respectively. For rev16, expose
11278;; byte-swapping in the lower 16 bits only.
11279(define_insn "*arm_revsh"
11280 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
11281 (sign_extend:SI (bswap:HI (match_operand:HI 1 "s_register_operand" "l,l,r"))))]
11282 "arm_arch6"
11283 "@
11284 revsh\t%0, %1
11285 revsh%?\t%0, %1
11286 revsh%?\t%0, %1"
11287 [(set_attr "arch" "t1,t2,32")
1b7da4ac 11288 (set_attr "length" "2,2,4")
11289 (set_attr "type" "rev")]
a486b499 11290)
11291
11292(define_insn "*arm_rev16"
11293 [(set (match_operand:HI 0 "s_register_operand" "=l,l,r")
11294 (bswap:HI (match_operand:HI 1 "s_register_operand" "l,l,r")))]
11295 "arm_arch6"
11296 "@
11297 rev16\t%0, %1
11298 rev16%?\t%0, %1
11299 rev16%?\t%0, %1"
11300 [(set_attr "arch" "t1,t2,32")
1b7da4ac 11301 (set_attr "length" "2,2,4")
11302 (set_attr "type" "rev")]
09f69e55 11303)
11304
11305;; There are no canonicalisation rules for the position of the lshiftrt, ashift
11306;; operations within an IOR/AND RTX, therefore we have two patterns matching
11307;; each valid permutation.
11308
11309(define_insn "arm_rev16si2"
11310 [(set (match_operand:SI 0 "register_operand" "=l,l,r")
11311 (ior:SI (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "l,l,r")
11312 (const_int 8))
11313 (match_operand:SI 3 "const_int_operand" "n,n,n"))
11314 (and:SI (lshiftrt:SI (match_dup 1)
11315 (const_int 8))
11316 (match_operand:SI 2 "const_int_operand" "n,n,n"))))]
11317 "arm_arch6
11318 && aarch_rev16_shleft_mask_imm_p (operands[3], SImode)
11319 && aarch_rev16_shright_mask_imm_p (operands[2], SImode)"
11320 "rev16\\t%0, %1"
11321 [(set_attr "arch" "t1,t2,32")
11322 (set_attr "length" "2,2,4")
11323 (set_attr "type" "rev")]
11324)
11325
11326(define_insn "arm_rev16si2_alt"
11327 [(set (match_operand:SI 0 "register_operand" "=l,l,r")
11328 (ior:SI (and:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,l,r")
11329 (const_int 8))
11330 (match_operand:SI 2 "const_int_operand" "n,n,n"))
11331 (and:SI (ashift:SI (match_dup 1)
11332 (const_int 8))
11333 (match_operand:SI 3 "const_int_operand" "n,n,n"))))]
11334 "arm_arch6
11335 && aarch_rev16_shleft_mask_imm_p (operands[3], SImode)
11336 && aarch_rev16_shright_mask_imm_p (operands[2], SImode)"
11337 "rev16\\t%0, %1"
11338 [(set_attr "arch" "t1,t2,32")
11339 (set_attr "length" "2,2,4")
11340 (set_attr "type" "rev")]
a486b499 11341)
11342
11343(define_expand "bswaphi2"
3934ae0e 11344 [(set (match_operand:HI 0 "s_register_operand")
11345 (bswap:HI (match_operand:HI 1 "s_register_operand")))]
a486b499 11346"arm_arch6"
11347""
11348)
11349
1653cf17 11350;; Patterns for LDRD/STRD in Thumb2 mode
11351
11352(define_insn "*thumb2_ldrd"
11353 [(set (match_operand:SI 0 "s_register_operand" "=r")
11354 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
11355 (match_operand:SI 2 "ldrd_strd_offset_operand" "Do"))))
11356 (set (match_operand:SI 3 "s_register_operand" "=r")
11357 (mem:SI (plus:SI (match_dup 1)
11358 (match_operand:SI 4 "const_int_operand" ""))))]
11359 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
1653cf17 11360 && ((INTVAL (operands[2]) + 4) == INTVAL (operands[4]))
11361 && (operands_ok_ldrd_strd (operands[0], operands[3],
11362 operands[1], INTVAL (operands[2]),
11363 false, true))"
11364 "ldrd%?\t%0, %3, [%1, %2]"
9f2c2a36 11365 [(set_attr "type" "load_8")
8bdfd6ed 11366 (set_attr "predicable" "yes")])
1653cf17 11367
11368(define_insn "*thumb2_ldrd_base"
11369 [(set (match_operand:SI 0 "s_register_operand" "=r")
11370 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
11371 (set (match_operand:SI 2 "s_register_operand" "=r")
11372 (mem:SI (plus:SI (match_dup 1)
11373 (const_int 4))))]
11374 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
1653cf17 11375 && (operands_ok_ldrd_strd (operands[0], operands[2],
11376 operands[1], 0, false, true))"
11377 "ldrd%?\t%0, %2, [%1]"
9f2c2a36 11378 [(set_attr "type" "load_8")
8bdfd6ed 11379 (set_attr "predicable" "yes")])
1653cf17 11380
11381(define_insn "*thumb2_ldrd_base_neg"
11382 [(set (match_operand:SI 0 "s_register_operand" "=r")
11383 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
11384 (const_int -4))))
11385 (set (match_operand:SI 2 "s_register_operand" "=r")
11386 (mem:SI (match_dup 1)))]
11387 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
1653cf17 11388 && (operands_ok_ldrd_strd (operands[0], operands[2],
11389 operands[1], -4, false, true))"
11390 "ldrd%?\t%0, %2, [%1, #-4]"
9f2c2a36 11391 [(set_attr "type" "load_8")
8bdfd6ed 11392 (set_attr "predicable" "yes")])
1653cf17 11393
11394(define_insn "*thumb2_strd"
11395 [(set (mem:SI (plus:SI (match_operand:SI 0 "s_register_operand" "rk")
11396 (match_operand:SI 1 "ldrd_strd_offset_operand" "Do")))
11397 (match_operand:SI 2 "s_register_operand" "r"))
11398 (set (mem:SI (plus:SI (match_dup 0)
11399 (match_operand:SI 3 "const_int_operand" "")))
11400 (match_operand:SI 4 "s_register_operand" "r"))]
11401 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
1653cf17 11402 && ((INTVAL (operands[1]) + 4) == INTVAL (operands[3]))
11403 && (operands_ok_ldrd_strd (operands[2], operands[4],
11404 operands[0], INTVAL (operands[1]),
11405 false, false))"
11406 "strd%?\t%2, %4, [%0, %1]"
9f2c2a36 11407 [(set_attr "type" "store_8")
8bdfd6ed 11408 (set_attr "predicable" "yes")])
1653cf17 11409
11410(define_insn "*thumb2_strd_base"
11411 [(set (mem:SI (match_operand:SI 0 "s_register_operand" "rk"))
11412 (match_operand:SI 1 "s_register_operand" "r"))
11413 (set (mem:SI (plus:SI (match_dup 0)
11414 (const_int 4)))
11415 (match_operand:SI 2 "s_register_operand" "r"))]
11416 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
1653cf17 11417 && (operands_ok_ldrd_strd (operands[1], operands[2],
11418 operands[0], 0, false, false))"
11419 "strd%?\t%1, %2, [%0]"
9f2c2a36 11420 [(set_attr "type" "store_8")
8bdfd6ed 11421 (set_attr "predicable" "yes")])
1653cf17 11422
11423(define_insn "*thumb2_strd_base_neg"
11424 [(set (mem:SI (plus:SI (match_operand:SI 0 "s_register_operand" "rk")
11425 (const_int -4)))
11426 (match_operand:SI 1 "s_register_operand" "r"))
11427 (set (mem:SI (match_dup 0))
11428 (match_operand:SI 2 "s_register_operand" "r"))]
11429 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
1653cf17 11430 && (operands_ok_ldrd_strd (operands[1], operands[2],
11431 operands[0], -4, false, false))"
11432 "strd%?\t%1, %2, [%0, #-4]"
9f2c2a36 11433 [(set_attr "type" "store_8")
8bdfd6ed 11434 (set_attr "predicable" "yes")])
1653cf17 11435
2a0c73f2 11436;; ARMv8 CRC32 instructions.
8656245d 11437(define_insn "arm_<crc_variant>"
2a0c73f2 11438 [(set (match_operand:SI 0 "s_register_operand" "=r")
11439 (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")
11440 (match_operand:<crc_mode> 2 "s_register_operand" "r")]
11441 CRC))]
11442 "TARGET_CRC32"
11443 "<crc_variant>\\t%0, %1, %2"
11444 [(set_attr "type" "crc")
11445 (set_attr "conds" "unconditional")]
11446)
1653cf17 11447
353cf59a 11448;; Load the load/store double peephole optimizations.
11449(include "ldrdstrd.md")
11450
320ea44d 11451;; Load the load/store multiple patterns
11452(include "ldmstm.md")
426be8c5 11453
11454;; Patterns in ldmstm.md don't cover more than 4 registers. This pattern covers
11455;; large lists without explicit writeback generated for APCS_FRAME epilogue.
3873efff 11456;; The operands are validated through the load_multiple_operation
11457;; match_parallel predicate rather than through constraints so enable it only
11458;; after reload.
426be8c5 11459(define_insn "*load_multiple"
11460 [(match_parallel 0 "load_multiple_operation"
11461 [(set (match_operand:SI 2 "s_register_operand" "=rk")
11462 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
11463 ])]
3873efff 11464 "TARGET_32BIT && reload_completed"
426be8c5 11465 "*
11466 {
11467 arm_output_multireg_pop (operands, /*return_pc=*/false,
11468 /*cond=*/const_true_rtx,
11469 /*reverse=*/false,
11470 /*update=*/false);
11471 return \"\";
11472 }
11473 "
11474 [(set_attr "predicable" "yes")]
11475)
11476
84450ddc 11477(define_expand "copysignsf3"
11478 [(match_operand:SF 0 "register_operand")
11479 (match_operand:SF 1 "register_operand")
11480 (match_operand:SF 2 "register_operand")]
11481 "TARGET_SOFT_FLOAT && arm_arch_thumb2"
11482 "{
11483 emit_move_insn (operands[0], operands[2]);
11484 emit_insn (gen_insv_t2 (simplify_gen_subreg (SImode, operands[0], SFmode, 0),
11485 GEN_INT (31), GEN_INT (0),
11486 simplify_gen_subreg (SImode, operands[1], SFmode, 0)));
11487 DONE;
11488 }"
11489)
11490
11491(define_expand "copysigndf3"
11492 [(match_operand:DF 0 "register_operand")
11493 (match_operand:DF 1 "register_operand")
11494 (match_operand:DF 2 "register_operand")]
11495 "TARGET_SOFT_FLOAT && arm_arch_thumb2"
11496 "{
11497 rtx op0_low = gen_lowpart (SImode, operands[0]);
11498 rtx op0_high = gen_highpart (SImode, operands[0]);
11499 rtx op1_low = gen_lowpart (SImode, operands[1]);
11500 rtx op1_high = gen_highpart (SImode, operands[1]);
11501 rtx op2_high = gen_highpart (SImode, operands[2]);
11502
11503 rtx scratch1 = gen_reg_rtx (SImode);
11504 rtx scratch2 = gen_reg_rtx (SImode);
11505 emit_move_insn (scratch1, op2_high);
11506 emit_move_insn (scratch2, op1_high);
11507
d1f9b275 11508 emit_insn(gen_rtx_SET(scratch1,
84450ddc 11509 gen_rtx_LSHIFTRT (SImode, op2_high, GEN_INT(31))));
11510 emit_insn(gen_insv_t2(scratch2, GEN_INT(1), GEN_INT(31), scratch1));
11511 emit_move_insn (op0_low, op1_low);
11512 emit_move_insn (op0_high, scratch2);
11513
11514 DONE;
11515 }"
11516)
11517
115857ef 11518;; movmisalign patterns for HImode and SImode.
11519(define_expand "movmisalign<mode>"
11520 [(match_operand:HSI 0 "general_operand")
11521 (match_operand:HSI 1 "general_operand")]
11522 "unaligned_access"
11523{
11524 /* This pattern is not permitted to fail during expansion: if both arguments
11525 are non-registers (e.g. memory := constant), force operand 1 into a
11526 register. */
11527 rtx (* gen_unaligned_load)(rtx, rtx);
11528 rtx tmp_dest = operands[0];
11529 if (!s_register_operand (operands[0], <MODE>mode)
11530 && !s_register_operand (operands[1], <MODE>mode))
11531 operands[1] = force_reg (<MODE>mode, operands[1]);
11532
11533 if (<MODE>mode == HImode)
11534 {
11535 gen_unaligned_load = gen_unaligned_loadhiu;
11536 tmp_dest = gen_reg_rtx (SImode);
11537 }
11538 else
11539 gen_unaligned_load = gen_unaligned_loadsi;
11540
11541 if (MEM_P (operands[1]))
11542 {
11543 emit_insn (gen_unaligned_load (tmp_dest, operands[1]));
11544 if (<MODE>mode == HImode)
11545 emit_move_insn (operands[0], gen_lowpart (HImode, tmp_dest));
11546 }
11547 else
11548 emit_insn (gen_unaligned_store<mode> (operands[0], operands[1]));
11549
11550 DONE;
11551})
11552
8656245d 11553(define_insn "arm_<cdp>"
1be6395a 11554 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "n")
11555 (match_operand:SI 1 "immediate_operand" "n")
11556 (match_operand:SI 2 "immediate_operand" "n")
11557 (match_operand:SI 3 "immediate_operand" "n")
11558 (match_operand:SI 4 "immediate_operand" "n")
11559 (match_operand:SI 5 "immediate_operand" "n")] CDPI)]
11560 "arm_coproc_builtin_available (VUNSPEC_<CDP>)"
11561{
11562 arm_const_bounds (operands[0], 0, 16);
11563 arm_const_bounds (operands[1], 0, 16);
11564 arm_const_bounds (operands[2], 0, (1 << 5));
11565 arm_const_bounds (operands[3], 0, (1 << 5));
11566 arm_const_bounds (operands[4], 0, (1 << 5));
11567 arm_const_bounds (operands[5], 0, 8);
11568 return "<cdp>\\tp%c0, %1, CR%c2, CR%c3, CR%c4, %5";
11569}
11570 [(set_attr "length" "4")
11571 (set_attr "type" "coproc")])
11572
638b44bd 11573(define_insn "*ldc"
11574 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "n")
11575 (match_operand:SI 1 "immediate_operand" "n")
11576 (match_operand:SI 2 "memory_operand" "Uz")] LDCI)]
11577 "arm_coproc_builtin_available (VUNSPEC_<LDC>)"
11578{
11579 arm_const_bounds (operands[0], 0, 16);
11580 arm_const_bounds (operands[1], 0, (1 << 5));
11581 return "<ldc>\\tp%c0, CR%c1, %2";
11582}
11583 [(set_attr "length" "4")
11584 (set_attr "type" "coproc")])
11585
11586(define_insn "*stc"
11587 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "n")
11588 (match_operand:SI 1 "immediate_operand" "n")
11589 (match_operand:SI 2 "memory_operand" "=Uz")] STCI)]
11590 "arm_coproc_builtin_available (VUNSPEC_<STC>)"
11591{
11592 arm_const_bounds (operands[0], 0, 16);
11593 arm_const_bounds (operands[1], 0, (1 << 5));
11594 return "<stc>\\tp%c0, CR%c1, %2";
11595}
11596 [(set_attr "length" "4")
11597 (set_attr "type" "coproc")])
11598
8656245d 11599(define_expand "arm_<ldc>"
638b44bd 11600 [(unspec_volatile [(match_operand:SI 0 "immediate_operand")
11601 (match_operand:SI 1 "immediate_operand")
11602 (mem:SI (match_operand:SI 2 "s_register_operand"))] LDCI)]
11603 "arm_coproc_builtin_available (VUNSPEC_<LDC>)")
11604
8656245d 11605(define_expand "arm_<stc>"
638b44bd 11606 [(unspec_volatile [(match_operand:SI 0 "immediate_operand")
11607 (match_operand:SI 1 "immediate_operand")
11608 (mem:SI (match_operand:SI 2 "s_register_operand"))] STCI)]
11609 "arm_coproc_builtin_available (VUNSPEC_<STC>)")
11610
8656245d 11611(define_insn "arm_<mcr>"
415e9b1f 11612 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "n")
11613 (match_operand:SI 1 "immediate_operand" "n")
11614 (match_operand:SI 2 "s_register_operand" "r")
11615 (match_operand:SI 3 "immediate_operand" "n")
11616 (match_operand:SI 4 "immediate_operand" "n")
11617 (match_operand:SI 5 "immediate_operand" "n")] MCRI)
11618 (use (match_dup 2))]
11619 "arm_coproc_builtin_available (VUNSPEC_<MCR>)"
11620{
11621 arm_const_bounds (operands[0], 0, 16);
11622 arm_const_bounds (operands[1], 0, 8);
11623 arm_const_bounds (operands[3], 0, (1 << 5));
11624 arm_const_bounds (operands[4], 0, (1 << 5));
11625 arm_const_bounds (operands[5], 0, 8);
11626 return "<mcr>\\tp%c0, %1, %2, CR%c3, CR%c4, %5";
11627}
11628 [(set_attr "length" "4")
11629 (set_attr "type" "coproc")])
11630
8656245d 11631(define_insn "arm_<mrc>"
415e9b1f 11632 [(set (match_operand:SI 0 "s_register_operand" "=r")
6f8d7784 11633 (unspec_volatile:SI [(match_operand:SI 1 "immediate_operand" "n")
415e9b1f 11634 (match_operand:SI 2 "immediate_operand" "n")
11635 (match_operand:SI 3 "immediate_operand" "n")
11636 (match_operand:SI 4 "immediate_operand" "n")
11637 (match_operand:SI 5 "immediate_operand" "n")] MRCI))]
11638 "arm_coproc_builtin_available (VUNSPEC_<MRC>)"
11639{
11640 arm_const_bounds (operands[1], 0, 16);
11641 arm_const_bounds (operands[2], 0, 8);
11642 arm_const_bounds (operands[3], 0, (1 << 5));
11643 arm_const_bounds (operands[4], 0, (1 << 5));
11644 arm_const_bounds (operands[5], 0, 8);
11645 return "<mrc>\\tp%c1, %2, %0, CR%c3, CR%c4, %5";
11646}
11647 [(set_attr "length" "4")
11648 (set_attr "type" "coproc")])
11649
8656245d 11650(define_insn "arm_<mcrr>"
cabfd710 11651 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "n")
11652 (match_operand:SI 1 "immediate_operand" "n")
11653 (match_operand:DI 2 "s_register_operand" "r")
11654 (match_operand:SI 3 "immediate_operand" "n")] MCRRI)
11655 (use (match_dup 2))]
11656 "arm_coproc_builtin_available (VUNSPEC_<MCRR>)"
11657{
11658 arm_const_bounds (operands[0], 0, 16);
11659 arm_const_bounds (operands[1], 0, 8);
11660 arm_const_bounds (operands[3], 0, (1 << 5));
11661 return "<mcrr>\\tp%c0, %1, %Q2, %R2, CR%c3";
11662}
11663 [(set_attr "length" "4")
11664 (set_attr "type" "coproc")])
11665
8656245d 11666(define_insn "arm_<mrrc>"
cabfd710 11667 [(set (match_operand:DI 0 "s_register_operand" "=r")
6f8d7784 11668 (unspec_volatile:DI [(match_operand:SI 1 "immediate_operand" "n")
cabfd710 11669 (match_operand:SI 2 "immediate_operand" "n")
11670 (match_operand:SI 3 "immediate_operand" "n")] MRRCI))]
11671 "arm_coproc_builtin_available (VUNSPEC_<MRRC>)"
11672{
11673 arm_const_bounds (operands[1], 0, 16);
11674 arm_const_bounds (operands[2], 0, 8);
11675 arm_const_bounds (operands[3], 0, (1 << 5));
11676 return "<mrrc>\\tp%c1, %2, %Q0, %R0, CR%c3";
11677}
11678 [(set_attr "length" "4")
11679 (set_attr "type" "coproc")])
11680
be626997 11681(define_expand "speculation_barrier"
11682 [(unspec_volatile [(const_int 0)] VUNSPEC_SPECULATION_BARRIER)]
11683 "TARGET_EITHER"
11684 "
a7852b35 11685 /* For thumb1 (except Armv8 derivatives), and for pre-Armv7 we don't
11686 have a usable barrier (and probably don't need one in practice).
11687 But to be safe if such code is run on later architectures, call a
11688 helper function in libgcc that will do the thing for the active
11689 system. */
11690 if (!(arm_arch7 || arm_arch8))
11691 {
11692 arm_emit_speculation_barrier_function ();
11693 DONE;
11694 }
be626997 11695 "
11696)
11697
11698;; Generate a hard speculation barrier when we have not enabled speculation
11699;; tracking.
11700(define_insn "*speculation_barrier_insn"
11701 [(unspec_volatile [(const_int 0)] VUNSPEC_SPECULATION_BARRIER)]
a7852b35 11702 "arm_arch7 || arm_arch8"
be626997 11703 "isb\;dsb\\tsy"
11704 [(set_attr "type" "block")
11705 (set_attr "length" "8")]
11706)
11707
d98a3884 11708;; Vector bits common to IWMMXT and Neon
11709(include "vec-common.md")
755eb2b4 11710;; Load the Intel Wireless Multimedia Extension patterns
11711(include "iwmmxt.md")
a2cd141b 11712;; Load the VFP co-processor patterns
11713(include "vfp.md")
bc360af8 11714;; Thumb-1 patterns
11715(include "thumb1.md")
25f905c2 11716;; Thumb-2 patterns
11717(include "thumb2.md")
d98a3884 11718;; Neon patterns
11719(include "neon.md")
e84fdf6e 11720;; Crypto patterns
11721(include "crypto.md")
06df6b17 11722;; Synchronization Primitives
11723(include "sync.md")
bbbe4599 11724;; Fixed-point patterns
11725(include "arm-fixed.md")