]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/arm/arm.md
[arm] Cleanup dead code - old support for DImode comparisons
[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
473 emit_insn (gen_addsi3_compareC (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
f6c98a9a 491(define_expand "addv<mode>4"
492 [(match_operand:SIDI 0 "register_operand")
493 (match_operand:SIDI 1 "register_operand")
494 (match_operand:SIDI 2 "register_operand")
495 (match_operand 3 "")]
496 "TARGET_32BIT"
497{
498 emit_insn (gen_add<mode>3_compareV (operands[0], operands[1], operands[2]));
499 arm_gen_unlikely_cbranch (NE, CC_Vmode, operands[3]);
500
501 DONE;
502})
503
504(define_expand "uaddv<mode>4"
505 [(match_operand:SIDI 0 "register_operand")
506 (match_operand:SIDI 1 "register_operand")
507 (match_operand:SIDI 2 "register_operand")
508 (match_operand 3 "")]
509 "TARGET_32BIT"
510{
511 emit_insn (gen_add<mode>3_compareC (operands[0], operands[1], operands[2]));
e62551fd 512 arm_gen_unlikely_cbranch (LTU, CC_Cmode, operands[3]);
f6c98a9a 513
514 DONE;
515})
516
87b22bf7 517(define_expand "addsi3"
3934ae0e 518 [(set (match_operand:SI 0 "s_register_operand")
519 (plus:SI (match_operand:SI 1 "s_register_operand")
520 (match_operand:SI 2 "reg_or_int_operand")))]
cffb2a26 521 "TARGET_EITHER"
87b22bf7 522 "
0438d37f 523 if (TARGET_32BIT && CONST_INT_P (operands[2]))
87b22bf7 524 {
96f57e36 525 arm_split_constant (PLUS, SImode, NULL_RTX,
526 INTVAL (operands[2]), operands[0], operands[1],
e1ba4a27 527 optimize && can_create_pseudo_p ());
87b22bf7 528 DONE;
529 }
cffb2a26 530 "
531)
87b22bf7 532
5bd751ff 533; If there is a scratch available, this will be faster than synthesizing the
a0f94409 534; addition.
535(define_peephole2
536 [(match_scratch:SI 3 "r")
372575c7 537 (set (match_operand:SI 0 "arm_general_register_operand" "")
538 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
cffb2a26 539 (match_operand:SI 2 "const_int_operand" "")))]
25f905c2 540 "TARGET_32BIT &&
a0f94409 541 !(const_ok_for_arm (INTVAL (operands[2]))
542 || const_ok_for_arm (-INTVAL (operands[2])))
543 && const_ok_for_arm (~INTVAL (operands[2]))"
544 [(set (match_dup 3) (match_dup 2))
545 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
546 ""
547)
87b22bf7 548
2f02c19f 549;; The r/r/k alternative is required when reloading the address
550;; (plus (reg rN) (reg sp)) into (reg rN). In this case reload will
551;; put the duplicated register first, and not try the commutative version.
a0f94409 552(define_insn_and_split "*arm_addsi3"
fa1f9c9e 553 [(set (match_operand:SI 0 "s_register_operand" "=rk,l,l ,l ,r ,k ,r,k ,r ,k ,r ,k,k,r ,k ,r")
554 (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")
555 (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 556 "TARGET_32BIT"
5565501b 557 "@
c24d855d 558 add%?\\t%0, %0, %2
5565501b 559 add%?\\t%0, %1, %2
a0b3420a 560 add%?\\t%0, %1, %2
7c36fe71 561 add%?\\t%0, %1, %2
562 add%?\\t%0, %1, %2
aaa37ad6 563 add%?\\t%0, %1, %2
2f02c19f 564 add%?\\t%0, %2, %1
fa1f9c9e 565 add%?\\t%0, %1, %2
d5cbae34 566 addw%?\\t%0, %1, %2
567 addw%?\\t%0, %1, %2
aaa37ad6 568 sub%?\\t%0, %1, #%n2
87b22bf7 569 sub%?\\t%0, %1, #%n2
d7757711 570 sub%?\\t%0, %1, #%n2
d5cbae34 571 subw%?\\t%0, %1, #%n2
572 subw%?\\t%0, %1, #%n2
87b22bf7 573 #"
a3ffc315 574 "TARGET_32BIT
0438d37f 575 && CONST_INT_P (operands[2])
d5cbae34 576 && !const_ok_for_op (INTVAL (operands[2]), PLUS)
a3ffc315 577 && (reload_completed || !arm_eliminable_register (operands[1]))"
a0f94409 578 [(clobber (const_int 0))]
579 "
96f57e36 580 arm_split_constant (PLUS, SImode, curr_insn,
581 INTVAL (operands[2]), operands[0],
a0f94409 582 operands[1], 0);
583 DONE;
584 "
fa1f9c9e 585 [(set_attr "length" "2,4,4,4,4,4,4,4,4,4,4,4,4,4,4,16")
d5cbae34 586 (set_attr "predicable" "yes")
fa1f9c9e 587 (set_attr "predicable_short_it" "yes,yes,yes,yes,no,no,no,no,no,no,no,no,no,no,no,no")
588 (set_attr "arch" "t2,t2,t2,t2,*,*,*,a,t2,t2,*,*,a,t2,t2,*")
65f68e55 589 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
d82e788e 590 (const_string "alu_imm")
112eda6f 591 (const_string "alu_sreg")))
65f68e55 592 ]
cffb2a26 593)
594
e62551fd 595(define_insn "adddi3_compareV"
f6c98a9a 596 [(set (reg:CC_V CC_REGNUM)
597 (ne:CC_V
598 (plus:TI
e62551fd 599 (sign_extend:TI (match_operand:DI 1 "s_register_operand" "r"))
600 (sign_extend:TI (match_operand:DI 2 "s_register_operand" "r")))
f6c98a9a 601 (sign_extend:TI (plus:DI (match_dup 1) (match_dup 2)))))
e62551fd 602 (set (match_operand:DI 0 "s_register_operand" "=&r")
f6c98a9a 603 (plus:DI (match_dup 1) (match_dup 2)))]
604 "TARGET_32BIT"
e62551fd 605 "adds\\t%Q0, %Q1, %Q2;adcs\\t%R0, %R1, %R2"
f6c98a9a 606 [(set_attr "conds" "set")
607 (set_attr "length" "8")
608 (set_attr "type" "multiple")]
609)
610
611(define_insn "addsi3_compareV"
612 [(set (reg:CC_V CC_REGNUM)
613 (ne:CC_V
614 (plus:DI
615 (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
616 (sign_extend:DI (match_operand:SI 2 "register_operand" "r")))
617 (sign_extend:DI (plus:SI (match_dup 1) (match_dup 2)))))
618 (set (match_operand:SI 0 "register_operand" "=r")
619 (plus:SI (match_dup 1) (match_dup 2)))]
620 "TARGET_32BIT"
621 "adds%?\\t%0, %1, %2"
622 [(set_attr "conds" "set")
623 (set_attr "type" "alus_sreg")]
624)
625
e62551fd 626(define_insn "adddi3_compareC"
f6c98a9a 627 [(set (reg:CC_C CC_REGNUM)
e62551fd 628 (compare:CC_C
629 (plus:DI
630 (match_operand:DI 1 "register_operand" "r")
631 (match_operand:DI 2 "register_operand" "r"))
632 (match_dup 1)))
f6c98a9a 633 (set (match_operand:DI 0 "register_operand" "=&r")
634 (plus:DI (match_dup 1) (match_dup 2)))]
635 "TARGET_32BIT"
e62551fd 636 "adds\\t%Q0, %Q1, %Q2;adcs\\t%R0, %R1, %R2"
f6c98a9a 637 [(set_attr "conds" "set")
638 (set_attr "length" "8")
639 (set_attr "type" "multiple")]
640)
641
f6c98a9a 642(define_insn "addsi3_compareC"
643 [(set (reg:CC_C CC_REGNUM)
e62551fd 644 (compare:CC_C (plus:SI (match_operand:SI 1 "register_operand" "r")
645 (match_operand:SI 2 "register_operand" "r"))
646 (match_dup 1)))
f6c98a9a 647 (set (match_operand:SI 0 "register_operand" "=r")
648 (plus:SI (match_dup 1) (match_dup 2)))]
649 "TARGET_32BIT"
650 "adds%?\\t%0, %1, %2"
651 [(set_attr "conds" "set")
652 (set_attr "type" "alus_sreg")]
653)
654
90c2bcf0 655(define_insn "addsi3_compare0"
bd5b4116 656 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 657 (compare:CC_NOOV
65f68e55 658 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r,r")
659 (match_operand:SI 2 "arm_add_operand" "I,L,r"))
5565501b 660 (const_int 0)))
65f68e55 661 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9c08d1fa 662 (plus:SI (match_dup 1) (match_dup 2)))]
ec792a7b 663 "TARGET_ARM"
5565501b 664 "@
3ef90e77 665 adds%?\\t%0, %1, %2
666 subs%?\\t%0, %1, #%n2
667 adds%?\\t%0, %1, %2"
65f68e55 668 [(set_attr "conds" "set")
112eda6f 669 (set_attr "type" "alus_imm,alus_imm,alus_sreg")]
cffb2a26 670)
9c08d1fa 671
aea4c774 672(define_insn "*addsi3_compare0_scratch"
bd5b4116 673 [(set (reg:CC_NOOV CC_REGNUM)
aea4c774 674 (compare:CC_NOOV
65f68e55 675 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r, r")
676 (match_operand:SI 1 "arm_add_operand" "I,L, r"))
aea4c774 677 (const_int 0)))]
ec792a7b 678 "TARGET_ARM"
cffb2a26 679 "@
680 cmn%?\\t%0, %1
65f68e55 681 cmp%?\\t%0, #%n1
682 cmn%?\\t%0, %1"
596e5e8f 683 [(set_attr "conds" "set")
65f68e55 684 (set_attr "predicable" "yes")
112eda6f 685 (set_attr "type" "alus_imm,alus_imm,alus_sreg")]
0d66636f 686)
cffb2a26 687
aed179ae 688(define_insn "*compare_negsi_si"
689 [(set (reg:CC_Z CC_REGNUM)
690 (compare:CC_Z
7c36fe71 691 (neg:SI (match_operand:SI 0 "s_register_operand" "l,r"))
692 (match_operand:SI 1 "s_register_operand" "l,r")))]
25f905c2 693 "TARGET_32BIT"
aed179ae 694 "cmn%?\\t%1, %0"
596e5e8f 695 [(set_attr "conds" "set")
7c36fe71 696 (set_attr "predicable" "yes")
697 (set_attr "arch" "t2,*")
698 (set_attr "length" "2,4")
1b7da4ac 699 (set_attr "predicable_short_it" "yes,no")
112eda6f 700 (set_attr "type" "alus_sreg")]
0d66636f 701)
aea4c774 702
7f100343 703;; This is the canonicalization of subsi3_compare when the
203c488f 704;; addend is a constant.
190efb17 705(define_insn "cmpsi2_addneg"
203c488f 706 [(set (reg:CC CC_REGNUM)
707 (compare:CC
708 (match_operand:SI 1 "s_register_operand" "r,r")
7f100343 709 (match_operand:SI 2 "arm_addimm_operand" "I,L")))
203c488f 710 (set (match_operand:SI 0 "s_register_operand" "=r,r")
711 (plus:SI (match_dup 1)
7f100343 712 (match_operand:SI 3 "arm_addimm_operand" "L,I")))]
e3dcfc16 713 "TARGET_32BIT
714 && (INTVAL (operands[2])
715 == trunc_int_for_mode (-INTVAL (operands[3]), SImode))"
716{
7f100343 717 /* For 0 and INT_MIN it is essential that we use subs, as adds will result
718 in different condition codes (like cmn rather than like cmp), so that
719 alternative comes first. Both alternatives can match for any 0x??000000
720 where except for 0 and INT_MIN it doesn't matter what we choose, and also
721 for -1 and 1 with TARGET_THUMB2, in that case prefer instruction with #1
722 as it is shorter. */
723 if (which_alternative == 0 && operands[3] != const1_rtx)
e3dcfc16 724 return "subs%?\\t%0, %1, #%n3";
725 else
726 return "adds%?\\t%0, %1, %3";
727}
1b7da4ac 728 [(set_attr "conds" "set")
112eda6f 729 (set_attr "type" "alus_sreg")]
203c488f 730)
731
732;; Convert the sequence
733;; sub rd, rn, #1
734;; cmn rd, #1 (equivalent to cmp rd, #-1)
735;; bne dest
736;; into
737;; subs rd, rn, #1
738;; bcs dest ((unsigned)rn >= 1)
739;; similarly for the beq variant using bcc.
740;; This is a common looping idiom (while (n--))
741(define_peephole2
372575c7 742 [(set (match_operand:SI 0 "arm_general_register_operand" "")
743 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
203c488f 744 (const_int -1)))
745 (set (match_operand 2 "cc_register" "")
746 (compare (match_dup 0) (const_int -1)))
747 (set (pc)
748 (if_then_else (match_operator 3 "equality_operator"
749 [(match_dup 2) (const_int 0)])
750 (match_operand 4 "" "")
751 (match_operand 5 "" "")))]
25f905c2 752 "TARGET_32BIT && peep2_reg_dead_p (3, operands[2])"
203c488f 753 [(parallel[
754 (set (match_dup 2)
755 (compare:CC
756 (match_dup 1) (const_int 1)))
757 (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
758 (set (pc)
759 (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
760 (match_dup 4)
761 (match_dup 5)))]
762 "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
763 operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
764 ? GEU : LTU),
765 VOIDmode,
766 operands[2], const0_rtx);"
767)
768
ebcc79bc 769;; The next four insns work because they compare the result with one of
770;; the operands, and we know that the use of the condition code is
771;; either GEU or LTU, so we can use the carry flag from the addition
772;; instead of doing the compare a second time.
773(define_insn "*addsi3_compare_op1"
bd5b4116 774 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 775 (compare:CC_C
4fe655e9 776 (plus:SI (match_operand:SI 1 "s_register_operand" "l,0,l,0,r,r,r")
777 (match_operand:SI 2 "arm_add_operand" "lPd,Py,lPx,Pw,I,L,r"))
ebcc79bc 778 (match_dup 1)))
4fe655e9 779 (set (match_operand:SI 0 "s_register_operand" "=l,l,l,l,r,r,r")
ebcc79bc 780 (plus:SI (match_dup 1) (match_dup 2)))]
25f905c2 781 "TARGET_32BIT"
ebcc79bc 782 "@
4fe655e9 783 adds%?\\t%0, %1, %2
784 adds%?\\t%0, %0, %2
785 subs%?\\t%0, %1, #%n2
786 subs%?\\t%0, %0, #%n2
3ef90e77 787 adds%?\\t%0, %1, %2
788 subs%?\\t%0, %1, #%n2
789 adds%?\\t%0, %1, %2"
65f68e55 790 [(set_attr "conds" "set")
4fe655e9 791 (set_attr "arch" "t2,t2,t2,t2,*,*,*")
792 (set_attr "length" "2,2,2,2,4,4,4")
793 (set_attr "type"
794 "alus_sreg,alus_imm,alus_sreg,alus_imm,alus_imm,alus_imm,alus_sreg")]
0d66636f 795)
ebcc79bc 796
797(define_insn "*addsi3_compare_op2"
bd5b4116 798 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 799 (compare:CC_C
4fe655e9 800 (plus:SI (match_operand:SI 1 "s_register_operand" "l,0,l,0,r,r,r")
801 (match_operand:SI 2 "arm_add_operand" "lPd,Py,lPx,Pw,I,L,r"))
ebcc79bc 802 (match_dup 2)))
4fe655e9 803 (set (match_operand:SI 0 "s_register_operand" "=l,l,l,l,r,r,r")
9c08d1fa 804 (plus:SI (match_dup 1) (match_dup 2)))]
25f905c2 805 "TARGET_32BIT"
5565501b 806 "@
4fe655e9 807 adds%?\\t%0, %1, %2
808 adds%?\\t%0, %0, %2
809 subs%?\\t%0, %1, #%n2
810 subs%?\\t%0, %0, #%n2
3ef90e77 811 adds%?\\t%0, %1, %2
38128b57 812 subs%?\\t%0, %1, #%n2
813 adds%?\\t%0, %1, %2"
65f68e55 814 [(set_attr "conds" "set")
4fe655e9 815 (set_attr "arch" "t2,t2,t2,t2,*,*,*")
816 (set_attr "length" "2,2,2,2,4,4,4")
817 (set_attr "type"
818 "alus_sreg,alus_imm,alus_sreg,alus_imm,alus_imm,alus_imm,alus_sreg")]
0d66636f 819)
9c08d1fa 820
ebcc79bc 821(define_insn "*compare_addsi2_op0"
bd5b4116 822 [(set (reg:CC_C CC_REGNUM)
7c36fe71 823 (compare:CC_C
824 (plus:SI (match_operand:SI 0 "s_register_operand" "l,l,r,r,r")
825 (match_operand:SI 1 "arm_add_operand" "Pv,l,I,L,r"))
826 (match_dup 0)))]
25f905c2 827 "TARGET_32BIT"
ebcc79bc 828 "@
7c36fe71 829 cmp%?\\t%0, #%n1
830 cmn%?\\t%0, %1
ebcc79bc 831 cmn%?\\t%0, %1
65f68e55 832 cmp%?\\t%0, #%n1
833 cmn%?\\t%0, %1"
596e5e8f 834 [(set_attr "conds" "set")
65f68e55 835 (set_attr "predicable" "yes")
7c36fe71 836 (set_attr "arch" "t2,t2,*,*,*")
837 (set_attr "predicable_short_it" "yes,yes,no,no,no")
838 (set_attr "length" "2,2,4,4,4")
112eda6f 839 (set_attr "type" "alus_imm,alus_sreg,alus_imm,alus_imm,alus_sreg")]
0d66636f 840)
ebcc79bc 841
842(define_insn "*compare_addsi2_op1"
bd5b4116 843 [(set (reg:CC_C CC_REGNUM)
7c36fe71 844 (compare:CC_C
845 (plus:SI (match_operand:SI 0 "s_register_operand" "l,l,r,r,r")
846 (match_operand:SI 1 "arm_add_operand" "Pv,l,I,L,r"))
847 (match_dup 1)))]
25f905c2 848 "TARGET_32BIT"
ebcc79bc 849 "@
7c36fe71 850 cmp%?\\t%0, #%n1
851 cmn%?\\t%0, %1
ebcc79bc 852 cmn%?\\t%0, %1
65f68e55 853 cmp%?\\t%0, #%n1
854 cmn%?\\t%0, %1"
596e5e8f 855 [(set_attr "conds" "set")
65f68e55 856 (set_attr "predicable" "yes")
7c36fe71 857 (set_attr "arch" "t2,t2,*,*,*")
858 (set_attr "predicable_short_it" "yes,yes,no,no,no")
859 (set_attr "length" "2,2,4,4,4")
112eda6f 860 (set_attr "type" "alus_imm,alus_sreg,alus_imm,alus_imm,alus_sreg")]
7c36fe71 861 )
ebcc79bc 862
40155e19 863(define_insn "addsi3_carryin"
7c36fe71 864 [(set (match_operand:SI 0 "s_register_operand" "=l,r,r")
865 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%l,r,r")
866 (match_operand:SI 2 "arm_not_operand" "0,rI,K"))
40155e19 867 (match_operand:SI 3 "arm_carry_operation" "")))]
25f905c2 868 "TARGET_32BIT"
10e5ccd5 869 "@
a0b3420a 870 adc%?\\t%0, %1, %2
10e5ccd5 871 adc%?\\t%0, %1, %2
872 sbc%?\\t%0, %1, #%B2"
a7de272d 873 [(set_attr "conds" "use")
7c36fe71 874 (set_attr "predicable" "yes")
875 (set_attr "arch" "t2,*,*")
876 (set_attr "length" "4")
1b7da4ac 877 (set_attr "predicable_short_it" "yes,no,no")
878 (set_attr "type" "adc_reg,adc_reg,adc_imm")]
cffb2a26 879)
ebcc79bc 880
6cc8c27c 881;; Canonicalization of the above when the immediate is zero.
40155e19 882(define_insn "add0si3_carryin"
6cc8c27c 883 [(set (match_operand:SI 0 "s_register_operand" "=r")
40155e19 884 (plus:SI (match_operand:SI 2 "arm_carry_operation" "")
6cc8c27c 885 (match_operand:SI 1 "arm_not_operand" "r")))]
886 "TARGET_32BIT"
887 "adc%?\\t%0, %1, #0"
888 [(set_attr "conds" "use")
889 (set_attr "predicable" "yes")
890 (set_attr "length" "4")
891 (set_attr "type" "adc_imm")]
892)
893
40155e19 894(define_insn "*addsi3_carryin_alt2"
7c36fe71 895 [(set (match_operand:SI 0 "s_register_operand" "=l,r,r")
40155e19 896 (plus:SI (plus:SI (match_operand:SI 3 "arm_carry_operation" "")
7c36fe71 897 (match_operand:SI 1 "s_register_operand" "%l,r,r"))
3f095d09 898 (match_operand:SI 2 "arm_not_operand" "l,rI,K")))]
25f905c2 899 "TARGET_32BIT"
10e5ccd5 900 "@
a0b3420a 901 adc%?\\t%0, %1, %2
10e5ccd5 902 adc%?\\t%0, %1, %2
903 sbc%?\\t%0, %1, #%B2"
a7de272d 904 [(set_attr "conds" "use")
7c36fe71 905 (set_attr "predicable" "yes")
906 (set_attr "arch" "t2,*,*")
907 (set_attr "length" "4")
1b7da4ac 908 (set_attr "predicable_short_it" "yes,no,no")
909 (set_attr "type" "adc_reg,adc_reg,adc_imm")]
0d66636f 910)
ebcc79bc 911
40155e19 912(define_insn "*addsi3_carryin_shift"
913 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
080c0b9a 914 (plus:SI (plus:SI
915 (match_operator:SI 2 "shift_operator"
40155e19 916 [(match_operand:SI 3 "s_register_operand" "r,r")
917 (match_operand:SI 4 "shift_amount_operand" "M,r")])
918 (match_operand:SI 5 "arm_carry_operation" ""))
919 (match_operand:SI 1 "s_register_operand" "r,r")))]
25f905c2 920 "TARGET_32BIT"
080c0b9a 921 "adc%?\\t%0, %1, %3%S2"
922 [(set_attr "conds" "use")
40155e19 923 (set_attr "arch" "32,a")
924 (set_attr "shift" "3")
a7de272d 925 (set_attr "predicable" "yes")
080c0b9a 926 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
d82e788e 927 (const_string "alu_shift_imm")
928 (const_string "alu_shift_reg")))]
cffb2a26 929)
ebcc79bc 930
40155e19 931(define_insn "*addsi3_carryin_clobercc"
922b6913 932 [(set (match_operand:SI 0 "s_register_operand" "=r")
933 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%r")
934 (match_operand:SI 2 "arm_rhs_operand" "rI"))
40155e19 935 (match_operand:SI 3 "arm_carry_operation" "")))
922b6913 936 (clobber (reg:CC CC_REGNUM))]
937 "TARGET_32BIT"
3ef90e77 938 "adcs%?\\t%0, %1, %2"
1b7da4ac 939 [(set_attr "conds" "set")
940 (set_attr "type" "adcs_reg")]
922b6913 941)
942
f6c98a9a 943(define_expand "subv<mode>4"
944 [(match_operand:SIDI 0 "register_operand")
945 (match_operand:SIDI 1 "register_operand")
946 (match_operand:SIDI 2 "register_operand")
947 (match_operand 3 "")]
948 "TARGET_32BIT"
949{
950 emit_insn (gen_sub<mode>3_compare1 (operands[0], operands[1], operands[2]));
951 arm_gen_unlikely_cbranch (NE, CC_Vmode, operands[3]);
952
953 DONE;
954})
955
956(define_expand "usubv<mode>4"
957 [(match_operand:SIDI 0 "register_operand")
958 (match_operand:SIDI 1 "register_operand")
959 (match_operand:SIDI 2 "register_operand")
960 (match_operand 3 "")]
961 "TARGET_32BIT"
962{
963 emit_insn (gen_sub<mode>3_compare1 (operands[0], operands[1], operands[2]));
964 arm_gen_unlikely_cbranch (LTU, CCmode, operands[3]);
965
966 DONE;
967})
968
e62551fd 969(define_insn "subdi3_compare1"
f6c98a9a 970 [(set (reg:CC CC_REGNUM)
971 (compare:CC
e62551fd 972 (match_operand:DI 1 "s_register_operand" "r")
973 (match_operand:DI 2 "s_register_operand" "r")))
974 (set (match_operand:DI 0 "s_register_operand" "=&r")
f6c98a9a 975 (minus:DI (match_dup 1) (match_dup 2)))]
976 "TARGET_32BIT"
e62551fd 977 "subs\\t%Q0, %Q1, %Q2;sbcs\\t%R0, %R1, %R2"
f6c98a9a 978 [(set_attr "conds" "set")
979 (set_attr "length" "8")
980 (set_attr "type" "multiple")]
981)
982
983(define_insn "subsi3_compare1"
984 [(set (reg:CC CC_REGNUM)
985 (compare:CC
986 (match_operand:SI 1 "register_operand" "r")
987 (match_operand:SI 2 "register_operand" "r")))
988 (set (match_operand:SI 0 "register_operand" "=r")
989 (minus:SI (match_dup 1) (match_dup 2)))]
990 "TARGET_32BIT"
991 "subs%?\\t%0, %1, %2"
992 [(set_attr "conds" "set")
993 (set_attr "type" "alus_sreg")]
994)
995
7724f74b 996(define_insn "subsi3_carryin"
d5bf2b53 997 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
998 (minus:SI (minus:SI (match_operand:SI 1 "reg_or_int_operand" "r,I,Pz")
999 (match_operand:SI 2 "s_register_operand" "r,r,r"))
3b0dcaf2 1000 (match_operand:SI 3 "arm_borrow_operation" "")))]
9154bd82 1001 "TARGET_32BIT"
1002 "@
1003 sbc%?\\t%0, %1, %2
d5bf2b53 1004 rsc%?\\t%0, %2, %1
1005 sbc%?\\t%0, %2, %2, lsl #1"
9154bd82 1006 [(set_attr "conds" "use")
d5bf2b53 1007 (set_attr "arch" "*,a,t2")
7c36fe71 1008 (set_attr "predicable" "yes")
d5bf2b53 1009 (set_attr "type" "adc_reg,adc_imm,alu_shift_imm")]
9154bd82 1010)
1011
060a96ad 1012(define_insn "cmpsi3_carryin_<CC_EXTEND>out"
1013 [(set (reg:<CC_EXTEND> CC_REGNUM)
1014 (compare:<CC_EXTEND>
1015 (SE:DI (match_operand:SI 1 "s_register_operand" "0,r"))
1016 (plus:DI (match_operand:DI 3 "arm_borrow_operation" "")
1017 (SE:DI (match_operand:SI 2 "s_register_operand" "l,r")))))
1018 (clobber (match_scratch:SI 0 "=l,r"))]
1019 "TARGET_32BIT"
1020 "sbcs\\t%0, %1, %2"
1021 [(set_attr "conds" "set")
1022 (set_attr "arch" "t2,*")
1023 (set_attr "length" "2,4")
1024 (set_attr "type" "adc_reg")]
1025)
1026
1027;; Similar to the above, but handling a constant which has a different
1028;; canonicalization.
1029(define_insn "cmpsi3_imm_carryin_<CC_EXTEND>out"
1030 [(set (reg:<CC_EXTEND> CC_REGNUM)
1031 (compare:<CC_EXTEND>
1032 (SE:DI (match_operand:SI 1 "s_register_operand" "r,r"))
1033 (plus:DI (match_operand:DI 3 "arm_borrow_operation" "")
1034 (match_operand:DI 2 "arm_adcimm_operand" "I,K"))))
1035 (clobber (match_scratch:SI 0 "=l,r"))]
1036 "TARGET_32BIT"
1037 "@
1038 sbcs\\t%0, %1, %2
1039 adcs\\t%0, %1, #%B2"
1040 [(set_attr "conds" "set")
1041 (set_attr "type" "adc_imm")]
1042)
1043
1044;; Further canonicalization when the constant is zero.
1045(define_insn "cmpsi3_0_carryin_<CC_EXTEND>out"
1046 [(set (reg:<CC_EXTEND> CC_REGNUM)
1047 (compare:<CC_EXTEND>
1048 (SE:DI (match_operand:SI 1 "s_register_operand" "r,r"))
1049 (match_operand:DI 2 "arm_borrow_operation" "")))
1050 (clobber (match_scratch:SI 0 "=l,r"))]
1051 "TARGET_32BIT"
1052 "sbcs\\t%0, %1, #0"
1053 [(set_attr "conds" "set")
1054 (set_attr "type" "adc_imm")]
1055)
1056
9154bd82 1057(define_insn "*subsi3_carryin_const"
1058 [(set (match_operand:SI 0 "s_register_operand" "=r")
3b0dcaf2 1059 (minus:SI (plus:SI
1060 (match_operand:SI 1 "s_register_operand" "r")
1061 (match_operand:SI 2 "arm_neg_immediate_operand" "L"))
1062 (match_operand:SI 3 "arm_borrow_operation" "")))]
9154bd82 1063 "TARGET_32BIT"
16a3cf9c 1064 "sbc\\t%0, %1, #%n2"
1065 [(set_attr "conds" "use")
1066 (set_attr "type" "adc_imm")]
1067)
1068
1069(define_insn "*subsi3_carryin_const0"
1070 [(set (match_operand:SI 0 "s_register_operand" "=r")
3b0dcaf2 1071 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
1072 (match_operand:SI 2 "arm_borrow_operation" "")))]
16a3cf9c 1073 "TARGET_32BIT"
1074 "sbc\\t%0, %1, #0"
1b7da4ac 1075 [(set_attr "conds" "use")
1076 (set_attr "type" "adc_imm")]
9154bd82 1077)
1078
9154bd82 1079(define_insn "*subsi3_carryin_shift"
1080 [(set (match_operand:SI 0 "s_register_operand" "=r")
1081 (minus:SI (minus:SI
3b0dcaf2 1082 (match_operand:SI 1 "s_register_operand" "r")
1083 (match_operator:SI 2 "shift_operator"
1084 [(match_operand:SI 3 "s_register_operand" "r")
1085 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
1086 (match_operand:SI 5 "arm_borrow_operation" "")))]
9154bd82 1087 "TARGET_32BIT"
1088 "sbc%?\\t%0, %1, %3%S2"
1089 [(set_attr "conds" "use")
1090 (set_attr "predicable" "yes")
1091 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
3b0dcaf2 1092 (const_string "alu_shift_imm")
1093 (const_string "alu_shift_reg")))]
9154bd82 1094)
1095
263f9e4d 1096(define_insn "*subsi3_carryin_shift_alt"
1097 [(set (match_operand:SI 0 "s_register_operand" "=r")
1098 (minus:SI (minus:SI
1099 (match_operand:SI 1 "s_register_operand" "r")
1100 (match_operand:SI 5 "arm_borrow_operation" ""))
1101 (match_operator:SI 2 "shift_operator"
1102 [(match_operand:SI 3 "s_register_operand" "r")
1103 (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
1104 "TARGET_32BIT"
1105 "sbc%?\\t%0, %1, %3%S2"
1106 [(set_attr "conds" "use")
1107 (set_attr "predicable" "yes")
1108 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
1109 (const_string "alu_shift_imm")
1110 (const_string "alu_shift_reg")))]
1111)
1112
9154bd82 1113(define_insn "*rsbsi3_carryin_shift"
1114 [(set (match_operand:SI 0 "s_register_operand" "=r")
1115 (minus:SI (minus:SI
3b0dcaf2 1116 (match_operator:SI 2 "shift_operator"
1117 [(match_operand:SI 3 "s_register_operand" "r")
1118 (match_operand:SI 4 "reg_or_int_operand" "rM")])
9154bd82 1119 (match_operand:SI 1 "s_register_operand" "r"))
3b0dcaf2 1120 (match_operand:SI 5 "arm_borrow_operation" "")))]
9154bd82 1121 "TARGET_ARM"
1122 "rsc%?\\t%0, %1, %3%S2"
1123 [(set_attr "conds" "use")
1124 (set_attr "predicable" "yes")
1125 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
d82e788e 1126 (const_string "alu_shift_imm")
1127 (const_string "alu_shift_reg")))]
9154bd82 1128)
1129
263f9e4d 1130(define_insn "*rsbsi3_carryin_shift_alt"
1131 [(set (match_operand:SI 0 "s_register_operand" "=r")
1132 (minus:SI (minus:SI
1133 (match_operator:SI 2 "shift_operator"
1134 [(match_operand:SI 3 "s_register_operand" "r")
1135 (match_operand:SI 4 "reg_or_int_operand" "rM")])
1136 (match_operand:SI 5 "arm_borrow_operation" ""))
1137 (match_operand:SI 1 "s_register_operand" "r")))]
1138 "TARGET_ARM"
1139 "rsc%?\\t%0, %1, %3%S2"
1140 [(set_attr "conds" "use")
1141 (set_attr "predicable" "yes")
1142 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
1143 (const_string "alu_shift_imm")
1144 (const_string "alu_shift_reg")))]
1145)
1146
d795fb69 1147; transform ((x << y) - 1) to ~(~(x-1) << y) Where X is a constant.
1148(define_split
1149 [(set (match_operand:SI 0 "s_register_operand" "")
1150 (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
1151 (match_operand:SI 2 "s_register_operand" ""))
1152 (const_int -1)))
1153 (clobber (match_operand:SI 3 "s_register_operand" ""))]
25f905c2 1154 "TARGET_32BIT"
d795fb69 1155 [(set (match_dup 3) (match_dup 1))
1156 (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
1157 "
1158 operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
1159")
1160
604f3a0a 1161(define_expand "addsf3"
3934ae0e 1162 [(set (match_operand:SF 0 "s_register_operand")
1163 (plus:SF (match_operand:SF 1 "s_register_operand")
1164 (match_operand:SF 2 "s_register_operand")))]
25f905c2 1165 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1166 "
604f3a0a 1167")
1168
604f3a0a 1169(define_expand "adddf3"
3934ae0e 1170 [(set (match_operand:DF 0 "s_register_operand")
1171 (plus:DF (match_operand:DF 1 "s_register_operand")
1172 (match_operand:DF 2 "s_register_operand")))]
a50d7267 1173 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 1174 "
604f3a0a 1175")
1176
cffb2a26 1177(define_expand "subdi3"
1178 [(parallel
3934ae0e 1179 [(set (match_operand:DI 0 "s_register_operand")
7724f74b 1180 (minus:DI (match_operand:DI 1 "reg_or_int_operand")
e62551fd 1181 (match_operand:DI 2 "s_register_operand")))
bd5b4116 1182 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 1183 "TARGET_EITHER"
1184 "
7724f74b 1185 if (TARGET_THUMB1)
1186 {
1187 if (!REG_P (operands[1]))
1188 operands[1] = force_reg (DImode, operands[1]);
1189 }
1190 else
1191 {
1192 rtx lo_result, hi_result, lo_dest, hi_dest;
1193 rtx lo_op1, hi_op1, lo_op2, hi_op2;
1194 rtx condition;
1195
1196 /* Since operands[1] may be an integer, pass it second, so that
1197 any necessary simplifications will be done on the decomposed
1198 constant. */
1199 arm_decompose_di_binop (operands[2], operands[1], &lo_op2, &hi_op2,
1200 &lo_op1, &hi_op1);
1201 lo_result = lo_dest = gen_lowpart (SImode, operands[0]);
1202 hi_result = hi_dest = gen_highpart (SImode, operands[0]);
1203
1204 if (!arm_rhs_operand (lo_op1, SImode))
1205 lo_op1 = force_reg (SImode, lo_op1);
1206
1207 if ((TARGET_THUMB2 && ! s_register_operand (hi_op1, SImode))
1208 || !arm_rhs_operand (hi_op1, SImode))
1209 hi_op1 = force_reg (SImode, hi_op1);
1210
1211 rtx cc_reg;
1212 if (lo_op1 == const0_rtx)
1213 {
1214 cc_reg = gen_rtx_REG (CC_RSBmode, CC_REGNUM);
1215 emit_insn (gen_negsi2_0compare (lo_dest, lo_op2));
1216 }
1217 else if (CONST_INT_P (lo_op1))
1218 {
1219 cc_reg = gen_rtx_REG (CC_RSBmode, CC_REGNUM);
1220 emit_insn (gen_rsb_imm_compare (lo_dest, lo_op1, lo_op2,
1221 GEN_INT (~UINTVAL (lo_op1))));
1222 }
1223 else
1224 {
1225 cc_reg = gen_rtx_REG (CCmode, CC_REGNUM);
1226 emit_insn (gen_subsi3_compare (lo_dest, lo_op1, lo_op2));
1227 }
1228
1229 condition = gen_rtx_LTU (SImode, cc_reg, const0_rtx);
1230
1231 if (hi_op1 == const0_rtx)
1232 emit_insn (gen_negsi2_carryin (hi_dest, hi_op2, condition));
1233 else
1234 emit_insn (gen_subsi3_carryin (hi_dest, hi_op1, hi_op2, condition));
1235
1236 if (lo_result != lo_dest)
1237 emit_move_insn (lo_result, lo_dest);
1238
1239 if (hi_result != hi_dest)
1240 emit_move_insn (hi_result, hi_dest);
1241
1242 DONE;
1243 }
1244 "
1245)
cffb2a26 1246
87b22bf7 1247(define_expand "subsi3"
3934ae0e 1248 [(set (match_operand:SI 0 "s_register_operand")
1249 (minus:SI (match_operand:SI 1 "reg_or_int_operand")
1250 (match_operand:SI 2 "s_register_operand")))]
cffb2a26 1251 "TARGET_EITHER"
87b22bf7 1252 "
0438d37f 1253 if (CONST_INT_P (operands[1]))
87b22bf7 1254 {
25f905c2 1255 if (TARGET_32BIT)
cffb2a26 1256 {
17202aa5 1257 if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[1]), MINUS))
1258 operands[1] = force_reg (SImode, operands[1]);
1259 else
1260 {
1261 arm_split_constant (MINUS, SImode, NULL_RTX,
1262 INTVAL (operands[1]), operands[0],
1263 operands[2],
1264 optimize && can_create_pseudo_p ());
1265 DONE;
1266 }
cffb2a26 1267 }
25f905c2 1268 else /* TARGET_THUMB1 */
cffb2a26 1269 operands[1] = force_reg (SImode, operands[1]);
87b22bf7 1270 }
cffb2a26 1271 "
1272)
87b22bf7 1273
25f905c2 1274; ??? Check Thumb-2 split length
a0f94409 1275(define_insn_and_split "*arm_subsi3_insn"
3a44c5a9 1276 [(set (match_operand:SI 0 "s_register_operand" "=l,l ,l ,l ,r,r,r,rk,r")
1277 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "l ,0 ,l ,Pz,I,r,r,k ,?n")
1278 (match_operand:SI 2 "reg_or_int_operand" "l ,Py,Pd,l ,r,I,r,r ,r")))]
25f905c2 1279 "TARGET_32BIT"
e2348bcb 1280 "@
7c36fe71 1281 sub%?\\t%0, %1, %2
1282 sub%?\\t%0, %2
1283 sub%?\\t%0, %1, %2
1284 rsb%?\\t%0, %2, %1
87b22bf7 1285 rsb%?\\t%0, %2, %1
aaa37ad6 1286 sub%?\\t%0, %1, %2
080c0b9a 1287 sub%?\\t%0, %1, %2
65f68e55 1288 sub%?\\t%0, %1, %2
87b22bf7 1289 #"
0438d37f 1290 "&& (CONST_INT_P (operands[1])
91a5e339 1291 && !const_ok_for_arm (INTVAL (operands[1])))"
87b22bf7 1292 [(clobber (const_int 0))]
1293 "
96f57e36 1294 arm_split_constant (MINUS, SImode, curr_insn,
1295 INTVAL (operands[1]), operands[0], operands[2], 0);
87b22bf7 1296 DONE;
cffb2a26 1297 "
7c36fe71 1298 [(set_attr "length" "4,4,4,4,4,4,4,4,16")
1299 (set_attr "arch" "t2,t2,t2,t2,*,*,*,*,*")
65f68e55 1300 (set_attr "predicable" "yes")
7c36fe71 1301 (set_attr "predicable_short_it" "yes,yes,yes,yes,no,no,no,no,no")
112eda6f 1302 (set_attr "type" "alu_sreg,alu_sreg,alu_sreg,alu_sreg,alu_imm,alu_imm,alu_sreg,alu_sreg,multiple")]
a0f94409 1303)
1304
1305(define_peephole2
1306 [(match_scratch:SI 3 "r")
372575c7 1307 (set (match_operand:SI 0 "arm_general_register_operand" "")
a0f94409 1308 (minus:SI (match_operand:SI 1 "const_int_operand" "")
372575c7 1309 (match_operand:SI 2 "arm_general_register_operand" "")))]
25f905c2 1310 "TARGET_32BIT
a0f94409 1311 && !const_ok_for_arm (INTVAL (operands[1]))
1312 && const_ok_for_arm (~INTVAL (operands[1]))"
1313 [(set (match_dup 3) (match_dup 1))
1314 (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1315 ""
cffb2a26 1316)
b11cae9e 1317
62e39b06 1318(define_insn "subsi3_compare0"
bd5b4116 1319 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1320 (compare:CC_NOOV
65f68e55 1321 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,r,I")
1322 (match_operand:SI 2 "arm_rhs_operand" "I,r,r"))
215b30b3 1323 (const_int 0)))
65f68e55 1324 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9c08d1fa 1325 (minus:SI (match_dup 1) (match_dup 2)))]
25f905c2 1326 "TARGET_32BIT"
e2348bcb 1327 "@
3ef90e77 1328 subs%?\\t%0, %1, %2
1329 subs%?\\t%0, %1, %2
1330 rsbs%?\\t%0, %2, %1"
65f68e55 1331 [(set_attr "conds" "set")
112eda6f 1332 (set_attr "type" "alus_imm,alus_sreg,alus_sreg")]
cffb2a26 1333)
9c08d1fa 1334
190efb17 1335(define_insn "subsi3_compare"
080c0b9a 1336 [(set (reg:CC CC_REGNUM)
65f68e55 1337 (compare:CC (match_operand:SI 1 "arm_rhs_operand" "r,r,I")
1338 (match_operand:SI 2 "arm_rhs_operand" "I,r,r")))
1339 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2df9477b 1340 (minus:SI (match_dup 1) (match_dup 2)))]
1341 "TARGET_32BIT"
1342 "@
3ef90e77 1343 subs%?\\t%0, %1, %2
1344 subs%?\\t%0, %1, %2
1345 rsbs%?\\t%0, %2, %1"
65f68e55 1346 [(set_attr "conds" "set")
7724f74b 1347 (set_attr "type" "alus_imm,alus_sreg,alus_imm")]
1348)
1349
1350;; To keep the comparison in canonical form we express it as (~reg cmp ~0)
1351;; rather than (0 cmp reg). This gives the same results for unsigned
1352;; and equality compares which is what we mostly need here.
1353(define_insn "rsb_imm_compare"
1354 [(set (reg:CC_RSB CC_REGNUM)
1355 (compare:CC_RSB (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1356 (match_operand 3 "const_int_operand" "")))
1357 (set (match_operand:SI 0 "s_register_operand" "=r")
1358 (minus:SI (match_operand 1 "arm_immediate_operand" "I")
1359 (match_dup 2)))]
1360 "TARGET_32BIT && ~UINTVAL (operands[1]) == UINTVAL (operands[3])"
1361 "rsbs\\t%0, %2, %1"
1362 [(set_attr "conds" "set")
1363 (set_attr "type" "alus_imm")]
2df9477b 1364)
1365
efaa33f9 1366;; Similarly, but the result is unused.
1367(define_insn "rsb_imm_compare_scratch"
1368 [(set (reg:CC_RSB CC_REGNUM)
1369 (compare:CC_RSB (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1370 (match_operand 1 "arm_not_immediate_operand" "K")))
1371 (clobber (match_scratch:SI 0 "=r"))]
1372 "TARGET_32BIT"
1373 "rsbs\\t%0, %2, #%B1"
1374 [(set_attr "conds" "set")
1375 (set_attr "type" "alus_imm")]
1376)
1377
1378;; Compare the sum of a value plus a carry against a constant. Uses
1379;; RSC, so the result is swapped. Only available on Arm
1380(define_insn "rscsi3_<CC_EXTEND>out_scratch"
1381 [(set (reg:CC_SWP CC_REGNUM)
1382 (compare:CC_SWP
1383 (plus:DI (SE:DI (match_operand:SI 2 "s_register_operand" "r"))
1384 (match_operand:DI 3 "arm_borrow_operation" ""))
1385 (match_operand 1 "arm_immediate_operand" "I")))
1386 (clobber (match_scratch:SI 0 "=r"))]
1387 "TARGET_ARM"
1388 "rscs\\t%0, %2, %1"
1389 [(set_attr "conds" "set")
1390 (set_attr "type" "alus_imm")]
1391)
1392
604f3a0a 1393(define_expand "subsf3"
3934ae0e 1394 [(set (match_operand:SF 0 "s_register_operand")
1395 (minus:SF (match_operand:SF 1 "s_register_operand")
1396 (match_operand:SF 2 "s_register_operand")))]
25f905c2 1397 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1398 "
604f3a0a 1399")
1400
604f3a0a 1401(define_expand "subdf3"
3934ae0e 1402 [(set (match_operand:DF 0 "s_register_operand")
1403 (minus:DF (match_operand:DF 1 "s_register_operand")
1404 (match_operand:DF 2 "s_register_operand")))]
a50d7267 1405 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 1406 "
604f3a0a 1407")
1408
b11cae9e 1409\f
1410;; Multiplication insns
1411
4422d91f 1412(define_expand "mulhi3"
3934ae0e 1413 [(set (match_operand:HI 0 "s_register_operand")
1414 (mult:HI (match_operand:HI 1 "s_register_operand")
1415 (match_operand:HI 2 "s_register_operand")))]
4422d91f 1416 "TARGET_DSP_MULTIPLY"
1417 "
1418 {
1419 rtx result = gen_reg_rtx (SImode);
1420 emit_insn (gen_mulhisi3 (result, operands[1], operands[2]));
1421 emit_move_insn (operands[0], gen_lowpart (HImode, result));
1422 DONE;
1423 }"
1424)
1425
cffb2a26 1426(define_expand "mulsi3"
3934ae0e 1427 [(set (match_operand:SI 0 "s_register_operand")
1428 (mult:SI (match_operand:SI 2 "s_register_operand")
1429 (match_operand:SI 1 "s_register_operand")))]
cffb2a26 1430 "TARGET_EITHER"
1431 ""
1432)
1433
40ac65c8 1434;; Use `&' and then `0' to prevent operands 0 and 2 being the same
1435(define_insn "*mul"
1436 [(set (match_operand:SI 0 "s_register_operand" "=l,r,&r,&r")
1437 (mult:SI (match_operand:SI 2 "s_register_operand" "l,r,r,r")
1438 (match_operand:SI 1 "s_register_operand" "%0,r,0,r")))]
1439 "TARGET_32BIT"
f7fbdd4a 1440 "mul%?\\t%0, %2, %1"
9da0ec36 1441 [(set_attr "type" "mul")
40ac65c8 1442 (set_attr "predicable" "yes")
1443 (set_attr "arch" "t2,v6,nov6,nov6")
1444 (set_attr "length" "4")
1445 (set_attr "predicable_short_it" "yes,no,*,*")]
cffb2a26 1446)
1447
40ac65c8 1448;; MLA and MLS instruction. Use operand 1 for the accumulator to prefer
1449;; reusing the same register.
1450
1451(define_insn "*mla"
1452 [(set (match_operand:SI 0 "s_register_operand" "=r,&r,&r,&r")
1453 (plus:SI
1454 (mult:SI (match_operand:SI 3 "s_register_operand" "r,r,r,r")
1455 (match_operand:SI 2 "s_register_operand" "%r,r,0,r"))
1456 (match_operand:SI 1 "s_register_operand" "r,0,r,r")))]
1457 "TARGET_32BIT"
1458 "mla%?\\t%0, %3, %2, %1"
1459 [(set_attr "type" "mla")
d952d547 1460 (set_attr "predicable" "yes")
40ac65c8 1461 (set_attr "arch" "v6,nov6,nov6,nov6")]
1462)
1463
1464(define_insn "*mls"
1465 [(set (match_operand:SI 0 "s_register_operand" "=r")
1466 (minus:SI
1467 (match_operand:SI 1 "s_register_operand" "r")
1468 (mult:SI (match_operand:SI 3 "s_register_operand" "r")
1469 (match_operand:SI 2 "s_register_operand" "r"))))]
1470 "TARGET_32BIT && arm_arch_thumb2"
1471 "mls%?\\t%0, %3, %2, %1"
1472 [(set_attr "type" "mla")
1473 (set_attr "predicable" "yes")]
58d7d654 1474)
1475
f7fbdd4a 1476(define_insn "*mulsi3_compare0"
bd5b4116 1477 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1478 (compare:CC_NOOV (mult:SI
1479 (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1480 (match_operand:SI 1 "s_register_operand" "%0,r"))
9c08d1fa 1481 (const_int 0)))
1482 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1483 (mult:SI (match_dup 2) (match_dup 1)))]
58d7d654 1484 "TARGET_ARM && !arm_arch6"
3ef90e77 1485 "muls%?\\t%0, %2, %1"
58d7d654 1486 [(set_attr "conds" "set")
9da0ec36 1487 (set_attr "type" "muls")]
58d7d654 1488)
1489
1490(define_insn "*mulsi3_compare0_v6"
1491 [(set (reg:CC_NOOV CC_REGNUM)
1492 (compare:CC_NOOV (mult:SI
1493 (match_operand:SI 2 "s_register_operand" "r")
1494 (match_operand:SI 1 "s_register_operand" "r"))
1495 (const_int 0)))
1496 (set (match_operand:SI 0 "s_register_operand" "=r")
1497 (mult:SI (match_dup 2) (match_dup 1)))]
1498 "TARGET_ARM && arm_arch6 && optimize_size"
3ef90e77 1499 "muls%?\\t%0, %2, %1"
cffb2a26 1500 [(set_attr "conds" "set")
9da0ec36 1501 (set_attr "type" "muls")]
cffb2a26 1502)
9c08d1fa 1503
f7fbdd4a 1504(define_insn "*mulsi_compare0_scratch"
bd5b4116 1505 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1506 (compare:CC_NOOV (mult:SI
1507 (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1508 (match_operand:SI 1 "s_register_operand" "%0,r"))
9c08d1fa 1509 (const_int 0)))
1510 (clobber (match_scratch:SI 0 "=&r,&r"))]
58d7d654 1511 "TARGET_ARM && !arm_arch6"
3ef90e77 1512 "muls%?\\t%0, %2, %1"
58d7d654 1513 [(set_attr "conds" "set")
9da0ec36 1514 (set_attr "type" "muls")]
58d7d654 1515)
1516
1517(define_insn "*mulsi_compare0_scratch_v6"
1518 [(set (reg:CC_NOOV CC_REGNUM)
1519 (compare:CC_NOOV (mult:SI
1520 (match_operand:SI 2 "s_register_operand" "r")
1521 (match_operand:SI 1 "s_register_operand" "r"))
1522 (const_int 0)))
1523 (clobber (match_scratch:SI 0 "=r"))]
1524 "TARGET_ARM && arm_arch6 && optimize_size"
3ef90e77 1525 "muls%?\\t%0, %2, %1"
cffb2a26 1526 [(set_attr "conds" "set")
9da0ec36 1527 (set_attr "type" "muls")]
cffb2a26 1528)
9c08d1fa 1529
f7fbdd4a 1530(define_insn "*mulsi3addsi_compare0"
bd5b4116 1531 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1532 (compare:CC_NOOV
1533 (plus:SI (mult:SI
1534 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1535 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1536 (match_operand:SI 3 "s_register_operand" "r,r,0,0"))
215b30b3 1537 (const_int 0)))
9c08d1fa 1538 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1539 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1540 (match_dup 3)))]
58d7d654 1541 "TARGET_ARM && arm_arch6"
3ef90e77 1542 "mlas%?\\t%0, %2, %1, %3"
58d7d654 1543 [(set_attr "conds" "set")
9da0ec36 1544 (set_attr "type" "mlas")]
58d7d654 1545)
1546
1547(define_insn "*mulsi3addsi_compare0_v6"
1548 [(set (reg:CC_NOOV CC_REGNUM)
1549 (compare:CC_NOOV
1550 (plus:SI (mult:SI
1551 (match_operand:SI 2 "s_register_operand" "r")
1552 (match_operand:SI 1 "s_register_operand" "r"))
1553 (match_operand:SI 3 "s_register_operand" "r"))
1554 (const_int 0)))
1555 (set (match_operand:SI 0 "s_register_operand" "=r")
1556 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1557 (match_dup 3)))]
1558 "TARGET_ARM && arm_arch6 && optimize_size"
3ef90e77 1559 "mlas%?\\t%0, %2, %1, %3"
0d66636f 1560 [(set_attr "conds" "set")
9da0ec36 1561 (set_attr "type" "mlas")]
0d66636f 1562)
9c08d1fa 1563
f7fbdd4a 1564(define_insn "*mulsi3addsi_compare0_scratch"
bd5b4116 1565 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1566 (compare:CC_NOOV
1567 (plus:SI (mult:SI
1568 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1569 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
215b30b3 1570 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1571 (const_int 0)))
9c08d1fa 1572 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
58d7d654 1573 "TARGET_ARM && !arm_arch6"
3ef90e77 1574 "mlas%?\\t%0, %2, %1, %3"
58d7d654 1575 [(set_attr "conds" "set")
9da0ec36 1576 (set_attr "type" "mlas")]
58d7d654 1577)
1578
1579(define_insn "*mulsi3addsi_compare0_scratch_v6"
1580 [(set (reg:CC_NOOV CC_REGNUM)
1581 (compare:CC_NOOV
1582 (plus:SI (mult:SI
1583 (match_operand:SI 2 "s_register_operand" "r")
1584 (match_operand:SI 1 "s_register_operand" "r"))
1585 (match_operand:SI 3 "s_register_operand" "r"))
1586 (const_int 0)))
1587 (clobber (match_scratch:SI 0 "=r"))]
1588 "TARGET_ARM && arm_arch6 && optimize_size"
3ef90e77 1589 "mlas%?\\t%0, %2, %1, %3"
cffb2a26 1590 [(set_attr "conds" "set")
9da0ec36 1591 (set_attr "type" "mlas")]
cffb2a26 1592)
f7fbdd4a 1593
957788b0 1594;; 32x32->64 widening multiply.
fa761b10 1595;; The only difference between the v3-5 and v6+ versions is the requirement
1596;; that the output does not overlap with either input.
957788b0 1597
fa761b10 1598(define_expand "<Us>mulsidi3"
3934ae0e 1599 [(set (match_operand:DI 0 "s_register_operand")
957788b0 1600 (mult:DI
fa761b10 1601 (SE:DI (match_operand:SI 1 "s_register_operand"))
1602 (SE:DI (match_operand:SI 2 "s_register_operand"))))]
1930b04c 1603 "TARGET_32BIT"
fa761b10 1604 {
1605 emit_insn (gen_<US>mull (gen_lowpart (SImode, operands[0]),
1606 gen_highpart (SImode, operands[0]),
1607 operands[1], operands[2]));
1608 DONE;
1609 }
0d66636f 1610)
f7fbdd4a 1611
fa761b10 1612(define_insn "<US>mull"
1613 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
1614 (mult:SI
1615 (match_operand:SI 2 "s_register_operand" "%r,r")
1616 (match_operand:SI 3 "s_register_operand" "r,r")))
1617 (set (match_operand:SI 1 "s_register_operand" "=r,&r")
1618 (truncate:SI
1619 (lshiftrt:DI
1620 (mult:DI (SE:DI (match_dup 2)) (SE:DI (match_dup 3)))
1621 (const_int 32))))]
1930b04c 1622 "TARGET_32BIT"
fa761b10 1623 "<US>mull%?\\t%0, %1, %2, %3"
9da0ec36 1624 [(set_attr "type" "umull")
fa761b10 1625 (set_attr "predicable" "yes")
1626 (set_attr "arch" "v6,nov6")]
0d66636f 1627)
b11cae9e 1628
fa761b10 1629(define_expand "<Us>maddsidi4"
3934ae0e 1630 [(set (match_operand:DI 0 "s_register_operand")
5cdca009 1631 (plus:DI
1632 (mult:DI
fa761b10 1633 (SE:DI (match_operand:SI 1 "s_register_operand"))
1634 (SE:DI (match_operand:SI 2 "s_register_operand")))
3934ae0e 1635 (match_operand:DI 3 "s_register_operand")))]
1930b04c 1636 "TARGET_32BIT"
fa761b10 1637 {
1638 emit_insn (gen_<US>mlal (gen_lowpart (SImode, operands[0]),
1639 gen_lowpart (SImode, operands[3]),
1640 gen_highpart (SImode, operands[0]),
1641 gen_highpart (SImode, operands[3]),
1642 operands[1], operands[2]));
1643 DONE;
1644 }
58d7d654 1645)
1646
fa761b10 1647(define_insn "<US>mlal"
1648 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
1649 (plus:SI
1650 (mult:SI
49833aa2 1651 (match_operand:SI 4 "s_register_operand" "%r,r")
1652 (match_operand:SI 5 "s_register_operand" "r,r"))
fa761b10 1653 (match_operand:SI 1 "s_register_operand" "0,0")))
1654 (set (match_operand:SI 2 "s_register_operand" "=r,&r")
1655 (plus:SI
1656 (truncate:SI
1657 (lshiftrt:DI
1658 (plus:DI
1659 (mult:DI (SE:DI (match_dup 4)) (SE:DI (match_dup 5)))
1660 (zero_extend:DI (match_dup 1)))
1661 (const_int 32)))
1662 (match_operand:SI 3 "s_register_operand" "2,2")))]
1663 "TARGET_32BIT"
1664 "<US>mlal%?\\t%0, %2, %4, %5"
9da0ec36 1665 [(set_attr "type" "umlal")
fa761b10 1666 (set_attr "predicable" "yes")
1667 (set_attr "arch" "v6,nov6")]
0d66636f 1668)
82b85d08 1669
662cc42a 1670(define_expand "<US>mulsi3_highpart"
957788b0 1671 [(parallel
3934ae0e 1672 [(set (match_operand:SI 0 "s_register_operand")
957788b0 1673 (truncate:SI
1674 (lshiftrt:DI
1675 (mult:DI
662cc42a 1676 (SE:DI (match_operand:SI 1 "s_register_operand"))
1677 (SE:DI (match_operand:SI 2 "s_register_operand")))
957788b0 1678 (const_int 32))))
1679 (clobber (match_scratch:SI 3 ""))])]
1930b04c 1680 "TARGET_32BIT"
957788b0 1681 ""
1682)
1683
662cc42a 1684(define_insn "*<US>mull_high"
1685 [(set (match_operand:SI 0 "s_register_operand" "=r,&r,&r")
f082f1c4 1686 (truncate:SI
1687 (lshiftrt:DI
215b30b3 1688 (mult:DI
662cc42a 1689 (SE:DI (match_operand:SI 1 "s_register_operand" "%r,0,r"))
1690 (SE:DI (match_operand:SI 2 "s_register_operand" "r,r,r")))
f082f1c4 1691 (const_int 32))))
662cc42a 1692 (clobber (match_scratch:SI 3 "=r,&r,&r"))]
1930b04c 1693 "TARGET_32BIT"
662cc42a 1694 "<US>mull%?\\t%3, %0, %2, %1"
9da0ec36 1695 [(set_attr "type" "umull")
662cc42a 1696 (set_attr "predicable" "yes")
1697 (set_attr "arch" "v6,nov6,nov6")]
cffb2a26 1698)
f082f1c4 1699
331beb1a 1700(define_insn "mulhisi3"
1701 [(set (match_operand:SI 0 "s_register_operand" "=r")
1702 (mult:SI (sign_extend:SI
1703 (match_operand:HI 1 "s_register_operand" "%r"))
1704 (sign_extend:SI
1705 (match_operand:HI 2 "s_register_operand" "r"))))]
25f905c2 1706 "TARGET_DSP_MULTIPLY"
61a2d04c 1707 "smulbb%?\\t%0, %1, %2"
9da0ec36 1708 [(set_attr "type" "smulxy")
fec538d9 1709 (set_attr "predicable" "yes")]
1710)
1711
1712(define_insn "*mulhisi3tb"
1713 [(set (match_operand:SI 0 "s_register_operand" "=r")
1714 (mult:SI (ashiftrt:SI
1715 (match_operand:SI 1 "s_register_operand" "r")
1716 (const_int 16))
1717 (sign_extend:SI
1718 (match_operand:HI 2 "s_register_operand" "r"))))]
25f905c2 1719 "TARGET_DSP_MULTIPLY"
fec538d9 1720 "smultb%?\\t%0, %1, %2"
9da0ec36 1721 [(set_attr "type" "smulxy")
8bdfd6ed 1722 (set_attr "predicable" "yes")]
fec538d9 1723)
1724
1725(define_insn "*mulhisi3bt"
1726 [(set (match_operand:SI 0 "s_register_operand" "=r")
1727 (mult:SI (sign_extend:SI
1728 (match_operand:HI 1 "s_register_operand" "r"))
1729 (ashiftrt:SI
1730 (match_operand:SI 2 "s_register_operand" "r")
1731 (const_int 16))))]
25f905c2 1732 "TARGET_DSP_MULTIPLY"
fec538d9 1733 "smulbt%?\\t%0, %1, %2"
9da0ec36 1734 [(set_attr "type" "smulxy")
8bdfd6ed 1735 (set_attr "predicable" "yes")]
fec538d9 1736)
1737
1738(define_insn "*mulhisi3tt"
1739 [(set (match_operand:SI 0 "s_register_operand" "=r")
1740 (mult:SI (ashiftrt:SI
1741 (match_operand:SI 1 "s_register_operand" "r")
1742 (const_int 16))
1743 (ashiftrt:SI
1744 (match_operand:SI 2 "s_register_operand" "r")
1745 (const_int 16))))]
25f905c2 1746 "TARGET_DSP_MULTIPLY"
fec538d9 1747 "smultt%?\\t%0, %1, %2"
9da0ec36 1748 [(set_attr "type" "smulxy")
8bdfd6ed 1749 (set_attr "predicable" "yes")]
331beb1a 1750)
1751
5cdca009 1752(define_insn "maddhisi4"
331beb1a 1753 [(set (match_operand:SI 0 "s_register_operand" "=r")
cfa6c608 1754 (plus:SI (mult:SI (sign_extend:SI
1755 (match_operand:HI 1 "s_register_operand" "r"))
331beb1a 1756 (sign_extend:SI
cfa6c608 1757 (match_operand:HI 2 "s_register_operand" "r")))
1758 (match_operand:SI 3 "s_register_operand" "r")))]
25f905c2 1759 "TARGET_DSP_MULTIPLY"
5cdca009 1760 "smlabb%?\\t%0, %1, %2, %3"
9da0ec36 1761 [(set_attr "type" "smlaxy")
8bdfd6ed 1762 (set_attr "predicable" "yes")]
331beb1a 1763)
1764
9a92f368 1765;; Note: there is no maddhisi4ibt because this one is canonical form
1766(define_insn "*maddhisi4tb"
1767 [(set (match_operand:SI 0 "s_register_operand" "=r")
1768 (plus:SI (mult:SI (ashiftrt:SI
1769 (match_operand:SI 1 "s_register_operand" "r")
1770 (const_int 16))
1771 (sign_extend:SI
1772 (match_operand:HI 2 "s_register_operand" "r")))
1773 (match_operand:SI 3 "s_register_operand" "r")))]
1774 "TARGET_DSP_MULTIPLY"
1775 "smlatb%?\\t%0, %1, %2, %3"
9da0ec36 1776 [(set_attr "type" "smlaxy")
8bdfd6ed 1777 (set_attr "predicable" "yes")]
9a92f368 1778)
1779
1780(define_insn "*maddhisi4tt"
1781 [(set (match_operand:SI 0 "s_register_operand" "=r")
1782 (plus:SI (mult:SI (ashiftrt:SI
1783 (match_operand:SI 1 "s_register_operand" "r")
1784 (const_int 16))
1785 (ashiftrt:SI
1786 (match_operand:SI 2 "s_register_operand" "r")
1787 (const_int 16)))
1788 (match_operand:SI 3 "s_register_operand" "r")))]
1789 "TARGET_DSP_MULTIPLY"
1790 "smlatt%?\\t%0, %1, %2, %3"
9da0ec36 1791 [(set_attr "type" "smlaxy")
8bdfd6ed 1792 (set_attr "predicable" "yes")]
9a92f368 1793)
1794
aff5fb4d 1795(define_insn "maddhidi4"
331beb1a 1796 [(set (match_operand:DI 0 "s_register_operand" "=r")
1797 (plus:DI
331beb1a 1798 (mult:DI (sign_extend:DI
d952d547 1799 (match_operand:HI 1 "s_register_operand" "r"))
331beb1a 1800 (sign_extend:DI
cfa6c608 1801 (match_operand:HI 2 "s_register_operand" "r")))
1802 (match_operand:DI 3 "s_register_operand" "0")))]
25f905c2 1803 "TARGET_DSP_MULTIPLY"
5cdca009 1804 "smlalbb%?\\t%Q0, %R0, %1, %2"
9da0ec36 1805 [(set_attr "type" "smlalxy")
8bdfd6ed 1806 (set_attr "predicable" "yes")])
331beb1a 1807
9a92f368 1808;; Note: there is no maddhidi4ibt because this one is canonical form
1809(define_insn "*maddhidi4tb"
1810 [(set (match_operand:DI 0 "s_register_operand" "=r")
1811 (plus:DI
1812 (mult:DI (sign_extend:DI
1813 (ashiftrt:SI
1814 (match_operand:SI 1 "s_register_operand" "r")
1815 (const_int 16)))
1816 (sign_extend:DI
1817 (match_operand:HI 2 "s_register_operand" "r")))
1818 (match_operand:DI 3 "s_register_operand" "0")))]
1819 "TARGET_DSP_MULTIPLY"
1820 "smlaltb%?\\t%Q0, %R0, %1, %2"
9da0ec36 1821 [(set_attr "type" "smlalxy")
8bdfd6ed 1822 (set_attr "predicable" "yes")])
9a92f368 1823
1824(define_insn "*maddhidi4tt"
1825 [(set (match_operand:DI 0 "s_register_operand" "=r")
1826 (plus:DI
1827 (mult:DI (sign_extend:DI
1828 (ashiftrt:SI
1829 (match_operand:SI 1 "s_register_operand" "r")
1830 (const_int 16)))
1831 (sign_extend:DI
1832 (ashiftrt:SI
1833 (match_operand:SI 2 "s_register_operand" "r")
1834 (const_int 16))))
1835 (match_operand:DI 3 "s_register_operand" "0")))]
1836 "TARGET_DSP_MULTIPLY"
1837 "smlaltt%?\\t%Q0, %R0, %1, %2"
9da0ec36 1838 [(set_attr "type" "smlalxy")
8bdfd6ed 1839 (set_attr "predicable" "yes")])
9a92f368 1840
604f3a0a 1841(define_expand "mulsf3"
3934ae0e 1842 [(set (match_operand:SF 0 "s_register_operand")
1843 (mult:SF (match_operand:SF 1 "s_register_operand")
1844 (match_operand:SF 2 "s_register_operand")))]
25f905c2 1845 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1846 "
604f3a0a 1847")
1848
604f3a0a 1849(define_expand "muldf3"
3934ae0e 1850 [(set (match_operand:DF 0 "s_register_operand")
1851 (mult:DF (match_operand:DF 1 "s_register_operand")
1852 (match_operand:DF 2 "s_register_operand")))]
a50d7267 1853 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 1854 "
604f3a0a 1855")
b11cae9e 1856\f
1857;; Division insns
1858
7db9af5d 1859(define_expand "divsf3"
3934ae0e 1860 [(set (match_operand:SF 0 "s_register_operand")
1861 (div:SF (match_operand:SF 1 "s_register_operand")
1862 (match_operand:SF 2 "s_register_operand")))]
d7216193 1863 "TARGET_32BIT && TARGET_HARD_FLOAT"
7db9af5d 1864 "")
9c08d1fa 1865
7db9af5d 1866(define_expand "divdf3"
3934ae0e 1867 [(set (match_operand:DF 0 "s_register_operand")
1868 (div:DF (match_operand:DF 1 "s_register_operand")
1869 (match_operand:DF 2 "s_register_operand")))]
994606f8 1870 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
7db9af5d 1871 "")
b11cae9e 1872\f
b11cae9e 1873
9a7e877f 1874; Expand logical operations. The mid-end expander does not split off memory
1875; operands or complex immediates, which leads to fewer LDRD/STRD instructions.
1876; So an explicit expander is needed to generate better code.
1877
c9ad5cc4 1878(define_expand "<LOGICAL:optab>di3"
9a7e877f 1879 [(set (match_operand:DI 0 "s_register_operand")
1880 (LOGICAL:DI (match_operand:DI 1 "s_register_operand")
c9ad5cc4 1881 (match_operand:DI 2 "arm_<optab>di_operand")))]
9a7e877f 1882 "TARGET_32BIT"
1883 {
c9ad5cc4 1884 rtx low = simplify_gen_binary (<CODE>, SImode,
9a7e877f 1885 gen_lowpart (SImode, operands[1]),
1886 gen_lowpart (SImode, operands[2]));
c9ad5cc4 1887 rtx high = simplify_gen_binary (<CODE>, SImode,
9a7e877f 1888 gen_highpart (SImode, operands[1]),
1889 gen_highpart_mode (SImode, DImode,
1890 operands[2]));
1891
1892 emit_insn (gen_rtx_SET (gen_lowpart (SImode, operands[0]), low));
1893 emit_insn (gen_rtx_SET (gen_highpart (SImode, operands[0]), high));
1894 DONE;
1895 }
1896)
1897
1898(define_expand "one_cmpldi2"
1899 [(set (match_operand:DI 0 "s_register_operand")
1900 (not:DI (match_operand:DI 1 "s_register_operand")))]
1901 "TARGET_32BIT"
1902 {
1903 rtx low = simplify_gen_unary (NOT, SImode,
1904 gen_lowpart (SImode, operands[1]),
1905 SImode);
1906 rtx high = simplify_gen_unary (NOT, SImode,
1907 gen_highpart_mode (SImode, DImode,
1908 operands[1]),
1909 SImode);
1910
1911 emit_insn (gen_rtx_SET (gen_lowpart (SImode, operands[0]), low));
1912 emit_insn (gen_rtx_SET (gen_highpart (SImode, operands[0]), high));
1913 DONE;
1914 }
1915)
1916
5eddd275 1917;; Split DImode and, ior, xor operations. Simply perform the logical
f6ebffac 1918;; operation on the upper and lower halves of the registers.
5eddd275 1919;; This is needed for atomic operations in arm_split_atomic_op.
1920;; Avoid splitting IWMMXT instructions.
f6ebffac 1921(define_split
1922 [(set (match_operand:DI 0 "s_register_operand" "")
1923 (match_operator:DI 6 "logical_binary_operator"
1924 [(match_operand:DI 1 "s_register_operand" "")
1925 (match_operand:DI 2 "s_register_operand" "")]))]
25f905c2 1926 "TARGET_32BIT && reload_completed
1927 && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
f6ebffac 1928 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1929 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1930 "
215b30b3 1931 {
1932 operands[3] = gen_highpart (SImode, operands[0]);
1933 operands[0] = gen_lowpart (SImode, operands[0]);
1934 operands[4] = gen_highpart (SImode, operands[1]);
1935 operands[1] = gen_lowpart (SImode, operands[1]);
1936 operands[5] = gen_highpart (SImode, operands[2]);
1937 operands[2] = gen_lowpart (SImode, operands[2]);
1938 }"
1939)
f6ebffac 1940
5eddd275 1941;; Split DImode not (needed for atomic operations in arm_split_atomic_op).
1942;; Unconditionally split since there is no SIMD DImode NOT pattern.
f6ebffac 1943(define_split
5eddd275 1944 [(set (match_operand:DI 0 "s_register_operand")
1945 (not:DI (match_operand:DI 1 "s_register_operand")))]
25f905c2 1946 "TARGET_32BIT"
5eddd275 1947 [(set (match_dup 0) (not:SI (match_dup 1)))
1948 (set (match_dup 2) (not:SI (match_dup 3)))]
a0f94409 1949 "
1950 {
5eddd275 1951 operands[2] = gen_highpart (SImode, operands[0]);
a0f94409 1952 operands[0] = gen_lowpart (SImode, operands[0]);
5eddd275 1953 operands[3] = gen_highpart (SImode, operands[1]);
a0f94409 1954 operands[1] = gen_lowpart (SImode, operands[1]);
1955 }"
cffb2a26 1956)
b11cae9e 1957
87b22bf7 1958(define_expand "andsi3"
3934ae0e 1959 [(set (match_operand:SI 0 "s_register_operand")
1960 (and:SI (match_operand:SI 1 "s_register_operand")
1961 (match_operand:SI 2 "reg_or_int_operand")))]
cffb2a26 1962 "TARGET_EITHER"
87b22bf7 1963 "
25f905c2 1964 if (TARGET_32BIT)
87b22bf7 1965 {
0438d37f 1966 if (CONST_INT_P (operands[2]))
cffb2a26 1967 {
47b5b27b 1968 if (INTVAL (operands[2]) == 255 && arm_arch6)
1969 {
1970 operands[1] = convert_to_mode (QImode, operands[1], 1);
1971 emit_insn (gen_thumb2_zero_extendqisi2_v6 (operands[0],
1972 operands[1]));
17202aa5 1973 DONE;
47b5b27b 1974 }
17202aa5 1975 else if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[2]), AND))
1976 operands[2] = force_reg (SImode, operands[2]);
47b5b27b 1977 else
17202aa5 1978 {
1979 arm_split_constant (AND, SImode, NULL_RTX,
1980 INTVAL (operands[2]), operands[0],
1981 operands[1],
1982 optimize && can_create_pseudo_p ());
615caa51 1983
17202aa5 1984 DONE;
1985 }
cffb2a26 1986 }
87b22bf7 1987 }
25f905c2 1988 else /* TARGET_THUMB1 */
cffb2a26 1989 {
0438d37f 1990 if (!CONST_INT_P (operands[2]))
923ffadb 1991 {
1992 rtx tmp = force_reg (SImode, operands[2]);
1993 if (rtx_equal_p (operands[0], operands[1]))
1994 operands[2] = tmp;
1995 else
1996 {
1997 operands[2] = operands[1];
1998 operands[1] = tmp;
1999 }
2000 }
cffb2a26 2001 else
2002 {
2003 int i;
2004
215b30b3 2005 if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
cffb2a26 2006 {
215b30b3 2007 operands[2] = force_reg (SImode,
2008 GEN_INT (~INTVAL (operands[2])));
cffb2a26 2009
747b7458 2010 emit_insn (gen_thumb1_bicsi3 (operands[0], operands[2], operands[1]));
cffb2a26 2011
2012 DONE;
2013 }
87b22bf7 2014
cffb2a26 2015 for (i = 9; i <= 31; i++)
2016 {
db2faf44 2017 if ((HOST_WIDE_INT_1 << i) - 1 == INTVAL (operands[2]))
cffb2a26 2018 {
2019 emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
2020 const0_rtx));
2021 DONE;
2022 }
db2faf44 2023 else if ((HOST_WIDE_INT_1 << i) - 1
215b30b3 2024 == ~INTVAL (operands[2]))
cffb2a26 2025 {
2026 rtx shift = GEN_INT (i);
2027 rtx reg = gen_reg_rtx (SImode);
2028
2029 emit_insn (gen_lshrsi3 (reg, operands[1], shift));
2030 emit_insn (gen_ashlsi3 (operands[0], reg, shift));
2031
2032 DONE;
2033 }
2034 }
2035
2036 operands[2] = force_reg (SImode, operands[2]);
2037 }
215b30b3 2038 }
2039 "
cffb2a26 2040)
2041
25f905c2 2042; ??? Check split length for Thumb-2
a0f94409 2043(define_insn_and_split "*arm_andsi3_insn"
29e234a3 2044 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r,r,r")
2045 (and:SI (match_operand:SI 1 "s_register_operand" "%r,0,r,r,r")
2046 (match_operand:SI 2 "reg_or_int_operand" "I,l,K,r,?n")))]
25f905c2 2047 "TARGET_32BIT"
5565501b 2048 "@
29e234a3 2049 and%?\\t%0, %1, %2
5565501b 2050 and%?\\t%0, %1, %2
87b22bf7 2051 bic%?\\t%0, %1, #%B2
65f68e55 2052 and%?\\t%0, %1, %2
87b22bf7 2053 #"
25f905c2 2054 "TARGET_32BIT
0438d37f 2055 && CONST_INT_P (operands[2])
a0f94409 2056 && !(const_ok_for_arm (INTVAL (operands[2]))
2057 || const_ok_for_arm (~INTVAL (operands[2])))"
2058 [(clobber (const_int 0))]
2059 "
96f57e36 2060 arm_split_constant (AND, SImode, curr_insn,
2061 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 2062 DONE;
2063 "
29e234a3 2064 [(set_attr "length" "4,4,4,4,16")
65f68e55 2065 (set_attr "predicable" "yes")
29e234a3 2066 (set_attr "predicable_short_it" "no,yes,no,no,no")
d82e788e 2067 (set_attr "type" "logic_imm,logic_imm,logic_reg,logic_reg,logic_imm")]
cffb2a26 2068)
2069
f7fbdd4a 2070(define_insn "*andsi3_compare0"
bd5b4116 2071 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 2072 (compare:CC_NOOV
65f68e55 2073 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
2074 (match_operand:SI 2 "arm_not_operand" "I,K,r"))
5565501b 2075 (const_int 0)))
65f68e55 2076 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9c08d1fa 2077 (and:SI (match_dup 1) (match_dup 2)))]
25f905c2 2078 "TARGET_32BIT"
5565501b 2079 "@
3ef90e77 2080 ands%?\\t%0, %1, %2
2081 bics%?\\t%0, %1, #%B2
2082 ands%?\\t%0, %1, %2"
65f68e55 2083 [(set_attr "conds" "set")
d82e788e 2084 (set_attr "type" "logics_imm,logics_imm,logics_reg")]
cffb2a26 2085)
9c08d1fa 2086
f7fbdd4a 2087(define_insn "*andsi3_compare0_scratch"
bd5b4116 2088 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 2089 (compare:CC_NOOV
65f68e55 2090 (and:SI (match_operand:SI 0 "s_register_operand" "r,r,r")
2091 (match_operand:SI 1 "arm_not_operand" "I,K,r"))
5565501b 2092 (const_int 0)))
65f68e55 2093 (clobber (match_scratch:SI 2 "=X,r,X"))]
25f905c2 2094 "TARGET_32BIT"
5565501b 2095 "@
2096 tst%?\\t%0, %1
3ef90e77 2097 bics%?\\t%2, %0, #%B1
65f68e55 2098 tst%?\\t%0, %1"
2099 [(set_attr "conds" "set")
d82e788e 2100 (set_attr "type" "logics_imm,logics_imm,logics_reg")]
0d66636f 2101)
9c08d1fa 2102
f7fbdd4a 2103(define_insn "*zeroextractsi_compare0_scratch"
bd5b4116 2104 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2105 (compare:CC_NOOV (zero_extract:SI
2106 (match_operand:SI 0 "s_register_operand" "r")
d952d547 2107 (match_operand 1 "const_int_operand" "n")
206ee9a2 2108 (match_operand 2 "const_int_operand" "n"))
9c08d1fa 2109 (const_int 0)))]
25f905c2 2110 "TARGET_32BIT
cffb2a26 2111 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
2112 && INTVAL (operands[1]) > 0
2113 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
2114 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
9c08d1fa 2115 "*
5c49a439 2116 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
2117 << INTVAL (operands[2]));
40dbec34 2118 output_asm_insn (\"tst%?\\t%0, %1\", operands);
e2348bcb 2119 return \"\";
0d66636f 2120 "
596e5e8f 2121 [(set_attr "conds" "set")
65f68e55 2122 (set_attr "predicable" "yes")
d82e788e 2123 (set_attr "type" "logics_imm")]
0d66636f 2124)
9c08d1fa 2125
f4462328 2126(define_insn_and_split "*ne_zeroextractsi"
c4034607 2127 [(set (match_operand:SI 0 "s_register_operand" "=r")
2128 (ne:SI (zero_extract:SI
2129 (match_operand:SI 1 "s_register_operand" "r")
2130 (match_operand:SI 2 "const_int_operand" "n")
2131 (match_operand:SI 3 "const_int_operand" "n"))
3b8c7f7a 2132 (const_int 0)))
2133 (clobber (reg:CC CC_REGNUM))]
25f905c2 2134 "TARGET_32BIT
cffb2a26 2135 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2136 && INTVAL (operands[2]) > 0
2137 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2138 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
f4462328 2139 "#"
25f905c2 2140 "TARGET_32BIT
f4462328 2141 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2142 && INTVAL (operands[2]) > 0
2143 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2144 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
2145 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2146 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2147 (const_int 0)))
2148 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2149 (set (match_dup 0)
2150 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2151 (match_dup 0) (const_int 1)))]
2152 "
2153 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
2154 << INTVAL (operands[3]));
2155 "
2156 [(set_attr "conds" "clob")
25f905c2 2157 (set (attr "length")
2158 (if_then_else (eq_attr "is_thumb" "yes")
2159 (const_int 12)
1b7da4ac 2160 (const_int 8)))
2161 (set_attr "type" "multiple")]
f4462328 2162)
2163
2164(define_insn_and_split "*ne_zeroextractsi_shifted"
2165 [(set (match_operand:SI 0 "s_register_operand" "=r")
2166 (ne:SI (zero_extract:SI
2167 (match_operand:SI 1 "s_register_operand" "r")
2168 (match_operand:SI 2 "const_int_operand" "n")
2169 (const_int 0))
2170 (const_int 0)))
2171 (clobber (reg:CC CC_REGNUM))]
2172 "TARGET_ARM"
2173 "#"
2174 "TARGET_ARM"
2175 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2176 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2177 (const_int 0)))
2178 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2179 (set (match_dup 0)
2180 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2181 (match_dup 0) (const_int 1)))]
2182 "
2183 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
2184 "
2185 [(set_attr "conds" "clob")
1b7da4ac 2186 (set_attr "length" "8")
2187 (set_attr "type" "multiple")]
f4462328 2188)
2189
2190(define_insn_and_split "*ite_ne_zeroextractsi"
2191 [(set (match_operand:SI 0 "s_register_operand" "=r")
2192 (if_then_else:SI (ne (zero_extract:SI
2193 (match_operand:SI 1 "s_register_operand" "r")
2194 (match_operand:SI 2 "const_int_operand" "n")
2195 (match_operand:SI 3 "const_int_operand" "n"))
2196 (const_int 0))
2197 (match_operand:SI 4 "arm_not_operand" "rIK")
2198 (const_int 0)))
2199 (clobber (reg:CC CC_REGNUM))]
2200 "TARGET_ARM
2201 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2202 && INTVAL (operands[2]) > 0
2203 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 2204 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2205 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 2206 "#"
2207 "TARGET_ARM
2208 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2209 && INTVAL (operands[2]) > 0
2210 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 2211 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2212 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 2213 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2214 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2215 (const_int 0)))
2216 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2217 (set (match_dup 0)
2218 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2219 (match_dup 0) (match_dup 4)))]
2220 "
c4034607 2221 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
f4462328 2222 << INTVAL (operands[3]));
2223 "
2224 [(set_attr "conds" "clob")
1b7da4ac 2225 (set_attr "length" "8")
2226 (set_attr "type" "multiple")]
f4462328 2227)
2228
2229(define_insn_and_split "*ite_ne_zeroextractsi_shifted"
2230 [(set (match_operand:SI 0 "s_register_operand" "=r")
2231 (if_then_else:SI (ne (zero_extract:SI
2232 (match_operand:SI 1 "s_register_operand" "r")
2233 (match_operand:SI 2 "const_int_operand" "n")
2234 (const_int 0))
2235 (const_int 0))
2236 (match_operand:SI 3 "arm_not_operand" "rIK")
2237 (const_int 0)))
2238 (clobber (reg:CC CC_REGNUM))]
f8d7bf2f 2239 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 2240 "#"
f8d7bf2f 2241 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 2242 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2243 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2244 (const_int 0)))
2245 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2246 (set (match_dup 0)
2247 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2248 (match_dup 0) (match_dup 3)))]
2249 "
2250 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
0d66636f 2251 "
2252 [(set_attr "conds" "clob")
1b7da4ac 2253 (set_attr "length" "8")
2254 (set_attr "type" "multiple")]
215b30b3 2255)
9c08d1fa 2256
25f905c2 2257;; ??? Use Thumb-2 has bitfield insert/extract instructions.
d7863cfe 2258(define_split
2259 [(set (match_operand:SI 0 "s_register_operand" "")
2260 (match_operator:SI 1 "shiftable_operator"
2261 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2262 (match_operand:SI 3 "const_int_operand" "")
2263 (match_operand:SI 4 "const_int_operand" ""))
2264 (match_operand:SI 5 "s_register_operand" "")]))
2265 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2266 "TARGET_ARM"
2267 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2268 (set (match_dup 0)
2269 (match_op_dup 1
2270 [(lshiftrt:SI (match_dup 6) (match_dup 4))
2271 (match_dup 5)]))]
2272 "{
2273 HOST_WIDE_INT temp = INTVAL (operands[3]);
2274
2275 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2276 operands[4] = GEN_INT (32 - temp);
2277 }"
2278)
2279
d7863cfe 2280(define_split
2281 [(set (match_operand:SI 0 "s_register_operand" "")
2282 (match_operator:SI 1 "shiftable_operator"
2283 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2284 (match_operand:SI 3 "const_int_operand" "")
2285 (match_operand:SI 4 "const_int_operand" ""))
2286 (match_operand:SI 5 "s_register_operand" "")]))
2287 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2288 "TARGET_ARM"
2289 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2290 (set (match_dup 0)
2291 (match_op_dup 1
2292 [(ashiftrt:SI (match_dup 6) (match_dup 4))
2293 (match_dup 5)]))]
2294 "{
2295 HOST_WIDE_INT temp = INTVAL (operands[3]);
2296
2297 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2298 operands[4] = GEN_INT (32 - temp);
2299 }"
2300)
2301
a42059fd 2302;;; ??? This pattern is bogus. If operand3 has bits outside the range
2303;;; represented by the bitfield, then this will produce incorrect results.
2304;;; Somewhere, the value needs to be truncated. On targets like the m68k,
ceb2fe0f 2305;;; which have a real bit-field insert instruction, the truncation happens
2306;;; in the bit-field insert instruction itself. Since arm does not have a
2307;;; bit-field insert instruction, we would have to emit code here to truncate
a42059fd 2308;;; the value before we insert. This loses some of the advantage of having
2309;;; this insv pattern, so this pattern needs to be reevalutated.
2310
8a18b90c 2311(define_expand "insv"
3934ae0e 2312 [(set (zero_extract (match_operand 0 "nonimmediate_operand")
2313 (match_operand 1 "general_operand")
2314 (match_operand 2 "general_operand"))
2315 (match_operand 3 "reg_or_int_operand"))]
8b054d5a 2316 "TARGET_ARM || arm_arch_thumb2"
8a18b90c 2317 "
215b30b3 2318 {
2319 int start_bit = INTVAL (operands[2]);
2320 int width = INTVAL (operands[1]);
db2faf44 2321 HOST_WIDE_INT mask = (HOST_WIDE_INT_1 << width) - 1;
215b30b3 2322 rtx target, subtarget;
2323
8b054d5a 2324 if (arm_arch_thumb2)
2325 {
eb04cafb 2326 if (unaligned_access && MEM_P (operands[0])
2327 && s_register_operand (operands[3], GET_MODE (operands[3]))
2328 && (width == 16 || width == 32) && (start_bit % BITS_PER_UNIT) == 0)
8b054d5a 2329 {
eb04cafb 2330 rtx base_addr;
2331
2332 if (BYTES_BIG_ENDIAN)
2333 start_bit = GET_MODE_BITSIZE (GET_MODE (operands[3])) - width
2334 - start_bit;
8b054d5a 2335
eb04cafb 2336 if (width == 32)
8b054d5a 2337 {
eb04cafb 2338 base_addr = adjust_address (operands[0], SImode,
2339 start_bit / BITS_PER_UNIT);
2340 emit_insn (gen_unaligned_storesi (base_addr, operands[3]));
8b054d5a 2341 }
eb04cafb 2342 else
2343 {
2344 rtx tmp = gen_reg_rtx (HImode);
8b054d5a 2345
eb04cafb 2346 base_addr = adjust_address (operands[0], HImode,
2347 start_bit / BITS_PER_UNIT);
2348 emit_move_insn (tmp, gen_lowpart (HImode, operands[3]));
2349 emit_insn (gen_unaligned_storehi (base_addr, tmp));
2350 }
2351 DONE;
8b054d5a 2352 }
eb04cafb 2353 else if (s_register_operand (operands[0], GET_MODE (operands[0])))
8b054d5a 2354 {
eb04cafb 2355 bool use_bfi = TRUE;
8b054d5a 2356
0438d37f 2357 if (CONST_INT_P (operands[3]))
eb04cafb 2358 {
2359 HOST_WIDE_INT val = INTVAL (operands[3]) & mask;
2360
2361 if (val == 0)
2362 {
2363 emit_insn (gen_insv_zero (operands[0], operands[1],
2364 operands[2]));
2365 DONE;
2366 }
2367
2368 /* See if the set can be done with a single orr instruction. */
2369 if (val == mask && const_ok_for_arm (val << start_bit))
2370 use_bfi = FALSE;
2371 }
2372
2373 if (use_bfi)
2374 {
0438d37f 2375 if (!REG_P (operands[3]))
eb04cafb 2376 operands[3] = force_reg (SImode, operands[3]);
2377
2378 emit_insn (gen_insv_t2 (operands[0], operands[1], operands[2],
2379 operands[3]));
2380 DONE;
2381 }
8b054d5a 2382 }
eb04cafb 2383 else
2384 FAIL;
8b054d5a 2385 }
2386
eb04cafb 2387 if (!s_register_operand (operands[0], GET_MODE (operands[0])))
2388 FAIL;
2389
3f8fde42 2390 target = copy_rtx (operands[0]);
215b30b3 2391 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
2392 subreg as the final target. */
2393 if (GET_CODE (target) == SUBREG)
2394 {
2395 subtarget = gen_reg_rtx (SImode);
2396 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
2397 < GET_MODE_SIZE (SImode))
2398 target = SUBREG_REG (target);
2399 }
2400 else
2401 subtarget = target;
8a18b90c 2402
0438d37f 2403 if (CONST_INT_P (operands[3]))
215b30b3 2404 {
2405 /* Since we are inserting a known constant, we may be able to
2406 reduce the number of bits that we have to clear so that
2407 the mask becomes simple. */
2408 /* ??? This code does not check to see if the new mask is actually
2409 simpler. It may not be. */
2410 rtx op1 = gen_reg_rtx (SImode);
2411 /* ??? Truncate operand3 to fit in the bitfield. See comment before
2412 start of this pattern. */
2413 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
2414 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
2415
c5b3a71b 2416 emit_insn (gen_andsi3 (op1, operands[0],
2417 gen_int_mode (~mask2, SImode)));
215b30b3 2418 emit_insn (gen_iorsi3 (subtarget, op1,
4292ca6b 2419 gen_int_mode (op3_value << start_bit, SImode)));
215b30b3 2420 }
2421 else if (start_bit == 0
2422 && !(const_ok_for_arm (mask)
2423 || const_ok_for_arm (~mask)))
2424 {
2425 /* A Trick, since we are setting the bottom bits in the word,
2426 we can shift operand[3] up, operand[0] down, OR them together
2427 and rotate the result back again. This takes 3 insns, and
5910bb95 2428 the third might be mergeable into another op. */
215b30b3 2429 /* The shift up copes with the possibility that operand[3] is
2430 wider than the bitfield. */
2431 rtx op0 = gen_reg_rtx (SImode);
2432 rtx op1 = gen_reg_rtx (SImode);
2433
2434 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2435 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
2436 emit_insn (gen_iorsi3 (op1, op1, op0));
2437 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
2438 }
2439 else if ((width + start_bit == 32)
2440 && !(const_ok_for_arm (mask)
2441 || const_ok_for_arm (~mask)))
2442 {
2443 /* Similar trick, but slightly less efficient. */
8a18b90c 2444
215b30b3 2445 rtx op0 = gen_reg_rtx (SImode);
2446 rtx op1 = gen_reg_rtx (SImode);
8a18b90c 2447
215b30b3 2448 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2449 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
2450 emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
2451 emit_insn (gen_iorsi3 (subtarget, op1, op0));
2452 }
2453 else
2454 {
c5b3a71b 2455 rtx op0 = gen_int_mode (mask, SImode);
215b30b3 2456 rtx op1 = gen_reg_rtx (SImode);
2457 rtx op2 = gen_reg_rtx (SImode);
8a18b90c 2458
215b30b3 2459 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
2460 {
2461 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 2462
215b30b3 2463 emit_insn (gen_movsi (tmp, op0));
2464 op0 = tmp;
2465 }
8a18b90c 2466
215b30b3 2467 /* Mask out any bits in operand[3] that are not needed. */
2468 emit_insn (gen_andsi3 (op1, operands[3], op0));
8a18b90c 2469
0438d37f 2470 if (CONST_INT_P (op0)
215b30b3 2471 && (const_ok_for_arm (mask << start_bit)
2472 || const_ok_for_arm (~(mask << start_bit))))
2473 {
c5b3a71b 2474 op0 = gen_int_mode (~(mask << start_bit), SImode);
215b30b3 2475 emit_insn (gen_andsi3 (op2, operands[0], op0));
2476 }
2477 else
2478 {
0438d37f 2479 if (CONST_INT_P (op0))
215b30b3 2480 {
2481 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 2482
215b30b3 2483 emit_insn (gen_movsi (tmp, op0));
2484 op0 = tmp;
2485 }
2486
2487 if (start_bit != 0)
2488 emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
a42059fd 2489
215b30b3 2490 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
2491 }
8a18b90c 2492
215b30b3 2493 if (start_bit != 0)
2494 emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
8a18b90c 2495
215b30b3 2496 emit_insn (gen_iorsi3 (subtarget, op1, op2));
2497 }
f082f1c4 2498
215b30b3 2499 if (subtarget != target)
2500 {
2501 /* If TARGET is still a SUBREG, then it must be wider than a word,
2502 so we must be careful only to set the subword we were asked to. */
2503 if (GET_CODE (target) == SUBREG)
2504 emit_move_insn (target, subtarget);
2505 else
2506 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
2507 }
8a18b90c 2508
215b30b3 2509 DONE;
2510 }"
2511)
8a18b90c 2512
8b054d5a 2513(define_insn "insv_zero"
2514 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
809003b3 2515 (match_operand:SI 1 "const_int_M_operand" "M")
2516 (match_operand:SI 2 "const_int_M_operand" "M"))
8b054d5a 2517 (const_int 0))]
2518 "arm_arch_thumb2"
2519 "bfc%?\t%0, %2, %1"
2520 [(set_attr "length" "4")
d952d547 2521 (set_attr "predicable" "yes")
d82e788e 2522 (set_attr "type" "bfm")]
8b054d5a 2523)
2524
2525(define_insn "insv_t2"
2526 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
809003b3 2527 (match_operand:SI 1 "const_int_M_operand" "M")
2528 (match_operand:SI 2 "const_int_M_operand" "M"))
8b054d5a 2529 (match_operand:SI 3 "s_register_operand" "r"))]
2530 "arm_arch_thumb2"
2531 "bfi%?\t%0, %3, %2, %1"
2532 [(set_attr "length" "4")
d952d547 2533 (set_attr "predicable" "yes")
d82e788e 2534 (set_attr "type" "bfm")]
8b054d5a 2535)
2536
8a18b90c 2537(define_insn "andsi_notsi_si"
9c08d1fa 2538 [(set (match_operand:SI 0 "s_register_operand" "=r")
2539 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2540 (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 2541 "TARGET_32BIT"
0d66636f 2542 "bic%?\\t%0, %1, %2"
d952d547 2543 [(set_attr "predicable" "yes")
1b7da4ac 2544 (set_attr "type" "logic_reg")]
0d66636f 2545)
b11cae9e 2546
8a18b90c 2547(define_insn "andsi_not_shiftsi_si"
a2cd141b 2548 [(set (match_operand:SI 0 "s_register_operand" "=r")
2549 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2550 [(match_operand:SI 2 "s_register_operand" "r")
2551 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2552 (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 2553 "TARGET_ARM"
6c4c2133 2554 "bic%?\\t%0, %1, %2%S4"
344495ea 2555 [(set_attr "predicable" "yes")
331beb1a 2556 (set_attr "shift" "2")
a2cd141b 2557 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
d82e788e 2558 (const_string "logic_shift_imm")
2559 (const_string "logic_shift_reg")))]
6c4c2133 2560)
8a18b90c 2561
9ed784d8 2562;; Shifted bics pattern used to set up CC status register and not reusing
2563;; bics output. Pattern restricts Thumb2 shift operand as bics for Thumb2
2564;; does not support shift by register.
2565(define_insn "andsi_not_shiftsi_si_scc_no_reuse"
2566 [(set (reg:CC_NOOV CC_REGNUM)
2567 (compare:CC_NOOV
2568 (and:SI (not:SI (match_operator:SI 0 "shift_operator"
2569 [(match_operand:SI 1 "s_register_operand" "r")
2570 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2571 (match_operand:SI 3 "s_register_operand" "r"))
2572 (const_int 0)))
2573 (clobber (match_scratch:SI 4 "=r"))]
2574 "TARGET_ARM || (TARGET_THUMB2 && CONST_INT_P (operands[2]))"
3ef90e77 2575 "bics%?\\t%4, %3, %1%S0"
9ed784d8 2576 [(set_attr "predicable" "yes")
9ed784d8 2577 (set_attr "conds" "set")
2578 (set_attr "shift" "1")
2579 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2580 (const_string "logic_shift_imm")
2581 (const_string "logic_shift_reg")))]
2582)
2583
2584;; Same as andsi_not_shiftsi_si_scc_no_reuse, but the bics result is also
2585;; getting reused later.
2586(define_insn "andsi_not_shiftsi_si_scc"
2587 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2588 (compare:CC_NOOV
2589 (and:SI (not:SI (match_operator:SI 0 "shift_operator"
2590 [(match_operand:SI 1 "s_register_operand" "r")
2591 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2592 (match_operand:SI 3 "s_register_operand" "r"))
2593 (const_int 0)))
2594 (set (match_operand:SI 4 "s_register_operand" "=r")
2595 (and:SI (not:SI (match_op_dup 0
2596 [(match_dup 1)
2597 (match_dup 2)]))
2598 (match_dup 3)))])]
2599 "TARGET_ARM || (TARGET_THUMB2 && CONST_INT_P (operands[2]))"
3ef90e77 2600 "bics%?\\t%4, %3, %1%S0"
9ed784d8 2601 [(set_attr "predicable" "yes")
9ed784d8 2602 (set_attr "conds" "set")
2603 (set_attr "shift" "1")
2604 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2605 (const_string "logic_shift_imm")
2606 (const_string "logic_shift_reg")))]
2607)
2608
f7fbdd4a 2609(define_insn "*andsi_notsi_si_compare0"
bd5b4116 2610 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 2611 (compare:CC_NOOV
2612 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2613 (match_operand:SI 1 "s_register_operand" "r"))
2614 (const_int 0)))
9c08d1fa 2615 (set (match_operand:SI 0 "s_register_operand" "=r")
2616 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
25f905c2 2617 "TARGET_32BIT"
3ef90e77 2618 "bics\\t%0, %1, %2"
d82e788e 2619 [(set_attr "conds" "set")
2620 (set_attr "type" "logics_shift_reg")]
0d66636f 2621)
9c08d1fa 2622
f7fbdd4a 2623(define_insn "*andsi_notsi_si_compare0_scratch"
bd5b4116 2624 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 2625 (compare:CC_NOOV
2626 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2627 (match_operand:SI 1 "s_register_operand" "r"))
2628 (const_int 0)))
9c08d1fa 2629 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 2630 "TARGET_32BIT"
3ef90e77 2631 "bics\\t%0, %1, %2"
d82e788e 2632 [(set_attr "conds" "set")
2633 (set_attr "type" "logics_shift_reg")]
0d66636f 2634)
9c08d1fa 2635
87b22bf7 2636(define_expand "iorsi3"
3934ae0e 2637 [(set (match_operand:SI 0 "s_register_operand")
2638 (ior:SI (match_operand:SI 1 "s_register_operand")
2639 (match_operand:SI 2 "reg_or_int_operand")))]
cffb2a26 2640 "TARGET_EITHER"
87b22bf7 2641 "
0438d37f 2642 if (CONST_INT_P (operands[2]))
87b22bf7 2643 {
25f905c2 2644 if (TARGET_32BIT)
cffb2a26 2645 {
17202aa5 2646 if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[2]), IOR))
2647 operands[2] = force_reg (SImode, operands[2]);
2648 else
2649 {
2650 arm_split_constant (IOR, SImode, NULL_RTX,
2651 INTVAL (operands[2]), operands[0],
2652 operands[1],
2653 optimize && can_create_pseudo_p ());
2654 DONE;
2655 }
cffb2a26 2656 }
25f905c2 2657 else /* TARGET_THUMB1 */
923ffadb 2658 {
2659 rtx tmp = force_reg (SImode, operands[2]);
2660 if (rtx_equal_p (operands[0], operands[1]))
2661 operands[2] = tmp;
2662 else
2663 {
2664 operands[2] = operands[1];
2665 operands[1] = tmp;
2666 }
2667 }
87b22bf7 2668 }
cffb2a26 2669 "
2670)
87b22bf7 2671
d5d4dc8d 2672(define_insn_and_split "*iorsi3_insn"
29e234a3 2673 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r,r,r")
2674 (ior:SI (match_operand:SI 1 "s_register_operand" "%r,0,r,r,r")
2675 (match_operand:SI 2 "reg_or_int_operand" "I,l,K,r,?n")))]
d5d4dc8d 2676 "TARGET_32BIT"
87b22bf7 2677 "@
29e234a3 2678 orr%?\\t%0, %1, %2
87b22bf7 2679 orr%?\\t%0, %1, %2
d5d4dc8d 2680 orn%?\\t%0, %1, #%B2
65f68e55 2681 orr%?\\t%0, %1, %2
87b22bf7 2682 #"
d5d4dc8d 2683 "TARGET_32BIT
0438d37f 2684 && CONST_INT_P (operands[2])
d5d4dc8d 2685 && !(const_ok_for_arm (INTVAL (operands[2]))
2686 || (TARGET_THUMB2 && const_ok_for_arm (~INTVAL (operands[2]))))"
a0f94409 2687 [(clobber (const_int 0))]
d5d4dc8d 2688{
29e234a3 2689 arm_split_constant (IOR, SImode, curr_insn,
96f57e36 2690 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 2691 DONE;
d5d4dc8d 2692}
29e234a3 2693 [(set_attr "length" "4,4,4,4,16")
2694 (set_attr "arch" "32,t2,t2,32,32")
65f68e55 2695 (set_attr "predicable" "yes")
29e234a3 2696 (set_attr "predicable_short_it" "no,yes,no,no,no")
d82e788e 2697 (set_attr "type" "logic_imm,logic_reg,logic_imm,logic_reg,logic_reg")]
65f68e55 2698)
cffb2a26 2699
a0f94409 2700(define_peephole2
2701 [(match_scratch:SI 3 "r")
372575c7 2702 (set (match_operand:SI 0 "arm_general_register_operand" "")
2703 (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
87b22bf7 2704 (match_operand:SI 2 "const_int_operand" "")))]
90560cad 2705 "TARGET_ARM
a0f94409 2706 && !const_ok_for_arm (INTVAL (operands[2]))
2707 && const_ok_for_arm (~INTVAL (operands[2]))"
2708 [(set (match_dup 3) (match_dup 2))
2709 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2710 ""
215b30b3 2711)
a0f94409 2712
f7fbdd4a 2713(define_insn "*iorsi3_compare0"
bd5b4116 2714 [(set (reg:CC_NOOV CC_REGNUM)
a02b858e 2715 (compare:CC_NOOV
2716 (ior:SI (match_operand:SI 1 "s_register_operand" "%r,0,r")
2717 (match_operand:SI 2 "arm_rhs_operand" "I,l,r"))
2718 (const_int 0)))
2719 (set (match_operand:SI 0 "s_register_operand" "=r,l,r")
9c08d1fa 2720 (ior:SI (match_dup 1) (match_dup 2)))]
25f905c2 2721 "TARGET_32BIT"
3ef90e77 2722 "orrs%?\\t%0, %1, %2"
65f68e55 2723 [(set_attr "conds" "set")
a02b858e 2724 (set_attr "arch" "*,t2,*")
2725 (set_attr "length" "4,2,4")
2726 (set_attr "type" "logics_imm,logics_reg,logics_reg")]
cffb2a26 2727)
9c08d1fa 2728
f7fbdd4a 2729(define_insn "*iorsi3_compare0_scratch"
bd5b4116 2730 [(set (reg:CC_NOOV CC_REGNUM)
a02b858e 2731 (compare:CC_NOOV
2732 (ior:SI (match_operand:SI 1 "s_register_operand" "%r,0,r")
2733 (match_operand:SI 2 "arm_rhs_operand" "I,l,r"))
2734 (const_int 0)))
2735 (clobber (match_scratch:SI 0 "=r,l,r"))]
25f905c2 2736 "TARGET_32BIT"
3ef90e77 2737 "orrs%?\\t%0, %1, %2"
65f68e55 2738 [(set_attr "conds" "set")
a02b858e 2739 (set_attr "arch" "*,t2,*")
2740 (set_attr "length" "4,2,4")
2741 (set_attr "type" "logics_imm,logics_reg,logics_reg")]
0d66636f 2742)
9c08d1fa 2743
cffb2a26 2744(define_expand "xorsi3"
3934ae0e 2745 [(set (match_operand:SI 0 "s_register_operand")
2746 (xor:SI (match_operand:SI 1 "s_register_operand")
2747 (match_operand:SI 2 "reg_or_int_operand")))]
cffb2a26 2748 "TARGET_EITHER"
0438d37f 2749 "if (CONST_INT_P (operands[2]))
923ffadb 2750 {
2751 if (TARGET_32BIT)
2752 {
17202aa5 2753 if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[2]), XOR))
2754 operands[2] = force_reg (SImode, operands[2]);
2755 else
2756 {
2757 arm_split_constant (XOR, SImode, NULL_RTX,
2758 INTVAL (operands[2]), operands[0],
2759 operands[1],
2760 optimize && can_create_pseudo_p ());
2761 DONE;
2762 }
923ffadb 2763 }
2764 else /* TARGET_THUMB1 */
2765 {
2766 rtx tmp = force_reg (SImode, operands[2]);
2767 if (rtx_equal_p (operands[0], operands[1]))
2768 operands[2] = tmp;
2769 else
2770 {
2771 operands[2] = operands[1];
2772 operands[1] = tmp;
2773 }
2774 }
2775 }"
cffb2a26 2776)
2777
5dcb35d9 2778(define_insn_and_split "*arm_xorsi3"
29e234a3 2779 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r,r")
2780 (xor:SI (match_operand:SI 1 "s_register_operand" "%r,0,r,r")
2781 (match_operand:SI 2 "reg_or_int_operand" "I,l,r,?n")))]
25f905c2 2782 "TARGET_32BIT"
5dcb35d9 2783 "@
29e234a3 2784 eor%?\\t%0, %1, %2
65f68e55 2785 eor%?\\t%0, %1, %2
5dcb35d9 2786 eor%?\\t%0, %1, %2
2787 #"
2788 "TARGET_32BIT
0438d37f 2789 && CONST_INT_P (operands[2])
5dcb35d9 2790 && !const_ok_for_arm (INTVAL (operands[2]))"
2791 [(clobber (const_int 0))]
2792{
2793 arm_split_constant (XOR, SImode, curr_insn,
2794 INTVAL (operands[2]), operands[0], operands[1], 0);
2795 DONE;
2796}
29e234a3 2797 [(set_attr "length" "4,4,4,16")
65f68e55 2798 (set_attr "predicable" "yes")
29e234a3 2799 (set_attr "predicable_short_it" "no,yes,no,no")
1b7da4ac 2800 (set_attr "type" "logic_imm,logic_reg,logic_reg,multiple")]
cffb2a26 2801)
2802
f7fbdd4a 2803(define_insn "*xorsi3_compare0"
bd5b4116 2804 [(set (reg:CC_NOOV CC_REGNUM)
65f68e55 2805 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r,r")
2806 (match_operand:SI 2 "arm_rhs_operand" "I,r"))
9c08d1fa 2807 (const_int 0)))
65f68e55 2808 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 2809 (xor:SI (match_dup 1) (match_dup 2)))]
25f905c2 2810 "TARGET_32BIT"
3ef90e77 2811 "eors%?\\t%0, %1, %2"
65f68e55 2812 [(set_attr "conds" "set")
d82e788e 2813 (set_attr "type" "logics_imm,logics_reg")]
0d66636f 2814)
9c08d1fa 2815
f7fbdd4a 2816(define_insn "*xorsi3_compare0_scratch"
bd5b4116 2817 [(set (reg:CC_NOOV CC_REGNUM)
65f68e55 2818 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r,r")
2819 (match_operand:SI 1 "arm_rhs_operand" "I,r"))
9c08d1fa 2820 (const_int 0)))]
25f905c2 2821 "TARGET_32BIT"
40dbec34 2822 "teq%?\\t%0, %1"
65f68e55 2823 [(set_attr "conds" "set")
d82e788e 2824 (set_attr "type" "logics_imm,logics_reg")]
cffb2a26 2825)
9c08d1fa 2826
215b30b3 2827; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
2828; (NOT D) we can sometimes merge the final NOT into one of the following
2829; insns.
9c08d1fa 2830
2831(define_split
a058e94a 2832 [(set (match_operand:SI 0 "s_register_operand" "")
2833 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2834 (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2835 (match_operand:SI 3 "arm_rhs_operand" "")))
2836 (clobber (match_operand:SI 4 "s_register_operand" ""))]
25f905c2 2837 "TARGET_32BIT"
9c08d1fa 2838 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2839 (not:SI (match_dup 3))))
2840 (set (match_dup 0) (not:SI (match_dup 4)))]
2841 ""
2842)
2843
ba6a3b2f 2844(define_insn_and_split "*andsi_iorsi3_notsi"
9c08d1fa 2845 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
e5fea38e 2846 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "%0,r,r")
9c08d1fa 2847 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2848 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
25f905c2 2849 "TARGET_32BIT"
ba6a3b2f 2850 "#" ; "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
2851 "&& reload_completed"
2852 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
054fd237 2853 (set (match_dup 0) (and:SI (match_dup 4) (match_dup 5)))]
2854 {
2855 /* If operands[3] is a constant make sure to fold the NOT into it
2856 to avoid creating a NOT of a CONST_INT. */
2857 rtx not_rtx = simplify_gen_unary (NOT, SImode, operands[3], SImode);
2858 if (CONST_INT_P (not_rtx))
2859 {
2860 operands[4] = operands[0];
2861 operands[5] = not_rtx;
2862 }
2863 else
2864 {
2865 operands[5] = operands[0];
2866 operands[4] = not_rtx;
2867 }
2868 }
0d66636f 2869 [(set_attr "length" "8")
25f905c2 2870 (set_attr "ce_count" "2")
d952d547 2871 (set_attr "predicable" "yes")
1b7da4ac 2872 (set_attr "type" "multiple")]
cffb2a26 2873)
9c08d1fa 2874
25f905c2 2875; ??? Are these four splitters still beneficial when the Thumb-2 bitfield
2876; insns are available?
d7863cfe 2877(define_split
2878 [(set (match_operand:SI 0 "s_register_operand" "")
2879 (match_operator:SI 1 "logical_binary_operator"
2880 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2881 (match_operand:SI 3 "const_int_operand" "")
2882 (match_operand:SI 4 "const_int_operand" ""))
2883 (match_operator:SI 9 "logical_binary_operator"
2884 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2885 (match_operand:SI 6 "const_int_operand" ""))
2886 (match_operand:SI 7 "s_register_operand" "")])]))
2887 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 2888 "TARGET_32BIT
d7863cfe 2889 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2890 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2891 [(set (match_dup 8)
2892 (match_op_dup 1
2893 [(ashift:SI (match_dup 2) (match_dup 4))
2894 (match_dup 5)]))
2895 (set (match_dup 0)
2896 (match_op_dup 1
2897 [(lshiftrt:SI (match_dup 8) (match_dup 6))
2898 (match_dup 7)]))]
2899 "
2900 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2901")
2902
2903(define_split
2904 [(set (match_operand:SI 0 "s_register_operand" "")
2905 (match_operator:SI 1 "logical_binary_operator"
2906 [(match_operator:SI 9 "logical_binary_operator"
2907 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2908 (match_operand:SI 6 "const_int_operand" ""))
2909 (match_operand:SI 7 "s_register_operand" "")])
2910 (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2911 (match_operand:SI 3 "const_int_operand" "")
2912 (match_operand:SI 4 "const_int_operand" ""))]))
2913 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 2914 "TARGET_32BIT
d7863cfe 2915 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2916 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2917 [(set (match_dup 8)
2918 (match_op_dup 1
2919 [(ashift:SI (match_dup 2) (match_dup 4))
2920 (match_dup 5)]))
2921 (set (match_dup 0)
2922 (match_op_dup 1
2923 [(lshiftrt:SI (match_dup 8) (match_dup 6))
2924 (match_dup 7)]))]
2925 "
2926 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2927")
2928
2929(define_split
2930 [(set (match_operand:SI 0 "s_register_operand" "")
2931 (match_operator:SI 1 "logical_binary_operator"
2932 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2933 (match_operand:SI 3 "const_int_operand" "")
2934 (match_operand:SI 4 "const_int_operand" ""))
2935 (match_operator:SI 9 "logical_binary_operator"
2936 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2937 (match_operand:SI 6 "const_int_operand" ""))
2938 (match_operand:SI 7 "s_register_operand" "")])]))
2939 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 2940 "TARGET_32BIT
d7863cfe 2941 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2942 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2943 [(set (match_dup 8)
2944 (match_op_dup 1
2945 [(ashift:SI (match_dup 2) (match_dup 4))
2946 (match_dup 5)]))
2947 (set (match_dup 0)
2948 (match_op_dup 1
2949 [(ashiftrt:SI (match_dup 8) (match_dup 6))
2950 (match_dup 7)]))]
2951 "
2952 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2953")
2954
2955(define_split
2956 [(set (match_operand:SI 0 "s_register_operand" "")
2957 (match_operator:SI 1 "logical_binary_operator"
2958 [(match_operator:SI 9 "logical_binary_operator"
2959 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2960 (match_operand:SI 6 "const_int_operand" ""))
2961 (match_operand:SI 7 "s_register_operand" "")])
2962 (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2963 (match_operand:SI 3 "const_int_operand" "")
2964 (match_operand:SI 4 "const_int_operand" ""))]))
2965 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 2966 "TARGET_32BIT
d7863cfe 2967 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2968 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2969 [(set (match_dup 8)
2970 (match_op_dup 1
2971 [(ashift:SI (match_dup 2) (match_dup 4))
2972 (match_dup 5)]))
2973 (set (match_dup 0)
2974 (match_op_dup 1
2975 [(ashiftrt:SI (match_dup 8) (match_dup 6))
2976 (match_dup 7)]))]
2977 "
2978 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2979")
9c08d1fa 2980\f
2981
2982;; Minimum and maximum insns
2983
8b9dc177 2984(define_expand "smaxsi3"
2985 [(parallel [
3934ae0e 2986 (set (match_operand:SI 0 "s_register_operand")
2987 (smax:SI (match_operand:SI 1 "s_register_operand")
2988 (match_operand:SI 2 "arm_rhs_operand")))
8b9dc177 2989 (clobber (reg:CC CC_REGNUM))])]
25f905c2 2990 "TARGET_32BIT"
8b9dc177 2991 "
8774928b 2992 if (operands[2] == const0_rtx || operands[2] == constm1_rtx)
8b9dc177 2993 {
2994 /* No need for a clobber of the condition code register here. */
d1f9b275 2995 emit_insn (gen_rtx_SET (operands[0],
8b9dc177 2996 gen_rtx_SMAX (SImode, operands[1],
2997 operands[2])));
2998 DONE;
2999 }
3000")
3001
3002(define_insn "*smax_0"
3003 [(set (match_operand:SI 0 "s_register_operand" "=r")
3004 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3005 (const_int 0)))]
25f905c2 3006 "TARGET_32BIT"
8b9dc177 3007 "bic%?\\t%0, %1, %1, asr #31"
d952d547 3008 [(set_attr "predicable" "yes")
1b7da4ac 3009 (set_attr "type" "logic_shift_reg")]
8b9dc177 3010)
3011
8774928b 3012(define_insn "*smax_m1"
3013 [(set (match_operand:SI 0 "s_register_operand" "=r")
3014 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3015 (const_int -1)))]
25f905c2 3016 "TARGET_32BIT"
8774928b 3017 "orr%?\\t%0, %1, %1, asr #31"
d952d547 3018 [(set_attr "predicable" "yes")
1b7da4ac 3019 (set_attr "type" "logic_shift_reg")]
8774928b 3020)
3021
3dc953f2 3022(define_insn_and_split "*arm_smax_insn"
8b9dc177 3023 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3024 (smax:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3025 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
bd5b4116 3026 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3027 "TARGET_ARM"
3dc953f2 3028 "#"
3029 ; cmp\\t%1, %2\;movlt\\t%0, %2
3030 ; cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
3031 "TARGET_ARM"
3032 [(set (reg:CC CC_REGNUM)
3033 (compare:CC (match_dup 1) (match_dup 2)))
3034 (set (match_dup 0)
3035 (if_then_else:SI (ge:SI (reg:CC CC_REGNUM) (const_int 0))
3036 (match_dup 1)
3037 (match_dup 2)))]
3038 ""
cffb2a26 3039 [(set_attr "conds" "clob")
1b7da4ac 3040 (set_attr "length" "8,12")
3041 (set_attr "type" "multiple")]
cffb2a26 3042)
9c08d1fa 3043
8b9dc177 3044(define_expand "sminsi3"
3045 [(parallel [
3934ae0e 3046 (set (match_operand:SI 0 "s_register_operand")
3047 (smin:SI (match_operand:SI 1 "s_register_operand")
3048 (match_operand:SI 2 "arm_rhs_operand")))
8b9dc177 3049 (clobber (reg:CC CC_REGNUM))])]
25f905c2 3050 "TARGET_32BIT"
8b9dc177 3051 "
3052 if (operands[2] == const0_rtx)
3053 {
3054 /* No need for a clobber of the condition code register here. */
d1f9b275 3055 emit_insn (gen_rtx_SET (operands[0],
8b9dc177 3056 gen_rtx_SMIN (SImode, operands[1],
3057 operands[2])));
3058 DONE;
3059 }
3060")
3061
3062(define_insn "*smin_0"
3063 [(set (match_operand:SI 0 "s_register_operand" "=r")
3064 (smin:SI (match_operand:SI 1 "s_register_operand" "r")
3065 (const_int 0)))]
25f905c2 3066 "TARGET_32BIT"
8b9dc177 3067 "and%?\\t%0, %1, %1, asr #31"
d952d547 3068 [(set_attr "predicable" "yes")
1b7da4ac 3069 (set_attr "type" "logic_shift_reg")]
8b9dc177 3070)
3071
3dc953f2 3072(define_insn_and_split "*arm_smin_insn"
8b9dc177 3073 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3074 (smin:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3075 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
bd5b4116 3076 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3077 "TARGET_ARM"
3dc953f2 3078 "#"
3079 ; cmp\\t%1, %2\;movge\\t%0, %2
3080 ; cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
3081 "TARGET_ARM"
3082 [(set (reg:CC CC_REGNUM)
3083 (compare:CC (match_dup 1) (match_dup 2)))
3084 (set (match_dup 0)
3085 (if_then_else:SI (lt:SI (reg:CC CC_REGNUM) (const_int 0))
3086 (match_dup 1)
3087 (match_dup 2)))]
3088 ""
0d66636f 3089 [(set_attr "conds" "clob")
1b7da4ac 3090 (set_attr "length" "8,12")
3091 (set_attr "type" "multiple,multiple")]
0d66636f 3092)
9c08d1fa 3093
25f905c2 3094(define_expand "umaxsi3"
3095 [(parallel [
3934ae0e 3096 (set (match_operand:SI 0 "s_register_operand")
3097 (umax:SI (match_operand:SI 1 "s_register_operand")
3098 (match_operand:SI 2 "arm_rhs_operand")))
25f905c2 3099 (clobber (reg:CC CC_REGNUM))])]
3100 "TARGET_32BIT"
3101 ""
3102)
3103
3dc953f2 3104(define_insn_and_split "*arm_umaxsi3"
9c08d1fa 3105 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3106 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3107 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 3108 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3109 "TARGET_ARM"
3dc953f2 3110 "#"
3111 ; cmp\\t%1, %2\;movcc\\t%0, %2
3112 ; cmp\\t%1, %2\;movcs\\t%0, %1
3113 ; cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
3114 "TARGET_ARM"
3115 [(set (reg:CC CC_REGNUM)
3116 (compare:CC (match_dup 1) (match_dup 2)))
3117 (set (match_dup 0)
3118 (if_then_else:SI (geu:SI (reg:CC CC_REGNUM) (const_int 0))
3119 (match_dup 1)
3120 (match_dup 2)))]
3121 ""
0d66636f 3122 [(set_attr "conds" "clob")
1b7da4ac 3123 (set_attr "length" "8,8,12")
9f2c2a36 3124 (set_attr "type" "store_4")]
0d66636f 3125)
9c08d1fa 3126
25f905c2 3127(define_expand "uminsi3"
3128 [(parallel [
3934ae0e 3129 (set (match_operand:SI 0 "s_register_operand")
3130 (umin:SI (match_operand:SI 1 "s_register_operand")
3131 (match_operand:SI 2 "arm_rhs_operand")))
25f905c2 3132 (clobber (reg:CC CC_REGNUM))])]
3133 "TARGET_32BIT"
3134 ""
3135)
3136
3dc953f2 3137(define_insn_and_split "*arm_uminsi3"
9c08d1fa 3138 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3139 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3140 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 3141 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3142 "TARGET_ARM"
3dc953f2 3143 "#"
3144 ; cmp\\t%1, %2\;movcs\\t%0, %2
3145 ; cmp\\t%1, %2\;movcc\\t%0, %1
3146 ; cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
3147 "TARGET_ARM"
3148 [(set (reg:CC CC_REGNUM)
3149 (compare:CC (match_dup 1) (match_dup 2)))
3150 (set (match_dup 0)
3151 (if_then_else:SI (ltu:SI (reg:CC CC_REGNUM) (const_int 0))
3152 (match_dup 1)
3153 (match_dup 2)))]
3154 ""
0d66636f 3155 [(set_attr "conds" "clob")
1b7da4ac 3156 (set_attr "length" "8,8,12")
9f2c2a36 3157 (set_attr "type" "store_4")]
0d66636f 3158)
9c08d1fa 3159
8a18b90c 3160(define_insn "*store_minmaxsi"
9c08d1fa 3161 [(set (match_operand:SI 0 "memory_operand" "=m")
3162 (match_operator:SI 3 "minmax_operator"
3163 [(match_operand:SI 1 "s_register_operand" "r")
3164 (match_operand:SI 2 "s_register_operand" "r")]))
bd5b4116 3165 (clobber (reg:CC CC_REGNUM))]
b207d152 3166 "TARGET_32BIT && optimize_function_for_size_p (cfun) && !arm_restrict_it"
9c08d1fa 3167 "*
dc55b8a9 3168 operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
3169 operands[1], operands[2]);
e2348bcb 3170 output_asm_insn (\"cmp\\t%1, %2\", operands);
25f905c2 3171 if (TARGET_THUMB2)
3172 output_asm_insn (\"ite\t%d3\", operands);
e2348bcb 3173 output_asm_insn (\"str%d3\\t%1, %0\", operands);
3174 output_asm_insn (\"str%D3\\t%2, %0\", operands);
3175 return \"\";
0d66636f 3176 "
3177 [(set_attr "conds" "clob")
25f905c2 3178 (set (attr "length")
3179 (if_then_else (eq_attr "is_thumb" "yes")
3180 (const_int 14)
3181 (const_int 12)))
9f2c2a36 3182 (set_attr "type" "store_4")]
0d66636f 3183)
9c08d1fa 3184
8a18b90c 3185; Reject the frame pointer in operand[1], since reloading this after
3186; it has been eliminated can cause carnage.
f7fbdd4a 3187(define_insn "*minmax_arithsi"
9c08d1fa 3188 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3189 (match_operator:SI 4 "shiftable_operator"
3190 [(match_operator:SI 5 "minmax_operator"
3191 [(match_operand:SI 2 "s_register_operand" "r,r")
3192 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
3193 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 3194 (clobber (reg:CC CC_REGNUM))]
7c36fe71 3195 "TARGET_32BIT && !arm_eliminable_register (operands[1]) && !arm_restrict_it"
9c08d1fa 3196 "*
0d66636f 3197 {
3198 enum rtx_code code = GET_CODE (operands[4]);
25f905c2 3199 bool need_else;
3200
3201 if (which_alternative != 0 || operands[3] != const0_rtx
ca0fc5a2 3202 || (code != PLUS && code != IOR && code != XOR))
25f905c2 3203 need_else = true;
3204 else
3205 need_else = false;
0d66636f 3206
dc55b8a9 3207 operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
3208 operands[2], operands[3]);
0d66636f 3209 output_asm_insn (\"cmp\\t%2, %3\", operands);
25f905c2 3210 if (TARGET_THUMB2)
3211 {
3212 if (need_else)
3213 output_asm_insn (\"ite\\t%d5\", operands);
3214 else
3215 output_asm_insn (\"it\\t%d5\", operands);
3216 }
0d66636f 3217 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
25f905c2 3218 if (need_else)
0d66636f 3219 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
3220 return \"\";
215b30b3 3221 }"
0d66636f 3222 [(set_attr "conds" "clob")
25f905c2 3223 (set (attr "length")
3224 (if_then_else (eq_attr "is_thumb" "yes")
3225 (const_int 14)
1b7da4ac 3226 (const_int 12)))
3227 (set_attr "type" "multiple")]
0d66636f 3228)
9c08d1fa 3229
4164bca1 3230; Reject the frame pointer in operand[1], since reloading this after
3231; it has been eliminated can cause carnage.
3232(define_insn_and_split "*minmax_arithsi_non_canon"
7c36fe71 3233 [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts")
4164bca1 3234 (minus:SI
7c36fe71 3235 (match_operand:SI 1 "s_register_operand" "0,?Ts")
4164bca1 3236 (match_operator:SI 4 "minmax_operator"
7c36fe71 3237 [(match_operand:SI 2 "s_register_operand" "Ts,Ts")
3238 (match_operand:SI 3 "arm_rhs_operand" "TsI,TsI")])))
4164bca1 3239 (clobber (reg:CC CC_REGNUM))]
7c36fe71 3240 "TARGET_32BIT && !arm_eliminable_register (operands[1])
3241 && !(arm_restrict_it && CONST_INT_P (operands[3]))"
4164bca1 3242 "#"
3243 "TARGET_32BIT && !arm_eliminable_register (operands[1]) && reload_completed"
3244 [(set (reg:CC CC_REGNUM)
3245 (compare:CC (match_dup 2) (match_dup 3)))
3246
3247 (cond_exec (match_op_dup 4 [(reg:CC CC_REGNUM) (const_int 0)])
3248 (set (match_dup 0)
3249 (minus:SI (match_dup 1)
3250 (match_dup 2))))
3251 (cond_exec (match_op_dup 5 [(reg:CC CC_REGNUM) (const_int 0)])
3252 (set (match_dup 0)
36ee0cde 3253 (match_dup 6)))]
4164bca1 3254 {
3754d046 3255 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
4164bca1 3256 operands[2], operands[3]);
3257 enum rtx_code rc = minmax_code (operands[4]);
3258 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode,
3259 operands[2], operands[3]);
3260
3261 if (mode == CCFPmode || mode == CCFPEmode)
3262 rc = reverse_condition_maybe_unordered (rc);
3263 else
3264 rc = reverse_condition (rc);
3265 operands[5] = gen_rtx_fmt_ee (rc, SImode, operands[2], operands[3]);
36ee0cde 3266 if (CONST_INT_P (operands[3]))
3267 operands[6] = plus_constant (SImode, operands[1], -INTVAL (operands[3]));
3268 else
3269 operands[6] = gen_rtx_MINUS (SImode, operands[1], operands[3]);
4164bca1 3270 }
3271 [(set_attr "conds" "clob")
3272 (set (attr "length")
3273 (if_then_else (eq_attr "is_thumb" "yes")
3274 (const_int 14)
1b7da4ac 3275 (const_int 12)))
3276 (set_attr "type" "multiple")]
4164bca1 3277)
3278
b49e3742 3279(define_code_iterator SAT [smin smax])
f0038cf3 3280(define_code_attr SATrev [(smin "smax") (smax "smin")])
b49e3742 3281(define_code_attr SATlo [(smin "1") (smax "2")])
3282(define_code_attr SAThi [(smin "2") (smax "1")])
3283
3284(define_insn "*satsi_<SAT:code>"
3285 [(set (match_operand:SI 0 "s_register_operand" "=r")
f0038cf3 3286 (SAT:SI (<SATrev>:SI (match_operand:SI 3 "s_register_operand" "r")
b49e3742 3287 (match_operand:SI 1 "const_int_operand" "i"))
3288 (match_operand:SI 2 "const_int_operand" "i")))]
f0038cf3 3289 "TARGET_32BIT && arm_arch6
b49e3742 3290 && arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>], NULL, NULL)"
3291{
3292 int mask;
3293 bool signed_sat;
3294 if (!arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>],
3295 &mask, &signed_sat))
3296 gcc_unreachable ();
3297
3298 operands[1] = GEN_INT (mask);
3299 if (signed_sat)
3300 return "ssat%?\t%0, %1, %3";
3301 else
3302 return "usat%?\t%0, %1, %3";
3303}
7c36fe71 3304 [(set_attr "predicable" "yes")
1b7da4ac 3305 (set_attr "type" "alus_imm")]
bebe9bbb 3306)
b49e3742 3307
3308(define_insn "*satsi_<SAT:code>_shift"
3309 [(set (match_operand:SI 0 "s_register_operand" "=r")
f0038cf3 3310 (SAT:SI (<SATrev>:SI (match_operator:SI 3 "sat_shift_operator"
b49e3742 3311 [(match_operand:SI 4 "s_register_operand" "r")
3312 (match_operand:SI 5 "const_int_operand" "i")])
3313 (match_operand:SI 1 "const_int_operand" "i"))
3314 (match_operand:SI 2 "const_int_operand" "i")))]
f0038cf3 3315 "TARGET_32BIT && arm_arch6
b49e3742 3316 && arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>], NULL, NULL)"
3317{
3318 int mask;
3319 bool signed_sat;
3320 if (!arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>],
3321 &mask, &signed_sat))
3322 gcc_unreachable ();
3323
3324 operands[1] = GEN_INT (mask);
3325 if (signed_sat)
3326 return "ssat%?\t%0, %1, %4%S3";
3327 else
3328 return "usat%?\t%0, %1, %4%S3";
3329}
3330 [(set_attr "predicable" "yes")
b49e3742 3331 (set_attr "shift" "3")
d82e788e 3332 (set_attr "type" "logic_shift_reg")])
b11cae9e 3333\f
3334;; Shift and rotation insns
3335
a2cd141b 3336(define_expand "ashldi3"
3934ae0e 3337 [(set (match_operand:DI 0 "s_register_operand")
3338 (ashift:DI (match_operand:DI 1 "s_register_operand")
8baabb36 3339 (match_operand:SI 2 "reg_or_int_operand")))]
25f905c2 3340 "TARGET_32BIT"
a2cd141b 3341 "
8baabb36 3342 arm_emit_coreregs_64bit_shift (ASHIFT, operands[0], operands[1],
3343 operands[2], gen_reg_rtx (SImode),
3344 gen_reg_rtx (SImode));
3345 DONE;
3346")
a2cd141b 3347
87b22bf7 3348(define_expand "ashlsi3"
3934ae0e 3349 [(set (match_operand:SI 0 "s_register_operand")
3350 (ashift:SI (match_operand:SI 1 "s_register_operand")
3351 (match_operand:SI 2 "arm_rhs_operand")))]
cffb2a26 3352 "TARGET_EITHER"
87b22bf7 3353 "
0438d37f 3354 if (CONST_INT_P (operands[2])
8c4e8755 3355 && (UINTVAL (operands[2])) > 31)
87b22bf7 3356 {
3357 emit_insn (gen_movsi (operands[0], const0_rtx));
3358 DONE;
3359 }
cffb2a26 3360 "
3361)
3362
a2cd141b 3363(define_expand "ashrdi3"
3934ae0e 3364 [(set (match_operand:DI 0 "s_register_operand")
3365 (ashiftrt:DI (match_operand:DI 1 "s_register_operand")
3366 (match_operand:SI 2 "reg_or_int_operand")))]
25f905c2 3367 "TARGET_32BIT"
a2cd141b 3368 "
8baabb36 3369 arm_emit_coreregs_64bit_shift (ASHIFTRT, operands[0], operands[1],
3370 operands[2], gen_reg_rtx (SImode),
3371 gen_reg_rtx (SImode));
3372 DONE;
3373")
a2cd141b 3374
87b22bf7 3375(define_expand "ashrsi3"
3934ae0e 3376 [(set (match_operand:SI 0 "s_register_operand")
3377 (ashiftrt:SI (match_operand:SI 1 "s_register_operand")
3378 (match_operand:SI 2 "arm_rhs_operand")))]
cffb2a26 3379 "TARGET_EITHER"
87b22bf7 3380 "
0438d37f 3381 if (CONST_INT_P (operands[2])
8c4e8755 3382 && UINTVAL (operands[2]) > 31)
87b22bf7 3383 operands[2] = GEN_INT (31);
cffb2a26 3384 "
3385)
3386
a2cd141b 3387(define_expand "lshrdi3"
3934ae0e 3388 [(set (match_operand:DI 0 "s_register_operand")
3389 (lshiftrt:DI (match_operand:DI 1 "s_register_operand")
3390 (match_operand:SI 2 "reg_or_int_operand")))]
25f905c2 3391 "TARGET_32BIT"
a2cd141b 3392 "
8baabb36 3393 arm_emit_coreregs_64bit_shift (LSHIFTRT, operands[0], operands[1],
3394 operands[2], gen_reg_rtx (SImode),
3395 gen_reg_rtx (SImode));
3396 DONE;
3397")
a2cd141b 3398
87b22bf7 3399(define_expand "lshrsi3"
3934ae0e 3400 [(set (match_operand:SI 0 "s_register_operand")
3401 (lshiftrt:SI (match_operand:SI 1 "s_register_operand")
3402 (match_operand:SI 2 "arm_rhs_operand")))]
cffb2a26 3403 "TARGET_EITHER"
87b22bf7 3404 "
0438d37f 3405 if (CONST_INT_P (operands[2])
8c4e8755 3406 && (UINTVAL (operands[2])) > 31)
87b22bf7 3407 {
3408 emit_insn (gen_movsi (operands[0], const0_rtx));
3409 DONE;
3410 }
cffb2a26 3411 "
3412)
3413
87b22bf7 3414(define_expand "rotlsi3"
3934ae0e 3415 [(set (match_operand:SI 0 "s_register_operand")
3416 (rotatert:SI (match_operand:SI 1 "s_register_operand")
3417 (match_operand:SI 2 "reg_or_int_operand")))]
25f905c2 3418 "TARGET_32BIT"
87b22bf7 3419 "
0438d37f 3420 if (CONST_INT_P (operands[2]))
87b22bf7 3421 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
3422 else
b11cae9e 3423 {
87b22bf7 3424 rtx reg = gen_reg_rtx (SImode);
3425 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
3426 operands[2] = reg;
b11cae9e 3427 }
cffb2a26 3428 "
3429)
9c08d1fa 3430
87b22bf7 3431(define_expand "rotrsi3"
3934ae0e 3432 [(set (match_operand:SI 0 "s_register_operand")
3433 (rotatert:SI (match_operand:SI 1 "s_register_operand")
3434 (match_operand:SI 2 "arm_rhs_operand")))]
cffb2a26 3435 "TARGET_EITHER"
87b22bf7 3436 "
25f905c2 3437 if (TARGET_32BIT)
cffb2a26 3438 {
0438d37f 3439 if (CONST_INT_P (operands[2])
8c4e8755 3440 && UINTVAL (operands[2]) > 31)
cffb2a26 3441 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
3442 }
25f905c2 3443 else /* TARGET_THUMB1 */
cffb2a26 3444 {
0438d37f 3445 if (CONST_INT_P (operands [2]))
cffb2a26 3446 operands [2] = force_reg (SImode, operands[2]);
3447 }
3448 "
3449)
87b22bf7 3450
cffb2a26 3451(define_insn "*arm_shiftsi3"
88c29385 3452 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r,r")
cffb2a26 3453 (match_operator:SI 3 "shift_operator"
88c29385 3454 [(match_operand:SI 1 "s_register_operand" "0,l,r,r")
3455 (match_operand:SI 2 "reg_or_int_operand" "l,M,M,r")]))]
25f905c2 3456 "TARGET_32BIT"
3457 "* return arm_output_shift(operands, 0);"
344495ea 3458 [(set_attr "predicable" "yes")
88c29385 3459 (set_attr "arch" "t2,t2,*,*")
3460 (set_attr "predicable_short_it" "yes,yes,no,no")
7c36fe71 3461 (set_attr "length" "4")
331beb1a 3462 (set_attr "shift" "1")
88c29385 3463 (set_attr "type" "alu_shift_reg,alu_shift_imm,alu_shift_imm,alu_shift_reg")]
6c4c2133 3464)
87b22bf7 3465
f7fbdd4a 3466(define_insn "*shiftsi3_compare0"
bd5b4116 3467 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 3468 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
6b6abc9c 3469 [(match_operand:SI 1 "s_register_operand" "r,r")
3470 (match_operand:SI 2 "arm_rhs_operand" "M,r")])
9c08d1fa 3471 (const_int 0)))
6b6abc9c 3472 (set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 3473 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
25f905c2 3474 "TARGET_32BIT"
3475 "* return arm_output_shift(operands, 1);"
344495ea 3476 [(set_attr "conds" "set")
331beb1a 3477 (set_attr "shift" "1")
d82e788e 3478 (set_attr "type" "alus_shift_imm,alus_shift_reg")]
0d66636f 3479)
9c08d1fa 3480
f7fbdd4a 3481(define_insn "*shiftsi3_compare0_scratch"
bd5b4116 3482 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 3483 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
6b6abc9c 3484 [(match_operand:SI 1 "s_register_operand" "r,r")
3485 (match_operand:SI 2 "arm_rhs_operand" "M,r")])
9c08d1fa 3486 (const_int 0)))
6b6abc9c 3487 (clobber (match_scratch:SI 0 "=r,r"))]
25f905c2 3488 "TARGET_32BIT"
3489 "* return arm_output_shift(operands, 1);"
344495ea 3490 [(set_attr "conds" "set")
6b6abc9c 3491 (set_attr "shift" "1")
d82e788e 3492 (set_attr "type" "shift_imm,shift_reg")]
0d66636f 3493)
9c08d1fa 3494
d5d4dc8d 3495(define_insn "*not_shiftsi"
3496 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 3497 (not:SI (match_operator:SI 3 "shift_operator"
d5d4dc8d 3498 [(match_operand:SI 1 "s_register_operand" "r,r")
3499 (match_operand:SI 2 "shift_amount_operand" "M,rM")])))]
3500 "TARGET_32BIT"
6c4c2133 3501 "mvn%?\\t%0, %1%S3"
344495ea 3502 [(set_attr "predicable" "yes")
331beb1a 3503 (set_attr "shift" "1")
d5d4dc8d 3504 (set_attr "arch" "32,a")
1aed5204 3505 (set_attr "type" "mvn_shift,mvn_shift_reg")])
9c08d1fa 3506
d5d4dc8d 3507(define_insn "*not_shiftsi_compare0"
bd5b4116 3508 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 3509 (compare:CC_NOOV
3510 (not:SI (match_operator:SI 3 "shift_operator"
3511 [(match_operand:SI 1 "s_register_operand" "r,r")
3512 (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
3513 (const_int 0)))
3514 (set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 3515 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
d5d4dc8d 3516 "TARGET_32BIT"
3ef90e77 3517 "mvns%?\\t%0, %1%S3"
344495ea 3518 [(set_attr "conds" "set")
331beb1a 3519 (set_attr "shift" "1")
d5d4dc8d 3520 (set_attr "arch" "32,a")
1aed5204 3521 (set_attr "type" "mvn_shift,mvn_shift_reg")])
9c08d1fa 3522
d5d4dc8d 3523(define_insn "*not_shiftsi_compare0_scratch"
bd5b4116 3524 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 3525 (compare:CC_NOOV
3526 (not:SI (match_operator:SI 3 "shift_operator"
3527 [(match_operand:SI 1 "s_register_operand" "r,r")
3528 (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
3529 (const_int 0)))
3530 (clobber (match_scratch:SI 0 "=r,r"))]
3531 "TARGET_32BIT"
3ef90e77 3532 "mvns%?\\t%0, %1%S3"
344495ea 3533 [(set_attr "conds" "set")
331beb1a 3534 (set_attr "shift" "1")
d5d4dc8d 3535 (set_attr "arch" "32,a")
1aed5204 3536 (set_attr "type" "mvn_shift,mvn_shift_reg")])
9c08d1fa 3537
cffb2a26 3538;; We don't really have extzv, but defining this using shifts helps
3539;; to reduce register pressure later on.
3540
3541(define_expand "extzv"
3934ae0e 3542 [(set (match_operand 0 "s_register_operand")
3543 (zero_extract (match_operand 1 "nonimmediate_operand")
3544 (match_operand 2 "const_int_operand")
3545 (match_operand 3 "const_int_operand")))]
8b054d5a 3546 "TARGET_THUMB1 || arm_arch_thumb2"
cffb2a26 3547 "
3548 {
3549 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
3550 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
3551
8b054d5a 3552 if (arm_arch_thumb2)
3553 {
eb04cafb 3554 HOST_WIDE_INT width = INTVAL (operands[2]);
3555 HOST_WIDE_INT bitpos = INTVAL (operands[3]);
3556
3557 if (unaligned_access && MEM_P (operands[1])
3558 && (width == 16 || width == 32) && (bitpos % BITS_PER_UNIT) == 0)
3559 {
3560 rtx base_addr;
3561
3562 if (BYTES_BIG_ENDIAN)
3563 bitpos = GET_MODE_BITSIZE (GET_MODE (operands[0])) - width
3564 - bitpos;
3565
3566 if (width == 32)
3567 {
3568 base_addr = adjust_address (operands[1], SImode,
3569 bitpos / BITS_PER_UNIT);
3570 emit_insn (gen_unaligned_loadsi (operands[0], base_addr));
3571 }
3572 else
3573 {
3574 rtx dest = operands[0];
3575 rtx tmp = gen_reg_rtx (SImode);
3576
3577 /* We may get a paradoxical subreg here. Strip it off. */
3578 if (GET_CODE (dest) == SUBREG
3579 && GET_MODE (dest) == SImode
3580 && GET_MODE (SUBREG_REG (dest)) == HImode)
3581 dest = SUBREG_REG (dest);
3582
3583 if (GET_MODE_BITSIZE (GET_MODE (dest)) != width)
3584 FAIL;
3585
3586 base_addr = adjust_address (operands[1], HImode,
3587 bitpos / BITS_PER_UNIT);
3588 emit_insn (gen_unaligned_loadhiu (tmp, base_addr));
3589 emit_move_insn (gen_lowpart (SImode, dest), tmp);
3590 }
3591 DONE;
3592 }
3593 else if (s_register_operand (operands[1], GET_MODE (operands[1])))
3594 {
3595 emit_insn (gen_extzv_t2 (operands[0], operands[1], operands[2],
3596 operands[3]));
3597 DONE;
3598 }
3599 else
3600 FAIL;
8b054d5a 3601 }
eb04cafb 3602
3603 if (!s_register_operand (operands[1], GET_MODE (operands[1])))
3604 FAIL;
8b054d5a 3605
cffb2a26 3606 operands[3] = GEN_INT (rshift);
3607
3608 if (lshift == 0)
3609 {
3610 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
3611 DONE;
3612 }
3613
eb04cafb 3614 emit_insn (gen_extzv_t1 (operands[0], operands[1], GEN_INT (lshift),
3615 operands[3], gen_reg_rtx (SImode)));
3616 DONE;
215b30b3 3617 }"
cffb2a26 3618)
3619
eb04cafb 3620;; Helper for extzv, for the Thumb-1 register-shifts case.
3621
3622(define_expand "extzv_t1"
3934ae0e 3623 [(set (match_operand:SI 4 "s_register_operand")
3624 (ashift:SI (match_operand:SI 1 "nonimmediate_operand")
3625 (match_operand:SI 2 "const_int_operand")))
3626 (set (match_operand:SI 0 "s_register_operand")
eb04cafb 3627 (lshiftrt:SI (match_dup 4)
3934ae0e 3628 (match_operand:SI 3 "const_int_operand")))]
eb04cafb 3629 "TARGET_THUMB1"
3630 "")
3631
3632(define_expand "extv"
3934ae0e 3633 [(set (match_operand 0 "s_register_operand")
3634 (sign_extract (match_operand 1 "nonimmediate_operand")
3635 (match_operand 2 "const_int_operand")
3636 (match_operand 3 "const_int_operand")))]
eb04cafb 3637 "arm_arch_thumb2"
3638{
3639 HOST_WIDE_INT width = INTVAL (operands[2]);
3640 HOST_WIDE_INT bitpos = INTVAL (operands[3]);
3641
3642 if (unaligned_access && MEM_P (operands[1]) && (width == 16 || width == 32)
3643 && (bitpos % BITS_PER_UNIT) == 0)
3644 {
3645 rtx base_addr;
3646
3647 if (BYTES_BIG_ENDIAN)
3648 bitpos = GET_MODE_BITSIZE (GET_MODE (operands[0])) - width - bitpos;
3649
3650 if (width == 32)
3651 {
3652 base_addr = adjust_address (operands[1], SImode,
3653 bitpos / BITS_PER_UNIT);
3654 emit_insn (gen_unaligned_loadsi (operands[0], base_addr));
3655 }
3656 else
3657 {
3658 rtx dest = operands[0];
3659 rtx tmp = gen_reg_rtx (SImode);
3660
3661 /* We may get a paradoxical subreg here. Strip it off. */
3662 if (GET_CODE (dest) == SUBREG
3663 && GET_MODE (dest) == SImode
3664 && GET_MODE (SUBREG_REG (dest)) == HImode)
3665 dest = SUBREG_REG (dest);
3666
3667 if (GET_MODE_BITSIZE (GET_MODE (dest)) != width)
3668 FAIL;
3669
3670 base_addr = adjust_address (operands[1], HImode,
3671 bitpos / BITS_PER_UNIT);
3672 emit_insn (gen_unaligned_loadhis (tmp, base_addr));
3673 emit_move_insn (gen_lowpart (SImode, dest), tmp);
3674 }
3675
3676 DONE;
3677 }
3678 else if (!s_register_operand (operands[1], GET_MODE (operands[1])))
3679 FAIL;
3680 else if (GET_MODE (operands[0]) == SImode
3681 && GET_MODE (operands[1]) == SImode)
3682 {
3683 emit_insn (gen_extv_regsi (operands[0], operands[1], operands[2],
3684 operands[3]));
3685 DONE;
3686 }
3687
3688 FAIL;
3689})
3690
3691; Helper to expand register forms of extv with the proper modes.
3692
3693(define_expand "extv_regsi"
3934ae0e 3694 [(set (match_operand:SI 0 "s_register_operand")
3695 (sign_extract:SI (match_operand:SI 1 "s_register_operand")
3696 (match_operand 2 "const_int_operand")
3697 (match_operand 3 "const_int_operand")))]
eb04cafb 3698 ""
3699{
3700})
3701
3702; ARMv6+ unaligned load/store instructions (used for packed structure accesses).
3703
122f262a 3704(define_insn "unaligned_loaddi"
3705 [(set (match_operand:DI 0 "s_register_operand" "=r")
3706 (unspec:DI [(match_operand:DI 1 "memory_operand" "m")]
3707 UNSPEC_UNALIGNED_LOAD))]
3708 "TARGET_32BIT && TARGET_LDRD"
3709 "*
3710 return output_move_double (operands, true, NULL);
3711 "
3712 [(set_attr "length" "8")
3713 (set_attr "type" "load_8")])
3714
eb04cafb 3715(define_insn "unaligned_loadsi"
70ce330a 3716 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
3717 (unspec:SI [(match_operand:SI 1 "memory_operand" "m,Uw,m")]
eb04cafb 3718 UNSPEC_UNALIGNED_LOAD))]
8fe38eb2 3719 "unaligned_access"
70ce330a 3720 "@
3721 ldr\t%0, %1\t@ unaligned
3722 ldr%?\t%0, %1\t@ unaligned
3723 ldr%?\t%0, %1\t@ unaligned"
3724 [(set_attr "arch" "t1,t2,32")
3725 (set_attr "length" "2,2,4")
3726 (set_attr "predicable" "no,yes,yes")
3727 (set_attr "predicable_short_it" "no,yes,no")
9f2c2a36 3728 (set_attr "type" "load_4")])
eb04cafb 3729
70ce330a 3730;; The 16-bit Thumb1 variant of ldrsh requires two registers in the
3731;; address (there's no immediate format). That's tricky to support
3732;; here and we don't really need this pattern for that case, so only
3733;; enable for 32-bit ISAs.
eb04cafb 3734(define_insn "unaligned_loadhis"
5d79b75e 3735 [(set (match_operand:SI 0 "s_register_operand" "=r")
eb04cafb 3736 (sign_extend:SI
5d79b75e 3737 (unspec:HI [(match_operand:HI 1 "memory_operand" "Uh")]
eb04cafb 3738 UNSPEC_UNALIGNED_LOAD)))]
70ce330a 3739 "unaligned_access && TARGET_32BIT"
3ef90e77 3740 "ldrsh%?\t%0, %1\t@ unaligned"
5d79b75e 3741 [(set_attr "predicable" "yes")
eb04cafb 3742 (set_attr "type" "load_byte")])
3743
3744(define_insn "unaligned_loadhiu"
70ce330a 3745 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
eb04cafb 3746 (zero_extend:SI
70ce330a 3747 (unspec:HI [(match_operand:HI 1 "memory_operand" "m,Uw,m")]
eb04cafb 3748 UNSPEC_UNALIGNED_LOAD)))]
8fe38eb2 3749 "unaligned_access"
70ce330a 3750 "@
3751 ldrh\t%0, %1\t@ unaligned
3752 ldrh%?\t%0, %1\t@ unaligned
3753 ldrh%?\t%0, %1\t@ unaligned"
3754 [(set_attr "arch" "t1,t2,32")
3755 (set_attr "length" "2,2,4")
3756 (set_attr "predicable" "no,yes,yes")
3757 (set_attr "predicable_short_it" "no,yes,no")
eb04cafb 3758 (set_attr "type" "load_byte")])
3759
122f262a 3760(define_insn "unaligned_storedi"
3761 [(set (match_operand:DI 0 "memory_operand" "=m")
3762 (unspec:DI [(match_operand:DI 1 "s_register_operand" "r")]
3763 UNSPEC_UNALIGNED_STORE))]
3764 "TARGET_32BIT && TARGET_LDRD"
3765 "*
3766 return output_move_double (operands, true, NULL);
3767 "
3768 [(set_attr "length" "8")
3769 (set_attr "type" "store_8")])
3770
eb04cafb 3771(define_insn "unaligned_storesi"
70ce330a 3772 [(set (match_operand:SI 0 "memory_operand" "=m,Uw,m")
3773 (unspec:SI [(match_operand:SI 1 "s_register_operand" "l,l,r")]
eb04cafb 3774 UNSPEC_UNALIGNED_STORE))]
8fe38eb2 3775 "unaligned_access"
70ce330a 3776 "@
3777 str\t%1, %0\t@ unaligned
3778 str%?\t%1, %0\t@ unaligned
3779 str%?\t%1, %0\t@ unaligned"
3780 [(set_attr "arch" "t1,t2,32")
3781 (set_attr "length" "2,2,4")
3782 (set_attr "predicable" "no,yes,yes")
3783 (set_attr "predicable_short_it" "no,yes,no")
9f2c2a36 3784 (set_attr "type" "store_4")])
eb04cafb 3785
3786(define_insn "unaligned_storehi"
70ce330a 3787 [(set (match_operand:HI 0 "memory_operand" "=m,Uw,m")
3788 (unspec:HI [(match_operand:HI 1 "s_register_operand" "l,l,r")]
eb04cafb 3789 UNSPEC_UNALIGNED_STORE))]
8fe38eb2 3790 "unaligned_access"
70ce330a 3791 "@
3792 strh\t%1, %0\t@ unaligned
3793 strh%?\t%1, %0\t@ unaligned
3794 strh%?\t%1, %0\t@ unaligned"
3795 [(set_attr "arch" "t1,t2,32")
3796 (set_attr "length" "2,2,4")
3797 (set_attr "predicable" "no,yes,yes")
3798 (set_attr "predicable_short_it" "no,yes,no")
9f2c2a36 3799 (set_attr "type" "store_4")])
eb04cafb 3800
ae51a965 3801
eb04cafb 3802(define_insn "*extv_reg"
8b054d5a 3803 [(set (match_operand:SI 0 "s_register_operand" "=r")
3804 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
13051f13 3805 (match_operand:SI 2 "const_int_operand" "n")
3806 (match_operand:SI 3 "const_int_operand" "n")))]
3807 "arm_arch_thumb2
3808 && IN_RANGE (INTVAL (operands[3]), 0, 31)
3809 && IN_RANGE (INTVAL (operands[2]), 1, 32 - INTVAL (operands[3]))"
8b054d5a 3810 "sbfx%?\t%0, %1, %3, %2"
3811 [(set_attr "length" "4")
d952d547 3812 (set_attr "predicable" "yes")
d82e788e 3813 (set_attr "type" "bfm")]
8b054d5a 3814)
3815
3816(define_insn "extzv_t2"
3817 [(set (match_operand:SI 0 "s_register_operand" "=r")
3818 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "r")
13051f13 3819 (match_operand:SI 2 "const_int_operand" "n")
3820 (match_operand:SI 3 "const_int_operand" "n")))]
3821 "arm_arch_thumb2
3822 && IN_RANGE (INTVAL (operands[3]), 0, 31)
3823 && IN_RANGE (INTVAL (operands[2]), 1, 32 - INTVAL (operands[3]))"
8b054d5a 3824 "ubfx%?\t%0, %1, %3, %2"
3825 [(set_attr "length" "4")
d952d547 3826 (set_attr "predicable" "yes")
d82e788e 3827 (set_attr "type" "bfm")]
8b054d5a 3828)
3829
7d3cda8c 3830
3831;; Division instructions
3832(define_insn "divsi3"
8f5f2788 3833 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3834 (div:SI (match_operand:SI 1 "s_register_operand" "r,r")
3835 (match_operand:SI 2 "s_register_operand" "r,r")))]
7d3cda8c 3836 "TARGET_IDIV"
8f5f2788 3837 "@
3838 sdiv%?\t%0, %1, %2
3839 sdiv\t%0, %1, %2"
3840 [(set_attr "arch" "32,v8mb")
3841 (set_attr "predicable" "yes")
9da0ec36 3842 (set_attr "type" "sdiv")]
7d3cda8c 3843)
3844
3845(define_insn "udivsi3"
8f5f2788 3846 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3847 (udiv:SI (match_operand:SI 1 "s_register_operand" "r,r")
3848 (match_operand:SI 2 "s_register_operand" "r,r")))]
7d3cda8c 3849 "TARGET_IDIV"
8f5f2788 3850 "@
3851 udiv%?\t%0, %1, %2
3852 udiv\t%0, %1, %2"
3853 [(set_attr "arch" "32,v8mb")
3854 (set_attr "predicable" "yes")
9da0ec36 3855 (set_attr "type" "udiv")]
7d3cda8c 3856)
3857
b11cae9e 3858\f
3859;; Unary arithmetic insns
3860
f6c98a9a 3861(define_expand "negvsi3"
3862 [(match_operand:SI 0 "register_operand")
3863 (match_operand:SI 1 "register_operand")
3864 (match_operand 2 "")]
3865 "TARGET_32BIT"
3866{
3867 emit_insn (gen_subsi3_compare (operands[0], const0_rtx, operands[1]));
3868 arm_gen_unlikely_cbranch (NE, CC_Vmode, operands[2]);
3869
3870 DONE;
3871})
3872
3873(define_expand "negvdi3"
e62551fd 3874 [(match_operand:DI 0 "s_register_operand")
3875 (match_operand:DI 1 "s_register_operand")
f6c98a9a 3876 (match_operand 2 "")]
3877 "TARGET_ARM"
3878{
3879 emit_insn (gen_negdi2_compare (operands[0], operands[1]));
3880 arm_gen_unlikely_cbranch (NE, CC_Vmode, operands[2]);
3881
3882 DONE;
3883})
3884
3885
e62551fd 3886(define_insn "negdi2_compare"
f6c98a9a 3887 [(set (reg:CC CC_REGNUM)
3888 (compare:CC
3889 (const_int 0)
e62551fd 3890 (match_operand:DI 1 "register_operand" "r,r")))
3891 (set (match_operand:DI 0 "register_operand" "=&r,&r")
f6c98a9a 3892 (minus:DI (const_int 0) (match_dup 1)))]
3893 "TARGET_ARM"
e62551fd 3894 "@
3895 rsbs\\t%Q0, %Q1, #0;rscs\\t%R0, %R1, #0
3896 rsbs\\t%Q0, %Q1, #0;sbcs\\t%R0, %R1, %R1, lsl #1"
f6c98a9a 3897 [(set_attr "conds" "set")
e62551fd 3898 (set_attr "arch" "a,t2")
f6c98a9a 3899 (set_attr "length" "8")
3900 (set_attr "type" "multiple")]
3901)
3902
cffb2a26 3903(define_expand "negsi2"
3934ae0e 3904 [(set (match_operand:SI 0 "s_register_operand")
3905 (neg:SI (match_operand:SI 1 "s_register_operand")))]
cffb2a26 3906 "TARGET_EITHER"
b11cae9e 3907 ""
cffb2a26 3908)
3909
3910(define_insn "*arm_negsi2"
d952d547 3911 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
3912 (neg:SI (match_operand:SI 1 "s_register_operand" "l,r")))]
25f905c2 3913 "TARGET_32BIT"
cffb2a26 3914 "rsb%?\\t%0, %1, #0"
d952d547 3915 [(set_attr "predicable" "yes")
3916 (set_attr "predicable_short_it" "yes,no")
3917 (set_attr "arch" "t2,*")
1b7da4ac 3918 (set_attr "length" "4")
7724f74b 3919 (set_attr "type" "alu_imm")]
3920)
3921
3922;; To keep the comparison in canonical form we express it as (~reg cmp ~0)
3923;; rather than (0 cmp reg). This gives the same results for unsigned
3924;; and equality compares which is what we mostly need here.
3925(define_insn "negsi2_0compare"
3926 [(set (reg:CC_RSB CC_REGNUM)
3927 (compare:CC_RSB (not:SI (match_operand:SI 1 "s_register_operand" "l,r"))
3928 (const_int -1)))
3929 (set (match_operand:SI 0 "s_register_operand" "=l,r")
3930 (neg:SI (match_dup 1)))]
3931 "TARGET_32BIT"
3932 "@
3933 negs\\t%0, %1
3934 rsbs\\t%0, %1, #0"
3935 [(set_attr "conds" "set")
3936 (set_attr "arch" "t2,*")
3937 (set_attr "length" "2,*")
3938 (set_attr "type" "alus_imm")]
3939)
3940
3941(define_insn "negsi2_carryin"
3942 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3943 (minus:SI (neg:SI (match_operand:SI 1 "s_register_operand" "r,r"))
3944 (match_operand:SI 2 "arm_borrow_operation" "")))]
3945 "TARGET_32BIT"
3946 "@
3947 rsc\\t%0, %1, #0
3948 sbc\\t%0, %1, %1, lsl #1"
3949 [(set_attr "conds" "use")
3950 (set_attr "arch" "a,t2")
3951 (set_attr "type" "adc_imm,adc_reg")]
cffb2a26 3952)
3953
604f3a0a 3954(define_expand "negsf2"
3934ae0e 3955 [(set (match_operand:SF 0 "s_register_operand")
3956 (neg:SF (match_operand:SF 1 "s_register_operand")))]
d7216193 3957 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 3958 ""
3959)
3960
3961(define_expand "negdf2"
3934ae0e 3962 [(set (match_operand:DF 0 "s_register_operand")
3963 (neg:DF (match_operand:DF 1 "s_register_operand")))]
994606f8 3964 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
604f3a0a 3965 "")
3966
9c08d1fa 3967;; abssi2 doesn't really clobber the condition codes if a different register
3968;; is being set. To keep things simple, assume during rtl manipulations that
3969;; it does, but tell the final scan operator the truth. Similarly for
3970;; (neg (abs...))
3971
604f3a0a 3972(define_expand "abssi2"
3973 [(parallel
3934ae0e 3974 [(set (match_operand:SI 0 "s_register_operand")
3975 (abs:SI (match_operand:SI 1 "s_register_operand")))
ba156559 3976 (clobber (match_dup 2))])]
3977 "TARGET_EITHER"
3978 "
25f905c2 3979 if (TARGET_THUMB1)
ba156559 3980 operands[2] = gen_rtx_SCRATCH (SImode);
3981 else
3982 operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
3983")
604f3a0a 3984
ba6a3b2f 3985(define_insn_and_split "*arm_abssi2"
ba156559 3986 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
9c08d1fa 3987 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
bd5b4116 3988 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3989 "TARGET_ARM"
ba6a3b2f 3990 "#"
3991 "&& reload_completed"
3992 [(const_int 0)]
3993 {
3994 /* if (which_alternative == 0) */
3995 if (REGNO(operands[0]) == REGNO(operands[1]))
3996 {
3997 /* Emit the pattern:
3998 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
3999 [(set (reg:CC CC_REGNUM)
4000 (compare:CC (match_dup 0) (const_int 0)))
4001 (cond_exec (lt:CC (reg:CC CC_REGNUM) (const_int 0))
4002 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 1))))]
4003 */
d1f9b275 4004 emit_insn (gen_rtx_SET (gen_rtx_REG (CCmode, CC_REGNUM),
ba6a3b2f 4005 gen_rtx_COMPARE (CCmode, operands[0], const0_rtx)));
4006 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
4007 (gen_rtx_LT (SImode,
4008 gen_rtx_REG (CCmode, CC_REGNUM),
4009 const0_rtx)),
d1f9b275 4010 (gen_rtx_SET (operands[0],
ba6a3b2f 4011 (gen_rtx_MINUS (SImode,
4012 const0_rtx,
4013 operands[1]))))));
4014 DONE;
4015 }
4016 else
4017 {
4018 /* Emit the pattern:
4019 alt1: eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31
4020 [(set (match_dup 0)
4021 (xor:SI (match_dup 1)
4022 (ashiftrt:SI (match_dup 1) (const_int 31))))
4023 (set (match_dup 0)
4024 (minus:SI (match_dup 0)
4025 (ashiftrt:SI (match_dup 1) (const_int 31))))]
4026 */
d1f9b275 4027 emit_insn (gen_rtx_SET (operands[0],
ba6a3b2f 4028 gen_rtx_XOR (SImode,
4029 gen_rtx_ASHIFTRT (SImode,
4030 operands[1],
4031 GEN_INT (31)),
4032 operands[1])));
d1f9b275 4033 emit_insn (gen_rtx_SET (operands[0],
ba6a3b2f 4034 gen_rtx_MINUS (SImode,
4035 operands[0],
4036 gen_rtx_ASHIFTRT (SImode,
4037 operands[1],
4038 GEN_INT (31)))));
4039 DONE;
4040 }
4041 }
cffb2a26 4042 [(set_attr "conds" "clob,*")
331beb1a 4043 (set_attr "shift" "1")
2ad08b65 4044 (set_attr "predicable" "no, yes")
1b7da4ac 4045 (set_attr "length" "8")
4046 (set_attr "type" "multiple")]
cffb2a26 4047)
9c08d1fa 4048
ba6a3b2f 4049(define_insn_and_split "*arm_neg_abssi2"
9c08d1fa 4050 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
4051 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
bd5b4116 4052 (clobber (reg:CC CC_REGNUM))]
cffb2a26 4053 "TARGET_ARM"
ba6a3b2f 4054 "#"
4055 "&& reload_completed"
4056 [(const_int 0)]
4057 {
4058 /* if (which_alternative == 0) */
4059 if (REGNO (operands[0]) == REGNO (operands[1]))
4060 {
4061 /* Emit the pattern:
4062 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
4063 */
d1f9b275 4064 emit_insn (gen_rtx_SET (gen_rtx_REG (CCmode, CC_REGNUM),
ba6a3b2f 4065 gen_rtx_COMPARE (CCmode, operands[0], const0_rtx)));
4066 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
4067 gen_rtx_GT (SImode,
4068 gen_rtx_REG (CCmode, CC_REGNUM),
4069 const0_rtx),
d1f9b275 4070 gen_rtx_SET (operands[0],
ba6a3b2f 4071 (gen_rtx_MINUS (SImode,
4072 const0_rtx,
4073 operands[1])))));
4074 }
4075 else
4076 {
4077 /* Emit the pattern:
4078 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31
4079 */
d1f9b275 4080 emit_insn (gen_rtx_SET (operands[0],
ba6a3b2f 4081 gen_rtx_XOR (SImode,
4082 gen_rtx_ASHIFTRT (SImode,
4083 operands[1],
4084 GEN_INT (31)),
4085 operands[1])));
d1f9b275 4086 emit_insn (gen_rtx_SET (operands[0],
ba6a3b2f 4087 gen_rtx_MINUS (SImode,
4088 gen_rtx_ASHIFTRT (SImode,
4089 operands[1],
4090 GEN_INT (31)),
4091 operands[0])));
4092 }
4093 DONE;
4094 }
cffb2a26 4095 [(set_attr "conds" "clob,*")
331beb1a 4096 (set_attr "shift" "1")
2ad08b65 4097 (set_attr "predicable" "no, yes")
1b7da4ac 4098 (set_attr "length" "8")
4099 (set_attr "type" "multiple")]
cffb2a26 4100)
b11cae9e 4101
604f3a0a 4102(define_expand "abssf2"
3934ae0e 4103 [(set (match_operand:SF 0 "s_register_operand")
4104 (abs:SF (match_operand:SF 1 "s_register_operand")))]
25f905c2 4105 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 4106 "")
4107
604f3a0a 4108(define_expand "absdf2"
3934ae0e 4109 [(set (match_operand:DF 0 "s_register_operand")
4110 (abs:DF (match_operand:DF 1 "s_register_operand")))]
a50d7267 4111 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 4112 "")
4113
7db9af5d 4114(define_expand "sqrtsf2"
3934ae0e 4115 [(set (match_operand:SF 0 "s_register_operand")
4116 (sqrt:SF (match_operand:SF 1 "s_register_operand")))]
d7216193 4117 "TARGET_32BIT && TARGET_HARD_FLOAT"
7db9af5d 4118 "")
9c08d1fa 4119
7db9af5d 4120(define_expand "sqrtdf2"
3934ae0e 4121 [(set (match_operand:DF 0 "s_register_operand")
4122 (sqrt:DF (match_operand:DF 1 "s_register_operand")))]
994606f8 4123 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
7db9af5d 4124 "")
9c08d1fa 4125
cffb2a26 4126(define_expand "one_cmplsi2"
3934ae0e 4127 [(set (match_operand:SI 0 "s_register_operand")
4128 (not:SI (match_operand:SI 1 "s_register_operand")))]
cffb2a26 4129 "TARGET_EITHER"
b11cae9e 4130 ""
cffb2a26 4131)
4132
4133(define_insn "*arm_one_cmplsi2"
d952d547 4134 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4135 (not:SI (match_operand:SI 1 "s_register_operand" "l,r")))]
25f905c2 4136 "TARGET_32BIT"
cffb2a26 4137 "mvn%?\\t%0, %1"
d2a518d1 4138 [(set_attr "predicable" "yes")
d952d547 4139 (set_attr "predicable_short_it" "yes,no")
4140 (set_attr "arch" "t2,*")
4141 (set_attr "length" "4")
1aed5204 4142 (set_attr "type" "mvn_reg")]
cffb2a26 4143)
4144
f7fbdd4a 4145(define_insn "*notsi_compare0"
bd5b4116 4146 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 4147 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
4148 (const_int 0)))
4149 (set (match_operand:SI 0 "s_register_operand" "=r")
4150 (not:SI (match_dup 1)))]
25f905c2 4151 "TARGET_32BIT"
3ef90e77 4152 "mvns%?\\t%0, %1"
d2a518d1 4153 [(set_attr "conds" "set")
1aed5204 4154 (set_attr "type" "mvn_reg")]
cffb2a26 4155)
9c08d1fa 4156
f7fbdd4a 4157(define_insn "*notsi_compare0_scratch"
bd5b4116 4158 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 4159 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
4160 (const_int 0)))
4161 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 4162 "TARGET_32BIT"
3ef90e77 4163 "mvns%?\\t%0, %1"
d2a518d1 4164 [(set_attr "conds" "set")
1aed5204 4165 (set_attr "type" "mvn_reg")]
cffb2a26 4166)
b11cae9e 4167\f
4168;; Fixed <--> Floating conversion insns
4169
9b8516be 4170(define_expand "floatsihf2"
3934ae0e 4171 [(set (match_operand:HF 0 "general_operand")
4172 (float:HF (match_operand:SI 1 "general_operand")))]
9b8516be 4173 "TARGET_EITHER"
4174 "
4175 {
4176 rtx op1 = gen_reg_rtx (SFmode);
4177 expand_float (op1, operands[1], 0);
4178 op1 = convert_to_mode (HFmode, op1, 0);
4179 emit_move_insn (operands[0], op1);
4180 DONE;
4181 }"
4182)
4183
4184(define_expand "floatdihf2"
3934ae0e 4185 [(set (match_operand:HF 0 "general_operand")
4186 (float:HF (match_operand:DI 1 "general_operand")))]
9b8516be 4187 "TARGET_EITHER"
4188 "
4189 {
4190 rtx op1 = gen_reg_rtx (SFmode);
4191 expand_float (op1, operands[1], 0);
4192 op1 = convert_to_mode (HFmode, op1, 0);
4193 emit_move_insn (operands[0], op1);
4194 DONE;
4195 }"
4196)
4197
604f3a0a 4198(define_expand "floatsisf2"
3934ae0e 4199 [(set (match_operand:SF 0 "s_register_operand")
4200 (float:SF (match_operand:SI 1 "s_register_operand")))]
25f905c2 4201 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 4202 "
604f3a0a 4203")
4204
604f3a0a 4205(define_expand "floatsidf2"
3934ae0e 4206 [(set (match_operand:DF 0 "s_register_operand")
4207 (float:DF (match_operand:SI 1 "s_register_operand")))]
a50d7267 4208 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 4209 "
604f3a0a 4210")
4211
9b8516be 4212(define_expand "fix_trunchfsi2"
3934ae0e 4213 [(set (match_operand:SI 0 "general_operand")
4214 (fix:SI (fix:HF (match_operand:HF 1 "general_operand"))))]
9b8516be 4215 "TARGET_EITHER"
4216 "
4217 {
4218 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
4219 expand_fix (operands[0], op1, 0);
4220 DONE;
4221 }"
4222)
4223
4224(define_expand "fix_trunchfdi2"
3934ae0e 4225 [(set (match_operand:DI 0 "general_operand")
4226 (fix:DI (fix:HF (match_operand:HF 1 "general_operand"))))]
9b8516be 4227 "TARGET_EITHER"
4228 "
4229 {
4230 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
4231 expand_fix (operands[0], op1, 0);
4232 DONE;
4233 }"
4234)
4235
604f3a0a 4236(define_expand "fix_truncsfsi2"
3934ae0e 4237 [(set (match_operand:SI 0 "s_register_operand")
4238 (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand"))))]
25f905c2 4239 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 4240 "
604f3a0a 4241")
4242
604f3a0a 4243(define_expand "fix_truncdfsi2"
3934ae0e 4244 [(set (match_operand:SI 0 "s_register_operand")
4245 (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand"))))]
a50d7267 4246 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 4247 "
604f3a0a 4248")
4249
f544c6d2 4250;; Truncation insns
b11cae9e 4251
604f3a0a 4252(define_expand "truncdfsf2"
3934ae0e 4253 [(set (match_operand:SF 0 "s_register_operand")
604f3a0a 4254 (float_truncate:SF
3934ae0e 4255 (match_operand:DF 1 "s_register_operand")))]
a50d7267 4256 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 4257 ""
4258)
9b8516be 4259
539b44ee 4260;; DFmode to HFmode conversions on targets without a single-step hardware
4261;; instruction for it would have to go through SFmode. This is dangerous
4262;; as it introduces double rounding.
4263;;
4264;; Disable this pattern unless we are in an unsafe math mode, or we have
4265;; a single-step instruction.
4266
9b8516be 4267(define_expand "truncdfhf2"
3934ae0e 4268 [(set (match_operand:HF 0 "s_register_operand")
9b8516be 4269 (float_truncate:HF
3934ae0e 4270 (match_operand:DF 1 "s_register_operand")))]
539b44ee 4271 "(TARGET_EITHER && flag_unsafe_math_optimizations)
4272 || (TARGET_32BIT && TARGET_FP16_TO_DOUBLE)"
4273{
4274 /* We don't have a direct instruction for this, so we must be in
4275 an unsafe math mode, and going via SFmode. */
4276
4277 if (!(TARGET_32BIT && TARGET_FP16_TO_DOUBLE))
4278 {
4279 rtx op1;
4280 op1 = convert_to_mode (SFmode, operands[1], 0);
4281 op1 = convert_to_mode (HFmode, op1, 0);
4282 emit_move_insn (operands[0], op1);
4283 DONE;
4284 }
4285 /* Otherwise, we will pick this up as a single instruction with
4286 no intermediary rounding. */
4287}
9b8516be 4288)
b11cae9e 4289\f
9c08d1fa 4290;; Zero and sign extension instructions.
b11cae9e 4291
2e55c7de 4292(define_expand "zero_extend<mode>di2"
4293 [(set (match_operand:DI 0 "s_register_operand" "")
4294 (zero_extend:DI (match_operand:QHSI 1 "<qhs_zextenddi_op>" "")))]
848e66ac 4295 "TARGET_32BIT <qhs_zextenddi_cond>"
2e55c7de 4296 {
4297 rtx res_lo, res_hi, op0_lo, op0_hi;
4298 res_lo = gen_lowpart (SImode, operands[0]);
4299 res_hi = gen_highpart (SImode, operands[0]);
4300 if (can_create_pseudo_p ())
4301 {
4302 op0_lo = <MODE>mode == SImode ? operands[1] : gen_reg_rtx (SImode);
4303 op0_hi = gen_reg_rtx (SImode);
4304 }
4305 else
4306 {
4307 op0_lo = <MODE>mode == SImode ? operands[1] : res_lo;
4308 op0_hi = res_hi;
4309 }
4310 if (<MODE>mode != SImode)
4311 emit_insn (gen_rtx_SET (op0_lo,
4312 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
4313 emit_insn (gen_movsi (op0_hi, const0_rtx));
4314 if (res_lo != op0_lo)
4315 emit_move_insn (res_lo, op0_lo);
4316 if (res_hi != op0_hi)
4317 emit_move_insn (res_hi, op0_hi);
4318 DONE;
4319 }
25f905c2 4320)
4321
2e55c7de 4322(define_expand "extend<mode>di2"
4323 [(set (match_operand:DI 0 "s_register_operand" "")
4324 (sign_extend:DI (match_operand:QHSI 1 "<qhs_extenddi_op>" "")))]
848e66ac 4325 "TARGET_32BIT <qhs_sextenddi_cond>"
2e55c7de 4326 {
4327 rtx res_lo, res_hi, op0_lo, op0_hi;
4328 res_lo = gen_lowpart (SImode, operands[0]);
4329 res_hi = gen_highpart (SImode, operands[0]);
4330 if (can_create_pseudo_p ())
4331 {
4332 op0_lo = <MODE>mode == SImode ? operands[1] : gen_reg_rtx (SImode);
4333 op0_hi = gen_reg_rtx (SImode);
4334 }
4335 else
4336 {
4337 op0_lo = <MODE>mode == SImode ? operands[1] : res_lo;
4338 op0_hi = res_hi;
4339 }
4340 if (<MODE>mode != SImode)
4341 emit_insn (gen_rtx_SET (op0_lo,
4342 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
4343 emit_insn (gen_ashrsi3 (op0_hi, op0_lo, GEN_INT (31)));
4344 if (res_lo != op0_lo)
4345 emit_move_insn (res_lo, op0_lo);
4346 if (res_hi != op0_hi)
4347 emit_move_insn (res_hi, op0_hi);
4348 DONE;
4349 }
0d66636f 4350)
9c08d1fa 4351
848e66ac 4352;; Splits for all extensions to DImode
4353(define_split
4354 [(set (match_operand:DI 0 "s_register_operand" "")
4355 (zero_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
def2e672 4356 "TARGET_32BIT"
848e66ac 4357 [(set (match_dup 0) (match_dup 1))]
4358{
848e66ac 4359 rtx lo_part = gen_lowpart (SImode, operands[0]);
3754d046 4360 machine_mode src_mode = GET_MODE (operands[1]);
848e66ac 4361
def2e672 4362 if (src_mode == SImode)
4363 emit_move_insn (lo_part, operands[1]);
4364 else
4365 emit_insn (gen_rtx_SET (lo_part,
4366 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
848e66ac 4367 operands[0] = gen_highpart (SImode, operands[0]);
4368 operands[1] = const0_rtx;
4369})
9c08d1fa 4370
848e66ac 4371(define_split
25f905c2 4372 [(set (match_operand:DI 0 "s_register_operand" "")
848e66ac 4373 (sign_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
def2e672 4374 "TARGET_32BIT"
848e66ac 4375 [(set (match_dup 0) (ashiftrt:SI (match_dup 1) (const_int 31)))]
4376{
4377 rtx lo_part = gen_lowpart (SImode, operands[0]);
3754d046 4378 machine_mode src_mode = GET_MODE (operands[1]);
25f905c2 4379
def2e672 4380 if (src_mode == SImode)
4381 emit_move_insn (lo_part, operands[1]);
4382 else
4383 emit_insn (gen_rtx_SET (lo_part,
4384 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
4385 operands[1] = lo_part;
848e66ac 4386 operands[0] = gen_highpart (SImode, operands[0]);
4387})
9c08d1fa 4388
4389(define_expand "zero_extendhisi2"
3934ae0e 4390 [(set (match_operand:SI 0 "s_register_operand")
4391 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand")))]
cffb2a26 4392 "TARGET_EITHER"
ef51b8e1 4393{
4394 if (TARGET_ARM && !arm_arch4 && MEM_P (operands[1]))
f7fbdd4a 4395 {
ef51b8e1 4396 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
4397 DONE;
25f7a26e 4398 }
ef51b8e1 4399 if (!arm_arch6 && !MEM_P (operands[1]))
4400 {
4401 rtx t = gen_lowpart (SImode, operands[1]);
4402 rtx tmp = gen_reg_rtx (SImode);
4403 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
4404 emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (16)));
4405 DONE;
4406 }
4407})
9c08d1fa 4408
ef51b8e1 4409(define_split
b146458f 4410 [(set (match_operand:SI 0 "s_register_operand" "")
4411 (zero_extend:SI (match_operand:HI 1 "s_register_operand" "")))]
ef51b8e1 4412 "!TARGET_THUMB2 && !arm_arch6"
4413 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4414 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 16)))]
4415{
4416 operands[2] = gen_lowpart (SImode, operands[1]);
4417})
4418
cffb2a26 4419(define_insn "*arm_zero_extendhisi2"
ef51b8e1 4420 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4421 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 4422 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 4423 "@
4424 #
3ef90e77 4425 ldrh%?\\t%0, %1"
d82e788e 4426 [(set_attr "type" "alu_shift_reg,load_byte")
848e66ac 4427 (set_attr "predicable" "yes")]
cffb2a26 4428)
f7fbdd4a 4429
a2cd141b 4430(define_insn "*arm_zero_extendhisi2_v6"
4431 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
e3f4ccee 4432 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,Uh")))]
a2cd141b 4433 "TARGET_ARM && arm_arch6"
4434 "@
4435 uxth%?\\t%0, %1
3ef90e77 4436 ldrh%?\\t%0, %1"
65f68e55 4437 [(set_attr "predicable" "yes")
6b6abc9c 4438 (set_attr "type" "extend,load_byte")]
a2cd141b 4439)
4440
4441(define_insn "*arm_zero_extendhisi2addsi"
4442 [(set (match_operand:SI 0 "s_register_operand" "=r")
4443 (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
4444 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4445 "TARGET_INT_SIMD"
a2cd141b 4446 "uxtah%?\\t%0, %2, %1"
d82e788e 4447 [(set_attr "type" "alu_shift_reg")
8bdfd6ed 4448 (set_attr "predicable" "yes")]
a2cd141b 4449)
4450
87b22bf7 4451(define_expand "zero_extendqisi2"
3934ae0e 4452 [(set (match_operand:SI 0 "s_register_operand")
4453 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand")))]
cffb2a26 4454 "TARGET_EITHER"
ef51b8e1 4455{
0438d37f 4456 if (TARGET_ARM && !arm_arch6 && !MEM_P (operands[1]))
87b22bf7 4457 {
ef51b8e1 4458 emit_insn (gen_andsi3 (operands[0],
4459 gen_lowpart (SImode, operands[1]),
4460 GEN_INT (255)));
4461 DONE;
4462 }
4463 if (!arm_arch6 && !MEM_P (operands[1]))
4464 {
4465 rtx t = gen_lowpart (SImode, operands[1]);
4466 rtx tmp = gen_reg_rtx (SImode);
4467 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
4468 emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (24)));
4469 DONE;
4470 }
4471})
cffb2a26 4472
ef51b8e1 4473(define_split
b146458f 4474 [(set (match_operand:SI 0 "s_register_operand" "")
4475 (zero_extend:SI (match_operand:QI 1 "s_register_operand" "")))]
ef51b8e1 4476 "!arm_arch6"
4477 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
4478 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 24)))]
4479{
4480 operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
4481 if (TARGET_ARM)
4482 {
4483 emit_insn (gen_andsi3 (operands[0], operands[2], GEN_INT (255)));
87b22bf7 4484 DONE;
4485 }
ef51b8e1 4486})
9c08d1fa 4487
cffb2a26 4488(define_insn "*arm_zero_extendqisi2"
ef51b8e1 4489 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4490 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 4491 "TARGET_ARM && !arm_arch6"
ef51b8e1 4492 "@
4493 #
3ef90e77 4494 ldrb%?\\t%0, %1\\t%@ zero_extendqisi2"
ef51b8e1 4495 [(set_attr "length" "8,4")
d82e788e 4496 (set_attr "type" "alu_shift_reg,load_byte")
848e66ac 4497 (set_attr "predicable" "yes")]
cffb2a26 4498)
87b22bf7 4499
a2cd141b 4500(define_insn "*arm_zero_extendqisi2_v6"
4501 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
e3f4ccee 4502 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,Uh")))]
a2cd141b 4503 "TARGET_ARM && arm_arch6"
4504 "@
3ef90e77 4505 uxtb%?\\t%0, %1
4506 ldrb%?\\t%0, %1\\t%@ zero_extendqisi2"
6b6abc9c 4507 [(set_attr "type" "extend,load_byte")
848e66ac 4508 (set_attr "predicable" "yes")]
a2cd141b 4509)
4510
4511(define_insn "*arm_zero_extendqisi2addsi"
4512 [(set (match_operand:SI 0 "s_register_operand" "=r")
4513 (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
4514 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4515 "TARGET_INT_SIMD"
a2cd141b 4516 "uxtab%?\\t%0, %2, %1"
4517 [(set_attr "predicable" "yes")
d82e788e 4518 (set_attr "type" "alu_shift_reg")]
a2cd141b 4519)
4520
87b22bf7 4521(define_split
4522 [(set (match_operand:SI 0 "s_register_operand" "")
4523 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
4524 (clobber (match_operand:SI 2 "s_register_operand" ""))]
0438d37f 4525 "TARGET_32BIT && (!MEM_P (operands[1])) && ! BYTES_BIG_ENDIAN"
87b22bf7 4526 [(set (match_dup 2) (match_dup 1))
4527 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
cffb2a26 4528 ""
4529)
9c08d1fa 4530
8a4d25d6 4531(define_split
4532 [(set (match_operand:SI 0 "s_register_operand" "")
4533 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 3)))
4534 (clobber (match_operand:SI 2 "s_register_operand" ""))]
0438d37f 4535 "TARGET_32BIT && (!MEM_P (operands[1])) && BYTES_BIG_ENDIAN"
8a4d25d6 4536 [(set (match_dup 2) (match_dup 1))
4537 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
4538 ""
4539)
4540
1c274529 4541
4542(define_split
4543 [(set (match_operand:SI 0 "s_register_operand" "")
9b23f0a7 4544 (IOR_XOR:SI (and:SI (ashift:SI
1c274529 4545 (match_operand:SI 1 "s_register_operand" "")
4546 (match_operand:SI 2 "const_int_operand" ""))
4547 (match_operand:SI 3 "const_int_operand" ""))
4548 (zero_extend:SI
4549 (match_operator 5 "subreg_lowpart_operator"
4550 [(match_operand:SI 4 "s_register_operand" "")]))))]
4551 "TARGET_32BIT
8c4e8755 4552 && (UINTVAL (operands[3])
1c274529 4553 == (GET_MODE_MASK (GET_MODE (operands[5]))
4554 & (GET_MODE_MASK (GET_MODE (operands[5]))
4555 << (INTVAL (operands[2])))))"
9b23f0a7 4556 [(set (match_dup 0) (IOR_XOR:SI (ashift:SI (match_dup 1) (match_dup 2))
1c274529 4557 (match_dup 4)))
4558 (set (match_dup 0) (zero_extend:SI (match_dup 5)))]
4559 "operands[5] = gen_lowpart (GET_MODE (operands[5]), operands[0]);"
4560)
4561
f7fbdd4a 4562(define_insn "*compareqi_eq0"
bd5b4116 4563 [(set (reg:CC_Z CC_REGNUM)
206ee9a2 4564 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
87b22bf7 4565 (const_int 0)))]
25f905c2 4566 "TARGET_32BIT"
596e5e8f 4567 "tst%?\\t%0, #255"
4568 [(set_attr "conds" "set")
d952d547 4569 (set_attr "predicable" "yes")
1b7da4ac 4570 (set_attr "type" "logic_imm")]
cffb2a26 4571)
b11cae9e 4572
b11cae9e 4573(define_expand "extendhisi2"
3934ae0e 4574 [(set (match_operand:SI 0 "s_register_operand")
4575 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand")))]
cffb2a26 4576 "TARGET_EITHER"
ef51b8e1 4577{
4578 if (TARGET_THUMB1)
4579 {
4580 emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1]));
4581 DONE;
4582 }
4583 if (MEM_P (operands[1]) && TARGET_ARM && !arm_arch4)
4584 {
4585 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
4586 DONE;
4587 }
ed29c566 4588
ef51b8e1 4589 if (!arm_arch6 && !MEM_P (operands[1]))
4590 {
4591 rtx t = gen_lowpart (SImode, operands[1]);
4592 rtx tmp = gen_reg_rtx (SImode);
4593 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
4594 emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (16)));
4595 DONE;
4596 }
4597})
cffb2a26 4598
ef51b8e1 4599(define_split
4600 [(parallel
4601 [(set (match_operand:SI 0 "register_operand" "")
4602 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))
4603 (clobber (match_scratch:SI 2 ""))])]
4604 "!arm_arch6"
4605 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4606 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
4607{
4608 operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
4609})
25f7a26e 4610
25f905c2 4611;; This pattern will only be used when ldsh is not available
25f7a26e 4612(define_expand "extendhisi2_mem"
eab14235 4613 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 4614 (set (match_dup 3)
eab14235 4615 (zero_extend:SI (match_dup 7)))
25f7a26e 4616 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
4617 (set (match_operand:SI 0 "" "")
4618 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
cffb2a26 4619 "TARGET_ARM"
25f7a26e 4620 "
215b30b3 4621 {
4622 rtx mem1, mem2;
4623 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4624
788fcce0 4625 mem1 = change_address (operands[1], QImode, addr);
29c05e22 4626 mem2 = change_address (operands[1], QImode,
4627 plus_constant (Pmode, addr, 1));
215b30b3 4628 operands[0] = gen_lowpart (SImode, operands[0]);
4629 operands[1] = mem1;
4630 operands[2] = gen_reg_rtx (SImode);
4631 operands[3] = gen_reg_rtx (SImode);
4632 operands[6] = gen_reg_rtx (SImode);
4633 operands[7] = mem2;
25f7a26e 4634
215b30b3 4635 if (BYTES_BIG_ENDIAN)
4636 {
4637 operands[4] = operands[2];
4638 operands[5] = operands[3];
4639 }
4640 else
4641 {
4642 operands[4] = operands[3];
4643 operands[5] = operands[2];
4644 }
4645 }"
4646)
b11cae9e 4647
ef51b8e1 4648(define_split
4649 [(set (match_operand:SI 0 "register_operand" "")
4650 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
4651 "!arm_arch6"
4652 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4653 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
4654{
4655 operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
4656})
4657
a2cd141b 4658(define_insn "*arm_extendhisi2"
ef51b8e1 4659 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
e3f4ccee 4660 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,Uh")))]
a2cd141b 4661 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 4662 "@
4663 #
3ef90e77 4664 ldrsh%?\\t%0, %1"
ef51b8e1 4665 [(set_attr "length" "8,4")
d82e788e 4666 (set_attr "type" "alu_shift_reg,load_byte")
e3f4ccee 4667 (set_attr "predicable" "yes")]
cffb2a26 4668)
f7fbdd4a 4669
25f905c2 4670;; ??? Check Thumb-2 pool range
a2cd141b 4671(define_insn "*arm_extendhisi2_v6"
4672 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
e3f4ccee 4673 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,Uh")))]
25f905c2 4674 "TARGET_32BIT && arm_arch6"
a2cd141b 4675 "@
4676 sxth%?\\t%0, %1
3ef90e77 4677 ldrsh%?\\t%0, %1"
6b6abc9c 4678 [(set_attr "type" "extend,load_byte")
8bdfd6ed 4679 (set_attr "predicable" "yes")]
a2cd141b 4680)
4681
4682(define_insn "*arm_extendhisi2addsi"
4683 [(set (match_operand:SI 0 "s_register_operand" "=r")
4684 (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
4685 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4686 "TARGET_INT_SIMD"
a2cd141b 4687 "sxtah%?\\t%0, %2, %1"
1b7da4ac 4688 [(set_attr "type" "alu_shift_reg")]
a2cd141b 4689)
4690
c8f69309 4691(define_expand "extendqihi2"
4692 [(set (match_dup 2)
3934ae0e 4693 (ashift:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op")
c8f69309 4694 (const_int 24)))
3934ae0e 4695 (set (match_operand:HI 0 "s_register_operand")
c8f69309 4696 (ashiftrt:SI (match_dup 2)
4697 (const_int 24)))]
cffb2a26 4698 "TARGET_ARM"
c8f69309 4699 "
215b30b3 4700 {
0438d37f 4701 if (arm_arch4 && MEM_P (operands[1]))
215b30b3 4702 {
d1f9b275 4703 emit_insn (gen_rtx_SET (operands[0],
215b30b3 4704 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
4705 DONE;
4706 }
4707 if (!s_register_operand (operands[1], QImode))
4708 operands[1] = copy_to_mode_reg (QImode, operands[1]);
4709 operands[0] = gen_lowpart (SImode, operands[0]);
4710 operands[1] = gen_lowpart (SImode, operands[1]);
4711 operands[2] = gen_reg_rtx (SImode);
4712 }"
4713)
f7fbdd4a 4714
25f905c2 4715(define_insn "*arm_extendqihi_insn"
b4e8a300 4716 [(set (match_operand:HI 0 "s_register_operand" "=r")
bed7d9a5 4717 (sign_extend:HI (match_operand:QI 1 "arm_extendqisi_mem_op" "Uq")))]
cffb2a26 4718 "TARGET_ARM && arm_arch4"
3ef90e77 4719 "ldrsb%?\\t%0, %1"
a2cd141b 4720 [(set_attr "type" "load_byte")
e3f4ccee 4721 (set_attr "predicable" "yes")]
cffb2a26 4722)
3fc2009e 4723
b11cae9e 4724(define_expand "extendqisi2"
3934ae0e 4725 [(set (match_operand:SI 0 "s_register_operand")
4726 (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op")))]
cffb2a26 4727 "TARGET_EITHER"
ef51b8e1 4728{
4729 if (!arm_arch4 && MEM_P (operands[1]))
4730 operands[1] = copy_to_mode_reg (QImode, operands[1]);
a2cd141b 4731
ef51b8e1 4732 if (!arm_arch6 && !MEM_P (operands[1]))
4733 {
4734 rtx t = gen_lowpart (SImode, operands[1]);
4735 rtx tmp = gen_reg_rtx (SImode);
4736 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
4737 emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (24)));
4738 DONE;
4739 }
4740})
a2cd141b 4741
ef51b8e1 4742(define_split
4743 [(set (match_operand:SI 0 "register_operand" "")
4744 (sign_extend:SI (match_operand:QI 1 "register_operand" "")))]
4745 "!arm_arch6"
4746 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
4747 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))]
4748{
4749 operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
4750})
f7fbdd4a 4751
a2cd141b 4752(define_insn "*arm_extendqisi"
ef51b8e1 4753 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4754 (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
a2cd141b 4755 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 4756 "@
4757 #
3ef90e77 4758 ldrsb%?\\t%0, %1"
ef51b8e1 4759 [(set_attr "length" "8,4")
d82e788e 4760 (set_attr "type" "alu_shift_reg,load_byte")
e3f4ccee 4761 (set_attr "predicable" "yes")]
cffb2a26 4762)
3fc2009e 4763
a2cd141b 4764(define_insn "*arm_extendqisi_v6"
4765 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
bed7d9a5 4766 (sign_extend:SI
4767 (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
a2cd141b 4768 "TARGET_ARM && arm_arch6"
b4e8a300 4769 "@
4770 sxtb%?\\t%0, %1
3ef90e77 4771 ldrsb%?\\t%0, %1"
6b6abc9c 4772 [(set_attr "type" "extend,load_byte")
e3f4ccee 4773 (set_attr "predicable" "yes")]
a2cd141b 4774)
4775
4776(define_insn "*arm_extendqisi2addsi"
4777 [(set (match_operand:SI 0 "s_register_operand" "=r")
4778 (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
4779 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4780 "TARGET_INT_SIMD"
a2cd141b 4781 "sxtab%?\\t%0, %2, %1"
d82e788e 4782 [(set_attr "type" "alu_shift_reg")
8bdfd6ed 4783 (set_attr "predicable" "yes")]
a2cd141b 4784)
4785
856adc5d 4786(define_insn "arm_<sup>xtb16"
4787 [(set (match_operand:SI 0 "s_register_operand" "=r")
4788 (unspec:SI
4789 [(match_operand:SI 1 "s_register_operand" "r")] USXTB16))]
4790 "TARGET_INT_SIMD"
4791 "<sup>xtb16%?\\t%0, %1"
4792 [(set_attr "predicable" "yes")
4793 (set_attr "type" "alu_dsp_reg")])
4794
4795(define_insn "arm_<simd32_op>"
4796 [(set (match_operand:SI 0 "s_register_operand" "=r")
4797 (unspec:SI
4798 [(match_operand:SI 1 "s_register_operand" "r")
4799 (match_operand:SI 2 "s_register_operand" "r")] SIMD32_NOGE_BINOP))]
4800 "TARGET_INT_SIMD"
4801 "<simd32_op>%?\\t%0, %1, %2"
4802 [(set_attr "predicable" "yes")
4803 (set_attr "type" "alu_dsp_reg")])
4804
4805(define_insn "arm_usada8"
4806 [(set (match_operand:SI 0 "s_register_operand" "=r")
4807 (unspec:SI
4808 [(match_operand:SI 1 "s_register_operand" "r")
4809 (match_operand:SI 2 "s_register_operand" "r")
4810 (match_operand:SI 3 "s_register_operand" "r")] UNSPEC_USADA8))]
4811 "TARGET_INT_SIMD"
4812 "usada8%?\\t%0, %1, %2, %3"
4813 [(set_attr "predicable" "yes")
4814 (set_attr "type" "alu_dsp_reg")])
4815
433c7595 4816(define_insn "arm_<simd32_op>"
4817 [(set (match_operand:DI 0 "s_register_operand" "=r")
4818 (unspec:DI
4819 [(match_operand:SI 1 "s_register_operand" "r")
4820 (match_operand:SI 2 "s_register_operand" "r")
4821 (match_operand:DI 3 "s_register_operand" "0")] SIMD32_DIMODE))]
4822 "TARGET_INT_SIMD"
4823 "<simd32_op>%?\\t%Q0, %R0, %1, %2"
4824 [(set_attr "predicable" "yes")
4825 (set_attr "type" "smlald")])
4826
caedf871 4827(define_expand "extendsfdf2"
3934ae0e 4828 [(set (match_operand:DF 0 "s_register_operand")
4829 (float_extend:DF (match_operand:SF 1 "s_register_operand")))]
a50d7267 4830 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
caedf871 4831 ""
4832)
9b8516be 4833
539b44ee 4834;; HFmode -> DFmode conversions where we don't have an instruction for it
4835;; must go through SFmode.
4836;;
4837;; This is always safe for an extend.
4838
9b8516be 4839(define_expand "extendhfdf2"
3934ae0e 4840 [(set (match_operand:DF 0 "s_register_operand")
4841 (float_extend:DF (match_operand:HF 1 "s_register_operand")))]
9b8516be 4842 "TARGET_EITHER"
539b44ee 4843{
4844 /* We don't have a direct instruction for this, so go via SFmode. */
4845 if (!(TARGET_32BIT && TARGET_FP16_TO_DOUBLE))
4846 {
4847 rtx op1;
4848 op1 = convert_to_mode (SFmode, operands[1], 0);
4849 op1 = convert_to_mode (DFmode, op1, 0);
4850 emit_insn (gen_movdf (operands[0], op1));
4851 DONE;
4852 }
4853 /* Otherwise, we're done producing RTL and will pick up the correct
4854 pattern to do this with one rounding-step in a single instruction. */
4855}
9b8516be 4856)
b11cae9e 4857\f
4858;; Move insns (including loads and stores)
4859
4860;; XXX Just some ideas about movti.
9c08d1fa 4861;; I don't think these are a good idea on the arm, there just aren't enough
4862;; registers
b11cae9e 4863;;(define_expand "loadti"
3934ae0e 4864;; [(set (match_operand:TI 0 "s_register_operand")
4865;; (mem:TI (match_operand:SI 1 "address_operand")))]
b11cae9e 4866;; "" "")
4867
4868;;(define_expand "storeti"
3934ae0e 4869;; [(set (mem:TI (match_operand:TI 0 "address_operand"))
4870;; (match_operand:TI 1 "s_register_operand"))]
b11cae9e 4871;; "" "")
4872
4873;;(define_expand "movti"
3934ae0e 4874;; [(set (match_operand:TI 0 "general_operand")
4875;; (match_operand:TI 1 "general_operand"))]
b11cae9e 4876;; ""
4877;; "
4878;;{
4879;; rtx insn;
4880;;
0438d37f 4881;; if (MEM_P (operands[0]) && MEM_P (operands[1]))
b11cae9e 4882;; operands[1] = copy_to_reg (operands[1]);
0438d37f 4883;; if (MEM_P (operands[0]))
b11cae9e 4884;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
0438d37f 4885;; else if (MEM_P (operands[1]))
b11cae9e 4886;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
4887;; else
4888;; FAIL;
4889;;
4890;; emit_insn (insn);
4891;; DONE;
4892;;}")
4893
a2f10574 4894;; Recognize garbage generated above.
b11cae9e 4895
4896;;(define_insn ""
4897;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
4898;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
4899;; ""
4900;; "*
4901;; {
4902;; register mem = (which_alternative < 3);
0d66636f 4903;; register const char *template;
b11cae9e 4904;;
4905;; operands[mem] = XEXP (operands[mem], 0);
4906;; switch (which_alternative)
4907;; {
4908;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
4909;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
4910;; case 2: template = \"ldmia\\t%1, %M0\"; break;
4911;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
4912;; case 4: template = \"stmia\\t%0!, %M1\"; break;
4913;; case 5: template = \"stmia\\t%0, %M1\"; break;
4914;; }
e2348bcb 4915;; output_asm_insn (template, operands);
4916;; return \"\";
b11cae9e 4917;; }")
4918
cffb2a26 4919(define_expand "movdi"
3934ae0e 4920 [(set (match_operand:DI 0 "general_operand")
4921 (match_operand:DI 1 "general_operand"))]
cffb2a26 4922 "TARGET_EITHER"
4923 "
e723310d 4924 gcc_checking_assert (aligned_operand (operands[0], DImode));
4925 gcc_checking_assert (aligned_operand (operands[1], DImode));
e1ba4a27 4926 if (can_create_pseudo_p ())
cffb2a26 4927 {
0438d37f 4928 if (!REG_P (operands[0]))
b2778788 4929 operands[1] = force_reg (DImode, operands[1]);
cffb2a26 4930 }
6b97fdcc 4931 if (REG_P (operands[0]) && REGNO (operands[0]) <= LAST_ARM_REGNUM
b395382f 4932 && !targetm.hard_regno_mode_ok (REGNO (operands[0]), DImode))
4f0e25ca 4933 {
4934 /* Avoid LDRD's into an odd-numbered register pair in ARM state
4935 when expanding function calls. */
4936 gcc_assert (can_create_pseudo_p ());
4937 if (MEM_P (operands[1]) && MEM_VOLATILE_P (operands[1]))
4938 {
4939 /* Perform load into legal reg pair first, then move. */
4940 rtx reg = gen_reg_rtx (DImode);
4941 emit_insn (gen_movdi (reg, operands[1]));
4942 operands[1] = reg;
4943 }
4944 emit_move_insn (gen_lowpart (SImode, operands[0]),
4945 gen_lowpart (SImode, operands[1]));
4946 emit_move_insn (gen_highpart (SImode, operands[0]),
4947 gen_highpart (SImode, operands[1]));
4948 DONE;
4949 }
6b97fdcc 4950 else if (REG_P (operands[1]) && REGNO (operands[1]) <= LAST_ARM_REGNUM
b395382f 4951 && !targetm.hard_regno_mode_ok (REGNO (operands[1]), DImode))
4f0e25ca 4952 {
4953 /* Avoid STRD's from an odd-numbered register pair in ARM state
4954 when expanding function prologue. */
4955 gcc_assert (can_create_pseudo_p ());
4956 rtx split_dest = (MEM_P (operands[0]) && MEM_VOLATILE_P (operands[0]))
4957 ? gen_reg_rtx (DImode)
4958 : operands[0];
4959 emit_move_insn (gen_lowpart (SImode, split_dest),
4960 gen_lowpart (SImode, operands[1]));
4961 emit_move_insn (gen_highpart (SImode, split_dest),
4962 gen_highpart (SImode, operands[1]));
4963 if (split_dest != operands[0])
4964 emit_insn (gen_movdi (operands[0], split_dest));
4965 DONE;
4966 }
cffb2a26 4967 "
4968)
b11cae9e 4969
cffb2a26 4970(define_insn "*arm_movdi"
8f1c7041 4971 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, r, m")
4972 (match_operand:DI 1 "di_operand" "rDa,Db,Dc,mi,r"))]
cde1623a 4973 "TARGET_32BIT
d7216193 4974 && !(TARGET_HARD_FLOAT)
b2778788 4975 && !TARGET_IWMMXT
4976 && ( register_operand (operands[0], DImode)
4977 || register_operand (operands[1], DImode))"
b11cae9e 4978 "*
d51f92df 4979 switch (which_alternative)
4980 {
4981 case 0:
4982 case 1:
4983 case 2:
4984 return \"#\";
581f16e5 4985 case 3:
4986 /* Cannot load it directly, split to load it via MOV / MOVT. */
4987 if (!MEM_P (operands[1]) && arm_disable_literal_pool)
4988 return \"#\";
4989 /* Fall through. */
d51f92df 4990 default:
26ff80c0 4991 return output_move_double (operands, true, NULL);
d51f92df 4992 }
cffb2a26 4993 "
359a6e9f 4994 [(set_attr "length" "8,12,16,8,8")
9f2c2a36 4995 (set_attr "type" "multiple,multiple,multiple,load_8,store_8")
cde1623a 4996 (set_attr "arm_pool_range" "*,*,*,1020,*")
8848d797 4997 (set_attr "arm_neg_pool_range" "*,*,*,1004,*")
42e1de19 4998 (set_attr "thumb2_pool_range" "*,*,*,4094,*")
cde1623a 4999 (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
cffb2a26 5000)
5001
d51f92df 5002(define_split
5003 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
e6dd3afa 5004 (match_operand:ANY64 1 "immediate_operand" ""))]
25f905c2 5005 "TARGET_32BIT
d51f92df 5006 && reload_completed
a869c476 5007 && (arm_disable_literal_pool
5008 || (arm_const_double_inline_cost (operands[1])
5009 <= arm_max_const_double_inline_cost ()))"
d51f92df 5010 [(const_int 0)]
5011 "
5012 arm_split_constant (SET, SImode, curr_insn,
5013 INTVAL (gen_lowpart (SImode, operands[1])),
5014 gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
5015 arm_split_constant (SET, SImode, curr_insn,
5016 INTVAL (gen_highpart_mode (SImode,
5017 GET_MODE (operands[0]),
5018 operands[1])),
5019 gen_highpart (SImode, operands[0]), NULL_RTX, 0);
5020 DONE;
5021 "
5022)
5023
e5ba9289 5024; If optimizing for size, or if we have load delay slots, then
5025; we want to split the constant into two separate operations.
5026; In both cases this may split a trivial part into a single data op
5027; leaving a single complex constant to load. We can also get longer
5028; offsets in a LDR which means we get better chances of sharing the pool
5029; entries. Finally, we can normally do a better job of scheduling
5030; LDR instructions than we can with LDM.
5031; This pattern will only match if the one above did not.
5032(define_split
5033 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
5034 (match_operand:ANY64 1 "const_double_operand" ""))]
5035 "TARGET_ARM && reload_completed
5036 && arm_const_double_by_parts (operands[1])"
5037 [(set (match_dup 0) (match_dup 1))
5038 (set (match_dup 2) (match_dup 3))]
5039 "
5040 operands[2] = gen_highpart (SImode, operands[0]);
5041 operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
5042 operands[1]);
5043 operands[0] = gen_lowpart (SImode, operands[0]);
5044 operands[1] = gen_lowpart (SImode, operands[1]);
5045 "
5046)
5047
d51f92df 5048(define_split
5049 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
5050 (match_operand:ANY64 1 "arm_general_register_operand" ""))]
5051 "TARGET_EITHER && reload_completed"
5052 [(set (match_dup 0) (match_dup 1))
5053 (set (match_dup 2) (match_dup 3))]
5054 "
5055 operands[2] = gen_highpart (SImode, operands[0]);
5056 operands[3] = gen_highpart (SImode, operands[1]);
5057 operands[0] = gen_lowpart (SImode, operands[0]);
5058 operands[1] = gen_lowpart (SImode, operands[1]);
5059
5060 /* Handle a partial overlap. */
5061 if (rtx_equal_p (operands[0], operands[3]))
5062 {
5063 rtx tmp0 = operands[0];
5064 rtx tmp1 = operands[1];
5065
5066 operands[0] = operands[2];
5067 operands[1] = operands[3];
5068 operands[2] = tmp0;
5069 operands[3] = tmp1;
5070 }
5071 "
5072)
5073
a8a3b539 5074;; We can't actually do base+index doubleword loads if the index and
5075;; destination overlap. Split here so that we at least have chance to
5076;; schedule.
5077(define_split
5078 [(set (match_operand:DI 0 "s_register_operand" "")
5079 (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
5080 (match_operand:SI 2 "s_register_operand" ""))))]
5081 "TARGET_LDRD
5082 && reg_overlap_mentioned_p (operands[0], operands[1])
5083 && reg_overlap_mentioned_p (operands[0], operands[2])"
5084 [(set (match_dup 4)
5085 (plus:SI (match_dup 1)
5086 (match_dup 2)))
5087 (set (match_dup 0)
5088 (mem:DI (match_dup 4)))]
5089 "
5090 operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
5091 "
5092)
5093
9c08d1fa 5094(define_expand "movsi"
3934ae0e 5095 [(set (match_operand:SI 0 "general_operand")
5096 (match_operand:SI 1 "general_operand"))]
cffb2a26 5097 "TARGET_EITHER"
9c08d1fa 5098 "
befb0bac 5099 {
e348ff3e 5100 rtx base, offset, tmp;
5101
e723310d 5102 gcc_checking_assert (aligned_operand (operands[0], SImode));
5103 gcc_checking_assert (aligned_operand (operands[1], SImode));
6e291830 5104 if (TARGET_32BIT || TARGET_HAVE_MOVT)
9c08d1fa 5105 {
674a8f0b 5106 /* Everything except mem = const or mem = mem can be done easily. */
0438d37f 5107 if (MEM_P (operands[0]))
cffb2a26 5108 operands[1] = force_reg (SImode, operands[1]);
a2cd141b 5109 if (arm_general_register_operand (operands[0], SImode)
0438d37f 5110 && CONST_INT_P (operands[1])
cffb2a26 5111 && !(const_ok_for_arm (INTVAL (operands[1]))
5112 || const_ok_for_arm (~INTVAL (operands[1]))))
5113 {
17202aa5 5114 if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[1]), SET))
5115 {
5116 emit_insn (gen_rtx_SET (operands[0], operands[1]));
5117 DONE;
5118 }
5119 else
5120 {
5121 arm_split_constant (SET, SImode, NULL_RTX,
5122 INTVAL (operands[1]), operands[0], NULL_RTX,
5123 optimize && can_create_pseudo_p ());
5124 DONE;
5125 }
cffb2a26 5126 }
5127 }
75612252 5128 else /* Target doesn't have MOVT... */
cffb2a26 5129 {
e1ba4a27 5130 if (can_create_pseudo_p ())
cffb2a26 5131 {
0438d37f 5132 if (!REG_P (operands[0]))
cffb2a26 5133 operands[1] = force_reg (SImode, operands[1]);
5134 }
9c08d1fa 5135 }
f655717d 5136
eeb22b66 5137 split_const (operands[1], &base, &offset);
5138 if (INTVAL (offset) != 0
5139 && targetm.cannot_force_const_mem (SImode, operands[1]))
e348ff3e 5140 {
eeb22b66 5141 tmp = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
5142 emit_move_insn (tmp, base);
5143 emit_insn (gen_addsi3 (operands[0], tmp, offset));
5144 DONE;
e348ff3e 5145 }
5146
eeb22b66 5147 tmp = can_create_pseudo_p () ? NULL_RTX : operands[0];
5148
f655717d 5149 /* Recognize the case where operand[1] is a reference to thread-local
eeb22b66 5150 data and load its address to a register. Offsets have been split off
5151 already. */
f655717d 5152 if (arm_tls_referenced_p (operands[1]))
eeb22b66 5153 operands[1] = legitimize_tls_address (operands[1], tmp);
f655717d 5154 else if (flag_pic
5155 && (CONSTANT_P (operands[1])
5156 || symbol_mentioned_p (operands[1])
5157 || label_mentioned_p (operands[1])))
eeb22b66 5158 operands[1] =
5159 legitimize_pic_address (operands[1], SImode, tmp, NULL_RTX, false);
befb0bac 5160 }
215b30b3 5161 "
5162)
9c08d1fa 5163
d0e6a121 5164;; The ARM LO_SUM and HIGH are backwards - HIGH sets the low bits, and
5165;; LO_SUM adds in the high bits. Fortunately these are opaque operations
5166;; so this does not matter.
5167(define_insn "*arm_movt"
417e5cc5 5168 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r")
5169 (lo_sum:SI (match_operand:SI 1 "nonimmediate_operand" "0,0")
5170 (match_operand:SI 2 "general_operand" "i,i")))]
60a48e7d 5171 "TARGET_HAVE_MOVT && arm_valid_symbolic_address_p (operands[2])"
417e5cc5 5172 "@
5173 movt%?\t%0, #:upper16:%c2
5174 movt\t%0, #:upper16:%c2"
5175 [(set_attr "arch" "32,v8mb")
5176 (set_attr "predicable" "yes")
1b7da4ac 5177 (set_attr "length" "4")
282b4c75 5178 (set_attr "type" "alu_sreg")]
d0e6a121 5179)
5180
cffb2a26 5181(define_insn "*arm_movsi_insn"
aaa37ad6 5182 [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,rk,m")
110eae03 5183 (match_operand:SI 1 "general_operand" "rk, I,K,j,mi,rk"))]
d7216193 5184 "TARGET_ARM && !TARGET_IWMMXT && !TARGET_HARD_FLOAT
cffb2a26 5185 && ( register_operand (operands[0], SImode)
5186 || register_operand (operands[1], SImode))"
f7fbdd4a 5187 "@
aaa37ad6 5188 mov%?\\t%0, %1
f7fbdd4a 5189 mov%?\\t%0, %1
5190 mvn%?\\t%0, #%B1
25f905c2 5191 movw%?\\t%0, %1
f7fbdd4a 5192 ldr%?\\t%0, %1
5193 str%?\\t%1, %0"
9f2c2a36 5194 [(set_attr "type" "mov_reg,mov_imm,mvn_imm,mov_imm,load_4,store_4")
0d66636f 5195 (set_attr "predicable" "yes")
100cd063 5196 (set_attr "arch" "*,*,*,v6t2,*,*")
aaa37ad6 5197 (set_attr "pool_range" "*,*,*,*,4096,*")
5198 (set_attr "neg_pool_range" "*,*,*,*,4084,*")]
cffb2a26 5199)
87b22bf7 5200
5201(define_split
a2cd141b 5202 [(set (match_operand:SI 0 "arm_general_register_operand" "")
87b22bf7 5203 (match_operand:SI 1 "const_int_operand" ""))]
6e291830 5204 "(TARGET_32BIT || TARGET_HAVE_MOVT)
215b30b3 5205 && (!(const_ok_for_arm (INTVAL (operands[1]))
5206 || const_ok_for_arm (~INTVAL (operands[1]))))"
87b22bf7 5207 [(clobber (const_int 0))]
5208 "
96f57e36 5209 arm_split_constant (SET, SImode, NULL_RTX,
5210 INTVAL (operands[1]), operands[0], NULL_RTX, 0);
87b22bf7 5211 DONE;
215b30b3 5212 "
5213)
9c08d1fa 5214
861033d5 5215;; A normal way to do (symbol + offset) requires three instructions at least
5216;; (depends on how big the offset is) as below:
5217;; movw r0, #:lower16:g
5218;; movw r0, #:upper16:g
5219;; adds r0, #4
5220;;
5221;; A better way would be:
5222;; movw r0, #:lower16:g+4
5223;; movw r0, #:upper16:g+4
5224;;
5225;; The limitation of this way is that the length of offset should be a 16-bit
5226;; signed value, because current assembler only supports REL type relocation for
5227;; such case. If the more powerful RELA type is supported in future, we should
5228;; update this pattern to go with better way.
5229(define_split
5230 [(set (match_operand:SI 0 "arm_general_register_operand" "")
5231 (const:SI (plus:SI (match_operand:SI 1 "general_operand" "")
5232 (match_operand:SI 2 "const_int_operand" ""))))]
60a48e7d 5233 "TARGET_THUMB
5234 && TARGET_HAVE_MOVT
861033d5 5235 && arm_disable_literal_pool
5236 && reload_completed
5237 && GET_CODE (operands[1]) == SYMBOL_REF"
5238 [(clobber (const_int 0))]
5239 "
5240 int offset = INTVAL (operands[2]);
5241
5242 if (offset < -0x8000 || offset > 0x7fff)
5243 {
5244 arm_emit_movpair (operands[0], operands[1]);
d1f9b275 5245 emit_insn (gen_rtx_SET (operands[0],
861033d5 5246 gen_rtx_PLUS (SImode, operands[0], operands[2])));
5247 }
5248 else
5249 {
5250 rtx op = gen_rtx_CONST (SImode,
5251 gen_rtx_PLUS (SImode, operands[1], operands[2]));
5252 arm_emit_movpair (operands[0], op);
5253 }
5254 "
5255)
5256
b8d5d078 5257;; Split symbol_refs at the later stage (after cprop), instead of generating
5258;; movt/movw pair directly at expand. Otherwise corresponding high_sum
5259;; and lo_sum would be merged back into memory load at cprop. However,
5260;; if the default is to prefer movt/movw rather than a load from the constant
5261;; pool, the performance is better.
5262(define_split
5263 [(set (match_operand:SI 0 "arm_general_register_operand" "")
5264 (match_operand:SI 1 "general_operand" ""))]
60a48e7d 5265 "TARGET_USE_MOVT && GET_CODE (operands[1]) == SYMBOL_REF
d022aaf3 5266 && !target_word_relocations
b8d5d078 5267 && !arm_tls_referenced_p (operands[1])"
5268 [(clobber (const_int 0))]
5269{
5270 arm_emit_movpair (operands[0], operands[1]);
5271 DONE;
5272})
5273
bc360af8 5274;; When generating pic, we need to load the symbol offset into a register.
5275;; So that the optimizer does not confuse this with a normal symbol load
5276;; we use an unspec. The offset will be loaded from a constant pool entry,
5277;; since that is the only type of relocation we can use.
cffb2a26 5278
bc360af8 5279;; Wrap calculation of the whole PIC address in a single pattern for the
5280;; benefit of optimizers, particularly, PRE and HOIST. Calculation of
5281;; a PIC address involves two loads from memory, so we want to CSE it
5282;; as often as possible.
5283;; This pattern will be split into one of the pic_load_addr_* patterns
5284;; and a move after GCSE optimizations.
5285;;
5286;; Note: Update arm.c: legitimize_pic_address() when changing this pattern.
5287(define_expand "calculate_pic_address"
3934ae0e 5288 [(set (match_operand:SI 0 "register_operand")
5289 (mem:SI (plus:SI (match_operand:SI 1 "register_operand")
94f8caca 5290 (unspec:SI [(match_operand:SI 2 "" "")]
5291 UNSPEC_PIC_SYM))))]
5292 "flag_pic"
5293)
5294
5295;; Split calculate_pic_address into pic_load_addr_* and a move.
5296(define_split
5297 [(set (match_operand:SI 0 "register_operand" "")
5298 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "")
5299 (unspec:SI [(match_operand:SI 2 "" "")]
5300 UNSPEC_PIC_SYM))))]
5301 "flag_pic"
5302 [(set (match_dup 3) (unspec:SI [(match_dup 2)] UNSPEC_PIC_SYM))
5303 (set (match_dup 0) (mem:SI (plus:SI (match_dup 1) (match_dup 3))))]
5304 "operands[3] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];"
5305)
5306
350ccca5 5307;; operand1 is the memory address to go into
5308;; pic_load_addr_32bit.
5309;; operand2 is the PIC label to be emitted
5310;; from pic_add_dot_plus_eight.
5311;; We do this to allow hoisting of the entire insn.
5312(define_insn_and_split "pic_load_addr_unified"
5313 [(set (match_operand:SI 0 "s_register_operand" "=r,r,l")
5314 (unspec:SI [(match_operand:SI 1 "" "mX,mX,mX")
5315 (match_operand:SI 2 "" "")]
5316 UNSPEC_PIC_UNIFIED))]
5317 "flag_pic"
5318 "#"
5319 "&& reload_completed"
5320 [(set (match_dup 0) (unspec:SI [(match_dup 1)] UNSPEC_PIC_SYM))
5321 (set (match_dup 0) (unspec:SI [(match_dup 0) (match_dup 3)
5322 (match_dup 2)] UNSPEC_PIC_BASE))]
5323 "operands[3] = TARGET_THUMB ? GEN_INT (4) : GEN_INT (8);"
9f2c2a36 5324 [(set_attr "type" "load_4,load_4,load_4")
42e1de19 5325 (set_attr "pool_range" "4096,4094,1022")
350ccca5 5326 (set_attr "neg_pool_range" "4084,0,0")
5327 (set_attr "arch" "a,t2,t1")
5328 (set_attr "length" "8,6,4")]
5329)
5330
67336bcf 5331;; The rather odd constraints on the following are to force reload to leave
5332;; the insn alone, and to force the minipool generation pass to then move
5333;; the GOT symbol to memory.
849170fd 5334
b3cd5f55 5335(define_insn "pic_load_addr_32bit"
849170fd 5336 [(set (match_operand:SI 0 "s_register_operand" "=r")
e1159bbe 5337 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
b3cd5f55 5338 "TARGET_32BIT && flag_pic"
67336bcf 5339 "ldr%?\\t%0, %1"
9f2c2a36 5340 [(set_attr "type" "load_4")
42e1de19 5341 (set (attr "pool_range")
5342 (if_then_else (eq_attr "is_thumb" "no")
5343 (const_int 4096)
5344 (const_int 4094)))
b3cd5f55 5345 (set (attr "neg_pool_range")
5346 (if_then_else (eq_attr "is_thumb" "no")
5347 (const_int 4084)
5348 (const_int 0)))]
8c4d8060 5349)
5350
25f905c2 5351(define_insn "pic_load_addr_thumb1"
8c4d8060 5352 [(set (match_operand:SI 0 "s_register_operand" "=l")
e1159bbe 5353 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
25f905c2 5354 "TARGET_THUMB1 && flag_pic"
8c4d8060 5355 "ldr\\t%0, %1"
9f2c2a36 5356 [(set_attr "type" "load_4")
42e1de19 5357 (set (attr "pool_range") (const_int 1018))]
cffb2a26 5358)
849170fd 5359
cffb2a26 5360(define_insn "pic_add_dot_plus_four"
15d5d060 5361 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5362 (unspec:SI [(match_operand:SI 1 "register_operand" "0")
5363 (const_int 4)
beef0fb5 5364 (match_operand 2 "" "")]
5365 UNSPEC_PIC_BASE))]
b3cd5f55 5366 "TARGET_THUMB"
cffb2a26 5367 "*
6cdcb15c 5368 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5369 INTVAL (operands[2]));
cffb2a26 5370 return \"add\\t%0, %|pc\";
5371 "
1b7da4ac 5372 [(set_attr "length" "2")
112eda6f 5373 (set_attr "type" "alu_sreg")]
cffb2a26 5374)
849170fd 5375
5376(define_insn "pic_add_dot_plus_eight"
15d5d060 5377 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5378 (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5379 (const_int 8)
beef0fb5 5380 (match_operand 2 "" "")]
5381 UNSPEC_PIC_BASE))]
f655717d 5382 "TARGET_ARM"
c4034607 5383 "*
6cdcb15c 5384 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5385 INTVAL (operands[2]));
15d5d060 5386 return \"add%?\\t%0, %|pc, %1\";
cffb2a26 5387 "
1b7da4ac 5388 [(set_attr "predicable" "yes")
112eda6f 5389 (set_attr "type" "alu_sreg")]
cffb2a26 5390)
849170fd 5391
f655717d 5392(define_insn "tls_load_dot_plus_eight"
cc071db6 5393 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5394 (mem:SI (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5395 (const_int 8)
beef0fb5 5396 (match_operand 2 "" "")]
5397 UNSPEC_PIC_BASE)))]
f655717d 5398 "TARGET_ARM"
5399 "*
6cdcb15c 5400 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5401 INTVAL (operands[2]));
f655717d 5402 return \"ldr%?\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_eight\";
5403 "
1b7da4ac 5404 [(set_attr "predicable" "yes")
9f2c2a36 5405 (set_attr "type" "load_4")]
f655717d 5406)
5407
5408;; PIC references to local variables can generate pic_add_dot_plus_eight
5409;; followed by a load. These sequences can be crunched down to
5410;; tls_load_dot_plus_eight by a peephole.
5411
5412(define_peephole2
c0c1fba5 5413 [(set (match_operand:SI 0 "register_operand" "")
5414 (unspec:SI [(match_operand:SI 3 "register_operand" "")
5415 (const_int 8)
5416 (match_operand 1 "" "")]
5417 UNSPEC_PIC_BASE))
2d05dfad 5418 (set (match_operand:SI 2 "arm_general_register_operand" "")
5419 (mem:SI (match_dup 0)))]
f655717d 5420 "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
c0c1fba5 5421 [(set (match_dup 2)
5422 (mem:SI (unspec:SI [(match_dup 3)
5423 (const_int 8)
5424 (match_dup 1)]
5425 UNSPEC_PIC_BASE)))]
f655717d 5426 ""
5427)
5428
bac7fc85 5429(define_insn "pic_offset_arm"
5430 [(set (match_operand:SI 0 "register_operand" "=r")
5431 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
5432 (unspec:SI [(match_operand:SI 2 "" "X")]
5433 UNSPEC_PIC_OFFSET))))]
5434 "TARGET_VXWORKS_RTP && TARGET_ARM && flag_pic"
5435 "ldr%?\\t%0, [%1,%2]"
9f2c2a36 5436 [(set_attr "type" "load_4")]
bac7fc85 5437)
5438
95373f08 5439(define_expand "builtin_setjmp_receiver"
5440 [(label_ref (match_operand 0 "" ""))]
5441 "flag_pic"
5442 "
5443{
b935b306 5444 /* r3 is clobbered by set/longjmp, so we can use it as a scratch
5445 register. */
2cb7d577 5446 if (arm_pic_register != INVALID_REGNUM)
f98495d9 5447 arm_load_pic_register (1UL << 3, NULL_RTX);
95373f08 5448 DONE;
5449}")
5450
9c08d1fa 5451;; If copying one reg to another we can set the condition codes according to
5452;; its value. Such a move is common after a return from subroutine and the
5453;; result is being tested against zero.
5454
f7fbdd4a 5455(define_insn "*movsi_compare0"
bd5b4116 5456 [(set (reg:CC CC_REGNUM)
cffb2a26 5457 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
5458 (const_int 0)))
5459 (set (match_operand:SI 0 "s_register_operand" "=r,r")
5460 (match_dup 1))]
25f905c2 5461 "TARGET_32BIT"
e2348bcb 5462 "@
40dbec34 5463 cmp%?\\t%0, #0
3ef90e77 5464 subs%?\\t%0, %1, #0"
65f68e55 5465 [(set_attr "conds" "set")
d82e788e 5466 (set_attr "type" "alus_imm,alus_imm")]
cffb2a26 5467)
b11cae9e 5468
b11cae9e 5469;; Subroutine to store a half word from a register into memory.
5470;; Operand 0 is the source register (HImode)
c8f69309 5471;; Operand 1 is the destination address in a register (SImode)
b11cae9e 5472
9c08d1fa 5473;; In both this routine and the next, we must be careful not to spill
01cc3b75 5474;; a memory address of reg+large_const into a separate PLUS insn, since this
9c08d1fa 5475;; can generate unrecognizable rtl.
5476
b11cae9e 5477(define_expand "storehi"
c8f69309 5478 [;; store the low byte
f082f1c4 5479 (set (match_operand 1 "" "") (match_dup 3))
b11cae9e 5480 ;; extract the high byte
c8f69309 5481 (set (match_dup 2)
5482 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
b11cae9e 5483 ;; store the high byte
787f8210 5484 (set (match_dup 4) (match_dup 5))]
cffb2a26 5485 "TARGET_ARM"
b11cae9e 5486 "
215b30b3 5487 {
537ffcfc 5488 rtx op1 = operands[1];
5489 rtx addr = XEXP (op1, 0);
215b30b3 5490 enum rtx_code code = GET_CODE (addr);
5491
0438d37f 5492 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
215b30b3 5493 || code == MINUS)
537ffcfc 5494 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
215b30b3 5495
537ffcfc 5496 operands[4] = adjust_address (op1, QImode, 1);
e513d163 5497 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 5498 operands[3] = gen_lowpart (QImode, operands[0]);
5499 operands[0] = gen_lowpart (SImode, operands[0]);
787f8210 5500 operands[2] = gen_reg_rtx (SImode);
5501 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 5502 }"
5503)
b11cae9e 5504
c7597b5d 5505(define_expand "storehi_bigend"
f082f1c4 5506 [(set (match_dup 4) (match_dup 3))
c7597b5d 5507 (set (match_dup 2)
5508 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
787f8210 5509 (set (match_operand 1 "" "") (match_dup 5))]
cffb2a26 5510 "TARGET_ARM"
b11cae9e 5511 "
215b30b3 5512 {
537ffcfc 5513 rtx op1 = operands[1];
5514 rtx addr = XEXP (op1, 0);
215b30b3 5515 enum rtx_code code = GET_CODE (addr);
5516
0438d37f 5517 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
215b30b3 5518 || code == MINUS)
537ffcfc 5519 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
215b30b3 5520
537ffcfc 5521 operands[4] = adjust_address (op1, QImode, 1);
e513d163 5522 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 5523 operands[3] = gen_lowpart (QImode, operands[0]);
5524 operands[0] = gen_lowpart (SImode, operands[0]);
5525 operands[2] = gen_reg_rtx (SImode);
787f8210 5526 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 5527 }"
5528)
c7597b5d 5529
5530;; Subroutine to store a half word integer constant into memory.
5531(define_expand "storeinthi"
f082f1c4 5532 [(set (match_operand 0 "" "")
787f8210 5533 (match_operand 1 "" ""))
9e8503e6 5534 (set (match_dup 3) (match_dup 2))]
cffb2a26 5535 "TARGET_ARM"
c7597b5d 5536 "
215b30b3 5537 {
5538 HOST_WIDE_INT value = INTVAL (operands[1]);
5539 rtx addr = XEXP (operands[0], 0);
537ffcfc 5540 rtx op0 = operands[0];
215b30b3 5541 enum rtx_code code = GET_CODE (addr);
c7597b5d 5542
0438d37f 5543 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
215b30b3 5544 || code == MINUS)
537ffcfc 5545 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
c7597b5d 5546
215b30b3 5547 operands[1] = gen_reg_rtx (SImode);
5548 if (BYTES_BIG_ENDIAN)
5549 {
5550 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
5551 if ((value & 255) == ((value >> 8) & 255))
5552 operands[2] = operands[1];
5553 else
5554 {
5555 operands[2] = gen_reg_rtx (SImode);
5556 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
5557 }
5558 }
5559 else
5560 {
5561 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
5562 if ((value & 255) == ((value >> 8) & 255))
5563 operands[2] = operands[1];
5564 else
5565 {
5566 operands[2] = gen_reg_rtx (SImode);
5567 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
5568 }
5569 }
c7597b5d 5570
537ffcfc 5571 operands[3] = adjust_address (op0, QImode, 1);
e513d163 5572 operands[0] = adjust_address (operands[0], QImode, 0);
9e8503e6 5573 operands[2] = gen_lowpart (QImode, operands[2]);
787f8210 5574 operands[1] = gen_lowpart (QImode, operands[1]);
215b30b3 5575 }"
5576)
b11cae9e 5577
f7fbdd4a 5578(define_expand "storehi_single_op"
3934ae0e 5579 [(set (match_operand:HI 0 "memory_operand")
5580 (match_operand:HI 1 "general_operand"))]
25f905c2 5581 "TARGET_32BIT && arm_arch4"
f7fbdd4a 5582 "
215b30b3 5583 if (!s_register_operand (operands[1], HImode))
f7fbdd4a 5584 operands[1] = copy_to_mode_reg (HImode, operands[1]);
215b30b3 5585 "
5586)
f7fbdd4a 5587
b11cae9e 5588(define_expand "movhi"
3934ae0e 5589 [(set (match_operand:HI 0 "general_operand")
5590 (match_operand:HI 1 "general_operand"))]
cffb2a26 5591 "TARGET_EITHER"
b11cae9e 5592 "
e723310d 5593 gcc_checking_assert (aligned_operand (operands[0], HImode));
5594 gcc_checking_assert (aligned_operand (operands[1], HImode));
cffb2a26 5595 if (TARGET_ARM)
b11cae9e 5596 {
e1ba4a27 5597 if (can_create_pseudo_p ())
cffb2a26 5598 {
0438d37f 5599 if (MEM_P (operands[0]))
b11cae9e 5600 {
cffb2a26 5601 if (arm_arch4)
5602 {
5603 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
5604 DONE;
5605 }
0438d37f 5606 if (CONST_INT_P (operands[1]))
cffb2a26 5607 emit_insn (gen_storeinthi (operands[0], operands[1]));
c7597b5d 5608 else
cffb2a26 5609 {
0438d37f 5610 if (MEM_P (operands[1]))
cffb2a26 5611 operands[1] = force_reg (HImode, operands[1]);
5612 if (BYTES_BIG_ENDIAN)
5613 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
5614 else
5615 emit_insn (gen_storehi (operands[1], operands[0]));
5616 }
5617 DONE;
b11cae9e 5618 }
cffb2a26 5619 /* Sign extend a constant, and keep it in an SImode reg. */
0438d37f 5620 else if (CONST_INT_P (operands[1]))
9c08d1fa 5621 {
cffb2a26 5622 rtx reg = gen_reg_rtx (SImode);
5623 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
5624
5625 /* If the constant is already valid, leave it alone. */
215b30b3 5626 if (!const_ok_for_arm (val))
cffb2a26 5627 {
5628 /* If setting all the top bits will make the constant
5629 loadable in a single instruction, then set them.
5630 Otherwise, sign extend the number. */
5631
215b30b3 5632 if (const_ok_for_arm (~(val | ~0xffff)))
cffb2a26 5633 val |= ~0xffff;
5634 else if (val & 0x8000)
5635 val |= ~0xffff;
5636 }
5637
5638 emit_insn (gen_movsi (reg, GEN_INT (val)));
9e8503e6 5639 operands[1] = gen_lowpart (HImode, reg);
9c08d1fa 5640 }
e1ba4a27 5641 else if (arm_arch4 && optimize && can_create_pseudo_p ()
0438d37f 5642 && MEM_P (operands[1]))
0045890a 5643 {
5644 rtx reg = gen_reg_rtx (SImode);
5645
5646 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
5647 operands[1] = gen_lowpart (HImode, reg);
5648 }
215b30b3 5649 else if (!arm_arch4)
f7fbdd4a 5650 {
0438d37f 5651 if (MEM_P (operands[1]))
cffb2a26 5652 {
c1a66faf 5653 rtx base;
5654 rtx offset = const0_rtx;
5655 rtx reg = gen_reg_rtx (SImode);
5656
0438d37f 5657 if ((REG_P (base = XEXP (operands[1], 0))
c1a66faf 5658 || (GET_CODE (base) == PLUS
0438d37f 5659 && (CONST_INT_P (offset = XEXP (base, 1)))
c1a66faf 5660 && ((INTVAL(offset) & 1) != 1)
0438d37f 5661 && REG_P (base = XEXP (base, 0))))
c1a66faf 5662 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
206ee9a2 5663 {
8deb3959 5664 rtx new_rtx;
c1a66faf 5665
8deb3959 5666 new_rtx = widen_memory_access (operands[1], SImode,
5667 ((INTVAL (offset) & ~3)
5668 - INTVAL (offset)));
5669 emit_insn (gen_movsi (reg, new_rtx));
c1a66faf 5670 if (((INTVAL (offset) & 2) != 0)
5671 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
5672 {
5673 rtx reg2 = gen_reg_rtx (SImode);
5674
5675 emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
5676 reg = reg2;
5677 }
206ee9a2 5678 }
c1a66faf 5679 else
5680 emit_insn (gen_movhi_bytes (reg, operands[1]));
5681
5682 operands[1] = gen_lowpart (HImode, reg);
cffb2a26 5683 }
5684 }
5685 }
674a8f0b 5686 /* Handle loading a large integer during reload. */
0438d37f 5687 else if (CONST_INT_P (operands[1])
215b30b3 5688 && !const_ok_for_arm (INTVAL (operands[1]))
5689 && !const_ok_for_arm (~INTVAL (operands[1])))
cffb2a26 5690 {
5691 /* Writing a constant to memory needs a scratch, which should
5692 be handled with SECONDARY_RELOADs. */
0438d37f 5693 gcc_assert (REG_P (operands[0]));
cffb2a26 5694
5695 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5696 emit_insn (gen_movsi (operands[0], operands[1]));
5697 DONE;
5698 }
5699 }
25f905c2 5700 else if (TARGET_THUMB2)
5701 {
5702 /* Thumb-2 can do everything except mem=mem and mem=const easily. */
e1ba4a27 5703 if (can_create_pseudo_p ())
25f905c2 5704 {
0438d37f 5705 if (!REG_P (operands[0]))
25f905c2 5706 operands[1] = force_reg (HImode, operands[1]);
5707 /* Zero extend a constant, and keep it in an SImode reg. */
0438d37f 5708 else if (CONST_INT_P (operands[1]))
25f905c2 5709 {
5710 rtx reg = gen_reg_rtx (SImode);
5711 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
5712
5713 emit_insn (gen_movsi (reg, GEN_INT (val)));
5714 operands[1] = gen_lowpart (HImode, reg);
5715 }
5716 }
5717 }
5718 else /* TARGET_THUMB1 */
cffb2a26 5719 {
e1ba4a27 5720 if (can_create_pseudo_p ())
cffb2a26 5721 {
0438d37f 5722 if (CONST_INT_P (operands[1]))
6cffc037 5723 {
5724 rtx reg = gen_reg_rtx (SImode);
5725
5726 emit_insn (gen_movsi (reg, operands[1]));
5727 operands[1] = gen_lowpart (HImode, reg);
5728 }
cffb2a26 5729
5730 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 5731 happen if we are passed a SP (never OK for HImode/QImode) or
bc409cb4 5732 virtual register (also rejected as illegitimate for HImode/QImode)
5733 relative address. */
cffb2a26 5734 /* ??? This should perhaps be fixed elsewhere, for instance, in
5735 fixup_stack_1, by checking for other kinds of invalid addresses,
5736 e.g. a bare reference to a virtual register. This may confuse the
5737 alpha though, which must handle this case differently. */
0438d37f 5738 if (MEM_P (operands[0])
215b30b3 5739 && !memory_address_p (GET_MODE (operands[0]),
5740 XEXP (operands[0], 0)))
537ffcfc 5741 operands[0]
5742 = replace_equiv_address (operands[0],
5743 copy_to_reg (XEXP (operands[0], 0)));
cffb2a26 5744
0438d37f 5745 if (MEM_P (operands[1])
215b30b3 5746 && !memory_address_p (GET_MODE (operands[1]),
5747 XEXP (operands[1], 0)))
537ffcfc 5748 operands[1]
5749 = replace_equiv_address (operands[1],
5750 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 5751
0438d37f 5752 if (MEM_P (operands[1]) && optimize > 0)
6cffc037 5753 {
5754 rtx reg = gen_reg_rtx (SImode);
5755
5756 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
5757 operands[1] = gen_lowpart (HImode, reg);
5758 }
5759
0438d37f 5760 if (MEM_P (operands[0]))
6cffc037 5761 operands[1] = force_reg (HImode, operands[1]);
cffb2a26 5762 }
0438d37f 5763 else if (CONST_INT_P (operands[1])
234f6557 5764 && !satisfies_constraint_I (operands[1]))
cffb2a26 5765 {
6cffc037 5766 /* Handle loading a large integer during reload. */
5767
cffb2a26 5768 /* Writing a constant to memory needs a scratch, which should
5769 be handled with SECONDARY_RELOADs. */
0438d37f 5770 gcc_assert (REG_P (operands[0]));
cffb2a26 5771
1a83b3ff 5772 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
cffb2a26 5773 emit_insn (gen_movsi (operands[0], operands[1]));
5774 DONE;
5775 }
b11cae9e 5776 }
cffb2a26 5777 "
5778)
5779
25f7a26e 5780(define_expand "movhi_bytes"
eab14235 5781 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 5782 (set (match_dup 3)
eab14235 5783 (zero_extend:SI (match_dup 6)))
25f7a26e 5784 (set (match_operand:SI 0 "" "")
5785 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
cffb2a26 5786 "TARGET_ARM"
25f7a26e 5787 "
215b30b3 5788 {
5789 rtx mem1, mem2;
5790 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
5791
788fcce0 5792 mem1 = change_address (operands[1], QImode, addr);
29c05e22 5793 mem2 = change_address (operands[1], QImode,
5794 plus_constant (Pmode, addr, 1));
215b30b3 5795 operands[0] = gen_lowpart (SImode, operands[0]);
5796 operands[1] = mem1;
5797 operands[2] = gen_reg_rtx (SImode);
5798 operands[3] = gen_reg_rtx (SImode);
5799 operands[6] = mem2;
25f7a26e 5800
215b30b3 5801 if (BYTES_BIG_ENDIAN)
5802 {
5803 operands[4] = operands[2];
5804 operands[5] = operands[3];
5805 }
5806 else
5807 {
5808 operands[4] = operands[3];
5809 operands[5] = operands[2];
5810 }
5811 }"
5812)
25f7a26e 5813
c7597b5d 5814(define_expand "movhi_bigend"
5815 [(set (match_dup 2)
3934ae0e 5816 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand") 0)
c7597b5d 5817 (const_int 16)))
5818 (set (match_dup 3)
5819 (ashiftrt:SI (match_dup 2) (const_int 16)))
3934ae0e 5820 (set (match_operand:HI 0 "s_register_operand")
787f8210 5821 (match_dup 4))]
cffb2a26 5822 "TARGET_ARM"
c7597b5d 5823 "
5824 operands[2] = gen_reg_rtx (SImode);
5825 operands[3] = gen_reg_rtx (SImode);
787f8210 5826 operands[4] = gen_lowpart (HImode, operands[3]);
215b30b3 5827 "
5828)
b11cae9e 5829
a2f10574 5830;; Pattern to recognize insn generated default case above
f7fbdd4a 5831(define_insn "*movhi_insn_arch4"
e4585731 5832 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r,m,r")
5833 (match_operand:HI 1 "general_operand" "rIk,K,n,r,mi"))]
cffb2a26 5834 "TARGET_ARM
d7216193 5835 && arm_arch4 && !TARGET_HARD_FLOAT
85e02ccb 5836 && (register_operand (operands[0], HImode)
5837 || register_operand (operands[1], HImode))"
f7fbdd4a 5838 "@
5839 mov%?\\t%0, %1\\t%@ movhi
5840 mvn%?\\t%0, #%B1\\t%@ movhi
b1c1a101 5841 movw%?\\t%0, %L1\\t%@ movhi
3ef90e77 5842 strh%?\\t%1, %0\\t%@ movhi
5843 ldrh%?\\t%0, %1\\t%@ movhi"
65f68e55 5844 [(set_attr "predicable" "yes")
e4585731 5845 (set_attr "pool_range" "*,*,*,*,256")
5846 (set_attr "neg_pool_range" "*,*,*,*,244")
5847 (set_attr "arch" "*,*,v6t2,*,*")
65f68e55 5848 (set_attr_alternative "type"
5849 [(if_then_else (match_operand 1 "const_int_operand" "")
1aed5204 5850 (const_string "mov_imm" )
5851 (const_string "mov_reg"))
5852 (const_string "mvn_imm")
e4585731 5853 (const_string "mov_imm")
9f2c2a36 5854 (const_string "store_4")
5855 (const_string "load_4")])]
cffb2a26 5856)
f7fbdd4a 5857
f7fbdd4a 5858(define_insn "*movhi_bytes"
65f68e55 5859 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
5fd254ed 5860 (match_operand:HI 1 "arm_rhs_operand" "I,rk,K"))]
d7216193 5861 "TARGET_ARM && !TARGET_HARD_FLOAT"
25f7a26e 5862 "@
65f68e55 5863 mov%?\\t%0, %1\\t%@ movhi
25f7a26e 5864 mov%?\\t%0, %1\\t%@ movhi
0d66636f 5865 mvn%?\\t%0, #%B1\\t%@ movhi"
d2a518d1 5866 [(set_attr "predicable" "yes")
1aed5204 5867 (set_attr "type" "mov_imm,mov_reg,mvn_imm")]
0d66636f 5868)
837bb76e 5869
bc5c7e08 5870;; We use a DImode scratch because we may occasionally need an additional
5871;; temporary if the address isn't offsettable -- push_reload doesn't seem
5872;; to take any notice of the "o" constraints on reload_memory_operand operand.
3934ae0e 5873;; The reload_in<m> and reload_out<m> patterns require special constraints
5874;; to be correctly handled in default_secondary_reload function.
d3373b54 5875(define_expand "reload_outhi"
cffb2a26 5876 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
215b30b3 5877 (match_operand:HI 1 "s_register_operand" "r")
5878 (match_operand:DI 2 "s_register_operand" "=&l")])]
cffb2a26 5879 "TARGET_EITHER"
5880 "if (TARGET_ARM)
5881 arm_reload_out_hi (operands);
5882 else
5883 thumb_reload_out_hi (operands);
d3373b54 5884 DONE;
cffb2a26 5885 "
5886)
d3373b54 5887
25f7a26e 5888(define_expand "reload_inhi"
5889 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
cffb2a26 5890 (match_operand:HI 1 "arm_reload_memory_operand" "o")
bc5c7e08 5891 (match_operand:DI 2 "s_register_operand" "=&r")])]
c1a66faf 5892 "TARGET_EITHER"
25f7a26e 5893 "
cffb2a26 5894 if (TARGET_ARM)
5895 arm_reload_in_hi (operands);
5896 else
5897 thumb_reload_out_hi (operands);
25f7a26e 5898 DONE;
5899")
5900
9c08d1fa 5901(define_expand "movqi"
3934ae0e 5902 [(set (match_operand:QI 0 "general_operand")
5903 (match_operand:QI 1 "general_operand"))]
cffb2a26 5904 "TARGET_EITHER"
9c08d1fa 5905 "
6cffc037 5906 /* Everything except mem = const or mem = mem can be done easily */
0045890a 5907
e1ba4a27 5908 if (can_create_pseudo_p ())
cffb2a26 5909 {
0438d37f 5910 if (CONST_INT_P (operands[1]))
6cffc037 5911 {
5912 rtx reg = gen_reg_rtx (SImode);
5913
03770691 5914 /* For thumb we want an unsigned immediate, then we are more likely
5915 to be able to use a movs insn. */
5916 if (TARGET_THUMB)
5917 operands[1] = GEN_INT (INTVAL (operands[1]) & 255);
5918
6cffc037 5919 emit_insn (gen_movsi (reg, operands[1]));
5920 operands[1] = gen_lowpart (QImode, reg);
5921 }
cffb2a26 5922
6cffc037 5923 if (TARGET_THUMB)
5924 {
cffb2a26 5925 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 5926 happen if we are passed a SP (never OK for HImode/QImode) or
bc409cb4 5927 virtual register (also rejected as illegitimate for HImode/QImode)
5928 relative address. */
cffb2a26 5929 /* ??? This should perhaps be fixed elsewhere, for instance, in
5930 fixup_stack_1, by checking for other kinds of invalid addresses,
5931 e.g. a bare reference to a virtual register. This may confuse the
5932 alpha though, which must handle this case differently. */
0438d37f 5933 if (MEM_P (operands[0])
215b30b3 5934 && !memory_address_p (GET_MODE (operands[0]),
cffb2a26 5935 XEXP (operands[0], 0)))
537ffcfc 5936 operands[0]
5937 = replace_equiv_address (operands[0],
5938 copy_to_reg (XEXP (operands[0], 0)));
0438d37f 5939 if (MEM_P (operands[1])
215b30b3 5940 && !memory_address_p (GET_MODE (operands[1]),
cffb2a26 5941 XEXP (operands[1], 0)))
537ffcfc 5942 operands[1]
5943 = replace_equiv_address (operands[1],
5944 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 5945 }
5946
0438d37f 5947 if (MEM_P (operands[1]) && optimize > 0)
6cffc037 5948 {
5949 rtx reg = gen_reg_rtx (SImode);
5950
5951 emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
5952 operands[1] = gen_lowpart (QImode, reg);
5953 }
5954
0438d37f 5955 if (MEM_P (operands[0]))
6cffc037 5956 operands[1] = force_reg (QImode, operands[1]);
5957 }
5958 else if (TARGET_THUMB
0438d37f 5959 && CONST_INT_P (operands[1])
234f6557 5960 && !satisfies_constraint_I (operands[1]))
6cffc037 5961 {
674a8f0b 5962 /* Handle loading a large integer during reload. */
cffb2a26 5963
6cffc037 5964 /* Writing a constant to memory needs a scratch, which should
5965 be handled with SECONDARY_RELOADs. */
0438d37f 5966 gcc_assert (REG_P (operands[0]));
6cffc037 5967
5968 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5969 emit_insn (gen_movsi (operands[0], operands[1]));
5970 DONE;
cffb2a26 5971 }
5972 "
5973)
b11cae9e 5974
cffb2a26 5975(define_insn "*arm_movqi_insn"
fd711051 5976 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,l,r,l,Uu,r,m")
490f62ca 5977 (match_operand:QI 1 "general_operand" "rk,rk,I,Py,K,Uu,l,Uh,r"))]
25f905c2 5978 "TARGET_32BIT
cffb2a26 5979 && ( register_operand (operands[0], QImode)
5980 || register_operand (operands[1], QImode))"
5565501b 5981 "@
fd711051 5982 mov%?\\t%0, %1
5983 mov%?\\t%0, %1
65f68e55 5984 mov%?\\t%0, %1
5565501b 5985 mov%?\\t%0, %1
5986 mvn%?\\t%0, #%B1
3ef90e77 5987 ldrb%?\\t%0, %1
5988 strb%?\\t%1, %0
5989 ldrb%?\\t%0, %1
5990 strb%?\\t%1, %0"
9f2c2a36 5991 [(set_attr "type" "mov_reg,mov_reg,mov_imm,mov_imm,mvn_imm,load_4,store_4,load_4,store_4")
a54e3e7b 5992 (set_attr "predicable" "yes")
5233bf6a 5993 (set_attr "predicable_short_it" "yes,yes,no,yes,no,no,no,no,no")
fd711051 5994 (set_attr "arch" "t2,any,any,t2,any,t2,t2,any,any")
5995 (set_attr "length" "2,4,4,2,4,2,2,4,4")]
cffb2a26 5996)
5997
9b8516be 5998;; HFmode moves
5999(define_expand "movhf"
3934ae0e 6000 [(set (match_operand:HF 0 "general_operand")
6001 (match_operand:HF 1 "general_operand"))]
9b8516be 6002 "TARGET_EITHER"
6003 "
e723310d 6004 gcc_checking_assert (aligned_operand (operands[0], HFmode));
6005 gcc_checking_assert (aligned_operand (operands[1], HFmode));
9b8516be 6006 if (TARGET_32BIT)
6007 {
0438d37f 6008 if (MEM_P (operands[0]))
9b8516be 6009 operands[1] = force_reg (HFmode, operands[1]);
6010 }
6011 else /* TARGET_THUMB1 */
6012 {
6013 if (can_create_pseudo_p ())
6014 {
0438d37f 6015 if (!REG_P (operands[0]))
9b8516be 6016 operands[1] = force_reg (HFmode, operands[1]);
6017 }
6018 }
6019 "
6020)
6021
6022(define_insn "*arm32_movhf"
6023 [(set (match_operand:HF 0 "nonimmediate_operand" "=r,m,r,r")
6024 (match_operand:HF 1 "general_operand" " m,r,r,F"))]
d7216193 6025 "TARGET_32BIT && !TARGET_HARD_FLOAT
9b8516be 6026 && ( s_register_operand (operands[0], HFmode)
6027 || s_register_operand (operands[1], HFmode))"
6028 "*
6029 switch (which_alternative)
6030 {
6031 case 0: /* ARM register from memory */
3ef90e77 6032 return \"ldrh%?\\t%0, %1\\t%@ __fp16\";
9b8516be 6033 case 1: /* memory from ARM register */
3ef90e77 6034 return \"strh%?\\t%1, %0\\t%@ __fp16\";
9b8516be 6035 case 2: /* ARM register from ARM register */
6036 return \"mov%?\\t%0, %1\\t%@ __fp16\";
6037 case 3: /* ARM register from constant */
6038 {
9b8516be 6039 long bits;
6040 rtx ops[4];
6041
945f7b03 6042 bits = real_to_target (NULL, CONST_DOUBLE_REAL_VALUE (operands[1]),
6043 HFmode);
9b8516be 6044 ops[0] = operands[0];
6045 ops[1] = GEN_INT (bits);
6046 ops[2] = GEN_INT (bits & 0xff00);
6047 ops[3] = GEN_INT (bits & 0x00ff);
6048
6049 if (arm_arch_thumb2)
6050 output_asm_insn (\"movw%?\\t%0, %1\", ops);
6051 else
6052 output_asm_insn (\"mov%?\\t%0, %2\;orr%?\\t%0, %0, %3\", ops);
6053 return \"\";
6054 }
6055 default:
6056 gcc_unreachable ();
6057 }
6058 "
6059 [(set_attr "conds" "unconditional")
9f2c2a36 6060 (set_attr "type" "load_4,store_4,mov_reg,multiple")
9b8516be 6061 (set_attr "length" "4,4,4,8")
8bdfd6ed 6062 (set_attr "predicable" "yes")]
9b8516be 6063)
6064
87b22bf7 6065(define_expand "movsf"
3934ae0e 6066 [(set (match_operand:SF 0 "general_operand")
6067 (match_operand:SF 1 "general_operand"))]
cffb2a26 6068 "TARGET_EITHER"
87b22bf7 6069 "
e723310d 6070 gcc_checking_assert (aligned_operand (operands[0], SFmode));
6071 gcc_checking_assert (aligned_operand (operands[1], SFmode));
25f905c2 6072 if (TARGET_32BIT)
cffb2a26 6073 {
0438d37f 6074 if (MEM_P (operands[0]))
cffb2a26 6075 operands[1] = force_reg (SFmode, operands[1]);
6076 }
25f905c2 6077 else /* TARGET_THUMB1 */
cffb2a26 6078 {
e1ba4a27 6079 if (can_create_pseudo_p ())
cffb2a26 6080 {
0438d37f 6081 if (!REG_P (operands[0]))
cffb2a26 6082 operands[1] = force_reg (SFmode, operands[1]);
6083 }
6084 }
581f16e5 6085
6086 /* Cannot load it directly, generate a load with clobber so that it can be
6087 loaded via GPR with MOV / MOVT. */
6088 if (arm_disable_literal_pool
6089 && (REG_P (operands[0]) || SUBREG_P (operands[0]))
6090 && CONST_DOUBLE_P (operands[1])
6091 && TARGET_HARD_FLOAT
6092 && !vfp3_const_double_rtx (operands[1]))
6093 {
6094 rtx clobreg = gen_reg_rtx (SFmode);
6095 emit_insn (gen_no_literal_pool_sf_immediate (operands[0], operands[1],
6096 clobreg));
6097 DONE;
6098 }
cffb2a26 6099 "
6100)
6101
03d440a6 6102;; Transform a floating-point move of a constant into a core register into
6103;; an SImode operation.
cffb2a26 6104(define_split
03d440a6 6105 [(set (match_operand:SF 0 "arm_general_register_operand" "")
cffb2a26 6106 (match_operand:SF 1 "immediate_operand" ""))]
339034d0 6107 "TARGET_EITHER
cffb2a26 6108 && reload_completed
0438d37f 6109 && CONST_DOUBLE_P (operands[1])"
cffb2a26 6110 [(set (match_dup 2) (match_dup 3))]
6111 "
6112 operands[2] = gen_lowpart (SImode, operands[0]);
6113 operands[3] = gen_lowpart (SImode, operands[1]);
6114 if (operands[2] == 0 || operands[3] == 0)
6115 FAIL;
215b30b3 6116 "
6117)
87b22bf7 6118
cffb2a26 6119(define_insn "*arm_movsf_soft_insn"
6120 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
6121 (match_operand:SF 1 "general_operand" "r,mE,r"))]
cde1623a 6122 "TARGET_32BIT
cffb2a26 6123 && TARGET_SOFT_FLOAT
0438d37f 6124 && (!MEM_P (operands[0])
215b30b3 6125 || register_operand (operands[1], SFmode))"
581f16e5 6126{
6127 switch (which_alternative)
6128 {
6129 case 0: return \"mov%?\\t%0, %1\";
6130 case 1:
6131 /* Cannot load it directly, split to load it via MOV / MOVT. */
6132 if (!MEM_P (operands[1]) && arm_disable_literal_pool)
6133 return \"#\";
6134 return \"ldr%?\\t%0, %1\\t%@ float\";
6135 case 2: return \"str%?\\t%1, %0\\t%@ float\";
6136 default: gcc_unreachable ();
6137 }
6138}
cde1623a 6139 [(set_attr "predicable" "yes")
9f2c2a36 6140 (set_attr "type" "mov_reg,load_4,store_4")
42e1de19 6141 (set_attr "arm_pool_range" "*,4096,*")
6142 (set_attr "thumb2_pool_range" "*,4094,*")
cde1623a 6143 (set_attr "arm_neg_pool_range" "*,4084,*")
6144 (set_attr "thumb2_neg_pool_range" "*,0,*")]
cffb2a26 6145)
6146
581f16e5 6147;; Splitter for the above.
6148(define_split
6149 [(set (match_operand:SF 0 "s_register_operand")
6150 (match_operand:SF 1 "const_double_operand"))]
6151 "arm_disable_literal_pool && TARGET_SOFT_FLOAT"
6152 [(const_int 0)]
6153{
6154 long buf;
6155 real_to_target (&buf, CONST_DOUBLE_REAL_VALUE (operands[1]), SFmode);
6156 rtx cst = gen_int_mode (buf, SImode);
6157 emit_move_insn (simplify_gen_subreg (SImode, operands[0], SFmode, 0), cst);
6158 DONE;
6159}
6160)
6161
9c08d1fa 6162(define_expand "movdf"
3934ae0e 6163 [(set (match_operand:DF 0 "general_operand")
6164 (match_operand:DF 1 "general_operand"))]
cffb2a26 6165 "TARGET_EITHER"
9c08d1fa 6166 "
e723310d 6167 gcc_checking_assert (aligned_operand (operands[0], DFmode));
6168 gcc_checking_assert (aligned_operand (operands[1], DFmode));
25f905c2 6169 if (TARGET_32BIT)
cffb2a26 6170 {
0438d37f 6171 if (MEM_P (operands[0]))
cffb2a26 6172 operands[1] = force_reg (DFmode, operands[1]);
6173 }
6174 else /* TARGET_THUMB */
6175 {
e1ba4a27 6176 if (can_create_pseudo_p ())
cffb2a26 6177 {
0438d37f 6178 if (!REG_P (operands[0]))
cffb2a26 6179 operands[1] = force_reg (DFmode, operands[1]);
6180 }
6181 }
581f16e5 6182
6183 /* Cannot load it directly, generate a load with clobber so that it can be
6184 loaded via GPR with MOV / MOVT. */
6185 if (arm_disable_literal_pool
6186 && (REG_P (operands[0]) || SUBREG_P (operands[0]))
6187 && CONSTANT_P (operands[1])
6188 && TARGET_HARD_FLOAT
6189 && !arm_const_double_rtx (operands[1])
6190 && !(TARGET_VFP_DOUBLE && vfp3_const_double_rtx (operands[1])))
6191 {
6192 rtx clobreg = gen_reg_rtx (DFmode);
6193 emit_insn (gen_no_literal_pool_df_immediate (operands[0], operands[1],
6194 clobreg));
6195 DONE;
6196 }
cffb2a26 6197 "
6198)
b11cae9e 6199
9c08d1fa 6200;; Reloading a df mode value stored in integer regs to memory can require a
6201;; scratch reg.
3934ae0e 6202;; Another reload_out<m> pattern that requires special constraints.
9c08d1fa 6203(define_expand "reload_outdf"
cffb2a26 6204 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
87b22bf7 6205 (match_operand:DF 1 "s_register_operand" "r")
6206 (match_operand:SI 2 "s_register_operand" "=&r")]
06adefdc 6207 "TARGET_THUMB2"
87b22bf7 6208 "
215b30b3 6209 {
6210 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
f7fbdd4a 6211
215b30b3 6212 if (code == REG)
6213 operands[2] = XEXP (operands[0], 0);
6214 else if (code == POST_INC || code == PRE_DEC)
6215 {
6216 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
6217 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
6218 emit_insn (gen_movdi (operands[0], operands[1]));
6219 DONE;
6220 }
6221 else if (code == PRE_INC)
6222 {
6223 rtx reg = XEXP (XEXP (operands[0], 0), 0);
f7fbdd4a 6224
215b30b3 6225 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
6226 operands[2] = reg;
6227 }
6228 else if (code == POST_DEC)
6229 operands[2] = XEXP (XEXP (operands[0], 0), 0);
6230 else
6231 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
6232 XEXP (XEXP (operands[0], 0), 1)));
f7fbdd4a 6233
d1f9b275 6234 emit_insn (gen_rtx_SET (replace_equiv_address (operands[0], operands[2]),
215b30b3 6235 operands[1]));
f7fbdd4a 6236
215b30b3 6237 if (code == POST_DEC)
6238 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
6239
6240 DONE;
6241 }"
6242)
9c08d1fa 6243
9a1112d7 6244(define_insn "*movdf_soft_insn"
8f1c7041 6245 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,r,m")
6246 (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))]
cde1623a 6247 "TARGET_32BIT && TARGET_SOFT_FLOAT
b2778788 6248 && ( register_operand (operands[0], DFmode)
6249 || register_operand (operands[1], DFmode))"
d51f92df 6250 "*
6251 switch (which_alternative)
6252 {
6253 case 0:
6254 case 1:
6255 case 2:
6256 return \"#\";
581f16e5 6257 case 3:
6258 /* Cannot load it directly, split to load it via MOV / MOVT. */
6259 if (!MEM_P (operands[1]) && arm_disable_literal_pool)
6260 return \"#\";
6261 /* Fall through. */
d51f92df 6262 default:
26ff80c0 6263 return output_move_double (operands, true, NULL);
d51f92df 6264 }
6265 "
359a6e9f 6266 [(set_attr "length" "8,12,16,8,8")
9f2c2a36 6267 (set_attr "type" "multiple,multiple,multiple,load_8,store_8")
42e1de19 6268 (set_attr "arm_pool_range" "*,*,*,1020,*")
6269 (set_attr "thumb2_pool_range" "*,*,*,1018,*")
8848d797 6270 (set_attr "arm_neg_pool_range" "*,*,*,1004,*")
cde1623a 6271 (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
cffb2a26 6272)
581f16e5 6273
6274;; Splitter for the above.
6275(define_split
6276 [(set (match_operand:DF 0 "s_register_operand")
6277 (match_operand:DF 1 "const_double_operand"))]
6278 "arm_disable_literal_pool && TARGET_SOFT_FLOAT"
6279 [(const_int 0)]
6280{
6281 long buf[2];
6282 int order = BYTES_BIG_ENDIAN ? 1 : 0;
6283 real_to_target (buf, CONST_DOUBLE_REAL_VALUE (operands[1]), DFmode);
6284 unsigned HOST_WIDE_INT ival = zext_hwi (buf[order], 32);
6285 ival |= (zext_hwi (buf[1 - order], 32) << 32);
6286 rtx cst = gen_int_mode (ival, DImode);
6287 emit_move_insn (simplify_gen_subreg (DImode, operands[0], DFmode, 0), cst);
6288 DONE;
6289}
6290)
b11cae9e 6291\f
b11cae9e 6292
9c08d1fa 6293;; load- and store-multiple insns
6294;; The arm can load/store any set of registers, provided that they are in
320ea44d 6295;; ascending order, but these expanders assume a contiguous set.
b11cae9e 6296
9c08d1fa 6297(define_expand "load_multiple"
6298 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6299 (match_operand:SI 1 "" ""))
6300 (use (match_operand:SI 2 "" ""))])]
25f905c2 6301 "TARGET_32BIT"
9580c25f 6302{
6303 HOST_WIDE_INT offset = 0;
6304
bd5b4116 6305 /* Support only fixed point registers. */
0438d37f 6306 if (!CONST_INT_P (operands[2])
6e628811 6307 || INTVAL (operands[2]) > MAX_LDM_STM_OPS
9c08d1fa 6308 || INTVAL (operands[2]) < 2
0438d37f 6309 || !MEM_P (operands[1])
6310 || !REG_P (operands[0])
bd5b4116 6311 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
6312 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 6313 FAIL;
6314
6315 operands[3]
320ea44d 6316 = arm_gen_load_multiple (arm_regs_in_sequence + REGNO (operands[0]),
6317 INTVAL (operands[2]),
f082f1c4 6318 force_reg (SImode, XEXP (operands[1], 0)),
320ea44d 6319 FALSE, operands[1], &offset);
9580c25f 6320})
b11cae9e 6321
9c08d1fa 6322(define_expand "store_multiple"
6323 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6324 (match_operand:SI 1 "" ""))
6325 (use (match_operand:SI 2 "" ""))])]
25f905c2 6326 "TARGET_32BIT"
9580c25f 6327{
6328 HOST_WIDE_INT offset = 0;
6329
674a8f0b 6330 /* Support only fixed point registers. */
0438d37f 6331 if (!CONST_INT_P (operands[2])
6e628811 6332 || INTVAL (operands[2]) > MAX_LDM_STM_OPS
9c08d1fa 6333 || INTVAL (operands[2]) < 2
0438d37f 6334 || !REG_P (operands[1])
6335 || !MEM_P (operands[0])
bd5b4116 6336 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
6337 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 6338 FAIL;
6339
6340 operands[3]
320ea44d 6341 = arm_gen_store_multiple (arm_regs_in_sequence + REGNO (operands[1]),
6342 INTVAL (operands[2]),
f082f1c4 6343 force_reg (SImode, XEXP (operands[0], 0)),
320ea44d 6344 FALSE, operands[0], &offset);
9580c25f 6345})
b11cae9e 6346
9c08d1fa 6347
e34ebfca 6348(define_expand "setmemsi"
3934ae0e 6349 [(match_operand:BLK 0 "general_operand")
6350 (match_operand:SI 1 "const_int_operand")
6351 (match_operand:SI 2 "const_int_operand")
6352 (match_operand:SI 3 "const_int_operand")]
e34ebfca 6353 "TARGET_32BIT"
6354{
6355 if (arm_gen_setmem (operands))
6356 DONE;
6357
6358 FAIL;
6359})
6360
6361
9c08d1fa 6362;; Move a block of memory if it is word aligned and MORE than 2 words long.
6363;; We could let this apply for blocks of less than this, but it clobbers so
6364;; many registers that there is then probably a better way.
6365
f135a8d4 6366(define_expand "cpymemqi"
3934ae0e 6367 [(match_operand:BLK 0 "general_operand")
6368 (match_operand:BLK 1 "general_operand")
6369 (match_operand:SI 2 "const_int_operand")
6370 (match_operand:SI 3 "const_int_operand")]
ae51a965 6371 ""
9c08d1fa 6372 "
25f905c2 6373 if (TARGET_32BIT)
cffb2a26 6374 {
ae51a965 6375 if (TARGET_LDRD && current_tune->prefer_ldrd_strd
6376 && !optimize_function_for_size_p (cfun))
6377 {
f135a8d4 6378 if (gen_cpymem_ldrd_strd (operands))
ae51a965 6379 DONE;
6380 FAIL;
6381 }
6382
f135a8d4 6383 if (arm_gen_cpymemqi (operands))
cffb2a26 6384 DONE;
6385 FAIL;
6386 }
25f905c2 6387 else /* TARGET_THUMB1 */
cffb2a26 6388 {
6389 if ( INTVAL (operands[3]) != 4
6390 || INTVAL (operands[2]) > 48)
6391 FAIL;
6392
f135a8d4 6393 thumb_expand_cpymemqi (operands);
cffb2a26 6394 DONE;
6395 }
6396 "
6397)
9c08d1fa 6398\f
b11cae9e 6399
341940e8 6400;; Compare & branch insns
8d232dc7 6401;; The range calculations are based as follows:
341940e8 6402;; For forward branches, the address calculation returns the address of
6403;; the next instruction. This is 2 beyond the branch instruction.
6404;; For backward branches, the address calculation returns the address of
6405;; the first instruction in this pattern (cmp). This is 2 before the branch
6406;; instruction for the shortest sequence, and 4 before the branch instruction
6407;; if we have to jump around an unconditional branch.
6408;; To the basic branch range the PC offset must be added (this is +4).
6409;; So for forward branches we have
6410;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
6411;; And for backward branches we have
6412;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
6413;;
6414;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
6415;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
cffb2a26 6416
aeac46d4 6417(define_expand "cbranchsi4"
6418 [(set (pc) (if_then_else
aa06947a 6419 (match_operator 0 "expandable_comparison_operator"
3934ae0e 6420 [(match_operand:SI 1 "s_register_operand")
6421 (match_operand:SI 2 "nonmemory_operand")])
aeac46d4 6422 (label_ref (match_operand 3 "" ""))
6423 (pc)))]
f9aa4160 6424 "TARGET_EITHER"
aeac46d4 6425 "
74f4459c 6426 if (!TARGET_THUMB1)
6427 {
f9aa4160 6428 if (!arm_validize_comparison (&operands[0], &operands[1], &operands[2]))
6429 FAIL;
74f4459c 6430 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6431 operands[3]));
6432 DONE;
6433 }
25f905c2 6434 if (thumb1_cmpneg_operand (operands[2], SImode))
aeac46d4 6435 {
6436 emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
6437 operands[3], operands[0]));
6438 DONE;
6439 }
25f905c2 6440 if (!thumb1_cmp_operand (operands[2], SImode))
aeac46d4 6441 operands[2] = force_reg (SImode, operands[2]);
6442 ")
6443
74f4459c 6444(define_expand "cbranchsf4"
6445 [(set (pc) (if_then_else
aa06947a 6446 (match_operator 0 "expandable_comparison_operator"
3934ae0e 6447 [(match_operand:SF 1 "s_register_operand")
6448 (match_operand:SF 2 "vfp_compare_operand")])
74f4459c 6449 (label_ref (match_operand 3 "" ""))
6450 (pc)))]
6451 "TARGET_32BIT && TARGET_HARD_FLOAT"
6452 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6453 operands[3])); DONE;"
6454)
6455
6456(define_expand "cbranchdf4"
6457 [(set (pc) (if_then_else
aa06947a 6458 (match_operator 0 "expandable_comparison_operator"
3934ae0e 6459 [(match_operand:DF 1 "s_register_operand")
6460 (match_operand:DF 2 "vfp_compare_operand")])
74f4459c 6461 (label_ref (match_operand 3 "" ""))
6462 (pc)))]
a50d7267 6463 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
74f4459c 6464 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6465 operands[3])); DONE;"
6466)
6467
74f4459c 6468(define_expand "cbranchdi4"
6469 [(set (pc) (if_then_else
aa06947a 6470 (match_operator 0 "expandable_comparison_operator"
3934ae0e 6471 [(match_operand:DI 1 "s_register_operand")
d6852b47 6472 (match_operand:DI 2 "reg_or_int_operand")])
74f4459c 6473 (label_ref (match_operand 3 "" ""))
6474 (pc)))]
a8045a4f 6475 "TARGET_32BIT"
6476 "{
0438d37f 6477 if (!arm_validize_comparison (&operands[0], &operands[1], &operands[2]))
f9aa4160 6478 FAIL;
6479 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
a8045a4f 6480 operands[3]));
6481 DONE;
6482 }"
74f4459c 6483)
6484
9c08d1fa 6485;; Comparison and test insns
6486
cffb2a26 6487(define_insn "*arm_cmpsi_insn"
bd5b4116 6488 [(set (reg:CC CC_REGNUM)
f9f234ec 6489 (compare:CC (match_operand:SI 0 "s_register_operand" "l,r,r,r,r")
6490 (match_operand:SI 1 "arm_add_operand" "Py,r,r,I,L")))]
25f905c2 6491 "TARGET_32BIT"
5565501b 6492 "@
a6864a24 6493 cmp%?\\t%0, %1
6494 cmp%?\\t%0, %1
aea4c774 6495 cmp%?\\t%0, %1
f9f234ec 6496 cmp%?\\t%0, %1
aea4c774 6497 cmn%?\\t%0, #%n1"
a6864a24 6498 [(set_attr "conds" "set")
f9f234ec 6499 (set_attr "arch" "t2,t2,any,any,any")
6500 (set_attr "length" "2,2,4,4,4")
65f68e55 6501 (set_attr "predicable" "yes")
f9f234ec 6502 (set_attr "predicable_short_it" "yes,yes,yes,no,no")
112eda6f 6503 (set_attr "type" "alus_imm,alus_sreg,alus_sreg,alus_imm,alus_imm")]
cffb2a26 6504)
b11cae9e 6505
d5d4dc8d 6506(define_insn "*cmpsi_shiftsi"
bd5b4116 6507 [(set (reg:CC CC_REGNUM)
d82e788e 6508 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r,r")
cffb2a26 6509 (match_operator:SI 3 "shift_operator"
d82e788e 6510 [(match_operand:SI 1 "s_register_operand" "r,r,r")
6511 (match_operand:SI 2 "shift_amount_operand" "M,r,M")])))]
d5d4dc8d 6512 "TARGET_32BIT"
f9f234ec 6513 "cmp\\t%0, %1%S3"
344495ea 6514 [(set_attr "conds" "set")
331beb1a 6515 (set_attr "shift" "1")
d82e788e 6516 (set_attr "arch" "32,a,a")
282b4c75 6517 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
b11cae9e 6518
d5d4dc8d 6519(define_insn "*cmpsi_shiftsi_swp"
bd5b4116 6520 [(set (reg:CC_SWP CC_REGNUM)
aea4c774 6521 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
d82e788e 6522 [(match_operand:SI 1 "s_register_operand" "r,r,r")
6523 (match_operand:SI 2 "shift_amount_operand" "M,r,M")])
6524 (match_operand:SI 0 "s_register_operand" "r,r,r")))]
d5d4dc8d 6525 "TARGET_32BIT"
aea4c774 6526 "cmp%?\\t%0, %1%S3"
344495ea 6527 [(set_attr "conds" "set")
331beb1a 6528 (set_attr "shift" "1")
d82e788e 6529 (set_attr "arch" "32,a,a")
282b4c75 6530 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
b11cae9e 6531
25f905c2 6532(define_insn "*arm_cmpsi_negshiftsi_si"
aed179ae 6533 [(set (reg:CC_Z CC_REGNUM)
6534 (compare:CC_Z
6535 (neg:SI (match_operator:SI 1 "shift_operator"
6536 [(match_operand:SI 2 "s_register_operand" "r")
6537 (match_operand:SI 3 "reg_or_int_operand" "rM")]))
6538 (match_operand:SI 0 "s_register_operand" "r")))]
cffb2a26 6539 "TARGET_ARM"
aed179ae 6540 "cmn%?\\t%0, %2%S1"
344495ea 6541 [(set_attr "conds" "set")
aed179ae 6542 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
d82e788e 6543 (const_string "alus_shift_imm")
6544 (const_string "alus_shift_reg")))
596e5e8f 6545 (set_attr "predicable" "yes")]
0d66636f 6546)
b11cae9e 6547
9c08d1fa 6548; This insn allows redundant compares to be removed by cse, nothing should
6549; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
6550; is deleted later on. The match_dup will match the mode here, so that
6551; mode changes of the condition codes aren't lost by this even though we don't
6552; specify what they are.
6553
8a18b90c 6554(define_insn "*deleted_compare"
9c08d1fa 6555 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
25f905c2 6556 "TARGET_32BIT"
40dbec34 6557 "\\t%@ deleted compare"
cffb2a26 6558 [(set_attr "conds" "set")
1b7da4ac 6559 (set_attr "length" "0")
6560 (set_attr "type" "no_insn")]
cffb2a26 6561)
9c08d1fa 6562
6563\f
6564;; Conditional branch insns
6565
74f4459c 6566(define_expand "cbranch_cc"
9c08d1fa 6567 [(set (pc)
74f4459c 6568 (if_then_else (match_operator 0 "" [(match_operand 1 "" "")
6569 (match_operand 2 "" "")])
6570 (label_ref (match_operand 3 "" ""))
9c08d1fa 6571 (pc)))]
25f905c2 6572 "TARGET_32BIT"
74f4459c 6573 "operands[1] = arm_gen_compare_reg (GET_CODE (operands[0]),
e1b93706 6574 operands[1], operands[2], NULL_RTX);
74f4459c 6575 operands[2] = const0_rtx;"
8fa3ba89 6576)
6577
6578;;
6579;; Patterns to match conditional branch insns.
6580;;
6581
ffcc986d 6582(define_insn "arm_cond_branch"
9c08d1fa 6583 [(set (pc)
8fa3ba89 6584 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 6585 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 6586 (label_ref (match_operand 0 "" ""))
6587 (pc)))]
25f905c2 6588 "TARGET_32BIT"
d75350ce 6589 "*
9c08d1fa 6590 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 6591 {
6592 arm_ccfsm_state += 2;
6593 return \"\";
6594 }
e2348bcb 6595 return \"b%d1\\t%l0\";
cffb2a26 6596 "
a2cd141b 6597 [(set_attr "conds" "use")
a6864a24 6598 (set_attr "type" "branch")
6599 (set (attr "length")
6600 (if_then_else
0bf497f5 6601 (and (match_test "TARGET_THUMB2")
a6864a24 6602 (and (ge (minus (match_dup 0) (pc)) (const_int -250))
6603 (le (minus (match_dup 0) (pc)) (const_int 256))))
6604 (const_int 2)
6605 (const_int 4)))]
cffb2a26 6606)
d75350ce 6607
cffb2a26 6608(define_insn "*arm_cond_branch_reversed"
9c08d1fa 6609 [(set (pc)
8fa3ba89 6610 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 6611 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 6612 (pc)
6613 (label_ref (match_operand 0 "" ""))))]
25f905c2 6614 "TARGET_32BIT"
d75350ce 6615 "*
9c08d1fa 6616 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 6617 {
6618 arm_ccfsm_state += 2;
6619 return \"\";
6620 }
e2348bcb 6621 return \"b%D1\\t%l0\";
cffb2a26 6622 "
a2cd141b 6623 [(set_attr "conds" "use")
a6864a24 6624 (set_attr "type" "branch")
6625 (set (attr "length")
6626 (if_then_else
0bf497f5 6627 (and (match_test "TARGET_THUMB2")
a6864a24 6628 (and (ge (minus (match_dup 0) (pc)) (const_int -250))
6629 (le (minus (match_dup 0) (pc)) (const_int 256))))
6630 (const_int 2)
6631 (const_int 4)))]
cffb2a26 6632)
6633
b11cae9e 6634\f
9c08d1fa 6635
6636; scc insns
6637
74f4459c 6638(define_expand "cstore_cc"
3934ae0e 6639 [(set (match_operand:SI 0 "s_register_operand")
74f4459c 6640 (match_operator:SI 1 "" [(match_operand 2 "" "")
6641 (match_operand 3 "" "")]))]
25f905c2 6642 "TARGET_32BIT"
74f4459c 6643 "operands[2] = arm_gen_compare_reg (GET_CODE (operands[1]),
e1b93706 6644 operands[2], operands[3], NULL_RTX);
74f4459c 6645 operands[3] = const0_rtx;"
8fa3ba89 6646)
6647
a3b84066 6648(define_insn_and_split "*mov_scc"
9c08d1fa 6649 [(set (match_operand:SI 0 "s_register_operand" "=r")
ff74dd54 6650 (match_operator:SI 1 "arm_comparison_operator_mode"
8a18b90c 6651 [(match_operand 2 "cc_register" "") (const_int 0)]))]
cffb2a26 6652 "TARGET_ARM"
a3b84066 6653 "#" ; "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
6654 "TARGET_ARM"
6655 [(set (match_dup 0)
6656 (if_then_else:SI (match_dup 1)
6657 (const_int 1)
6658 (const_int 0)))]
6659 ""
cffb2a26 6660 [(set_attr "conds" "use")
1b7da4ac 6661 (set_attr "length" "8")
6662 (set_attr "type" "multiple")]
cffb2a26 6663)
9c08d1fa 6664
01089cc7 6665(define_insn "*negscc_borrow"
6666 [(set (match_operand:SI 0 "s_register_operand" "=r")
6667 (neg:SI (match_operand:SI 1 "arm_borrow_operation" "")))]
6668 "TARGET_32BIT"
6669 "sbc\\t%0, %0, %0"
6670 [(set_attr "conds" "use")
6671 (set_attr "length" "4")
6672 (set_attr "type" "adc_reg")]
6673)
6674
a3b84066 6675(define_insn_and_split "*mov_negscc"
9c08d1fa 6676 [(set (match_operand:SI 0 "s_register_operand" "=r")
ff74dd54 6677 (neg:SI (match_operator:SI 1 "arm_comparison_operator_mode"
8a18b90c 6678 [(match_operand 2 "cc_register" "") (const_int 0)])))]
01089cc7 6679 "TARGET_ARM && !arm_borrow_operation (operands[1], SImode)"
a3b84066 6680 "#" ; "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
01089cc7 6681 "&& true"
a3b84066 6682 [(set (match_dup 0)
6683 (if_then_else:SI (match_dup 1)
6684 (match_dup 3)
6685 (const_int 0)))]
6686 {
6687 operands[3] = GEN_INT (~0);
6688 }
cffb2a26 6689 [(set_attr "conds" "use")
1b7da4ac 6690 (set_attr "length" "8")
6691 (set_attr "type" "multiple")]
cffb2a26 6692)
9c08d1fa 6693
a3b84066 6694(define_insn_and_split "*mov_notscc"
9c08d1fa 6695 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 6696 (not:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 6697 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 6698 "TARGET_ARM"
a3b84066 6699 "#" ; "mvn%D1\\t%0, #0\;mvn%d1\\t%0, #1"
6700 "TARGET_ARM"
6701 [(set (match_dup 0)
6702 (if_then_else:SI (match_dup 1)
6703 (match_dup 3)
6704 (match_dup 4)))]
6705 {
6706 operands[3] = GEN_INT (~1);
6707 operands[4] = GEN_INT (~0);
6708 }
cffb2a26 6709 [(set_attr "conds" "use")
1b7da4ac 6710 (set_attr "length" "8")
6711 (set_attr "type" "multiple")]
cffb2a26 6712)
9c08d1fa 6713
595d88b5 6714(define_expand "cstoresi4"
3934ae0e 6715 [(set (match_operand:SI 0 "s_register_operand")
aa06947a 6716 (match_operator:SI 1 "expandable_comparison_operator"
3934ae0e 6717 [(match_operand:SI 2 "s_register_operand")
6718 (match_operand:SI 3 "reg_or_int_operand")]))]
74f4459c 6719 "TARGET_32BIT || TARGET_THUMB1"
595d88b5 6720 "{
6721 rtx op3, scratch, scratch2;
6722
74f4459c 6723 if (!TARGET_THUMB1)
6724 {
6725 if (!arm_add_operand (operands[3], SImode))
6726 operands[3] = force_reg (SImode, operands[3]);
6727 emit_insn (gen_cstore_cc (operands[0], operands[1],
6728 operands[2], operands[3]));
6729 DONE;
6730 }
6731
595d88b5 6732 if (operands[3] == const0_rtx)
6733 {
6734 switch (GET_CODE (operands[1]))
6735 {
6736 case EQ:
25f905c2 6737 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], operands[2]));
595d88b5 6738 break;
6739
6740 case NE:
25f905c2 6741 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], operands[2]));
595d88b5 6742 break;
6743
6744 case LE:
6745 scratch = expand_binop (SImode, add_optab, operands[2], constm1_rtx,
6746 NULL_RTX, 0, OPTAB_WIDEN);
6747 scratch = expand_binop (SImode, ior_optab, operands[2], scratch,
6748 NULL_RTX, 0, OPTAB_WIDEN);
6749 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
6750 operands[0], 1, OPTAB_WIDEN);
6751 break;
6752
6753 case GE:
6754 scratch = expand_unop (SImode, one_cmpl_optab, operands[2],
6755 NULL_RTX, 1);
6756 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
6757 NULL_RTX, 1, OPTAB_WIDEN);
6758 break;
6759
6760 case GT:
6761 scratch = expand_binop (SImode, ashr_optab, operands[2],
6762 GEN_INT (31), NULL_RTX, 0, OPTAB_WIDEN);
6763 scratch = expand_binop (SImode, sub_optab, scratch, operands[2],
6764 NULL_RTX, 0, OPTAB_WIDEN);
6765 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31), operands[0],
6766 0, OPTAB_WIDEN);
6767 break;
6768
6769 /* LT is handled by generic code. No need for unsigned with 0. */
6770 default:
6771 FAIL;
6772 }
6773 DONE;
6774 }
6775
6776 switch (GET_CODE (operands[1]))
6777 {
6778 case EQ:
6779 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
6780 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 6781 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], scratch));
595d88b5 6782 break;
6783
6784 case NE:
6785 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
6786 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 6787 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], scratch));
595d88b5 6788 break;
6789
6790 case LE:
6791 op3 = force_reg (SImode, operands[3]);
6792
6793 scratch = expand_binop (SImode, lshr_optab, operands[2], GEN_INT (31),
6794 NULL_RTX, 1, OPTAB_WIDEN);
6795 scratch2 = expand_binop (SImode, ashr_optab, op3, GEN_INT (31),
6796 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 6797 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
595d88b5 6798 op3, operands[2]));
6799 break;
6800
6801 case GE:
6802 op3 = operands[3];
25f905c2 6803 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 6804 op3 = force_reg (SImode, op3);
6805 scratch = expand_binop (SImode, ashr_optab, operands[2], GEN_INT (31),
6806 NULL_RTX, 0, OPTAB_WIDEN);
6807 scratch2 = expand_binop (SImode, lshr_optab, op3, GEN_INT (31),
6808 NULL_RTX, 1, OPTAB_WIDEN);
25f905c2 6809 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
595d88b5 6810 operands[2], op3));
6811 break;
6812
6813 case LEU:
6814 op3 = force_reg (SImode, operands[3]);
6815 scratch = force_reg (SImode, const0_rtx);
25f905c2 6816 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
595d88b5 6817 op3, operands[2]));
6818 break;
6819
6820 case GEU:
6821 op3 = operands[3];
25f905c2 6822 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 6823 op3 = force_reg (SImode, op3);
6824 scratch = force_reg (SImode, const0_rtx);
25f905c2 6825 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
595d88b5 6826 operands[2], op3));
6827 break;
6828
6829 case LTU:
6830 op3 = operands[3];
25f905c2 6831 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 6832 op3 = force_reg (SImode, op3);
6833 scratch = gen_reg_rtx (SImode);
408b7ae5 6834 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], operands[2], op3));
595d88b5 6835 break;
6836
6837 case GTU:
6838 op3 = force_reg (SImode, operands[3]);
6839 scratch = gen_reg_rtx (SImode);
408b7ae5 6840 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], op3, operands[2]));
595d88b5 6841 break;
6842
6843 /* No good sequences for GT, LT. */
6844 default:
6845 FAIL;
6846 }
6847 DONE;
6848}")
6849
9854d864 6850(define_expand "cstorehf4"
6851 [(set (match_operand:SI 0 "s_register_operand")
6852 (match_operator:SI 1 "expandable_comparison_operator"
6853 [(match_operand:HF 2 "s_register_operand")
d7216193 6854 (match_operand:HF 3 "vfp_compare_operand")]))]
9854d864 6855 "TARGET_VFP_FP16INST"
6856 {
6857 if (!arm_validize_comparison (&operands[1],
6858 &operands[2],
6859 &operands[3]))
6860 FAIL;
6861
6862 emit_insn (gen_cstore_cc (operands[0], operands[1],
6863 operands[2], operands[3]));
6864 DONE;
6865 }
6866)
6867
74f4459c 6868(define_expand "cstoresf4"
3934ae0e 6869 [(set (match_operand:SI 0 "s_register_operand")
aa06947a 6870 (match_operator:SI 1 "expandable_comparison_operator"
3934ae0e 6871 [(match_operand:SF 2 "s_register_operand")
6872 (match_operand:SF 3 "vfp_compare_operand")]))]
74f4459c 6873 "TARGET_32BIT && TARGET_HARD_FLOAT"
6874 "emit_insn (gen_cstore_cc (operands[0], operands[1],
6875 operands[2], operands[3])); DONE;"
6876)
6877
6878(define_expand "cstoredf4"
3934ae0e 6879 [(set (match_operand:SI 0 "s_register_operand")
aa06947a 6880 (match_operator:SI 1 "expandable_comparison_operator"
3934ae0e 6881 [(match_operand:DF 2 "s_register_operand")
6882 (match_operand:DF 3 "vfp_compare_operand")]))]
d63ed457 6883 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
74f4459c 6884 "emit_insn (gen_cstore_cc (operands[0], operands[1],
6885 operands[2], operands[3])); DONE;"
6886)
6887
74f4459c 6888(define_expand "cstoredi4"
3934ae0e 6889 [(set (match_operand:SI 0 "s_register_operand")
aa06947a 6890 (match_operator:SI 1 "expandable_comparison_operator"
3934ae0e 6891 [(match_operand:DI 2 "s_register_operand")
d6852b47 6892 (match_operand:DI 3 "reg_or_int_operand")]))]
a8045a4f 6893 "TARGET_32BIT"
6894 "{
f9aa4160 6895 if (!arm_validize_comparison (&operands[1],
6896 &operands[2],
6897 &operands[3]))
6898 FAIL;
6899 emit_insn (gen_cstore_cc (operands[0], operands[1], operands[2],
a8045a4f 6900 operands[3]));
6901 DONE;
6902 }"
74f4459c 6903)
6904
9c08d1fa 6905\f
39b5e676 6906;; Conditional move insns
6907
6908(define_expand "movsicc"
3934ae0e 6909 [(set (match_operand:SI 0 "s_register_operand")
6910 (if_then_else:SI (match_operand 1 "expandable_comparison_operator")
6911 (match_operand:SI 2 "arm_not_operand")
6912 (match_operand:SI 3 "arm_not_operand")))]
25f905c2 6913 "TARGET_32BIT"
39b5e676 6914 "
215b30b3 6915 {
f9aa4160 6916 enum rtx_code code;
278b301d 6917 rtx ccreg;
6918
f9aa4160 6919 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
9854d864 6920 &XEXP (operands[1], 1)))
278b301d 6921 FAIL;
9854d864 6922
6923 code = GET_CODE (operands[1]);
6924 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
6925 XEXP (operands[1], 1), NULL_RTX);
6926 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
6927 }"
6928)
6929
6930(define_expand "movhfcc"
6931 [(set (match_operand:HF 0 "s_register_operand")
6932 (if_then_else:HF (match_operand 1 "arm_cond_move_operator")
6933 (match_operand:HF 2 "s_register_operand")
6934 (match_operand:HF 3 "s_register_operand")))]
6935 "TARGET_VFP_FP16INST"
6936 "
6937 {
6938 enum rtx_code code = GET_CODE (operands[1]);
6939 rtx ccreg;
6940
6941 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
6942 &XEXP (operands[1], 1)))
6943 FAIL;
6944
f9aa4160 6945 code = GET_CODE (operands[1]);
74f4459c 6946 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
e1b93706 6947 XEXP (operands[1], 1), NULL_RTX);
29bb088d 6948 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 6949 }"
6950)
39b5e676 6951
6952(define_expand "movsfcc"
3934ae0e 6953 [(set (match_operand:SF 0 "s_register_operand")
6954 (if_then_else:SF (match_operand 1 "arm_cond_move_operator")
6955 (match_operand:SF 2 "s_register_operand")
6956 (match_operand:SF 3 "s_register_operand")))]
19f6bf8d 6957 "TARGET_32BIT && TARGET_HARD_FLOAT"
39b5e676 6958 "
215b30b3 6959 {
6960 enum rtx_code code = GET_CODE (operands[1]);
6961 rtx ccreg;
f082f1c4 6962
9854d864 6963 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
f9aa4160 6964 &XEXP (operands[1], 1)))
6965 FAIL;
39b5e676 6966
f9aa4160 6967 code = GET_CODE (operands[1]);
74f4459c 6968 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
e1b93706 6969 XEXP (operands[1], 1), NULL_RTX);
29bb088d 6970 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 6971 }"
6972)
39b5e676 6973
6974(define_expand "movdfcc"
3934ae0e 6975 [(set (match_operand:DF 0 "s_register_operand")
6976 (if_then_else:DF (match_operand 1 "arm_cond_move_operator")
6977 (match_operand:DF 2 "s_register_operand")
6978 (match_operand:DF 3 "s_register_operand")))]
994606f8 6979 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
39b5e676 6980 "
215b30b3 6981 {
6982 enum rtx_code code = GET_CODE (operands[1]);
278b301d 6983 rtx ccreg;
39b5e676 6984
f9aa4160 6985 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
6986 &XEXP (operands[1], 1)))
6987 FAIL;
6988 code = GET_CODE (operands[1]);
74f4459c 6989 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
e1b93706 6990 XEXP (operands[1], 1), NULL_RTX);
29bb088d 6991 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 6992 }"
6993)
39b5e676 6994
91cb50d2 6995(define_insn "*cmov<mode>"
6996 [(set (match_operand:SDF 0 "s_register_operand" "=<F_constraint>")
6997 (if_then_else:SDF (match_operator 1 "arm_vsel_comparison_operator"
6998 [(match_operand 2 "cc_register" "") (const_int 0)])
6999 (match_operand:SDF 3 "s_register_operand"
7000 "<F_constraint>")
7001 (match_operand:SDF 4 "s_register_operand"
7002 "<F_constraint>")))]
c79c1b1b 7003 "TARGET_HARD_FLOAT && TARGET_VFP5 <vfp_double_cond>"
91cb50d2 7004 "*
7005 {
7006 enum arm_cond_code code = maybe_get_arm_condition_code (operands[1]);
7007 switch (code)
7008 {
7009 case ARM_GE:
7010 case ARM_GT:
7011 case ARM_EQ:
7012 case ARM_VS:
7013 return \"vsel%d1.<V_if_elem>\\t%<V_reg>0, %<V_reg>3, %<V_reg>4\";
7014 case ARM_LT:
7015 case ARM_LE:
7016 case ARM_NE:
7017 case ARM_VC:
7018 return \"vsel%D1.<V_if_elem>\\t%<V_reg>0, %<V_reg>4, %<V_reg>3\";
7019 default:
7020 gcc_unreachable ();
7021 }
7022 return \"\";
7023 }"
7024 [(set_attr "conds" "use")
6664d308 7025 (set_attr "type" "fcsel")]
91cb50d2 7026)
7027
9854d864 7028(define_insn "*cmovhf"
7029 [(set (match_operand:HF 0 "s_register_operand" "=t")
7030 (if_then_else:HF (match_operator 1 "arm_vsel_comparison_operator"
7031 [(match_operand 2 "cc_register" "") (const_int 0)])
7032 (match_operand:HF 3 "s_register_operand" "t")
7033 (match_operand:HF 4 "s_register_operand" "t")))]
7034 "TARGET_VFP_FP16INST"
7035 "*
7036 {
7037 enum arm_cond_code code = maybe_get_arm_condition_code (operands[1]);
7038 switch (code)
7039 {
7040 case ARM_GE:
7041 case ARM_GT:
7042 case ARM_EQ:
7043 case ARM_VS:
7044 return \"vsel%d1.f16\\t%0, %3, %4\";
7045 case ARM_LT:
7046 case ARM_LE:
7047 case ARM_NE:
7048 case ARM_VC:
7049 return \"vsel%D1.f16\\t%0, %4, %3\";
7050 default:
7051 gcc_unreachable ();
7052 }
7053 return \"\";
7054 }"
7055 [(set_attr "conds" "use")
7056 (set_attr "type" "fcsel")]
7057)
7058
190efb17 7059(define_insn_and_split "*movsicc_insn"
f082f1c4 7060 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
8a18b90c 7061 (if_then_else:SI
8fa3ba89 7062 (match_operator 3 "arm_comparison_operator"
8a18b90c 7063 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 7064 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
7065 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
cffb2a26 7066 "TARGET_ARM"
39b5e676 7067 "@
8a18b90c 7068 mov%D3\\t%0, %2
7069 mvn%D3\\t%0, #%B2
f082f1c4 7070 mov%d3\\t%0, %1
7071 mvn%d3\\t%0, #%B1
190efb17 7072 #
7073 #
7074 #
7075 #"
7076 ; alt4: mov%d3\\t%0, %1\;mov%D3\\t%0, %2
7077 ; alt5: mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
7078 ; alt6: mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
7079 ; alt7: mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
7080 "&& reload_completed"
7081 [(const_int 0)]
7082 {
7083 enum rtx_code rev_code;
3754d046 7084 machine_mode mode;
190efb17 7085 rtx rev_cond;
7086
7087 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
7088 operands[3],
d1f9b275 7089 gen_rtx_SET (operands[0], operands[1])));
190efb17 7090
7091 rev_code = GET_CODE (operands[3]);
7092 mode = GET_MODE (operands[4]);
7093 if (mode == CCFPmode || mode == CCFPEmode)
7094 rev_code = reverse_condition_maybe_unordered (rev_code);
7095 else
7096 rev_code = reverse_condition (rev_code);
7097
7098 rev_cond = gen_rtx_fmt_ee (rev_code,
7099 VOIDmode,
7100 operands[4],
7101 const0_rtx);
7102 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
7103 rev_cond,
d1f9b275 7104 gen_rtx_SET (operands[0], operands[2])));
190efb17 7105 DONE;
7106 }
f082f1c4 7107 [(set_attr "length" "4,4,4,4,8,8,8,8")
d2a518d1 7108 (set_attr "conds" "use")
65f68e55 7109 (set_attr_alternative "type"
7110 [(if_then_else (match_operand 2 "const_int_operand" "")
1aed5204 7111 (const_string "mov_imm")
7112 (const_string "mov_reg"))
7113 (const_string "mvn_imm")
65f68e55 7114 (if_then_else (match_operand 1 "const_int_operand" "")
1aed5204 7115 (const_string "mov_imm")
7116 (const_string "mov_reg"))
7117 (const_string "mvn_imm")
282b4c75 7118 (const_string "multiple")
7119 (const_string "multiple")
7120 (const_string "multiple")
7121 (const_string "multiple")])]
215b30b3 7122)
39b5e676 7123
39b5e676 7124(define_insn "*movsfcc_soft_insn"
f082f1c4 7125 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
8fa3ba89 7126 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
8a18b90c 7127 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 7128 (match_operand:SF 1 "s_register_operand" "0,r")
7129 (match_operand:SF 2 "s_register_operand" "r,0")))]
cffb2a26 7130 "TARGET_ARM && TARGET_SOFT_FLOAT"
f082f1c4 7131 "@
7132 mov%D3\\t%0, %2
7133 mov%d3\\t%0, %1"
d2a518d1 7134 [(set_attr "conds" "use")
1aed5204 7135 (set_attr "type" "mov_reg")]
8fa3ba89 7136)
39b5e676 7137
39b5e676 7138\f
9c08d1fa 7139;; Jump and linkage insns
7140
cffb2a26 7141(define_expand "jump"
9c08d1fa 7142 [(set (pc)
7143 (label_ref (match_operand 0 "" "")))]
cffb2a26 7144 "TARGET_EITHER"
9c08d1fa 7145 ""
cffb2a26 7146)
7147
7148(define_insn "*arm_jump"
7149 [(set (pc)
7150 (label_ref (match_operand 0 "" "")))]
25f905c2 7151 "TARGET_32BIT"
9c08d1fa 7152 "*
0d66636f 7153 {
7154 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7155 {
7156 arm_ccfsm_state += 2;
7157 return \"\";
7158 }
7159 return \"b%?\\t%l0\";
7160 }
7161 "
a6864a24 7162 [(set_attr "predicable" "yes")
7163 (set (attr "length")
7164 (if_then_else
0bf497f5 7165 (and (match_test "TARGET_THUMB2")
a6864a24 7166 (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
7167 (le (minus (match_dup 0) (pc)) (const_int 2048))))
7168 (const_int 2)
1b7da4ac 7169 (const_int 4)))
7170 (set_attr "type" "branch")]
0d66636f 7171)
9c08d1fa 7172
d3373b54 7173(define_expand "call"
3934ae0e 7174 [(parallel [(call (match_operand 0 "memory_operand")
7175 (match_operand 1 "general_operand"))
cffb2a26 7176 (use (match_operand 2 "" ""))
bd5b4116 7177 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 7178 "TARGET_EITHER"
6c4c2133 7179 "
7180 {
bac7fc85 7181 rtx callee, pat;
2d3a01a7 7182 tree addr = MEM_EXPR (operands[0]);
bbe777ea 7183
bbe777ea 7184 /* In an untyped call, we can get NULL for operand 2. */
7185 if (operands[2] == NULL_RTX)
7186 operands[2] = const0_rtx;
7187
de55252a 7188 /* Decide if we should generate indirect calls by loading the
85c36fd1 7189 32-bit address of the callee into a register before performing the
de55252a 7190 branch and link. */
7191 callee = XEXP (operands[0], 0);
7192 if (GET_CODE (callee) == SYMBOL_REF
7193 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
7194 : !REG_P (callee))
bbe777ea 7195 XEXP (operands[0], 0) = force_reg (Pmode, callee);
bac7fc85 7196
2649fa41 7197 if (TARGET_FDPIC && !SYMBOL_REF_P (XEXP (operands[0], 0)))
7198 /* Indirect call: set r9 with FDPIC value of callee. */
7199 XEXP (operands[0], 0)
7200 = arm_load_function_descriptor (XEXP (operands[0], 0));
7201
2d3a01a7 7202 if (detect_cmse_nonsecure_call (addr))
7203 {
7204 pat = gen_nonsecure_call_internal (operands[0], operands[1],
7205 operands[2]);
7206 emit_call_insn (pat);
7207 }
7208 else
7209 {
7210 pat = gen_call_internal (operands[0], operands[1], operands[2]);
7211 arm_emit_call_insn (pat, XEXP (operands[0], 0), false);
7212 }
2649fa41 7213
7214 /* Restore FDPIC register (r9) after call. */
7215 if (TARGET_FDPIC)
7216 {
7217 rtx fdpic_reg = gen_rtx_REG (Pmode, FDPIC_REGNUM);
7218 rtx initial_fdpic_reg
7219 = get_hard_reg_initial_val (Pmode, FDPIC_REGNUM);
7220
7221 emit_insn (gen_restore_pic_register_after_call (fdpic_reg,
7222 initial_fdpic_reg));
7223 }
7224
bac7fc85 7225 DONE;
6c4c2133 7226 }"
7227)
d3373b54 7228
2649fa41 7229(define_insn "restore_pic_register_after_call"
7230 [(set (match_operand:SI 0 "s_register_operand" "+r,r")
7231 (unspec:SI [(match_dup 0)
7232 (match_operand:SI 1 "nonimmediate_operand" "r,m")]
7233 UNSPEC_PIC_RESTORE))]
7234 ""
7235 "@
7236 mov\t%0, %1
7237 ldr\t%0, %1"
7238)
7239
bac7fc85 7240(define_expand "call_internal"
3934ae0e 7241 [(parallel [(call (match_operand 0 "memory_operand")
7242 (match_operand 1 "general_operand"))
bac7fc85 7243 (use (match_operand 2 "" ""))
7244 (clobber (reg:SI LR_REGNUM))])])
7245
2d3a01a7 7246(define_expand "nonsecure_call_internal"
3934ae0e 7247 [(parallel [(call (unspec:SI [(match_operand 0 "memory_operand")]
2d3a01a7 7248 UNSPEC_NONSECURE_MEM)
3934ae0e 7249 (match_operand 1 "general_operand"))
2d3a01a7 7250 (use (match_operand 2 "" ""))
e27c5a70 7251 (clobber (reg:SI LR_REGNUM))])]
2d3a01a7 7252 "use_cmse"
7253 "
7254 {
7255 rtx tmp;
7256 tmp = copy_to_suggested_reg (XEXP (operands[0], 0),
e27c5a70 7257 gen_rtx_REG (SImode, R4_REGNUM),
2d3a01a7 7258 SImode);
7259
7260 operands[0] = replace_equiv_address (operands[0], tmp);
7261 }")
7262
f1039640 7263(define_insn "*call_reg_armv5"
d3373b54 7264 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
cffb2a26 7265 (match_operand 1 "" ""))
7266 (use (match_operand 2 "" ""))
bd5b4116 7267 (clobber (reg:SI LR_REGNUM))]
b232e6b5 7268 "TARGET_ARM && arm_arch5t && !SIBLING_CALL_P (insn)"
f1039640 7269 "blx%?\\t%0"
7270 [(set_attr "type" "call")]
7271)
7272
7273(define_insn "*call_reg_arm"
7274 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7275 (match_operand 1 "" ""))
7276 (use (match_operand 2 "" ""))
7277 (clobber (reg:SI LR_REGNUM))]
b232e6b5 7278 "TARGET_ARM && !arm_arch5t && !SIBLING_CALL_P (insn)"
9c08d1fa 7279 "*
5565501b 7280 return output_call (operands);
cffb2a26 7281 "
7282 ;; length is worst case, normally it is only two
7283 [(set_attr "length" "12")
7284 (set_attr "type" "call")]
7285)
9c08d1fa 7286
89504fc1 7287
d3373b54 7288(define_expand "call_value"
e0698af7 7289 [(parallel [(set (match_operand 0 "" "")
3934ae0e 7290 (call (match_operand 1 "memory_operand")
7291 (match_operand 2 "general_operand")))
cffb2a26 7292 (use (match_operand 3 "" ""))
bd5b4116 7293 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 7294 "TARGET_EITHER"
6c4c2133 7295 "
7296 {
bac7fc85 7297 rtx pat, callee;
2d3a01a7 7298 tree addr = MEM_EXPR (operands[1]);
bbe777ea 7299
7300 /* In an untyped call, we can get NULL for operand 2. */
7301 if (operands[3] == 0)
7302 operands[3] = const0_rtx;
7303
de55252a 7304 /* Decide if we should generate indirect calls by loading the
7305 32-bit address of the callee into a register before performing the
7306 branch and link. */
7307 callee = XEXP (operands[1], 0);
7308 if (GET_CODE (callee) == SYMBOL_REF
7309 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
7310 : !REG_P (callee))
78fe751b 7311 XEXP (operands[1], 0) = force_reg (Pmode, callee);
bac7fc85 7312
2649fa41 7313 if (TARGET_FDPIC && !SYMBOL_REF_P (XEXP (operands[1], 0)))
7314 /* Indirect call: set r9 with FDPIC value of callee. */
7315 XEXP (operands[1], 0)
7316 = arm_load_function_descriptor (XEXP (operands[1], 0));
7317
2d3a01a7 7318 if (detect_cmse_nonsecure_call (addr))
7319 {
7320 pat = gen_nonsecure_call_value_internal (operands[0], operands[1],
7321 operands[2], operands[3]);
7322 emit_call_insn (pat);
7323 }
7324 else
7325 {
7326 pat = gen_call_value_internal (operands[0], operands[1],
7327 operands[2], operands[3]);
7328 arm_emit_call_insn (pat, XEXP (operands[1], 0), false);
7329 }
2649fa41 7330
7331 /* Restore FDPIC register (r9) after call. */
7332 if (TARGET_FDPIC)
7333 {
7334 rtx fdpic_reg = gen_rtx_REG (Pmode, FDPIC_REGNUM);
7335 rtx initial_fdpic_reg
7336 = get_hard_reg_initial_val (Pmode, FDPIC_REGNUM);
7337
7338 emit_insn (gen_restore_pic_register_after_call (fdpic_reg,
7339 initial_fdpic_reg));
7340 }
7341
bac7fc85 7342 DONE;
6c4c2133 7343 }"
7344)
d3373b54 7345
bac7fc85 7346(define_expand "call_value_internal"
7347 [(parallel [(set (match_operand 0 "" "")
3934ae0e 7348 (call (match_operand 1 "memory_operand")
7349 (match_operand 2 "general_operand")))
bac7fc85 7350 (use (match_operand 3 "" ""))
7351 (clobber (reg:SI LR_REGNUM))])])
7352
2d3a01a7 7353(define_expand "nonsecure_call_value_internal"
7354 [(parallel [(set (match_operand 0 "" "")
3934ae0e 7355 (call (unspec:SI [(match_operand 1 "memory_operand")]
2d3a01a7 7356 UNSPEC_NONSECURE_MEM)
3934ae0e 7357 (match_operand 2 "general_operand")))
2d3a01a7 7358 (use (match_operand 3 "" ""))
e27c5a70 7359 (clobber (reg:SI LR_REGNUM))])]
2d3a01a7 7360 "use_cmse"
7361 "
7362 {
7363 rtx tmp;
7364 tmp = copy_to_suggested_reg (XEXP (operands[1], 0),
e27c5a70 7365 gen_rtx_REG (SImode, R4_REGNUM),
2d3a01a7 7366 SImode);
7367
7368 operands[1] = replace_equiv_address (operands[1], tmp);
7369 }")
7370
f1039640 7371(define_insn "*call_value_reg_armv5"
27ed6835 7372 [(set (match_operand 0 "" "")
755eb2b4 7373 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
cffb2a26 7374 (match_operand 2 "" "")))
bbe777ea 7375 (use (match_operand 3 "" ""))
bd5b4116 7376 (clobber (reg:SI LR_REGNUM))]
b232e6b5 7377 "TARGET_ARM && arm_arch5t && !SIBLING_CALL_P (insn)"
f1039640 7378 "blx%?\\t%1"
7379 [(set_attr "type" "call")]
7380)
7381
7382(define_insn "*call_value_reg_arm"
7383 [(set (match_operand 0 "" "")
7384 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7385 (match_operand 2 "" "")))
7386 (use (match_operand 3 "" ""))
7387 (clobber (reg:SI LR_REGNUM))]
b232e6b5 7388 "TARGET_ARM && !arm_arch5t && !SIBLING_CALL_P (insn)"
9c08d1fa 7389 "*
215b30b3 7390 return output_call (&operands[1]);
cffb2a26 7391 "
7392 [(set_attr "length" "12")
7393 (set_attr "type" "call")]
7394)
9c08d1fa 7395
9c08d1fa 7396;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
7397;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
7398
f7fbdd4a 7399(define_insn "*call_symbol"
27ed6835 7400 [(call (mem:SI (match_operand:SI 0 "" ""))
cffb2a26 7401 (match_operand 1 "" ""))
bbe777ea 7402 (use (match_operand 2 "" ""))
bd5b4116 7403 (clobber (reg:SI LR_REGNUM))]
d68c2c10 7404 "TARGET_32BIT
33ae7c4b 7405 && !SIBLING_CALL_P (insn)
cffb2a26 7406 && (GET_CODE (operands[0]) == SYMBOL_REF)
de55252a 7407 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
6ebaa29d 7408 "*
7409 {
95f1e0d1 7410 rtx op = operands[0];
7411
7412 /* Switch mode now when possible. */
7413 if (SYMBOL_REF_DECL (op) && !TREE_PUBLIC (SYMBOL_REF_DECL (op))
b232e6b5 7414 && arm_arch5t && arm_change_mode_p (SYMBOL_REF_DECL (op)))
95f1e0d1 7415 return NEED_PLT_RELOC ? \"blx%?\\t%a0(PLT)\" : \"blx%?\\t(%a0)\";
7416
55c1e470 7417 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
6ebaa29d 7418 }"
cffb2a26 7419 [(set_attr "type" "call")]
7420)
9c08d1fa 7421
f7fbdd4a 7422(define_insn "*call_value_symbol"
ccd90aaa 7423 [(set (match_operand 0 "" "")
27ed6835 7424 (call (mem:SI (match_operand:SI 1 "" ""))
dd6d7504 7425 (match_operand:SI 2 "" "")))
bbe777ea 7426 (use (match_operand 3 "" ""))
bd5b4116 7427 (clobber (reg:SI LR_REGNUM))]
d68c2c10 7428 "TARGET_32BIT
33ae7c4b 7429 && !SIBLING_CALL_P (insn)
cffb2a26 7430 && (GET_CODE (operands[1]) == SYMBOL_REF)
de55252a 7431 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
6ebaa29d 7432 "*
7433 {
95f1e0d1 7434 rtx op = operands[1];
7435
7436 /* Switch mode now when possible. */
7437 if (SYMBOL_REF_DECL (op) && !TREE_PUBLIC (SYMBOL_REF_DECL (op))
b232e6b5 7438 && arm_arch5t && arm_change_mode_p (SYMBOL_REF_DECL (op)))
3f6b66fa 7439 return NEED_PLT_RELOC ? \"blx%?\\t%a1(PLT)\" : \"blx%?\\t(%a1)\";
95f1e0d1 7440
55c1e470 7441 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
6ebaa29d 7442 }"
cffb2a26 7443 [(set_attr "type" "call")]
7444)
7445
ca373797 7446(define_expand "sibcall_internal"
3934ae0e 7447 [(parallel [(call (match_operand 0 "memory_operand")
7448 (match_operand 1 "general_operand"))
ca373797 7449 (return)
7450 (use (match_operand 2 "" ""))])])
7451
1c494086 7452;; We may also be able to do sibcalls for Thumb, but it's much harder...
7453(define_expand "sibcall"
3934ae0e 7454 [(parallel [(call (match_operand 0 "memory_operand")
7455 (match_operand 1 "general_operand"))
2ba80634 7456 (return)
7457 (use (match_operand 2 "" ""))])]
d68c2c10 7458 "TARGET_32BIT"
1c494086 7459 "
7460 {
ca373797 7461 rtx pat;
7462
3112c3f7 7463 if ((!REG_P (XEXP (operands[0], 0))
7464 && GET_CODE (XEXP (operands[0], 0)) != SYMBOL_REF)
7465 || (GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
7466 && arm_is_long_call_p (SYMBOL_REF_DECL (XEXP (operands[0], 0)))))
33ae7c4b 7467 XEXP (operands[0], 0) = force_reg (SImode, XEXP (operands[0], 0));
7468
1c494086 7469 if (operands[2] == NULL_RTX)
7470 operands[2] = const0_rtx;
ca373797 7471
7472 pat = gen_sibcall_internal (operands[0], operands[1], operands[2]);
7473 arm_emit_call_insn (pat, operands[0], true);
7474 DONE;
1c494086 7475 }"
7476)
7477
ca373797 7478(define_expand "sibcall_value_internal"
7479 [(parallel [(set (match_operand 0 "" "")
3934ae0e 7480 (call (match_operand 1 "memory_operand")
7481 (match_operand 2 "general_operand")))
ca373797 7482 (return)
7483 (use (match_operand 3 "" ""))])])
7484
1c494086 7485(define_expand "sibcall_value"
ccd90aaa 7486 [(parallel [(set (match_operand 0 "" "")
3934ae0e 7487 (call (match_operand 1 "memory_operand")
7488 (match_operand 2 "general_operand")))
2ba80634 7489 (return)
7490 (use (match_operand 3 "" ""))])]
d68c2c10 7491 "TARGET_32BIT"
1c494086 7492 "
7493 {
ca373797 7494 rtx pat;
7495
3112c3f7 7496 if ((!REG_P (XEXP (operands[1], 0))
7497 && GET_CODE (XEXP (operands[1], 0)) != SYMBOL_REF)
7498 || (GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
7499 && arm_is_long_call_p (SYMBOL_REF_DECL (XEXP (operands[1], 0)))))
33ae7c4b 7500 XEXP (operands[1], 0) = force_reg (SImode, XEXP (operands[1], 0));
7501
1c494086 7502 if (operands[3] == NULL_RTX)
7503 operands[3] = const0_rtx;
ca373797 7504
7505 pat = gen_sibcall_value_internal (operands[0], operands[1],
7506 operands[2], operands[3]);
7507 arm_emit_call_insn (pat, operands[1], true);
7508 DONE;
1c494086 7509 }"
7510)
7511
7512(define_insn "*sibcall_insn"
84ce8e5c 7513 [(call (mem:SI (match_operand:SI 0 "call_insn_operand" "Cs, US"))
1c494086 7514 (match_operand 1 "" ""))
2ba80634 7515 (return)
7516 (use (match_operand 2 "" ""))]
33ae7c4b 7517 "TARGET_32BIT && SIBLING_CALL_P (insn)"
1c494086 7518 "*
33ae7c4b 7519 if (which_alternative == 1)
7520 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
7521 else
7522 {
b232e6b5 7523 if (arm_arch5t || arm_arch4t)
947d113e 7524 return \"bx%?\\t%0\\t%@ indirect register sibling call\";
33ae7c4b 7525 else
7526 return \"mov%?\\t%|pc, %0\\t%@ indirect register sibling call\";
7527 }
1c494086 7528 "
7529 [(set_attr "type" "call")]
7530)
7531
7532(define_insn "*sibcall_value_insn"
84ce8e5c 7533 [(set (match_operand 0 "" "")
7534 (call (mem:SI (match_operand:SI 1 "call_insn_operand" "Cs,US"))
1c494086 7535 (match_operand 2 "" "")))
2ba80634 7536 (return)
7537 (use (match_operand 3 "" ""))]
33ae7c4b 7538 "TARGET_32BIT && SIBLING_CALL_P (insn)"
1c494086 7539 "*
33ae7c4b 7540 if (which_alternative == 1)
7541 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
7542 else
7543 {
b232e6b5 7544 if (arm_arch5t || arm_arch4t)
84ce8e5c 7545 return \"bx%?\\t%1\";
33ae7c4b 7546 else
7547 return \"mov%?\\t%|pc, %1\\t@ indirect sibling call \";
7548 }
1c494086 7549 "
7550 [(set_attr "type" "call")]
7551)
7552
0686440e 7553(define_expand "<return_str>return"
9b23f0a7 7554 [(RETURNS)]
8cba51a5 7555 "(TARGET_ARM || (TARGET_THUMB2
7556 && ARM_FUNC_TYPE (arm_current_func_type ()) == ARM_FT_NORMAL
7557 && !IS_STACKALIGN (arm_current_func_type ())))
0686440e 7558 <return_cond_false>"
8cba51a5 7559 "
7560 {
7561 if (TARGET_THUMB2)
7562 {
0686440e 7563 thumb2_expand_return (<return_simple_p>);
8cba51a5 7564 DONE;
7565 }
7566 }
7567 "
7568)
d68c2c10 7569
9c08d1fa 7570;; Often the return insn will be the same as loading from memory, so set attr
d68c2c10 7571(define_insn "*arm_return"
9c08d1fa 7572 [(return)]
cffb2a26 7573 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
9c08d1fa 7574 "*
9c08d1fa 7575 {
cffb2a26 7576 if (arm_ccfsm_state == 2)
7577 {
7578 arm_ccfsm_state += 2;
7579 return \"\";
7580 }
e2549f81 7581 return output_return_instruction (const_true_rtx, true, false, false);
cffb2a26 7582 }"
9f2c2a36 7583 [(set_attr "type" "load_4")
755eb2b4 7584 (set_attr "length" "12")
0d66636f 7585 (set_attr "predicable" "yes")]
cffb2a26 7586)
9c08d1fa 7587
0686440e 7588(define_insn "*cond_<return_str>return"
9c08d1fa 7589 [(set (pc)
8fa3ba89 7590 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 7591 [(match_operand 1 "cc_register" "") (const_int 0)])
9b23f0a7 7592 (RETURNS)
9c08d1fa 7593 (pc)))]
0686440e 7594 "TARGET_ARM <return_cond_true>"
9c08d1fa 7595 "*
8fa3ba89 7596 {
7597 if (arm_ccfsm_state == 2)
7598 {
7599 arm_ccfsm_state += 2;
7600 return \"\";
7601 }
0686440e 7602 return output_return_instruction (operands[0], true, false,
7603 <return_simple_p>);
8fa3ba89 7604 }"
7605 [(set_attr "conds" "use")
755eb2b4 7606 (set_attr "length" "12")
9f2c2a36 7607 (set_attr "type" "load_4")]
8fa3ba89 7608)
9c08d1fa 7609
0686440e 7610(define_insn "*cond_<return_str>return_inverted"
9c08d1fa 7611 [(set (pc)
8fa3ba89 7612 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 7613 [(match_operand 1 "cc_register" "") (const_int 0)])
9c08d1fa 7614 (pc)
9b23f0a7 7615 (RETURNS)))]
0686440e 7616 "TARGET_ARM <return_cond_true>"
9c08d1fa 7617 "*
8fa3ba89 7618 {
7619 if (arm_ccfsm_state == 2)
7620 {
7621 arm_ccfsm_state += 2;
7622 return \"\";
7623 }
0686440e 7624 return output_return_instruction (operands[0], true, true,
7625 <return_simple_p>);
8fa3ba89 7626 }"
7627 [(set_attr "conds" "use")
37a1317b 7628 (set_attr "length" "12")
9f2c2a36 7629 (set_attr "type" "load_4")]
8fa3ba89 7630)
9c08d1fa 7631
e2549f81 7632(define_insn "*arm_simple_return"
7633 [(simple_return)]
7634 "TARGET_ARM"
7635 "*
7636 {
7637 if (arm_ccfsm_state == 2)
7638 {
7639 arm_ccfsm_state += 2;
7640 return \"\";
7641 }
7642 return output_return_instruction (const_true_rtx, true, false, true);
7643 }"
7644 [(set_attr "type" "branch")
7645 (set_attr "length" "4")
7646 (set_attr "predicable" "yes")]
7647)
7648
68121397 7649;; Generate a sequence of instructions to determine if the processor is
7650;; in 26-bit or 32-bit mode, and return the appropriate return address
7651;; mask.
7652
7653(define_expand "return_addr_mask"
7654 [(set (match_dup 1)
7655 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7656 (const_int 0)))
3934ae0e 7657 (set (match_operand:SI 0 "s_register_operand")
68121397 7658 (if_then_else:SI (eq (match_dup 1) (const_int 0))
7659 (const_int -1)
7660 (const_int 67108860)))] ; 0x03fffffc
7661 "TARGET_ARM"
7662 "
62eddbd4 7663 operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
68121397 7664 ")
7665
7666(define_insn "*check_arch2"
7667 [(set (match_operand:CC_NOOV 0 "cc_register" "")
7668 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7669 (const_int 0)))]
7670 "TARGET_ARM"
7671 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
7672 [(set_attr "length" "8")
1b7da4ac 7673 (set_attr "conds" "set")
7674 (set_attr "type" "multiple")]
68121397 7675)
7676
9c08d1fa 7677;; Call subroutine returning any type.
7678
7679(define_expand "untyped_call"
7680 [(parallel [(call (match_operand 0 "" "")
7681 (const_int 0))
7682 (match_operand 1 "" "")
7683 (match_operand 2 "" "")])]
2649fa41 7684 "TARGET_EITHER && !TARGET_FDPIC"
9c08d1fa 7685 "
215b30b3 7686 {
7687 int i;
ccd90aaa 7688 rtx par = gen_rtx_PARALLEL (VOIDmode,
7689 rtvec_alloc (XVECLEN (operands[2], 0)));
7690 rtx addr = gen_reg_rtx (Pmode);
7691 rtx mem;
7692 int size = 0;
9c08d1fa 7693
ccd90aaa 7694 emit_move_insn (addr, XEXP (operands[1], 0));
7695 mem = change_address (operands[1], BLKmode, addr);
9c08d1fa 7696
215b30b3 7697 for (i = 0; i < XVECLEN (operands[2], 0); i++)
7698 {
ccd90aaa 7699 rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
9c08d1fa 7700
ccd90aaa 7701 /* Default code only uses r0 as a return value, but we could
7702 be using anything up to 4 registers. */
7703 if (REGNO (src) == R0_REGNUM)
7704 src = gen_rtx_REG (TImode, R0_REGNUM);
7705
7706 XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
7707 GEN_INT (size));
7708 size += GET_MODE_SIZE (GET_MODE (src));
7709 }
7710
7f265a08 7711 emit_call_insn (gen_call_value (par, operands[0], const0_rtx, NULL));
ccd90aaa 7712
7713 size = 0;
7714
7715 for (i = 0; i < XVECLEN (par, 0); i++)
7716 {
7717 HOST_WIDE_INT offset = 0;
7718 rtx reg = XEXP (XVECEXP (par, 0, i), 0);
7719
7720 if (size != 0)
29c05e22 7721 emit_move_insn (addr, plus_constant (Pmode, addr, size));
ccd90aaa 7722
7723 mem = change_address (mem, GET_MODE (reg), NULL);
7724 if (REGNO (reg) == R0_REGNUM)
7725 {
7726 /* On thumb we have to use a write-back instruction. */
320ea44d 7727 emit_insn (arm_gen_store_multiple (arm_regs_in_sequence, 4, addr,
7728 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
ccd90aaa 7729 size = TARGET_ARM ? 16 : 0;
7730 }
7731 else
7732 {
7733 emit_move_insn (mem, reg);
7734 size = GET_MODE_SIZE (GET_MODE (reg));
7735 }
215b30b3 7736 }
9c08d1fa 7737
215b30b3 7738 /* The optimizer does not know that the call sets the function value
7739 registers we stored in the result block. We avoid problems by
7740 claiming that all hard registers are used and clobbered at this
7741 point. */
7742 emit_insn (gen_blockage ());
7743
7744 DONE;
7745 }"
7746)
9c08d1fa 7747
ccd90aaa 7748(define_expand "untyped_return"
3934ae0e 7749 [(match_operand:BLK 0 "memory_operand")
ccd90aaa 7750 (match_operand 1 "" "")]
2649fa41 7751 "TARGET_EITHER && !TARGET_FDPIC"
ccd90aaa 7752 "
7753 {
7754 int i;
7755 rtx addr = gen_reg_rtx (Pmode);
7756 rtx mem;
7757 int size = 0;
7758
7759 emit_move_insn (addr, XEXP (operands[0], 0));
7760 mem = change_address (operands[0], BLKmode, addr);
7761
7762 for (i = 0; i < XVECLEN (operands[1], 0); i++)
7763 {
7764 HOST_WIDE_INT offset = 0;
7765 rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
7766
7767 if (size != 0)
29c05e22 7768 emit_move_insn (addr, plus_constant (Pmode, addr, size));
ccd90aaa 7769
7770 mem = change_address (mem, GET_MODE (reg), NULL);
7771 if (REGNO (reg) == R0_REGNUM)
7772 {
7773 /* On thumb we have to use a write-back instruction. */
320ea44d 7774 emit_insn (arm_gen_load_multiple (arm_regs_in_sequence, 4, addr,
7775 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
ccd90aaa 7776 size = TARGET_ARM ? 16 : 0;
7777 }
7778 else
7779 {
7780 emit_move_insn (reg, mem);
7781 size = GET_MODE_SIZE (GET_MODE (reg));
7782 }
7783 }
7784
7785 /* Emit USE insns before the return. */
7786 for (i = 0; i < XVECLEN (operands[1], 0); i++)
18b42941 7787 emit_use (SET_DEST (XVECEXP (operands[1], 0, i)));
ccd90aaa 7788
7789 /* Construct the return. */
7790 expand_naked_return ();
7791
7792 DONE;
7793 }"
7794)
7795
9c08d1fa 7796;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
7797;; all of memory. This blocks insns from being moved across this point.
7798
7799(define_insn "blockage"
e1159bbe 7800 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
cffb2a26 7801 "TARGET_EITHER"
9c08d1fa 7802 ""
cffb2a26 7803 [(set_attr "length" "0")
7804 (set_attr "type" "block")]
7805)
9c08d1fa 7806
80c63fc3 7807;; Since we hard code r0 here use the 'o' constraint to prevent
7808;; provoking undefined behaviour in the hardware with putting out
7809;; auto-increment operations with potentially r0 as the base register.
706dca65 7810(define_insn "probe_stack"
80c63fc3 7811 [(set (match_operand:SI 0 "memory_operand" "=o")
f8570abe 7812 (unspec:SI [(const_int 0)] UNSPEC_PROBE_STACK))]
706dca65 7813 "TARGET_32BIT"
154ae8e6 7814 "str%?\\tr0, %0"
9f2c2a36 7815 [(set_attr "type" "store_4")
706dca65 7816 (set_attr "predicable" "yes")]
7817)
7818
7819(define_insn "probe_stack_range"
7820 [(set (match_operand:SI 0 "register_operand" "=r")
7821 (unspec_volatile:SI [(match_operand:SI 1 "register_operand" "0")
7822 (match_operand:SI 2 "register_operand" "r")]
dd8aabc9 7823 VUNSPEC_PROBE_STACK_RANGE))]
706dca65 7824 "TARGET_32BIT"
7825{
7826 return output_probe_stack_range (operands[0], operands[2]);
7827}
7828 [(set_attr "type" "multiple")
7829 (set_attr "conds" "clob")]
7830)
7831
f98495d9 7832;; Named patterns for stack smashing protection.
7833(define_expand "stack_protect_combined_set"
7834 [(parallel
3934ae0e 7835 [(set (match_operand:SI 0 "memory_operand")
7836 (unspec:SI [(match_operand:SI 1 "guard_operand")]
f98495d9 7837 UNSPEC_SP_SET))
7838 (clobber (match_scratch:SI 2 ""))
7839 (clobber (match_scratch:SI 3 ""))])]
7840 ""
7841 ""
7842)
7843
7844;; Use a separate insn from the above expand to be able to have the mem outside
7845;; the operand #1 when register allocation comes. This is needed to avoid LRA
7846;; try to reload the guard since we need to control how PIC access is done in
7847;; the -fpic/-fPIC case (see COMPUTE_NOW parameter when calling
7848;; legitimize_pic_address ()).
7849(define_insn_and_split "*stack_protect_combined_set_insn"
7850 [(set (match_operand:SI 0 "memory_operand" "=m,m")
7851 (unspec:SI [(mem:SI (match_operand:SI 1 "guard_addr_operand" "X,X"))]
7852 UNSPEC_SP_SET))
7853 (clobber (match_scratch:SI 2 "=&l,&r"))
7854 (clobber (match_scratch:SI 3 "=&l,&r"))]
7855 ""
7856 "#"
7857 "reload_completed"
7858 [(parallel [(set (match_dup 0) (unspec:SI [(mem:SI (match_dup 2))]
7859 UNSPEC_SP_SET))
7860 (clobber (match_dup 2))])]
7861 "
7862{
7863 if (flag_pic)
7864 {
d89c0749 7865 rtx pic_reg;
7866
7867 if (TARGET_FDPIC)
7868 pic_reg = gen_rtx_REG (Pmode, FDPIC_REGNUM);
7869 else
7870 pic_reg = operands[3];
7871
f98495d9 7872 /* Forces recomputing of GOT base now. */
d89c0749 7873 legitimize_pic_address (operands[1], SImode, operands[2], pic_reg,
f98495d9 7874 true /*compute_now*/);
7875 }
7876 else
7877 {
7878 if (address_operand (operands[1], SImode))
7879 operands[2] = operands[1];
7880 else
7881 {
7882 rtx mem = XEXP (force_const_mem (SImode, operands[1]), 0);
7883 emit_move_insn (operands[2], mem);
7884 }
7885 }
7886}"
7887 [(set_attr "arch" "t1,32")]
7888)
7889
fa66a3db 7890;; DO NOT SPLIT THIS INSN. It's important for security reasons that the
7891;; canary value does not live beyond the life of this sequence.
f98495d9 7892(define_insn "*stack_protect_set_insn"
7893 [(set (match_operand:SI 0 "memory_operand" "=m,m")
7894 (unspec:SI [(mem:SI (match_operand:SI 1 "register_operand" "+&l,&r"))]
7895 UNSPEC_SP_SET))
7896 (clobber (match_dup 1))]
7897 ""
7898 "@
fa66a3db 7899 ldr\\t%1, [%1]\;str\\t%1, %0\;movs\t%1, #0
7900 ldr\\t%1, [%1]\;str\\t%1, %0\;mov\t%1, #0"
f98495d9 7901 [(set_attr "length" "8,12")
7902 (set_attr "conds" "clob,nocond")
7903 (set_attr "type" "multiple")
7904 (set_attr "arch" "t1,32")]
7905)
7906
7907(define_expand "stack_protect_combined_test"
7908 [(parallel
7909 [(set (pc)
7910 (if_then_else
3934ae0e 7911 (eq (match_operand:SI 0 "memory_operand")
7912 (unspec:SI [(match_operand:SI 1 "guard_operand")]
f98495d9 7913 UNSPEC_SP_TEST))
7914 (label_ref (match_operand 2))
7915 (pc)))
7916 (clobber (match_scratch:SI 3 ""))
7917 (clobber (match_scratch:SI 4 ""))
7918 (clobber (reg:CC CC_REGNUM))])]
7919 ""
7920 ""
7921)
7922
7923;; Use a separate insn from the above expand to be able to have the mem outside
7924;; the operand #1 when register allocation comes. This is needed to avoid LRA
7925;; try to reload the guard since we need to control how PIC access is done in
7926;; the -fpic/-fPIC case (see COMPUTE_NOW parameter when calling
7927;; legitimize_pic_address ()).
7928(define_insn_and_split "*stack_protect_combined_test_insn"
7929 [(set (pc)
7930 (if_then_else
7931 (eq (match_operand:SI 0 "memory_operand" "m,m")
7932 (unspec:SI [(mem:SI (match_operand:SI 1 "guard_addr_operand" "X,X"))]
7933 UNSPEC_SP_TEST))
7934 (label_ref (match_operand 2))
7935 (pc)))
7936 (clobber (match_scratch:SI 3 "=&l,&r"))
7937 (clobber (match_scratch:SI 4 "=&l,&r"))
7938 (clobber (reg:CC CC_REGNUM))]
7939 ""
7940 "#"
7941 "reload_completed"
7942 [(const_int 0)]
7943{
7944 rtx eq;
7945
7946 if (flag_pic)
7947 {
d89c0749 7948 rtx pic_reg;
7949
7950 if (TARGET_FDPIC)
7951 pic_reg = gen_rtx_REG (Pmode, FDPIC_REGNUM);
7952 else
7953 pic_reg = operands[4];
7954
f98495d9 7955 /* Forces recomputing of GOT base now. */
d89c0749 7956 legitimize_pic_address (operands[1], SImode, operands[3], pic_reg,
f98495d9 7957 true /*compute_now*/);
7958 }
7959 else
7960 {
7961 if (address_operand (operands[1], SImode))
7962 operands[3] = operands[1];
7963 else
7964 {
7965 rtx mem = XEXP (force_const_mem (SImode, operands[1]), 0);
7966 emit_move_insn (operands[3], mem);
7967 }
7968 }
7969 if (TARGET_32BIT)
7970 {
7971 emit_insn (gen_arm_stack_protect_test_insn (operands[4], operands[0],
7972 operands[3]));
7973 rtx cc_reg = gen_rtx_REG (CC_Zmode, CC_REGNUM);
7974 eq = gen_rtx_EQ (CC_Zmode, cc_reg, const0_rtx);
7975 emit_jump_insn (gen_arm_cond_branch (operands[2], eq, cc_reg));
7976 }
7977 else
7978 {
7979 emit_insn (gen_thumb1_stack_protect_test_insn (operands[4], operands[0],
7980 operands[3]));
7981 eq = gen_rtx_EQ (VOIDmode, operands[4], const0_rtx);
7982 emit_jump_insn (gen_cbranchsi4 (eq, operands[4], const0_rtx,
7983 operands[2]));
7984 }
7985 DONE;
7986}
7987 [(set_attr "arch" "t1,32")]
7988)
7989
7990(define_insn "arm_stack_protect_test_insn"
7991 [(set (reg:CC_Z CC_REGNUM)
7992 (compare:CC_Z (unspec:SI [(match_operand:SI 1 "memory_operand" "m,m")
7993 (mem:SI (match_operand:SI 2 "register_operand" "+l,r"))]
7994 UNSPEC_SP_TEST)
7995 (const_int 0)))
7996 (clobber (match_operand:SI 0 "register_operand" "=&l,&r"))
7997 (clobber (match_dup 2))]
7998 "TARGET_32BIT"
7999 "ldr\t%0, [%2]\;ldr\t%2, %1\;eors\t%0, %2, %0"
8000 [(set_attr "length" "8,12")
8001 (set_attr "conds" "set")
8002 (set_attr "type" "multiple")
8003 (set_attr "arch" "t,32")]
8004)
8005
f7fbdd4a 8006(define_expand "casesi"
3934ae0e 8007 [(match_operand:SI 0 "s_register_operand") ; index to jump on
8008 (match_operand:SI 1 "const_int_operand") ; lower bound
8009 (match_operand:SI 2 "const_int_operand") ; total range
f7fbdd4a 8010 (match_operand:SI 3 "" "") ; table label
8011 (match_operand:SI 4 "" "")] ; Out of range label
9753b549 8012 "(TARGET_32BIT || optimize_size || flag_pic) && !target_pure_code"
f7fbdd4a 8013 "
215b30b3 8014 {
e6ac8414 8015 enum insn_code code;
215b30b3 8016 if (operands[1] != const0_rtx)
8017 {
e6ac8414 8018 rtx reg = gen_reg_rtx (SImode);
f7fbdd4a 8019
215b30b3 8020 emit_insn (gen_addsi3 (reg, operands[0],
d022fa24 8021 gen_int_mode (-INTVAL (operands[1]),
8022 SImode)));
215b30b3 8023 operands[0] = reg;
8024 }
9c08d1fa 8025
25f905c2 8026 if (TARGET_ARM)
e6ac8414 8027 code = CODE_FOR_arm_casesi_internal;
3db2019b 8028 else if (TARGET_THUMB1)
e6ac8414 8029 code = CODE_FOR_thumb1_casesi_internal_pic;
25f905c2 8030 else if (flag_pic)
e6ac8414 8031 code = CODE_FOR_thumb2_casesi_internal_pic;
25f905c2 8032 else
e6ac8414 8033 code = CODE_FOR_thumb2_casesi_internal;
8034
8035 if (!insn_data[(int) code].operand[1].predicate(operands[2], SImode))
8036 operands[2] = force_reg (SImode, operands[2]);
8037
8038 emit_jump_insn (GEN_FCN ((int) code) (operands[0], operands[2],
8039 operands[3], operands[4]));
215b30b3 8040 DONE;
8041 }"
8042)
f7fbdd4a 8043
f082f1c4 8044;; The USE in this pattern is needed to tell flow analysis that this is
8045;; a CASESI insn. It has no other purpose.
b634d96a 8046(define_expand "arm_casesi_internal"
8047 [(parallel [(set (pc)
8048 (if_then_else
8049 (leu (match_operand:SI 0 "s_register_operand")
8050 (match_operand:SI 1 "arm_rhs_operand"))
8051 (match_dup 4)
8052 (label_ref:SI (match_operand 3 ""))))
8053 (clobber (reg:CC CC_REGNUM))
8054 (use (label_ref:SI (match_operand 2 "")))])]
8055 "TARGET_ARM"
8056{
8057 operands[4] = gen_rtx_MULT (SImode, operands[0], GEN_INT (4));
8058 operands[4] = gen_rtx_PLUS (SImode, operands[4],
8059 gen_rtx_LABEL_REF (SImode, operands[2]));
8060 operands[4] = gen_rtx_MEM (SImode, operands[4]);
8061 MEM_READONLY_P (operands[4]) = 1;
8062 MEM_NOTRAP_P (operands[4]) = 1;
8063})
8064
8065(define_insn "*arm_casesi_internal"
f082f1c4 8066 [(parallel [(set (pc)
8067 (if_then_else
8068 (leu (match_operand:SI 0 "s_register_operand" "r")
8069 (match_operand:SI 1 "arm_rhs_operand" "rI"))
8070 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
b634d96a 8071 (label_ref:SI (match_operand 2 "" ""))))
8072 (label_ref:SI (match_operand 3 "" ""))))
bd5b4116 8073 (clobber (reg:CC CC_REGNUM))
b634d96a 8074 (use (label_ref:SI (match_dup 2)))])]
cffb2a26 8075 "TARGET_ARM"
f7fbdd4a 8076 "*
0d66636f 8077 if (flag_pic)
8078 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
8079 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
8080 "
8081 [(set_attr "conds" "clob")
1b7da4ac 8082 (set_attr "length" "12")
8083 (set_attr "type" "multiple")]
0d66636f 8084)
9c08d1fa 8085
cffb2a26 8086(define_expand "indirect_jump"
9c08d1fa 8087 [(set (pc)
3934ae0e 8088 (match_operand:SI 0 "s_register_operand"))]
cffb2a26 8089 "TARGET_EITHER"
25f905c2 8090 "
8091 /* Thumb-2 doesn't have mov pc, reg. Explicitly set the low bit of the
8092 address and use bx. */
8093 if (TARGET_THUMB2)
8094 {
8095 rtx tmp;
8096 tmp = gen_reg_rtx (SImode);
8097 emit_insn (gen_iorsi3 (tmp, operands[0], GEN_INT(1)));
8098 operands[0] = tmp;
8099 }
8100 "
cffb2a26 8101)
8102
f1039640 8103;; NB Never uses BX.
cffb2a26 8104(define_insn "*arm_indirect_jump"
8105 [(set (pc)
8106 (match_operand:SI 0 "s_register_operand" "r"))]
8107 "TARGET_ARM"
8108 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
1b7da4ac 8109 [(set_attr "predicable" "yes")
8110 (set_attr "type" "branch")]
cffb2a26 8111)
9c08d1fa 8112
f7fbdd4a 8113(define_insn "*load_indirect_jump"
9c08d1fa 8114 [(set (pc)
8115 (match_operand:SI 0 "memory_operand" "m"))]
cffb2a26 8116 "TARGET_ARM"
8117 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
9f2c2a36 8118 [(set_attr "type" "load_4")
61a2d04c 8119 (set_attr "pool_range" "4096")
8120 (set_attr "neg_pool_range" "4084")
0d66636f 8121 (set_attr "predicable" "yes")]
cffb2a26 8122)
8123
9c08d1fa 8124\f
8125;; Misc insns
8126
8127(define_insn "nop"
8128 [(const_int 0)]
cffb2a26 8129 "TARGET_EITHER"
3ef90e77 8130 "nop"
cffb2a26 8131 [(set (attr "length")
8132 (if_then_else (eq_attr "is_thumb" "yes")
8133 (const_int 2)
1b7da4ac 8134 (const_int 4)))
8135 (set_attr "type" "mov_reg")]
cffb2a26 8136)
8137
ad9d4399 8138(define_insn "trap"
8139 [(trap_if (const_int 1) (const_int 0))]
8140 ""
8141 "*
8142 if (TARGET_ARM)
8143 return \".inst\\t0xe7f000f0\";
8144 else
8145 return \".inst\\t0xdeff\";
8146 "
8147 [(set (attr "length")
8148 (if_then_else (eq_attr "is_thumb" "yes")
8149 (const_int 2)
8150 (const_int 4)))
8151 (set_attr "type" "trap")
8152 (set_attr "conds" "unconditional")]
8153)
8154
9c08d1fa 8155\f
8156;; Patterns to allow combination of arithmetic, cond code and shifts
8157
0abea32c 8158(define_insn "*<arith_shift_insn>_multsi"
8159 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9b23f0a7 8160 (SHIFTABLE_OPS:SI
0abea32c 8161 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
8162 (match_operand:SI 3 "power_of_two_operand" ""))
8163 (match_operand:SI 1 "s_register_operand" "rk,<t2_binop0>")))]
d5d4dc8d 8164 "TARGET_32BIT"
0abea32c 8165 "<arith_shift_insn>%?\\t%0, %1, %2, lsl %b3"
8166 [(set_attr "predicable" "yes")
753d9835 8167 (set_attr "shift" "2")
0abea32c 8168 (set_attr "arch" "a,t2")
8169 (set_attr "type" "alu_shift_imm")])
8170
8171(define_insn "*<arith_shift_insn>_shiftsi"
8172 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9b23f0a7 8173 (SHIFTABLE_OPS:SI
0abea32c 8174 (match_operator:SI 2 "shift_nomul_operator"
8175 [(match_operand:SI 3 "s_register_operand" "r,r,r")
8176 (match_operand:SI 4 "shift_amount_operand" "M,M,r")])
8177 (match_operand:SI 1 "s_register_operand" "rk,<t2_binop0>,rk")))]
a021b821 8178 "TARGET_32BIT && GET_CODE (operands[2]) != MULT"
0abea32c 8179 "<arith_shift_insn>%?\\t%0, %1, %3%S2"
344495ea 8180 [(set_attr "predicable" "yes")
753d9835 8181 (set_attr "shift" "3")
0abea32c 8182 (set_attr "arch" "a,t2,a")
8183 (set_attr "type" "alu_shift_imm,alu_shift_imm,alu_shift_reg")])
9c08d1fa 8184
d7863cfe 8185(define_split
8186 [(set (match_operand:SI 0 "s_register_operand" "")
8187 (match_operator:SI 1 "shiftable_operator"
8188 [(match_operator:SI 2 "shiftable_operator"
8189 [(match_operator:SI 3 "shift_operator"
8190 [(match_operand:SI 4 "s_register_operand" "")
8191 (match_operand:SI 5 "reg_or_int_operand" "")])
8192 (match_operand:SI 6 "s_register_operand" "")])
8193 (match_operand:SI 7 "arm_rhs_operand" "")]))
8194 (clobber (match_operand:SI 8 "s_register_operand" ""))]
d5d4dc8d 8195 "TARGET_32BIT"
d7863cfe 8196 [(set (match_dup 8)
8197 (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8198 (match_dup 6)]))
8199 (set (match_dup 0)
8200 (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
8201 "")
8202
f7fbdd4a 8203(define_insn "*arith_shiftsi_compare0"
bd5b4116 8204 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 8205 (compare:CC_NOOV
8206 (match_operator:SI 1 "shiftable_operator"
8207 [(match_operator:SI 3 "shift_operator"
8208 [(match_operand:SI 4 "s_register_operand" "r,r")
8209 (match_operand:SI 5 "shift_amount_operand" "M,r")])
8210 (match_operand:SI 2 "s_register_operand" "r,r")])
8211 (const_int 0)))
8212 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 8213 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8214 (match_dup 2)]))]
d5d4dc8d 8215 "TARGET_32BIT"
3ef90e77 8216 "%i1s%?\\t%0, %2, %4%S3"
344495ea 8217 [(set_attr "conds" "set")
331beb1a 8218 (set_attr "shift" "4")
d5d4dc8d 8219 (set_attr "arch" "32,a")
d82e788e 8220 (set_attr "type" "alus_shift_imm,alus_shift_reg")])
9c08d1fa 8221
f7fbdd4a 8222(define_insn "*arith_shiftsi_compare0_scratch"
bd5b4116 8223 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 8224 (compare:CC_NOOV
8225 (match_operator:SI 1 "shiftable_operator"
8226 [(match_operator:SI 3 "shift_operator"
8227 [(match_operand:SI 4 "s_register_operand" "r,r")
8228 (match_operand:SI 5 "shift_amount_operand" "M,r")])
8229 (match_operand:SI 2 "s_register_operand" "r,r")])
8230 (const_int 0)))
8231 (clobber (match_scratch:SI 0 "=r,r"))]
8232 "TARGET_32BIT"
3ef90e77 8233 "%i1s%?\\t%0, %2, %4%S3"
344495ea 8234 [(set_attr "conds" "set")
331beb1a 8235 (set_attr "shift" "4")
d5d4dc8d 8236 (set_attr "arch" "32,a")
d82e788e 8237 (set_attr "type" "alus_shift_imm,alus_shift_reg")])
9c08d1fa 8238
f7fbdd4a 8239(define_insn "*sub_shiftsi"
d5d4dc8d 8240 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8241 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
9c08d1fa 8242 (match_operator:SI 2 "shift_operator"
d5d4dc8d 8243 [(match_operand:SI 3 "s_register_operand" "r,r")
8244 (match_operand:SI 4 "shift_amount_operand" "M,r")])))]
8245 "TARGET_32BIT"
6c4c2133 8246 "sub%?\\t%0, %1, %3%S2"
344495ea 8247 [(set_attr "predicable" "yes")
2df5a382 8248 (set_attr "predicable_short_it" "no")
331beb1a 8249 (set_attr "shift" "3")
d5d4dc8d 8250 (set_attr "arch" "32,a")
d82e788e 8251 (set_attr "type" "alus_shift_imm,alus_shift_reg")])
9c08d1fa 8252
f7fbdd4a 8253(define_insn "*sub_shiftsi_compare0"
bd5b4116 8254 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 8255 (compare:CC_NOOV
d82e788e 8256 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
40dbec34 8257 (match_operator:SI 2 "shift_operator"
d82e788e 8258 [(match_operand:SI 3 "s_register_operand" "r,r,r")
8259 (match_operand:SI 4 "shift_amount_operand" "M,r,M")]))
40dbec34 8260 (const_int 0)))
d82e788e 8261 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
d5d4dc8d 8262 (minus:SI (match_dup 1)
8263 (match_op_dup 2 [(match_dup 3) (match_dup 4)])))]
8264 "TARGET_32BIT"
3ef90e77 8265 "subs%?\\t%0, %1, %3%S2"
344495ea 8266 [(set_attr "conds" "set")
a2cd141b 8267 (set_attr "shift" "3")
d82e788e 8268 (set_attr "arch" "32,a,a")
8269 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
9c08d1fa 8270
f7fbdd4a 8271(define_insn "*sub_shiftsi_compare0_scratch"
bd5b4116 8272 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 8273 (compare:CC_NOOV
d82e788e 8274 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
40dbec34 8275 (match_operator:SI 2 "shift_operator"
d82e788e 8276 [(match_operand:SI 3 "s_register_operand" "r,r,r")
8277 (match_operand:SI 4 "shift_amount_operand" "M,r,M")]))
40dbec34 8278 (const_int 0)))
d82e788e 8279 (clobber (match_scratch:SI 0 "=r,r,r"))]
d5d4dc8d 8280 "TARGET_32BIT"
3ef90e77 8281 "subs%?\\t%0, %1, %3%S2"
344495ea 8282 [(set_attr "conds" "set")
a2cd141b 8283 (set_attr "shift" "3")
d82e788e 8284 (set_attr "arch" "32,a,a")
8285 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
9c08d1fa 8286\f
8287
190efb17 8288(define_insn_and_split "*and_scc"
9c08d1fa 8289 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 8290 (and:SI (match_operator:SI 1 "arm_comparison_operator"
190efb17 8291 [(match_operand 2 "cc_register" "") (const_int 0)])
8292 (match_operand:SI 3 "s_register_operand" "r")))]
cffb2a26 8293 "TARGET_ARM"
190efb17 8294 "#" ; "mov%D1\\t%0, #0\;and%d1\\t%0, %3, #1"
8295 "&& reload_completed"
8296 [(cond_exec (match_dup 5) (set (match_dup 0) (const_int 0)))
8297 (cond_exec (match_dup 4) (set (match_dup 0)
8298 (and:SI (match_dup 3) (const_int 1))))]
8299 {
3754d046 8300 machine_mode mode = GET_MODE (operands[2]);
190efb17 8301 enum rtx_code rc = GET_CODE (operands[1]);
8302
8303 /* Note that operands[4] is the same as operands[1],
8304 but with VOIDmode as the result. */
8305 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
8306 if (mode == CCFPmode || mode == CCFPEmode)
8307 rc = reverse_condition_maybe_unordered (rc);
8308 else
8309 rc = reverse_condition (rc);
8310 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
8311 }
8fa3ba89 8312 [(set_attr "conds" "use")
1b7da4ac 8313 (set_attr "type" "multiple")
8fa3ba89 8314 (set_attr "length" "8")]
8315)
9c08d1fa 8316
190efb17 8317(define_insn_and_split "*ior_scc"
9c08d1fa 8318 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
190efb17 8319 (ior:SI (match_operator:SI 1 "arm_comparison_operator"
8320 [(match_operand 2 "cc_register" "") (const_int 0)])
8321 (match_operand:SI 3 "s_register_operand" "0,?r")))]
cffb2a26 8322 "TARGET_ARM"
e2348bcb 8323 "@
190efb17 8324 orr%d1\\t%0, %3, #1
8325 #"
8326 "&& reload_completed
8327 && REGNO (operands [0]) != REGNO (operands[3])"
8328 ;; && which_alternative == 1
8329 ; mov%D1\\t%0, %3\;orr%d1\\t%0, %3, #1
8330 [(cond_exec (match_dup 5) (set (match_dup 0) (match_dup 3)))
8331 (cond_exec (match_dup 4) (set (match_dup 0)
8332 (ior:SI (match_dup 3) (const_int 1))))]
8333 {
3754d046 8334 machine_mode mode = GET_MODE (operands[2]);
190efb17 8335 enum rtx_code rc = GET_CODE (operands[1]);
8336
8337 /* Note that operands[4] is the same as operands[1],
8338 but with VOIDmode as the result. */
8339 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
8340 if (mode == CCFPmode || mode == CCFPEmode)
8341 rc = reverse_condition_maybe_unordered (rc);
8342 else
8343 rc = reverse_condition (rc);
8344 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
8345 }
8fa3ba89 8346 [(set_attr "conds" "use")
1b7da4ac 8347 (set_attr "length" "4,8")
8348 (set_attr "type" "logic_imm,multiple")]
8fa3ba89 8349)
9c08d1fa 8350
2df9477b 8351; A series of splitters for the compare_scc pattern below. Note that
8352; order is important.
8353(define_split
8354 [(set (match_operand:SI 0 "s_register_operand" "")
8355 (lt:SI (match_operand:SI 1 "s_register_operand" "")
8356 (const_int 0)))
8357 (clobber (reg:CC CC_REGNUM))]
8358 "TARGET_32BIT && reload_completed"
8359 [(set (match_dup 0) (lshiftrt:SI (match_dup 1) (const_int 31)))])
8360
8361(define_split
8362 [(set (match_operand:SI 0 "s_register_operand" "")
8363 (ge:SI (match_operand:SI 1 "s_register_operand" "")
8364 (const_int 0)))
8365 (clobber (reg:CC CC_REGNUM))]
8366 "TARGET_32BIT && reload_completed"
8367 [(set (match_dup 0) (not:SI (match_dup 1)))
8368 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 31)))])
8369
98562479 8370(define_split
8371 [(set (match_operand:SI 0 "s_register_operand" "")
8372 (eq:SI (match_operand:SI 1 "s_register_operand" "")
8373 (const_int 0)))
8374 (clobber (reg:CC CC_REGNUM))]
b232e6b5 8375 "arm_arch5t && TARGET_32BIT"
98562479 8376 [(set (match_dup 0) (clz:SI (match_dup 1)))
8377 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 5)))]
8378)
8379
2df9477b 8380(define_split
8381 [(set (match_operand:SI 0 "s_register_operand" "")
8382 (eq:SI (match_operand:SI 1 "s_register_operand" "")
8383 (const_int 0)))
8384 (clobber (reg:CC CC_REGNUM))]
8385 "TARGET_32BIT && reload_completed"
8386 [(parallel
080c0b9a 8387 [(set (reg:CC CC_REGNUM)
8388 (compare:CC (const_int 1) (match_dup 1)))
2df9477b 8389 (set (match_dup 0)
8390 (minus:SI (const_int 1) (match_dup 1)))])
080c0b9a 8391 (cond_exec (ltu:CC (reg:CC CC_REGNUM) (const_int 0))
2df9477b 8392 (set (match_dup 0) (const_int 0)))])
8393
8394(define_split
8395 [(set (match_operand:SI 0 "s_register_operand" "")
8396 (ne:SI (match_operand:SI 1 "s_register_operand" "")
8397 (match_operand:SI 2 "const_int_operand" "")))
8398 (clobber (reg:CC CC_REGNUM))]
8399 "TARGET_32BIT && reload_completed"
8400 [(parallel
8401 [(set (reg:CC CC_REGNUM)
8402 (compare:CC (match_dup 1) (match_dup 2)))
8403 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))])
8404 (cond_exec (ne:CC (reg:CC CC_REGNUM) (const_int 0))
8405 (set (match_dup 0) (const_int 1)))]
8406{
e3dcfc16 8407 operands[3] = gen_int_mode (-INTVAL (operands[2]), SImode);
2df9477b 8408})
8409
8410(define_split
8411 [(set (match_operand:SI 0 "s_register_operand" "")
8412 (ne:SI (match_operand:SI 1 "s_register_operand" "")
8413 (match_operand:SI 2 "arm_add_operand" "")))
8414 (clobber (reg:CC CC_REGNUM))]
8415 "TARGET_32BIT && reload_completed"
8416 [(parallel
8417 [(set (reg:CC_NOOV CC_REGNUM)
8418 (compare:CC_NOOV (minus:SI (match_dup 1) (match_dup 2))
8419 (const_int 0)))
8420 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
8421 (cond_exec (ne:CC_NOOV (reg:CC_NOOV CC_REGNUM) (const_int 0))
8422 (set (match_dup 0) (const_int 1)))])
8423
8424(define_insn_and_split "*compare_scc"
fd711051 8425 [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts")
8fa3ba89 8426 (match_operator:SI 1 "arm_comparison_operator"
5565501b 8427 [(match_operand:SI 2 "s_register_operand" "r,r")
8428 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
bd5b4116 8429 (clobber (reg:CC CC_REGNUM))]
2df9477b 8430 "TARGET_32BIT"
8431 "#"
8432 "&& reload_completed"
8433 [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 3)))
8434 (cond_exec (match_dup 4) (set (match_dup 0) (const_int 0)))
8435 (cond_exec (match_dup 5) (set (match_dup 0) (const_int 1)))]
8436{
8437 rtx tmp1;
3754d046 8438 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
2df9477b 8439 operands[2], operands[3]);
8440 enum rtx_code rc = GET_CODE (operands[1]);
e2348bcb 8441
2df9477b 8442 tmp1 = gen_rtx_REG (mode, CC_REGNUM);
080c0b9a 8443
2df9477b 8444 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
8445 if (mode == CCFPmode || mode == CCFPEmode)
8446 rc = reverse_condition_maybe_unordered (rc);
8447 else
8448 rc = reverse_condition (rc);
8449 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
1b7da4ac 8450}
8451 [(set_attr "type" "multiple")]
8452)
9c08d1fa 8453
080c0b9a 8454;; Attempt to improve the sequence generated by the compare_scc splitters
8455;; not to use conditional execution.
98562479 8456
8457;; Rd = (eq (reg1) (const_int0)) // ARMv5
8458;; clz Rd, reg1
8459;; lsr Rd, Rd, #5
080c0b9a 8460(define_peephole2
8461 [(set (reg:CC CC_REGNUM)
8462 (compare:CC (match_operand:SI 1 "register_operand" "")
98562479 8463 (const_int 0)))
8464 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
8465 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
8466 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
8467 (set (match_dup 0) (const_int 1)))]
b232e6b5 8468 "arm_arch5t && TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)"
98562479 8469 [(set (match_dup 0) (clz:SI (match_dup 1)))
8470 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 5)))]
8471)
8472
8473;; Rd = (eq (reg1) (const_int0)) // !ARMv5
8474;; negs Rd, reg1
8475;; adc Rd, Rd, reg1
8476(define_peephole2
8477 [(set (reg:CC CC_REGNUM)
8478 (compare:CC (match_operand:SI 1 "register_operand" "")
8479 (const_int 0)))
080c0b9a 8480 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
8481 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
8482 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
8483 (set (match_dup 0) (const_int 1)))
98562479 8484 (match_scratch:SI 2 "r")]
8485 "TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)"
922b6913 8486 [(parallel
8487 [(set (reg:CC CC_REGNUM)
98562479 8488 (compare:CC (const_int 0) (match_dup 1)))
8489 (set (match_dup 2) (minus:SI (const_int 0) (match_dup 1)))])
8490 (set (match_dup 0)
8491 (plus:SI (plus:SI (match_dup 1) (match_dup 2))
8492 (geu:SI (reg:CC CC_REGNUM) (const_int 0))))]
8493)
8494
31991287 8495;; Rd = (eq (reg1) (reg2/imm)) // ARMv5 and optimising for speed.
98562479 8496;; sub Rd, Reg1, reg2
8497;; clz Rd, Rd
8498;; lsr Rd, Rd, #5
8499(define_peephole2
8500 [(set (reg:CC CC_REGNUM)
8501 (compare:CC (match_operand:SI 1 "register_operand" "")
8502 (match_operand:SI 2 "arm_rhs_operand" "")))
8503 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
8504 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
8505 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
8506 (set (match_dup 0) (const_int 1)))]
b232e6b5 8507 "arm_arch5t && TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)
31991287 8508 && !(TARGET_THUMB2 && optimize_insn_for_size_p ())"
98562479 8509 [(set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))
8510 (set (match_dup 0) (clz:SI (match_dup 0)))
8511 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 5)))]
8512)
8513
8514
31991287 8515;; Rd = (eq (reg1) (reg2)) // ! ARMv5 or optimising for size.
98562479 8516;; sub T1, Reg1, reg2
8517;; negs Rd, T1
8518;; adc Rd, Rd, T1
8519(define_peephole2
8520 [(set (reg:CC CC_REGNUM)
8521 (compare:CC (match_operand:SI 1 "register_operand" "")
8522 (match_operand:SI 2 "arm_rhs_operand" "")))
8523 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
8524 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
8525 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
8526 (set (match_dup 0) (const_int 1)))
8527 (match_scratch:SI 3 "r")]
8528 "TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)"
31991287 8529 [(set (match_dup 3) (match_dup 4))
080c0b9a 8530 (parallel
8531 [(set (reg:CC CC_REGNUM)
8532 (compare:CC (const_int 0) (match_dup 3)))
8533 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 3)))])
98562479 8534 (set (match_dup 0)
8535 (plus:SI (plus:SI (match_dup 0) (match_dup 3))
8536 (geu:SI (reg:CC CC_REGNUM) (const_int 0))))]
31991287 8537 "
8538 if (CONST_INT_P (operands[2]))
8539 operands[4] = plus_constant (SImode, operands[1], -INTVAL (operands[2]));
8540 else
8541 operands[4] = gen_rtx_MINUS (SImode, operands[1], operands[2]);
8542 ")
080c0b9a 8543
f7fbdd4a 8544(define_insn "*cond_move"
9c08d1fa 8545 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
aea4c774 8546 (if_then_else:SI (match_operator 3 "equality_operator"
8fa3ba89 8547 [(match_operator 4 "arm_comparison_operator"
8a18b90c 8548 [(match_operand 5 "cc_register" "") (const_int 0)])
aea4c774 8549 (const_int 0)])
8550 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8551 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
cffb2a26 8552 "TARGET_ARM"
9c08d1fa 8553 "*
8fa3ba89 8554 if (GET_CODE (operands[3]) == NE)
8555 {
8556 if (which_alternative != 1)
8557 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
8558 if (which_alternative != 0)
8559 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
8560 return \"\";
8561 }
8562 if (which_alternative != 0)
8563 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8564 if (which_alternative != 1)
8565 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
8566 return \"\";
8567 "
8568 [(set_attr "conds" "use")
282b4c75 8569 (set_attr_alternative "type"
8570 [(if_then_else (match_operand 2 "const_int_operand" "")
8571 (const_string "mov_imm")
8572 (const_string "mov_reg"))
8573 (if_then_else (match_operand 1 "const_int_operand" "")
8574 (const_string "mov_imm")
8575 (const_string "mov_reg"))
8576 (const_string "multiple")])
8fa3ba89 8577 (set_attr "length" "4,4,8")]
8578)
9c08d1fa 8579
f7fbdd4a 8580(define_insn "*cond_arith"
9c08d1fa 8581 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8582 (match_operator:SI 5 "shiftable_operator"
8fa3ba89 8583 [(match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 8584 [(match_operand:SI 2 "s_register_operand" "r,r")
8585 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8586 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 8587 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8588 "TARGET_ARM"
9c08d1fa 8589 "*
8fa3ba89 8590 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
8591 return \"%i5\\t%0, %1, %2, lsr #31\";
40dbec34 8592
8fa3ba89 8593 output_asm_insn (\"cmp\\t%2, %3\", operands);
8594 if (GET_CODE (operands[5]) == AND)
8595 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
8596 else if (GET_CODE (operands[5]) == MINUS)
8597 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
8598 else if (which_alternative != 0)
8599 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8600 return \"%i5%d4\\t%0, %1, #1\";
8601 "
8602 [(set_attr "conds" "clob")
1b7da4ac 8603 (set_attr "length" "12")
8604 (set_attr "type" "multiple")]
8fa3ba89 8605)
9c08d1fa 8606
f7fbdd4a 8607(define_insn "*cond_sub"
9c08d1fa 8608 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8609 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8fa3ba89 8610 (match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 8611 [(match_operand:SI 2 "s_register_operand" "r,r")
8612 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 8613 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8614 "TARGET_ARM"
9c08d1fa 8615 "*
8fa3ba89 8616 output_asm_insn (\"cmp\\t%2, %3\", operands);
8617 if (which_alternative != 0)
8618 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8619 return \"sub%d4\\t%0, %1, #1\";
8620 "
8621 [(set_attr "conds" "clob")
1b7da4ac 8622 (set_attr "length" "8,12")
8623 (set_attr "type" "multiple")]
8fa3ba89 8624)
9c08d1fa 8625
aea4c774 8626(define_insn "*cmp_ite0"
cffb2a26 8627 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 8628 (compare
8629 (if_then_else:SI
8fa3ba89 8630 (match_operator 4 "arm_comparison_operator"
2ff91fec 8631 [(match_operand:SI 0 "s_register_operand"
8632 "l,l,l,r,r,r,r,r,r")
8633 (match_operand:SI 1 "arm_add_operand"
8634 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
8fa3ba89 8635 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 8636 [(match_operand:SI 2 "s_register_operand"
8637 "l,r,r,l,l,r,r,r,r")
8638 (match_operand:SI 3 "arm_add_operand"
8639 "lPy,rI,L,lPy,lPy,rI,rI,L,L")])
aea4c774 8640 (const_int 0))
8641 (const_int 0)))]
2ff91fec 8642 "TARGET_32BIT"
9c08d1fa 8643 "*
aea4c774 8644 {
2ff91fec 8645 static const char * const cmp1[NUM_OF_COND_CMP][2] =
8646 {
8647 {\"cmp%d5\\t%0, %1\",
8648 \"cmp%d4\\t%2, %3\"},
8649 {\"cmn%d5\\t%0, #%n1\",
8650 \"cmp%d4\\t%2, %3\"},
8651 {\"cmp%d5\\t%0, %1\",
8652 \"cmn%d4\\t%2, #%n3\"},
8653 {\"cmn%d5\\t%0, #%n1\",
8654 \"cmn%d4\\t%2, #%n3\"}
8655 };
8656 static const char * const cmp2[NUM_OF_COND_CMP][2] =
8657 {
8658 {\"cmp\\t%2, %3\",
8659 \"cmp\\t%0, %1\"},
8660 {\"cmp\\t%2, %3\",
8661 \"cmn\\t%0, #%n1\"},
8662 {\"cmn\\t%2, #%n3\",
8663 \"cmp\\t%0, %1\"},
8664 {\"cmn\\t%2, #%n3\",
8665 \"cmn\\t%0, #%n1\"}
8666 };
8667 static const char * const ite[2] =
8fa3ba89 8668 {
2ff91fec 8669 \"it\\t%d5\",
8670 \"it\\t%d4\"
8fa3ba89 8671 };
2ff91fec 8672 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
8673 CMP_CMP, CMN_CMP, CMP_CMP,
8674 CMN_CMP, CMP_CMN, CMN_CMN};
8fa3ba89 8675 int swap =
8676 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8677
2ff91fec 8678 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
8679 if (TARGET_THUMB2) {
8680 output_asm_insn (ite[swap], operands);
8681 }
8682 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
8683 return \"\";
8fa3ba89 8684 }"
8685 [(set_attr "conds" "set")
2ff91fec 8686 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
8bdfd6ed 8687 (set_attr "enabled_for_short_it" "yes,no,no,no,no,no,no,no,no")
1b7da4ac 8688 (set_attr "type" "multiple")
2ff91fec 8689 (set_attr_alternative "length"
8690 [(const_int 6)
8691 (const_int 8)
8692 (const_int 8)
8693 (const_int 8)
8694 (const_int 8)
8695 (if_then_else (eq_attr "is_thumb" "no")
8696 (const_int 8)
8697 (const_int 10))
8698 (if_then_else (eq_attr "is_thumb" "no")
8699 (const_int 8)
8700 (const_int 10))
8701 (if_then_else (eq_attr "is_thumb" "no")
8702 (const_int 8)
8703 (const_int 10))
8704 (if_then_else (eq_attr "is_thumb" "no")
8705 (const_int 8)
8706 (const_int 10))])]
8fa3ba89 8707)
9c08d1fa 8708
aea4c774 8709(define_insn "*cmp_ite1"
cffb2a26 8710 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 8711 (compare
8712 (if_then_else:SI
8fa3ba89 8713 (match_operator 4 "arm_comparison_operator"
2ff91fec 8714 [(match_operand:SI 0 "s_register_operand"
8715 "l,l,l,r,r,r,r,r,r")
8716 (match_operand:SI 1 "arm_add_operand"
8717 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
8fa3ba89 8718 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 8719 [(match_operand:SI 2 "s_register_operand"
8720 "l,r,r,l,l,r,r,r,r")
8721 (match_operand:SI 3 "arm_add_operand"
8722 "lPy,rI,L,lPy,lPy,rI,rI,L,L")])
aea4c774 8723 (const_int 1))
8724 (const_int 0)))]
2ff91fec 8725 "TARGET_32BIT"
9c08d1fa 8726 "*
9c08d1fa 8727 {
2ff91fec 8728 static const char * const cmp1[NUM_OF_COND_CMP][2] =
8729 {
8730 {\"cmp\\t%0, %1\",
8731 \"cmp\\t%2, %3\"},
8732 {\"cmn\\t%0, #%n1\",
8733 \"cmp\\t%2, %3\"},
8734 {\"cmp\\t%0, %1\",
8735 \"cmn\\t%2, #%n3\"},
8736 {\"cmn\\t%0, #%n1\",
8737 \"cmn\\t%2, #%n3\"}
8738 };
8739 static const char * const cmp2[NUM_OF_COND_CMP][2] =
215b30b3 8740 {
2ff91fec 8741 {\"cmp%d4\\t%2, %3\",
8742 \"cmp%D5\\t%0, %1\"},
8743 {\"cmp%d4\\t%2, %3\",
8744 \"cmn%D5\\t%0, #%n1\"},
8745 {\"cmn%d4\\t%2, #%n3\",
8746 \"cmp%D5\\t%0, %1\"},
8747 {\"cmn%d4\\t%2, #%n3\",
8748 \"cmn%D5\\t%0, #%n1\"}
215b30b3 8749 };
2ff91fec 8750 static const char * const ite[2] =
8751 {
8752 \"it\\t%d4\",
8753 \"it\\t%D5\"
8754 };
8755 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
8756 CMP_CMP, CMN_CMP, CMP_CMP,
8757 CMN_CMP, CMP_CMN, CMN_CMN};
215b30b3 8758 int swap =
8759 comparison_dominates_p (GET_CODE (operands[5]),
8760 reverse_condition (GET_CODE (operands[4])));
8761
2ff91fec 8762 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
8763 if (TARGET_THUMB2) {
8764 output_asm_insn (ite[swap], operands);
8765 }
8766 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
8767 return \"\";
215b30b3 8768 }"
8fa3ba89 8769 [(set_attr "conds" "set")
2ff91fec 8770 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
8bdfd6ed 8771 (set_attr "enabled_for_short_it" "yes,no,no,no,no,no,no,no,no")
2ff91fec 8772 (set_attr_alternative "length"
8773 [(const_int 6)
8774 (const_int 8)
8775 (const_int 8)
8776 (const_int 8)
8777 (const_int 8)
8778 (if_then_else (eq_attr "is_thumb" "no")
8779 (const_int 8)
8780 (const_int 10))
8781 (if_then_else (eq_attr "is_thumb" "no")
8782 (const_int 8)
8783 (const_int 10))
8784 (if_then_else (eq_attr "is_thumb" "no")
8785 (const_int 8)
8786 (const_int 10))
8787 (if_then_else (eq_attr "is_thumb" "no")
8788 (const_int 8)
1b7da4ac 8789 (const_int 10))])
8790 (set_attr "type" "multiple")]
8fa3ba89 8791)
9c08d1fa 8792
f6c53574 8793(define_insn "*cmp_and"
8794 [(set (match_operand 6 "dominant_cc_register" "")
8795 (compare
8796 (and:SI
8797 (match_operator 4 "arm_comparison_operator"
db23acf2 8798 [(match_operand:SI 0 "s_register_operand"
8799 "l,l,l,r,r,r,r,r,r,r")
8800 (match_operand:SI 1 "arm_add_operand"
8801 "lPy,lPy,lPy,rI,L,r,rI,L,rI,L")])
f6c53574 8802 (match_operator:SI 5 "arm_comparison_operator"
db23acf2 8803 [(match_operand:SI 2 "s_register_operand"
8804 "l,r,r,l,l,r,r,r,r,r")
8805 (match_operand:SI 3 "arm_add_operand"
8806 "lPy,rI,L,lPy,lPy,r,rI,rI,L,L")]))
f6c53574 8807 (const_int 0)))]
2ff91fec 8808 "TARGET_32BIT"
f6c53574 8809 "*
8810 {
2ff91fec 8811 static const char *const cmp1[NUM_OF_COND_CMP][2] =
f6c53574 8812 {
2ff91fec 8813 {\"cmp%d5\\t%0, %1\",
8814 \"cmp%d4\\t%2, %3\"},
8815 {\"cmn%d5\\t%0, #%n1\",
8816 \"cmp%d4\\t%2, %3\"},
8817 {\"cmp%d5\\t%0, %1\",
8818 \"cmn%d4\\t%2, #%n3\"},
8819 {\"cmn%d5\\t%0, #%n1\",
8820 \"cmn%d4\\t%2, #%n3\"}
f6c53574 8821 };
2ff91fec 8822 static const char *const cmp2[NUM_OF_COND_CMP][2] =
8823 {
8824 {\"cmp\\t%2, %3\",
8825 \"cmp\\t%0, %1\"},
8826 {\"cmp\\t%2, %3\",
8827 \"cmn\\t%0, #%n1\"},
8828 {\"cmn\\t%2, #%n3\",
8829 \"cmp\\t%0, %1\"},
8830 {\"cmn\\t%2, #%n3\",
8831 \"cmn\\t%0, #%n1\"}
8832 };
8833 static const char *const ite[2] =
8834 {
8835 \"it\\t%d5\",
8836 \"it\\t%d4\"
8837 };
db23acf2 8838 static const int cmp_idx[] = {CMP_CMP, CMP_CMP, CMP_CMN,
8839 CMP_CMP, CMN_CMP, CMP_CMP,
8840 CMP_CMP, CMN_CMP, CMP_CMN,
8841 CMN_CMN};
f6c53574 8842 int swap =
8843 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8844
2ff91fec 8845 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
8846 if (TARGET_THUMB2) {
8847 output_asm_insn (ite[swap], operands);
8848 }
8849 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
8850 return \"\";
f6c53574 8851 }"
8852 [(set_attr "conds" "set")
8853 (set_attr "predicable" "no")
db23acf2 8854 (set_attr "arch" "t2,t2,t2,t2,t2,t2,any,any,any,any")
8855 (set_attr "enabled_for_short_it" "yes,no,no,no,no,yes,no,no,no,no")
2ff91fec 8856 (set_attr_alternative "length"
8857 [(const_int 6)
8858 (const_int 8)
8859 (const_int 8)
8860 (const_int 8)
8861 (const_int 8)
db23acf2 8862 (const_int 6)
2ff91fec 8863 (if_then_else (eq_attr "is_thumb" "no")
8864 (const_int 8)
8865 (const_int 10))
8866 (if_then_else (eq_attr "is_thumb" "no")
8867 (const_int 8)
8868 (const_int 10))
8869 (if_then_else (eq_attr "is_thumb" "no")
8870 (const_int 8)
8871 (const_int 10))
8872 (if_then_else (eq_attr "is_thumb" "no")
8873 (const_int 8)
1b7da4ac 8874 (const_int 10))])
8875 (set_attr "type" "multiple")]
f6c53574 8876)
8877
8878(define_insn "*cmp_ior"
8879 [(set (match_operand 6 "dominant_cc_register" "")
8880 (compare
8881 (ior:SI
8882 (match_operator 4 "arm_comparison_operator"
2ff91fec 8883 [(match_operand:SI 0 "s_register_operand"
db23acf2 8884 "l,l,l,r,r,r,r,r,r,r")
2ff91fec 8885 (match_operand:SI 1 "arm_add_operand"
db23acf2 8886 "lPy,lPy,lPy,rI,L,r,rI,L,rI,L")])
f6c53574 8887 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 8888 [(match_operand:SI 2 "s_register_operand"
db23acf2 8889 "l,r,r,l,l,r,r,r,r,r")
2ff91fec 8890 (match_operand:SI 3 "arm_add_operand"
db23acf2 8891 "lPy,rI,L,lPy,lPy,r,rI,rI,L,L")]))
f6c53574 8892 (const_int 0)))]
2ff91fec 8893 "TARGET_32BIT"
f6c53574 8894 "*
f6c53574 8895 {
2ff91fec 8896 static const char *const cmp1[NUM_OF_COND_CMP][2] =
8897 {
8898 {\"cmp\\t%0, %1\",
8899 \"cmp\\t%2, %3\"},
8900 {\"cmn\\t%0, #%n1\",
8901 \"cmp\\t%2, %3\"},
8902 {\"cmp\\t%0, %1\",
8903 \"cmn\\t%2, #%n3\"},
8904 {\"cmn\\t%0, #%n1\",
8905 \"cmn\\t%2, #%n3\"}
8906 };
8907 static const char *const cmp2[NUM_OF_COND_CMP][2] =
8908 {
8909 {\"cmp%D4\\t%2, %3\",
8910 \"cmp%D5\\t%0, %1\"},
8911 {\"cmp%D4\\t%2, %3\",
8912 \"cmn%D5\\t%0, #%n1\"},
8913 {\"cmn%D4\\t%2, #%n3\",
8914 \"cmp%D5\\t%0, %1\"},
8915 {\"cmn%D4\\t%2, #%n3\",
8916 \"cmn%D5\\t%0, #%n1\"}
8917 };
8918 static const char *const ite[2] =
8919 {
8920 \"it\\t%D4\",
8921 \"it\\t%D5\"
8922 };
db23acf2 8923 static const int cmp_idx[] = {CMP_CMP, CMP_CMP, CMP_CMN,
8924 CMP_CMP, CMN_CMP, CMP_CMP,
8925 CMP_CMP, CMN_CMP, CMP_CMN,
8926 CMN_CMN};
2ff91fec 8927 int swap =
8928 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8929
8930 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
8931 if (TARGET_THUMB2) {
8932 output_asm_insn (ite[swap], operands);
8933 }
8934 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
8935 return \"\";
8936 }
8937 "
f6c53574 8938 [(set_attr "conds" "set")
db23acf2 8939 (set_attr "arch" "t2,t2,t2,t2,t2,t2,any,any,any,any")
8940 (set_attr "enabled_for_short_it" "yes,no,no,no,no,yes,no,no,no,no")
2ff91fec 8941 (set_attr_alternative "length"
8942 [(const_int 6)
8943 (const_int 8)
8944 (const_int 8)
8945 (const_int 8)
8946 (const_int 8)
db23acf2 8947 (const_int 6)
2ff91fec 8948 (if_then_else (eq_attr "is_thumb" "no")
8949 (const_int 8)
8950 (const_int 10))
8951 (if_then_else (eq_attr "is_thumb" "no")
8952 (const_int 8)
8953 (const_int 10))
8954 (if_then_else (eq_attr "is_thumb" "no")
8955 (const_int 8)
8956 (const_int 10))
8957 (if_then_else (eq_attr "is_thumb" "no")
8958 (const_int 8)
1b7da4ac 8959 (const_int 10))])
8960 (set_attr "type" "multiple")]
f6c53574 8961)
8962
3c5afce6 8963(define_insn_and_split "*ior_scc_scc"
f9d240a0 8964 [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts")
3c5afce6 8965 (ior:SI (match_operator:SI 3 "arm_comparison_operator"
f9d240a0 8966 [(match_operand:SI 1 "s_register_operand" "l,r")
8967 (match_operand:SI 2 "arm_add_operand" "lPy,rIL")])
3c5afce6 8968 (match_operator:SI 6 "arm_comparison_operator"
f9d240a0 8969 [(match_operand:SI 4 "s_register_operand" "l,r")
8970 (match_operand:SI 5 "arm_add_operand" "lPy,rIL")])))
3c5afce6 8971 (clobber (reg:CC CC_REGNUM))]
2ff91fec 8972 "TARGET_32BIT
3c5afce6 8973 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
8974 != CCmode)"
8975 "#"
2ff91fec 8976 "TARGET_32BIT && reload_completed"
3c5afce6 8977 [(set (match_dup 7)
8978 (compare
8979 (ior:SI
8980 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8981 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8982 (const_int 0)))
8983 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8984 "operands[7]
8985 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8986 DOM_CC_X_OR_Y),
601f584c 8987 CC_REGNUM);"
8988 [(set_attr "conds" "clob")
8bdfd6ed 8989 (set_attr "enabled_for_short_it" "yes,no")
1b7da4ac 8990 (set_attr "length" "16")
8991 (set_attr "type" "multiple")]
8992)
601f584c 8993
8994; If the above pattern is followed by a CMP insn, then the compare is
8995; redundant, since we can rework the conditional instruction that follows.
8996(define_insn_and_split "*ior_scc_scc_cmp"
8997 [(set (match_operand 0 "dominant_cc_register" "")
8998 (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
f9d240a0 8999 [(match_operand:SI 1 "s_register_operand" "l,r")
9000 (match_operand:SI 2 "arm_add_operand" "lPy,rIL")])
601f584c 9001 (match_operator:SI 6 "arm_comparison_operator"
f9d240a0 9002 [(match_operand:SI 4 "s_register_operand" "l,r")
9003 (match_operand:SI 5 "arm_add_operand" "lPy,rIL")]))
601f584c 9004 (const_int 0)))
f9d240a0 9005 (set (match_operand:SI 7 "s_register_operand" "=Ts,Ts")
601f584c 9006 (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9007 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
2ff91fec 9008 "TARGET_32BIT"
601f584c 9009 "#"
2ff91fec 9010 "TARGET_32BIT && reload_completed"
601f584c 9011 [(set (match_dup 0)
9012 (compare
9013 (ior:SI
9014 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9015 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9016 (const_int 0)))
9017 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9018 ""
9019 [(set_attr "conds" "set")
8bdfd6ed 9020 (set_attr "enabled_for_short_it" "yes,no")
1b7da4ac 9021 (set_attr "length" "16")
9022 (set_attr "type" "multiple")]
9023)
3c5afce6 9024
9025(define_insn_and_split "*and_scc_scc"
f9d240a0 9026 [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts")
3c5afce6 9027 (and:SI (match_operator:SI 3 "arm_comparison_operator"
f9d240a0 9028 [(match_operand:SI 1 "s_register_operand" "l,r")
9029 (match_operand:SI 2 "arm_add_operand" "lPy,rIL")])
3c5afce6 9030 (match_operator:SI 6 "arm_comparison_operator"
f9d240a0 9031 [(match_operand:SI 4 "s_register_operand" "l,r")
9032 (match_operand:SI 5 "arm_add_operand" "lPy,rIL")])))
3c5afce6 9033 (clobber (reg:CC CC_REGNUM))]
2ff91fec 9034 "TARGET_32BIT
3c5afce6 9035 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9036 != CCmode)"
9037 "#"
2ff91fec 9038 "TARGET_32BIT && reload_completed
601f584c 9039 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9040 != CCmode)"
3c5afce6 9041 [(set (match_dup 7)
9042 (compare
9043 (and:SI
9044 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9045 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9046 (const_int 0)))
9047 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9048 "operands[7]
9049 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9050 DOM_CC_X_AND_Y),
601f584c 9051 CC_REGNUM);"
9052 [(set_attr "conds" "clob")
8bdfd6ed 9053 (set_attr "enabled_for_short_it" "yes,no")
1b7da4ac 9054 (set_attr "length" "16")
9055 (set_attr "type" "multiple")]
9056)
601f584c 9057
9058; If the above pattern is followed by a CMP insn, then the compare is
9059; redundant, since we can rework the conditional instruction that follows.
9060(define_insn_and_split "*and_scc_scc_cmp"
9061 [(set (match_operand 0 "dominant_cc_register" "")
9062 (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
f9d240a0 9063 [(match_operand:SI 1 "s_register_operand" "l,r")
9064 (match_operand:SI 2 "arm_add_operand" "lPy,rIL")])
601f584c 9065 (match_operator:SI 6 "arm_comparison_operator"
f9d240a0 9066 [(match_operand:SI 4 "s_register_operand" "l,r")
9067 (match_operand:SI 5 "arm_add_operand" "lPy,rIL")]))
601f584c 9068 (const_int 0)))
f9d240a0 9069 (set (match_operand:SI 7 "s_register_operand" "=Ts,Ts")
601f584c 9070 (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9071 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
2ff91fec 9072 "TARGET_32BIT"
601f584c 9073 "#"
2ff91fec 9074 "TARGET_32BIT && reload_completed"
601f584c 9075 [(set (match_dup 0)
9076 (compare
9077 (and:SI
9078 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9079 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9080 (const_int 0)))
9081 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9082 ""
9083 [(set_attr "conds" "set")
8bdfd6ed 9084 (set_attr "enabled_for_short_it" "yes,no")
1b7da4ac 9085 (set_attr "length" "16")
9086 (set_attr "type" "multiple")]
9087)
601f584c 9088
9089;; If there is no dominance in the comparison, then we can still save an
9090;; instruction in the AND case, since we can know that the second compare
9091;; need only zero the value if false (if true, then the value is already
9092;; correct).
9093(define_insn_and_split "*and_scc_scc_nodom"
fd711051 9094 [(set (match_operand:SI 0 "s_register_operand" "=&Ts,&Ts,&Ts")
601f584c 9095 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9096 [(match_operand:SI 1 "s_register_operand" "r,r,0")
9097 (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
9098 (match_operator:SI 6 "arm_comparison_operator"
9099 [(match_operand:SI 4 "s_register_operand" "r,r,r")
9100 (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
9101 (clobber (reg:CC CC_REGNUM))]
2ff91fec 9102 "TARGET_32BIT
601f584c 9103 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9104 == CCmode)"
9105 "#"
2ff91fec 9106 "TARGET_32BIT && reload_completed"
601f584c 9107 [(parallel [(set (match_dup 0)
9108 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
9109 (clobber (reg:CC CC_REGNUM))])
9110 (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
9111 (set (match_dup 0)
9112 (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
9113 (match_dup 0)
9114 (const_int 0)))]
9115 "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
9116 operands[4], operands[5]),
9117 CC_REGNUM);
9118 operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
9119 operands[5]);"
9120 [(set_attr "conds" "clob")
1b7da4ac 9121 (set_attr "length" "20")
9122 (set_attr "type" "multiple")]
9123)
3c5afce6 9124
3a0bdee0 9125(define_split
9126 [(set (reg:CC_NOOV CC_REGNUM)
9127 (compare:CC_NOOV (ior:SI
9128 (and:SI (match_operand:SI 0 "s_register_operand" "")
9129 (const_int 1))
b0694be0 9130 (match_operator:SI 1 "arm_comparison_operator"
3a0bdee0 9131 [(match_operand:SI 2 "s_register_operand" "")
9132 (match_operand:SI 3 "arm_add_operand" "")]))
9133 (const_int 0)))
9134 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9135 "TARGET_ARM"
9136 [(set (match_dup 4)
9137 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9138 (match_dup 0)))
9139 (set (reg:CC_NOOV CC_REGNUM)
9140 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9141 (const_int 0)))]
9142 "")
9143
9144(define_split
9145 [(set (reg:CC_NOOV CC_REGNUM)
9146 (compare:CC_NOOV (ior:SI
b0694be0 9147 (match_operator:SI 1 "arm_comparison_operator"
3a0bdee0 9148 [(match_operand:SI 2 "s_register_operand" "")
9149 (match_operand:SI 3 "arm_add_operand" "")])
9150 (and:SI (match_operand:SI 0 "s_register_operand" "")
9151 (const_int 1)))
9152 (const_int 0)))
9153 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9154 "TARGET_ARM"
9155 [(set (match_dup 4)
9156 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9157 (match_dup 0)))
9158 (set (reg:CC_NOOV CC_REGNUM)
9159 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9160 (const_int 0)))]
9161 "")
25f905c2 9162;; ??? The conditional patterns above need checking for Thumb-2 usefulness
3a0bdee0 9163
190efb17 9164(define_insn_and_split "*negscc"
9c08d1fa 9165 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9166 (neg:SI (match_operator 3 "arm_comparison_operator"
9c08d1fa 9167 [(match_operand:SI 1 "s_register_operand" "r")
9168 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
bd5b4116 9169 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9170 "TARGET_ARM"
190efb17 9171 "#"
9172 "&& reload_completed"
9173 [(const_int 0)]
9174 {
9175 rtx cc_reg = gen_rtx_REG (CCmode, CC_REGNUM);
e2348bcb 9176
190efb17 9177 if (GET_CODE (operands[3]) == LT && operands[2] == const0_rtx)
9178 {
9179 /* Emit mov\\t%0, %1, asr #31 */
d1f9b275 9180 emit_insn (gen_rtx_SET (operands[0],
190efb17 9181 gen_rtx_ASHIFTRT (SImode,
9182 operands[1],
9183 GEN_INT (31))));
9184 DONE;
9185 }
9186 else if (GET_CODE (operands[3]) == NE)
9187 {
9188 /* Emit subs\\t%0, %1, %2\;mvnne\\t%0, #0 */
9189 if (CONST_INT_P (operands[2]))
9190 emit_insn (gen_cmpsi2_addneg (operands[0], operands[1], operands[2],
e3dcfc16 9191 gen_int_mode (-INTVAL (operands[2]),
9192 SImode)));
190efb17 9193 else
9194 emit_insn (gen_subsi3_compare (operands[0], operands[1], operands[2]));
9195
9196 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
9197 gen_rtx_NE (SImode,
9198 cc_reg,
9199 const0_rtx),
d1f9b275 9200 gen_rtx_SET (operands[0],
190efb17 9201 GEN_INT (~0))));
9202 DONE;
9203 }
9204 else
9205 {
9206 /* Emit: cmp\\t%1, %2\;mov%D3\\t%0, #0\;mvn%d3\\t%0, #0 */
d1f9b275 9207 emit_insn (gen_rtx_SET (cc_reg,
190efb17 9208 gen_rtx_COMPARE (CCmode, operands[1], operands[2])));
9209 enum rtx_code rc = GET_CODE (operands[3]);
9210
9211 rc = reverse_condition (rc);
9212 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
9213 gen_rtx_fmt_ee (rc,
9214 VOIDmode,
9215 cc_reg,
9216 const0_rtx),
d1f9b275 9217 gen_rtx_SET (operands[0], const0_rtx)));
190efb17 9218 rc = GET_CODE (operands[3]);
9219 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
9220 gen_rtx_fmt_ee (rc,
9221 VOIDmode,
9222 cc_reg,
9223 const0_rtx),
d1f9b275 9224 gen_rtx_SET (operands[0],
190efb17 9225 GEN_INT (~0))));
9226 DONE;
9227 }
9228 FAIL;
9229 }
8fa3ba89 9230 [(set_attr "conds" "clob")
1b7da4ac 9231 (set_attr "length" "12")
9232 (set_attr "type" "multiple")]
8fa3ba89 9233)
9c08d1fa 9234
90404b57 9235(define_insn_and_split "movcond_addsi"
9236 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r")
9237 (if_then_else:SI
9238 (match_operator 5 "comparison_operator"
9239 [(plus:SI (match_operand:SI 3 "s_register_operand" "r,r,r")
9240 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL"))
9241 (const_int 0)])
9242 (match_operand:SI 1 "arm_rhs_operand" "rI,rPy,r")
9243 (match_operand:SI 2 "arm_rhs_operand" "rI,rPy,r")))
9244 (clobber (reg:CC CC_REGNUM))]
9245 "TARGET_32BIT"
9246 "#"
9247 "&& reload_completed"
9248 [(set (reg:CC_NOOV CC_REGNUM)
9249 (compare:CC_NOOV
9250 (plus:SI (match_dup 3)
9251 (match_dup 4))
9252 (const_int 0)))
9253 (set (match_dup 0) (match_dup 1))
9254 (cond_exec (match_dup 6)
9255 (set (match_dup 0) (match_dup 2)))]
9256 "
9257 {
3754d046 9258 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[5]),
90404b57 9259 operands[3], operands[4]);
9260 enum rtx_code rc = GET_CODE (operands[5]);
90404b57 9261 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9262 gcc_assert (!(mode == CCFPmode || mode == CCFPEmode));
22440aeb 9263 if (!REG_P (operands[2]) || REGNO (operands[2]) != REGNO (operands[0]))
4d01ce2f 9264 rc = reverse_condition (rc);
f145bcba 9265 else
9266 std::swap (operands[1], operands[2]);
90404b57 9267
9268 operands[6] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9269 }
9270 "
9271 [(set_attr "conds" "clob")
8bdfd6ed 9272 (set_attr "enabled_for_short_it" "no,yes,yes")
1b7da4ac 9273 (set_attr "type" "multiple")]
90404b57 9274)
9275
9c08d1fa 9276(define_insn "movcond"
9277 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 9278 (if_then_else:SI
8fa3ba89 9279 (match_operator 5 "arm_comparison_operator"
5565501b 9280 [(match_operand:SI 3 "s_register_operand" "r,r,r")
9281 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
9282 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9283 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 9284 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9285 "TARGET_ARM"
9c08d1fa 9286 "*
9287 if (GET_CODE (operands[5]) == LT
9288 && (operands[4] == const0_rtx))
9289 {
0438d37f 9290 if (which_alternative != 1 && REG_P (operands[1]))
9c08d1fa 9291 {
9c08d1fa 9292 if (operands[2] == const0_rtx)
e2348bcb 9293 return \"and\\t%0, %1, %3, asr #31\";
9294 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
9c08d1fa 9295 }
0438d37f 9296 else if (which_alternative != 0 && REG_P (operands[2]))
9c08d1fa 9297 {
9c08d1fa 9298 if (operands[1] == const0_rtx)
e2348bcb 9299 return \"bic\\t%0, %2, %3, asr #31\";
9300 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
9c08d1fa 9301 }
9302 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 9303 are constants. */
9c08d1fa 9304 }
e2348bcb 9305
9c08d1fa 9306 if (GET_CODE (operands[5]) == GE
9307 && (operands[4] == const0_rtx))
9308 {
0438d37f 9309 if (which_alternative != 1 && REG_P (operands[1]))
9c08d1fa 9310 {
9c08d1fa 9311 if (operands[2] == const0_rtx)
e2348bcb 9312 return \"bic\\t%0, %1, %3, asr #31\";
9313 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
9c08d1fa 9314 }
0438d37f 9315 else if (which_alternative != 0 && REG_P (operands[2]))
9c08d1fa 9316 {
9c08d1fa 9317 if (operands[1] == const0_rtx)
e2348bcb 9318 return \"and\\t%0, %2, %3, asr #31\";
9319 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
9c08d1fa 9320 }
9321 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 9322 are constants. */
9c08d1fa 9323 }
0438d37f 9324 if (CONST_INT_P (operands[4])
9c08d1fa 9325 && !const_ok_for_arm (INTVAL (operands[4])))
e2348bcb 9326 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
9c08d1fa 9327 else
e2348bcb 9328 output_asm_insn (\"cmp\\t%3, %4\", operands);
9c08d1fa 9329 if (which_alternative != 0)
e2348bcb 9330 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
9c08d1fa 9331 if (which_alternative != 1)
e2348bcb 9332 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
9c08d1fa 9333 return \"\";
215b30b3 9334 "
8fa3ba89 9335 [(set_attr "conds" "clob")
1b7da4ac 9336 (set_attr "length" "8,8,12")
9337 (set_attr "type" "multiple")]
8fa3ba89 9338)
9c08d1fa 9339
25f905c2 9340;; ??? The patterns below need checking for Thumb-2 usefulness.
9341
8a18b90c 9342(define_insn "*ifcompare_plus_move"
9343 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9344 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 9345 [(match_operand:SI 4 "s_register_operand" "r,r")
9346 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9347 (plus:SI
9348 (match_operand:SI 2 "s_register_operand" "r,r")
9349 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
129a2fe4 9350 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 9351 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9352 "TARGET_ARM"
8a18b90c 9353 "#"
8fa3ba89 9354 [(set_attr "conds" "clob")
1b7da4ac 9355 (set_attr "length" "8,12")
9356 (set_attr "type" "multiple")]
8fa3ba89 9357)
8a18b90c 9358
9359(define_insn "*if_plus_move"
129a2fe4 9360 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 9361 (if_then_else:SI
8fa3ba89 9362 (match_operator 4 "arm_comparison_operator"
8a18b90c 9363 [(match_operand 5 "cc_register" "") (const_int 0)])
9364 (plus:SI
129a2fe4 9365 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9366 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
9367 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
cffb2a26 9368 "TARGET_ARM"
8a18b90c 9369 "@
9370 add%d4\\t%0, %2, %3
9371 sub%d4\\t%0, %2, #%n3
9372 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
129a2fe4 9373 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8fa3ba89 9374 [(set_attr "conds" "use")
9375 (set_attr "length" "4,4,8,8")
65f68e55 9376 (set_attr_alternative "type"
9377 [(if_then_else (match_operand 3 "const_int_operand" "")
d82e788e 9378 (const_string "alu_imm" )
112eda6f 9379 (const_string "alu_sreg"))
d82e788e 9380 (const_string "alu_imm")
282b4c75 9381 (const_string "multiple")
9382 (const_string "multiple")])]
8fa3ba89 9383)
8a18b90c 9384
9385(define_insn "*ifcompare_move_plus"
5565501b 9386 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9387 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 9388 [(match_operand:SI 4 "s_register_operand" "r,r")
9389 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 9390 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 9391 (plus:SI
9392 (match_operand:SI 2 "s_register_operand" "r,r")
9393 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
bd5b4116 9394 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9395 "TARGET_ARM"
8a18b90c 9396 "#"
8fa3ba89 9397 [(set_attr "conds" "clob")
1b7da4ac 9398 (set_attr "length" "8,12")
9399 (set_attr "type" "multiple")]
8fa3ba89 9400)
8a18b90c 9401
9402(define_insn "*if_move_plus"
129a2fe4 9403 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 9404 (if_then_else:SI
8fa3ba89 9405 (match_operator 4 "arm_comparison_operator"
8a18b90c 9406 [(match_operand 5 "cc_register" "") (const_int 0)])
129a2fe4 9407 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8a18b90c 9408 (plus:SI
129a2fe4 9409 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9410 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
cffb2a26 9411 "TARGET_ARM"
8a18b90c 9412 "@
9413 add%D4\\t%0, %2, %3
9414 sub%D4\\t%0, %2, #%n3
9415 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
129a2fe4 9416 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8fa3ba89 9417 [(set_attr "conds" "use")
9418 (set_attr "length" "4,4,8,8")
282b4c75 9419 (set_attr_alternative "type"
9420 [(if_then_else (match_operand 3 "const_int_operand" "")
9421 (const_string "alu_imm" )
9422 (const_string "alu_sreg"))
9423 (const_string "alu_imm")
9424 (const_string "multiple")
9425 (const_string "multiple")])]
8fa3ba89 9426)
8a18b90c 9427
9428(define_insn "*ifcompare_arith_arith"
9429 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9430 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8a18b90c 9431 [(match_operand:SI 5 "s_register_operand" "r")
9432 (match_operand:SI 6 "arm_add_operand" "rIL")])
9c08d1fa 9433 (match_operator:SI 8 "shiftable_operator"
8a18b90c 9434 [(match_operand:SI 1 "s_register_operand" "r")
9435 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9c08d1fa 9436 (match_operator:SI 7 "shiftable_operator"
8a18b90c 9437 [(match_operand:SI 3 "s_register_operand" "r")
9438 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
bd5b4116 9439 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9440 "TARGET_ARM"
8a18b90c 9441 "#"
8fa3ba89 9442 [(set_attr "conds" "clob")
1b7da4ac 9443 (set_attr "length" "12")
9444 (set_attr "type" "multiple")]
8fa3ba89 9445)
9c08d1fa 9446
8a18b90c 9447(define_insn "*if_arith_arith"
9448 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9449 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8a18b90c 9450 [(match_operand 8 "cc_register" "") (const_int 0)])
9451 (match_operator:SI 6 "shiftable_operator"
9452 [(match_operand:SI 1 "s_register_operand" "r")
9453 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9454 (match_operator:SI 7 "shiftable_operator"
9455 [(match_operand:SI 3 "s_register_operand" "r")
9456 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
cffb2a26 9457 "TARGET_ARM"
8a18b90c 9458 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8fa3ba89 9459 [(set_attr "conds" "use")
1b7da4ac 9460 (set_attr "length" "8")
9461 (set_attr "type" "multiple")]
8fa3ba89 9462)
8a18b90c 9463
f7fbdd4a 9464(define_insn "*ifcompare_arith_move"
9c08d1fa 9465 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9466 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 9467 [(match_operand:SI 2 "s_register_operand" "r,r")
5565501b 9468 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
9c08d1fa 9469 (match_operator:SI 7 "shiftable_operator"
9470 [(match_operand:SI 4 "s_register_operand" "r,r")
9471 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
129a2fe4 9472 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 9473 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9474 "TARGET_ARM"
9c08d1fa 9475 "*
9c08d1fa 9476 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 9477 the conditional operator is LT or GE and we are comparing against zero and
674a8f0b 9478 everything is in registers then we can do this in two instructions. */
9c08d1fa 9479 if (operands[3] == const0_rtx
9480 && GET_CODE (operands[7]) != AND
0438d37f 9481 && REG_P (operands[5])
9482 && REG_P (operands[1])
9c08d1fa 9483 && REGNO (operands[1]) == REGNO (operands[4])
9484 && REGNO (operands[4]) != REGNO (operands[0]))
9485 {
9486 if (GET_CODE (operands[6]) == LT)
40dbec34 9487 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 9488 else if (GET_CODE (operands[6]) == GE)
40dbec34 9489 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 9490 }
0438d37f 9491 if (CONST_INT_P (operands[3])
9c08d1fa 9492 && !const_ok_for_arm (INTVAL (operands[3])))
e2348bcb 9493 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
9c08d1fa 9494 else
e2348bcb 9495 output_asm_insn (\"cmp\\t%2, %3\", operands);
40dbec34 9496 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
9c08d1fa 9497 if (which_alternative != 0)
129a2fe4 9498 return \"mov%D6\\t%0, %1\";
9c08d1fa 9499 return \"\";
215b30b3 9500 "
8fa3ba89 9501 [(set_attr "conds" "clob")
1b7da4ac 9502 (set_attr "length" "8,12")
9503 (set_attr "type" "multiple")]
8fa3ba89 9504)
9c08d1fa 9505
8a18b90c 9506(define_insn "*if_arith_move"
129a2fe4 9507 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9508 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8a18b90c 9509 [(match_operand 6 "cc_register" "") (const_int 0)])
9510 (match_operator:SI 5 "shiftable_operator"
129a2fe4 9511 [(match_operand:SI 2 "s_register_operand" "r,r")
9512 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
9513 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
cffb2a26 9514 "TARGET_ARM"
8a18b90c 9515 "@
9516 %I5%d4\\t%0, %2, %3
129a2fe4 9517 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8fa3ba89 9518 [(set_attr "conds" "use")
9519 (set_attr "length" "4,8")
282b4c75 9520 (set_attr_alternative "type"
9521 [(if_then_else (match_operand 3 "const_int_operand" "")
9522 (const_string "alu_shift_imm" )
9523 (const_string "alu_shift_reg"))
9524 (const_string "multiple")])]
8fa3ba89 9525)
8a18b90c 9526
f7fbdd4a 9527(define_insn "*ifcompare_move_arith"
9c08d1fa 9528 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9529 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 9530 [(match_operand:SI 4 "s_register_operand" "r,r")
5565501b 9531 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 9532 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9c08d1fa 9533 (match_operator:SI 7 "shiftable_operator"
9534 [(match_operand:SI 2 "s_register_operand" "r,r")
9535 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 9536 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9537 "TARGET_ARM"
9c08d1fa 9538 "*
9c08d1fa 9539 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 9540 the conditional operator is LT or GE and we are comparing against zero and
9c08d1fa 9541 everything is in registers then we can do this in two instructions */
9542 if (operands[5] == const0_rtx
9543 && GET_CODE (operands[7]) != AND
0438d37f 9544 && REG_P (operands[3])
9545 && REG_P (operands[1])
9c08d1fa 9546 && REGNO (operands[1]) == REGNO (operands[2])
9547 && REGNO (operands[2]) != REGNO (operands[0]))
9548 {
9549 if (GET_CODE (operands[6]) == GE)
40dbec34 9550 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 9551 else if (GET_CODE (operands[6]) == LT)
40dbec34 9552 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 9553 }
40dbec34 9554
0438d37f 9555 if (CONST_INT_P (operands[5])
9c08d1fa 9556 && !const_ok_for_arm (INTVAL (operands[5])))
e2348bcb 9557 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
9c08d1fa 9558 else
e2348bcb 9559 output_asm_insn (\"cmp\\t%4, %5\", operands);
40dbec34 9560
9c08d1fa 9561 if (which_alternative != 0)
129a2fe4 9562 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
40dbec34 9563 return \"%I7%D6\\t%0, %2, %3\";
215b30b3 9564 "
8fa3ba89 9565 [(set_attr "conds" "clob")
1b7da4ac 9566 (set_attr "length" "8,12")
9567 (set_attr "type" "multiple")]
8fa3ba89 9568)
9c08d1fa 9569
8a18b90c 9570(define_insn "*if_move_arith"
129a2fe4 9571 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9572 (if_then_else:SI
8fa3ba89 9573 (match_operator 4 "arm_comparison_operator"
8a18b90c 9574 [(match_operand 6 "cc_register" "") (const_int 0)])
129a2fe4 9575 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 9576 (match_operator:SI 5 "shiftable_operator"
129a2fe4 9577 [(match_operand:SI 2 "s_register_operand" "r,r")
9578 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
cffb2a26 9579 "TARGET_ARM"
8a18b90c 9580 "@
9581 %I5%D4\\t%0, %2, %3
129a2fe4 9582 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
8fa3ba89 9583 [(set_attr "conds" "use")
9584 (set_attr "length" "4,8")
282b4c75 9585 (set_attr_alternative "type"
9586 [(if_then_else (match_operand 3 "const_int_operand" "")
9587 (const_string "alu_shift_imm" )
9588 (const_string "alu_shift_reg"))
9589 (const_string "multiple")])]
8fa3ba89 9590)
8a18b90c 9591
9592(define_insn "*ifcompare_move_not"
9c08d1fa 9593 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9594 (if_then_else:SI
8fa3ba89 9595 (match_operator 5 "arm_comparison_operator"
8a18b90c 9596 [(match_operand:SI 3 "s_register_operand" "r,r")
9597 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9598 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9599 (not:SI
9600 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 9601 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9602 "TARGET_ARM"
8a18b90c 9603 "#"
8fa3ba89 9604 [(set_attr "conds" "clob")
1b7da4ac 9605 (set_attr "length" "8,12")
9606 (set_attr "type" "multiple")]
8fa3ba89 9607)
9c08d1fa 9608
8a18b90c 9609(define_insn "*if_move_not"
9610 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9611 (if_then_else:SI
8fa3ba89 9612 (match_operator 4 "arm_comparison_operator"
8a18b90c 9613 [(match_operand 3 "cc_register" "") (const_int 0)])
9614 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9615 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
cffb2a26 9616 "TARGET_ARM"
8a18b90c 9617 "@
9618 mvn%D4\\t%0, %2
9619 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
9620 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
8fa3ba89 9621 [(set_attr "conds" "use")
1aed5204 9622 (set_attr "type" "mvn_reg")
1b7da4ac 9623 (set_attr "length" "4,8,8")
9624 (set_attr "type" "mvn_reg,multiple,multiple")]
8fa3ba89 9625)
8a18b90c 9626
9627(define_insn "*ifcompare_not_move"
9c08d1fa 9628 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9629 (if_then_else:SI
8fa3ba89 9630 (match_operator 5 "arm_comparison_operator"
8a18b90c 9631 [(match_operand:SI 3 "s_register_operand" "r,r")
9632 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9633 (not:SI
9634 (match_operand:SI 2 "s_register_operand" "r,r"))
9635 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 9636 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9637 "TARGET_ARM"
8a18b90c 9638 "#"
8fa3ba89 9639 [(set_attr "conds" "clob")
1b7da4ac 9640 (set_attr "length" "8,12")
9641 (set_attr "type" "multiple")]
8fa3ba89 9642)
9c08d1fa 9643
8a18b90c 9644(define_insn "*if_not_move"
9645 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9646 (if_then_else:SI
8fa3ba89 9647 (match_operator 4 "arm_comparison_operator"
8a18b90c 9648 [(match_operand 3 "cc_register" "") (const_int 0)])
9649 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9650 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 9651 "TARGET_ARM"
8a18b90c 9652 "@
9653 mvn%d4\\t%0, %2
9654 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
9655 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
8fa3ba89 9656 [(set_attr "conds" "use")
1b7da4ac 9657 (set_attr "type" "mvn_reg,multiple,multiple")
8fa3ba89 9658 (set_attr "length" "4,8,8")]
9659)
8a18b90c 9660
9661(define_insn "*ifcompare_shift_move"
9c08d1fa 9662 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9663 (if_then_else:SI
8fa3ba89 9664 (match_operator 6 "arm_comparison_operator"
8a18b90c 9665 [(match_operand:SI 4 "s_register_operand" "r,r")
9666 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9667 (match_operator:SI 7 "shift_operator"
9668 [(match_operand:SI 2 "s_register_operand" "r,r")
9669 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
9670 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 9671 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9672 "TARGET_ARM"
9c08d1fa 9673 "#"
8fa3ba89 9674 [(set_attr "conds" "clob")
1b7da4ac 9675 (set_attr "length" "8,12")
9676 (set_attr "type" "multiple")]
8fa3ba89 9677)
9c08d1fa 9678
8a18b90c 9679(define_insn "*if_shift_move"
9680 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9681 (if_then_else:SI
8fa3ba89 9682 (match_operator 5 "arm_comparison_operator"
8a18b90c 9683 [(match_operand 6 "cc_register" "") (const_int 0)])
9684 (match_operator:SI 4 "shift_operator"
9685 [(match_operand:SI 2 "s_register_operand" "r,r,r")
9686 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
9687 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 9688 "TARGET_ARM"
5565501b 9689 "@
8a18b90c 9690 mov%d5\\t%0, %2%S4
9691 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
9692 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
8fa3ba89 9693 [(set_attr "conds" "use")
331beb1a 9694 (set_attr "shift" "2")
a2cd141b 9695 (set_attr "length" "4,8,8")
282b4c75 9696 (set_attr_alternative "type"
9697 [(if_then_else (match_operand 3 "const_int_operand" "")
9698 (const_string "mov_shift" )
9699 (const_string "mov_shift_reg"))
9700 (const_string "multiple")
9701 (const_string "multiple")])]
8fa3ba89 9702)
5565501b 9703
8a18b90c 9704(define_insn "*ifcompare_move_shift"
9705 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 9706 (if_then_else:SI
8fa3ba89 9707 (match_operator 6 "arm_comparison_operator"
8a18b90c 9708 [(match_operand:SI 4 "s_register_operand" "r,r")
9709 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9710 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
5565501b 9711 (match_operator:SI 7 "shift_operator"
8a18b90c 9712 [(match_operand:SI 2 "s_register_operand" "r,r")
9713 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
bd5b4116 9714 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9715 "TARGET_ARM"
8a18b90c 9716 "#"
8fa3ba89 9717 [(set_attr "conds" "clob")
1b7da4ac 9718 (set_attr "length" "8,12")
9719 (set_attr "type" "multiple")]
8fa3ba89 9720)
5565501b 9721
8a18b90c 9722(define_insn "*if_move_shift"
9723 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 9724 (if_then_else:SI
8fa3ba89 9725 (match_operator 5 "arm_comparison_operator"
8a18b90c 9726 [(match_operand 6 "cc_register" "") (const_int 0)])
9727 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9728 (match_operator:SI 4 "shift_operator"
9729 [(match_operand:SI 2 "s_register_operand" "r,r,r")
9730 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
cffb2a26 9731 "TARGET_ARM"
5565501b 9732 "@
8a18b90c 9733 mov%D5\\t%0, %2%S4
9734 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
9735 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
8fa3ba89 9736 [(set_attr "conds" "use")
331beb1a 9737 (set_attr "shift" "2")
a2cd141b 9738 (set_attr "length" "4,8,8")
282b4c75 9739 (set_attr_alternative "type"
9740 [(if_then_else (match_operand 3 "const_int_operand" "")
9741 (const_string "mov_shift" )
9742 (const_string "mov_shift_reg"))
9743 (const_string "multiple")
9744 (const_string "multiple")])]
8fa3ba89 9745)
9c08d1fa 9746
f7fbdd4a 9747(define_insn "*ifcompare_shift_shift"
8a18b90c 9748 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 9749 (if_then_else:SI
8fa3ba89 9750 (match_operator 7 "arm_comparison_operator"
8a18b90c 9751 [(match_operand:SI 5 "s_register_operand" "r")
9752 (match_operand:SI 6 "arm_add_operand" "rIL")])
5565501b 9753 (match_operator:SI 8 "shift_operator"
8a18b90c 9754 [(match_operand:SI 1 "s_register_operand" "r")
9755 (match_operand:SI 2 "arm_rhs_operand" "rM")])
5565501b 9756 (match_operator:SI 9 "shift_operator"
8a18b90c 9757 [(match_operand:SI 3 "s_register_operand" "r")
9758 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
bd5b4116 9759 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9760 "TARGET_ARM"
8a18b90c 9761 "#"
8fa3ba89 9762 [(set_attr "conds" "clob")
1b7da4ac 9763 (set_attr "length" "12")
9764 (set_attr "type" "multiple")]
8fa3ba89 9765)
9c08d1fa 9766
8a18b90c 9767(define_insn "*if_shift_shift"
9768 [(set (match_operand:SI 0 "s_register_operand" "=r")
9769 (if_then_else:SI
8fa3ba89 9770 (match_operator 5 "arm_comparison_operator"
8a18b90c 9771 [(match_operand 8 "cc_register" "") (const_int 0)])
9772 (match_operator:SI 6 "shift_operator"
9773 [(match_operand:SI 1 "s_register_operand" "r")
9774 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9775 (match_operator:SI 7 "shift_operator"
9776 [(match_operand:SI 3 "s_register_operand" "r")
9777 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
cffb2a26 9778 "TARGET_ARM"
8a18b90c 9779 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
8fa3ba89 9780 [(set_attr "conds" "use")
331beb1a 9781 (set_attr "shift" "1")
a2cd141b 9782 (set_attr "length" "8")
9783 (set (attr "type") (if_then_else
9784 (and (match_operand 2 "const_int_operand" "")
9785 (match_operand 4 "const_int_operand" ""))
1aed5204 9786 (const_string "mov_shift")
9787 (const_string "mov_shift_reg")))]
8fa3ba89 9788)
8a18b90c 9789
f7fbdd4a 9790(define_insn "*ifcompare_not_arith"
8a18b90c 9791 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 9792 (if_then_else:SI
8fa3ba89 9793 (match_operator 6 "arm_comparison_operator"
8a18b90c 9794 [(match_operand:SI 4 "s_register_operand" "r")
9795 (match_operand:SI 5 "arm_add_operand" "rIL")])
9796 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5565501b 9797 (match_operator:SI 7 "shiftable_operator"
8a18b90c 9798 [(match_operand:SI 2 "s_register_operand" "r")
9799 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
bd5b4116 9800 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9801 "TARGET_ARM"
8a18b90c 9802 "#"
8fa3ba89 9803 [(set_attr "conds" "clob")
1b7da4ac 9804 (set_attr "length" "12")
9805 (set_attr "type" "multiple")]
8fa3ba89 9806)
9c08d1fa 9807
8a18b90c 9808(define_insn "*if_not_arith"
9809 [(set (match_operand:SI 0 "s_register_operand" "=r")
9810 (if_then_else:SI
8fa3ba89 9811 (match_operator 5 "arm_comparison_operator"
8a18b90c 9812 [(match_operand 4 "cc_register" "") (const_int 0)])
9813 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9814 (match_operator:SI 6 "shiftable_operator"
9815 [(match_operand:SI 2 "s_register_operand" "r")
9816 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
cffb2a26 9817 "TARGET_ARM"
8a18b90c 9818 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
8fa3ba89 9819 [(set_attr "conds" "use")
1aed5204 9820 (set_attr "type" "mvn_reg")
8fa3ba89 9821 (set_attr "length" "8")]
9822)
8a18b90c 9823
9824(define_insn "*ifcompare_arith_not"
9825 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 9826 (if_then_else:SI
8fa3ba89 9827 (match_operator 6 "arm_comparison_operator"
8a18b90c 9828 [(match_operand:SI 4 "s_register_operand" "r")
9829 (match_operand:SI 5 "arm_add_operand" "rIL")])
5565501b 9830 (match_operator:SI 7 "shiftable_operator"
8a18b90c 9831 [(match_operand:SI 2 "s_register_operand" "r")
9832 (match_operand:SI 3 "arm_rhs_operand" "rI")])
9833 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
bd5b4116 9834 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9835 "TARGET_ARM"
8a18b90c 9836 "#"
8fa3ba89 9837 [(set_attr "conds" "clob")
1b7da4ac 9838 (set_attr "length" "12")
9839 (set_attr "type" "multiple")]
8fa3ba89 9840)
9c08d1fa 9841
8a18b90c 9842(define_insn "*if_arith_not"
9843 [(set (match_operand:SI 0 "s_register_operand" "=r")
9844 (if_then_else:SI
8fa3ba89 9845 (match_operator 5 "arm_comparison_operator"
8a18b90c 9846 [(match_operand 4 "cc_register" "") (const_int 0)])
9847 (match_operator:SI 6 "shiftable_operator"
9848 [(match_operand:SI 2 "s_register_operand" "r")
9849 (match_operand:SI 3 "arm_rhs_operand" "rI")])
9850 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
cffb2a26 9851 "TARGET_ARM"
8a18b90c 9852 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
8fa3ba89 9853 [(set_attr "conds" "use")
1b7da4ac 9854 (set_attr "type" "multiple")
8fa3ba89 9855 (set_attr "length" "8")]
9856)
8a18b90c 9857
f7fbdd4a 9858(define_insn "*ifcompare_neg_move"
8a18b90c 9859 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 9860 (if_then_else:SI
8fa3ba89 9861 (match_operator 5 "arm_comparison_operator"
8a18b90c 9862 [(match_operand:SI 3 "s_register_operand" "r,r")
9863 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9864 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
9865 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 9866 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9867 "TARGET_ARM"
8a18b90c 9868 "#"
8fa3ba89 9869 [(set_attr "conds" "clob")
1b7da4ac 9870 (set_attr "length" "8,12")
9871 (set_attr "type" "multiple")]
8fa3ba89 9872)
8a18b90c 9873
530bb693 9874(define_insn_and_split "*if_neg_move"
9875 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
8a18b90c 9876 (if_then_else:SI
8fa3ba89 9877 (match_operator 4 "arm_comparison_operator"
8a18b90c 9878 [(match_operand 3 "cc_register" "") (const_int 0)])
530bb693 9879 (neg:SI (match_operand:SI 2 "s_register_operand" "l,r"))
9880 (match_operand:SI 1 "s_register_operand" "0,0")))]
9881 "TARGET_32BIT"
9882 "#"
9883 "&& reload_completed"
9884 [(cond_exec (match_op_dup 4 [(match_dup 3) (const_int 0)])
9885 (set (match_dup 0) (neg:SI (match_dup 2))))]
9886 ""
8fa3ba89 9887 [(set_attr "conds" "use")
530bb693 9888 (set_attr "length" "4")
9889 (set_attr "arch" "t2,32")
8bdfd6ed 9890 (set_attr "enabled_for_short_it" "yes,no")
530bb693 9891 (set_attr "type" "logic_shift_imm")]
8fa3ba89 9892)
9c08d1fa 9893
f7fbdd4a 9894(define_insn "*ifcompare_move_neg"
8a18b90c 9895 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 9896 (if_then_else:SI
8fa3ba89 9897 (match_operator 5 "arm_comparison_operator"
8a18b90c 9898 [(match_operand:SI 3 "s_register_operand" "r,r")
9899 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9900 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9901 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 9902 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9903 "TARGET_ARM"
8a18b90c 9904 "#"
8fa3ba89 9905 [(set_attr "conds" "clob")
1b7da4ac 9906 (set_attr "length" "8,12")
9907 (set_attr "type" "multiple")]
8fa3ba89 9908)
8a18b90c 9909
530bb693 9910(define_insn_and_split "*if_move_neg"
9911 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
8a18b90c 9912 (if_then_else:SI
8fa3ba89 9913 (match_operator 4 "arm_comparison_operator"
8a18b90c 9914 [(match_operand 3 "cc_register" "") (const_int 0)])
530bb693 9915 (match_operand:SI 1 "s_register_operand" "0,0")
9916 (neg:SI (match_operand:SI 2 "s_register_operand" "l,r"))))]
9917 "TARGET_32BIT"
9918 "#"
9919 "&& reload_completed"
9920 [(cond_exec (match_dup 5)
9921 (set (match_dup 0) (neg:SI (match_dup 2))))]
9922 {
9923 machine_mode mode = GET_MODE (operands[3]);
9924 rtx_code rc = GET_CODE (operands[4]);
9925
9926 if (mode == CCFPmode || mode == CCFPEmode)
9927 rc = reverse_condition_maybe_unordered (rc);
9928 else
9929 rc = reverse_condition (rc);
9930
9931 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[3], const0_rtx);
9932 }
0d66636f 9933 [(set_attr "conds" "use")
530bb693 9934 (set_attr "length" "4")
9935 (set_attr "arch" "t2,32")
8bdfd6ed 9936 (set_attr "enabled_for_short_it" "yes,no")
530bb693 9937 (set_attr "type" "logic_shift_imm")]
0d66636f 9938)
9c08d1fa 9939
f7fbdd4a 9940(define_insn "*arith_adjacentmem"
9c08d1fa 9941 [(set (match_operand:SI 0 "s_register_operand" "=r")
9942 (match_operator:SI 1 "shiftable_operator"
9943 [(match_operand:SI 2 "memory_operand" "m")
9944 (match_operand:SI 3 "memory_operand" "m")]))
9945 (clobber (match_scratch:SI 4 "=r"))]
cffb2a26 9946 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9c08d1fa 9947 "*
215b30b3 9948 {
9949 rtx ldm[3];
9950 rtx arith[4];
94dee231 9951 rtx base_reg;
9952 HOST_WIDE_INT val1 = 0, val2 = 0;
9c08d1fa 9953
215b30b3 9954 if (REGNO (operands[0]) > REGNO (operands[4]))
9955 {
9956 ldm[1] = operands[4];
9957 ldm[2] = operands[0];
9958 }
9959 else
9960 {
9961 ldm[1] = operands[0];
9962 ldm[2] = operands[4];
9963 }
94dee231 9964
9965 base_reg = XEXP (operands[2], 0);
9966
9967 if (!REG_P (base_reg))
9968 {
9969 val1 = INTVAL (XEXP (base_reg, 1));
9970 base_reg = XEXP (base_reg, 0);
9971 }
9972
9973 if (!REG_P (XEXP (operands[3], 0)))
215b30b3 9974 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
94dee231 9975
215b30b3 9976 arith[0] = operands[0];
9977 arith[3] = operands[1];
94dee231 9978
215b30b3 9979 if (val1 < val2)
9980 {
9981 arith[1] = ldm[1];
9982 arith[2] = ldm[2];
9983 }
9984 else
9985 {
9986 arith[1] = ldm[2];
9987 arith[2] = ldm[1];
9988 }
94dee231 9989
9990 ldm[0] = base_reg;
9991 if (val1 !=0 && val2 != 0)
215b30b3 9992 {
cdb1295a 9993 rtx ops[3];
9994
94dee231 9995 if (val1 == 4 || val2 == 4)
9996 /* Other val must be 8, since we know they are adjacent and neither
9997 is zero. */
3ef90e77 9998 output_asm_insn (\"ldmib%?\\t%0, {%1, %2}\", ldm);
cdb1295a 9999 else if (const_ok_for_arm (val1) || const_ok_for_arm (-val1))
94dee231 10000 {
94dee231 10001 ldm[0] = ops[0] = operands[4];
10002 ops[1] = base_reg;
10003 ops[2] = GEN_INT (val1);
10004 output_add_immediate (ops);
10005 if (val1 < val2)
3ef90e77 10006 output_asm_insn (\"ldmia%?\\t%0, {%1, %2}\", ldm);
94dee231 10007 else
3ef90e77 10008 output_asm_insn (\"ldmda%?\\t%0, {%1, %2}\", ldm);
94dee231 10009 }
cdb1295a 10010 else
10011 {
10012 /* Offset is out of range for a single add, so use two ldr. */
10013 ops[0] = ldm[1];
10014 ops[1] = base_reg;
10015 ops[2] = GEN_INT (val1);
10016 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10017 ops[0] = ldm[2];
10018 ops[2] = GEN_INT (val2);
10019 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10020 }
215b30b3 10021 }
94dee231 10022 else if (val1 != 0)
215b30b3 10023 {
215b30b3 10024 if (val1 < val2)
3ef90e77 10025 output_asm_insn (\"ldmda%?\\t%0, {%1, %2}\", ldm);
215b30b3 10026 else
3ef90e77 10027 output_asm_insn (\"ldmia%?\\t%0, {%1, %2}\", ldm);
215b30b3 10028 }
10029 else
10030 {
215b30b3 10031 if (val1 < val2)
3ef90e77 10032 output_asm_insn (\"ldmia%?\\t%0, {%1, %2}\", ldm);
215b30b3 10033 else
3ef90e77 10034 output_asm_insn (\"ldmda%?\\t%0, {%1, %2}\", ldm);
215b30b3 10035 }
10036 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
10037 return \"\";
10038 }"
10039 [(set_attr "length" "12")
10040 (set_attr "predicable" "yes")
9f2c2a36 10041 (set_attr "type" "load_4")]
215b30b3 10042)
9c08d1fa 10043
9c08d1fa 10044; This pattern is never tried by combine, so do it as a peephole
10045
a0f94409 10046(define_peephole2
372575c7 10047 [(set (match_operand:SI 0 "arm_general_register_operand" "")
10048 (match_operand:SI 1 "arm_general_register_operand" ""))
bd5b4116 10049 (set (reg:CC CC_REGNUM)
aea4c774 10050 (compare:CC (match_dup 1) (const_int 0)))]
372575c7 10051 "TARGET_ARM"
a0f94409 10052 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
10053 (set (match_dup 0) (match_dup 1))])]
10054 ""
0d66636f 10055)
9c08d1fa 10056
9c08d1fa 10057(define_split
10058 [(set (match_operand:SI 0 "s_register_operand" "")
10059 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
10060 (const_int 0))
8fa3ba89 10061 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9c08d1fa 10062 [(match_operand:SI 3 "s_register_operand" "")
10063 (match_operand:SI 4 "arm_rhs_operand" "")]))))
10064 (clobber (match_operand:SI 5 "s_register_operand" ""))]
cffb2a26 10065 "TARGET_ARM"
9c08d1fa 10066 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
10067 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
10068 (match_dup 5)))]
215b30b3 10069 ""
10070)
9c08d1fa 10071
aea4c774 10072;; This split can be used because CC_Z mode implies that the following
10073;; branch will be an equality, or an unsigned inequality, so the sign
10074;; extension is not needed.
9c08d1fa 10075
aea4c774 10076(define_split
bd5b4116 10077 [(set (reg:CC_Z CC_REGNUM)
aea4c774 10078 (compare:CC_Z
10079 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9c08d1fa 10080 (const_int 24))
aea4c774 10081 (match_operand 1 "const_int_operand" "")))
10082 (clobber (match_scratch:SI 2 ""))]
cffb2a26 10083 "TARGET_ARM
8c4e8755 10084 && ((UINTVAL (operands[1]))
10085 == ((UINTVAL (operands[1])) >> 24) << 24)"
aea4c774 10086 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
bd5b4116 10087 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
aea4c774 10088 "
9c08d1fa 10089 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
215b30b3 10090 "
10091)
25f905c2 10092;; ??? Check the patterns above for Thumb-2 usefulness
9c08d1fa 10093
87b22bf7 10094(define_expand "prologue"
10095 [(clobber (const_int 0))]
cffb2a26 10096 "TARGET_EITHER"
25f905c2 10097 "if (TARGET_32BIT)
cffb2a26 10098 arm_expand_prologue ();
10099 else
25f905c2 10100 thumb1_expand_prologue ();
87b22bf7 10101 DONE;
cffb2a26 10102 "
10103)
87b22bf7 10104
56d27660 10105(define_expand "epilogue"
4c44712e 10106 [(clobber (const_int 0))]
cffb2a26 10107 "TARGET_EITHER"
56d27660 10108 "
18d50ae6 10109 if (crtl->calls_eh_return)
fb94f18b 10110 emit_insn (gen_force_register_use (gen_rtx_REG (Pmode, 2)));
25f905c2 10111 if (TARGET_THUMB1)
c3635784 10112 {
10113 thumb1_expand_epilogue ();
10114 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
10115 gen_rtvec (1, ret_rtx), VUNSPEC_EPILOGUE));
10116 }
10117 else if (HAVE_return)
10118 {
10119 /* HAVE_return is testing for USE_RETURN_INSN (FALSE). Hence,
10120 no need for explicit testing again. */
10121 emit_jump_insn (gen_return ());
10122 }
10123 else if (TARGET_32BIT)
10124 {
10125 arm_expand_epilogue (true);
10126 }
cffb2a26 10127 DONE;
10128 "
10129)
56d27660 10130
ef5651d0 10131;; Note - although unspec_volatile's USE all hard registers,
10132;; USEs are ignored after relaod has completed. Thus we need
10133;; to add an unspec of the link register to ensure that flow
10134;; does not think that it is unused by the sibcall branch that
10135;; will replace the standard function epilogue.
c3635784 10136(define_expand "sibcall_epilogue"
fb94f18b 10137 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_REGISTER_USE)
c3635784 10138 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
10139 "TARGET_32BIT"
10140 "
10141 arm_expand_epilogue (false);
10142 DONE;
10143 "
1c494086 10144)
10145
cffb2a26 10146(define_expand "eh_epilogue"
3934ae0e 10147 [(use (match_operand:SI 0 "register_operand"))
10148 (use (match_operand:SI 1 "register_operand"))
10149 (use (match_operand:SI 2 "register_operand"))]
cffb2a26 10150 "TARGET_EITHER"
10151 "
215b30b3 10152 {
10153 cfun->machine->eh_epilogue_sp_ofs = operands[1];
0438d37f 10154 if (!REG_P (operands[2]) || REGNO (operands[2]) != 2)
215b30b3 10155 {
10156 rtx ra = gen_rtx_REG (Pmode, 2);
10157
10158 emit_move_insn (ra, operands[2]);
10159 operands[2] = ra;
10160 }
5cf3595a 10161 /* This is a hack -- we may have crystalized the function type too
10162 early. */
10163 cfun->machine->func_type = 0;
215b30b3 10164 }"
10165)
56d27660 10166
9c08d1fa 10167;; This split is only used during output to reduce the number of patterns
10168;; that need assembler instructions adding to them. We allowed the setting
10169;; of the conditions to be implicit during rtl generation so that
10170;; the conditional compare patterns would work. However this conflicts to
8a18b90c 10171;; some extent with the conditional data operations, so we have to split them
9c08d1fa 10172;; up again here.
10173
25f905c2 10174;; ??? Need to audit these splitters for Thumb-2. Why isn't normal
10175;; conditional execution sufficient?
10176
9c08d1fa 10177(define_split
10178 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 10179 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10180 [(match_operand 2 "" "") (match_operand 3 "" "")])
10181 (match_dup 0)
10182 (match_operand 4 "" "")))
bd5b4116 10183 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10184 "TARGET_ARM && reload_completed"
8fa3ba89 10185 [(set (match_dup 5) (match_dup 6))
10186 (cond_exec (match_dup 7)
10187 (set (match_dup 0) (match_dup 4)))]
10188 "
10189 {
3754d046 10190 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8fa3ba89 10191 operands[2], operands[3]);
10192 enum rtx_code rc = GET_CODE (operands[1]);
10193
bd5b4116 10194 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10195 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10196 if (mode == CCFPmode || mode == CCFPEmode)
10197 rc = reverse_condition_maybe_unordered (rc);
10198 else
10199 rc = reverse_condition (rc);
10200
10201 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
10202 }"
10203)
10204
10205(define_split
10206 [(set (match_operand:SI 0 "s_register_operand" "")
10207 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10208 [(match_operand 2 "" "") (match_operand 3 "" "")])
10209 (match_operand 4 "" "")
10210 (match_dup 0)))
bd5b4116 10211 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10212 "TARGET_ARM && reload_completed"
8fa3ba89 10213 [(set (match_dup 5) (match_dup 6))
10214 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
10215 (set (match_dup 0) (match_dup 4)))]
10216 "
10217 {
3754d046 10218 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8fa3ba89 10219 operands[2], operands[3]);
10220
bd5b4116 10221 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10222 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10223 }"
10224)
10225
10226(define_split
10227 [(set (match_operand:SI 0 "s_register_operand" "")
10228 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9c08d1fa 10229 [(match_operand 2 "" "") (match_operand 3 "" "")])
10230 (match_operand 4 "" "")
10231 (match_operand 5 "" "")))
bd5b4116 10232 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10233 "TARGET_ARM && reload_completed"
8fa3ba89 10234 [(set (match_dup 6) (match_dup 7))
10235 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10236 (set (match_dup 0) (match_dup 4)))
10237 (cond_exec (match_dup 8)
10238 (set (match_dup 0) (match_dup 5)))]
10239 "
10240 {
3754d046 10241 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8fa3ba89 10242 operands[2], operands[3]);
10243 enum rtx_code rc = GET_CODE (operands[1]);
10244
bd5b4116 10245 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10246 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10247 if (mode == CCFPmode || mode == CCFPEmode)
10248 rc = reverse_condition_maybe_unordered (rc);
10249 else
10250 rc = reverse_condition (rc);
10251
10252 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10253 }"
10254)
10255
cffb2a26 10256(define_split
10257 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 10258 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
cffb2a26 10259 [(match_operand:SI 2 "s_register_operand" "")
10260 (match_operand:SI 3 "arm_add_operand" "")])
10261 (match_operand:SI 4 "arm_rhs_operand" "")
10262 (not:SI
10263 (match_operand:SI 5 "s_register_operand" ""))))
bd5b4116 10264 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10265 "TARGET_ARM && reload_completed"
cffb2a26 10266 [(set (match_dup 6) (match_dup 7))
f6c53574 10267 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10268 (set (match_dup 0) (match_dup 4)))
10269 (cond_exec (match_dup 8)
10270 (set (match_dup 0) (not:SI (match_dup 5))))]
cffb2a26 10271 "
215b30b3 10272 {
3754d046 10273 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
215b30b3 10274 operands[2], operands[3]);
f6c53574 10275 enum rtx_code rc = GET_CODE (operands[1]);
cffb2a26 10276
bd5b4116 10277 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
1a83b3ff 10278 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
f6c53574 10279 if (mode == CCFPmode || mode == CCFPEmode)
10280 rc = reverse_condition_maybe_unordered (rc);
10281 else
10282 rc = reverse_condition (rc);
10283
10284 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
215b30b3 10285 }"
10286)
cffb2a26 10287
10288(define_insn "*cond_move_not"
10289 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10290 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
cffb2a26 10291 [(match_operand 3 "cc_register" "") (const_int 0)])
10292 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10293 (not:SI
10294 (match_operand:SI 2 "s_register_operand" "r,r"))))]
10295 "TARGET_ARM"
10296 "@
10297 mvn%D4\\t%0, %2
10298 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
0d66636f 10299 [(set_attr "conds" "use")
1b7da4ac 10300 (set_attr "type" "mvn_reg,multiple")
0d66636f 10301 (set_attr "length" "4,8")]
10302)
cffb2a26 10303
9c08d1fa 10304;; The next two patterns occur when an AND operation is followed by a
10305;; scc insn sequence
10306
f7fbdd4a 10307(define_insn "*sign_extract_onebit"
9c08d1fa 10308 [(set (match_operand:SI 0 "s_register_operand" "=r")
10309 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10310 (const_int 1)
ed750274 10311 (match_operand:SI 2 "const_int_operand" "n")))
10312 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10313 "TARGET_ARM"
9c08d1fa 10314 "*
0d66636f 10315 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10316 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
10317 return \"mvnne\\t%0, #0\";
10318 "
10319 [(set_attr "conds" "clob")
1b7da4ac 10320 (set_attr "length" "8")
10321 (set_attr "type" "multiple")]
0d66636f 10322)
9c08d1fa 10323
f7fbdd4a 10324(define_insn "*not_signextract_onebit"
9c08d1fa 10325 [(set (match_operand:SI 0 "s_register_operand" "=r")
10326 (not:SI
10327 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10328 (const_int 1)
ed750274 10329 (match_operand:SI 2 "const_int_operand" "n"))))
10330 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10331 "TARGET_ARM"
9c08d1fa 10332 "*
0d66636f 10333 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10334 output_asm_insn (\"tst\\t%1, %2\", operands);
10335 output_asm_insn (\"mvneq\\t%0, #0\", operands);
10336 return \"movne\\t%0, #0\";
10337 "
10338 [(set_attr "conds" "clob")
1b7da4ac 10339 (set_attr "length" "12")
10340 (set_attr "type" "multiple")]
0d66636f 10341)
25f905c2 10342;; ??? The above patterns need auditing for Thumb-2
87b22bf7 10343
0d66636f 10344;; Push multiple registers to the stack. Registers are in parallel (use ...)
10345;; expressions. For simplicity, the first register is also in the unspec
10346;; part.
08508cbf 10347;; To avoid the usage of GNU extension, the length attribute is computed
10348;; in a C function arm_attr_length_push_multi.
f7fbdd4a 10349(define_insn "*push_multi"
87b22bf7 10350 [(match_parallel 2 "multi_register_push"
7571d3f7 10351 [(set (match_operand:BLK 0 "push_mult_memory_operand" "")
3cc80a30 10352 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "")]
e1159bbe 10353 UNSPEC_PUSH_MULT))])]
7571d3f7 10354 ""
87b22bf7 10355 "*
215b30b3 10356 {
10357 int num_saves = XVECLEN (operands[2], 0);
ed593f11 10358
215b30b3 10359 /* For the StrongARM at least it is faster to
25f905c2 10360 use STR to store only a single register.
542d5028 10361 In Thumb mode always use push, and the assembler will pick
10362 something appropriate. */
25f905c2 10363 if (num_saves == 1 && TARGET_ARM)
61309563 10364 output_asm_insn (\"str%?\\t%1, [%m0, #-4]!\", operands);
215b30b3 10365 else
10366 {
10367 int i;
10368 char pattern[100];
ed593f11 10369
3ef90e77 10370 if (TARGET_32BIT)
61309563 10371 strcpy (pattern, \"push%?\\t{%1\");
25f905c2 10372 else
10373 strcpy (pattern, \"push\\t{%1\");
215b30b3 10374
6079f055 10375 for (i = 1; i < num_saves; i++)
215b30b3 10376 {
10377 strcat (pattern, \", %|\");
10378 strcat (pattern,
10379 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
10380 }
10381
10382 strcat (pattern, \"}\");
10383 output_asm_insn (pattern, operands);
10384 }
10385
10386 return \"\";
10387 }"
9f2c2a36 10388 [(set_attr "type" "store_16")
a6864a24 10389 (set (attr "length")
08508cbf 10390 (symbol_ref "arm_attr_length_push_multi (operands[2], operands[1])"))]
215b30b3 10391)
f7fbdd4a 10392
4c58c898 10393(define_insn "stack_tie"
10394 [(set (mem:BLK (scratch))
aaa37ad6 10395 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "rk")
10396 (match_operand:SI 1 "s_register_operand" "rk")]
4c58c898 10397 UNSPEC_PRLG_STK))]
10398 ""
10399 ""
1b7da4ac 10400 [(set_attr "length" "0")
10401 (set_attr "type" "block")]
4c58c898 10402)
10403
426be8c5 10404;; Pop (as used in epilogue RTL)
10405;;
10406(define_insn "*load_multiple_with_writeback"
10407 [(match_parallel 0 "load_multiple_operation"
10408 [(set (match_operand:SI 1 "s_register_operand" "+rk")
10409 (plus:SI (match_dup 1)
809003b3 10410 (match_operand:SI 2 "const_int_I_operand" "I")))
426be8c5 10411 (set (match_operand:SI 3 "s_register_operand" "=rk")
10412 (mem:SI (match_dup 1)))
10413 ])]
10414 "TARGET_32BIT && (reload_in_progress || reload_completed)"
10415 "*
10416 {
10417 arm_output_multireg_pop (operands, /*return_pc=*/false,
10418 /*cond=*/const_true_rtx,
10419 /*reverse=*/false,
10420 /*update=*/true);
10421 return \"\";
10422 }
10423 "
9f2c2a36 10424 [(set_attr "type" "load_16")
5431c9c9 10425 (set_attr "predicable" "yes")
10426 (set (attr "length")
10427 (symbol_ref "arm_attr_length_pop_multi (operands,
10428 /*return_pc=*/false,
10429 /*write_back_p=*/true)"))]
426be8c5 10430)
10431
10432;; Pop with return (as used in epilogue RTL)
10433;;
10434;; This instruction is generated when the registers are popped at the end of
10435;; epilogue. Here, instead of popping the value into LR and then generating
10436;; jump to LR, value is popped into PC directly. Hence, the pattern is combined
10437;; with (return).
10438(define_insn "*pop_multiple_with_writeback_and_return"
10439 [(match_parallel 0 "pop_multiple_return"
10440 [(return)
10441 (set (match_operand:SI 1 "s_register_operand" "+rk")
10442 (plus:SI (match_dup 1)
809003b3 10443 (match_operand:SI 2 "const_int_I_operand" "I")))
426be8c5 10444 (set (match_operand:SI 3 "s_register_operand" "=rk")
10445 (mem:SI (match_dup 1)))
10446 ])]
10447 "TARGET_32BIT && (reload_in_progress || reload_completed)"
10448 "*
10449 {
10450 arm_output_multireg_pop (operands, /*return_pc=*/true,
10451 /*cond=*/const_true_rtx,
10452 /*reverse=*/false,
10453 /*update=*/true);
10454 return \"\";
10455 }
10456 "
9f2c2a36 10457 [(set_attr "type" "load_16")
5431c9c9 10458 (set_attr "predicable" "yes")
10459 (set (attr "length")
10460 (symbol_ref "arm_attr_length_pop_multi (operands, /*return_pc=*/true,
10461 /*write_back_p=*/true)"))]
426be8c5 10462)
10463
10464(define_insn "*pop_multiple_with_return"
10465 [(match_parallel 0 "pop_multiple_return"
10466 [(return)
10467 (set (match_operand:SI 2 "s_register_operand" "=rk")
10468 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
10469 ])]
10470 "TARGET_32BIT && (reload_in_progress || reload_completed)"
10471 "*
10472 {
10473 arm_output_multireg_pop (operands, /*return_pc=*/true,
10474 /*cond=*/const_true_rtx,
10475 /*reverse=*/false,
10476 /*update=*/false);
10477 return \"\";
10478 }
10479 "
9f2c2a36 10480 [(set_attr "type" "load_16")
5431c9c9 10481 (set_attr "predicable" "yes")
10482 (set (attr "length")
10483 (symbol_ref "arm_attr_length_pop_multi (operands, /*return_pc=*/true,
10484 /*write_back_p=*/false)"))]
426be8c5 10485)
10486
10487;; Load into PC and return
10488(define_insn "*ldr_with_return"
10489 [(return)
10490 (set (reg:SI PC_REGNUM)
10491 (mem:SI (post_inc:SI (match_operand:SI 0 "s_register_operand" "+rk"))))]
10492 "TARGET_32BIT && (reload_in_progress || reload_completed)"
10493 "ldr%?\t%|pc, [%0], #4"
9f2c2a36 10494 [(set_attr "type" "load_4")
426be8c5 10495 (set_attr "predicable" "yes")]
10496)
1a0b0f12 10497;; Pop for floating point registers (as used in epilogue RTL)
10498(define_insn "*vfp_pop_multiple_with_writeback"
10499 [(match_parallel 0 "pop_multiple_fp"
10500 [(set (match_operand:SI 1 "s_register_operand" "+rk")
10501 (plus:SI (match_dup 1)
809003b3 10502 (match_operand:SI 2 "const_int_I_operand" "I")))
2f2163a4 10503 (set (match_operand:DF 3 "vfp_hard_register_operand" "")
1a0b0f12 10504 (mem:DF (match_dup 1)))])]
d7216193 10505 "TARGET_32BIT && TARGET_HARD_FLOAT"
1a0b0f12 10506 "*
10507 {
10508 int num_regs = XVECLEN (operands[0], 0);
10509 char pattern[100];
10510 rtx op_list[2];
b34d8dac 10511 strcpy (pattern, \"vldm\\t\");
1a0b0f12 10512 strcat (pattern, reg_names[REGNO (SET_DEST (XVECEXP (operands[0], 0, 0)))]);
10513 strcat (pattern, \"!, {\");
10514 op_list[0] = XEXP (XVECEXP (operands[0], 0, 1), 0);
10515 strcat (pattern, \"%P0\");
10516 if ((num_regs - 1) > 1)
10517 {
10518 strcat (pattern, \"-%P1\");
10519 op_list [1] = XEXP (XVECEXP (operands[0], 0, num_regs - 1), 0);
10520 }
10521
10522 strcat (pattern, \"}\");
10523 output_asm_insn (pattern, op_list);
10524 return \"\";
10525 }
10526 "
9f2c2a36 10527 [(set_attr "type" "load_16")
1a0b0f12 10528 (set_attr "conds" "unconditional")
10529 (set_attr "predicable" "no")]
10530)
10531
f7fbdd4a 10532;; Special patterns for dealing with the constant pool
10533
cffb2a26 10534(define_insn "align_4"
e1159bbe 10535 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
cffb2a26 10536 "TARGET_EITHER"
f7fbdd4a 10537 "*
cffb2a26 10538 assemble_align (32);
f7fbdd4a 10539 return \"\";
cffb2a26 10540 "
1b7da4ac 10541 [(set_attr "type" "no_insn")]
cffb2a26 10542)
f7fbdd4a 10543
755eb2b4 10544(define_insn "align_8"
10545 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
f9273c43 10546 "TARGET_EITHER"
755eb2b4 10547 "*
10548 assemble_align (64);
10549 return \"\";
10550 "
1b7da4ac 10551 [(set_attr "type" "no_insn")]
755eb2b4 10552)
10553
cffb2a26 10554(define_insn "consttable_end"
e1159bbe 10555 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
cffb2a26 10556 "TARGET_EITHER"
f7fbdd4a 10557 "*
cffb2a26 10558 making_const_table = FALSE;
f7fbdd4a 10559 return \"\";
cffb2a26 10560 "
1b7da4ac 10561 [(set_attr "type" "no_insn")]
cffb2a26 10562)
f7fbdd4a 10563
0e207eb8 10564(define_insn "consttable_1"
10565 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
10566 "TARGET_EITHER"
10567 "*
10568 making_const_table = TRUE;
10569 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
10570 assemble_zeros (3);
10571 return \"\";
10572 "
10573 [(set_attr "length" "4")
10574 (set_attr "type" "no_insn")]
10575)
10576
10577(define_insn "consttable_2"
10578 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
10579 "TARGET_EITHER"
10580 "*
10581 {
10582 rtx x = operands[0];
10583 making_const_table = TRUE;
10584 switch (GET_MODE_CLASS (GET_MODE (x)))
10585 {
10586 case MODE_FLOAT:
10587 arm_emit_fp16_const (x);
10588 break;
10589 default:
10590 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
10591 assemble_zeros (2);
10592 break;
10593 }
10594 return \"\";
10595 }"
10596 [(set_attr "length" "4")
10597 (set_attr "type" "no_insn")]
10598)
10599
cffb2a26 10600(define_insn "consttable_4"
e1159bbe 10601 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
cffb2a26 10602 "TARGET_EITHER"
10603 "*
10604 {
9b8516be 10605 rtx x = operands[0];
cffb2a26 10606 making_const_table = TRUE;
0f97e0f5 10607 scalar_float_mode float_mode;
10608 if (is_a <scalar_float_mode> (GET_MODE (x), &float_mode))
10609 assemble_real (*CONST_DOUBLE_REAL_VALUE (x), float_mode, BITS_PER_WORD);
10610 else
cffb2a26 10611 {
7b04c5d5 10612 /* XXX: Sometimes gcc does something really dumb and ends up with
10613 a HIGH in a constant pool entry, usually because it's trying to
10614 load into a VFP register. We know this will always be used in
10615 combination with a LO_SUM which ignores the high bits, so just
10616 strip off the HIGH. */
10617 if (GET_CODE (x) == HIGH)
10618 x = XEXP (x, 0);
9b8516be 10619 assemble_integer (x, 4, BITS_PER_WORD, 1);
10620 mark_symbol_refs_as_used (x);
cffb2a26 10621 }
10622 return \"\";
10623 }"
1b7da4ac 10624 [(set_attr "length" "4")
10625 (set_attr "type" "no_insn")]
cffb2a26 10626)
10627
10628(define_insn "consttable_8"
e1159bbe 10629 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
cffb2a26 10630 "TARGET_EITHER"
10631 "*
10632 {
10633 making_const_table = TRUE;
0f97e0f5 10634 scalar_float_mode float_mode;
10635 if (is_a <scalar_float_mode> (GET_MODE (operands[0]), &float_mode))
10636 assemble_real (*CONST_DOUBLE_REAL_VALUE (operands[0]),
10637 float_mode, BITS_PER_WORD);
10638 else
10639 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
cffb2a26 10640 return \"\";
10641 }"
1b7da4ac 10642 [(set_attr "length" "8")
10643 (set_attr "type" "no_insn")]
cffb2a26 10644)
10645
d98a3884 10646(define_insn "consttable_16"
10647 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_16)]
10648 "TARGET_EITHER"
10649 "*
10650 {
10651 making_const_table = TRUE;
0f97e0f5 10652 scalar_float_mode float_mode;
10653 if (is_a <scalar_float_mode> (GET_MODE (operands[0]), &float_mode))
10654 assemble_real (*CONST_DOUBLE_REAL_VALUE (operands[0]),
10655 float_mode, BITS_PER_WORD);
10656 else
10657 assemble_integer (operands[0], 16, BITS_PER_WORD, 1);
d98a3884 10658 return \"\";
10659 }"
1b7da4ac 10660 [(set_attr "length" "16")
10661 (set_attr "type" "no_insn")]
d98a3884 10662)
10663
331beb1a 10664;; V5 Instructions,
10665
8f4be2be 10666(define_insn "clzsi2"
10667 [(set (match_operand:SI 0 "s_register_operand" "=r")
10668 (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
b232e6b5 10669 "TARGET_32BIT && arm_arch5t"
ee7cbe0e 10670 "clz%?\\t%0, %1"
bcaec148 10671 [(set_attr "predicable" "yes")
bebe9bbb 10672 (set_attr "type" "clz")])
331beb1a 10673
099ad98b 10674(define_insn "rbitsi2"
10675 [(set (match_operand:SI 0 "s_register_operand" "=r")
10676 (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")] UNSPEC_RBIT))]
10677 "TARGET_32BIT && arm_arch_thumb2"
10678 "rbit%?\\t%0, %1"
10679 [(set_attr "predicable" "yes")
bebe9bbb 10680 (set_attr "type" "clz")])
099ad98b 10681
99ffa689 10682;; Keep this as a CTZ expression until after reload and then split
10683;; into RBIT + CLZ. Since RBIT is represented as an UNSPEC it is unlikely
10684;; to fold with any other expression.
10685
10686(define_insn_and_split "ctzsi2"
10687 [(set (match_operand:SI 0 "s_register_operand" "=r")
10688 (ctz:SI (match_operand:SI 1 "s_register_operand" "r")))]
099ad98b 10689 "TARGET_32BIT && arm_arch_thumb2"
99ffa689 10690 "#"
10691 "&& reload_completed"
10692 [(const_int 0)]
099ad98b 10693 "
99ffa689 10694 emit_insn (gen_rbitsi2 (operands[0], operands[1]));
10695 emit_insn (gen_clzsi2 (operands[0], operands[0]));
10696 DONE;
10697")
099ad98b 10698
e1159bbe 10699;; V5E instructions.
331beb1a 10700
10701(define_insn "prefetch"
f4e79814 10702 [(prefetch (match_operand:SI 0 "address_operand" "p")
10703 (match_operand:SI 1 "" "")
10704 (match_operand:SI 2 "" ""))]
b232e6b5 10705 "TARGET_32BIT && arm_arch5te"
1b7da4ac 10706 "pld\\t%a0"
9f2c2a36 10707 [(set_attr "type" "load_4")]
1b7da4ac 10708)
331beb1a 10709
0d66636f 10710;; General predication pattern
10711
10712(define_cond_exec
10713 [(match_operator 0 "arm_comparison_operator"
10714 [(match_operand 1 "cc_register" "")
10715 (const_int 0)])]
580f4c48 10716 "TARGET_32BIT
10717 && (!TARGET_NO_VOLATILE_CE || !volatile_refs_p (PATTERN (insn)))"
0d66636f 10718 ""
c7a58118 10719[(set_attr "predicated" "yes")]
0d66636f 10720)
10721
fb94f18b 10722(define_insn "force_register_use"
10723 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_REGISTER_USE)]
063a05c7 10724 ""
fb94f18b 10725 "%@ %0 needed"
1b7da4ac 10726 [(set_attr "length" "0")
10727 (set_attr "type" "no_insn")]
063a05c7 10728)
7db9af5d 10729
4c44712e 10730
10731;; Patterns for exception handling
10732
10733(define_expand "eh_return"
3934ae0e 10734 [(use (match_operand 0 "general_operand"))]
4c44712e 10735 "TARGET_EITHER"
10736 "
10737 {
25f905c2 10738 if (TARGET_32BIT)
4c44712e 10739 emit_insn (gen_arm_eh_return (operands[0]));
10740 else
10741 emit_insn (gen_thumb_eh_return (operands[0]));
10742 DONE;
10743 }"
10744)
10745
10746;; We can't expand this before we know where the link register is stored.
10747(define_insn_and_split "arm_eh_return"
10748 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
10749 VUNSPEC_EH_RETURN)
10750 (clobber (match_scratch:SI 1 "=&r"))]
10751 "TARGET_ARM"
10752 "#"
10753 "&& reload_completed"
10754 [(const_int 0)]
10755 "
10756 {
10757 arm_set_return_address (operands[0], operands[1]);
10758 DONE;
10759 }"
10760)
10761
f655717d 10762\f
10763;; TLS support
10764
10765(define_insn "load_tp_hard"
10766 [(set (match_operand:SI 0 "register_operand" "=r")
10767 (unspec:SI [(const_int 0)] UNSPEC_TLS))]
10768 "TARGET_HARD_TP"
10769 "mrc%?\\tp15, 0, %0, c13, c0, 3\\t@ load_tp_hard"
1b7da4ac 10770 [(set_attr "predicable" "yes")
4b5d7374 10771 (set_attr "type" "mrs")]
f655717d 10772)
10773
85fc66a7 10774;; Doesn't clobber R1-R3. Must use r0 for the first operand.
10775(define_insn "load_tp_soft_fdpic"
10776 [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
10777 (clobber (reg:SI FDPIC_REGNUM))
10778 (clobber (reg:SI LR_REGNUM))
10779 (clobber (reg:SI IP_REGNUM))
10780 (clobber (reg:CC CC_REGNUM))]
10781 "TARGET_SOFT_TP && TARGET_FDPIC"
10782 "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
10783 [(set_attr "conds" "clob")
10784 (set_attr "type" "branch")]
10785)
10786
f655717d 10787;; Doesn't clobber R1-R3. Must use r0 for the first operand.
10788(define_insn "load_tp_soft"
10789 [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
10790 (clobber (reg:SI LR_REGNUM))
10791 (clobber (reg:SI IP_REGNUM))
10792 (clobber (reg:CC CC_REGNUM))]
85fc66a7 10793 "TARGET_SOFT_TP && !TARGET_FDPIC"
f655717d 10794 "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
1b7da4ac 10795 [(set_attr "conds" "clob")
10796 (set_attr "type" "branch")]
f655717d 10797)
10798
f41e4452 10799;; tls descriptor call
10800(define_insn "tlscall"
10801 [(set (reg:SI R0_REGNUM)
10802 (unspec:SI [(reg:SI R0_REGNUM)
10803 (match_operand:SI 0 "" "X")
10804 (match_operand 1 "" "")] UNSPEC_TLS))
10805 (clobber (reg:SI R1_REGNUM))
10806 (clobber (reg:SI LR_REGNUM))
10807 (clobber (reg:SI CC_REGNUM))]
10808 "TARGET_GNU2_TLS"
10809 {
10810 targetm.asm_out.internal_label (asm_out_file, "LPIC",
10811 INTVAL (operands[1]));
10812 return "bl\\t%c0(tlscall)";
10813 }
10814 [(set_attr "conds" "clob")
1b7da4ac 10815 (set_attr "length" "4")
10816 (set_attr "type" "branch")]
f41e4452 10817)
10818
1fe0edab 10819;; For thread pointer builtin
10820(define_expand "get_thread_pointersi"
3934ae0e 10821 [(match_operand:SI 0 "s_register_operand")]
1fe0edab 10822 ""
10823 "
10824 {
10825 arm_load_tp (operands[0]);
10826 DONE;
10827 }")
10828
f41e4452 10829;;
10830
aabe09ac 10831;; We only care about the lower 16 bits of the constant
10832;; being inserted into the upper 16 bits of the register.
eca5c984 10833(define_insn "*arm_movtas_ze"
417e5cc5 10834 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r,r")
eca5c984 10835 (const_int 16)
10836 (const_int 16))
10837 (match_operand:SI 1 "const_int_operand" ""))]
60a48e7d 10838 "TARGET_HAVE_MOVT"
417e5cc5 10839 "@
10840 movt%?\t%0, %L1
10841 movt\t%0, %L1"
10842 [(set_attr "arch" "32,v8mb")
10843 (set_attr "predicable" "yes")
1b7da4ac 10844 (set_attr "length" "4")
282b4c75 10845 (set_attr "type" "alu_sreg")]
eca5c984 10846)
10847
c0fc3696 10848(define_insn "*arm_rev"
a486b499 10849 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
10850 (bswap:SI (match_operand:SI 1 "s_register_operand" "l,l,r")))]
10851 "arm_arch6"
10852 "@
10853 rev\t%0, %1
10854 rev%?\t%0, %1
10855 rev%?\t%0, %1"
10856 [(set_attr "arch" "t1,t2,32")
1b7da4ac 10857 (set_attr "length" "2,2,4")
4a510717 10858 (set_attr "predicable" "no,yes,yes")
1b7da4ac 10859 (set_attr "type" "rev")]
ff82f757 10860)
10861
10862(define_expand "arm_legacy_rev"
3934ae0e 10863 [(set (match_operand:SI 2 "s_register_operand")
10864 (xor:SI (rotatert:SI (match_operand:SI 1 "s_register_operand")
ff82f757 10865 (const_int 16))
10866 (match_dup 1)))
10867 (set (match_dup 2)
10868 (lshiftrt:SI (match_dup 2)
10869 (const_int 8)))
3934ae0e 10870 (set (match_operand:SI 3 "s_register_operand")
ff82f757 10871 (rotatert:SI (match_dup 1)
10872 (const_int 8)))
10873 (set (match_dup 2)
10874 (and:SI (match_dup 2)
10875 (const_int -65281)))
3934ae0e 10876 (set (match_operand:SI 0 "s_register_operand")
ff82f757 10877 (xor:SI (match_dup 3)
10878 (match_dup 2)))]
10879 "TARGET_32BIT"
10880 ""
10881)
10882
10883;; Reuse temporaries to keep register pressure down.
10884(define_expand "thumb_legacy_rev"
3934ae0e 10885 [(set (match_operand:SI 2 "s_register_operand")
10886 (ashift:SI (match_operand:SI 1 "s_register_operand")
ff82f757 10887 (const_int 24)))
3934ae0e 10888 (set (match_operand:SI 3 "s_register_operand")
ff82f757 10889 (lshiftrt:SI (match_dup 1)
10890 (const_int 24)))
10891 (set (match_dup 3)
10892 (ior:SI (match_dup 3)
10893 (match_dup 2)))
3934ae0e 10894 (set (match_operand:SI 4 "s_register_operand")
ff82f757 10895 (const_int 16))
3934ae0e 10896 (set (match_operand:SI 5 "s_register_operand")
ff82f757 10897 (rotatert:SI (match_dup 1)
10898 (match_dup 4)))
10899 (set (match_dup 2)
10900 (ashift:SI (match_dup 5)
10901 (const_int 24)))
10902 (set (match_dup 5)
10903 (lshiftrt:SI (match_dup 5)
10904 (const_int 24)))
10905 (set (match_dup 5)
10906 (ior:SI (match_dup 5)
10907 (match_dup 2)))
10908 (set (match_dup 5)
10909 (rotatert:SI (match_dup 5)
10910 (match_dup 4)))
3934ae0e 10911 (set (match_operand:SI 0 "s_register_operand")
ff82f757 10912 (ior:SI (match_dup 5)
10913 (match_dup 3)))]
10914 "TARGET_THUMB"
10915 ""
10916)
10917
62e39b06 10918;; ARM-specific expansion of signed mod by power of 2
10919;; using conditional negate.
10920;; For r0 % n where n is a power of 2 produce:
10921;; rsbs r1, r0, #0
10922;; and r0, r0, #(n - 1)
10923;; and r1, r1, #(n - 1)
10924;; rsbpl r0, r1, #0
10925
10926(define_expand "modsi3"
3934ae0e 10927 [(match_operand:SI 0 "register_operand")
10928 (match_operand:SI 1 "register_operand")
10929 (match_operand:SI 2 "const_int_operand")]
62e39b06 10930 "TARGET_32BIT"
10931 {
10932 HOST_WIDE_INT val = INTVAL (operands[2]);
10933
10934 if (val <= 0
10935 || exact_log2 (val) <= 0)
10936 FAIL;
10937
10938 rtx mask = GEN_INT (val - 1);
10939
10940 /* In the special case of x0 % 2 we can do the even shorter:
10941 cmp r0, #0
10942 and r0, r0, #1
10943 rsblt r0, r0, #0. */
10944
10945 if (val == 2)
10946 {
10947 rtx cc_reg = arm_gen_compare_reg (LT,
10948 operands[1], const0_rtx, NULL_RTX);
10949 rtx cond = gen_rtx_LT (SImode, cc_reg, const0_rtx);
10950 rtx masked = gen_reg_rtx (SImode);
10951
10952 emit_insn (gen_andsi3 (masked, operands[1], mask));
10953 emit_move_insn (operands[0],
10954 gen_rtx_IF_THEN_ELSE (SImode, cond,
10955 gen_rtx_NEG (SImode,
10956 masked),
10957 masked));
10958 DONE;
10959 }
10960
10961 rtx neg_op = gen_reg_rtx (SImode);
10962 rtx_insn *insn = emit_insn (gen_subsi3_compare0 (neg_op, const0_rtx,
10963 operands[1]));
10964
10965 /* Extract the condition register and mode. */
10966 rtx cmp = XVECEXP (PATTERN (insn), 0, 0);
10967 rtx cc_reg = SET_DEST (cmp);
10968 rtx cond = gen_rtx_GE (SImode, cc_reg, const0_rtx);
10969
10970 emit_insn (gen_andsi3 (operands[0], operands[1], mask));
10971
10972 rtx masked_neg = gen_reg_rtx (SImode);
10973 emit_insn (gen_andsi3 (masked_neg, neg_op, mask));
10974
10975 /* We want a conditional negate here, but emitting COND_EXEC rtxes
10976 during expand does not always work. Do an IF_THEN_ELSE instead. */
10977 emit_move_insn (operands[0],
10978 gen_rtx_IF_THEN_ELSE (SImode, cond,
10979 gen_rtx_NEG (SImode, masked_neg),
10980 operands[0]));
10981
10982
10983 DONE;
10984 }
10985)
10986
ff82f757 10987(define_expand "bswapsi2"
3934ae0e 10988 [(set (match_operand:SI 0 "s_register_operand")
10989 (bswap:SI (match_operand:SI 1 "s_register_operand")))]
8d1af482 10990"TARGET_EITHER && (arm_arch6 || !optimize_size)"
ff82f757 10991"
8d1af482 10992 if (!arm_arch6)
10993 {
10994 rtx op2 = gen_reg_rtx (SImode);
10995 rtx op3 = gen_reg_rtx (SImode);
ff82f757 10996
8d1af482 10997 if (TARGET_THUMB)
10998 {
10999 rtx op4 = gen_reg_rtx (SImode);
11000 rtx op5 = gen_reg_rtx (SImode);
ff82f757 11001
8d1af482 11002 emit_insn (gen_thumb_legacy_rev (operands[0], operands[1],
11003 op2, op3, op4, op5));
11004 }
11005 else
11006 {
11007 emit_insn (gen_arm_legacy_rev (operands[0], operands[1],
11008 op2, op3));
11009 }
ff82f757 11010
8d1af482 11011 DONE;
11012 }
ff82f757 11013 "
11014)
11015
a486b499 11016;; bswap16 patterns: use revsh and rev16 instructions for the signed
11017;; and unsigned variants, respectively. For rev16, expose
11018;; byte-swapping in the lower 16 bits only.
11019(define_insn "*arm_revsh"
11020 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
11021 (sign_extend:SI (bswap:HI (match_operand:HI 1 "s_register_operand" "l,l,r"))))]
11022 "arm_arch6"
11023 "@
11024 revsh\t%0, %1
11025 revsh%?\t%0, %1
11026 revsh%?\t%0, %1"
11027 [(set_attr "arch" "t1,t2,32")
1b7da4ac 11028 (set_attr "length" "2,2,4")
11029 (set_attr "type" "rev")]
a486b499 11030)
11031
11032(define_insn "*arm_rev16"
11033 [(set (match_operand:HI 0 "s_register_operand" "=l,l,r")
11034 (bswap:HI (match_operand:HI 1 "s_register_operand" "l,l,r")))]
11035 "arm_arch6"
11036 "@
11037 rev16\t%0, %1
11038 rev16%?\t%0, %1
11039 rev16%?\t%0, %1"
11040 [(set_attr "arch" "t1,t2,32")
1b7da4ac 11041 (set_attr "length" "2,2,4")
11042 (set_attr "type" "rev")]
09f69e55 11043)
11044
11045;; There are no canonicalisation rules for the position of the lshiftrt, ashift
11046;; operations within an IOR/AND RTX, therefore we have two patterns matching
11047;; each valid permutation.
11048
11049(define_insn "arm_rev16si2"
11050 [(set (match_operand:SI 0 "register_operand" "=l,l,r")
11051 (ior:SI (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "l,l,r")
11052 (const_int 8))
11053 (match_operand:SI 3 "const_int_operand" "n,n,n"))
11054 (and:SI (lshiftrt:SI (match_dup 1)
11055 (const_int 8))
11056 (match_operand:SI 2 "const_int_operand" "n,n,n"))))]
11057 "arm_arch6
11058 && aarch_rev16_shleft_mask_imm_p (operands[3], SImode)
11059 && aarch_rev16_shright_mask_imm_p (operands[2], SImode)"
11060 "rev16\\t%0, %1"
11061 [(set_attr "arch" "t1,t2,32")
11062 (set_attr "length" "2,2,4")
11063 (set_attr "type" "rev")]
11064)
11065
11066(define_insn "arm_rev16si2_alt"
11067 [(set (match_operand:SI 0 "register_operand" "=l,l,r")
11068 (ior:SI (and:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,l,r")
11069 (const_int 8))
11070 (match_operand:SI 2 "const_int_operand" "n,n,n"))
11071 (and:SI (ashift:SI (match_dup 1)
11072 (const_int 8))
11073 (match_operand:SI 3 "const_int_operand" "n,n,n"))))]
11074 "arm_arch6
11075 && aarch_rev16_shleft_mask_imm_p (operands[3], SImode)
11076 && aarch_rev16_shright_mask_imm_p (operands[2], SImode)"
11077 "rev16\\t%0, %1"
11078 [(set_attr "arch" "t1,t2,32")
11079 (set_attr "length" "2,2,4")
11080 (set_attr "type" "rev")]
a486b499 11081)
11082
11083(define_expand "bswaphi2"
3934ae0e 11084 [(set (match_operand:HI 0 "s_register_operand")
11085 (bswap:HI (match_operand:HI 1 "s_register_operand")))]
a486b499 11086"arm_arch6"
11087""
11088)
11089
1653cf17 11090;; Patterns for LDRD/STRD in Thumb2 mode
11091
11092(define_insn "*thumb2_ldrd"
11093 [(set (match_operand:SI 0 "s_register_operand" "=r")
11094 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
11095 (match_operand:SI 2 "ldrd_strd_offset_operand" "Do"))))
11096 (set (match_operand:SI 3 "s_register_operand" "=r")
11097 (mem:SI (plus:SI (match_dup 1)
11098 (match_operand:SI 4 "const_int_operand" ""))))]
11099 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
1653cf17 11100 && ((INTVAL (operands[2]) + 4) == INTVAL (operands[4]))
11101 && (operands_ok_ldrd_strd (operands[0], operands[3],
11102 operands[1], INTVAL (operands[2]),
11103 false, true))"
11104 "ldrd%?\t%0, %3, [%1, %2]"
9f2c2a36 11105 [(set_attr "type" "load_8")
8bdfd6ed 11106 (set_attr "predicable" "yes")])
1653cf17 11107
11108(define_insn "*thumb2_ldrd_base"
11109 [(set (match_operand:SI 0 "s_register_operand" "=r")
11110 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
11111 (set (match_operand:SI 2 "s_register_operand" "=r")
11112 (mem:SI (plus:SI (match_dup 1)
11113 (const_int 4))))]
11114 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
1653cf17 11115 && (operands_ok_ldrd_strd (operands[0], operands[2],
11116 operands[1], 0, false, true))"
11117 "ldrd%?\t%0, %2, [%1]"
9f2c2a36 11118 [(set_attr "type" "load_8")
8bdfd6ed 11119 (set_attr "predicable" "yes")])
1653cf17 11120
11121(define_insn "*thumb2_ldrd_base_neg"
11122 [(set (match_operand:SI 0 "s_register_operand" "=r")
11123 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
11124 (const_int -4))))
11125 (set (match_operand:SI 2 "s_register_operand" "=r")
11126 (mem:SI (match_dup 1)))]
11127 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
1653cf17 11128 && (operands_ok_ldrd_strd (operands[0], operands[2],
11129 operands[1], -4, false, true))"
11130 "ldrd%?\t%0, %2, [%1, #-4]"
9f2c2a36 11131 [(set_attr "type" "load_8")
8bdfd6ed 11132 (set_attr "predicable" "yes")])
1653cf17 11133
11134(define_insn "*thumb2_strd"
11135 [(set (mem:SI (plus:SI (match_operand:SI 0 "s_register_operand" "rk")
11136 (match_operand:SI 1 "ldrd_strd_offset_operand" "Do")))
11137 (match_operand:SI 2 "s_register_operand" "r"))
11138 (set (mem:SI (plus:SI (match_dup 0)
11139 (match_operand:SI 3 "const_int_operand" "")))
11140 (match_operand:SI 4 "s_register_operand" "r"))]
11141 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
1653cf17 11142 && ((INTVAL (operands[1]) + 4) == INTVAL (operands[3]))
11143 && (operands_ok_ldrd_strd (operands[2], operands[4],
11144 operands[0], INTVAL (operands[1]),
11145 false, false))"
11146 "strd%?\t%2, %4, [%0, %1]"
9f2c2a36 11147 [(set_attr "type" "store_8")
8bdfd6ed 11148 (set_attr "predicable" "yes")])
1653cf17 11149
11150(define_insn "*thumb2_strd_base"
11151 [(set (mem:SI (match_operand:SI 0 "s_register_operand" "rk"))
11152 (match_operand:SI 1 "s_register_operand" "r"))
11153 (set (mem:SI (plus:SI (match_dup 0)
11154 (const_int 4)))
11155 (match_operand:SI 2 "s_register_operand" "r"))]
11156 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
1653cf17 11157 && (operands_ok_ldrd_strd (operands[1], operands[2],
11158 operands[0], 0, false, false))"
11159 "strd%?\t%1, %2, [%0]"
9f2c2a36 11160 [(set_attr "type" "store_8")
8bdfd6ed 11161 (set_attr "predicable" "yes")])
1653cf17 11162
11163(define_insn "*thumb2_strd_base_neg"
11164 [(set (mem:SI (plus:SI (match_operand:SI 0 "s_register_operand" "rk")
11165 (const_int -4)))
11166 (match_operand:SI 1 "s_register_operand" "r"))
11167 (set (mem:SI (match_dup 0))
11168 (match_operand:SI 2 "s_register_operand" "r"))]
11169 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
1653cf17 11170 && (operands_ok_ldrd_strd (operands[1], operands[2],
11171 operands[0], -4, false, false))"
11172 "strd%?\t%1, %2, [%0, #-4]"
9f2c2a36 11173 [(set_attr "type" "store_8")
8bdfd6ed 11174 (set_attr "predicable" "yes")])
1653cf17 11175
2a0c73f2 11176;; ARMv8 CRC32 instructions.
8656245d 11177(define_insn "arm_<crc_variant>"
2a0c73f2 11178 [(set (match_operand:SI 0 "s_register_operand" "=r")
11179 (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")
11180 (match_operand:<crc_mode> 2 "s_register_operand" "r")]
11181 CRC))]
11182 "TARGET_CRC32"
11183 "<crc_variant>\\t%0, %1, %2"
11184 [(set_attr "type" "crc")
11185 (set_attr "conds" "unconditional")]
11186)
1653cf17 11187
353cf59a 11188;; Load the load/store double peephole optimizations.
11189(include "ldrdstrd.md")
11190
320ea44d 11191;; Load the load/store multiple patterns
11192(include "ldmstm.md")
426be8c5 11193
11194;; Patterns in ldmstm.md don't cover more than 4 registers. This pattern covers
11195;; large lists without explicit writeback generated for APCS_FRAME epilogue.
3873efff 11196;; The operands are validated through the load_multiple_operation
11197;; match_parallel predicate rather than through constraints so enable it only
11198;; after reload.
426be8c5 11199(define_insn "*load_multiple"
11200 [(match_parallel 0 "load_multiple_operation"
11201 [(set (match_operand:SI 2 "s_register_operand" "=rk")
11202 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
11203 ])]
3873efff 11204 "TARGET_32BIT && reload_completed"
426be8c5 11205 "*
11206 {
11207 arm_output_multireg_pop (operands, /*return_pc=*/false,
11208 /*cond=*/const_true_rtx,
11209 /*reverse=*/false,
11210 /*update=*/false);
11211 return \"\";
11212 }
11213 "
11214 [(set_attr "predicable" "yes")]
11215)
11216
84450ddc 11217(define_expand "copysignsf3"
11218 [(match_operand:SF 0 "register_operand")
11219 (match_operand:SF 1 "register_operand")
11220 (match_operand:SF 2 "register_operand")]
11221 "TARGET_SOFT_FLOAT && arm_arch_thumb2"
11222 "{
11223 emit_move_insn (operands[0], operands[2]);
11224 emit_insn (gen_insv_t2 (simplify_gen_subreg (SImode, operands[0], SFmode, 0),
11225 GEN_INT (31), GEN_INT (0),
11226 simplify_gen_subreg (SImode, operands[1], SFmode, 0)));
11227 DONE;
11228 }"
11229)
11230
11231(define_expand "copysigndf3"
11232 [(match_operand:DF 0 "register_operand")
11233 (match_operand:DF 1 "register_operand")
11234 (match_operand:DF 2 "register_operand")]
11235 "TARGET_SOFT_FLOAT && arm_arch_thumb2"
11236 "{
11237 rtx op0_low = gen_lowpart (SImode, operands[0]);
11238 rtx op0_high = gen_highpart (SImode, operands[0]);
11239 rtx op1_low = gen_lowpart (SImode, operands[1]);
11240 rtx op1_high = gen_highpart (SImode, operands[1]);
11241 rtx op2_high = gen_highpart (SImode, operands[2]);
11242
11243 rtx scratch1 = gen_reg_rtx (SImode);
11244 rtx scratch2 = gen_reg_rtx (SImode);
11245 emit_move_insn (scratch1, op2_high);
11246 emit_move_insn (scratch2, op1_high);
11247
d1f9b275 11248 emit_insn(gen_rtx_SET(scratch1,
84450ddc 11249 gen_rtx_LSHIFTRT (SImode, op2_high, GEN_INT(31))));
11250 emit_insn(gen_insv_t2(scratch2, GEN_INT(1), GEN_INT(31), scratch1));
11251 emit_move_insn (op0_low, op1_low);
11252 emit_move_insn (op0_high, scratch2);
11253
11254 DONE;
11255 }"
11256)
11257
115857ef 11258;; movmisalign patterns for HImode and SImode.
11259(define_expand "movmisalign<mode>"
11260 [(match_operand:HSI 0 "general_operand")
11261 (match_operand:HSI 1 "general_operand")]
11262 "unaligned_access"
11263{
11264 /* This pattern is not permitted to fail during expansion: if both arguments
11265 are non-registers (e.g. memory := constant), force operand 1 into a
11266 register. */
11267 rtx (* gen_unaligned_load)(rtx, rtx);
11268 rtx tmp_dest = operands[0];
11269 if (!s_register_operand (operands[0], <MODE>mode)
11270 && !s_register_operand (operands[1], <MODE>mode))
11271 operands[1] = force_reg (<MODE>mode, operands[1]);
11272
11273 if (<MODE>mode == HImode)
11274 {
11275 gen_unaligned_load = gen_unaligned_loadhiu;
11276 tmp_dest = gen_reg_rtx (SImode);
11277 }
11278 else
11279 gen_unaligned_load = gen_unaligned_loadsi;
11280
11281 if (MEM_P (operands[1]))
11282 {
11283 emit_insn (gen_unaligned_load (tmp_dest, operands[1]));
11284 if (<MODE>mode == HImode)
11285 emit_move_insn (operands[0], gen_lowpart (HImode, tmp_dest));
11286 }
11287 else
11288 emit_insn (gen_unaligned_store<mode> (operands[0], operands[1]));
11289
11290 DONE;
11291})
11292
8656245d 11293(define_insn "arm_<cdp>"
1be6395a 11294 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "n")
11295 (match_operand:SI 1 "immediate_operand" "n")
11296 (match_operand:SI 2 "immediate_operand" "n")
11297 (match_operand:SI 3 "immediate_operand" "n")
11298 (match_operand:SI 4 "immediate_operand" "n")
11299 (match_operand:SI 5 "immediate_operand" "n")] CDPI)]
11300 "arm_coproc_builtin_available (VUNSPEC_<CDP>)"
11301{
11302 arm_const_bounds (operands[0], 0, 16);
11303 arm_const_bounds (operands[1], 0, 16);
11304 arm_const_bounds (operands[2], 0, (1 << 5));
11305 arm_const_bounds (operands[3], 0, (1 << 5));
11306 arm_const_bounds (operands[4], 0, (1 << 5));
11307 arm_const_bounds (operands[5], 0, 8);
11308 return "<cdp>\\tp%c0, %1, CR%c2, CR%c3, CR%c4, %5";
11309}
11310 [(set_attr "length" "4")
11311 (set_attr "type" "coproc")])
11312
638b44bd 11313(define_insn "*ldc"
11314 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "n")
11315 (match_operand:SI 1 "immediate_operand" "n")
11316 (match_operand:SI 2 "memory_operand" "Uz")] LDCI)]
11317 "arm_coproc_builtin_available (VUNSPEC_<LDC>)"
11318{
11319 arm_const_bounds (operands[0], 0, 16);
11320 arm_const_bounds (operands[1], 0, (1 << 5));
11321 return "<ldc>\\tp%c0, CR%c1, %2";
11322}
11323 [(set_attr "length" "4")
11324 (set_attr "type" "coproc")])
11325
11326(define_insn "*stc"
11327 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "n")
11328 (match_operand:SI 1 "immediate_operand" "n")
11329 (match_operand:SI 2 "memory_operand" "=Uz")] STCI)]
11330 "arm_coproc_builtin_available (VUNSPEC_<STC>)"
11331{
11332 arm_const_bounds (operands[0], 0, 16);
11333 arm_const_bounds (operands[1], 0, (1 << 5));
11334 return "<stc>\\tp%c0, CR%c1, %2";
11335}
11336 [(set_attr "length" "4")
11337 (set_attr "type" "coproc")])
11338
8656245d 11339(define_expand "arm_<ldc>"
638b44bd 11340 [(unspec_volatile [(match_operand:SI 0 "immediate_operand")
11341 (match_operand:SI 1 "immediate_operand")
11342 (mem:SI (match_operand:SI 2 "s_register_operand"))] LDCI)]
11343 "arm_coproc_builtin_available (VUNSPEC_<LDC>)")
11344
8656245d 11345(define_expand "arm_<stc>"
638b44bd 11346 [(unspec_volatile [(match_operand:SI 0 "immediate_operand")
11347 (match_operand:SI 1 "immediate_operand")
11348 (mem:SI (match_operand:SI 2 "s_register_operand"))] STCI)]
11349 "arm_coproc_builtin_available (VUNSPEC_<STC>)")
11350
8656245d 11351(define_insn "arm_<mcr>"
415e9b1f 11352 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "n")
11353 (match_operand:SI 1 "immediate_operand" "n")
11354 (match_operand:SI 2 "s_register_operand" "r")
11355 (match_operand:SI 3 "immediate_operand" "n")
11356 (match_operand:SI 4 "immediate_operand" "n")
11357 (match_operand:SI 5 "immediate_operand" "n")] MCRI)
11358 (use (match_dup 2))]
11359 "arm_coproc_builtin_available (VUNSPEC_<MCR>)"
11360{
11361 arm_const_bounds (operands[0], 0, 16);
11362 arm_const_bounds (operands[1], 0, 8);
11363 arm_const_bounds (operands[3], 0, (1 << 5));
11364 arm_const_bounds (operands[4], 0, (1 << 5));
11365 arm_const_bounds (operands[5], 0, 8);
11366 return "<mcr>\\tp%c0, %1, %2, CR%c3, CR%c4, %5";
11367}
11368 [(set_attr "length" "4")
11369 (set_attr "type" "coproc")])
11370
8656245d 11371(define_insn "arm_<mrc>"
415e9b1f 11372 [(set (match_operand:SI 0 "s_register_operand" "=r")
6f8d7784 11373 (unspec_volatile:SI [(match_operand:SI 1 "immediate_operand" "n")
415e9b1f 11374 (match_operand:SI 2 "immediate_operand" "n")
11375 (match_operand:SI 3 "immediate_operand" "n")
11376 (match_operand:SI 4 "immediate_operand" "n")
11377 (match_operand:SI 5 "immediate_operand" "n")] MRCI))]
11378 "arm_coproc_builtin_available (VUNSPEC_<MRC>)"
11379{
11380 arm_const_bounds (operands[1], 0, 16);
11381 arm_const_bounds (operands[2], 0, 8);
11382 arm_const_bounds (operands[3], 0, (1 << 5));
11383 arm_const_bounds (operands[4], 0, (1 << 5));
11384 arm_const_bounds (operands[5], 0, 8);
11385 return "<mrc>\\tp%c1, %2, %0, CR%c3, CR%c4, %5";
11386}
11387 [(set_attr "length" "4")
11388 (set_attr "type" "coproc")])
11389
8656245d 11390(define_insn "arm_<mcrr>"
cabfd710 11391 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "n")
11392 (match_operand:SI 1 "immediate_operand" "n")
11393 (match_operand:DI 2 "s_register_operand" "r")
11394 (match_operand:SI 3 "immediate_operand" "n")] MCRRI)
11395 (use (match_dup 2))]
11396 "arm_coproc_builtin_available (VUNSPEC_<MCRR>)"
11397{
11398 arm_const_bounds (operands[0], 0, 16);
11399 arm_const_bounds (operands[1], 0, 8);
11400 arm_const_bounds (operands[3], 0, (1 << 5));
11401 return "<mcrr>\\tp%c0, %1, %Q2, %R2, CR%c3";
11402}
11403 [(set_attr "length" "4")
11404 (set_attr "type" "coproc")])
11405
8656245d 11406(define_insn "arm_<mrrc>"
cabfd710 11407 [(set (match_operand:DI 0 "s_register_operand" "=r")
6f8d7784 11408 (unspec_volatile:DI [(match_operand:SI 1 "immediate_operand" "n")
cabfd710 11409 (match_operand:SI 2 "immediate_operand" "n")
11410 (match_operand:SI 3 "immediate_operand" "n")] MRRCI))]
11411 "arm_coproc_builtin_available (VUNSPEC_<MRRC>)"
11412{
11413 arm_const_bounds (operands[1], 0, 16);
11414 arm_const_bounds (operands[2], 0, 8);
11415 arm_const_bounds (operands[3], 0, (1 << 5));
11416 return "<mrrc>\\tp%c1, %2, %Q0, %R0, CR%c3";
11417}
11418 [(set_attr "length" "4")
11419 (set_attr "type" "coproc")])
11420
be626997 11421(define_expand "speculation_barrier"
11422 [(unspec_volatile [(const_int 0)] VUNSPEC_SPECULATION_BARRIER)]
11423 "TARGET_EITHER"
11424 "
a7852b35 11425 /* For thumb1 (except Armv8 derivatives), and for pre-Armv7 we don't
11426 have a usable barrier (and probably don't need one in practice).
11427 But to be safe if such code is run on later architectures, call a
11428 helper function in libgcc that will do the thing for the active
11429 system. */
11430 if (!(arm_arch7 || arm_arch8))
11431 {
11432 arm_emit_speculation_barrier_function ();
11433 DONE;
11434 }
be626997 11435 "
11436)
11437
11438;; Generate a hard speculation barrier when we have not enabled speculation
11439;; tracking.
11440(define_insn "*speculation_barrier_insn"
11441 [(unspec_volatile [(const_int 0)] VUNSPEC_SPECULATION_BARRIER)]
a7852b35 11442 "arm_arch7 || arm_arch8"
be626997 11443 "isb\;dsb\\tsy"
11444 [(set_attr "type" "block")
11445 (set_attr "length" "8")]
11446)
11447
d98a3884 11448;; Vector bits common to IWMMXT and Neon
11449(include "vec-common.md")
755eb2b4 11450;; Load the Intel Wireless Multimedia Extension patterns
11451(include "iwmmxt.md")
a2cd141b 11452;; Load the VFP co-processor patterns
11453(include "vfp.md")
bc360af8 11454;; Thumb-1 patterns
11455(include "thumb1.md")
25f905c2 11456;; Thumb-2 patterns
11457(include "thumb2.md")
d98a3884 11458;; Neon patterns
11459(include "neon.md")
e84fdf6e 11460;; Crypto patterns
11461(include "crypto.md")
06df6b17 11462;; Synchronization Primitives
11463(include "sync.md")
bbbe4599 11464;; Fixed-point patterns
11465(include "arm-fixed.md")