]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/arm/arm.md
[arm] Improve code generation for addvsi4.
[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
d302ef3a 806(define_insn "addsi3_compareV_imm"
807 [(set (reg:CC_V CC_REGNUM)
808 (compare:CC_V
809 (plus:DI
810 (sign_extend:DI
811 (match_operand:SI 1 "register_operand" "l,0,l,0,r,r"))
812 (match_operand 2 "arm_addimm_operand" "Pd,Py,Px,Pw,I,L"))
813 (sign_extend:DI (plus:SI (match_dup 1) (match_dup 2)))))
814 (set (match_operand:SI 0 "register_operand" "=l,l,l,l,r,r")
815 (plus:SI (match_dup 1) (match_dup 2)))]
816 "TARGET_32BIT
817 && INTVAL (operands[2]) == ARM_SIGN_EXTEND (INTVAL (operands[2]))"
818 "@
819 adds%?\\t%0, %1, %2
820 adds%?\\t%0, %0, %2
821 subs%?\\t%0, %1, #%n2
822 subs%?\\t%0, %0, #%n2
823 adds%?\\t%0, %1, %2
824 subs%?\\t%0, %1, #%n2"
825 [(set_attr "conds" "set")
826 (set_attr "arch" "t2,t2,t2,t2,*,*")
827 (set_attr "length" "2,2,2,2,4,4")
828 (set_attr "type" "alus_imm")]
829)
830
90c2bcf0 831(define_insn "addsi3_compare0"
bd5b4116 832 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 833 (compare:CC_NOOV
65f68e55 834 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r,r")
835 (match_operand:SI 2 "arm_add_operand" "I,L,r"))
5565501b 836 (const_int 0)))
65f68e55 837 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9c08d1fa 838 (plus:SI (match_dup 1) (match_dup 2)))]
ec792a7b 839 "TARGET_ARM"
5565501b 840 "@
3ef90e77 841 adds%?\\t%0, %1, %2
842 subs%?\\t%0, %1, #%n2
843 adds%?\\t%0, %1, %2"
65f68e55 844 [(set_attr "conds" "set")
112eda6f 845 (set_attr "type" "alus_imm,alus_imm,alus_sreg")]
cffb2a26 846)
9c08d1fa 847
aea4c774 848(define_insn "*addsi3_compare0_scratch"
bd5b4116 849 [(set (reg:CC_NOOV CC_REGNUM)
aea4c774 850 (compare:CC_NOOV
65f68e55 851 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r, r")
852 (match_operand:SI 1 "arm_add_operand" "I,L, r"))
aea4c774 853 (const_int 0)))]
ec792a7b 854 "TARGET_ARM"
cffb2a26 855 "@
856 cmn%?\\t%0, %1
65f68e55 857 cmp%?\\t%0, #%n1
858 cmn%?\\t%0, %1"
596e5e8f 859 [(set_attr "conds" "set")
65f68e55 860 (set_attr "predicable" "yes")
112eda6f 861 (set_attr "type" "alus_imm,alus_imm,alus_sreg")]
0d66636f 862)
cffb2a26 863
aed179ae 864(define_insn "*compare_negsi_si"
865 [(set (reg:CC_Z CC_REGNUM)
866 (compare:CC_Z
7c36fe71 867 (neg:SI (match_operand:SI 0 "s_register_operand" "l,r"))
868 (match_operand:SI 1 "s_register_operand" "l,r")))]
25f905c2 869 "TARGET_32BIT"
aed179ae 870 "cmn%?\\t%1, %0"
596e5e8f 871 [(set_attr "conds" "set")
7c36fe71 872 (set_attr "predicable" "yes")
873 (set_attr "arch" "t2,*")
874 (set_attr "length" "2,4")
1b7da4ac 875 (set_attr "predicable_short_it" "yes,no")
112eda6f 876 (set_attr "type" "alus_sreg")]
0d66636f 877)
aea4c774 878
7f100343 879;; This is the canonicalization of subsi3_compare when the
203c488f 880;; addend is a constant.
190efb17 881(define_insn "cmpsi2_addneg"
203c488f 882 [(set (reg:CC CC_REGNUM)
883 (compare:CC
884 (match_operand:SI 1 "s_register_operand" "r,r")
7f100343 885 (match_operand:SI 2 "arm_addimm_operand" "I,L")))
203c488f 886 (set (match_operand:SI 0 "s_register_operand" "=r,r")
887 (plus:SI (match_dup 1)
7f100343 888 (match_operand:SI 3 "arm_addimm_operand" "L,I")))]
e3dcfc16 889 "TARGET_32BIT
890 && (INTVAL (operands[2])
891 == trunc_int_for_mode (-INTVAL (operands[3]), SImode))"
892{
7f100343 893 /* For 0 and INT_MIN it is essential that we use subs, as adds will result
894 in different condition codes (like cmn rather than like cmp), so that
895 alternative comes first. Both alternatives can match for any 0x??000000
896 where except for 0 and INT_MIN it doesn't matter what we choose, and also
897 for -1 and 1 with TARGET_THUMB2, in that case prefer instruction with #1
898 as it is shorter. */
899 if (which_alternative == 0 && operands[3] != const1_rtx)
e3dcfc16 900 return "subs%?\\t%0, %1, #%n3";
901 else
902 return "adds%?\\t%0, %1, %3";
903}
1b7da4ac 904 [(set_attr "conds" "set")
112eda6f 905 (set_attr "type" "alus_sreg")]
203c488f 906)
907
908;; Convert the sequence
909;; sub rd, rn, #1
910;; cmn rd, #1 (equivalent to cmp rd, #-1)
911;; bne dest
912;; into
913;; subs rd, rn, #1
914;; bcs dest ((unsigned)rn >= 1)
915;; similarly for the beq variant using bcc.
916;; This is a common looping idiom (while (n--))
917(define_peephole2
372575c7 918 [(set (match_operand:SI 0 "arm_general_register_operand" "")
919 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
203c488f 920 (const_int -1)))
921 (set (match_operand 2 "cc_register" "")
922 (compare (match_dup 0) (const_int -1)))
923 (set (pc)
924 (if_then_else (match_operator 3 "equality_operator"
925 [(match_dup 2) (const_int 0)])
926 (match_operand 4 "" "")
927 (match_operand 5 "" "")))]
25f905c2 928 "TARGET_32BIT && peep2_reg_dead_p (3, operands[2])"
203c488f 929 [(parallel[
930 (set (match_dup 2)
931 (compare:CC
932 (match_dup 1) (const_int 1)))
933 (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
934 (set (pc)
935 (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
936 (match_dup 4)
937 (match_dup 5)))]
938 "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
939 operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
940 ? GEU : LTU),
941 VOIDmode,
942 operands[2], const0_rtx);"
943)
944
ebcc79bc 945;; The next four insns work because they compare the result with one of
946;; the operands, and we know that the use of the condition code is
947;; either GEU or LTU, so we can use the carry flag from the addition
948;; instead of doing the compare a second time.
eaddabc8 949(define_insn "addsi3_compare_op1"
bd5b4116 950 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 951 (compare:CC_C
eaddabc8 952 (plus:SI (match_operand:SI 1 "s_register_operand" "l,0,l,0,rk,rk")
953 (match_operand:SI 2 "arm_add_operand" "lPd,Py,lPx,Pw,rkI,L"))
ebcc79bc 954 (match_dup 1)))
eaddabc8 955 (set (match_operand:SI 0 "s_register_operand" "=l,l,l,l,rk,rk")
ebcc79bc 956 (plus:SI (match_dup 1) (match_dup 2)))]
25f905c2 957 "TARGET_32BIT"
ebcc79bc 958 "@
4fe655e9 959 adds%?\\t%0, %1, %2
960 adds%?\\t%0, %0, %2
961 subs%?\\t%0, %1, #%n2
962 subs%?\\t%0, %0, #%n2
3ef90e77 963 adds%?\\t%0, %1, %2
eaddabc8 964 subs%?\\t%0, %1, #%n2"
65f68e55 965 [(set_attr "conds" "set")
eaddabc8 966 (set_attr "arch" "t2,t2,t2,t2,*,*")
967 (set_attr "length" "2,2,2,2,4,4")
968 (set (attr "type")
969 (if_then_else (match_operand 2 "const_int_operand")
970 (const_string "alu_imm")
971 (const_string "alu_sreg")))]
0d66636f 972)
ebcc79bc 973
974(define_insn "*addsi3_compare_op2"
bd5b4116 975 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 976 (compare:CC_C
eaddabc8 977 (plus:SI (match_operand:SI 1 "s_register_operand" "l,0,l,0,r,r")
978 (match_operand:SI 2 "arm_add_operand" "lPd,Py,lPx,Pw,rI,L"))
ebcc79bc 979 (match_dup 2)))
eaddabc8 980 (set (match_operand:SI 0 "s_register_operand" "=l,l,l,l,r,r")
9c08d1fa 981 (plus:SI (match_dup 1) (match_dup 2)))]
25f905c2 982 "TARGET_32BIT"
5565501b 983 "@
4fe655e9 984 adds%?\\t%0, %1, %2
985 adds%?\\t%0, %0, %2
986 subs%?\\t%0, %1, #%n2
987 subs%?\\t%0, %0, #%n2
3ef90e77 988 adds%?\\t%0, %1, %2
eaddabc8 989 subs%?\\t%0, %1, #%n2"
65f68e55 990 [(set_attr "conds" "set")
eaddabc8 991 (set_attr "arch" "t2,t2,t2,t2,*,*")
992 (set_attr "length" "2,2,2,2,4,4")
993 (set (attr "type")
994 (if_then_else (match_operand 2 "const_int_operand")
995 (const_string "alu_imm")
996 (const_string "alu_sreg")))]
0d66636f 997)
9c08d1fa 998
ebcc79bc 999(define_insn "*compare_addsi2_op0"
bd5b4116 1000 [(set (reg:CC_C CC_REGNUM)
7c36fe71 1001 (compare:CC_C
eaddabc8 1002 (plus:SI (match_operand:SI 0 "s_register_operand" "l,l,r,r")
1003 (match_operand:SI 1 "arm_add_operand" "l,Pw,rI,L"))
7c36fe71 1004 (match_dup 0)))]
25f905c2 1005 "TARGET_32BIT"
ebcc79bc 1006 "@
1007 cmn%?\\t%0, %1
65f68e55 1008 cmp%?\\t%0, #%n1
eaddabc8 1009 cmn%?\\t%0, %1
1010 cmp%?\\t%0, #%n1"
596e5e8f 1011 [(set_attr "conds" "set")
65f68e55 1012 (set_attr "predicable" "yes")
eaddabc8 1013 (set_attr "arch" "t2,t2,*,*")
1014 (set_attr "predicable_short_it" "yes,yes,no,no")
1015 (set_attr "length" "2,2,4,4")
1016 (set (attr "type")
1017 (if_then_else (match_operand 1 "const_int_operand")
1018 (const_string "alu_imm")
1019 (const_string "alu_sreg")))]
0d66636f 1020)
ebcc79bc 1021
1022(define_insn "*compare_addsi2_op1"
bd5b4116 1023 [(set (reg:CC_C CC_REGNUM)
7c36fe71 1024 (compare:CC_C
eaddabc8 1025 (plus:SI (match_operand:SI 0 "s_register_operand" "l,l,r,r")
1026 (match_operand:SI 1 "arm_add_operand" "l,Pw,rI,L"))
7c36fe71 1027 (match_dup 1)))]
25f905c2 1028 "TARGET_32BIT"
ebcc79bc 1029 "@
1030 cmn%?\\t%0, %1
65f68e55 1031 cmp%?\\t%0, #%n1
eaddabc8 1032 cmn%?\\t%0, %1
1033 cmp%?\\t%0, #%n1"
596e5e8f 1034 [(set_attr "conds" "set")
65f68e55 1035 (set_attr "predicable" "yes")
eaddabc8 1036 (set_attr "arch" "t2,t2,*,*")
1037 (set_attr "predicable_short_it" "yes,yes,no,no")
1038 (set_attr "length" "2,2,4,4")
1039 (set (attr "type")
1040 (if_then_else (match_operand 1 "const_int_operand")
1041 (const_string "alu_imm")
1042 (const_string "alu_sreg")))]
7c36fe71 1043 )
ebcc79bc 1044
40155e19 1045(define_insn "addsi3_carryin"
7c36fe71 1046 [(set (match_operand:SI 0 "s_register_operand" "=l,r,r")
1047 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%l,r,r")
1048 (match_operand:SI 2 "arm_not_operand" "0,rI,K"))
40155e19 1049 (match_operand:SI 3 "arm_carry_operation" "")))]
25f905c2 1050 "TARGET_32BIT"
10e5ccd5 1051 "@
a0b3420a 1052 adc%?\\t%0, %1, %2
10e5ccd5 1053 adc%?\\t%0, %1, %2
1054 sbc%?\\t%0, %1, #%B2"
a7de272d 1055 [(set_attr "conds" "use")
7c36fe71 1056 (set_attr "predicable" "yes")
1057 (set_attr "arch" "t2,*,*")
1058 (set_attr "length" "4")
1b7da4ac 1059 (set_attr "predicable_short_it" "yes,no,no")
1060 (set_attr "type" "adc_reg,adc_reg,adc_imm")]
cffb2a26 1061)
ebcc79bc 1062
6cc8c27c 1063;; Canonicalization of the above when the immediate is zero.
40155e19 1064(define_insn "add0si3_carryin"
6cc8c27c 1065 [(set (match_operand:SI 0 "s_register_operand" "=r")
40155e19 1066 (plus:SI (match_operand:SI 2 "arm_carry_operation" "")
6cc8c27c 1067 (match_operand:SI 1 "arm_not_operand" "r")))]
1068 "TARGET_32BIT"
1069 "adc%?\\t%0, %1, #0"
1070 [(set_attr "conds" "use")
1071 (set_attr "predicable" "yes")
1072 (set_attr "length" "4")
1073 (set_attr "type" "adc_imm")]
1074)
1075
40155e19 1076(define_insn "*addsi3_carryin_alt2"
7c36fe71 1077 [(set (match_operand:SI 0 "s_register_operand" "=l,r,r")
40155e19 1078 (plus:SI (plus:SI (match_operand:SI 3 "arm_carry_operation" "")
7c36fe71 1079 (match_operand:SI 1 "s_register_operand" "%l,r,r"))
3f095d09 1080 (match_operand:SI 2 "arm_not_operand" "l,rI,K")))]
25f905c2 1081 "TARGET_32BIT"
10e5ccd5 1082 "@
a0b3420a 1083 adc%?\\t%0, %1, %2
10e5ccd5 1084 adc%?\\t%0, %1, %2
1085 sbc%?\\t%0, %1, #%B2"
a7de272d 1086 [(set_attr "conds" "use")
7c36fe71 1087 (set_attr "predicable" "yes")
1088 (set_attr "arch" "t2,*,*")
1089 (set_attr "length" "4")
1b7da4ac 1090 (set_attr "predicable_short_it" "yes,no,no")
1091 (set_attr "type" "adc_reg,adc_reg,adc_imm")]
0d66636f 1092)
ebcc79bc 1093
40155e19 1094(define_insn "*addsi3_carryin_shift"
1095 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
080c0b9a 1096 (plus:SI (plus:SI
1097 (match_operator:SI 2 "shift_operator"
40155e19 1098 [(match_operand:SI 3 "s_register_operand" "r,r")
1099 (match_operand:SI 4 "shift_amount_operand" "M,r")])
1100 (match_operand:SI 5 "arm_carry_operation" ""))
1101 (match_operand:SI 1 "s_register_operand" "r,r")))]
25f905c2 1102 "TARGET_32BIT"
080c0b9a 1103 "adc%?\\t%0, %1, %3%S2"
1104 [(set_attr "conds" "use")
40155e19 1105 (set_attr "arch" "32,a")
1106 (set_attr "shift" "3")
a7de272d 1107 (set_attr "predicable" "yes")
080c0b9a 1108 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
d82e788e 1109 (const_string "alu_shift_imm")
1110 (const_string "alu_shift_reg")))]
cffb2a26 1111)
ebcc79bc 1112
40155e19 1113(define_insn "*addsi3_carryin_clobercc"
922b6913 1114 [(set (match_operand:SI 0 "s_register_operand" "=r")
1115 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%r")
1116 (match_operand:SI 2 "arm_rhs_operand" "rI"))
40155e19 1117 (match_operand:SI 3 "arm_carry_operation" "")))
922b6913 1118 (clobber (reg:CC CC_REGNUM))]
1119 "TARGET_32BIT"
3ef90e77 1120 "adcs%?\\t%0, %1, %2"
1b7da4ac 1121 [(set_attr "conds" "set")
1122 (set_attr "type" "adcs_reg")]
922b6913 1123)
1124
f6c98a9a 1125(define_expand "subv<mode>4"
1126 [(match_operand:SIDI 0 "register_operand")
1127 (match_operand:SIDI 1 "register_operand")
1128 (match_operand:SIDI 2 "register_operand")
1129 (match_operand 3 "")]
1130 "TARGET_32BIT"
1131{
1132 emit_insn (gen_sub<mode>3_compare1 (operands[0], operands[1], operands[2]));
1133 arm_gen_unlikely_cbranch (NE, CC_Vmode, operands[3]);
1134
1135 DONE;
1136})
1137
1138(define_expand "usubv<mode>4"
1139 [(match_operand:SIDI 0 "register_operand")
1140 (match_operand:SIDI 1 "register_operand")
1141 (match_operand:SIDI 2 "register_operand")
1142 (match_operand 3 "")]
1143 "TARGET_32BIT"
1144{
1145 emit_insn (gen_sub<mode>3_compare1 (operands[0], operands[1], operands[2]));
1146 arm_gen_unlikely_cbranch (LTU, CCmode, operands[3]);
1147
1148 DONE;
1149})
1150
e62551fd 1151(define_insn "subdi3_compare1"
f6c98a9a 1152 [(set (reg:CC CC_REGNUM)
1153 (compare:CC
e62551fd 1154 (match_operand:DI 1 "s_register_operand" "r")
1155 (match_operand:DI 2 "s_register_operand" "r")))
1156 (set (match_operand:DI 0 "s_register_operand" "=&r")
f6c98a9a 1157 (minus:DI (match_dup 1) (match_dup 2)))]
1158 "TARGET_32BIT"
e62551fd 1159 "subs\\t%Q0, %Q1, %Q2;sbcs\\t%R0, %R1, %R2"
f6c98a9a 1160 [(set_attr "conds" "set")
1161 (set_attr "length" "8")
1162 (set_attr "type" "multiple")]
1163)
1164
1165(define_insn "subsi3_compare1"
1166 [(set (reg:CC CC_REGNUM)
1167 (compare:CC
1168 (match_operand:SI 1 "register_operand" "r")
1169 (match_operand:SI 2 "register_operand" "r")))
1170 (set (match_operand:SI 0 "register_operand" "=r")
1171 (minus:SI (match_dup 1) (match_dup 2)))]
1172 "TARGET_32BIT"
1173 "subs%?\\t%0, %1, %2"
1174 [(set_attr "conds" "set")
1175 (set_attr "type" "alus_sreg")]
1176)
1177
7724f74b 1178(define_insn "subsi3_carryin"
d5bf2b53 1179 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1180 (minus:SI (minus:SI (match_operand:SI 1 "reg_or_int_operand" "r,I,Pz")
1181 (match_operand:SI 2 "s_register_operand" "r,r,r"))
3b0dcaf2 1182 (match_operand:SI 3 "arm_borrow_operation" "")))]
9154bd82 1183 "TARGET_32BIT"
1184 "@
1185 sbc%?\\t%0, %1, %2
d5bf2b53 1186 rsc%?\\t%0, %2, %1
1187 sbc%?\\t%0, %2, %2, lsl #1"
9154bd82 1188 [(set_attr "conds" "use")
d5bf2b53 1189 (set_attr "arch" "*,a,t2")
7c36fe71 1190 (set_attr "predicable" "yes")
d5bf2b53 1191 (set_attr "type" "adc_reg,adc_imm,alu_shift_imm")]
9154bd82 1192)
1193
060a96ad 1194(define_insn "cmpsi3_carryin_<CC_EXTEND>out"
1195 [(set (reg:<CC_EXTEND> CC_REGNUM)
1196 (compare:<CC_EXTEND>
1197 (SE:DI (match_operand:SI 1 "s_register_operand" "0,r"))
1198 (plus:DI (match_operand:DI 3 "arm_borrow_operation" "")
1199 (SE:DI (match_operand:SI 2 "s_register_operand" "l,r")))))
1200 (clobber (match_scratch:SI 0 "=l,r"))]
1201 "TARGET_32BIT"
1202 "sbcs\\t%0, %1, %2"
1203 [(set_attr "conds" "set")
1204 (set_attr "arch" "t2,*")
1205 (set_attr "length" "2,4")
1206 (set_attr "type" "adc_reg")]
1207)
1208
1209;; Similar to the above, but handling a constant which has a different
1210;; canonicalization.
1211(define_insn "cmpsi3_imm_carryin_<CC_EXTEND>out"
1212 [(set (reg:<CC_EXTEND> CC_REGNUM)
1213 (compare:<CC_EXTEND>
1214 (SE:DI (match_operand:SI 1 "s_register_operand" "r,r"))
1215 (plus:DI (match_operand:DI 3 "arm_borrow_operation" "")
1216 (match_operand:DI 2 "arm_adcimm_operand" "I,K"))))
1217 (clobber (match_scratch:SI 0 "=l,r"))]
1218 "TARGET_32BIT"
1219 "@
1220 sbcs\\t%0, %1, %2
1221 adcs\\t%0, %1, #%B2"
1222 [(set_attr "conds" "set")
1223 (set_attr "type" "adc_imm")]
1224)
1225
1226;; Further canonicalization when the constant is zero.
1227(define_insn "cmpsi3_0_carryin_<CC_EXTEND>out"
1228 [(set (reg:<CC_EXTEND> CC_REGNUM)
1229 (compare:<CC_EXTEND>
1230 (SE:DI (match_operand:SI 1 "s_register_operand" "r,r"))
1231 (match_operand:DI 2 "arm_borrow_operation" "")))
1232 (clobber (match_scratch:SI 0 "=l,r"))]
1233 "TARGET_32BIT"
1234 "sbcs\\t%0, %1, #0"
1235 [(set_attr "conds" "set")
1236 (set_attr "type" "adc_imm")]
1237)
1238
9154bd82 1239(define_insn "*subsi3_carryin_const"
1240 [(set (match_operand:SI 0 "s_register_operand" "=r")
3b0dcaf2 1241 (minus:SI (plus:SI
1242 (match_operand:SI 1 "s_register_operand" "r")
1243 (match_operand:SI 2 "arm_neg_immediate_operand" "L"))
1244 (match_operand:SI 3 "arm_borrow_operation" "")))]
9154bd82 1245 "TARGET_32BIT"
16a3cf9c 1246 "sbc\\t%0, %1, #%n2"
1247 [(set_attr "conds" "use")
1248 (set_attr "type" "adc_imm")]
1249)
1250
1251(define_insn "*subsi3_carryin_const0"
1252 [(set (match_operand:SI 0 "s_register_operand" "=r")
3b0dcaf2 1253 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
1254 (match_operand:SI 2 "arm_borrow_operation" "")))]
16a3cf9c 1255 "TARGET_32BIT"
1256 "sbc\\t%0, %1, #0"
1b7da4ac 1257 [(set_attr "conds" "use")
1258 (set_attr "type" "adc_imm")]
9154bd82 1259)
1260
9154bd82 1261(define_insn "*subsi3_carryin_shift"
1262 [(set (match_operand:SI 0 "s_register_operand" "=r")
1263 (minus:SI (minus:SI
3b0dcaf2 1264 (match_operand:SI 1 "s_register_operand" "r")
1265 (match_operator:SI 2 "shift_operator"
1266 [(match_operand:SI 3 "s_register_operand" "r")
1267 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
1268 (match_operand:SI 5 "arm_borrow_operation" "")))]
9154bd82 1269 "TARGET_32BIT"
1270 "sbc%?\\t%0, %1, %3%S2"
1271 [(set_attr "conds" "use")
1272 (set_attr "predicable" "yes")
1273 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
3b0dcaf2 1274 (const_string "alu_shift_imm")
1275 (const_string "alu_shift_reg")))]
9154bd82 1276)
1277
263f9e4d 1278(define_insn "*subsi3_carryin_shift_alt"
1279 [(set (match_operand:SI 0 "s_register_operand" "=r")
1280 (minus:SI (minus:SI
1281 (match_operand:SI 1 "s_register_operand" "r")
1282 (match_operand:SI 5 "arm_borrow_operation" ""))
1283 (match_operator:SI 2 "shift_operator"
1284 [(match_operand:SI 3 "s_register_operand" "r")
1285 (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
1286 "TARGET_32BIT"
1287 "sbc%?\\t%0, %1, %3%S2"
1288 [(set_attr "conds" "use")
1289 (set_attr "predicable" "yes")
1290 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
1291 (const_string "alu_shift_imm")
1292 (const_string "alu_shift_reg")))]
1293)
1294
9154bd82 1295(define_insn "*rsbsi3_carryin_shift"
1296 [(set (match_operand:SI 0 "s_register_operand" "=r")
1297 (minus:SI (minus:SI
3b0dcaf2 1298 (match_operator:SI 2 "shift_operator"
1299 [(match_operand:SI 3 "s_register_operand" "r")
1300 (match_operand:SI 4 "reg_or_int_operand" "rM")])
9154bd82 1301 (match_operand:SI 1 "s_register_operand" "r"))
3b0dcaf2 1302 (match_operand:SI 5 "arm_borrow_operation" "")))]
9154bd82 1303 "TARGET_ARM"
1304 "rsc%?\\t%0, %1, %3%S2"
1305 [(set_attr "conds" "use")
1306 (set_attr "predicable" "yes")
1307 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
d82e788e 1308 (const_string "alu_shift_imm")
1309 (const_string "alu_shift_reg")))]
9154bd82 1310)
1311
263f9e4d 1312(define_insn "*rsbsi3_carryin_shift_alt"
1313 [(set (match_operand:SI 0 "s_register_operand" "=r")
1314 (minus:SI (minus:SI
1315 (match_operator:SI 2 "shift_operator"
1316 [(match_operand:SI 3 "s_register_operand" "r")
1317 (match_operand:SI 4 "reg_or_int_operand" "rM")])
1318 (match_operand:SI 5 "arm_borrow_operation" ""))
1319 (match_operand:SI 1 "s_register_operand" "r")))]
1320 "TARGET_ARM"
1321 "rsc%?\\t%0, %1, %3%S2"
1322 [(set_attr "conds" "use")
1323 (set_attr "predicable" "yes")
1324 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
1325 (const_string "alu_shift_imm")
1326 (const_string "alu_shift_reg")))]
1327)
1328
d795fb69 1329; transform ((x << y) - 1) to ~(~(x-1) << y) Where X is a constant.
1330(define_split
1331 [(set (match_operand:SI 0 "s_register_operand" "")
1332 (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
1333 (match_operand:SI 2 "s_register_operand" ""))
1334 (const_int -1)))
1335 (clobber (match_operand:SI 3 "s_register_operand" ""))]
25f905c2 1336 "TARGET_32BIT"
d795fb69 1337 [(set (match_dup 3) (match_dup 1))
1338 (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
1339 "
1340 operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
1341")
1342
604f3a0a 1343(define_expand "addsf3"
3934ae0e 1344 [(set (match_operand:SF 0 "s_register_operand")
1345 (plus:SF (match_operand:SF 1 "s_register_operand")
1346 (match_operand:SF 2 "s_register_operand")))]
25f905c2 1347 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1348 "
604f3a0a 1349")
1350
604f3a0a 1351(define_expand "adddf3"
3934ae0e 1352 [(set (match_operand:DF 0 "s_register_operand")
1353 (plus:DF (match_operand:DF 1 "s_register_operand")
1354 (match_operand:DF 2 "s_register_operand")))]
a50d7267 1355 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 1356 "
604f3a0a 1357")
1358
cffb2a26 1359(define_expand "subdi3"
1360 [(parallel
3934ae0e 1361 [(set (match_operand:DI 0 "s_register_operand")
7724f74b 1362 (minus:DI (match_operand:DI 1 "reg_or_int_operand")
e62551fd 1363 (match_operand:DI 2 "s_register_operand")))
bd5b4116 1364 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 1365 "TARGET_EITHER"
1366 "
7724f74b 1367 if (TARGET_THUMB1)
1368 {
1369 if (!REG_P (operands[1]))
1370 operands[1] = force_reg (DImode, operands[1]);
1371 }
1372 else
1373 {
1374 rtx lo_result, hi_result, lo_dest, hi_dest;
1375 rtx lo_op1, hi_op1, lo_op2, hi_op2;
1376 rtx condition;
1377
1378 /* Since operands[1] may be an integer, pass it second, so that
1379 any necessary simplifications will be done on the decomposed
1380 constant. */
1381 arm_decompose_di_binop (operands[2], operands[1], &lo_op2, &hi_op2,
1382 &lo_op1, &hi_op1);
1383 lo_result = lo_dest = gen_lowpart (SImode, operands[0]);
1384 hi_result = hi_dest = gen_highpart (SImode, operands[0]);
1385
1386 if (!arm_rhs_operand (lo_op1, SImode))
1387 lo_op1 = force_reg (SImode, lo_op1);
1388
1389 if ((TARGET_THUMB2 && ! s_register_operand (hi_op1, SImode))
1390 || !arm_rhs_operand (hi_op1, SImode))
1391 hi_op1 = force_reg (SImode, hi_op1);
1392
1393 rtx cc_reg;
1394 if (lo_op1 == const0_rtx)
1395 {
1396 cc_reg = gen_rtx_REG (CC_RSBmode, CC_REGNUM);
1397 emit_insn (gen_negsi2_0compare (lo_dest, lo_op2));
1398 }
1399 else if (CONST_INT_P (lo_op1))
1400 {
1401 cc_reg = gen_rtx_REG (CC_RSBmode, CC_REGNUM);
1402 emit_insn (gen_rsb_imm_compare (lo_dest, lo_op1, lo_op2,
1403 GEN_INT (~UINTVAL (lo_op1))));
1404 }
1405 else
1406 {
1407 cc_reg = gen_rtx_REG (CCmode, CC_REGNUM);
1408 emit_insn (gen_subsi3_compare (lo_dest, lo_op1, lo_op2));
1409 }
1410
1411 condition = gen_rtx_LTU (SImode, cc_reg, const0_rtx);
1412
1413 if (hi_op1 == const0_rtx)
1414 emit_insn (gen_negsi2_carryin (hi_dest, hi_op2, condition));
1415 else
1416 emit_insn (gen_subsi3_carryin (hi_dest, hi_op1, hi_op2, condition));
1417
1418 if (lo_result != lo_dest)
1419 emit_move_insn (lo_result, lo_dest);
1420
1421 if (hi_result != hi_dest)
1422 emit_move_insn (hi_result, hi_dest);
1423
1424 DONE;
1425 }
1426 "
1427)
cffb2a26 1428
87b22bf7 1429(define_expand "subsi3"
3934ae0e 1430 [(set (match_operand:SI 0 "s_register_operand")
1431 (minus:SI (match_operand:SI 1 "reg_or_int_operand")
1432 (match_operand:SI 2 "s_register_operand")))]
cffb2a26 1433 "TARGET_EITHER"
87b22bf7 1434 "
0438d37f 1435 if (CONST_INT_P (operands[1]))
87b22bf7 1436 {
25f905c2 1437 if (TARGET_32BIT)
cffb2a26 1438 {
17202aa5 1439 if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[1]), MINUS))
1440 operands[1] = force_reg (SImode, operands[1]);
1441 else
1442 {
1443 arm_split_constant (MINUS, SImode, NULL_RTX,
1444 INTVAL (operands[1]), operands[0],
1445 operands[2],
1446 optimize && can_create_pseudo_p ());
1447 DONE;
1448 }
cffb2a26 1449 }
25f905c2 1450 else /* TARGET_THUMB1 */
cffb2a26 1451 operands[1] = force_reg (SImode, operands[1]);
87b22bf7 1452 }
cffb2a26 1453 "
1454)
87b22bf7 1455
25f905c2 1456; ??? Check Thumb-2 split length
a0f94409 1457(define_insn_and_split "*arm_subsi3_insn"
3a44c5a9 1458 [(set (match_operand:SI 0 "s_register_operand" "=l,l ,l ,l ,r,r,r,rk,r")
1459 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "l ,0 ,l ,Pz,I,r,r,k ,?n")
1460 (match_operand:SI 2 "reg_or_int_operand" "l ,Py,Pd,l ,r,I,r,r ,r")))]
25f905c2 1461 "TARGET_32BIT"
e2348bcb 1462 "@
7c36fe71 1463 sub%?\\t%0, %1, %2
1464 sub%?\\t%0, %2
1465 sub%?\\t%0, %1, %2
1466 rsb%?\\t%0, %2, %1
87b22bf7 1467 rsb%?\\t%0, %2, %1
aaa37ad6 1468 sub%?\\t%0, %1, %2
080c0b9a 1469 sub%?\\t%0, %1, %2
65f68e55 1470 sub%?\\t%0, %1, %2
87b22bf7 1471 #"
0438d37f 1472 "&& (CONST_INT_P (operands[1])
91a5e339 1473 && !const_ok_for_arm (INTVAL (operands[1])))"
87b22bf7 1474 [(clobber (const_int 0))]
1475 "
96f57e36 1476 arm_split_constant (MINUS, SImode, curr_insn,
1477 INTVAL (operands[1]), operands[0], operands[2], 0);
87b22bf7 1478 DONE;
cffb2a26 1479 "
7c36fe71 1480 [(set_attr "length" "4,4,4,4,4,4,4,4,16")
1481 (set_attr "arch" "t2,t2,t2,t2,*,*,*,*,*")
65f68e55 1482 (set_attr "predicable" "yes")
7c36fe71 1483 (set_attr "predicable_short_it" "yes,yes,yes,yes,no,no,no,no,no")
112eda6f 1484 (set_attr "type" "alu_sreg,alu_sreg,alu_sreg,alu_sreg,alu_imm,alu_imm,alu_sreg,alu_sreg,multiple")]
a0f94409 1485)
1486
1487(define_peephole2
1488 [(match_scratch:SI 3 "r")
372575c7 1489 (set (match_operand:SI 0 "arm_general_register_operand" "")
a0f94409 1490 (minus:SI (match_operand:SI 1 "const_int_operand" "")
372575c7 1491 (match_operand:SI 2 "arm_general_register_operand" "")))]
25f905c2 1492 "TARGET_32BIT
a0f94409 1493 && !const_ok_for_arm (INTVAL (operands[1]))
1494 && const_ok_for_arm (~INTVAL (operands[1]))"
1495 [(set (match_dup 3) (match_dup 1))
1496 (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1497 ""
cffb2a26 1498)
b11cae9e 1499
62e39b06 1500(define_insn "subsi3_compare0"
bd5b4116 1501 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1502 (compare:CC_NOOV
65f68e55 1503 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,r,I")
1504 (match_operand:SI 2 "arm_rhs_operand" "I,r,r"))
215b30b3 1505 (const_int 0)))
65f68e55 1506 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9c08d1fa 1507 (minus:SI (match_dup 1) (match_dup 2)))]
25f905c2 1508 "TARGET_32BIT"
e2348bcb 1509 "@
3ef90e77 1510 subs%?\\t%0, %1, %2
1511 subs%?\\t%0, %1, %2
1512 rsbs%?\\t%0, %2, %1"
65f68e55 1513 [(set_attr "conds" "set")
112eda6f 1514 (set_attr "type" "alus_imm,alus_sreg,alus_sreg")]
cffb2a26 1515)
9c08d1fa 1516
190efb17 1517(define_insn "subsi3_compare"
080c0b9a 1518 [(set (reg:CC CC_REGNUM)
65f68e55 1519 (compare:CC (match_operand:SI 1 "arm_rhs_operand" "r,r,I")
1520 (match_operand:SI 2 "arm_rhs_operand" "I,r,r")))
1521 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2df9477b 1522 (minus:SI (match_dup 1) (match_dup 2)))]
1523 "TARGET_32BIT"
1524 "@
3ef90e77 1525 subs%?\\t%0, %1, %2
1526 subs%?\\t%0, %1, %2
1527 rsbs%?\\t%0, %2, %1"
65f68e55 1528 [(set_attr "conds" "set")
7724f74b 1529 (set_attr "type" "alus_imm,alus_sreg,alus_imm")]
1530)
1531
1532;; To keep the comparison in canonical form we express it as (~reg cmp ~0)
1533;; rather than (0 cmp reg). This gives the same results for unsigned
1534;; and equality compares which is what we mostly need here.
1535(define_insn "rsb_imm_compare"
1536 [(set (reg:CC_RSB CC_REGNUM)
1537 (compare:CC_RSB (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1538 (match_operand 3 "const_int_operand" "")))
1539 (set (match_operand:SI 0 "s_register_operand" "=r")
1540 (minus:SI (match_operand 1 "arm_immediate_operand" "I")
1541 (match_dup 2)))]
1542 "TARGET_32BIT && ~UINTVAL (operands[1]) == UINTVAL (operands[3])"
1543 "rsbs\\t%0, %2, %1"
1544 [(set_attr "conds" "set")
1545 (set_attr "type" "alus_imm")]
2df9477b 1546)
1547
efaa33f9 1548;; Similarly, but the result is unused.
1549(define_insn "rsb_imm_compare_scratch"
1550 [(set (reg:CC_RSB CC_REGNUM)
1551 (compare:CC_RSB (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1552 (match_operand 1 "arm_not_immediate_operand" "K")))
1553 (clobber (match_scratch:SI 0 "=r"))]
1554 "TARGET_32BIT"
1555 "rsbs\\t%0, %2, #%B1"
1556 [(set_attr "conds" "set")
1557 (set_attr "type" "alus_imm")]
1558)
1559
1560;; Compare the sum of a value plus a carry against a constant. Uses
1561;; RSC, so the result is swapped. Only available on Arm
1562(define_insn "rscsi3_<CC_EXTEND>out_scratch"
1563 [(set (reg:CC_SWP CC_REGNUM)
1564 (compare:CC_SWP
1565 (plus:DI (SE:DI (match_operand:SI 2 "s_register_operand" "r"))
1566 (match_operand:DI 3 "arm_borrow_operation" ""))
1567 (match_operand 1 "arm_immediate_operand" "I")))
1568 (clobber (match_scratch:SI 0 "=r"))]
1569 "TARGET_ARM"
1570 "rscs\\t%0, %2, %1"
1571 [(set_attr "conds" "set")
1572 (set_attr "type" "alus_imm")]
1573)
1574
604f3a0a 1575(define_expand "subsf3"
3934ae0e 1576 [(set (match_operand:SF 0 "s_register_operand")
1577 (minus:SF (match_operand:SF 1 "s_register_operand")
1578 (match_operand:SF 2 "s_register_operand")))]
25f905c2 1579 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1580 "
604f3a0a 1581")
1582
604f3a0a 1583(define_expand "subdf3"
3934ae0e 1584 [(set (match_operand:DF 0 "s_register_operand")
1585 (minus:DF (match_operand:DF 1 "s_register_operand")
1586 (match_operand:DF 2 "s_register_operand")))]
a50d7267 1587 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 1588 "
604f3a0a 1589")
1590
b11cae9e 1591\f
1592;; Multiplication insns
1593
4422d91f 1594(define_expand "mulhi3"
3934ae0e 1595 [(set (match_operand:HI 0 "s_register_operand")
1596 (mult:HI (match_operand:HI 1 "s_register_operand")
1597 (match_operand:HI 2 "s_register_operand")))]
4422d91f 1598 "TARGET_DSP_MULTIPLY"
1599 "
1600 {
1601 rtx result = gen_reg_rtx (SImode);
1602 emit_insn (gen_mulhisi3 (result, operands[1], operands[2]));
1603 emit_move_insn (operands[0], gen_lowpart (HImode, result));
1604 DONE;
1605 }"
1606)
1607
cffb2a26 1608(define_expand "mulsi3"
3934ae0e 1609 [(set (match_operand:SI 0 "s_register_operand")
1610 (mult:SI (match_operand:SI 2 "s_register_operand")
1611 (match_operand:SI 1 "s_register_operand")))]
cffb2a26 1612 "TARGET_EITHER"
1613 ""
1614)
1615
40ac65c8 1616;; Use `&' and then `0' to prevent operands 0 and 2 being the same
1617(define_insn "*mul"
1618 [(set (match_operand:SI 0 "s_register_operand" "=l,r,&r,&r")
1619 (mult:SI (match_operand:SI 2 "s_register_operand" "l,r,r,r")
1620 (match_operand:SI 1 "s_register_operand" "%0,r,0,r")))]
1621 "TARGET_32BIT"
f7fbdd4a 1622 "mul%?\\t%0, %2, %1"
9da0ec36 1623 [(set_attr "type" "mul")
40ac65c8 1624 (set_attr "predicable" "yes")
1625 (set_attr "arch" "t2,v6,nov6,nov6")
1626 (set_attr "length" "4")
1627 (set_attr "predicable_short_it" "yes,no,*,*")]
cffb2a26 1628)
1629
40ac65c8 1630;; MLA and MLS instruction. Use operand 1 for the accumulator to prefer
1631;; reusing the same register.
1632
1633(define_insn "*mla"
1634 [(set (match_operand:SI 0 "s_register_operand" "=r,&r,&r,&r")
1635 (plus:SI
1636 (mult:SI (match_operand:SI 3 "s_register_operand" "r,r,r,r")
1637 (match_operand:SI 2 "s_register_operand" "%r,r,0,r"))
1638 (match_operand:SI 1 "s_register_operand" "r,0,r,r")))]
1639 "TARGET_32BIT"
1640 "mla%?\\t%0, %3, %2, %1"
1641 [(set_attr "type" "mla")
d952d547 1642 (set_attr "predicable" "yes")
40ac65c8 1643 (set_attr "arch" "v6,nov6,nov6,nov6")]
1644)
1645
1646(define_insn "*mls"
1647 [(set (match_operand:SI 0 "s_register_operand" "=r")
1648 (minus:SI
1649 (match_operand:SI 1 "s_register_operand" "r")
1650 (mult:SI (match_operand:SI 3 "s_register_operand" "r")
1651 (match_operand:SI 2 "s_register_operand" "r"))))]
1652 "TARGET_32BIT && arm_arch_thumb2"
1653 "mls%?\\t%0, %3, %2, %1"
1654 [(set_attr "type" "mla")
1655 (set_attr "predicable" "yes")]
58d7d654 1656)
1657
f7fbdd4a 1658(define_insn "*mulsi3_compare0"
bd5b4116 1659 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1660 (compare:CC_NOOV (mult:SI
1661 (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1662 (match_operand:SI 1 "s_register_operand" "%0,r"))
9c08d1fa 1663 (const_int 0)))
1664 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1665 (mult:SI (match_dup 2) (match_dup 1)))]
58d7d654 1666 "TARGET_ARM && !arm_arch6"
3ef90e77 1667 "muls%?\\t%0, %2, %1"
58d7d654 1668 [(set_attr "conds" "set")
9da0ec36 1669 (set_attr "type" "muls")]
58d7d654 1670)
1671
1672(define_insn "*mulsi3_compare0_v6"
1673 [(set (reg:CC_NOOV CC_REGNUM)
1674 (compare:CC_NOOV (mult:SI
1675 (match_operand:SI 2 "s_register_operand" "r")
1676 (match_operand:SI 1 "s_register_operand" "r"))
1677 (const_int 0)))
1678 (set (match_operand:SI 0 "s_register_operand" "=r")
1679 (mult:SI (match_dup 2) (match_dup 1)))]
1680 "TARGET_ARM && arm_arch6 && optimize_size"
3ef90e77 1681 "muls%?\\t%0, %2, %1"
cffb2a26 1682 [(set_attr "conds" "set")
9da0ec36 1683 (set_attr "type" "muls")]
cffb2a26 1684)
9c08d1fa 1685
f7fbdd4a 1686(define_insn "*mulsi_compare0_scratch"
bd5b4116 1687 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1688 (compare:CC_NOOV (mult:SI
1689 (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1690 (match_operand:SI 1 "s_register_operand" "%0,r"))
9c08d1fa 1691 (const_int 0)))
1692 (clobber (match_scratch:SI 0 "=&r,&r"))]
58d7d654 1693 "TARGET_ARM && !arm_arch6"
3ef90e77 1694 "muls%?\\t%0, %2, %1"
58d7d654 1695 [(set_attr "conds" "set")
9da0ec36 1696 (set_attr "type" "muls")]
58d7d654 1697)
1698
1699(define_insn "*mulsi_compare0_scratch_v6"
1700 [(set (reg:CC_NOOV CC_REGNUM)
1701 (compare:CC_NOOV (mult:SI
1702 (match_operand:SI 2 "s_register_operand" "r")
1703 (match_operand:SI 1 "s_register_operand" "r"))
1704 (const_int 0)))
1705 (clobber (match_scratch:SI 0 "=r"))]
1706 "TARGET_ARM && arm_arch6 && optimize_size"
3ef90e77 1707 "muls%?\\t%0, %2, %1"
cffb2a26 1708 [(set_attr "conds" "set")
9da0ec36 1709 (set_attr "type" "muls")]
cffb2a26 1710)
9c08d1fa 1711
f7fbdd4a 1712(define_insn "*mulsi3addsi_compare0"
bd5b4116 1713 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1714 (compare:CC_NOOV
1715 (plus:SI (mult:SI
1716 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1717 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1718 (match_operand:SI 3 "s_register_operand" "r,r,0,0"))
215b30b3 1719 (const_int 0)))
9c08d1fa 1720 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1721 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1722 (match_dup 3)))]
58d7d654 1723 "TARGET_ARM && arm_arch6"
3ef90e77 1724 "mlas%?\\t%0, %2, %1, %3"
58d7d654 1725 [(set_attr "conds" "set")
9da0ec36 1726 (set_attr "type" "mlas")]
58d7d654 1727)
1728
1729(define_insn "*mulsi3addsi_compare0_v6"
1730 [(set (reg:CC_NOOV CC_REGNUM)
1731 (compare:CC_NOOV
1732 (plus:SI (mult:SI
1733 (match_operand:SI 2 "s_register_operand" "r")
1734 (match_operand:SI 1 "s_register_operand" "r"))
1735 (match_operand:SI 3 "s_register_operand" "r"))
1736 (const_int 0)))
1737 (set (match_operand:SI 0 "s_register_operand" "=r")
1738 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1739 (match_dup 3)))]
1740 "TARGET_ARM && arm_arch6 && optimize_size"
3ef90e77 1741 "mlas%?\\t%0, %2, %1, %3"
0d66636f 1742 [(set_attr "conds" "set")
9da0ec36 1743 (set_attr "type" "mlas")]
0d66636f 1744)
9c08d1fa 1745
f7fbdd4a 1746(define_insn "*mulsi3addsi_compare0_scratch"
bd5b4116 1747 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1748 (compare:CC_NOOV
1749 (plus:SI (mult:SI
1750 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1751 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
215b30b3 1752 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1753 (const_int 0)))
9c08d1fa 1754 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
58d7d654 1755 "TARGET_ARM && !arm_arch6"
3ef90e77 1756 "mlas%?\\t%0, %2, %1, %3"
58d7d654 1757 [(set_attr "conds" "set")
9da0ec36 1758 (set_attr "type" "mlas")]
58d7d654 1759)
1760
1761(define_insn "*mulsi3addsi_compare0_scratch_v6"
1762 [(set (reg:CC_NOOV CC_REGNUM)
1763 (compare:CC_NOOV
1764 (plus:SI (mult:SI
1765 (match_operand:SI 2 "s_register_operand" "r")
1766 (match_operand:SI 1 "s_register_operand" "r"))
1767 (match_operand:SI 3 "s_register_operand" "r"))
1768 (const_int 0)))
1769 (clobber (match_scratch:SI 0 "=r"))]
1770 "TARGET_ARM && arm_arch6 && optimize_size"
3ef90e77 1771 "mlas%?\\t%0, %2, %1, %3"
cffb2a26 1772 [(set_attr "conds" "set")
9da0ec36 1773 (set_attr "type" "mlas")]
cffb2a26 1774)
f7fbdd4a 1775
957788b0 1776;; 32x32->64 widening multiply.
fa761b10 1777;; The only difference between the v3-5 and v6+ versions is the requirement
1778;; that the output does not overlap with either input.
957788b0 1779
fa761b10 1780(define_expand "<Us>mulsidi3"
3934ae0e 1781 [(set (match_operand:DI 0 "s_register_operand")
957788b0 1782 (mult:DI
fa761b10 1783 (SE:DI (match_operand:SI 1 "s_register_operand"))
1784 (SE:DI (match_operand:SI 2 "s_register_operand"))))]
1930b04c 1785 "TARGET_32BIT"
fa761b10 1786 {
1787 emit_insn (gen_<US>mull (gen_lowpart (SImode, operands[0]),
1788 gen_highpart (SImode, operands[0]),
1789 operands[1], operands[2]));
1790 DONE;
1791 }
0d66636f 1792)
f7fbdd4a 1793
fa761b10 1794(define_insn "<US>mull"
1795 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
1796 (mult:SI
1797 (match_operand:SI 2 "s_register_operand" "%r,r")
1798 (match_operand:SI 3 "s_register_operand" "r,r")))
1799 (set (match_operand:SI 1 "s_register_operand" "=r,&r")
1800 (truncate:SI
1801 (lshiftrt:DI
1802 (mult:DI (SE:DI (match_dup 2)) (SE:DI (match_dup 3)))
1803 (const_int 32))))]
1930b04c 1804 "TARGET_32BIT"
fa761b10 1805 "<US>mull%?\\t%0, %1, %2, %3"
9da0ec36 1806 [(set_attr "type" "umull")
fa761b10 1807 (set_attr "predicable" "yes")
1808 (set_attr "arch" "v6,nov6")]
0d66636f 1809)
b11cae9e 1810
fa761b10 1811(define_expand "<Us>maddsidi4"
3934ae0e 1812 [(set (match_operand:DI 0 "s_register_operand")
5cdca009 1813 (plus:DI
1814 (mult:DI
fa761b10 1815 (SE:DI (match_operand:SI 1 "s_register_operand"))
1816 (SE:DI (match_operand:SI 2 "s_register_operand")))
3934ae0e 1817 (match_operand:DI 3 "s_register_operand")))]
1930b04c 1818 "TARGET_32BIT"
fa761b10 1819 {
1820 emit_insn (gen_<US>mlal (gen_lowpart (SImode, operands[0]),
1821 gen_lowpart (SImode, operands[3]),
1822 gen_highpart (SImode, operands[0]),
1823 gen_highpart (SImode, operands[3]),
1824 operands[1], operands[2]));
1825 DONE;
1826 }
58d7d654 1827)
1828
fa761b10 1829(define_insn "<US>mlal"
1830 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
1831 (plus:SI
1832 (mult:SI
49833aa2 1833 (match_operand:SI 4 "s_register_operand" "%r,r")
1834 (match_operand:SI 5 "s_register_operand" "r,r"))
fa761b10 1835 (match_operand:SI 1 "s_register_operand" "0,0")))
1836 (set (match_operand:SI 2 "s_register_operand" "=r,&r")
1837 (plus:SI
1838 (truncate:SI
1839 (lshiftrt:DI
1840 (plus:DI
1841 (mult:DI (SE:DI (match_dup 4)) (SE:DI (match_dup 5)))
1842 (zero_extend:DI (match_dup 1)))
1843 (const_int 32)))
1844 (match_operand:SI 3 "s_register_operand" "2,2")))]
1845 "TARGET_32BIT"
1846 "<US>mlal%?\\t%0, %2, %4, %5"
9da0ec36 1847 [(set_attr "type" "umlal")
fa761b10 1848 (set_attr "predicable" "yes")
1849 (set_attr "arch" "v6,nov6")]
0d66636f 1850)
82b85d08 1851
662cc42a 1852(define_expand "<US>mulsi3_highpart"
957788b0 1853 [(parallel
3934ae0e 1854 [(set (match_operand:SI 0 "s_register_operand")
957788b0 1855 (truncate:SI
1856 (lshiftrt:DI
1857 (mult:DI
662cc42a 1858 (SE:DI (match_operand:SI 1 "s_register_operand"))
1859 (SE:DI (match_operand:SI 2 "s_register_operand")))
957788b0 1860 (const_int 32))))
1861 (clobber (match_scratch:SI 3 ""))])]
1930b04c 1862 "TARGET_32BIT"
957788b0 1863 ""
1864)
1865
662cc42a 1866(define_insn "*<US>mull_high"
1867 [(set (match_operand:SI 0 "s_register_operand" "=r,&r,&r")
f082f1c4 1868 (truncate:SI
1869 (lshiftrt:DI
215b30b3 1870 (mult:DI
662cc42a 1871 (SE:DI (match_operand:SI 1 "s_register_operand" "%r,0,r"))
1872 (SE:DI (match_operand:SI 2 "s_register_operand" "r,r,r")))
f082f1c4 1873 (const_int 32))))
662cc42a 1874 (clobber (match_scratch:SI 3 "=r,&r,&r"))]
1930b04c 1875 "TARGET_32BIT"
662cc42a 1876 "<US>mull%?\\t%3, %0, %2, %1"
9da0ec36 1877 [(set_attr "type" "umull")
662cc42a 1878 (set_attr "predicable" "yes")
1879 (set_attr "arch" "v6,nov6,nov6")]
cffb2a26 1880)
f082f1c4 1881
331beb1a 1882(define_insn "mulhisi3"
1883 [(set (match_operand:SI 0 "s_register_operand" "=r")
1884 (mult:SI (sign_extend:SI
1885 (match_operand:HI 1 "s_register_operand" "%r"))
1886 (sign_extend:SI
1887 (match_operand:HI 2 "s_register_operand" "r"))))]
25f905c2 1888 "TARGET_DSP_MULTIPLY"
61a2d04c 1889 "smulbb%?\\t%0, %1, %2"
9da0ec36 1890 [(set_attr "type" "smulxy")
fec538d9 1891 (set_attr "predicable" "yes")]
1892)
1893
1894(define_insn "*mulhisi3tb"
1895 [(set (match_operand:SI 0 "s_register_operand" "=r")
1896 (mult:SI (ashiftrt:SI
1897 (match_operand:SI 1 "s_register_operand" "r")
1898 (const_int 16))
1899 (sign_extend:SI
1900 (match_operand:HI 2 "s_register_operand" "r"))))]
25f905c2 1901 "TARGET_DSP_MULTIPLY"
fec538d9 1902 "smultb%?\\t%0, %1, %2"
9da0ec36 1903 [(set_attr "type" "smulxy")
8bdfd6ed 1904 (set_attr "predicable" "yes")]
fec538d9 1905)
1906
1907(define_insn "*mulhisi3bt"
1908 [(set (match_operand:SI 0 "s_register_operand" "=r")
1909 (mult:SI (sign_extend:SI
1910 (match_operand:HI 1 "s_register_operand" "r"))
1911 (ashiftrt:SI
1912 (match_operand:SI 2 "s_register_operand" "r")
1913 (const_int 16))))]
25f905c2 1914 "TARGET_DSP_MULTIPLY"
fec538d9 1915 "smulbt%?\\t%0, %1, %2"
9da0ec36 1916 [(set_attr "type" "smulxy")
8bdfd6ed 1917 (set_attr "predicable" "yes")]
fec538d9 1918)
1919
1920(define_insn "*mulhisi3tt"
1921 [(set (match_operand:SI 0 "s_register_operand" "=r")
1922 (mult:SI (ashiftrt:SI
1923 (match_operand:SI 1 "s_register_operand" "r")
1924 (const_int 16))
1925 (ashiftrt:SI
1926 (match_operand:SI 2 "s_register_operand" "r")
1927 (const_int 16))))]
25f905c2 1928 "TARGET_DSP_MULTIPLY"
fec538d9 1929 "smultt%?\\t%0, %1, %2"
9da0ec36 1930 [(set_attr "type" "smulxy")
8bdfd6ed 1931 (set_attr "predicable" "yes")]
331beb1a 1932)
1933
5cdca009 1934(define_insn "maddhisi4"
331beb1a 1935 [(set (match_operand:SI 0 "s_register_operand" "=r")
cfa6c608 1936 (plus:SI (mult:SI (sign_extend:SI
1937 (match_operand:HI 1 "s_register_operand" "r"))
331beb1a 1938 (sign_extend:SI
cfa6c608 1939 (match_operand:HI 2 "s_register_operand" "r")))
1940 (match_operand:SI 3 "s_register_operand" "r")))]
25f905c2 1941 "TARGET_DSP_MULTIPLY"
5cdca009 1942 "smlabb%?\\t%0, %1, %2, %3"
9da0ec36 1943 [(set_attr "type" "smlaxy")
8bdfd6ed 1944 (set_attr "predicable" "yes")]
331beb1a 1945)
1946
9a92f368 1947;; Note: there is no maddhisi4ibt because this one is canonical form
1948(define_insn "*maddhisi4tb"
1949 [(set (match_operand:SI 0 "s_register_operand" "=r")
1950 (plus:SI (mult:SI (ashiftrt:SI
1951 (match_operand:SI 1 "s_register_operand" "r")
1952 (const_int 16))
1953 (sign_extend:SI
1954 (match_operand:HI 2 "s_register_operand" "r")))
1955 (match_operand:SI 3 "s_register_operand" "r")))]
1956 "TARGET_DSP_MULTIPLY"
1957 "smlatb%?\\t%0, %1, %2, %3"
9da0ec36 1958 [(set_attr "type" "smlaxy")
8bdfd6ed 1959 (set_attr "predicable" "yes")]
9a92f368 1960)
1961
1962(define_insn "*maddhisi4tt"
1963 [(set (match_operand:SI 0 "s_register_operand" "=r")
1964 (plus:SI (mult:SI (ashiftrt:SI
1965 (match_operand:SI 1 "s_register_operand" "r")
1966 (const_int 16))
1967 (ashiftrt:SI
1968 (match_operand:SI 2 "s_register_operand" "r")
1969 (const_int 16)))
1970 (match_operand:SI 3 "s_register_operand" "r")))]
1971 "TARGET_DSP_MULTIPLY"
1972 "smlatt%?\\t%0, %1, %2, %3"
9da0ec36 1973 [(set_attr "type" "smlaxy")
8bdfd6ed 1974 (set_attr "predicable" "yes")]
9a92f368 1975)
1976
aff5fb4d 1977(define_insn "maddhidi4"
331beb1a 1978 [(set (match_operand:DI 0 "s_register_operand" "=r")
1979 (plus:DI
331beb1a 1980 (mult:DI (sign_extend:DI
d952d547 1981 (match_operand:HI 1 "s_register_operand" "r"))
331beb1a 1982 (sign_extend:DI
cfa6c608 1983 (match_operand:HI 2 "s_register_operand" "r")))
1984 (match_operand:DI 3 "s_register_operand" "0")))]
25f905c2 1985 "TARGET_DSP_MULTIPLY"
5cdca009 1986 "smlalbb%?\\t%Q0, %R0, %1, %2"
9da0ec36 1987 [(set_attr "type" "smlalxy")
8bdfd6ed 1988 (set_attr "predicable" "yes")])
331beb1a 1989
9a92f368 1990;; Note: there is no maddhidi4ibt because this one is canonical form
1991(define_insn "*maddhidi4tb"
1992 [(set (match_operand:DI 0 "s_register_operand" "=r")
1993 (plus:DI
1994 (mult:DI (sign_extend:DI
1995 (ashiftrt:SI
1996 (match_operand:SI 1 "s_register_operand" "r")
1997 (const_int 16)))
1998 (sign_extend:DI
1999 (match_operand:HI 2 "s_register_operand" "r")))
2000 (match_operand:DI 3 "s_register_operand" "0")))]
2001 "TARGET_DSP_MULTIPLY"
2002 "smlaltb%?\\t%Q0, %R0, %1, %2"
9da0ec36 2003 [(set_attr "type" "smlalxy")
8bdfd6ed 2004 (set_attr "predicable" "yes")])
9a92f368 2005
2006(define_insn "*maddhidi4tt"
2007 [(set (match_operand:DI 0 "s_register_operand" "=r")
2008 (plus:DI
2009 (mult:DI (sign_extend:DI
2010 (ashiftrt:SI
2011 (match_operand:SI 1 "s_register_operand" "r")
2012 (const_int 16)))
2013 (sign_extend:DI
2014 (ashiftrt:SI
2015 (match_operand:SI 2 "s_register_operand" "r")
2016 (const_int 16))))
2017 (match_operand:DI 3 "s_register_operand" "0")))]
2018 "TARGET_DSP_MULTIPLY"
2019 "smlaltt%?\\t%Q0, %R0, %1, %2"
9da0ec36 2020 [(set_attr "type" "smlalxy")
8bdfd6ed 2021 (set_attr "predicable" "yes")])
9a92f368 2022
604f3a0a 2023(define_expand "mulsf3"
3934ae0e 2024 [(set (match_operand:SF 0 "s_register_operand")
2025 (mult:SF (match_operand:SF 1 "s_register_operand")
2026 (match_operand:SF 2 "s_register_operand")))]
25f905c2 2027 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 2028 "
604f3a0a 2029")
2030
604f3a0a 2031(define_expand "muldf3"
3934ae0e 2032 [(set (match_operand:DF 0 "s_register_operand")
2033 (mult:DF (match_operand:DF 1 "s_register_operand")
2034 (match_operand:DF 2 "s_register_operand")))]
a50d7267 2035 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 2036 "
604f3a0a 2037")
b11cae9e 2038\f
2039;; Division insns
2040
7db9af5d 2041(define_expand "divsf3"
3934ae0e 2042 [(set (match_operand:SF 0 "s_register_operand")
2043 (div:SF (match_operand:SF 1 "s_register_operand")
2044 (match_operand:SF 2 "s_register_operand")))]
d7216193 2045 "TARGET_32BIT && TARGET_HARD_FLOAT"
7db9af5d 2046 "")
9c08d1fa 2047
7db9af5d 2048(define_expand "divdf3"
3934ae0e 2049 [(set (match_operand:DF 0 "s_register_operand")
2050 (div:DF (match_operand:DF 1 "s_register_operand")
2051 (match_operand:DF 2 "s_register_operand")))]
994606f8 2052 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
7db9af5d 2053 "")
b11cae9e 2054\f
b11cae9e 2055
9a7e877f 2056; Expand logical operations. The mid-end expander does not split off memory
2057; operands or complex immediates, which leads to fewer LDRD/STRD instructions.
2058; So an explicit expander is needed to generate better code.
2059
c9ad5cc4 2060(define_expand "<LOGICAL:optab>di3"
9a7e877f 2061 [(set (match_operand:DI 0 "s_register_operand")
2062 (LOGICAL:DI (match_operand:DI 1 "s_register_operand")
c9ad5cc4 2063 (match_operand:DI 2 "arm_<optab>di_operand")))]
9a7e877f 2064 "TARGET_32BIT"
2065 {
c9ad5cc4 2066 rtx low = simplify_gen_binary (<CODE>, SImode,
9a7e877f 2067 gen_lowpart (SImode, operands[1]),
2068 gen_lowpart (SImode, operands[2]));
c9ad5cc4 2069 rtx high = simplify_gen_binary (<CODE>, SImode,
9a7e877f 2070 gen_highpart (SImode, operands[1]),
2071 gen_highpart_mode (SImode, DImode,
2072 operands[2]));
2073
2074 emit_insn (gen_rtx_SET (gen_lowpart (SImode, operands[0]), low));
2075 emit_insn (gen_rtx_SET (gen_highpart (SImode, operands[0]), high));
2076 DONE;
2077 }
2078)
2079
2080(define_expand "one_cmpldi2"
2081 [(set (match_operand:DI 0 "s_register_operand")
2082 (not:DI (match_operand:DI 1 "s_register_operand")))]
2083 "TARGET_32BIT"
2084 {
2085 rtx low = simplify_gen_unary (NOT, SImode,
2086 gen_lowpart (SImode, operands[1]),
2087 SImode);
2088 rtx high = simplify_gen_unary (NOT, SImode,
2089 gen_highpart_mode (SImode, DImode,
2090 operands[1]),
2091 SImode);
2092
2093 emit_insn (gen_rtx_SET (gen_lowpart (SImode, operands[0]), low));
2094 emit_insn (gen_rtx_SET (gen_highpart (SImode, operands[0]), high));
2095 DONE;
2096 }
2097)
2098
5eddd275 2099;; Split DImode and, ior, xor operations. Simply perform the logical
f6ebffac 2100;; operation on the upper and lower halves of the registers.
5eddd275 2101;; This is needed for atomic operations in arm_split_atomic_op.
2102;; Avoid splitting IWMMXT instructions.
f6ebffac 2103(define_split
2104 [(set (match_operand:DI 0 "s_register_operand" "")
2105 (match_operator:DI 6 "logical_binary_operator"
2106 [(match_operand:DI 1 "s_register_operand" "")
2107 (match_operand:DI 2 "s_register_operand" "")]))]
25f905c2 2108 "TARGET_32BIT && reload_completed
2109 && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
f6ebffac 2110 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
2111 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
2112 "
215b30b3 2113 {
2114 operands[3] = gen_highpart (SImode, operands[0]);
2115 operands[0] = gen_lowpart (SImode, operands[0]);
2116 operands[4] = gen_highpart (SImode, operands[1]);
2117 operands[1] = gen_lowpart (SImode, operands[1]);
2118 operands[5] = gen_highpart (SImode, operands[2]);
2119 operands[2] = gen_lowpart (SImode, operands[2]);
2120 }"
2121)
f6ebffac 2122
5eddd275 2123;; Split DImode not (needed for atomic operations in arm_split_atomic_op).
2124;; Unconditionally split since there is no SIMD DImode NOT pattern.
f6ebffac 2125(define_split
5eddd275 2126 [(set (match_operand:DI 0 "s_register_operand")
2127 (not:DI (match_operand:DI 1 "s_register_operand")))]
25f905c2 2128 "TARGET_32BIT"
5eddd275 2129 [(set (match_dup 0) (not:SI (match_dup 1)))
2130 (set (match_dup 2) (not:SI (match_dup 3)))]
a0f94409 2131 "
2132 {
5eddd275 2133 operands[2] = gen_highpart (SImode, operands[0]);
a0f94409 2134 operands[0] = gen_lowpart (SImode, operands[0]);
5eddd275 2135 operands[3] = gen_highpart (SImode, operands[1]);
a0f94409 2136 operands[1] = gen_lowpart (SImode, operands[1]);
2137 }"
cffb2a26 2138)
b11cae9e 2139
87b22bf7 2140(define_expand "andsi3"
3934ae0e 2141 [(set (match_operand:SI 0 "s_register_operand")
2142 (and:SI (match_operand:SI 1 "s_register_operand")
2143 (match_operand:SI 2 "reg_or_int_operand")))]
cffb2a26 2144 "TARGET_EITHER"
87b22bf7 2145 "
25f905c2 2146 if (TARGET_32BIT)
87b22bf7 2147 {
0438d37f 2148 if (CONST_INT_P (operands[2]))
cffb2a26 2149 {
47b5b27b 2150 if (INTVAL (operands[2]) == 255 && arm_arch6)
2151 {
2152 operands[1] = convert_to_mode (QImode, operands[1], 1);
2153 emit_insn (gen_thumb2_zero_extendqisi2_v6 (operands[0],
2154 operands[1]));
17202aa5 2155 DONE;
47b5b27b 2156 }
17202aa5 2157 else if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[2]), AND))
2158 operands[2] = force_reg (SImode, operands[2]);
47b5b27b 2159 else
17202aa5 2160 {
2161 arm_split_constant (AND, SImode, NULL_RTX,
2162 INTVAL (operands[2]), operands[0],
2163 operands[1],
2164 optimize && can_create_pseudo_p ());
615caa51 2165
17202aa5 2166 DONE;
2167 }
cffb2a26 2168 }
87b22bf7 2169 }
25f905c2 2170 else /* TARGET_THUMB1 */
cffb2a26 2171 {
0438d37f 2172 if (!CONST_INT_P (operands[2]))
923ffadb 2173 {
2174 rtx tmp = force_reg (SImode, operands[2]);
2175 if (rtx_equal_p (operands[0], operands[1]))
2176 operands[2] = tmp;
2177 else
2178 {
2179 operands[2] = operands[1];
2180 operands[1] = tmp;
2181 }
2182 }
cffb2a26 2183 else
2184 {
2185 int i;
2186
215b30b3 2187 if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
cffb2a26 2188 {
215b30b3 2189 operands[2] = force_reg (SImode,
2190 GEN_INT (~INTVAL (operands[2])));
cffb2a26 2191
747b7458 2192 emit_insn (gen_thumb1_bicsi3 (operands[0], operands[2], operands[1]));
cffb2a26 2193
2194 DONE;
2195 }
87b22bf7 2196
cffb2a26 2197 for (i = 9; i <= 31; i++)
2198 {
db2faf44 2199 if ((HOST_WIDE_INT_1 << i) - 1 == INTVAL (operands[2]))
cffb2a26 2200 {
2201 emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
2202 const0_rtx));
2203 DONE;
2204 }
db2faf44 2205 else if ((HOST_WIDE_INT_1 << i) - 1
215b30b3 2206 == ~INTVAL (operands[2]))
cffb2a26 2207 {
2208 rtx shift = GEN_INT (i);
2209 rtx reg = gen_reg_rtx (SImode);
2210
2211 emit_insn (gen_lshrsi3 (reg, operands[1], shift));
2212 emit_insn (gen_ashlsi3 (operands[0], reg, shift));
2213
2214 DONE;
2215 }
2216 }
2217
2218 operands[2] = force_reg (SImode, operands[2]);
2219 }
215b30b3 2220 }
2221 "
cffb2a26 2222)
2223
25f905c2 2224; ??? Check split length for Thumb-2
a0f94409 2225(define_insn_and_split "*arm_andsi3_insn"
29e234a3 2226 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r,r,r")
2227 (and:SI (match_operand:SI 1 "s_register_operand" "%r,0,r,r,r")
2228 (match_operand:SI 2 "reg_or_int_operand" "I,l,K,r,?n")))]
25f905c2 2229 "TARGET_32BIT"
5565501b 2230 "@
29e234a3 2231 and%?\\t%0, %1, %2
5565501b 2232 and%?\\t%0, %1, %2
87b22bf7 2233 bic%?\\t%0, %1, #%B2
65f68e55 2234 and%?\\t%0, %1, %2
87b22bf7 2235 #"
25f905c2 2236 "TARGET_32BIT
0438d37f 2237 && CONST_INT_P (operands[2])
a0f94409 2238 && !(const_ok_for_arm (INTVAL (operands[2]))
2239 || const_ok_for_arm (~INTVAL (operands[2])))"
2240 [(clobber (const_int 0))]
2241 "
96f57e36 2242 arm_split_constant (AND, SImode, curr_insn,
2243 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 2244 DONE;
2245 "
29e234a3 2246 [(set_attr "length" "4,4,4,4,16")
65f68e55 2247 (set_attr "predicable" "yes")
29e234a3 2248 (set_attr "predicable_short_it" "no,yes,no,no,no")
d82e788e 2249 (set_attr "type" "logic_imm,logic_imm,logic_reg,logic_reg,logic_imm")]
cffb2a26 2250)
2251
f7fbdd4a 2252(define_insn "*andsi3_compare0"
bd5b4116 2253 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 2254 (compare:CC_NOOV
65f68e55 2255 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
2256 (match_operand:SI 2 "arm_not_operand" "I,K,r"))
5565501b 2257 (const_int 0)))
65f68e55 2258 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9c08d1fa 2259 (and:SI (match_dup 1) (match_dup 2)))]
25f905c2 2260 "TARGET_32BIT"
5565501b 2261 "@
3ef90e77 2262 ands%?\\t%0, %1, %2
2263 bics%?\\t%0, %1, #%B2
2264 ands%?\\t%0, %1, %2"
65f68e55 2265 [(set_attr "conds" "set")
d82e788e 2266 (set_attr "type" "logics_imm,logics_imm,logics_reg")]
cffb2a26 2267)
9c08d1fa 2268
f7fbdd4a 2269(define_insn "*andsi3_compare0_scratch"
bd5b4116 2270 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 2271 (compare:CC_NOOV
65f68e55 2272 (and:SI (match_operand:SI 0 "s_register_operand" "r,r,r")
2273 (match_operand:SI 1 "arm_not_operand" "I,K,r"))
5565501b 2274 (const_int 0)))
65f68e55 2275 (clobber (match_scratch:SI 2 "=X,r,X"))]
25f905c2 2276 "TARGET_32BIT"
5565501b 2277 "@
2278 tst%?\\t%0, %1
3ef90e77 2279 bics%?\\t%2, %0, #%B1
65f68e55 2280 tst%?\\t%0, %1"
2281 [(set_attr "conds" "set")
d82e788e 2282 (set_attr "type" "logics_imm,logics_imm,logics_reg")]
0d66636f 2283)
9c08d1fa 2284
f7fbdd4a 2285(define_insn "*zeroextractsi_compare0_scratch"
bd5b4116 2286 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2287 (compare:CC_NOOV (zero_extract:SI
2288 (match_operand:SI 0 "s_register_operand" "r")
d952d547 2289 (match_operand 1 "const_int_operand" "n")
206ee9a2 2290 (match_operand 2 "const_int_operand" "n"))
9c08d1fa 2291 (const_int 0)))]
25f905c2 2292 "TARGET_32BIT
cffb2a26 2293 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
2294 && INTVAL (operands[1]) > 0
2295 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
2296 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
9c08d1fa 2297 "*
5c49a439 2298 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
2299 << INTVAL (operands[2]));
40dbec34 2300 output_asm_insn (\"tst%?\\t%0, %1\", operands);
e2348bcb 2301 return \"\";
0d66636f 2302 "
596e5e8f 2303 [(set_attr "conds" "set")
65f68e55 2304 (set_attr "predicable" "yes")
d82e788e 2305 (set_attr "type" "logics_imm")]
0d66636f 2306)
9c08d1fa 2307
f4462328 2308(define_insn_and_split "*ne_zeroextractsi"
c4034607 2309 [(set (match_operand:SI 0 "s_register_operand" "=r")
2310 (ne:SI (zero_extract:SI
2311 (match_operand:SI 1 "s_register_operand" "r")
2312 (match_operand:SI 2 "const_int_operand" "n")
2313 (match_operand:SI 3 "const_int_operand" "n"))
3b8c7f7a 2314 (const_int 0)))
2315 (clobber (reg:CC CC_REGNUM))]
25f905c2 2316 "TARGET_32BIT
cffb2a26 2317 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2318 && INTVAL (operands[2]) > 0
2319 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2320 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
f4462328 2321 "#"
25f905c2 2322 "TARGET_32BIT
f4462328 2323 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2324 && INTVAL (operands[2]) > 0
2325 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2326 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
2327 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2328 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2329 (const_int 0)))
2330 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2331 (set (match_dup 0)
2332 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2333 (match_dup 0) (const_int 1)))]
2334 "
2335 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
2336 << INTVAL (operands[3]));
2337 "
2338 [(set_attr "conds" "clob")
25f905c2 2339 (set (attr "length")
2340 (if_then_else (eq_attr "is_thumb" "yes")
2341 (const_int 12)
1b7da4ac 2342 (const_int 8)))
2343 (set_attr "type" "multiple")]
f4462328 2344)
2345
2346(define_insn_and_split "*ne_zeroextractsi_shifted"
2347 [(set (match_operand:SI 0 "s_register_operand" "=r")
2348 (ne:SI (zero_extract:SI
2349 (match_operand:SI 1 "s_register_operand" "r")
2350 (match_operand:SI 2 "const_int_operand" "n")
2351 (const_int 0))
2352 (const_int 0)))
2353 (clobber (reg:CC CC_REGNUM))]
2354 "TARGET_ARM"
2355 "#"
2356 "TARGET_ARM"
2357 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2358 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2359 (const_int 0)))
2360 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2361 (set (match_dup 0)
2362 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2363 (match_dup 0) (const_int 1)))]
2364 "
2365 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
2366 "
2367 [(set_attr "conds" "clob")
1b7da4ac 2368 (set_attr "length" "8")
2369 (set_attr "type" "multiple")]
f4462328 2370)
2371
2372(define_insn_and_split "*ite_ne_zeroextractsi"
2373 [(set (match_operand:SI 0 "s_register_operand" "=r")
2374 (if_then_else:SI (ne (zero_extract:SI
2375 (match_operand:SI 1 "s_register_operand" "r")
2376 (match_operand:SI 2 "const_int_operand" "n")
2377 (match_operand:SI 3 "const_int_operand" "n"))
2378 (const_int 0))
2379 (match_operand:SI 4 "arm_not_operand" "rIK")
2380 (const_int 0)))
2381 (clobber (reg:CC CC_REGNUM))]
2382 "TARGET_ARM
2383 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2384 && INTVAL (operands[2]) > 0
2385 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 2386 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2387 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 2388 "#"
2389 "TARGET_ARM
2390 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2391 && INTVAL (operands[2]) > 0
2392 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 2393 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2394 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 2395 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2396 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2397 (const_int 0)))
2398 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2399 (set (match_dup 0)
2400 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2401 (match_dup 0) (match_dup 4)))]
2402 "
c4034607 2403 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
f4462328 2404 << INTVAL (operands[3]));
2405 "
2406 [(set_attr "conds" "clob")
1b7da4ac 2407 (set_attr "length" "8")
2408 (set_attr "type" "multiple")]
f4462328 2409)
2410
2411(define_insn_and_split "*ite_ne_zeroextractsi_shifted"
2412 [(set (match_operand:SI 0 "s_register_operand" "=r")
2413 (if_then_else:SI (ne (zero_extract:SI
2414 (match_operand:SI 1 "s_register_operand" "r")
2415 (match_operand:SI 2 "const_int_operand" "n")
2416 (const_int 0))
2417 (const_int 0))
2418 (match_operand:SI 3 "arm_not_operand" "rIK")
2419 (const_int 0)))
2420 (clobber (reg:CC CC_REGNUM))]
f8d7bf2f 2421 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 2422 "#"
f8d7bf2f 2423 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 2424 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2425 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2426 (const_int 0)))
2427 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2428 (set (match_dup 0)
2429 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2430 (match_dup 0) (match_dup 3)))]
2431 "
2432 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
0d66636f 2433 "
2434 [(set_attr "conds" "clob")
1b7da4ac 2435 (set_attr "length" "8")
2436 (set_attr "type" "multiple")]
215b30b3 2437)
9c08d1fa 2438
25f905c2 2439;; ??? Use Thumb-2 has bitfield insert/extract instructions.
d7863cfe 2440(define_split
2441 [(set (match_operand:SI 0 "s_register_operand" "")
2442 (match_operator:SI 1 "shiftable_operator"
2443 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2444 (match_operand:SI 3 "const_int_operand" "")
2445 (match_operand:SI 4 "const_int_operand" ""))
2446 (match_operand:SI 5 "s_register_operand" "")]))
2447 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2448 "TARGET_ARM"
2449 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2450 (set (match_dup 0)
2451 (match_op_dup 1
2452 [(lshiftrt:SI (match_dup 6) (match_dup 4))
2453 (match_dup 5)]))]
2454 "{
2455 HOST_WIDE_INT temp = INTVAL (operands[3]);
2456
2457 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2458 operands[4] = GEN_INT (32 - temp);
2459 }"
2460)
2461
d7863cfe 2462(define_split
2463 [(set (match_operand:SI 0 "s_register_operand" "")
2464 (match_operator:SI 1 "shiftable_operator"
2465 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2466 (match_operand:SI 3 "const_int_operand" "")
2467 (match_operand:SI 4 "const_int_operand" ""))
2468 (match_operand:SI 5 "s_register_operand" "")]))
2469 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2470 "TARGET_ARM"
2471 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2472 (set (match_dup 0)
2473 (match_op_dup 1
2474 [(ashiftrt:SI (match_dup 6) (match_dup 4))
2475 (match_dup 5)]))]
2476 "{
2477 HOST_WIDE_INT temp = INTVAL (operands[3]);
2478
2479 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2480 operands[4] = GEN_INT (32 - temp);
2481 }"
2482)
2483
a42059fd 2484;;; ??? This pattern is bogus. If operand3 has bits outside the range
2485;;; represented by the bitfield, then this will produce incorrect results.
2486;;; Somewhere, the value needs to be truncated. On targets like the m68k,
ceb2fe0f 2487;;; which have a real bit-field insert instruction, the truncation happens
2488;;; in the bit-field insert instruction itself. Since arm does not have a
2489;;; bit-field insert instruction, we would have to emit code here to truncate
a42059fd 2490;;; the value before we insert. This loses some of the advantage of having
2491;;; this insv pattern, so this pattern needs to be reevalutated.
2492
8a18b90c 2493(define_expand "insv"
3934ae0e 2494 [(set (zero_extract (match_operand 0 "nonimmediate_operand")
2495 (match_operand 1 "general_operand")
2496 (match_operand 2 "general_operand"))
2497 (match_operand 3 "reg_or_int_operand"))]
8b054d5a 2498 "TARGET_ARM || arm_arch_thumb2"
8a18b90c 2499 "
215b30b3 2500 {
2501 int start_bit = INTVAL (operands[2]);
2502 int width = INTVAL (operands[1]);
db2faf44 2503 HOST_WIDE_INT mask = (HOST_WIDE_INT_1 << width) - 1;
215b30b3 2504 rtx target, subtarget;
2505
8b054d5a 2506 if (arm_arch_thumb2)
2507 {
eb04cafb 2508 if (unaligned_access && MEM_P (operands[0])
2509 && s_register_operand (operands[3], GET_MODE (operands[3]))
2510 && (width == 16 || width == 32) && (start_bit % BITS_PER_UNIT) == 0)
8b054d5a 2511 {
eb04cafb 2512 rtx base_addr;
2513
2514 if (BYTES_BIG_ENDIAN)
2515 start_bit = GET_MODE_BITSIZE (GET_MODE (operands[3])) - width
2516 - start_bit;
8b054d5a 2517
eb04cafb 2518 if (width == 32)
8b054d5a 2519 {
eb04cafb 2520 base_addr = adjust_address (operands[0], SImode,
2521 start_bit / BITS_PER_UNIT);
2522 emit_insn (gen_unaligned_storesi (base_addr, operands[3]));
8b054d5a 2523 }
eb04cafb 2524 else
2525 {
2526 rtx tmp = gen_reg_rtx (HImode);
8b054d5a 2527
eb04cafb 2528 base_addr = adjust_address (operands[0], HImode,
2529 start_bit / BITS_PER_UNIT);
2530 emit_move_insn (tmp, gen_lowpart (HImode, operands[3]));
2531 emit_insn (gen_unaligned_storehi (base_addr, tmp));
2532 }
2533 DONE;
8b054d5a 2534 }
eb04cafb 2535 else if (s_register_operand (operands[0], GET_MODE (operands[0])))
8b054d5a 2536 {
eb04cafb 2537 bool use_bfi = TRUE;
8b054d5a 2538
0438d37f 2539 if (CONST_INT_P (operands[3]))
eb04cafb 2540 {
2541 HOST_WIDE_INT val = INTVAL (operands[3]) & mask;
2542
2543 if (val == 0)
2544 {
2545 emit_insn (gen_insv_zero (operands[0], operands[1],
2546 operands[2]));
2547 DONE;
2548 }
2549
2550 /* See if the set can be done with a single orr instruction. */
2551 if (val == mask && const_ok_for_arm (val << start_bit))
2552 use_bfi = FALSE;
2553 }
2554
2555 if (use_bfi)
2556 {
0438d37f 2557 if (!REG_P (operands[3]))
eb04cafb 2558 operands[3] = force_reg (SImode, operands[3]);
2559
2560 emit_insn (gen_insv_t2 (operands[0], operands[1], operands[2],
2561 operands[3]));
2562 DONE;
2563 }
8b054d5a 2564 }
eb04cafb 2565 else
2566 FAIL;
8b054d5a 2567 }
2568
eb04cafb 2569 if (!s_register_operand (operands[0], GET_MODE (operands[0])))
2570 FAIL;
2571
3f8fde42 2572 target = copy_rtx (operands[0]);
215b30b3 2573 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
2574 subreg as the final target. */
2575 if (GET_CODE (target) == SUBREG)
2576 {
2577 subtarget = gen_reg_rtx (SImode);
2578 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
2579 < GET_MODE_SIZE (SImode))
2580 target = SUBREG_REG (target);
2581 }
2582 else
2583 subtarget = target;
8a18b90c 2584
0438d37f 2585 if (CONST_INT_P (operands[3]))
215b30b3 2586 {
2587 /* Since we are inserting a known constant, we may be able to
2588 reduce the number of bits that we have to clear so that
2589 the mask becomes simple. */
2590 /* ??? This code does not check to see if the new mask is actually
2591 simpler. It may not be. */
2592 rtx op1 = gen_reg_rtx (SImode);
2593 /* ??? Truncate operand3 to fit in the bitfield. See comment before
2594 start of this pattern. */
2595 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
2596 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
2597
c5b3a71b 2598 emit_insn (gen_andsi3 (op1, operands[0],
2599 gen_int_mode (~mask2, SImode)));
215b30b3 2600 emit_insn (gen_iorsi3 (subtarget, op1,
4292ca6b 2601 gen_int_mode (op3_value << start_bit, SImode)));
215b30b3 2602 }
2603 else if (start_bit == 0
2604 && !(const_ok_for_arm (mask)
2605 || const_ok_for_arm (~mask)))
2606 {
2607 /* A Trick, since we are setting the bottom bits in the word,
2608 we can shift operand[3] up, operand[0] down, OR them together
2609 and rotate the result back again. This takes 3 insns, and
5910bb95 2610 the third might be mergeable into another op. */
215b30b3 2611 /* The shift up copes with the possibility that operand[3] is
2612 wider than the bitfield. */
2613 rtx op0 = gen_reg_rtx (SImode);
2614 rtx op1 = gen_reg_rtx (SImode);
2615
2616 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2617 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
2618 emit_insn (gen_iorsi3 (op1, op1, op0));
2619 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
2620 }
2621 else if ((width + start_bit == 32)
2622 && !(const_ok_for_arm (mask)
2623 || const_ok_for_arm (~mask)))
2624 {
2625 /* Similar trick, but slightly less efficient. */
8a18b90c 2626
215b30b3 2627 rtx op0 = gen_reg_rtx (SImode);
2628 rtx op1 = gen_reg_rtx (SImode);
8a18b90c 2629
215b30b3 2630 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2631 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
2632 emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
2633 emit_insn (gen_iorsi3 (subtarget, op1, op0));
2634 }
2635 else
2636 {
c5b3a71b 2637 rtx op0 = gen_int_mode (mask, SImode);
215b30b3 2638 rtx op1 = gen_reg_rtx (SImode);
2639 rtx op2 = gen_reg_rtx (SImode);
8a18b90c 2640
215b30b3 2641 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
2642 {
2643 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 2644
215b30b3 2645 emit_insn (gen_movsi (tmp, op0));
2646 op0 = tmp;
2647 }
8a18b90c 2648
215b30b3 2649 /* Mask out any bits in operand[3] that are not needed. */
2650 emit_insn (gen_andsi3 (op1, operands[3], op0));
8a18b90c 2651
0438d37f 2652 if (CONST_INT_P (op0)
215b30b3 2653 && (const_ok_for_arm (mask << start_bit)
2654 || const_ok_for_arm (~(mask << start_bit))))
2655 {
c5b3a71b 2656 op0 = gen_int_mode (~(mask << start_bit), SImode);
215b30b3 2657 emit_insn (gen_andsi3 (op2, operands[0], op0));
2658 }
2659 else
2660 {
0438d37f 2661 if (CONST_INT_P (op0))
215b30b3 2662 {
2663 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 2664
215b30b3 2665 emit_insn (gen_movsi (tmp, op0));
2666 op0 = tmp;
2667 }
2668
2669 if (start_bit != 0)
2670 emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
a42059fd 2671
215b30b3 2672 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
2673 }
8a18b90c 2674
215b30b3 2675 if (start_bit != 0)
2676 emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
8a18b90c 2677
215b30b3 2678 emit_insn (gen_iorsi3 (subtarget, op1, op2));
2679 }
f082f1c4 2680
215b30b3 2681 if (subtarget != target)
2682 {
2683 /* If TARGET is still a SUBREG, then it must be wider than a word,
2684 so we must be careful only to set the subword we were asked to. */
2685 if (GET_CODE (target) == SUBREG)
2686 emit_move_insn (target, subtarget);
2687 else
2688 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
2689 }
8a18b90c 2690
215b30b3 2691 DONE;
2692 }"
2693)
8a18b90c 2694
8b054d5a 2695(define_insn "insv_zero"
2696 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
809003b3 2697 (match_operand:SI 1 "const_int_M_operand" "M")
2698 (match_operand:SI 2 "const_int_M_operand" "M"))
8b054d5a 2699 (const_int 0))]
2700 "arm_arch_thumb2"
2701 "bfc%?\t%0, %2, %1"
2702 [(set_attr "length" "4")
d952d547 2703 (set_attr "predicable" "yes")
d82e788e 2704 (set_attr "type" "bfm")]
8b054d5a 2705)
2706
2707(define_insn "insv_t2"
2708 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
809003b3 2709 (match_operand:SI 1 "const_int_M_operand" "M")
2710 (match_operand:SI 2 "const_int_M_operand" "M"))
8b054d5a 2711 (match_operand:SI 3 "s_register_operand" "r"))]
2712 "arm_arch_thumb2"
2713 "bfi%?\t%0, %3, %2, %1"
2714 [(set_attr "length" "4")
d952d547 2715 (set_attr "predicable" "yes")
d82e788e 2716 (set_attr "type" "bfm")]
8b054d5a 2717)
2718
8a18b90c 2719(define_insn "andsi_notsi_si"
9c08d1fa 2720 [(set (match_operand:SI 0 "s_register_operand" "=r")
2721 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2722 (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 2723 "TARGET_32BIT"
0d66636f 2724 "bic%?\\t%0, %1, %2"
d952d547 2725 [(set_attr "predicable" "yes")
1b7da4ac 2726 (set_attr "type" "logic_reg")]
0d66636f 2727)
b11cae9e 2728
8a18b90c 2729(define_insn "andsi_not_shiftsi_si"
a2cd141b 2730 [(set (match_operand:SI 0 "s_register_operand" "=r")
2731 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2732 [(match_operand:SI 2 "s_register_operand" "r")
2733 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2734 (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 2735 "TARGET_ARM"
6c4c2133 2736 "bic%?\\t%0, %1, %2%S4"
344495ea 2737 [(set_attr "predicable" "yes")
331beb1a 2738 (set_attr "shift" "2")
a2cd141b 2739 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
d82e788e 2740 (const_string "logic_shift_imm")
2741 (const_string "logic_shift_reg")))]
6c4c2133 2742)
8a18b90c 2743
9ed784d8 2744;; Shifted bics pattern used to set up CC status register and not reusing
2745;; bics output. Pattern restricts Thumb2 shift operand as bics for Thumb2
2746;; does not support shift by register.
2747(define_insn "andsi_not_shiftsi_si_scc_no_reuse"
2748 [(set (reg:CC_NOOV CC_REGNUM)
2749 (compare:CC_NOOV
2750 (and:SI (not:SI (match_operator:SI 0 "shift_operator"
2751 [(match_operand:SI 1 "s_register_operand" "r")
2752 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2753 (match_operand:SI 3 "s_register_operand" "r"))
2754 (const_int 0)))
2755 (clobber (match_scratch:SI 4 "=r"))]
2756 "TARGET_ARM || (TARGET_THUMB2 && CONST_INT_P (operands[2]))"
3ef90e77 2757 "bics%?\\t%4, %3, %1%S0"
9ed784d8 2758 [(set_attr "predicable" "yes")
9ed784d8 2759 (set_attr "conds" "set")
2760 (set_attr "shift" "1")
2761 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2762 (const_string "logic_shift_imm")
2763 (const_string "logic_shift_reg")))]
2764)
2765
2766;; Same as andsi_not_shiftsi_si_scc_no_reuse, but the bics result is also
2767;; getting reused later.
2768(define_insn "andsi_not_shiftsi_si_scc"
2769 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2770 (compare:CC_NOOV
2771 (and:SI (not:SI (match_operator:SI 0 "shift_operator"
2772 [(match_operand:SI 1 "s_register_operand" "r")
2773 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2774 (match_operand:SI 3 "s_register_operand" "r"))
2775 (const_int 0)))
2776 (set (match_operand:SI 4 "s_register_operand" "=r")
2777 (and:SI (not:SI (match_op_dup 0
2778 [(match_dup 1)
2779 (match_dup 2)]))
2780 (match_dup 3)))])]
2781 "TARGET_ARM || (TARGET_THUMB2 && CONST_INT_P (operands[2]))"
3ef90e77 2782 "bics%?\\t%4, %3, %1%S0"
9ed784d8 2783 [(set_attr "predicable" "yes")
9ed784d8 2784 (set_attr "conds" "set")
2785 (set_attr "shift" "1")
2786 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2787 (const_string "logic_shift_imm")
2788 (const_string "logic_shift_reg")))]
2789)
2790
f7fbdd4a 2791(define_insn "*andsi_notsi_si_compare0"
bd5b4116 2792 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 2793 (compare:CC_NOOV
2794 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2795 (match_operand:SI 1 "s_register_operand" "r"))
2796 (const_int 0)))
9c08d1fa 2797 (set (match_operand:SI 0 "s_register_operand" "=r")
2798 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
25f905c2 2799 "TARGET_32BIT"
3ef90e77 2800 "bics\\t%0, %1, %2"
d82e788e 2801 [(set_attr "conds" "set")
2802 (set_attr "type" "logics_shift_reg")]
0d66636f 2803)
9c08d1fa 2804
f7fbdd4a 2805(define_insn "*andsi_notsi_si_compare0_scratch"
bd5b4116 2806 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 2807 (compare:CC_NOOV
2808 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2809 (match_operand:SI 1 "s_register_operand" "r"))
2810 (const_int 0)))
9c08d1fa 2811 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 2812 "TARGET_32BIT"
3ef90e77 2813 "bics\\t%0, %1, %2"
d82e788e 2814 [(set_attr "conds" "set")
2815 (set_attr "type" "logics_shift_reg")]
0d66636f 2816)
9c08d1fa 2817
87b22bf7 2818(define_expand "iorsi3"
3934ae0e 2819 [(set (match_operand:SI 0 "s_register_operand")
2820 (ior:SI (match_operand:SI 1 "s_register_operand")
2821 (match_operand:SI 2 "reg_or_int_operand")))]
cffb2a26 2822 "TARGET_EITHER"
87b22bf7 2823 "
0438d37f 2824 if (CONST_INT_P (operands[2]))
87b22bf7 2825 {
25f905c2 2826 if (TARGET_32BIT)
cffb2a26 2827 {
17202aa5 2828 if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[2]), IOR))
2829 operands[2] = force_reg (SImode, operands[2]);
2830 else
2831 {
2832 arm_split_constant (IOR, SImode, NULL_RTX,
2833 INTVAL (operands[2]), operands[0],
2834 operands[1],
2835 optimize && can_create_pseudo_p ());
2836 DONE;
2837 }
cffb2a26 2838 }
25f905c2 2839 else /* TARGET_THUMB1 */
923ffadb 2840 {
2841 rtx tmp = force_reg (SImode, operands[2]);
2842 if (rtx_equal_p (operands[0], operands[1]))
2843 operands[2] = tmp;
2844 else
2845 {
2846 operands[2] = operands[1];
2847 operands[1] = tmp;
2848 }
2849 }
87b22bf7 2850 }
cffb2a26 2851 "
2852)
87b22bf7 2853
d5d4dc8d 2854(define_insn_and_split "*iorsi3_insn"
29e234a3 2855 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r,r,r")
2856 (ior:SI (match_operand:SI 1 "s_register_operand" "%r,0,r,r,r")
2857 (match_operand:SI 2 "reg_or_int_operand" "I,l,K,r,?n")))]
d5d4dc8d 2858 "TARGET_32BIT"
87b22bf7 2859 "@
29e234a3 2860 orr%?\\t%0, %1, %2
87b22bf7 2861 orr%?\\t%0, %1, %2
d5d4dc8d 2862 orn%?\\t%0, %1, #%B2
65f68e55 2863 orr%?\\t%0, %1, %2
87b22bf7 2864 #"
d5d4dc8d 2865 "TARGET_32BIT
0438d37f 2866 && CONST_INT_P (operands[2])
d5d4dc8d 2867 && !(const_ok_for_arm (INTVAL (operands[2]))
2868 || (TARGET_THUMB2 && const_ok_for_arm (~INTVAL (operands[2]))))"
a0f94409 2869 [(clobber (const_int 0))]
d5d4dc8d 2870{
29e234a3 2871 arm_split_constant (IOR, SImode, curr_insn,
96f57e36 2872 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 2873 DONE;
d5d4dc8d 2874}
29e234a3 2875 [(set_attr "length" "4,4,4,4,16")
2876 (set_attr "arch" "32,t2,t2,32,32")
65f68e55 2877 (set_attr "predicable" "yes")
29e234a3 2878 (set_attr "predicable_short_it" "no,yes,no,no,no")
d82e788e 2879 (set_attr "type" "logic_imm,logic_reg,logic_imm,logic_reg,logic_reg")]
65f68e55 2880)
cffb2a26 2881
a0f94409 2882(define_peephole2
2883 [(match_scratch:SI 3 "r")
372575c7 2884 (set (match_operand:SI 0 "arm_general_register_operand" "")
2885 (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
87b22bf7 2886 (match_operand:SI 2 "const_int_operand" "")))]
90560cad 2887 "TARGET_ARM
a0f94409 2888 && !const_ok_for_arm (INTVAL (operands[2]))
2889 && const_ok_for_arm (~INTVAL (operands[2]))"
2890 [(set (match_dup 3) (match_dup 2))
2891 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2892 ""
215b30b3 2893)
a0f94409 2894
f7fbdd4a 2895(define_insn "*iorsi3_compare0"
bd5b4116 2896 [(set (reg:CC_NOOV CC_REGNUM)
a02b858e 2897 (compare:CC_NOOV
2898 (ior:SI (match_operand:SI 1 "s_register_operand" "%r,0,r")
2899 (match_operand:SI 2 "arm_rhs_operand" "I,l,r"))
2900 (const_int 0)))
2901 (set (match_operand:SI 0 "s_register_operand" "=r,l,r")
9c08d1fa 2902 (ior:SI (match_dup 1) (match_dup 2)))]
25f905c2 2903 "TARGET_32BIT"
3ef90e77 2904 "orrs%?\\t%0, %1, %2"
65f68e55 2905 [(set_attr "conds" "set")
a02b858e 2906 (set_attr "arch" "*,t2,*")
2907 (set_attr "length" "4,2,4")
2908 (set_attr "type" "logics_imm,logics_reg,logics_reg")]
cffb2a26 2909)
9c08d1fa 2910
f7fbdd4a 2911(define_insn "*iorsi3_compare0_scratch"
bd5b4116 2912 [(set (reg:CC_NOOV CC_REGNUM)
a02b858e 2913 (compare:CC_NOOV
2914 (ior:SI (match_operand:SI 1 "s_register_operand" "%r,0,r")
2915 (match_operand:SI 2 "arm_rhs_operand" "I,l,r"))
2916 (const_int 0)))
2917 (clobber (match_scratch:SI 0 "=r,l,r"))]
25f905c2 2918 "TARGET_32BIT"
3ef90e77 2919 "orrs%?\\t%0, %1, %2"
65f68e55 2920 [(set_attr "conds" "set")
a02b858e 2921 (set_attr "arch" "*,t2,*")
2922 (set_attr "length" "4,2,4")
2923 (set_attr "type" "logics_imm,logics_reg,logics_reg")]
0d66636f 2924)
9c08d1fa 2925
cffb2a26 2926(define_expand "xorsi3"
3934ae0e 2927 [(set (match_operand:SI 0 "s_register_operand")
2928 (xor:SI (match_operand:SI 1 "s_register_operand")
2929 (match_operand:SI 2 "reg_or_int_operand")))]
cffb2a26 2930 "TARGET_EITHER"
0438d37f 2931 "if (CONST_INT_P (operands[2]))
923ffadb 2932 {
2933 if (TARGET_32BIT)
2934 {
17202aa5 2935 if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[2]), XOR))
2936 operands[2] = force_reg (SImode, operands[2]);
2937 else
2938 {
2939 arm_split_constant (XOR, SImode, NULL_RTX,
2940 INTVAL (operands[2]), operands[0],
2941 operands[1],
2942 optimize && can_create_pseudo_p ());
2943 DONE;
2944 }
923ffadb 2945 }
2946 else /* TARGET_THUMB1 */
2947 {
2948 rtx tmp = force_reg (SImode, operands[2]);
2949 if (rtx_equal_p (operands[0], operands[1]))
2950 operands[2] = tmp;
2951 else
2952 {
2953 operands[2] = operands[1];
2954 operands[1] = tmp;
2955 }
2956 }
2957 }"
cffb2a26 2958)
2959
5dcb35d9 2960(define_insn_and_split "*arm_xorsi3"
29e234a3 2961 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r,r")
2962 (xor:SI (match_operand:SI 1 "s_register_operand" "%r,0,r,r")
2963 (match_operand:SI 2 "reg_or_int_operand" "I,l,r,?n")))]
25f905c2 2964 "TARGET_32BIT"
5dcb35d9 2965 "@
29e234a3 2966 eor%?\\t%0, %1, %2
65f68e55 2967 eor%?\\t%0, %1, %2
5dcb35d9 2968 eor%?\\t%0, %1, %2
2969 #"
2970 "TARGET_32BIT
0438d37f 2971 && CONST_INT_P (operands[2])
5dcb35d9 2972 && !const_ok_for_arm (INTVAL (operands[2]))"
2973 [(clobber (const_int 0))]
2974{
2975 arm_split_constant (XOR, SImode, curr_insn,
2976 INTVAL (operands[2]), operands[0], operands[1], 0);
2977 DONE;
2978}
29e234a3 2979 [(set_attr "length" "4,4,4,16")
65f68e55 2980 (set_attr "predicable" "yes")
29e234a3 2981 (set_attr "predicable_short_it" "no,yes,no,no")
1b7da4ac 2982 (set_attr "type" "logic_imm,logic_reg,logic_reg,multiple")]
cffb2a26 2983)
2984
f7fbdd4a 2985(define_insn "*xorsi3_compare0"
bd5b4116 2986 [(set (reg:CC_NOOV CC_REGNUM)
65f68e55 2987 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r,r")
2988 (match_operand:SI 2 "arm_rhs_operand" "I,r"))
9c08d1fa 2989 (const_int 0)))
65f68e55 2990 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 2991 (xor:SI (match_dup 1) (match_dup 2)))]
25f905c2 2992 "TARGET_32BIT"
3ef90e77 2993 "eors%?\\t%0, %1, %2"
65f68e55 2994 [(set_attr "conds" "set")
d82e788e 2995 (set_attr "type" "logics_imm,logics_reg")]
0d66636f 2996)
9c08d1fa 2997
f7fbdd4a 2998(define_insn "*xorsi3_compare0_scratch"
bd5b4116 2999 [(set (reg:CC_NOOV CC_REGNUM)
65f68e55 3000 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r,r")
3001 (match_operand:SI 1 "arm_rhs_operand" "I,r"))
9c08d1fa 3002 (const_int 0)))]
25f905c2 3003 "TARGET_32BIT"
40dbec34 3004 "teq%?\\t%0, %1"
65f68e55 3005 [(set_attr "conds" "set")
d82e788e 3006 (set_attr "type" "logics_imm,logics_reg")]
cffb2a26 3007)
9c08d1fa 3008
215b30b3 3009; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
3010; (NOT D) we can sometimes merge the final NOT into one of the following
3011; insns.
9c08d1fa 3012
3013(define_split
a058e94a 3014 [(set (match_operand:SI 0 "s_register_operand" "")
3015 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
3016 (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
3017 (match_operand:SI 3 "arm_rhs_operand" "")))
3018 (clobber (match_operand:SI 4 "s_register_operand" ""))]
25f905c2 3019 "TARGET_32BIT"
9c08d1fa 3020 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
3021 (not:SI (match_dup 3))))
3022 (set (match_dup 0) (not:SI (match_dup 4)))]
3023 ""
3024)
3025
ba6a3b2f 3026(define_insn_and_split "*andsi_iorsi3_notsi"
9c08d1fa 3027 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
e5fea38e 3028 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "%0,r,r")
9c08d1fa 3029 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
3030 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
25f905c2 3031 "TARGET_32BIT"
ba6a3b2f 3032 "#" ; "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
3033 "&& reload_completed"
3034 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
054fd237 3035 (set (match_dup 0) (and:SI (match_dup 4) (match_dup 5)))]
3036 {
3037 /* If operands[3] is a constant make sure to fold the NOT into it
3038 to avoid creating a NOT of a CONST_INT. */
3039 rtx not_rtx = simplify_gen_unary (NOT, SImode, operands[3], SImode);
3040 if (CONST_INT_P (not_rtx))
3041 {
3042 operands[4] = operands[0];
3043 operands[5] = not_rtx;
3044 }
3045 else
3046 {
3047 operands[5] = operands[0];
3048 operands[4] = not_rtx;
3049 }
3050 }
0d66636f 3051 [(set_attr "length" "8")
25f905c2 3052 (set_attr "ce_count" "2")
d952d547 3053 (set_attr "predicable" "yes")
1b7da4ac 3054 (set_attr "type" "multiple")]
cffb2a26 3055)
9c08d1fa 3056
25f905c2 3057; ??? Are these four splitters still beneficial when the Thumb-2 bitfield
3058; insns are available?
d7863cfe 3059(define_split
3060 [(set (match_operand:SI 0 "s_register_operand" "")
3061 (match_operator:SI 1 "logical_binary_operator"
3062 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
3063 (match_operand:SI 3 "const_int_operand" "")
3064 (match_operand:SI 4 "const_int_operand" ""))
3065 (match_operator:SI 9 "logical_binary_operator"
3066 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3067 (match_operand:SI 6 "const_int_operand" ""))
3068 (match_operand:SI 7 "s_register_operand" "")])]))
3069 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3070 "TARGET_32BIT
d7863cfe 3071 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3072 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3073 [(set (match_dup 8)
3074 (match_op_dup 1
3075 [(ashift:SI (match_dup 2) (match_dup 4))
3076 (match_dup 5)]))
3077 (set (match_dup 0)
3078 (match_op_dup 1
3079 [(lshiftrt:SI (match_dup 8) (match_dup 6))
3080 (match_dup 7)]))]
3081 "
3082 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3083")
3084
3085(define_split
3086 [(set (match_operand:SI 0 "s_register_operand" "")
3087 (match_operator:SI 1 "logical_binary_operator"
3088 [(match_operator:SI 9 "logical_binary_operator"
3089 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3090 (match_operand:SI 6 "const_int_operand" ""))
3091 (match_operand:SI 7 "s_register_operand" "")])
3092 (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
3093 (match_operand:SI 3 "const_int_operand" "")
3094 (match_operand:SI 4 "const_int_operand" ""))]))
3095 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3096 "TARGET_32BIT
d7863cfe 3097 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3098 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3099 [(set (match_dup 8)
3100 (match_op_dup 1
3101 [(ashift:SI (match_dup 2) (match_dup 4))
3102 (match_dup 5)]))
3103 (set (match_dup 0)
3104 (match_op_dup 1
3105 [(lshiftrt:SI (match_dup 8) (match_dup 6))
3106 (match_dup 7)]))]
3107 "
3108 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3109")
3110
3111(define_split
3112 [(set (match_operand:SI 0 "s_register_operand" "")
3113 (match_operator:SI 1 "logical_binary_operator"
3114 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
3115 (match_operand:SI 3 "const_int_operand" "")
3116 (match_operand:SI 4 "const_int_operand" ""))
3117 (match_operator:SI 9 "logical_binary_operator"
3118 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3119 (match_operand:SI 6 "const_int_operand" ""))
3120 (match_operand:SI 7 "s_register_operand" "")])]))
3121 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3122 "TARGET_32BIT
d7863cfe 3123 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3124 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3125 [(set (match_dup 8)
3126 (match_op_dup 1
3127 [(ashift:SI (match_dup 2) (match_dup 4))
3128 (match_dup 5)]))
3129 (set (match_dup 0)
3130 (match_op_dup 1
3131 [(ashiftrt:SI (match_dup 8) (match_dup 6))
3132 (match_dup 7)]))]
3133 "
3134 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3135")
3136
3137(define_split
3138 [(set (match_operand:SI 0 "s_register_operand" "")
3139 (match_operator:SI 1 "logical_binary_operator"
3140 [(match_operator:SI 9 "logical_binary_operator"
3141 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3142 (match_operand:SI 6 "const_int_operand" ""))
3143 (match_operand:SI 7 "s_register_operand" "")])
3144 (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
3145 (match_operand:SI 3 "const_int_operand" "")
3146 (match_operand:SI 4 "const_int_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 [(ashiftrt: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")
9c08d1fa 3162\f
3163
3164;; Minimum and maximum insns
3165
8b9dc177 3166(define_expand "smaxsi3"
3167 [(parallel [
3934ae0e 3168 (set (match_operand:SI 0 "s_register_operand")
3169 (smax:SI (match_operand:SI 1 "s_register_operand")
3170 (match_operand:SI 2 "arm_rhs_operand")))
8b9dc177 3171 (clobber (reg:CC CC_REGNUM))])]
25f905c2 3172 "TARGET_32BIT"
8b9dc177 3173 "
8774928b 3174 if (operands[2] == const0_rtx || operands[2] == constm1_rtx)
8b9dc177 3175 {
3176 /* No need for a clobber of the condition code register here. */
d1f9b275 3177 emit_insn (gen_rtx_SET (operands[0],
8b9dc177 3178 gen_rtx_SMAX (SImode, operands[1],
3179 operands[2])));
3180 DONE;
3181 }
3182")
3183
3184(define_insn "*smax_0"
3185 [(set (match_operand:SI 0 "s_register_operand" "=r")
3186 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3187 (const_int 0)))]
25f905c2 3188 "TARGET_32BIT"
8b9dc177 3189 "bic%?\\t%0, %1, %1, asr #31"
d952d547 3190 [(set_attr "predicable" "yes")
1b7da4ac 3191 (set_attr "type" "logic_shift_reg")]
8b9dc177 3192)
3193
8774928b 3194(define_insn "*smax_m1"
3195 [(set (match_operand:SI 0 "s_register_operand" "=r")
3196 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3197 (const_int -1)))]
25f905c2 3198 "TARGET_32BIT"
8774928b 3199 "orr%?\\t%0, %1, %1, asr #31"
d952d547 3200 [(set_attr "predicable" "yes")
1b7da4ac 3201 (set_attr "type" "logic_shift_reg")]
8774928b 3202)
3203
3dc953f2 3204(define_insn_and_split "*arm_smax_insn"
8b9dc177 3205 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3206 (smax:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3207 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
bd5b4116 3208 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3209 "TARGET_ARM"
3dc953f2 3210 "#"
3211 ; cmp\\t%1, %2\;movlt\\t%0, %2
3212 ; cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
3213 "TARGET_ARM"
3214 [(set (reg:CC CC_REGNUM)
3215 (compare:CC (match_dup 1) (match_dup 2)))
3216 (set (match_dup 0)
3217 (if_then_else:SI (ge:SI (reg:CC CC_REGNUM) (const_int 0))
3218 (match_dup 1)
3219 (match_dup 2)))]
3220 ""
cffb2a26 3221 [(set_attr "conds" "clob")
1b7da4ac 3222 (set_attr "length" "8,12")
3223 (set_attr "type" "multiple")]
cffb2a26 3224)
9c08d1fa 3225
8b9dc177 3226(define_expand "sminsi3"
3227 [(parallel [
3934ae0e 3228 (set (match_operand:SI 0 "s_register_operand")
3229 (smin:SI (match_operand:SI 1 "s_register_operand")
3230 (match_operand:SI 2 "arm_rhs_operand")))
8b9dc177 3231 (clobber (reg:CC CC_REGNUM))])]
25f905c2 3232 "TARGET_32BIT"
8b9dc177 3233 "
3234 if (operands[2] == const0_rtx)
3235 {
3236 /* No need for a clobber of the condition code register here. */
d1f9b275 3237 emit_insn (gen_rtx_SET (operands[0],
8b9dc177 3238 gen_rtx_SMIN (SImode, operands[1],
3239 operands[2])));
3240 DONE;
3241 }
3242")
3243
3244(define_insn "*smin_0"
3245 [(set (match_operand:SI 0 "s_register_operand" "=r")
3246 (smin:SI (match_operand:SI 1 "s_register_operand" "r")
3247 (const_int 0)))]
25f905c2 3248 "TARGET_32BIT"
8b9dc177 3249 "and%?\\t%0, %1, %1, asr #31"
d952d547 3250 [(set_attr "predicable" "yes")
1b7da4ac 3251 (set_attr "type" "logic_shift_reg")]
8b9dc177 3252)
3253
3dc953f2 3254(define_insn_and_split "*arm_smin_insn"
8b9dc177 3255 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3256 (smin:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3257 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
bd5b4116 3258 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3259 "TARGET_ARM"
3dc953f2 3260 "#"
3261 ; cmp\\t%1, %2\;movge\\t%0, %2
3262 ; cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
3263 "TARGET_ARM"
3264 [(set (reg:CC CC_REGNUM)
3265 (compare:CC (match_dup 1) (match_dup 2)))
3266 (set (match_dup 0)
3267 (if_then_else:SI (lt:SI (reg:CC CC_REGNUM) (const_int 0))
3268 (match_dup 1)
3269 (match_dup 2)))]
3270 ""
0d66636f 3271 [(set_attr "conds" "clob")
1b7da4ac 3272 (set_attr "length" "8,12")
3273 (set_attr "type" "multiple,multiple")]
0d66636f 3274)
9c08d1fa 3275
25f905c2 3276(define_expand "umaxsi3"
3277 [(parallel [
3934ae0e 3278 (set (match_operand:SI 0 "s_register_operand")
3279 (umax:SI (match_operand:SI 1 "s_register_operand")
3280 (match_operand:SI 2 "arm_rhs_operand")))
25f905c2 3281 (clobber (reg:CC CC_REGNUM))])]
3282 "TARGET_32BIT"
3283 ""
3284)
3285
3dc953f2 3286(define_insn_and_split "*arm_umaxsi3"
9c08d1fa 3287 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3288 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3289 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 3290 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3291 "TARGET_ARM"
3dc953f2 3292 "#"
3293 ; cmp\\t%1, %2\;movcc\\t%0, %2
3294 ; cmp\\t%1, %2\;movcs\\t%0, %1
3295 ; cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
3296 "TARGET_ARM"
3297 [(set (reg:CC CC_REGNUM)
3298 (compare:CC (match_dup 1) (match_dup 2)))
3299 (set (match_dup 0)
3300 (if_then_else:SI (geu:SI (reg:CC CC_REGNUM) (const_int 0))
3301 (match_dup 1)
3302 (match_dup 2)))]
3303 ""
0d66636f 3304 [(set_attr "conds" "clob")
1b7da4ac 3305 (set_attr "length" "8,8,12")
9f2c2a36 3306 (set_attr "type" "store_4")]
0d66636f 3307)
9c08d1fa 3308
25f905c2 3309(define_expand "uminsi3"
3310 [(parallel [
3934ae0e 3311 (set (match_operand:SI 0 "s_register_operand")
3312 (umin:SI (match_operand:SI 1 "s_register_operand")
3313 (match_operand:SI 2 "arm_rhs_operand")))
25f905c2 3314 (clobber (reg:CC CC_REGNUM))])]
3315 "TARGET_32BIT"
3316 ""
3317)
3318
3dc953f2 3319(define_insn_and_split "*arm_uminsi3"
9c08d1fa 3320 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3321 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3322 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 3323 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3324 "TARGET_ARM"
3dc953f2 3325 "#"
3326 ; cmp\\t%1, %2\;movcs\\t%0, %2
3327 ; cmp\\t%1, %2\;movcc\\t%0, %1
3328 ; cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
3329 "TARGET_ARM"
3330 [(set (reg:CC CC_REGNUM)
3331 (compare:CC (match_dup 1) (match_dup 2)))
3332 (set (match_dup 0)
3333 (if_then_else:SI (ltu:SI (reg:CC CC_REGNUM) (const_int 0))
3334 (match_dup 1)
3335 (match_dup 2)))]
3336 ""
0d66636f 3337 [(set_attr "conds" "clob")
1b7da4ac 3338 (set_attr "length" "8,8,12")
9f2c2a36 3339 (set_attr "type" "store_4")]
0d66636f 3340)
9c08d1fa 3341
8a18b90c 3342(define_insn "*store_minmaxsi"
9c08d1fa 3343 [(set (match_operand:SI 0 "memory_operand" "=m")
3344 (match_operator:SI 3 "minmax_operator"
3345 [(match_operand:SI 1 "s_register_operand" "r")
3346 (match_operand:SI 2 "s_register_operand" "r")]))
bd5b4116 3347 (clobber (reg:CC CC_REGNUM))]
b207d152 3348 "TARGET_32BIT && optimize_function_for_size_p (cfun) && !arm_restrict_it"
9c08d1fa 3349 "*
dc55b8a9 3350 operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
3351 operands[1], operands[2]);
e2348bcb 3352 output_asm_insn (\"cmp\\t%1, %2\", operands);
25f905c2 3353 if (TARGET_THUMB2)
3354 output_asm_insn (\"ite\t%d3\", operands);
e2348bcb 3355 output_asm_insn (\"str%d3\\t%1, %0\", operands);
3356 output_asm_insn (\"str%D3\\t%2, %0\", operands);
3357 return \"\";
0d66636f 3358 "
3359 [(set_attr "conds" "clob")
25f905c2 3360 (set (attr "length")
3361 (if_then_else (eq_attr "is_thumb" "yes")
3362 (const_int 14)
3363 (const_int 12)))
9f2c2a36 3364 (set_attr "type" "store_4")]
0d66636f 3365)
9c08d1fa 3366
8a18b90c 3367; Reject the frame pointer in operand[1], since reloading this after
3368; it has been eliminated can cause carnage.
f7fbdd4a 3369(define_insn "*minmax_arithsi"
9c08d1fa 3370 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3371 (match_operator:SI 4 "shiftable_operator"
3372 [(match_operator:SI 5 "minmax_operator"
3373 [(match_operand:SI 2 "s_register_operand" "r,r")
3374 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
3375 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 3376 (clobber (reg:CC CC_REGNUM))]
7c36fe71 3377 "TARGET_32BIT && !arm_eliminable_register (operands[1]) && !arm_restrict_it"
9c08d1fa 3378 "*
0d66636f 3379 {
3380 enum rtx_code code = GET_CODE (operands[4]);
25f905c2 3381 bool need_else;
3382
3383 if (which_alternative != 0 || operands[3] != const0_rtx
ca0fc5a2 3384 || (code != PLUS && code != IOR && code != XOR))
25f905c2 3385 need_else = true;
3386 else
3387 need_else = false;
0d66636f 3388
dc55b8a9 3389 operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
3390 operands[2], operands[3]);
0d66636f 3391 output_asm_insn (\"cmp\\t%2, %3\", operands);
25f905c2 3392 if (TARGET_THUMB2)
3393 {
3394 if (need_else)
3395 output_asm_insn (\"ite\\t%d5\", operands);
3396 else
3397 output_asm_insn (\"it\\t%d5\", operands);
3398 }
0d66636f 3399 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
25f905c2 3400 if (need_else)
0d66636f 3401 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
3402 return \"\";
215b30b3 3403 }"
0d66636f 3404 [(set_attr "conds" "clob")
25f905c2 3405 (set (attr "length")
3406 (if_then_else (eq_attr "is_thumb" "yes")
3407 (const_int 14)
1b7da4ac 3408 (const_int 12)))
3409 (set_attr "type" "multiple")]
0d66636f 3410)
9c08d1fa 3411
4164bca1 3412; Reject the frame pointer in operand[1], since reloading this after
3413; it has been eliminated can cause carnage.
3414(define_insn_and_split "*minmax_arithsi_non_canon"
7c36fe71 3415 [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts")
4164bca1 3416 (minus:SI
7c36fe71 3417 (match_operand:SI 1 "s_register_operand" "0,?Ts")
4164bca1 3418 (match_operator:SI 4 "minmax_operator"
7c36fe71 3419 [(match_operand:SI 2 "s_register_operand" "Ts,Ts")
3420 (match_operand:SI 3 "arm_rhs_operand" "TsI,TsI")])))
4164bca1 3421 (clobber (reg:CC CC_REGNUM))]
7c36fe71 3422 "TARGET_32BIT && !arm_eliminable_register (operands[1])
3423 && !(arm_restrict_it && CONST_INT_P (operands[3]))"
4164bca1 3424 "#"
3425 "TARGET_32BIT && !arm_eliminable_register (operands[1]) && reload_completed"
3426 [(set (reg:CC CC_REGNUM)
3427 (compare:CC (match_dup 2) (match_dup 3)))
3428
3429 (cond_exec (match_op_dup 4 [(reg:CC CC_REGNUM) (const_int 0)])
3430 (set (match_dup 0)
3431 (minus:SI (match_dup 1)
3432 (match_dup 2))))
3433 (cond_exec (match_op_dup 5 [(reg:CC CC_REGNUM) (const_int 0)])
3434 (set (match_dup 0)
36ee0cde 3435 (match_dup 6)))]
4164bca1 3436 {
3754d046 3437 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
4164bca1 3438 operands[2], operands[3]);
3439 enum rtx_code rc = minmax_code (operands[4]);
3440 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode,
3441 operands[2], operands[3]);
3442
3443 if (mode == CCFPmode || mode == CCFPEmode)
3444 rc = reverse_condition_maybe_unordered (rc);
3445 else
3446 rc = reverse_condition (rc);
3447 operands[5] = gen_rtx_fmt_ee (rc, SImode, operands[2], operands[3]);
36ee0cde 3448 if (CONST_INT_P (operands[3]))
3449 operands[6] = plus_constant (SImode, operands[1], -INTVAL (operands[3]));
3450 else
3451 operands[6] = gen_rtx_MINUS (SImode, operands[1], operands[3]);
4164bca1 3452 }
3453 [(set_attr "conds" "clob")
3454 (set (attr "length")
3455 (if_then_else (eq_attr "is_thumb" "yes")
3456 (const_int 14)
1b7da4ac 3457 (const_int 12)))
3458 (set_attr "type" "multiple")]
4164bca1 3459)
3460
b49e3742 3461(define_code_iterator SAT [smin smax])
f0038cf3 3462(define_code_attr SATrev [(smin "smax") (smax "smin")])
b49e3742 3463(define_code_attr SATlo [(smin "1") (smax "2")])
3464(define_code_attr SAThi [(smin "2") (smax "1")])
3465
3466(define_insn "*satsi_<SAT:code>"
3467 [(set (match_operand:SI 0 "s_register_operand" "=r")
f0038cf3 3468 (SAT:SI (<SATrev>:SI (match_operand:SI 3 "s_register_operand" "r")
b49e3742 3469 (match_operand:SI 1 "const_int_operand" "i"))
3470 (match_operand:SI 2 "const_int_operand" "i")))]
f0038cf3 3471 "TARGET_32BIT && arm_arch6
b49e3742 3472 && arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>], NULL, NULL)"
3473{
3474 int mask;
3475 bool signed_sat;
3476 if (!arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>],
3477 &mask, &signed_sat))
3478 gcc_unreachable ();
3479
3480 operands[1] = GEN_INT (mask);
3481 if (signed_sat)
3482 return "ssat%?\t%0, %1, %3";
3483 else
3484 return "usat%?\t%0, %1, %3";
3485}
7c36fe71 3486 [(set_attr "predicable" "yes")
1b7da4ac 3487 (set_attr "type" "alus_imm")]
bebe9bbb 3488)
b49e3742 3489
3490(define_insn "*satsi_<SAT:code>_shift"
3491 [(set (match_operand:SI 0 "s_register_operand" "=r")
f0038cf3 3492 (SAT:SI (<SATrev>:SI (match_operator:SI 3 "sat_shift_operator"
b49e3742 3493 [(match_operand:SI 4 "s_register_operand" "r")
3494 (match_operand:SI 5 "const_int_operand" "i")])
3495 (match_operand:SI 1 "const_int_operand" "i"))
3496 (match_operand:SI 2 "const_int_operand" "i")))]
f0038cf3 3497 "TARGET_32BIT && arm_arch6
b49e3742 3498 && arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>], NULL, NULL)"
3499{
3500 int mask;
3501 bool signed_sat;
3502 if (!arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>],
3503 &mask, &signed_sat))
3504 gcc_unreachable ();
3505
3506 operands[1] = GEN_INT (mask);
3507 if (signed_sat)
3508 return "ssat%?\t%0, %1, %4%S3";
3509 else
3510 return "usat%?\t%0, %1, %4%S3";
3511}
3512 [(set_attr "predicable" "yes")
b49e3742 3513 (set_attr "shift" "3")
d82e788e 3514 (set_attr "type" "logic_shift_reg")])
b11cae9e 3515\f
3516;; Shift and rotation insns
3517
a2cd141b 3518(define_expand "ashldi3"
3934ae0e 3519 [(set (match_operand:DI 0 "s_register_operand")
3520 (ashift:DI (match_operand:DI 1 "s_register_operand")
8baabb36 3521 (match_operand:SI 2 "reg_or_int_operand")))]
25f905c2 3522 "TARGET_32BIT"
a2cd141b 3523 "
8baabb36 3524 arm_emit_coreregs_64bit_shift (ASHIFT, operands[0], operands[1],
3525 operands[2], gen_reg_rtx (SImode),
3526 gen_reg_rtx (SImode));
3527 DONE;
3528")
a2cd141b 3529
87b22bf7 3530(define_expand "ashlsi3"
3934ae0e 3531 [(set (match_operand:SI 0 "s_register_operand")
3532 (ashift:SI (match_operand:SI 1 "s_register_operand")
3533 (match_operand:SI 2 "arm_rhs_operand")))]
cffb2a26 3534 "TARGET_EITHER"
87b22bf7 3535 "
0438d37f 3536 if (CONST_INT_P (operands[2])
8c4e8755 3537 && (UINTVAL (operands[2])) > 31)
87b22bf7 3538 {
3539 emit_insn (gen_movsi (operands[0], const0_rtx));
3540 DONE;
3541 }
cffb2a26 3542 "
3543)
3544
a2cd141b 3545(define_expand "ashrdi3"
3934ae0e 3546 [(set (match_operand:DI 0 "s_register_operand")
3547 (ashiftrt:DI (match_operand:DI 1 "s_register_operand")
3548 (match_operand:SI 2 "reg_or_int_operand")))]
25f905c2 3549 "TARGET_32BIT"
a2cd141b 3550 "
8baabb36 3551 arm_emit_coreregs_64bit_shift (ASHIFTRT, operands[0], operands[1],
3552 operands[2], gen_reg_rtx (SImode),
3553 gen_reg_rtx (SImode));
3554 DONE;
3555")
a2cd141b 3556
87b22bf7 3557(define_expand "ashrsi3"
3934ae0e 3558 [(set (match_operand:SI 0 "s_register_operand")
3559 (ashiftrt:SI (match_operand:SI 1 "s_register_operand")
3560 (match_operand:SI 2 "arm_rhs_operand")))]
cffb2a26 3561 "TARGET_EITHER"
87b22bf7 3562 "
0438d37f 3563 if (CONST_INT_P (operands[2])
8c4e8755 3564 && UINTVAL (operands[2]) > 31)
87b22bf7 3565 operands[2] = GEN_INT (31);
cffb2a26 3566 "
3567)
3568
a2cd141b 3569(define_expand "lshrdi3"
3934ae0e 3570 [(set (match_operand:DI 0 "s_register_operand")
3571 (lshiftrt:DI (match_operand:DI 1 "s_register_operand")
3572 (match_operand:SI 2 "reg_or_int_operand")))]
25f905c2 3573 "TARGET_32BIT"
a2cd141b 3574 "
8baabb36 3575 arm_emit_coreregs_64bit_shift (LSHIFTRT, operands[0], operands[1],
3576 operands[2], gen_reg_rtx (SImode),
3577 gen_reg_rtx (SImode));
3578 DONE;
3579")
a2cd141b 3580
87b22bf7 3581(define_expand "lshrsi3"
3934ae0e 3582 [(set (match_operand:SI 0 "s_register_operand")
3583 (lshiftrt:SI (match_operand:SI 1 "s_register_operand")
3584 (match_operand:SI 2 "arm_rhs_operand")))]
cffb2a26 3585 "TARGET_EITHER"
87b22bf7 3586 "
0438d37f 3587 if (CONST_INT_P (operands[2])
8c4e8755 3588 && (UINTVAL (operands[2])) > 31)
87b22bf7 3589 {
3590 emit_insn (gen_movsi (operands[0], const0_rtx));
3591 DONE;
3592 }
cffb2a26 3593 "
3594)
3595
87b22bf7 3596(define_expand "rotlsi3"
3934ae0e 3597 [(set (match_operand:SI 0 "s_register_operand")
3598 (rotatert:SI (match_operand:SI 1 "s_register_operand")
3599 (match_operand:SI 2 "reg_or_int_operand")))]
25f905c2 3600 "TARGET_32BIT"
87b22bf7 3601 "
0438d37f 3602 if (CONST_INT_P (operands[2]))
87b22bf7 3603 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
3604 else
b11cae9e 3605 {
87b22bf7 3606 rtx reg = gen_reg_rtx (SImode);
3607 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
3608 operands[2] = reg;
b11cae9e 3609 }
cffb2a26 3610 "
3611)
9c08d1fa 3612
87b22bf7 3613(define_expand "rotrsi3"
3934ae0e 3614 [(set (match_operand:SI 0 "s_register_operand")
3615 (rotatert:SI (match_operand:SI 1 "s_register_operand")
3616 (match_operand:SI 2 "arm_rhs_operand")))]
cffb2a26 3617 "TARGET_EITHER"
87b22bf7 3618 "
25f905c2 3619 if (TARGET_32BIT)
cffb2a26 3620 {
0438d37f 3621 if (CONST_INT_P (operands[2])
8c4e8755 3622 && UINTVAL (operands[2]) > 31)
cffb2a26 3623 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
3624 }
25f905c2 3625 else /* TARGET_THUMB1 */
cffb2a26 3626 {
0438d37f 3627 if (CONST_INT_P (operands [2]))
cffb2a26 3628 operands [2] = force_reg (SImode, operands[2]);
3629 }
3630 "
3631)
87b22bf7 3632
cffb2a26 3633(define_insn "*arm_shiftsi3"
88c29385 3634 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r,r")
cffb2a26 3635 (match_operator:SI 3 "shift_operator"
88c29385 3636 [(match_operand:SI 1 "s_register_operand" "0,l,r,r")
3637 (match_operand:SI 2 "reg_or_int_operand" "l,M,M,r")]))]
25f905c2 3638 "TARGET_32BIT"
3639 "* return arm_output_shift(operands, 0);"
344495ea 3640 [(set_attr "predicable" "yes")
88c29385 3641 (set_attr "arch" "t2,t2,*,*")
3642 (set_attr "predicable_short_it" "yes,yes,no,no")
7c36fe71 3643 (set_attr "length" "4")
331beb1a 3644 (set_attr "shift" "1")
88c29385 3645 (set_attr "type" "alu_shift_reg,alu_shift_imm,alu_shift_imm,alu_shift_reg")]
6c4c2133 3646)
87b22bf7 3647
f7fbdd4a 3648(define_insn "*shiftsi3_compare0"
bd5b4116 3649 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 3650 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
6b6abc9c 3651 [(match_operand:SI 1 "s_register_operand" "r,r")
3652 (match_operand:SI 2 "arm_rhs_operand" "M,r")])
9c08d1fa 3653 (const_int 0)))
6b6abc9c 3654 (set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 3655 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
25f905c2 3656 "TARGET_32BIT"
3657 "* return arm_output_shift(operands, 1);"
344495ea 3658 [(set_attr "conds" "set")
331beb1a 3659 (set_attr "shift" "1")
d82e788e 3660 (set_attr "type" "alus_shift_imm,alus_shift_reg")]
0d66636f 3661)
9c08d1fa 3662
f7fbdd4a 3663(define_insn "*shiftsi3_compare0_scratch"
bd5b4116 3664 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 3665 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
6b6abc9c 3666 [(match_operand:SI 1 "s_register_operand" "r,r")
3667 (match_operand:SI 2 "arm_rhs_operand" "M,r")])
9c08d1fa 3668 (const_int 0)))
6b6abc9c 3669 (clobber (match_scratch:SI 0 "=r,r"))]
25f905c2 3670 "TARGET_32BIT"
3671 "* return arm_output_shift(operands, 1);"
344495ea 3672 [(set_attr "conds" "set")
6b6abc9c 3673 (set_attr "shift" "1")
d82e788e 3674 (set_attr "type" "shift_imm,shift_reg")]
0d66636f 3675)
9c08d1fa 3676
d5d4dc8d 3677(define_insn "*not_shiftsi"
3678 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 3679 (not:SI (match_operator:SI 3 "shift_operator"
d5d4dc8d 3680 [(match_operand:SI 1 "s_register_operand" "r,r")
3681 (match_operand:SI 2 "shift_amount_operand" "M,rM")])))]
3682 "TARGET_32BIT"
6c4c2133 3683 "mvn%?\\t%0, %1%S3"
344495ea 3684 [(set_attr "predicable" "yes")
331beb1a 3685 (set_attr "shift" "1")
d5d4dc8d 3686 (set_attr "arch" "32,a")
1aed5204 3687 (set_attr "type" "mvn_shift,mvn_shift_reg")])
9c08d1fa 3688
d5d4dc8d 3689(define_insn "*not_shiftsi_compare0"
bd5b4116 3690 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 3691 (compare:CC_NOOV
3692 (not:SI (match_operator:SI 3 "shift_operator"
3693 [(match_operand:SI 1 "s_register_operand" "r,r")
3694 (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
3695 (const_int 0)))
3696 (set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 3697 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
d5d4dc8d 3698 "TARGET_32BIT"
3ef90e77 3699 "mvns%?\\t%0, %1%S3"
344495ea 3700 [(set_attr "conds" "set")
331beb1a 3701 (set_attr "shift" "1")
d5d4dc8d 3702 (set_attr "arch" "32,a")
1aed5204 3703 (set_attr "type" "mvn_shift,mvn_shift_reg")])
9c08d1fa 3704
d5d4dc8d 3705(define_insn "*not_shiftsi_compare0_scratch"
bd5b4116 3706 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 3707 (compare:CC_NOOV
3708 (not:SI (match_operator:SI 3 "shift_operator"
3709 [(match_operand:SI 1 "s_register_operand" "r,r")
3710 (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
3711 (const_int 0)))
3712 (clobber (match_scratch:SI 0 "=r,r"))]
3713 "TARGET_32BIT"
3ef90e77 3714 "mvns%?\\t%0, %1%S3"
344495ea 3715 [(set_attr "conds" "set")
331beb1a 3716 (set_attr "shift" "1")
d5d4dc8d 3717 (set_attr "arch" "32,a")
1aed5204 3718 (set_attr "type" "mvn_shift,mvn_shift_reg")])
9c08d1fa 3719
cffb2a26 3720;; We don't really have extzv, but defining this using shifts helps
3721;; to reduce register pressure later on.
3722
3723(define_expand "extzv"
3934ae0e 3724 [(set (match_operand 0 "s_register_operand")
3725 (zero_extract (match_operand 1 "nonimmediate_operand")
3726 (match_operand 2 "const_int_operand")
3727 (match_operand 3 "const_int_operand")))]
8b054d5a 3728 "TARGET_THUMB1 || arm_arch_thumb2"
cffb2a26 3729 "
3730 {
3731 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
3732 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
3733
8b054d5a 3734 if (arm_arch_thumb2)
3735 {
eb04cafb 3736 HOST_WIDE_INT width = INTVAL (operands[2]);
3737 HOST_WIDE_INT bitpos = INTVAL (operands[3]);
3738
3739 if (unaligned_access && MEM_P (operands[1])
3740 && (width == 16 || width == 32) && (bitpos % BITS_PER_UNIT) == 0)
3741 {
3742 rtx base_addr;
3743
3744 if (BYTES_BIG_ENDIAN)
3745 bitpos = GET_MODE_BITSIZE (GET_MODE (operands[0])) - width
3746 - bitpos;
3747
3748 if (width == 32)
3749 {
3750 base_addr = adjust_address (operands[1], SImode,
3751 bitpos / BITS_PER_UNIT);
3752 emit_insn (gen_unaligned_loadsi (operands[0], base_addr));
3753 }
3754 else
3755 {
3756 rtx dest = operands[0];
3757 rtx tmp = gen_reg_rtx (SImode);
3758
3759 /* We may get a paradoxical subreg here. Strip it off. */
3760 if (GET_CODE (dest) == SUBREG
3761 && GET_MODE (dest) == SImode
3762 && GET_MODE (SUBREG_REG (dest)) == HImode)
3763 dest = SUBREG_REG (dest);
3764
3765 if (GET_MODE_BITSIZE (GET_MODE (dest)) != width)
3766 FAIL;
3767
3768 base_addr = adjust_address (operands[1], HImode,
3769 bitpos / BITS_PER_UNIT);
3770 emit_insn (gen_unaligned_loadhiu (tmp, base_addr));
3771 emit_move_insn (gen_lowpart (SImode, dest), tmp);
3772 }
3773 DONE;
3774 }
3775 else if (s_register_operand (operands[1], GET_MODE (operands[1])))
3776 {
3777 emit_insn (gen_extzv_t2 (operands[0], operands[1], operands[2],
3778 operands[3]));
3779 DONE;
3780 }
3781 else
3782 FAIL;
8b054d5a 3783 }
eb04cafb 3784
3785 if (!s_register_operand (operands[1], GET_MODE (operands[1])))
3786 FAIL;
8b054d5a 3787
cffb2a26 3788 operands[3] = GEN_INT (rshift);
3789
3790 if (lshift == 0)
3791 {
3792 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
3793 DONE;
3794 }
3795
eb04cafb 3796 emit_insn (gen_extzv_t1 (operands[0], operands[1], GEN_INT (lshift),
3797 operands[3], gen_reg_rtx (SImode)));
3798 DONE;
215b30b3 3799 }"
cffb2a26 3800)
3801
eb04cafb 3802;; Helper for extzv, for the Thumb-1 register-shifts case.
3803
3804(define_expand "extzv_t1"
3934ae0e 3805 [(set (match_operand:SI 4 "s_register_operand")
3806 (ashift:SI (match_operand:SI 1 "nonimmediate_operand")
3807 (match_operand:SI 2 "const_int_operand")))
3808 (set (match_operand:SI 0 "s_register_operand")
eb04cafb 3809 (lshiftrt:SI (match_dup 4)
3934ae0e 3810 (match_operand:SI 3 "const_int_operand")))]
eb04cafb 3811 "TARGET_THUMB1"
3812 "")
3813
3814(define_expand "extv"
3934ae0e 3815 [(set (match_operand 0 "s_register_operand")
3816 (sign_extract (match_operand 1 "nonimmediate_operand")
3817 (match_operand 2 "const_int_operand")
3818 (match_operand 3 "const_int_operand")))]
eb04cafb 3819 "arm_arch_thumb2"
3820{
3821 HOST_WIDE_INT width = INTVAL (operands[2]);
3822 HOST_WIDE_INT bitpos = INTVAL (operands[3]);
3823
3824 if (unaligned_access && MEM_P (operands[1]) && (width == 16 || width == 32)
3825 && (bitpos % BITS_PER_UNIT) == 0)
3826 {
3827 rtx base_addr;
3828
3829 if (BYTES_BIG_ENDIAN)
3830 bitpos = GET_MODE_BITSIZE (GET_MODE (operands[0])) - width - bitpos;
3831
3832 if (width == 32)
3833 {
3834 base_addr = adjust_address (operands[1], SImode,
3835 bitpos / BITS_PER_UNIT);
3836 emit_insn (gen_unaligned_loadsi (operands[0], base_addr));
3837 }
3838 else
3839 {
3840 rtx dest = operands[0];
3841 rtx tmp = gen_reg_rtx (SImode);
3842
3843 /* We may get a paradoxical subreg here. Strip it off. */
3844 if (GET_CODE (dest) == SUBREG
3845 && GET_MODE (dest) == SImode
3846 && GET_MODE (SUBREG_REG (dest)) == HImode)
3847 dest = SUBREG_REG (dest);
3848
3849 if (GET_MODE_BITSIZE (GET_MODE (dest)) != width)
3850 FAIL;
3851
3852 base_addr = adjust_address (operands[1], HImode,
3853 bitpos / BITS_PER_UNIT);
3854 emit_insn (gen_unaligned_loadhis (tmp, base_addr));
3855 emit_move_insn (gen_lowpart (SImode, dest), tmp);
3856 }
3857
3858 DONE;
3859 }
3860 else if (!s_register_operand (operands[1], GET_MODE (operands[1])))
3861 FAIL;
3862 else if (GET_MODE (operands[0]) == SImode
3863 && GET_MODE (operands[1]) == SImode)
3864 {
3865 emit_insn (gen_extv_regsi (operands[0], operands[1], operands[2],
3866 operands[3]));
3867 DONE;
3868 }
3869
3870 FAIL;
3871})
3872
3873; Helper to expand register forms of extv with the proper modes.
3874
3875(define_expand "extv_regsi"
3934ae0e 3876 [(set (match_operand:SI 0 "s_register_operand")
3877 (sign_extract:SI (match_operand:SI 1 "s_register_operand")
3878 (match_operand 2 "const_int_operand")
3879 (match_operand 3 "const_int_operand")))]
eb04cafb 3880 ""
3881{
3882})
3883
3884; ARMv6+ unaligned load/store instructions (used for packed structure accesses).
3885
122f262a 3886(define_insn "unaligned_loaddi"
3887 [(set (match_operand:DI 0 "s_register_operand" "=r")
3888 (unspec:DI [(match_operand:DI 1 "memory_operand" "m")]
3889 UNSPEC_UNALIGNED_LOAD))]
3890 "TARGET_32BIT && TARGET_LDRD"
3891 "*
3892 return output_move_double (operands, true, NULL);
3893 "
3894 [(set_attr "length" "8")
3895 (set_attr "type" "load_8")])
3896
eb04cafb 3897(define_insn "unaligned_loadsi"
70ce330a 3898 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
3899 (unspec:SI [(match_operand:SI 1 "memory_operand" "m,Uw,m")]
eb04cafb 3900 UNSPEC_UNALIGNED_LOAD))]
8fe38eb2 3901 "unaligned_access"
70ce330a 3902 "@
3903 ldr\t%0, %1\t@ unaligned
3904 ldr%?\t%0, %1\t@ unaligned
3905 ldr%?\t%0, %1\t@ unaligned"
3906 [(set_attr "arch" "t1,t2,32")
3907 (set_attr "length" "2,2,4")
3908 (set_attr "predicable" "no,yes,yes")
3909 (set_attr "predicable_short_it" "no,yes,no")
9f2c2a36 3910 (set_attr "type" "load_4")])
eb04cafb 3911
70ce330a 3912;; The 16-bit Thumb1 variant of ldrsh requires two registers in the
3913;; address (there's no immediate format). That's tricky to support
3914;; here and we don't really need this pattern for that case, so only
3915;; enable for 32-bit ISAs.
eb04cafb 3916(define_insn "unaligned_loadhis"
5d79b75e 3917 [(set (match_operand:SI 0 "s_register_operand" "=r")
eb04cafb 3918 (sign_extend:SI
5d79b75e 3919 (unspec:HI [(match_operand:HI 1 "memory_operand" "Uh")]
eb04cafb 3920 UNSPEC_UNALIGNED_LOAD)))]
70ce330a 3921 "unaligned_access && TARGET_32BIT"
3ef90e77 3922 "ldrsh%?\t%0, %1\t@ unaligned"
5d79b75e 3923 [(set_attr "predicable" "yes")
eb04cafb 3924 (set_attr "type" "load_byte")])
3925
3926(define_insn "unaligned_loadhiu"
70ce330a 3927 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
eb04cafb 3928 (zero_extend:SI
70ce330a 3929 (unspec:HI [(match_operand:HI 1 "memory_operand" "m,Uw,m")]
eb04cafb 3930 UNSPEC_UNALIGNED_LOAD)))]
8fe38eb2 3931 "unaligned_access"
70ce330a 3932 "@
3933 ldrh\t%0, %1\t@ unaligned
3934 ldrh%?\t%0, %1\t@ unaligned
3935 ldrh%?\t%0, %1\t@ unaligned"
3936 [(set_attr "arch" "t1,t2,32")
3937 (set_attr "length" "2,2,4")
3938 (set_attr "predicable" "no,yes,yes")
3939 (set_attr "predicable_short_it" "no,yes,no")
eb04cafb 3940 (set_attr "type" "load_byte")])
3941
122f262a 3942(define_insn "unaligned_storedi"
3943 [(set (match_operand:DI 0 "memory_operand" "=m")
3944 (unspec:DI [(match_operand:DI 1 "s_register_operand" "r")]
3945 UNSPEC_UNALIGNED_STORE))]
3946 "TARGET_32BIT && TARGET_LDRD"
3947 "*
3948 return output_move_double (operands, true, NULL);
3949 "
3950 [(set_attr "length" "8")
3951 (set_attr "type" "store_8")])
3952
eb04cafb 3953(define_insn "unaligned_storesi"
70ce330a 3954 [(set (match_operand:SI 0 "memory_operand" "=m,Uw,m")
3955 (unspec:SI [(match_operand:SI 1 "s_register_operand" "l,l,r")]
eb04cafb 3956 UNSPEC_UNALIGNED_STORE))]
8fe38eb2 3957 "unaligned_access"
70ce330a 3958 "@
3959 str\t%1, %0\t@ unaligned
3960 str%?\t%1, %0\t@ unaligned
3961 str%?\t%1, %0\t@ unaligned"
3962 [(set_attr "arch" "t1,t2,32")
3963 (set_attr "length" "2,2,4")
3964 (set_attr "predicable" "no,yes,yes")
3965 (set_attr "predicable_short_it" "no,yes,no")
9f2c2a36 3966 (set_attr "type" "store_4")])
eb04cafb 3967
3968(define_insn "unaligned_storehi"
70ce330a 3969 [(set (match_operand:HI 0 "memory_operand" "=m,Uw,m")
3970 (unspec:HI [(match_operand:HI 1 "s_register_operand" "l,l,r")]
eb04cafb 3971 UNSPEC_UNALIGNED_STORE))]
8fe38eb2 3972 "unaligned_access"
70ce330a 3973 "@
3974 strh\t%1, %0\t@ unaligned
3975 strh%?\t%1, %0\t@ unaligned
3976 strh%?\t%1, %0\t@ unaligned"
3977 [(set_attr "arch" "t1,t2,32")
3978 (set_attr "length" "2,2,4")
3979 (set_attr "predicable" "no,yes,yes")
3980 (set_attr "predicable_short_it" "no,yes,no")
9f2c2a36 3981 (set_attr "type" "store_4")])
eb04cafb 3982
ae51a965 3983
eb04cafb 3984(define_insn "*extv_reg"
8b054d5a 3985 [(set (match_operand:SI 0 "s_register_operand" "=r")
3986 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
13051f13 3987 (match_operand:SI 2 "const_int_operand" "n")
3988 (match_operand:SI 3 "const_int_operand" "n")))]
3989 "arm_arch_thumb2
3990 && IN_RANGE (INTVAL (operands[3]), 0, 31)
3991 && IN_RANGE (INTVAL (operands[2]), 1, 32 - INTVAL (operands[3]))"
8b054d5a 3992 "sbfx%?\t%0, %1, %3, %2"
3993 [(set_attr "length" "4")
d952d547 3994 (set_attr "predicable" "yes")
d82e788e 3995 (set_attr "type" "bfm")]
8b054d5a 3996)
3997
3998(define_insn "extzv_t2"
3999 [(set (match_operand:SI 0 "s_register_operand" "=r")
4000 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "r")
13051f13 4001 (match_operand:SI 2 "const_int_operand" "n")
4002 (match_operand:SI 3 "const_int_operand" "n")))]
4003 "arm_arch_thumb2
4004 && IN_RANGE (INTVAL (operands[3]), 0, 31)
4005 && IN_RANGE (INTVAL (operands[2]), 1, 32 - INTVAL (operands[3]))"
8b054d5a 4006 "ubfx%?\t%0, %1, %3, %2"
4007 [(set_attr "length" "4")
d952d547 4008 (set_attr "predicable" "yes")
d82e788e 4009 (set_attr "type" "bfm")]
8b054d5a 4010)
4011
7d3cda8c 4012
4013;; Division instructions
4014(define_insn "divsi3"
8f5f2788 4015 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4016 (div:SI (match_operand:SI 1 "s_register_operand" "r,r")
4017 (match_operand:SI 2 "s_register_operand" "r,r")))]
7d3cda8c 4018 "TARGET_IDIV"
8f5f2788 4019 "@
4020 sdiv%?\t%0, %1, %2
4021 sdiv\t%0, %1, %2"
4022 [(set_attr "arch" "32,v8mb")
4023 (set_attr "predicable" "yes")
9da0ec36 4024 (set_attr "type" "sdiv")]
7d3cda8c 4025)
4026
4027(define_insn "udivsi3"
8f5f2788 4028 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4029 (udiv:SI (match_operand:SI 1 "s_register_operand" "r,r")
4030 (match_operand:SI 2 "s_register_operand" "r,r")))]
7d3cda8c 4031 "TARGET_IDIV"
8f5f2788 4032 "@
4033 udiv%?\t%0, %1, %2
4034 udiv\t%0, %1, %2"
4035 [(set_attr "arch" "32,v8mb")
4036 (set_attr "predicable" "yes")
9da0ec36 4037 (set_attr "type" "udiv")]
7d3cda8c 4038)
4039
b11cae9e 4040\f
4041;; Unary arithmetic insns
4042
f6c98a9a 4043(define_expand "negvsi3"
4044 [(match_operand:SI 0 "register_operand")
4045 (match_operand:SI 1 "register_operand")
4046 (match_operand 2 "")]
4047 "TARGET_32BIT"
4048{
4049 emit_insn (gen_subsi3_compare (operands[0], const0_rtx, operands[1]));
4050 arm_gen_unlikely_cbranch (NE, CC_Vmode, operands[2]);
4051
4052 DONE;
4053})
4054
4055(define_expand "negvdi3"
e62551fd 4056 [(match_operand:DI 0 "s_register_operand")
4057 (match_operand:DI 1 "s_register_operand")
f6c98a9a 4058 (match_operand 2 "")]
4059 "TARGET_ARM"
4060{
4061 emit_insn (gen_negdi2_compare (operands[0], operands[1]));
4062 arm_gen_unlikely_cbranch (NE, CC_Vmode, operands[2]);
4063
4064 DONE;
4065})
4066
4067
e62551fd 4068(define_insn "negdi2_compare"
f6c98a9a 4069 [(set (reg:CC CC_REGNUM)
4070 (compare:CC
4071 (const_int 0)
e62551fd 4072 (match_operand:DI 1 "register_operand" "r,r")))
4073 (set (match_operand:DI 0 "register_operand" "=&r,&r")
f6c98a9a 4074 (minus:DI (const_int 0) (match_dup 1)))]
4075 "TARGET_ARM"
e62551fd 4076 "@
4077 rsbs\\t%Q0, %Q1, #0;rscs\\t%R0, %R1, #0
4078 rsbs\\t%Q0, %Q1, #0;sbcs\\t%R0, %R1, %R1, lsl #1"
f6c98a9a 4079 [(set_attr "conds" "set")
e62551fd 4080 (set_attr "arch" "a,t2")
f6c98a9a 4081 (set_attr "length" "8")
4082 (set_attr "type" "multiple")]
4083)
4084
cffb2a26 4085(define_expand "negsi2"
3934ae0e 4086 [(set (match_operand:SI 0 "s_register_operand")
4087 (neg:SI (match_operand:SI 1 "s_register_operand")))]
cffb2a26 4088 "TARGET_EITHER"
b11cae9e 4089 ""
cffb2a26 4090)
4091
4092(define_insn "*arm_negsi2"
d952d547 4093 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4094 (neg:SI (match_operand:SI 1 "s_register_operand" "l,r")))]
25f905c2 4095 "TARGET_32BIT"
cffb2a26 4096 "rsb%?\\t%0, %1, #0"
d952d547 4097 [(set_attr "predicable" "yes")
4098 (set_attr "predicable_short_it" "yes,no")
4099 (set_attr "arch" "t2,*")
1b7da4ac 4100 (set_attr "length" "4")
7724f74b 4101 (set_attr "type" "alu_imm")]
4102)
4103
4104;; To keep the comparison in canonical form we express it as (~reg cmp ~0)
4105;; rather than (0 cmp reg). This gives the same results for unsigned
4106;; and equality compares which is what we mostly need here.
4107(define_insn "negsi2_0compare"
4108 [(set (reg:CC_RSB CC_REGNUM)
4109 (compare:CC_RSB (not:SI (match_operand:SI 1 "s_register_operand" "l,r"))
4110 (const_int -1)))
4111 (set (match_operand:SI 0 "s_register_operand" "=l,r")
4112 (neg:SI (match_dup 1)))]
4113 "TARGET_32BIT"
4114 "@
4115 negs\\t%0, %1
4116 rsbs\\t%0, %1, #0"
4117 [(set_attr "conds" "set")
4118 (set_attr "arch" "t2,*")
4119 (set_attr "length" "2,*")
4120 (set_attr "type" "alus_imm")]
4121)
4122
4123(define_insn "negsi2_carryin"
4124 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4125 (minus:SI (neg:SI (match_operand:SI 1 "s_register_operand" "r,r"))
4126 (match_operand:SI 2 "arm_borrow_operation" "")))]
4127 "TARGET_32BIT"
4128 "@
4129 rsc\\t%0, %1, #0
4130 sbc\\t%0, %1, %1, lsl #1"
4131 [(set_attr "conds" "use")
4132 (set_attr "arch" "a,t2")
4133 (set_attr "type" "adc_imm,adc_reg")]
cffb2a26 4134)
4135
604f3a0a 4136(define_expand "negsf2"
3934ae0e 4137 [(set (match_operand:SF 0 "s_register_operand")
4138 (neg:SF (match_operand:SF 1 "s_register_operand")))]
d7216193 4139 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 4140 ""
4141)
4142
4143(define_expand "negdf2"
3934ae0e 4144 [(set (match_operand:DF 0 "s_register_operand")
4145 (neg:DF (match_operand:DF 1 "s_register_operand")))]
994606f8 4146 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
604f3a0a 4147 "")
4148
9c08d1fa 4149;; abssi2 doesn't really clobber the condition codes if a different register
4150;; is being set. To keep things simple, assume during rtl manipulations that
4151;; it does, but tell the final scan operator the truth. Similarly for
4152;; (neg (abs...))
4153
604f3a0a 4154(define_expand "abssi2"
4155 [(parallel
3934ae0e 4156 [(set (match_operand:SI 0 "s_register_operand")
4157 (abs:SI (match_operand:SI 1 "s_register_operand")))
ba156559 4158 (clobber (match_dup 2))])]
4159 "TARGET_EITHER"
4160 "
25f905c2 4161 if (TARGET_THUMB1)
ba156559 4162 operands[2] = gen_rtx_SCRATCH (SImode);
4163 else
4164 operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
4165")
604f3a0a 4166
ba6a3b2f 4167(define_insn_and_split "*arm_abssi2"
ba156559 4168 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
9c08d1fa 4169 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
bd5b4116 4170 (clobber (reg:CC CC_REGNUM))]
cffb2a26 4171 "TARGET_ARM"
ba6a3b2f 4172 "#"
4173 "&& reload_completed"
4174 [(const_int 0)]
4175 {
4176 /* if (which_alternative == 0) */
4177 if (REGNO(operands[0]) == REGNO(operands[1]))
4178 {
4179 /* Emit the pattern:
4180 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
4181 [(set (reg:CC CC_REGNUM)
4182 (compare:CC (match_dup 0) (const_int 0)))
4183 (cond_exec (lt:CC (reg:CC CC_REGNUM) (const_int 0))
4184 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 1))))]
4185 */
d1f9b275 4186 emit_insn (gen_rtx_SET (gen_rtx_REG (CCmode, CC_REGNUM),
ba6a3b2f 4187 gen_rtx_COMPARE (CCmode, operands[0], const0_rtx)));
4188 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
4189 (gen_rtx_LT (SImode,
4190 gen_rtx_REG (CCmode, CC_REGNUM),
4191 const0_rtx)),
d1f9b275 4192 (gen_rtx_SET (operands[0],
ba6a3b2f 4193 (gen_rtx_MINUS (SImode,
4194 const0_rtx,
4195 operands[1]))))));
4196 DONE;
4197 }
4198 else
4199 {
4200 /* Emit the pattern:
4201 alt1: eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31
4202 [(set (match_dup 0)
4203 (xor:SI (match_dup 1)
4204 (ashiftrt:SI (match_dup 1) (const_int 31))))
4205 (set (match_dup 0)
4206 (minus:SI (match_dup 0)
4207 (ashiftrt:SI (match_dup 1) (const_int 31))))]
4208 */
d1f9b275 4209 emit_insn (gen_rtx_SET (operands[0],
ba6a3b2f 4210 gen_rtx_XOR (SImode,
4211 gen_rtx_ASHIFTRT (SImode,
4212 operands[1],
4213 GEN_INT (31)),
4214 operands[1])));
d1f9b275 4215 emit_insn (gen_rtx_SET (operands[0],
ba6a3b2f 4216 gen_rtx_MINUS (SImode,
4217 operands[0],
4218 gen_rtx_ASHIFTRT (SImode,
4219 operands[1],
4220 GEN_INT (31)))));
4221 DONE;
4222 }
4223 }
cffb2a26 4224 [(set_attr "conds" "clob,*")
331beb1a 4225 (set_attr "shift" "1")
2ad08b65 4226 (set_attr "predicable" "no, yes")
1b7da4ac 4227 (set_attr "length" "8")
4228 (set_attr "type" "multiple")]
cffb2a26 4229)
9c08d1fa 4230
ba6a3b2f 4231(define_insn_and_split "*arm_neg_abssi2"
9c08d1fa 4232 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
4233 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
bd5b4116 4234 (clobber (reg:CC CC_REGNUM))]
cffb2a26 4235 "TARGET_ARM"
ba6a3b2f 4236 "#"
4237 "&& reload_completed"
4238 [(const_int 0)]
4239 {
4240 /* if (which_alternative == 0) */
4241 if (REGNO (operands[0]) == REGNO (operands[1]))
4242 {
4243 /* Emit the pattern:
4244 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
4245 */
d1f9b275 4246 emit_insn (gen_rtx_SET (gen_rtx_REG (CCmode, CC_REGNUM),
ba6a3b2f 4247 gen_rtx_COMPARE (CCmode, operands[0], const0_rtx)));
4248 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
4249 gen_rtx_GT (SImode,
4250 gen_rtx_REG (CCmode, CC_REGNUM),
4251 const0_rtx),
d1f9b275 4252 gen_rtx_SET (operands[0],
ba6a3b2f 4253 (gen_rtx_MINUS (SImode,
4254 const0_rtx,
4255 operands[1])))));
4256 }
4257 else
4258 {
4259 /* Emit the pattern:
4260 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31
4261 */
d1f9b275 4262 emit_insn (gen_rtx_SET (operands[0],
ba6a3b2f 4263 gen_rtx_XOR (SImode,
4264 gen_rtx_ASHIFTRT (SImode,
4265 operands[1],
4266 GEN_INT (31)),
4267 operands[1])));
d1f9b275 4268 emit_insn (gen_rtx_SET (operands[0],
ba6a3b2f 4269 gen_rtx_MINUS (SImode,
4270 gen_rtx_ASHIFTRT (SImode,
4271 operands[1],
4272 GEN_INT (31)),
4273 operands[0])));
4274 }
4275 DONE;
4276 }
cffb2a26 4277 [(set_attr "conds" "clob,*")
331beb1a 4278 (set_attr "shift" "1")
2ad08b65 4279 (set_attr "predicable" "no, yes")
1b7da4ac 4280 (set_attr "length" "8")
4281 (set_attr "type" "multiple")]
cffb2a26 4282)
b11cae9e 4283
604f3a0a 4284(define_expand "abssf2"
3934ae0e 4285 [(set (match_operand:SF 0 "s_register_operand")
4286 (abs:SF (match_operand:SF 1 "s_register_operand")))]
25f905c2 4287 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 4288 "")
4289
604f3a0a 4290(define_expand "absdf2"
3934ae0e 4291 [(set (match_operand:DF 0 "s_register_operand")
4292 (abs:DF (match_operand:DF 1 "s_register_operand")))]
a50d7267 4293 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 4294 "")
4295
7db9af5d 4296(define_expand "sqrtsf2"
3934ae0e 4297 [(set (match_operand:SF 0 "s_register_operand")
4298 (sqrt:SF (match_operand:SF 1 "s_register_operand")))]
d7216193 4299 "TARGET_32BIT && TARGET_HARD_FLOAT"
7db9af5d 4300 "")
9c08d1fa 4301
7db9af5d 4302(define_expand "sqrtdf2"
3934ae0e 4303 [(set (match_operand:DF 0 "s_register_operand")
4304 (sqrt:DF (match_operand:DF 1 "s_register_operand")))]
994606f8 4305 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
7db9af5d 4306 "")
9c08d1fa 4307
cffb2a26 4308(define_expand "one_cmplsi2"
3934ae0e 4309 [(set (match_operand:SI 0 "s_register_operand")
4310 (not:SI (match_operand:SI 1 "s_register_operand")))]
cffb2a26 4311 "TARGET_EITHER"
b11cae9e 4312 ""
cffb2a26 4313)
4314
4315(define_insn "*arm_one_cmplsi2"
d952d547 4316 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4317 (not:SI (match_operand:SI 1 "s_register_operand" "l,r")))]
25f905c2 4318 "TARGET_32BIT"
cffb2a26 4319 "mvn%?\\t%0, %1"
d2a518d1 4320 [(set_attr "predicable" "yes")
d952d547 4321 (set_attr "predicable_short_it" "yes,no")
4322 (set_attr "arch" "t2,*")
4323 (set_attr "length" "4")
1aed5204 4324 (set_attr "type" "mvn_reg")]
cffb2a26 4325)
4326
f7fbdd4a 4327(define_insn "*notsi_compare0"
bd5b4116 4328 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 4329 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
4330 (const_int 0)))
4331 (set (match_operand:SI 0 "s_register_operand" "=r")
4332 (not:SI (match_dup 1)))]
25f905c2 4333 "TARGET_32BIT"
3ef90e77 4334 "mvns%?\\t%0, %1"
d2a518d1 4335 [(set_attr "conds" "set")
1aed5204 4336 (set_attr "type" "mvn_reg")]
cffb2a26 4337)
9c08d1fa 4338
f7fbdd4a 4339(define_insn "*notsi_compare0_scratch"
bd5b4116 4340 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 4341 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
4342 (const_int 0)))
4343 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 4344 "TARGET_32BIT"
3ef90e77 4345 "mvns%?\\t%0, %1"
d2a518d1 4346 [(set_attr "conds" "set")
1aed5204 4347 (set_attr "type" "mvn_reg")]
cffb2a26 4348)
b11cae9e 4349\f
4350;; Fixed <--> Floating conversion insns
4351
9b8516be 4352(define_expand "floatsihf2"
3934ae0e 4353 [(set (match_operand:HF 0 "general_operand")
4354 (float:HF (match_operand:SI 1 "general_operand")))]
9b8516be 4355 "TARGET_EITHER"
4356 "
4357 {
4358 rtx op1 = gen_reg_rtx (SFmode);
4359 expand_float (op1, operands[1], 0);
4360 op1 = convert_to_mode (HFmode, op1, 0);
4361 emit_move_insn (operands[0], op1);
4362 DONE;
4363 }"
4364)
4365
4366(define_expand "floatdihf2"
3934ae0e 4367 [(set (match_operand:HF 0 "general_operand")
4368 (float:HF (match_operand:DI 1 "general_operand")))]
9b8516be 4369 "TARGET_EITHER"
4370 "
4371 {
4372 rtx op1 = gen_reg_rtx (SFmode);
4373 expand_float (op1, operands[1], 0);
4374 op1 = convert_to_mode (HFmode, op1, 0);
4375 emit_move_insn (operands[0], op1);
4376 DONE;
4377 }"
4378)
4379
604f3a0a 4380(define_expand "floatsisf2"
3934ae0e 4381 [(set (match_operand:SF 0 "s_register_operand")
4382 (float:SF (match_operand:SI 1 "s_register_operand")))]
25f905c2 4383 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 4384 "
604f3a0a 4385")
4386
604f3a0a 4387(define_expand "floatsidf2"
3934ae0e 4388 [(set (match_operand:DF 0 "s_register_operand")
4389 (float:DF (match_operand:SI 1 "s_register_operand")))]
a50d7267 4390 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 4391 "
604f3a0a 4392")
4393
9b8516be 4394(define_expand "fix_trunchfsi2"
3934ae0e 4395 [(set (match_operand:SI 0 "general_operand")
4396 (fix:SI (fix:HF (match_operand:HF 1 "general_operand"))))]
9b8516be 4397 "TARGET_EITHER"
4398 "
4399 {
4400 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
4401 expand_fix (operands[0], op1, 0);
4402 DONE;
4403 }"
4404)
4405
4406(define_expand "fix_trunchfdi2"
3934ae0e 4407 [(set (match_operand:DI 0 "general_operand")
4408 (fix:DI (fix:HF (match_operand:HF 1 "general_operand"))))]
9b8516be 4409 "TARGET_EITHER"
4410 "
4411 {
4412 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
4413 expand_fix (operands[0], op1, 0);
4414 DONE;
4415 }"
4416)
4417
604f3a0a 4418(define_expand "fix_truncsfsi2"
3934ae0e 4419 [(set (match_operand:SI 0 "s_register_operand")
4420 (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand"))))]
25f905c2 4421 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 4422 "
604f3a0a 4423")
4424
604f3a0a 4425(define_expand "fix_truncdfsi2"
3934ae0e 4426 [(set (match_operand:SI 0 "s_register_operand")
4427 (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand"))))]
a50d7267 4428 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 4429 "
604f3a0a 4430")
4431
f544c6d2 4432;; Truncation insns
b11cae9e 4433
604f3a0a 4434(define_expand "truncdfsf2"
3934ae0e 4435 [(set (match_operand:SF 0 "s_register_operand")
604f3a0a 4436 (float_truncate:SF
3934ae0e 4437 (match_operand:DF 1 "s_register_operand")))]
a50d7267 4438 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 4439 ""
4440)
9b8516be 4441
539b44ee 4442;; DFmode to HFmode conversions on targets without a single-step hardware
4443;; instruction for it would have to go through SFmode. This is dangerous
4444;; as it introduces double rounding.
4445;;
4446;; Disable this pattern unless we are in an unsafe math mode, or we have
4447;; a single-step instruction.
4448
9b8516be 4449(define_expand "truncdfhf2"
3934ae0e 4450 [(set (match_operand:HF 0 "s_register_operand")
9b8516be 4451 (float_truncate:HF
3934ae0e 4452 (match_operand:DF 1 "s_register_operand")))]
539b44ee 4453 "(TARGET_EITHER && flag_unsafe_math_optimizations)
4454 || (TARGET_32BIT && TARGET_FP16_TO_DOUBLE)"
4455{
4456 /* We don't have a direct instruction for this, so we must be in
4457 an unsafe math mode, and going via SFmode. */
4458
4459 if (!(TARGET_32BIT && TARGET_FP16_TO_DOUBLE))
4460 {
4461 rtx op1;
4462 op1 = convert_to_mode (SFmode, operands[1], 0);
4463 op1 = convert_to_mode (HFmode, op1, 0);
4464 emit_move_insn (operands[0], op1);
4465 DONE;
4466 }
4467 /* Otherwise, we will pick this up as a single instruction with
4468 no intermediary rounding. */
4469}
9b8516be 4470)
b11cae9e 4471\f
9c08d1fa 4472;; Zero and sign extension instructions.
b11cae9e 4473
2e55c7de 4474(define_expand "zero_extend<mode>di2"
4475 [(set (match_operand:DI 0 "s_register_operand" "")
4476 (zero_extend:DI (match_operand:QHSI 1 "<qhs_zextenddi_op>" "")))]
848e66ac 4477 "TARGET_32BIT <qhs_zextenddi_cond>"
2e55c7de 4478 {
4479 rtx res_lo, res_hi, op0_lo, op0_hi;
4480 res_lo = gen_lowpart (SImode, operands[0]);
4481 res_hi = gen_highpart (SImode, operands[0]);
4482 if (can_create_pseudo_p ())
4483 {
4484 op0_lo = <MODE>mode == SImode ? operands[1] : gen_reg_rtx (SImode);
4485 op0_hi = gen_reg_rtx (SImode);
4486 }
4487 else
4488 {
4489 op0_lo = <MODE>mode == SImode ? operands[1] : res_lo;
4490 op0_hi = res_hi;
4491 }
4492 if (<MODE>mode != SImode)
4493 emit_insn (gen_rtx_SET (op0_lo,
4494 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
4495 emit_insn (gen_movsi (op0_hi, const0_rtx));
4496 if (res_lo != op0_lo)
4497 emit_move_insn (res_lo, op0_lo);
4498 if (res_hi != op0_hi)
4499 emit_move_insn (res_hi, op0_hi);
4500 DONE;
4501 }
25f905c2 4502)
4503
2e55c7de 4504(define_expand "extend<mode>di2"
4505 [(set (match_operand:DI 0 "s_register_operand" "")
4506 (sign_extend:DI (match_operand:QHSI 1 "<qhs_extenddi_op>" "")))]
848e66ac 4507 "TARGET_32BIT <qhs_sextenddi_cond>"
2e55c7de 4508 {
4509 rtx res_lo, res_hi, op0_lo, op0_hi;
4510 res_lo = gen_lowpart (SImode, operands[0]);
4511 res_hi = gen_highpart (SImode, operands[0]);
4512 if (can_create_pseudo_p ())
4513 {
4514 op0_lo = <MODE>mode == SImode ? operands[1] : gen_reg_rtx (SImode);
4515 op0_hi = gen_reg_rtx (SImode);
4516 }
4517 else
4518 {
4519 op0_lo = <MODE>mode == SImode ? operands[1] : res_lo;
4520 op0_hi = res_hi;
4521 }
4522 if (<MODE>mode != SImode)
4523 emit_insn (gen_rtx_SET (op0_lo,
4524 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
4525 emit_insn (gen_ashrsi3 (op0_hi, op0_lo, GEN_INT (31)));
4526 if (res_lo != op0_lo)
4527 emit_move_insn (res_lo, op0_lo);
4528 if (res_hi != op0_hi)
4529 emit_move_insn (res_hi, op0_hi);
4530 DONE;
4531 }
0d66636f 4532)
9c08d1fa 4533
848e66ac 4534;; Splits for all extensions to DImode
4535(define_split
4536 [(set (match_operand:DI 0 "s_register_operand" "")
4537 (zero_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
def2e672 4538 "TARGET_32BIT"
848e66ac 4539 [(set (match_dup 0) (match_dup 1))]
4540{
848e66ac 4541 rtx lo_part = gen_lowpart (SImode, operands[0]);
3754d046 4542 machine_mode src_mode = GET_MODE (operands[1]);
848e66ac 4543
def2e672 4544 if (src_mode == SImode)
4545 emit_move_insn (lo_part, operands[1]);
4546 else
4547 emit_insn (gen_rtx_SET (lo_part,
4548 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
848e66ac 4549 operands[0] = gen_highpart (SImode, operands[0]);
4550 operands[1] = const0_rtx;
4551})
9c08d1fa 4552
848e66ac 4553(define_split
25f905c2 4554 [(set (match_operand:DI 0 "s_register_operand" "")
848e66ac 4555 (sign_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
def2e672 4556 "TARGET_32BIT"
848e66ac 4557 [(set (match_dup 0) (ashiftrt:SI (match_dup 1) (const_int 31)))]
4558{
4559 rtx lo_part = gen_lowpart (SImode, operands[0]);
3754d046 4560 machine_mode src_mode = GET_MODE (operands[1]);
25f905c2 4561
def2e672 4562 if (src_mode == SImode)
4563 emit_move_insn (lo_part, operands[1]);
4564 else
4565 emit_insn (gen_rtx_SET (lo_part,
4566 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
4567 operands[1] = lo_part;
848e66ac 4568 operands[0] = gen_highpart (SImode, operands[0]);
4569})
9c08d1fa 4570
4571(define_expand "zero_extendhisi2"
3934ae0e 4572 [(set (match_operand:SI 0 "s_register_operand")
4573 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand")))]
cffb2a26 4574 "TARGET_EITHER"
ef51b8e1 4575{
4576 if (TARGET_ARM && !arm_arch4 && MEM_P (operands[1]))
f7fbdd4a 4577 {
ef51b8e1 4578 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
4579 DONE;
25f7a26e 4580 }
ef51b8e1 4581 if (!arm_arch6 && !MEM_P (operands[1]))
4582 {
4583 rtx t = gen_lowpart (SImode, operands[1]);
4584 rtx tmp = gen_reg_rtx (SImode);
4585 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
4586 emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (16)));
4587 DONE;
4588 }
4589})
9c08d1fa 4590
ef51b8e1 4591(define_split
b146458f 4592 [(set (match_operand:SI 0 "s_register_operand" "")
4593 (zero_extend:SI (match_operand:HI 1 "s_register_operand" "")))]
ef51b8e1 4594 "!TARGET_THUMB2 && !arm_arch6"
4595 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4596 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 16)))]
4597{
4598 operands[2] = gen_lowpart (SImode, operands[1]);
4599})
4600
cffb2a26 4601(define_insn "*arm_zero_extendhisi2"
ef51b8e1 4602 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4603 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 4604 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 4605 "@
4606 #
3ef90e77 4607 ldrh%?\\t%0, %1"
d82e788e 4608 [(set_attr "type" "alu_shift_reg,load_byte")
848e66ac 4609 (set_attr "predicable" "yes")]
cffb2a26 4610)
f7fbdd4a 4611
a2cd141b 4612(define_insn "*arm_zero_extendhisi2_v6"
4613 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
e3f4ccee 4614 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,Uh")))]
a2cd141b 4615 "TARGET_ARM && arm_arch6"
4616 "@
4617 uxth%?\\t%0, %1
3ef90e77 4618 ldrh%?\\t%0, %1"
65f68e55 4619 [(set_attr "predicable" "yes")
6b6abc9c 4620 (set_attr "type" "extend,load_byte")]
a2cd141b 4621)
4622
4623(define_insn "*arm_zero_extendhisi2addsi"
4624 [(set (match_operand:SI 0 "s_register_operand" "=r")
4625 (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
4626 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4627 "TARGET_INT_SIMD"
a2cd141b 4628 "uxtah%?\\t%0, %2, %1"
d82e788e 4629 [(set_attr "type" "alu_shift_reg")
8bdfd6ed 4630 (set_attr "predicable" "yes")]
a2cd141b 4631)
4632
87b22bf7 4633(define_expand "zero_extendqisi2"
3934ae0e 4634 [(set (match_operand:SI 0 "s_register_operand")
4635 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand")))]
cffb2a26 4636 "TARGET_EITHER"
ef51b8e1 4637{
0438d37f 4638 if (TARGET_ARM && !arm_arch6 && !MEM_P (operands[1]))
87b22bf7 4639 {
ef51b8e1 4640 emit_insn (gen_andsi3 (operands[0],
4641 gen_lowpart (SImode, operands[1]),
4642 GEN_INT (255)));
4643 DONE;
4644 }
4645 if (!arm_arch6 && !MEM_P (operands[1]))
4646 {
4647 rtx t = gen_lowpart (SImode, operands[1]);
4648 rtx tmp = gen_reg_rtx (SImode);
4649 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
4650 emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (24)));
4651 DONE;
4652 }
4653})
cffb2a26 4654
ef51b8e1 4655(define_split
b146458f 4656 [(set (match_operand:SI 0 "s_register_operand" "")
4657 (zero_extend:SI (match_operand:QI 1 "s_register_operand" "")))]
ef51b8e1 4658 "!arm_arch6"
4659 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
4660 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 24)))]
4661{
4662 operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
4663 if (TARGET_ARM)
4664 {
4665 emit_insn (gen_andsi3 (operands[0], operands[2], GEN_INT (255)));
87b22bf7 4666 DONE;
4667 }
ef51b8e1 4668})
9c08d1fa 4669
cffb2a26 4670(define_insn "*arm_zero_extendqisi2"
ef51b8e1 4671 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4672 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 4673 "TARGET_ARM && !arm_arch6"
ef51b8e1 4674 "@
4675 #
3ef90e77 4676 ldrb%?\\t%0, %1\\t%@ zero_extendqisi2"
ef51b8e1 4677 [(set_attr "length" "8,4")
d82e788e 4678 (set_attr "type" "alu_shift_reg,load_byte")
848e66ac 4679 (set_attr "predicable" "yes")]
cffb2a26 4680)
87b22bf7 4681
a2cd141b 4682(define_insn "*arm_zero_extendqisi2_v6"
4683 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
e3f4ccee 4684 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,Uh")))]
a2cd141b 4685 "TARGET_ARM && arm_arch6"
4686 "@
3ef90e77 4687 uxtb%?\\t%0, %1
4688 ldrb%?\\t%0, %1\\t%@ zero_extendqisi2"
6b6abc9c 4689 [(set_attr "type" "extend,load_byte")
848e66ac 4690 (set_attr "predicable" "yes")]
a2cd141b 4691)
4692
4693(define_insn "*arm_zero_extendqisi2addsi"
4694 [(set (match_operand:SI 0 "s_register_operand" "=r")
4695 (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
4696 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4697 "TARGET_INT_SIMD"
a2cd141b 4698 "uxtab%?\\t%0, %2, %1"
4699 [(set_attr "predicable" "yes")
d82e788e 4700 (set_attr "type" "alu_shift_reg")]
a2cd141b 4701)
4702
87b22bf7 4703(define_split
4704 [(set (match_operand:SI 0 "s_register_operand" "")
4705 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
4706 (clobber (match_operand:SI 2 "s_register_operand" ""))]
0438d37f 4707 "TARGET_32BIT && (!MEM_P (operands[1])) && ! BYTES_BIG_ENDIAN"
87b22bf7 4708 [(set (match_dup 2) (match_dup 1))
4709 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
cffb2a26 4710 ""
4711)
9c08d1fa 4712
8a4d25d6 4713(define_split
4714 [(set (match_operand:SI 0 "s_register_operand" "")
4715 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 3)))
4716 (clobber (match_operand:SI 2 "s_register_operand" ""))]
0438d37f 4717 "TARGET_32BIT && (!MEM_P (operands[1])) && BYTES_BIG_ENDIAN"
8a4d25d6 4718 [(set (match_dup 2) (match_dup 1))
4719 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
4720 ""
4721)
4722
1c274529 4723
4724(define_split
4725 [(set (match_operand:SI 0 "s_register_operand" "")
9b23f0a7 4726 (IOR_XOR:SI (and:SI (ashift:SI
1c274529 4727 (match_operand:SI 1 "s_register_operand" "")
4728 (match_operand:SI 2 "const_int_operand" ""))
4729 (match_operand:SI 3 "const_int_operand" ""))
4730 (zero_extend:SI
4731 (match_operator 5 "subreg_lowpart_operator"
4732 [(match_operand:SI 4 "s_register_operand" "")]))))]
4733 "TARGET_32BIT
8c4e8755 4734 && (UINTVAL (operands[3])
1c274529 4735 == (GET_MODE_MASK (GET_MODE (operands[5]))
4736 & (GET_MODE_MASK (GET_MODE (operands[5]))
4737 << (INTVAL (operands[2])))))"
9b23f0a7 4738 [(set (match_dup 0) (IOR_XOR:SI (ashift:SI (match_dup 1) (match_dup 2))
1c274529 4739 (match_dup 4)))
4740 (set (match_dup 0) (zero_extend:SI (match_dup 5)))]
4741 "operands[5] = gen_lowpart (GET_MODE (operands[5]), operands[0]);"
4742)
4743
f7fbdd4a 4744(define_insn "*compareqi_eq0"
bd5b4116 4745 [(set (reg:CC_Z CC_REGNUM)
206ee9a2 4746 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
87b22bf7 4747 (const_int 0)))]
25f905c2 4748 "TARGET_32BIT"
596e5e8f 4749 "tst%?\\t%0, #255"
4750 [(set_attr "conds" "set")
d952d547 4751 (set_attr "predicable" "yes")
1b7da4ac 4752 (set_attr "type" "logic_imm")]
cffb2a26 4753)
b11cae9e 4754
b11cae9e 4755(define_expand "extendhisi2"
3934ae0e 4756 [(set (match_operand:SI 0 "s_register_operand")
4757 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand")))]
cffb2a26 4758 "TARGET_EITHER"
ef51b8e1 4759{
4760 if (TARGET_THUMB1)
4761 {
4762 emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1]));
4763 DONE;
4764 }
4765 if (MEM_P (operands[1]) && TARGET_ARM && !arm_arch4)
4766 {
4767 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
4768 DONE;
4769 }
ed29c566 4770
ef51b8e1 4771 if (!arm_arch6 && !MEM_P (operands[1]))
4772 {
4773 rtx t = gen_lowpart (SImode, operands[1]);
4774 rtx tmp = gen_reg_rtx (SImode);
4775 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
4776 emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (16)));
4777 DONE;
4778 }
4779})
cffb2a26 4780
ef51b8e1 4781(define_split
4782 [(parallel
4783 [(set (match_operand:SI 0 "register_operand" "")
4784 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))
4785 (clobber (match_scratch:SI 2 ""))])]
4786 "!arm_arch6"
4787 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4788 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
4789{
4790 operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
4791})
25f7a26e 4792
25f905c2 4793;; This pattern will only be used when ldsh is not available
25f7a26e 4794(define_expand "extendhisi2_mem"
eab14235 4795 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 4796 (set (match_dup 3)
eab14235 4797 (zero_extend:SI (match_dup 7)))
25f7a26e 4798 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
4799 (set (match_operand:SI 0 "" "")
4800 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
cffb2a26 4801 "TARGET_ARM"
25f7a26e 4802 "
215b30b3 4803 {
4804 rtx mem1, mem2;
4805 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4806
788fcce0 4807 mem1 = change_address (operands[1], QImode, addr);
29c05e22 4808 mem2 = change_address (operands[1], QImode,
4809 plus_constant (Pmode, addr, 1));
215b30b3 4810 operands[0] = gen_lowpart (SImode, operands[0]);
4811 operands[1] = mem1;
4812 operands[2] = gen_reg_rtx (SImode);
4813 operands[3] = gen_reg_rtx (SImode);
4814 operands[6] = gen_reg_rtx (SImode);
4815 operands[7] = mem2;
25f7a26e 4816
215b30b3 4817 if (BYTES_BIG_ENDIAN)
4818 {
4819 operands[4] = operands[2];
4820 operands[5] = operands[3];
4821 }
4822 else
4823 {
4824 operands[4] = operands[3];
4825 operands[5] = operands[2];
4826 }
4827 }"
4828)
b11cae9e 4829
ef51b8e1 4830(define_split
4831 [(set (match_operand:SI 0 "register_operand" "")
4832 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
4833 "!arm_arch6"
4834 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4835 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
4836{
4837 operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
4838})
4839
a2cd141b 4840(define_insn "*arm_extendhisi2"
ef51b8e1 4841 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
e3f4ccee 4842 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,Uh")))]
a2cd141b 4843 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 4844 "@
4845 #
3ef90e77 4846 ldrsh%?\\t%0, %1"
ef51b8e1 4847 [(set_attr "length" "8,4")
d82e788e 4848 (set_attr "type" "alu_shift_reg,load_byte")
e3f4ccee 4849 (set_attr "predicable" "yes")]
cffb2a26 4850)
f7fbdd4a 4851
25f905c2 4852;; ??? Check Thumb-2 pool range
a2cd141b 4853(define_insn "*arm_extendhisi2_v6"
4854 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
e3f4ccee 4855 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,Uh")))]
25f905c2 4856 "TARGET_32BIT && arm_arch6"
a2cd141b 4857 "@
4858 sxth%?\\t%0, %1
3ef90e77 4859 ldrsh%?\\t%0, %1"
6b6abc9c 4860 [(set_attr "type" "extend,load_byte")
8bdfd6ed 4861 (set_attr "predicable" "yes")]
a2cd141b 4862)
4863
4864(define_insn "*arm_extendhisi2addsi"
4865 [(set (match_operand:SI 0 "s_register_operand" "=r")
4866 (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
4867 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4868 "TARGET_INT_SIMD"
a2cd141b 4869 "sxtah%?\\t%0, %2, %1"
1b7da4ac 4870 [(set_attr "type" "alu_shift_reg")]
a2cd141b 4871)
4872
c8f69309 4873(define_expand "extendqihi2"
4874 [(set (match_dup 2)
3934ae0e 4875 (ashift:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op")
c8f69309 4876 (const_int 24)))
3934ae0e 4877 (set (match_operand:HI 0 "s_register_operand")
c8f69309 4878 (ashiftrt:SI (match_dup 2)
4879 (const_int 24)))]
cffb2a26 4880 "TARGET_ARM"
c8f69309 4881 "
215b30b3 4882 {
0438d37f 4883 if (arm_arch4 && MEM_P (operands[1]))
215b30b3 4884 {
d1f9b275 4885 emit_insn (gen_rtx_SET (operands[0],
215b30b3 4886 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
4887 DONE;
4888 }
4889 if (!s_register_operand (operands[1], QImode))
4890 operands[1] = copy_to_mode_reg (QImode, operands[1]);
4891 operands[0] = gen_lowpart (SImode, operands[0]);
4892 operands[1] = gen_lowpart (SImode, operands[1]);
4893 operands[2] = gen_reg_rtx (SImode);
4894 }"
4895)
f7fbdd4a 4896
25f905c2 4897(define_insn "*arm_extendqihi_insn"
b4e8a300 4898 [(set (match_operand:HI 0 "s_register_operand" "=r")
bed7d9a5 4899 (sign_extend:HI (match_operand:QI 1 "arm_extendqisi_mem_op" "Uq")))]
cffb2a26 4900 "TARGET_ARM && arm_arch4"
3ef90e77 4901 "ldrsb%?\\t%0, %1"
a2cd141b 4902 [(set_attr "type" "load_byte")
e3f4ccee 4903 (set_attr "predicable" "yes")]
cffb2a26 4904)
3fc2009e 4905
b11cae9e 4906(define_expand "extendqisi2"
3934ae0e 4907 [(set (match_operand:SI 0 "s_register_operand")
4908 (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op")))]
cffb2a26 4909 "TARGET_EITHER"
ef51b8e1 4910{
4911 if (!arm_arch4 && MEM_P (operands[1]))
4912 operands[1] = copy_to_mode_reg (QImode, operands[1]);
a2cd141b 4913
ef51b8e1 4914 if (!arm_arch6 && !MEM_P (operands[1]))
4915 {
4916 rtx t = gen_lowpart (SImode, operands[1]);
4917 rtx tmp = gen_reg_rtx (SImode);
4918 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
4919 emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (24)));
4920 DONE;
4921 }
4922})
a2cd141b 4923
ef51b8e1 4924(define_split
4925 [(set (match_operand:SI 0 "register_operand" "")
4926 (sign_extend:SI (match_operand:QI 1 "register_operand" "")))]
4927 "!arm_arch6"
4928 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
4929 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))]
4930{
4931 operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
4932})
f7fbdd4a 4933
a2cd141b 4934(define_insn "*arm_extendqisi"
ef51b8e1 4935 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4936 (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
a2cd141b 4937 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 4938 "@
4939 #
3ef90e77 4940 ldrsb%?\\t%0, %1"
ef51b8e1 4941 [(set_attr "length" "8,4")
d82e788e 4942 (set_attr "type" "alu_shift_reg,load_byte")
e3f4ccee 4943 (set_attr "predicable" "yes")]
cffb2a26 4944)
3fc2009e 4945
a2cd141b 4946(define_insn "*arm_extendqisi_v6"
4947 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
bed7d9a5 4948 (sign_extend:SI
4949 (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
a2cd141b 4950 "TARGET_ARM && arm_arch6"
b4e8a300 4951 "@
4952 sxtb%?\\t%0, %1
3ef90e77 4953 ldrsb%?\\t%0, %1"
6b6abc9c 4954 [(set_attr "type" "extend,load_byte")
e3f4ccee 4955 (set_attr "predicable" "yes")]
a2cd141b 4956)
4957
4958(define_insn "*arm_extendqisi2addsi"
4959 [(set (match_operand:SI 0 "s_register_operand" "=r")
4960 (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
4961 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4962 "TARGET_INT_SIMD"
a2cd141b 4963 "sxtab%?\\t%0, %2, %1"
d82e788e 4964 [(set_attr "type" "alu_shift_reg")
8bdfd6ed 4965 (set_attr "predicable" "yes")]
a2cd141b 4966)
4967
856adc5d 4968(define_insn "arm_<sup>xtb16"
4969 [(set (match_operand:SI 0 "s_register_operand" "=r")
4970 (unspec:SI
4971 [(match_operand:SI 1 "s_register_operand" "r")] USXTB16))]
4972 "TARGET_INT_SIMD"
4973 "<sup>xtb16%?\\t%0, %1"
4974 [(set_attr "predicable" "yes")
4975 (set_attr "type" "alu_dsp_reg")])
4976
4977(define_insn "arm_<simd32_op>"
4978 [(set (match_operand:SI 0 "s_register_operand" "=r")
4979 (unspec:SI
4980 [(match_operand:SI 1 "s_register_operand" "r")
4981 (match_operand:SI 2 "s_register_operand" "r")] SIMD32_NOGE_BINOP))]
4982 "TARGET_INT_SIMD"
4983 "<simd32_op>%?\\t%0, %1, %2"
4984 [(set_attr "predicable" "yes")
4985 (set_attr "type" "alu_dsp_reg")])
4986
4987(define_insn "arm_usada8"
4988 [(set (match_operand:SI 0 "s_register_operand" "=r")
4989 (unspec:SI
4990 [(match_operand:SI 1 "s_register_operand" "r")
4991 (match_operand:SI 2 "s_register_operand" "r")
4992 (match_operand:SI 3 "s_register_operand" "r")] UNSPEC_USADA8))]
4993 "TARGET_INT_SIMD"
4994 "usada8%?\\t%0, %1, %2, %3"
4995 [(set_attr "predicable" "yes")
4996 (set_attr "type" "alu_dsp_reg")])
4997
433c7595 4998(define_insn "arm_<simd32_op>"
4999 [(set (match_operand:DI 0 "s_register_operand" "=r")
5000 (unspec:DI
5001 [(match_operand:SI 1 "s_register_operand" "r")
5002 (match_operand:SI 2 "s_register_operand" "r")
5003 (match_operand:DI 3 "s_register_operand" "0")] SIMD32_DIMODE))]
5004 "TARGET_INT_SIMD"
5005 "<simd32_op>%?\\t%Q0, %R0, %1, %2"
5006 [(set_attr "predicable" "yes")
5007 (set_attr "type" "smlald")])
5008
caedf871 5009(define_expand "extendsfdf2"
3934ae0e 5010 [(set (match_operand:DF 0 "s_register_operand")
5011 (float_extend:DF (match_operand:SF 1 "s_register_operand")))]
a50d7267 5012 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
caedf871 5013 ""
5014)
9b8516be 5015
539b44ee 5016;; HFmode -> DFmode conversions where we don't have an instruction for it
5017;; must go through SFmode.
5018;;
5019;; This is always safe for an extend.
5020
9b8516be 5021(define_expand "extendhfdf2"
3934ae0e 5022 [(set (match_operand:DF 0 "s_register_operand")
5023 (float_extend:DF (match_operand:HF 1 "s_register_operand")))]
9b8516be 5024 "TARGET_EITHER"
539b44ee 5025{
5026 /* We don't have a direct instruction for this, so go via SFmode. */
5027 if (!(TARGET_32BIT && TARGET_FP16_TO_DOUBLE))
5028 {
5029 rtx op1;
5030 op1 = convert_to_mode (SFmode, operands[1], 0);
5031 op1 = convert_to_mode (DFmode, op1, 0);
5032 emit_insn (gen_movdf (operands[0], op1));
5033 DONE;
5034 }
5035 /* Otherwise, we're done producing RTL and will pick up the correct
5036 pattern to do this with one rounding-step in a single instruction. */
5037}
9b8516be 5038)
b11cae9e 5039\f
5040;; Move insns (including loads and stores)
5041
5042;; XXX Just some ideas about movti.
9c08d1fa 5043;; I don't think these are a good idea on the arm, there just aren't enough
5044;; registers
b11cae9e 5045;;(define_expand "loadti"
3934ae0e 5046;; [(set (match_operand:TI 0 "s_register_operand")
5047;; (mem:TI (match_operand:SI 1 "address_operand")))]
b11cae9e 5048;; "" "")
5049
5050;;(define_expand "storeti"
3934ae0e 5051;; [(set (mem:TI (match_operand:TI 0 "address_operand"))
5052;; (match_operand:TI 1 "s_register_operand"))]
b11cae9e 5053;; "" "")
5054
5055;;(define_expand "movti"
3934ae0e 5056;; [(set (match_operand:TI 0 "general_operand")
5057;; (match_operand:TI 1 "general_operand"))]
b11cae9e 5058;; ""
5059;; "
5060;;{
5061;; rtx insn;
5062;;
0438d37f 5063;; if (MEM_P (operands[0]) && MEM_P (operands[1]))
b11cae9e 5064;; operands[1] = copy_to_reg (operands[1]);
0438d37f 5065;; if (MEM_P (operands[0]))
b11cae9e 5066;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
0438d37f 5067;; else if (MEM_P (operands[1]))
b11cae9e 5068;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
5069;; else
5070;; FAIL;
5071;;
5072;; emit_insn (insn);
5073;; DONE;
5074;;}")
5075
a2f10574 5076;; Recognize garbage generated above.
b11cae9e 5077
5078;;(define_insn ""
5079;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
5080;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
5081;; ""
5082;; "*
5083;; {
5084;; register mem = (which_alternative < 3);
0d66636f 5085;; register const char *template;
b11cae9e 5086;;
5087;; operands[mem] = XEXP (operands[mem], 0);
5088;; switch (which_alternative)
5089;; {
5090;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
5091;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
5092;; case 2: template = \"ldmia\\t%1, %M0\"; break;
5093;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
5094;; case 4: template = \"stmia\\t%0!, %M1\"; break;
5095;; case 5: template = \"stmia\\t%0, %M1\"; break;
5096;; }
e2348bcb 5097;; output_asm_insn (template, operands);
5098;; return \"\";
b11cae9e 5099;; }")
5100
cffb2a26 5101(define_expand "movdi"
3934ae0e 5102 [(set (match_operand:DI 0 "general_operand")
5103 (match_operand:DI 1 "general_operand"))]
cffb2a26 5104 "TARGET_EITHER"
5105 "
e723310d 5106 gcc_checking_assert (aligned_operand (operands[0], DImode));
5107 gcc_checking_assert (aligned_operand (operands[1], DImode));
e1ba4a27 5108 if (can_create_pseudo_p ())
cffb2a26 5109 {
0438d37f 5110 if (!REG_P (operands[0]))
b2778788 5111 operands[1] = force_reg (DImode, operands[1]);
cffb2a26 5112 }
6b97fdcc 5113 if (REG_P (operands[0]) && REGNO (operands[0]) <= LAST_ARM_REGNUM
b395382f 5114 && !targetm.hard_regno_mode_ok (REGNO (operands[0]), DImode))
4f0e25ca 5115 {
5116 /* Avoid LDRD's into an odd-numbered register pair in ARM state
5117 when expanding function calls. */
5118 gcc_assert (can_create_pseudo_p ());
5119 if (MEM_P (operands[1]) && MEM_VOLATILE_P (operands[1]))
5120 {
5121 /* Perform load into legal reg pair first, then move. */
5122 rtx reg = gen_reg_rtx (DImode);
5123 emit_insn (gen_movdi (reg, operands[1]));
5124 operands[1] = reg;
5125 }
5126 emit_move_insn (gen_lowpart (SImode, operands[0]),
5127 gen_lowpart (SImode, operands[1]));
5128 emit_move_insn (gen_highpart (SImode, operands[0]),
5129 gen_highpart (SImode, operands[1]));
5130 DONE;
5131 }
6b97fdcc 5132 else if (REG_P (operands[1]) && REGNO (operands[1]) <= LAST_ARM_REGNUM
b395382f 5133 && !targetm.hard_regno_mode_ok (REGNO (operands[1]), DImode))
4f0e25ca 5134 {
5135 /* Avoid STRD's from an odd-numbered register pair in ARM state
5136 when expanding function prologue. */
5137 gcc_assert (can_create_pseudo_p ());
5138 rtx split_dest = (MEM_P (operands[0]) && MEM_VOLATILE_P (operands[0]))
5139 ? gen_reg_rtx (DImode)
5140 : operands[0];
5141 emit_move_insn (gen_lowpart (SImode, split_dest),
5142 gen_lowpart (SImode, operands[1]));
5143 emit_move_insn (gen_highpart (SImode, split_dest),
5144 gen_highpart (SImode, operands[1]));
5145 if (split_dest != operands[0])
5146 emit_insn (gen_movdi (operands[0], split_dest));
5147 DONE;
5148 }
cffb2a26 5149 "
5150)
b11cae9e 5151
cffb2a26 5152(define_insn "*arm_movdi"
8f1c7041 5153 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, r, m")
5154 (match_operand:DI 1 "di_operand" "rDa,Db,Dc,mi,r"))]
cde1623a 5155 "TARGET_32BIT
d7216193 5156 && !(TARGET_HARD_FLOAT)
b2778788 5157 && !TARGET_IWMMXT
5158 && ( register_operand (operands[0], DImode)
5159 || register_operand (operands[1], DImode))"
b11cae9e 5160 "*
d51f92df 5161 switch (which_alternative)
5162 {
5163 case 0:
5164 case 1:
5165 case 2:
5166 return \"#\";
581f16e5 5167 case 3:
5168 /* Cannot load it directly, split to load it via MOV / MOVT. */
5169 if (!MEM_P (operands[1]) && arm_disable_literal_pool)
5170 return \"#\";
5171 /* Fall through. */
d51f92df 5172 default:
26ff80c0 5173 return output_move_double (operands, true, NULL);
d51f92df 5174 }
cffb2a26 5175 "
359a6e9f 5176 [(set_attr "length" "8,12,16,8,8")
9f2c2a36 5177 (set_attr "type" "multiple,multiple,multiple,load_8,store_8")
cde1623a 5178 (set_attr "arm_pool_range" "*,*,*,1020,*")
8848d797 5179 (set_attr "arm_neg_pool_range" "*,*,*,1004,*")
42e1de19 5180 (set_attr "thumb2_pool_range" "*,*,*,4094,*")
cde1623a 5181 (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
cffb2a26 5182)
5183
d51f92df 5184(define_split
5185 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
e6dd3afa 5186 (match_operand:ANY64 1 "immediate_operand" ""))]
25f905c2 5187 "TARGET_32BIT
d51f92df 5188 && reload_completed
a869c476 5189 && (arm_disable_literal_pool
5190 || (arm_const_double_inline_cost (operands[1])
5191 <= arm_max_const_double_inline_cost ()))"
d51f92df 5192 [(const_int 0)]
5193 "
5194 arm_split_constant (SET, SImode, curr_insn,
5195 INTVAL (gen_lowpart (SImode, operands[1])),
5196 gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
5197 arm_split_constant (SET, SImode, curr_insn,
5198 INTVAL (gen_highpart_mode (SImode,
5199 GET_MODE (operands[0]),
5200 operands[1])),
5201 gen_highpart (SImode, operands[0]), NULL_RTX, 0);
5202 DONE;
5203 "
5204)
5205
e5ba9289 5206; If optimizing for size, or if we have load delay slots, then
5207; we want to split the constant into two separate operations.
5208; In both cases this may split a trivial part into a single data op
5209; leaving a single complex constant to load. We can also get longer
5210; offsets in a LDR which means we get better chances of sharing the pool
5211; entries. Finally, we can normally do a better job of scheduling
5212; LDR instructions than we can with LDM.
5213; This pattern will only match if the one above did not.
5214(define_split
5215 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
5216 (match_operand:ANY64 1 "const_double_operand" ""))]
5217 "TARGET_ARM && reload_completed
5218 && arm_const_double_by_parts (operands[1])"
5219 [(set (match_dup 0) (match_dup 1))
5220 (set (match_dup 2) (match_dup 3))]
5221 "
5222 operands[2] = gen_highpart (SImode, operands[0]);
5223 operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
5224 operands[1]);
5225 operands[0] = gen_lowpart (SImode, operands[0]);
5226 operands[1] = gen_lowpart (SImode, operands[1]);
5227 "
5228)
5229
d51f92df 5230(define_split
5231 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
5232 (match_operand:ANY64 1 "arm_general_register_operand" ""))]
5233 "TARGET_EITHER && reload_completed"
5234 [(set (match_dup 0) (match_dup 1))
5235 (set (match_dup 2) (match_dup 3))]
5236 "
5237 operands[2] = gen_highpart (SImode, operands[0]);
5238 operands[3] = gen_highpart (SImode, operands[1]);
5239 operands[0] = gen_lowpart (SImode, operands[0]);
5240 operands[1] = gen_lowpart (SImode, operands[1]);
5241
5242 /* Handle a partial overlap. */
5243 if (rtx_equal_p (operands[0], operands[3]))
5244 {
5245 rtx tmp0 = operands[0];
5246 rtx tmp1 = operands[1];
5247
5248 operands[0] = operands[2];
5249 operands[1] = operands[3];
5250 operands[2] = tmp0;
5251 operands[3] = tmp1;
5252 }
5253 "
5254)
5255
a8a3b539 5256;; We can't actually do base+index doubleword loads if the index and
5257;; destination overlap. Split here so that we at least have chance to
5258;; schedule.
5259(define_split
5260 [(set (match_operand:DI 0 "s_register_operand" "")
5261 (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
5262 (match_operand:SI 2 "s_register_operand" ""))))]
5263 "TARGET_LDRD
5264 && reg_overlap_mentioned_p (operands[0], operands[1])
5265 && reg_overlap_mentioned_p (operands[0], operands[2])"
5266 [(set (match_dup 4)
5267 (plus:SI (match_dup 1)
5268 (match_dup 2)))
5269 (set (match_dup 0)
5270 (mem:DI (match_dup 4)))]
5271 "
5272 operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
5273 "
5274)
5275
9c08d1fa 5276(define_expand "movsi"
3934ae0e 5277 [(set (match_operand:SI 0 "general_operand")
5278 (match_operand:SI 1 "general_operand"))]
cffb2a26 5279 "TARGET_EITHER"
9c08d1fa 5280 "
befb0bac 5281 {
e348ff3e 5282 rtx base, offset, tmp;
5283
e723310d 5284 gcc_checking_assert (aligned_operand (operands[0], SImode));
5285 gcc_checking_assert (aligned_operand (operands[1], SImode));
6e291830 5286 if (TARGET_32BIT || TARGET_HAVE_MOVT)
9c08d1fa 5287 {
674a8f0b 5288 /* Everything except mem = const or mem = mem can be done easily. */
0438d37f 5289 if (MEM_P (operands[0]))
cffb2a26 5290 operands[1] = force_reg (SImode, operands[1]);
a2cd141b 5291 if (arm_general_register_operand (operands[0], SImode)
0438d37f 5292 && CONST_INT_P (operands[1])
cffb2a26 5293 && !(const_ok_for_arm (INTVAL (operands[1]))
5294 || const_ok_for_arm (~INTVAL (operands[1]))))
5295 {
17202aa5 5296 if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[1]), SET))
5297 {
5298 emit_insn (gen_rtx_SET (operands[0], operands[1]));
5299 DONE;
5300 }
5301 else
5302 {
5303 arm_split_constant (SET, SImode, NULL_RTX,
5304 INTVAL (operands[1]), operands[0], NULL_RTX,
5305 optimize && can_create_pseudo_p ());
5306 DONE;
5307 }
cffb2a26 5308 }
5309 }
75612252 5310 else /* Target doesn't have MOVT... */
cffb2a26 5311 {
e1ba4a27 5312 if (can_create_pseudo_p ())
cffb2a26 5313 {
0438d37f 5314 if (!REG_P (operands[0]))
cffb2a26 5315 operands[1] = force_reg (SImode, operands[1]);
5316 }
9c08d1fa 5317 }
f655717d 5318
eeb22b66 5319 split_const (operands[1], &base, &offset);
5320 if (INTVAL (offset) != 0
5321 && targetm.cannot_force_const_mem (SImode, operands[1]))
e348ff3e 5322 {
eeb22b66 5323 tmp = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
5324 emit_move_insn (tmp, base);
5325 emit_insn (gen_addsi3 (operands[0], tmp, offset));
5326 DONE;
e348ff3e 5327 }
5328
eeb22b66 5329 tmp = can_create_pseudo_p () ? NULL_RTX : operands[0];
5330
f655717d 5331 /* Recognize the case where operand[1] is a reference to thread-local
eeb22b66 5332 data and load its address to a register. Offsets have been split off
5333 already. */
f655717d 5334 if (arm_tls_referenced_p (operands[1]))
eeb22b66 5335 operands[1] = legitimize_tls_address (operands[1], tmp);
f655717d 5336 else if (flag_pic
5337 && (CONSTANT_P (operands[1])
5338 || symbol_mentioned_p (operands[1])
5339 || label_mentioned_p (operands[1])))
eeb22b66 5340 operands[1] =
5341 legitimize_pic_address (operands[1], SImode, tmp, NULL_RTX, false);
befb0bac 5342 }
215b30b3 5343 "
5344)
9c08d1fa 5345
d0e6a121 5346;; The ARM LO_SUM and HIGH are backwards - HIGH sets the low bits, and
5347;; LO_SUM adds in the high bits. Fortunately these are opaque operations
5348;; so this does not matter.
5349(define_insn "*arm_movt"
417e5cc5 5350 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r")
5351 (lo_sum:SI (match_operand:SI 1 "nonimmediate_operand" "0,0")
5352 (match_operand:SI 2 "general_operand" "i,i")))]
60a48e7d 5353 "TARGET_HAVE_MOVT && arm_valid_symbolic_address_p (operands[2])"
417e5cc5 5354 "@
5355 movt%?\t%0, #:upper16:%c2
5356 movt\t%0, #:upper16:%c2"
5357 [(set_attr "arch" "32,v8mb")
5358 (set_attr "predicable" "yes")
1b7da4ac 5359 (set_attr "length" "4")
282b4c75 5360 (set_attr "type" "alu_sreg")]
d0e6a121 5361)
5362
cffb2a26 5363(define_insn "*arm_movsi_insn"
aaa37ad6 5364 [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,rk,m")
110eae03 5365 (match_operand:SI 1 "general_operand" "rk, I,K,j,mi,rk"))]
d7216193 5366 "TARGET_ARM && !TARGET_IWMMXT && !TARGET_HARD_FLOAT
cffb2a26 5367 && ( register_operand (operands[0], SImode)
5368 || register_operand (operands[1], SImode))"
f7fbdd4a 5369 "@
aaa37ad6 5370 mov%?\\t%0, %1
f7fbdd4a 5371 mov%?\\t%0, %1
5372 mvn%?\\t%0, #%B1
25f905c2 5373 movw%?\\t%0, %1
f7fbdd4a 5374 ldr%?\\t%0, %1
5375 str%?\\t%1, %0"
9f2c2a36 5376 [(set_attr "type" "mov_reg,mov_imm,mvn_imm,mov_imm,load_4,store_4")
0d66636f 5377 (set_attr "predicable" "yes")
100cd063 5378 (set_attr "arch" "*,*,*,v6t2,*,*")
aaa37ad6 5379 (set_attr "pool_range" "*,*,*,*,4096,*")
5380 (set_attr "neg_pool_range" "*,*,*,*,4084,*")]
cffb2a26 5381)
87b22bf7 5382
5383(define_split
a2cd141b 5384 [(set (match_operand:SI 0 "arm_general_register_operand" "")
87b22bf7 5385 (match_operand:SI 1 "const_int_operand" ""))]
6e291830 5386 "(TARGET_32BIT || TARGET_HAVE_MOVT)
215b30b3 5387 && (!(const_ok_for_arm (INTVAL (operands[1]))
5388 || const_ok_for_arm (~INTVAL (operands[1]))))"
87b22bf7 5389 [(clobber (const_int 0))]
5390 "
96f57e36 5391 arm_split_constant (SET, SImode, NULL_RTX,
5392 INTVAL (operands[1]), operands[0], NULL_RTX, 0);
87b22bf7 5393 DONE;
215b30b3 5394 "
5395)
9c08d1fa 5396
861033d5 5397;; A normal way to do (symbol + offset) requires three instructions at least
5398;; (depends on how big the offset is) as below:
5399;; movw r0, #:lower16:g
5400;; movw r0, #:upper16:g
5401;; adds r0, #4
5402;;
5403;; A better way would be:
5404;; movw r0, #:lower16:g+4
5405;; movw r0, #:upper16:g+4
5406;;
5407;; The limitation of this way is that the length of offset should be a 16-bit
5408;; signed value, because current assembler only supports REL type relocation for
5409;; such case. If the more powerful RELA type is supported in future, we should
5410;; update this pattern to go with better way.
5411(define_split
5412 [(set (match_operand:SI 0 "arm_general_register_operand" "")
5413 (const:SI (plus:SI (match_operand:SI 1 "general_operand" "")
5414 (match_operand:SI 2 "const_int_operand" ""))))]
60a48e7d 5415 "TARGET_THUMB
5416 && TARGET_HAVE_MOVT
861033d5 5417 && arm_disable_literal_pool
5418 && reload_completed
5419 && GET_CODE (operands[1]) == SYMBOL_REF"
5420 [(clobber (const_int 0))]
5421 "
5422 int offset = INTVAL (operands[2]);
5423
5424 if (offset < -0x8000 || offset > 0x7fff)
5425 {
5426 arm_emit_movpair (operands[0], operands[1]);
d1f9b275 5427 emit_insn (gen_rtx_SET (operands[0],
861033d5 5428 gen_rtx_PLUS (SImode, operands[0], operands[2])));
5429 }
5430 else
5431 {
5432 rtx op = gen_rtx_CONST (SImode,
5433 gen_rtx_PLUS (SImode, operands[1], operands[2]));
5434 arm_emit_movpair (operands[0], op);
5435 }
5436 "
5437)
5438
b8d5d078 5439;; Split symbol_refs at the later stage (after cprop), instead of generating
5440;; movt/movw pair directly at expand. Otherwise corresponding high_sum
5441;; and lo_sum would be merged back into memory load at cprop. However,
5442;; if the default is to prefer movt/movw rather than a load from the constant
5443;; pool, the performance is better.
5444(define_split
5445 [(set (match_operand:SI 0 "arm_general_register_operand" "")
5446 (match_operand:SI 1 "general_operand" ""))]
60a48e7d 5447 "TARGET_USE_MOVT && GET_CODE (operands[1]) == SYMBOL_REF
d022aaf3 5448 && !target_word_relocations
b8d5d078 5449 && !arm_tls_referenced_p (operands[1])"
5450 [(clobber (const_int 0))]
5451{
5452 arm_emit_movpair (operands[0], operands[1]);
5453 DONE;
5454})
5455
bc360af8 5456;; When generating pic, we need to load the symbol offset into a register.
5457;; So that the optimizer does not confuse this with a normal symbol load
5458;; we use an unspec. The offset will be loaded from a constant pool entry,
5459;; since that is the only type of relocation we can use.
cffb2a26 5460
bc360af8 5461;; Wrap calculation of the whole PIC address in a single pattern for the
5462;; benefit of optimizers, particularly, PRE and HOIST. Calculation of
5463;; a PIC address involves two loads from memory, so we want to CSE it
5464;; as often as possible.
5465;; This pattern will be split into one of the pic_load_addr_* patterns
5466;; and a move after GCSE optimizations.
5467;;
5468;; Note: Update arm.c: legitimize_pic_address() when changing this pattern.
5469(define_expand "calculate_pic_address"
3934ae0e 5470 [(set (match_operand:SI 0 "register_operand")
5471 (mem:SI (plus:SI (match_operand:SI 1 "register_operand")
94f8caca 5472 (unspec:SI [(match_operand:SI 2 "" "")]
5473 UNSPEC_PIC_SYM))))]
5474 "flag_pic"
5475)
5476
5477;; Split calculate_pic_address into pic_load_addr_* and a move.
5478(define_split
5479 [(set (match_operand:SI 0 "register_operand" "")
5480 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "")
5481 (unspec:SI [(match_operand:SI 2 "" "")]
5482 UNSPEC_PIC_SYM))))]
5483 "flag_pic"
5484 [(set (match_dup 3) (unspec:SI [(match_dup 2)] UNSPEC_PIC_SYM))
5485 (set (match_dup 0) (mem:SI (plus:SI (match_dup 1) (match_dup 3))))]
5486 "operands[3] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];"
5487)
5488
350ccca5 5489;; operand1 is the memory address to go into
5490;; pic_load_addr_32bit.
5491;; operand2 is the PIC label to be emitted
5492;; from pic_add_dot_plus_eight.
5493;; We do this to allow hoisting of the entire insn.
5494(define_insn_and_split "pic_load_addr_unified"
5495 [(set (match_operand:SI 0 "s_register_operand" "=r,r,l")
5496 (unspec:SI [(match_operand:SI 1 "" "mX,mX,mX")
5497 (match_operand:SI 2 "" "")]
5498 UNSPEC_PIC_UNIFIED))]
5499 "flag_pic"
5500 "#"
5501 "&& reload_completed"
5502 [(set (match_dup 0) (unspec:SI [(match_dup 1)] UNSPEC_PIC_SYM))
5503 (set (match_dup 0) (unspec:SI [(match_dup 0) (match_dup 3)
5504 (match_dup 2)] UNSPEC_PIC_BASE))]
5505 "operands[3] = TARGET_THUMB ? GEN_INT (4) : GEN_INT (8);"
9f2c2a36 5506 [(set_attr "type" "load_4,load_4,load_4")
42e1de19 5507 (set_attr "pool_range" "4096,4094,1022")
350ccca5 5508 (set_attr "neg_pool_range" "4084,0,0")
5509 (set_attr "arch" "a,t2,t1")
5510 (set_attr "length" "8,6,4")]
5511)
5512
67336bcf 5513;; The rather odd constraints on the following are to force reload to leave
5514;; the insn alone, and to force the minipool generation pass to then move
5515;; the GOT symbol to memory.
849170fd 5516
b3cd5f55 5517(define_insn "pic_load_addr_32bit"
849170fd 5518 [(set (match_operand:SI 0 "s_register_operand" "=r")
e1159bbe 5519 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
b3cd5f55 5520 "TARGET_32BIT && flag_pic"
67336bcf 5521 "ldr%?\\t%0, %1"
9f2c2a36 5522 [(set_attr "type" "load_4")
42e1de19 5523 (set (attr "pool_range")
5524 (if_then_else (eq_attr "is_thumb" "no")
5525 (const_int 4096)
5526 (const_int 4094)))
b3cd5f55 5527 (set (attr "neg_pool_range")
5528 (if_then_else (eq_attr "is_thumb" "no")
5529 (const_int 4084)
5530 (const_int 0)))]
8c4d8060 5531)
5532
25f905c2 5533(define_insn "pic_load_addr_thumb1"
8c4d8060 5534 [(set (match_operand:SI 0 "s_register_operand" "=l")
e1159bbe 5535 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
25f905c2 5536 "TARGET_THUMB1 && flag_pic"
8c4d8060 5537 "ldr\\t%0, %1"
9f2c2a36 5538 [(set_attr "type" "load_4")
42e1de19 5539 (set (attr "pool_range") (const_int 1018))]
cffb2a26 5540)
849170fd 5541
cffb2a26 5542(define_insn "pic_add_dot_plus_four"
15d5d060 5543 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5544 (unspec:SI [(match_operand:SI 1 "register_operand" "0")
5545 (const_int 4)
beef0fb5 5546 (match_operand 2 "" "")]
5547 UNSPEC_PIC_BASE))]
b3cd5f55 5548 "TARGET_THUMB"
cffb2a26 5549 "*
6cdcb15c 5550 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5551 INTVAL (operands[2]));
cffb2a26 5552 return \"add\\t%0, %|pc\";
5553 "
1b7da4ac 5554 [(set_attr "length" "2")
112eda6f 5555 (set_attr "type" "alu_sreg")]
cffb2a26 5556)
849170fd 5557
5558(define_insn "pic_add_dot_plus_eight"
15d5d060 5559 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5560 (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5561 (const_int 8)
beef0fb5 5562 (match_operand 2 "" "")]
5563 UNSPEC_PIC_BASE))]
f655717d 5564 "TARGET_ARM"
c4034607 5565 "*
6cdcb15c 5566 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5567 INTVAL (operands[2]));
15d5d060 5568 return \"add%?\\t%0, %|pc, %1\";
cffb2a26 5569 "
1b7da4ac 5570 [(set_attr "predicable" "yes")
112eda6f 5571 (set_attr "type" "alu_sreg")]
cffb2a26 5572)
849170fd 5573
f655717d 5574(define_insn "tls_load_dot_plus_eight"
cc071db6 5575 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5576 (mem:SI (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5577 (const_int 8)
beef0fb5 5578 (match_operand 2 "" "")]
5579 UNSPEC_PIC_BASE)))]
f655717d 5580 "TARGET_ARM"
5581 "*
6cdcb15c 5582 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5583 INTVAL (operands[2]));
f655717d 5584 return \"ldr%?\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_eight\";
5585 "
1b7da4ac 5586 [(set_attr "predicable" "yes")
9f2c2a36 5587 (set_attr "type" "load_4")]
f655717d 5588)
5589
5590;; PIC references to local variables can generate pic_add_dot_plus_eight
5591;; followed by a load. These sequences can be crunched down to
5592;; tls_load_dot_plus_eight by a peephole.
5593
5594(define_peephole2
c0c1fba5 5595 [(set (match_operand:SI 0 "register_operand" "")
5596 (unspec:SI [(match_operand:SI 3 "register_operand" "")
5597 (const_int 8)
5598 (match_operand 1 "" "")]
5599 UNSPEC_PIC_BASE))
2d05dfad 5600 (set (match_operand:SI 2 "arm_general_register_operand" "")
5601 (mem:SI (match_dup 0)))]
f655717d 5602 "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
c0c1fba5 5603 [(set (match_dup 2)
5604 (mem:SI (unspec:SI [(match_dup 3)
5605 (const_int 8)
5606 (match_dup 1)]
5607 UNSPEC_PIC_BASE)))]
f655717d 5608 ""
5609)
5610
bac7fc85 5611(define_insn "pic_offset_arm"
5612 [(set (match_operand:SI 0 "register_operand" "=r")
5613 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
5614 (unspec:SI [(match_operand:SI 2 "" "X")]
5615 UNSPEC_PIC_OFFSET))))]
5616 "TARGET_VXWORKS_RTP && TARGET_ARM && flag_pic"
5617 "ldr%?\\t%0, [%1,%2]"
9f2c2a36 5618 [(set_attr "type" "load_4")]
bac7fc85 5619)
5620
95373f08 5621(define_expand "builtin_setjmp_receiver"
5622 [(label_ref (match_operand 0 "" ""))]
5623 "flag_pic"
5624 "
5625{
b935b306 5626 /* r3 is clobbered by set/longjmp, so we can use it as a scratch
5627 register. */
2cb7d577 5628 if (arm_pic_register != INVALID_REGNUM)
f98495d9 5629 arm_load_pic_register (1UL << 3, NULL_RTX);
95373f08 5630 DONE;
5631}")
5632
9c08d1fa 5633;; If copying one reg to another we can set the condition codes according to
5634;; its value. Such a move is common after a return from subroutine and the
5635;; result is being tested against zero.
5636
f7fbdd4a 5637(define_insn "*movsi_compare0"
bd5b4116 5638 [(set (reg:CC CC_REGNUM)
cffb2a26 5639 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
5640 (const_int 0)))
5641 (set (match_operand:SI 0 "s_register_operand" "=r,r")
5642 (match_dup 1))]
25f905c2 5643 "TARGET_32BIT"
e2348bcb 5644 "@
40dbec34 5645 cmp%?\\t%0, #0
3ef90e77 5646 subs%?\\t%0, %1, #0"
65f68e55 5647 [(set_attr "conds" "set")
d82e788e 5648 (set_attr "type" "alus_imm,alus_imm")]
cffb2a26 5649)
b11cae9e 5650
b11cae9e 5651;; Subroutine to store a half word from a register into memory.
5652;; Operand 0 is the source register (HImode)
c8f69309 5653;; Operand 1 is the destination address in a register (SImode)
b11cae9e 5654
9c08d1fa 5655;; In both this routine and the next, we must be careful not to spill
01cc3b75 5656;; a memory address of reg+large_const into a separate PLUS insn, since this
9c08d1fa 5657;; can generate unrecognizable rtl.
5658
b11cae9e 5659(define_expand "storehi"
c8f69309 5660 [;; store the low byte
f082f1c4 5661 (set (match_operand 1 "" "") (match_dup 3))
b11cae9e 5662 ;; extract the high byte
c8f69309 5663 (set (match_dup 2)
5664 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
b11cae9e 5665 ;; store the high byte
787f8210 5666 (set (match_dup 4) (match_dup 5))]
cffb2a26 5667 "TARGET_ARM"
b11cae9e 5668 "
215b30b3 5669 {
537ffcfc 5670 rtx op1 = operands[1];
5671 rtx addr = XEXP (op1, 0);
215b30b3 5672 enum rtx_code code = GET_CODE (addr);
5673
0438d37f 5674 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
215b30b3 5675 || code == MINUS)
537ffcfc 5676 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
215b30b3 5677
537ffcfc 5678 operands[4] = adjust_address (op1, QImode, 1);
e513d163 5679 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 5680 operands[3] = gen_lowpart (QImode, operands[0]);
5681 operands[0] = gen_lowpart (SImode, operands[0]);
787f8210 5682 operands[2] = gen_reg_rtx (SImode);
5683 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 5684 }"
5685)
b11cae9e 5686
c7597b5d 5687(define_expand "storehi_bigend"
f082f1c4 5688 [(set (match_dup 4) (match_dup 3))
c7597b5d 5689 (set (match_dup 2)
5690 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
787f8210 5691 (set (match_operand 1 "" "") (match_dup 5))]
cffb2a26 5692 "TARGET_ARM"
b11cae9e 5693 "
215b30b3 5694 {
537ffcfc 5695 rtx op1 = operands[1];
5696 rtx addr = XEXP (op1, 0);
215b30b3 5697 enum rtx_code code = GET_CODE (addr);
5698
0438d37f 5699 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
215b30b3 5700 || code == MINUS)
537ffcfc 5701 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
215b30b3 5702
537ffcfc 5703 operands[4] = adjust_address (op1, QImode, 1);
e513d163 5704 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 5705 operands[3] = gen_lowpart (QImode, operands[0]);
5706 operands[0] = gen_lowpart (SImode, operands[0]);
5707 operands[2] = gen_reg_rtx (SImode);
787f8210 5708 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 5709 }"
5710)
c7597b5d 5711
5712;; Subroutine to store a half word integer constant into memory.
5713(define_expand "storeinthi"
f082f1c4 5714 [(set (match_operand 0 "" "")
787f8210 5715 (match_operand 1 "" ""))
9e8503e6 5716 (set (match_dup 3) (match_dup 2))]
cffb2a26 5717 "TARGET_ARM"
c7597b5d 5718 "
215b30b3 5719 {
5720 HOST_WIDE_INT value = INTVAL (operands[1]);
5721 rtx addr = XEXP (operands[0], 0);
537ffcfc 5722 rtx op0 = operands[0];
215b30b3 5723 enum rtx_code code = GET_CODE (addr);
c7597b5d 5724
0438d37f 5725 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
215b30b3 5726 || code == MINUS)
537ffcfc 5727 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
c7597b5d 5728
215b30b3 5729 operands[1] = gen_reg_rtx (SImode);
5730 if (BYTES_BIG_ENDIAN)
5731 {
5732 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
5733 if ((value & 255) == ((value >> 8) & 255))
5734 operands[2] = operands[1];
5735 else
5736 {
5737 operands[2] = gen_reg_rtx (SImode);
5738 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
5739 }
5740 }
5741 else
5742 {
5743 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
5744 if ((value & 255) == ((value >> 8) & 255))
5745 operands[2] = operands[1];
5746 else
5747 {
5748 operands[2] = gen_reg_rtx (SImode);
5749 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
5750 }
5751 }
c7597b5d 5752
537ffcfc 5753 operands[3] = adjust_address (op0, QImode, 1);
e513d163 5754 operands[0] = adjust_address (operands[0], QImode, 0);
9e8503e6 5755 operands[2] = gen_lowpart (QImode, operands[2]);
787f8210 5756 operands[1] = gen_lowpart (QImode, operands[1]);
215b30b3 5757 }"
5758)
b11cae9e 5759
f7fbdd4a 5760(define_expand "storehi_single_op"
3934ae0e 5761 [(set (match_operand:HI 0 "memory_operand")
5762 (match_operand:HI 1 "general_operand"))]
25f905c2 5763 "TARGET_32BIT && arm_arch4"
f7fbdd4a 5764 "
215b30b3 5765 if (!s_register_operand (operands[1], HImode))
f7fbdd4a 5766 operands[1] = copy_to_mode_reg (HImode, operands[1]);
215b30b3 5767 "
5768)
f7fbdd4a 5769
b11cae9e 5770(define_expand "movhi"
3934ae0e 5771 [(set (match_operand:HI 0 "general_operand")
5772 (match_operand:HI 1 "general_operand"))]
cffb2a26 5773 "TARGET_EITHER"
b11cae9e 5774 "
e723310d 5775 gcc_checking_assert (aligned_operand (operands[0], HImode));
5776 gcc_checking_assert (aligned_operand (operands[1], HImode));
cffb2a26 5777 if (TARGET_ARM)
b11cae9e 5778 {
e1ba4a27 5779 if (can_create_pseudo_p ())
cffb2a26 5780 {
0438d37f 5781 if (MEM_P (operands[0]))
b11cae9e 5782 {
cffb2a26 5783 if (arm_arch4)
5784 {
5785 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
5786 DONE;
5787 }
0438d37f 5788 if (CONST_INT_P (operands[1]))
cffb2a26 5789 emit_insn (gen_storeinthi (operands[0], operands[1]));
c7597b5d 5790 else
cffb2a26 5791 {
0438d37f 5792 if (MEM_P (operands[1]))
cffb2a26 5793 operands[1] = force_reg (HImode, operands[1]);
5794 if (BYTES_BIG_ENDIAN)
5795 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
5796 else
5797 emit_insn (gen_storehi (operands[1], operands[0]));
5798 }
5799 DONE;
b11cae9e 5800 }
cffb2a26 5801 /* Sign extend a constant, and keep it in an SImode reg. */
0438d37f 5802 else if (CONST_INT_P (operands[1]))
9c08d1fa 5803 {
cffb2a26 5804 rtx reg = gen_reg_rtx (SImode);
5805 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
5806
5807 /* If the constant is already valid, leave it alone. */
215b30b3 5808 if (!const_ok_for_arm (val))
cffb2a26 5809 {
5810 /* If setting all the top bits will make the constant
5811 loadable in a single instruction, then set them.
5812 Otherwise, sign extend the number. */
5813
215b30b3 5814 if (const_ok_for_arm (~(val | ~0xffff)))
cffb2a26 5815 val |= ~0xffff;
5816 else if (val & 0x8000)
5817 val |= ~0xffff;
5818 }
5819
5820 emit_insn (gen_movsi (reg, GEN_INT (val)));
9e8503e6 5821 operands[1] = gen_lowpart (HImode, reg);
9c08d1fa 5822 }
e1ba4a27 5823 else if (arm_arch4 && optimize && can_create_pseudo_p ()
0438d37f 5824 && MEM_P (operands[1]))
0045890a 5825 {
5826 rtx reg = gen_reg_rtx (SImode);
5827
5828 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
5829 operands[1] = gen_lowpart (HImode, reg);
5830 }
215b30b3 5831 else if (!arm_arch4)
f7fbdd4a 5832 {
0438d37f 5833 if (MEM_P (operands[1]))
cffb2a26 5834 {
c1a66faf 5835 rtx base;
5836 rtx offset = const0_rtx;
5837 rtx reg = gen_reg_rtx (SImode);
5838
0438d37f 5839 if ((REG_P (base = XEXP (operands[1], 0))
c1a66faf 5840 || (GET_CODE (base) == PLUS
0438d37f 5841 && (CONST_INT_P (offset = XEXP (base, 1)))
c1a66faf 5842 && ((INTVAL(offset) & 1) != 1)
0438d37f 5843 && REG_P (base = XEXP (base, 0))))
c1a66faf 5844 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
206ee9a2 5845 {
8deb3959 5846 rtx new_rtx;
c1a66faf 5847
8deb3959 5848 new_rtx = widen_memory_access (operands[1], SImode,
5849 ((INTVAL (offset) & ~3)
5850 - INTVAL (offset)));
5851 emit_insn (gen_movsi (reg, new_rtx));
c1a66faf 5852 if (((INTVAL (offset) & 2) != 0)
5853 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
5854 {
5855 rtx reg2 = gen_reg_rtx (SImode);
5856
5857 emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
5858 reg = reg2;
5859 }
206ee9a2 5860 }
c1a66faf 5861 else
5862 emit_insn (gen_movhi_bytes (reg, operands[1]));
5863
5864 operands[1] = gen_lowpart (HImode, reg);
cffb2a26 5865 }
5866 }
5867 }
674a8f0b 5868 /* Handle loading a large integer during reload. */
0438d37f 5869 else if (CONST_INT_P (operands[1])
215b30b3 5870 && !const_ok_for_arm (INTVAL (operands[1]))
5871 && !const_ok_for_arm (~INTVAL (operands[1])))
cffb2a26 5872 {
5873 /* Writing a constant to memory needs a scratch, which should
5874 be handled with SECONDARY_RELOADs. */
0438d37f 5875 gcc_assert (REG_P (operands[0]));
cffb2a26 5876
5877 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5878 emit_insn (gen_movsi (operands[0], operands[1]));
5879 DONE;
5880 }
5881 }
25f905c2 5882 else if (TARGET_THUMB2)
5883 {
5884 /* Thumb-2 can do everything except mem=mem and mem=const easily. */
e1ba4a27 5885 if (can_create_pseudo_p ())
25f905c2 5886 {
0438d37f 5887 if (!REG_P (operands[0]))
25f905c2 5888 operands[1] = force_reg (HImode, operands[1]);
5889 /* Zero extend a constant, and keep it in an SImode reg. */
0438d37f 5890 else if (CONST_INT_P (operands[1]))
25f905c2 5891 {
5892 rtx reg = gen_reg_rtx (SImode);
5893 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
5894
5895 emit_insn (gen_movsi (reg, GEN_INT (val)));
5896 operands[1] = gen_lowpart (HImode, reg);
5897 }
5898 }
5899 }
5900 else /* TARGET_THUMB1 */
cffb2a26 5901 {
e1ba4a27 5902 if (can_create_pseudo_p ())
cffb2a26 5903 {
0438d37f 5904 if (CONST_INT_P (operands[1]))
6cffc037 5905 {
5906 rtx reg = gen_reg_rtx (SImode);
5907
5908 emit_insn (gen_movsi (reg, operands[1]));
5909 operands[1] = gen_lowpart (HImode, reg);
5910 }
cffb2a26 5911
5912 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 5913 happen if we are passed a SP (never OK for HImode/QImode) or
bc409cb4 5914 virtual register (also rejected as illegitimate for HImode/QImode)
5915 relative address. */
cffb2a26 5916 /* ??? This should perhaps be fixed elsewhere, for instance, in
5917 fixup_stack_1, by checking for other kinds of invalid addresses,
5918 e.g. a bare reference to a virtual register. This may confuse the
5919 alpha though, which must handle this case differently. */
0438d37f 5920 if (MEM_P (operands[0])
215b30b3 5921 && !memory_address_p (GET_MODE (operands[0]),
5922 XEXP (operands[0], 0)))
537ffcfc 5923 operands[0]
5924 = replace_equiv_address (operands[0],
5925 copy_to_reg (XEXP (operands[0], 0)));
cffb2a26 5926
0438d37f 5927 if (MEM_P (operands[1])
215b30b3 5928 && !memory_address_p (GET_MODE (operands[1]),
5929 XEXP (operands[1], 0)))
537ffcfc 5930 operands[1]
5931 = replace_equiv_address (operands[1],
5932 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 5933
0438d37f 5934 if (MEM_P (operands[1]) && optimize > 0)
6cffc037 5935 {
5936 rtx reg = gen_reg_rtx (SImode);
5937
5938 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
5939 operands[1] = gen_lowpart (HImode, reg);
5940 }
5941
0438d37f 5942 if (MEM_P (operands[0]))
6cffc037 5943 operands[1] = force_reg (HImode, operands[1]);
cffb2a26 5944 }
0438d37f 5945 else if (CONST_INT_P (operands[1])
234f6557 5946 && !satisfies_constraint_I (operands[1]))
cffb2a26 5947 {
6cffc037 5948 /* Handle loading a large integer during reload. */
5949
cffb2a26 5950 /* Writing a constant to memory needs a scratch, which should
5951 be handled with SECONDARY_RELOADs. */
0438d37f 5952 gcc_assert (REG_P (operands[0]));
cffb2a26 5953
1a83b3ff 5954 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
cffb2a26 5955 emit_insn (gen_movsi (operands[0], operands[1]));
5956 DONE;
5957 }
b11cae9e 5958 }
cffb2a26 5959 "
5960)
5961
25f7a26e 5962(define_expand "movhi_bytes"
eab14235 5963 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 5964 (set (match_dup 3)
eab14235 5965 (zero_extend:SI (match_dup 6)))
25f7a26e 5966 (set (match_operand:SI 0 "" "")
5967 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
cffb2a26 5968 "TARGET_ARM"
25f7a26e 5969 "
215b30b3 5970 {
5971 rtx mem1, mem2;
5972 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
5973
788fcce0 5974 mem1 = change_address (operands[1], QImode, addr);
29c05e22 5975 mem2 = change_address (operands[1], QImode,
5976 plus_constant (Pmode, addr, 1));
215b30b3 5977 operands[0] = gen_lowpart (SImode, operands[0]);
5978 operands[1] = mem1;
5979 operands[2] = gen_reg_rtx (SImode);
5980 operands[3] = gen_reg_rtx (SImode);
5981 operands[6] = mem2;
25f7a26e 5982
215b30b3 5983 if (BYTES_BIG_ENDIAN)
5984 {
5985 operands[4] = operands[2];
5986 operands[5] = operands[3];
5987 }
5988 else
5989 {
5990 operands[4] = operands[3];
5991 operands[5] = operands[2];
5992 }
5993 }"
5994)
25f7a26e 5995
c7597b5d 5996(define_expand "movhi_bigend"
5997 [(set (match_dup 2)
3934ae0e 5998 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand") 0)
c7597b5d 5999 (const_int 16)))
6000 (set (match_dup 3)
6001 (ashiftrt:SI (match_dup 2) (const_int 16)))
3934ae0e 6002 (set (match_operand:HI 0 "s_register_operand")
787f8210 6003 (match_dup 4))]
cffb2a26 6004 "TARGET_ARM"
c7597b5d 6005 "
6006 operands[2] = gen_reg_rtx (SImode);
6007 operands[3] = gen_reg_rtx (SImode);
787f8210 6008 operands[4] = gen_lowpart (HImode, operands[3]);
215b30b3 6009 "
6010)
b11cae9e 6011
a2f10574 6012;; Pattern to recognize insn generated default case above
f7fbdd4a 6013(define_insn "*movhi_insn_arch4"
e4585731 6014 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r,m,r")
6015 (match_operand:HI 1 "general_operand" "rIk,K,n,r,mi"))]
cffb2a26 6016 "TARGET_ARM
d7216193 6017 && arm_arch4 && !TARGET_HARD_FLOAT
85e02ccb 6018 && (register_operand (operands[0], HImode)
6019 || register_operand (operands[1], HImode))"
f7fbdd4a 6020 "@
6021 mov%?\\t%0, %1\\t%@ movhi
6022 mvn%?\\t%0, #%B1\\t%@ movhi
b1c1a101 6023 movw%?\\t%0, %L1\\t%@ movhi
3ef90e77 6024 strh%?\\t%1, %0\\t%@ movhi
6025 ldrh%?\\t%0, %1\\t%@ movhi"
65f68e55 6026 [(set_attr "predicable" "yes")
e4585731 6027 (set_attr "pool_range" "*,*,*,*,256")
6028 (set_attr "neg_pool_range" "*,*,*,*,244")
6029 (set_attr "arch" "*,*,v6t2,*,*")
65f68e55 6030 (set_attr_alternative "type"
6031 [(if_then_else (match_operand 1 "const_int_operand" "")
1aed5204 6032 (const_string "mov_imm" )
6033 (const_string "mov_reg"))
6034 (const_string "mvn_imm")
e4585731 6035 (const_string "mov_imm")
9f2c2a36 6036 (const_string "store_4")
6037 (const_string "load_4")])]
cffb2a26 6038)
f7fbdd4a 6039
f7fbdd4a 6040(define_insn "*movhi_bytes"
65f68e55 6041 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
5fd254ed 6042 (match_operand:HI 1 "arm_rhs_operand" "I,rk,K"))]
d7216193 6043 "TARGET_ARM && !TARGET_HARD_FLOAT"
25f7a26e 6044 "@
65f68e55 6045 mov%?\\t%0, %1\\t%@ movhi
25f7a26e 6046 mov%?\\t%0, %1\\t%@ movhi
0d66636f 6047 mvn%?\\t%0, #%B1\\t%@ movhi"
d2a518d1 6048 [(set_attr "predicable" "yes")
1aed5204 6049 (set_attr "type" "mov_imm,mov_reg,mvn_imm")]
0d66636f 6050)
837bb76e 6051
bc5c7e08 6052;; We use a DImode scratch because we may occasionally need an additional
6053;; temporary if the address isn't offsettable -- push_reload doesn't seem
6054;; to take any notice of the "o" constraints on reload_memory_operand operand.
3934ae0e 6055;; The reload_in<m> and reload_out<m> patterns require special constraints
6056;; to be correctly handled in default_secondary_reload function.
d3373b54 6057(define_expand "reload_outhi"
cffb2a26 6058 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
215b30b3 6059 (match_operand:HI 1 "s_register_operand" "r")
6060 (match_operand:DI 2 "s_register_operand" "=&l")])]
cffb2a26 6061 "TARGET_EITHER"
6062 "if (TARGET_ARM)
6063 arm_reload_out_hi (operands);
6064 else
6065 thumb_reload_out_hi (operands);
d3373b54 6066 DONE;
cffb2a26 6067 "
6068)
d3373b54 6069
25f7a26e 6070(define_expand "reload_inhi"
6071 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
cffb2a26 6072 (match_operand:HI 1 "arm_reload_memory_operand" "o")
bc5c7e08 6073 (match_operand:DI 2 "s_register_operand" "=&r")])]
c1a66faf 6074 "TARGET_EITHER"
25f7a26e 6075 "
cffb2a26 6076 if (TARGET_ARM)
6077 arm_reload_in_hi (operands);
6078 else
6079 thumb_reload_out_hi (operands);
25f7a26e 6080 DONE;
6081")
6082
9c08d1fa 6083(define_expand "movqi"
3934ae0e 6084 [(set (match_operand:QI 0 "general_operand")
6085 (match_operand:QI 1 "general_operand"))]
cffb2a26 6086 "TARGET_EITHER"
9c08d1fa 6087 "
6cffc037 6088 /* Everything except mem = const or mem = mem can be done easily */
0045890a 6089
e1ba4a27 6090 if (can_create_pseudo_p ())
cffb2a26 6091 {
0438d37f 6092 if (CONST_INT_P (operands[1]))
6cffc037 6093 {
6094 rtx reg = gen_reg_rtx (SImode);
6095
03770691 6096 /* For thumb we want an unsigned immediate, then we are more likely
6097 to be able to use a movs insn. */
6098 if (TARGET_THUMB)
6099 operands[1] = GEN_INT (INTVAL (operands[1]) & 255);
6100
6cffc037 6101 emit_insn (gen_movsi (reg, operands[1]));
6102 operands[1] = gen_lowpart (QImode, reg);
6103 }
cffb2a26 6104
6cffc037 6105 if (TARGET_THUMB)
6106 {
cffb2a26 6107 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 6108 happen if we are passed a SP (never OK for HImode/QImode) or
bc409cb4 6109 virtual register (also rejected as illegitimate for HImode/QImode)
6110 relative address. */
cffb2a26 6111 /* ??? This should perhaps be fixed elsewhere, for instance, in
6112 fixup_stack_1, by checking for other kinds of invalid addresses,
6113 e.g. a bare reference to a virtual register. This may confuse the
6114 alpha though, which must handle this case differently. */
0438d37f 6115 if (MEM_P (operands[0])
215b30b3 6116 && !memory_address_p (GET_MODE (operands[0]),
cffb2a26 6117 XEXP (operands[0], 0)))
537ffcfc 6118 operands[0]
6119 = replace_equiv_address (operands[0],
6120 copy_to_reg (XEXP (operands[0], 0)));
0438d37f 6121 if (MEM_P (operands[1])
215b30b3 6122 && !memory_address_p (GET_MODE (operands[1]),
cffb2a26 6123 XEXP (operands[1], 0)))
537ffcfc 6124 operands[1]
6125 = replace_equiv_address (operands[1],
6126 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 6127 }
6128
0438d37f 6129 if (MEM_P (operands[1]) && optimize > 0)
6cffc037 6130 {
6131 rtx reg = gen_reg_rtx (SImode);
6132
6133 emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
6134 operands[1] = gen_lowpart (QImode, reg);
6135 }
6136
0438d37f 6137 if (MEM_P (operands[0]))
6cffc037 6138 operands[1] = force_reg (QImode, operands[1]);
6139 }
6140 else if (TARGET_THUMB
0438d37f 6141 && CONST_INT_P (operands[1])
234f6557 6142 && !satisfies_constraint_I (operands[1]))
6cffc037 6143 {
674a8f0b 6144 /* Handle loading a large integer during reload. */
cffb2a26 6145
6cffc037 6146 /* Writing a constant to memory needs a scratch, which should
6147 be handled with SECONDARY_RELOADs. */
0438d37f 6148 gcc_assert (REG_P (operands[0]));
6cffc037 6149
6150 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
6151 emit_insn (gen_movsi (operands[0], operands[1]));
6152 DONE;
cffb2a26 6153 }
6154 "
6155)
b11cae9e 6156
cffb2a26 6157(define_insn "*arm_movqi_insn"
fd711051 6158 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,l,r,l,Uu,r,m")
490f62ca 6159 (match_operand:QI 1 "general_operand" "rk,rk,I,Py,K,Uu,l,Uh,r"))]
25f905c2 6160 "TARGET_32BIT
cffb2a26 6161 && ( register_operand (operands[0], QImode)
6162 || register_operand (operands[1], QImode))"
5565501b 6163 "@
fd711051 6164 mov%?\\t%0, %1
6165 mov%?\\t%0, %1
65f68e55 6166 mov%?\\t%0, %1
5565501b 6167 mov%?\\t%0, %1
6168 mvn%?\\t%0, #%B1
3ef90e77 6169 ldrb%?\\t%0, %1
6170 strb%?\\t%1, %0
6171 ldrb%?\\t%0, %1
6172 strb%?\\t%1, %0"
9f2c2a36 6173 [(set_attr "type" "mov_reg,mov_reg,mov_imm,mov_imm,mvn_imm,load_4,store_4,load_4,store_4")
a54e3e7b 6174 (set_attr "predicable" "yes")
5233bf6a 6175 (set_attr "predicable_short_it" "yes,yes,no,yes,no,no,no,no,no")
fd711051 6176 (set_attr "arch" "t2,any,any,t2,any,t2,t2,any,any")
6177 (set_attr "length" "2,4,4,2,4,2,2,4,4")]
cffb2a26 6178)
6179
9b8516be 6180;; HFmode moves
6181(define_expand "movhf"
3934ae0e 6182 [(set (match_operand:HF 0 "general_operand")
6183 (match_operand:HF 1 "general_operand"))]
9b8516be 6184 "TARGET_EITHER"
6185 "
e723310d 6186 gcc_checking_assert (aligned_operand (operands[0], HFmode));
6187 gcc_checking_assert (aligned_operand (operands[1], HFmode));
9b8516be 6188 if (TARGET_32BIT)
6189 {
0438d37f 6190 if (MEM_P (operands[0]))
9b8516be 6191 operands[1] = force_reg (HFmode, operands[1]);
6192 }
6193 else /* TARGET_THUMB1 */
6194 {
6195 if (can_create_pseudo_p ())
6196 {
0438d37f 6197 if (!REG_P (operands[0]))
9b8516be 6198 operands[1] = force_reg (HFmode, operands[1]);
6199 }
6200 }
6201 "
6202)
6203
6204(define_insn "*arm32_movhf"
6205 [(set (match_operand:HF 0 "nonimmediate_operand" "=r,m,r,r")
6206 (match_operand:HF 1 "general_operand" " m,r,r,F"))]
d7216193 6207 "TARGET_32BIT && !TARGET_HARD_FLOAT
9b8516be 6208 && ( s_register_operand (operands[0], HFmode)
6209 || s_register_operand (operands[1], HFmode))"
6210 "*
6211 switch (which_alternative)
6212 {
6213 case 0: /* ARM register from memory */
3ef90e77 6214 return \"ldrh%?\\t%0, %1\\t%@ __fp16\";
9b8516be 6215 case 1: /* memory from ARM register */
3ef90e77 6216 return \"strh%?\\t%1, %0\\t%@ __fp16\";
9b8516be 6217 case 2: /* ARM register from ARM register */
6218 return \"mov%?\\t%0, %1\\t%@ __fp16\";
6219 case 3: /* ARM register from constant */
6220 {
9b8516be 6221 long bits;
6222 rtx ops[4];
6223
945f7b03 6224 bits = real_to_target (NULL, CONST_DOUBLE_REAL_VALUE (operands[1]),
6225 HFmode);
9b8516be 6226 ops[0] = operands[0];
6227 ops[1] = GEN_INT (bits);
6228 ops[2] = GEN_INT (bits & 0xff00);
6229 ops[3] = GEN_INT (bits & 0x00ff);
6230
6231 if (arm_arch_thumb2)
6232 output_asm_insn (\"movw%?\\t%0, %1\", ops);
6233 else
6234 output_asm_insn (\"mov%?\\t%0, %2\;orr%?\\t%0, %0, %3\", ops);
6235 return \"\";
6236 }
6237 default:
6238 gcc_unreachable ();
6239 }
6240 "
6241 [(set_attr "conds" "unconditional")
9f2c2a36 6242 (set_attr "type" "load_4,store_4,mov_reg,multiple")
9b8516be 6243 (set_attr "length" "4,4,4,8")
8bdfd6ed 6244 (set_attr "predicable" "yes")]
9b8516be 6245)
6246
87b22bf7 6247(define_expand "movsf"
3934ae0e 6248 [(set (match_operand:SF 0 "general_operand")
6249 (match_operand:SF 1 "general_operand"))]
cffb2a26 6250 "TARGET_EITHER"
87b22bf7 6251 "
e723310d 6252 gcc_checking_assert (aligned_operand (operands[0], SFmode));
6253 gcc_checking_assert (aligned_operand (operands[1], SFmode));
25f905c2 6254 if (TARGET_32BIT)
cffb2a26 6255 {
0438d37f 6256 if (MEM_P (operands[0]))
cffb2a26 6257 operands[1] = force_reg (SFmode, operands[1]);
6258 }
25f905c2 6259 else /* TARGET_THUMB1 */
cffb2a26 6260 {
e1ba4a27 6261 if (can_create_pseudo_p ())
cffb2a26 6262 {
0438d37f 6263 if (!REG_P (operands[0]))
cffb2a26 6264 operands[1] = force_reg (SFmode, operands[1]);
6265 }
6266 }
581f16e5 6267
6268 /* Cannot load it directly, generate a load with clobber so that it can be
6269 loaded via GPR with MOV / MOVT. */
6270 if (arm_disable_literal_pool
6271 && (REG_P (operands[0]) || SUBREG_P (operands[0]))
6272 && CONST_DOUBLE_P (operands[1])
6273 && TARGET_HARD_FLOAT
6274 && !vfp3_const_double_rtx (operands[1]))
6275 {
6276 rtx clobreg = gen_reg_rtx (SFmode);
6277 emit_insn (gen_no_literal_pool_sf_immediate (operands[0], operands[1],
6278 clobreg));
6279 DONE;
6280 }
cffb2a26 6281 "
6282)
6283
03d440a6 6284;; Transform a floating-point move of a constant into a core register into
6285;; an SImode operation.
cffb2a26 6286(define_split
03d440a6 6287 [(set (match_operand:SF 0 "arm_general_register_operand" "")
cffb2a26 6288 (match_operand:SF 1 "immediate_operand" ""))]
339034d0 6289 "TARGET_EITHER
cffb2a26 6290 && reload_completed
0438d37f 6291 && CONST_DOUBLE_P (operands[1])"
cffb2a26 6292 [(set (match_dup 2) (match_dup 3))]
6293 "
6294 operands[2] = gen_lowpart (SImode, operands[0]);
6295 operands[3] = gen_lowpart (SImode, operands[1]);
6296 if (operands[2] == 0 || operands[3] == 0)
6297 FAIL;
215b30b3 6298 "
6299)
87b22bf7 6300
cffb2a26 6301(define_insn "*arm_movsf_soft_insn"
6302 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
6303 (match_operand:SF 1 "general_operand" "r,mE,r"))]
cde1623a 6304 "TARGET_32BIT
cffb2a26 6305 && TARGET_SOFT_FLOAT
0438d37f 6306 && (!MEM_P (operands[0])
215b30b3 6307 || register_operand (operands[1], SFmode))"
581f16e5 6308{
6309 switch (which_alternative)
6310 {
6311 case 0: return \"mov%?\\t%0, %1\";
6312 case 1:
6313 /* Cannot load it directly, split to load it via MOV / MOVT. */
6314 if (!MEM_P (operands[1]) && arm_disable_literal_pool)
6315 return \"#\";
6316 return \"ldr%?\\t%0, %1\\t%@ float\";
6317 case 2: return \"str%?\\t%1, %0\\t%@ float\";
6318 default: gcc_unreachable ();
6319 }
6320}
cde1623a 6321 [(set_attr "predicable" "yes")
9f2c2a36 6322 (set_attr "type" "mov_reg,load_4,store_4")
42e1de19 6323 (set_attr "arm_pool_range" "*,4096,*")
6324 (set_attr "thumb2_pool_range" "*,4094,*")
cde1623a 6325 (set_attr "arm_neg_pool_range" "*,4084,*")
6326 (set_attr "thumb2_neg_pool_range" "*,0,*")]
cffb2a26 6327)
6328
581f16e5 6329;; Splitter for the above.
6330(define_split
6331 [(set (match_operand:SF 0 "s_register_operand")
6332 (match_operand:SF 1 "const_double_operand"))]
6333 "arm_disable_literal_pool && TARGET_SOFT_FLOAT"
6334 [(const_int 0)]
6335{
6336 long buf;
6337 real_to_target (&buf, CONST_DOUBLE_REAL_VALUE (operands[1]), SFmode);
6338 rtx cst = gen_int_mode (buf, SImode);
6339 emit_move_insn (simplify_gen_subreg (SImode, operands[0], SFmode, 0), cst);
6340 DONE;
6341}
6342)
6343
9c08d1fa 6344(define_expand "movdf"
3934ae0e 6345 [(set (match_operand:DF 0 "general_operand")
6346 (match_operand:DF 1 "general_operand"))]
cffb2a26 6347 "TARGET_EITHER"
9c08d1fa 6348 "
e723310d 6349 gcc_checking_assert (aligned_operand (operands[0], DFmode));
6350 gcc_checking_assert (aligned_operand (operands[1], DFmode));
25f905c2 6351 if (TARGET_32BIT)
cffb2a26 6352 {
0438d37f 6353 if (MEM_P (operands[0]))
cffb2a26 6354 operands[1] = force_reg (DFmode, operands[1]);
6355 }
6356 else /* TARGET_THUMB */
6357 {
e1ba4a27 6358 if (can_create_pseudo_p ())
cffb2a26 6359 {
0438d37f 6360 if (!REG_P (operands[0]))
cffb2a26 6361 operands[1] = force_reg (DFmode, operands[1]);
6362 }
6363 }
581f16e5 6364
6365 /* Cannot load it directly, generate a load with clobber so that it can be
6366 loaded via GPR with MOV / MOVT. */
6367 if (arm_disable_literal_pool
6368 && (REG_P (operands[0]) || SUBREG_P (operands[0]))
6369 && CONSTANT_P (operands[1])
6370 && TARGET_HARD_FLOAT
6371 && !arm_const_double_rtx (operands[1])
6372 && !(TARGET_VFP_DOUBLE && vfp3_const_double_rtx (operands[1])))
6373 {
6374 rtx clobreg = gen_reg_rtx (DFmode);
6375 emit_insn (gen_no_literal_pool_df_immediate (operands[0], operands[1],
6376 clobreg));
6377 DONE;
6378 }
cffb2a26 6379 "
6380)
b11cae9e 6381
9c08d1fa 6382;; Reloading a df mode value stored in integer regs to memory can require a
6383;; scratch reg.
3934ae0e 6384;; Another reload_out<m> pattern that requires special constraints.
9c08d1fa 6385(define_expand "reload_outdf"
cffb2a26 6386 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
87b22bf7 6387 (match_operand:DF 1 "s_register_operand" "r")
6388 (match_operand:SI 2 "s_register_operand" "=&r")]
06adefdc 6389 "TARGET_THUMB2"
87b22bf7 6390 "
215b30b3 6391 {
6392 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
f7fbdd4a 6393
215b30b3 6394 if (code == REG)
6395 operands[2] = XEXP (operands[0], 0);
6396 else if (code == POST_INC || code == PRE_DEC)
6397 {
6398 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
6399 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
6400 emit_insn (gen_movdi (operands[0], operands[1]));
6401 DONE;
6402 }
6403 else if (code == PRE_INC)
6404 {
6405 rtx reg = XEXP (XEXP (operands[0], 0), 0);
f7fbdd4a 6406
215b30b3 6407 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
6408 operands[2] = reg;
6409 }
6410 else if (code == POST_DEC)
6411 operands[2] = XEXP (XEXP (operands[0], 0), 0);
6412 else
6413 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
6414 XEXP (XEXP (operands[0], 0), 1)));
f7fbdd4a 6415
d1f9b275 6416 emit_insn (gen_rtx_SET (replace_equiv_address (operands[0], operands[2]),
215b30b3 6417 operands[1]));
f7fbdd4a 6418
215b30b3 6419 if (code == POST_DEC)
6420 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
6421
6422 DONE;
6423 }"
6424)
9c08d1fa 6425
9a1112d7 6426(define_insn "*movdf_soft_insn"
8f1c7041 6427 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,r,m")
6428 (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))]
cde1623a 6429 "TARGET_32BIT && TARGET_SOFT_FLOAT
b2778788 6430 && ( register_operand (operands[0], DFmode)
6431 || register_operand (operands[1], DFmode))"
d51f92df 6432 "*
6433 switch (which_alternative)
6434 {
6435 case 0:
6436 case 1:
6437 case 2:
6438 return \"#\";
581f16e5 6439 case 3:
6440 /* Cannot load it directly, split to load it via MOV / MOVT. */
6441 if (!MEM_P (operands[1]) && arm_disable_literal_pool)
6442 return \"#\";
6443 /* Fall through. */
d51f92df 6444 default:
26ff80c0 6445 return output_move_double (operands, true, NULL);
d51f92df 6446 }
6447 "
359a6e9f 6448 [(set_attr "length" "8,12,16,8,8")
9f2c2a36 6449 (set_attr "type" "multiple,multiple,multiple,load_8,store_8")
42e1de19 6450 (set_attr "arm_pool_range" "*,*,*,1020,*")
6451 (set_attr "thumb2_pool_range" "*,*,*,1018,*")
8848d797 6452 (set_attr "arm_neg_pool_range" "*,*,*,1004,*")
cde1623a 6453 (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
cffb2a26 6454)
581f16e5 6455
6456;; Splitter for the above.
6457(define_split
6458 [(set (match_operand:DF 0 "s_register_operand")
6459 (match_operand:DF 1 "const_double_operand"))]
6460 "arm_disable_literal_pool && TARGET_SOFT_FLOAT"
6461 [(const_int 0)]
6462{
6463 long buf[2];
6464 int order = BYTES_BIG_ENDIAN ? 1 : 0;
6465 real_to_target (buf, CONST_DOUBLE_REAL_VALUE (operands[1]), DFmode);
6466 unsigned HOST_WIDE_INT ival = zext_hwi (buf[order], 32);
6467 ival |= (zext_hwi (buf[1 - order], 32) << 32);
6468 rtx cst = gen_int_mode (ival, DImode);
6469 emit_move_insn (simplify_gen_subreg (DImode, operands[0], DFmode, 0), cst);
6470 DONE;
6471}
6472)
b11cae9e 6473\f
b11cae9e 6474
9c08d1fa 6475;; load- and store-multiple insns
6476;; The arm can load/store any set of registers, provided that they are in
320ea44d 6477;; ascending order, but these expanders assume a contiguous set.
b11cae9e 6478
9c08d1fa 6479(define_expand "load_multiple"
6480 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6481 (match_operand:SI 1 "" ""))
6482 (use (match_operand:SI 2 "" ""))])]
25f905c2 6483 "TARGET_32BIT"
9580c25f 6484{
6485 HOST_WIDE_INT offset = 0;
6486
bd5b4116 6487 /* Support only fixed point registers. */
0438d37f 6488 if (!CONST_INT_P (operands[2])
6e628811 6489 || INTVAL (operands[2]) > MAX_LDM_STM_OPS
9c08d1fa 6490 || INTVAL (operands[2]) < 2
0438d37f 6491 || !MEM_P (operands[1])
6492 || !REG_P (operands[0])
bd5b4116 6493 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
6494 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 6495 FAIL;
6496
6497 operands[3]
320ea44d 6498 = arm_gen_load_multiple (arm_regs_in_sequence + REGNO (operands[0]),
6499 INTVAL (operands[2]),
f082f1c4 6500 force_reg (SImode, XEXP (operands[1], 0)),
320ea44d 6501 FALSE, operands[1], &offset);
9580c25f 6502})
b11cae9e 6503
9c08d1fa 6504(define_expand "store_multiple"
6505 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6506 (match_operand:SI 1 "" ""))
6507 (use (match_operand:SI 2 "" ""))])]
25f905c2 6508 "TARGET_32BIT"
9580c25f 6509{
6510 HOST_WIDE_INT offset = 0;
6511
674a8f0b 6512 /* Support only fixed point registers. */
0438d37f 6513 if (!CONST_INT_P (operands[2])
6e628811 6514 || INTVAL (operands[2]) > MAX_LDM_STM_OPS
9c08d1fa 6515 || INTVAL (operands[2]) < 2
0438d37f 6516 || !REG_P (operands[1])
6517 || !MEM_P (operands[0])
bd5b4116 6518 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
6519 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 6520 FAIL;
6521
6522 operands[3]
320ea44d 6523 = arm_gen_store_multiple (arm_regs_in_sequence + REGNO (operands[1]),
6524 INTVAL (operands[2]),
f082f1c4 6525 force_reg (SImode, XEXP (operands[0], 0)),
320ea44d 6526 FALSE, operands[0], &offset);
9580c25f 6527})
b11cae9e 6528
9c08d1fa 6529
e34ebfca 6530(define_expand "setmemsi"
3934ae0e 6531 [(match_operand:BLK 0 "general_operand")
6532 (match_operand:SI 1 "const_int_operand")
6533 (match_operand:SI 2 "const_int_operand")
6534 (match_operand:SI 3 "const_int_operand")]
e34ebfca 6535 "TARGET_32BIT"
6536{
6537 if (arm_gen_setmem (operands))
6538 DONE;
6539
6540 FAIL;
6541})
6542
6543
9c08d1fa 6544;; Move a block of memory if it is word aligned and MORE than 2 words long.
6545;; We could let this apply for blocks of less than this, but it clobbers so
6546;; many registers that there is then probably a better way.
6547
f135a8d4 6548(define_expand "cpymemqi"
3934ae0e 6549 [(match_operand:BLK 0 "general_operand")
6550 (match_operand:BLK 1 "general_operand")
6551 (match_operand:SI 2 "const_int_operand")
6552 (match_operand:SI 3 "const_int_operand")]
ae51a965 6553 ""
9c08d1fa 6554 "
25f905c2 6555 if (TARGET_32BIT)
cffb2a26 6556 {
ae51a965 6557 if (TARGET_LDRD && current_tune->prefer_ldrd_strd
6558 && !optimize_function_for_size_p (cfun))
6559 {
f135a8d4 6560 if (gen_cpymem_ldrd_strd (operands))
ae51a965 6561 DONE;
6562 FAIL;
6563 }
6564
f135a8d4 6565 if (arm_gen_cpymemqi (operands))
cffb2a26 6566 DONE;
6567 FAIL;
6568 }
25f905c2 6569 else /* TARGET_THUMB1 */
cffb2a26 6570 {
6571 if ( INTVAL (operands[3]) != 4
6572 || INTVAL (operands[2]) > 48)
6573 FAIL;
6574
f135a8d4 6575 thumb_expand_cpymemqi (operands);
cffb2a26 6576 DONE;
6577 }
6578 "
6579)
9c08d1fa 6580\f
b11cae9e 6581
341940e8 6582;; Compare & branch insns
8d232dc7 6583;; The range calculations are based as follows:
341940e8 6584;; For forward branches, the address calculation returns the address of
6585;; the next instruction. This is 2 beyond the branch instruction.
6586;; For backward branches, the address calculation returns the address of
6587;; the first instruction in this pattern (cmp). This is 2 before the branch
6588;; instruction for the shortest sequence, and 4 before the branch instruction
6589;; if we have to jump around an unconditional branch.
6590;; To the basic branch range the PC offset must be added (this is +4).
6591;; So for forward branches we have
6592;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
6593;; And for backward branches we have
6594;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
6595;;
6596;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
6597;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
cffb2a26 6598
aeac46d4 6599(define_expand "cbranchsi4"
6600 [(set (pc) (if_then_else
aa06947a 6601 (match_operator 0 "expandable_comparison_operator"
3934ae0e 6602 [(match_operand:SI 1 "s_register_operand")
6603 (match_operand:SI 2 "nonmemory_operand")])
aeac46d4 6604 (label_ref (match_operand 3 "" ""))
6605 (pc)))]
f9aa4160 6606 "TARGET_EITHER"
aeac46d4 6607 "
74f4459c 6608 if (!TARGET_THUMB1)
6609 {
f9aa4160 6610 if (!arm_validize_comparison (&operands[0], &operands[1], &operands[2]))
6611 FAIL;
74f4459c 6612 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6613 operands[3]));
6614 DONE;
6615 }
25f905c2 6616 if (thumb1_cmpneg_operand (operands[2], SImode))
aeac46d4 6617 {
6618 emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
6619 operands[3], operands[0]));
6620 DONE;
6621 }
25f905c2 6622 if (!thumb1_cmp_operand (operands[2], SImode))
aeac46d4 6623 operands[2] = force_reg (SImode, operands[2]);
6624 ")
6625
74f4459c 6626(define_expand "cbranchsf4"
6627 [(set (pc) (if_then_else
aa06947a 6628 (match_operator 0 "expandable_comparison_operator"
3934ae0e 6629 [(match_operand:SF 1 "s_register_operand")
6630 (match_operand:SF 2 "vfp_compare_operand")])
74f4459c 6631 (label_ref (match_operand 3 "" ""))
6632 (pc)))]
6633 "TARGET_32BIT && TARGET_HARD_FLOAT"
6634 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6635 operands[3])); DONE;"
6636)
6637
6638(define_expand "cbranchdf4"
6639 [(set (pc) (if_then_else
aa06947a 6640 (match_operator 0 "expandable_comparison_operator"
3934ae0e 6641 [(match_operand:DF 1 "s_register_operand")
6642 (match_operand:DF 2 "vfp_compare_operand")])
74f4459c 6643 (label_ref (match_operand 3 "" ""))
6644 (pc)))]
a50d7267 6645 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
74f4459c 6646 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6647 operands[3])); DONE;"
6648)
6649
74f4459c 6650(define_expand "cbranchdi4"
6651 [(set (pc) (if_then_else
aa06947a 6652 (match_operator 0 "expandable_comparison_operator"
3934ae0e 6653 [(match_operand:DI 1 "s_register_operand")
d6852b47 6654 (match_operand:DI 2 "reg_or_int_operand")])
74f4459c 6655 (label_ref (match_operand 3 "" ""))
6656 (pc)))]
a8045a4f 6657 "TARGET_32BIT"
6658 "{
0438d37f 6659 if (!arm_validize_comparison (&operands[0], &operands[1], &operands[2]))
f9aa4160 6660 FAIL;
6661 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
a8045a4f 6662 operands[3]));
6663 DONE;
6664 }"
74f4459c 6665)
6666
9c08d1fa 6667;; Comparison and test insns
6668
cffb2a26 6669(define_insn "*arm_cmpsi_insn"
bd5b4116 6670 [(set (reg:CC CC_REGNUM)
f9f234ec 6671 (compare:CC (match_operand:SI 0 "s_register_operand" "l,r,r,r,r")
6672 (match_operand:SI 1 "arm_add_operand" "Py,r,r,I,L")))]
25f905c2 6673 "TARGET_32BIT"
5565501b 6674 "@
a6864a24 6675 cmp%?\\t%0, %1
6676 cmp%?\\t%0, %1
aea4c774 6677 cmp%?\\t%0, %1
f9f234ec 6678 cmp%?\\t%0, %1
aea4c774 6679 cmn%?\\t%0, #%n1"
a6864a24 6680 [(set_attr "conds" "set")
f9f234ec 6681 (set_attr "arch" "t2,t2,any,any,any")
6682 (set_attr "length" "2,2,4,4,4")
65f68e55 6683 (set_attr "predicable" "yes")
f9f234ec 6684 (set_attr "predicable_short_it" "yes,yes,yes,no,no")
112eda6f 6685 (set_attr "type" "alus_imm,alus_sreg,alus_sreg,alus_imm,alus_imm")]
cffb2a26 6686)
b11cae9e 6687
d5d4dc8d 6688(define_insn "*cmpsi_shiftsi"
bd5b4116 6689 [(set (reg:CC CC_REGNUM)
d82e788e 6690 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r,r")
cffb2a26 6691 (match_operator:SI 3 "shift_operator"
d82e788e 6692 [(match_operand:SI 1 "s_register_operand" "r,r,r")
6693 (match_operand:SI 2 "shift_amount_operand" "M,r,M")])))]
d5d4dc8d 6694 "TARGET_32BIT"
f9f234ec 6695 "cmp\\t%0, %1%S3"
344495ea 6696 [(set_attr "conds" "set")
331beb1a 6697 (set_attr "shift" "1")
d82e788e 6698 (set_attr "arch" "32,a,a")
282b4c75 6699 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
b11cae9e 6700
d5d4dc8d 6701(define_insn "*cmpsi_shiftsi_swp"
bd5b4116 6702 [(set (reg:CC_SWP CC_REGNUM)
aea4c774 6703 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
d82e788e 6704 [(match_operand:SI 1 "s_register_operand" "r,r,r")
6705 (match_operand:SI 2 "shift_amount_operand" "M,r,M")])
6706 (match_operand:SI 0 "s_register_operand" "r,r,r")))]
d5d4dc8d 6707 "TARGET_32BIT"
aea4c774 6708 "cmp%?\\t%0, %1%S3"
344495ea 6709 [(set_attr "conds" "set")
331beb1a 6710 (set_attr "shift" "1")
d82e788e 6711 (set_attr "arch" "32,a,a")
282b4c75 6712 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
b11cae9e 6713
25f905c2 6714(define_insn "*arm_cmpsi_negshiftsi_si"
aed179ae 6715 [(set (reg:CC_Z CC_REGNUM)
6716 (compare:CC_Z
6717 (neg:SI (match_operator:SI 1 "shift_operator"
6718 [(match_operand:SI 2 "s_register_operand" "r")
6719 (match_operand:SI 3 "reg_or_int_operand" "rM")]))
6720 (match_operand:SI 0 "s_register_operand" "r")))]
cffb2a26 6721 "TARGET_ARM"
aed179ae 6722 "cmn%?\\t%0, %2%S1"
344495ea 6723 [(set_attr "conds" "set")
aed179ae 6724 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
d82e788e 6725 (const_string "alus_shift_imm")
6726 (const_string "alus_shift_reg")))
596e5e8f 6727 (set_attr "predicable" "yes")]
0d66636f 6728)
b11cae9e 6729
9c08d1fa 6730; This insn allows redundant compares to be removed by cse, nothing should
6731; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
6732; is deleted later on. The match_dup will match the mode here, so that
6733; mode changes of the condition codes aren't lost by this even though we don't
6734; specify what they are.
6735
8a18b90c 6736(define_insn "*deleted_compare"
9c08d1fa 6737 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
25f905c2 6738 "TARGET_32BIT"
40dbec34 6739 "\\t%@ deleted compare"
cffb2a26 6740 [(set_attr "conds" "set")
1b7da4ac 6741 (set_attr "length" "0")
6742 (set_attr "type" "no_insn")]
cffb2a26 6743)
9c08d1fa 6744
6745\f
6746;; Conditional branch insns
6747
74f4459c 6748(define_expand "cbranch_cc"
9c08d1fa 6749 [(set (pc)
74f4459c 6750 (if_then_else (match_operator 0 "" [(match_operand 1 "" "")
6751 (match_operand 2 "" "")])
6752 (label_ref (match_operand 3 "" ""))
9c08d1fa 6753 (pc)))]
25f905c2 6754 "TARGET_32BIT"
74f4459c 6755 "operands[1] = arm_gen_compare_reg (GET_CODE (operands[0]),
e1b93706 6756 operands[1], operands[2], NULL_RTX);
74f4459c 6757 operands[2] = const0_rtx;"
8fa3ba89 6758)
6759
6760;;
6761;; Patterns to match conditional branch insns.
6762;;
6763
ffcc986d 6764(define_insn "arm_cond_branch"
9c08d1fa 6765 [(set (pc)
8fa3ba89 6766 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 6767 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 6768 (label_ref (match_operand 0 "" ""))
6769 (pc)))]
25f905c2 6770 "TARGET_32BIT"
d75350ce 6771 "*
9c08d1fa 6772 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 6773 {
6774 arm_ccfsm_state += 2;
6775 return \"\";
6776 }
e2348bcb 6777 return \"b%d1\\t%l0\";
cffb2a26 6778 "
a2cd141b 6779 [(set_attr "conds" "use")
a6864a24 6780 (set_attr "type" "branch")
6781 (set (attr "length")
6782 (if_then_else
0bf497f5 6783 (and (match_test "TARGET_THUMB2")
a6864a24 6784 (and (ge (minus (match_dup 0) (pc)) (const_int -250))
6785 (le (minus (match_dup 0) (pc)) (const_int 256))))
6786 (const_int 2)
6787 (const_int 4)))]
cffb2a26 6788)
d75350ce 6789
cffb2a26 6790(define_insn "*arm_cond_branch_reversed"
9c08d1fa 6791 [(set (pc)
8fa3ba89 6792 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 6793 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 6794 (pc)
6795 (label_ref (match_operand 0 "" ""))))]
25f905c2 6796 "TARGET_32BIT"
d75350ce 6797 "*
9c08d1fa 6798 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 6799 {
6800 arm_ccfsm_state += 2;
6801 return \"\";
6802 }
e2348bcb 6803 return \"b%D1\\t%l0\";
cffb2a26 6804 "
a2cd141b 6805 [(set_attr "conds" "use")
a6864a24 6806 (set_attr "type" "branch")
6807 (set (attr "length")
6808 (if_then_else
0bf497f5 6809 (and (match_test "TARGET_THUMB2")
a6864a24 6810 (and (ge (minus (match_dup 0) (pc)) (const_int -250))
6811 (le (minus (match_dup 0) (pc)) (const_int 256))))
6812 (const_int 2)
6813 (const_int 4)))]
cffb2a26 6814)
6815
b11cae9e 6816\f
9c08d1fa 6817
6818; scc insns
6819
74f4459c 6820(define_expand "cstore_cc"
3934ae0e 6821 [(set (match_operand:SI 0 "s_register_operand")
74f4459c 6822 (match_operator:SI 1 "" [(match_operand 2 "" "")
6823 (match_operand 3 "" "")]))]
25f905c2 6824 "TARGET_32BIT"
74f4459c 6825 "operands[2] = arm_gen_compare_reg (GET_CODE (operands[1]),
e1b93706 6826 operands[2], operands[3], NULL_RTX);
74f4459c 6827 operands[3] = const0_rtx;"
8fa3ba89 6828)
6829
a3b84066 6830(define_insn_and_split "*mov_scc"
9c08d1fa 6831 [(set (match_operand:SI 0 "s_register_operand" "=r")
ff74dd54 6832 (match_operator:SI 1 "arm_comparison_operator_mode"
8a18b90c 6833 [(match_operand 2 "cc_register" "") (const_int 0)]))]
cffb2a26 6834 "TARGET_ARM"
a3b84066 6835 "#" ; "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
6836 "TARGET_ARM"
6837 [(set (match_dup 0)
6838 (if_then_else:SI (match_dup 1)
6839 (const_int 1)
6840 (const_int 0)))]
6841 ""
cffb2a26 6842 [(set_attr "conds" "use")
1b7da4ac 6843 (set_attr "length" "8")
6844 (set_attr "type" "multiple")]
cffb2a26 6845)
9c08d1fa 6846
01089cc7 6847(define_insn "*negscc_borrow"
6848 [(set (match_operand:SI 0 "s_register_operand" "=r")
6849 (neg:SI (match_operand:SI 1 "arm_borrow_operation" "")))]
6850 "TARGET_32BIT"
6851 "sbc\\t%0, %0, %0"
6852 [(set_attr "conds" "use")
6853 (set_attr "length" "4")
6854 (set_attr "type" "adc_reg")]
6855)
6856
a3b84066 6857(define_insn_and_split "*mov_negscc"
9c08d1fa 6858 [(set (match_operand:SI 0 "s_register_operand" "=r")
ff74dd54 6859 (neg:SI (match_operator:SI 1 "arm_comparison_operator_mode"
8a18b90c 6860 [(match_operand 2 "cc_register" "") (const_int 0)])))]
01089cc7 6861 "TARGET_ARM && !arm_borrow_operation (operands[1], SImode)"
a3b84066 6862 "#" ; "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
01089cc7 6863 "&& true"
a3b84066 6864 [(set (match_dup 0)
6865 (if_then_else:SI (match_dup 1)
6866 (match_dup 3)
6867 (const_int 0)))]
6868 {
6869 operands[3] = GEN_INT (~0);
6870 }
cffb2a26 6871 [(set_attr "conds" "use")
1b7da4ac 6872 (set_attr "length" "8")
6873 (set_attr "type" "multiple")]
cffb2a26 6874)
9c08d1fa 6875
a3b84066 6876(define_insn_and_split "*mov_notscc"
9c08d1fa 6877 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 6878 (not:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 6879 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 6880 "TARGET_ARM"
a3b84066 6881 "#" ; "mvn%D1\\t%0, #0\;mvn%d1\\t%0, #1"
6882 "TARGET_ARM"
6883 [(set (match_dup 0)
6884 (if_then_else:SI (match_dup 1)
6885 (match_dup 3)
6886 (match_dup 4)))]
6887 {
6888 operands[3] = GEN_INT (~1);
6889 operands[4] = GEN_INT (~0);
6890 }
cffb2a26 6891 [(set_attr "conds" "use")
1b7da4ac 6892 (set_attr "length" "8")
6893 (set_attr "type" "multiple")]
cffb2a26 6894)
9c08d1fa 6895
595d88b5 6896(define_expand "cstoresi4"
3934ae0e 6897 [(set (match_operand:SI 0 "s_register_operand")
aa06947a 6898 (match_operator:SI 1 "expandable_comparison_operator"
3934ae0e 6899 [(match_operand:SI 2 "s_register_operand")
6900 (match_operand:SI 3 "reg_or_int_operand")]))]
74f4459c 6901 "TARGET_32BIT || TARGET_THUMB1"
595d88b5 6902 "{
6903 rtx op3, scratch, scratch2;
6904
74f4459c 6905 if (!TARGET_THUMB1)
6906 {
6907 if (!arm_add_operand (operands[3], SImode))
6908 operands[3] = force_reg (SImode, operands[3]);
6909 emit_insn (gen_cstore_cc (operands[0], operands[1],
6910 operands[2], operands[3]));
6911 DONE;
6912 }
6913
595d88b5 6914 if (operands[3] == const0_rtx)
6915 {
6916 switch (GET_CODE (operands[1]))
6917 {
6918 case EQ:
25f905c2 6919 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], operands[2]));
595d88b5 6920 break;
6921
6922 case NE:
25f905c2 6923 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], operands[2]));
595d88b5 6924 break;
6925
6926 case LE:
6927 scratch = expand_binop (SImode, add_optab, operands[2], constm1_rtx,
6928 NULL_RTX, 0, OPTAB_WIDEN);
6929 scratch = expand_binop (SImode, ior_optab, operands[2], scratch,
6930 NULL_RTX, 0, OPTAB_WIDEN);
6931 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
6932 operands[0], 1, OPTAB_WIDEN);
6933 break;
6934
6935 case GE:
6936 scratch = expand_unop (SImode, one_cmpl_optab, operands[2],
6937 NULL_RTX, 1);
6938 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
6939 NULL_RTX, 1, OPTAB_WIDEN);
6940 break;
6941
6942 case GT:
6943 scratch = expand_binop (SImode, ashr_optab, operands[2],
6944 GEN_INT (31), NULL_RTX, 0, OPTAB_WIDEN);
6945 scratch = expand_binop (SImode, sub_optab, scratch, operands[2],
6946 NULL_RTX, 0, OPTAB_WIDEN);
6947 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31), operands[0],
6948 0, OPTAB_WIDEN);
6949 break;
6950
6951 /* LT is handled by generic code. No need for unsigned with 0. */
6952 default:
6953 FAIL;
6954 }
6955 DONE;
6956 }
6957
6958 switch (GET_CODE (operands[1]))
6959 {
6960 case EQ:
6961 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
6962 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 6963 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], scratch));
595d88b5 6964 break;
6965
6966 case NE:
6967 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
6968 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 6969 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], scratch));
595d88b5 6970 break;
6971
6972 case LE:
6973 op3 = force_reg (SImode, operands[3]);
6974
6975 scratch = expand_binop (SImode, lshr_optab, operands[2], GEN_INT (31),
6976 NULL_RTX, 1, OPTAB_WIDEN);
6977 scratch2 = expand_binop (SImode, ashr_optab, op3, GEN_INT (31),
6978 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 6979 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
595d88b5 6980 op3, operands[2]));
6981 break;
6982
6983 case GE:
6984 op3 = operands[3];
25f905c2 6985 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 6986 op3 = force_reg (SImode, op3);
6987 scratch = expand_binop (SImode, ashr_optab, operands[2], GEN_INT (31),
6988 NULL_RTX, 0, OPTAB_WIDEN);
6989 scratch2 = expand_binop (SImode, lshr_optab, op3, GEN_INT (31),
6990 NULL_RTX, 1, OPTAB_WIDEN);
25f905c2 6991 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
595d88b5 6992 operands[2], op3));
6993 break;
6994
6995 case LEU:
6996 op3 = force_reg (SImode, operands[3]);
6997 scratch = force_reg (SImode, const0_rtx);
25f905c2 6998 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
595d88b5 6999 op3, operands[2]));
7000 break;
7001
7002 case GEU:
7003 op3 = operands[3];
25f905c2 7004 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7005 op3 = force_reg (SImode, op3);
7006 scratch = force_reg (SImode, const0_rtx);
25f905c2 7007 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
595d88b5 7008 operands[2], op3));
7009 break;
7010
7011 case LTU:
7012 op3 = operands[3];
25f905c2 7013 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7014 op3 = force_reg (SImode, op3);
7015 scratch = gen_reg_rtx (SImode);
408b7ae5 7016 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], operands[2], op3));
595d88b5 7017 break;
7018
7019 case GTU:
7020 op3 = force_reg (SImode, operands[3]);
7021 scratch = gen_reg_rtx (SImode);
408b7ae5 7022 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], op3, operands[2]));
595d88b5 7023 break;
7024
7025 /* No good sequences for GT, LT. */
7026 default:
7027 FAIL;
7028 }
7029 DONE;
7030}")
7031
9854d864 7032(define_expand "cstorehf4"
7033 [(set (match_operand:SI 0 "s_register_operand")
7034 (match_operator:SI 1 "expandable_comparison_operator"
7035 [(match_operand:HF 2 "s_register_operand")
d7216193 7036 (match_operand:HF 3 "vfp_compare_operand")]))]
9854d864 7037 "TARGET_VFP_FP16INST"
7038 {
7039 if (!arm_validize_comparison (&operands[1],
7040 &operands[2],
7041 &operands[3]))
7042 FAIL;
7043
7044 emit_insn (gen_cstore_cc (operands[0], operands[1],
7045 operands[2], operands[3]));
7046 DONE;
7047 }
7048)
7049
74f4459c 7050(define_expand "cstoresf4"
3934ae0e 7051 [(set (match_operand:SI 0 "s_register_operand")
aa06947a 7052 (match_operator:SI 1 "expandable_comparison_operator"
3934ae0e 7053 [(match_operand:SF 2 "s_register_operand")
7054 (match_operand:SF 3 "vfp_compare_operand")]))]
74f4459c 7055 "TARGET_32BIT && TARGET_HARD_FLOAT"
7056 "emit_insn (gen_cstore_cc (operands[0], operands[1],
7057 operands[2], operands[3])); DONE;"
7058)
7059
7060(define_expand "cstoredf4"
3934ae0e 7061 [(set (match_operand:SI 0 "s_register_operand")
aa06947a 7062 (match_operator:SI 1 "expandable_comparison_operator"
3934ae0e 7063 [(match_operand:DF 2 "s_register_operand")
7064 (match_operand:DF 3 "vfp_compare_operand")]))]
d63ed457 7065 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
74f4459c 7066 "emit_insn (gen_cstore_cc (operands[0], operands[1],
7067 operands[2], operands[3])); DONE;"
7068)
7069
74f4459c 7070(define_expand "cstoredi4"
3934ae0e 7071 [(set (match_operand:SI 0 "s_register_operand")
aa06947a 7072 (match_operator:SI 1 "expandable_comparison_operator"
3934ae0e 7073 [(match_operand:DI 2 "s_register_operand")
d6852b47 7074 (match_operand:DI 3 "reg_or_int_operand")]))]
a8045a4f 7075 "TARGET_32BIT"
7076 "{
f9aa4160 7077 if (!arm_validize_comparison (&operands[1],
7078 &operands[2],
7079 &operands[3]))
7080 FAIL;
7081 emit_insn (gen_cstore_cc (operands[0], operands[1], operands[2],
a8045a4f 7082 operands[3]));
7083 DONE;
7084 }"
74f4459c 7085)
7086
9c08d1fa 7087\f
39b5e676 7088;; Conditional move insns
7089
7090(define_expand "movsicc"
3934ae0e 7091 [(set (match_operand:SI 0 "s_register_operand")
7092 (if_then_else:SI (match_operand 1 "expandable_comparison_operator")
7093 (match_operand:SI 2 "arm_not_operand")
7094 (match_operand:SI 3 "arm_not_operand")))]
25f905c2 7095 "TARGET_32BIT"
39b5e676 7096 "
215b30b3 7097 {
f9aa4160 7098 enum rtx_code code;
278b301d 7099 rtx ccreg;
7100
f9aa4160 7101 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
9854d864 7102 &XEXP (operands[1], 1)))
278b301d 7103 FAIL;
9854d864 7104
7105 code = GET_CODE (operands[1]);
7106 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
7107 XEXP (operands[1], 1), NULL_RTX);
7108 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7109 }"
7110)
7111
7112(define_expand "movhfcc"
7113 [(set (match_operand:HF 0 "s_register_operand")
7114 (if_then_else:HF (match_operand 1 "arm_cond_move_operator")
7115 (match_operand:HF 2 "s_register_operand")
7116 (match_operand:HF 3 "s_register_operand")))]
7117 "TARGET_VFP_FP16INST"
7118 "
7119 {
7120 enum rtx_code code = GET_CODE (operands[1]);
7121 rtx ccreg;
7122
7123 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
7124 &XEXP (operands[1], 1)))
7125 FAIL;
7126
f9aa4160 7127 code = GET_CODE (operands[1]);
74f4459c 7128 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
e1b93706 7129 XEXP (operands[1], 1), NULL_RTX);
29bb088d 7130 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7131 }"
7132)
39b5e676 7133
7134(define_expand "movsfcc"
3934ae0e 7135 [(set (match_operand:SF 0 "s_register_operand")
7136 (if_then_else:SF (match_operand 1 "arm_cond_move_operator")
7137 (match_operand:SF 2 "s_register_operand")
7138 (match_operand:SF 3 "s_register_operand")))]
19f6bf8d 7139 "TARGET_32BIT && TARGET_HARD_FLOAT"
39b5e676 7140 "
215b30b3 7141 {
7142 enum rtx_code code = GET_CODE (operands[1]);
7143 rtx ccreg;
f082f1c4 7144
9854d864 7145 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
f9aa4160 7146 &XEXP (operands[1], 1)))
7147 FAIL;
39b5e676 7148
f9aa4160 7149 code = GET_CODE (operands[1]);
74f4459c 7150 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
e1b93706 7151 XEXP (operands[1], 1), NULL_RTX);
29bb088d 7152 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7153 }"
7154)
39b5e676 7155
7156(define_expand "movdfcc"
3934ae0e 7157 [(set (match_operand:DF 0 "s_register_operand")
7158 (if_then_else:DF (match_operand 1 "arm_cond_move_operator")
7159 (match_operand:DF 2 "s_register_operand")
7160 (match_operand:DF 3 "s_register_operand")))]
994606f8 7161 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
39b5e676 7162 "
215b30b3 7163 {
7164 enum rtx_code code = GET_CODE (operands[1]);
278b301d 7165 rtx ccreg;
39b5e676 7166
f9aa4160 7167 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
7168 &XEXP (operands[1], 1)))
7169 FAIL;
7170 code = GET_CODE (operands[1]);
74f4459c 7171 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
e1b93706 7172 XEXP (operands[1], 1), NULL_RTX);
29bb088d 7173 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7174 }"
7175)
39b5e676 7176
91cb50d2 7177(define_insn "*cmov<mode>"
7178 [(set (match_operand:SDF 0 "s_register_operand" "=<F_constraint>")
7179 (if_then_else:SDF (match_operator 1 "arm_vsel_comparison_operator"
7180 [(match_operand 2 "cc_register" "") (const_int 0)])
7181 (match_operand:SDF 3 "s_register_operand"
7182 "<F_constraint>")
7183 (match_operand:SDF 4 "s_register_operand"
7184 "<F_constraint>")))]
c79c1b1b 7185 "TARGET_HARD_FLOAT && TARGET_VFP5 <vfp_double_cond>"
91cb50d2 7186 "*
7187 {
7188 enum arm_cond_code code = maybe_get_arm_condition_code (operands[1]);
7189 switch (code)
7190 {
7191 case ARM_GE:
7192 case ARM_GT:
7193 case ARM_EQ:
7194 case ARM_VS:
7195 return \"vsel%d1.<V_if_elem>\\t%<V_reg>0, %<V_reg>3, %<V_reg>4\";
7196 case ARM_LT:
7197 case ARM_LE:
7198 case ARM_NE:
7199 case ARM_VC:
7200 return \"vsel%D1.<V_if_elem>\\t%<V_reg>0, %<V_reg>4, %<V_reg>3\";
7201 default:
7202 gcc_unreachable ();
7203 }
7204 return \"\";
7205 }"
7206 [(set_attr "conds" "use")
6664d308 7207 (set_attr "type" "fcsel")]
91cb50d2 7208)
7209
9854d864 7210(define_insn "*cmovhf"
7211 [(set (match_operand:HF 0 "s_register_operand" "=t")
7212 (if_then_else:HF (match_operator 1 "arm_vsel_comparison_operator"
7213 [(match_operand 2 "cc_register" "") (const_int 0)])
7214 (match_operand:HF 3 "s_register_operand" "t")
7215 (match_operand:HF 4 "s_register_operand" "t")))]
7216 "TARGET_VFP_FP16INST"
7217 "*
7218 {
7219 enum arm_cond_code code = maybe_get_arm_condition_code (operands[1]);
7220 switch (code)
7221 {
7222 case ARM_GE:
7223 case ARM_GT:
7224 case ARM_EQ:
7225 case ARM_VS:
7226 return \"vsel%d1.f16\\t%0, %3, %4\";
7227 case ARM_LT:
7228 case ARM_LE:
7229 case ARM_NE:
7230 case ARM_VC:
7231 return \"vsel%D1.f16\\t%0, %4, %3\";
7232 default:
7233 gcc_unreachable ();
7234 }
7235 return \"\";
7236 }"
7237 [(set_attr "conds" "use")
7238 (set_attr "type" "fcsel")]
7239)
7240
190efb17 7241(define_insn_and_split "*movsicc_insn"
f082f1c4 7242 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
8a18b90c 7243 (if_then_else:SI
8fa3ba89 7244 (match_operator 3 "arm_comparison_operator"
8a18b90c 7245 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 7246 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
7247 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
cffb2a26 7248 "TARGET_ARM"
39b5e676 7249 "@
8a18b90c 7250 mov%D3\\t%0, %2
7251 mvn%D3\\t%0, #%B2
f082f1c4 7252 mov%d3\\t%0, %1
7253 mvn%d3\\t%0, #%B1
190efb17 7254 #
7255 #
7256 #
7257 #"
7258 ; alt4: mov%d3\\t%0, %1\;mov%D3\\t%0, %2
7259 ; alt5: mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
7260 ; alt6: mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
7261 ; alt7: mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
7262 "&& reload_completed"
7263 [(const_int 0)]
7264 {
7265 enum rtx_code rev_code;
3754d046 7266 machine_mode mode;
190efb17 7267 rtx rev_cond;
7268
7269 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
7270 operands[3],
d1f9b275 7271 gen_rtx_SET (operands[0], operands[1])));
190efb17 7272
7273 rev_code = GET_CODE (operands[3]);
7274 mode = GET_MODE (operands[4]);
7275 if (mode == CCFPmode || mode == CCFPEmode)
7276 rev_code = reverse_condition_maybe_unordered (rev_code);
7277 else
7278 rev_code = reverse_condition (rev_code);
7279
7280 rev_cond = gen_rtx_fmt_ee (rev_code,
7281 VOIDmode,
7282 operands[4],
7283 const0_rtx);
7284 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
7285 rev_cond,
d1f9b275 7286 gen_rtx_SET (operands[0], operands[2])));
190efb17 7287 DONE;
7288 }
f082f1c4 7289 [(set_attr "length" "4,4,4,4,8,8,8,8")
d2a518d1 7290 (set_attr "conds" "use")
65f68e55 7291 (set_attr_alternative "type"
7292 [(if_then_else (match_operand 2 "const_int_operand" "")
1aed5204 7293 (const_string "mov_imm")
7294 (const_string "mov_reg"))
7295 (const_string "mvn_imm")
65f68e55 7296 (if_then_else (match_operand 1 "const_int_operand" "")
1aed5204 7297 (const_string "mov_imm")
7298 (const_string "mov_reg"))
7299 (const_string "mvn_imm")
282b4c75 7300 (const_string "multiple")
7301 (const_string "multiple")
7302 (const_string "multiple")
7303 (const_string "multiple")])]
215b30b3 7304)
39b5e676 7305
39b5e676 7306(define_insn "*movsfcc_soft_insn"
f082f1c4 7307 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
8fa3ba89 7308 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
8a18b90c 7309 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 7310 (match_operand:SF 1 "s_register_operand" "0,r")
7311 (match_operand:SF 2 "s_register_operand" "r,0")))]
cffb2a26 7312 "TARGET_ARM && TARGET_SOFT_FLOAT"
f082f1c4 7313 "@
7314 mov%D3\\t%0, %2
7315 mov%d3\\t%0, %1"
d2a518d1 7316 [(set_attr "conds" "use")
1aed5204 7317 (set_attr "type" "mov_reg")]
8fa3ba89 7318)
39b5e676 7319
39b5e676 7320\f
9c08d1fa 7321;; Jump and linkage insns
7322
cffb2a26 7323(define_expand "jump"
9c08d1fa 7324 [(set (pc)
7325 (label_ref (match_operand 0 "" "")))]
cffb2a26 7326 "TARGET_EITHER"
9c08d1fa 7327 ""
cffb2a26 7328)
7329
7330(define_insn "*arm_jump"
7331 [(set (pc)
7332 (label_ref (match_operand 0 "" "")))]
25f905c2 7333 "TARGET_32BIT"
9c08d1fa 7334 "*
0d66636f 7335 {
7336 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7337 {
7338 arm_ccfsm_state += 2;
7339 return \"\";
7340 }
7341 return \"b%?\\t%l0\";
7342 }
7343 "
a6864a24 7344 [(set_attr "predicable" "yes")
7345 (set (attr "length")
7346 (if_then_else
0bf497f5 7347 (and (match_test "TARGET_THUMB2")
a6864a24 7348 (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
7349 (le (minus (match_dup 0) (pc)) (const_int 2048))))
7350 (const_int 2)
1b7da4ac 7351 (const_int 4)))
7352 (set_attr "type" "branch")]
0d66636f 7353)
9c08d1fa 7354
d3373b54 7355(define_expand "call"
3934ae0e 7356 [(parallel [(call (match_operand 0 "memory_operand")
7357 (match_operand 1 "general_operand"))
cffb2a26 7358 (use (match_operand 2 "" ""))
bd5b4116 7359 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 7360 "TARGET_EITHER"
6c4c2133 7361 "
7362 {
bac7fc85 7363 rtx callee, pat;
2d3a01a7 7364 tree addr = MEM_EXPR (operands[0]);
bbe777ea 7365
bbe777ea 7366 /* In an untyped call, we can get NULL for operand 2. */
7367 if (operands[2] == NULL_RTX)
7368 operands[2] = const0_rtx;
7369
de55252a 7370 /* Decide if we should generate indirect calls by loading the
85c36fd1 7371 32-bit address of the callee into a register before performing the
de55252a 7372 branch and link. */
7373 callee = XEXP (operands[0], 0);
7374 if (GET_CODE (callee) == SYMBOL_REF
7375 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
7376 : !REG_P (callee))
bbe777ea 7377 XEXP (operands[0], 0) = force_reg (Pmode, callee);
bac7fc85 7378
2649fa41 7379 if (TARGET_FDPIC && !SYMBOL_REF_P (XEXP (operands[0], 0)))
7380 /* Indirect call: set r9 with FDPIC value of callee. */
7381 XEXP (operands[0], 0)
7382 = arm_load_function_descriptor (XEXP (operands[0], 0));
7383
2d3a01a7 7384 if (detect_cmse_nonsecure_call (addr))
7385 {
7386 pat = gen_nonsecure_call_internal (operands[0], operands[1],
7387 operands[2]);
7388 emit_call_insn (pat);
7389 }
7390 else
7391 {
7392 pat = gen_call_internal (operands[0], operands[1], operands[2]);
7393 arm_emit_call_insn (pat, XEXP (operands[0], 0), false);
7394 }
2649fa41 7395
7396 /* Restore FDPIC register (r9) after call. */
7397 if (TARGET_FDPIC)
7398 {
7399 rtx fdpic_reg = gen_rtx_REG (Pmode, FDPIC_REGNUM);
7400 rtx initial_fdpic_reg
7401 = get_hard_reg_initial_val (Pmode, FDPIC_REGNUM);
7402
7403 emit_insn (gen_restore_pic_register_after_call (fdpic_reg,
7404 initial_fdpic_reg));
7405 }
7406
bac7fc85 7407 DONE;
6c4c2133 7408 }"
7409)
d3373b54 7410
2649fa41 7411(define_insn "restore_pic_register_after_call"
7412 [(set (match_operand:SI 0 "s_register_operand" "+r,r")
7413 (unspec:SI [(match_dup 0)
7414 (match_operand:SI 1 "nonimmediate_operand" "r,m")]
7415 UNSPEC_PIC_RESTORE))]
7416 ""
7417 "@
7418 mov\t%0, %1
7419 ldr\t%0, %1"
7420)
7421
bac7fc85 7422(define_expand "call_internal"
3934ae0e 7423 [(parallel [(call (match_operand 0 "memory_operand")
7424 (match_operand 1 "general_operand"))
bac7fc85 7425 (use (match_operand 2 "" ""))
7426 (clobber (reg:SI LR_REGNUM))])])
7427
2d3a01a7 7428(define_expand "nonsecure_call_internal"
3934ae0e 7429 [(parallel [(call (unspec:SI [(match_operand 0 "memory_operand")]
2d3a01a7 7430 UNSPEC_NONSECURE_MEM)
3934ae0e 7431 (match_operand 1 "general_operand"))
2d3a01a7 7432 (use (match_operand 2 "" ""))
e27c5a70 7433 (clobber (reg:SI LR_REGNUM))])]
2d3a01a7 7434 "use_cmse"
7435 "
7436 {
7437 rtx tmp;
7438 tmp = copy_to_suggested_reg (XEXP (operands[0], 0),
e27c5a70 7439 gen_rtx_REG (SImode, R4_REGNUM),
2d3a01a7 7440 SImode);
7441
7442 operands[0] = replace_equiv_address (operands[0], tmp);
7443 }")
7444
f1039640 7445(define_insn "*call_reg_armv5"
d3373b54 7446 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
cffb2a26 7447 (match_operand 1 "" ""))
7448 (use (match_operand 2 "" ""))
bd5b4116 7449 (clobber (reg:SI LR_REGNUM))]
b232e6b5 7450 "TARGET_ARM && arm_arch5t && !SIBLING_CALL_P (insn)"
f1039640 7451 "blx%?\\t%0"
7452 [(set_attr "type" "call")]
7453)
7454
7455(define_insn "*call_reg_arm"
7456 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7457 (match_operand 1 "" ""))
7458 (use (match_operand 2 "" ""))
7459 (clobber (reg:SI LR_REGNUM))]
b232e6b5 7460 "TARGET_ARM && !arm_arch5t && !SIBLING_CALL_P (insn)"
9c08d1fa 7461 "*
5565501b 7462 return output_call (operands);
cffb2a26 7463 "
7464 ;; length is worst case, normally it is only two
7465 [(set_attr "length" "12")
7466 (set_attr "type" "call")]
7467)
9c08d1fa 7468
89504fc1 7469
d3373b54 7470(define_expand "call_value"
e0698af7 7471 [(parallel [(set (match_operand 0 "" "")
3934ae0e 7472 (call (match_operand 1 "memory_operand")
7473 (match_operand 2 "general_operand")))
cffb2a26 7474 (use (match_operand 3 "" ""))
bd5b4116 7475 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 7476 "TARGET_EITHER"
6c4c2133 7477 "
7478 {
bac7fc85 7479 rtx pat, callee;
2d3a01a7 7480 tree addr = MEM_EXPR (operands[1]);
bbe777ea 7481
7482 /* In an untyped call, we can get NULL for operand 2. */
7483 if (operands[3] == 0)
7484 operands[3] = const0_rtx;
7485
de55252a 7486 /* Decide if we should generate indirect calls by loading the
7487 32-bit address of the callee into a register before performing the
7488 branch and link. */
7489 callee = XEXP (operands[1], 0);
7490 if (GET_CODE (callee) == SYMBOL_REF
7491 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
7492 : !REG_P (callee))
78fe751b 7493 XEXP (operands[1], 0) = force_reg (Pmode, callee);
bac7fc85 7494
2649fa41 7495 if (TARGET_FDPIC && !SYMBOL_REF_P (XEXP (operands[1], 0)))
7496 /* Indirect call: set r9 with FDPIC value of callee. */
7497 XEXP (operands[1], 0)
7498 = arm_load_function_descriptor (XEXP (operands[1], 0));
7499
2d3a01a7 7500 if (detect_cmse_nonsecure_call (addr))
7501 {
7502 pat = gen_nonsecure_call_value_internal (operands[0], operands[1],
7503 operands[2], operands[3]);
7504 emit_call_insn (pat);
7505 }
7506 else
7507 {
7508 pat = gen_call_value_internal (operands[0], operands[1],
7509 operands[2], operands[3]);
7510 arm_emit_call_insn (pat, XEXP (operands[1], 0), false);
7511 }
2649fa41 7512
7513 /* Restore FDPIC register (r9) after call. */
7514 if (TARGET_FDPIC)
7515 {
7516 rtx fdpic_reg = gen_rtx_REG (Pmode, FDPIC_REGNUM);
7517 rtx initial_fdpic_reg
7518 = get_hard_reg_initial_val (Pmode, FDPIC_REGNUM);
7519
7520 emit_insn (gen_restore_pic_register_after_call (fdpic_reg,
7521 initial_fdpic_reg));
7522 }
7523
bac7fc85 7524 DONE;
6c4c2133 7525 }"
7526)
d3373b54 7527
bac7fc85 7528(define_expand "call_value_internal"
7529 [(parallel [(set (match_operand 0 "" "")
3934ae0e 7530 (call (match_operand 1 "memory_operand")
7531 (match_operand 2 "general_operand")))
bac7fc85 7532 (use (match_operand 3 "" ""))
7533 (clobber (reg:SI LR_REGNUM))])])
7534
2d3a01a7 7535(define_expand "nonsecure_call_value_internal"
7536 [(parallel [(set (match_operand 0 "" "")
3934ae0e 7537 (call (unspec:SI [(match_operand 1 "memory_operand")]
2d3a01a7 7538 UNSPEC_NONSECURE_MEM)
3934ae0e 7539 (match_operand 2 "general_operand")))
2d3a01a7 7540 (use (match_operand 3 "" ""))
e27c5a70 7541 (clobber (reg:SI LR_REGNUM))])]
2d3a01a7 7542 "use_cmse"
7543 "
7544 {
7545 rtx tmp;
7546 tmp = copy_to_suggested_reg (XEXP (operands[1], 0),
e27c5a70 7547 gen_rtx_REG (SImode, R4_REGNUM),
2d3a01a7 7548 SImode);
7549
7550 operands[1] = replace_equiv_address (operands[1], tmp);
7551 }")
7552
f1039640 7553(define_insn "*call_value_reg_armv5"
27ed6835 7554 [(set (match_operand 0 "" "")
755eb2b4 7555 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
cffb2a26 7556 (match_operand 2 "" "")))
bbe777ea 7557 (use (match_operand 3 "" ""))
bd5b4116 7558 (clobber (reg:SI LR_REGNUM))]
b232e6b5 7559 "TARGET_ARM && arm_arch5t && !SIBLING_CALL_P (insn)"
f1039640 7560 "blx%?\\t%1"
7561 [(set_attr "type" "call")]
7562)
7563
7564(define_insn "*call_value_reg_arm"
7565 [(set (match_operand 0 "" "")
7566 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7567 (match_operand 2 "" "")))
7568 (use (match_operand 3 "" ""))
7569 (clobber (reg:SI LR_REGNUM))]
b232e6b5 7570 "TARGET_ARM && !arm_arch5t && !SIBLING_CALL_P (insn)"
9c08d1fa 7571 "*
215b30b3 7572 return output_call (&operands[1]);
cffb2a26 7573 "
7574 [(set_attr "length" "12")
7575 (set_attr "type" "call")]
7576)
9c08d1fa 7577
9c08d1fa 7578;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
7579;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
7580
f7fbdd4a 7581(define_insn "*call_symbol"
27ed6835 7582 [(call (mem:SI (match_operand:SI 0 "" ""))
cffb2a26 7583 (match_operand 1 "" ""))
bbe777ea 7584 (use (match_operand 2 "" ""))
bd5b4116 7585 (clobber (reg:SI LR_REGNUM))]
d68c2c10 7586 "TARGET_32BIT
33ae7c4b 7587 && !SIBLING_CALL_P (insn)
cffb2a26 7588 && (GET_CODE (operands[0]) == SYMBOL_REF)
de55252a 7589 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
6ebaa29d 7590 "*
7591 {
95f1e0d1 7592 rtx op = operands[0];
7593
7594 /* Switch mode now when possible. */
7595 if (SYMBOL_REF_DECL (op) && !TREE_PUBLIC (SYMBOL_REF_DECL (op))
b232e6b5 7596 && arm_arch5t && arm_change_mode_p (SYMBOL_REF_DECL (op)))
95f1e0d1 7597 return NEED_PLT_RELOC ? \"blx%?\\t%a0(PLT)\" : \"blx%?\\t(%a0)\";
7598
55c1e470 7599 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
6ebaa29d 7600 }"
cffb2a26 7601 [(set_attr "type" "call")]
7602)
9c08d1fa 7603
f7fbdd4a 7604(define_insn "*call_value_symbol"
ccd90aaa 7605 [(set (match_operand 0 "" "")
27ed6835 7606 (call (mem:SI (match_operand:SI 1 "" ""))
dd6d7504 7607 (match_operand:SI 2 "" "")))
bbe777ea 7608 (use (match_operand 3 "" ""))
bd5b4116 7609 (clobber (reg:SI LR_REGNUM))]
d68c2c10 7610 "TARGET_32BIT
33ae7c4b 7611 && !SIBLING_CALL_P (insn)
cffb2a26 7612 && (GET_CODE (operands[1]) == SYMBOL_REF)
de55252a 7613 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
6ebaa29d 7614 "*
7615 {
95f1e0d1 7616 rtx op = operands[1];
7617
7618 /* Switch mode now when possible. */
7619 if (SYMBOL_REF_DECL (op) && !TREE_PUBLIC (SYMBOL_REF_DECL (op))
b232e6b5 7620 && arm_arch5t && arm_change_mode_p (SYMBOL_REF_DECL (op)))
3f6b66fa 7621 return NEED_PLT_RELOC ? \"blx%?\\t%a1(PLT)\" : \"blx%?\\t(%a1)\";
95f1e0d1 7622
55c1e470 7623 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
6ebaa29d 7624 }"
cffb2a26 7625 [(set_attr "type" "call")]
7626)
7627
ca373797 7628(define_expand "sibcall_internal"
3934ae0e 7629 [(parallel [(call (match_operand 0 "memory_operand")
7630 (match_operand 1 "general_operand"))
ca373797 7631 (return)
7632 (use (match_operand 2 "" ""))])])
7633
1c494086 7634;; We may also be able to do sibcalls for Thumb, but it's much harder...
7635(define_expand "sibcall"
3934ae0e 7636 [(parallel [(call (match_operand 0 "memory_operand")
7637 (match_operand 1 "general_operand"))
2ba80634 7638 (return)
7639 (use (match_operand 2 "" ""))])]
d68c2c10 7640 "TARGET_32BIT"
1c494086 7641 "
7642 {
ca373797 7643 rtx pat;
7644
3112c3f7 7645 if ((!REG_P (XEXP (operands[0], 0))
7646 && GET_CODE (XEXP (operands[0], 0)) != SYMBOL_REF)
7647 || (GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
7648 && arm_is_long_call_p (SYMBOL_REF_DECL (XEXP (operands[0], 0)))))
33ae7c4b 7649 XEXP (operands[0], 0) = force_reg (SImode, XEXP (operands[0], 0));
7650
1c494086 7651 if (operands[2] == NULL_RTX)
7652 operands[2] = const0_rtx;
ca373797 7653
7654 pat = gen_sibcall_internal (operands[0], operands[1], operands[2]);
7655 arm_emit_call_insn (pat, operands[0], true);
7656 DONE;
1c494086 7657 }"
7658)
7659
ca373797 7660(define_expand "sibcall_value_internal"
7661 [(parallel [(set (match_operand 0 "" "")
3934ae0e 7662 (call (match_operand 1 "memory_operand")
7663 (match_operand 2 "general_operand")))
ca373797 7664 (return)
7665 (use (match_operand 3 "" ""))])])
7666
1c494086 7667(define_expand "sibcall_value"
ccd90aaa 7668 [(parallel [(set (match_operand 0 "" "")
3934ae0e 7669 (call (match_operand 1 "memory_operand")
7670 (match_operand 2 "general_operand")))
2ba80634 7671 (return)
7672 (use (match_operand 3 "" ""))])]
d68c2c10 7673 "TARGET_32BIT"
1c494086 7674 "
7675 {
ca373797 7676 rtx pat;
7677
3112c3f7 7678 if ((!REG_P (XEXP (operands[1], 0))
7679 && GET_CODE (XEXP (operands[1], 0)) != SYMBOL_REF)
7680 || (GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
7681 && arm_is_long_call_p (SYMBOL_REF_DECL (XEXP (operands[1], 0)))))
33ae7c4b 7682 XEXP (operands[1], 0) = force_reg (SImode, XEXP (operands[1], 0));
7683
1c494086 7684 if (operands[3] == NULL_RTX)
7685 operands[3] = const0_rtx;
ca373797 7686
7687 pat = gen_sibcall_value_internal (operands[0], operands[1],
7688 operands[2], operands[3]);
7689 arm_emit_call_insn (pat, operands[1], true);
7690 DONE;
1c494086 7691 }"
7692)
7693
7694(define_insn "*sibcall_insn"
84ce8e5c 7695 [(call (mem:SI (match_operand:SI 0 "call_insn_operand" "Cs, US"))
1c494086 7696 (match_operand 1 "" ""))
2ba80634 7697 (return)
7698 (use (match_operand 2 "" ""))]
33ae7c4b 7699 "TARGET_32BIT && SIBLING_CALL_P (insn)"
1c494086 7700 "*
33ae7c4b 7701 if (which_alternative == 1)
7702 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
7703 else
7704 {
b232e6b5 7705 if (arm_arch5t || arm_arch4t)
947d113e 7706 return \"bx%?\\t%0\\t%@ indirect register sibling call\";
33ae7c4b 7707 else
7708 return \"mov%?\\t%|pc, %0\\t%@ indirect register sibling call\";
7709 }
1c494086 7710 "
7711 [(set_attr "type" "call")]
7712)
7713
7714(define_insn "*sibcall_value_insn"
84ce8e5c 7715 [(set (match_operand 0 "" "")
7716 (call (mem:SI (match_operand:SI 1 "call_insn_operand" "Cs,US"))
1c494086 7717 (match_operand 2 "" "")))
2ba80634 7718 (return)
7719 (use (match_operand 3 "" ""))]
33ae7c4b 7720 "TARGET_32BIT && SIBLING_CALL_P (insn)"
1c494086 7721 "*
33ae7c4b 7722 if (which_alternative == 1)
7723 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
7724 else
7725 {
b232e6b5 7726 if (arm_arch5t || arm_arch4t)
84ce8e5c 7727 return \"bx%?\\t%1\";
33ae7c4b 7728 else
7729 return \"mov%?\\t%|pc, %1\\t@ indirect sibling call \";
7730 }
1c494086 7731 "
7732 [(set_attr "type" "call")]
7733)
7734
0686440e 7735(define_expand "<return_str>return"
9b23f0a7 7736 [(RETURNS)]
8cba51a5 7737 "(TARGET_ARM || (TARGET_THUMB2
7738 && ARM_FUNC_TYPE (arm_current_func_type ()) == ARM_FT_NORMAL
7739 && !IS_STACKALIGN (arm_current_func_type ())))
0686440e 7740 <return_cond_false>"
8cba51a5 7741 "
7742 {
7743 if (TARGET_THUMB2)
7744 {
0686440e 7745 thumb2_expand_return (<return_simple_p>);
8cba51a5 7746 DONE;
7747 }
7748 }
7749 "
7750)
d68c2c10 7751
9c08d1fa 7752;; Often the return insn will be the same as loading from memory, so set attr
d68c2c10 7753(define_insn "*arm_return"
9c08d1fa 7754 [(return)]
cffb2a26 7755 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
9c08d1fa 7756 "*
9c08d1fa 7757 {
cffb2a26 7758 if (arm_ccfsm_state == 2)
7759 {
7760 arm_ccfsm_state += 2;
7761 return \"\";
7762 }
e2549f81 7763 return output_return_instruction (const_true_rtx, true, false, false);
cffb2a26 7764 }"
9f2c2a36 7765 [(set_attr "type" "load_4")
755eb2b4 7766 (set_attr "length" "12")
0d66636f 7767 (set_attr "predicable" "yes")]
cffb2a26 7768)
9c08d1fa 7769
0686440e 7770(define_insn "*cond_<return_str>return"
9c08d1fa 7771 [(set (pc)
8fa3ba89 7772 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 7773 [(match_operand 1 "cc_register" "") (const_int 0)])
9b23f0a7 7774 (RETURNS)
9c08d1fa 7775 (pc)))]
0686440e 7776 "TARGET_ARM <return_cond_true>"
9c08d1fa 7777 "*
8fa3ba89 7778 {
7779 if (arm_ccfsm_state == 2)
7780 {
7781 arm_ccfsm_state += 2;
7782 return \"\";
7783 }
0686440e 7784 return output_return_instruction (operands[0], true, false,
7785 <return_simple_p>);
8fa3ba89 7786 }"
7787 [(set_attr "conds" "use")
755eb2b4 7788 (set_attr "length" "12")
9f2c2a36 7789 (set_attr "type" "load_4")]
8fa3ba89 7790)
9c08d1fa 7791
0686440e 7792(define_insn "*cond_<return_str>return_inverted"
9c08d1fa 7793 [(set (pc)
8fa3ba89 7794 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 7795 [(match_operand 1 "cc_register" "") (const_int 0)])
9c08d1fa 7796 (pc)
9b23f0a7 7797 (RETURNS)))]
0686440e 7798 "TARGET_ARM <return_cond_true>"
9c08d1fa 7799 "*
8fa3ba89 7800 {
7801 if (arm_ccfsm_state == 2)
7802 {
7803 arm_ccfsm_state += 2;
7804 return \"\";
7805 }
0686440e 7806 return output_return_instruction (operands[0], true, true,
7807 <return_simple_p>);
8fa3ba89 7808 }"
7809 [(set_attr "conds" "use")
37a1317b 7810 (set_attr "length" "12")
9f2c2a36 7811 (set_attr "type" "load_4")]
8fa3ba89 7812)
9c08d1fa 7813
e2549f81 7814(define_insn "*arm_simple_return"
7815 [(simple_return)]
7816 "TARGET_ARM"
7817 "*
7818 {
7819 if (arm_ccfsm_state == 2)
7820 {
7821 arm_ccfsm_state += 2;
7822 return \"\";
7823 }
7824 return output_return_instruction (const_true_rtx, true, false, true);
7825 }"
7826 [(set_attr "type" "branch")
7827 (set_attr "length" "4")
7828 (set_attr "predicable" "yes")]
7829)
7830
68121397 7831;; Generate a sequence of instructions to determine if the processor is
7832;; in 26-bit or 32-bit mode, and return the appropriate return address
7833;; mask.
7834
7835(define_expand "return_addr_mask"
7836 [(set (match_dup 1)
7837 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7838 (const_int 0)))
3934ae0e 7839 (set (match_operand:SI 0 "s_register_operand")
68121397 7840 (if_then_else:SI (eq (match_dup 1) (const_int 0))
7841 (const_int -1)
7842 (const_int 67108860)))] ; 0x03fffffc
7843 "TARGET_ARM"
7844 "
62eddbd4 7845 operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
68121397 7846 ")
7847
7848(define_insn "*check_arch2"
7849 [(set (match_operand:CC_NOOV 0 "cc_register" "")
7850 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7851 (const_int 0)))]
7852 "TARGET_ARM"
7853 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
7854 [(set_attr "length" "8")
1b7da4ac 7855 (set_attr "conds" "set")
7856 (set_attr "type" "multiple")]
68121397 7857)
7858
9c08d1fa 7859;; Call subroutine returning any type.
7860
7861(define_expand "untyped_call"
7862 [(parallel [(call (match_operand 0 "" "")
7863 (const_int 0))
7864 (match_operand 1 "" "")
7865 (match_operand 2 "" "")])]
2649fa41 7866 "TARGET_EITHER && !TARGET_FDPIC"
9c08d1fa 7867 "
215b30b3 7868 {
7869 int i;
ccd90aaa 7870 rtx par = gen_rtx_PARALLEL (VOIDmode,
7871 rtvec_alloc (XVECLEN (operands[2], 0)));
7872 rtx addr = gen_reg_rtx (Pmode);
7873 rtx mem;
7874 int size = 0;
9c08d1fa 7875
ccd90aaa 7876 emit_move_insn (addr, XEXP (operands[1], 0));
7877 mem = change_address (operands[1], BLKmode, addr);
9c08d1fa 7878
215b30b3 7879 for (i = 0; i < XVECLEN (operands[2], 0); i++)
7880 {
ccd90aaa 7881 rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
9c08d1fa 7882
ccd90aaa 7883 /* Default code only uses r0 as a return value, but we could
7884 be using anything up to 4 registers. */
7885 if (REGNO (src) == R0_REGNUM)
7886 src = gen_rtx_REG (TImode, R0_REGNUM);
7887
7888 XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
7889 GEN_INT (size));
7890 size += GET_MODE_SIZE (GET_MODE (src));
7891 }
7892
7f265a08 7893 emit_call_insn (gen_call_value (par, operands[0], const0_rtx, NULL));
ccd90aaa 7894
7895 size = 0;
7896
7897 for (i = 0; i < XVECLEN (par, 0); i++)
7898 {
7899 HOST_WIDE_INT offset = 0;
7900 rtx reg = XEXP (XVECEXP (par, 0, i), 0);
7901
7902 if (size != 0)
29c05e22 7903 emit_move_insn (addr, plus_constant (Pmode, addr, size));
ccd90aaa 7904
7905 mem = change_address (mem, GET_MODE (reg), NULL);
7906 if (REGNO (reg) == R0_REGNUM)
7907 {
7908 /* On thumb we have to use a write-back instruction. */
320ea44d 7909 emit_insn (arm_gen_store_multiple (arm_regs_in_sequence, 4, addr,
7910 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
ccd90aaa 7911 size = TARGET_ARM ? 16 : 0;
7912 }
7913 else
7914 {
7915 emit_move_insn (mem, reg);
7916 size = GET_MODE_SIZE (GET_MODE (reg));
7917 }
215b30b3 7918 }
9c08d1fa 7919
215b30b3 7920 /* The optimizer does not know that the call sets the function value
7921 registers we stored in the result block. We avoid problems by
7922 claiming that all hard registers are used and clobbered at this
7923 point. */
7924 emit_insn (gen_blockage ());
7925
7926 DONE;
7927 }"
7928)
9c08d1fa 7929
ccd90aaa 7930(define_expand "untyped_return"
3934ae0e 7931 [(match_operand:BLK 0 "memory_operand")
ccd90aaa 7932 (match_operand 1 "" "")]
2649fa41 7933 "TARGET_EITHER && !TARGET_FDPIC"
ccd90aaa 7934 "
7935 {
7936 int i;
7937 rtx addr = gen_reg_rtx (Pmode);
7938 rtx mem;
7939 int size = 0;
7940
7941 emit_move_insn (addr, XEXP (operands[0], 0));
7942 mem = change_address (operands[0], BLKmode, addr);
7943
7944 for (i = 0; i < XVECLEN (operands[1], 0); i++)
7945 {
7946 HOST_WIDE_INT offset = 0;
7947 rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
7948
7949 if (size != 0)
29c05e22 7950 emit_move_insn (addr, plus_constant (Pmode, addr, size));
ccd90aaa 7951
7952 mem = change_address (mem, GET_MODE (reg), NULL);
7953 if (REGNO (reg) == R0_REGNUM)
7954 {
7955 /* On thumb we have to use a write-back instruction. */
320ea44d 7956 emit_insn (arm_gen_load_multiple (arm_regs_in_sequence, 4, addr,
7957 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
ccd90aaa 7958 size = TARGET_ARM ? 16 : 0;
7959 }
7960 else
7961 {
7962 emit_move_insn (reg, mem);
7963 size = GET_MODE_SIZE (GET_MODE (reg));
7964 }
7965 }
7966
7967 /* Emit USE insns before the return. */
7968 for (i = 0; i < XVECLEN (operands[1], 0); i++)
18b42941 7969 emit_use (SET_DEST (XVECEXP (operands[1], 0, i)));
ccd90aaa 7970
7971 /* Construct the return. */
7972 expand_naked_return ();
7973
7974 DONE;
7975 }"
7976)
7977
9c08d1fa 7978;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
7979;; all of memory. This blocks insns from being moved across this point.
7980
7981(define_insn "blockage"
e1159bbe 7982 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
cffb2a26 7983 "TARGET_EITHER"
9c08d1fa 7984 ""
cffb2a26 7985 [(set_attr "length" "0")
7986 (set_attr "type" "block")]
7987)
9c08d1fa 7988
80c63fc3 7989;; Since we hard code r0 here use the 'o' constraint to prevent
7990;; provoking undefined behaviour in the hardware with putting out
7991;; auto-increment operations with potentially r0 as the base register.
706dca65 7992(define_insn "probe_stack"
80c63fc3 7993 [(set (match_operand:SI 0 "memory_operand" "=o")
f8570abe 7994 (unspec:SI [(const_int 0)] UNSPEC_PROBE_STACK))]
706dca65 7995 "TARGET_32BIT"
154ae8e6 7996 "str%?\\tr0, %0"
9f2c2a36 7997 [(set_attr "type" "store_4")
706dca65 7998 (set_attr "predicable" "yes")]
7999)
8000
8001(define_insn "probe_stack_range"
8002 [(set (match_operand:SI 0 "register_operand" "=r")
8003 (unspec_volatile:SI [(match_operand:SI 1 "register_operand" "0")
8004 (match_operand:SI 2 "register_operand" "r")]
dd8aabc9 8005 VUNSPEC_PROBE_STACK_RANGE))]
706dca65 8006 "TARGET_32BIT"
8007{
8008 return output_probe_stack_range (operands[0], operands[2]);
8009}
8010 [(set_attr "type" "multiple")
8011 (set_attr "conds" "clob")]
8012)
8013
f98495d9 8014;; Named patterns for stack smashing protection.
8015(define_expand "stack_protect_combined_set"
8016 [(parallel
3934ae0e 8017 [(set (match_operand:SI 0 "memory_operand")
8018 (unspec:SI [(match_operand:SI 1 "guard_operand")]
f98495d9 8019 UNSPEC_SP_SET))
8020 (clobber (match_scratch:SI 2 ""))
8021 (clobber (match_scratch:SI 3 ""))])]
8022 ""
8023 ""
8024)
8025
8026;; Use a separate insn from the above expand to be able to have the mem outside
8027;; the operand #1 when register allocation comes. This is needed to avoid LRA
8028;; try to reload the guard since we need to control how PIC access is done in
8029;; the -fpic/-fPIC case (see COMPUTE_NOW parameter when calling
8030;; legitimize_pic_address ()).
8031(define_insn_and_split "*stack_protect_combined_set_insn"
8032 [(set (match_operand:SI 0 "memory_operand" "=m,m")
8033 (unspec:SI [(mem:SI (match_operand:SI 1 "guard_addr_operand" "X,X"))]
8034 UNSPEC_SP_SET))
8035 (clobber (match_scratch:SI 2 "=&l,&r"))
8036 (clobber (match_scratch:SI 3 "=&l,&r"))]
8037 ""
8038 "#"
8039 "reload_completed"
8040 [(parallel [(set (match_dup 0) (unspec:SI [(mem:SI (match_dup 2))]
8041 UNSPEC_SP_SET))
8042 (clobber (match_dup 2))])]
8043 "
8044{
8045 if (flag_pic)
8046 {
d89c0749 8047 rtx pic_reg;
8048
8049 if (TARGET_FDPIC)
8050 pic_reg = gen_rtx_REG (Pmode, FDPIC_REGNUM);
8051 else
8052 pic_reg = operands[3];
8053
f98495d9 8054 /* Forces recomputing of GOT base now. */
d89c0749 8055 legitimize_pic_address (operands[1], SImode, operands[2], pic_reg,
f98495d9 8056 true /*compute_now*/);
8057 }
8058 else
8059 {
8060 if (address_operand (operands[1], SImode))
8061 operands[2] = operands[1];
8062 else
8063 {
8064 rtx mem = XEXP (force_const_mem (SImode, operands[1]), 0);
8065 emit_move_insn (operands[2], mem);
8066 }
8067 }
8068}"
8069 [(set_attr "arch" "t1,32")]
8070)
8071
fa66a3db 8072;; DO NOT SPLIT THIS INSN. It's important for security reasons that the
8073;; canary value does not live beyond the life of this sequence.
f98495d9 8074(define_insn "*stack_protect_set_insn"
8075 [(set (match_operand:SI 0 "memory_operand" "=m,m")
8076 (unspec:SI [(mem:SI (match_operand:SI 1 "register_operand" "+&l,&r"))]
8077 UNSPEC_SP_SET))
8078 (clobber (match_dup 1))]
8079 ""
8080 "@
fa66a3db 8081 ldr\\t%1, [%1]\;str\\t%1, %0\;movs\t%1, #0
8082 ldr\\t%1, [%1]\;str\\t%1, %0\;mov\t%1, #0"
f98495d9 8083 [(set_attr "length" "8,12")
8084 (set_attr "conds" "clob,nocond")
8085 (set_attr "type" "multiple")
8086 (set_attr "arch" "t1,32")]
8087)
8088
8089(define_expand "stack_protect_combined_test"
8090 [(parallel
8091 [(set (pc)
8092 (if_then_else
3934ae0e 8093 (eq (match_operand:SI 0 "memory_operand")
8094 (unspec:SI [(match_operand:SI 1 "guard_operand")]
f98495d9 8095 UNSPEC_SP_TEST))
8096 (label_ref (match_operand 2))
8097 (pc)))
8098 (clobber (match_scratch:SI 3 ""))
8099 (clobber (match_scratch:SI 4 ""))
8100 (clobber (reg:CC CC_REGNUM))])]
8101 ""
8102 ""
8103)
8104
8105;; Use a separate insn from the above expand to be able to have the mem outside
8106;; the operand #1 when register allocation comes. This is needed to avoid LRA
8107;; try to reload the guard since we need to control how PIC access is done in
8108;; the -fpic/-fPIC case (see COMPUTE_NOW parameter when calling
8109;; legitimize_pic_address ()).
8110(define_insn_and_split "*stack_protect_combined_test_insn"
8111 [(set (pc)
8112 (if_then_else
8113 (eq (match_operand:SI 0 "memory_operand" "m,m")
8114 (unspec:SI [(mem:SI (match_operand:SI 1 "guard_addr_operand" "X,X"))]
8115 UNSPEC_SP_TEST))
8116 (label_ref (match_operand 2))
8117 (pc)))
8118 (clobber (match_scratch:SI 3 "=&l,&r"))
8119 (clobber (match_scratch:SI 4 "=&l,&r"))
8120 (clobber (reg:CC CC_REGNUM))]
8121 ""
8122 "#"
8123 "reload_completed"
8124 [(const_int 0)]
8125{
8126 rtx eq;
8127
8128 if (flag_pic)
8129 {
d89c0749 8130 rtx pic_reg;
8131
8132 if (TARGET_FDPIC)
8133 pic_reg = gen_rtx_REG (Pmode, FDPIC_REGNUM);
8134 else
8135 pic_reg = operands[4];
8136
f98495d9 8137 /* Forces recomputing of GOT base now. */
d89c0749 8138 legitimize_pic_address (operands[1], SImode, operands[3], pic_reg,
f98495d9 8139 true /*compute_now*/);
8140 }
8141 else
8142 {
8143 if (address_operand (operands[1], SImode))
8144 operands[3] = operands[1];
8145 else
8146 {
8147 rtx mem = XEXP (force_const_mem (SImode, operands[1]), 0);
8148 emit_move_insn (operands[3], mem);
8149 }
8150 }
8151 if (TARGET_32BIT)
8152 {
8153 emit_insn (gen_arm_stack_protect_test_insn (operands[4], operands[0],
8154 operands[3]));
8155 rtx cc_reg = gen_rtx_REG (CC_Zmode, CC_REGNUM);
8156 eq = gen_rtx_EQ (CC_Zmode, cc_reg, const0_rtx);
8157 emit_jump_insn (gen_arm_cond_branch (operands[2], eq, cc_reg));
8158 }
8159 else
8160 {
8161 emit_insn (gen_thumb1_stack_protect_test_insn (operands[4], operands[0],
8162 operands[3]));
8163 eq = gen_rtx_EQ (VOIDmode, operands[4], const0_rtx);
8164 emit_jump_insn (gen_cbranchsi4 (eq, operands[4], const0_rtx,
8165 operands[2]));
8166 }
8167 DONE;
8168}
8169 [(set_attr "arch" "t1,32")]
8170)
8171
8172(define_insn "arm_stack_protect_test_insn"
8173 [(set (reg:CC_Z CC_REGNUM)
8174 (compare:CC_Z (unspec:SI [(match_operand:SI 1 "memory_operand" "m,m")
8175 (mem:SI (match_operand:SI 2 "register_operand" "+l,r"))]
8176 UNSPEC_SP_TEST)
8177 (const_int 0)))
8178 (clobber (match_operand:SI 0 "register_operand" "=&l,&r"))
8179 (clobber (match_dup 2))]
8180 "TARGET_32BIT"
8181 "ldr\t%0, [%2]\;ldr\t%2, %1\;eors\t%0, %2, %0"
8182 [(set_attr "length" "8,12")
8183 (set_attr "conds" "set")
8184 (set_attr "type" "multiple")
8185 (set_attr "arch" "t,32")]
8186)
8187
f7fbdd4a 8188(define_expand "casesi"
3934ae0e 8189 [(match_operand:SI 0 "s_register_operand") ; index to jump on
8190 (match_operand:SI 1 "const_int_operand") ; lower bound
8191 (match_operand:SI 2 "const_int_operand") ; total range
f7fbdd4a 8192 (match_operand:SI 3 "" "") ; table label
8193 (match_operand:SI 4 "" "")] ; Out of range label
9753b549 8194 "(TARGET_32BIT || optimize_size || flag_pic) && !target_pure_code"
f7fbdd4a 8195 "
215b30b3 8196 {
e6ac8414 8197 enum insn_code code;
215b30b3 8198 if (operands[1] != const0_rtx)
8199 {
e6ac8414 8200 rtx reg = gen_reg_rtx (SImode);
f7fbdd4a 8201
215b30b3 8202 emit_insn (gen_addsi3 (reg, operands[0],
d022fa24 8203 gen_int_mode (-INTVAL (operands[1]),
8204 SImode)));
215b30b3 8205 operands[0] = reg;
8206 }
9c08d1fa 8207
25f905c2 8208 if (TARGET_ARM)
e6ac8414 8209 code = CODE_FOR_arm_casesi_internal;
3db2019b 8210 else if (TARGET_THUMB1)
e6ac8414 8211 code = CODE_FOR_thumb1_casesi_internal_pic;
25f905c2 8212 else if (flag_pic)
e6ac8414 8213 code = CODE_FOR_thumb2_casesi_internal_pic;
25f905c2 8214 else
e6ac8414 8215 code = CODE_FOR_thumb2_casesi_internal;
8216
8217 if (!insn_data[(int) code].operand[1].predicate(operands[2], SImode))
8218 operands[2] = force_reg (SImode, operands[2]);
8219
8220 emit_jump_insn (GEN_FCN ((int) code) (operands[0], operands[2],
8221 operands[3], operands[4]));
215b30b3 8222 DONE;
8223 }"
8224)
f7fbdd4a 8225
f082f1c4 8226;; The USE in this pattern is needed to tell flow analysis that this is
8227;; a CASESI insn. It has no other purpose.
b634d96a 8228(define_expand "arm_casesi_internal"
8229 [(parallel [(set (pc)
8230 (if_then_else
8231 (leu (match_operand:SI 0 "s_register_operand")
8232 (match_operand:SI 1 "arm_rhs_operand"))
8233 (match_dup 4)
8234 (label_ref:SI (match_operand 3 ""))))
8235 (clobber (reg:CC CC_REGNUM))
8236 (use (label_ref:SI (match_operand 2 "")))])]
8237 "TARGET_ARM"
8238{
8239 operands[4] = gen_rtx_MULT (SImode, operands[0], GEN_INT (4));
8240 operands[4] = gen_rtx_PLUS (SImode, operands[4],
8241 gen_rtx_LABEL_REF (SImode, operands[2]));
8242 operands[4] = gen_rtx_MEM (SImode, operands[4]);
8243 MEM_READONLY_P (operands[4]) = 1;
8244 MEM_NOTRAP_P (operands[4]) = 1;
8245})
8246
8247(define_insn "*arm_casesi_internal"
f082f1c4 8248 [(parallel [(set (pc)
8249 (if_then_else
8250 (leu (match_operand:SI 0 "s_register_operand" "r")
8251 (match_operand:SI 1 "arm_rhs_operand" "rI"))
8252 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
b634d96a 8253 (label_ref:SI (match_operand 2 "" ""))))
8254 (label_ref:SI (match_operand 3 "" ""))))
bd5b4116 8255 (clobber (reg:CC CC_REGNUM))
b634d96a 8256 (use (label_ref:SI (match_dup 2)))])]
cffb2a26 8257 "TARGET_ARM"
f7fbdd4a 8258 "*
0d66636f 8259 if (flag_pic)
8260 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
8261 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
8262 "
8263 [(set_attr "conds" "clob")
1b7da4ac 8264 (set_attr "length" "12")
8265 (set_attr "type" "multiple")]
0d66636f 8266)
9c08d1fa 8267
cffb2a26 8268(define_expand "indirect_jump"
9c08d1fa 8269 [(set (pc)
3934ae0e 8270 (match_operand:SI 0 "s_register_operand"))]
cffb2a26 8271 "TARGET_EITHER"
25f905c2 8272 "
8273 /* Thumb-2 doesn't have mov pc, reg. Explicitly set the low bit of the
8274 address and use bx. */
8275 if (TARGET_THUMB2)
8276 {
8277 rtx tmp;
8278 tmp = gen_reg_rtx (SImode);
8279 emit_insn (gen_iorsi3 (tmp, operands[0], GEN_INT(1)));
8280 operands[0] = tmp;
8281 }
8282 "
cffb2a26 8283)
8284
f1039640 8285;; NB Never uses BX.
cffb2a26 8286(define_insn "*arm_indirect_jump"
8287 [(set (pc)
8288 (match_operand:SI 0 "s_register_operand" "r"))]
8289 "TARGET_ARM"
8290 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
1b7da4ac 8291 [(set_attr "predicable" "yes")
8292 (set_attr "type" "branch")]
cffb2a26 8293)
9c08d1fa 8294
f7fbdd4a 8295(define_insn "*load_indirect_jump"
9c08d1fa 8296 [(set (pc)
8297 (match_operand:SI 0 "memory_operand" "m"))]
cffb2a26 8298 "TARGET_ARM"
8299 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
9f2c2a36 8300 [(set_attr "type" "load_4")
61a2d04c 8301 (set_attr "pool_range" "4096")
8302 (set_attr "neg_pool_range" "4084")
0d66636f 8303 (set_attr "predicable" "yes")]
cffb2a26 8304)
8305
9c08d1fa 8306\f
8307;; Misc insns
8308
8309(define_insn "nop"
8310 [(const_int 0)]
cffb2a26 8311 "TARGET_EITHER"
3ef90e77 8312 "nop"
cffb2a26 8313 [(set (attr "length")
8314 (if_then_else (eq_attr "is_thumb" "yes")
8315 (const_int 2)
1b7da4ac 8316 (const_int 4)))
8317 (set_attr "type" "mov_reg")]
cffb2a26 8318)
8319
ad9d4399 8320(define_insn "trap"
8321 [(trap_if (const_int 1) (const_int 0))]
8322 ""
8323 "*
8324 if (TARGET_ARM)
8325 return \".inst\\t0xe7f000f0\";
8326 else
8327 return \".inst\\t0xdeff\";
8328 "
8329 [(set (attr "length")
8330 (if_then_else (eq_attr "is_thumb" "yes")
8331 (const_int 2)
8332 (const_int 4)))
8333 (set_attr "type" "trap")
8334 (set_attr "conds" "unconditional")]
8335)
8336
9c08d1fa 8337\f
8338;; Patterns to allow combination of arithmetic, cond code and shifts
8339
0abea32c 8340(define_insn "*<arith_shift_insn>_multsi"
8341 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9b23f0a7 8342 (SHIFTABLE_OPS:SI
0abea32c 8343 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
8344 (match_operand:SI 3 "power_of_two_operand" ""))
8345 (match_operand:SI 1 "s_register_operand" "rk,<t2_binop0>")))]
d5d4dc8d 8346 "TARGET_32BIT"
0abea32c 8347 "<arith_shift_insn>%?\\t%0, %1, %2, lsl %b3"
8348 [(set_attr "predicable" "yes")
753d9835 8349 (set_attr "shift" "2")
0abea32c 8350 (set_attr "arch" "a,t2")
8351 (set_attr "type" "alu_shift_imm")])
8352
8353(define_insn "*<arith_shift_insn>_shiftsi"
8354 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9b23f0a7 8355 (SHIFTABLE_OPS:SI
0abea32c 8356 (match_operator:SI 2 "shift_nomul_operator"
8357 [(match_operand:SI 3 "s_register_operand" "r,r,r")
8358 (match_operand:SI 4 "shift_amount_operand" "M,M,r")])
8359 (match_operand:SI 1 "s_register_operand" "rk,<t2_binop0>,rk")))]
a021b821 8360 "TARGET_32BIT && GET_CODE (operands[2]) != MULT"
0abea32c 8361 "<arith_shift_insn>%?\\t%0, %1, %3%S2"
344495ea 8362 [(set_attr "predicable" "yes")
753d9835 8363 (set_attr "shift" "3")
0abea32c 8364 (set_attr "arch" "a,t2,a")
8365 (set_attr "type" "alu_shift_imm,alu_shift_imm,alu_shift_reg")])
9c08d1fa 8366
d7863cfe 8367(define_split
8368 [(set (match_operand:SI 0 "s_register_operand" "")
8369 (match_operator:SI 1 "shiftable_operator"
8370 [(match_operator:SI 2 "shiftable_operator"
8371 [(match_operator:SI 3 "shift_operator"
8372 [(match_operand:SI 4 "s_register_operand" "")
8373 (match_operand:SI 5 "reg_or_int_operand" "")])
8374 (match_operand:SI 6 "s_register_operand" "")])
8375 (match_operand:SI 7 "arm_rhs_operand" "")]))
8376 (clobber (match_operand:SI 8 "s_register_operand" ""))]
d5d4dc8d 8377 "TARGET_32BIT"
d7863cfe 8378 [(set (match_dup 8)
8379 (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8380 (match_dup 6)]))
8381 (set (match_dup 0)
8382 (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
8383 "")
8384
f7fbdd4a 8385(define_insn "*arith_shiftsi_compare0"
bd5b4116 8386 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 8387 (compare:CC_NOOV
8388 (match_operator:SI 1 "shiftable_operator"
8389 [(match_operator:SI 3 "shift_operator"
8390 [(match_operand:SI 4 "s_register_operand" "r,r")
8391 (match_operand:SI 5 "shift_amount_operand" "M,r")])
8392 (match_operand:SI 2 "s_register_operand" "r,r")])
8393 (const_int 0)))
8394 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 8395 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8396 (match_dup 2)]))]
d5d4dc8d 8397 "TARGET_32BIT"
3ef90e77 8398 "%i1s%?\\t%0, %2, %4%S3"
344495ea 8399 [(set_attr "conds" "set")
331beb1a 8400 (set_attr "shift" "4")
d5d4dc8d 8401 (set_attr "arch" "32,a")
d82e788e 8402 (set_attr "type" "alus_shift_imm,alus_shift_reg")])
9c08d1fa 8403
f7fbdd4a 8404(define_insn "*arith_shiftsi_compare0_scratch"
bd5b4116 8405 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 8406 (compare:CC_NOOV
8407 (match_operator:SI 1 "shiftable_operator"
8408 [(match_operator:SI 3 "shift_operator"
8409 [(match_operand:SI 4 "s_register_operand" "r,r")
8410 (match_operand:SI 5 "shift_amount_operand" "M,r")])
8411 (match_operand:SI 2 "s_register_operand" "r,r")])
8412 (const_int 0)))
8413 (clobber (match_scratch:SI 0 "=r,r"))]
8414 "TARGET_32BIT"
3ef90e77 8415 "%i1s%?\\t%0, %2, %4%S3"
344495ea 8416 [(set_attr "conds" "set")
331beb1a 8417 (set_attr "shift" "4")
d5d4dc8d 8418 (set_attr "arch" "32,a")
d82e788e 8419 (set_attr "type" "alus_shift_imm,alus_shift_reg")])
9c08d1fa 8420
f7fbdd4a 8421(define_insn "*sub_shiftsi"
d5d4dc8d 8422 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8423 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
9c08d1fa 8424 (match_operator:SI 2 "shift_operator"
d5d4dc8d 8425 [(match_operand:SI 3 "s_register_operand" "r,r")
8426 (match_operand:SI 4 "shift_amount_operand" "M,r")])))]
8427 "TARGET_32BIT"
6c4c2133 8428 "sub%?\\t%0, %1, %3%S2"
344495ea 8429 [(set_attr "predicable" "yes")
2df5a382 8430 (set_attr "predicable_short_it" "no")
331beb1a 8431 (set_attr "shift" "3")
d5d4dc8d 8432 (set_attr "arch" "32,a")
d82e788e 8433 (set_attr "type" "alus_shift_imm,alus_shift_reg")])
9c08d1fa 8434
f7fbdd4a 8435(define_insn "*sub_shiftsi_compare0"
bd5b4116 8436 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 8437 (compare:CC_NOOV
d82e788e 8438 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
40dbec34 8439 (match_operator:SI 2 "shift_operator"
d82e788e 8440 [(match_operand:SI 3 "s_register_operand" "r,r,r")
8441 (match_operand:SI 4 "shift_amount_operand" "M,r,M")]))
40dbec34 8442 (const_int 0)))
d82e788e 8443 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
d5d4dc8d 8444 (minus:SI (match_dup 1)
8445 (match_op_dup 2 [(match_dup 3) (match_dup 4)])))]
8446 "TARGET_32BIT"
3ef90e77 8447 "subs%?\\t%0, %1, %3%S2"
344495ea 8448 [(set_attr "conds" "set")
a2cd141b 8449 (set_attr "shift" "3")
d82e788e 8450 (set_attr "arch" "32,a,a")
8451 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
9c08d1fa 8452
f7fbdd4a 8453(define_insn "*sub_shiftsi_compare0_scratch"
bd5b4116 8454 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 8455 (compare:CC_NOOV
d82e788e 8456 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
40dbec34 8457 (match_operator:SI 2 "shift_operator"
d82e788e 8458 [(match_operand:SI 3 "s_register_operand" "r,r,r")
8459 (match_operand:SI 4 "shift_amount_operand" "M,r,M")]))
40dbec34 8460 (const_int 0)))
d82e788e 8461 (clobber (match_scratch:SI 0 "=r,r,r"))]
d5d4dc8d 8462 "TARGET_32BIT"
3ef90e77 8463 "subs%?\\t%0, %1, %3%S2"
344495ea 8464 [(set_attr "conds" "set")
a2cd141b 8465 (set_attr "shift" "3")
d82e788e 8466 (set_attr "arch" "32,a,a")
8467 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
9c08d1fa 8468\f
8469
190efb17 8470(define_insn_and_split "*and_scc"
9c08d1fa 8471 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 8472 (and:SI (match_operator:SI 1 "arm_comparison_operator"
190efb17 8473 [(match_operand 2 "cc_register" "") (const_int 0)])
8474 (match_operand:SI 3 "s_register_operand" "r")))]
cffb2a26 8475 "TARGET_ARM"
190efb17 8476 "#" ; "mov%D1\\t%0, #0\;and%d1\\t%0, %3, #1"
8477 "&& reload_completed"
8478 [(cond_exec (match_dup 5) (set (match_dup 0) (const_int 0)))
8479 (cond_exec (match_dup 4) (set (match_dup 0)
8480 (and:SI (match_dup 3) (const_int 1))))]
8481 {
3754d046 8482 machine_mode mode = GET_MODE (operands[2]);
190efb17 8483 enum rtx_code rc = GET_CODE (operands[1]);
8484
8485 /* Note that operands[4] is the same as operands[1],
8486 but with VOIDmode as the result. */
8487 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
8488 if (mode == CCFPmode || mode == CCFPEmode)
8489 rc = reverse_condition_maybe_unordered (rc);
8490 else
8491 rc = reverse_condition (rc);
8492 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
8493 }
8fa3ba89 8494 [(set_attr "conds" "use")
1b7da4ac 8495 (set_attr "type" "multiple")
8fa3ba89 8496 (set_attr "length" "8")]
8497)
9c08d1fa 8498
190efb17 8499(define_insn_and_split "*ior_scc"
9c08d1fa 8500 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
190efb17 8501 (ior:SI (match_operator:SI 1 "arm_comparison_operator"
8502 [(match_operand 2 "cc_register" "") (const_int 0)])
8503 (match_operand:SI 3 "s_register_operand" "0,?r")))]
cffb2a26 8504 "TARGET_ARM"
e2348bcb 8505 "@
190efb17 8506 orr%d1\\t%0, %3, #1
8507 #"
8508 "&& reload_completed
8509 && REGNO (operands [0]) != REGNO (operands[3])"
8510 ;; && which_alternative == 1
8511 ; mov%D1\\t%0, %3\;orr%d1\\t%0, %3, #1
8512 [(cond_exec (match_dup 5) (set (match_dup 0) (match_dup 3)))
8513 (cond_exec (match_dup 4) (set (match_dup 0)
8514 (ior:SI (match_dup 3) (const_int 1))))]
8515 {
3754d046 8516 machine_mode mode = GET_MODE (operands[2]);
190efb17 8517 enum rtx_code rc = GET_CODE (operands[1]);
8518
8519 /* Note that operands[4] is the same as operands[1],
8520 but with VOIDmode as the result. */
8521 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
8522 if (mode == CCFPmode || mode == CCFPEmode)
8523 rc = reverse_condition_maybe_unordered (rc);
8524 else
8525 rc = reverse_condition (rc);
8526 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
8527 }
8fa3ba89 8528 [(set_attr "conds" "use")
1b7da4ac 8529 (set_attr "length" "4,8")
8530 (set_attr "type" "logic_imm,multiple")]
8fa3ba89 8531)
9c08d1fa 8532
2df9477b 8533; A series of splitters for the compare_scc pattern below. Note that
8534; order is important.
8535(define_split
8536 [(set (match_operand:SI 0 "s_register_operand" "")
8537 (lt:SI (match_operand:SI 1 "s_register_operand" "")
8538 (const_int 0)))
8539 (clobber (reg:CC CC_REGNUM))]
8540 "TARGET_32BIT && reload_completed"
8541 [(set (match_dup 0) (lshiftrt:SI (match_dup 1) (const_int 31)))])
8542
8543(define_split
8544 [(set (match_operand:SI 0 "s_register_operand" "")
8545 (ge:SI (match_operand:SI 1 "s_register_operand" "")
8546 (const_int 0)))
8547 (clobber (reg:CC CC_REGNUM))]
8548 "TARGET_32BIT && reload_completed"
8549 [(set (match_dup 0) (not:SI (match_dup 1)))
8550 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 31)))])
8551
98562479 8552(define_split
8553 [(set (match_operand:SI 0 "s_register_operand" "")
8554 (eq:SI (match_operand:SI 1 "s_register_operand" "")
8555 (const_int 0)))
8556 (clobber (reg:CC CC_REGNUM))]
b232e6b5 8557 "arm_arch5t && TARGET_32BIT"
98562479 8558 [(set (match_dup 0) (clz:SI (match_dup 1)))
8559 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 5)))]
8560)
8561
2df9477b 8562(define_split
8563 [(set (match_operand:SI 0 "s_register_operand" "")
8564 (eq:SI (match_operand:SI 1 "s_register_operand" "")
8565 (const_int 0)))
8566 (clobber (reg:CC CC_REGNUM))]
8567 "TARGET_32BIT && reload_completed"
8568 [(parallel
080c0b9a 8569 [(set (reg:CC CC_REGNUM)
8570 (compare:CC (const_int 1) (match_dup 1)))
2df9477b 8571 (set (match_dup 0)
8572 (minus:SI (const_int 1) (match_dup 1)))])
080c0b9a 8573 (cond_exec (ltu:CC (reg:CC CC_REGNUM) (const_int 0))
2df9477b 8574 (set (match_dup 0) (const_int 0)))])
8575
8576(define_split
8577 [(set (match_operand:SI 0 "s_register_operand" "")
8578 (ne:SI (match_operand:SI 1 "s_register_operand" "")
8579 (match_operand:SI 2 "const_int_operand" "")))
8580 (clobber (reg:CC CC_REGNUM))]
8581 "TARGET_32BIT && reload_completed"
8582 [(parallel
8583 [(set (reg:CC CC_REGNUM)
8584 (compare:CC (match_dup 1) (match_dup 2)))
8585 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))])
8586 (cond_exec (ne:CC (reg:CC CC_REGNUM) (const_int 0))
8587 (set (match_dup 0) (const_int 1)))]
8588{
e3dcfc16 8589 operands[3] = gen_int_mode (-INTVAL (operands[2]), SImode);
2df9477b 8590})
8591
8592(define_split
8593 [(set (match_operand:SI 0 "s_register_operand" "")
8594 (ne:SI (match_operand:SI 1 "s_register_operand" "")
8595 (match_operand:SI 2 "arm_add_operand" "")))
8596 (clobber (reg:CC CC_REGNUM))]
8597 "TARGET_32BIT && reload_completed"
8598 [(parallel
8599 [(set (reg:CC_NOOV CC_REGNUM)
8600 (compare:CC_NOOV (minus:SI (match_dup 1) (match_dup 2))
8601 (const_int 0)))
8602 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
8603 (cond_exec (ne:CC_NOOV (reg:CC_NOOV CC_REGNUM) (const_int 0))
8604 (set (match_dup 0) (const_int 1)))])
8605
8606(define_insn_and_split "*compare_scc"
fd711051 8607 [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts")
8fa3ba89 8608 (match_operator:SI 1 "arm_comparison_operator"
5565501b 8609 [(match_operand:SI 2 "s_register_operand" "r,r")
8610 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
bd5b4116 8611 (clobber (reg:CC CC_REGNUM))]
2df9477b 8612 "TARGET_32BIT"
8613 "#"
8614 "&& reload_completed"
8615 [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 3)))
8616 (cond_exec (match_dup 4) (set (match_dup 0) (const_int 0)))
8617 (cond_exec (match_dup 5) (set (match_dup 0) (const_int 1)))]
8618{
8619 rtx tmp1;
3754d046 8620 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
2df9477b 8621 operands[2], operands[3]);
8622 enum rtx_code rc = GET_CODE (operands[1]);
e2348bcb 8623
2df9477b 8624 tmp1 = gen_rtx_REG (mode, CC_REGNUM);
080c0b9a 8625
2df9477b 8626 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
8627 if (mode == CCFPmode || mode == CCFPEmode)
8628 rc = reverse_condition_maybe_unordered (rc);
8629 else
8630 rc = reverse_condition (rc);
8631 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
1b7da4ac 8632}
8633 [(set_attr "type" "multiple")]
8634)
9c08d1fa 8635
080c0b9a 8636;; Attempt to improve the sequence generated by the compare_scc splitters
8637;; not to use conditional execution.
98562479 8638
8639;; Rd = (eq (reg1) (const_int0)) // ARMv5
8640;; clz Rd, reg1
8641;; lsr Rd, Rd, #5
080c0b9a 8642(define_peephole2
8643 [(set (reg:CC CC_REGNUM)
8644 (compare:CC (match_operand:SI 1 "register_operand" "")
98562479 8645 (const_int 0)))
8646 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
8647 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
8648 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
8649 (set (match_dup 0) (const_int 1)))]
b232e6b5 8650 "arm_arch5t && TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)"
98562479 8651 [(set (match_dup 0) (clz:SI (match_dup 1)))
8652 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 5)))]
8653)
8654
8655;; Rd = (eq (reg1) (const_int0)) // !ARMv5
8656;; negs Rd, reg1
8657;; adc Rd, Rd, reg1
8658(define_peephole2
8659 [(set (reg:CC CC_REGNUM)
8660 (compare:CC (match_operand:SI 1 "register_operand" "")
8661 (const_int 0)))
080c0b9a 8662 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
8663 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
8664 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
8665 (set (match_dup 0) (const_int 1)))
98562479 8666 (match_scratch:SI 2 "r")]
8667 "TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)"
922b6913 8668 [(parallel
8669 [(set (reg:CC CC_REGNUM)
98562479 8670 (compare:CC (const_int 0) (match_dup 1)))
8671 (set (match_dup 2) (minus:SI (const_int 0) (match_dup 1)))])
8672 (set (match_dup 0)
8673 (plus:SI (plus:SI (match_dup 1) (match_dup 2))
8674 (geu:SI (reg:CC CC_REGNUM) (const_int 0))))]
8675)
8676
31991287 8677;; Rd = (eq (reg1) (reg2/imm)) // ARMv5 and optimising for speed.
98562479 8678;; sub Rd, Reg1, reg2
8679;; clz Rd, Rd
8680;; lsr Rd, Rd, #5
8681(define_peephole2
8682 [(set (reg:CC CC_REGNUM)
8683 (compare:CC (match_operand:SI 1 "register_operand" "")
8684 (match_operand:SI 2 "arm_rhs_operand" "")))
8685 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
8686 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
8687 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
8688 (set (match_dup 0) (const_int 1)))]
b232e6b5 8689 "arm_arch5t && TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)
31991287 8690 && !(TARGET_THUMB2 && optimize_insn_for_size_p ())"
98562479 8691 [(set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))
8692 (set (match_dup 0) (clz:SI (match_dup 0)))
8693 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 5)))]
8694)
8695
8696
31991287 8697;; Rd = (eq (reg1) (reg2)) // ! ARMv5 or optimising for size.
98562479 8698;; sub T1, Reg1, reg2
8699;; negs Rd, T1
8700;; adc Rd, Rd, T1
8701(define_peephole2
8702 [(set (reg:CC CC_REGNUM)
8703 (compare:CC (match_operand:SI 1 "register_operand" "")
8704 (match_operand:SI 2 "arm_rhs_operand" "")))
8705 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
8706 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
8707 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
8708 (set (match_dup 0) (const_int 1)))
8709 (match_scratch:SI 3 "r")]
8710 "TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)"
31991287 8711 [(set (match_dup 3) (match_dup 4))
080c0b9a 8712 (parallel
8713 [(set (reg:CC CC_REGNUM)
8714 (compare:CC (const_int 0) (match_dup 3)))
8715 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 3)))])
98562479 8716 (set (match_dup 0)
8717 (plus:SI (plus:SI (match_dup 0) (match_dup 3))
8718 (geu:SI (reg:CC CC_REGNUM) (const_int 0))))]
31991287 8719 "
8720 if (CONST_INT_P (operands[2]))
8721 operands[4] = plus_constant (SImode, operands[1], -INTVAL (operands[2]));
8722 else
8723 operands[4] = gen_rtx_MINUS (SImode, operands[1], operands[2]);
8724 ")
080c0b9a 8725
f7fbdd4a 8726(define_insn "*cond_move"
9c08d1fa 8727 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
aea4c774 8728 (if_then_else:SI (match_operator 3 "equality_operator"
8fa3ba89 8729 [(match_operator 4 "arm_comparison_operator"
8a18b90c 8730 [(match_operand 5 "cc_register" "") (const_int 0)])
aea4c774 8731 (const_int 0)])
8732 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8733 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
cffb2a26 8734 "TARGET_ARM"
9c08d1fa 8735 "*
8fa3ba89 8736 if (GET_CODE (operands[3]) == NE)
8737 {
8738 if (which_alternative != 1)
8739 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
8740 if (which_alternative != 0)
8741 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
8742 return \"\";
8743 }
8744 if (which_alternative != 0)
8745 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8746 if (which_alternative != 1)
8747 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
8748 return \"\";
8749 "
8750 [(set_attr "conds" "use")
282b4c75 8751 (set_attr_alternative "type"
8752 [(if_then_else (match_operand 2 "const_int_operand" "")
8753 (const_string "mov_imm")
8754 (const_string "mov_reg"))
8755 (if_then_else (match_operand 1 "const_int_operand" "")
8756 (const_string "mov_imm")
8757 (const_string "mov_reg"))
8758 (const_string "multiple")])
8fa3ba89 8759 (set_attr "length" "4,4,8")]
8760)
9c08d1fa 8761
f7fbdd4a 8762(define_insn "*cond_arith"
9c08d1fa 8763 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8764 (match_operator:SI 5 "shiftable_operator"
8fa3ba89 8765 [(match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 8766 [(match_operand:SI 2 "s_register_operand" "r,r")
8767 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8768 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 8769 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8770 "TARGET_ARM"
9c08d1fa 8771 "*
8fa3ba89 8772 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
8773 return \"%i5\\t%0, %1, %2, lsr #31\";
40dbec34 8774
8fa3ba89 8775 output_asm_insn (\"cmp\\t%2, %3\", operands);
8776 if (GET_CODE (operands[5]) == AND)
8777 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
8778 else if (GET_CODE (operands[5]) == MINUS)
8779 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
8780 else if (which_alternative != 0)
8781 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8782 return \"%i5%d4\\t%0, %1, #1\";
8783 "
8784 [(set_attr "conds" "clob")
1b7da4ac 8785 (set_attr "length" "12")
8786 (set_attr "type" "multiple")]
8fa3ba89 8787)
9c08d1fa 8788
f7fbdd4a 8789(define_insn "*cond_sub"
9c08d1fa 8790 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8791 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8fa3ba89 8792 (match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 8793 [(match_operand:SI 2 "s_register_operand" "r,r")
8794 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 8795 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8796 "TARGET_ARM"
9c08d1fa 8797 "*
8fa3ba89 8798 output_asm_insn (\"cmp\\t%2, %3\", operands);
8799 if (which_alternative != 0)
8800 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8801 return \"sub%d4\\t%0, %1, #1\";
8802 "
8803 [(set_attr "conds" "clob")
1b7da4ac 8804 (set_attr "length" "8,12")
8805 (set_attr "type" "multiple")]
8fa3ba89 8806)
9c08d1fa 8807
aea4c774 8808(define_insn "*cmp_ite0"
cffb2a26 8809 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 8810 (compare
8811 (if_then_else:SI
8fa3ba89 8812 (match_operator 4 "arm_comparison_operator"
2ff91fec 8813 [(match_operand:SI 0 "s_register_operand"
8814 "l,l,l,r,r,r,r,r,r")
8815 (match_operand:SI 1 "arm_add_operand"
8816 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
8fa3ba89 8817 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 8818 [(match_operand:SI 2 "s_register_operand"
8819 "l,r,r,l,l,r,r,r,r")
8820 (match_operand:SI 3 "arm_add_operand"
8821 "lPy,rI,L,lPy,lPy,rI,rI,L,L")])
aea4c774 8822 (const_int 0))
8823 (const_int 0)))]
2ff91fec 8824 "TARGET_32BIT"
9c08d1fa 8825 "*
aea4c774 8826 {
2ff91fec 8827 static const char * const cmp1[NUM_OF_COND_CMP][2] =
8828 {
8829 {\"cmp%d5\\t%0, %1\",
8830 \"cmp%d4\\t%2, %3\"},
8831 {\"cmn%d5\\t%0, #%n1\",
8832 \"cmp%d4\\t%2, %3\"},
8833 {\"cmp%d5\\t%0, %1\",
8834 \"cmn%d4\\t%2, #%n3\"},
8835 {\"cmn%d5\\t%0, #%n1\",
8836 \"cmn%d4\\t%2, #%n3\"}
8837 };
8838 static const char * const cmp2[NUM_OF_COND_CMP][2] =
8839 {
8840 {\"cmp\\t%2, %3\",
8841 \"cmp\\t%0, %1\"},
8842 {\"cmp\\t%2, %3\",
8843 \"cmn\\t%0, #%n1\"},
8844 {\"cmn\\t%2, #%n3\",
8845 \"cmp\\t%0, %1\"},
8846 {\"cmn\\t%2, #%n3\",
8847 \"cmn\\t%0, #%n1\"}
8848 };
8849 static const char * const ite[2] =
8fa3ba89 8850 {
2ff91fec 8851 \"it\\t%d5\",
8852 \"it\\t%d4\"
8fa3ba89 8853 };
2ff91fec 8854 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
8855 CMP_CMP, CMN_CMP, CMP_CMP,
8856 CMN_CMP, CMP_CMN, CMN_CMN};
8fa3ba89 8857 int swap =
8858 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8859
2ff91fec 8860 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
8861 if (TARGET_THUMB2) {
8862 output_asm_insn (ite[swap], operands);
8863 }
8864 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
8865 return \"\";
8fa3ba89 8866 }"
8867 [(set_attr "conds" "set")
2ff91fec 8868 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
8bdfd6ed 8869 (set_attr "enabled_for_short_it" "yes,no,no,no,no,no,no,no,no")
1b7da4ac 8870 (set_attr "type" "multiple")
2ff91fec 8871 (set_attr_alternative "length"
8872 [(const_int 6)
8873 (const_int 8)
8874 (const_int 8)
8875 (const_int 8)
8876 (const_int 8)
8877 (if_then_else (eq_attr "is_thumb" "no")
8878 (const_int 8)
8879 (const_int 10))
8880 (if_then_else (eq_attr "is_thumb" "no")
8881 (const_int 8)
8882 (const_int 10))
8883 (if_then_else (eq_attr "is_thumb" "no")
8884 (const_int 8)
8885 (const_int 10))
8886 (if_then_else (eq_attr "is_thumb" "no")
8887 (const_int 8)
8888 (const_int 10))])]
8fa3ba89 8889)
9c08d1fa 8890
aea4c774 8891(define_insn "*cmp_ite1"
cffb2a26 8892 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 8893 (compare
8894 (if_then_else:SI
8fa3ba89 8895 (match_operator 4 "arm_comparison_operator"
2ff91fec 8896 [(match_operand:SI 0 "s_register_operand"
8897 "l,l,l,r,r,r,r,r,r")
8898 (match_operand:SI 1 "arm_add_operand"
8899 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
8fa3ba89 8900 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 8901 [(match_operand:SI 2 "s_register_operand"
8902 "l,r,r,l,l,r,r,r,r")
8903 (match_operand:SI 3 "arm_add_operand"
8904 "lPy,rI,L,lPy,lPy,rI,rI,L,L")])
aea4c774 8905 (const_int 1))
8906 (const_int 0)))]
2ff91fec 8907 "TARGET_32BIT"
9c08d1fa 8908 "*
9c08d1fa 8909 {
2ff91fec 8910 static const char * const cmp1[NUM_OF_COND_CMP][2] =
8911 {
8912 {\"cmp\\t%0, %1\",
8913 \"cmp\\t%2, %3\"},
8914 {\"cmn\\t%0, #%n1\",
8915 \"cmp\\t%2, %3\"},
8916 {\"cmp\\t%0, %1\",
8917 \"cmn\\t%2, #%n3\"},
8918 {\"cmn\\t%0, #%n1\",
8919 \"cmn\\t%2, #%n3\"}
8920 };
8921 static const char * const cmp2[NUM_OF_COND_CMP][2] =
215b30b3 8922 {
2ff91fec 8923 {\"cmp%d4\\t%2, %3\",
8924 \"cmp%D5\\t%0, %1\"},
8925 {\"cmp%d4\\t%2, %3\",
8926 \"cmn%D5\\t%0, #%n1\"},
8927 {\"cmn%d4\\t%2, #%n3\",
8928 \"cmp%D5\\t%0, %1\"},
8929 {\"cmn%d4\\t%2, #%n3\",
8930 \"cmn%D5\\t%0, #%n1\"}
215b30b3 8931 };
2ff91fec 8932 static const char * const ite[2] =
8933 {
8934 \"it\\t%d4\",
8935 \"it\\t%D5\"
8936 };
8937 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
8938 CMP_CMP, CMN_CMP, CMP_CMP,
8939 CMN_CMP, CMP_CMN, CMN_CMN};
215b30b3 8940 int swap =
8941 comparison_dominates_p (GET_CODE (operands[5]),
8942 reverse_condition (GET_CODE (operands[4])));
8943
2ff91fec 8944 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
8945 if (TARGET_THUMB2) {
8946 output_asm_insn (ite[swap], operands);
8947 }
8948 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
8949 return \"\";
215b30b3 8950 }"
8fa3ba89 8951 [(set_attr "conds" "set")
2ff91fec 8952 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
8bdfd6ed 8953 (set_attr "enabled_for_short_it" "yes,no,no,no,no,no,no,no,no")
2ff91fec 8954 (set_attr_alternative "length"
8955 [(const_int 6)
8956 (const_int 8)
8957 (const_int 8)
8958 (const_int 8)
8959 (const_int 8)
8960 (if_then_else (eq_attr "is_thumb" "no")
8961 (const_int 8)
8962 (const_int 10))
8963 (if_then_else (eq_attr "is_thumb" "no")
8964 (const_int 8)
8965 (const_int 10))
8966 (if_then_else (eq_attr "is_thumb" "no")
8967 (const_int 8)
8968 (const_int 10))
8969 (if_then_else (eq_attr "is_thumb" "no")
8970 (const_int 8)
1b7da4ac 8971 (const_int 10))])
8972 (set_attr "type" "multiple")]
8fa3ba89 8973)
9c08d1fa 8974
f6c53574 8975(define_insn "*cmp_and"
8976 [(set (match_operand 6 "dominant_cc_register" "")
8977 (compare
8978 (and:SI
8979 (match_operator 4 "arm_comparison_operator"
db23acf2 8980 [(match_operand:SI 0 "s_register_operand"
8981 "l,l,l,r,r,r,r,r,r,r")
8982 (match_operand:SI 1 "arm_add_operand"
8983 "lPy,lPy,lPy,rI,L,r,rI,L,rI,L")])
f6c53574 8984 (match_operator:SI 5 "arm_comparison_operator"
db23acf2 8985 [(match_operand:SI 2 "s_register_operand"
8986 "l,r,r,l,l,r,r,r,r,r")
8987 (match_operand:SI 3 "arm_add_operand"
8988 "lPy,rI,L,lPy,lPy,r,rI,rI,L,L")]))
f6c53574 8989 (const_int 0)))]
2ff91fec 8990 "TARGET_32BIT"
f6c53574 8991 "*
8992 {
2ff91fec 8993 static const char *const cmp1[NUM_OF_COND_CMP][2] =
f6c53574 8994 {
2ff91fec 8995 {\"cmp%d5\\t%0, %1\",
8996 \"cmp%d4\\t%2, %3\"},
8997 {\"cmn%d5\\t%0, #%n1\",
8998 \"cmp%d4\\t%2, %3\"},
8999 {\"cmp%d5\\t%0, %1\",
9000 \"cmn%d4\\t%2, #%n3\"},
9001 {\"cmn%d5\\t%0, #%n1\",
9002 \"cmn%d4\\t%2, #%n3\"}
f6c53574 9003 };
2ff91fec 9004 static const char *const cmp2[NUM_OF_COND_CMP][2] =
9005 {
9006 {\"cmp\\t%2, %3\",
9007 \"cmp\\t%0, %1\"},
9008 {\"cmp\\t%2, %3\",
9009 \"cmn\\t%0, #%n1\"},
9010 {\"cmn\\t%2, #%n3\",
9011 \"cmp\\t%0, %1\"},
9012 {\"cmn\\t%2, #%n3\",
9013 \"cmn\\t%0, #%n1\"}
9014 };
9015 static const char *const ite[2] =
9016 {
9017 \"it\\t%d5\",
9018 \"it\\t%d4\"
9019 };
db23acf2 9020 static const int cmp_idx[] = {CMP_CMP, CMP_CMP, CMP_CMN,
9021 CMP_CMP, CMN_CMP, CMP_CMP,
9022 CMP_CMP, CMN_CMP, CMP_CMN,
9023 CMN_CMN};
f6c53574 9024 int swap =
9025 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9026
2ff91fec 9027 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9028 if (TARGET_THUMB2) {
9029 output_asm_insn (ite[swap], operands);
9030 }
9031 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9032 return \"\";
f6c53574 9033 }"
9034 [(set_attr "conds" "set")
9035 (set_attr "predicable" "no")
db23acf2 9036 (set_attr "arch" "t2,t2,t2,t2,t2,t2,any,any,any,any")
9037 (set_attr "enabled_for_short_it" "yes,no,no,no,no,yes,no,no,no,no")
2ff91fec 9038 (set_attr_alternative "length"
9039 [(const_int 6)
9040 (const_int 8)
9041 (const_int 8)
9042 (const_int 8)
9043 (const_int 8)
db23acf2 9044 (const_int 6)
2ff91fec 9045 (if_then_else (eq_attr "is_thumb" "no")
9046 (const_int 8)
9047 (const_int 10))
9048 (if_then_else (eq_attr "is_thumb" "no")
9049 (const_int 8)
9050 (const_int 10))
9051 (if_then_else (eq_attr "is_thumb" "no")
9052 (const_int 8)
9053 (const_int 10))
9054 (if_then_else (eq_attr "is_thumb" "no")
9055 (const_int 8)
1b7da4ac 9056 (const_int 10))])
9057 (set_attr "type" "multiple")]
f6c53574 9058)
9059
9060(define_insn "*cmp_ior"
9061 [(set (match_operand 6 "dominant_cc_register" "")
9062 (compare
9063 (ior:SI
9064 (match_operator 4 "arm_comparison_operator"
2ff91fec 9065 [(match_operand:SI 0 "s_register_operand"
db23acf2 9066 "l,l,l,r,r,r,r,r,r,r")
2ff91fec 9067 (match_operand:SI 1 "arm_add_operand"
db23acf2 9068 "lPy,lPy,lPy,rI,L,r,rI,L,rI,L")])
f6c53574 9069 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 9070 [(match_operand:SI 2 "s_register_operand"
db23acf2 9071 "l,r,r,l,l,r,r,r,r,r")
2ff91fec 9072 (match_operand:SI 3 "arm_add_operand"
db23acf2 9073 "lPy,rI,L,lPy,lPy,r,rI,rI,L,L")]))
f6c53574 9074 (const_int 0)))]
2ff91fec 9075 "TARGET_32BIT"
f6c53574 9076 "*
f6c53574 9077 {
2ff91fec 9078 static const char *const cmp1[NUM_OF_COND_CMP][2] =
9079 {
9080 {\"cmp\\t%0, %1\",
9081 \"cmp\\t%2, %3\"},
9082 {\"cmn\\t%0, #%n1\",
9083 \"cmp\\t%2, %3\"},
9084 {\"cmp\\t%0, %1\",
9085 \"cmn\\t%2, #%n3\"},
9086 {\"cmn\\t%0, #%n1\",
9087 \"cmn\\t%2, #%n3\"}
9088 };
9089 static const char *const cmp2[NUM_OF_COND_CMP][2] =
9090 {
9091 {\"cmp%D4\\t%2, %3\",
9092 \"cmp%D5\\t%0, %1\"},
9093 {\"cmp%D4\\t%2, %3\",
9094 \"cmn%D5\\t%0, #%n1\"},
9095 {\"cmn%D4\\t%2, #%n3\",
9096 \"cmp%D5\\t%0, %1\"},
9097 {\"cmn%D4\\t%2, #%n3\",
9098 \"cmn%D5\\t%0, #%n1\"}
9099 };
9100 static const char *const ite[2] =
9101 {
9102 \"it\\t%D4\",
9103 \"it\\t%D5\"
9104 };
db23acf2 9105 static const int cmp_idx[] = {CMP_CMP, CMP_CMP, CMP_CMN,
9106 CMP_CMP, CMN_CMP, CMP_CMP,
9107 CMP_CMP, CMN_CMP, CMP_CMN,
9108 CMN_CMN};
2ff91fec 9109 int swap =
9110 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9111
9112 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9113 if (TARGET_THUMB2) {
9114 output_asm_insn (ite[swap], operands);
9115 }
9116 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9117 return \"\";
9118 }
9119 "
f6c53574 9120 [(set_attr "conds" "set")
db23acf2 9121 (set_attr "arch" "t2,t2,t2,t2,t2,t2,any,any,any,any")
9122 (set_attr "enabled_for_short_it" "yes,no,no,no,no,yes,no,no,no,no")
2ff91fec 9123 (set_attr_alternative "length"
9124 [(const_int 6)
9125 (const_int 8)
9126 (const_int 8)
9127 (const_int 8)
9128 (const_int 8)
db23acf2 9129 (const_int 6)
2ff91fec 9130 (if_then_else (eq_attr "is_thumb" "no")
9131 (const_int 8)
9132 (const_int 10))
9133 (if_then_else (eq_attr "is_thumb" "no")
9134 (const_int 8)
9135 (const_int 10))
9136 (if_then_else (eq_attr "is_thumb" "no")
9137 (const_int 8)
9138 (const_int 10))
9139 (if_then_else (eq_attr "is_thumb" "no")
9140 (const_int 8)
1b7da4ac 9141 (const_int 10))])
9142 (set_attr "type" "multiple")]
f6c53574 9143)
9144
3c5afce6 9145(define_insn_and_split "*ior_scc_scc"
f9d240a0 9146 [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts")
3c5afce6 9147 (ior:SI (match_operator:SI 3 "arm_comparison_operator"
f9d240a0 9148 [(match_operand:SI 1 "s_register_operand" "l,r")
9149 (match_operand:SI 2 "arm_add_operand" "lPy,rIL")])
3c5afce6 9150 (match_operator:SI 6 "arm_comparison_operator"
f9d240a0 9151 [(match_operand:SI 4 "s_register_operand" "l,r")
9152 (match_operand:SI 5 "arm_add_operand" "lPy,rIL")])))
3c5afce6 9153 (clobber (reg:CC CC_REGNUM))]
2ff91fec 9154 "TARGET_32BIT
3c5afce6 9155 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
9156 != CCmode)"
9157 "#"
2ff91fec 9158 "TARGET_32BIT && reload_completed"
3c5afce6 9159 [(set (match_dup 7)
9160 (compare
9161 (ior:SI
9162 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9163 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9164 (const_int 0)))
9165 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9166 "operands[7]
9167 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9168 DOM_CC_X_OR_Y),
601f584c 9169 CC_REGNUM);"
9170 [(set_attr "conds" "clob")
8bdfd6ed 9171 (set_attr "enabled_for_short_it" "yes,no")
1b7da4ac 9172 (set_attr "length" "16")
9173 (set_attr "type" "multiple")]
9174)
601f584c 9175
9176; If the above pattern is followed by a CMP insn, then the compare is
9177; redundant, since we can rework the conditional instruction that follows.
9178(define_insn_and_split "*ior_scc_scc_cmp"
9179 [(set (match_operand 0 "dominant_cc_register" "")
9180 (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
f9d240a0 9181 [(match_operand:SI 1 "s_register_operand" "l,r")
9182 (match_operand:SI 2 "arm_add_operand" "lPy,rIL")])
601f584c 9183 (match_operator:SI 6 "arm_comparison_operator"
f9d240a0 9184 [(match_operand:SI 4 "s_register_operand" "l,r")
9185 (match_operand:SI 5 "arm_add_operand" "lPy,rIL")]))
601f584c 9186 (const_int 0)))
f9d240a0 9187 (set (match_operand:SI 7 "s_register_operand" "=Ts,Ts")
601f584c 9188 (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9189 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
2ff91fec 9190 "TARGET_32BIT"
601f584c 9191 "#"
2ff91fec 9192 "TARGET_32BIT && reload_completed"
601f584c 9193 [(set (match_dup 0)
9194 (compare
9195 (ior:SI
9196 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9197 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9198 (const_int 0)))
9199 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9200 ""
9201 [(set_attr "conds" "set")
8bdfd6ed 9202 (set_attr "enabled_for_short_it" "yes,no")
1b7da4ac 9203 (set_attr "length" "16")
9204 (set_attr "type" "multiple")]
9205)
3c5afce6 9206
9207(define_insn_and_split "*and_scc_scc"
f9d240a0 9208 [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts")
3c5afce6 9209 (and:SI (match_operator:SI 3 "arm_comparison_operator"
f9d240a0 9210 [(match_operand:SI 1 "s_register_operand" "l,r")
9211 (match_operand:SI 2 "arm_add_operand" "lPy,rIL")])
3c5afce6 9212 (match_operator:SI 6 "arm_comparison_operator"
f9d240a0 9213 [(match_operand:SI 4 "s_register_operand" "l,r")
9214 (match_operand:SI 5 "arm_add_operand" "lPy,rIL")])))
3c5afce6 9215 (clobber (reg:CC CC_REGNUM))]
2ff91fec 9216 "TARGET_32BIT
3c5afce6 9217 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9218 != CCmode)"
9219 "#"
2ff91fec 9220 "TARGET_32BIT && reload_completed
601f584c 9221 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9222 != CCmode)"
3c5afce6 9223 [(set (match_dup 7)
9224 (compare
9225 (and:SI
9226 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9227 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9228 (const_int 0)))
9229 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9230 "operands[7]
9231 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9232 DOM_CC_X_AND_Y),
601f584c 9233 CC_REGNUM);"
9234 [(set_attr "conds" "clob")
8bdfd6ed 9235 (set_attr "enabled_for_short_it" "yes,no")
1b7da4ac 9236 (set_attr "length" "16")
9237 (set_attr "type" "multiple")]
9238)
601f584c 9239
9240; If the above pattern is followed by a CMP insn, then the compare is
9241; redundant, since we can rework the conditional instruction that follows.
9242(define_insn_and_split "*and_scc_scc_cmp"
9243 [(set (match_operand 0 "dominant_cc_register" "")
9244 (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
f9d240a0 9245 [(match_operand:SI 1 "s_register_operand" "l,r")
9246 (match_operand:SI 2 "arm_add_operand" "lPy,rIL")])
601f584c 9247 (match_operator:SI 6 "arm_comparison_operator"
f9d240a0 9248 [(match_operand:SI 4 "s_register_operand" "l,r")
9249 (match_operand:SI 5 "arm_add_operand" "lPy,rIL")]))
601f584c 9250 (const_int 0)))
f9d240a0 9251 (set (match_operand:SI 7 "s_register_operand" "=Ts,Ts")
601f584c 9252 (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9253 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
2ff91fec 9254 "TARGET_32BIT"
601f584c 9255 "#"
2ff91fec 9256 "TARGET_32BIT && reload_completed"
601f584c 9257 [(set (match_dup 0)
9258 (compare
9259 (and:SI
9260 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9261 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9262 (const_int 0)))
9263 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9264 ""
9265 [(set_attr "conds" "set")
8bdfd6ed 9266 (set_attr "enabled_for_short_it" "yes,no")
1b7da4ac 9267 (set_attr "length" "16")
9268 (set_attr "type" "multiple")]
9269)
601f584c 9270
9271;; If there is no dominance in the comparison, then we can still save an
9272;; instruction in the AND case, since we can know that the second compare
9273;; need only zero the value if false (if true, then the value is already
9274;; correct).
9275(define_insn_and_split "*and_scc_scc_nodom"
fd711051 9276 [(set (match_operand:SI 0 "s_register_operand" "=&Ts,&Ts,&Ts")
601f584c 9277 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9278 [(match_operand:SI 1 "s_register_operand" "r,r,0")
9279 (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
9280 (match_operator:SI 6 "arm_comparison_operator"
9281 [(match_operand:SI 4 "s_register_operand" "r,r,r")
9282 (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
9283 (clobber (reg:CC CC_REGNUM))]
2ff91fec 9284 "TARGET_32BIT
601f584c 9285 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9286 == CCmode)"
9287 "#"
2ff91fec 9288 "TARGET_32BIT && reload_completed"
601f584c 9289 [(parallel [(set (match_dup 0)
9290 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
9291 (clobber (reg:CC CC_REGNUM))])
9292 (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
9293 (set (match_dup 0)
9294 (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
9295 (match_dup 0)
9296 (const_int 0)))]
9297 "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
9298 operands[4], operands[5]),
9299 CC_REGNUM);
9300 operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
9301 operands[5]);"
9302 [(set_attr "conds" "clob")
1b7da4ac 9303 (set_attr "length" "20")
9304 (set_attr "type" "multiple")]
9305)
3c5afce6 9306
3a0bdee0 9307(define_split
9308 [(set (reg:CC_NOOV CC_REGNUM)
9309 (compare:CC_NOOV (ior:SI
9310 (and:SI (match_operand:SI 0 "s_register_operand" "")
9311 (const_int 1))
b0694be0 9312 (match_operator:SI 1 "arm_comparison_operator"
3a0bdee0 9313 [(match_operand:SI 2 "s_register_operand" "")
9314 (match_operand:SI 3 "arm_add_operand" "")]))
9315 (const_int 0)))
9316 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9317 "TARGET_ARM"
9318 [(set (match_dup 4)
9319 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9320 (match_dup 0)))
9321 (set (reg:CC_NOOV CC_REGNUM)
9322 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9323 (const_int 0)))]
9324 "")
9325
9326(define_split
9327 [(set (reg:CC_NOOV CC_REGNUM)
9328 (compare:CC_NOOV (ior:SI
b0694be0 9329 (match_operator:SI 1 "arm_comparison_operator"
3a0bdee0 9330 [(match_operand:SI 2 "s_register_operand" "")
9331 (match_operand:SI 3 "arm_add_operand" "")])
9332 (and:SI (match_operand:SI 0 "s_register_operand" "")
9333 (const_int 1)))
9334 (const_int 0)))
9335 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9336 "TARGET_ARM"
9337 [(set (match_dup 4)
9338 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9339 (match_dup 0)))
9340 (set (reg:CC_NOOV CC_REGNUM)
9341 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9342 (const_int 0)))]
9343 "")
25f905c2 9344;; ??? The conditional patterns above need checking for Thumb-2 usefulness
3a0bdee0 9345
190efb17 9346(define_insn_and_split "*negscc"
9c08d1fa 9347 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9348 (neg:SI (match_operator 3 "arm_comparison_operator"
9c08d1fa 9349 [(match_operand:SI 1 "s_register_operand" "r")
9350 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
bd5b4116 9351 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9352 "TARGET_ARM"
190efb17 9353 "#"
9354 "&& reload_completed"
9355 [(const_int 0)]
9356 {
9357 rtx cc_reg = gen_rtx_REG (CCmode, CC_REGNUM);
e2348bcb 9358
190efb17 9359 if (GET_CODE (operands[3]) == LT && operands[2] == const0_rtx)
9360 {
9361 /* Emit mov\\t%0, %1, asr #31 */
d1f9b275 9362 emit_insn (gen_rtx_SET (operands[0],
190efb17 9363 gen_rtx_ASHIFTRT (SImode,
9364 operands[1],
9365 GEN_INT (31))));
9366 DONE;
9367 }
9368 else if (GET_CODE (operands[3]) == NE)
9369 {
9370 /* Emit subs\\t%0, %1, %2\;mvnne\\t%0, #0 */
9371 if (CONST_INT_P (operands[2]))
9372 emit_insn (gen_cmpsi2_addneg (operands[0], operands[1], operands[2],
e3dcfc16 9373 gen_int_mode (-INTVAL (operands[2]),
9374 SImode)));
190efb17 9375 else
9376 emit_insn (gen_subsi3_compare (operands[0], operands[1], operands[2]));
9377
9378 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
9379 gen_rtx_NE (SImode,
9380 cc_reg,
9381 const0_rtx),
d1f9b275 9382 gen_rtx_SET (operands[0],
190efb17 9383 GEN_INT (~0))));
9384 DONE;
9385 }
9386 else
9387 {
9388 /* Emit: cmp\\t%1, %2\;mov%D3\\t%0, #0\;mvn%d3\\t%0, #0 */
d1f9b275 9389 emit_insn (gen_rtx_SET (cc_reg,
190efb17 9390 gen_rtx_COMPARE (CCmode, operands[1], operands[2])));
9391 enum rtx_code rc = GET_CODE (operands[3]);
9392
9393 rc = reverse_condition (rc);
9394 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
9395 gen_rtx_fmt_ee (rc,
9396 VOIDmode,
9397 cc_reg,
9398 const0_rtx),
d1f9b275 9399 gen_rtx_SET (operands[0], const0_rtx)));
190efb17 9400 rc = GET_CODE (operands[3]);
9401 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
9402 gen_rtx_fmt_ee (rc,
9403 VOIDmode,
9404 cc_reg,
9405 const0_rtx),
d1f9b275 9406 gen_rtx_SET (operands[0],
190efb17 9407 GEN_INT (~0))));
9408 DONE;
9409 }
9410 FAIL;
9411 }
8fa3ba89 9412 [(set_attr "conds" "clob")
1b7da4ac 9413 (set_attr "length" "12")
9414 (set_attr "type" "multiple")]
8fa3ba89 9415)
9c08d1fa 9416
90404b57 9417(define_insn_and_split "movcond_addsi"
9418 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r")
9419 (if_then_else:SI
9420 (match_operator 5 "comparison_operator"
9421 [(plus:SI (match_operand:SI 3 "s_register_operand" "r,r,r")
9422 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL"))
9423 (const_int 0)])
9424 (match_operand:SI 1 "arm_rhs_operand" "rI,rPy,r")
9425 (match_operand:SI 2 "arm_rhs_operand" "rI,rPy,r")))
9426 (clobber (reg:CC CC_REGNUM))]
9427 "TARGET_32BIT"
9428 "#"
9429 "&& reload_completed"
9430 [(set (reg:CC_NOOV CC_REGNUM)
9431 (compare:CC_NOOV
9432 (plus:SI (match_dup 3)
9433 (match_dup 4))
9434 (const_int 0)))
9435 (set (match_dup 0) (match_dup 1))
9436 (cond_exec (match_dup 6)
9437 (set (match_dup 0) (match_dup 2)))]
9438 "
9439 {
3754d046 9440 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[5]),
90404b57 9441 operands[3], operands[4]);
9442 enum rtx_code rc = GET_CODE (operands[5]);
90404b57 9443 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9444 gcc_assert (!(mode == CCFPmode || mode == CCFPEmode));
22440aeb 9445 if (!REG_P (operands[2]) || REGNO (operands[2]) != REGNO (operands[0]))
4d01ce2f 9446 rc = reverse_condition (rc);
f145bcba 9447 else
9448 std::swap (operands[1], operands[2]);
90404b57 9449
9450 operands[6] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9451 }
9452 "
9453 [(set_attr "conds" "clob")
8bdfd6ed 9454 (set_attr "enabled_for_short_it" "no,yes,yes")
1b7da4ac 9455 (set_attr "type" "multiple")]
90404b57 9456)
9457
9c08d1fa 9458(define_insn "movcond"
9459 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 9460 (if_then_else:SI
8fa3ba89 9461 (match_operator 5 "arm_comparison_operator"
5565501b 9462 [(match_operand:SI 3 "s_register_operand" "r,r,r")
9463 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
9464 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9465 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 9466 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9467 "TARGET_ARM"
9c08d1fa 9468 "*
9469 if (GET_CODE (operands[5]) == LT
9470 && (operands[4] == const0_rtx))
9471 {
0438d37f 9472 if (which_alternative != 1 && REG_P (operands[1]))
9c08d1fa 9473 {
9c08d1fa 9474 if (operands[2] == const0_rtx)
e2348bcb 9475 return \"and\\t%0, %1, %3, asr #31\";
9476 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
9c08d1fa 9477 }
0438d37f 9478 else if (which_alternative != 0 && REG_P (operands[2]))
9c08d1fa 9479 {
9c08d1fa 9480 if (operands[1] == const0_rtx)
e2348bcb 9481 return \"bic\\t%0, %2, %3, asr #31\";
9482 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
9c08d1fa 9483 }
9484 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 9485 are constants. */
9c08d1fa 9486 }
e2348bcb 9487
9c08d1fa 9488 if (GET_CODE (operands[5]) == GE
9489 && (operands[4] == const0_rtx))
9490 {
0438d37f 9491 if (which_alternative != 1 && REG_P (operands[1]))
9c08d1fa 9492 {
9c08d1fa 9493 if (operands[2] == const0_rtx)
e2348bcb 9494 return \"bic\\t%0, %1, %3, asr #31\";
9495 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
9c08d1fa 9496 }
0438d37f 9497 else if (which_alternative != 0 && REG_P (operands[2]))
9c08d1fa 9498 {
9c08d1fa 9499 if (operands[1] == const0_rtx)
e2348bcb 9500 return \"and\\t%0, %2, %3, asr #31\";
9501 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
9c08d1fa 9502 }
9503 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 9504 are constants. */
9c08d1fa 9505 }
0438d37f 9506 if (CONST_INT_P (operands[4])
9c08d1fa 9507 && !const_ok_for_arm (INTVAL (operands[4])))
e2348bcb 9508 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
9c08d1fa 9509 else
e2348bcb 9510 output_asm_insn (\"cmp\\t%3, %4\", operands);
9c08d1fa 9511 if (which_alternative != 0)
e2348bcb 9512 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
9c08d1fa 9513 if (which_alternative != 1)
e2348bcb 9514 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
9c08d1fa 9515 return \"\";
215b30b3 9516 "
8fa3ba89 9517 [(set_attr "conds" "clob")
1b7da4ac 9518 (set_attr "length" "8,8,12")
9519 (set_attr "type" "multiple")]
8fa3ba89 9520)
9c08d1fa 9521
25f905c2 9522;; ??? The patterns below need checking for Thumb-2 usefulness.
9523
8a18b90c 9524(define_insn "*ifcompare_plus_move"
9525 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9526 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 9527 [(match_operand:SI 4 "s_register_operand" "r,r")
9528 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9529 (plus:SI
9530 (match_operand:SI 2 "s_register_operand" "r,r")
9531 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
129a2fe4 9532 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 9533 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9534 "TARGET_ARM"
8a18b90c 9535 "#"
8fa3ba89 9536 [(set_attr "conds" "clob")
1b7da4ac 9537 (set_attr "length" "8,12")
9538 (set_attr "type" "multiple")]
8fa3ba89 9539)
8a18b90c 9540
9541(define_insn "*if_plus_move"
129a2fe4 9542 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 9543 (if_then_else:SI
8fa3ba89 9544 (match_operator 4 "arm_comparison_operator"
8a18b90c 9545 [(match_operand 5 "cc_register" "") (const_int 0)])
9546 (plus:SI
129a2fe4 9547 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9548 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
9549 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
cffb2a26 9550 "TARGET_ARM"
8a18b90c 9551 "@
9552 add%d4\\t%0, %2, %3
9553 sub%d4\\t%0, %2, #%n3
9554 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
129a2fe4 9555 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8fa3ba89 9556 [(set_attr "conds" "use")
9557 (set_attr "length" "4,4,8,8")
65f68e55 9558 (set_attr_alternative "type"
9559 [(if_then_else (match_operand 3 "const_int_operand" "")
d82e788e 9560 (const_string "alu_imm" )
112eda6f 9561 (const_string "alu_sreg"))
d82e788e 9562 (const_string "alu_imm")
282b4c75 9563 (const_string "multiple")
9564 (const_string "multiple")])]
8fa3ba89 9565)
8a18b90c 9566
9567(define_insn "*ifcompare_move_plus"
5565501b 9568 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9569 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 9570 [(match_operand:SI 4 "s_register_operand" "r,r")
9571 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 9572 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 9573 (plus:SI
9574 (match_operand:SI 2 "s_register_operand" "r,r")
9575 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
bd5b4116 9576 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9577 "TARGET_ARM"
8a18b90c 9578 "#"
8fa3ba89 9579 [(set_attr "conds" "clob")
1b7da4ac 9580 (set_attr "length" "8,12")
9581 (set_attr "type" "multiple")]
8fa3ba89 9582)
8a18b90c 9583
9584(define_insn "*if_move_plus"
129a2fe4 9585 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 9586 (if_then_else:SI
8fa3ba89 9587 (match_operator 4 "arm_comparison_operator"
8a18b90c 9588 [(match_operand 5 "cc_register" "") (const_int 0)])
129a2fe4 9589 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8a18b90c 9590 (plus:SI
129a2fe4 9591 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9592 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
cffb2a26 9593 "TARGET_ARM"
8a18b90c 9594 "@
9595 add%D4\\t%0, %2, %3
9596 sub%D4\\t%0, %2, #%n3
9597 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
129a2fe4 9598 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8fa3ba89 9599 [(set_attr "conds" "use")
9600 (set_attr "length" "4,4,8,8")
282b4c75 9601 (set_attr_alternative "type"
9602 [(if_then_else (match_operand 3 "const_int_operand" "")
9603 (const_string "alu_imm" )
9604 (const_string "alu_sreg"))
9605 (const_string "alu_imm")
9606 (const_string "multiple")
9607 (const_string "multiple")])]
8fa3ba89 9608)
8a18b90c 9609
9610(define_insn "*ifcompare_arith_arith"
9611 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9612 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8a18b90c 9613 [(match_operand:SI 5 "s_register_operand" "r")
9614 (match_operand:SI 6 "arm_add_operand" "rIL")])
9c08d1fa 9615 (match_operator:SI 8 "shiftable_operator"
8a18b90c 9616 [(match_operand:SI 1 "s_register_operand" "r")
9617 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9c08d1fa 9618 (match_operator:SI 7 "shiftable_operator"
8a18b90c 9619 [(match_operand:SI 3 "s_register_operand" "r")
9620 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
bd5b4116 9621 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9622 "TARGET_ARM"
8a18b90c 9623 "#"
8fa3ba89 9624 [(set_attr "conds" "clob")
1b7da4ac 9625 (set_attr "length" "12")
9626 (set_attr "type" "multiple")]
8fa3ba89 9627)
9c08d1fa 9628
8a18b90c 9629(define_insn "*if_arith_arith"
9630 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9631 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8a18b90c 9632 [(match_operand 8 "cc_register" "") (const_int 0)])
9633 (match_operator:SI 6 "shiftable_operator"
9634 [(match_operand:SI 1 "s_register_operand" "r")
9635 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9636 (match_operator:SI 7 "shiftable_operator"
9637 [(match_operand:SI 3 "s_register_operand" "r")
9638 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
cffb2a26 9639 "TARGET_ARM"
8a18b90c 9640 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8fa3ba89 9641 [(set_attr "conds" "use")
1b7da4ac 9642 (set_attr "length" "8")
9643 (set_attr "type" "multiple")]
8fa3ba89 9644)
8a18b90c 9645
f7fbdd4a 9646(define_insn "*ifcompare_arith_move"
9c08d1fa 9647 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9648 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 9649 [(match_operand:SI 2 "s_register_operand" "r,r")
5565501b 9650 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
9c08d1fa 9651 (match_operator:SI 7 "shiftable_operator"
9652 [(match_operand:SI 4 "s_register_operand" "r,r")
9653 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
129a2fe4 9654 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 9655 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9656 "TARGET_ARM"
9c08d1fa 9657 "*
9c08d1fa 9658 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 9659 the conditional operator is LT or GE and we are comparing against zero and
674a8f0b 9660 everything is in registers then we can do this in two instructions. */
9c08d1fa 9661 if (operands[3] == const0_rtx
9662 && GET_CODE (operands[7]) != AND
0438d37f 9663 && REG_P (operands[5])
9664 && REG_P (operands[1])
9c08d1fa 9665 && REGNO (operands[1]) == REGNO (operands[4])
9666 && REGNO (operands[4]) != REGNO (operands[0]))
9667 {
9668 if (GET_CODE (operands[6]) == LT)
40dbec34 9669 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 9670 else if (GET_CODE (operands[6]) == GE)
40dbec34 9671 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 9672 }
0438d37f 9673 if (CONST_INT_P (operands[3])
9c08d1fa 9674 && !const_ok_for_arm (INTVAL (operands[3])))
e2348bcb 9675 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
9c08d1fa 9676 else
e2348bcb 9677 output_asm_insn (\"cmp\\t%2, %3\", operands);
40dbec34 9678 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
9c08d1fa 9679 if (which_alternative != 0)
129a2fe4 9680 return \"mov%D6\\t%0, %1\";
9c08d1fa 9681 return \"\";
215b30b3 9682 "
8fa3ba89 9683 [(set_attr "conds" "clob")
1b7da4ac 9684 (set_attr "length" "8,12")
9685 (set_attr "type" "multiple")]
8fa3ba89 9686)
9c08d1fa 9687
8a18b90c 9688(define_insn "*if_arith_move"
129a2fe4 9689 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9690 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8a18b90c 9691 [(match_operand 6 "cc_register" "") (const_int 0)])
9692 (match_operator:SI 5 "shiftable_operator"
129a2fe4 9693 [(match_operand:SI 2 "s_register_operand" "r,r")
9694 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
9695 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
cffb2a26 9696 "TARGET_ARM"
8a18b90c 9697 "@
9698 %I5%d4\\t%0, %2, %3
129a2fe4 9699 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8fa3ba89 9700 [(set_attr "conds" "use")
9701 (set_attr "length" "4,8")
282b4c75 9702 (set_attr_alternative "type"
9703 [(if_then_else (match_operand 3 "const_int_operand" "")
9704 (const_string "alu_shift_imm" )
9705 (const_string "alu_shift_reg"))
9706 (const_string "multiple")])]
8fa3ba89 9707)
8a18b90c 9708
f7fbdd4a 9709(define_insn "*ifcompare_move_arith"
9c08d1fa 9710 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9711 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 9712 [(match_operand:SI 4 "s_register_operand" "r,r")
5565501b 9713 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 9714 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9c08d1fa 9715 (match_operator:SI 7 "shiftable_operator"
9716 [(match_operand:SI 2 "s_register_operand" "r,r")
9717 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 9718 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9719 "TARGET_ARM"
9c08d1fa 9720 "*
9c08d1fa 9721 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 9722 the conditional operator is LT or GE and we are comparing against zero and
9c08d1fa 9723 everything is in registers then we can do this in two instructions */
9724 if (operands[5] == const0_rtx
9725 && GET_CODE (operands[7]) != AND
0438d37f 9726 && REG_P (operands[3])
9727 && REG_P (operands[1])
9c08d1fa 9728 && REGNO (operands[1]) == REGNO (operands[2])
9729 && REGNO (operands[2]) != REGNO (operands[0]))
9730 {
9731 if (GET_CODE (operands[6]) == GE)
40dbec34 9732 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 9733 else if (GET_CODE (operands[6]) == LT)
40dbec34 9734 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 9735 }
40dbec34 9736
0438d37f 9737 if (CONST_INT_P (operands[5])
9c08d1fa 9738 && !const_ok_for_arm (INTVAL (operands[5])))
e2348bcb 9739 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
9c08d1fa 9740 else
e2348bcb 9741 output_asm_insn (\"cmp\\t%4, %5\", operands);
40dbec34 9742
9c08d1fa 9743 if (which_alternative != 0)
129a2fe4 9744 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
40dbec34 9745 return \"%I7%D6\\t%0, %2, %3\";
215b30b3 9746 "
8fa3ba89 9747 [(set_attr "conds" "clob")
1b7da4ac 9748 (set_attr "length" "8,12")
9749 (set_attr "type" "multiple")]
8fa3ba89 9750)
9c08d1fa 9751
8a18b90c 9752(define_insn "*if_move_arith"
129a2fe4 9753 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9754 (if_then_else:SI
8fa3ba89 9755 (match_operator 4 "arm_comparison_operator"
8a18b90c 9756 [(match_operand 6 "cc_register" "") (const_int 0)])
129a2fe4 9757 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 9758 (match_operator:SI 5 "shiftable_operator"
129a2fe4 9759 [(match_operand:SI 2 "s_register_operand" "r,r")
9760 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
cffb2a26 9761 "TARGET_ARM"
8a18b90c 9762 "@
9763 %I5%D4\\t%0, %2, %3
129a2fe4 9764 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
8fa3ba89 9765 [(set_attr "conds" "use")
9766 (set_attr "length" "4,8")
282b4c75 9767 (set_attr_alternative "type"
9768 [(if_then_else (match_operand 3 "const_int_operand" "")
9769 (const_string "alu_shift_imm" )
9770 (const_string "alu_shift_reg"))
9771 (const_string "multiple")])]
8fa3ba89 9772)
8a18b90c 9773
9774(define_insn "*ifcompare_move_not"
9c08d1fa 9775 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9776 (if_then_else:SI
8fa3ba89 9777 (match_operator 5 "arm_comparison_operator"
8a18b90c 9778 [(match_operand:SI 3 "s_register_operand" "r,r")
9779 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9780 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9781 (not:SI
9782 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 9783 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9784 "TARGET_ARM"
8a18b90c 9785 "#"
8fa3ba89 9786 [(set_attr "conds" "clob")
1b7da4ac 9787 (set_attr "length" "8,12")
9788 (set_attr "type" "multiple")]
8fa3ba89 9789)
9c08d1fa 9790
8a18b90c 9791(define_insn "*if_move_not"
9792 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9793 (if_then_else:SI
8fa3ba89 9794 (match_operator 4 "arm_comparison_operator"
8a18b90c 9795 [(match_operand 3 "cc_register" "") (const_int 0)])
9796 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9797 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
cffb2a26 9798 "TARGET_ARM"
8a18b90c 9799 "@
9800 mvn%D4\\t%0, %2
9801 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
9802 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
8fa3ba89 9803 [(set_attr "conds" "use")
1aed5204 9804 (set_attr "type" "mvn_reg")
1b7da4ac 9805 (set_attr "length" "4,8,8")
9806 (set_attr "type" "mvn_reg,multiple,multiple")]
8fa3ba89 9807)
8a18b90c 9808
9809(define_insn "*ifcompare_not_move"
9c08d1fa 9810 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9811 (if_then_else:SI
8fa3ba89 9812 (match_operator 5 "arm_comparison_operator"
8a18b90c 9813 [(match_operand:SI 3 "s_register_operand" "r,r")
9814 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9815 (not:SI
9816 (match_operand:SI 2 "s_register_operand" "r,r"))
9817 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 9818 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9819 "TARGET_ARM"
8a18b90c 9820 "#"
8fa3ba89 9821 [(set_attr "conds" "clob")
1b7da4ac 9822 (set_attr "length" "8,12")
9823 (set_attr "type" "multiple")]
8fa3ba89 9824)
9c08d1fa 9825
8a18b90c 9826(define_insn "*if_not_move"
9827 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9828 (if_then_else:SI
8fa3ba89 9829 (match_operator 4 "arm_comparison_operator"
8a18b90c 9830 [(match_operand 3 "cc_register" "") (const_int 0)])
9831 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9832 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 9833 "TARGET_ARM"
8a18b90c 9834 "@
9835 mvn%d4\\t%0, %2
9836 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
9837 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
8fa3ba89 9838 [(set_attr "conds" "use")
1b7da4ac 9839 (set_attr "type" "mvn_reg,multiple,multiple")
8fa3ba89 9840 (set_attr "length" "4,8,8")]
9841)
8a18b90c 9842
9843(define_insn "*ifcompare_shift_move"
9c08d1fa 9844 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9845 (if_then_else:SI
8fa3ba89 9846 (match_operator 6 "arm_comparison_operator"
8a18b90c 9847 [(match_operand:SI 4 "s_register_operand" "r,r")
9848 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9849 (match_operator:SI 7 "shift_operator"
9850 [(match_operand:SI 2 "s_register_operand" "r,r")
9851 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
9852 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 9853 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9854 "TARGET_ARM"
9c08d1fa 9855 "#"
8fa3ba89 9856 [(set_attr "conds" "clob")
1b7da4ac 9857 (set_attr "length" "8,12")
9858 (set_attr "type" "multiple")]
8fa3ba89 9859)
9c08d1fa 9860
8a18b90c 9861(define_insn "*if_shift_move"
9862 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9863 (if_then_else:SI
8fa3ba89 9864 (match_operator 5 "arm_comparison_operator"
8a18b90c 9865 [(match_operand 6 "cc_register" "") (const_int 0)])
9866 (match_operator:SI 4 "shift_operator"
9867 [(match_operand:SI 2 "s_register_operand" "r,r,r")
9868 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
9869 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 9870 "TARGET_ARM"
5565501b 9871 "@
8a18b90c 9872 mov%d5\\t%0, %2%S4
9873 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
9874 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
8fa3ba89 9875 [(set_attr "conds" "use")
331beb1a 9876 (set_attr "shift" "2")
a2cd141b 9877 (set_attr "length" "4,8,8")
282b4c75 9878 (set_attr_alternative "type"
9879 [(if_then_else (match_operand 3 "const_int_operand" "")
9880 (const_string "mov_shift" )
9881 (const_string "mov_shift_reg"))
9882 (const_string "multiple")
9883 (const_string "multiple")])]
8fa3ba89 9884)
5565501b 9885
8a18b90c 9886(define_insn "*ifcompare_move_shift"
9887 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 9888 (if_then_else:SI
8fa3ba89 9889 (match_operator 6 "arm_comparison_operator"
8a18b90c 9890 [(match_operand:SI 4 "s_register_operand" "r,r")
9891 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9892 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
5565501b 9893 (match_operator:SI 7 "shift_operator"
8a18b90c 9894 [(match_operand:SI 2 "s_register_operand" "r,r")
9895 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
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)
5565501b 9903
8a18b90c 9904(define_insn "*if_move_shift"
9905 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 9906 (if_then_else:SI
8fa3ba89 9907 (match_operator 5 "arm_comparison_operator"
8a18b90c 9908 [(match_operand 6 "cc_register" "") (const_int 0)])
9909 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9910 (match_operator:SI 4 "shift_operator"
9911 [(match_operand:SI 2 "s_register_operand" "r,r,r")
9912 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
cffb2a26 9913 "TARGET_ARM"
5565501b 9914 "@
8a18b90c 9915 mov%D5\\t%0, %2%S4
9916 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
9917 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
8fa3ba89 9918 [(set_attr "conds" "use")
331beb1a 9919 (set_attr "shift" "2")
a2cd141b 9920 (set_attr "length" "4,8,8")
282b4c75 9921 (set_attr_alternative "type"
9922 [(if_then_else (match_operand 3 "const_int_operand" "")
9923 (const_string "mov_shift" )
9924 (const_string "mov_shift_reg"))
9925 (const_string "multiple")
9926 (const_string "multiple")])]
8fa3ba89 9927)
9c08d1fa 9928
f7fbdd4a 9929(define_insn "*ifcompare_shift_shift"
8a18b90c 9930 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 9931 (if_then_else:SI
8fa3ba89 9932 (match_operator 7 "arm_comparison_operator"
8a18b90c 9933 [(match_operand:SI 5 "s_register_operand" "r")
9934 (match_operand:SI 6 "arm_add_operand" "rIL")])
5565501b 9935 (match_operator:SI 8 "shift_operator"
8a18b90c 9936 [(match_operand:SI 1 "s_register_operand" "r")
9937 (match_operand:SI 2 "arm_rhs_operand" "rM")])
5565501b 9938 (match_operator:SI 9 "shift_operator"
8a18b90c 9939 [(match_operand:SI 3 "s_register_operand" "r")
9940 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
bd5b4116 9941 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9942 "TARGET_ARM"
8a18b90c 9943 "#"
8fa3ba89 9944 [(set_attr "conds" "clob")
1b7da4ac 9945 (set_attr "length" "12")
9946 (set_attr "type" "multiple")]
8fa3ba89 9947)
9c08d1fa 9948
8a18b90c 9949(define_insn "*if_shift_shift"
9950 [(set (match_operand:SI 0 "s_register_operand" "=r")
9951 (if_then_else:SI
8fa3ba89 9952 (match_operator 5 "arm_comparison_operator"
8a18b90c 9953 [(match_operand 8 "cc_register" "") (const_int 0)])
9954 (match_operator:SI 6 "shift_operator"
9955 [(match_operand:SI 1 "s_register_operand" "r")
9956 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9957 (match_operator:SI 7 "shift_operator"
9958 [(match_operand:SI 3 "s_register_operand" "r")
9959 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
cffb2a26 9960 "TARGET_ARM"
8a18b90c 9961 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
8fa3ba89 9962 [(set_attr "conds" "use")
331beb1a 9963 (set_attr "shift" "1")
a2cd141b 9964 (set_attr "length" "8")
9965 (set (attr "type") (if_then_else
9966 (and (match_operand 2 "const_int_operand" "")
9967 (match_operand 4 "const_int_operand" ""))
1aed5204 9968 (const_string "mov_shift")
9969 (const_string "mov_shift_reg")))]
8fa3ba89 9970)
8a18b90c 9971
f7fbdd4a 9972(define_insn "*ifcompare_not_arith"
8a18b90c 9973 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 9974 (if_then_else:SI
8fa3ba89 9975 (match_operator 6 "arm_comparison_operator"
8a18b90c 9976 [(match_operand:SI 4 "s_register_operand" "r")
9977 (match_operand:SI 5 "arm_add_operand" "rIL")])
9978 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5565501b 9979 (match_operator:SI 7 "shiftable_operator"
8a18b90c 9980 [(match_operand:SI 2 "s_register_operand" "r")
9981 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
bd5b4116 9982 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9983 "TARGET_ARM"
8a18b90c 9984 "#"
8fa3ba89 9985 [(set_attr "conds" "clob")
1b7da4ac 9986 (set_attr "length" "12")
9987 (set_attr "type" "multiple")]
8fa3ba89 9988)
9c08d1fa 9989
8a18b90c 9990(define_insn "*if_not_arith"
9991 [(set (match_operand:SI 0 "s_register_operand" "=r")
9992 (if_then_else:SI
8fa3ba89 9993 (match_operator 5 "arm_comparison_operator"
8a18b90c 9994 [(match_operand 4 "cc_register" "") (const_int 0)])
9995 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9996 (match_operator:SI 6 "shiftable_operator"
9997 [(match_operand:SI 2 "s_register_operand" "r")
9998 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
cffb2a26 9999 "TARGET_ARM"
8a18b90c 10000 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
8fa3ba89 10001 [(set_attr "conds" "use")
1aed5204 10002 (set_attr "type" "mvn_reg")
8fa3ba89 10003 (set_attr "length" "8")]
10004)
8a18b90c 10005
10006(define_insn "*ifcompare_arith_not"
10007 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 10008 (if_then_else:SI
8fa3ba89 10009 (match_operator 6 "arm_comparison_operator"
8a18b90c 10010 [(match_operand:SI 4 "s_register_operand" "r")
10011 (match_operand:SI 5 "arm_add_operand" "rIL")])
5565501b 10012 (match_operator:SI 7 "shiftable_operator"
8a18b90c 10013 [(match_operand:SI 2 "s_register_operand" "r")
10014 (match_operand:SI 3 "arm_rhs_operand" "rI")])
10015 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
bd5b4116 10016 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10017 "TARGET_ARM"
8a18b90c 10018 "#"
8fa3ba89 10019 [(set_attr "conds" "clob")
1b7da4ac 10020 (set_attr "length" "12")
10021 (set_attr "type" "multiple")]
8fa3ba89 10022)
9c08d1fa 10023
8a18b90c 10024(define_insn "*if_arith_not"
10025 [(set (match_operand:SI 0 "s_register_operand" "=r")
10026 (if_then_else:SI
8fa3ba89 10027 (match_operator 5 "arm_comparison_operator"
8a18b90c 10028 [(match_operand 4 "cc_register" "") (const_int 0)])
10029 (match_operator:SI 6 "shiftable_operator"
10030 [(match_operand:SI 2 "s_register_operand" "r")
10031 (match_operand:SI 3 "arm_rhs_operand" "rI")])
10032 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
cffb2a26 10033 "TARGET_ARM"
8a18b90c 10034 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
8fa3ba89 10035 [(set_attr "conds" "use")
1b7da4ac 10036 (set_attr "type" "multiple")
8fa3ba89 10037 (set_attr "length" "8")]
10038)
8a18b90c 10039
f7fbdd4a 10040(define_insn "*ifcompare_neg_move"
8a18b90c 10041 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 10042 (if_then_else:SI
8fa3ba89 10043 (match_operator 5 "arm_comparison_operator"
8a18b90c 10044 [(match_operand:SI 3 "s_register_operand" "r,r")
10045 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10046 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
10047 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 10048 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10049 "TARGET_ARM"
8a18b90c 10050 "#"
8fa3ba89 10051 [(set_attr "conds" "clob")
1b7da4ac 10052 (set_attr "length" "8,12")
10053 (set_attr "type" "multiple")]
8fa3ba89 10054)
8a18b90c 10055
530bb693 10056(define_insn_and_split "*if_neg_move"
10057 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
8a18b90c 10058 (if_then_else:SI
8fa3ba89 10059 (match_operator 4 "arm_comparison_operator"
8a18b90c 10060 [(match_operand 3 "cc_register" "") (const_int 0)])
530bb693 10061 (neg:SI (match_operand:SI 2 "s_register_operand" "l,r"))
10062 (match_operand:SI 1 "s_register_operand" "0,0")))]
10063 "TARGET_32BIT"
10064 "#"
10065 "&& reload_completed"
10066 [(cond_exec (match_op_dup 4 [(match_dup 3) (const_int 0)])
10067 (set (match_dup 0) (neg:SI (match_dup 2))))]
10068 ""
8fa3ba89 10069 [(set_attr "conds" "use")
530bb693 10070 (set_attr "length" "4")
10071 (set_attr "arch" "t2,32")
8bdfd6ed 10072 (set_attr "enabled_for_short_it" "yes,no")
530bb693 10073 (set_attr "type" "logic_shift_imm")]
8fa3ba89 10074)
9c08d1fa 10075
f7fbdd4a 10076(define_insn "*ifcompare_move_neg"
8a18b90c 10077 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 10078 (if_then_else:SI
8fa3ba89 10079 (match_operator 5 "arm_comparison_operator"
8a18b90c 10080 [(match_operand:SI 3 "s_register_operand" "r,r")
10081 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10082 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
10083 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 10084 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10085 "TARGET_ARM"
8a18b90c 10086 "#"
8fa3ba89 10087 [(set_attr "conds" "clob")
1b7da4ac 10088 (set_attr "length" "8,12")
10089 (set_attr "type" "multiple")]
8fa3ba89 10090)
8a18b90c 10091
530bb693 10092(define_insn_and_split "*if_move_neg"
10093 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
8a18b90c 10094 (if_then_else:SI
8fa3ba89 10095 (match_operator 4 "arm_comparison_operator"
8a18b90c 10096 [(match_operand 3 "cc_register" "") (const_int 0)])
530bb693 10097 (match_operand:SI 1 "s_register_operand" "0,0")
10098 (neg:SI (match_operand:SI 2 "s_register_operand" "l,r"))))]
10099 "TARGET_32BIT"
10100 "#"
10101 "&& reload_completed"
10102 [(cond_exec (match_dup 5)
10103 (set (match_dup 0) (neg:SI (match_dup 2))))]
10104 {
10105 machine_mode mode = GET_MODE (operands[3]);
10106 rtx_code rc = GET_CODE (operands[4]);
10107
10108 if (mode == CCFPmode || mode == CCFPEmode)
10109 rc = reverse_condition_maybe_unordered (rc);
10110 else
10111 rc = reverse_condition (rc);
10112
10113 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[3], const0_rtx);
10114 }
0d66636f 10115 [(set_attr "conds" "use")
530bb693 10116 (set_attr "length" "4")
10117 (set_attr "arch" "t2,32")
8bdfd6ed 10118 (set_attr "enabled_for_short_it" "yes,no")
530bb693 10119 (set_attr "type" "logic_shift_imm")]
0d66636f 10120)
9c08d1fa 10121
f7fbdd4a 10122(define_insn "*arith_adjacentmem"
9c08d1fa 10123 [(set (match_operand:SI 0 "s_register_operand" "=r")
10124 (match_operator:SI 1 "shiftable_operator"
10125 [(match_operand:SI 2 "memory_operand" "m")
10126 (match_operand:SI 3 "memory_operand" "m")]))
10127 (clobber (match_scratch:SI 4 "=r"))]
cffb2a26 10128 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9c08d1fa 10129 "*
215b30b3 10130 {
10131 rtx ldm[3];
10132 rtx arith[4];
94dee231 10133 rtx base_reg;
10134 HOST_WIDE_INT val1 = 0, val2 = 0;
9c08d1fa 10135
215b30b3 10136 if (REGNO (operands[0]) > REGNO (operands[4]))
10137 {
10138 ldm[1] = operands[4];
10139 ldm[2] = operands[0];
10140 }
10141 else
10142 {
10143 ldm[1] = operands[0];
10144 ldm[2] = operands[4];
10145 }
94dee231 10146
10147 base_reg = XEXP (operands[2], 0);
10148
10149 if (!REG_P (base_reg))
10150 {
10151 val1 = INTVAL (XEXP (base_reg, 1));
10152 base_reg = XEXP (base_reg, 0);
10153 }
10154
10155 if (!REG_P (XEXP (operands[3], 0)))
215b30b3 10156 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
94dee231 10157
215b30b3 10158 arith[0] = operands[0];
10159 arith[3] = operands[1];
94dee231 10160
215b30b3 10161 if (val1 < val2)
10162 {
10163 arith[1] = ldm[1];
10164 arith[2] = ldm[2];
10165 }
10166 else
10167 {
10168 arith[1] = ldm[2];
10169 arith[2] = ldm[1];
10170 }
94dee231 10171
10172 ldm[0] = base_reg;
10173 if (val1 !=0 && val2 != 0)
215b30b3 10174 {
cdb1295a 10175 rtx ops[3];
10176
94dee231 10177 if (val1 == 4 || val2 == 4)
10178 /* Other val must be 8, since we know they are adjacent and neither
10179 is zero. */
3ef90e77 10180 output_asm_insn (\"ldmib%?\\t%0, {%1, %2}\", ldm);
cdb1295a 10181 else if (const_ok_for_arm (val1) || const_ok_for_arm (-val1))
94dee231 10182 {
94dee231 10183 ldm[0] = ops[0] = operands[4];
10184 ops[1] = base_reg;
10185 ops[2] = GEN_INT (val1);
10186 output_add_immediate (ops);
10187 if (val1 < val2)
3ef90e77 10188 output_asm_insn (\"ldmia%?\\t%0, {%1, %2}\", ldm);
94dee231 10189 else
3ef90e77 10190 output_asm_insn (\"ldmda%?\\t%0, {%1, %2}\", ldm);
94dee231 10191 }
cdb1295a 10192 else
10193 {
10194 /* Offset is out of range for a single add, so use two ldr. */
10195 ops[0] = ldm[1];
10196 ops[1] = base_reg;
10197 ops[2] = GEN_INT (val1);
10198 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10199 ops[0] = ldm[2];
10200 ops[2] = GEN_INT (val2);
10201 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10202 }
215b30b3 10203 }
94dee231 10204 else if (val1 != 0)
215b30b3 10205 {
215b30b3 10206 if (val1 < val2)
3ef90e77 10207 output_asm_insn (\"ldmda%?\\t%0, {%1, %2}\", ldm);
215b30b3 10208 else
3ef90e77 10209 output_asm_insn (\"ldmia%?\\t%0, {%1, %2}\", ldm);
215b30b3 10210 }
10211 else
10212 {
215b30b3 10213 if (val1 < val2)
3ef90e77 10214 output_asm_insn (\"ldmia%?\\t%0, {%1, %2}\", ldm);
215b30b3 10215 else
3ef90e77 10216 output_asm_insn (\"ldmda%?\\t%0, {%1, %2}\", ldm);
215b30b3 10217 }
10218 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
10219 return \"\";
10220 }"
10221 [(set_attr "length" "12")
10222 (set_attr "predicable" "yes")
9f2c2a36 10223 (set_attr "type" "load_4")]
215b30b3 10224)
9c08d1fa 10225
9c08d1fa 10226; This pattern is never tried by combine, so do it as a peephole
10227
a0f94409 10228(define_peephole2
372575c7 10229 [(set (match_operand:SI 0 "arm_general_register_operand" "")
10230 (match_operand:SI 1 "arm_general_register_operand" ""))
bd5b4116 10231 (set (reg:CC CC_REGNUM)
aea4c774 10232 (compare:CC (match_dup 1) (const_int 0)))]
372575c7 10233 "TARGET_ARM"
a0f94409 10234 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
10235 (set (match_dup 0) (match_dup 1))])]
10236 ""
0d66636f 10237)
9c08d1fa 10238
9c08d1fa 10239(define_split
10240 [(set (match_operand:SI 0 "s_register_operand" "")
10241 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
10242 (const_int 0))
8fa3ba89 10243 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9c08d1fa 10244 [(match_operand:SI 3 "s_register_operand" "")
10245 (match_operand:SI 4 "arm_rhs_operand" "")]))))
10246 (clobber (match_operand:SI 5 "s_register_operand" ""))]
cffb2a26 10247 "TARGET_ARM"
9c08d1fa 10248 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
10249 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
10250 (match_dup 5)))]
215b30b3 10251 ""
10252)
9c08d1fa 10253
aea4c774 10254;; This split can be used because CC_Z mode implies that the following
10255;; branch will be an equality, or an unsigned inequality, so the sign
10256;; extension is not needed.
9c08d1fa 10257
aea4c774 10258(define_split
bd5b4116 10259 [(set (reg:CC_Z CC_REGNUM)
aea4c774 10260 (compare:CC_Z
10261 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9c08d1fa 10262 (const_int 24))
aea4c774 10263 (match_operand 1 "const_int_operand" "")))
10264 (clobber (match_scratch:SI 2 ""))]
cffb2a26 10265 "TARGET_ARM
8c4e8755 10266 && ((UINTVAL (operands[1]))
10267 == ((UINTVAL (operands[1])) >> 24) << 24)"
aea4c774 10268 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
bd5b4116 10269 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
aea4c774 10270 "
9c08d1fa 10271 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
215b30b3 10272 "
10273)
25f905c2 10274;; ??? Check the patterns above for Thumb-2 usefulness
9c08d1fa 10275
87b22bf7 10276(define_expand "prologue"
10277 [(clobber (const_int 0))]
cffb2a26 10278 "TARGET_EITHER"
25f905c2 10279 "if (TARGET_32BIT)
cffb2a26 10280 arm_expand_prologue ();
10281 else
25f905c2 10282 thumb1_expand_prologue ();
87b22bf7 10283 DONE;
cffb2a26 10284 "
10285)
87b22bf7 10286
56d27660 10287(define_expand "epilogue"
4c44712e 10288 [(clobber (const_int 0))]
cffb2a26 10289 "TARGET_EITHER"
56d27660 10290 "
18d50ae6 10291 if (crtl->calls_eh_return)
fb94f18b 10292 emit_insn (gen_force_register_use (gen_rtx_REG (Pmode, 2)));
25f905c2 10293 if (TARGET_THUMB1)
c3635784 10294 {
10295 thumb1_expand_epilogue ();
10296 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
10297 gen_rtvec (1, ret_rtx), VUNSPEC_EPILOGUE));
10298 }
10299 else if (HAVE_return)
10300 {
10301 /* HAVE_return is testing for USE_RETURN_INSN (FALSE). Hence,
10302 no need for explicit testing again. */
10303 emit_jump_insn (gen_return ());
10304 }
10305 else if (TARGET_32BIT)
10306 {
10307 arm_expand_epilogue (true);
10308 }
cffb2a26 10309 DONE;
10310 "
10311)
56d27660 10312
ef5651d0 10313;; Note - although unspec_volatile's USE all hard registers,
10314;; USEs are ignored after relaod has completed. Thus we need
10315;; to add an unspec of the link register to ensure that flow
10316;; does not think that it is unused by the sibcall branch that
10317;; will replace the standard function epilogue.
c3635784 10318(define_expand "sibcall_epilogue"
fb94f18b 10319 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_REGISTER_USE)
c3635784 10320 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
10321 "TARGET_32BIT"
10322 "
10323 arm_expand_epilogue (false);
10324 DONE;
10325 "
1c494086 10326)
10327
cffb2a26 10328(define_expand "eh_epilogue"
3934ae0e 10329 [(use (match_operand:SI 0 "register_operand"))
10330 (use (match_operand:SI 1 "register_operand"))
10331 (use (match_operand:SI 2 "register_operand"))]
cffb2a26 10332 "TARGET_EITHER"
10333 "
215b30b3 10334 {
10335 cfun->machine->eh_epilogue_sp_ofs = operands[1];
0438d37f 10336 if (!REG_P (operands[2]) || REGNO (operands[2]) != 2)
215b30b3 10337 {
10338 rtx ra = gen_rtx_REG (Pmode, 2);
10339
10340 emit_move_insn (ra, operands[2]);
10341 operands[2] = ra;
10342 }
5cf3595a 10343 /* This is a hack -- we may have crystalized the function type too
10344 early. */
10345 cfun->machine->func_type = 0;
215b30b3 10346 }"
10347)
56d27660 10348
9c08d1fa 10349;; This split is only used during output to reduce the number of patterns
10350;; that need assembler instructions adding to them. We allowed the setting
10351;; of the conditions to be implicit during rtl generation so that
10352;; the conditional compare patterns would work. However this conflicts to
8a18b90c 10353;; some extent with the conditional data operations, so we have to split them
9c08d1fa 10354;; up again here.
10355
25f905c2 10356;; ??? Need to audit these splitters for Thumb-2. Why isn't normal
10357;; conditional execution sufficient?
10358
9c08d1fa 10359(define_split
10360 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 10361 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10362 [(match_operand 2 "" "") (match_operand 3 "" "")])
10363 (match_dup 0)
10364 (match_operand 4 "" "")))
bd5b4116 10365 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10366 "TARGET_ARM && reload_completed"
8fa3ba89 10367 [(set (match_dup 5) (match_dup 6))
10368 (cond_exec (match_dup 7)
10369 (set (match_dup 0) (match_dup 4)))]
10370 "
10371 {
3754d046 10372 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8fa3ba89 10373 operands[2], operands[3]);
10374 enum rtx_code rc = GET_CODE (operands[1]);
10375
bd5b4116 10376 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10377 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10378 if (mode == CCFPmode || mode == CCFPEmode)
10379 rc = reverse_condition_maybe_unordered (rc);
10380 else
10381 rc = reverse_condition (rc);
10382
10383 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
10384 }"
10385)
10386
10387(define_split
10388 [(set (match_operand:SI 0 "s_register_operand" "")
10389 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10390 [(match_operand 2 "" "") (match_operand 3 "" "")])
10391 (match_operand 4 "" "")
10392 (match_dup 0)))
bd5b4116 10393 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10394 "TARGET_ARM && reload_completed"
8fa3ba89 10395 [(set (match_dup 5) (match_dup 6))
10396 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
10397 (set (match_dup 0) (match_dup 4)))]
10398 "
10399 {
3754d046 10400 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8fa3ba89 10401 operands[2], operands[3]);
10402
bd5b4116 10403 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10404 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10405 }"
10406)
10407
10408(define_split
10409 [(set (match_operand:SI 0 "s_register_operand" "")
10410 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9c08d1fa 10411 [(match_operand 2 "" "") (match_operand 3 "" "")])
10412 (match_operand 4 "" "")
10413 (match_operand 5 "" "")))
bd5b4116 10414 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10415 "TARGET_ARM && reload_completed"
8fa3ba89 10416 [(set (match_dup 6) (match_dup 7))
10417 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10418 (set (match_dup 0) (match_dup 4)))
10419 (cond_exec (match_dup 8)
10420 (set (match_dup 0) (match_dup 5)))]
10421 "
10422 {
3754d046 10423 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8fa3ba89 10424 operands[2], operands[3]);
10425 enum rtx_code rc = GET_CODE (operands[1]);
10426
bd5b4116 10427 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10428 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10429 if (mode == CCFPmode || mode == CCFPEmode)
10430 rc = reverse_condition_maybe_unordered (rc);
10431 else
10432 rc = reverse_condition (rc);
10433
10434 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10435 }"
10436)
10437
cffb2a26 10438(define_split
10439 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 10440 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
cffb2a26 10441 [(match_operand:SI 2 "s_register_operand" "")
10442 (match_operand:SI 3 "arm_add_operand" "")])
10443 (match_operand:SI 4 "arm_rhs_operand" "")
10444 (not:SI
10445 (match_operand:SI 5 "s_register_operand" ""))))
bd5b4116 10446 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10447 "TARGET_ARM && reload_completed"
cffb2a26 10448 [(set (match_dup 6) (match_dup 7))
f6c53574 10449 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10450 (set (match_dup 0) (match_dup 4)))
10451 (cond_exec (match_dup 8)
10452 (set (match_dup 0) (not:SI (match_dup 5))))]
cffb2a26 10453 "
215b30b3 10454 {
3754d046 10455 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
215b30b3 10456 operands[2], operands[3]);
f6c53574 10457 enum rtx_code rc = GET_CODE (operands[1]);
cffb2a26 10458
bd5b4116 10459 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
1a83b3ff 10460 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
f6c53574 10461 if (mode == CCFPmode || mode == CCFPEmode)
10462 rc = reverse_condition_maybe_unordered (rc);
10463 else
10464 rc = reverse_condition (rc);
10465
10466 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
215b30b3 10467 }"
10468)
cffb2a26 10469
10470(define_insn "*cond_move_not"
10471 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10472 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
cffb2a26 10473 [(match_operand 3 "cc_register" "") (const_int 0)])
10474 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10475 (not:SI
10476 (match_operand:SI 2 "s_register_operand" "r,r"))))]
10477 "TARGET_ARM"
10478 "@
10479 mvn%D4\\t%0, %2
10480 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
0d66636f 10481 [(set_attr "conds" "use")
1b7da4ac 10482 (set_attr "type" "mvn_reg,multiple")
0d66636f 10483 (set_attr "length" "4,8")]
10484)
cffb2a26 10485
9c08d1fa 10486;; The next two patterns occur when an AND operation is followed by a
10487;; scc insn sequence
10488
f7fbdd4a 10489(define_insn "*sign_extract_onebit"
9c08d1fa 10490 [(set (match_operand:SI 0 "s_register_operand" "=r")
10491 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10492 (const_int 1)
ed750274 10493 (match_operand:SI 2 "const_int_operand" "n")))
10494 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10495 "TARGET_ARM"
9c08d1fa 10496 "*
0d66636f 10497 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10498 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
10499 return \"mvnne\\t%0, #0\";
10500 "
10501 [(set_attr "conds" "clob")
1b7da4ac 10502 (set_attr "length" "8")
10503 (set_attr "type" "multiple")]
0d66636f 10504)
9c08d1fa 10505
f7fbdd4a 10506(define_insn "*not_signextract_onebit"
9c08d1fa 10507 [(set (match_operand:SI 0 "s_register_operand" "=r")
10508 (not:SI
10509 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10510 (const_int 1)
ed750274 10511 (match_operand:SI 2 "const_int_operand" "n"))))
10512 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10513 "TARGET_ARM"
9c08d1fa 10514 "*
0d66636f 10515 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10516 output_asm_insn (\"tst\\t%1, %2\", operands);
10517 output_asm_insn (\"mvneq\\t%0, #0\", operands);
10518 return \"movne\\t%0, #0\";
10519 "
10520 [(set_attr "conds" "clob")
1b7da4ac 10521 (set_attr "length" "12")
10522 (set_attr "type" "multiple")]
0d66636f 10523)
25f905c2 10524;; ??? The above patterns need auditing for Thumb-2
87b22bf7 10525
0d66636f 10526;; Push multiple registers to the stack. Registers are in parallel (use ...)
10527;; expressions. For simplicity, the first register is also in the unspec
10528;; part.
08508cbf 10529;; To avoid the usage of GNU extension, the length attribute is computed
10530;; in a C function arm_attr_length_push_multi.
f7fbdd4a 10531(define_insn "*push_multi"
87b22bf7 10532 [(match_parallel 2 "multi_register_push"
7571d3f7 10533 [(set (match_operand:BLK 0 "push_mult_memory_operand" "")
3cc80a30 10534 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "")]
e1159bbe 10535 UNSPEC_PUSH_MULT))])]
7571d3f7 10536 ""
87b22bf7 10537 "*
215b30b3 10538 {
10539 int num_saves = XVECLEN (operands[2], 0);
ed593f11 10540
215b30b3 10541 /* For the StrongARM at least it is faster to
25f905c2 10542 use STR to store only a single register.
542d5028 10543 In Thumb mode always use push, and the assembler will pick
10544 something appropriate. */
25f905c2 10545 if (num_saves == 1 && TARGET_ARM)
61309563 10546 output_asm_insn (\"str%?\\t%1, [%m0, #-4]!\", operands);
215b30b3 10547 else
10548 {
10549 int i;
10550 char pattern[100];
ed593f11 10551
3ef90e77 10552 if (TARGET_32BIT)
61309563 10553 strcpy (pattern, \"push%?\\t{%1\");
25f905c2 10554 else
10555 strcpy (pattern, \"push\\t{%1\");
215b30b3 10556
6079f055 10557 for (i = 1; i < num_saves; i++)
215b30b3 10558 {
10559 strcat (pattern, \", %|\");
10560 strcat (pattern,
10561 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
10562 }
10563
10564 strcat (pattern, \"}\");
10565 output_asm_insn (pattern, operands);
10566 }
10567
10568 return \"\";
10569 }"
9f2c2a36 10570 [(set_attr "type" "store_16")
a6864a24 10571 (set (attr "length")
08508cbf 10572 (symbol_ref "arm_attr_length_push_multi (operands[2], operands[1])"))]
215b30b3 10573)
f7fbdd4a 10574
4c58c898 10575(define_insn "stack_tie"
10576 [(set (mem:BLK (scratch))
aaa37ad6 10577 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "rk")
10578 (match_operand:SI 1 "s_register_operand" "rk")]
4c58c898 10579 UNSPEC_PRLG_STK))]
10580 ""
10581 ""
1b7da4ac 10582 [(set_attr "length" "0")
10583 (set_attr "type" "block")]
4c58c898 10584)
10585
426be8c5 10586;; Pop (as used in epilogue RTL)
10587;;
10588(define_insn "*load_multiple_with_writeback"
10589 [(match_parallel 0 "load_multiple_operation"
10590 [(set (match_operand:SI 1 "s_register_operand" "+rk")
10591 (plus:SI (match_dup 1)
809003b3 10592 (match_operand:SI 2 "const_int_I_operand" "I")))
426be8c5 10593 (set (match_operand:SI 3 "s_register_operand" "=rk")
10594 (mem:SI (match_dup 1)))
10595 ])]
10596 "TARGET_32BIT && (reload_in_progress || reload_completed)"
10597 "*
10598 {
10599 arm_output_multireg_pop (operands, /*return_pc=*/false,
10600 /*cond=*/const_true_rtx,
10601 /*reverse=*/false,
10602 /*update=*/true);
10603 return \"\";
10604 }
10605 "
9f2c2a36 10606 [(set_attr "type" "load_16")
5431c9c9 10607 (set_attr "predicable" "yes")
10608 (set (attr "length")
10609 (symbol_ref "arm_attr_length_pop_multi (operands,
10610 /*return_pc=*/false,
10611 /*write_back_p=*/true)"))]
426be8c5 10612)
10613
10614;; Pop with return (as used in epilogue RTL)
10615;;
10616;; This instruction is generated when the registers are popped at the end of
10617;; epilogue. Here, instead of popping the value into LR and then generating
10618;; jump to LR, value is popped into PC directly. Hence, the pattern is combined
10619;; with (return).
10620(define_insn "*pop_multiple_with_writeback_and_return"
10621 [(match_parallel 0 "pop_multiple_return"
10622 [(return)
10623 (set (match_operand:SI 1 "s_register_operand" "+rk")
10624 (plus:SI (match_dup 1)
809003b3 10625 (match_operand:SI 2 "const_int_I_operand" "I")))
426be8c5 10626 (set (match_operand:SI 3 "s_register_operand" "=rk")
10627 (mem:SI (match_dup 1)))
10628 ])]
10629 "TARGET_32BIT && (reload_in_progress || reload_completed)"
10630 "*
10631 {
10632 arm_output_multireg_pop (operands, /*return_pc=*/true,
10633 /*cond=*/const_true_rtx,
10634 /*reverse=*/false,
10635 /*update=*/true);
10636 return \"\";
10637 }
10638 "
9f2c2a36 10639 [(set_attr "type" "load_16")
5431c9c9 10640 (set_attr "predicable" "yes")
10641 (set (attr "length")
10642 (symbol_ref "arm_attr_length_pop_multi (operands, /*return_pc=*/true,
10643 /*write_back_p=*/true)"))]
426be8c5 10644)
10645
10646(define_insn "*pop_multiple_with_return"
10647 [(match_parallel 0 "pop_multiple_return"
10648 [(return)
10649 (set (match_operand:SI 2 "s_register_operand" "=rk")
10650 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
10651 ])]
10652 "TARGET_32BIT && (reload_in_progress || reload_completed)"
10653 "*
10654 {
10655 arm_output_multireg_pop (operands, /*return_pc=*/true,
10656 /*cond=*/const_true_rtx,
10657 /*reverse=*/false,
10658 /*update=*/false);
10659 return \"\";
10660 }
10661 "
9f2c2a36 10662 [(set_attr "type" "load_16")
5431c9c9 10663 (set_attr "predicable" "yes")
10664 (set (attr "length")
10665 (symbol_ref "arm_attr_length_pop_multi (operands, /*return_pc=*/true,
10666 /*write_back_p=*/false)"))]
426be8c5 10667)
10668
10669;; Load into PC and return
10670(define_insn "*ldr_with_return"
10671 [(return)
10672 (set (reg:SI PC_REGNUM)
10673 (mem:SI (post_inc:SI (match_operand:SI 0 "s_register_operand" "+rk"))))]
10674 "TARGET_32BIT && (reload_in_progress || reload_completed)"
10675 "ldr%?\t%|pc, [%0], #4"
9f2c2a36 10676 [(set_attr "type" "load_4")
426be8c5 10677 (set_attr "predicable" "yes")]
10678)
1a0b0f12 10679;; Pop for floating point registers (as used in epilogue RTL)
10680(define_insn "*vfp_pop_multiple_with_writeback"
10681 [(match_parallel 0 "pop_multiple_fp"
10682 [(set (match_operand:SI 1 "s_register_operand" "+rk")
10683 (plus:SI (match_dup 1)
809003b3 10684 (match_operand:SI 2 "const_int_I_operand" "I")))
2f2163a4 10685 (set (match_operand:DF 3 "vfp_hard_register_operand" "")
1a0b0f12 10686 (mem:DF (match_dup 1)))])]
d7216193 10687 "TARGET_32BIT && TARGET_HARD_FLOAT"
1a0b0f12 10688 "*
10689 {
10690 int num_regs = XVECLEN (operands[0], 0);
10691 char pattern[100];
10692 rtx op_list[2];
b34d8dac 10693 strcpy (pattern, \"vldm\\t\");
1a0b0f12 10694 strcat (pattern, reg_names[REGNO (SET_DEST (XVECEXP (operands[0], 0, 0)))]);
10695 strcat (pattern, \"!, {\");
10696 op_list[0] = XEXP (XVECEXP (operands[0], 0, 1), 0);
10697 strcat (pattern, \"%P0\");
10698 if ((num_regs - 1) > 1)
10699 {
10700 strcat (pattern, \"-%P1\");
10701 op_list [1] = XEXP (XVECEXP (operands[0], 0, num_regs - 1), 0);
10702 }
10703
10704 strcat (pattern, \"}\");
10705 output_asm_insn (pattern, op_list);
10706 return \"\";
10707 }
10708 "
9f2c2a36 10709 [(set_attr "type" "load_16")
1a0b0f12 10710 (set_attr "conds" "unconditional")
10711 (set_attr "predicable" "no")]
10712)
10713
f7fbdd4a 10714;; Special patterns for dealing with the constant pool
10715
cffb2a26 10716(define_insn "align_4"
e1159bbe 10717 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
cffb2a26 10718 "TARGET_EITHER"
f7fbdd4a 10719 "*
cffb2a26 10720 assemble_align (32);
f7fbdd4a 10721 return \"\";
cffb2a26 10722 "
1b7da4ac 10723 [(set_attr "type" "no_insn")]
cffb2a26 10724)
f7fbdd4a 10725
755eb2b4 10726(define_insn "align_8"
10727 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
f9273c43 10728 "TARGET_EITHER"
755eb2b4 10729 "*
10730 assemble_align (64);
10731 return \"\";
10732 "
1b7da4ac 10733 [(set_attr "type" "no_insn")]
755eb2b4 10734)
10735
cffb2a26 10736(define_insn "consttable_end"
e1159bbe 10737 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
cffb2a26 10738 "TARGET_EITHER"
f7fbdd4a 10739 "*
cffb2a26 10740 making_const_table = FALSE;
f7fbdd4a 10741 return \"\";
cffb2a26 10742 "
1b7da4ac 10743 [(set_attr "type" "no_insn")]
cffb2a26 10744)
f7fbdd4a 10745
0e207eb8 10746(define_insn "consttable_1"
10747 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
10748 "TARGET_EITHER"
10749 "*
10750 making_const_table = TRUE;
10751 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
10752 assemble_zeros (3);
10753 return \"\";
10754 "
10755 [(set_attr "length" "4")
10756 (set_attr "type" "no_insn")]
10757)
10758
10759(define_insn "consttable_2"
10760 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
10761 "TARGET_EITHER"
10762 "*
10763 {
10764 rtx x = operands[0];
10765 making_const_table = TRUE;
10766 switch (GET_MODE_CLASS (GET_MODE (x)))
10767 {
10768 case MODE_FLOAT:
10769 arm_emit_fp16_const (x);
10770 break;
10771 default:
10772 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
10773 assemble_zeros (2);
10774 break;
10775 }
10776 return \"\";
10777 }"
10778 [(set_attr "length" "4")
10779 (set_attr "type" "no_insn")]
10780)
10781
cffb2a26 10782(define_insn "consttable_4"
e1159bbe 10783 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
cffb2a26 10784 "TARGET_EITHER"
10785 "*
10786 {
9b8516be 10787 rtx x = operands[0];
cffb2a26 10788 making_const_table = TRUE;
0f97e0f5 10789 scalar_float_mode float_mode;
10790 if (is_a <scalar_float_mode> (GET_MODE (x), &float_mode))
10791 assemble_real (*CONST_DOUBLE_REAL_VALUE (x), float_mode, BITS_PER_WORD);
10792 else
cffb2a26 10793 {
7b04c5d5 10794 /* XXX: Sometimes gcc does something really dumb and ends up with
10795 a HIGH in a constant pool entry, usually because it's trying to
10796 load into a VFP register. We know this will always be used in
10797 combination with a LO_SUM which ignores the high bits, so just
10798 strip off the HIGH. */
10799 if (GET_CODE (x) == HIGH)
10800 x = XEXP (x, 0);
9b8516be 10801 assemble_integer (x, 4, BITS_PER_WORD, 1);
10802 mark_symbol_refs_as_used (x);
cffb2a26 10803 }
10804 return \"\";
10805 }"
1b7da4ac 10806 [(set_attr "length" "4")
10807 (set_attr "type" "no_insn")]
cffb2a26 10808)
10809
10810(define_insn "consttable_8"
e1159bbe 10811 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
cffb2a26 10812 "TARGET_EITHER"
10813 "*
10814 {
10815 making_const_table = TRUE;
0f97e0f5 10816 scalar_float_mode float_mode;
10817 if (is_a <scalar_float_mode> (GET_MODE (operands[0]), &float_mode))
10818 assemble_real (*CONST_DOUBLE_REAL_VALUE (operands[0]),
10819 float_mode, BITS_PER_WORD);
10820 else
10821 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
cffb2a26 10822 return \"\";
10823 }"
1b7da4ac 10824 [(set_attr "length" "8")
10825 (set_attr "type" "no_insn")]
cffb2a26 10826)
10827
d98a3884 10828(define_insn "consttable_16"
10829 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_16)]
10830 "TARGET_EITHER"
10831 "*
10832 {
10833 making_const_table = TRUE;
0f97e0f5 10834 scalar_float_mode float_mode;
10835 if (is_a <scalar_float_mode> (GET_MODE (operands[0]), &float_mode))
10836 assemble_real (*CONST_DOUBLE_REAL_VALUE (operands[0]),
10837 float_mode, BITS_PER_WORD);
10838 else
10839 assemble_integer (operands[0], 16, BITS_PER_WORD, 1);
d98a3884 10840 return \"\";
10841 }"
1b7da4ac 10842 [(set_attr "length" "16")
10843 (set_attr "type" "no_insn")]
d98a3884 10844)
10845
331beb1a 10846;; V5 Instructions,
10847
8f4be2be 10848(define_insn "clzsi2"
10849 [(set (match_operand:SI 0 "s_register_operand" "=r")
10850 (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
b232e6b5 10851 "TARGET_32BIT && arm_arch5t"
ee7cbe0e 10852 "clz%?\\t%0, %1"
bcaec148 10853 [(set_attr "predicable" "yes")
bebe9bbb 10854 (set_attr "type" "clz")])
331beb1a 10855
099ad98b 10856(define_insn "rbitsi2"
10857 [(set (match_operand:SI 0 "s_register_operand" "=r")
10858 (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")] UNSPEC_RBIT))]
10859 "TARGET_32BIT && arm_arch_thumb2"
10860 "rbit%?\\t%0, %1"
10861 [(set_attr "predicable" "yes")
bebe9bbb 10862 (set_attr "type" "clz")])
099ad98b 10863
99ffa689 10864;; Keep this as a CTZ expression until after reload and then split
10865;; into RBIT + CLZ. Since RBIT is represented as an UNSPEC it is unlikely
10866;; to fold with any other expression.
10867
10868(define_insn_and_split "ctzsi2"
10869 [(set (match_operand:SI 0 "s_register_operand" "=r")
10870 (ctz:SI (match_operand:SI 1 "s_register_operand" "r")))]
099ad98b 10871 "TARGET_32BIT && arm_arch_thumb2"
99ffa689 10872 "#"
10873 "&& reload_completed"
10874 [(const_int 0)]
099ad98b 10875 "
99ffa689 10876 emit_insn (gen_rbitsi2 (operands[0], operands[1]));
10877 emit_insn (gen_clzsi2 (operands[0], operands[0]));
10878 DONE;
10879")
099ad98b 10880
e1159bbe 10881;; V5E instructions.
331beb1a 10882
10883(define_insn "prefetch"
f4e79814 10884 [(prefetch (match_operand:SI 0 "address_operand" "p")
10885 (match_operand:SI 1 "" "")
10886 (match_operand:SI 2 "" ""))]
b232e6b5 10887 "TARGET_32BIT && arm_arch5te"
1b7da4ac 10888 "pld\\t%a0"
9f2c2a36 10889 [(set_attr "type" "load_4")]
1b7da4ac 10890)
331beb1a 10891
0d66636f 10892;; General predication pattern
10893
10894(define_cond_exec
10895 [(match_operator 0 "arm_comparison_operator"
10896 [(match_operand 1 "cc_register" "")
10897 (const_int 0)])]
580f4c48 10898 "TARGET_32BIT
10899 && (!TARGET_NO_VOLATILE_CE || !volatile_refs_p (PATTERN (insn)))"
0d66636f 10900 ""
c7a58118 10901[(set_attr "predicated" "yes")]
0d66636f 10902)
10903
fb94f18b 10904(define_insn "force_register_use"
10905 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_REGISTER_USE)]
063a05c7 10906 ""
fb94f18b 10907 "%@ %0 needed"
1b7da4ac 10908 [(set_attr "length" "0")
10909 (set_attr "type" "no_insn")]
063a05c7 10910)
7db9af5d 10911
4c44712e 10912
10913;; Patterns for exception handling
10914
10915(define_expand "eh_return"
3934ae0e 10916 [(use (match_operand 0 "general_operand"))]
4c44712e 10917 "TARGET_EITHER"
10918 "
10919 {
25f905c2 10920 if (TARGET_32BIT)
4c44712e 10921 emit_insn (gen_arm_eh_return (operands[0]));
10922 else
10923 emit_insn (gen_thumb_eh_return (operands[0]));
10924 DONE;
10925 }"
10926)
10927
10928;; We can't expand this before we know where the link register is stored.
10929(define_insn_and_split "arm_eh_return"
10930 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
10931 VUNSPEC_EH_RETURN)
10932 (clobber (match_scratch:SI 1 "=&r"))]
10933 "TARGET_ARM"
10934 "#"
10935 "&& reload_completed"
10936 [(const_int 0)]
10937 "
10938 {
10939 arm_set_return_address (operands[0], operands[1]);
10940 DONE;
10941 }"
10942)
10943
f655717d 10944\f
10945;; TLS support
10946
10947(define_insn "load_tp_hard"
10948 [(set (match_operand:SI 0 "register_operand" "=r")
10949 (unspec:SI [(const_int 0)] UNSPEC_TLS))]
10950 "TARGET_HARD_TP"
10951 "mrc%?\\tp15, 0, %0, c13, c0, 3\\t@ load_tp_hard"
1b7da4ac 10952 [(set_attr "predicable" "yes")
4b5d7374 10953 (set_attr "type" "mrs")]
f655717d 10954)
10955
85fc66a7 10956;; Doesn't clobber R1-R3. Must use r0 for the first operand.
10957(define_insn "load_tp_soft_fdpic"
10958 [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
10959 (clobber (reg:SI FDPIC_REGNUM))
10960 (clobber (reg:SI LR_REGNUM))
10961 (clobber (reg:SI IP_REGNUM))
10962 (clobber (reg:CC CC_REGNUM))]
10963 "TARGET_SOFT_TP && TARGET_FDPIC"
10964 "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
10965 [(set_attr "conds" "clob")
10966 (set_attr "type" "branch")]
10967)
10968
f655717d 10969;; Doesn't clobber R1-R3. Must use r0 for the first operand.
10970(define_insn "load_tp_soft"
10971 [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
10972 (clobber (reg:SI LR_REGNUM))
10973 (clobber (reg:SI IP_REGNUM))
10974 (clobber (reg:CC CC_REGNUM))]
85fc66a7 10975 "TARGET_SOFT_TP && !TARGET_FDPIC"
f655717d 10976 "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
1b7da4ac 10977 [(set_attr "conds" "clob")
10978 (set_attr "type" "branch")]
f655717d 10979)
10980
f41e4452 10981;; tls descriptor call
10982(define_insn "tlscall"
10983 [(set (reg:SI R0_REGNUM)
10984 (unspec:SI [(reg:SI R0_REGNUM)
10985 (match_operand:SI 0 "" "X")
10986 (match_operand 1 "" "")] UNSPEC_TLS))
10987 (clobber (reg:SI R1_REGNUM))
10988 (clobber (reg:SI LR_REGNUM))
10989 (clobber (reg:SI CC_REGNUM))]
10990 "TARGET_GNU2_TLS"
10991 {
10992 targetm.asm_out.internal_label (asm_out_file, "LPIC",
10993 INTVAL (operands[1]));
10994 return "bl\\t%c0(tlscall)";
10995 }
10996 [(set_attr "conds" "clob")
1b7da4ac 10997 (set_attr "length" "4")
10998 (set_attr "type" "branch")]
f41e4452 10999)
11000
1fe0edab 11001;; For thread pointer builtin
11002(define_expand "get_thread_pointersi"
3934ae0e 11003 [(match_operand:SI 0 "s_register_operand")]
1fe0edab 11004 ""
11005 "
11006 {
11007 arm_load_tp (operands[0]);
11008 DONE;
11009 }")
11010
f41e4452 11011;;
11012
aabe09ac 11013;; We only care about the lower 16 bits of the constant
11014;; being inserted into the upper 16 bits of the register.
eca5c984 11015(define_insn "*arm_movtas_ze"
417e5cc5 11016 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r,r")
eca5c984 11017 (const_int 16)
11018 (const_int 16))
11019 (match_operand:SI 1 "const_int_operand" ""))]
60a48e7d 11020 "TARGET_HAVE_MOVT"
417e5cc5 11021 "@
11022 movt%?\t%0, %L1
11023 movt\t%0, %L1"
11024 [(set_attr "arch" "32,v8mb")
11025 (set_attr "predicable" "yes")
1b7da4ac 11026 (set_attr "length" "4")
282b4c75 11027 (set_attr "type" "alu_sreg")]
eca5c984 11028)
11029
c0fc3696 11030(define_insn "*arm_rev"
a486b499 11031 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
11032 (bswap:SI (match_operand:SI 1 "s_register_operand" "l,l,r")))]
11033 "arm_arch6"
11034 "@
11035 rev\t%0, %1
11036 rev%?\t%0, %1
11037 rev%?\t%0, %1"
11038 [(set_attr "arch" "t1,t2,32")
1b7da4ac 11039 (set_attr "length" "2,2,4")
4a510717 11040 (set_attr "predicable" "no,yes,yes")
1b7da4ac 11041 (set_attr "type" "rev")]
ff82f757 11042)
11043
11044(define_expand "arm_legacy_rev"
3934ae0e 11045 [(set (match_operand:SI 2 "s_register_operand")
11046 (xor:SI (rotatert:SI (match_operand:SI 1 "s_register_operand")
ff82f757 11047 (const_int 16))
11048 (match_dup 1)))
11049 (set (match_dup 2)
11050 (lshiftrt:SI (match_dup 2)
11051 (const_int 8)))
3934ae0e 11052 (set (match_operand:SI 3 "s_register_operand")
ff82f757 11053 (rotatert:SI (match_dup 1)
11054 (const_int 8)))
11055 (set (match_dup 2)
11056 (and:SI (match_dup 2)
11057 (const_int -65281)))
3934ae0e 11058 (set (match_operand:SI 0 "s_register_operand")
ff82f757 11059 (xor:SI (match_dup 3)
11060 (match_dup 2)))]
11061 "TARGET_32BIT"
11062 ""
11063)
11064
11065;; Reuse temporaries to keep register pressure down.
11066(define_expand "thumb_legacy_rev"
3934ae0e 11067 [(set (match_operand:SI 2 "s_register_operand")
11068 (ashift:SI (match_operand:SI 1 "s_register_operand")
ff82f757 11069 (const_int 24)))
3934ae0e 11070 (set (match_operand:SI 3 "s_register_operand")
ff82f757 11071 (lshiftrt:SI (match_dup 1)
11072 (const_int 24)))
11073 (set (match_dup 3)
11074 (ior:SI (match_dup 3)
11075 (match_dup 2)))
3934ae0e 11076 (set (match_operand:SI 4 "s_register_operand")
ff82f757 11077 (const_int 16))
3934ae0e 11078 (set (match_operand:SI 5 "s_register_operand")
ff82f757 11079 (rotatert:SI (match_dup 1)
11080 (match_dup 4)))
11081 (set (match_dup 2)
11082 (ashift:SI (match_dup 5)
11083 (const_int 24)))
11084 (set (match_dup 5)
11085 (lshiftrt:SI (match_dup 5)
11086 (const_int 24)))
11087 (set (match_dup 5)
11088 (ior:SI (match_dup 5)
11089 (match_dup 2)))
11090 (set (match_dup 5)
11091 (rotatert:SI (match_dup 5)
11092 (match_dup 4)))
3934ae0e 11093 (set (match_operand:SI 0 "s_register_operand")
ff82f757 11094 (ior:SI (match_dup 5)
11095 (match_dup 3)))]
11096 "TARGET_THUMB"
11097 ""
11098)
11099
62e39b06 11100;; ARM-specific expansion of signed mod by power of 2
11101;; using conditional negate.
11102;; For r0 % n where n is a power of 2 produce:
11103;; rsbs r1, r0, #0
11104;; and r0, r0, #(n - 1)
11105;; and r1, r1, #(n - 1)
11106;; rsbpl r0, r1, #0
11107
11108(define_expand "modsi3"
3934ae0e 11109 [(match_operand:SI 0 "register_operand")
11110 (match_operand:SI 1 "register_operand")
11111 (match_operand:SI 2 "const_int_operand")]
62e39b06 11112 "TARGET_32BIT"
11113 {
11114 HOST_WIDE_INT val = INTVAL (operands[2]);
11115
11116 if (val <= 0
11117 || exact_log2 (val) <= 0)
11118 FAIL;
11119
11120 rtx mask = GEN_INT (val - 1);
11121
11122 /* In the special case of x0 % 2 we can do the even shorter:
11123 cmp r0, #0
11124 and r0, r0, #1
11125 rsblt r0, r0, #0. */
11126
11127 if (val == 2)
11128 {
11129 rtx cc_reg = arm_gen_compare_reg (LT,
11130 operands[1], const0_rtx, NULL_RTX);
11131 rtx cond = gen_rtx_LT (SImode, cc_reg, const0_rtx);
11132 rtx masked = gen_reg_rtx (SImode);
11133
11134 emit_insn (gen_andsi3 (masked, operands[1], mask));
11135 emit_move_insn (operands[0],
11136 gen_rtx_IF_THEN_ELSE (SImode, cond,
11137 gen_rtx_NEG (SImode,
11138 masked),
11139 masked));
11140 DONE;
11141 }
11142
11143 rtx neg_op = gen_reg_rtx (SImode);
11144 rtx_insn *insn = emit_insn (gen_subsi3_compare0 (neg_op, const0_rtx,
11145 operands[1]));
11146
11147 /* Extract the condition register and mode. */
11148 rtx cmp = XVECEXP (PATTERN (insn), 0, 0);
11149 rtx cc_reg = SET_DEST (cmp);
11150 rtx cond = gen_rtx_GE (SImode, cc_reg, const0_rtx);
11151
11152 emit_insn (gen_andsi3 (operands[0], operands[1], mask));
11153
11154 rtx masked_neg = gen_reg_rtx (SImode);
11155 emit_insn (gen_andsi3 (masked_neg, neg_op, mask));
11156
11157 /* We want a conditional negate here, but emitting COND_EXEC rtxes
11158 during expand does not always work. Do an IF_THEN_ELSE instead. */
11159 emit_move_insn (operands[0],
11160 gen_rtx_IF_THEN_ELSE (SImode, cond,
11161 gen_rtx_NEG (SImode, masked_neg),
11162 operands[0]));
11163
11164
11165 DONE;
11166 }
11167)
11168
ff82f757 11169(define_expand "bswapsi2"
3934ae0e 11170 [(set (match_operand:SI 0 "s_register_operand")
11171 (bswap:SI (match_operand:SI 1 "s_register_operand")))]
8d1af482 11172"TARGET_EITHER && (arm_arch6 || !optimize_size)"
ff82f757 11173"
8d1af482 11174 if (!arm_arch6)
11175 {
11176 rtx op2 = gen_reg_rtx (SImode);
11177 rtx op3 = gen_reg_rtx (SImode);
ff82f757 11178
8d1af482 11179 if (TARGET_THUMB)
11180 {
11181 rtx op4 = gen_reg_rtx (SImode);
11182 rtx op5 = gen_reg_rtx (SImode);
ff82f757 11183
8d1af482 11184 emit_insn (gen_thumb_legacy_rev (operands[0], operands[1],
11185 op2, op3, op4, op5));
11186 }
11187 else
11188 {
11189 emit_insn (gen_arm_legacy_rev (operands[0], operands[1],
11190 op2, op3));
11191 }
ff82f757 11192
8d1af482 11193 DONE;
11194 }
ff82f757 11195 "
11196)
11197
a486b499 11198;; bswap16 patterns: use revsh and rev16 instructions for the signed
11199;; and unsigned variants, respectively. For rev16, expose
11200;; byte-swapping in the lower 16 bits only.
11201(define_insn "*arm_revsh"
11202 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
11203 (sign_extend:SI (bswap:HI (match_operand:HI 1 "s_register_operand" "l,l,r"))))]
11204 "arm_arch6"
11205 "@
11206 revsh\t%0, %1
11207 revsh%?\t%0, %1
11208 revsh%?\t%0, %1"
11209 [(set_attr "arch" "t1,t2,32")
1b7da4ac 11210 (set_attr "length" "2,2,4")
11211 (set_attr "type" "rev")]
a486b499 11212)
11213
11214(define_insn "*arm_rev16"
11215 [(set (match_operand:HI 0 "s_register_operand" "=l,l,r")
11216 (bswap:HI (match_operand:HI 1 "s_register_operand" "l,l,r")))]
11217 "arm_arch6"
11218 "@
11219 rev16\t%0, %1
11220 rev16%?\t%0, %1
11221 rev16%?\t%0, %1"
11222 [(set_attr "arch" "t1,t2,32")
1b7da4ac 11223 (set_attr "length" "2,2,4")
11224 (set_attr "type" "rev")]
09f69e55 11225)
11226
11227;; There are no canonicalisation rules for the position of the lshiftrt, ashift
11228;; operations within an IOR/AND RTX, therefore we have two patterns matching
11229;; each valid permutation.
11230
11231(define_insn "arm_rev16si2"
11232 [(set (match_operand:SI 0 "register_operand" "=l,l,r")
11233 (ior:SI (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "l,l,r")
11234 (const_int 8))
11235 (match_operand:SI 3 "const_int_operand" "n,n,n"))
11236 (and:SI (lshiftrt:SI (match_dup 1)
11237 (const_int 8))
11238 (match_operand:SI 2 "const_int_operand" "n,n,n"))))]
11239 "arm_arch6
11240 && aarch_rev16_shleft_mask_imm_p (operands[3], SImode)
11241 && aarch_rev16_shright_mask_imm_p (operands[2], SImode)"
11242 "rev16\\t%0, %1"
11243 [(set_attr "arch" "t1,t2,32")
11244 (set_attr "length" "2,2,4")
11245 (set_attr "type" "rev")]
11246)
11247
11248(define_insn "arm_rev16si2_alt"
11249 [(set (match_operand:SI 0 "register_operand" "=l,l,r")
11250 (ior:SI (and:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,l,r")
11251 (const_int 8))
11252 (match_operand:SI 2 "const_int_operand" "n,n,n"))
11253 (and:SI (ashift:SI (match_dup 1)
11254 (const_int 8))
11255 (match_operand:SI 3 "const_int_operand" "n,n,n"))))]
11256 "arm_arch6
11257 && aarch_rev16_shleft_mask_imm_p (operands[3], SImode)
11258 && aarch_rev16_shright_mask_imm_p (operands[2], SImode)"
11259 "rev16\\t%0, %1"
11260 [(set_attr "arch" "t1,t2,32")
11261 (set_attr "length" "2,2,4")
11262 (set_attr "type" "rev")]
a486b499 11263)
11264
11265(define_expand "bswaphi2"
3934ae0e 11266 [(set (match_operand:HI 0 "s_register_operand")
11267 (bswap:HI (match_operand:HI 1 "s_register_operand")))]
a486b499 11268"arm_arch6"
11269""
11270)
11271
1653cf17 11272;; Patterns for LDRD/STRD in Thumb2 mode
11273
11274(define_insn "*thumb2_ldrd"
11275 [(set (match_operand:SI 0 "s_register_operand" "=r")
11276 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
11277 (match_operand:SI 2 "ldrd_strd_offset_operand" "Do"))))
11278 (set (match_operand:SI 3 "s_register_operand" "=r")
11279 (mem:SI (plus:SI (match_dup 1)
11280 (match_operand:SI 4 "const_int_operand" ""))))]
11281 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
1653cf17 11282 && ((INTVAL (operands[2]) + 4) == INTVAL (operands[4]))
11283 && (operands_ok_ldrd_strd (operands[0], operands[3],
11284 operands[1], INTVAL (operands[2]),
11285 false, true))"
11286 "ldrd%?\t%0, %3, [%1, %2]"
9f2c2a36 11287 [(set_attr "type" "load_8")
8bdfd6ed 11288 (set_attr "predicable" "yes")])
1653cf17 11289
11290(define_insn "*thumb2_ldrd_base"
11291 [(set (match_operand:SI 0 "s_register_operand" "=r")
11292 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
11293 (set (match_operand:SI 2 "s_register_operand" "=r")
11294 (mem:SI (plus:SI (match_dup 1)
11295 (const_int 4))))]
11296 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
1653cf17 11297 && (operands_ok_ldrd_strd (operands[0], operands[2],
11298 operands[1], 0, false, true))"
11299 "ldrd%?\t%0, %2, [%1]"
9f2c2a36 11300 [(set_attr "type" "load_8")
8bdfd6ed 11301 (set_attr "predicable" "yes")])
1653cf17 11302
11303(define_insn "*thumb2_ldrd_base_neg"
11304 [(set (match_operand:SI 0 "s_register_operand" "=r")
11305 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
11306 (const_int -4))))
11307 (set (match_operand:SI 2 "s_register_operand" "=r")
11308 (mem:SI (match_dup 1)))]
11309 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
1653cf17 11310 && (operands_ok_ldrd_strd (operands[0], operands[2],
11311 operands[1], -4, false, true))"
11312 "ldrd%?\t%0, %2, [%1, #-4]"
9f2c2a36 11313 [(set_attr "type" "load_8")
8bdfd6ed 11314 (set_attr "predicable" "yes")])
1653cf17 11315
11316(define_insn "*thumb2_strd"
11317 [(set (mem:SI (plus:SI (match_operand:SI 0 "s_register_operand" "rk")
11318 (match_operand:SI 1 "ldrd_strd_offset_operand" "Do")))
11319 (match_operand:SI 2 "s_register_operand" "r"))
11320 (set (mem:SI (plus:SI (match_dup 0)
11321 (match_operand:SI 3 "const_int_operand" "")))
11322 (match_operand:SI 4 "s_register_operand" "r"))]
11323 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
1653cf17 11324 && ((INTVAL (operands[1]) + 4) == INTVAL (operands[3]))
11325 && (operands_ok_ldrd_strd (operands[2], operands[4],
11326 operands[0], INTVAL (operands[1]),
11327 false, false))"
11328 "strd%?\t%2, %4, [%0, %1]"
9f2c2a36 11329 [(set_attr "type" "store_8")
8bdfd6ed 11330 (set_attr "predicable" "yes")])
1653cf17 11331
11332(define_insn "*thumb2_strd_base"
11333 [(set (mem:SI (match_operand:SI 0 "s_register_operand" "rk"))
11334 (match_operand:SI 1 "s_register_operand" "r"))
11335 (set (mem:SI (plus:SI (match_dup 0)
11336 (const_int 4)))
11337 (match_operand:SI 2 "s_register_operand" "r"))]
11338 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
1653cf17 11339 && (operands_ok_ldrd_strd (operands[1], operands[2],
11340 operands[0], 0, false, false))"
11341 "strd%?\t%1, %2, [%0]"
9f2c2a36 11342 [(set_attr "type" "store_8")
8bdfd6ed 11343 (set_attr "predicable" "yes")])
1653cf17 11344
11345(define_insn "*thumb2_strd_base_neg"
11346 [(set (mem:SI (plus:SI (match_operand:SI 0 "s_register_operand" "rk")
11347 (const_int -4)))
11348 (match_operand:SI 1 "s_register_operand" "r"))
11349 (set (mem:SI (match_dup 0))
11350 (match_operand:SI 2 "s_register_operand" "r"))]
11351 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
1653cf17 11352 && (operands_ok_ldrd_strd (operands[1], operands[2],
11353 operands[0], -4, false, false))"
11354 "strd%?\t%1, %2, [%0, #-4]"
9f2c2a36 11355 [(set_attr "type" "store_8")
8bdfd6ed 11356 (set_attr "predicable" "yes")])
1653cf17 11357
2a0c73f2 11358;; ARMv8 CRC32 instructions.
8656245d 11359(define_insn "arm_<crc_variant>"
2a0c73f2 11360 [(set (match_operand:SI 0 "s_register_operand" "=r")
11361 (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")
11362 (match_operand:<crc_mode> 2 "s_register_operand" "r")]
11363 CRC))]
11364 "TARGET_CRC32"
11365 "<crc_variant>\\t%0, %1, %2"
11366 [(set_attr "type" "crc")
11367 (set_attr "conds" "unconditional")]
11368)
1653cf17 11369
353cf59a 11370;; Load the load/store double peephole optimizations.
11371(include "ldrdstrd.md")
11372
320ea44d 11373;; Load the load/store multiple patterns
11374(include "ldmstm.md")
426be8c5 11375
11376;; Patterns in ldmstm.md don't cover more than 4 registers. This pattern covers
11377;; large lists without explicit writeback generated for APCS_FRAME epilogue.
3873efff 11378;; The operands are validated through the load_multiple_operation
11379;; match_parallel predicate rather than through constraints so enable it only
11380;; after reload.
426be8c5 11381(define_insn "*load_multiple"
11382 [(match_parallel 0 "load_multiple_operation"
11383 [(set (match_operand:SI 2 "s_register_operand" "=rk")
11384 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
11385 ])]
3873efff 11386 "TARGET_32BIT && reload_completed"
426be8c5 11387 "*
11388 {
11389 arm_output_multireg_pop (operands, /*return_pc=*/false,
11390 /*cond=*/const_true_rtx,
11391 /*reverse=*/false,
11392 /*update=*/false);
11393 return \"\";
11394 }
11395 "
11396 [(set_attr "predicable" "yes")]
11397)
11398
84450ddc 11399(define_expand "copysignsf3"
11400 [(match_operand:SF 0 "register_operand")
11401 (match_operand:SF 1 "register_operand")
11402 (match_operand:SF 2 "register_operand")]
11403 "TARGET_SOFT_FLOAT && arm_arch_thumb2"
11404 "{
11405 emit_move_insn (operands[0], operands[2]);
11406 emit_insn (gen_insv_t2 (simplify_gen_subreg (SImode, operands[0], SFmode, 0),
11407 GEN_INT (31), GEN_INT (0),
11408 simplify_gen_subreg (SImode, operands[1], SFmode, 0)));
11409 DONE;
11410 }"
11411)
11412
11413(define_expand "copysigndf3"
11414 [(match_operand:DF 0 "register_operand")
11415 (match_operand:DF 1 "register_operand")
11416 (match_operand:DF 2 "register_operand")]
11417 "TARGET_SOFT_FLOAT && arm_arch_thumb2"
11418 "{
11419 rtx op0_low = gen_lowpart (SImode, operands[0]);
11420 rtx op0_high = gen_highpart (SImode, operands[0]);
11421 rtx op1_low = gen_lowpart (SImode, operands[1]);
11422 rtx op1_high = gen_highpart (SImode, operands[1]);
11423 rtx op2_high = gen_highpart (SImode, operands[2]);
11424
11425 rtx scratch1 = gen_reg_rtx (SImode);
11426 rtx scratch2 = gen_reg_rtx (SImode);
11427 emit_move_insn (scratch1, op2_high);
11428 emit_move_insn (scratch2, op1_high);
11429
d1f9b275 11430 emit_insn(gen_rtx_SET(scratch1,
84450ddc 11431 gen_rtx_LSHIFTRT (SImode, op2_high, GEN_INT(31))));
11432 emit_insn(gen_insv_t2(scratch2, GEN_INT(1), GEN_INT(31), scratch1));
11433 emit_move_insn (op0_low, op1_low);
11434 emit_move_insn (op0_high, scratch2);
11435
11436 DONE;
11437 }"
11438)
11439
115857ef 11440;; movmisalign patterns for HImode and SImode.
11441(define_expand "movmisalign<mode>"
11442 [(match_operand:HSI 0 "general_operand")
11443 (match_operand:HSI 1 "general_operand")]
11444 "unaligned_access"
11445{
11446 /* This pattern is not permitted to fail during expansion: if both arguments
11447 are non-registers (e.g. memory := constant), force operand 1 into a
11448 register. */
11449 rtx (* gen_unaligned_load)(rtx, rtx);
11450 rtx tmp_dest = operands[0];
11451 if (!s_register_operand (operands[0], <MODE>mode)
11452 && !s_register_operand (operands[1], <MODE>mode))
11453 operands[1] = force_reg (<MODE>mode, operands[1]);
11454
11455 if (<MODE>mode == HImode)
11456 {
11457 gen_unaligned_load = gen_unaligned_loadhiu;
11458 tmp_dest = gen_reg_rtx (SImode);
11459 }
11460 else
11461 gen_unaligned_load = gen_unaligned_loadsi;
11462
11463 if (MEM_P (operands[1]))
11464 {
11465 emit_insn (gen_unaligned_load (tmp_dest, operands[1]));
11466 if (<MODE>mode == HImode)
11467 emit_move_insn (operands[0], gen_lowpart (HImode, tmp_dest));
11468 }
11469 else
11470 emit_insn (gen_unaligned_store<mode> (operands[0], operands[1]));
11471
11472 DONE;
11473})
11474
8656245d 11475(define_insn "arm_<cdp>"
1be6395a 11476 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "n")
11477 (match_operand:SI 1 "immediate_operand" "n")
11478 (match_operand:SI 2 "immediate_operand" "n")
11479 (match_operand:SI 3 "immediate_operand" "n")
11480 (match_operand:SI 4 "immediate_operand" "n")
11481 (match_operand:SI 5 "immediate_operand" "n")] CDPI)]
11482 "arm_coproc_builtin_available (VUNSPEC_<CDP>)"
11483{
11484 arm_const_bounds (operands[0], 0, 16);
11485 arm_const_bounds (operands[1], 0, 16);
11486 arm_const_bounds (operands[2], 0, (1 << 5));
11487 arm_const_bounds (operands[3], 0, (1 << 5));
11488 arm_const_bounds (operands[4], 0, (1 << 5));
11489 arm_const_bounds (operands[5], 0, 8);
11490 return "<cdp>\\tp%c0, %1, CR%c2, CR%c3, CR%c4, %5";
11491}
11492 [(set_attr "length" "4")
11493 (set_attr "type" "coproc")])
11494
638b44bd 11495(define_insn "*ldc"
11496 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "n")
11497 (match_operand:SI 1 "immediate_operand" "n")
11498 (match_operand:SI 2 "memory_operand" "Uz")] LDCI)]
11499 "arm_coproc_builtin_available (VUNSPEC_<LDC>)"
11500{
11501 arm_const_bounds (operands[0], 0, 16);
11502 arm_const_bounds (operands[1], 0, (1 << 5));
11503 return "<ldc>\\tp%c0, CR%c1, %2";
11504}
11505 [(set_attr "length" "4")
11506 (set_attr "type" "coproc")])
11507
11508(define_insn "*stc"
11509 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "n")
11510 (match_operand:SI 1 "immediate_operand" "n")
11511 (match_operand:SI 2 "memory_operand" "=Uz")] STCI)]
11512 "arm_coproc_builtin_available (VUNSPEC_<STC>)"
11513{
11514 arm_const_bounds (operands[0], 0, 16);
11515 arm_const_bounds (operands[1], 0, (1 << 5));
11516 return "<stc>\\tp%c0, CR%c1, %2";
11517}
11518 [(set_attr "length" "4")
11519 (set_attr "type" "coproc")])
11520
8656245d 11521(define_expand "arm_<ldc>"
638b44bd 11522 [(unspec_volatile [(match_operand:SI 0 "immediate_operand")
11523 (match_operand:SI 1 "immediate_operand")
11524 (mem:SI (match_operand:SI 2 "s_register_operand"))] LDCI)]
11525 "arm_coproc_builtin_available (VUNSPEC_<LDC>)")
11526
8656245d 11527(define_expand "arm_<stc>"
638b44bd 11528 [(unspec_volatile [(match_operand:SI 0 "immediate_operand")
11529 (match_operand:SI 1 "immediate_operand")
11530 (mem:SI (match_operand:SI 2 "s_register_operand"))] STCI)]
11531 "arm_coproc_builtin_available (VUNSPEC_<STC>)")
11532
8656245d 11533(define_insn "arm_<mcr>"
415e9b1f 11534 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "n")
11535 (match_operand:SI 1 "immediate_operand" "n")
11536 (match_operand:SI 2 "s_register_operand" "r")
11537 (match_operand:SI 3 "immediate_operand" "n")
11538 (match_operand:SI 4 "immediate_operand" "n")
11539 (match_operand:SI 5 "immediate_operand" "n")] MCRI)
11540 (use (match_dup 2))]
11541 "arm_coproc_builtin_available (VUNSPEC_<MCR>)"
11542{
11543 arm_const_bounds (operands[0], 0, 16);
11544 arm_const_bounds (operands[1], 0, 8);
11545 arm_const_bounds (operands[3], 0, (1 << 5));
11546 arm_const_bounds (operands[4], 0, (1 << 5));
11547 arm_const_bounds (operands[5], 0, 8);
11548 return "<mcr>\\tp%c0, %1, %2, CR%c3, CR%c4, %5";
11549}
11550 [(set_attr "length" "4")
11551 (set_attr "type" "coproc")])
11552
8656245d 11553(define_insn "arm_<mrc>"
415e9b1f 11554 [(set (match_operand:SI 0 "s_register_operand" "=r")
6f8d7784 11555 (unspec_volatile:SI [(match_operand:SI 1 "immediate_operand" "n")
415e9b1f 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")] MRCI))]
11560 "arm_coproc_builtin_available (VUNSPEC_<MRC>)"
11561{
11562 arm_const_bounds (operands[1], 0, 16);
11563 arm_const_bounds (operands[2], 0, 8);
11564 arm_const_bounds (operands[3], 0, (1 << 5));
11565 arm_const_bounds (operands[4], 0, (1 << 5));
11566 arm_const_bounds (operands[5], 0, 8);
11567 return "<mrc>\\tp%c1, %2, %0, CR%c3, CR%c4, %5";
11568}
11569 [(set_attr "length" "4")
11570 (set_attr "type" "coproc")])
11571
8656245d 11572(define_insn "arm_<mcrr>"
cabfd710 11573 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "n")
11574 (match_operand:SI 1 "immediate_operand" "n")
11575 (match_operand:DI 2 "s_register_operand" "r")
11576 (match_operand:SI 3 "immediate_operand" "n")] MCRRI)
11577 (use (match_dup 2))]
11578 "arm_coproc_builtin_available (VUNSPEC_<MCRR>)"
11579{
11580 arm_const_bounds (operands[0], 0, 16);
11581 arm_const_bounds (operands[1], 0, 8);
11582 arm_const_bounds (operands[3], 0, (1 << 5));
11583 return "<mcrr>\\tp%c0, %1, %Q2, %R2, CR%c3";
11584}
11585 [(set_attr "length" "4")
11586 (set_attr "type" "coproc")])
11587
8656245d 11588(define_insn "arm_<mrrc>"
cabfd710 11589 [(set (match_operand:DI 0 "s_register_operand" "=r")
6f8d7784 11590 (unspec_volatile:DI [(match_operand:SI 1 "immediate_operand" "n")
cabfd710 11591 (match_operand:SI 2 "immediate_operand" "n")
11592 (match_operand:SI 3 "immediate_operand" "n")] MRRCI))]
11593 "arm_coproc_builtin_available (VUNSPEC_<MRRC>)"
11594{
11595 arm_const_bounds (operands[1], 0, 16);
11596 arm_const_bounds (operands[2], 0, 8);
11597 arm_const_bounds (operands[3], 0, (1 << 5));
11598 return "<mrrc>\\tp%c1, %2, %Q0, %R0, CR%c3";
11599}
11600 [(set_attr "length" "4")
11601 (set_attr "type" "coproc")])
11602
be626997 11603(define_expand "speculation_barrier"
11604 [(unspec_volatile [(const_int 0)] VUNSPEC_SPECULATION_BARRIER)]
11605 "TARGET_EITHER"
11606 "
a7852b35 11607 /* For thumb1 (except Armv8 derivatives), and for pre-Armv7 we don't
11608 have a usable barrier (and probably don't need one in practice).
11609 But to be safe if such code is run on later architectures, call a
11610 helper function in libgcc that will do the thing for the active
11611 system. */
11612 if (!(arm_arch7 || arm_arch8))
11613 {
11614 arm_emit_speculation_barrier_function ();
11615 DONE;
11616 }
be626997 11617 "
11618)
11619
11620;; Generate a hard speculation barrier when we have not enabled speculation
11621;; tracking.
11622(define_insn "*speculation_barrier_insn"
11623 [(unspec_volatile [(const_int 0)] VUNSPEC_SPECULATION_BARRIER)]
a7852b35 11624 "arm_arch7 || arm_arch8"
be626997 11625 "isb\;dsb\\tsy"
11626 [(set_attr "type" "block")
11627 (set_attr "length" "8")]
11628)
11629
d98a3884 11630;; Vector bits common to IWMMXT and Neon
11631(include "vec-common.md")
755eb2b4 11632;; Load the Intel Wireless Multimedia Extension patterns
11633(include "iwmmxt.md")
a2cd141b 11634;; Load the VFP co-processor patterns
11635(include "vfp.md")
bc360af8 11636;; Thumb-1 patterns
11637(include "thumb1.md")
25f905c2 11638;; Thumb-2 patterns
11639(include "thumb2.md")
d98a3884 11640;; Neon patterns
11641(include "neon.md")
e84fdf6e 11642;; Crypto patterns
11643(include "crypto.md")
06df6b17 11644;; Synchronization Primitives
11645(include "sync.md")
bbbe4599 11646;; Fixed-point patterns
11647(include "arm-fixed.md")