]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/arm/arm.md
Tighten syntax checking for OpenACC routine construct in C
[thirdparty/gcc.git] / gcc / config / arm / arm.md
CommitLineData
129a2fe4 1;;- Machine description for ARM for GNU compiler
f1717362 2;; Copyright (C) 1991-2016 Free Software Foundation, Inc.
b11cae9e 3;; Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
f082f1c4 4;; and Martin Simmons (@harleqn.co.uk).
129a2fe4 5;; More major hacks by Richard Earnshaw (rearnsha@arm.com).
b11cae9e 6
acf6ed70 7;; This file is part of GCC.
b11cae9e 8
acf6ed70 9;; GCC is free software; you can redistribute it and/or modify it
10;; under the terms of the GNU General Public License as published
038d1e19 11;; by the Free Software Foundation; either version 3, or (at your
acf6ed70 12;; option) any later version.
b11cae9e 13
acf6ed70 14;; GCC is distributed in the hope that it will be useful, but WITHOUT
15;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
17;; License for more details.
b11cae9e 18
19;; You should have received a copy of the GNU General Public License
038d1e19 20;; along with GCC; see the file COPYING3. If not see
21;; <http://www.gnu.org/licenses/>.
b11cae9e 22
23;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
24
9c08d1fa 25\f
e1159bbe 26;;---------------------------------------------------------------------------
27;; Constants
28
bffbb863 29;; Register numbers -- All machine registers should be defined here
e1159bbe 30(define_constants
bffbb863 31 [(R0_REGNUM 0) ; First CORE register
32 (R1_REGNUM 1) ; Second CORE register
33 (IP_REGNUM 12) ; Scratch register
34 (SP_REGNUM 13) ; Stack pointer
35 (LR_REGNUM 14) ; Return address register
36 (PC_REGNUM 15) ; Program counter
37 (LAST_ARM_REGNUM 15) ;
38 (CC_REGNUM 100) ; Condition code pseudo register
39 (VFPCC_REGNUM 101) ; VFP Condition code pseudo register
e1159bbe 40 ]
41)
3c5afce6 42;; 3rd operand to select_dominance_cc_mode
43(define_constants
44 [(DOM_CC_X_AND_Y 0)
45 (DOM_CC_NX_OR_Y 1)
46 (DOM_CC_X_OR_Y 2)
47 ]
48)
2ff91fec 49;; conditional compare combination
50(define_constants
51 [(CMP_CMP 0)
52 (CMN_CMP 1)
53 (CMP_CMN 2)
54 (CMN_CMN 3)
55 (NUM_OF_COND_CMP 4)
56 ]
57)
e1159bbe 58
b11cae9e 59\f
e1159bbe 60;;---------------------------------------------------------------------------
9c08d1fa 61;; Attributes
62
a651f34d 63;; Processor type. This is created automatically from arm-cores.def.
64(include "arm-tune.md")
65
861033d5 66;; Instruction classification types
67(include "types.md")
68
215b30b3 69; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
70; generating ARM code. This is used to control the length of some insn
71; patterns that share the same RTL in both ARM and Thumb code.
8724f216 72(define_attr "is_thumb" "yes,no"
73 (const (if_then_else (symbol_ref "TARGET_THUMB")
74 (const_string "yes") (const_string "no"))))
cffb2a26 75
ef51b8e1 76; IS_ARCH6 is set to 'yes' when we are generating code form ARMv6.
77(define_attr "is_arch6" "no,yes" (const (symbol_ref "arm_arch6")))
78
747b7458 79; IS_THUMB1 is set to 'yes' iff we are generating Thumb-1 code.
8724f216 80(define_attr "is_thumb1" "yes,no"
81 (const (if_then_else (symbol_ref "TARGET_THUMB1")
82 (const_string "yes") (const_string "no"))))
747b7458 83
c7a58118 84; We use this attribute to disable alternatives that can produce 32-bit
85; instructions inside an IT-block in Thumb2 state. ARMv8 deprecates IT blocks
86; that contain 32-bit instructions.
87(define_attr "enabled_for_depr_it" "no,yes" (const_string "yes"))
88
89; This attribute is used to disable a predicated alternative when we have
90; arm_restrict_it.
91(define_attr "predicable_short_it" "no,yes" (const_string "yes"))
92
331beb1a 93;; Operand number of an input operand that is shifted. Zero if the
94;; given instruction does not shift one of its input operands.
331beb1a 95(define_attr "shift" "" (const_int 0))
96
55a94dda 97;; [For compatibility with AArch64 in pipeline models]
98;; Attribute that specifies whether or not the instruction touches fp
99;; registers.
100(define_attr "fp" "no,yes" (const_string "no"))
101
3d91c5d6 102; Floating Point Unit. If we only have floating point emulation, then there
103; is no point in scheduling the floating point insns. (Well, for best
104; performance we should try and group them together).
bffbb863 105(define_attr "fpu" "none,vfp"
c7f506fd 106 (const (symbol_ref "arm_fpu_attr")))
3d91c5d6 107
b2bcff19 108; Predicated means that the insn form is conditionally executed based on a
109; predicate. We default to 'no' because no Thumb patterns match this rule
110; and not all ARM insns do.
c7a58118 111(define_attr "predicated" "yes,no" (const_string "no"))
112
094e994f 113; LENGTH of an instruction (in bytes)
06df6b17 114(define_attr "length" ""
e1b93706 115 (const_int 4))
9c08d1fa 116
d5d4dc8d 117; The architecture which supports the instruction (or alternative).
118; This can be "a" for ARM, "t" for either of the Thumbs, "32" for
119; TARGET_32BIT, "t1" or "t2" to specify a specific Thumb mode. "v6"
120; for ARM or Thumb-2 with arm_arch6, and nov6 for ARM without
e4585731 121; arm_arch6. "v6t2" for Thumb-2 with arm_arch6. This attribute is
122; used to compute attribute "enabled", use type "any" to enable an
123; alternative in all cases.
ac876af5 124(define_attr "arch" "any,a,t,32,t1,t2,v6,nov6,v6t2,neon_for_64bits,avoid_neon_for_64bits,iwmmxt,iwmmxt2,armv6_or_vfpv3,neon"
d5d4dc8d 125 (const_string "any"))
126
127(define_attr "arch_enabled" "no,yes"
128 (cond [(eq_attr "arch" "any")
129 (const_string "yes")
130
131 (and (eq_attr "arch" "a")
0bf497f5 132 (match_test "TARGET_ARM"))
d5d4dc8d 133 (const_string "yes")
134
135 (and (eq_attr "arch" "t")
0bf497f5 136 (match_test "TARGET_THUMB"))
d5d4dc8d 137 (const_string "yes")
138
139 (and (eq_attr "arch" "t1")
0bf497f5 140 (match_test "TARGET_THUMB1"))
d5d4dc8d 141 (const_string "yes")
142
143 (and (eq_attr "arch" "t2")
0bf497f5 144 (match_test "TARGET_THUMB2"))
d5d4dc8d 145 (const_string "yes")
146
147 (and (eq_attr "arch" "32")
0bf497f5 148 (match_test "TARGET_32BIT"))
d5d4dc8d 149 (const_string "yes")
150
151 (and (eq_attr "arch" "v6")
0bf497f5 152 (match_test "TARGET_32BIT && arm_arch6"))
d5d4dc8d 153 (const_string "yes")
154
155 (and (eq_attr "arch" "nov6")
0bf497f5 156 (match_test "TARGET_32BIT && !arm_arch6"))
a651f34d 157 (const_string "yes")
158
e4585731 159 (and (eq_attr "arch" "v6t2")
160 (match_test "TARGET_32BIT && arm_arch6 && arm_arch_thumb2"))
161 (const_string "yes")
162
b6779ddc 163 (and (eq_attr "arch" "avoid_neon_for_64bits")
164 (match_test "TARGET_NEON")
165 (not (match_test "TARGET_PREFER_NEON_64BITS")))
a651f34d 166 (const_string "yes")
167
b6779ddc 168 (and (eq_attr "arch" "neon_for_64bits")
169 (match_test "TARGET_NEON")
170 (match_test "TARGET_PREFER_NEON_64BITS"))
6b8f7c28 171 (const_string "yes")
172
173 (and (eq_attr "arch" "iwmmxt2")
174 (match_test "TARGET_REALLY_IWMMXT2"))
21cc9773 175 (const_string "yes")
176
177 (and (eq_attr "arch" "armv6_or_vfpv3")
178 (match_test "arm_arch6 || TARGET_VFP3"))
179 (const_string "yes")
ac876af5 180
181 (and (eq_attr "arch" "neon")
182 (match_test "TARGET_NEON"))
183 (const_string "yes")
21cc9773 184 ]
6b8f7c28 185
d5d4dc8d 186 (const_string "no")))
187
aa06c51c 188(define_attr "opt" "any,speed,size"
189 (const_string "any"))
190
191(define_attr "opt_enabled" "no,yes"
192 (cond [(eq_attr "opt" "any")
193 (const_string "yes")
194
195 (and (eq_attr "opt" "speed")
196 (match_test "optimize_function_for_speed_p (cfun)"))
197 (const_string "yes")
198
199 (and (eq_attr "opt" "size")
200 (match_test "optimize_function_for_size_p (cfun)"))
201 (const_string "yes")]
202 (const_string "no")))
203
861033d5 204(define_attr "use_literal_pool" "no,yes"
205 (cond [(and (eq_attr "type" "f_loads,f_loadd")
206 (match_test "CONSTANT_P (operands[1])"))
207 (const_string "yes")]
208 (const_string "no")))
209
d5d4dc8d 210; Enable all alternatives that are both arch_enabled and insn_enabled.
951a3f72 211; FIXME:: opt_enabled has been temporarily removed till the time we have
212; an attribute that allows the use of such alternatives.
213; This depends on caching of speed_p, size_p on a per
214; alternative basis. The problem is that the enabled attribute
215; cannot depend on any state that is not cached or is not constant
216; for a compilation unit. We probably need a generic "hot/cold"
217; alternative which if implemented can help with this. We disable this
218; until such a time as this is implemented and / or the improvements or
219; regressions with removing this attribute are double checked.
220; See ashldi3_neon and <shift>di3_neon in neon.md.
221
93b431d9 222 (define_attr "enabled" "no,yes"
0abea32c 223 (cond [(and (eq_attr "predicable_short_it" "no")
c7a58118 224 (and (eq_attr "predicated" "yes")
225 (match_test "arm_restrict_it")))
226 (const_string "no")
227
228 (and (eq_attr "enabled_for_depr_it" "no")
229 (match_test "arm_restrict_it"))
230 (const_string "no")
231
861033d5 232 (and (eq_attr "use_literal_pool" "yes")
233 (match_test "arm_disable_literal_pool"))
234 (const_string "no")
235
aa06c51c 236 (eq_attr "arch_enabled" "no")
aa06c51c 237 (const_string "no")]
238 (const_string "yes")))
d5d4dc8d 239
56d27660 240; POOL_RANGE is how far away from a constant pool entry that this insn
241; can be placed. If the distance is zero, then this insn will never
242; reference the pool.
42e1de19 243; Note that for Thumb constant pools the PC value is rounded down to the
244; nearest multiple of four. Therefore, THUMB2_POOL_RANGE (and POOL_RANGE for
245; Thumb insns) should be set to <max_range> - 2.
cffb2a26 246; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
8848d797 247; before its address. It is set to <max_range> - (8 + <data_size>).
cde1623a 248(define_attr "arm_pool_range" "" (const_int 0))
249(define_attr "thumb2_pool_range" "" (const_int 0))
250(define_attr "arm_neg_pool_range" "" (const_int 0))
251(define_attr "thumb2_neg_pool_range" "" (const_int 0))
252
253(define_attr "pool_range" ""
254 (cond [(eq_attr "is_thumb" "yes") (attr "thumb2_pool_range")]
255 (attr "arm_pool_range")))
256(define_attr "neg_pool_range" ""
257 (cond [(eq_attr "is_thumb" "yes") (attr "thumb2_neg_pool_range")]
258 (attr "arm_neg_pool_range")))
56d27660 259
215b30b3 260; An assembler sequence may clobber the condition codes without us knowing.
4d7a8451 261; If such an insn references the pool, then we have no way of knowing how,
262; so use the most conservative value for pool_range.
9c08d1fa 263(define_asm_attributes
4d7a8451 264 [(set_attr "conds" "clob")
265 (set_attr "length" "4")
266 (set_attr "pool_range" "250")])
9c08d1fa 267
9888ad6d 268; Load scheduling, set from the arm_ld_sched variable
4c834714 269; initialized by arm_option_override()
9888ad6d 270(define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
849170fd 271
f7fbdd4a 272; condition codes: this one is used by final_prescan_insn to speed up
273; conditionalizing instructions. It saves having to scan the rtl to see if
274; it uses or alters the condition codes.
215b30b3 275;
f7fbdd4a 276; USE means that the condition codes are used by the insn in the process of
215b30b3 277; outputting code, this means (at present) that we can't use the insn in
278; inlined branches
279;
f7fbdd4a 280; SET means that the purpose of the insn is to set the condition codes in a
215b30b3 281; well defined manner.
282;
f7fbdd4a 283; CLOB means that the condition codes are altered in an undefined manner, if
215b30b3 284; they are altered at all
285;
ad6d3e2a 286; UNCONDITIONAL means the instruction can not be conditionally executed and
287; that the instruction does not use or alter the condition codes.
c52acdd2 288;
ad6d3e2a 289; NOCOND means that the instruction does not use or alter the condition
290; codes but can be converted into a conditionally exectuted instruction.
f7fbdd4a 291
b0694be0 292(define_attr "conds" "use,set,clob,unconditional,nocond"
747b7458 293 (if_then_else
294 (ior (eq_attr "is_thumb1" "yes")
295 (eq_attr "type" "call"))
c1a66faf 296 (const_string "clob")
32093010 297 (if_then_else (eq_attr "is_neon_type" "no")
52432540 298 (const_string "nocond")
299 (const_string "unconditional"))))
f7fbdd4a 300
215b30b3 301; Predicable means that the insn can be conditionally executed based on
302; an automatically added predicate (additional patterns are generated by
303; gen...). We default to 'no' because no Thumb patterns match this rule
304; and not all ARM patterns do.
0d66636f 305(define_attr "predicable" "no,yes" (const_string "no"))
306
129a2fe4 307; Only model the write buffer for ARM6 and ARM7. Earlier processors don't
308; have one. Later ones, such as StrongARM, have write-back caches, so don't
8d232dc7 309; suffer blockages enough to warrant modelling this (and it can adversely
129a2fe4 310; affect the schedule).
74a71f7d 311(define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_tune_wbuf")))
129a2fe4 312
215b30b3 313; WRITE_CONFLICT implies that a read following an unrelated write is likely
314; to stall the processor. Used with model_wbuf above.
9c08d1fa 315(define_attr "write_conflict" "no,yes"
316 (if_then_else (eq_attr "type"
96854199 317 "block,call,load1")
9c08d1fa 318 (const_string "yes")
319 (const_string "no")))
320
215b30b3 321; Classify the insns into those that take one cycle and those that take more
322; than one on the main cpu execution unit.
f7fbdd4a 323(define_attr "core_cycles" "single,multi"
324 (if_then_else (eq_attr "type"
112eda6f 325 "adc_imm, adc_reg, adcs_imm, adcs_reg, adr, alu_ext, alu_imm, alu_sreg,\
326 alu_shift_imm, alu_shift_reg, alu_dsp_reg, alus_ext, alus_imm, alus_sreg,\
d82e788e 327 alus_shift_imm, alus_shift_reg, bfm, csel, rev, logic_imm, logic_reg,\
328 logic_shift_imm, logic_shift_reg, logics_imm, logics_reg,\
329 logics_shift_imm, logics_shift_reg, extend, shift_imm, float, fcsel,\
7cb6c048 330 wmmx_wor, wmmx_wxor, wmmx_wand, wmmx_wandn, wmmx_wmov, wmmx_tmcrr,\
331 wmmx_tmrrc, wmmx_wldr, wmmx_wstr, wmmx_tmcr, wmmx_tmrc, wmmx_wadd,\
332 wmmx_wsub, wmmx_wmul, wmmx_wmac, wmmx_wavg2, wmmx_tinsr, wmmx_textrm,\
333 wmmx_wshufh, wmmx_wcmpeq, wmmx_wcmpgt, wmmx_wmax, wmmx_wmin, wmmx_wpack,\
334 wmmx_wunpckih, wmmx_wunpckil, wmmx_wunpckeh, wmmx_wunpckel, wmmx_wror,\
335 wmmx_wsra, wmmx_wsrl, wmmx_wsll, wmmx_wmadd, wmmx_tmia, wmmx_tmiaph,\
336 wmmx_tmiaxy, wmmx_tbcst, wmmx_tmovmsk, wmmx_wacc, wmmx_waligni,\
337 wmmx_walignr, wmmx_tandc, wmmx_textrc, wmmx_torc, wmmx_torvsc, wmmx_wsad,\
338 wmmx_wabs, wmmx_wabsdiff, wmmx_waddsubhx, wmmx_wsubaddhx, wmmx_wavg4,\
339 wmmx_wmulw, wmmx_wqmulm, wmmx_wqmulwm, wmmx_waddbhus, wmmx_wqmiaxy,\
340 wmmx_wmiaxy, wmmx_wmiawxy, wmmx_wmerge")
f7fbdd4a 341 (const_string "single")
342 (const_string "multi")))
343
cffb2a26 344;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
215b30b3 345;; distant label. Only applicable to Thumb code.
cffb2a26 346(define_attr "far_jump" "yes,no" (const_string "no"))
347
d51f92df 348
25f905c2 349;; The number of machine instructions this pattern expands to.
350;; Used for Thumb-2 conditional execution.
351(define_attr "ce_count" "" (const_int 1))
352
4182b724 353;;---------------------------------------------------------------------------
354;; Unspecs
355
356(include "unspecs.md")
357
d51f92df 358;;---------------------------------------------------------------------------
fd781bb2 359;; Mode iterators
d51f92df 360
3de0dec6 361(include "iterators.md")
03770691 362
d51f92df 363;;---------------------------------------------------------------------------
364;; Predicates
365
9c9db025 366(include "predicates.md")
234f6557 367(include "constraints.md")
9c9db025 368
a2cd141b 369;;---------------------------------------------------------------------------
370;; Pipeline descriptions
215b30b3 371
e3879fd0 372(define_attr "tune_cortexr4" "yes,no"
373 (const (if_then_else
7d3cda8c 374 (eq_attr "tune" "cortexr4,cortexr4f,cortexr5")
e3879fd0 375 (const_string "yes")
376 (const_string "no"))))
377
a2cd141b 378;; True if the generic scheduling description should be used.
379
380(define_attr "generic_sched" "yes,no"
2546d93a 381 (const (if_then_else
e18862f3 382 (ior (eq_attr "tune" "fa526,fa626,fa606te,fa626te,fmp626,fa726te,\
383 arm926ejs,arm1020e,arm1026ejs,arm1136js,\
384 arm1136jfs,cortexa5,cortexa7,cortexa8,\
42e7b263 385 cortexa9,cortexa12,cortexa15,cortexa17,\
b1099bfd 386 cortexa53,cortexa57,cortexm4,cortexm7,\
802e6377 387 exynosm1,marvell_pj4,xgene1")
2546d93a 388 (eq_attr "tune_cortexr4" "yes"))
4d5cb40d 389 (const_string "no")
390 (const_string "yes"))))
391
c0e1af52 392(define_attr "generic_vfp" "yes,no"
393 (const (if_then_else
394 (and (eq_attr "fpu" "vfp")
e18862f3 395 (eq_attr "tune" "!arm1020e,arm1022e,cortexa5,cortexa7,\
396 cortexa8,cortexa9,cortexa53,cortexm4,\
55a94dda 397 cortexm7,marvell_pj4,xgene1")
e3879fd0 398 (eq_attr "tune_cortexr4" "no"))
c0e1af52 399 (const_string "yes")
400 (const_string "no"))))
401
6b8f7c28 402(include "marvell-f-iwmmxt.md")
a2cd141b 403(include "arm-generic.md")
404(include "arm926ejs.md")
c0e1af52 405(include "arm1020e.md")
a2cd141b 406(include "arm1026ejs.md")
407(include "arm1136jfs.md")
0e266d06 408(include "fa526.md")
409(include "fa606te.md")
410(include "fa626te.md")
411(include "fmp626.md")
412(include "fa726te.md")
3f1e069f 413(include "cortex-a5.md")
d6b7f019 414(include "cortex-a7.md")
bcaec148 415(include "cortex-a8.md")
036068af 416(include "cortex-a9.md")
65f2f758 417(include "cortex-a15.md")
42e7b263 418(include "cortex-a17.md")
da10bc87 419(include "cortex-a53.md")
b1099bfd 420(include "cortex-a57.md")
934a1e72 421(include "cortex-r4.md")
e3879fd0 422(include "cortex-r4f.md")
e18862f3 423(include "cortex-m7.md")
2546d93a 424(include "cortex-m4.md")
425(include "cortex-m4-fpu.md")
802e6377 426(include "exynos-m1.md")
55e3ada8 427(include "vfp11.md")
ea7d210b 428(include "marvell-pj4.md")
55a94dda 429(include "xgene1.md")
3586df96 430
9c08d1fa 431\f
215b30b3 432;;---------------------------------------------------------------------------
e1159bbe 433;; Insn patterns
434;;
a0f94409 435;; Addition insns.
215b30b3 436
9c08d1fa 437;; Note: For DImode insns, there is normally no reason why operands should
438;; not be in the same register, what we don't want is for something being
439;; written to partially overlap something that is an input.
440
cffb2a26 441(define_expand "adddi3"
442 [(parallel
215b30b3 443 [(set (match_operand:DI 0 "s_register_operand" "")
cffb2a26 444 (plus:DI (match_operand:DI 1 "s_register_operand" "")
10e5ccd5 445 (match_operand:DI 2 "arm_adddi_operand" "")))
bd5b4116 446 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 447 "TARGET_EITHER"
448 "
25f905c2 449 if (TARGET_THUMB1)
cffb2a26 450 {
0438d37f 451 if (!REG_P (operands[1]))
bc5a93af 452 operands[1] = force_reg (DImode, operands[1]);
0438d37f 453 if (!REG_P (operands[2]))
bc5a93af 454 operands[2] = force_reg (DImode, operands[2]);
cffb2a26 455 }
456 "
457)
458
a0f94409 459(define_insn_and_split "*arm_adddi3"
10e5ccd5 460 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r,&r,&r")
461 (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0, r, 0, r")
462 (match_operand:DI 2 "arm_adddi_operand" "r, 0, r, Dd, Dd")))
bd5b4116 463 (clobber (reg:CC CC_REGNUM))]
b805622c 464 "TARGET_32BIT && !TARGET_NEON"
33782ec7 465 "#"
94829feb 466 "TARGET_32BIT && reload_completed
467 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))"
a0f94409 468 [(parallel [(set (reg:CC_C CC_REGNUM)
469 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
470 (match_dup 1)))
471 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 472 (set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (match_dup 5))
473 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
a0f94409 474 "
475 {
476 operands[3] = gen_highpart (SImode, operands[0]);
477 operands[0] = gen_lowpart (SImode, operands[0]);
478 operands[4] = gen_highpart (SImode, operands[1]);
479 operands[1] = gen_lowpart (SImode, operands[1]);
10e5ccd5 480 operands[5] = gen_highpart_mode (SImode, DImode, operands[2]);
a0f94409 481 operands[2] = gen_lowpart (SImode, operands[2]);
482 }"
cffb2a26 483 [(set_attr "conds" "clob")
1b7da4ac 484 (set_attr "length" "8")
485 (set_attr "type" "multiple")]
cffb2a26 486)
9c08d1fa 487
a0f94409 488(define_insn_and_split "*adddi_sesidi_di"
9c08d1fa 489 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
490 (plus:DI (sign_extend:DI
97499065 491 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 492 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 493 (clobber (reg:CC CC_REGNUM))]
b805622c 494 "TARGET_32BIT"
33782ec7 495 "#"
25f905c2 496 "TARGET_32BIT && reload_completed"
a0f94409 497 [(parallel [(set (reg:CC_C CC_REGNUM)
498 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
499 (match_dup 1)))
500 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 501 (set (match_dup 3) (plus:SI (plus:SI (ashiftrt:SI (match_dup 2)
a0f94409 502 (const_int 31))
080c0b9a 503 (match_dup 4))
504 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
a0f94409 505 "
506 {
507 operands[3] = gen_highpart (SImode, operands[0]);
508 operands[0] = gen_lowpart (SImode, operands[0]);
509 operands[4] = gen_highpart (SImode, operands[1]);
510 operands[1] = gen_lowpart (SImode, operands[1]);
511 operands[2] = gen_lowpart (SImode, operands[2]);
512 }"
215b30b3 513 [(set_attr "conds" "clob")
1b7da4ac 514 (set_attr "length" "8")
515 (set_attr "type" "multiple")]
215b30b3 516)
9c08d1fa 517
a0f94409 518(define_insn_and_split "*adddi_zesidi_di"
9c08d1fa 519 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
520 (plus:DI (zero_extend:DI
97499065 521 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 522 (match_operand:DI 1 "s_register_operand" "0,r")))
a0f94409 523 (clobber (reg:CC CC_REGNUM))]
b805622c 524 "TARGET_32BIT"
33782ec7 525 "#"
25f905c2 526 "TARGET_32BIT && reload_completed"
a0f94409 527 [(parallel [(set (reg:CC_C CC_REGNUM)
528 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
529 (match_dup 1)))
530 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 531 (set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (const_int 0))
532 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
a0f94409 533 "
534 {
535 operands[3] = gen_highpart (SImode, operands[0]);
536 operands[0] = gen_lowpart (SImode, operands[0]);
537 operands[4] = gen_highpart (SImode, operands[1]);
538 operands[1] = gen_lowpart (SImode, operands[1]);
539 operands[2] = gen_lowpart (SImode, operands[2]);
540 }"
cffb2a26 541 [(set_attr "conds" "clob")
1b7da4ac 542 (set_attr "length" "8")
543 (set_attr "type" "multiple")]
cffb2a26 544)
b11cae9e 545
87b22bf7 546(define_expand "addsi3"
cffb2a26 547 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 548 (plus:SI (match_operand:SI 1 "s_register_operand" "")
549 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 550 "TARGET_EITHER"
87b22bf7 551 "
0438d37f 552 if (TARGET_32BIT && CONST_INT_P (operands[2]))
87b22bf7 553 {
96f57e36 554 arm_split_constant (PLUS, SImode, NULL_RTX,
555 INTVAL (operands[2]), operands[0], operands[1],
e1ba4a27 556 optimize && can_create_pseudo_p ());
87b22bf7 557 DONE;
558 }
cffb2a26 559 "
560)
87b22bf7 561
5bd751ff 562; If there is a scratch available, this will be faster than synthesizing the
a0f94409 563; addition.
564(define_peephole2
565 [(match_scratch:SI 3 "r")
372575c7 566 (set (match_operand:SI 0 "arm_general_register_operand" "")
567 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
cffb2a26 568 (match_operand:SI 2 "const_int_operand" "")))]
25f905c2 569 "TARGET_32BIT &&
a0f94409 570 !(const_ok_for_arm (INTVAL (operands[2]))
571 || const_ok_for_arm (-INTVAL (operands[2])))
572 && const_ok_for_arm (~INTVAL (operands[2]))"
573 [(set (match_dup 3) (match_dup 2))
574 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
575 ""
576)
87b22bf7 577
2f02c19f 578;; The r/r/k alternative is required when reloading the address
579;; (plus (reg rN) (reg sp)) into (reg rN). In this case reload will
580;; put the duplicated register first, and not try the commutative version.
a0f94409 581(define_insn_and_split "*arm_addsi3"
7c36fe71 582 [(set (match_operand:SI 0 "s_register_operand" "=rk,l,l ,l ,r ,k ,r,r ,k ,r ,k,k,r ,k ,r")
583 (plus:SI (match_operand:SI 1 "s_register_operand" "%0 ,l,0 ,l ,rk,k ,r,rk,k ,rk,k,r,rk,k ,rk")
584 (match_operand:SI 2 "reg_or_int_operand" "rk ,l,Py,Pd,rI,rI,k,Pj,Pj,L ,L,L,PJ,PJ,?n")))]
25f905c2 585 "TARGET_32BIT"
5565501b 586 "@
c24d855d 587 add%?\\t%0, %0, %2
5565501b 588 add%?\\t%0, %1, %2
a0b3420a 589 add%?\\t%0, %1, %2
7c36fe71 590 add%?\\t%0, %1, %2
591 add%?\\t%0, %1, %2
aaa37ad6 592 add%?\\t%0, %1, %2
2f02c19f 593 add%?\\t%0, %2, %1
d5cbae34 594 addw%?\\t%0, %1, %2
595 addw%?\\t%0, %1, %2
aaa37ad6 596 sub%?\\t%0, %1, #%n2
87b22bf7 597 sub%?\\t%0, %1, #%n2
d7757711 598 sub%?\\t%0, %1, #%n2
d5cbae34 599 subw%?\\t%0, %1, #%n2
600 subw%?\\t%0, %1, #%n2
87b22bf7 601 #"
a3ffc315 602 "TARGET_32BIT
0438d37f 603 && CONST_INT_P (operands[2])
d5cbae34 604 && !const_ok_for_op (INTVAL (operands[2]), PLUS)
a3ffc315 605 && (reload_completed || !arm_eliminable_register (operands[1]))"
a0f94409 606 [(clobber (const_int 0))]
607 "
96f57e36 608 arm_split_constant (PLUS, SImode, curr_insn,
609 INTVAL (operands[2]), operands[0],
a0f94409 610 operands[1], 0);
611 DONE;
612 "
7c36fe71 613 [(set_attr "length" "2,4,4,4,4,4,4,4,4,4,4,4,4,4,16")
d5cbae34 614 (set_attr "predicable" "yes")
7c36fe71 615 (set_attr "predicable_short_it" "yes,yes,yes,yes,no,no,no,no,no,no,no,no,no,no,no")
616 (set_attr "arch" "t2,t2,t2,t2,*,*,*,t2,t2,*,*,a,t2,t2,*")
65f68e55 617 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
d82e788e 618 (const_string "alu_imm")
112eda6f 619 (const_string "alu_sreg")))
65f68e55 620 ]
cffb2a26 621)
622
90c2bcf0 623(define_insn "addsi3_compare0"
bd5b4116 624 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 625 (compare:CC_NOOV
65f68e55 626 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r,r")
627 (match_operand:SI 2 "arm_add_operand" "I,L,r"))
5565501b 628 (const_int 0)))
65f68e55 629 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9c08d1fa 630 (plus:SI (match_dup 1) (match_dup 2)))]
ec792a7b 631 "TARGET_ARM"
5565501b 632 "@
3ef90e77 633 adds%?\\t%0, %1, %2
634 subs%?\\t%0, %1, #%n2
635 adds%?\\t%0, %1, %2"
65f68e55 636 [(set_attr "conds" "set")
112eda6f 637 (set_attr "type" "alus_imm,alus_imm,alus_sreg")]
cffb2a26 638)
9c08d1fa 639
aea4c774 640(define_insn "*addsi3_compare0_scratch"
bd5b4116 641 [(set (reg:CC_NOOV CC_REGNUM)
aea4c774 642 (compare:CC_NOOV
65f68e55 643 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r, r")
644 (match_operand:SI 1 "arm_add_operand" "I,L, r"))
aea4c774 645 (const_int 0)))]
ec792a7b 646 "TARGET_ARM"
cffb2a26 647 "@
648 cmn%?\\t%0, %1
65f68e55 649 cmp%?\\t%0, #%n1
650 cmn%?\\t%0, %1"
596e5e8f 651 [(set_attr "conds" "set")
65f68e55 652 (set_attr "predicable" "yes")
112eda6f 653 (set_attr "type" "alus_imm,alus_imm,alus_sreg")]
0d66636f 654)
cffb2a26 655
aed179ae 656(define_insn "*compare_negsi_si"
657 [(set (reg:CC_Z CC_REGNUM)
658 (compare:CC_Z
7c36fe71 659 (neg:SI (match_operand:SI 0 "s_register_operand" "l,r"))
660 (match_operand:SI 1 "s_register_operand" "l,r")))]
25f905c2 661 "TARGET_32BIT"
aed179ae 662 "cmn%?\\t%1, %0"
596e5e8f 663 [(set_attr "conds" "set")
7c36fe71 664 (set_attr "predicable" "yes")
665 (set_attr "arch" "t2,*")
666 (set_attr "length" "2,4")
1b7da4ac 667 (set_attr "predicable_short_it" "yes,no")
112eda6f 668 (set_attr "type" "alus_sreg")]
0d66636f 669)
aea4c774 670
203c488f 671;; This is the canonicalization of addsi3_compare0_for_combiner when the
672;; addend is a constant.
190efb17 673(define_insn "cmpsi2_addneg"
203c488f 674 [(set (reg:CC CC_REGNUM)
675 (compare:CC
676 (match_operand:SI 1 "s_register_operand" "r,r")
2a977b78 677 (match_operand:SI 2 "arm_addimm_operand" "L,I")))
203c488f 678 (set (match_operand:SI 0 "s_register_operand" "=r,r")
679 (plus:SI (match_dup 1)
2a977b78 680 (match_operand:SI 3 "arm_addimm_operand" "I,L")))]
25f905c2 681 "TARGET_32BIT && INTVAL (operands[2]) == -INTVAL (operands[3])"
203c488f 682 "@
3ef90e77 683 adds%?\\t%0, %1, %3
684 subs%?\\t%0, %1, #%n3"
1b7da4ac 685 [(set_attr "conds" "set")
112eda6f 686 (set_attr "type" "alus_sreg")]
203c488f 687)
688
689;; Convert the sequence
690;; sub rd, rn, #1
691;; cmn rd, #1 (equivalent to cmp rd, #-1)
692;; bne dest
693;; into
694;; subs rd, rn, #1
695;; bcs dest ((unsigned)rn >= 1)
696;; similarly for the beq variant using bcc.
697;; This is a common looping idiom (while (n--))
698(define_peephole2
372575c7 699 [(set (match_operand:SI 0 "arm_general_register_operand" "")
700 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
203c488f 701 (const_int -1)))
702 (set (match_operand 2 "cc_register" "")
703 (compare (match_dup 0) (const_int -1)))
704 (set (pc)
705 (if_then_else (match_operator 3 "equality_operator"
706 [(match_dup 2) (const_int 0)])
707 (match_operand 4 "" "")
708 (match_operand 5 "" "")))]
25f905c2 709 "TARGET_32BIT && peep2_reg_dead_p (3, operands[2])"
203c488f 710 [(parallel[
711 (set (match_dup 2)
712 (compare:CC
713 (match_dup 1) (const_int 1)))
714 (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
715 (set (pc)
716 (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
717 (match_dup 4)
718 (match_dup 5)))]
719 "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
720 operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
721 ? GEU : LTU),
722 VOIDmode,
723 operands[2], const0_rtx);"
724)
725
ebcc79bc 726;; The next four insns work because they compare the result with one of
727;; the operands, and we know that the use of the condition code is
728;; either GEU or LTU, so we can use the carry flag from the addition
729;; instead of doing the compare a second time.
730(define_insn "*addsi3_compare_op1"
bd5b4116 731 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 732 (compare:CC_C
65f68e55 733 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
734 (match_operand:SI 2 "arm_add_operand" "I,L,r"))
ebcc79bc 735 (match_dup 1)))
65f68e55 736 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
ebcc79bc 737 (plus:SI (match_dup 1) (match_dup 2)))]
25f905c2 738 "TARGET_32BIT"
ebcc79bc 739 "@
3ef90e77 740 adds%?\\t%0, %1, %2
741 subs%?\\t%0, %1, #%n2
742 adds%?\\t%0, %1, %2"
65f68e55 743 [(set_attr "conds" "set")
112eda6f 744 (set_attr "type" "alus_imm,alus_imm,alus_sreg")]
0d66636f 745)
ebcc79bc 746
747(define_insn "*addsi3_compare_op2"
bd5b4116 748 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 749 (compare:CC_C
65f68e55 750 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
751 (match_operand:SI 2 "arm_add_operand" "I,L,r"))
ebcc79bc 752 (match_dup 2)))
65f68e55 753 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9c08d1fa 754 (plus:SI (match_dup 1) (match_dup 2)))]
25f905c2 755 "TARGET_32BIT"
5565501b 756 "@
3ef90e77 757 adds%?\\t%0, %1, %2
38128b57 758 subs%?\\t%0, %1, #%n2
759 adds%?\\t%0, %1, %2"
65f68e55 760 [(set_attr "conds" "set")
112eda6f 761 (set_attr "type" "alus_imm,alus_imm,alus_sreg")]
0d66636f 762)
9c08d1fa 763
ebcc79bc 764(define_insn "*compare_addsi2_op0"
bd5b4116 765 [(set (reg:CC_C CC_REGNUM)
7c36fe71 766 (compare:CC_C
767 (plus:SI (match_operand:SI 0 "s_register_operand" "l,l,r,r,r")
768 (match_operand:SI 1 "arm_add_operand" "Pv,l,I,L,r"))
769 (match_dup 0)))]
25f905c2 770 "TARGET_32BIT"
ebcc79bc 771 "@
7c36fe71 772 cmp%?\\t%0, #%n1
773 cmn%?\\t%0, %1
ebcc79bc 774 cmn%?\\t%0, %1
65f68e55 775 cmp%?\\t%0, #%n1
776 cmn%?\\t%0, %1"
596e5e8f 777 [(set_attr "conds" "set")
65f68e55 778 (set_attr "predicable" "yes")
7c36fe71 779 (set_attr "arch" "t2,t2,*,*,*")
780 (set_attr "predicable_short_it" "yes,yes,no,no,no")
781 (set_attr "length" "2,2,4,4,4")
112eda6f 782 (set_attr "type" "alus_imm,alus_sreg,alus_imm,alus_imm,alus_sreg")]
0d66636f 783)
ebcc79bc 784
785(define_insn "*compare_addsi2_op1"
bd5b4116 786 [(set (reg:CC_C CC_REGNUM)
7c36fe71 787 (compare:CC_C
788 (plus:SI (match_operand:SI 0 "s_register_operand" "l,l,r,r,r")
789 (match_operand:SI 1 "arm_add_operand" "Pv,l,I,L,r"))
790 (match_dup 1)))]
25f905c2 791 "TARGET_32BIT"
ebcc79bc 792 "@
7c36fe71 793 cmp%?\\t%0, #%n1
794 cmn%?\\t%0, %1
ebcc79bc 795 cmn%?\\t%0, %1
65f68e55 796 cmp%?\\t%0, #%n1
797 cmn%?\\t%0, %1"
596e5e8f 798 [(set_attr "conds" "set")
65f68e55 799 (set_attr "predicable" "yes")
7c36fe71 800 (set_attr "arch" "t2,t2,*,*,*")
801 (set_attr "predicable_short_it" "yes,yes,no,no,no")
802 (set_attr "length" "2,2,4,4,4")
112eda6f 803 (set_attr "type" "alus_imm,alus_sreg,alus_imm,alus_imm,alus_sreg")]
7c36fe71 804 )
ebcc79bc 805
080c0b9a 806(define_insn "*addsi3_carryin_<optab>"
7c36fe71 807 [(set (match_operand:SI 0 "s_register_operand" "=l,r,r")
808 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%l,r,r")
809 (match_operand:SI 2 "arm_not_operand" "0,rI,K"))
810 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))]
25f905c2 811 "TARGET_32BIT"
10e5ccd5 812 "@
a0b3420a 813 adc%?\\t%0, %1, %2
10e5ccd5 814 adc%?\\t%0, %1, %2
815 sbc%?\\t%0, %1, #%B2"
a7de272d 816 [(set_attr "conds" "use")
7c36fe71 817 (set_attr "predicable" "yes")
818 (set_attr "arch" "t2,*,*")
819 (set_attr "length" "4")
1b7da4ac 820 (set_attr "predicable_short_it" "yes,no,no")
821 (set_attr "type" "adc_reg,adc_reg,adc_imm")]
cffb2a26 822)
ebcc79bc 823
080c0b9a 824(define_insn "*addsi3_carryin_alt2_<optab>"
7c36fe71 825 [(set (match_operand:SI 0 "s_register_operand" "=l,r,r")
826 (plus:SI (plus:SI (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))
827 (match_operand:SI 1 "s_register_operand" "%l,r,r"))
828 (match_operand:SI 2 "arm_rhs_operand" "l,rI,K")))]
25f905c2 829 "TARGET_32BIT"
10e5ccd5 830 "@
a0b3420a 831 adc%?\\t%0, %1, %2
10e5ccd5 832 adc%?\\t%0, %1, %2
833 sbc%?\\t%0, %1, #%B2"
a7de272d 834 [(set_attr "conds" "use")
7c36fe71 835 (set_attr "predicable" "yes")
836 (set_attr "arch" "t2,*,*")
837 (set_attr "length" "4")
1b7da4ac 838 (set_attr "predicable_short_it" "yes,no,no")
839 (set_attr "type" "adc_reg,adc_reg,adc_imm")]
0d66636f 840)
ebcc79bc 841
080c0b9a 842(define_insn "*addsi3_carryin_shift_<optab>"
ebcc79bc 843 [(set (match_operand:SI 0 "s_register_operand" "=r")
080c0b9a 844 (plus:SI (plus:SI
845 (match_operator:SI 2 "shift_operator"
846 [(match_operand:SI 3 "s_register_operand" "r")
847 (match_operand:SI 4 "reg_or_int_operand" "rM")])
848 (match_operand:SI 1 "s_register_operand" "r"))
849 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))]
25f905c2 850 "TARGET_32BIT"
080c0b9a 851 "adc%?\\t%0, %1, %3%S2"
852 [(set_attr "conds" "use")
a7de272d 853 (set_attr "predicable" "yes")
7c36fe71 854 (set_attr "predicable_short_it" "no")
080c0b9a 855 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
d82e788e 856 (const_string "alu_shift_imm")
857 (const_string "alu_shift_reg")))]
cffb2a26 858)
ebcc79bc 859
922b6913 860(define_insn "*addsi3_carryin_clobercc_<optab>"
861 [(set (match_operand:SI 0 "s_register_operand" "=r")
862 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%r")
863 (match_operand:SI 2 "arm_rhs_operand" "rI"))
864 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))
865 (clobber (reg:CC CC_REGNUM))]
866 "TARGET_32BIT"
3ef90e77 867 "adcs%?\\t%0, %1, %2"
1b7da4ac 868 [(set_attr "conds" "set")
869 (set_attr "type" "adcs_reg")]
922b6913 870)
871
9154bd82 872(define_insn "*subsi3_carryin"
873 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
874 (minus:SI (minus:SI (match_operand:SI 1 "reg_or_int_operand" "r,I")
875 (match_operand:SI 2 "s_register_operand" "r,r"))
876 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
877 "TARGET_32BIT"
878 "@
879 sbc%?\\t%0, %1, %2
880 rsc%?\\t%0, %2, %1"
881 [(set_attr "conds" "use")
882 (set_attr "arch" "*,a")
7c36fe71 883 (set_attr "predicable" "yes")
1b7da4ac 884 (set_attr "predicable_short_it" "no")
885 (set_attr "type" "adc_reg,adc_imm")]
9154bd82 886)
887
888(define_insn "*subsi3_carryin_const"
889 [(set (match_operand:SI 0 "s_register_operand" "=r")
df46fd5e 890 (minus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
891 (match_operand:SI 2 "arm_not_immediate_operand" "K"))
9154bd82 892 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
893 "TARGET_32BIT"
894 "sbc\\t%0, %1, #%B2"
1b7da4ac 895 [(set_attr "conds" "use")
896 (set_attr "type" "adc_imm")]
9154bd82 897)
898
899(define_insn "*subsi3_carryin_compare"
900 [(set (reg:CC CC_REGNUM)
901 (compare:CC (match_operand:SI 1 "s_register_operand" "r")
902 (match_operand:SI 2 "s_register_operand" "r")))
903 (set (match_operand:SI 0 "s_register_operand" "=r")
904 (minus:SI (minus:SI (match_dup 1)
905 (match_dup 2))
906 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
907 "TARGET_32BIT"
908 "sbcs\\t%0, %1, %2"
1b7da4ac 909 [(set_attr "conds" "set")
910 (set_attr "type" "adcs_reg")]
9154bd82 911)
912
913(define_insn "*subsi3_carryin_compare_const"
914 [(set (reg:CC CC_REGNUM)
915 (compare:CC (match_operand:SI 1 "reg_or_int_operand" "r")
916 (match_operand:SI 2 "arm_not_operand" "K")))
917 (set (match_operand:SI 0 "s_register_operand" "=r")
918 (minus:SI (plus:SI (match_dup 1)
919 (match_dup 2))
920 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
921 "TARGET_32BIT"
922 "sbcs\\t%0, %1, #%B2"
1b7da4ac 923 [(set_attr "conds" "set")
924 (set_attr "type" "adcs_imm")]
9154bd82 925)
926
927(define_insn "*subsi3_carryin_shift"
928 [(set (match_operand:SI 0 "s_register_operand" "=r")
929 (minus:SI (minus:SI
930 (match_operand:SI 1 "s_register_operand" "r")
931 (match_operator:SI 2 "shift_operator"
932 [(match_operand:SI 3 "s_register_operand" "r")
933 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
934 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
935 "TARGET_32BIT"
936 "sbc%?\\t%0, %1, %3%S2"
937 [(set_attr "conds" "use")
938 (set_attr "predicable" "yes")
939 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
d82e788e 940 (const_string "alu_shift_imm")
941 (const_string "alu_shift_reg")))]
9154bd82 942)
943
944(define_insn "*rsbsi3_carryin_shift"
945 [(set (match_operand:SI 0 "s_register_operand" "=r")
946 (minus:SI (minus:SI
947 (match_operator:SI 2 "shift_operator"
948 [(match_operand:SI 3 "s_register_operand" "r")
949 (match_operand:SI 4 "reg_or_int_operand" "rM")])
950 (match_operand:SI 1 "s_register_operand" "r"))
951 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
952 "TARGET_ARM"
953 "rsc%?\\t%0, %1, %3%S2"
954 [(set_attr "conds" "use")
955 (set_attr "predicable" "yes")
956 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
d82e788e 957 (const_string "alu_shift_imm")
958 (const_string "alu_shift_reg")))]
9154bd82 959)
960
d795fb69 961; transform ((x << y) - 1) to ~(~(x-1) << y) Where X is a constant.
962(define_split
963 [(set (match_operand:SI 0 "s_register_operand" "")
964 (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
965 (match_operand:SI 2 "s_register_operand" ""))
966 (const_int -1)))
967 (clobber (match_operand:SI 3 "s_register_operand" ""))]
25f905c2 968 "TARGET_32BIT"
d795fb69 969 [(set (match_dup 3) (match_dup 1))
970 (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
971 "
972 operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
973")
974
604f3a0a 975(define_expand "addsf3"
976 [(set (match_operand:SF 0 "s_register_operand" "")
977 (plus:SF (match_operand:SF 1 "s_register_operand" "")
d86c91f6 978 (match_operand:SF 2 "s_register_operand" "")))]
25f905c2 979 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 980 "
604f3a0a 981")
982
604f3a0a 983(define_expand "adddf3"
984 [(set (match_operand:DF 0 "s_register_operand" "")
985 (plus:DF (match_operand:DF 1 "s_register_operand" "")
d86c91f6 986 (match_operand:DF 2 "s_register_operand" "")))]
a50d7267 987 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 988 "
604f3a0a 989")
990
cffb2a26 991(define_expand "subdi3"
992 [(parallel
993 [(set (match_operand:DI 0 "s_register_operand" "")
994 (minus:DI (match_operand:DI 1 "s_register_operand" "")
995 (match_operand:DI 2 "s_register_operand" "")))
bd5b4116 996 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 997 "TARGET_EITHER"
998 "
25f905c2 999 if (TARGET_THUMB1)
cffb2a26 1000 {
0438d37f 1001 if (!REG_P (operands[1]))
5aa8c5f0 1002 operands[1] = force_reg (DImode, operands[1]);
0438d37f 1003 if (!REG_P (operands[2]))
5aa8c5f0 1004 operands[2] = force_reg (DImode, operands[2]);
cffb2a26 1005 }
1006 "
1007)
1008
2f9b23e3 1009(define_insn_and_split "*arm_subdi3"
cffb2a26 1010 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
9c08d1fa 1011 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
1012 (match_operand:DI 2 "s_register_operand" "r,0,0")))
bd5b4116 1013 (clobber (reg:CC CC_REGNUM))]
94829feb 1014 "TARGET_32BIT && !TARGET_NEON"
2f9b23e3 1015 "#" ; "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
1016 "&& reload_completed"
1017 [(parallel [(set (reg:CC CC_REGNUM)
1018 (compare:CC (match_dup 1) (match_dup 2)))
1019 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1020 (set (match_dup 3) (minus:SI (minus:SI (match_dup 4) (match_dup 5))
1021 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1022 {
1023 operands[3] = gen_highpart (SImode, operands[0]);
1024 operands[0] = gen_lowpart (SImode, operands[0]);
1025 operands[4] = gen_highpart (SImode, operands[1]);
1026 operands[1] = gen_lowpart (SImode, operands[1]);
1027 operands[5] = gen_highpart (SImode, operands[2]);
1028 operands[2] = gen_lowpart (SImode, operands[2]);
1029 }
cffb2a26 1030 [(set_attr "conds" "clob")
1b7da4ac 1031 (set_attr "length" "8")
1032 (set_attr "type" "multiple")]
cffb2a26 1033)
1034
2f9b23e3 1035(define_insn_and_split "*subdi_di_zesidi"
cffb2a26 1036 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 1037 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r")
9c08d1fa 1038 (zero_extend:DI
cffb2a26 1039 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 1040 (clobber (reg:CC CC_REGNUM))]
25f905c2 1041 "TARGET_32BIT"
2f9b23e3 1042 "#" ; "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
1043 "&& reload_completed"
1044 [(parallel [(set (reg:CC CC_REGNUM)
1045 (compare:CC (match_dup 1) (match_dup 2)))
1046 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1047 (set (match_dup 3) (minus:SI (plus:SI (match_dup 4) (match_dup 5))
1048 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1049 {
1050 operands[3] = gen_highpart (SImode, operands[0]);
1051 operands[0] = gen_lowpart (SImode, operands[0]);
1052 operands[4] = gen_highpart (SImode, operands[1]);
1053 operands[1] = gen_lowpart (SImode, operands[1]);
1054 operands[5] = GEN_INT (~0);
1055 }
cffb2a26 1056 [(set_attr "conds" "clob")
1b7da4ac 1057 (set_attr "length" "8")
1058 (set_attr "type" "multiple")]
cffb2a26 1059)
9c08d1fa 1060
2f9b23e3 1061(define_insn_and_split "*subdi_di_sesidi"
cffb2a26 1062 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 1063 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r")
9c08d1fa 1064 (sign_extend:DI
cffb2a26 1065 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 1066 (clobber (reg:CC CC_REGNUM))]
25f905c2 1067 "TARGET_32BIT"
2f9b23e3 1068 "#" ; "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
1069 "&& reload_completed"
1070 [(parallel [(set (reg:CC CC_REGNUM)
1071 (compare:CC (match_dup 1) (match_dup 2)))
1072 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1073 (set (match_dup 3) (minus:SI (minus:SI (match_dup 4)
1074 (ashiftrt:SI (match_dup 2)
1075 (const_int 31)))
1076 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1077 {
1078 operands[3] = gen_highpart (SImode, operands[0]);
1079 operands[0] = gen_lowpart (SImode, operands[0]);
1080 operands[4] = gen_highpart (SImode, operands[1]);
1081 operands[1] = gen_lowpart (SImode, operands[1]);
1082 }
cffb2a26 1083 [(set_attr "conds" "clob")
1b7da4ac 1084 (set_attr "length" "8")
1085 (set_attr "type" "multiple")]
cffb2a26 1086)
9c08d1fa 1087
2f9b23e3 1088(define_insn_and_split "*subdi_zesidi_di"
cffb2a26 1089 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1090 (minus:DI (zero_extend:DI
cffb2a26 1091 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 1092 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 1093 (clobber (reg:CC CC_REGNUM))]
cffb2a26 1094 "TARGET_ARM"
2f9b23e3 1095 "#" ; "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
1096 ; is equivalent to:
1097 ; "subs\\t%Q0, %2, %Q1\;rsc\\t%R0, %R1, #0"
1098 "&& reload_completed"
1099 [(parallel [(set (reg:CC CC_REGNUM)
1100 (compare:CC (match_dup 2) (match_dup 1)))
1101 (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))])
1102 (set (match_dup 3) (minus:SI (minus:SI (const_int 0) (match_dup 4))
1103 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1104 {
1105 operands[3] = gen_highpart (SImode, operands[0]);
1106 operands[0] = gen_lowpart (SImode, operands[0]);
1107 operands[4] = gen_highpart (SImode, operands[1]);
1108 operands[1] = gen_lowpart (SImode, operands[1]);
1109 }
cffb2a26 1110 [(set_attr "conds" "clob")
1b7da4ac 1111 (set_attr "length" "8")
1112 (set_attr "type" "multiple")]
cffb2a26 1113)
9c08d1fa 1114
2f9b23e3 1115(define_insn_and_split "*subdi_sesidi_di"
cffb2a26 1116 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1117 (minus:DI (sign_extend:DI
cffb2a26 1118 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 1119 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 1120 (clobber (reg:CC CC_REGNUM))]
cffb2a26 1121 "TARGET_ARM"
2f9b23e3 1122 "#" ; "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
1123 ; is equivalent to:
1124 ; "subs\\t%Q0, %2, %Q1\;rsc\\t%R0, %R1, %2, asr #31"
1125 "&& reload_completed"
1126 [(parallel [(set (reg:CC CC_REGNUM)
1127 (compare:CC (match_dup 2) (match_dup 1)))
1128 (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))])
1129 (set (match_dup 3) (minus:SI (minus:SI
1130 (ashiftrt:SI (match_dup 2)
1131 (const_int 31))
1132 (match_dup 4))
1133 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1134 {
1135 operands[3] = gen_highpart (SImode, operands[0]);
1136 operands[0] = gen_lowpart (SImode, operands[0]);
1137 operands[4] = gen_highpart (SImode, operands[1]);
1138 operands[1] = gen_lowpart (SImode, operands[1]);
1139 }
cffb2a26 1140 [(set_attr "conds" "clob")
1b7da4ac 1141 (set_attr "length" "8")
1142 (set_attr "type" "multiple")]
cffb2a26 1143)
9c08d1fa 1144
2f9b23e3 1145(define_insn_and_split "*subdi_zesidi_zesidi"
cffb2a26 1146 [(set (match_operand:DI 0 "s_register_operand" "=r")
9c08d1fa 1147 (minus:DI (zero_extend:DI
cffb2a26 1148 (match_operand:SI 1 "s_register_operand" "r"))
9c08d1fa 1149 (zero_extend:DI
cffb2a26 1150 (match_operand:SI 2 "s_register_operand" "r"))))
bd5b4116 1151 (clobber (reg:CC CC_REGNUM))]
25f905c2 1152 "TARGET_32BIT"
2f9b23e3 1153 "#" ; "subs\\t%Q0, %1, %2\;sbc\\t%R0, %1, %1"
1154 "&& reload_completed"
1155 [(parallel [(set (reg:CC CC_REGNUM)
1156 (compare:CC (match_dup 1) (match_dup 2)))
1157 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1158 (set (match_dup 3) (minus:SI (minus:SI (match_dup 1) (match_dup 1))
1159 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1160 {
1161 operands[3] = gen_highpart (SImode, operands[0]);
1162 operands[0] = gen_lowpart (SImode, operands[0]);
1163 }
cffb2a26 1164 [(set_attr "conds" "clob")
1b7da4ac 1165 (set_attr "length" "8")
1166 (set_attr "type" "multiple")]
cffb2a26 1167)
b11cae9e 1168
87b22bf7 1169(define_expand "subsi3"
cffb2a26 1170 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 1171 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
1172 (match_operand:SI 2 "s_register_operand" "")))]
cffb2a26 1173 "TARGET_EITHER"
87b22bf7 1174 "
0438d37f 1175 if (CONST_INT_P (operands[1]))
87b22bf7 1176 {
25f905c2 1177 if (TARGET_32BIT)
cffb2a26 1178 {
17202aa5 1179 if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[1]), MINUS))
1180 operands[1] = force_reg (SImode, operands[1]);
1181 else
1182 {
1183 arm_split_constant (MINUS, SImode, NULL_RTX,
1184 INTVAL (operands[1]), operands[0],
1185 operands[2],
1186 optimize && can_create_pseudo_p ());
1187 DONE;
1188 }
cffb2a26 1189 }
25f905c2 1190 else /* TARGET_THUMB1 */
cffb2a26 1191 operands[1] = force_reg (SImode, operands[1]);
87b22bf7 1192 }
cffb2a26 1193 "
1194)
87b22bf7 1195
25f905c2 1196; ??? Check Thumb-2 split length
a0f94409 1197(define_insn_and_split "*arm_subsi3_insn"
3a44c5a9 1198 [(set (match_operand:SI 0 "s_register_operand" "=l,l ,l ,l ,r,r,r,rk,r")
1199 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "l ,0 ,l ,Pz,I,r,r,k ,?n")
1200 (match_operand:SI 2 "reg_or_int_operand" "l ,Py,Pd,l ,r,I,r,r ,r")))]
25f905c2 1201 "TARGET_32BIT"
e2348bcb 1202 "@
7c36fe71 1203 sub%?\\t%0, %1, %2
1204 sub%?\\t%0, %2
1205 sub%?\\t%0, %1, %2
1206 rsb%?\\t%0, %2, %1
87b22bf7 1207 rsb%?\\t%0, %2, %1
aaa37ad6 1208 sub%?\\t%0, %1, %2
080c0b9a 1209 sub%?\\t%0, %1, %2
65f68e55 1210 sub%?\\t%0, %1, %2
87b22bf7 1211 #"
0438d37f 1212 "&& (CONST_INT_P (operands[1])
91a5e339 1213 && !const_ok_for_arm (INTVAL (operands[1])))"
87b22bf7 1214 [(clobber (const_int 0))]
1215 "
96f57e36 1216 arm_split_constant (MINUS, SImode, curr_insn,
1217 INTVAL (operands[1]), operands[0], operands[2], 0);
87b22bf7 1218 DONE;
cffb2a26 1219 "
7c36fe71 1220 [(set_attr "length" "4,4,4,4,4,4,4,4,16")
1221 (set_attr "arch" "t2,t2,t2,t2,*,*,*,*,*")
65f68e55 1222 (set_attr "predicable" "yes")
7c36fe71 1223 (set_attr "predicable_short_it" "yes,yes,yes,yes,no,no,no,no,no")
112eda6f 1224 (set_attr "type" "alu_sreg,alu_sreg,alu_sreg,alu_sreg,alu_imm,alu_imm,alu_sreg,alu_sreg,multiple")]
a0f94409 1225)
1226
1227(define_peephole2
1228 [(match_scratch:SI 3 "r")
372575c7 1229 (set (match_operand:SI 0 "arm_general_register_operand" "")
a0f94409 1230 (minus:SI (match_operand:SI 1 "const_int_operand" "")
372575c7 1231 (match_operand:SI 2 "arm_general_register_operand" "")))]
25f905c2 1232 "TARGET_32BIT
a0f94409 1233 && !const_ok_for_arm (INTVAL (operands[1]))
1234 && const_ok_for_arm (~INTVAL (operands[1]))"
1235 [(set (match_dup 3) (match_dup 1))
1236 (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1237 ""
cffb2a26 1238)
b11cae9e 1239
62e39b06 1240(define_insn "subsi3_compare0"
bd5b4116 1241 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1242 (compare:CC_NOOV
65f68e55 1243 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,r,I")
1244 (match_operand:SI 2 "arm_rhs_operand" "I,r,r"))
215b30b3 1245 (const_int 0)))
65f68e55 1246 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9c08d1fa 1247 (minus:SI (match_dup 1) (match_dup 2)))]
25f905c2 1248 "TARGET_32BIT"
e2348bcb 1249 "@
3ef90e77 1250 subs%?\\t%0, %1, %2
1251 subs%?\\t%0, %1, %2
1252 rsbs%?\\t%0, %2, %1"
65f68e55 1253 [(set_attr "conds" "set")
112eda6f 1254 (set_attr "type" "alus_imm,alus_sreg,alus_sreg")]
cffb2a26 1255)
9c08d1fa 1256
190efb17 1257(define_insn "subsi3_compare"
080c0b9a 1258 [(set (reg:CC CC_REGNUM)
65f68e55 1259 (compare:CC (match_operand:SI 1 "arm_rhs_operand" "r,r,I")
1260 (match_operand:SI 2 "arm_rhs_operand" "I,r,r")))
1261 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2df9477b 1262 (minus:SI (match_dup 1) (match_dup 2)))]
1263 "TARGET_32BIT"
1264 "@
3ef90e77 1265 subs%?\\t%0, %1, %2
1266 subs%?\\t%0, %1, %2
1267 rsbs%?\\t%0, %2, %1"
65f68e55 1268 [(set_attr "conds" "set")
112eda6f 1269 (set_attr "type" "alus_imm,alus_sreg,alus_sreg")]
2df9477b 1270)
1271
604f3a0a 1272(define_expand "subsf3"
1273 [(set (match_operand:SF 0 "s_register_operand" "")
d86c91f6 1274 (minus:SF (match_operand:SF 1 "s_register_operand" "")
1275 (match_operand:SF 2 "s_register_operand" "")))]
25f905c2 1276 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1277 "
604f3a0a 1278")
1279
604f3a0a 1280(define_expand "subdf3"
1281 [(set (match_operand:DF 0 "s_register_operand" "")
d86c91f6 1282 (minus:DF (match_operand:DF 1 "s_register_operand" "")
1283 (match_operand:DF 2 "s_register_operand" "")))]
a50d7267 1284 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 1285 "
604f3a0a 1286")
1287
b11cae9e 1288\f
1289;; Multiplication insns
1290
4422d91f 1291(define_expand "mulhi3"
1292 [(set (match_operand:HI 0 "s_register_operand" "")
1293 (mult:HI (match_operand:HI 1 "s_register_operand" "")
1294 (match_operand:HI 2 "s_register_operand" "")))]
1295 "TARGET_DSP_MULTIPLY"
1296 "
1297 {
1298 rtx result = gen_reg_rtx (SImode);
1299 emit_insn (gen_mulhisi3 (result, operands[1], operands[2]));
1300 emit_move_insn (operands[0], gen_lowpart (HImode, result));
1301 DONE;
1302 }"
1303)
1304
cffb2a26 1305(define_expand "mulsi3"
1306 [(set (match_operand:SI 0 "s_register_operand" "")
1307 (mult:SI (match_operand:SI 2 "s_register_operand" "")
1308 (match_operand:SI 1 "s_register_operand" "")))]
1309 "TARGET_EITHER"
1310 ""
1311)
1312
9c08d1fa 1313;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
cffb2a26 1314(define_insn "*arm_mulsi3"
1315 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1316 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1317 (match_operand:SI 1 "s_register_operand" "%0,r")))]
58d7d654 1318 "TARGET_32BIT && !arm_arch6"
f7fbdd4a 1319 "mul%?\\t%0, %2, %1"
9da0ec36 1320 [(set_attr "type" "mul")
0d66636f 1321 (set_attr "predicable" "yes")]
cffb2a26 1322)
1323
58d7d654 1324(define_insn "*arm_mulsi3_v6"
d952d547 1325 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
1326 (mult:SI (match_operand:SI 1 "s_register_operand" "0,l,r")
1327 (match_operand:SI 2 "s_register_operand" "l,0,r")))]
58d7d654 1328 "TARGET_32BIT && arm_arch6"
1329 "mul%?\\t%0, %1, %2"
9da0ec36 1330 [(set_attr "type" "mul")
d952d547 1331 (set_attr "predicable" "yes")
1332 (set_attr "arch" "t2,t2,*")
1333 (set_attr "length" "4")
1334 (set_attr "predicable_short_it" "yes,yes,no")]
58d7d654 1335)
1336
f7fbdd4a 1337(define_insn "*mulsi3_compare0"
bd5b4116 1338 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1339 (compare:CC_NOOV (mult:SI
1340 (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1341 (match_operand:SI 1 "s_register_operand" "%0,r"))
9c08d1fa 1342 (const_int 0)))
1343 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1344 (mult:SI (match_dup 2) (match_dup 1)))]
58d7d654 1345 "TARGET_ARM && !arm_arch6"
3ef90e77 1346 "muls%?\\t%0, %2, %1"
58d7d654 1347 [(set_attr "conds" "set")
9da0ec36 1348 (set_attr "type" "muls")]
58d7d654 1349)
1350
1351(define_insn "*mulsi3_compare0_v6"
1352 [(set (reg:CC_NOOV CC_REGNUM)
1353 (compare:CC_NOOV (mult:SI
1354 (match_operand:SI 2 "s_register_operand" "r")
1355 (match_operand:SI 1 "s_register_operand" "r"))
1356 (const_int 0)))
1357 (set (match_operand:SI 0 "s_register_operand" "=r")
1358 (mult:SI (match_dup 2) (match_dup 1)))]
1359 "TARGET_ARM && arm_arch6 && optimize_size"
3ef90e77 1360 "muls%?\\t%0, %2, %1"
cffb2a26 1361 [(set_attr "conds" "set")
9da0ec36 1362 (set_attr "type" "muls")]
cffb2a26 1363)
9c08d1fa 1364
f7fbdd4a 1365(define_insn "*mulsi_compare0_scratch"
bd5b4116 1366 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1367 (compare:CC_NOOV (mult:SI
1368 (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1369 (match_operand:SI 1 "s_register_operand" "%0,r"))
9c08d1fa 1370 (const_int 0)))
1371 (clobber (match_scratch:SI 0 "=&r,&r"))]
58d7d654 1372 "TARGET_ARM && !arm_arch6"
3ef90e77 1373 "muls%?\\t%0, %2, %1"
58d7d654 1374 [(set_attr "conds" "set")
9da0ec36 1375 (set_attr "type" "muls")]
58d7d654 1376)
1377
1378(define_insn "*mulsi_compare0_scratch_v6"
1379 [(set (reg:CC_NOOV CC_REGNUM)
1380 (compare:CC_NOOV (mult:SI
1381 (match_operand:SI 2 "s_register_operand" "r")
1382 (match_operand:SI 1 "s_register_operand" "r"))
1383 (const_int 0)))
1384 (clobber (match_scratch:SI 0 "=r"))]
1385 "TARGET_ARM && arm_arch6 && optimize_size"
3ef90e77 1386 "muls%?\\t%0, %2, %1"
cffb2a26 1387 [(set_attr "conds" "set")
9da0ec36 1388 (set_attr "type" "muls")]
cffb2a26 1389)
9c08d1fa 1390
b11cae9e 1391;; Unnamed templates to match MLA instruction.
1392
f7fbdd4a 1393(define_insn "*mulsi3addsi"
9c08d1fa 1394 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
c8f69309 1395 (plus:SI
9c08d1fa 1396 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1397 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1398 (match_operand:SI 3 "s_register_operand" "r,r,0,0")))]
58d7d654 1399 "TARGET_32BIT && !arm_arch6"
1400 "mla%?\\t%0, %2, %1, %3"
9da0ec36 1401 [(set_attr "type" "mla")
58d7d654 1402 (set_attr "predicable" "yes")]
1403)
1404
1405(define_insn "*mulsi3addsi_v6"
1406 [(set (match_operand:SI 0 "s_register_operand" "=r")
1407 (plus:SI
1408 (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1409 (match_operand:SI 1 "s_register_operand" "r"))
1410 (match_operand:SI 3 "s_register_operand" "r")))]
1411 "TARGET_32BIT && arm_arch6"
f7fbdd4a 1412 "mla%?\\t%0, %2, %1, %3"
9da0ec36 1413 [(set_attr "type" "mla")
d952d547 1414 (set_attr "predicable" "yes")
1415 (set_attr "predicable_short_it" "no")]
0d66636f 1416)
b11cae9e 1417
f7fbdd4a 1418(define_insn "*mulsi3addsi_compare0"
bd5b4116 1419 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1420 (compare:CC_NOOV
1421 (plus:SI (mult:SI
1422 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1423 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1424 (match_operand:SI 3 "s_register_operand" "r,r,0,0"))
215b30b3 1425 (const_int 0)))
9c08d1fa 1426 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1427 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1428 (match_dup 3)))]
58d7d654 1429 "TARGET_ARM && arm_arch6"
3ef90e77 1430 "mlas%?\\t%0, %2, %1, %3"
58d7d654 1431 [(set_attr "conds" "set")
9da0ec36 1432 (set_attr "type" "mlas")]
58d7d654 1433)
1434
1435(define_insn "*mulsi3addsi_compare0_v6"
1436 [(set (reg:CC_NOOV CC_REGNUM)
1437 (compare:CC_NOOV
1438 (plus:SI (mult:SI
1439 (match_operand:SI 2 "s_register_operand" "r")
1440 (match_operand:SI 1 "s_register_operand" "r"))
1441 (match_operand:SI 3 "s_register_operand" "r"))
1442 (const_int 0)))
1443 (set (match_operand:SI 0 "s_register_operand" "=r")
1444 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1445 (match_dup 3)))]
1446 "TARGET_ARM && arm_arch6 && optimize_size"
3ef90e77 1447 "mlas%?\\t%0, %2, %1, %3"
0d66636f 1448 [(set_attr "conds" "set")
9da0ec36 1449 (set_attr "type" "mlas")]
0d66636f 1450)
9c08d1fa 1451
f7fbdd4a 1452(define_insn "*mulsi3addsi_compare0_scratch"
bd5b4116 1453 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1454 (compare:CC_NOOV
1455 (plus:SI (mult:SI
1456 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1457 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
215b30b3 1458 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1459 (const_int 0)))
9c08d1fa 1460 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
58d7d654 1461 "TARGET_ARM && !arm_arch6"
3ef90e77 1462 "mlas%?\\t%0, %2, %1, %3"
58d7d654 1463 [(set_attr "conds" "set")
9da0ec36 1464 (set_attr "type" "mlas")]
58d7d654 1465)
1466
1467(define_insn "*mulsi3addsi_compare0_scratch_v6"
1468 [(set (reg:CC_NOOV CC_REGNUM)
1469 (compare:CC_NOOV
1470 (plus:SI (mult:SI
1471 (match_operand:SI 2 "s_register_operand" "r")
1472 (match_operand:SI 1 "s_register_operand" "r"))
1473 (match_operand:SI 3 "s_register_operand" "r"))
1474 (const_int 0)))
1475 (clobber (match_scratch:SI 0 "=r"))]
1476 "TARGET_ARM && arm_arch6 && optimize_size"
3ef90e77 1477 "mlas%?\\t%0, %2, %1, %3"
cffb2a26 1478 [(set_attr "conds" "set")
9da0ec36 1479 (set_attr "type" "mlas")]
cffb2a26 1480)
f7fbdd4a 1481
89545238 1482(define_insn "*mulsi3subsi"
1483 [(set (match_operand:SI 0 "s_register_operand" "=r")
1484 (minus:SI
1485 (match_operand:SI 3 "s_register_operand" "r")
1486 (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1487 (match_operand:SI 1 "s_register_operand" "r"))))]
1488 "TARGET_32BIT && arm_arch_thumb2"
1489 "mls%?\\t%0, %2, %1, %3"
9da0ec36 1490 [(set_attr "type" "mla")
d952d547 1491 (set_attr "predicable" "yes")
1492 (set_attr "predicable_short_it" "no")]
89545238 1493)
1494
5cdca009 1495(define_expand "maddsidi4"
1496 [(set (match_operand:DI 0 "s_register_operand" "")
1497 (plus:DI
1498 (mult:DI
1499 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1500 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1501 (match_operand:DI 3 "s_register_operand" "")))]
1502 "TARGET_32BIT && arm_arch3m"
1503 "")
82b85d08 1504
1505(define_insn "*mulsidi3adddi"
fe8dbf85 1506 [(set (match_operand:DI 0 "s_register_operand" "=&r")
82b85d08 1507 (plus:DI
215b30b3 1508 (mult:DI
fe8dbf85 1509 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1510 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1511 (match_operand:DI 1 "s_register_operand" "0")))]
58d7d654 1512 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1513 "smlal%?\\t%Q0, %R0, %3, %2"
9da0ec36 1514 [(set_attr "type" "smlal")
58d7d654 1515 (set_attr "predicable" "yes")]
1516)
1517
1518(define_insn "*mulsidi3adddi_v6"
1519 [(set (match_operand:DI 0 "s_register_operand" "=r")
1520 (plus:DI
1521 (mult:DI
1522 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1523 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1524 (match_operand:DI 1 "s_register_operand" "0")))]
1525 "TARGET_32BIT && arm_arch6"
fe8dbf85 1526 "smlal%?\\t%Q0, %R0, %3, %2"
9da0ec36 1527 [(set_attr "type" "smlal")
d952d547 1528 (set_attr "predicable" "yes")
1529 (set_attr "predicable_short_it" "no")]
0d66636f 1530)
82b85d08 1531
957788b0 1532;; 32x32->64 widening multiply.
1533;; As with mulsi3, the only difference between the v3-5 and v6+
1534;; versions of these patterns is the requirement that the output not
1535;; overlap the inputs, but that still means we have to have a named
1536;; expander and two different starred insns.
1537
1538(define_expand "mulsidi3"
1539 [(set (match_operand:DI 0 "s_register_operand" "")
1540 (mult:DI
1541 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1542 (sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1543 "TARGET_32BIT && arm_arch3m"
1544 ""
1545)
1546
1547(define_insn "*mulsidi3_nov6"
f7fbdd4a 1548 [(set (match_operand:DI 0 "s_register_operand" "=&r")
215b30b3 1549 (mult:DI
1550 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1551 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
58d7d654 1552 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1553 "smull%?\\t%Q0, %R0, %1, %2"
9da0ec36 1554 [(set_attr "type" "smull")
58d7d654 1555 (set_attr "predicable" "yes")]
1556)
1557
957788b0 1558(define_insn "*mulsidi3_v6"
58d7d654 1559 [(set (match_operand:DI 0 "s_register_operand" "=r")
1560 (mult:DI
1561 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1562 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1563 "TARGET_32BIT && arm_arch6"
97499065 1564 "smull%?\\t%Q0, %R0, %1, %2"
9da0ec36 1565 [(set_attr "type" "smull")
d952d547 1566 (set_attr "predicable" "yes")
1567 (set_attr "predicable_short_it" "no")]
0d66636f 1568)
f7fbdd4a 1569
957788b0 1570(define_expand "umulsidi3"
1571 [(set (match_operand:DI 0 "s_register_operand" "")
1572 (mult:DI
1573 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1574 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1575 "TARGET_32BIT && arm_arch3m"
1576 ""
1577)
1578
1579(define_insn "*umulsidi3_nov6"
f7fbdd4a 1580 [(set (match_operand:DI 0 "s_register_operand" "=&r")
215b30b3 1581 (mult:DI
1582 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1583 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
58d7d654 1584 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1585 "umull%?\\t%Q0, %R0, %1, %2"
9da0ec36 1586 [(set_attr "type" "umull")
58d7d654 1587 (set_attr "predicable" "yes")]
1588)
1589
957788b0 1590(define_insn "*umulsidi3_v6"
58d7d654 1591 [(set (match_operand:DI 0 "s_register_operand" "=r")
1592 (mult:DI
1593 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1594 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1595 "TARGET_32BIT && arm_arch6"
97499065 1596 "umull%?\\t%Q0, %R0, %1, %2"
9da0ec36 1597 [(set_attr "type" "umull")
d952d547 1598 (set_attr "predicable" "yes")
1599 (set_attr "predicable_short_it" "no")]
0d66636f 1600)
b11cae9e 1601
5cdca009 1602(define_expand "umaddsidi4"
1603 [(set (match_operand:DI 0 "s_register_operand" "")
1604 (plus:DI
1605 (mult:DI
1606 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1607 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1608 (match_operand:DI 3 "s_register_operand" "")))]
1609 "TARGET_32BIT && arm_arch3m"
1610 "")
82b85d08 1611
1612(define_insn "*umulsidi3adddi"
8ead09f9 1613 [(set (match_operand:DI 0 "s_register_operand" "=&r")
82b85d08 1614 (plus:DI
215b30b3 1615 (mult:DI
fe8dbf85 1616 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1617 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1618 (match_operand:DI 1 "s_register_operand" "0")))]
58d7d654 1619 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1620 "umlal%?\\t%Q0, %R0, %3, %2"
9da0ec36 1621 [(set_attr "type" "umlal")
58d7d654 1622 (set_attr "predicable" "yes")]
1623)
1624
1625(define_insn "*umulsidi3adddi_v6"
1626 [(set (match_operand:DI 0 "s_register_operand" "=r")
1627 (plus:DI
1628 (mult:DI
1629 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1630 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1631 (match_operand:DI 1 "s_register_operand" "0")))]
1632 "TARGET_32BIT && arm_arch6"
fe8dbf85 1633 "umlal%?\\t%Q0, %R0, %3, %2"
9da0ec36 1634 [(set_attr "type" "umlal")
d952d547 1635 (set_attr "predicable" "yes")
1636 (set_attr "predicable_short_it" "no")]
0d66636f 1637)
82b85d08 1638
957788b0 1639(define_expand "smulsi3_highpart"
1640 [(parallel
1641 [(set (match_operand:SI 0 "s_register_operand" "")
1642 (truncate:SI
1643 (lshiftrt:DI
1644 (mult:DI
1645 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1646 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1647 (const_int 32))))
1648 (clobber (match_scratch:SI 3 ""))])]
1649 "TARGET_32BIT && arm_arch3m"
1650 ""
1651)
1652
1653(define_insn "*smulsi3_highpart_nov6"
f082f1c4 1654 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1655 (truncate:SI
1656 (lshiftrt:DI
215b30b3 1657 (mult:DI
e5fea38e 1658 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
215b30b3 1659 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
f082f1c4 1660 (const_int 32))))
1661 (clobber (match_scratch:SI 3 "=&r,&r"))]
58d7d654 1662 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1663 "smull%?\\t%3, %0, %2, %1"
9da0ec36 1664 [(set_attr "type" "smull")
58d7d654 1665 (set_attr "predicable" "yes")]
1666)
1667
957788b0 1668(define_insn "*smulsi3_highpart_v6"
58d7d654 1669 [(set (match_operand:SI 0 "s_register_operand" "=r")
1670 (truncate:SI
1671 (lshiftrt:DI
1672 (mult:DI
1673 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1674 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1675 (const_int 32))))
1676 (clobber (match_scratch:SI 3 "=r"))]
1677 "TARGET_32BIT && arm_arch6"
f082f1c4 1678 "smull%?\\t%3, %0, %2, %1"
9da0ec36 1679 [(set_attr "type" "smull")
d952d547 1680 (set_attr "predicable" "yes")
1681 (set_attr "predicable_short_it" "no")]
cffb2a26 1682)
f082f1c4 1683
957788b0 1684(define_expand "umulsi3_highpart"
1685 [(parallel
1686 [(set (match_operand:SI 0 "s_register_operand" "")
1687 (truncate:SI
1688 (lshiftrt:DI
1689 (mult:DI
1690 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1691 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1692 (const_int 32))))
1693 (clobber (match_scratch:SI 3 ""))])]
1694 "TARGET_32BIT && arm_arch3m"
1695 ""
1696)
1697
1698(define_insn "*umulsi3_highpart_nov6"
f082f1c4 1699 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1700 (truncate:SI
1701 (lshiftrt:DI
215b30b3 1702 (mult:DI
e5fea38e 1703 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
215b30b3 1704 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
f082f1c4 1705 (const_int 32))))
1706 (clobber (match_scratch:SI 3 "=&r,&r"))]
58d7d654 1707 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1708 "umull%?\\t%3, %0, %2, %1"
9da0ec36 1709 [(set_attr "type" "umull")
58d7d654 1710 (set_attr "predicable" "yes")]
1711)
1712
957788b0 1713(define_insn "*umulsi3_highpart_v6"
58d7d654 1714 [(set (match_operand:SI 0 "s_register_operand" "=r")
1715 (truncate:SI
1716 (lshiftrt:DI
1717 (mult:DI
1718 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1719 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1720 (const_int 32))))
1721 (clobber (match_scratch:SI 3 "=r"))]
1722 "TARGET_32BIT && arm_arch6"
f082f1c4 1723 "umull%?\\t%3, %0, %2, %1"
9da0ec36 1724 [(set_attr "type" "umull")
d952d547 1725 (set_attr "predicable" "yes")
1726 (set_attr "predicable_short_it" "no")]
cffb2a26 1727)
f082f1c4 1728
331beb1a 1729(define_insn "mulhisi3"
1730 [(set (match_operand:SI 0 "s_register_operand" "=r")
1731 (mult:SI (sign_extend:SI
1732 (match_operand:HI 1 "s_register_operand" "%r"))
1733 (sign_extend:SI
1734 (match_operand:HI 2 "s_register_operand" "r"))))]
25f905c2 1735 "TARGET_DSP_MULTIPLY"
61a2d04c 1736 "smulbb%?\\t%0, %1, %2"
9da0ec36 1737 [(set_attr "type" "smulxy")
fec538d9 1738 (set_attr "predicable" "yes")]
1739)
1740
1741(define_insn "*mulhisi3tb"
1742 [(set (match_operand:SI 0 "s_register_operand" "=r")
1743 (mult:SI (ashiftrt:SI
1744 (match_operand:SI 1 "s_register_operand" "r")
1745 (const_int 16))
1746 (sign_extend:SI
1747 (match_operand:HI 2 "s_register_operand" "r"))))]
25f905c2 1748 "TARGET_DSP_MULTIPLY"
fec538d9 1749 "smultb%?\\t%0, %1, %2"
9da0ec36 1750 [(set_attr "type" "smulxy")
d952d547 1751 (set_attr "predicable" "yes")
1752 (set_attr "predicable_short_it" "no")]
fec538d9 1753)
1754
1755(define_insn "*mulhisi3bt"
1756 [(set (match_operand:SI 0 "s_register_operand" "=r")
1757 (mult:SI (sign_extend:SI
1758 (match_operand:HI 1 "s_register_operand" "r"))
1759 (ashiftrt:SI
1760 (match_operand:SI 2 "s_register_operand" "r")
1761 (const_int 16))))]
25f905c2 1762 "TARGET_DSP_MULTIPLY"
fec538d9 1763 "smulbt%?\\t%0, %1, %2"
9da0ec36 1764 [(set_attr "type" "smulxy")
d952d547 1765 (set_attr "predicable" "yes")
1766 (set_attr "predicable_short_it" "no")]
fec538d9 1767)
1768
1769(define_insn "*mulhisi3tt"
1770 [(set (match_operand:SI 0 "s_register_operand" "=r")
1771 (mult:SI (ashiftrt:SI
1772 (match_operand:SI 1 "s_register_operand" "r")
1773 (const_int 16))
1774 (ashiftrt:SI
1775 (match_operand:SI 2 "s_register_operand" "r")
1776 (const_int 16))))]
25f905c2 1777 "TARGET_DSP_MULTIPLY"
fec538d9 1778 "smultt%?\\t%0, %1, %2"
9da0ec36 1779 [(set_attr "type" "smulxy")
d952d547 1780 (set_attr "predicable" "yes")
1781 (set_attr "predicable_short_it" "no")]
331beb1a 1782)
1783
5cdca009 1784(define_insn "maddhisi4"
331beb1a 1785 [(set (match_operand:SI 0 "s_register_operand" "=r")
cfa6c608 1786 (plus:SI (mult:SI (sign_extend:SI
1787 (match_operand:HI 1 "s_register_operand" "r"))
331beb1a 1788 (sign_extend:SI
cfa6c608 1789 (match_operand:HI 2 "s_register_operand" "r")))
1790 (match_operand:SI 3 "s_register_operand" "r")))]
25f905c2 1791 "TARGET_DSP_MULTIPLY"
5cdca009 1792 "smlabb%?\\t%0, %1, %2, %3"
9da0ec36 1793 [(set_attr "type" "smlaxy")
d952d547 1794 (set_attr "predicable" "yes")
1795 (set_attr "predicable_short_it" "no")]
331beb1a 1796)
1797
9a92f368 1798;; Note: there is no maddhisi4ibt because this one is canonical form
1799(define_insn "*maddhisi4tb"
1800 [(set (match_operand:SI 0 "s_register_operand" "=r")
1801 (plus:SI (mult:SI (ashiftrt:SI
1802 (match_operand:SI 1 "s_register_operand" "r")
1803 (const_int 16))
1804 (sign_extend:SI
1805 (match_operand:HI 2 "s_register_operand" "r")))
1806 (match_operand:SI 3 "s_register_operand" "r")))]
1807 "TARGET_DSP_MULTIPLY"
1808 "smlatb%?\\t%0, %1, %2, %3"
9da0ec36 1809 [(set_attr "type" "smlaxy")
d952d547 1810 (set_attr "predicable" "yes")
1811 (set_attr "predicable_short_it" "no")]
9a92f368 1812)
1813
1814(define_insn "*maddhisi4tt"
1815 [(set (match_operand:SI 0 "s_register_operand" "=r")
1816 (plus:SI (mult:SI (ashiftrt:SI
1817 (match_operand:SI 1 "s_register_operand" "r")
1818 (const_int 16))
1819 (ashiftrt:SI
1820 (match_operand:SI 2 "s_register_operand" "r")
1821 (const_int 16)))
1822 (match_operand:SI 3 "s_register_operand" "r")))]
1823 "TARGET_DSP_MULTIPLY"
1824 "smlatt%?\\t%0, %1, %2, %3"
9da0ec36 1825 [(set_attr "type" "smlaxy")
d952d547 1826 (set_attr "predicable" "yes")
1827 (set_attr "predicable_short_it" "no")]
9a92f368 1828)
1829
aff5fb4d 1830(define_insn "maddhidi4"
331beb1a 1831 [(set (match_operand:DI 0 "s_register_operand" "=r")
1832 (plus:DI
331beb1a 1833 (mult:DI (sign_extend:DI
d952d547 1834 (match_operand:HI 1 "s_register_operand" "r"))
331beb1a 1835 (sign_extend:DI
cfa6c608 1836 (match_operand:HI 2 "s_register_operand" "r")))
1837 (match_operand:DI 3 "s_register_operand" "0")))]
25f905c2 1838 "TARGET_DSP_MULTIPLY"
5cdca009 1839 "smlalbb%?\\t%Q0, %R0, %1, %2"
9da0ec36 1840 [(set_attr "type" "smlalxy")
d952d547 1841 (set_attr "predicable" "yes")
1842 (set_attr "predicable_short_it" "no")])
331beb1a 1843
9a92f368 1844;; Note: there is no maddhidi4ibt because this one is canonical form
1845(define_insn "*maddhidi4tb"
1846 [(set (match_operand:DI 0 "s_register_operand" "=r")
1847 (plus:DI
1848 (mult:DI (sign_extend:DI
1849 (ashiftrt:SI
1850 (match_operand:SI 1 "s_register_operand" "r")
1851 (const_int 16)))
1852 (sign_extend:DI
1853 (match_operand:HI 2 "s_register_operand" "r")))
1854 (match_operand:DI 3 "s_register_operand" "0")))]
1855 "TARGET_DSP_MULTIPLY"
1856 "smlaltb%?\\t%Q0, %R0, %1, %2"
9da0ec36 1857 [(set_attr "type" "smlalxy")
d952d547 1858 (set_attr "predicable" "yes")
1859 (set_attr "predicable_short_it" "no")])
9a92f368 1860
1861(define_insn "*maddhidi4tt"
1862 [(set (match_operand:DI 0 "s_register_operand" "=r")
1863 (plus:DI
1864 (mult:DI (sign_extend:DI
1865 (ashiftrt:SI
1866 (match_operand:SI 1 "s_register_operand" "r")
1867 (const_int 16)))
1868 (sign_extend:DI
1869 (ashiftrt:SI
1870 (match_operand:SI 2 "s_register_operand" "r")
1871 (const_int 16))))
1872 (match_operand:DI 3 "s_register_operand" "0")))]
1873 "TARGET_DSP_MULTIPLY"
1874 "smlaltt%?\\t%Q0, %R0, %1, %2"
9da0ec36 1875 [(set_attr "type" "smlalxy")
d952d547 1876 (set_attr "predicable" "yes")
1877 (set_attr "predicable_short_it" "no")])
9a92f368 1878
604f3a0a 1879(define_expand "mulsf3"
1880 [(set (match_operand:SF 0 "s_register_operand" "")
1881 (mult:SF (match_operand:SF 1 "s_register_operand" "")
d86c91f6 1882 (match_operand:SF 2 "s_register_operand" "")))]
25f905c2 1883 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1884 "
604f3a0a 1885")
1886
604f3a0a 1887(define_expand "muldf3"
1888 [(set (match_operand:DF 0 "s_register_operand" "")
1889 (mult:DF (match_operand:DF 1 "s_register_operand" "")
d86c91f6 1890 (match_operand:DF 2 "s_register_operand" "")))]
a50d7267 1891 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 1892 "
604f3a0a 1893")
b11cae9e 1894\f
1895;; Division insns
1896
7db9af5d 1897(define_expand "divsf3"
1898 [(set (match_operand:SF 0 "s_register_operand" "")
d86c91f6 1899 (div:SF (match_operand:SF 1 "s_register_operand" "")
1900 (match_operand:SF 2 "s_register_operand" "")))]
994606f8 1901 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
7db9af5d 1902 "")
9c08d1fa 1903
7db9af5d 1904(define_expand "divdf3"
1905 [(set (match_operand:DF 0 "s_register_operand" "")
d86c91f6 1906 (div:DF (match_operand:DF 1 "s_register_operand" "")
1907 (match_operand:DF 2 "s_register_operand" "")))]
994606f8 1908 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
7db9af5d 1909 "")
b11cae9e 1910\f
1911;; Boolean and,ior,xor insns
1912
f6ebffac 1913;; Split up double word logical operations
1914
1915;; Split up simple DImode logical operations. Simply perform the logical
1916;; operation on the upper and lower halves of the registers.
1917(define_split
1918 [(set (match_operand:DI 0 "s_register_operand" "")
1919 (match_operator:DI 6 "logical_binary_operator"
1920 [(match_operand:DI 1 "s_register_operand" "")
1921 (match_operand:DI 2 "s_register_operand" "")]))]
25f905c2 1922 "TARGET_32BIT && reload_completed
e2669ea7 1923 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))
25f905c2 1924 && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
f6ebffac 1925 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1926 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1927 "
215b30b3 1928 {
1929 operands[3] = gen_highpart (SImode, operands[0]);
1930 operands[0] = gen_lowpart (SImode, operands[0]);
1931 operands[4] = gen_highpart (SImode, operands[1]);
1932 operands[1] = gen_lowpart (SImode, operands[1]);
1933 operands[5] = gen_highpart (SImode, operands[2]);
1934 operands[2] = gen_lowpart (SImode, operands[2]);
1935 }"
1936)
f6ebffac 1937
f6ebffac 1938(define_split
1939 [(set (match_operand:DI 0 "s_register_operand" "")
1940 (match_operator:DI 6 "logical_binary_operator"
1941 [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1942 (match_operand:DI 1 "s_register_operand" "")]))]
25f905c2 1943 "TARGET_32BIT && reload_completed"
f6ebffac 1944 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1945 (set (match_dup 3) (match_op_dup:SI 6
1946 [(ashiftrt:SI (match_dup 2) (const_int 31))
1947 (match_dup 4)]))]
1948 "
215b30b3 1949 {
1950 operands[3] = gen_highpart (SImode, operands[0]);
1951 operands[0] = gen_lowpart (SImode, operands[0]);
1952 operands[4] = gen_highpart (SImode, operands[1]);
1953 operands[1] = gen_lowpart (SImode, operands[1]);
1954 operands[5] = gen_highpart (SImode, operands[2]);
1955 operands[2] = gen_lowpart (SImode, operands[2]);
1956 }"
1957)
f6ebffac 1958
f6ebffac 1959;; The zero extend of operand 2 means we can just copy the high part of
1960;; operand1 into operand0.
1961(define_split
1962 [(set (match_operand:DI 0 "s_register_operand" "")
1963 (ior:DI
1964 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1965 (match_operand:DI 1 "s_register_operand" "")))]
25f905c2 1966 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
f6ebffac 1967 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1968 (set (match_dup 3) (match_dup 4))]
1969 "
215b30b3 1970 {
1971 operands[4] = gen_highpart (SImode, operands[1]);
1972 operands[3] = gen_highpart (SImode, operands[0]);
1973 operands[0] = gen_lowpart (SImode, operands[0]);
1974 operands[1] = gen_lowpart (SImode, operands[1]);
1975 }"
1976)
f6ebffac 1977
1978;; The zero extend of operand 2 means we can just copy the high part of
1979;; operand1 into operand0.
1980(define_split
1981 [(set (match_operand:DI 0 "s_register_operand" "")
1982 (xor:DI
1983 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1984 (match_operand:DI 1 "s_register_operand" "")))]
25f905c2 1985 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
f6ebffac 1986 [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1987 (set (match_dup 3) (match_dup 4))]
1988 "
215b30b3 1989 {
1990 operands[4] = gen_highpart (SImode, operands[1]);
1991 operands[3] = gen_highpart (SImode, operands[0]);
1992 operands[0] = gen_lowpart (SImode, operands[0]);
1993 operands[1] = gen_lowpart (SImode, operands[1]);
1994 }"
1995)
f6ebffac 1996
e2669ea7 1997(define_expand "anddi3"
1998 [(set (match_operand:DI 0 "s_register_operand" "")
1999 (and:DI (match_operand:DI 1 "s_register_operand" "")
2000 (match_operand:DI 2 "neon_inv_logic_op2" "")))]
2001 "TARGET_32BIT"
2002 ""
2003)
2004
f6bbdcf6 2005(define_insn_and_split "*anddi3_insn"
0a314dcd 2006 [(set (match_operand:DI 0 "s_register_operand" "=w,w ,&r,&r,&r,&r,?w,?w")
2007 (and:DI (match_operand:DI 1 "s_register_operand" "%w,0 ,0 ,r ,0 ,r ,w ,0")
2008 (match_operand:DI 2 "arm_anddi_operand_neon" "w ,DL,r ,r ,De,De,w ,DL")))]
f6bbdcf6 2009 "TARGET_32BIT && !TARGET_IWMMXT"
2010{
2011 switch (which_alternative)
2012 {
0a314dcd 2013 case 0: /* fall through */
2014 case 6: return "vand\t%P0, %P1, %P2";
2015 case 1: /* fall through */
2016 case 7: return neon_output_logic_immediate ("vand", &operands[2],
2017 DImode, 1, VALID_NEON_QREG_MODE (DImode));
f6bbdcf6 2018 case 2:
0a314dcd 2019 case 3:
2020 case 4:
f6bbdcf6 2021 case 5: /* fall through */
0a314dcd 2022 return "#";
f6bbdcf6 2023 default: gcc_unreachable ();
2024 }
2025}
0a314dcd 2026 "TARGET_32BIT && !TARGET_IWMMXT && reload_completed
2027 && !(IS_VFP_REGNUM (REGNO (operands[0])))"
f6bbdcf6 2028 [(set (match_dup 3) (match_dup 4))
2029 (set (match_dup 5) (match_dup 6))]
2030 "
2031 {
2032 operands[3] = gen_lowpart (SImode, operands[0]);
2033 operands[5] = gen_highpart (SImode, operands[0]);
2034
2035 operands[4] = simplify_gen_binary (AND, SImode,
2036 gen_lowpart (SImode, operands[1]),
2037 gen_lowpart (SImode, operands[2]));
2038 operands[6] = simplify_gen_binary (AND, SImode,
2039 gen_highpart (SImode, operands[1]),
2040 gen_highpart_mode (SImode, DImode, operands[2]));
2041
2042 }"
32093010 2043 [(set_attr "type" "neon_logic,neon_logic,multiple,multiple,\
2044 multiple,multiple,neon_logic,neon_logic")
0a314dcd 2045 (set_attr "arch" "neon_for_64bits,neon_for_64bits,*,*,*,*,
f6bbdcf6 2046 avoid_neon_for_64bits,avoid_neon_for_64bits")
0a314dcd 2047 (set_attr "length" "*,*,8,8,8,8,*,*")
2048 ]
215b30b3 2049)
b11cae9e 2050
a0f94409 2051(define_insn_and_split "*anddi_zesidi_di"
9c08d1fa 2052 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2053 (and:DI (zero_extend:DI
2054 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 2055 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2056 "TARGET_32BIT"
f6ebffac 2057 "#"
25f905c2 2058 "TARGET_32BIT && reload_completed"
a0f94409 2059 ; The zero extend of operand 2 clears the high word of the output
2060 ; operand.
2061 [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
2062 (set (match_dup 3) (const_int 0))]
2063 "
2064 {
2065 operands[3] = gen_highpart (SImode, operands[0]);
2066 operands[0] = gen_lowpart (SImode, operands[0]);
2067 operands[1] = gen_lowpart (SImode, operands[1]);
2068 }"
1b7da4ac 2069 [(set_attr "length" "8")
2070 (set_attr "type" "multiple")]
215b30b3 2071)
b11cae9e 2072
f7fbdd4a 2073(define_insn "*anddi_sesdi_di"
cffb2a26 2074 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 2075 (and:DI (sign_extend:DI
2076 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 2077 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2078 "TARGET_32BIT"
f6ebffac 2079 "#"
1b7da4ac 2080 [(set_attr "length" "8")
2081 (set_attr "type" "multiple")]
cffb2a26 2082)
b11cae9e 2083
87b22bf7 2084(define_expand "andsi3"
cffb2a26 2085 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2086 (and:SI (match_operand:SI 1 "s_register_operand" "")
2087 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 2088 "TARGET_EITHER"
87b22bf7 2089 "
25f905c2 2090 if (TARGET_32BIT)
87b22bf7 2091 {
0438d37f 2092 if (CONST_INT_P (operands[2]))
cffb2a26 2093 {
47b5b27b 2094 if (INTVAL (operands[2]) == 255 && arm_arch6)
2095 {
2096 operands[1] = convert_to_mode (QImode, operands[1], 1);
2097 emit_insn (gen_thumb2_zero_extendqisi2_v6 (operands[0],
2098 operands[1]));
17202aa5 2099 DONE;
47b5b27b 2100 }
17202aa5 2101 else if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[2]), AND))
2102 operands[2] = force_reg (SImode, operands[2]);
47b5b27b 2103 else
17202aa5 2104 {
2105 arm_split_constant (AND, SImode, NULL_RTX,
2106 INTVAL (operands[2]), operands[0],
2107 operands[1],
2108 optimize && can_create_pseudo_p ());
615caa51 2109
17202aa5 2110 DONE;
2111 }
cffb2a26 2112 }
87b22bf7 2113 }
25f905c2 2114 else /* TARGET_THUMB1 */
cffb2a26 2115 {
0438d37f 2116 if (!CONST_INT_P (operands[2]))
923ffadb 2117 {
2118 rtx tmp = force_reg (SImode, operands[2]);
2119 if (rtx_equal_p (operands[0], operands[1]))
2120 operands[2] = tmp;
2121 else
2122 {
2123 operands[2] = operands[1];
2124 operands[1] = tmp;
2125 }
2126 }
cffb2a26 2127 else
2128 {
2129 int i;
2130
215b30b3 2131 if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
cffb2a26 2132 {
215b30b3 2133 operands[2] = force_reg (SImode,
2134 GEN_INT (~INTVAL (operands[2])));
cffb2a26 2135
747b7458 2136 emit_insn (gen_thumb1_bicsi3 (operands[0], operands[2], operands[1]));
cffb2a26 2137
2138 DONE;
2139 }
87b22bf7 2140
cffb2a26 2141 for (i = 9; i <= 31; i++)
2142 {
db2faf44 2143 if ((HOST_WIDE_INT_1 << i) - 1 == INTVAL (operands[2]))
cffb2a26 2144 {
2145 emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
2146 const0_rtx));
2147 DONE;
2148 }
db2faf44 2149 else if ((HOST_WIDE_INT_1 << i) - 1
215b30b3 2150 == ~INTVAL (operands[2]))
cffb2a26 2151 {
2152 rtx shift = GEN_INT (i);
2153 rtx reg = gen_reg_rtx (SImode);
2154
2155 emit_insn (gen_lshrsi3 (reg, operands[1], shift));
2156 emit_insn (gen_ashlsi3 (operands[0], reg, shift));
2157
2158 DONE;
2159 }
2160 }
2161
2162 operands[2] = force_reg (SImode, operands[2]);
2163 }
215b30b3 2164 }
2165 "
cffb2a26 2166)
2167
25f905c2 2168; ??? Check split length for Thumb-2
a0f94409 2169(define_insn_and_split "*arm_andsi3_insn"
29e234a3 2170 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r,r,r")
2171 (and:SI (match_operand:SI 1 "s_register_operand" "%r,0,r,r,r")
2172 (match_operand:SI 2 "reg_or_int_operand" "I,l,K,r,?n")))]
25f905c2 2173 "TARGET_32BIT"
5565501b 2174 "@
29e234a3 2175 and%?\\t%0, %1, %2
5565501b 2176 and%?\\t%0, %1, %2
87b22bf7 2177 bic%?\\t%0, %1, #%B2
65f68e55 2178 and%?\\t%0, %1, %2
87b22bf7 2179 #"
25f905c2 2180 "TARGET_32BIT
0438d37f 2181 && CONST_INT_P (operands[2])
a0f94409 2182 && !(const_ok_for_arm (INTVAL (operands[2]))
2183 || const_ok_for_arm (~INTVAL (operands[2])))"
2184 [(clobber (const_int 0))]
2185 "
96f57e36 2186 arm_split_constant (AND, SImode, curr_insn,
2187 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 2188 DONE;
2189 "
29e234a3 2190 [(set_attr "length" "4,4,4,4,16")
65f68e55 2191 (set_attr "predicable" "yes")
29e234a3 2192 (set_attr "predicable_short_it" "no,yes,no,no,no")
d82e788e 2193 (set_attr "type" "logic_imm,logic_imm,logic_reg,logic_reg,logic_imm")]
cffb2a26 2194)
2195
f7fbdd4a 2196(define_insn "*andsi3_compare0"
bd5b4116 2197 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 2198 (compare:CC_NOOV
65f68e55 2199 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
2200 (match_operand:SI 2 "arm_not_operand" "I,K,r"))
5565501b 2201 (const_int 0)))
65f68e55 2202 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9c08d1fa 2203 (and:SI (match_dup 1) (match_dup 2)))]
25f905c2 2204 "TARGET_32BIT"
5565501b 2205 "@
3ef90e77 2206 ands%?\\t%0, %1, %2
2207 bics%?\\t%0, %1, #%B2
2208 ands%?\\t%0, %1, %2"
65f68e55 2209 [(set_attr "conds" "set")
d82e788e 2210 (set_attr "type" "logics_imm,logics_imm,logics_reg")]
cffb2a26 2211)
9c08d1fa 2212
f7fbdd4a 2213(define_insn "*andsi3_compare0_scratch"
bd5b4116 2214 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 2215 (compare:CC_NOOV
65f68e55 2216 (and:SI (match_operand:SI 0 "s_register_operand" "r,r,r")
2217 (match_operand:SI 1 "arm_not_operand" "I,K,r"))
5565501b 2218 (const_int 0)))
65f68e55 2219 (clobber (match_scratch:SI 2 "=X,r,X"))]
25f905c2 2220 "TARGET_32BIT"
5565501b 2221 "@
2222 tst%?\\t%0, %1
3ef90e77 2223 bics%?\\t%2, %0, #%B1
65f68e55 2224 tst%?\\t%0, %1"
2225 [(set_attr "conds" "set")
d82e788e 2226 (set_attr "type" "logics_imm,logics_imm,logics_reg")]
0d66636f 2227)
9c08d1fa 2228
f7fbdd4a 2229(define_insn "*zeroextractsi_compare0_scratch"
bd5b4116 2230 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2231 (compare:CC_NOOV (zero_extract:SI
2232 (match_operand:SI 0 "s_register_operand" "r")
d952d547 2233 (match_operand 1 "const_int_operand" "n")
206ee9a2 2234 (match_operand 2 "const_int_operand" "n"))
9c08d1fa 2235 (const_int 0)))]
25f905c2 2236 "TARGET_32BIT
cffb2a26 2237 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
2238 && INTVAL (operands[1]) > 0
2239 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
2240 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
9c08d1fa 2241 "*
5c49a439 2242 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
2243 << INTVAL (operands[2]));
40dbec34 2244 output_asm_insn (\"tst%?\\t%0, %1\", operands);
e2348bcb 2245 return \"\";
0d66636f 2246 "
596e5e8f 2247 [(set_attr "conds" "set")
65f68e55 2248 (set_attr "predicable" "yes")
d952d547 2249 (set_attr "predicable_short_it" "no")
d82e788e 2250 (set_attr "type" "logics_imm")]
0d66636f 2251)
9c08d1fa 2252
f4462328 2253(define_insn_and_split "*ne_zeroextractsi"
c4034607 2254 [(set (match_operand:SI 0 "s_register_operand" "=r")
2255 (ne:SI (zero_extract:SI
2256 (match_operand:SI 1 "s_register_operand" "r")
2257 (match_operand:SI 2 "const_int_operand" "n")
2258 (match_operand:SI 3 "const_int_operand" "n"))
3b8c7f7a 2259 (const_int 0)))
2260 (clobber (reg:CC CC_REGNUM))]
25f905c2 2261 "TARGET_32BIT
cffb2a26 2262 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2263 && INTVAL (operands[2]) > 0
2264 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2265 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
f4462328 2266 "#"
25f905c2 2267 "TARGET_32BIT
f4462328 2268 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2269 && INTVAL (operands[2]) > 0
2270 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2271 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
2272 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2273 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2274 (const_int 0)))
2275 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2276 (set (match_dup 0)
2277 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2278 (match_dup 0) (const_int 1)))]
2279 "
2280 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
2281 << INTVAL (operands[3]));
2282 "
2283 [(set_attr "conds" "clob")
25f905c2 2284 (set (attr "length")
2285 (if_then_else (eq_attr "is_thumb" "yes")
2286 (const_int 12)
1b7da4ac 2287 (const_int 8)))
2288 (set_attr "type" "multiple")]
f4462328 2289)
2290
2291(define_insn_and_split "*ne_zeroextractsi_shifted"
2292 [(set (match_operand:SI 0 "s_register_operand" "=r")
2293 (ne:SI (zero_extract:SI
2294 (match_operand:SI 1 "s_register_operand" "r")
2295 (match_operand:SI 2 "const_int_operand" "n")
2296 (const_int 0))
2297 (const_int 0)))
2298 (clobber (reg:CC CC_REGNUM))]
2299 "TARGET_ARM"
2300 "#"
2301 "TARGET_ARM"
2302 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2303 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2304 (const_int 0)))
2305 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2306 (set (match_dup 0)
2307 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2308 (match_dup 0) (const_int 1)))]
2309 "
2310 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
2311 "
2312 [(set_attr "conds" "clob")
1b7da4ac 2313 (set_attr "length" "8")
2314 (set_attr "type" "multiple")]
f4462328 2315)
2316
2317(define_insn_and_split "*ite_ne_zeroextractsi"
2318 [(set (match_operand:SI 0 "s_register_operand" "=r")
2319 (if_then_else:SI (ne (zero_extract:SI
2320 (match_operand:SI 1 "s_register_operand" "r")
2321 (match_operand:SI 2 "const_int_operand" "n")
2322 (match_operand:SI 3 "const_int_operand" "n"))
2323 (const_int 0))
2324 (match_operand:SI 4 "arm_not_operand" "rIK")
2325 (const_int 0)))
2326 (clobber (reg:CC CC_REGNUM))]
2327 "TARGET_ARM
2328 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2329 && INTVAL (operands[2]) > 0
2330 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 2331 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2332 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 2333 "#"
2334 "TARGET_ARM
2335 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2336 && INTVAL (operands[2]) > 0
2337 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 2338 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2339 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 2340 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2341 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2342 (const_int 0)))
2343 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2344 (set (match_dup 0)
2345 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2346 (match_dup 0) (match_dup 4)))]
2347 "
c4034607 2348 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
f4462328 2349 << INTVAL (operands[3]));
2350 "
2351 [(set_attr "conds" "clob")
1b7da4ac 2352 (set_attr "length" "8")
2353 (set_attr "type" "multiple")]
f4462328 2354)
2355
2356(define_insn_and_split "*ite_ne_zeroextractsi_shifted"
2357 [(set (match_operand:SI 0 "s_register_operand" "=r")
2358 (if_then_else:SI (ne (zero_extract:SI
2359 (match_operand:SI 1 "s_register_operand" "r")
2360 (match_operand:SI 2 "const_int_operand" "n")
2361 (const_int 0))
2362 (const_int 0))
2363 (match_operand:SI 3 "arm_not_operand" "rIK")
2364 (const_int 0)))
2365 (clobber (reg:CC CC_REGNUM))]
f8d7bf2f 2366 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 2367 "#"
f8d7bf2f 2368 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 2369 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2370 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2371 (const_int 0)))
2372 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2373 (set (match_dup 0)
2374 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2375 (match_dup 0) (match_dup 3)))]
2376 "
2377 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
0d66636f 2378 "
2379 [(set_attr "conds" "clob")
1b7da4ac 2380 (set_attr "length" "8")
2381 (set_attr "type" "multiple")]
215b30b3 2382)
9c08d1fa 2383
25f905c2 2384;; ??? Use Thumb-2 has bitfield insert/extract instructions.
d7863cfe 2385(define_split
2386 [(set (match_operand:SI 0 "s_register_operand" "")
2387 (match_operator:SI 1 "shiftable_operator"
2388 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2389 (match_operand:SI 3 "const_int_operand" "")
2390 (match_operand:SI 4 "const_int_operand" ""))
2391 (match_operand:SI 5 "s_register_operand" "")]))
2392 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2393 "TARGET_ARM"
2394 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2395 (set (match_dup 0)
2396 (match_op_dup 1
2397 [(lshiftrt:SI (match_dup 6) (match_dup 4))
2398 (match_dup 5)]))]
2399 "{
2400 HOST_WIDE_INT temp = INTVAL (operands[3]);
2401
2402 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2403 operands[4] = GEN_INT (32 - temp);
2404 }"
2405)
2406
d7863cfe 2407(define_split
2408 [(set (match_operand:SI 0 "s_register_operand" "")
2409 (match_operator:SI 1 "shiftable_operator"
2410 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2411 (match_operand:SI 3 "const_int_operand" "")
2412 (match_operand:SI 4 "const_int_operand" ""))
2413 (match_operand:SI 5 "s_register_operand" "")]))
2414 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2415 "TARGET_ARM"
2416 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2417 (set (match_dup 0)
2418 (match_op_dup 1
2419 [(ashiftrt:SI (match_dup 6) (match_dup 4))
2420 (match_dup 5)]))]
2421 "{
2422 HOST_WIDE_INT temp = INTVAL (operands[3]);
2423
2424 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2425 operands[4] = GEN_INT (32 - temp);
2426 }"
2427)
2428
a42059fd 2429;;; ??? This pattern is bogus. If operand3 has bits outside the range
2430;;; represented by the bitfield, then this will produce incorrect results.
2431;;; Somewhere, the value needs to be truncated. On targets like the m68k,
ceb2fe0f 2432;;; which have a real bit-field insert instruction, the truncation happens
2433;;; in the bit-field insert instruction itself. Since arm does not have a
2434;;; bit-field insert instruction, we would have to emit code here to truncate
a42059fd 2435;;; the value before we insert. This loses some of the advantage of having
2436;;; this insv pattern, so this pattern needs to be reevalutated.
2437
8a18b90c 2438(define_expand "insv"
eb04cafb 2439 [(set (zero_extract (match_operand 0 "nonimmediate_operand" "")
2440 (match_operand 1 "general_operand" "")
2441 (match_operand 2 "general_operand" ""))
2442 (match_operand 3 "reg_or_int_operand" ""))]
8b054d5a 2443 "TARGET_ARM || arm_arch_thumb2"
8a18b90c 2444 "
215b30b3 2445 {
2446 int start_bit = INTVAL (operands[2]);
2447 int width = INTVAL (operands[1]);
db2faf44 2448 HOST_WIDE_INT mask = (HOST_WIDE_INT_1 << width) - 1;
215b30b3 2449 rtx target, subtarget;
2450
8b054d5a 2451 if (arm_arch_thumb2)
2452 {
eb04cafb 2453 if (unaligned_access && MEM_P (operands[0])
2454 && s_register_operand (operands[3], GET_MODE (operands[3]))
2455 && (width == 16 || width == 32) && (start_bit % BITS_PER_UNIT) == 0)
8b054d5a 2456 {
eb04cafb 2457 rtx base_addr;
2458
2459 if (BYTES_BIG_ENDIAN)
2460 start_bit = GET_MODE_BITSIZE (GET_MODE (operands[3])) - width
2461 - start_bit;
8b054d5a 2462
eb04cafb 2463 if (width == 32)
8b054d5a 2464 {
eb04cafb 2465 base_addr = adjust_address (operands[0], SImode,
2466 start_bit / BITS_PER_UNIT);
2467 emit_insn (gen_unaligned_storesi (base_addr, operands[3]));
8b054d5a 2468 }
eb04cafb 2469 else
2470 {
2471 rtx tmp = gen_reg_rtx (HImode);
8b054d5a 2472
eb04cafb 2473 base_addr = adjust_address (operands[0], HImode,
2474 start_bit / BITS_PER_UNIT);
2475 emit_move_insn (tmp, gen_lowpart (HImode, operands[3]));
2476 emit_insn (gen_unaligned_storehi (base_addr, tmp));
2477 }
2478 DONE;
8b054d5a 2479 }
eb04cafb 2480 else if (s_register_operand (operands[0], GET_MODE (operands[0])))
8b054d5a 2481 {
eb04cafb 2482 bool use_bfi = TRUE;
8b054d5a 2483
0438d37f 2484 if (CONST_INT_P (operands[3]))
eb04cafb 2485 {
2486 HOST_WIDE_INT val = INTVAL (operands[3]) & mask;
2487
2488 if (val == 0)
2489 {
2490 emit_insn (gen_insv_zero (operands[0], operands[1],
2491 operands[2]));
2492 DONE;
2493 }
2494
2495 /* See if the set can be done with a single orr instruction. */
2496 if (val == mask && const_ok_for_arm (val << start_bit))
2497 use_bfi = FALSE;
2498 }
2499
2500 if (use_bfi)
2501 {
0438d37f 2502 if (!REG_P (operands[3]))
eb04cafb 2503 operands[3] = force_reg (SImode, operands[3]);
2504
2505 emit_insn (gen_insv_t2 (operands[0], operands[1], operands[2],
2506 operands[3]));
2507 DONE;
2508 }
8b054d5a 2509 }
eb04cafb 2510 else
2511 FAIL;
8b054d5a 2512 }
2513
eb04cafb 2514 if (!s_register_operand (operands[0], GET_MODE (operands[0])))
2515 FAIL;
2516
3f8fde42 2517 target = copy_rtx (operands[0]);
215b30b3 2518 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
2519 subreg as the final target. */
2520 if (GET_CODE (target) == SUBREG)
2521 {
2522 subtarget = gen_reg_rtx (SImode);
2523 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
2524 < GET_MODE_SIZE (SImode))
2525 target = SUBREG_REG (target);
2526 }
2527 else
2528 subtarget = target;
8a18b90c 2529
0438d37f 2530 if (CONST_INT_P (operands[3]))
215b30b3 2531 {
2532 /* Since we are inserting a known constant, we may be able to
2533 reduce the number of bits that we have to clear so that
2534 the mask becomes simple. */
2535 /* ??? This code does not check to see if the new mask is actually
2536 simpler. It may not be. */
2537 rtx op1 = gen_reg_rtx (SImode);
2538 /* ??? Truncate operand3 to fit in the bitfield. See comment before
2539 start of this pattern. */
2540 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
2541 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
2542
c5b3a71b 2543 emit_insn (gen_andsi3 (op1, operands[0],
2544 gen_int_mode (~mask2, SImode)));
215b30b3 2545 emit_insn (gen_iorsi3 (subtarget, op1,
4292ca6b 2546 gen_int_mode (op3_value << start_bit, SImode)));
215b30b3 2547 }
2548 else if (start_bit == 0
2549 && !(const_ok_for_arm (mask)
2550 || const_ok_for_arm (~mask)))
2551 {
2552 /* A Trick, since we are setting the bottom bits in the word,
2553 we can shift operand[3] up, operand[0] down, OR them together
2554 and rotate the result back again. This takes 3 insns, and
5910bb95 2555 the third might be mergeable into another op. */
215b30b3 2556 /* The shift up copes with the possibility that operand[3] is
2557 wider than the bitfield. */
2558 rtx op0 = gen_reg_rtx (SImode);
2559 rtx op1 = gen_reg_rtx (SImode);
2560
2561 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2562 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
2563 emit_insn (gen_iorsi3 (op1, op1, op0));
2564 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
2565 }
2566 else if ((width + start_bit == 32)
2567 && !(const_ok_for_arm (mask)
2568 || const_ok_for_arm (~mask)))
2569 {
2570 /* Similar trick, but slightly less efficient. */
8a18b90c 2571
215b30b3 2572 rtx op0 = gen_reg_rtx (SImode);
2573 rtx op1 = gen_reg_rtx (SImode);
8a18b90c 2574
215b30b3 2575 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2576 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
2577 emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
2578 emit_insn (gen_iorsi3 (subtarget, op1, op0));
2579 }
2580 else
2581 {
c5b3a71b 2582 rtx op0 = gen_int_mode (mask, SImode);
215b30b3 2583 rtx op1 = gen_reg_rtx (SImode);
2584 rtx op2 = gen_reg_rtx (SImode);
8a18b90c 2585
215b30b3 2586 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
2587 {
2588 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 2589
215b30b3 2590 emit_insn (gen_movsi (tmp, op0));
2591 op0 = tmp;
2592 }
8a18b90c 2593
215b30b3 2594 /* Mask out any bits in operand[3] that are not needed. */
2595 emit_insn (gen_andsi3 (op1, operands[3], op0));
8a18b90c 2596
0438d37f 2597 if (CONST_INT_P (op0)
215b30b3 2598 && (const_ok_for_arm (mask << start_bit)
2599 || const_ok_for_arm (~(mask << start_bit))))
2600 {
c5b3a71b 2601 op0 = gen_int_mode (~(mask << start_bit), SImode);
215b30b3 2602 emit_insn (gen_andsi3 (op2, operands[0], op0));
2603 }
2604 else
2605 {
0438d37f 2606 if (CONST_INT_P (op0))
215b30b3 2607 {
2608 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 2609
215b30b3 2610 emit_insn (gen_movsi (tmp, op0));
2611 op0 = tmp;
2612 }
2613
2614 if (start_bit != 0)
2615 emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
a42059fd 2616
215b30b3 2617 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
2618 }
8a18b90c 2619
215b30b3 2620 if (start_bit != 0)
2621 emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
8a18b90c 2622
215b30b3 2623 emit_insn (gen_iorsi3 (subtarget, op1, op2));
2624 }
f082f1c4 2625
215b30b3 2626 if (subtarget != target)
2627 {
2628 /* If TARGET is still a SUBREG, then it must be wider than a word,
2629 so we must be careful only to set the subword we were asked to. */
2630 if (GET_CODE (target) == SUBREG)
2631 emit_move_insn (target, subtarget);
2632 else
2633 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
2634 }
8a18b90c 2635
215b30b3 2636 DONE;
2637 }"
2638)
8a18b90c 2639
8b054d5a 2640(define_insn "insv_zero"
2641 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
809003b3 2642 (match_operand:SI 1 "const_int_M_operand" "M")
2643 (match_operand:SI 2 "const_int_M_operand" "M"))
8b054d5a 2644 (const_int 0))]
2645 "arm_arch_thumb2"
2646 "bfc%?\t%0, %2, %1"
2647 [(set_attr "length" "4")
d952d547 2648 (set_attr "predicable" "yes")
d82e788e 2649 (set_attr "predicable_short_it" "no")
2650 (set_attr "type" "bfm")]
8b054d5a 2651)
2652
2653(define_insn "insv_t2"
2654 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
809003b3 2655 (match_operand:SI 1 "const_int_M_operand" "M")
2656 (match_operand:SI 2 "const_int_M_operand" "M"))
8b054d5a 2657 (match_operand:SI 3 "s_register_operand" "r"))]
2658 "arm_arch_thumb2"
2659 "bfi%?\t%0, %3, %2, %1"
2660 [(set_attr "length" "4")
d952d547 2661 (set_attr "predicable" "yes")
d82e788e 2662 (set_attr "predicable_short_it" "no")
2663 (set_attr "type" "bfm")]
8b054d5a 2664)
2665
215b30b3 2666; constants for op 2 will never be given to these patterns.
a0f94409 2667(define_insn_and_split "*anddi_notdi_di"
9c08d1fa 2668 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 2669 (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "0,r"))
2670 (match_operand:DI 2 "s_register_operand" "r,0")))]
25f905c2 2671 "TARGET_32BIT"
f6ebffac 2672 "#"
e2669ea7 2673 "TARGET_32BIT && reload_completed
2674 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))
2675 && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
a0f94409 2676 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2677 (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2678 "
2679 {
2680 operands[3] = gen_highpart (SImode, operands[0]);
2681 operands[0] = gen_lowpart (SImode, operands[0]);
2682 operands[4] = gen_highpart (SImode, operands[1]);
2683 operands[1] = gen_lowpart (SImode, operands[1]);
2684 operands[5] = gen_highpart (SImode, operands[2]);
2685 operands[2] = gen_lowpart (SImode, operands[2]);
2686 }"
0d66636f 2687 [(set_attr "length" "8")
1b7da4ac 2688 (set_attr "predicable" "yes")
2689 (set_attr "type" "multiple")]
0d66636f 2690)
d952d547 2691
a0f94409 2692(define_insn_and_split "*anddi_notzesidi_di"
9c08d1fa 2693 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2694 (and:DI (not:DI (zero_extend:DI
2695 (match_operand:SI 2 "s_register_operand" "r,r")))
e2348bcb 2696 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 2697 "TARGET_32BIT"
e2348bcb 2698 "@
97499065 2699 bic%?\\t%Q0, %Q1, %2
f6ebffac 2700 #"
a0f94409 2701 ; (not (zero_extend ...)) allows us to just copy the high word from
2702 ; operand1 to operand0.
25f905c2 2703 "TARGET_32BIT
a0f94409 2704 && reload_completed
2705 && operands[0] != operands[1]"
5a097f7d 2706 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
a0f94409 2707 (set (match_dup 3) (match_dup 4))]
2708 "
2709 {
2710 operands[3] = gen_highpart (SImode, operands[0]);
2711 operands[0] = gen_lowpart (SImode, operands[0]);
2712 operands[4] = gen_highpart (SImode, operands[1]);
2713 operands[1] = gen_lowpart (SImode, operands[1]);
2714 }"
0d66636f 2715 [(set_attr "length" "4,8")
d952d547 2716 (set_attr "predicable" "yes")
1b7da4ac 2717 (set_attr "predicable_short_it" "no")
2718 (set_attr "type" "multiple")]
0d66636f 2719)
d952d547 2720
d8cd5fa0 2721(define_insn_and_split "*anddi_notdi_zesidi"
2722 [(set (match_operand:DI 0 "s_register_operand" "=r")
2723 (and:DI (not:DI (match_operand:DI 2 "s_register_operand" "r"))
2724 (zero_extend:DI
2725 (match_operand:SI 1 "s_register_operand" "r"))))]
2726 "TARGET_32BIT"
2727 "#"
2728 "TARGET_32BIT && reload_completed"
2729 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2730 (set (match_dup 3) (const_int 0))]
2731 "
2732 {
2733 operands[3] = gen_highpart (SImode, operands[0]);
2734 operands[0] = gen_lowpart (SImode, operands[0]);
2735 operands[2] = gen_lowpart (SImode, operands[2]);
2736 }"
2737 [(set_attr "length" "8")
2738 (set_attr "predicable" "yes")
2739 (set_attr "predicable_short_it" "no")
2740 (set_attr "type" "multiple")]
2741)
2742
a0f94409 2743(define_insn_and_split "*anddi_notsesidi_di"
9c08d1fa 2744 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2745 (and:DI (not:DI (sign_extend:DI
2746 (match_operand:SI 2 "s_register_operand" "r,r")))
5a097f7d 2747 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2748 "TARGET_32BIT"
f6ebffac 2749 "#"
25f905c2 2750 "TARGET_32BIT && reload_completed"
5a097f7d 2751 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
a0f94409 2752 (set (match_dup 3) (and:SI (not:SI
2753 (ashiftrt:SI (match_dup 2) (const_int 31)))
2754 (match_dup 4)))]
2755 "
2756 {
2757 operands[3] = gen_highpart (SImode, operands[0]);
2758 operands[0] = gen_lowpart (SImode, operands[0]);
2759 operands[4] = gen_highpart (SImode, operands[1]);
2760 operands[1] = gen_lowpart (SImode, operands[1]);
2761 }"
0d66636f 2762 [(set_attr "length" "8")
d952d547 2763 (set_attr "predicable" "yes")
1b7da4ac 2764 (set_attr "predicable_short_it" "no")
2765 (set_attr "type" "multiple")]
0d66636f 2766)
d952d547 2767
8a18b90c 2768(define_insn "andsi_notsi_si"
9c08d1fa 2769 [(set (match_operand:SI 0 "s_register_operand" "=r")
2770 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2771 (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 2772 "TARGET_32BIT"
0d66636f 2773 "bic%?\\t%0, %1, %2"
d952d547 2774 [(set_attr "predicable" "yes")
1b7da4ac 2775 (set_attr "predicable_short_it" "no")
2776 (set_attr "type" "logic_reg")]
0d66636f 2777)
b11cae9e 2778
8a18b90c 2779(define_insn "andsi_not_shiftsi_si"
a2cd141b 2780 [(set (match_operand:SI 0 "s_register_operand" "=r")
2781 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2782 [(match_operand:SI 2 "s_register_operand" "r")
2783 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2784 (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 2785 "TARGET_ARM"
6c4c2133 2786 "bic%?\\t%0, %1, %2%S4"
344495ea 2787 [(set_attr "predicable" "yes")
331beb1a 2788 (set_attr "shift" "2")
a2cd141b 2789 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
d82e788e 2790 (const_string "logic_shift_imm")
2791 (const_string "logic_shift_reg")))]
6c4c2133 2792)
8a18b90c 2793
9ed784d8 2794;; Shifted bics pattern used to set up CC status register and not reusing
2795;; bics output. Pattern restricts Thumb2 shift operand as bics for Thumb2
2796;; does not support shift by register.
2797(define_insn "andsi_not_shiftsi_si_scc_no_reuse"
2798 [(set (reg:CC_NOOV CC_REGNUM)
2799 (compare:CC_NOOV
2800 (and:SI (not:SI (match_operator:SI 0 "shift_operator"
2801 [(match_operand:SI 1 "s_register_operand" "r")
2802 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2803 (match_operand:SI 3 "s_register_operand" "r"))
2804 (const_int 0)))
2805 (clobber (match_scratch:SI 4 "=r"))]
2806 "TARGET_ARM || (TARGET_THUMB2 && CONST_INT_P (operands[2]))"
3ef90e77 2807 "bics%?\\t%4, %3, %1%S0"
9ed784d8 2808 [(set_attr "predicable" "yes")
2809 (set_attr "predicable_short_it" "no")
2810 (set_attr "conds" "set")
2811 (set_attr "shift" "1")
2812 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2813 (const_string "logic_shift_imm")
2814 (const_string "logic_shift_reg")))]
2815)
2816
2817;; Same as andsi_not_shiftsi_si_scc_no_reuse, but the bics result is also
2818;; getting reused later.
2819(define_insn "andsi_not_shiftsi_si_scc"
2820 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2821 (compare:CC_NOOV
2822 (and:SI (not:SI (match_operator:SI 0 "shift_operator"
2823 [(match_operand:SI 1 "s_register_operand" "r")
2824 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2825 (match_operand:SI 3 "s_register_operand" "r"))
2826 (const_int 0)))
2827 (set (match_operand:SI 4 "s_register_operand" "=r")
2828 (and:SI (not:SI (match_op_dup 0
2829 [(match_dup 1)
2830 (match_dup 2)]))
2831 (match_dup 3)))])]
2832 "TARGET_ARM || (TARGET_THUMB2 && CONST_INT_P (operands[2]))"
3ef90e77 2833 "bics%?\\t%4, %3, %1%S0"
9ed784d8 2834 [(set_attr "predicable" "yes")
2835 (set_attr "predicable_short_it" "no")
2836 (set_attr "conds" "set")
2837 (set_attr "shift" "1")
2838 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2839 (const_string "logic_shift_imm")
2840 (const_string "logic_shift_reg")))]
2841)
2842
f7fbdd4a 2843(define_insn "*andsi_notsi_si_compare0"
bd5b4116 2844 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 2845 (compare:CC_NOOV
2846 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2847 (match_operand:SI 1 "s_register_operand" "r"))
2848 (const_int 0)))
9c08d1fa 2849 (set (match_operand:SI 0 "s_register_operand" "=r")
2850 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
25f905c2 2851 "TARGET_32BIT"
3ef90e77 2852 "bics\\t%0, %1, %2"
d82e788e 2853 [(set_attr "conds" "set")
2854 (set_attr "type" "logics_shift_reg")]
0d66636f 2855)
9c08d1fa 2856
f7fbdd4a 2857(define_insn "*andsi_notsi_si_compare0_scratch"
bd5b4116 2858 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 2859 (compare:CC_NOOV
2860 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2861 (match_operand:SI 1 "s_register_operand" "r"))
2862 (const_int 0)))
9c08d1fa 2863 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 2864 "TARGET_32BIT"
3ef90e77 2865 "bics\\t%0, %1, %2"
d82e788e 2866 [(set_attr "conds" "set")
2867 (set_attr "type" "logics_shift_reg")]
0d66636f 2868)
9c08d1fa 2869
e2669ea7 2870(define_expand "iordi3"
2871 [(set (match_operand:DI 0 "s_register_operand" "")
2872 (ior:DI (match_operand:DI 1 "s_register_operand" "")
2873 (match_operand:DI 2 "neon_logic_op2" "")))]
2874 "TARGET_32BIT"
2875 ""
2876)
2877
74d6113f 2878(define_insn_and_split "*iordi3_insn"
2879 [(set (match_operand:DI 0 "s_register_operand" "=w,w ,&r,&r,&r,&r,?w,?w")
2880 (ior:DI (match_operand:DI 1 "s_register_operand" "%w,0 ,0 ,r ,0 ,r ,w ,0")
e0fe6977 2881 (match_operand:DI 2 "arm_iordi_operand_neon" "w ,Dl,r ,r ,Df,Df,w ,Dl")))]
74d6113f 2882 "TARGET_32BIT && !TARGET_IWMMXT"
2883 {
2884 switch (which_alternative)
2885 {
2886 case 0: /* fall through */
2887 case 6: return "vorr\t%P0, %P1, %P2";
2888 case 1: /* fall through */
2889 case 7: return neon_output_logic_immediate ("vorr", &operands[2],
2890 DImode, 0, VALID_NEON_QREG_MODE (DImode));
2891 case 2:
2892 case 3:
2893 case 4:
2894 case 5:
2895 return "#";
2896 default: gcc_unreachable ();
2897 }
2898 }
2899 "TARGET_32BIT && !TARGET_IWMMXT && reload_completed
2900 && !(IS_VFP_REGNUM (REGNO (operands[0])))"
2901 [(set (match_dup 3) (match_dup 4))
2902 (set (match_dup 5) (match_dup 6))]
2903 "
2904 {
2905 operands[3] = gen_lowpart (SImode, operands[0]);
2906 operands[5] = gen_highpart (SImode, operands[0]);
2907
2908 operands[4] = simplify_gen_binary (IOR, SImode,
2909 gen_lowpart (SImode, operands[1]),
2910 gen_lowpart (SImode, operands[2]));
2911 operands[6] = simplify_gen_binary (IOR, SImode,
2912 gen_highpart (SImode, operands[1]),
2913 gen_highpart_mode (SImode, DImode, operands[2]));
2914
2915 }"
32093010 2916 [(set_attr "type" "neon_logic,neon_logic,multiple,multiple,multiple,\
2917 multiple,neon_logic,neon_logic")
e0fe6977 2918 (set_attr "length" "*,*,8,8,8,8,*,*")
74d6113f 2919 (set_attr "arch" "neon_for_64bits,neon_for_64bits,*,*,*,*,avoid_neon_for_64bits,avoid_neon_for_64bits")]
cffb2a26 2920)
9c08d1fa 2921
f7fbdd4a 2922(define_insn "*iordi_zesidi_di"
9c08d1fa 2923 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2924 (ior:DI (zero_extend:DI
2925 (match_operand:SI 2 "s_register_operand" "r,r"))
e2348bcb 2926 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 2927 "TARGET_32BIT"
e2348bcb 2928 "@
97499065 2929 orr%?\\t%Q0, %Q1, %2
f6ebffac 2930 #"
0d66636f 2931 [(set_attr "length" "4,8")
d952d547 2932 (set_attr "predicable" "yes")
1b7da4ac 2933 (set_attr "predicable_short_it" "no")
2934 (set_attr "type" "logic_reg,multiple")]
cffb2a26 2935)
9c08d1fa 2936
f7fbdd4a 2937(define_insn "*iordi_sesidi_di"
9c08d1fa 2938 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2939 (ior:DI (sign_extend:DI
2940 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 2941 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2942 "TARGET_32BIT"
f6ebffac 2943 "#"
0d66636f 2944 [(set_attr "length" "8")
1b7da4ac 2945 (set_attr "predicable" "yes")
2946 (set_attr "type" "multiple")]
cffb2a26 2947)
9c08d1fa 2948
87b22bf7 2949(define_expand "iorsi3"
cffb2a26 2950 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2951 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2952 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 2953 "TARGET_EITHER"
87b22bf7 2954 "
0438d37f 2955 if (CONST_INT_P (operands[2]))
87b22bf7 2956 {
25f905c2 2957 if (TARGET_32BIT)
cffb2a26 2958 {
17202aa5 2959 if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[2]), IOR))
2960 operands[2] = force_reg (SImode, operands[2]);
2961 else
2962 {
2963 arm_split_constant (IOR, SImode, NULL_RTX,
2964 INTVAL (operands[2]), operands[0],
2965 operands[1],
2966 optimize && can_create_pseudo_p ());
2967 DONE;
2968 }
cffb2a26 2969 }
25f905c2 2970 else /* TARGET_THUMB1 */
923ffadb 2971 {
2972 rtx tmp = force_reg (SImode, operands[2]);
2973 if (rtx_equal_p (operands[0], operands[1]))
2974 operands[2] = tmp;
2975 else
2976 {
2977 operands[2] = operands[1];
2978 operands[1] = tmp;
2979 }
2980 }
87b22bf7 2981 }
cffb2a26 2982 "
2983)
87b22bf7 2984
d5d4dc8d 2985(define_insn_and_split "*iorsi3_insn"
29e234a3 2986 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r,r,r")
2987 (ior:SI (match_operand:SI 1 "s_register_operand" "%r,0,r,r,r")
2988 (match_operand:SI 2 "reg_or_int_operand" "I,l,K,r,?n")))]
d5d4dc8d 2989 "TARGET_32BIT"
87b22bf7 2990 "@
29e234a3 2991 orr%?\\t%0, %1, %2
87b22bf7 2992 orr%?\\t%0, %1, %2
d5d4dc8d 2993 orn%?\\t%0, %1, #%B2
65f68e55 2994 orr%?\\t%0, %1, %2
87b22bf7 2995 #"
d5d4dc8d 2996 "TARGET_32BIT
0438d37f 2997 && CONST_INT_P (operands[2])
d5d4dc8d 2998 && !(const_ok_for_arm (INTVAL (operands[2]))
2999 || (TARGET_THUMB2 && const_ok_for_arm (~INTVAL (operands[2]))))"
a0f94409 3000 [(clobber (const_int 0))]
d5d4dc8d 3001{
29e234a3 3002 arm_split_constant (IOR, SImode, curr_insn,
96f57e36 3003 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 3004 DONE;
d5d4dc8d 3005}
29e234a3 3006 [(set_attr "length" "4,4,4,4,16")
3007 (set_attr "arch" "32,t2,t2,32,32")
65f68e55 3008 (set_attr "predicable" "yes")
29e234a3 3009 (set_attr "predicable_short_it" "no,yes,no,no,no")
d82e788e 3010 (set_attr "type" "logic_imm,logic_reg,logic_imm,logic_reg,logic_reg")]
65f68e55 3011)
cffb2a26 3012
a0f94409 3013(define_peephole2
3014 [(match_scratch:SI 3 "r")
372575c7 3015 (set (match_operand:SI 0 "arm_general_register_operand" "")
3016 (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
87b22bf7 3017 (match_operand:SI 2 "const_int_operand" "")))]
90560cad 3018 "TARGET_ARM
a0f94409 3019 && !const_ok_for_arm (INTVAL (operands[2]))
3020 && const_ok_for_arm (~INTVAL (operands[2]))"
3021 [(set (match_dup 3) (match_dup 2))
3022 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
3023 ""
215b30b3 3024)
a0f94409 3025
f7fbdd4a 3026(define_insn "*iorsi3_compare0"
bd5b4116 3027 [(set (reg:CC_NOOV CC_REGNUM)
65f68e55 3028 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r,r")
3029 (match_operand:SI 2 "arm_rhs_operand" "I,r"))
9c08d1fa 3030 (const_int 0)))
65f68e55 3031 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 3032 (ior:SI (match_dup 1) (match_dup 2)))]
25f905c2 3033 "TARGET_32BIT"
3ef90e77 3034 "orrs%?\\t%0, %1, %2"
65f68e55 3035 [(set_attr "conds" "set")
d82e788e 3036 (set_attr "type" "logics_imm,logics_reg")]
cffb2a26 3037)
9c08d1fa 3038
f7fbdd4a 3039(define_insn "*iorsi3_compare0_scratch"
bd5b4116 3040 [(set (reg:CC_NOOV CC_REGNUM)
65f68e55 3041 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r,r")
3042 (match_operand:SI 2 "arm_rhs_operand" "I,r"))
9c08d1fa 3043 (const_int 0)))
65f68e55 3044 (clobber (match_scratch:SI 0 "=r,r"))]
25f905c2 3045 "TARGET_32BIT"
3ef90e77 3046 "orrs%?\\t%0, %1, %2"
65f68e55 3047 [(set_attr "conds" "set")
d82e788e 3048 (set_attr "type" "logics_imm,logics_reg")]
0d66636f 3049)
9c08d1fa 3050
e2669ea7 3051(define_expand "xordi3"
3052 [(set (match_operand:DI 0 "s_register_operand" "")
3053 (xor:DI (match_operand:DI 1 "s_register_operand" "")
8ee7dc6f 3054 (match_operand:DI 2 "arm_xordi_operand" "")))]
e2669ea7 3055 "TARGET_32BIT"
3056 ""
3057)
3058
8ee7dc6f 3059(define_insn_and_split "*xordi3_insn"
3060 [(set (match_operand:DI 0 "s_register_operand" "=w,&r,&r,&r,&r,?w")
205c3b0a 3061 (xor:DI (match_operand:DI 1 "s_register_operand" "%w ,0,r ,0 ,r ,w")
8ee7dc6f 3062 (match_operand:DI 2 "arm_xordi_operand" "w ,r ,r ,Dg,Dg,w")))]
3063 "TARGET_32BIT && !TARGET_IWMMXT"
3064{
3065 switch (which_alternative)
3066 {
3067 case 1:
3068 case 2:
3069 case 3:
3070 case 4: /* fall through */
3071 return "#";
3072 case 0: /* fall through */
3073 case 5: return "veor\t%P0, %P1, %P2";
3074 default: gcc_unreachable ();
3075 }
3076}
3077 "TARGET_32BIT && !TARGET_IWMMXT && reload_completed
3078 && !(IS_VFP_REGNUM (REGNO (operands[0])))"
3079 [(set (match_dup 3) (match_dup 4))
3080 (set (match_dup 5) (match_dup 6))]
3081 "
3082 {
3083 operands[3] = gen_lowpart (SImode, operands[0]);
3084 operands[5] = gen_highpart (SImode, operands[0]);
3085
3086 operands[4] = simplify_gen_binary (XOR, SImode,
3087 gen_lowpart (SImode, operands[1]),
3088 gen_lowpart (SImode, operands[2]));
3089 operands[6] = simplify_gen_binary (XOR, SImode,
3090 gen_highpart (SImode, operands[1]),
3091 gen_highpart_mode (SImode, DImode, operands[2]));
3092
3093 }"
3094 [(set_attr "length" "*,8,8,8,8,*")
32093010 3095 (set_attr "type" "neon_logic,multiple,multiple,multiple,multiple,neon_logic")
8ee7dc6f 3096 (set_attr "arch" "neon_for_64bits,*,*,*,*,avoid_neon_for_64bits")]
cffb2a26 3097)
9c08d1fa 3098
f7fbdd4a 3099(define_insn "*xordi_zesidi_di"
9c08d1fa 3100 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3101 (xor:DI (zero_extend:DI
3102 (match_operand:SI 2 "s_register_operand" "r,r"))
e2348bcb 3103 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 3104 "TARGET_32BIT"
e2348bcb 3105 "@
97499065 3106 eor%?\\t%Q0, %Q1, %2
f6ebffac 3107 #"
0d66636f 3108 [(set_attr "length" "4,8")
d952d547 3109 (set_attr "predicable" "yes")
1b7da4ac 3110 (set_attr "predicable_short_it" "no")
3111 (set_attr "type" "logic_reg")]
cffb2a26 3112)
9c08d1fa 3113
f7fbdd4a 3114(define_insn "*xordi_sesidi_di"
9c08d1fa 3115 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3116 (xor:DI (sign_extend:DI
3117 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 3118 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 3119 "TARGET_32BIT"
f6ebffac 3120 "#"
0d66636f 3121 [(set_attr "length" "8")
1b7da4ac 3122 (set_attr "predicable" "yes")
3123 (set_attr "type" "multiple")]
cffb2a26 3124)
9c08d1fa 3125
cffb2a26 3126(define_expand "xorsi3"
3127 [(set (match_operand:SI 0 "s_register_operand" "")
3128 (xor:SI (match_operand:SI 1 "s_register_operand" "")
923ffadb 3129 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 3130 "TARGET_EITHER"
0438d37f 3131 "if (CONST_INT_P (operands[2]))
923ffadb 3132 {
3133 if (TARGET_32BIT)
3134 {
17202aa5 3135 if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[2]), XOR))
3136 operands[2] = force_reg (SImode, operands[2]);
3137 else
3138 {
3139 arm_split_constant (XOR, SImode, NULL_RTX,
3140 INTVAL (operands[2]), operands[0],
3141 operands[1],
3142 optimize && can_create_pseudo_p ());
3143 DONE;
3144 }
923ffadb 3145 }
3146 else /* TARGET_THUMB1 */
3147 {
3148 rtx tmp = force_reg (SImode, operands[2]);
3149 if (rtx_equal_p (operands[0], operands[1]))
3150 operands[2] = tmp;
3151 else
3152 {
3153 operands[2] = operands[1];
3154 operands[1] = tmp;
3155 }
3156 }
3157 }"
cffb2a26 3158)
3159
5dcb35d9 3160(define_insn_and_split "*arm_xorsi3"
29e234a3 3161 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r,r")
3162 (xor:SI (match_operand:SI 1 "s_register_operand" "%r,0,r,r")
3163 (match_operand:SI 2 "reg_or_int_operand" "I,l,r,?n")))]
25f905c2 3164 "TARGET_32BIT"
5dcb35d9 3165 "@
29e234a3 3166 eor%?\\t%0, %1, %2
65f68e55 3167 eor%?\\t%0, %1, %2
5dcb35d9 3168 eor%?\\t%0, %1, %2
3169 #"
3170 "TARGET_32BIT
0438d37f 3171 && CONST_INT_P (operands[2])
5dcb35d9 3172 && !const_ok_for_arm (INTVAL (operands[2]))"
3173 [(clobber (const_int 0))]
3174{
3175 arm_split_constant (XOR, SImode, curr_insn,
3176 INTVAL (operands[2]), operands[0], operands[1], 0);
3177 DONE;
3178}
29e234a3 3179 [(set_attr "length" "4,4,4,16")
65f68e55 3180 (set_attr "predicable" "yes")
29e234a3 3181 (set_attr "predicable_short_it" "no,yes,no,no")
1b7da4ac 3182 (set_attr "type" "logic_imm,logic_reg,logic_reg,multiple")]
cffb2a26 3183)
3184
f7fbdd4a 3185(define_insn "*xorsi3_compare0"
bd5b4116 3186 [(set (reg:CC_NOOV CC_REGNUM)
65f68e55 3187 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r,r")
3188 (match_operand:SI 2 "arm_rhs_operand" "I,r"))
9c08d1fa 3189 (const_int 0)))
65f68e55 3190 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 3191 (xor:SI (match_dup 1) (match_dup 2)))]
25f905c2 3192 "TARGET_32BIT"
3ef90e77 3193 "eors%?\\t%0, %1, %2"
65f68e55 3194 [(set_attr "conds" "set")
d82e788e 3195 (set_attr "type" "logics_imm,logics_reg")]
0d66636f 3196)
9c08d1fa 3197
f7fbdd4a 3198(define_insn "*xorsi3_compare0_scratch"
bd5b4116 3199 [(set (reg:CC_NOOV CC_REGNUM)
65f68e55 3200 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r,r")
3201 (match_operand:SI 1 "arm_rhs_operand" "I,r"))
9c08d1fa 3202 (const_int 0)))]
25f905c2 3203 "TARGET_32BIT"
40dbec34 3204 "teq%?\\t%0, %1"
65f68e55 3205 [(set_attr "conds" "set")
d82e788e 3206 (set_attr "type" "logics_imm,logics_reg")]
cffb2a26 3207)
9c08d1fa 3208
215b30b3 3209; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
3210; (NOT D) we can sometimes merge the final NOT into one of the following
3211; insns.
9c08d1fa 3212
3213(define_split
a058e94a 3214 [(set (match_operand:SI 0 "s_register_operand" "")
3215 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
3216 (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
3217 (match_operand:SI 3 "arm_rhs_operand" "")))
3218 (clobber (match_operand:SI 4 "s_register_operand" ""))]
25f905c2 3219 "TARGET_32BIT"
9c08d1fa 3220 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
3221 (not:SI (match_dup 3))))
3222 (set (match_dup 0) (not:SI (match_dup 4)))]
3223 ""
3224)
3225
ba6a3b2f 3226(define_insn_and_split "*andsi_iorsi3_notsi"
9c08d1fa 3227 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
e5fea38e 3228 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "%0,r,r")
9c08d1fa 3229 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
3230 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
25f905c2 3231 "TARGET_32BIT"
ba6a3b2f 3232 "#" ; "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
3233 "&& reload_completed"
3234 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
054fd237 3235 (set (match_dup 0) (and:SI (match_dup 4) (match_dup 5)))]
3236 {
3237 /* If operands[3] is a constant make sure to fold the NOT into it
3238 to avoid creating a NOT of a CONST_INT. */
3239 rtx not_rtx = simplify_gen_unary (NOT, SImode, operands[3], SImode);
3240 if (CONST_INT_P (not_rtx))
3241 {
3242 operands[4] = operands[0];
3243 operands[5] = not_rtx;
3244 }
3245 else
3246 {
3247 operands[5] = operands[0];
3248 operands[4] = not_rtx;
3249 }
3250 }
0d66636f 3251 [(set_attr "length" "8")
25f905c2 3252 (set_attr "ce_count" "2")
d952d547 3253 (set_attr "predicable" "yes")
1b7da4ac 3254 (set_attr "predicable_short_it" "no")
3255 (set_attr "type" "multiple")]
cffb2a26 3256)
9c08d1fa 3257
25f905c2 3258; ??? Are these four splitters still beneficial when the Thumb-2 bitfield
3259; insns are available?
d7863cfe 3260(define_split
3261 [(set (match_operand:SI 0 "s_register_operand" "")
3262 (match_operator:SI 1 "logical_binary_operator"
3263 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
3264 (match_operand:SI 3 "const_int_operand" "")
3265 (match_operand:SI 4 "const_int_operand" ""))
3266 (match_operator:SI 9 "logical_binary_operator"
3267 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3268 (match_operand:SI 6 "const_int_operand" ""))
3269 (match_operand:SI 7 "s_register_operand" "")])]))
3270 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3271 "TARGET_32BIT
d7863cfe 3272 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3273 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3274 [(set (match_dup 8)
3275 (match_op_dup 1
3276 [(ashift:SI (match_dup 2) (match_dup 4))
3277 (match_dup 5)]))
3278 (set (match_dup 0)
3279 (match_op_dup 1
3280 [(lshiftrt:SI (match_dup 8) (match_dup 6))
3281 (match_dup 7)]))]
3282 "
3283 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3284")
3285
3286(define_split
3287 [(set (match_operand:SI 0 "s_register_operand" "")
3288 (match_operator:SI 1 "logical_binary_operator"
3289 [(match_operator:SI 9 "logical_binary_operator"
3290 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3291 (match_operand:SI 6 "const_int_operand" ""))
3292 (match_operand:SI 7 "s_register_operand" "")])
3293 (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
3294 (match_operand:SI 3 "const_int_operand" "")
3295 (match_operand:SI 4 "const_int_operand" ""))]))
3296 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3297 "TARGET_32BIT
d7863cfe 3298 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3299 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3300 [(set (match_dup 8)
3301 (match_op_dup 1
3302 [(ashift:SI (match_dup 2) (match_dup 4))
3303 (match_dup 5)]))
3304 (set (match_dup 0)
3305 (match_op_dup 1
3306 [(lshiftrt:SI (match_dup 8) (match_dup 6))
3307 (match_dup 7)]))]
3308 "
3309 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3310")
3311
3312(define_split
3313 [(set (match_operand:SI 0 "s_register_operand" "")
3314 (match_operator:SI 1 "logical_binary_operator"
3315 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
3316 (match_operand:SI 3 "const_int_operand" "")
3317 (match_operand:SI 4 "const_int_operand" ""))
3318 (match_operator:SI 9 "logical_binary_operator"
3319 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3320 (match_operand:SI 6 "const_int_operand" ""))
3321 (match_operand:SI 7 "s_register_operand" "")])]))
3322 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3323 "TARGET_32BIT
d7863cfe 3324 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3325 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3326 [(set (match_dup 8)
3327 (match_op_dup 1
3328 [(ashift:SI (match_dup 2) (match_dup 4))
3329 (match_dup 5)]))
3330 (set (match_dup 0)
3331 (match_op_dup 1
3332 [(ashiftrt:SI (match_dup 8) (match_dup 6))
3333 (match_dup 7)]))]
3334 "
3335 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3336")
3337
3338(define_split
3339 [(set (match_operand:SI 0 "s_register_operand" "")
3340 (match_operator:SI 1 "logical_binary_operator"
3341 [(match_operator:SI 9 "logical_binary_operator"
3342 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3343 (match_operand:SI 6 "const_int_operand" ""))
3344 (match_operand:SI 7 "s_register_operand" "")])
3345 (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
3346 (match_operand:SI 3 "const_int_operand" "")
3347 (match_operand:SI 4 "const_int_operand" ""))]))
3348 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3349 "TARGET_32BIT
d7863cfe 3350 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3351 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3352 [(set (match_dup 8)
3353 (match_op_dup 1
3354 [(ashift:SI (match_dup 2) (match_dup 4))
3355 (match_dup 5)]))
3356 (set (match_dup 0)
3357 (match_op_dup 1
3358 [(ashiftrt:SI (match_dup 8) (match_dup 6))
3359 (match_dup 7)]))]
3360 "
3361 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3362")
9c08d1fa 3363\f
3364
3365;; Minimum and maximum insns
3366
8b9dc177 3367(define_expand "smaxsi3"
3368 [(parallel [
3369 (set (match_operand:SI 0 "s_register_operand" "")
3370 (smax:SI (match_operand:SI 1 "s_register_operand" "")
3371 (match_operand:SI 2 "arm_rhs_operand" "")))
3372 (clobber (reg:CC CC_REGNUM))])]
25f905c2 3373 "TARGET_32BIT"
8b9dc177 3374 "
8774928b 3375 if (operands[2] == const0_rtx || operands[2] == constm1_rtx)
8b9dc177 3376 {
3377 /* No need for a clobber of the condition code register here. */
d1f9b275 3378 emit_insn (gen_rtx_SET (operands[0],
8b9dc177 3379 gen_rtx_SMAX (SImode, operands[1],
3380 operands[2])));
3381 DONE;
3382 }
3383")
3384
3385(define_insn "*smax_0"
3386 [(set (match_operand:SI 0 "s_register_operand" "=r")
3387 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3388 (const_int 0)))]
25f905c2 3389 "TARGET_32BIT"
8b9dc177 3390 "bic%?\\t%0, %1, %1, asr #31"
d952d547 3391 [(set_attr "predicable" "yes")
1b7da4ac 3392 (set_attr "predicable_short_it" "no")
3393 (set_attr "type" "logic_shift_reg")]
8b9dc177 3394)
3395
8774928b 3396(define_insn "*smax_m1"
3397 [(set (match_operand:SI 0 "s_register_operand" "=r")
3398 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3399 (const_int -1)))]
25f905c2 3400 "TARGET_32BIT"
8774928b 3401 "orr%?\\t%0, %1, %1, asr #31"
d952d547 3402 [(set_attr "predicable" "yes")
1b7da4ac 3403 (set_attr "predicable_short_it" "no")
3404 (set_attr "type" "logic_shift_reg")]
8774928b 3405)
3406
3dc953f2 3407(define_insn_and_split "*arm_smax_insn"
8b9dc177 3408 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3409 (smax:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3410 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
bd5b4116 3411 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3412 "TARGET_ARM"
3dc953f2 3413 "#"
3414 ; cmp\\t%1, %2\;movlt\\t%0, %2
3415 ; cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
3416 "TARGET_ARM"
3417 [(set (reg:CC CC_REGNUM)
3418 (compare:CC (match_dup 1) (match_dup 2)))
3419 (set (match_dup 0)
3420 (if_then_else:SI (ge:SI (reg:CC CC_REGNUM) (const_int 0))
3421 (match_dup 1)
3422 (match_dup 2)))]
3423 ""
cffb2a26 3424 [(set_attr "conds" "clob")
1b7da4ac 3425 (set_attr "length" "8,12")
3426 (set_attr "type" "multiple")]
cffb2a26 3427)
9c08d1fa 3428
8b9dc177 3429(define_expand "sminsi3"
3430 [(parallel [
3431 (set (match_operand:SI 0 "s_register_operand" "")
3432 (smin:SI (match_operand:SI 1 "s_register_operand" "")
3433 (match_operand:SI 2 "arm_rhs_operand" "")))
3434 (clobber (reg:CC CC_REGNUM))])]
25f905c2 3435 "TARGET_32BIT"
8b9dc177 3436 "
3437 if (operands[2] == const0_rtx)
3438 {
3439 /* No need for a clobber of the condition code register here. */
d1f9b275 3440 emit_insn (gen_rtx_SET (operands[0],
8b9dc177 3441 gen_rtx_SMIN (SImode, operands[1],
3442 operands[2])));
3443 DONE;
3444 }
3445")
3446
3447(define_insn "*smin_0"
3448 [(set (match_operand:SI 0 "s_register_operand" "=r")
3449 (smin:SI (match_operand:SI 1 "s_register_operand" "r")
3450 (const_int 0)))]
25f905c2 3451 "TARGET_32BIT"
8b9dc177 3452 "and%?\\t%0, %1, %1, asr #31"
d952d547 3453 [(set_attr "predicable" "yes")
1b7da4ac 3454 (set_attr "predicable_short_it" "no")
3455 (set_attr "type" "logic_shift_reg")]
8b9dc177 3456)
3457
3dc953f2 3458(define_insn_and_split "*arm_smin_insn"
8b9dc177 3459 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3460 (smin:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3461 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
bd5b4116 3462 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3463 "TARGET_ARM"
3dc953f2 3464 "#"
3465 ; cmp\\t%1, %2\;movge\\t%0, %2
3466 ; cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
3467 "TARGET_ARM"
3468 [(set (reg:CC CC_REGNUM)
3469 (compare:CC (match_dup 1) (match_dup 2)))
3470 (set (match_dup 0)
3471 (if_then_else:SI (lt:SI (reg:CC CC_REGNUM) (const_int 0))
3472 (match_dup 1)
3473 (match_dup 2)))]
3474 ""
0d66636f 3475 [(set_attr "conds" "clob")
1b7da4ac 3476 (set_attr "length" "8,12")
3477 (set_attr "type" "multiple,multiple")]
0d66636f 3478)
9c08d1fa 3479
25f905c2 3480(define_expand "umaxsi3"
3481 [(parallel [
3482 (set (match_operand:SI 0 "s_register_operand" "")
3483 (umax:SI (match_operand:SI 1 "s_register_operand" "")
3484 (match_operand:SI 2 "arm_rhs_operand" "")))
3485 (clobber (reg:CC CC_REGNUM))])]
3486 "TARGET_32BIT"
3487 ""
3488)
3489
3dc953f2 3490(define_insn_and_split "*arm_umaxsi3"
9c08d1fa 3491 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3492 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3493 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 3494 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3495 "TARGET_ARM"
3dc953f2 3496 "#"
3497 ; cmp\\t%1, %2\;movcc\\t%0, %2
3498 ; cmp\\t%1, %2\;movcs\\t%0, %1
3499 ; cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
3500 "TARGET_ARM"
3501 [(set (reg:CC CC_REGNUM)
3502 (compare:CC (match_dup 1) (match_dup 2)))
3503 (set (match_dup 0)
3504 (if_then_else:SI (geu:SI (reg:CC CC_REGNUM) (const_int 0))
3505 (match_dup 1)
3506 (match_dup 2)))]
3507 ""
0d66636f 3508 [(set_attr "conds" "clob")
1b7da4ac 3509 (set_attr "length" "8,8,12")
3510 (set_attr "type" "store1")]
0d66636f 3511)
9c08d1fa 3512
25f905c2 3513(define_expand "uminsi3"
3514 [(parallel [
3515 (set (match_operand:SI 0 "s_register_operand" "")
3516 (umin:SI (match_operand:SI 1 "s_register_operand" "")
3517 (match_operand:SI 2 "arm_rhs_operand" "")))
3518 (clobber (reg:CC CC_REGNUM))])]
3519 "TARGET_32BIT"
3520 ""
3521)
3522
3dc953f2 3523(define_insn_and_split "*arm_uminsi3"
9c08d1fa 3524 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3525 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3526 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 3527 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3528 "TARGET_ARM"
3dc953f2 3529 "#"
3530 ; cmp\\t%1, %2\;movcs\\t%0, %2
3531 ; cmp\\t%1, %2\;movcc\\t%0, %1
3532 ; cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
3533 "TARGET_ARM"
3534 [(set (reg:CC CC_REGNUM)
3535 (compare:CC (match_dup 1) (match_dup 2)))
3536 (set (match_dup 0)
3537 (if_then_else:SI (ltu:SI (reg:CC CC_REGNUM) (const_int 0))
3538 (match_dup 1)
3539 (match_dup 2)))]
3540 ""
0d66636f 3541 [(set_attr "conds" "clob")
1b7da4ac 3542 (set_attr "length" "8,8,12")
3543 (set_attr "type" "store1")]
0d66636f 3544)
9c08d1fa 3545
8a18b90c 3546(define_insn "*store_minmaxsi"
9c08d1fa 3547 [(set (match_operand:SI 0 "memory_operand" "=m")
3548 (match_operator:SI 3 "minmax_operator"
3549 [(match_operand:SI 1 "s_register_operand" "r")
3550 (match_operand:SI 2 "s_register_operand" "r")]))
bd5b4116 3551 (clobber (reg:CC CC_REGNUM))]
b207d152 3552 "TARGET_32BIT && optimize_function_for_size_p (cfun) && !arm_restrict_it"
9c08d1fa 3553 "*
dc55b8a9 3554 operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
3555 operands[1], operands[2]);
e2348bcb 3556 output_asm_insn (\"cmp\\t%1, %2\", operands);
25f905c2 3557 if (TARGET_THUMB2)
3558 output_asm_insn (\"ite\t%d3\", operands);
e2348bcb 3559 output_asm_insn (\"str%d3\\t%1, %0\", operands);
3560 output_asm_insn (\"str%D3\\t%2, %0\", operands);
3561 return \"\";
0d66636f 3562 "
3563 [(set_attr "conds" "clob")
25f905c2 3564 (set (attr "length")
3565 (if_then_else (eq_attr "is_thumb" "yes")
3566 (const_int 14)
3567 (const_int 12)))
0d66636f 3568 (set_attr "type" "store1")]
3569)
9c08d1fa 3570
8a18b90c 3571; Reject the frame pointer in operand[1], since reloading this after
3572; it has been eliminated can cause carnage.
f7fbdd4a 3573(define_insn "*minmax_arithsi"
9c08d1fa 3574 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3575 (match_operator:SI 4 "shiftable_operator"
3576 [(match_operator:SI 5 "minmax_operator"
3577 [(match_operand:SI 2 "s_register_operand" "r,r")
3578 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
3579 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 3580 (clobber (reg:CC CC_REGNUM))]
7c36fe71 3581 "TARGET_32BIT && !arm_eliminable_register (operands[1]) && !arm_restrict_it"
9c08d1fa 3582 "*
0d66636f 3583 {
3584 enum rtx_code code = GET_CODE (operands[4]);
25f905c2 3585 bool need_else;
3586
3587 if (which_alternative != 0 || operands[3] != const0_rtx
ca0fc5a2 3588 || (code != PLUS && code != IOR && code != XOR))
25f905c2 3589 need_else = true;
3590 else
3591 need_else = false;
0d66636f 3592
dc55b8a9 3593 operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
3594 operands[2], operands[3]);
0d66636f 3595 output_asm_insn (\"cmp\\t%2, %3\", operands);
25f905c2 3596 if (TARGET_THUMB2)
3597 {
3598 if (need_else)
3599 output_asm_insn (\"ite\\t%d5\", operands);
3600 else
3601 output_asm_insn (\"it\\t%d5\", operands);
3602 }
0d66636f 3603 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
25f905c2 3604 if (need_else)
0d66636f 3605 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
3606 return \"\";
215b30b3 3607 }"
0d66636f 3608 [(set_attr "conds" "clob")
25f905c2 3609 (set (attr "length")
3610 (if_then_else (eq_attr "is_thumb" "yes")
3611 (const_int 14)
1b7da4ac 3612 (const_int 12)))
3613 (set_attr "type" "multiple")]
0d66636f 3614)
9c08d1fa 3615
4164bca1 3616; Reject the frame pointer in operand[1], since reloading this after
3617; it has been eliminated can cause carnage.
3618(define_insn_and_split "*minmax_arithsi_non_canon"
7c36fe71 3619 [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts")
4164bca1 3620 (minus:SI
7c36fe71 3621 (match_operand:SI 1 "s_register_operand" "0,?Ts")
4164bca1 3622 (match_operator:SI 4 "minmax_operator"
7c36fe71 3623 [(match_operand:SI 2 "s_register_operand" "Ts,Ts")
3624 (match_operand:SI 3 "arm_rhs_operand" "TsI,TsI")])))
4164bca1 3625 (clobber (reg:CC CC_REGNUM))]
7c36fe71 3626 "TARGET_32BIT && !arm_eliminable_register (operands[1])
3627 && !(arm_restrict_it && CONST_INT_P (operands[3]))"
4164bca1 3628 "#"
3629 "TARGET_32BIT && !arm_eliminable_register (operands[1]) && reload_completed"
3630 [(set (reg:CC CC_REGNUM)
3631 (compare:CC (match_dup 2) (match_dup 3)))
3632
3633 (cond_exec (match_op_dup 4 [(reg:CC CC_REGNUM) (const_int 0)])
3634 (set (match_dup 0)
3635 (minus:SI (match_dup 1)
3636 (match_dup 2))))
3637 (cond_exec (match_op_dup 5 [(reg:CC CC_REGNUM) (const_int 0)])
3638 (set (match_dup 0)
36ee0cde 3639 (match_dup 6)))]
4164bca1 3640 {
3754d046 3641 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
4164bca1 3642 operands[2], operands[3]);
3643 enum rtx_code rc = minmax_code (operands[4]);
3644 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode,
3645 operands[2], operands[3]);
3646
3647 if (mode == CCFPmode || mode == CCFPEmode)
3648 rc = reverse_condition_maybe_unordered (rc);
3649 else
3650 rc = reverse_condition (rc);
3651 operands[5] = gen_rtx_fmt_ee (rc, SImode, operands[2], operands[3]);
36ee0cde 3652 if (CONST_INT_P (operands[3]))
3653 operands[6] = plus_constant (SImode, operands[1], -INTVAL (operands[3]));
3654 else
3655 operands[6] = gen_rtx_MINUS (SImode, operands[1], operands[3]);
4164bca1 3656 }
3657 [(set_attr "conds" "clob")
3658 (set (attr "length")
3659 (if_then_else (eq_attr "is_thumb" "yes")
3660 (const_int 14)
1b7da4ac 3661 (const_int 12)))
3662 (set_attr "type" "multiple")]
4164bca1 3663)
3664
b49e3742 3665(define_code_iterator SAT [smin smax])
3666(define_code_iterator SATrev [smin smax])
3667(define_code_attr SATlo [(smin "1") (smax "2")])
3668(define_code_attr SAThi [(smin "2") (smax "1")])
3669
3670(define_insn "*satsi_<SAT:code>"
3671 [(set (match_operand:SI 0 "s_register_operand" "=r")
3672 (SAT:SI (SATrev:SI (match_operand:SI 3 "s_register_operand" "r")
3673 (match_operand:SI 1 "const_int_operand" "i"))
3674 (match_operand:SI 2 "const_int_operand" "i")))]
3675 "TARGET_32BIT && arm_arch6 && <SAT:CODE> != <SATrev:CODE>
3676 && arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>], NULL, NULL)"
3677{
3678 int mask;
3679 bool signed_sat;
3680 if (!arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>],
3681 &mask, &signed_sat))
3682 gcc_unreachable ();
3683
3684 operands[1] = GEN_INT (mask);
3685 if (signed_sat)
3686 return "ssat%?\t%0, %1, %3";
3687 else
3688 return "usat%?\t%0, %1, %3";
3689}
7c36fe71 3690 [(set_attr "predicable" "yes")
1b7da4ac 3691 (set_attr "predicable_short_it" "no")
3692 (set_attr "type" "alus_imm")]
bebe9bbb 3693)
b49e3742 3694
3695(define_insn "*satsi_<SAT:code>_shift"
3696 [(set (match_operand:SI 0 "s_register_operand" "=r")
3697 (SAT:SI (SATrev:SI (match_operator:SI 3 "sat_shift_operator"
3698 [(match_operand:SI 4 "s_register_operand" "r")
3699 (match_operand:SI 5 "const_int_operand" "i")])
3700 (match_operand:SI 1 "const_int_operand" "i"))
3701 (match_operand:SI 2 "const_int_operand" "i")))]
3702 "TARGET_32BIT && arm_arch6 && <SAT:CODE> != <SATrev:CODE>
3703 && arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>], NULL, NULL)"
3704{
3705 int mask;
3706 bool signed_sat;
3707 if (!arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>],
3708 &mask, &signed_sat))
3709 gcc_unreachable ();
3710
3711 operands[1] = GEN_INT (mask);
3712 if (signed_sat)
3713 return "ssat%?\t%0, %1, %4%S3";
3714 else
3715 return "usat%?\t%0, %1, %4%S3";
3716}
3717 [(set_attr "predicable" "yes")
7c36fe71 3718 (set_attr "predicable_short_it" "no")
b49e3742 3719 (set_attr "shift" "3")
d82e788e 3720 (set_attr "type" "logic_shift_reg")])
b11cae9e 3721\f
3722;; Shift and rotation insns
3723
a2cd141b 3724(define_expand "ashldi3"
3725 [(set (match_operand:DI 0 "s_register_operand" "")
3726 (ashift:DI (match_operand:DI 1 "s_register_operand" "")
aa06c51c 3727 (match_operand:SI 2 "general_operand" "")))]
25f905c2 3728 "TARGET_32BIT"
a2cd141b 3729 "
aa06c51c 3730 if (TARGET_NEON)
3731 {
3732 /* Delay the decision whether to use NEON or core-regs until
3733 register allocation. */
3734 emit_insn (gen_ashldi3_neon (operands[0], operands[1], operands[2]));
3735 DONE;
3736 }
3737 else
3738 {
3739 /* Only the NEON case can handle in-memory shift counts. */
3740 if (!reg_or_int_operand (operands[2], SImode))
3741 operands[2] = force_reg (SImode, operands[2]);
3742 }
3743
b805622c 3744 if (!CONST_INT_P (operands[2]) && TARGET_REALLY_IWMMXT)
ffcc986d 3745 ; /* No special preparation statements; expand pattern as above. */
3746 else
a2cd141b 3747 {
ffcc986d 3748 rtx scratch1, scratch2;
3749
3750 if (CONST_INT_P (operands[2])
3751 && (HOST_WIDE_INT) INTVAL (operands[2]) == 1)
a2cd141b 3752 {
3753 emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
3754 DONE;
3755 }
ffcc986d 3756
3757 /* Ideally we should use iwmmxt here if we could know that operands[1]
3758 ends up already living in an iwmmxt register. Otherwise it's
3759 cheaper to have the alternate code being generated than moving
3760 values to iwmmxt regs and back. */
3761
3762 /* If we're optimizing for size, we prefer the libgcc calls. */
3763 if (optimize_function_for_size_p (cfun))
3764 FAIL;
3765
3766 /* Expand operation using core-registers.
3767 'FAIL' would achieve the same thing, but this is a bit smarter. */
3768 scratch1 = gen_reg_rtx (SImode);
3769 scratch2 = gen_reg_rtx (SImode);
3770 arm_emit_coreregs_64bit_shift (ASHIFT, operands[0], operands[1],
3771 operands[2], scratch1, scratch2);
3772 DONE;
a2cd141b 3773 }
a2cd141b 3774 "
3775)
3776
2837e3fb 3777(define_insn "arm_ashldi3_1bit"
50ad1bf9 3778 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 3779 (ashift:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 3780 (const_int 1)))
3781 (clobber (reg:CC CC_REGNUM))]
25f905c2 3782 "TARGET_32BIT"
2837e3fb 3783 "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
a2cd141b 3784 [(set_attr "conds" "clob")
1b7da4ac 3785 (set_attr "length" "8")
3786 (set_attr "type" "multiple")]
a2cd141b 3787)
3788
87b22bf7 3789(define_expand "ashlsi3"
cffb2a26 3790 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3791 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
3792 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3793 "TARGET_EITHER"
87b22bf7 3794 "
0438d37f 3795 if (CONST_INT_P (operands[2])
87b22bf7 3796 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3797 {
3798 emit_insn (gen_movsi (operands[0], const0_rtx));
3799 DONE;
3800 }
cffb2a26 3801 "
3802)
3803
a2cd141b 3804(define_expand "ashrdi3"
3805 [(set (match_operand:DI 0 "s_register_operand" "")
3806 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
3807 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3808 "TARGET_32BIT"
a2cd141b 3809 "
aa06c51c 3810 if (TARGET_NEON)
3811 {
3812 /* Delay the decision whether to use NEON or core-regs until
3813 register allocation. */
3814 emit_insn (gen_ashrdi3_neon (operands[0], operands[1], operands[2]));
3815 DONE;
3816 }
3817
b805622c 3818 if (!CONST_INT_P (operands[2]) && TARGET_REALLY_IWMMXT)
ffcc986d 3819 ; /* No special preparation statements; expand pattern as above. */
3820 else
a2cd141b 3821 {
ffcc986d 3822 rtx scratch1, scratch2;
3823
3824 if (CONST_INT_P (operands[2])
3825 && (HOST_WIDE_INT) INTVAL (operands[2]) == 1)
a2cd141b 3826 {
3827 emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
3828 DONE;
3829 }
ffcc986d 3830
3831 /* Ideally we should use iwmmxt here if we could know that operands[1]
3832 ends up already living in an iwmmxt register. Otherwise it's
3833 cheaper to have the alternate code being generated than moving
3834 values to iwmmxt regs and back. */
3835
3836 /* If we're optimizing for size, we prefer the libgcc calls. */
3837 if (optimize_function_for_size_p (cfun))
3838 FAIL;
3839
3840 /* Expand operation using core-registers.
3841 'FAIL' would achieve the same thing, but this is a bit smarter. */
3842 scratch1 = gen_reg_rtx (SImode);
3843 scratch2 = gen_reg_rtx (SImode);
3844 arm_emit_coreregs_64bit_shift (ASHIFTRT, operands[0], operands[1],
3845 operands[2], scratch1, scratch2);
3846 DONE;
a2cd141b 3847 }
a2cd141b 3848 "
3849)
3850
2837e3fb 3851(define_insn "arm_ashrdi3_1bit"
50ad1bf9 3852 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 3853 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 3854 (const_int 1)))
3855 (clobber (reg:CC CC_REGNUM))]
25f905c2 3856 "TARGET_32BIT"
2837e3fb 3857 "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
a2cd141b 3858 [(set_attr "conds" "clob")
1b7da4ac 3859 (set_attr "length" "8")
3860 (set_attr "type" "multiple")]
a2cd141b 3861)
3862
87b22bf7 3863(define_expand "ashrsi3"
cffb2a26 3864 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3865 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
3866 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3867 "TARGET_EITHER"
87b22bf7 3868 "
0438d37f 3869 if (CONST_INT_P (operands[2])
87b22bf7 3870 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3871 operands[2] = GEN_INT (31);
cffb2a26 3872 "
3873)
3874
a2cd141b 3875(define_expand "lshrdi3"
3876 [(set (match_operand:DI 0 "s_register_operand" "")
3877 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
3878 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3879 "TARGET_32BIT"
a2cd141b 3880 "
aa06c51c 3881 if (TARGET_NEON)
3882 {
3883 /* Delay the decision whether to use NEON or core-regs until
3884 register allocation. */
3885 emit_insn (gen_lshrdi3_neon (operands[0], operands[1], operands[2]));
3886 DONE;
3887 }
3888
b805622c 3889 if (!CONST_INT_P (operands[2]) && TARGET_REALLY_IWMMXT)
ffcc986d 3890 ; /* No special preparation statements; expand pattern as above. */
3891 else
a2cd141b 3892 {
ffcc986d 3893 rtx scratch1, scratch2;
3894
3895 if (CONST_INT_P (operands[2])
3896 && (HOST_WIDE_INT) INTVAL (operands[2]) == 1)
a2cd141b 3897 {
3898 emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
3899 DONE;
3900 }
ffcc986d 3901
3902 /* Ideally we should use iwmmxt here if we could know that operands[1]
3903 ends up already living in an iwmmxt register. Otherwise it's
3904 cheaper to have the alternate code being generated than moving
3905 values to iwmmxt regs and back. */
3906
3907 /* If we're optimizing for size, we prefer the libgcc calls. */
3908 if (optimize_function_for_size_p (cfun))
3909 FAIL;
3910
3911 /* Expand operation using core-registers.
3912 'FAIL' would achieve the same thing, but this is a bit smarter. */
3913 scratch1 = gen_reg_rtx (SImode);
3914 scratch2 = gen_reg_rtx (SImode);
3915 arm_emit_coreregs_64bit_shift (LSHIFTRT, operands[0], operands[1],
3916 operands[2], scratch1, scratch2);
3917 DONE;
a2cd141b 3918 }
a2cd141b 3919 "
3920)
3921
2837e3fb 3922(define_insn "arm_lshrdi3_1bit"
50ad1bf9 3923 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 3924 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 3925 (const_int 1)))
3926 (clobber (reg:CC CC_REGNUM))]
25f905c2 3927 "TARGET_32BIT"
2837e3fb 3928 "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
a2cd141b 3929 [(set_attr "conds" "clob")
1b7da4ac 3930 (set_attr "length" "8")
3931 (set_attr "type" "multiple")]
a2cd141b 3932)
3933
87b22bf7 3934(define_expand "lshrsi3"
cffb2a26 3935 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3936 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
3937 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3938 "TARGET_EITHER"
87b22bf7 3939 "
0438d37f 3940 if (CONST_INT_P (operands[2])
87b22bf7 3941 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3942 {
3943 emit_insn (gen_movsi (operands[0], const0_rtx));
3944 DONE;
3945 }
cffb2a26 3946 "
3947)
3948
87b22bf7 3949(define_expand "rotlsi3"
cffb2a26 3950 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3951 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
3952 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3953 "TARGET_32BIT"
87b22bf7 3954 "
0438d37f 3955 if (CONST_INT_P (operands[2]))
87b22bf7 3956 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
3957 else
b11cae9e 3958 {
87b22bf7 3959 rtx reg = gen_reg_rtx (SImode);
3960 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
3961 operands[2] = reg;
b11cae9e 3962 }
cffb2a26 3963 "
3964)
9c08d1fa 3965
87b22bf7 3966(define_expand "rotrsi3"
cffb2a26 3967 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3968 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
3969 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3970 "TARGET_EITHER"
87b22bf7 3971 "
25f905c2 3972 if (TARGET_32BIT)
cffb2a26 3973 {
0438d37f 3974 if (CONST_INT_P (operands[2])
cffb2a26 3975 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3976 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
3977 }
25f905c2 3978 else /* TARGET_THUMB1 */
cffb2a26 3979 {
0438d37f 3980 if (CONST_INT_P (operands [2]))
cffb2a26 3981 operands [2] = force_reg (SImode, operands[2]);
3982 }
3983 "
3984)
87b22bf7 3985
cffb2a26 3986(define_insn "*arm_shiftsi3"
88c29385 3987 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r,r")
cffb2a26 3988 (match_operator:SI 3 "shift_operator"
88c29385 3989 [(match_operand:SI 1 "s_register_operand" "0,l,r,r")
3990 (match_operand:SI 2 "reg_or_int_operand" "l,M,M,r")]))]
25f905c2 3991 "TARGET_32BIT"
3992 "* return arm_output_shift(operands, 0);"
344495ea 3993 [(set_attr "predicable" "yes")
88c29385 3994 (set_attr "arch" "t2,t2,*,*")
3995 (set_attr "predicable_short_it" "yes,yes,no,no")
7c36fe71 3996 (set_attr "length" "4")
331beb1a 3997 (set_attr "shift" "1")
88c29385 3998 (set_attr "type" "alu_shift_reg,alu_shift_imm,alu_shift_imm,alu_shift_reg")]
6c4c2133 3999)
87b22bf7 4000
f7fbdd4a 4001(define_insn "*shiftsi3_compare0"
bd5b4116 4002 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 4003 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
6b6abc9c 4004 [(match_operand:SI 1 "s_register_operand" "r,r")
4005 (match_operand:SI 2 "arm_rhs_operand" "M,r")])
9c08d1fa 4006 (const_int 0)))
6b6abc9c 4007 (set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 4008 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
25f905c2 4009 "TARGET_32BIT"
4010 "* return arm_output_shift(operands, 1);"
344495ea 4011 [(set_attr "conds" "set")
331beb1a 4012 (set_attr "shift" "1")
d82e788e 4013 (set_attr "type" "alus_shift_imm,alus_shift_reg")]
0d66636f 4014)
9c08d1fa 4015
f7fbdd4a 4016(define_insn "*shiftsi3_compare0_scratch"
bd5b4116 4017 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 4018 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
6b6abc9c 4019 [(match_operand:SI 1 "s_register_operand" "r,r")
4020 (match_operand:SI 2 "arm_rhs_operand" "M,r")])
9c08d1fa 4021 (const_int 0)))
6b6abc9c 4022 (clobber (match_scratch:SI 0 "=r,r"))]
25f905c2 4023 "TARGET_32BIT"
4024 "* return arm_output_shift(operands, 1);"
344495ea 4025 [(set_attr "conds" "set")
6b6abc9c 4026 (set_attr "shift" "1")
d82e788e 4027 (set_attr "type" "shift_imm,shift_reg")]
0d66636f 4028)
9c08d1fa 4029
d5d4dc8d 4030(define_insn "*not_shiftsi"
4031 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 4032 (not:SI (match_operator:SI 3 "shift_operator"
d5d4dc8d 4033 [(match_operand:SI 1 "s_register_operand" "r,r")
4034 (match_operand:SI 2 "shift_amount_operand" "M,rM")])))]
4035 "TARGET_32BIT"
6c4c2133 4036 "mvn%?\\t%0, %1%S3"
344495ea 4037 [(set_attr "predicable" "yes")
d952d547 4038 (set_attr "predicable_short_it" "no")
331beb1a 4039 (set_attr "shift" "1")
d5d4dc8d 4040 (set_attr "arch" "32,a")
1aed5204 4041 (set_attr "type" "mvn_shift,mvn_shift_reg")])
9c08d1fa 4042
d5d4dc8d 4043(define_insn "*not_shiftsi_compare0"
bd5b4116 4044 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 4045 (compare:CC_NOOV
4046 (not:SI (match_operator:SI 3 "shift_operator"
4047 [(match_operand:SI 1 "s_register_operand" "r,r")
4048 (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
4049 (const_int 0)))
4050 (set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 4051 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
d5d4dc8d 4052 "TARGET_32BIT"
3ef90e77 4053 "mvns%?\\t%0, %1%S3"
344495ea 4054 [(set_attr "conds" "set")
331beb1a 4055 (set_attr "shift" "1")
d5d4dc8d 4056 (set_attr "arch" "32,a")
1aed5204 4057 (set_attr "type" "mvn_shift,mvn_shift_reg")])
9c08d1fa 4058
d5d4dc8d 4059(define_insn "*not_shiftsi_compare0_scratch"
bd5b4116 4060 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 4061 (compare:CC_NOOV
4062 (not:SI (match_operator:SI 3 "shift_operator"
4063 [(match_operand:SI 1 "s_register_operand" "r,r")
4064 (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
4065 (const_int 0)))
4066 (clobber (match_scratch:SI 0 "=r,r"))]
4067 "TARGET_32BIT"
3ef90e77 4068 "mvns%?\\t%0, %1%S3"
344495ea 4069 [(set_attr "conds" "set")
331beb1a 4070 (set_attr "shift" "1")
d5d4dc8d 4071 (set_attr "arch" "32,a")
1aed5204 4072 (set_attr "type" "mvn_shift,mvn_shift_reg")])
9c08d1fa 4073
cffb2a26 4074;; We don't really have extzv, but defining this using shifts helps
4075;; to reduce register pressure later on.
4076
4077(define_expand "extzv"
eb04cafb 4078 [(set (match_operand 0 "s_register_operand" "")
4079 (zero_extract (match_operand 1 "nonimmediate_operand" "")
4080 (match_operand 2 "const_int_operand" "")
4081 (match_operand 3 "const_int_operand" "")))]
8b054d5a 4082 "TARGET_THUMB1 || arm_arch_thumb2"
cffb2a26 4083 "
4084 {
4085 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
4086 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
4087
8b054d5a 4088 if (arm_arch_thumb2)
4089 {
eb04cafb 4090 HOST_WIDE_INT width = INTVAL (operands[2]);
4091 HOST_WIDE_INT bitpos = INTVAL (operands[3]);
4092
4093 if (unaligned_access && MEM_P (operands[1])
4094 && (width == 16 || width == 32) && (bitpos % BITS_PER_UNIT) == 0)
4095 {
4096 rtx base_addr;
4097
4098 if (BYTES_BIG_ENDIAN)
4099 bitpos = GET_MODE_BITSIZE (GET_MODE (operands[0])) - width
4100 - bitpos;
4101
4102 if (width == 32)
4103 {
4104 base_addr = adjust_address (operands[1], SImode,
4105 bitpos / BITS_PER_UNIT);
4106 emit_insn (gen_unaligned_loadsi (operands[0], base_addr));
4107 }
4108 else
4109 {
4110 rtx dest = operands[0];
4111 rtx tmp = gen_reg_rtx (SImode);
4112
4113 /* We may get a paradoxical subreg here. Strip it off. */
4114 if (GET_CODE (dest) == SUBREG
4115 && GET_MODE (dest) == SImode
4116 && GET_MODE (SUBREG_REG (dest)) == HImode)
4117 dest = SUBREG_REG (dest);
4118
4119 if (GET_MODE_BITSIZE (GET_MODE (dest)) != width)
4120 FAIL;
4121
4122 base_addr = adjust_address (operands[1], HImode,
4123 bitpos / BITS_PER_UNIT);
4124 emit_insn (gen_unaligned_loadhiu (tmp, base_addr));
4125 emit_move_insn (gen_lowpart (SImode, dest), tmp);
4126 }
4127 DONE;
4128 }
4129 else if (s_register_operand (operands[1], GET_MODE (operands[1])))
4130 {
4131 emit_insn (gen_extzv_t2 (operands[0], operands[1], operands[2],
4132 operands[3]));
4133 DONE;
4134 }
4135 else
4136 FAIL;
8b054d5a 4137 }
eb04cafb 4138
4139 if (!s_register_operand (operands[1], GET_MODE (operands[1])))
4140 FAIL;
8b054d5a 4141
cffb2a26 4142 operands[3] = GEN_INT (rshift);
4143
4144 if (lshift == 0)
4145 {
4146 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
4147 DONE;
4148 }
4149
eb04cafb 4150 emit_insn (gen_extzv_t1 (operands[0], operands[1], GEN_INT (lshift),
4151 operands[3], gen_reg_rtx (SImode)));
4152 DONE;
215b30b3 4153 }"
cffb2a26 4154)
4155
eb04cafb 4156;; Helper for extzv, for the Thumb-1 register-shifts case.
4157
4158(define_expand "extzv_t1"
4159 [(set (match_operand:SI 4 "s_register_operand" "")
4160 (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "")
4161 (match_operand:SI 2 "const_int_operand" "")))
4162 (set (match_operand:SI 0 "s_register_operand" "")
4163 (lshiftrt:SI (match_dup 4)
4164 (match_operand:SI 3 "const_int_operand" "")))]
4165 "TARGET_THUMB1"
4166 "")
4167
4168(define_expand "extv"
4169 [(set (match_operand 0 "s_register_operand" "")
4170 (sign_extract (match_operand 1 "nonimmediate_operand" "")
4171 (match_operand 2 "const_int_operand" "")
4172 (match_operand 3 "const_int_operand" "")))]
4173 "arm_arch_thumb2"
4174{
4175 HOST_WIDE_INT width = INTVAL (operands[2]);
4176 HOST_WIDE_INT bitpos = INTVAL (operands[3]);
4177
4178 if (unaligned_access && MEM_P (operands[1]) && (width == 16 || width == 32)
4179 && (bitpos % BITS_PER_UNIT) == 0)
4180 {
4181 rtx base_addr;
4182
4183 if (BYTES_BIG_ENDIAN)
4184 bitpos = GET_MODE_BITSIZE (GET_MODE (operands[0])) - width - bitpos;
4185
4186 if (width == 32)
4187 {
4188 base_addr = adjust_address (operands[1], SImode,
4189 bitpos / BITS_PER_UNIT);
4190 emit_insn (gen_unaligned_loadsi (operands[0], base_addr));
4191 }
4192 else
4193 {
4194 rtx dest = operands[0];
4195 rtx tmp = gen_reg_rtx (SImode);
4196
4197 /* We may get a paradoxical subreg here. Strip it off. */
4198 if (GET_CODE (dest) == SUBREG
4199 && GET_MODE (dest) == SImode
4200 && GET_MODE (SUBREG_REG (dest)) == HImode)
4201 dest = SUBREG_REG (dest);
4202
4203 if (GET_MODE_BITSIZE (GET_MODE (dest)) != width)
4204 FAIL;
4205
4206 base_addr = adjust_address (operands[1], HImode,
4207 bitpos / BITS_PER_UNIT);
4208 emit_insn (gen_unaligned_loadhis (tmp, base_addr));
4209 emit_move_insn (gen_lowpart (SImode, dest), tmp);
4210 }
4211
4212 DONE;
4213 }
4214 else if (!s_register_operand (operands[1], GET_MODE (operands[1])))
4215 FAIL;
4216 else if (GET_MODE (operands[0]) == SImode
4217 && GET_MODE (operands[1]) == SImode)
4218 {
4219 emit_insn (gen_extv_regsi (operands[0], operands[1], operands[2],
4220 operands[3]));
4221 DONE;
4222 }
4223
4224 FAIL;
4225})
4226
4227; Helper to expand register forms of extv with the proper modes.
4228
4229(define_expand "extv_regsi"
4230 [(set (match_operand:SI 0 "s_register_operand" "")
4231 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
4232 (match_operand 2 "const_int_operand" "")
4233 (match_operand 3 "const_int_operand" "")))]
4234 ""
4235{
4236})
4237
4238; ARMv6+ unaligned load/store instructions (used for packed structure accesses).
4239
4240(define_insn "unaligned_loadsi"
4241 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4242 (unspec:SI [(match_operand:SI 1 "memory_operand" "Uw,m")]
4243 UNSPEC_UNALIGNED_LOAD))]
8fe38eb2 4244 "unaligned_access"
eb04cafb 4245 "ldr%?\t%0, %1\t@ unaligned"
4246 [(set_attr "arch" "t2,any")
4247 (set_attr "length" "2,4")
4248 (set_attr "predicable" "yes")
d952d547 4249 (set_attr "predicable_short_it" "yes,no")
eb04cafb 4250 (set_attr "type" "load1")])
4251
4252(define_insn "unaligned_loadhis"
4253 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4254 (sign_extend:SI
e3f4ccee 4255 (unspec:HI [(match_operand:HI 1 "memory_operand" "Uw,Uh")]
eb04cafb 4256 UNSPEC_UNALIGNED_LOAD)))]
8fe38eb2 4257 "unaligned_access"
3ef90e77 4258 "ldrsh%?\t%0, %1\t@ unaligned"
eb04cafb 4259 [(set_attr "arch" "t2,any")
4260 (set_attr "length" "2,4")
4261 (set_attr "predicable" "yes")
d952d547 4262 (set_attr "predicable_short_it" "yes,no")
eb04cafb 4263 (set_attr "type" "load_byte")])
4264
4265(define_insn "unaligned_loadhiu"
4266 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4267 (zero_extend:SI
4268 (unspec:HI [(match_operand:HI 1 "memory_operand" "Uw,m")]
4269 UNSPEC_UNALIGNED_LOAD)))]
8fe38eb2 4270 "unaligned_access"
3ef90e77 4271 "ldrh%?\t%0, %1\t@ unaligned"
eb04cafb 4272 [(set_attr "arch" "t2,any")
4273 (set_attr "length" "2,4")
4274 (set_attr "predicable" "yes")
d952d547 4275 (set_attr "predicable_short_it" "yes,no")
eb04cafb 4276 (set_attr "type" "load_byte")])
4277
4278(define_insn "unaligned_storesi"
4279 [(set (match_operand:SI 0 "memory_operand" "=Uw,m")
4280 (unspec:SI [(match_operand:SI 1 "s_register_operand" "l,r")]
4281 UNSPEC_UNALIGNED_STORE))]
8fe38eb2 4282 "unaligned_access"
eb04cafb 4283 "str%?\t%1, %0\t@ unaligned"
4284 [(set_attr "arch" "t2,any")
4285 (set_attr "length" "2,4")
4286 (set_attr "predicable" "yes")
d952d547 4287 (set_attr "predicable_short_it" "yes,no")
eb04cafb 4288 (set_attr "type" "store1")])
4289
4290(define_insn "unaligned_storehi"
4291 [(set (match_operand:HI 0 "memory_operand" "=Uw,m")
4292 (unspec:HI [(match_operand:HI 1 "s_register_operand" "l,r")]
4293 UNSPEC_UNALIGNED_STORE))]
8fe38eb2 4294 "unaligned_access"
3ef90e77 4295 "strh%?\t%1, %0\t@ unaligned"
eb04cafb 4296 [(set_attr "arch" "t2,any")
4297 (set_attr "length" "2,4")
4298 (set_attr "predicable" "yes")
d952d547 4299 (set_attr "predicable_short_it" "yes,no")
eb04cafb 4300 (set_attr "type" "store1")])
4301
ae51a965 4302
eb04cafb 4303(define_insn "*extv_reg"
8b054d5a 4304 [(set (match_operand:SI 0 "s_register_operand" "=r")
4305 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
809003b3 4306 (match_operand:SI 2 "const_int_M_operand" "M")
4307 (match_operand:SI 3 "const_int_M_operand" "M")))]
8b054d5a 4308 "arm_arch_thumb2"
4309 "sbfx%?\t%0, %1, %3, %2"
4310 [(set_attr "length" "4")
d952d547 4311 (set_attr "predicable" "yes")
d82e788e 4312 (set_attr "predicable_short_it" "no")
4313 (set_attr "type" "bfm")]
8b054d5a 4314)
4315
4316(define_insn "extzv_t2"
4317 [(set (match_operand:SI 0 "s_register_operand" "=r")
4318 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "r")
809003b3 4319 (match_operand:SI 2 "const_int_M_operand" "M")
4320 (match_operand:SI 3 "const_int_M_operand" "M")))]
8b054d5a 4321 "arm_arch_thumb2"
4322 "ubfx%?\t%0, %1, %3, %2"
4323 [(set_attr "length" "4")
d952d547 4324 (set_attr "predicable" "yes")
d82e788e 4325 (set_attr "predicable_short_it" "no")
4326 (set_attr "type" "bfm")]
8b054d5a 4327)
4328
7d3cda8c 4329
4330;; Division instructions
4331(define_insn "divsi3"
4332 [(set (match_operand:SI 0 "s_register_operand" "=r")
4333 (div:SI (match_operand:SI 1 "s_register_operand" "r")
4334 (match_operand:SI 2 "s_register_operand" "r")))]
4335 "TARGET_IDIV"
4336 "sdiv%?\t%0, %1, %2"
4337 [(set_attr "predicable" "yes")
d952d547 4338 (set_attr "predicable_short_it" "no")
9da0ec36 4339 (set_attr "type" "sdiv")]
7d3cda8c 4340)
4341
4342(define_insn "udivsi3"
4343 [(set (match_operand:SI 0 "s_register_operand" "=r")
4344 (udiv:SI (match_operand:SI 1 "s_register_operand" "r")
4345 (match_operand:SI 2 "s_register_operand" "r")))]
4346 "TARGET_IDIV"
4347 "udiv%?\t%0, %1, %2"
4348 [(set_attr "predicable" "yes")
d952d547 4349 (set_attr "predicable_short_it" "no")
9da0ec36 4350 (set_attr "type" "udiv")]
7d3cda8c 4351)
4352
b11cae9e 4353\f
4354;; Unary arithmetic insns
4355
cffb2a26 4356(define_expand "negdi2"
4357 [(parallel
8135a42b 4358 [(set (match_operand:DI 0 "s_register_operand" "")
4359 (neg:DI (match_operand:DI 1 "s_register_operand" "")))
bd5b4116 4360 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 4361 "TARGET_EITHER"
774d2fbb 4362 {
4363 if (TARGET_NEON)
4364 {
4365 emit_insn (gen_negdi2_neon (operands[0], operands[1]));
4366 DONE;
4367 }
4368 }
cffb2a26 4369)
4370
4371;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
e5fea38e 4372;; The first alternative allows the common case of a *full* overlap.
ba6a3b2f 4373(define_insn_and_split "*arm_negdi2"
458a8706 4374 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 4375 (neg:DI (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 4376 (clobber (reg:CC CC_REGNUM))]
cffb2a26 4377 "TARGET_ARM"
ba6a3b2f 4378 "#" ; "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
4379 "&& reload_completed"
4380 [(parallel [(set (reg:CC CC_REGNUM)
4381 (compare:CC (const_int 0) (match_dup 1)))
4382 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 1)))])
4383 (set (match_dup 2) (minus:SI (minus:SI (const_int 0) (match_dup 3))
4384 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
4385 {
4386 operands[2] = gen_highpart (SImode, operands[0]);
4387 operands[0] = gen_lowpart (SImode, operands[0]);
4388 operands[3] = gen_highpart (SImode, operands[1]);
4389 operands[1] = gen_lowpart (SImode, operands[1]);
4390 }
cffb2a26 4391 [(set_attr "conds" "clob")
1b7da4ac 4392 (set_attr "length" "8")
4393 (set_attr "type" "multiple")]
cffb2a26 4394)
b11cae9e 4395
cffb2a26 4396(define_expand "negsi2"
4397 [(set (match_operand:SI 0 "s_register_operand" "")
4398 (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
4399 "TARGET_EITHER"
b11cae9e 4400 ""
cffb2a26 4401)
4402
4403(define_insn "*arm_negsi2"
d952d547 4404 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4405 (neg:SI (match_operand:SI 1 "s_register_operand" "l,r")))]
25f905c2 4406 "TARGET_32BIT"
cffb2a26 4407 "rsb%?\\t%0, %1, #0"
d952d547 4408 [(set_attr "predicable" "yes")
4409 (set_attr "predicable_short_it" "yes,no")
4410 (set_attr "arch" "t2,*")
1b7da4ac 4411 (set_attr "length" "4")
112eda6f 4412 (set_attr "type" "alu_sreg")]
cffb2a26 4413)
4414
604f3a0a 4415(define_expand "negsf2"
4416 [(set (match_operand:SF 0 "s_register_operand" "")
4417 (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
994606f8 4418 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
604f3a0a 4419 ""
4420)
4421
4422(define_expand "negdf2"
4423 [(set (match_operand:DF 0 "s_register_operand" "")
4424 (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
994606f8 4425 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
604f3a0a 4426 "")
4427
7eaf2be0 4428(define_insn_and_split "*zextendsidi_negsi"
4429 [(set (match_operand:DI 0 "s_register_operand" "=r")
4430 (zero_extend:DI (neg:SI (match_operand:SI 1 "s_register_operand" "r"))))]
4431 "TARGET_32BIT"
4432 "#"
4433 ""
4434 [(set (match_dup 2)
4435 (neg:SI (match_dup 1)))
4436 (set (match_dup 3)
4437 (const_int 0))]
4438 {
4439 operands[2] = gen_lowpart (SImode, operands[0]);
4440 operands[3] = gen_highpart (SImode, operands[0]);
4441 }
4442 [(set_attr "length" "8")
4443 (set_attr "type" "multiple")]
4444)
4445
83e2b922 4446;; Negate an extended 32-bit value.
4447(define_insn_and_split "*negdi_extendsidi"
61fa8ff2 4448 [(set (match_operand:DI 0 "s_register_operand" "=l,r")
4449 (neg:DI (sign_extend:DI
4450 (match_operand:SI 1 "s_register_operand" "l,r"))))
83e2b922 4451 (clobber (reg:CC CC_REGNUM))]
4452 "TARGET_32BIT"
61fa8ff2 4453 "#"
83e2b922 4454 "&& reload_completed"
4455 [(const_int 0)]
4456 {
61fa8ff2 4457 rtx low = gen_lowpart (SImode, operands[0]);
4458 rtx high = gen_highpart (SImode, operands[0]);
4459
4460 if (reg_overlap_mentioned_p (low, operands[1]))
4461 {
4462 /* Input overlaps the low word of the output. Use:
4463 asr Rhi, Rin, #31
4464 rsbs Rlo, Rin, #0
4465 rsc Rhi, Rhi, #0 (thumb2: sbc Rhi, Rhi, Rhi, lsl #1). */
4466 rtx cc_reg = gen_rtx_REG (CC_Cmode, CC_REGNUM);
4467
d1f9b275 4468 emit_insn (gen_rtx_SET (high,
61fa8ff2 4469 gen_rtx_ASHIFTRT (SImode, operands[1],
4470 GEN_INT (31))));
4471
4472 emit_insn (gen_subsi3_compare (low, const0_rtx, operands[1]));
4473 if (TARGET_ARM)
d1f9b275 4474 emit_insn (gen_rtx_SET (high,
61fa8ff2 4475 gen_rtx_MINUS (SImode,
4476 gen_rtx_MINUS (SImode,
4477 const0_rtx,
4478 high),
4479 gen_rtx_LTU (SImode,
4480 cc_reg,
4481 const0_rtx))));
4482 else
4483 {
4484 rtx two_x = gen_rtx_ASHIFT (SImode, high, GEN_INT (1));
d1f9b275 4485 emit_insn (gen_rtx_SET (high,
61fa8ff2 4486 gen_rtx_MINUS (SImode,
4487 gen_rtx_MINUS (SImode,
4488 high,
4489 two_x),
4490 gen_rtx_LTU (SImode,
4491 cc_reg,
4492 const0_rtx))));
4493 }
4494 }
4495 else
4496 {
4497 /* No overlap, or overlap on high word. Use:
4498 rsb Rlo, Rin, #0
4499 bic Rhi, Rlo, Rin
4500 asr Rhi, Rhi, #31
4501 Flags not needed for this sequence. */
d1f9b275 4502 emit_insn (gen_rtx_SET (low, gen_rtx_NEG (SImode, operands[1])));
4503 emit_insn (gen_rtx_SET (high,
61fa8ff2 4504 gen_rtx_AND (SImode,
4505 gen_rtx_NOT (SImode, operands[1]),
4506 low)));
d1f9b275 4507 emit_insn (gen_rtx_SET (high,
61fa8ff2 4508 gen_rtx_ASHIFTRT (SImode, high,
4509 GEN_INT (31))));
4510 }
4511 DONE;
83e2b922 4512 }
61fa8ff2 4513 [(set_attr "length" "12")
4514 (set_attr "arch" "t2,*")
1b7da4ac 4515 (set_attr "type" "multiple")]
83e2b922 4516)
4517
4518(define_insn_and_split "*negdi_zero_extendsidi"
4519 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
4520 (neg:DI (zero_extend:DI (match_operand:SI 1 "s_register_operand" "0,r"))))
4521 (clobber (reg:CC CC_REGNUM))]
4522 "TARGET_32BIT"
4523 "#" ; "rsbs\\t%Q0, %1, #0\;sbc\\t%R0,%R0,%R0"
4524 ;; Don't care what register is input to sbc,
47ae02b7 4525 ;; since we just need to propagate the carry.
83e2b922 4526 "&& reload_completed"
4527 [(parallel [(set (reg:CC CC_REGNUM)
4528 (compare:CC (const_int 0) (match_dup 1)))
4529 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 1)))])
4530 (set (match_dup 2) (minus:SI (minus:SI (match_dup 2) (match_dup 2))
4531 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
4532 {
4533 operands[2] = gen_highpart (SImode, operands[0]);
4534 operands[0] = gen_lowpart (SImode, operands[0]);
4535 }
4536 [(set_attr "conds" "clob")
1b7da4ac 4537 (set_attr "length" "8")
4538 (set_attr "type" "multiple")] ;; length in thumb is 4
83e2b922 4539)
4540
9c08d1fa 4541;; abssi2 doesn't really clobber the condition codes if a different register
4542;; is being set. To keep things simple, assume during rtl manipulations that
4543;; it does, but tell the final scan operator the truth. Similarly for
4544;; (neg (abs...))
4545
604f3a0a 4546(define_expand "abssi2"
4547 [(parallel
4548 [(set (match_operand:SI 0 "s_register_operand" "")
4549 (abs:SI (match_operand:SI 1 "s_register_operand" "")))
ba156559 4550 (clobber (match_dup 2))])]
4551 "TARGET_EITHER"
4552 "
25f905c2 4553 if (TARGET_THUMB1)
ba156559 4554 operands[2] = gen_rtx_SCRATCH (SImode);
4555 else
4556 operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
4557")
604f3a0a 4558
ba6a3b2f 4559(define_insn_and_split "*arm_abssi2"
ba156559 4560 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
9c08d1fa 4561 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
bd5b4116 4562 (clobber (reg:CC CC_REGNUM))]
cffb2a26 4563 "TARGET_ARM"
ba6a3b2f 4564 "#"
4565 "&& reload_completed"
4566 [(const_int 0)]
4567 {
4568 /* if (which_alternative == 0) */
4569 if (REGNO(operands[0]) == REGNO(operands[1]))
4570 {
4571 /* Emit the pattern:
4572 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
4573 [(set (reg:CC CC_REGNUM)
4574 (compare:CC (match_dup 0) (const_int 0)))
4575 (cond_exec (lt:CC (reg:CC CC_REGNUM) (const_int 0))
4576 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 1))))]
4577 */
d1f9b275 4578 emit_insn (gen_rtx_SET (gen_rtx_REG (CCmode, CC_REGNUM),
ba6a3b2f 4579 gen_rtx_COMPARE (CCmode, operands[0], const0_rtx)));
4580 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
4581 (gen_rtx_LT (SImode,
4582 gen_rtx_REG (CCmode, CC_REGNUM),
4583 const0_rtx)),
d1f9b275 4584 (gen_rtx_SET (operands[0],
ba6a3b2f 4585 (gen_rtx_MINUS (SImode,
4586 const0_rtx,
4587 operands[1]))))));
4588 DONE;
4589 }
4590 else
4591 {
4592 /* Emit the pattern:
4593 alt1: eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31
4594 [(set (match_dup 0)
4595 (xor:SI (match_dup 1)
4596 (ashiftrt:SI (match_dup 1) (const_int 31))))
4597 (set (match_dup 0)
4598 (minus:SI (match_dup 0)
4599 (ashiftrt:SI (match_dup 1) (const_int 31))))]
4600 */
d1f9b275 4601 emit_insn (gen_rtx_SET (operands[0],
ba6a3b2f 4602 gen_rtx_XOR (SImode,
4603 gen_rtx_ASHIFTRT (SImode,
4604 operands[1],
4605 GEN_INT (31)),
4606 operands[1])));
d1f9b275 4607 emit_insn (gen_rtx_SET (operands[0],
ba6a3b2f 4608 gen_rtx_MINUS (SImode,
4609 operands[0],
4610 gen_rtx_ASHIFTRT (SImode,
4611 operands[1],
4612 GEN_INT (31)))));
4613 DONE;
4614 }
4615 }
cffb2a26 4616 [(set_attr "conds" "clob,*")
331beb1a 4617 (set_attr "shift" "1")
2ad08b65 4618 (set_attr "predicable" "no, yes")
1b7da4ac 4619 (set_attr "length" "8")
4620 (set_attr "type" "multiple")]
cffb2a26 4621)
9c08d1fa 4622
ba6a3b2f 4623(define_insn_and_split "*arm_neg_abssi2"
9c08d1fa 4624 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
4625 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
bd5b4116 4626 (clobber (reg:CC CC_REGNUM))]
cffb2a26 4627 "TARGET_ARM"
ba6a3b2f 4628 "#"
4629 "&& reload_completed"
4630 [(const_int 0)]
4631 {
4632 /* if (which_alternative == 0) */
4633 if (REGNO (operands[0]) == REGNO (operands[1]))
4634 {
4635 /* Emit the pattern:
4636 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
4637 */
d1f9b275 4638 emit_insn (gen_rtx_SET (gen_rtx_REG (CCmode, CC_REGNUM),
ba6a3b2f 4639 gen_rtx_COMPARE (CCmode, operands[0], const0_rtx)));
4640 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
4641 gen_rtx_GT (SImode,
4642 gen_rtx_REG (CCmode, CC_REGNUM),
4643 const0_rtx),
d1f9b275 4644 gen_rtx_SET (operands[0],
ba6a3b2f 4645 (gen_rtx_MINUS (SImode,
4646 const0_rtx,
4647 operands[1])))));
4648 }
4649 else
4650 {
4651 /* Emit the pattern:
4652 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31
4653 */
d1f9b275 4654 emit_insn (gen_rtx_SET (operands[0],
ba6a3b2f 4655 gen_rtx_XOR (SImode,
4656 gen_rtx_ASHIFTRT (SImode,
4657 operands[1],
4658 GEN_INT (31)),
4659 operands[1])));
d1f9b275 4660 emit_insn (gen_rtx_SET (operands[0],
ba6a3b2f 4661 gen_rtx_MINUS (SImode,
4662 gen_rtx_ASHIFTRT (SImode,
4663 operands[1],
4664 GEN_INT (31)),
4665 operands[0])));
4666 }
4667 DONE;
4668 }
cffb2a26 4669 [(set_attr "conds" "clob,*")
331beb1a 4670 (set_attr "shift" "1")
2ad08b65 4671 (set_attr "predicable" "no, yes")
1b7da4ac 4672 (set_attr "length" "8")
4673 (set_attr "type" "multiple")]
cffb2a26 4674)
b11cae9e 4675
604f3a0a 4676(define_expand "abssf2"
4677 [(set (match_operand:SF 0 "s_register_operand" "")
4678 (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
25f905c2 4679 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 4680 "")
4681
604f3a0a 4682(define_expand "absdf2"
4683 [(set (match_operand:DF 0 "s_register_operand" "")
4684 (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 4685 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 4686 "")
4687
7db9af5d 4688(define_expand "sqrtsf2"
4689 [(set (match_operand:SF 0 "s_register_operand" "")
4690 (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
994606f8 4691 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
7db9af5d 4692 "")
9c08d1fa 4693
7db9af5d 4694(define_expand "sqrtdf2"
4695 [(set (match_operand:DF 0 "s_register_operand" "")
4696 (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
994606f8 4697 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
7db9af5d 4698 "")
9c08d1fa 4699
a0f94409 4700(define_insn_and_split "one_cmpldi2"
10efb95f 4701 [(set (match_operand:DI 0 "s_register_operand" "=w,&r,&r,?w")
4702 (not:DI (match_operand:DI 1 "s_register_operand" " w, 0, r, w")))]
25f905c2 4703 "TARGET_32BIT"
10efb95f 4704 "@
4705 vmvn\t%P0, %P1
4706 #
4707 #
4708 vmvn\t%P0, %P1"
4709 "TARGET_32BIT && reload_completed
4710 && arm_general_register_operand (operands[0], DImode)"
a0f94409 4711 [(set (match_dup 0) (not:SI (match_dup 1)))
4712 (set (match_dup 2) (not:SI (match_dup 3)))]
4713 "
4714 {
4715 operands[2] = gen_highpart (SImode, operands[0]);
4716 operands[0] = gen_lowpart (SImode, operands[0]);
4717 operands[3] = gen_highpart (SImode, operands[1]);
4718 operands[1] = gen_lowpart (SImode, operands[1]);
4719 }"
10efb95f 4720 [(set_attr "length" "*,8,8,*")
4721 (set_attr "predicable" "no,yes,yes,no")
32093010 4722 (set_attr "type" "neon_move,multiple,multiple,neon_move")
b6779ddc 4723 (set_attr "arch" "neon_for_64bits,*,*,avoid_neon_for_64bits")]
cffb2a26 4724)
b11cae9e 4725
cffb2a26 4726(define_expand "one_cmplsi2"
4727 [(set (match_operand:SI 0 "s_register_operand" "")
4728 (not:SI (match_operand:SI 1 "s_register_operand" "")))]
4729 "TARGET_EITHER"
b11cae9e 4730 ""
cffb2a26 4731)
4732
4733(define_insn "*arm_one_cmplsi2"
d952d547 4734 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4735 (not:SI (match_operand:SI 1 "s_register_operand" "l,r")))]
25f905c2 4736 "TARGET_32BIT"
cffb2a26 4737 "mvn%?\\t%0, %1"
d2a518d1 4738 [(set_attr "predicable" "yes")
d952d547 4739 (set_attr "predicable_short_it" "yes,no")
4740 (set_attr "arch" "t2,*")
4741 (set_attr "length" "4")
1aed5204 4742 (set_attr "type" "mvn_reg")]
cffb2a26 4743)
4744
f7fbdd4a 4745(define_insn "*notsi_compare0"
bd5b4116 4746 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 4747 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
4748 (const_int 0)))
4749 (set (match_operand:SI 0 "s_register_operand" "=r")
4750 (not:SI (match_dup 1)))]
25f905c2 4751 "TARGET_32BIT"
3ef90e77 4752 "mvns%?\\t%0, %1"
d2a518d1 4753 [(set_attr "conds" "set")
1aed5204 4754 (set_attr "type" "mvn_reg")]
cffb2a26 4755)
9c08d1fa 4756
f7fbdd4a 4757(define_insn "*notsi_compare0_scratch"
bd5b4116 4758 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 4759 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
4760 (const_int 0)))
4761 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 4762 "TARGET_32BIT"
3ef90e77 4763 "mvns%?\\t%0, %1"
d2a518d1 4764 [(set_attr "conds" "set")
1aed5204 4765 (set_attr "type" "mvn_reg")]
cffb2a26 4766)
b11cae9e 4767\f
4768;; Fixed <--> Floating conversion insns
4769
9b8516be 4770(define_expand "floatsihf2"
4771 [(set (match_operand:HF 0 "general_operand" "")
4772 (float:HF (match_operand:SI 1 "general_operand" "")))]
4773 "TARGET_EITHER"
4774 "
4775 {
4776 rtx op1 = gen_reg_rtx (SFmode);
4777 expand_float (op1, operands[1], 0);
4778 op1 = convert_to_mode (HFmode, op1, 0);
4779 emit_move_insn (operands[0], op1);
4780 DONE;
4781 }"
4782)
4783
4784(define_expand "floatdihf2"
4785 [(set (match_operand:HF 0 "general_operand" "")
4786 (float:HF (match_operand:DI 1 "general_operand" "")))]
4787 "TARGET_EITHER"
4788 "
4789 {
4790 rtx op1 = gen_reg_rtx (SFmode);
4791 expand_float (op1, operands[1], 0);
4792 op1 = convert_to_mode (HFmode, op1, 0);
4793 emit_move_insn (operands[0], op1);
4794 DONE;
4795 }"
4796)
4797
604f3a0a 4798(define_expand "floatsisf2"
4799 [(set (match_operand:SF 0 "s_register_operand" "")
4800 (float:SF (match_operand:SI 1 "s_register_operand" "")))]
25f905c2 4801 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 4802 "
604f3a0a 4803")
4804
604f3a0a 4805(define_expand "floatsidf2"
4806 [(set (match_operand:DF 0 "s_register_operand" "")
4807 (float:DF (match_operand:SI 1 "s_register_operand" "")))]
a50d7267 4808 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 4809 "
604f3a0a 4810")
4811
9b8516be 4812(define_expand "fix_trunchfsi2"
4813 [(set (match_operand:SI 0 "general_operand" "")
4814 (fix:SI (fix:HF (match_operand:HF 1 "general_operand" ""))))]
4815 "TARGET_EITHER"
4816 "
4817 {
4818 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
4819 expand_fix (operands[0], op1, 0);
4820 DONE;
4821 }"
4822)
4823
4824(define_expand "fix_trunchfdi2"
4825 [(set (match_operand:DI 0 "general_operand" "")
4826 (fix:DI (fix:HF (match_operand:HF 1 "general_operand" ""))))]
4827 "TARGET_EITHER"
4828 "
4829 {
4830 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
4831 expand_fix (operands[0], op1, 0);
4832 DONE;
4833 }"
4834)
4835
604f3a0a 4836(define_expand "fix_truncsfsi2"
4837 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 4838 (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" ""))))]
25f905c2 4839 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 4840 "
604f3a0a 4841")
4842
604f3a0a 4843(define_expand "fix_truncdfsi2"
4844 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 4845 (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" ""))))]
a50d7267 4846 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 4847 "
604f3a0a 4848")
4849
f544c6d2 4850;; Truncation insns
b11cae9e 4851
604f3a0a 4852(define_expand "truncdfsf2"
4853 [(set (match_operand:SF 0 "s_register_operand" "")
4854 (float_truncate:SF
4855 (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 4856 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 4857 ""
4858)
9b8516be 4859
4860/* DFmode -> HFmode conversions have to go through SFmode. */
4861(define_expand "truncdfhf2"
4862 [(set (match_operand:HF 0 "general_operand" "")
4863 (float_truncate:HF
4864 (match_operand:DF 1 "general_operand" "")))]
4865 "TARGET_EITHER"
4866 "
4867 {
4868 rtx op1;
4869 op1 = convert_to_mode (SFmode, operands[1], 0);
4870 op1 = convert_to_mode (HFmode, op1, 0);
4871 emit_move_insn (operands[0], op1);
4872 DONE;
4873 }"
4874)
b11cae9e 4875\f
9c08d1fa 4876;; Zero and sign extension instructions.
b11cae9e 4877
848e66ac 4878(define_insn "zero_extend<mode>di2"
6aa689e8 4879 [(set (match_operand:DI 0 "s_register_operand" "=w,r,?r,w")
6d97728e 4880 (zero_extend:DI (match_operand:QHSI 1 "<qhs_zextenddi_op>"
4881 "<qhs_zextenddi_cstr>")))]
848e66ac 4882 "TARGET_32BIT <qhs_zextenddi_cond>"
4883 "#"
6aa689e8 4884 [(set_attr "length" "8,4,8,8")
b6779ddc 4885 (set_attr "arch" "neon_for_64bits,*,*,avoid_neon_for_64bits")
848e66ac 4886 (set_attr "ce_count" "2")
efbb5e19 4887 (set_attr "predicable" "yes")
4888 (set_attr "type" "multiple,mov_reg,multiple,multiple")]
25f905c2 4889)
4890
848e66ac 4891(define_insn "extend<mode>di2"
6aa689e8 4892 [(set (match_operand:DI 0 "s_register_operand" "=w,r,?r,?r,w")
63d204a8 4893 (sign_extend:DI (match_operand:QHSI 1 "<qhs_extenddi_op>"
4894 "<qhs_extenddi_cstr>")))]
848e66ac 4895 "TARGET_32BIT <qhs_sextenddi_cond>"
4896 "#"
6aa689e8 4897 [(set_attr "length" "8,4,8,8,8")
848e66ac 4898 (set_attr "ce_count" "2")
4899 (set_attr "shift" "1")
8012d2c2 4900 (set_attr "predicable" "yes")
1b7da4ac 4901 (set_attr "arch" "neon_for_64bits,*,a,t,avoid_neon_for_64bits")
4902 (set_attr "type" "multiple,mov_reg,multiple,multiple,multiple")]
0d66636f 4903)
9c08d1fa 4904
848e66ac 4905;; Splits for all extensions to DImode
4906(define_split
4907 [(set (match_operand:DI 0 "s_register_operand" "")
4908 (zero_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
6aa689e8 4909 "TARGET_32BIT && reload_completed && !IS_VFP_REGNUM (REGNO (operands[0]))"
848e66ac 4910 [(set (match_dup 0) (match_dup 1))]
4911{
848e66ac 4912 rtx lo_part = gen_lowpart (SImode, operands[0]);
3754d046 4913 machine_mode src_mode = GET_MODE (operands[1]);
848e66ac 4914
4915 if (REG_P (operands[0])
4916 && !reg_overlap_mentioned_p (operands[0], operands[1]))
4917 emit_clobber (operands[0]);
4918 if (!REG_P (lo_part) || src_mode != SImode
4919 || !rtx_equal_p (lo_part, operands[1]))
4920 {
4921 if (src_mode == SImode)
4922 emit_move_insn (lo_part, operands[1]);
4923 else
d1f9b275 4924 emit_insn (gen_rtx_SET (lo_part,
848e66ac 4925 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
4926 operands[1] = lo_part;
4927 }
4928 operands[0] = gen_highpart (SImode, operands[0]);
4929 operands[1] = const0_rtx;
4930})
9c08d1fa 4931
848e66ac 4932(define_split
25f905c2 4933 [(set (match_operand:DI 0 "s_register_operand" "")
848e66ac 4934 (sign_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
6aa689e8 4935 "TARGET_32BIT && reload_completed && !IS_VFP_REGNUM (REGNO (operands[0]))"
848e66ac 4936 [(set (match_dup 0) (ashiftrt:SI (match_dup 1) (const_int 31)))]
4937{
4938 rtx lo_part = gen_lowpart (SImode, operands[0]);
3754d046 4939 machine_mode src_mode = GET_MODE (operands[1]);
25f905c2 4940
848e66ac 4941 if (REG_P (operands[0])
4942 && !reg_overlap_mentioned_p (operands[0], operands[1]))
4943 emit_clobber (operands[0]);
4944
4945 if (!REG_P (lo_part) || src_mode != SImode
4946 || !rtx_equal_p (lo_part, operands[1]))
4947 {
4948 if (src_mode == SImode)
4949 emit_move_insn (lo_part, operands[1]);
4950 else
d1f9b275 4951 emit_insn (gen_rtx_SET (lo_part,
848e66ac 4952 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
4953 operands[1] = lo_part;
4954 }
4955 operands[0] = gen_highpart (SImode, operands[0]);
4956})
9c08d1fa 4957
4958(define_expand "zero_extendhisi2"
ef51b8e1 4959 [(set (match_operand:SI 0 "s_register_operand" "")
4960 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
cffb2a26 4961 "TARGET_EITHER"
ef51b8e1 4962{
4963 if (TARGET_ARM && !arm_arch4 && MEM_P (operands[1]))
f7fbdd4a 4964 {
ef51b8e1 4965 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
4966 DONE;
25f7a26e 4967 }
ef51b8e1 4968 if (!arm_arch6 && !MEM_P (operands[1]))
4969 {
4970 rtx t = gen_lowpart (SImode, operands[1]);
4971 rtx tmp = gen_reg_rtx (SImode);
4972 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
4973 emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (16)));
4974 DONE;
4975 }
4976})
9c08d1fa 4977
ef51b8e1 4978(define_split
b146458f 4979 [(set (match_operand:SI 0 "s_register_operand" "")
4980 (zero_extend:SI (match_operand:HI 1 "s_register_operand" "")))]
ef51b8e1 4981 "!TARGET_THUMB2 && !arm_arch6"
4982 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4983 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 16)))]
4984{
4985 operands[2] = gen_lowpart (SImode, operands[1]);
4986})
4987
cffb2a26 4988(define_insn "*arm_zero_extendhisi2"
ef51b8e1 4989 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4990 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 4991 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 4992 "@
4993 #
3ef90e77 4994 ldrh%?\\t%0, %1"
d82e788e 4995 [(set_attr "type" "alu_shift_reg,load_byte")
848e66ac 4996 (set_attr "predicable" "yes")]
cffb2a26 4997)
f7fbdd4a 4998
a2cd141b 4999(define_insn "*arm_zero_extendhisi2_v6"
5000 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
e3f4ccee 5001 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,Uh")))]
a2cd141b 5002 "TARGET_ARM && arm_arch6"
5003 "@
5004 uxth%?\\t%0, %1
3ef90e77 5005 ldrh%?\\t%0, %1"
65f68e55 5006 [(set_attr "predicable" "yes")
6b6abc9c 5007 (set_attr "type" "extend,load_byte")]
a2cd141b 5008)
5009
5010(define_insn "*arm_zero_extendhisi2addsi"
5011 [(set (match_operand:SI 0 "s_register_operand" "=r")
5012 (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
5013 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 5014 "TARGET_INT_SIMD"
a2cd141b 5015 "uxtah%?\\t%0, %2, %1"
d82e788e 5016 [(set_attr "type" "alu_shift_reg")
d952d547 5017 (set_attr "predicable" "yes")
5018 (set_attr "predicable_short_it" "no")]
a2cd141b 5019)
5020
87b22bf7 5021(define_expand "zero_extendqisi2"
cffb2a26 5022 [(set (match_operand:SI 0 "s_register_operand" "")
5023 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
5024 "TARGET_EITHER"
ef51b8e1 5025{
0438d37f 5026 if (TARGET_ARM && !arm_arch6 && !MEM_P (operands[1]))
87b22bf7 5027 {
ef51b8e1 5028 emit_insn (gen_andsi3 (operands[0],
5029 gen_lowpart (SImode, operands[1]),
5030 GEN_INT (255)));
5031 DONE;
5032 }
5033 if (!arm_arch6 && !MEM_P (operands[1]))
5034 {
5035 rtx t = gen_lowpart (SImode, operands[1]);
5036 rtx tmp = gen_reg_rtx (SImode);
5037 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
5038 emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (24)));
5039 DONE;
5040 }
5041})
cffb2a26 5042
ef51b8e1 5043(define_split
b146458f 5044 [(set (match_operand:SI 0 "s_register_operand" "")
5045 (zero_extend:SI (match_operand:QI 1 "s_register_operand" "")))]
ef51b8e1 5046 "!arm_arch6"
5047 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
5048 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 24)))]
5049{
5050 operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
5051 if (TARGET_ARM)
5052 {
5053 emit_insn (gen_andsi3 (operands[0], operands[2], GEN_INT (255)));
87b22bf7 5054 DONE;
5055 }
ef51b8e1 5056})
9c08d1fa 5057
cffb2a26 5058(define_insn "*arm_zero_extendqisi2"
ef51b8e1 5059 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5060 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 5061 "TARGET_ARM && !arm_arch6"
ef51b8e1 5062 "@
5063 #
3ef90e77 5064 ldrb%?\\t%0, %1\\t%@ zero_extendqisi2"
ef51b8e1 5065 [(set_attr "length" "8,4")
d82e788e 5066 (set_attr "type" "alu_shift_reg,load_byte")
848e66ac 5067 (set_attr "predicable" "yes")]
cffb2a26 5068)
87b22bf7 5069
a2cd141b 5070(define_insn "*arm_zero_extendqisi2_v6"
5071 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
e3f4ccee 5072 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,Uh")))]
a2cd141b 5073 "TARGET_ARM && arm_arch6"
5074 "@
3ef90e77 5075 uxtb%?\\t%0, %1
5076 ldrb%?\\t%0, %1\\t%@ zero_extendqisi2"
6b6abc9c 5077 [(set_attr "type" "extend,load_byte")
848e66ac 5078 (set_attr "predicable" "yes")]
a2cd141b 5079)
5080
5081(define_insn "*arm_zero_extendqisi2addsi"
5082 [(set (match_operand:SI 0 "s_register_operand" "=r")
5083 (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
5084 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 5085 "TARGET_INT_SIMD"
a2cd141b 5086 "uxtab%?\\t%0, %2, %1"
5087 [(set_attr "predicable" "yes")
d952d547 5088 (set_attr "predicable_short_it" "no")
d82e788e 5089 (set_attr "type" "alu_shift_reg")]
a2cd141b 5090)
5091
87b22bf7 5092(define_split
5093 [(set (match_operand:SI 0 "s_register_operand" "")
5094 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
5095 (clobber (match_operand:SI 2 "s_register_operand" ""))]
0438d37f 5096 "TARGET_32BIT && (!MEM_P (operands[1])) && ! BYTES_BIG_ENDIAN"
87b22bf7 5097 [(set (match_dup 2) (match_dup 1))
5098 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
cffb2a26 5099 ""
5100)
9c08d1fa 5101
8a4d25d6 5102(define_split
5103 [(set (match_operand:SI 0 "s_register_operand" "")
5104 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 3)))
5105 (clobber (match_operand:SI 2 "s_register_operand" ""))]
0438d37f 5106 "TARGET_32BIT && (!MEM_P (operands[1])) && BYTES_BIG_ENDIAN"
8a4d25d6 5107 [(set (match_dup 2) (match_dup 1))
5108 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
5109 ""
5110)
5111
1c274529 5112
5113(define_split
5114 [(set (match_operand:SI 0 "s_register_operand" "")
9b23f0a7 5115 (IOR_XOR:SI (and:SI (ashift:SI
1c274529 5116 (match_operand:SI 1 "s_register_operand" "")
5117 (match_operand:SI 2 "const_int_operand" ""))
5118 (match_operand:SI 3 "const_int_operand" ""))
5119 (zero_extend:SI
5120 (match_operator 5 "subreg_lowpart_operator"
5121 [(match_operand:SI 4 "s_register_operand" "")]))))]
5122 "TARGET_32BIT
63787642 5123 && ((unsigned HOST_WIDE_INT) INTVAL (operands[3])
1c274529 5124 == (GET_MODE_MASK (GET_MODE (operands[5]))
5125 & (GET_MODE_MASK (GET_MODE (operands[5]))
5126 << (INTVAL (operands[2])))))"
9b23f0a7 5127 [(set (match_dup 0) (IOR_XOR:SI (ashift:SI (match_dup 1) (match_dup 2))
1c274529 5128 (match_dup 4)))
5129 (set (match_dup 0) (zero_extend:SI (match_dup 5)))]
5130 "operands[5] = gen_lowpart (GET_MODE (operands[5]), operands[0]);"
5131)
5132
f7fbdd4a 5133(define_insn "*compareqi_eq0"
bd5b4116 5134 [(set (reg:CC_Z CC_REGNUM)
206ee9a2 5135 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
87b22bf7 5136 (const_int 0)))]
25f905c2 5137 "TARGET_32BIT"
596e5e8f 5138 "tst%?\\t%0, #255"
5139 [(set_attr "conds" "set")
d952d547 5140 (set_attr "predicable" "yes")
1b7da4ac 5141 (set_attr "predicable_short_it" "no")
5142 (set_attr "type" "logic_imm")]
cffb2a26 5143)
b11cae9e 5144
b11cae9e 5145(define_expand "extendhisi2"
ef51b8e1 5146 [(set (match_operand:SI 0 "s_register_operand" "")
5147 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
cffb2a26 5148 "TARGET_EITHER"
ef51b8e1 5149{
5150 if (TARGET_THUMB1)
5151 {
5152 emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1]));
5153 DONE;
5154 }
5155 if (MEM_P (operands[1]) && TARGET_ARM && !arm_arch4)
5156 {
5157 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
5158 DONE;
5159 }
ed29c566 5160
ef51b8e1 5161 if (!arm_arch6 && !MEM_P (operands[1]))
5162 {
5163 rtx t = gen_lowpart (SImode, operands[1]);
5164 rtx tmp = gen_reg_rtx (SImode);
5165 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
5166 emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (16)));
5167 DONE;
5168 }
5169})
cffb2a26 5170
ef51b8e1 5171(define_split
5172 [(parallel
5173 [(set (match_operand:SI 0 "register_operand" "")
5174 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))
5175 (clobber (match_scratch:SI 2 ""))])]
5176 "!arm_arch6"
5177 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
5178 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
5179{
5180 operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
5181})
25f7a26e 5182
25f905c2 5183;; This pattern will only be used when ldsh is not available
25f7a26e 5184(define_expand "extendhisi2_mem"
eab14235 5185 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 5186 (set (match_dup 3)
eab14235 5187 (zero_extend:SI (match_dup 7)))
25f7a26e 5188 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
5189 (set (match_operand:SI 0 "" "")
5190 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
cffb2a26 5191 "TARGET_ARM"
25f7a26e 5192 "
215b30b3 5193 {
5194 rtx mem1, mem2;
5195 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
5196
788fcce0 5197 mem1 = change_address (operands[1], QImode, addr);
29c05e22 5198 mem2 = change_address (operands[1], QImode,
5199 plus_constant (Pmode, addr, 1));
215b30b3 5200 operands[0] = gen_lowpart (SImode, operands[0]);
5201 operands[1] = mem1;
5202 operands[2] = gen_reg_rtx (SImode);
5203 operands[3] = gen_reg_rtx (SImode);
5204 operands[6] = gen_reg_rtx (SImode);
5205 operands[7] = mem2;
25f7a26e 5206
215b30b3 5207 if (BYTES_BIG_ENDIAN)
5208 {
5209 operands[4] = operands[2];
5210 operands[5] = operands[3];
5211 }
5212 else
5213 {
5214 operands[4] = operands[3];
5215 operands[5] = operands[2];
5216 }
5217 }"
5218)
b11cae9e 5219
ef51b8e1 5220(define_split
5221 [(set (match_operand:SI 0 "register_operand" "")
5222 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
5223 "!arm_arch6"
5224 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
5225 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
5226{
5227 operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
5228})
5229
a2cd141b 5230(define_insn "*arm_extendhisi2"
ef51b8e1 5231 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
e3f4ccee 5232 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,Uh")))]
a2cd141b 5233 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 5234 "@
5235 #
3ef90e77 5236 ldrsh%?\\t%0, %1"
ef51b8e1 5237 [(set_attr "length" "8,4")
d82e788e 5238 (set_attr "type" "alu_shift_reg,load_byte")
e3f4ccee 5239 (set_attr "predicable" "yes")]
cffb2a26 5240)
f7fbdd4a 5241
25f905c2 5242;; ??? Check Thumb-2 pool range
a2cd141b 5243(define_insn "*arm_extendhisi2_v6"
5244 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
e3f4ccee 5245 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,Uh")))]
25f905c2 5246 "TARGET_32BIT && arm_arch6"
a2cd141b 5247 "@
5248 sxth%?\\t%0, %1
3ef90e77 5249 ldrsh%?\\t%0, %1"
6b6abc9c 5250 [(set_attr "type" "extend,load_byte")
a2cd141b 5251 (set_attr "predicable" "yes")
e3f4ccee 5252 (set_attr "predicable_short_it" "no")]
a2cd141b 5253)
5254
5255(define_insn "*arm_extendhisi2addsi"
5256 [(set (match_operand:SI 0 "s_register_operand" "=r")
5257 (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
5258 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 5259 "TARGET_INT_SIMD"
a2cd141b 5260 "sxtah%?\\t%0, %2, %1"
1b7da4ac 5261 [(set_attr "type" "alu_shift_reg")]
a2cd141b 5262)
5263
c8f69309 5264(define_expand "extendqihi2"
5265 [(set (match_dup 2)
bed7d9a5 5266 (ashift:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")
c8f69309 5267 (const_int 24)))
9c08d1fa 5268 (set (match_operand:HI 0 "s_register_operand" "")
c8f69309 5269 (ashiftrt:SI (match_dup 2)
5270 (const_int 24)))]
cffb2a26 5271 "TARGET_ARM"
c8f69309 5272 "
215b30b3 5273 {
0438d37f 5274 if (arm_arch4 && MEM_P (operands[1]))
215b30b3 5275 {
d1f9b275 5276 emit_insn (gen_rtx_SET (operands[0],
215b30b3 5277 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
5278 DONE;
5279 }
5280 if (!s_register_operand (operands[1], QImode))
5281 operands[1] = copy_to_mode_reg (QImode, operands[1]);
5282 operands[0] = gen_lowpart (SImode, operands[0]);
5283 operands[1] = gen_lowpart (SImode, operands[1]);
5284 operands[2] = gen_reg_rtx (SImode);
5285 }"
5286)
f7fbdd4a 5287
25f905c2 5288(define_insn "*arm_extendqihi_insn"
b4e8a300 5289 [(set (match_operand:HI 0 "s_register_operand" "=r")
bed7d9a5 5290 (sign_extend:HI (match_operand:QI 1 "arm_extendqisi_mem_op" "Uq")))]
cffb2a26 5291 "TARGET_ARM && arm_arch4"
3ef90e77 5292 "ldrsb%?\\t%0, %1"
a2cd141b 5293 [(set_attr "type" "load_byte")
e3f4ccee 5294 (set_attr "predicable" "yes")]
cffb2a26 5295)
3fc2009e 5296
b11cae9e 5297(define_expand "extendqisi2"
ef51b8e1 5298 [(set (match_operand:SI 0 "s_register_operand" "")
5299 (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")))]
cffb2a26 5300 "TARGET_EITHER"
ef51b8e1 5301{
5302 if (!arm_arch4 && MEM_P (operands[1]))
5303 operands[1] = copy_to_mode_reg (QImode, operands[1]);
a2cd141b 5304
ef51b8e1 5305 if (!arm_arch6 && !MEM_P (operands[1]))
5306 {
5307 rtx t = gen_lowpart (SImode, operands[1]);
5308 rtx tmp = gen_reg_rtx (SImode);
5309 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
5310 emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (24)));
5311 DONE;
5312 }
5313})
a2cd141b 5314
ef51b8e1 5315(define_split
5316 [(set (match_operand:SI 0 "register_operand" "")
5317 (sign_extend:SI (match_operand:QI 1 "register_operand" "")))]
5318 "!arm_arch6"
5319 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
5320 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))]
5321{
5322 operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
5323})
f7fbdd4a 5324
a2cd141b 5325(define_insn "*arm_extendqisi"
ef51b8e1 5326 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5327 (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
a2cd141b 5328 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 5329 "@
5330 #
3ef90e77 5331 ldrsb%?\\t%0, %1"
ef51b8e1 5332 [(set_attr "length" "8,4")
d82e788e 5333 (set_attr "type" "alu_shift_reg,load_byte")
e3f4ccee 5334 (set_attr "predicable" "yes")]
cffb2a26 5335)
3fc2009e 5336
a2cd141b 5337(define_insn "*arm_extendqisi_v6"
5338 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
bed7d9a5 5339 (sign_extend:SI
5340 (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
a2cd141b 5341 "TARGET_ARM && arm_arch6"
b4e8a300 5342 "@
5343 sxtb%?\\t%0, %1
3ef90e77 5344 ldrsb%?\\t%0, %1"
6b6abc9c 5345 [(set_attr "type" "extend,load_byte")
e3f4ccee 5346 (set_attr "predicable" "yes")]
a2cd141b 5347)
5348
5349(define_insn "*arm_extendqisi2addsi"
5350 [(set (match_operand:SI 0 "s_register_operand" "=r")
5351 (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
5352 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 5353 "TARGET_INT_SIMD"
a2cd141b 5354 "sxtab%?\\t%0, %2, %1"
d82e788e 5355 [(set_attr "type" "alu_shift_reg")
d952d547 5356 (set_attr "predicable" "yes")
5357 (set_attr "predicable_short_it" "no")]
a2cd141b 5358)
5359
caedf871 5360(define_expand "extendsfdf2"
5361 [(set (match_operand:DF 0 "s_register_operand" "")
5362 (float_extend:DF (match_operand:SF 1 "s_register_operand" "")))]
a50d7267 5363 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
caedf871 5364 ""
5365)
9b8516be 5366
5367/* HFmode -> DFmode conversions have to go through SFmode. */
5368(define_expand "extendhfdf2"
5369 [(set (match_operand:DF 0 "general_operand" "")
5370 (float_extend:DF (match_operand:HF 1 "general_operand" "")))]
5371 "TARGET_EITHER"
5372 "
5373 {
5374 rtx op1;
5375 op1 = convert_to_mode (SFmode, operands[1], 0);
5376 op1 = convert_to_mode (DFmode, op1, 0);
5377 emit_insn (gen_movdf (operands[0], op1));
5378 DONE;
5379 }"
5380)
b11cae9e 5381\f
5382;; Move insns (including loads and stores)
5383
5384;; XXX Just some ideas about movti.
9c08d1fa 5385;; I don't think these are a good idea on the arm, there just aren't enough
5386;; registers
b11cae9e 5387;;(define_expand "loadti"
9c08d1fa 5388;; [(set (match_operand:TI 0 "s_register_operand" "")
b11cae9e 5389;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
5390;; "" "")
5391
5392;;(define_expand "storeti"
5393;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
9c08d1fa 5394;; (match_operand:TI 1 "s_register_operand" ""))]
b11cae9e 5395;; "" "")
5396
5397;;(define_expand "movti"
5398;; [(set (match_operand:TI 0 "general_operand" "")
5399;; (match_operand:TI 1 "general_operand" ""))]
5400;; ""
5401;; "
5402;;{
5403;; rtx insn;
5404;;
0438d37f 5405;; if (MEM_P (operands[0]) && MEM_P (operands[1]))
b11cae9e 5406;; operands[1] = copy_to_reg (operands[1]);
0438d37f 5407;; if (MEM_P (operands[0]))
b11cae9e 5408;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
0438d37f 5409;; else if (MEM_P (operands[1]))
b11cae9e 5410;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
5411;; else
5412;; FAIL;
5413;;
5414;; emit_insn (insn);
5415;; DONE;
5416;;}")
5417
a2f10574 5418;; Recognize garbage generated above.
b11cae9e 5419
5420;;(define_insn ""
5421;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
5422;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
5423;; ""
5424;; "*
5425;; {
5426;; register mem = (which_alternative < 3);
0d66636f 5427;; register const char *template;
b11cae9e 5428;;
5429;; operands[mem] = XEXP (operands[mem], 0);
5430;; switch (which_alternative)
5431;; {
5432;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
5433;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
5434;; case 2: template = \"ldmia\\t%1, %M0\"; break;
5435;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
5436;; case 4: template = \"stmia\\t%0!, %M1\"; break;
5437;; case 5: template = \"stmia\\t%0, %M1\"; break;
5438;; }
e2348bcb 5439;; output_asm_insn (template, operands);
5440;; return \"\";
b11cae9e 5441;; }")
5442
cffb2a26 5443(define_expand "movdi"
5444 [(set (match_operand:DI 0 "general_operand" "")
5445 (match_operand:DI 1 "general_operand" ""))]
5446 "TARGET_EITHER"
5447 "
e1ba4a27 5448 if (can_create_pseudo_p ())
cffb2a26 5449 {
0438d37f 5450 if (!REG_P (operands[0]))
b2778788 5451 operands[1] = force_reg (DImode, operands[1]);
cffb2a26 5452 }
6b97fdcc 5453 if (REG_P (operands[0]) && REGNO (operands[0]) <= LAST_ARM_REGNUM
4f0e25ca 5454 && !HARD_REGNO_MODE_OK (REGNO (operands[0]), DImode))
5455 {
5456 /* Avoid LDRD's into an odd-numbered register pair in ARM state
5457 when expanding function calls. */
5458 gcc_assert (can_create_pseudo_p ());
5459 if (MEM_P (operands[1]) && MEM_VOLATILE_P (operands[1]))
5460 {
5461 /* Perform load into legal reg pair first, then move. */
5462 rtx reg = gen_reg_rtx (DImode);
5463 emit_insn (gen_movdi (reg, operands[1]));
5464 operands[1] = reg;
5465 }
5466 emit_move_insn (gen_lowpart (SImode, operands[0]),
5467 gen_lowpart (SImode, operands[1]));
5468 emit_move_insn (gen_highpart (SImode, operands[0]),
5469 gen_highpart (SImode, operands[1]));
5470 DONE;
5471 }
6b97fdcc 5472 else if (REG_P (operands[1]) && REGNO (operands[1]) <= LAST_ARM_REGNUM
4f0e25ca 5473 && !HARD_REGNO_MODE_OK (REGNO (operands[1]), DImode))
5474 {
5475 /* Avoid STRD's from an odd-numbered register pair in ARM state
5476 when expanding function prologue. */
5477 gcc_assert (can_create_pseudo_p ());
5478 rtx split_dest = (MEM_P (operands[0]) && MEM_VOLATILE_P (operands[0]))
5479 ? gen_reg_rtx (DImode)
5480 : operands[0];
5481 emit_move_insn (gen_lowpart (SImode, split_dest),
5482 gen_lowpart (SImode, operands[1]));
5483 emit_move_insn (gen_highpart (SImode, split_dest),
5484 gen_highpart (SImode, operands[1]));
5485 if (split_dest != operands[0])
5486 emit_insn (gen_movdi (operands[0], split_dest));
5487 DONE;
5488 }
cffb2a26 5489 "
5490)
b11cae9e 5491
cffb2a26 5492(define_insn "*arm_movdi"
353cf59a 5493 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, q, m")
5494 (match_operand:DI 1 "di_operand" "rDa,Db,Dc,mi,q"))]
cde1623a 5495 "TARGET_32BIT
b805622c 5496 && !(TARGET_HARD_FLOAT && TARGET_VFP)
b2778788 5497 && !TARGET_IWMMXT
5498 && ( register_operand (operands[0], DImode)
5499 || register_operand (operands[1], DImode))"
b11cae9e 5500 "*
d51f92df 5501 switch (which_alternative)
5502 {
5503 case 0:
5504 case 1:
5505 case 2:
5506 return \"#\";
5507 default:
26ff80c0 5508 return output_move_double (operands, true, NULL);
d51f92df 5509 }
cffb2a26 5510 "
359a6e9f 5511 [(set_attr "length" "8,12,16,8,8")
1b7da4ac 5512 (set_attr "type" "multiple,multiple,multiple,load2,store2")
cde1623a 5513 (set_attr "arm_pool_range" "*,*,*,1020,*")
8848d797 5514 (set_attr "arm_neg_pool_range" "*,*,*,1004,*")
42e1de19 5515 (set_attr "thumb2_pool_range" "*,*,*,4094,*")
cde1623a 5516 (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
cffb2a26 5517)
5518
d51f92df 5519(define_split
5520 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
e6dd3afa 5521 (match_operand:ANY64 1 "immediate_operand" ""))]
25f905c2 5522 "TARGET_32BIT
d51f92df 5523 && reload_completed
5524 && (arm_const_double_inline_cost (operands[1])
861033d5 5525 <= arm_max_const_double_inline_cost ())"
d51f92df 5526 [(const_int 0)]
5527 "
5528 arm_split_constant (SET, SImode, curr_insn,
5529 INTVAL (gen_lowpart (SImode, operands[1])),
5530 gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
5531 arm_split_constant (SET, SImode, curr_insn,
5532 INTVAL (gen_highpart_mode (SImode,
5533 GET_MODE (operands[0]),
5534 operands[1])),
5535 gen_highpart (SImode, operands[0]), NULL_RTX, 0);
5536 DONE;
5537 "
5538)
5539
e5ba9289 5540; If optimizing for size, or if we have load delay slots, then
5541; we want to split the constant into two separate operations.
5542; In both cases this may split a trivial part into a single data op
5543; leaving a single complex constant to load. We can also get longer
5544; offsets in a LDR which means we get better chances of sharing the pool
5545; entries. Finally, we can normally do a better job of scheduling
5546; LDR instructions than we can with LDM.
5547; This pattern will only match if the one above did not.
5548(define_split
5549 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
5550 (match_operand:ANY64 1 "const_double_operand" ""))]
5551 "TARGET_ARM && reload_completed
5552 && arm_const_double_by_parts (operands[1])"
5553 [(set (match_dup 0) (match_dup 1))
5554 (set (match_dup 2) (match_dup 3))]
5555 "
5556 operands[2] = gen_highpart (SImode, operands[0]);
5557 operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
5558 operands[1]);
5559 operands[0] = gen_lowpart (SImode, operands[0]);
5560 operands[1] = gen_lowpart (SImode, operands[1]);
5561 "
5562)
5563
d51f92df 5564(define_split
5565 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
5566 (match_operand:ANY64 1 "arm_general_register_operand" ""))]
5567 "TARGET_EITHER && reload_completed"
5568 [(set (match_dup 0) (match_dup 1))
5569 (set (match_dup 2) (match_dup 3))]
5570 "
5571 operands[2] = gen_highpart (SImode, operands[0]);
5572 operands[3] = gen_highpart (SImode, operands[1]);
5573 operands[0] = gen_lowpart (SImode, operands[0]);
5574 operands[1] = gen_lowpart (SImode, operands[1]);
5575
5576 /* Handle a partial overlap. */
5577 if (rtx_equal_p (operands[0], operands[3]))
5578 {
5579 rtx tmp0 = operands[0];
5580 rtx tmp1 = operands[1];
5581
5582 operands[0] = operands[2];
5583 operands[1] = operands[3];
5584 operands[2] = tmp0;
5585 operands[3] = tmp1;
5586 }
5587 "
5588)
5589
a8a3b539 5590;; We can't actually do base+index doubleword loads if the index and
5591;; destination overlap. Split here so that we at least have chance to
5592;; schedule.
5593(define_split
5594 [(set (match_operand:DI 0 "s_register_operand" "")
5595 (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
5596 (match_operand:SI 2 "s_register_operand" ""))))]
5597 "TARGET_LDRD
5598 && reg_overlap_mentioned_p (operands[0], operands[1])
5599 && reg_overlap_mentioned_p (operands[0], operands[2])"
5600 [(set (match_dup 4)
5601 (plus:SI (match_dup 1)
5602 (match_dup 2)))
5603 (set (match_dup 0)
5604 (mem:DI (match_dup 4)))]
5605 "
5606 operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
5607 "
5608)
5609
9c08d1fa 5610(define_expand "movsi"
5611 [(set (match_operand:SI 0 "general_operand" "")
5612 (match_operand:SI 1 "general_operand" ""))]
cffb2a26 5613 "TARGET_EITHER"
9c08d1fa 5614 "
befb0bac 5615 {
e348ff3e 5616 rtx base, offset, tmp;
5617
25f905c2 5618 if (TARGET_32BIT)
9c08d1fa 5619 {
674a8f0b 5620 /* Everything except mem = const or mem = mem can be done easily. */
0438d37f 5621 if (MEM_P (operands[0]))
cffb2a26 5622 operands[1] = force_reg (SImode, operands[1]);
a2cd141b 5623 if (arm_general_register_operand (operands[0], SImode)
0438d37f 5624 && CONST_INT_P (operands[1])
cffb2a26 5625 && !(const_ok_for_arm (INTVAL (operands[1]))
5626 || const_ok_for_arm (~INTVAL (operands[1]))))
5627 {
17202aa5 5628 if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[1]), SET))
5629 {
5630 emit_insn (gen_rtx_SET (operands[0], operands[1]));
5631 DONE;
5632 }
5633 else
5634 {
5635 arm_split_constant (SET, SImode, NULL_RTX,
5636 INTVAL (operands[1]), operands[0], NULL_RTX,
5637 optimize && can_create_pseudo_p ());
5638 DONE;
5639 }
cffb2a26 5640 }
5641 }
25f905c2 5642 else /* TARGET_THUMB1... */
cffb2a26 5643 {
e1ba4a27 5644 if (can_create_pseudo_p ())
cffb2a26 5645 {
0438d37f 5646 if (!REG_P (operands[0]))
cffb2a26 5647 operands[1] = force_reg (SImode, operands[1]);
5648 }
9c08d1fa 5649 }
f655717d 5650
e348ff3e 5651 if (ARM_OFFSETS_MUST_BE_WITHIN_SECTIONS_P)
5652 {
5653 split_const (operands[1], &base, &offset);
5654 if (GET_CODE (base) == SYMBOL_REF
5655 && !offset_within_block_p (base, INTVAL (offset)))
5656 {
b308ddcf 5657 tmp = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
e348ff3e 5658 emit_move_insn (tmp, base);
5659 emit_insn (gen_addsi3 (operands[0], tmp, offset));
5660 DONE;
5661 }
5662 }
5663
f655717d 5664 /* Recognize the case where operand[1] is a reference to thread-local
5665 data and load its address to a register. */
5666 if (arm_tls_referenced_p (operands[1]))
5667 {
5668 rtx tmp = operands[1];
5669 rtx addend = NULL;
5670
5671 if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
5672 {
5673 addend = XEXP (XEXP (tmp, 0), 1);
5674 tmp = XEXP (XEXP (tmp, 0), 0);
5675 }
5676
5677 gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
5678 gcc_assert (SYMBOL_REF_TLS_MODEL (tmp) != 0);
5679
e1ba4a27 5680 tmp = legitimize_tls_address (tmp,
5681 !can_create_pseudo_p () ? operands[0] : 0);
f655717d 5682 if (addend)
5683 {
5684 tmp = gen_rtx_PLUS (SImode, tmp, addend);
5685 tmp = force_operand (tmp, operands[0]);
5686 }
5687 operands[1] = tmp;
5688 }
5689 else if (flag_pic
5690 && (CONSTANT_P (operands[1])
5691 || symbol_mentioned_p (operands[1])
5692 || label_mentioned_p (operands[1])))
5693 operands[1] = legitimize_pic_address (operands[1], SImode,
e1ba4a27 5694 (!can_create_pseudo_p ()
5695 ? operands[0]
5696 : 0));
befb0bac 5697 }
215b30b3 5698 "
5699)
9c08d1fa 5700
d0e6a121 5701;; The ARM LO_SUM and HIGH are backwards - HIGH sets the low bits, and
5702;; LO_SUM adds in the high bits. Fortunately these are opaque operations
5703;; so this does not matter.
5704(define_insn "*arm_movt"
5705 [(set (match_operand:SI 0 "nonimmediate_operand" "=r")
5706 (lo_sum:SI (match_operand:SI 1 "nonimmediate_operand" "0")
5707 (match_operand:SI 2 "general_operand" "i")))]
ac528743 5708 "arm_arch_thumb2 && arm_valid_symbolic_address_p (operands[2])"
d0e6a121 5709 "movt%?\t%0, #:upper16:%c2"
5710 [(set_attr "predicable" "yes")
d952d547 5711 (set_attr "predicable_short_it" "no")
1b7da4ac 5712 (set_attr "length" "4")
282b4c75 5713 (set_attr "type" "alu_sreg")]
d0e6a121 5714)
5715
cffb2a26 5716(define_insn "*arm_movsi_insn"
aaa37ad6 5717 [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,rk,m")
110eae03 5718 (match_operand:SI 1 "general_operand" "rk, I,K,j,mi,rk"))]
755eb2b4 5719 "TARGET_ARM && ! TARGET_IWMMXT
a2cd141b 5720 && !(TARGET_HARD_FLOAT && TARGET_VFP)
cffb2a26 5721 && ( register_operand (operands[0], SImode)
5722 || register_operand (operands[1], SImode))"
f7fbdd4a 5723 "@
aaa37ad6 5724 mov%?\\t%0, %1
f7fbdd4a 5725 mov%?\\t%0, %1
5726 mvn%?\\t%0, #%B1
25f905c2 5727 movw%?\\t%0, %1
f7fbdd4a 5728 ldr%?\\t%0, %1
5729 str%?\\t%1, %0"
1aed5204 5730 [(set_attr "type" "mov_reg,mov_imm,mvn_imm,mov_imm,load1,store1")
0d66636f 5731 (set_attr "predicable" "yes")
aaa37ad6 5732 (set_attr "pool_range" "*,*,*,*,4096,*")
5733 (set_attr "neg_pool_range" "*,*,*,*,4084,*")]
cffb2a26 5734)
87b22bf7 5735
5736(define_split
a2cd141b 5737 [(set (match_operand:SI 0 "arm_general_register_operand" "")
87b22bf7 5738 (match_operand:SI 1 "const_int_operand" ""))]
25f905c2 5739 "TARGET_32BIT
215b30b3 5740 && (!(const_ok_for_arm (INTVAL (operands[1]))
5741 || const_ok_for_arm (~INTVAL (operands[1]))))"
87b22bf7 5742 [(clobber (const_int 0))]
5743 "
96f57e36 5744 arm_split_constant (SET, SImode, NULL_RTX,
5745 INTVAL (operands[1]), operands[0], NULL_RTX, 0);
87b22bf7 5746 DONE;
215b30b3 5747 "
5748)
9c08d1fa 5749
861033d5 5750;; A normal way to do (symbol + offset) requires three instructions at least
5751;; (depends on how big the offset is) as below:
5752;; movw r0, #:lower16:g
5753;; movw r0, #:upper16:g
5754;; adds r0, #4
5755;;
5756;; A better way would be:
5757;; movw r0, #:lower16:g+4
5758;; movw r0, #:upper16:g+4
5759;;
5760;; The limitation of this way is that the length of offset should be a 16-bit
5761;; signed value, because current assembler only supports REL type relocation for
5762;; such case. If the more powerful RELA type is supported in future, we should
5763;; update this pattern to go with better way.
5764(define_split
5765 [(set (match_operand:SI 0 "arm_general_register_operand" "")
5766 (const:SI (plus:SI (match_operand:SI 1 "general_operand" "")
5767 (match_operand:SI 2 "const_int_operand" ""))))]
5768 "TARGET_THUMB2
5769 && arm_disable_literal_pool
5770 && reload_completed
5771 && GET_CODE (operands[1]) == SYMBOL_REF"
5772 [(clobber (const_int 0))]
5773 "
5774 int offset = INTVAL (operands[2]);
5775
5776 if (offset < -0x8000 || offset > 0x7fff)
5777 {
5778 arm_emit_movpair (operands[0], operands[1]);
d1f9b275 5779 emit_insn (gen_rtx_SET (operands[0],
861033d5 5780 gen_rtx_PLUS (SImode, operands[0], operands[2])));
5781 }
5782 else
5783 {
5784 rtx op = gen_rtx_CONST (SImode,
5785 gen_rtx_PLUS (SImode, operands[1], operands[2]));
5786 arm_emit_movpair (operands[0], op);
5787 }
5788 "
5789)
5790
b8d5d078 5791;; Split symbol_refs at the later stage (after cprop), instead of generating
5792;; movt/movw pair directly at expand. Otherwise corresponding high_sum
5793;; and lo_sum would be merged back into memory load at cprop. However,
5794;; if the default is to prefer movt/movw rather than a load from the constant
5795;; pool, the performance is better.
5796(define_split
5797 [(set (match_operand:SI 0 "arm_general_register_operand" "")
5798 (match_operand:SI 1 "general_operand" ""))]
5799 "TARGET_32BIT
5800 && TARGET_USE_MOVT && GET_CODE (operands[1]) == SYMBOL_REF
5801 && !flag_pic && !target_word_relocations
5802 && !arm_tls_referenced_p (operands[1])"
5803 [(clobber (const_int 0))]
5804{
5805 arm_emit_movpair (operands[0], operands[1]);
5806 DONE;
5807})
5808
bc360af8 5809;; When generating pic, we need to load the symbol offset into a register.
5810;; So that the optimizer does not confuse this with a normal symbol load
5811;; we use an unspec. The offset will be loaded from a constant pool entry,
5812;; since that is the only type of relocation we can use.
cffb2a26 5813
bc360af8 5814;; Wrap calculation of the whole PIC address in a single pattern for the
5815;; benefit of optimizers, particularly, PRE and HOIST. Calculation of
5816;; a PIC address involves two loads from memory, so we want to CSE it
5817;; as often as possible.
5818;; This pattern will be split into one of the pic_load_addr_* patterns
5819;; and a move after GCSE optimizations.
5820;;
5821;; Note: Update arm.c: legitimize_pic_address() when changing this pattern.
5822(define_expand "calculate_pic_address"
94f8caca 5823 [(set (match_operand:SI 0 "register_operand" "")
5824 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "")
5825 (unspec:SI [(match_operand:SI 2 "" "")]
5826 UNSPEC_PIC_SYM))))]
5827 "flag_pic"
5828)
5829
5830;; Split calculate_pic_address into pic_load_addr_* and a move.
5831(define_split
5832 [(set (match_operand:SI 0 "register_operand" "")
5833 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "")
5834 (unspec:SI [(match_operand:SI 2 "" "")]
5835 UNSPEC_PIC_SYM))))]
5836 "flag_pic"
5837 [(set (match_dup 3) (unspec:SI [(match_dup 2)] UNSPEC_PIC_SYM))
5838 (set (match_dup 0) (mem:SI (plus:SI (match_dup 1) (match_dup 3))))]
5839 "operands[3] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];"
5840)
5841
350ccca5 5842;; operand1 is the memory address to go into
5843;; pic_load_addr_32bit.
5844;; operand2 is the PIC label to be emitted
5845;; from pic_add_dot_plus_eight.
5846;; We do this to allow hoisting of the entire insn.
5847(define_insn_and_split "pic_load_addr_unified"
5848 [(set (match_operand:SI 0 "s_register_operand" "=r,r,l")
5849 (unspec:SI [(match_operand:SI 1 "" "mX,mX,mX")
5850 (match_operand:SI 2 "" "")]
5851 UNSPEC_PIC_UNIFIED))]
5852 "flag_pic"
5853 "#"
5854 "&& reload_completed"
5855 [(set (match_dup 0) (unspec:SI [(match_dup 1)] UNSPEC_PIC_SYM))
5856 (set (match_dup 0) (unspec:SI [(match_dup 0) (match_dup 3)
5857 (match_dup 2)] UNSPEC_PIC_BASE))]
5858 "operands[3] = TARGET_THUMB ? GEN_INT (4) : GEN_INT (8);"
5859 [(set_attr "type" "load1,load1,load1")
42e1de19 5860 (set_attr "pool_range" "4096,4094,1022")
350ccca5 5861 (set_attr "neg_pool_range" "4084,0,0")
5862 (set_attr "arch" "a,t2,t1")
5863 (set_attr "length" "8,6,4")]
5864)
5865
67336bcf 5866;; The rather odd constraints on the following are to force reload to leave
5867;; the insn alone, and to force the minipool generation pass to then move
5868;; the GOT symbol to memory.
849170fd 5869
b3cd5f55 5870(define_insn "pic_load_addr_32bit"
849170fd 5871 [(set (match_operand:SI 0 "s_register_operand" "=r")
e1159bbe 5872 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
b3cd5f55 5873 "TARGET_32BIT && flag_pic"
67336bcf 5874 "ldr%?\\t%0, %1"
a2cd141b 5875 [(set_attr "type" "load1")
42e1de19 5876 (set (attr "pool_range")
5877 (if_then_else (eq_attr "is_thumb" "no")
5878 (const_int 4096)
5879 (const_int 4094)))
b3cd5f55 5880 (set (attr "neg_pool_range")
5881 (if_then_else (eq_attr "is_thumb" "no")
5882 (const_int 4084)
5883 (const_int 0)))]
8c4d8060 5884)
5885
25f905c2 5886(define_insn "pic_load_addr_thumb1"
8c4d8060 5887 [(set (match_operand:SI 0 "s_register_operand" "=l")
e1159bbe 5888 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
25f905c2 5889 "TARGET_THUMB1 && flag_pic"
8c4d8060 5890 "ldr\\t%0, %1"
a2cd141b 5891 [(set_attr "type" "load1")
42e1de19 5892 (set (attr "pool_range") (const_int 1018))]
cffb2a26 5893)
849170fd 5894
cffb2a26 5895(define_insn "pic_add_dot_plus_four"
15d5d060 5896 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5897 (unspec:SI [(match_operand:SI 1 "register_operand" "0")
5898 (const_int 4)
beef0fb5 5899 (match_operand 2 "" "")]
5900 UNSPEC_PIC_BASE))]
b3cd5f55 5901 "TARGET_THUMB"
cffb2a26 5902 "*
6cdcb15c 5903 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5904 INTVAL (operands[2]));
cffb2a26 5905 return \"add\\t%0, %|pc\";
5906 "
1b7da4ac 5907 [(set_attr "length" "2")
112eda6f 5908 (set_attr "type" "alu_sreg")]
cffb2a26 5909)
849170fd 5910
5911(define_insn "pic_add_dot_plus_eight"
15d5d060 5912 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5913 (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5914 (const_int 8)
beef0fb5 5915 (match_operand 2 "" "")]
5916 UNSPEC_PIC_BASE))]
f655717d 5917 "TARGET_ARM"
c4034607 5918 "*
6cdcb15c 5919 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5920 INTVAL (operands[2]));
15d5d060 5921 return \"add%?\\t%0, %|pc, %1\";
cffb2a26 5922 "
1b7da4ac 5923 [(set_attr "predicable" "yes")
112eda6f 5924 (set_attr "type" "alu_sreg")]
cffb2a26 5925)
849170fd 5926
f655717d 5927(define_insn "tls_load_dot_plus_eight"
cc071db6 5928 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5929 (mem:SI (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5930 (const_int 8)
beef0fb5 5931 (match_operand 2 "" "")]
5932 UNSPEC_PIC_BASE)))]
f655717d 5933 "TARGET_ARM"
5934 "*
6cdcb15c 5935 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5936 INTVAL (operands[2]));
f655717d 5937 return \"ldr%?\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_eight\";
5938 "
1b7da4ac 5939 [(set_attr "predicable" "yes")
5940 (set_attr "type" "load1")]
f655717d 5941)
5942
5943;; PIC references to local variables can generate pic_add_dot_plus_eight
5944;; followed by a load. These sequences can be crunched down to
5945;; tls_load_dot_plus_eight by a peephole.
5946
5947(define_peephole2
c0c1fba5 5948 [(set (match_operand:SI 0 "register_operand" "")
5949 (unspec:SI [(match_operand:SI 3 "register_operand" "")
5950 (const_int 8)
5951 (match_operand 1 "" "")]
5952 UNSPEC_PIC_BASE))
2d05dfad 5953 (set (match_operand:SI 2 "arm_general_register_operand" "")
5954 (mem:SI (match_dup 0)))]
f655717d 5955 "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
c0c1fba5 5956 [(set (match_dup 2)
5957 (mem:SI (unspec:SI [(match_dup 3)
5958 (const_int 8)
5959 (match_dup 1)]
5960 UNSPEC_PIC_BASE)))]
f655717d 5961 ""
5962)
5963
bac7fc85 5964(define_insn "pic_offset_arm"
5965 [(set (match_operand:SI 0 "register_operand" "=r")
5966 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
5967 (unspec:SI [(match_operand:SI 2 "" "X")]
5968 UNSPEC_PIC_OFFSET))))]
5969 "TARGET_VXWORKS_RTP && TARGET_ARM && flag_pic"
5970 "ldr%?\\t%0, [%1,%2]"
5971 [(set_attr "type" "load1")]
5972)
5973
95373f08 5974(define_expand "builtin_setjmp_receiver"
5975 [(label_ref (match_operand 0 "" ""))]
5976 "flag_pic"
5977 "
5978{
b935b306 5979 /* r3 is clobbered by set/longjmp, so we can use it as a scratch
5980 register. */
2cb7d577 5981 if (arm_pic_register != INVALID_REGNUM)
5982 arm_load_pic_register (1UL << 3);
95373f08 5983 DONE;
5984}")
5985
9c08d1fa 5986;; If copying one reg to another we can set the condition codes according to
5987;; its value. Such a move is common after a return from subroutine and the
5988;; result is being tested against zero.
5989
f7fbdd4a 5990(define_insn "*movsi_compare0"
bd5b4116 5991 [(set (reg:CC CC_REGNUM)
cffb2a26 5992 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
5993 (const_int 0)))
5994 (set (match_operand:SI 0 "s_register_operand" "=r,r")
5995 (match_dup 1))]
25f905c2 5996 "TARGET_32BIT"
e2348bcb 5997 "@
40dbec34 5998 cmp%?\\t%0, #0
3ef90e77 5999 subs%?\\t%0, %1, #0"
65f68e55 6000 [(set_attr "conds" "set")
d82e788e 6001 (set_attr "type" "alus_imm,alus_imm")]
cffb2a26 6002)
b11cae9e 6003
b11cae9e 6004;; Subroutine to store a half word from a register into memory.
6005;; Operand 0 is the source register (HImode)
c8f69309 6006;; Operand 1 is the destination address in a register (SImode)
b11cae9e 6007
9c08d1fa 6008;; In both this routine and the next, we must be careful not to spill
01cc3b75 6009;; a memory address of reg+large_const into a separate PLUS insn, since this
9c08d1fa 6010;; can generate unrecognizable rtl.
6011
b11cae9e 6012(define_expand "storehi"
c8f69309 6013 [;; store the low byte
f082f1c4 6014 (set (match_operand 1 "" "") (match_dup 3))
b11cae9e 6015 ;; extract the high byte
c8f69309 6016 (set (match_dup 2)
6017 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
b11cae9e 6018 ;; store the high byte
787f8210 6019 (set (match_dup 4) (match_dup 5))]
cffb2a26 6020 "TARGET_ARM"
b11cae9e 6021 "
215b30b3 6022 {
537ffcfc 6023 rtx op1 = operands[1];
6024 rtx addr = XEXP (op1, 0);
215b30b3 6025 enum rtx_code code = GET_CODE (addr);
6026
0438d37f 6027 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
215b30b3 6028 || code == MINUS)
537ffcfc 6029 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
215b30b3 6030
537ffcfc 6031 operands[4] = adjust_address (op1, QImode, 1);
e513d163 6032 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 6033 operands[3] = gen_lowpart (QImode, operands[0]);
6034 operands[0] = gen_lowpart (SImode, operands[0]);
787f8210 6035 operands[2] = gen_reg_rtx (SImode);
6036 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 6037 }"
6038)
b11cae9e 6039
c7597b5d 6040(define_expand "storehi_bigend"
f082f1c4 6041 [(set (match_dup 4) (match_dup 3))
c7597b5d 6042 (set (match_dup 2)
6043 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
787f8210 6044 (set (match_operand 1 "" "") (match_dup 5))]
cffb2a26 6045 "TARGET_ARM"
b11cae9e 6046 "
215b30b3 6047 {
537ffcfc 6048 rtx op1 = operands[1];
6049 rtx addr = XEXP (op1, 0);
215b30b3 6050 enum rtx_code code = GET_CODE (addr);
6051
0438d37f 6052 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
215b30b3 6053 || code == MINUS)
537ffcfc 6054 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
215b30b3 6055
537ffcfc 6056 operands[4] = adjust_address (op1, QImode, 1);
e513d163 6057 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 6058 operands[3] = gen_lowpart (QImode, operands[0]);
6059 operands[0] = gen_lowpart (SImode, operands[0]);
6060 operands[2] = gen_reg_rtx (SImode);
787f8210 6061 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 6062 }"
6063)
c7597b5d 6064
6065;; Subroutine to store a half word integer constant into memory.
6066(define_expand "storeinthi"
f082f1c4 6067 [(set (match_operand 0 "" "")
787f8210 6068 (match_operand 1 "" ""))
9e8503e6 6069 (set (match_dup 3) (match_dup 2))]
cffb2a26 6070 "TARGET_ARM"
c7597b5d 6071 "
215b30b3 6072 {
6073 HOST_WIDE_INT value = INTVAL (operands[1]);
6074 rtx addr = XEXP (operands[0], 0);
537ffcfc 6075 rtx op0 = operands[0];
215b30b3 6076 enum rtx_code code = GET_CODE (addr);
c7597b5d 6077
0438d37f 6078 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
215b30b3 6079 || code == MINUS)
537ffcfc 6080 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
c7597b5d 6081
215b30b3 6082 operands[1] = gen_reg_rtx (SImode);
6083 if (BYTES_BIG_ENDIAN)
6084 {
6085 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
6086 if ((value & 255) == ((value >> 8) & 255))
6087 operands[2] = operands[1];
6088 else
6089 {
6090 operands[2] = gen_reg_rtx (SImode);
6091 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
6092 }
6093 }
6094 else
6095 {
6096 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
6097 if ((value & 255) == ((value >> 8) & 255))
6098 operands[2] = operands[1];
6099 else
6100 {
6101 operands[2] = gen_reg_rtx (SImode);
6102 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
6103 }
6104 }
c7597b5d 6105
537ffcfc 6106 operands[3] = adjust_address (op0, QImode, 1);
e513d163 6107 operands[0] = adjust_address (operands[0], QImode, 0);
9e8503e6 6108 operands[2] = gen_lowpart (QImode, operands[2]);
787f8210 6109 operands[1] = gen_lowpart (QImode, operands[1]);
215b30b3 6110 }"
6111)
b11cae9e 6112
f7fbdd4a 6113(define_expand "storehi_single_op"
6114 [(set (match_operand:HI 0 "memory_operand" "")
6115 (match_operand:HI 1 "general_operand" ""))]
25f905c2 6116 "TARGET_32BIT && arm_arch4"
f7fbdd4a 6117 "
215b30b3 6118 if (!s_register_operand (operands[1], HImode))
f7fbdd4a 6119 operands[1] = copy_to_mode_reg (HImode, operands[1]);
215b30b3 6120 "
6121)
f7fbdd4a 6122
b11cae9e 6123(define_expand "movhi"
6124 [(set (match_operand:HI 0 "general_operand" "")
c8f69309 6125 (match_operand:HI 1 "general_operand" ""))]
cffb2a26 6126 "TARGET_EITHER"
b11cae9e 6127 "
cffb2a26 6128 if (TARGET_ARM)
b11cae9e 6129 {
e1ba4a27 6130 if (can_create_pseudo_p ())
cffb2a26 6131 {
0438d37f 6132 if (MEM_P (operands[0]))
b11cae9e 6133 {
cffb2a26 6134 if (arm_arch4)
6135 {
6136 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
6137 DONE;
6138 }
0438d37f 6139 if (CONST_INT_P (operands[1]))
cffb2a26 6140 emit_insn (gen_storeinthi (operands[0], operands[1]));
c7597b5d 6141 else
cffb2a26 6142 {
0438d37f 6143 if (MEM_P (operands[1]))
cffb2a26 6144 operands[1] = force_reg (HImode, operands[1]);
6145 if (BYTES_BIG_ENDIAN)
6146 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
6147 else
6148 emit_insn (gen_storehi (operands[1], operands[0]));
6149 }
6150 DONE;
b11cae9e 6151 }
cffb2a26 6152 /* Sign extend a constant, and keep it in an SImode reg. */
0438d37f 6153 else if (CONST_INT_P (operands[1]))
9c08d1fa 6154 {
cffb2a26 6155 rtx reg = gen_reg_rtx (SImode);
6156 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
6157
6158 /* If the constant is already valid, leave it alone. */
215b30b3 6159 if (!const_ok_for_arm (val))
cffb2a26 6160 {
6161 /* If setting all the top bits will make the constant
6162 loadable in a single instruction, then set them.
6163 Otherwise, sign extend the number. */
6164
215b30b3 6165 if (const_ok_for_arm (~(val | ~0xffff)))
cffb2a26 6166 val |= ~0xffff;
6167 else if (val & 0x8000)
6168 val |= ~0xffff;
6169 }
6170
6171 emit_insn (gen_movsi (reg, GEN_INT (val)));
9e8503e6 6172 operands[1] = gen_lowpart (HImode, reg);
9c08d1fa 6173 }
e1ba4a27 6174 else if (arm_arch4 && optimize && can_create_pseudo_p ()
0438d37f 6175 && MEM_P (operands[1]))
0045890a 6176 {
6177 rtx reg = gen_reg_rtx (SImode);
6178
6179 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
6180 operands[1] = gen_lowpart (HImode, reg);
6181 }
215b30b3 6182 else if (!arm_arch4)
f7fbdd4a 6183 {
0438d37f 6184 if (MEM_P (operands[1]))
cffb2a26 6185 {
c1a66faf 6186 rtx base;
6187 rtx offset = const0_rtx;
6188 rtx reg = gen_reg_rtx (SImode);
6189
0438d37f 6190 if ((REG_P (base = XEXP (operands[1], 0))
c1a66faf 6191 || (GET_CODE (base) == PLUS
0438d37f 6192 && (CONST_INT_P (offset = XEXP (base, 1)))
c1a66faf 6193 && ((INTVAL(offset) & 1) != 1)
0438d37f 6194 && REG_P (base = XEXP (base, 0))))
c1a66faf 6195 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
206ee9a2 6196 {
8deb3959 6197 rtx new_rtx;
c1a66faf 6198
8deb3959 6199 new_rtx = widen_memory_access (operands[1], SImode,
6200 ((INTVAL (offset) & ~3)
6201 - INTVAL (offset)));
6202 emit_insn (gen_movsi (reg, new_rtx));
c1a66faf 6203 if (((INTVAL (offset) & 2) != 0)
6204 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
6205 {
6206 rtx reg2 = gen_reg_rtx (SImode);
6207
6208 emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
6209 reg = reg2;
6210 }
206ee9a2 6211 }
c1a66faf 6212 else
6213 emit_insn (gen_movhi_bytes (reg, operands[1]));
6214
6215 operands[1] = gen_lowpart (HImode, reg);
cffb2a26 6216 }
6217 }
6218 }
674a8f0b 6219 /* Handle loading a large integer during reload. */
0438d37f 6220 else if (CONST_INT_P (operands[1])
215b30b3 6221 && !const_ok_for_arm (INTVAL (operands[1]))
6222 && !const_ok_for_arm (~INTVAL (operands[1])))
cffb2a26 6223 {
6224 /* Writing a constant to memory needs a scratch, which should
6225 be handled with SECONDARY_RELOADs. */
0438d37f 6226 gcc_assert (REG_P (operands[0]));
cffb2a26 6227
6228 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
6229 emit_insn (gen_movsi (operands[0], operands[1]));
6230 DONE;
6231 }
6232 }
25f905c2 6233 else if (TARGET_THUMB2)
6234 {
6235 /* Thumb-2 can do everything except mem=mem and mem=const easily. */
e1ba4a27 6236 if (can_create_pseudo_p ())
25f905c2 6237 {
0438d37f 6238 if (!REG_P (operands[0]))
25f905c2 6239 operands[1] = force_reg (HImode, operands[1]);
6240 /* Zero extend a constant, and keep it in an SImode reg. */
0438d37f 6241 else if (CONST_INT_P (operands[1]))
25f905c2 6242 {
6243 rtx reg = gen_reg_rtx (SImode);
6244 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
6245
6246 emit_insn (gen_movsi (reg, GEN_INT (val)));
6247 operands[1] = gen_lowpart (HImode, reg);
6248 }
6249 }
6250 }
6251 else /* TARGET_THUMB1 */
cffb2a26 6252 {
e1ba4a27 6253 if (can_create_pseudo_p ())
cffb2a26 6254 {
0438d37f 6255 if (CONST_INT_P (operands[1]))
6cffc037 6256 {
6257 rtx reg = gen_reg_rtx (SImode);
6258
6259 emit_insn (gen_movsi (reg, operands[1]));
6260 operands[1] = gen_lowpart (HImode, reg);
6261 }
cffb2a26 6262
6263 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 6264 happen if we are passed a SP (never OK for HImode/QImode) or
bc409cb4 6265 virtual register (also rejected as illegitimate for HImode/QImode)
6266 relative address. */
cffb2a26 6267 /* ??? This should perhaps be fixed elsewhere, for instance, in
6268 fixup_stack_1, by checking for other kinds of invalid addresses,
6269 e.g. a bare reference to a virtual register. This may confuse the
6270 alpha though, which must handle this case differently. */
0438d37f 6271 if (MEM_P (operands[0])
215b30b3 6272 && !memory_address_p (GET_MODE (operands[0]),
6273 XEXP (operands[0], 0)))
537ffcfc 6274 operands[0]
6275 = replace_equiv_address (operands[0],
6276 copy_to_reg (XEXP (operands[0], 0)));
cffb2a26 6277
0438d37f 6278 if (MEM_P (operands[1])
215b30b3 6279 && !memory_address_p (GET_MODE (operands[1]),
6280 XEXP (operands[1], 0)))
537ffcfc 6281 operands[1]
6282 = replace_equiv_address (operands[1],
6283 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 6284
0438d37f 6285 if (MEM_P (operands[1]) && optimize > 0)
6cffc037 6286 {
6287 rtx reg = gen_reg_rtx (SImode);
6288
6289 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
6290 operands[1] = gen_lowpart (HImode, reg);
6291 }
6292
0438d37f 6293 if (MEM_P (operands[0]))
6cffc037 6294 operands[1] = force_reg (HImode, operands[1]);
cffb2a26 6295 }
0438d37f 6296 else if (CONST_INT_P (operands[1])
234f6557 6297 && !satisfies_constraint_I (operands[1]))
cffb2a26 6298 {
6cffc037 6299 /* Handle loading a large integer during reload. */
6300
cffb2a26 6301 /* Writing a constant to memory needs a scratch, which should
6302 be handled with SECONDARY_RELOADs. */
0438d37f 6303 gcc_assert (REG_P (operands[0]));
cffb2a26 6304
1a83b3ff 6305 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
cffb2a26 6306 emit_insn (gen_movsi (operands[0], operands[1]));
6307 DONE;
6308 }
b11cae9e 6309 }
cffb2a26 6310 "
6311)
6312
25f7a26e 6313(define_expand "movhi_bytes"
eab14235 6314 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 6315 (set (match_dup 3)
eab14235 6316 (zero_extend:SI (match_dup 6)))
25f7a26e 6317 (set (match_operand:SI 0 "" "")
6318 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
cffb2a26 6319 "TARGET_ARM"
25f7a26e 6320 "
215b30b3 6321 {
6322 rtx mem1, mem2;
6323 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
6324
788fcce0 6325 mem1 = change_address (operands[1], QImode, addr);
29c05e22 6326 mem2 = change_address (operands[1], QImode,
6327 plus_constant (Pmode, addr, 1));
215b30b3 6328 operands[0] = gen_lowpart (SImode, operands[0]);
6329 operands[1] = mem1;
6330 operands[2] = gen_reg_rtx (SImode);
6331 operands[3] = gen_reg_rtx (SImode);
6332 operands[6] = mem2;
25f7a26e 6333
215b30b3 6334 if (BYTES_BIG_ENDIAN)
6335 {
6336 operands[4] = operands[2];
6337 operands[5] = operands[3];
6338 }
6339 else
6340 {
6341 operands[4] = operands[3];
6342 operands[5] = operands[2];
6343 }
6344 }"
6345)
25f7a26e 6346
c7597b5d 6347(define_expand "movhi_bigend"
6348 [(set (match_dup 2)
6349 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
6350 (const_int 16)))
6351 (set (match_dup 3)
6352 (ashiftrt:SI (match_dup 2) (const_int 16)))
6353 (set (match_operand:HI 0 "s_register_operand" "")
787f8210 6354 (match_dup 4))]
cffb2a26 6355 "TARGET_ARM"
c7597b5d 6356 "
6357 operands[2] = gen_reg_rtx (SImode);
6358 operands[3] = gen_reg_rtx (SImode);
787f8210 6359 operands[4] = gen_lowpart (HImode, operands[3]);
215b30b3 6360 "
6361)
b11cae9e 6362
a2f10574 6363;; Pattern to recognize insn generated default case above
f7fbdd4a 6364(define_insn "*movhi_insn_arch4"
e4585731 6365 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r,m,r")
6366 (match_operand:HI 1 "general_operand" "rIk,K,n,r,mi"))]
cffb2a26 6367 "TARGET_ARM
6368 && arm_arch4
85e02ccb 6369 && (register_operand (operands[0], HImode)
6370 || register_operand (operands[1], HImode))"
f7fbdd4a 6371 "@
6372 mov%?\\t%0, %1\\t%@ movhi
6373 mvn%?\\t%0, #%B1\\t%@ movhi
b1c1a101 6374 movw%?\\t%0, %L1\\t%@ movhi
3ef90e77 6375 strh%?\\t%1, %0\\t%@ movhi
6376 ldrh%?\\t%0, %1\\t%@ movhi"
65f68e55 6377 [(set_attr "predicable" "yes")
e4585731 6378 (set_attr "pool_range" "*,*,*,*,256")
6379 (set_attr "neg_pool_range" "*,*,*,*,244")
6380 (set_attr "arch" "*,*,v6t2,*,*")
65f68e55 6381 (set_attr_alternative "type"
6382 [(if_then_else (match_operand 1 "const_int_operand" "")
1aed5204 6383 (const_string "mov_imm" )
6384 (const_string "mov_reg"))
6385 (const_string "mvn_imm")
e4585731 6386 (const_string "mov_imm")
65f68e55 6387 (const_string "store1")
6388 (const_string "load1")])]
cffb2a26 6389)
f7fbdd4a 6390
f7fbdd4a 6391(define_insn "*movhi_bytes"
65f68e55 6392 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
5fd254ed 6393 (match_operand:HI 1 "arm_rhs_operand" "I,rk,K"))]
c1a66faf 6394 "TARGET_ARM"
25f7a26e 6395 "@
65f68e55 6396 mov%?\\t%0, %1\\t%@ movhi
25f7a26e 6397 mov%?\\t%0, %1\\t%@ movhi
0d66636f 6398 mvn%?\\t%0, #%B1\\t%@ movhi"
d2a518d1 6399 [(set_attr "predicable" "yes")
1aed5204 6400 (set_attr "type" "mov_imm,mov_reg,mvn_imm")]
0d66636f 6401)
cffb2a26 6402
bc5c7e08 6403;; We use a DImode scratch because we may occasionally need an additional
6404;; temporary if the address isn't offsettable -- push_reload doesn't seem
6405;; to take any notice of the "o" constraints on reload_memory_operand operand.
d3373b54 6406(define_expand "reload_outhi"
cffb2a26 6407 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
215b30b3 6408 (match_operand:HI 1 "s_register_operand" "r")
6409 (match_operand:DI 2 "s_register_operand" "=&l")])]
cffb2a26 6410 "TARGET_EITHER"
6411 "if (TARGET_ARM)
6412 arm_reload_out_hi (operands);
6413 else
6414 thumb_reload_out_hi (operands);
d3373b54 6415 DONE;
cffb2a26 6416 "
6417)
d3373b54 6418
25f7a26e 6419(define_expand "reload_inhi"
6420 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
cffb2a26 6421 (match_operand:HI 1 "arm_reload_memory_operand" "o")
bc5c7e08 6422 (match_operand:DI 2 "s_register_operand" "=&r")])]
c1a66faf 6423 "TARGET_EITHER"
25f7a26e 6424 "
cffb2a26 6425 if (TARGET_ARM)
6426 arm_reload_in_hi (operands);
6427 else
6428 thumb_reload_out_hi (operands);
25f7a26e 6429 DONE;
6430")
6431
9c08d1fa 6432(define_expand "movqi"
6433 [(set (match_operand:QI 0 "general_operand" "")
6434 (match_operand:QI 1 "general_operand" ""))]
cffb2a26 6435 "TARGET_EITHER"
9c08d1fa 6436 "
6cffc037 6437 /* Everything except mem = const or mem = mem can be done easily */
0045890a 6438
e1ba4a27 6439 if (can_create_pseudo_p ())
cffb2a26 6440 {
0438d37f 6441 if (CONST_INT_P (operands[1]))
6cffc037 6442 {
6443 rtx reg = gen_reg_rtx (SImode);
6444
03770691 6445 /* For thumb we want an unsigned immediate, then we are more likely
6446 to be able to use a movs insn. */
6447 if (TARGET_THUMB)
6448 operands[1] = GEN_INT (INTVAL (operands[1]) & 255);
6449
6cffc037 6450 emit_insn (gen_movsi (reg, operands[1]));
6451 operands[1] = gen_lowpart (QImode, reg);
6452 }
cffb2a26 6453
6cffc037 6454 if (TARGET_THUMB)
6455 {
cffb2a26 6456 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 6457 happen if we are passed a SP (never OK for HImode/QImode) or
bc409cb4 6458 virtual register (also rejected as illegitimate for HImode/QImode)
6459 relative address. */
cffb2a26 6460 /* ??? This should perhaps be fixed elsewhere, for instance, in
6461 fixup_stack_1, by checking for other kinds of invalid addresses,
6462 e.g. a bare reference to a virtual register. This may confuse the
6463 alpha though, which must handle this case differently. */
0438d37f 6464 if (MEM_P (operands[0])
215b30b3 6465 && !memory_address_p (GET_MODE (operands[0]),
cffb2a26 6466 XEXP (operands[0], 0)))
537ffcfc 6467 operands[0]
6468 = replace_equiv_address (operands[0],
6469 copy_to_reg (XEXP (operands[0], 0)));
0438d37f 6470 if (MEM_P (operands[1])
215b30b3 6471 && !memory_address_p (GET_MODE (operands[1]),
cffb2a26 6472 XEXP (operands[1], 0)))
537ffcfc 6473 operands[1]
6474 = replace_equiv_address (operands[1],
6475 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 6476 }
6477
0438d37f 6478 if (MEM_P (operands[1]) && optimize > 0)
6cffc037 6479 {
6480 rtx reg = gen_reg_rtx (SImode);
6481
6482 emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
6483 operands[1] = gen_lowpart (QImode, reg);
6484 }
6485
0438d37f 6486 if (MEM_P (operands[0]))
6cffc037 6487 operands[1] = force_reg (QImode, operands[1]);
6488 }
6489 else if (TARGET_THUMB
0438d37f 6490 && CONST_INT_P (operands[1])
234f6557 6491 && !satisfies_constraint_I (operands[1]))
6cffc037 6492 {
674a8f0b 6493 /* Handle loading a large integer during reload. */
cffb2a26 6494
6cffc037 6495 /* Writing a constant to memory needs a scratch, which should
6496 be handled with SECONDARY_RELOADs. */
0438d37f 6497 gcc_assert (REG_P (operands[0]));
6cffc037 6498
6499 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
6500 emit_insn (gen_movsi (operands[0], operands[1]));
6501 DONE;
cffb2a26 6502 }
6503 "
6504)
b11cae9e 6505
cffb2a26 6506(define_insn "*arm_movqi_insn"
fd711051 6507 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,l,r,l,Uu,r,m")
490f62ca 6508 (match_operand:QI 1 "general_operand" "rk,rk,I,Py,K,Uu,l,Uh,r"))]
25f905c2 6509 "TARGET_32BIT
cffb2a26 6510 && ( register_operand (operands[0], QImode)
6511 || register_operand (operands[1], QImode))"
5565501b 6512 "@
fd711051 6513 mov%?\\t%0, %1
6514 mov%?\\t%0, %1
65f68e55 6515 mov%?\\t%0, %1
5565501b 6516 mov%?\\t%0, %1
6517 mvn%?\\t%0, #%B1
3ef90e77 6518 ldrb%?\\t%0, %1
6519 strb%?\\t%1, %0
6520 ldrb%?\\t%0, %1
6521 strb%?\\t%1, %0"
1aed5204 6522 [(set_attr "type" "mov_reg,mov_reg,mov_imm,mov_imm,mvn_imm,load1,store1,load1,store1")
a54e3e7b 6523 (set_attr "predicable" "yes")
fd711051 6524 (set_attr "predicable_short_it" "yes,yes,yes,no,no,no,no,no,no")
6525 (set_attr "arch" "t2,any,any,t2,any,t2,t2,any,any")
6526 (set_attr "length" "2,4,4,2,4,2,2,4,4")]
cffb2a26 6527)
6528
9b8516be 6529;; HFmode moves
6530(define_expand "movhf"
6531 [(set (match_operand:HF 0 "general_operand" "")
6532 (match_operand:HF 1 "general_operand" ""))]
6533 "TARGET_EITHER"
6534 "
6535 if (TARGET_32BIT)
6536 {
0438d37f 6537 if (MEM_P (operands[0]))
9b8516be 6538 operands[1] = force_reg (HFmode, operands[1]);
6539 }
6540 else /* TARGET_THUMB1 */
6541 {
6542 if (can_create_pseudo_p ())
6543 {
0438d37f 6544 if (!REG_P (operands[0]))
9b8516be 6545 operands[1] = force_reg (HFmode, operands[1]);
6546 }
6547 }
6548 "
6549)
6550
6551(define_insn "*arm32_movhf"
6552 [(set (match_operand:HF 0 "nonimmediate_operand" "=r,m,r,r")
6553 (match_operand:HF 1 "general_operand" " m,r,r,F"))]
2a1125d6 6554 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_VFP)
9b8516be 6555 && ( s_register_operand (operands[0], HFmode)
6556 || s_register_operand (operands[1], HFmode))"
6557 "*
6558 switch (which_alternative)
6559 {
6560 case 0: /* ARM register from memory */
3ef90e77 6561 return \"ldrh%?\\t%0, %1\\t%@ __fp16\";
9b8516be 6562 case 1: /* memory from ARM register */
3ef90e77 6563 return \"strh%?\\t%1, %0\\t%@ __fp16\";
9b8516be 6564 case 2: /* ARM register from ARM register */
6565 return \"mov%?\\t%0, %1\\t%@ __fp16\";
6566 case 3: /* ARM register from constant */
6567 {
9b8516be 6568 long bits;
6569 rtx ops[4];
6570
945f7b03 6571 bits = real_to_target (NULL, CONST_DOUBLE_REAL_VALUE (operands[1]),
6572 HFmode);
9b8516be 6573 ops[0] = operands[0];
6574 ops[1] = GEN_INT (bits);
6575 ops[2] = GEN_INT (bits & 0xff00);
6576 ops[3] = GEN_INT (bits & 0x00ff);
6577
6578 if (arm_arch_thumb2)
6579 output_asm_insn (\"movw%?\\t%0, %1\", ops);
6580 else
6581 output_asm_insn (\"mov%?\\t%0, %2\;orr%?\\t%0, %0, %3\", ops);
6582 return \"\";
6583 }
6584 default:
6585 gcc_unreachable ();
6586 }
6587 "
6588 [(set_attr "conds" "unconditional")
ad4fc3c0 6589 (set_attr "type" "load1,store1,mov_reg,multiple")
9b8516be 6590 (set_attr "length" "4,4,4,8")
ea501323 6591 (set_attr "predicable" "yes")
6592 (set_attr "predicable_short_it" "no")]
9b8516be 6593)
6594
87b22bf7 6595(define_expand "movsf"
6596 [(set (match_operand:SF 0 "general_operand" "")
6597 (match_operand:SF 1 "general_operand" ""))]
cffb2a26 6598 "TARGET_EITHER"
87b22bf7 6599 "
25f905c2 6600 if (TARGET_32BIT)
cffb2a26 6601 {
0438d37f 6602 if (MEM_P (operands[0]))
cffb2a26 6603 operands[1] = force_reg (SFmode, operands[1]);
6604 }
25f905c2 6605 else /* TARGET_THUMB1 */
cffb2a26 6606 {
e1ba4a27 6607 if (can_create_pseudo_p ())
cffb2a26 6608 {
0438d37f 6609 if (!REG_P (operands[0]))
cffb2a26 6610 operands[1] = force_reg (SFmode, operands[1]);
6611 }
6612 }
6613 "
6614)
6615
03d440a6 6616;; Transform a floating-point move of a constant into a core register into
6617;; an SImode operation.
cffb2a26 6618(define_split
03d440a6 6619 [(set (match_operand:SF 0 "arm_general_register_operand" "")
cffb2a26 6620 (match_operand:SF 1 "immediate_operand" ""))]
339034d0 6621 "TARGET_EITHER
cffb2a26 6622 && reload_completed
0438d37f 6623 && CONST_DOUBLE_P (operands[1])"
cffb2a26 6624 [(set (match_dup 2) (match_dup 3))]
6625 "
6626 operands[2] = gen_lowpart (SImode, operands[0]);
6627 operands[3] = gen_lowpart (SImode, operands[1]);
6628 if (operands[2] == 0 || operands[3] == 0)
6629 FAIL;
215b30b3 6630 "
6631)
87b22bf7 6632
cffb2a26 6633(define_insn "*arm_movsf_soft_insn"
6634 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
6635 (match_operand:SF 1 "general_operand" "r,mE,r"))]
cde1623a 6636 "TARGET_32BIT
cffb2a26 6637 && TARGET_SOFT_FLOAT
0438d37f 6638 && (!MEM_P (operands[0])
215b30b3 6639 || register_operand (operands[1], SFmode))"
9a1112d7 6640 "@
6641 mov%?\\t%0, %1
6642 ldr%?\\t%0, %1\\t%@ float
6643 str%?\\t%1, %0\\t%@ float"
cde1623a 6644 [(set_attr "predicable" "yes")
7c36fe71 6645 (set_attr "predicable_short_it" "no")
1aed5204 6646 (set_attr "type" "mov_reg,load1,store1")
42e1de19 6647 (set_attr "arm_pool_range" "*,4096,*")
6648 (set_attr "thumb2_pool_range" "*,4094,*")
cde1623a 6649 (set_attr "arm_neg_pool_range" "*,4084,*")
6650 (set_attr "thumb2_neg_pool_range" "*,0,*")]
cffb2a26 6651)
6652
9c08d1fa 6653(define_expand "movdf"
87b22bf7 6654 [(set (match_operand:DF 0 "general_operand" "")
6655 (match_operand:DF 1 "general_operand" ""))]
cffb2a26 6656 "TARGET_EITHER"
9c08d1fa 6657 "
25f905c2 6658 if (TARGET_32BIT)
cffb2a26 6659 {
0438d37f 6660 if (MEM_P (operands[0]))
cffb2a26 6661 operands[1] = force_reg (DFmode, operands[1]);
6662 }
6663 else /* TARGET_THUMB */
6664 {
e1ba4a27 6665 if (can_create_pseudo_p ())
cffb2a26 6666 {
0438d37f 6667 if (!REG_P (operands[0]))
cffb2a26 6668 operands[1] = force_reg (DFmode, operands[1]);
6669 }
6670 }
6671 "
6672)
b11cae9e 6673
9c08d1fa 6674;; Reloading a df mode value stored in integer regs to memory can require a
6675;; scratch reg.
6676(define_expand "reload_outdf"
cffb2a26 6677 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
87b22bf7 6678 (match_operand:DF 1 "s_register_operand" "r")
6679 (match_operand:SI 2 "s_register_operand" "=&r")]
06adefdc 6680 "TARGET_THUMB2"
87b22bf7 6681 "
215b30b3 6682 {
6683 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
f7fbdd4a 6684
215b30b3 6685 if (code == REG)
6686 operands[2] = XEXP (operands[0], 0);
6687 else if (code == POST_INC || code == PRE_DEC)
6688 {
6689 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
6690 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
6691 emit_insn (gen_movdi (operands[0], operands[1]));
6692 DONE;
6693 }
6694 else if (code == PRE_INC)
6695 {
6696 rtx reg = XEXP (XEXP (operands[0], 0), 0);
f7fbdd4a 6697
215b30b3 6698 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
6699 operands[2] = reg;
6700 }
6701 else if (code == POST_DEC)
6702 operands[2] = XEXP (XEXP (operands[0], 0), 0);
6703 else
6704 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
6705 XEXP (XEXP (operands[0], 0), 1)));
f7fbdd4a 6706
d1f9b275 6707 emit_insn (gen_rtx_SET (replace_equiv_address (operands[0], operands[2]),
215b30b3 6708 operands[1]));
f7fbdd4a 6709
215b30b3 6710 if (code == POST_DEC)
6711 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
6712
6713 DONE;
6714 }"
6715)
9c08d1fa 6716
9a1112d7 6717(define_insn "*movdf_soft_insn"
353cf59a 6718 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,q,m")
6719 (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,q"))]
cde1623a 6720 "TARGET_32BIT && TARGET_SOFT_FLOAT
b2778788 6721 && ( register_operand (operands[0], DFmode)
6722 || register_operand (operands[1], DFmode))"
d51f92df 6723 "*
6724 switch (which_alternative)
6725 {
6726 case 0:
6727 case 1:
6728 case 2:
6729 return \"#\";
6730 default:
26ff80c0 6731 return output_move_double (operands, true, NULL);
d51f92df 6732 }
6733 "
359a6e9f 6734 [(set_attr "length" "8,12,16,8,8")
1b7da4ac 6735 (set_attr "type" "multiple,multiple,multiple,load2,store2")
42e1de19 6736 (set_attr "arm_pool_range" "*,*,*,1020,*")
6737 (set_attr "thumb2_pool_range" "*,*,*,1018,*")
8848d797 6738 (set_attr "arm_neg_pool_range" "*,*,*,1004,*")
cde1623a 6739 (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
cffb2a26 6740)
b11cae9e 6741\f
b11cae9e 6742
9c08d1fa 6743;; load- and store-multiple insns
6744;; The arm can load/store any set of registers, provided that they are in
320ea44d 6745;; ascending order, but these expanders assume a contiguous set.
b11cae9e 6746
9c08d1fa 6747(define_expand "load_multiple"
6748 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6749 (match_operand:SI 1 "" ""))
6750 (use (match_operand:SI 2 "" ""))])]
25f905c2 6751 "TARGET_32BIT"
9580c25f 6752{
6753 HOST_WIDE_INT offset = 0;
6754
bd5b4116 6755 /* Support only fixed point registers. */
0438d37f 6756 if (!CONST_INT_P (operands[2])
6e628811 6757 || INTVAL (operands[2]) > MAX_LDM_STM_OPS
9c08d1fa 6758 || INTVAL (operands[2]) < 2
0438d37f 6759 || !MEM_P (operands[1])
6760 || !REG_P (operands[0])
bd5b4116 6761 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
6762 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 6763 FAIL;
6764
6765 operands[3]
320ea44d 6766 = arm_gen_load_multiple (arm_regs_in_sequence + REGNO (operands[0]),
6767 INTVAL (operands[2]),
f082f1c4 6768 force_reg (SImode, XEXP (operands[1], 0)),
320ea44d 6769 FALSE, operands[1], &offset);
9580c25f 6770})
b11cae9e 6771
9c08d1fa 6772(define_expand "store_multiple"
6773 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6774 (match_operand:SI 1 "" ""))
6775 (use (match_operand:SI 2 "" ""))])]
25f905c2 6776 "TARGET_32BIT"
9580c25f 6777{
6778 HOST_WIDE_INT offset = 0;
6779
674a8f0b 6780 /* Support only fixed point registers. */
0438d37f 6781 if (!CONST_INT_P (operands[2])
6e628811 6782 || INTVAL (operands[2]) > MAX_LDM_STM_OPS
9c08d1fa 6783 || INTVAL (operands[2]) < 2
0438d37f 6784 || !REG_P (operands[1])
6785 || !MEM_P (operands[0])
bd5b4116 6786 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
6787 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 6788 FAIL;
6789
6790 operands[3]
320ea44d 6791 = arm_gen_store_multiple (arm_regs_in_sequence + REGNO (operands[1]),
6792 INTVAL (operands[2]),
f082f1c4 6793 force_reg (SImode, XEXP (operands[0], 0)),
320ea44d 6794 FALSE, operands[0], &offset);
9580c25f 6795})
b11cae9e 6796
9c08d1fa 6797
e34ebfca 6798(define_expand "setmemsi"
6799 [(match_operand:BLK 0 "general_operand" "")
6800 (match_operand:SI 1 "const_int_operand" "")
6801 (match_operand:SI 2 "const_int_operand" "")
6802 (match_operand:SI 3 "const_int_operand" "")]
6803 "TARGET_32BIT"
6804{
6805 if (arm_gen_setmem (operands))
6806 DONE;
6807
6808 FAIL;
6809})
6810
6811
9c08d1fa 6812;; Move a block of memory if it is word aligned and MORE than 2 words long.
6813;; We could let this apply for blocks of less than this, but it clobbers so
6814;; many registers that there is then probably a better way.
6815
008c057d 6816(define_expand "movmemqi"
34191dd1 6817 [(match_operand:BLK 0 "general_operand" "")
6818 (match_operand:BLK 1 "general_operand" "")
6819 (match_operand:SI 2 "const_int_operand" "")
6820 (match_operand:SI 3 "const_int_operand" "")]
ae51a965 6821 ""
9c08d1fa 6822 "
25f905c2 6823 if (TARGET_32BIT)
cffb2a26 6824 {
ae51a965 6825 if (TARGET_LDRD && current_tune->prefer_ldrd_strd
6826 && !optimize_function_for_size_p (cfun))
6827 {
6828 if (gen_movmem_ldrd_strd (operands))
6829 DONE;
6830 FAIL;
6831 }
6832
008c057d 6833 if (arm_gen_movmemqi (operands))
cffb2a26 6834 DONE;
6835 FAIL;
6836 }
25f905c2 6837 else /* TARGET_THUMB1 */
cffb2a26 6838 {
6839 if ( INTVAL (operands[3]) != 4
6840 || INTVAL (operands[2]) > 48)
6841 FAIL;
6842
008c057d 6843 thumb_expand_movmemqi (operands);
cffb2a26 6844 DONE;
6845 }
6846 "
6847)
9c08d1fa 6848\f
b11cae9e 6849
341940e8 6850;; Compare & branch insns
8d232dc7 6851;; The range calculations are based as follows:
341940e8 6852;; For forward branches, the address calculation returns the address of
6853;; the next instruction. This is 2 beyond the branch instruction.
6854;; For backward branches, the address calculation returns the address of
6855;; the first instruction in this pattern (cmp). This is 2 before the branch
6856;; instruction for the shortest sequence, and 4 before the branch instruction
6857;; if we have to jump around an unconditional branch.
6858;; To the basic branch range the PC offset must be added (this is +4).
6859;; So for forward branches we have
6860;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
6861;; And for backward branches we have
6862;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
6863;;
6864;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
6865;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
cffb2a26 6866
aeac46d4 6867(define_expand "cbranchsi4"
6868 [(set (pc) (if_then_else
aa06947a 6869 (match_operator 0 "expandable_comparison_operator"
aeac46d4 6870 [(match_operand:SI 1 "s_register_operand" "")
6871 (match_operand:SI 2 "nonmemory_operand" "")])
6872 (label_ref (match_operand 3 "" ""))
6873 (pc)))]
f9aa4160 6874 "TARGET_EITHER"
aeac46d4 6875 "
74f4459c 6876 if (!TARGET_THUMB1)
6877 {
f9aa4160 6878 if (!arm_validize_comparison (&operands[0], &operands[1], &operands[2]))
6879 FAIL;
74f4459c 6880 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6881 operands[3]));
6882 DONE;
6883 }
25f905c2 6884 if (thumb1_cmpneg_operand (operands[2], SImode))
aeac46d4 6885 {
6886 emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
6887 operands[3], operands[0]));
6888 DONE;
6889 }
25f905c2 6890 if (!thumb1_cmp_operand (operands[2], SImode))
aeac46d4 6891 operands[2] = force_reg (SImode, operands[2]);
6892 ")
6893
74f4459c 6894(define_expand "cbranchsf4"
6895 [(set (pc) (if_then_else
aa06947a 6896 (match_operator 0 "expandable_comparison_operator"
74f4459c 6897 [(match_operand:SF 1 "s_register_operand" "")
6898 (match_operand:SF 2 "arm_float_compare_operand" "")])
6899 (label_ref (match_operand 3 "" ""))
6900 (pc)))]
6901 "TARGET_32BIT && TARGET_HARD_FLOAT"
6902 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6903 operands[3])); DONE;"
6904)
6905
6906(define_expand "cbranchdf4"
6907 [(set (pc) (if_then_else
aa06947a 6908 (match_operator 0 "expandable_comparison_operator"
74f4459c 6909 [(match_operand:DF 1 "s_register_operand" "")
6910 (match_operand:DF 2 "arm_float_compare_operand" "")])
6911 (label_ref (match_operand 3 "" ""))
6912 (pc)))]
a50d7267 6913 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
74f4459c 6914 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6915 operands[3])); DONE;"
6916)
6917
74f4459c 6918(define_expand "cbranchdi4"
6919 [(set (pc) (if_then_else
aa06947a 6920 (match_operator 0 "expandable_comparison_operator"
b8eae306 6921 [(match_operand:DI 1 "s_register_operand" "")
a8045a4f 6922 (match_operand:DI 2 "cmpdi_operand" "")])
74f4459c 6923 (label_ref (match_operand 3 "" ""))
6924 (pc)))]
a8045a4f 6925 "TARGET_32BIT"
6926 "{
0438d37f 6927 if (!arm_validize_comparison (&operands[0], &operands[1], &operands[2]))
f9aa4160 6928 FAIL;
6929 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
a8045a4f 6930 operands[3]));
6931 DONE;
6932 }"
74f4459c 6933)
6934
9c08d1fa 6935;; Comparison and test insns
6936
cffb2a26 6937(define_insn "*arm_cmpsi_insn"
bd5b4116 6938 [(set (reg:CC CC_REGNUM)
f9f234ec 6939 (compare:CC (match_operand:SI 0 "s_register_operand" "l,r,r,r,r")
6940 (match_operand:SI 1 "arm_add_operand" "Py,r,r,I,L")))]
25f905c2 6941 "TARGET_32BIT"
5565501b 6942 "@
a6864a24 6943 cmp%?\\t%0, %1
6944 cmp%?\\t%0, %1
aea4c774 6945 cmp%?\\t%0, %1
f9f234ec 6946 cmp%?\\t%0, %1
aea4c774 6947 cmn%?\\t%0, #%n1"
a6864a24 6948 [(set_attr "conds" "set")
f9f234ec 6949 (set_attr "arch" "t2,t2,any,any,any")
6950 (set_attr "length" "2,2,4,4,4")
65f68e55 6951 (set_attr "predicable" "yes")
f9f234ec 6952 (set_attr "predicable_short_it" "yes,yes,yes,no,no")
112eda6f 6953 (set_attr "type" "alus_imm,alus_sreg,alus_sreg,alus_imm,alus_imm")]
cffb2a26 6954)
b11cae9e 6955
d5d4dc8d 6956(define_insn "*cmpsi_shiftsi"
bd5b4116 6957 [(set (reg:CC CC_REGNUM)
d82e788e 6958 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r,r")
cffb2a26 6959 (match_operator:SI 3 "shift_operator"
d82e788e 6960 [(match_operand:SI 1 "s_register_operand" "r,r,r")
6961 (match_operand:SI 2 "shift_amount_operand" "M,r,M")])))]
d5d4dc8d 6962 "TARGET_32BIT"
f9f234ec 6963 "cmp\\t%0, %1%S3"
344495ea 6964 [(set_attr "conds" "set")
331beb1a 6965 (set_attr "shift" "1")
d82e788e 6966 (set_attr "arch" "32,a,a")
282b4c75 6967 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
b11cae9e 6968
d5d4dc8d 6969(define_insn "*cmpsi_shiftsi_swp"
bd5b4116 6970 [(set (reg:CC_SWP CC_REGNUM)
aea4c774 6971 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
d82e788e 6972 [(match_operand:SI 1 "s_register_operand" "r,r,r")
6973 (match_operand:SI 2 "shift_amount_operand" "M,r,M")])
6974 (match_operand:SI 0 "s_register_operand" "r,r,r")))]
d5d4dc8d 6975 "TARGET_32BIT"
aea4c774 6976 "cmp%?\\t%0, %1%S3"
344495ea 6977 [(set_attr "conds" "set")
331beb1a 6978 (set_attr "shift" "1")
d82e788e 6979 (set_attr "arch" "32,a,a")
282b4c75 6980 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
b11cae9e 6981
25f905c2 6982(define_insn "*arm_cmpsi_negshiftsi_si"
aed179ae 6983 [(set (reg:CC_Z CC_REGNUM)
6984 (compare:CC_Z
6985 (neg:SI (match_operator:SI 1 "shift_operator"
6986 [(match_operand:SI 2 "s_register_operand" "r")
6987 (match_operand:SI 3 "reg_or_int_operand" "rM")]))
6988 (match_operand:SI 0 "s_register_operand" "r")))]
cffb2a26 6989 "TARGET_ARM"
aed179ae 6990 "cmn%?\\t%0, %2%S1"
344495ea 6991 [(set_attr "conds" "set")
aed179ae 6992 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
d82e788e 6993 (const_string "alus_shift_imm")
6994 (const_string "alus_shift_reg")))
596e5e8f 6995 (set_attr "predicable" "yes")]
0d66636f 6996)
b11cae9e 6997
a8045a4f 6998;; DImode comparisons. The generic code generates branches that
6999;; if-conversion can not reduce to a conditional compare, so we do
7000;; that directly.
7001
ba6a3b2f 7002(define_insn_and_split "*arm_cmpdi_insn"
a8045a4f 7003 [(set (reg:CC_NCV CC_REGNUM)
7004 (compare:CC_NCV (match_operand:DI 0 "s_register_operand" "r")
7005 (match_operand:DI 1 "arm_di_operand" "rDi")))
7006 (clobber (match_scratch:SI 2 "=r"))]
b805622c 7007 "TARGET_32BIT"
ba6a3b2f 7008 "#" ; "cmp\\t%Q0, %Q1\;sbcs\\t%2, %R0, %R1"
7009 "&& reload_completed"
7010 [(set (reg:CC CC_REGNUM)
7011 (compare:CC (match_dup 0) (match_dup 1)))
7012 (parallel [(set (reg:CC CC_REGNUM)
7013 (compare:CC (match_dup 3) (match_dup 4)))
7014 (set (match_dup 2)
7015 (minus:SI (match_dup 5)
7016 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))])]
7017 {
7018 operands[3] = gen_highpart (SImode, operands[0]);
7019 operands[0] = gen_lowpart (SImode, operands[0]);
7020 if (CONST_INT_P (operands[1]))
7021 {
7022 operands[4] = GEN_INT (~INTVAL (gen_highpart_mode (SImode,
7023 DImode,
7024 operands[1])));
7025 operands[5] = gen_rtx_PLUS (SImode, operands[3], operands[4]);
7026 }
7027 else
7028 {
7029 operands[4] = gen_highpart (SImode, operands[1]);
7030 operands[5] = gen_rtx_MINUS (SImode, operands[3], operands[4]);
7031 }
7032 operands[1] = gen_lowpart (SImode, operands[1]);
7033 operands[2] = gen_lowpart (SImode, operands[2]);
7034 }
a8045a4f 7035 [(set_attr "conds" "set")
1b7da4ac 7036 (set_attr "length" "8")
7037 (set_attr "type" "multiple")]
a8045a4f 7038)
7039
ba6a3b2f 7040(define_insn_and_split "*arm_cmpdi_unsigned"
a8045a4f 7041 [(set (reg:CC_CZ CC_REGNUM)
1a86364b 7042 (compare:CC_CZ (match_operand:DI 0 "s_register_operand" "l,r,r,r")
7043 (match_operand:DI 1 "arm_di_operand" "Py,r,Di,rDi")))]
7c36fe71 7044
48a98053 7045 "TARGET_32BIT"
ba6a3b2f 7046 "#" ; "cmp\\t%R0, %R1\;it eq\;cmpeq\\t%Q0, %Q1"
7047 "&& reload_completed"
7048 [(set (reg:CC CC_REGNUM)
7049 (compare:CC (match_dup 2) (match_dup 3)))
7050 (cond_exec (eq:SI (reg:CC CC_REGNUM) (const_int 0))
7051 (set (reg:CC CC_REGNUM)
7052 (compare:CC (match_dup 0) (match_dup 1))))]
7053 {
7054 operands[2] = gen_highpart (SImode, operands[0]);
7055 operands[0] = gen_lowpart (SImode, operands[0]);
7056 if (CONST_INT_P (operands[1]))
7057 operands[3] = gen_highpart_mode (SImode, DImode, operands[1]);
7058 else
7059 operands[3] = gen_highpart (SImode, operands[1]);
7060 operands[1] = gen_lowpart (SImode, operands[1]);
7061 }
a8045a4f 7062 [(set_attr "conds" "set")
1a86364b 7063 (set_attr "enabled_for_depr_it" "yes,yes,no,*")
7064 (set_attr "arch" "t2,t2,t2,a")
7065 (set_attr "length" "6,6,10,8")
1b7da4ac 7066 (set_attr "type" "multiple")]
a8045a4f 7067)
7068
7069(define_insn "*arm_cmpdi_zero"
7070 [(set (reg:CC_Z CC_REGNUM)
7071 (compare:CC_Z (match_operand:DI 0 "s_register_operand" "r")
7072 (const_int 0)))
7073 (clobber (match_scratch:SI 1 "=r"))]
7074 "TARGET_32BIT"
3ef90e77 7075 "orrs%?\\t%1, %Q0, %R0"
1b7da4ac 7076 [(set_attr "conds" "set")
7077 (set_attr "type" "logics_reg")]
a8045a4f 7078)
7079
9c08d1fa 7080; This insn allows redundant compares to be removed by cse, nothing should
7081; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
7082; is deleted later on. The match_dup will match the mode here, so that
7083; mode changes of the condition codes aren't lost by this even though we don't
7084; specify what they are.
7085
8a18b90c 7086(define_insn "*deleted_compare"
9c08d1fa 7087 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
25f905c2 7088 "TARGET_32BIT"
40dbec34 7089 "\\t%@ deleted compare"
cffb2a26 7090 [(set_attr "conds" "set")
1b7da4ac 7091 (set_attr "length" "0")
7092 (set_attr "type" "no_insn")]
cffb2a26 7093)
9c08d1fa 7094
7095\f
7096;; Conditional branch insns
7097
74f4459c 7098(define_expand "cbranch_cc"
9c08d1fa 7099 [(set (pc)
74f4459c 7100 (if_then_else (match_operator 0 "" [(match_operand 1 "" "")
7101 (match_operand 2 "" "")])
7102 (label_ref (match_operand 3 "" ""))
9c08d1fa 7103 (pc)))]
25f905c2 7104 "TARGET_32BIT"
74f4459c 7105 "operands[1] = arm_gen_compare_reg (GET_CODE (operands[0]),
e1b93706 7106 operands[1], operands[2], NULL_RTX);
74f4459c 7107 operands[2] = const0_rtx;"
8fa3ba89 7108)
7109
7110;;
7111;; Patterns to match conditional branch insns.
7112;;
7113
ffcc986d 7114(define_insn "arm_cond_branch"
9c08d1fa 7115 [(set (pc)
8fa3ba89 7116 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 7117 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 7118 (label_ref (match_operand 0 "" ""))
7119 (pc)))]
25f905c2 7120 "TARGET_32BIT"
d75350ce 7121 "*
9c08d1fa 7122 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 7123 {
7124 arm_ccfsm_state += 2;
7125 return \"\";
7126 }
e2348bcb 7127 return \"b%d1\\t%l0\";
cffb2a26 7128 "
a2cd141b 7129 [(set_attr "conds" "use")
a6864a24 7130 (set_attr "type" "branch")
7131 (set (attr "length")
7132 (if_then_else
0bf497f5 7133 (and (match_test "TARGET_THUMB2")
a6864a24 7134 (and (ge (minus (match_dup 0) (pc)) (const_int -250))
7135 (le (minus (match_dup 0) (pc)) (const_int 256))))
7136 (const_int 2)
7137 (const_int 4)))]
cffb2a26 7138)
d75350ce 7139
cffb2a26 7140(define_insn "*arm_cond_branch_reversed"
9c08d1fa 7141 [(set (pc)
8fa3ba89 7142 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 7143 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 7144 (pc)
7145 (label_ref (match_operand 0 "" ""))))]
25f905c2 7146 "TARGET_32BIT"
d75350ce 7147 "*
9c08d1fa 7148 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 7149 {
7150 arm_ccfsm_state += 2;
7151 return \"\";
7152 }
e2348bcb 7153 return \"b%D1\\t%l0\";
cffb2a26 7154 "
a2cd141b 7155 [(set_attr "conds" "use")
a6864a24 7156 (set_attr "type" "branch")
7157 (set (attr "length")
7158 (if_then_else
0bf497f5 7159 (and (match_test "TARGET_THUMB2")
a6864a24 7160 (and (ge (minus (match_dup 0) (pc)) (const_int -250))
7161 (le (minus (match_dup 0) (pc)) (const_int 256))))
7162 (const_int 2)
7163 (const_int 4)))]
cffb2a26 7164)
7165
b11cae9e 7166\f
9c08d1fa 7167
7168; scc insns
7169
74f4459c 7170(define_expand "cstore_cc"
7db9af5d 7171 [(set (match_operand:SI 0 "s_register_operand" "")
74f4459c 7172 (match_operator:SI 1 "" [(match_operand 2 "" "")
7173 (match_operand 3 "" "")]))]
25f905c2 7174 "TARGET_32BIT"
74f4459c 7175 "operands[2] = arm_gen_compare_reg (GET_CODE (operands[1]),
e1b93706 7176 operands[2], operands[3], NULL_RTX);
74f4459c 7177 operands[3] = const0_rtx;"
8fa3ba89 7178)
7179
a3b84066 7180(define_insn_and_split "*mov_scc"
9c08d1fa 7181 [(set (match_operand:SI 0 "s_register_operand" "=r")
ff74dd54 7182 (match_operator:SI 1 "arm_comparison_operator_mode"
8a18b90c 7183 [(match_operand 2 "cc_register" "") (const_int 0)]))]
cffb2a26 7184 "TARGET_ARM"
a3b84066 7185 "#" ; "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
7186 "TARGET_ARM"
7187 [(set (match_dup 0)
7188 (if_then_else:SI (match_dup 1)
7189 (const_int 1)
7190 (const_int 0)))]
7191 ""
cffb2a26 7192 [(set_attr "conds" "use")
1b7da4ac 7193 (set_attr "length" "8")
7194 (set_attr "type" "multiple")]
cffb2a26 7195)
9c08d1fa 7196
a3b84066 7197(define_insn_and_split "*mov_negscc"
9c08d1fa 7198 [(set (match_operand:SI 0 "s_register_operand" "=r")
ff74dd54 7199 (neg:SI (match_operator:SI 1 "arm_comparison_operator_mode"
8a18b90c 7200 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 7201 "TARGET_ARM"
a3b84066 7202 "#" ; "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
7203 "TARGET_ARM"
7204 [(set (match_dup 0)
7205 (if_then_else:SI (match_dup 1)
7206 (match_dup 3)
7207 (const_int 0)))]
7208 {
7209 operands[3] = GEN_INT (~0);
7210 }
cffb2a26 7211 [(set_attr "conds" "use")
1b7da4ac 7212 (set_attr "length" "8")
7213 (set_attr "type" "multiple")]
cffb2a26 7214)
9c08d1fa 7215
a3b84066 7216(define_insn_and_split "*mov_notscc"
9c08d1fa 7217 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7218 (not:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7219 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 7220 "TARGET_ARM"
a3b84066 7221 "#" ; "mvn%D1\\t%0, #0\;mvn%d1\\t%0, #1"
7222 "TARGET_ARM"
7223 [(set (match_dup 0)
7224 (if_then_else:SI (match_dup 1)
7225 (match_dup 3)
7226 (match_dup 4)))]
7227 {
7228 operands[3] = GEN_INT (~1);
7229 operands[4] = GEN_INT (~0);
7230 }
cffb2a26 7231 [(set_attr "conds" "use")
1b7da4ac 7232 (set_attr "length" "8")
7233 (set_attr "type" "multiple")]
cffb2a26 7234)
9c08d1fa 7235
595d88b5 7236(define_expand "cstoresi4"
7237 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 7238 (match_operator:SI 1 "expandable_comparison_operator"
595d88b5 7239 [(match_operand:SI 2 "s_register_operand" "")
7240 (match_operand:SI 3 "reg_or_int_operand" "")]))]
74f4459c 7241 "TARGET_32BIT || TARGET_THUMB1"
595d88b5 7242 "{
7243 rtx op3, scratch, scratch2;
7244
74f4459c 7245 if (!TARGET_THUMB1)
7246 {
7247 if (!arm_add_operand (operands[3], SImode))
7248 operands[3] = force_reg (SImode, operands[3]);
7249 emit_insn (gen_cstore_cc (operands[0], operands[1],
7250 operands[2], operands[3]));
7251 DONE;
7252 }
7253
595d88b5 7254 if (operands[3] == const0_rtx)
7255 {
7256 switch (GET_CODE (operands[1]))
7257 {
7258 case EQ:
25f905c2 7259 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], operands[2]));
595d88b5 7260 break;
7261
7262 case NE:
25f905c2 7263 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], operands[2]));
595d88b5 7264 break;
7265
7266 case LE:
7267 scratch = expand_binop (SImode, add_optab, operands[2], constm1_rtx,
7268 NULL_RTX, 0, OPTAB_WIDEN);
7269 scratch = expand_binop (SImode, ior_optab, operands[2], scratch,
7270 NULL_RTX, 0, OPTAB_WIDEN);
7271 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7272 operands[0], 1, OPTAB_WIDEN);
7273 break;
7274
7275 case GE:
7276 scratch = expand_unop (SImode, one_cmpl_optab, operands[2],
7277 NULL_RTX, 1);
7278 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7279 NULL_RTX, 1, OPTAB_WIDEN);
7280 break;
7281
7282 case GT:
7283 scratch = expand_binop (SImode, ashr_optab, operands[2],
7284 GEN_INT (31), NULL_RTX, 0, OPTAB_WIDEN);
7285 scratch = expand_binop (SImode, sub_optab, scratch, operands[2],
7286 NULL_RTX, 0, OPTAB_WIDEN);
7287 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31), operands[0],
7288 0, OPTAB_WIDEN);
7289 break;
7290
7291 /* LT is handled by generic code. No need for unsigned with 0. */
7292 default:
7293 FAIL;
7294 }
7295 DONE;
7296 }
7297
7298 switch (GET_CODE (operands[1]))
7299 {
7300 case EQ:
7301 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7302 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7303 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], scratch));
595d88b5 7304 break;
7305
7306 case NE:
7307 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7308 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7309 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], scratch));
595d88b5 7310 break;
7311
7312 case LE:
7313 op3 = force_reg (SImode, operands[3]);
7314
7315 scratch = expand_binop (SImode, lshr_optab, operands[2], GEN_INT (31),
7316 NULL_RTX, 1, OPTAB_WIDEN);
7317 scratch2 = expand_binop (SImode, ashr_optab, op3, GEN_INT (31),
7318 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7319 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
595d88b5 7320 op3, operands[2]));
7321 break;
7322
7323 case GE:
7324 op3 = operands[3];
25f905c2 7325 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7326 op3 = force_reg (SImode, op3);
7327 scratch = expand_binop (SImode, ashr_optab, operands[2], GEN_INT (31),
7328 NULL_RTX, 0, OPTAB_WIDEN);
7329 scratch2 = expand_binop (SImode, lshr_optab, op3, GEN_INT (31),
7330 NULL_RTX, 1, OPTAB_WIDEN);
25f905c2 7331 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
595d88b5 7332 operands[2], op3));
7333 break;
7334
7335 case LEU:
7336 op3 = force_reg (SImode, operands[3]);
7337 scratch = force_reg (SImode, const0_rtx);
25f905c2 7338 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
595d88b5 7339 op3, operands[2]));
7340 break;
7341
7342 case GEU:
7343 op3 = operands[3];
25f905c2 7344 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7345 op3 = force_reg (SImode, op3);
7346 scratch = force_reg (SImode, const0_rtx);
25f905c2 7347 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
595d88b5 7348 operands[2], op3));
7349 break;
7350
7351 case LTU:
7352 op3 = operands[3];
25f905c2 7353 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7354 op3 = force_reg (SImode, op3);
7355 scratch = gen_reg_rtx (SImode);
408b7ae5 7356 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], operands[2], op3));
595d88b5 7357 break;
7358
7359 case GTU:
7360 op3 = force_reg (SImode, operands[3]);
7361 scratch = gen_reg_rtx (SImode);
408b7ae5 7362 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], op3, operands[2]));
595d88b5 7363 break;
7364
7365 /* No good sequences for GT, LT. */
7366 default:
7367 FAIL;
7368 }
7369 DONE;
7370}")
7371
74f4459c 7372(define_expand "cstoresf4"
7373 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 7374 (match_operator:SI 1 "expandable_comparison_operator"
74f4459c 7375 [(match_operand:SF 2 "s_register_operand" "")
7376 (match_operand:SF 3 "arm_float_compare_operand" "")]))]
7377 "TARGET_32BIT && TARGET_HARD_FLOAT"
7378 "emit_insn (gen_cstore_cc (operands[0], operands[1],
7379 operands[2], operands[3])); DONE;"
7380)
7381
7382(define_expand "cstoredf4"
7383 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 7384 (match_operator:SI 1 "expandable_comparison_operator"
74f4459c 7385 [(match_operand:DF 2 "s_register_operand" "")
7386 (match_operand:DF 3 "arm_float_compare_operand" "")]))]
d63ed457 7387 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
74f4459c 7388 "emit_insn (gen_cstore_cc (operands[0], operands[1],
7389 operands[2], operands[3])); DONE;"
7390)
7391
74f4459c 7392(define_expand "cstoredi4"
7393 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 7394 (match_operator:SI 1 "expandable_comparison_operator"
b8eae306 7395 [(match_operand:DI 2 "s_register_operand" "")
a8045a4f 7396 (match_operand:DI 3 "cmpdi_operand" "")]))]
7397 "TARGET_32BIT"
7398 "{
f9aa4160 7399 if (!arm_validize_comparison (&operands[1],
7400 &operands[2],
7401 &operands[3]))
7402 FAIL;
7403 emit_insn (gen_cstore_cc (operands[0], operands[1], operands[2],
a8045a4f 7404 operands[3]));
7405 DONE;
7406 }"
74f4459c 7407)
7408
9c08d1fa 7409\f
39b5e676 7410;; Conditional move insns
7411
7412(define_expand "movsicc"
8a18b90c 7413 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 7414 (if_then_else:SI (match_operand 1 "expandable_comparison_operator" "")
aea4c774 7415 (match_operand:SI 2 "arm_not_operand" "")
8a18b90c 7416 (match_operand:SI 3 "arm_not_operand" "")))]
25f905c2 7417 "TARGET_32BIT"
39b5e676 7418 "
215b30b3 7419 {
f9aa4160 7420 enum rtx_code code;
278b301d 7421 rtx ccreg;
7422
f9aa4160 7423 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
7424 &XEXP (operands[1], 1)))
278b301d 7425 FAIL;
f9aa4160 7426
7427 code = GET_CODE (operands[1]);
74f4459c 7428 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
e1b93706 7429 XEXP (operands[1], 1), NULL_RTX);
29bb088d 7430 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7431 }"
7432)
39b5e676 7433
7434(define_expand "movsfcc"
8a18b90c 7435 [(set (match_operand:SF 0 "s_register_operand" "")
4df97ffc 7436 (if_then_else:SF (match_operand 1 "arm_cond_move_operator" "")
8a18b90c 7437 (match_operand:SF 2 "s_register_operand" "")
d86c91f6 7438 (match_operand:SF 3 "s_register_operand" "")))]
19f6bf8d 7439 "TARGET_32BIT && TARGET_HARD_FLOAT"
39b5e676 7440 "
215b30b3 7441 {
7442 enum rtx_code code = GET_CODE (operands[1]);
7443 rtx ccreg;
f082f1c4 7444
f9aa4160 7445 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
7446 &XEXP (operands[1], 1)))
7447 FAIL;
39b5e676 7448
f9aa4160 7449 code = GET_CODE (operands[1]);
74f4459c 7450 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
e1b93706 7451 XEXP (operands[1], 1), NULL_RTX);
29bb088d 7452 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7453 }"
7454)
39b5e676 7455
7456(define_expand "movdfcc"
8a18b90c 7457 [(set (match_operand:DF 0 "s_register_operand" "")
4df97ffc 7458 (if_then_else:DF (match_operand 1 "arm_cond_move_operator" "")
8a18b90c 7459 (match_operand:DF 2 "s_register_operand" "")
d86c91f6 7460 (match_operand:DF 3 "s_register_operand" "")))]
994606f8 7461 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
39b5e676 7462 "
215b30b3 7463 {
7464 enum rtx_code code = GET_CODE (operands[1]);
278b301d 7465 rtx ccreg;
39b5e676 7466
f9aa4160 7467 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
7468 &XEXP (operands[1], 1)))
7469 FAIL;
7470 code = GET_CODE (operands[1]);
74f4459c 7471 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
e1b93706 7472 XEXP (operands[1], 1), NULL_RTX);
29bb088d 7473 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7474 }"
7475)
39b5e676 7476
91cb50d2 7477(define_insn "*cmov<mode>"
7478 [(set (match_operand:SDF 0 "s_register_operand" "=<F_constraint>")
7479 (if_then_else:SDF (match_operator 1 "arm_vsel_comparison_operator"
7480 [(match_operand 2 "cc_register" "") (const_int 0)])
7481 (match_operand:SDF 3 "s_register_operand"
7482 "<F_constraint>")
7483 (match_operand:SDF 4 "s_register_operand"
7484 "<F_constraint>")))]
7485 "TARGET_HARD_FLOAT && TARGET_FPU_ARMV8 <vfp_double_cond>"
7486 "*
7487 {
7488 enum arm_cond_code code = maybe_get_arm_condition_code (operands[1]);
7489 switch (code)
7490 {
7491 case ARM_GE:
7492 case ARM_GT:
7493 case ARM_EQ:
7494 case ARM_VS:
7495 return \"vsel%d1.<V_if_elem>\\t%<V_reg>0, %<V_reg>3, %<V_reg>4\";
7496 case ARM_LT:
7497 case ARM_LE:
7498 case ARM_NE:
7499 case ARM_VC:
7500 return \"vsel%D1.<V_if_elem>\\t%<V_reg>0, %<V_reg>4, %<V_reg>3\";
7501 default:
7502 gcc_unreachable ();
7503 }
7504 return \"\";
7505 }"
7506 [(set_attr "conds" "use")
6664d308 7507 (set_attr "type" "fcsel")]
91cb50d2 7508)
7509
190efb17 7510(define_insn_and_split "*movsicc_insn"
f082f1c4 7511 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
8a18b90c 7512 (if_then_else:SI
8fa3ba89 7513 (match_operator 3 "arm_comparison_operator"
8a18b90c 7514 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 7515 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
7516 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
cffb2a26 7517 "TARGET_ARM"
39b5e676 7518 "@
8a18b90c 7519 mov%D3\\t%0, %2
7520 mvn%D3\\t%0, #%B2
f082f1c4 7521 mov%d3\\t%0, %1
7522 mvn%d3\\t%0, #%B1
190efb17 7523 #
7524 #
7525 #
7526 #"
7527 ; alt4: mov%d3\\t%0, %1\;mov%D3\\t%0, %2
7528 ; alt5: mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
7529 ; alt6: mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
7530 ; alt7: mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
7531 "&& reload_completed"
7532 [(const_int 0)]
7533 {
7534 enum rtx_code rev_code;
3754d046 7535 machine_mode mode;
190efb17 7536 rtx rev_cond;
7537
7538 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
7539 operands[3],
d1f9b275 7540 gen_rtx_SET (operands[0], operands[1])));
190efb17 7541
7542 rev_code = GET_CODE (operands[3]);
7543 mode = GET_MODE (operands[4]);
7544 if (mode == CCFPmode || mode == CCFPEmode)
7545 rev_code = reverse_condition_maybe_unordered (rev_code);
7546 else
7547 rev_code = reverse_condition (rev_code);
7548
7549 rev_cond = gen_rtx_fmt_ee (rev_code,
7550 VOIDmode,
7551 operands[4],
7552 const0_rtx);
7553 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
7554 rev_cond,
d1f9b275 7555 gen_rtx_SET (operands[0], operands[2])));
190efb17 7556 DONE;
7557 }
f082f1c4 7558 [(set_attr "length" "4,4,4,4,8,8,8,8")
d2a518d1 7559 (set_attr "conds" "use")
65f68e55 7560 (set_attr_alternative "type"
7561 [(if_then_else (match_operand 2 "const_int_operand" "")
1aed5204 7562 (const_string "mov_imm")
7563 (const_string "mov_reg"))
7564 (const_string "mvn_imm")
65f68e55 7565 (if_then_else (match_operand 1 "const_int_operand" "")
1aed5204 7566 (const_string "mov_imm")
7567 (const_string "mov_reg"))
7568 (const_string "mvn_imm")
282b4c75 7569 (const_string "multiple")
7570 (const_string "multiple")
7571 (const_string "multiple")
7572 (const_string "multiple")])]
215b30b3 7573)
39b5e676 7574
39b5e676 7575(define_insn "*movsfcc_soft_insn"
f082f1c4 7576 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
8fa3ba89 7577 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
8a18b90c 7578 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 7579 (match_operand:SF 1 "s_register_operand" "0,r")
7580 (match_operand:SF 2 "s_register_operand" "r,0")))]
cffb2a26 7581 "TARGET_ARM && TARGET_SOFT_FLOAT"
f082f1c4 7582 "@
7583 mov%D3\\t%0, %2
7584 mov%d3\\t%0, %1"
d2a518d1 7585 [(set_attr "conds" "use")
1aed5204 7586 (set_attr "type" "mov_reg")]
8fa3ba89 7587)
39b5e676 7588
39b5e676 7589\f
9c08d1fa 7590;; Jump and linkage insns
7591
cffb2a26 7592(define_expand "jump"
9c08d1fa 7593 [(set (pc)
7594 (label_ref (match_operand 0 "" "")))]
cffb2a26 7595 "TARGET_EITHER"
9c08d1fa 7596 ""
cffb2a26 7597)
7598
7599(define_insn "*arm_jump"
7600 [(set (pc)
7601 (label_ref (match_operand 0 "" "")))]
25f905c2 7602 "TARGET_32BIT"
9c08d1fa 7603 "*
0d66636f 7604 {
7605 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7606 {
7607 arm_ccfsm_state += 2;
7608 return \"\";
7609 }
7610 return \"b%?\\t%l0\";
7611 }
7612 "
a6864a24 7613 [(set_attr "predicable" "yes")
7614 (set (attr "length")
7615 (if_then_else
0bf497f5 7616 (and (match_test "TARGET_THUMB2")
a6864a24 7617 (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
7618 (le (minus (match_dup 0) (pc)) (const_int 2048))))
7619 (const_int 2)
1b7da4ac 7620 (const_int 4)))
7621 (set_attr "type" "branch")]
0d66636f 7622)
9c08d1fa 7623
d3373b54 7624(define_expand "call"
7625 [(parallel [(call (match_operand 0 "memory_operand" "")
7626 (match_operand 1 "general_operand" ""))
cffb2a26 7627 (use (match_operand 2 "" ""))
bd5b4116 7628 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 7629 "TARGET_EITHER"
6c4c2133 7630 "
7631 {
bac7fc85 7632 rtx callee, pat;
bbe777ea 7633
bbe777ea 7634 /* In an untyped call, we can get NULL for operand 2. */
7635 if (operands[2] == NULL_RTX)
7636 operands[2] = const0_rtx;
7637
de55252a 7638 /* Decide if we should generate indirect calls by loading the
85c36fd1 7639 32-bit address of the callee into a register before performing the
de55252a 7640 branch and link. */
7641 callee = XEXP (operands[0], 0);
7642 if (GET_CODE (callee) == SYMBOL_REF
7643 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
7644 : !REG_P (callee))
bbe777ea 7645 XEXP (operands[0], 0) = force_reg (Pmode, callee);
bac7fc85 7646
7647 pat = gen_call_internal (operands[0], operands[1], operands[2]);
ca373797 7648 arm_emit_call_insn (pat, XEXP (operands[0], 0), false);
bac7fc85 7649 DONE;
6c4c2133 7650 }"
7651)
d3373b54 7652
bac7fc85 7653(define_expand "call_internal"
7654 [(parallel [(call (match_operand 0 "memory_operand" "")
7655 (match_operand 1 "general_operand" ""))
7656 (use (match_operand 2 "" ""))
7657 (clobber (reg:SI LR_REGNUM))])])
7658
f1039640 7659(define_insn "*call_reg_armv5"
d3373b54 7660 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
cffb2a26 7661 (match_operand 1 "" ""))
7662 (use (match_operand 2 "" ""))
bd5b4116 7663 (clobber (reg:SI LR_REGNUM))]
33ae7c4b 7664 "TARGET_ARM && arm_arch5 && !SIBLING_CALL_P (insn)"
f1039640 7665 "blx%?\\t%0"
7666 [(set_attr "type" "call")]
7667)
7668
7669(define_insn "*call_reg_arm"
7670 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7671 (match_operand 1 "" ""))
7672 (use (match_operand 2 "" ""))
7673 (clobber (reg:SI LR_REGNUM))]
33ae7c4b 7674 "TARGET_ARM && !arm_arch5 && !SIBLING_CALL_P (insn)"
9c08d1fa 7675 "*
5565501b 7676 return output_call (operands);
cffb2a26 7677 "
7678 ;; length is worst case, normally it is only two
7679 [(set_attr "length" "12")
7680 (set_attr "type" "call")]
7681)
9c08d1fa 7682
89504fc1 7683
d3373b54 7684(define_expand "call_value"
e0698af7 7685 [(parallel [(set (match_operand 0 "" "")
7686 (call (match_operand 1 "memory_operand" "")
7687 (match_operand 2 "general_operand" "")))
cffb2a26 7688 (use (match_operand 3 "" ""))
bd5b4116 7689 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 7690 "TARGET_EITHER"
6c4c2133 7691 "
7692 {
bac7fc85 7693 rtx pat, callee;
bbe777ea 7694
7695 /* In an untyped call, we can get NULL for operand 2. */
7696 if (operands[3] == 0)
7697 operands[3] = const0_rtx;
7698
de55252a 7699 /* Decide if we should generate indirect calls by loading the
7700 32-bit address of the callee into a register before performing the
7701 branch and link. */
7702 callee = XEXP (operands[1], 0);
7703 if (GET_CODE (callee) == SYMBOL_REF
7704 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
7705 : !REG_P (callee))
78fe751b 7706 XEXP (operands[1], 0) = force_reg (Pmode, callee);
bac7fc85 7707
7708 pat = gen_call_value_internal (operands[0], operands[1],
7709 operands[2], operands[3]);
ca373797 7710 arm_emit_call_insn (pat, XEXP (operands[1], 0), false);
bac7fc85 7711 DONE;
6c4c2133 7712 }"
7713)
d3373b54 7714
bac7fc85 7715(define_expand "call_value_internal"
7716 [(parallel [(set (match_operand 0 "" "")
7717 (call (match_operand 1 "memory_operand" "")
7718 (match_operand 2 "general_operand" "")))
7719 (use (match_operand 3 "" ""))
7720 (clobber (reg:SI LR_REGNUM))])])
7721
f1039640 7722(define_insn "*call_value_reg_armv5"
27ed6835 7723 [(set (match_operand 0 "" "")
755eb2b4 7724 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
cffb2a26 7725 (match_operand 2 "" "")))
bbe777ea 7726 (use (match_operand 3 "" ""))
bd5b4116 7727 (clobber (reg:SI LR_REGNUM))]
33ae7c4b 7728 "TARGET_ARM && arm_arch5 && !SIBLING_CALL_P (insn)"
f1039640 7729 "blx%?\\t%1"
7730 [(set_attr "type" "call")]
7731)
7732
7733(define_insn "*call_value_reg_arm"
7734 [(set (match_operand 0 "" "")
7735 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7736 (match_operand 2 "" "")))
7737 (use (match_operand 3 "" ""))
7738 (clobber (reg:SI LR_REGNUM))]
33ae7c4b 7739 "TARGET_ARM && !arm_arch5 && !SIBLING_CALL_P (insn)"
9c08d1fa 7740 "*
215b30b3 7741 return output_call (&operands[1]);
cffb2a26 7742 "
7743 [(set_attr "length" "12")
7744 (set_attr "type" "call")]
7745)
9c08d1fa 7746
9c08d1fa 7747;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
7748;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
7749
f7fbdd4a 7750(define_insn "*call_symbol"
27ed6835 7751 [(call (mem:SI (match_operand:SI 0 "" ""))
cffb2a26 7752 (match_operand 1 "" ""))
bbe777ea 7753 (use (match_operand 2 "" ""))
bd5b4116 7754 (clobber (reg:SI LR_REGNUM))]
d68c2c10 7755 "TARGET_32BIT
33ae7c4b 7756 && !SIBLING_CALL_P (insn)
cffb2a26 7757 && (GET_CODE (operands[0]) == SYMBOL_REF)
de55252a 7758 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
6ebaa29d 7759 "*
7760 {
95f1e0d1 7761 rtx op = operands[0];
7762
7763 /* Switch mode now when possible. */
7764 if (SYMBOL_REF_DECL (op) && !TREE_PUBLIC (SYMBOL_REF_DECL (op))
7765 && arm_arch5 && arm_change_mode_p (SYMBOL_REF_DECL (op)))
7766 return NEED_PLT_RELOC ? \"blx%?\\t%a0(PLT)\" : \"blx%?\\t(%a0)\";
7767
55c1e470 7768 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
6ebaa29d 7769 }"
cffb2a26 7770 [(set_attr "type" "call")]
7771)
9c08d1fa 7772
f7fbdd4a 7773(define_insn "*call_value_symbol"
ccd90aaa 7774 [(set (match_operand 0 "" "")
27ed6835 7775 (call (mem:SI (match_operand:SI 1 "" ""))
dd6d7504 7776 (match_operand:SI 2 "" "")))
bbe777ea 7777 (use (match_operand 3 "" ""))
bd5b4116 7778 (clobber (reg:SI LR_REGNUM))]
d68c2c10 7779 "TARGET_32BIT
33ae7c4b 7780 && !SIBLING_CALL_P (insn)
cffb2a26 7781 && (GET_CODE (operands[1]) == SYMBOL_REF)
de55252a 7782 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
6ebaa29d 7783 "*
7784 {
95f1e0d1 7785 rtx op = operands[1];
7786
7787 /* Switch mode now when possible. */
7788 if (SYMBOL_REF_DECL (op) && !TREE_PUBLIC (SYMBOL_REF_DECL (op))
7789 && arm_arch5 && arm_change_mode_p (SYMBOL_REF_DECL (op)))
3f6b66fa 7790 return NEED_PLT_RELOC ? \"blx%?\\t%a1(PLT)\" : \"blx%?\\t(%a1)\";
95f1e0d1 7791
55c1e470 7792 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
6ebaa29d 7793 }"
cffb2a26 7794 [(set_attr "type" "call")]
7795)
7796
ca373797 7797(define_expand "sibcall_internal"
7798 [(parallel [(call (match_operand 0 "memory_operand" "")
7799 (match_operand 1 "general_operand" ""))
7800 (return)
7801 (use (match_operand 2 "" ""))])])
7802
1c494086 7803;; We may also be able to do sibcalls for Thumb, but it's much harder...
7804(define_expand "sibcall"
7805 [(parallel [(call (match_operand 0 "memory_operand" "")
7806 (match_operand 1 "general_operand" ""))
2ba80634 7807 (return)
7808 (use (match_operand 2 "" ""))])]
d68c2c10 7809 "TARGET_32BIT"
1c494086 7810 "
7811 {
ca373797 7812 rtx pat;
7813
3112c3f7 7814 if ((!REG_P (XEXP (operands[0], 0))
7815 && GET_CODE (XEXP (operands[0], 0)) != SYMBOL_REF)
7816 || (GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
7817 && arm_is_long_call_p (SYMBOL_REF_DECL (XEXP (operands[0], 0)))))
33ae7c4b 7818 XEXP (operands[0], 0) = force_reg (SImode, XEXP (operands[0], 0));
7819
1c494086 7820 if (operands[2] == NULL_RTX)
7821 operands[2] = const0_rtx;
ca373797 7822
7823 pat = gen_sibcall_internal (operands[0], operands[1], operands[2]);
7824 arm_emit_call_insn (pat, operands[0], true);
7825 DONE;
1c494086 7826 }"
7827)
7828
ca373797 7829(define_expand "sibcall_value_internal"
7830 [(parallel [(set (match_operand 0 "" "")
7831 (call (match_operand 1 "memory_operand" "")
7832 (match_operand 2 "general_operand" "")))
7833 (return)
7834 (use (match_operand 3 "" ""))])])
7835
1c494086 7836(define_expand "sibcall_value"
ccd90aaa 7837 [(parallel [(set (match_operand 0 "" "")
1c494086 7838 (call (match_operand 1 "memory_operand" "")
7839 (match_operand 2 "general_operand" "")))
2ba80634 7840 (return)
7841 (use (match_operand 3 "" ""))])]
d68c2c10 7842 "TARGET_32BIT"
1c494086 7843 "
7844 {
ca373797 7845 rtx pat;
7846
3112c3f7 7847 if ((!REG_P (XEXP (operands[1], 0))
7848 && GET_CODE (XEXP (operands[1], 0)) != SYMBOL_REF)
7849 || (GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
7850 && arm_is_long_call_p (SYMBOL_REF_DECL (XEXP (operands[1], 0)))))
33ae7c4b 7851 XEXP (operands[1], 0) = force_reg (SImode, XEXP (operands[1], 0));
7852
1c494086 7853 if (operands[3] == NULL_RTX)
7854 operands[3] = const0_rtx;
ca373797 7855
7856 pat = gen_sibcall_value_internal (operands[0], operands[1],
7857 operands[2], operands[3]);
7858 arm_emit_call_insn (pat, operands[1], true);
7859 DONE;
1c494086 7860 }"
7861)
7862
7863(define_insn "*sibcall_insn"
84ce8e5c 7864 [(call (mem:SI (match_operand:SI 0 "call_insn_operand" "Cs, US"))
1c494086 7865 (match_operand 1 "" ""))
2ba80634 7866 (return)
7867 (use (match_operand 2 "" ""))]
33ae7c4b 7868 "TARGET_32BIT && SIBLING_CALL_P (insn)"
1c494086 7869 "*
33ae7c4b 7870 if (which_alternative == 1)
7871 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
7872 else
7873 {
7874 if (arm_arch5 || arm_arch4t)
947d113e 7875 return \"bx%?\\t%0\\t%@ indirect register sibling call\";
33ae7c4b 7876 else
7877 return \"mov%?\\t%|pc, %0\\t%@ indirect register sibling call\";
7878 }
1c494086 7879 "
7880 [(set_attr "type" "call")]
7881)
7882
7883(define_insn "*sibcall_value_insn"
84ce8e5c 7884 [(set (match_operand 0 "" "")
7885 (call (mem:SI (match_operand:SI 1 "call_insn_operand" "Cs,US"))
1c494086 7886 (match_operand 2 "" "")))
2ba80634 7887 (return)
7888 (use (match_operand 3 "" ""))]
33ae7c4b 7889 "TARGET_32BIT && SIBLING_CALL_P (insn)"
1c494086 7890 "*
33ae7c4b 7891 if (which_alternative == 1)
7892 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
7893 else
7894 {
7895 if (arm_arch5 || arm_arch4t)
84ce8e5c 7896 return \"bx%?\\t%1\";
33ae7c4b 7897 else
7898 return \"mov%?\\t%|pc, %1\\t@ indirect sibling call \";
7899 }
1c494086 7900 "
7901 [(set_attr "type" "call")]
7902)
7903
0686440e 7904(define_expand "<return_str>return"
9b23f0a7 7905 [(RETURNS)]
8cba51a5 7906 "(TARGET_ARM || (TARGET_THUMB2
7907 && ARM_FUNC_TYPE (arm_current_func_type ()) == ARM_FT_NORMAL
7908 && !IS_STACKALIGN (arm_current_func_type ())))
0686440e 7909 <return_cond_false>"
8cba51a5 7910 "
7911 {
7912 if (TARGET_THUMB2)
7913 {
0686440e 7914 thumb2_expand_return (<return_simple_p>);
8cba51a5 7915 DONE;
7916 }
7917 }
7918 "
7919)
d68c2c10 7920
9c08d1fa 7921;; Often the return insn will be the same as loading from memory, so set attr
d68c2c10 7922(define_insn "*arm_return"
9c08d1fa 7923 [(return)]
cffb2a26 7924 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
9c08d1fa 7925 "*
9c08d1fa 7926 {
cffb2a26 7927 if (arm_ccfsm_state == 2)
7928 {
7929 arm_ccfsm_state += 2;
7930 return \"\";
7931 }
e2549f81 7932 return output_return_instruction (const_true_rtx, true, false, false);
cffb2a26 7933 }"
a2cd141b 7934 [(set_attr "type" "load1")
755eb2b4 7935 (set_attr "length" "12")
0d66636f 7936 (set_attr "predicable" "yes")]
cffb2a26 7937)
9c08d1fa 7938
0686440e 7939(define_insn "*cond_<return_str>return"
9c08d1fa 7940 [(set (pc)
8fa3ba89 7941 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 7942 [(match_operand 1 "cc_register" "") (const_int 0)])
9b23f0a7 7943 (RETURNS)
9c08d1fa 7944 (pc)))]
0686440e 7945 "TARGET_ARM <return_cond_true>"
9c08d1fa 7946 "*
8fa3ba89 7947 {
7948 if (arm_ccfsm_state == 2)
7949 {
7950 arm_ccfsm_state += 2;
7951 return \"\";
7952 }
0686440e 7953 return output_return_instruction (operands[0], true, false,
7954 <return_simple_p>);
8fa3ba89 7955 }"
7956 [(set_attr "conds" "use")
755eb2b4 7957 (set_attr "length" "12")
a2cd141b 7958 (set_attr "type" "load1")]
8fa3ba89 7959)
9c08d1fa 7960
0686440e 7961(define_insn "*cond_<return_str>return_inverted"
9c08d1fa 7962 [(set (pc)
8fa3ba89 7963 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 7964 [(match_operand 1 "cc_register" "") (const_int 0)])
9c08d1fa 7965 (pc)
9b23f0a7 7966 (RETURNS)))]
0686440e 7967 "TARGET_ARM <return_cond_true>"
9c08d1fa 7968 "*
8fa3ba89 7969 {
7970 if (arm_ccfsm_state == 2)
7971 {
7972 arm_ccfsm_state += 2;
7973 return \"\";
7974 }
0686440e 7975 return output_return_instruction (operands[0], true, true,
7976 <return_simple_p>);
8fa3ba89 7977 }"
7978 [(set_attr "conds" "use")
37a1317b 7979 (set_attr "length" "12")
a2cd141b 7980 (set_attr "type" "load1")]
8fa3ba89 7981)
9c08d1fa 7982
e2549f81 7983(define_insn "*arm_simple_return"
7984 [(simple_return)]
7985 "TARGET_ARM"
7986 "*
7987 {
7988 if (arm_ccfsm_state == 2)
7989 {
7990 arm_ccfsm_state += 2;
7991 return \"\";
7992 }
7993 return output_return_instruction (const_true_rtx, true, false, true);
7994 }"
7995 [(set_attr "type" "branch")
7996 (set_attr "length" "4")
7997 (set_attr "predicable" "yes")]
7998)
7999
68121397 8000;; Generate a sequence of instructions to determine if the processor is
8001;; in 26-bit or 32-bit mode, and return the appropriate return address
8002;; mask.
8003
8004(define_expand "return_addr_mask"
8005 [(set (match_dup 1)
8006 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8007 (const_int 0)))
8008 (set (match_operand:SI 0 "s_register_operand" "")
8009 (if_then_else:SI (eq (match_dup 1) (const_int 0))
8010 (const_int -1)
8011 (const_int 67108860)))] ; 0x03fffffc
8012 "TARGET_ARM"
8013 "
62eddbd4 8014 operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
68121397 8015 ")
8016
8017(define_insn "*check_arch2"
8018 [(set (match_operand:CC_NOOV 0 "cc_register" "")
8019 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8020 (const_int 0)))]
8021 "TARGET_ARM"
8022 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
8023 [(set_attr "length" "8")
1b7da4ac 8024 (set_attr "conds" "set")
8025 (set_attr "type" "multiple")]
68121397 8026)
8027
9c08d1fa 8028;; Call subroutine returning any type.
8029
8030(define_expand "untyped_call"
8031 [(parallel [(call (match_operand 0 "" "")
8032 (const_int 0))
8033 (match_operand 1 "" "")
8034 (match_operand 2 "" "")])]
ccd90aaa 8035 "TARGET_EITHER"
9c08d1fa 8036 "
215b30b3 8037 {
8038 int i;
ccd90aaa 8039 rtx par = gen_rtx_PARALLEL (VOIDmode,
8040 rtvec_alloc (XVECLEN (operands[2], 0)));
8041 rtx addr = gen_reg_rtx (Pmode);
8042 rtx mem;
8043 int size = 0;
9c08d1fa 8044
ccd90aaa 8045 emit_move_insn (addr, XEXP (operands[1], 0));
8046 mem = change_address (operands[1], BLKmode, addr);
9c08d1fa 8047
215b30b3 8048 for (i = 0; i < XVECLEN (operands[2], 0); i++)
8049 {
ccd90aaa 8050 rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
9c08d1fa 8051
ccd90aaa 8052 /* Default code only uses r0 as a return value, but we could
8053 be using anything up to 4 registers. */
8054 if (REGNO (src) == R0_REGNUM)
8055 src = gen_rtx_REG (TImode, R0_REGNUM);
8056
8057 XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
8058 GEN_INT (size));
8059 size += GET_MODE_SIZE (GET_MODE (src));
8060 }
8061
7f265a08 8062 emit_call_insn (gen_call_value (par, operands[0], const0_rtx, NULL));
ccd90aaa 8063
8064 size = 0;
8065
8066 for (i = 0; i < XVECLEN (par, 0); i++)
8067 {
8068 HOST_WIDE_INT offset = 0;
8069 rtx reg = XEXP (XVECEXP (par, 0, i), 0);
8070
8071 if (size != 0)
29c05e22 8072 emit_move_insn (addr, plus_constant (Pmode, addr, size));
ccd90aaa 8073
8074 mem = change_address (mem, GET_MODE (reg), NULL);
8075 if (REGNO (reg) == R0_REGNUM)
8076 {
8077 /* On thumb we have to use a write-back instruction. */
320ea44d 8078 emit_insn (arm_gen_store_multiple (arm_regs_in_sequence, 4, addr,
8079 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
ccd90aaa 8080 size = TARGET_ARM ? 16 : 0;
8081 }
8082 else
8083 {
8084 emit_move_insn (mem, reg);
8085 size = GET_MODE_SIZE (GET_MODE (reg));
8086 }
215b30b3 8087 }
9c08d1fa 8088
215b30b3 8089 /* The optimizer does not know that the call sets the function value
8090 registers we stored in the result block. We avoid problems by
8091 claiming that all hard registers are used and clobbered at this
8092 point. */
8093 emit_insn (gen_blockage ());
8094
8095 DONE;
8096 }"
8097)
9c08d1fa 8098
ccd90aaa 8099(define_expand "untyped_return"
8100 [(match_operand:BLK 0 "memory_operand" "")
8101 (match_operand 1 "" "")]
8102 "TARGET_EITHER"
8103 "
8104 {
8105 int i;
8106 rtx addr = gen_reg_rtx (Pmode);
8107 rtx mem;
8108 int size = 0;
8109
8110 emit_move_insn (addr, XEXP (operands[0], 0));
8111 mem = change_address (operands[0], BLKmode, addr);
8112
8113 for (i = 0; i < XVECLEN (operands[1], 0); i++)
8114 {
8115 HOST_WIDE_INT offset = 0;
8116 rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
8117
8118 if (size != 0)
29c05e22 8119 emit_move_insn (addr, plus_constant (Pmode, addr, size));
ccd90aaa 8120
8121 mem = change_address (mem, GET_MODE (reg), NULL);
8122 if (REGNO (reg) == R0_REGNUM)
8123 {
8124 /* On thumb we have to use a write-back instruction. */
320ea44d 8125 emit_insn (arm_gen_load_multiple (arm_regs_in_sequence, 4, addr,
8126 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
ccd90aaa 8127 size = TARGET_ARM ? 16 : 0;
8128 }
8129 else
8130 {
8131 emit_move_insn (reg, mem);
8132 size = GET_MODE_SIZE (GET_MODE (reg));
8133 }
8134 }
8135
8136 /* Emit USE insns before the return. */
8137 for (i = 0; i < XVECLEN (operands[1], 0); i++)
18b42941 8138 emit_use (SET_DEST (XVECEXP (operands[1], 0, i)));
ccd90aaa 8139
8140 /* Construct the return. */
8141 expand_naked_return ();
8142
8143 DONE;
8144 }"
8145)
8146
9c08d1fa 8147;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
8148;; all of memory. This blocks insns from being moved across this point.
8149
8150(define_insn "blockage"
e1159bbe 8151 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
cffb2a26 8152 "TARGET_EITHER"
9c08d1fa 8153 ""
cffb2a26 8154 [(set_attr "length" "0")
8155 (set_attr "type" "block")]
8156)
9c08d1fa 8157
706dca65 8158(define_insn "probe_stack"
f8570abe 8159 [(set (match_operand:SI 0 "memory_operand" "=m")
8160 (unspec:SI [(const_int 0)] UNSPEC_PROBE_STACK))]
706dca65 8161 "TARGET_32BIT"
154ae8e6 8162 "str%?\\tr0, %0"
706dca65 8163 [(set_attr "type" "store1")
8164 (set_attr "predicable" "yes")]
8165)
8166
8167(define_insn "probe_stack_range"
8168 [(set (match_operand:SI 0 "register_operand" "=r")
8169 (unspec_volatile:SI [(match_operand:SI 1 "register_operand" "0")
8170 (match_operand:SI 2 "register_operand" "r")]
dd8aabc9 8171 VUNSPEC_PROBE_STACK_RANGE))]
706dca65 8172 "TARGET_32BIT"
8173{
8174 return output_probe_stack_range (operands[0], operands[2]);
8175}
8176 [(set_attr "type" "multiple")
8177 (set_attr "conds" "clob")]
8178)
8179
f7fbdd4a 8180(define_expand "casesi"
8181 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
aea4c774 8182 (match_operand:SI 1 "const_int_operand" "") ; lower bound
8183 (match_operand:SI 2 "const_int_operand" "") ; total range
f7fbdd4a 8184 (match_operand:SI 3 "" "") ; table label
8185 (match_operand:SI 4 "" "")] ; Out of range label
e6ac8414 8186 "TARGET_32BIT || optimize_size || flag_pic"
f7fbdd4a 8187 "
215b30b3 8188 {
e6ac8414 8189 enum insn_code code;
215b30b3 8190 if (operands[1] != const0_rtx)
8191 {
e6ac8414 8192 rtx reg = gen_reg_rtx (SImode);
f7fbdd4a 8193
215b30b3 8194 emit_insn (gen_addsi3 (reg, operands[0],
d022fa24 8195 gen_int_mode (-INTVAL (operands[1]),
8196 SImode)));
215b30b3 8197 operands[0] = reg;
8198 }
9c08d1fa 8199
25f905c2 8200 if (TARGET_ARM)
e6ac8414 8201 code = CODE_FOR_arm_casesi_internal;
3db2019b 8202 else if (TARGET_THUMB1)
e6ac8414 8203 code = CODE_FOR_thumb1_casesi_internal_pic;
25f905c2 8204 else if (flag_pic)
e6ac8414 8205 code = CODE_FOR_thumb2_casesi_internal_pic;
25f905c2 8206 else
e6ac8414 8207 code = CODE_FOR_thumb2_casesi_internal;
8208
8209 if (!insn_data[(int) code].operand[1].predicate(operands[2], SImode))
8210 operands[2] = force_reg (SImode, operands[2]);
8211
8212 emit_jump_insn (GEN_FCN ((int) code) (operands[0], operands[2],
8213 operands[3], operands[4]));
215b30b3 8214 DONE;
8215 }"
8216)
f7fbdd4a 8217
f082f1c4 8218;; The USE in this pattern is needed to tell flow analysis that this is
8219;; a CASESI insn. It has no other purpose.
25f905c2 8220(define_insn "arm_casesi_internal"
f082f1c4 8221 [(parallel [(set (pc)
8222 (if_then_else
8223 (leu (match_operand:SI 0 "s_register_operand" "r")
8224 (match_operand:SI 1 "arm_rhs_operand" "rI"))
8225 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
8226 (label_ref (match_operand 2 "" ""))))
8227 (label_ref (match_operand 3 "" ""))))
bd5b4116 8228 (clobber (reg:CC CC_REGNUM))
f082f1c4 8229 (use (label_ref (match_dup 2)))])]
cffb2a26 8230 "TARGET_ARM"
f7fbdd4a 8231 "*
0d66636f 8232 if (flag_pic)
8233 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
8234 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
8235 "
8236 [(set_attr "conds" "clob")
1b7da4ac 8237 (set_attr "length" "12")
8238 (set_attr "type" "multiple")]
0d66636f 8239)
9c08d1fa 8240
cffb2a26 8241(define_expand "indirect_jump"
9c08d1fa 8242 [(set (pc)
cffb2a26 8243 (match_operand:SI 0 "s_register_operand" ""))]
8244 "TARGET_EITHER"
25f905c2 8245 "
8246 /* Thumb-2 doesn't have mov pc, reg. Explicitly set the low bit of the
8247 address and use bx. */
8248 if (TARGET_THUMB2)
8249 {
8250 rtx tmp;
8251 tmp = gen_reg_rtx (SImode);
8252 emit_insn (gen_iorsi3 (tmp, operands[0], GEN_INT(1)));
8253 operands[0] = tmp;
8254 }
8255 "
cffb2a26 8256)
8257
f1039640 8258;; NB Never uses BX.
cffb2a26 8259(define_insn "*arm_indirect_jump"
8260 [(set (pc)
8261 (match_operand:SI 0 "s_register_operand" "r"))]
8262 "TARGET_ARM"
8263 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
1b7da4ac 8264 [(set_attr "predicable" "yes")
8265 (set_attr "type" "branch")]
cffb2a26 8266)
9c08d1fa 8267
f7fbdd4a 8268(define_insn "*load_indirect_jump"
9c08d1fa 8269 [(set (pc)
8270 (match_operand:SI 0 "memory_operand" "m"))]
cffb2a26 8271 "TARGET_ARM"
8272 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
a2cd141b 8273 [(set_attr "type" "load1")
61a2d04c 8274 (set_attr "pool_range" "4096")
8275 (set_attr "neg_pool_range" "4084")
0d66636f 8276 (set_attr "predicable" "yes")]
cffb2a26 8277)
8278
9c08d1fa 8279\f
8280;; Misc insns
8281
8282(define_insn "nop"
8283 [(const_int 0)]
cffb2a26 8284 "TARGET_EITHER"
3ef90e77 8285 "nop"
cffb2a26 8286 [(set (attr "length")
8287 (if_then_else (eq_attr "is_thumb" "yes")
8288 (const_int 2)
1b7da4ac 8289 (const_int 4)))
8290 (set_attr "type" "mov_reg")]
cffb2a26 8291)
8292
ad9d4399 8293(define_insn "trap"
8294 [(trap_if (const_int 1) (const_int 0))]
8295 ""
8296 "*
8297 if (TARGET_ARM)
8298 return \".inst\\t0xe7f000f0\";
8299 else
8300 return \".inst\\t0xdeff\";
8301 "
8302 [(set (attr "length")
8303 (if_then_else (eq_attr "is_thumb" "yes")
8304 (const_int 2)
8305 (const_int 4)))
8306 (set_attr "type" "trap")
8307 (set_attr "conds" "unconditional")]
8308)
8309
9c08d1fa 8310\f
8311;; Patterns to allow combination of arithmetic, cond code and shifts
8312
0abea32c 8313(define_insn "*<arith_shift_insn>_multsi"
8314 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9b23f0a7 8315 (SHIFTABLE_OPS:SI
0abea32c 8316 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
8317 (match_operand:SI 3 "power_of_two_operand" ""))
8318 (match_operand:SI 1 "s_register_operand" "rk,<t2_binop0>")))]
d5d4dc8d 8319 "TARGET_32BIT"
0abea32c 8320 "<arith_shift_insn>%?\\t%0, %1, %2, lsl %b3"
8321 [(set_attr "predicable" "yes")
8322 (set_attr "predicable_short_it" "no")
753d9835 8323 (set_attr "shift" "2")
0abea32c 8324 (set_attr "arch" "a,t2")
8325 (set_attr "type" "alu_shift_imm")])
8326
8327(define_insn "*<arith_shift_insn>_shiftsi"
8328 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9b23f0a7 8329 (SHIFTABLE_OPS:SI
0abea32c 8330 (match_operator:SI 2 "shift_nomul_operator"
8331 [(match_operand:SI 3 "s_register_operand" "r,r,r")
8332 (match_operand:SI 4 "shift_amount_operand" "M,M,r")])
8333 (match_operand:SI 1 "s_register_operand" "rk,<t2_binop0>,rk")))]
a021b821 8334 "TARGET_32BIT && GET_CODE (operands[2]) != MULT"
0abea32c 8335 "<arith_shift_insn>%?\\t%0, %1, %3%S2"
344495ea 8336 [(set_attr "predicable" "yes")
74ef923b 8337 (set_attr "predicable_short_it" "no")
753d9835 8338 (set_attr "shift" "3")
0abea32c 8339 (set_attr "arch" "a,t2,a")
8340 (set_attr "type" "alu_shift_imm,alu_shift_imm,alu_shift_reg")])
9c08d1fa 8341
d7863cfe 8342(define_split
8343 [(set (match_operand:SI 0 "s_register_operand" "")
8344 (match_operator:SI 1 "shiftable_operator"
8345 [(match_operator:SI 2 "shiftable_operator"
8346 [(match_operator:SI 3 "shift_operator"
8347 [(match_operand:SI 4 "s_register_operand" "")
8348 (match_operand:SI 5 "reg_or_int_operand" "")])
8349 (match_operand:SI 6 "s_register_operand" "")])
8350 (match_operand:SI 7 "arm_rhs_operand" "")]))
8351 (clobber (match_operand:SI 8 "s_register_operand" ""))]
d5d4dc8d 8352 "TARGET_32BIT"
d7863cfe 8353 [(set (match_dup 8)
8354 (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8355 (match_dup 6)]))
8356 (set (match_dup 0)
8357 (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
8358 "")
8359
f7fbdd4a 8360(define_insn "*arith_shiftsi_compare0"
bd5b4116 8361 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 8362 (compare:CC_NOOV
8363 (match_operator:SI 1 "shiftable_operator"
8364 [(match_operator:SI 3 "shift_operator"
8365 [(match_operand:SI 4 "s_register_operand" "r,r")
8366 (match_operand:SI 5 "shift_amount_operand" "M,r")])
8367 (match_operand:SI 2 "s_register_operand" "r,r")])
8368 (const_int 0)))
8369 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 8370 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8371 (match_dup 2)]))]
d5d4dc8d 8372 "TARGET_32BIT"
3ef90e77 8373 "%i1s%?\\t%0, %2, %4%S3"
344495ea 8374 [(set_attr "conds" "set")
331beb1a 8375 (set_attr "shift" "4")
d5d4dc8d 8376 (set_attr "arch" "32,a")
d82e788e 8377 (set_attr "type" "alus_shift_imm,alus_shift_reg")])
9c08d1fa 8378
f7fbdd4a 8379(define_insn "*arith_shiftsi_compare0_scratch"
bd5b4116 8380 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 8381 (compare:CC_NOOV
8382 (match_operator:SI 1 "shiftable_operator"
8383 [(match_operator:SI 3 "shift_operator"
8384 [(match_operand:SI 4 "s_register_operand" "r,r")
8385 (match_operand:SI 5 "shift_amount_operand" "M,r")])
8386 (match_operand:SI 2 "s_register_operand" "r,r")])
8387 (const_int 0)))
8388 (clobber (match_scratch:SI 0 "=r,r"))]
8389 "TARGET_32BIT"
3ef90e77 8390 "%i1s%?\\t%0, %2, %4%S3"
344495ea 8391 [(set_attr "conds" "set")
331beb1a 8392 (set_attr "shift" "4")
d5d4dc8d 8393 (set_attr "arch" "32,a")
d82e788e 8394 (set_attr "type" "alus_shift_imm,alus_shift_reg")])
9c08d1fa 8395
f7fbdd4a 8396(define_insn "*sub_shiftsi"
d5d4dc8d 8397 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8398 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
9c08d1fa 8399 (match_operator:SI 2 "shift_operator"
d5d4dc8d 8400 [(match_operand:SI 3 "s_register_operand" "r,r")
8401 (match_operand:SI 4 "shift_amount_operand" "M,r")])))]
8402 "TARGET_32BIT"
6c4c2133 8403 "sub%?\\t%0, %1, %3%S2"
344495ea 8404 [(set_attr "predicable" "yes")
331beb1a 8405 (set_attr "shift" "3")
d5d4dc8d 8406 (set_attr "arch" "32,a")
d82e788e 8407 (set_attr "type" "alus_shift_imm,alus_shift_reg")])
9c08d1fa 8408
f7fbdd4a 8409(define_insn "*sub_shiftsi_compare0"
bd5b4116 8410 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 8411 (compare:CC_NOOV
d82e788e 8412 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
40dbec34 8413 (match_operator:SI 2 "shift_operator"
d82e788e 8414 [(match_operand:SI 3 "s_register_operand" "r,r,r")
8415 (match_operand:SI 4 "shift_amount_operand" "M,r,M")]))
40dbec34 8416 (const_int 0)))
d82e788e 8417 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
d5d4dc8d 8418 (minus:SI (match_dup 1)
8419 (match_op_dup 2 [(match_dup 3) (match_dup 4)])))]
8420 "TARGET_32BIT"
3ef90e77 8421 "subs%?\\t%0, %1, %3%S2"
344495ea 8422 [(set_attr "conds" "set")
a2cd141b 8423 (set_attr "shift" "3")
d82e788e 8424 (set_attr "arch" "32,a,a")
8425 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
9c08d1fa 8426
f7fbdd4a 8427(define_insn "*sub_shiftsi_compare0_scratch"
bd5b4116 8428 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 8429 (compare:CC_NOOV
d82e788e 8430 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
40dbec34 8431 (match_operator:SI 2 "shift_operator"
d82e788e 8432 [(match_operand:SI 3 "s_register_operand" "r,r,r")
8433 (match_operand:SI 4 "shift_amount_operand" "M,r,M")]))
40dbec34 8434 (const_int 0)))
d82e788e 8435 (clobber (match_scratch:SI 0 "=r,r,r"))]
d5d4dc8d 8436 "TARGET_32BIT"
3ef90e77 8437 "subs%?\\t%0, %1, %3%S2"
344495ea 8438 [(set_attr "conds" "set")
a2cd141b 8439 (set_attr "shift" "3")
d82e788e 8440 (set_attr "arch" "32,a,a")
8441 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
9c08d1fa 8442\f
8443
190efb17 8444(define_insn_and_split "*and_scc"
9c08d1fa 8445 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 8446 (and:SI (match_operator:SI 1 "arm_comparison_operator"
190efb17 8447 [(match_operand 2 "cc_register" "") (const_int 0)])
8448 (match_operand:SI 3 "s_register_operand" "r")))]
cffb2a26 8449 "TARGET_ARM"
190efb17 8450 "#" ; "mov%D1\\t%0, #0\;and%d1\\t%0, %3, #1"
8451 "&& reload_completed"
8452 [(cond_exec (match_dup 5) (set (match_dup 0) (const_int 0)))
8453 (cond_exec (match_dup 4) (set (match_dup 0)
8454 (and:SI (match_dup 3) (const_int 1))))]
8455 {
3754d046 8456 machine_mode mode = GET_MODE (operands[2]);
190efb17 8457 enum rtx_code rc = GET_CODE (operands[1]);
8458
8459 /* Note that operands[4] is the same as operands[1],
8460 but with VOIDmode as the result. */
8461 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
8462 if (mode == CCFPmode || mode == CCFPEmode)
8463 rc = reverse_condition_maybe_unordered (rc);
8464 else
8465 rc = reverse_condition (rc);
8466 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
8467 }
8fa3ba89 8468 [(set_attr "conds" "use")
1b7da4ac 8469 (set_attr "type" "multiple")
8fa3ba89 8470 (set_attr "length" "8")]
8471)
9c08d1fa 8472
190efb17 8473(define_insn_and_split "*ior_scc"
9c08d1fa 8474 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
190efb17 8475 (ior:SI (match_operator:SI 1 "arm_comparison_operator"
8476 [(match_operand 2 "cc_register" "") (const_int 0)])
8477 (match_operand:SI 3 "s_register_operand" "0,?r")))]
cffb2a26 8478 "TARGET_ARM"
e2348bcb 8479 "@
190efb17 8480 orr%d1\\t%0, %3, #1
8481 #"
8482 "&& reload_completed
8483 && REGNO (operands [0]) != REGNO (operands[3])"
8484 ;; && which_alternative == 1
8485 ; mov%D1\\t%0, %3\;orr%d1\\t%0, %3, #1
8486 [(cond_exec (match_dup 5) (set (match_dup 0) (match_dup 3)))
8487 (cond_exec (match_dup 4) (set (match_dup 0)
8488 (ior:SI (match_dup 3) (const_int 1))))]
8489 {
3754d046 8490 machine_mode mode = GET_MODE (operands[2]);
190efb17 8491 enum rtx_code rc = GET_CODE (operands[1]);
8492
8493 /* Note that operands[4] is the same as operands[1],
8494 but with VOIDmode as the result. */
8495 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
8496 if (mode == CCFPmode || mode == CCFPEmode)
8497 rc = reverse_condition_maybe_unordered (rc);
8498 else
8499 rc = reverse_condition (rc);
8500 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
8501 }
8fa3ba89 8502 [(set_attr "conds" "use")
1b7da4ac 8503 (set_attr "length" "4,8")
8504 (set_attr "type" "logic_imm,multiple")]
8fa3ba89 8505)
9c08d1fa 8506
2df9477b 8507; A series of splitters for the compare_scc pattern below. Note that
8508; order is important.
8509(define_split
8510 [(set (match_operand:SI 0 "s_register_operand" "")
8511 (lt:SI (match_operand:SI 1 "s_register_operand" "")
8512 (const_int 0)))
8513 (clobber (reg:CC CC_REGNUM))]
8514 "TARGET_32BIT && reload_completed"
8515 [(set (match_dup 0) (lshiftrt:SI (match_dup 1) (const_int 31)))])
8516
8517(define_split
8518 [(set (match_operand:SI 0 "s_register_operand" "")
8519 (ge:SI (match_operand:SI 1 "s_register_operand" "")
8520 (const_int 0)))
8521 (clobber (reg:CC CC_REGNUM))]
8522 "TARGET_32BIT && reload_completed"
8523 [(set (match_dup 0) (not:SI (match_dup 1)))
8524 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 31)))])
8525
98562479 8526(define_split
8527 [(set (match_operand:SI 0 "s_register_operand" "")
8528 (eq:SI (match_operand:SI 1 "s_register_operand" "")
8529 (const_int 0)))
8530 (clobber (reg:CC CC_REGNUM))]
8531 "arm_arch5 && TARGET_32BIT"
8532 [(set (match_dup 0) (clz:SI (match_dup 1)))
8533 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 5)))]
8534)
8535
2df9477b 8536(define_split
8537 [(set (match_operand:SI 0 "s_register_operand" "")
8538 (eq:SI (match_operand:SI 1 "s_register_operand" "")
8539 (const_int 0)))
8540 (clobber (reg:CC CC_REGNUM))]
8541 "TARGET_32BIT && reload_completed"
8542 [(parallel
080c0b9a 8543 [(set (reg:CC CC_REGNUM)
8544 (compare:CC (const_int 1) (match_dup 1)))
2df9477b 8545 (set (match_dup 0)
8546 (minus:SI (const_int 1) (match_dup 1)))])
080c0b9a 8547 (cond_exec (ltu:CC (reg:CC CC_REGNUM) (const_int 0))
2df9477b 8548 (set (match_dup 0) (const_int 0)))])
8549
8550(define_split
8551 [(set (match_operand:SI 0 "s_register_operand" "")
8552 (ne:SI (match_operand:SI 1 "s_register_operand" "")
8553 (match_operand:SI 2 "const_int_operand" "")))
8554 (clobber (reg:CC CC_REGNUM))]
8555 "TARGET_32BIT && reload_completed"
8556 [(parallel
8557 [(set (reg:CC CC_REGNUM)
8558 (compare:CC (match_dup 1) (match_dup 2)))
8559 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))])
8560 (cond_exec (ne:CC (reg:CC CC_REGNUM) (const_int 0))
8561 (set (match_dup 0) (const_int 1)))]
8562{
8563 operands[3] = GEN_INT (-INTVAL (operands[2]));
8564})
8565
8566(define_split
8567 [(set (match_operand:SI 0 "s_register_operand" "")
8568 (ne:SI (match_operand:SI 1 "s_register_operand" "")
8569 (match_operand:SI 2 "arm_add_operand" "")))
8570 (clobber (reg:CC CC_REGNUM))]
8571 "TARGET_32BIT && reload_completed"
8572 [(parallel
8573 [(set (reg:CC_NOOV CC_REGNUM)
8574 (compare:CC_NOOV (minus:SI (match_dup 1) (match_dup 2))
8575 (const_int 0)))
8576 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
8577 (cond_exec (ne:CC_NOOV (reg:CC_NOOV CC_REGNUM) (const_int 0))
8578 (set (match_dup 0) (const_int 1)))])
8579
8580(define_insn_and_split "*compare_scc"
fd711051 8581 [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts")
8fa3ba89 8582 (match_operator:SI 1 "arm_comparison_operator"
5565501b 8583 [(match_operand:SI 2 "s_register_operand" "r,r")
8584 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
bd5b4116 8585 (clobber (reg:CC CC_REGNUM))]
2df9477b 8586 "TARGET_32BIT"
8587 "#"
8588 "&& reload_completed"
8589 [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 3)))
8590 (cond_exec (match_dup 4) (set (match_dup 0) (const_int 0)))
8591 (cond_exec (match_dup 5) (set (match_dup 0) (const_int 1)))]
8592{
8593 rtx tmp1;
3754d046 8594 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
2df9477b 8595 operands[2], operands[3]);
8596 enum rtx_code rc = GET_CODE (operands[1]);
e2348bcb 8597
2df9477b 8598 tmp1 = gen_rtx_REG (mode, CC_REGNUM);
080c0b9a 8599
2df9477b 8600 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
8601 if (mode == CCFPmode || mode == CCFPEmode)
8602 rc = reverse_condition_maybe_unordered (rc);
8603 else
8604 rc = reverse_condition (rc);
8605 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
1b7da4ac 8606}
8607 [(set_attr "type" "multiple")]
8608)
9c08d1fa 8609
080c0b9a 8610;; Attempt to improve the sequence generated by the compare_scc splitters
8611;; not to use conditional execution.
98562479 8612
8613;; Rd = (eq (reg1) (const_int0)) // ARMv5
8614;; clz Rd, reg1
8615;; lsr Rd, Rd, #5
080c0b9a 8616(define_peephole2
8617 [(set (reg:CC CC_REGNUM)
8618 (compare:CC (match_operand:SI 1 "register_operand" "")
98562479 8619 (const_int 0)))
8620 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
8621 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
8622 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
8623 (set (match_dup 0) (const_int 1)))]
8624 "arm_arch5 && TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)"
8625 [(set (match_dup 0) (clz:SI (match_dup 1)))
8626 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 5)))]
8627)
8628
8629;; Rd = (eq (reg1) (const_int0)) // !ARMv5
8630;; negs Rd, reg1
8631;; adc Rd, Rd, reg1
8632(define_peephole2
8633 [(set (reg:CC CC_REGNUM)
8634 (compare:CC (match_operand:SI 1 "register_operand" "")
8635 (const_int 0)))
080c0b9a 8636 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
8637 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
8638 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
8639 (set (match_dup 0) (const_int 1)))
98562479 8640 (match_scratch:SI 2 "r")]
8641 "TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)"
922b6913 8642 [(parallel
8643 [(set (reg:CC CC_REGNUM)
98562479 8644 (compare:CC (const_int 0) (match_dup 1)))
8645 (set (match_dup 2) (minus:SI (const_int 0) (match_dup 1)))])
8646 (set (match_dup 0)
8647 (plus:SI (plus:SI (match_dup 1) (match_dup 2))
8648 (geu:SI (reg:CC CC_REGNUM) (const_int 0))))]
8649)
8650
31991287 8651;; Rd = (eq (reg1) (reg2/imm)) // ARMv5 and optimising for speed.
98562479 8652;; sub Rd, Reg1, reg2
8653;; clz Rd, Rd
8654;; lsr Rd, Rd, #5
8655(define_peephole2
8656 [(set (reg:CC CC_REGNUM)
8657 (compare:CC (match_operand:SI 1 "register_operand" "")
8658 (match_operand:SI 2 "arm_rhs_operand" "")))
8659 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
8660 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
8661 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
8662 (set (match_dup 0) (const_int 1)))]
31991287 8663 "arm_arch5 && TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)
8664 && !(TARGET_THUMB2 && optimize_insn_for_size_p ())"
98562479 8665 [(set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))
8666 (set (match_dup 0) (clz:SI (match_dup 0)))
8667 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 5)))]
8668)
8669
8670
31991287 8671;; Rd = (eq (reg1) (reg2)) // ! ARMv5 or optimising for size.
98562479 8672;; sub T1, Reg1, reg2
8673;; negs Rd, T1
8674;; adc Rd, Rd, T1
8675(define_peephole2
8676 [(set (reg:CC CC_REGNUM)
8677 (compare:CC (match_operand:SI 1 "register_operand" "")
8678 (match_operand:SI 2 "arm_rhs_operand" "")))
8679 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
8680 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
8681 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
8682 (set (match_dup 0) (const_int 1)))
8683 (match_scratch:SI 3 "r")]
8684 "TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)"
31991287 8685 [(set (match_dup 3) (match_dup 4))
080c0b9a 8686 (parallel
8687 [(set (reg:CC CC_REGNUM)
8688 (compare:CC (const_int 0) (match_dup 3)))
8689 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 3)))])
98562479 8690 (set (match_dup 0)
8691 (plus:SI (plus:SI (match_dup 0) (match_dup 3))
8692 (geu:SI (reg:CC CC_REGNUM) (const_int 0))))]
31991287 8693 "
8694 if (CONST_INT_P (operands[2]))
8695 operands[4] = plus_constant (SImode, operands[1], -INTVAL (operands[2]));
8696 else
8697 operands[4] = gen_rtx_MINUS (SImode, operands[1], operands[2]);
8698 ")
080c0b9a 8699
f7fbdd4a 8700(define_insn "*cond_move"
9c08d1fa 8701 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
aea4c774 8702 (if_then_else:SI (match_operator 3 "equality_operator"
8fa3ba89 8703 [(match_operator 4 "arm_comparison_operator"
8a18b90c 8704 [(match_operand 5 "cc_register" "") (const_int 0)])
aea4c774 8705 (const_int 0)])
8706 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8707 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
cffb2a26 8708 "TARGET_ARM"
9c08d1fa 8709 "*
8fa3ba89 8710 if (GET_CODE (operands[3]) == NE)
8711 {
8712 if (which_alternative != 1)
8713 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
8714 if (which_alternative != 0)
8715 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
8716 return \"\";
8717 }
8718 if (which_alternative != 0)
8719 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8720 if (which_alternative != 1)
8721 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
8722 return \"\";
8723 "
8724 [(set_attr "conds" "use")
282b4c75 8725 (set_attr_alternative "type"
8726 [(if_then_else (match_operand 2 "const_int_operand" "")
8727 (const_string "mov_imm")
8728 (const_string "mov_reg"))
8729 (if_then_else (match_operand 1 "const_int_operand" "")
8730 (const_string "mov_imm")
8731 (const_string "mov_reg"))
8732 (const_string "multiple")])
8fa3ba89 8733 (set_attr "length" "4,4,8")]
8734)
9c08d1fa 8735
f7fbdd4a 8736(define_insn "*cond_arith"
9c08d1fa 8737 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8738 (match_operator:SI 5 "shiftable_operator"
8fa3ba89 8739 [(match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 8740 [(match_operand:SI 2 "s_register_operand" "r,r")
8741 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8742 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 8743 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8744 "TARGET_ARM"
9c08d1fa 8745 "*
8fa3ba89 8746 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
8747 return \"%i5\\t%0, %1, %2, lsr #31\";
40dbec34 8748
8fa3ba89 8749 output_asm_insn (\"cmp\\t%2, %3\", operands);
8750 if (GET_CODE (operands[5]) == AND)
8751 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
8752 else if (GET_CODE (operands[5]) == MINUS)
8753 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
8754 else if (which_alternative != 0)
8755 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8756 return \"%i5%d4\\t%0, %1, #1\";
8757 "
8758 [(set_attr "conds" "clob")
1b7da4ac 8759 (set_attr "length" "12")
8760 (set_attr "type" "multiple")]
8fa3ba89 8761)
9c08d1fa 8762
f7fbdd4a 8763(define_insn "*cond_sub"
9c08d1fa 8764 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8765 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8fa3ba89 8766 (match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 8767 [(match_operand:SI 2 "s_register_operand" "r,r")
8768 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 8769 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8770 "TARGET_ARM"
9c08d1fa 8771 "*
8fa3ba89 8772 output_asm_insn (\"cmp\\t%2, %3\", operands);
8773 if (which_alternative != 0)
8774 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8775 return \"sub%d4\\t%0, %1, #1\";
8776 "
8777 [(set_attr "conds" "clob")
1b7da4ac 8778 (set_attr "length" "8,12")
8779 (set_attr "type" "multiple")]
8fa3ba89 8780)
9c08d1fa 8781
aea4c774 8782(define_insn "*cmp_ite0"
cffb2a26 8783 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 8784 (compare
8785 (if_then_else:SI
8fa3ba89 8786 (match_operator 4 "arm_comparison_operator"
2ff91fec 8787 [(match_operand:SI 0 "s_register_operand"
8788 "l,l,l,r,r,r,r,r,r")
8789 (match_operand:SI 1 "arm_add_operand"
8790 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
8fa3ba89 8791 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 8792 [(match_operand:SI 2 "s_register_operand"
8793 "l,r,r,l,l,r,r,r,r")
8794 (match_operand:SI 3 "arm_add_operand"
8795 "lPy,rI,L,lPy,lPy,rI,rI,L,L")])
aea4c774 8796 (const_int 0))
8797 (const_int 0)))]
2ff91fec 8798 "TARGET_32BIT"
9c08d1fa 8799 "*
aea4c774 8800 {
2ff91fec 8801 static const char * const cmp1[NUM_OF_COND_CMP][2] =
8802 {
8803 {\"cmp%d5\\t%0, %1\",
8804 \"cmp%d4\\t%2, %3\"},
8805 {\"cmn%d5\\t%0, #%n1\",
8806 \"cmp%d4\\t%2, %3\"},
8807 {\"cmp%d5\\t%0, %1\",
8808 \"cmn%d4\\t%2, #%n3\"},
8809 {\"cmn%d5\\t%0, #%n1\",
8810 \"cmn%d4\\t%2, #%n3\"}
8811 };
8812 static const char * const cmp2[NUM_OF_COND_CMP][2] =
8813 {
8814 {\"cmp\\t%2, %3\",
8815 \"cmp\\t%0, %1\"},
8816 {\"cmp\\t%2, %3\",
8817 \"cmn\\t%0, #%n1\"},
8818 {\"cmn\\t%2, #%n3\",
8819 \"cmp\\t%0, %1\"},
8820 {\"cmn\\t%2, #%n3\",
8821 \"cmn\\t%0, #%n1\"}
8822 };
8823 static const char * const ite[2] =
8fa3ba89 8824 {
2ff91fec 8825 \"it\\t%d5\",
8826 \"it\\t%d4\"
8fa3ba89 8827 };
2ff91fec 8828 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
8829 CMP_CMP, CMN_CMP, CMP_CMP,
8830 CMN_CMP, CMP_CMN, CMN_CMN};
8fa3ba89 8831 int swap =
8832 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8833
2ff91fec 8834 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
8835 if (TARGET_THUMB2) {
8836 output_asm_insn (ite[swap], operands);
8837 }
8838 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
8839 return \"\";
8fa3ba89 8840 }"
8841 [(set_attr "conds" "set")
2ff91fec 8842 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
1b7da4ac 8843 (set_attr "type" "multiple")
2ff91fec 8844 (set_attr_alternative "length"
8845 [(const_int 6)
8846 (const_int 8)
8847 (const_int 8)
8848 (const_int 8)
8849 (const_int 8)
8850 (if_then_else (eq_attr "is_thumb" "no")
8851 (const_int 8)
8852 (const_int 10))
8853 (if_then_else (eq_attr "is_thumb" "no")
8854 (const_int 8)
8855 (const_int 10))
8856 (if_then_else (eq_attr "is_thumb" "no")
8857 (const_int 8)
8858 (const_int 10))
8859 (if_then_else (eq_attr "is_thumb" "no")
8860 (const_int 8)
8861 (const_int 10))])]
8fa3ba89 8862)
9c08d1fa 8863
aea4c774 8864(define_insn "*cmp_ite1"
cffb2a26 8865 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 8866 (compare
8867 (if_then_else:SI
8fa3ba89 8868 (match_operator 4 "arm_comparison_operator"
2ff91fec 8869 [(match_operand:SI 0 "s_register_operand"
8870 "l,l,l,r,r,r,r,r,r")
8871 (match_operand:SI 1 "arm_add_operand"
8872 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
8fa3ba89 8873 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 8874 [(match_operand:SI 2 "s_register_operand"
8875 "l,r,r,l,l,r,r,r,r")
8876 (match_operand:SI 3 "arm_add_operand"
8877 "lPy,rI,L,lPy,lPy,rI,rI,L,L")])
aea4c774 8878 (const_int 1))
8879 (const_int 0)))]
2ff91fec 8880 "TARGET_32BIT"
9c08d1fa 8881 "*
9c08d1fa 8882 {
2ff91fec 8883 static const char * const cmp1[NUM_OF_COND_CMP][2] =
8884 {
8885 {\"cmp\\t%0, %1\",
8886 \"cmp\\t%2, %3\"},
8887 {\"cmn\\t%0, #%n1\",
8888 \"cmp\\t%2, %3\"},
8889 {\"cmp\\t%0, %1\",
8890 \"cmn\\t%2, #%n3\"},
8891 {\"cmn\\t%0, #%n1\",
8892 \"cmn\\t%2, #%n3\"}
8893 };
8894 static const char * const cmp2[NUM_OF_COND_CMP][2] =
215b30b3 8895 {
2ff91fec 8896 {\"cmp%d4\\t%2, %3\",
8897 \"cmp%D5\\t%0, %1\"},
8898 {\"cmp%d4\\t%2, %3\",
8899 \"cmn%D5\\t%0, #%n1\"},
8900 {\"cmn%d4\\t%2, #%n3\",
8901 \"cmp%D5\\t%0, %1\"},
8902 {\"cmn%d4\\t%2, #%n3\",
8903 \"cmn%D5\\t%0, #%n1\"}
215b30b3 8904 };
2ff91fec 8905 static const char * const ite[2] =
8906 {
8907 \"it\\t%d4\",
8908 \"it\\t%D5\"
8909 };
8910 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
8911 CMP_CMP, CMN_CMP, CMP_CMP,
8912 CMN_CMP, CMP_CMN, CMN_CMN};
215b30b3 8913 int swap =
8914 comparison_dominates_p (GET_CODE (operands[5]),
8915 reverse_condition (GET_CODE (operands[4])));
8916
2ff91fec 8917 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
8918 if (TARGET_THUMB2) {
8919 output_asm_insn (ite[swap], operands);
8920 }
8921 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
8922 return \"\";
215b30b3 8923 }"
8fa3ba89 8924 [(set_attr "conds" "set")
2ff91fec 8925 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
8926 (set_attr_alternative "length"
8927 [(const_int 6)
8928 (const_int 8)
8929 (const_int 8)
8930 (const_int 8)
8931 (const_int 8)
8932 (if_then_else (eq_attr "is_thumb" "no")
8933 (const_int 8)
8934 (const_int 10))
8935 (if_then_else (eq_attr "is_thumb" "no")
8936 (const_int 8)
8937 (const_int 10))
8938 (if_then_else (eq_attr "is_thumb" "no")
8939 (const_int 8)
8940 (const_int 10))
8941 (if_then_else (eq_attr "is_thumb" "no")
8942 (const_int 8)
1b7da4ac 8943 (const_int 10))])
8944 (set_attr "type" "multiple")]
8fa3ba89 8945)
9c08d1fa 8946
f6c53574 8947(define_insn "*cmp_and"
8948 [(set (match_operand 6 "dominant_cc_register" "")
8949 (compare
8950 (and:SI
8951 (match_operator 4 "arm_comparison_operator"
2ff91fec 8952 [(match_operand:SI 0 "s_register_operand"
8953 "l,l,l,r,r,r,r,r,r")
8954 (match_operand:SI 1 "arm_add_operand"
8955 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
f6c53574 8956 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 8957 [(match_operand:SI 2 "s_register_operand"
8958 "l,r,r,l,l,r,r,r,r")
8959 (match_operand:SI 3 "arm_add_operand"
8960 "lPy,rI,L,lPy,lPy,rI,rI,L,L")]))
f6c53574 8961 (const_int 0)))]
2ff91fec 8962 "TARGET_32BIT"
f6c53574 8963 "*
8964 {
2ff91fec 8965 static const char *const cmp1[NUM_OF_COND_CMP][2] =
f6c53574 8966 {
2ff91fec 8967 {\"cmp%d5\\t%0, %1\",
8968 \"cmp%d4\\t%2, %3\"},
8969 {\"cmn%d5\\t%0, #%n1\",
8970 \"cmp%d4\\t%2, %3\"},
8971 {\"cmp%d5\\t%0, %1\",
8972 \"cmn%d4\\t%2, #%n3\"},
8973 {\"cmn%d5\\t%0, #%n1\",
8974 \"cmn%d4\\t%2, #%n3\"}
f6c53574 8975 };
2ff91fec 8976 static const char *const cmp2[NUM_OF_COND_CMP][2] =
8977 {
8978 {\"cmp\\t%2, %3\",
8979 \"cmp\\t%0, %1\"},
8980 {\"cmp\\t%2, %3\",
8981 \"cmn\\t%0, #%n1\"},
8982 {\"cmn\\t%2, #%n3\",
8983 \"cmp\\t%0, %1\"},
8984 {\"cmn\\t%2, #%n3\",
8985 \"cmn\\t%0, #%n1\"}
8986 };
8987 static const char *const ite[2] =
8988 {
8989 \"it\\t%d5\",
8990 \"it\\t%d4\"
8991 };
8992 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
8993 CMP_CMP, CMN_CMP, CMP_CMP,
8994 CMN_CMP, CMP_CMN, CMN_CMN};
f6c53574 8995 int swap =
8996 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8997
2ff91fec 8998 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
8999 if (TARGET_THUMB2) {
9000 output_asm_insn (ite[swap], operands);
9001 }
9002 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9003 return \"\";
f6c53574 9004 }"
9005 [(set_attr "conds" "set")
9006 (set_attr "predicable" "no")
2ff91fec 9007 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
9008 (set_attr_alternative "length"
9009 [(const_int 6)
9010 (const_int 8)
9011 (const_int 8)
9012 (const_int 8)
9013 (const_int 8)
9014 (if_then_else (eq_attr "is_thumb" "no")
9015 (const_int 8)
9016 (const_int 10))
9017 (if_then_else (eq_attr "is_thumb" "no")
9018 (const_int 8)
9019 (const_int 10))
9020 (if_then_else (eq_attr "is_thumb" "no")
9021 (const_int 8)
9022 (const_int 10))
9023 (if_then_else (eq_attr "is_thumb" "no")
9024 (const_int 8)
1b7da4ac 9025 (const_int 10))])
9026 (set_attr "type" "multiple")]
f6c53574 9027)
9028
9029(define_insn "*cmp_ior"
9030 [(set (match_operand 6 "dominant_cc_register" "")
9031 (compare
9032 (ior:SI
9033 (match_operator 4 "arm_comparison_operator"
2ff91fec 9034 [(match_operand:SI 0 "s_register_operand"
9035 "l,l,l,r,r,r,r,r,r")
9036 (match_operand:SI 1 "arm_add_operand"
9037 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
f6c53574 9038 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 9039 [(match_operand:SI 2 "s_register_operand"
9040 "l,r,r,l,l,r,r,r,r")
9041 (match_operand:SI 3 "arm_add_operand"
9042 "lPy,rI,L,lPy,lPy,rI,rI,L,L")]))
f6c53574 9043 (const_int 0)))]
2ff91fec 9044 "TARGET_32BIT"
f6c53574 9045 "*
f6c53574 9046 {
2ff91fec 9047 static const char *const cmp1[NUM_OF_COND_CMP][2] =
9048 {
9049 {\"cmp\\t%0, %1\",
9050 \"cmp\\t%2, %3\"},
9051 {\"cmn\\t%0, #%n1\",
9052 \"cmp\\t%2, %3\"},
9053 {\"cmp\\t%0, %1\",
9054 \"cmn\\t%2, #%n3\"},
9055 {\"cmn\\t%0, #%n1\",
9056 \"cmn\\t%2, #%n3\"}
9057 };
9058 static const char *const cmp2[NUM_OF_COND_CMP][2] =
9059 {
9060 {\"cmp%D4\\t%2, %3\",
9061 \"cmp%D5\\t%0, %1\"},
9062 {\"cmp%D4\\t%2, %3\",
9063 \"cmn%D5\\t%0, #%n1\"},
9064 {\"cmn%D4\\t%2, #%n3\",
9065 \"cmp%D5\\t%0, %1\"},
9066 {\"cmn%D4\\t%2, #%n3\",
9067 \"cmn%D5\\t%0, #%n1\"}
9068 };
9069 static const char *const ite[2] =
9070 {
9071 \"it\\t%D4\",
9072 \"it\\t%D5\"
9073 };
9074 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
9075 CMP_CMP, CMN_CMP, CMP_CMP,
9076 CMN_CMP, CMP_CMN, CMN_CMN};
9077 int swap =
9078 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9079
9080 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9081 if (TARGET_THUMB2) {
9082 output_asm_insn (ite[swap], operands);
9083 }
9084 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9085 return \"\";
9086 }
9087 "
f6c53574 9088 [(set_attr "conds" "set")
2ff91fec 9089 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
9090 (set_attr_alternative "length"
9091 [(const_int 6)
9092 (const_int 8)
9093 (const_int 8)
9094 (const_int 8)
9095 (const_int 8)
9096 (if_then_else (eq_attr "is_thumb" "no")
9097 (const_int 8)
9098 (const_int 10))
9099 (if_then_else (eq_attr "is_thumb" "no")
9100 (const_int 8)
9101 (const_int 10))
9102 (if_then_else (eq_attr "is_thumb" "no")
9103 (const_int 8)
9104 (const_int 10))
9105 (if_then_else (eq_attr "is_thumb" "no")
9106 (const_int 8)
1b7da4ac 9107 (const_int 10))])
9108 (set_attr "type" "multiple")]
f6c53574 9109)
9110
3c5afce6 9111(define_insn_and_split "*ior_scc_scc"
fd711051 9112 [(set (match_operand:SI 0 "s_register_operand" "=Ts")
3c5afce6 9113 (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9114 [(match_operand:SI 1 "s_register_operand" "r")
9115 (match_operand:SI 2 "arm_add_operand" "rIL")])
9116 (match_operator:SI 6 "arm_comparison_operator"
9117 [(match_operand:SI 4 "s_register_operand" "r")
9118 (match_operand:SI 5 "arm_add_operand" "rIL")])))
9119 (clobber (reg:CC CC_REGNUM))]
2ff91fec 9120 "TARGET_32BIT
3c5afce6 9121 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
9122 != CCmode)"
9123 "#"
2ff91fec 9124 "TARGET_32BIT && reload_completed"
3c5afce6 9125 [(set (match_dup 7)
9126 (compare
9127 (ior:SI
9128 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9129 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9130 (const_int 0)))
9131 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9132 "operands[7]
9133 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9134 DOM_CC_X_OR_Y),
601f584c 9135 CC_REGNUM);"
9136 [(set_attr "conds" "clob")
1b7da4ac 9137 (set_attr "length" "16")
9138 (set_attr "type" "multiple")]
9139)
601f584c 9140
9141; If the above pattern is followed by a CMP insn, then the compare is
9142; redundant, since we can rework the conditional instruction that follows.
9143(define_insn_and_split "*ior_scc_scc_cmp"
9144 [(set (match_operand 0 "dominant_cc_register" "")
9145 (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9146 [(match_operand:SI 1 "s_register_operand" "r")
9147 (match_operand:SI 2 "arm_add_operand" "rIL")])
9148 (match_operator:SI 6 "arm_comparison_operator"
9149 [(match_operand:SI 4 "s_register_operand" "r")
9150 (match_operand:SI 5 "arm_add_operand" "rIL")]))
9151 (const_int 0)))
fd711051 9152 (set (match_operand:SI 7 "s_register_operand" "=Ts")
601f584c 9153 (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9154 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
2ff91fec 9155 "TARGET_32BIT"
601f584c 9156 "#"
2ff91fec 9157 "TARGET_32BIT && reload_completed"
601f584c 9158 [(set (match_dup 0)
9159 (compare
9160 (ior:SI
9161 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9162 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9163 (const_int 0)))
9164 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9165 ""
9166 [(set_attr "conds" "set")
1b7da4ac 9167 (set_attr "length" "16")
9168 (set_attr "type" "multiple")]
9169)
3c5afce6 9170
9171(define_insn_and_split "*and_scc_scc"
fd711051 9172 [(set (match_operand:SI 0 "s_register_operand" "=Ts")
3c5afce6 9173 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9174 [(match_operand:SI 1 "s_register_operand" "r")
9175 (match_operand:SI 2 "arm_add_operand" "rIL")])
9176 (match_operator:SI 6 "arm_comparison_operator"
9177 [(match_operand:SI 4 "s_register_operand" "r")
9178 (match_operand:SI 5 "arm_add_operand" "rIL")])))
9179 (clobber (reg:CC CC_REGNUM))]
2ff91fec 9180 "TARGET_32BIT
3c5afce6 9181 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9182 != CCmode)"
9183 "#"
2ff91fec 9184 "TARGET_32BIT && reload_completed
601f584c 9185 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9186 != CCmode)"
3c5afce6 9187 [(set (match_dup 7)
9188 (compare
9189 (and:SI
9190 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9191 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9192 (const_int 0)))
9193 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9194 "operands[7]
9195 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9196 DOM_CC_X_AND_Y),
601f584c 9197 CC_REGNUM);"
9198 [(set_attr "conds" "clob")
1b7da4ac 9199 (set_attr "length" "16")
9200 (set_attr "type" "multiple")]
9201)
601f584c 9202
9203; If the above pattern is followed by a CMP insn, then the compare is
9204; redundant, since we can rework the conditional instruction that follows.
9205(define_insn_and_split "*and_scc_scc_cmp"
9206 [(set (match_operand 0 "dominant_cc_register" "")
9207 (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
9208 [(match_operand:SI 1 "s_register_operand" "r")
9209 (match_operand:SI 2 "arm_add_operand" "rIL")])
9210 (match_operator:SI 6 "arm_comparison_operator"
9211 [(match_operand:SI 4 "s_register_operand" "r")
9212 (match_operand:SI 5 "arm_add_operand" "rIL")]))
9213 (const_int 0)))
fd711051 9214 (set (match_operand:SI 7 "s_register_operand" "=Ts")
601f584c 9215 (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9216 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
2ff91fec 9217 "TARGET_32BIT"
601f584c 9218 "#"
2ff91fec 9219 "TARGET_32BIT && reload_completed"
601f584c 9220 [(set (match_dup 0)
9221 (compare
9222 (and:SI
9223 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9224 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9225 (const_int 0)))
9226 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9227 ""
9228 [(set_attr "conds" "set")
1b7da4ac 9229 (set_attr "length" "16")
9230 (set_attr "type" "multiple")]
9231)
601f584c 9232
9233;; If there is no dominance in the comparison, then we can still save an
9234;; instruction in the AND case, since we can know that the second compare
9235;; need only zero the value if false (if true, then the value is already
9236;; correct).
9237(define_insn_and_split "*and_scc_scc_nodom"
fd711051 9238 [(set (match_operand:SI 0 "s_register_operand" "=&Ts,&Ts,&Ts")
601f584c 9239 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9240 [(match_operand:SI 1 "s_register_operand" "r,r,0")
9241 (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
9242 (match_operator:SI 6 "arm_comparison_operator"
9243 [(match_operand:SI 4 "s_register_operand" "r,r,r")
9244 (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
9245 (clobber (reg:CC CC_REGNUM))]
2ff91fec 9246 "TARGET_32BIT
601f584c 9247 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9248 == CCmode)"
9249 "#"
2ff91fec 9250 "TARGET_32BIT && reload_completed"
601f584c 9251 [(parallel [(set (match_dup 0)
9252 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
9253 (clobber (reg:CC CC_REGNUM))])
9254 (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
9255 (set (match_dup 0)
9256 (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
9257 (match_dup 0)
9258 (const_int 0)))]
9259 "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
9260 operands[4], operands[5]),
9261 CC_REGNUM);
9262 operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
9263 operands[5]);"
9264 [(set_attr "conds" "clob")
1b7da4ac 9265 (set_attr "length" "20")
9266 (set_attr "type" "multiple")]
9267)
3c5afce6 9268
3a0bdee0 9269(define_split
9270 [(set (reg:CC_NOOV CC_REGNUM)
9271 (compare:CC_NOOV (ior:SI
9272 (and:SI (match_operand:SI 0 "s_register_operand" "")
9273 (const_int 1))
b0694be0 9274 (match_operator:SI 1 "arm_comparison_operator"
3a0bdee0 9275 [(match_operand:SI 2 "s_register_operand" "")
9276 (match_operand:SI 3 "arm_add_operand" "")]))
9277 (const_int 0)))
9278 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9279 "TARGET_ARM"
9280 [(set (match_dup 4)
9281 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9282 (match_dup 0)))
9283 (set (reg:CC_NOOV CC_REGNUM)
9284 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9285 (const_int 0)))]
9286 "")
9287
9288(define_split
9289 [(set (reg:CC_NOOV CC_REGNUM)
9290 (compare:CC_NOOV (ior:SI
b0694be0 9291 (match_operator:SI 1 "arm_comparison_operator"
3a0bdee0 9292 [(match_operand:SI 2 "s_register_operand" "")
9293 (match_operand:SI 3 "arm_add_operand" "")])
9294 (and:SI (match_operand:SI 0 "s_register_operand" "")
9295 (const_int 1)))
9296 (const_int 0)))
9297 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9298 "TARGET_ARM"
9299 [(set (match_dup 4)
9300 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9301 (match_dup 0)))
9302 (set (reg:CC_NOOV CC_REGNUM)
9303 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9304 (const_int 0)))]
9305 "")
25f905c2 9306;; ??? The conditional patterns above need checking for Thumb-2 usefulness
3a0bdee0 9307
190efb17 9308(define_insn_and_split "*negscc"
9c08d1fa 9309 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9310 (neg:SI (match_operator 3 "arm_comparison_operator"
9c08d1fa 9311 [(match_operand:SI 1 "s_register_operand" "r")
9312 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
bd5b4116 9313 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9314 "TARGET_ARM"
190efb17 9315 "#"
9316 "&& reload_completed"
9317 [(const_int 0)]
9318 {
9319 rtx cc_reg = gen_rtx_REG (CCmode, CC_REGNUM);
e2348bcb 9320
190efb17 9321 if (GET_CODE (operands[3]) == LT && operands[2] == const0_rtx)
9322 {
9323 /* Emit mov\\t%0, %1, asr #31 */
d1f9b275 9324 emit_insn (gen_rtx_SET (operands[0],
190efb17 9325 gen_rtx_ASHIFTRT (SImode,
9326 operands[1],
9327 GEN_INT (31))));
9328 DONE;
9329 }
9330 else if (GET_CODE (operands[3]) == NE)
9331 {
9332 /* Emit subs\\t%0, %1, %2\;mvnne\\t%0, #0 */
9333 if (CONST_INT_P (operands[2]))
9334 emit_insn (gen_cmpsi2_addneg (operands[0], operands[1], operands[2],
9335 GEN_INT (- INTVAL (operands[2]))));
9336 else
9337 emit_insn (gen_subsi3_compare (operands[0], operands[1], operands[2]));
9338
9339 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
9340 gen_rtx_NE (SImode,
9341 cc_reg,
9342 const0_rtx),
d1f9b275 9343 gen_rtx_SET (operands[0],
190efb17 9344 GEN_INT (~0))));
9345 DONE;
9346 }
9347 else
9348 {
9349 /* Emit: cmp\\t%1, %2\;mov%D3\\t%0, #0\;mvn%d3\\t%0, #0 */
d1f9b275 9350 emit_insn (gen_rtx_SET (cc_reg,
190efb17 9351 gen_rtx_COMPARE (CCmode, operands[1], operands[2])));
9352 enum rtx_code rc = GET_CODE (operands[3]);
9353
9354 rc = reverse_condition (rc);
9355 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
9356 gen_rtx_fmt_ee (rc,
9357 VOIDmode,
9358 cc_reg,
9359 const0_rtx),
d1f9b275 9360 gen_rtx_SET (operands[0], const0_rtx)));
190efb17 9361 rc = GET_CODE (operands[3]);
9362 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
9363 gen_rtx_fmt_ee (rc,
9364 VOIDmode,
9365 cc_reg,
9366 const0_rtx),
d1f9b275 9367 gen_rtx_SET (operands[0],
190efb17 9368 GEN_INT (~0))));
9369 DONE;
9370 }
9371 FAIL;
9372 }
8fa3ba89 9373 [(set_attr "conds" "clob")
1b7da4ac 9374 (set_attr "length" "12")
9375 (set_attr "type" "multiple")]
8fa3ba89 9376)
9c08d1fa 9377
90404b57 9378(define_insn_and_split "movcond_addsi"
9379 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r")
9380 (if_then_else:SI
9381 (match_operator 5 "comparison_operator"
9382 [(plus:SI (match_operand:SI 3 "s_register_operand" "r,r,r")
9383 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL"))
9384 (const_int 0)])
9385 (match_operand:SI 1 "arm_rhs_operand" "rI,rPy,r")
9386 (match_operand:SI 2 "arm_rhs_operand" "rI,rPy,r")))
9387 (clobber (reg:CC CC_REGNUM))]
9388 "TARGET_32BIT"
9389 "#"
9390 "&& reload_completed"
9391 [(set (reg:CC_NOOV CC_REGNUM)
9392 (compare:CC_NOOV
9393 (plus:SI (match_dup 3)
9394 (match_dup 4))
9395 (const_int 0)))
9396 (set (match_dup 0) (match_dup 1))
9397 (cond_exec (match_dup 6)
9398 (set (match_dup 0) (match_dup 2)))]
9399 "
9400 {
3754d046 9401 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[5]),
90404b57 9402 operands[3], operands[4]);
9403 enum rtx_code rc = GET_CODE (operands[5]);
90404b57 9404 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9405 gcc_assert (!(mode == CCFPmode || mode == CCFPEmode));
22440aeb 9406 if (!REG_P (operands[2]) || REGNO (operands[2]) != REGNO (operands[0]))
4d01ce2f 9407 rc = reverse_condition (rc);
f145bcba 9408 else
9409 std::swap (operands[1], operands[2]);
90404b57 9410
9411 operands[6] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9412 }
9413 "
9414 [(set_attr "conds" "clob")
1b7da4ac 9415 (set_attr "enabled_for_depr_it" "no,yes,yes")
9416 (set_attr "type" "multiple")]
90404b57 9417)
9418
9c08d1fa 9419(define_insn "movcond"
9420 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 9421 (if_then_else:SI
8fa3ba89 9422 (match_operator 5 "arm_comparison_operator"
5565501b 9423 [(match_operand:SI 3 "s_register_operand" "r,r,r")
9424 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
9425 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9426 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 9427 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9428 "TARGET_ARM"
9c08d1fa 9429 "*
9430 if (GET_CODE (operands[5]) == LT
9431 && (operands[4] == const0_rtx))
9432 {
0438d37f 9433 if (which_alternative != 1 && REG_P (operands[1]))
9c08d1fa 9434 {
9c08d1fa 9435 if (operands[2] == const0_rtx)
e2348bcb 9436 return \"and\\t%0, %1, %3, asr #31\";
9437 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
9c08d1fa 9438 }
0438d37f 9439 else if (which_alternative != 0 && REG_P (operands[2]))
9c08d1fa 9440 {
9c08d1fa 9441 if (operands[1] == const0_rtx)
e2348bcb 9442 return \"bic\\t%0, %2, %3, asr #31\";
9443 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
9c08d1fa 9444 }
9445 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 9446 are constants. */
9c08d1fa 9447 }
e2348bcb 9448
9c08d1fa 9449 if (GET_CODE (operands[5]) == GE
9450 && (operands[4] == const0_rtx))
9451 {
0438d37f 9452 if (which_alternative != 1 && REG_P (operands[1]))
9c08d1fa 9453 {
9c08d1fa 9454 if (operands[2] == const0_rtx)
e2348bcb 9455 return \"bic\\t%0, %1, %3, asr #31\";
9456 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
9c08d1fa 9457 }
0438d37f 9458 else if (which_alternative != 0 && REG_P (operands[2]))
9c08d1fa 9459 {
9c08d1fa 9460 if (operands[1] == const0_rtx)
e2348bcb 9461 return \"and\\t%0, %2, %3, asr #31\";
9462 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
9c08d1fa 9463 }
9464 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 9465 are constants. */
9c08d1fa 9466 }
0438d37f 9467 if (CONST_INT_P (operands[4])
9c08d1fa 9468 && !const_ok_for_arm (INTVAL (operands[4])))
e2348bcb 9469 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
9c08d1fa 9470 else
e2348bcb 9471 output_asm_insn (\"cmp\\t%3, %4\", operands);
9c08d1fa 9472 if (which_alternative != 0)
e2348bcb 9473 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
9c08d1fa 9474 if (which_alternative != 1)
e2348bcb 9475 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
9c08d1fa 9476 return \"\";
215b30b3 9477 "
8fa3ba89 9478 [(set_attr "conds" "clob")
1b7da4ac 9479 (set_attr "length" "8,8,12")
9480 (set_attr "type" "multiple")]
8fa3ba89 9481)
9c08d1fa 9482
25f905c2 9483;; ??? The patterns below need checking for Thumb-2 usefulness.
9484
8a18b90c 9485(define_insn "*ifcompare_plus_move"
9486 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9487 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 9488 [(match_operand:SI 4 "s_register_operand" "r,r")
9489 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9490 (plus:SI
9491 (match_operand:SI 2 "s_register_operand" "r,r")
9492 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
129a2fe4 9493 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 9494 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9495 "TARGET_ARM"
8a18b90c 9496 "#"
8fa3ba89 9497 [(set_attr "conds" "clob")
1b7da4ac 9498 (set_attr "length" "8,12")
9499 (set_attr "type" "multiple")]
8fa3ba89 9500)
8a18b90c 9501
9502(define_insn "*if_plus_move"
129a2fe4 9503 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 9504 (if_then_else:SI
8fa3ba89 9505 (match_operator 4 "arm_comparison_operator"
8a18b90c 9506 [(match_operand 5 "cc_register" "") (const_int 0)])
9507 (plus:SI
129a2fe4 9508 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9509 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
9510 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
cffb2a26 9511 "TARGET_ARM"
8a18b90c 9512 "@
9513 add%d4\\t%0, %2, %3
9514 sub%d4\\t%0, %2, #%n3
9515 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
129a2fe4 9516 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8fa3ba89 9517 [(set_attr "conds" "use")
9518 (set_attr "length" "4,4,8,8")
65f68e55 9519 (set_attr_alternative "type"
9520 [(if_then_else (match_operand 3 "const_int_operand" "")
d82e788e 9521 (const_string "alu_imm" )
112eda6f 9522 (const_string "alu_sreg"))
d82e788e 9523 (const_string "alu_imm")
282b4c75 9524 (const_string "multiple")
9525 (const_string "multiple")])]
8fa3ba89 9526)
8a18b90c 9527
9528(define_insn "*ifcompare_move_plus"
5565501b 9529 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9530 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 9531 [(match_operand:SI 4 "s_register_operand" "r,r")
9532 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 9533 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 9534 (plus:SI
9535 (match_operand:SI 2 "s_register_operand" "r,r")
9536 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
bd5b4116 9537 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9538 "TARGET_ARM"
8a18b90c 9539 "#"
8fa3ba89 9540 [(set_attr "conds" "clob")
1b7da4ac 9541 (set_attr "length" "8,12")
9542 (set_attr "type" "multiple")]
8fa3ba89 9543)
8a18b90c 9544
9545(define_insn "*if_move_plus"
129a2fe4 9546 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 9547 (if_then_else:SI
8fa3ba89 9548 (match_operator 4 "arm_comparison_operator"
8a18b90c 9549 [(match_operand 5 "cc_register" "") (const_int 0)])
129a2fe4 9550 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8a18b90c 9551 (plus:SI
129a2fe4 9552 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9553 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
cffb2a26 9554 "TARGET_ARM"
8a18b90c 9555 "@
9556 add%D4\\t%0, %2, %3
9557 sub%D4\\t%0, %2, #%n3
9558 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
129a2fe4 9559 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8fa3ba89 9560 [(set_attr "conds" "use")
9561 (set_attr "length" "4,4,8,8")
282b4c75 9562 (set_attr_alternative "type"
9563 [(if_then_else (match_operand 3 "const_int_operand" "")
9564 (const_string "alu_imm" )
9565 (const_string "alu_sreg"))
9566 (const_string "alu_imm")
9567 (const_string "multiple")
9568 (const_string "multiple")])]
8fa3ba89 9569)
8a18b90c 9570
9571(define_insn "*ifcompare_arith_arith"
9572 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9573 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8a18b90c 9574 [(match_operand:SI 5 "s_register_operand" "r")
9575 (match_operand:SI 6 "arm_add_operand" "rIL")])
9c08d1fa 9576 (match_operator:SI 8 "shiftable_operator"
8a18b90c 9577 [(match_operand:SI 1 "s_register_operand" "r")
9578 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9c08d1fa 9579 (match_operator:SI 7 "shiftable_operator"
8a18b90c 9580 [(match_operand:SI 3 "s_register_operand" "r")
9581 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
bd5b4116 9582 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9583 "TARGET_ARM"
8a18b90c 9584 "#"
8fa3ba89 9585 [(set_attr "conds" "clob")
1b7da4ac 9586 (set_attr "length" "12")
9587 (set_attr "type" "multiple")]
8fa3ba89 9588)
9c08d1fa 9589
8a18b90c 9590(define_insn "*if_arith_arith"
9591 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9592 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8a18b90c 9593 [(match_operand 8 "cc_register" "") (const_int 0)])
9594 (match_operator:SI 6 "shiftable_operator"
9595 [(match_operand:SI 1 "s_register_operand" "r")
9596 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9597 (match_operator:SI 7 "shiftable_operator"
9598 [(match_operand:SI 3 "s_register_operand" "r")
9599 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
cffb2a26 9600 "TARGET_ARM"
8a18b90c 9601 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8fa3ba89 9602 [(set_attr "conds" "use")
1b7da4ac 9603 (set_attr "length" "8")
9604 (set_attr "type" "multiple")]
8fa3ba89 9605)
8a18b90c 9606
f7fbdd4a 9607(define_insn "*ifcompare_arith_move"
9c08d1fa 9608 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9609 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 9610 [(match_operand:SI 2 "s_register_operand" "r,r")
5565501b 9611 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
9c08d1fa 9612 (match_operator:SI 7 "shiftable_operator"
9613 [(match_operand:SI 4 "s_register_operand" "r,r")
9614 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
129a2fe4 9615 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 9616 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9617 "TARGET_ARM"
9c08d1fa 9618 "*
9c08d1fa 9619 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 9620 the conditional operator is LT or GE and we are comparing against zero and
674a8f0b 9621 everything is in registers then we can do this in two instructions. */
9c08d1fa 9622 if (operands[3] == const0_rtx
9623 && GET_CODE (operands[7]) != AND
0438d37f 9624 && REG_P (operands[5])
9625 && REG_P (operands[1])
9c08d1fa 9626 && REGNO (operands[1]) == REGNO (operands[4])
9627 && REGNO (operands[4]) != REGNO (operands[0]))
9628 {
9629 if (GET_CODE (operands[6]) == LT)
40dbec34 9630 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 9631 else if (GET_CODE (operands[6]) == GE)
40dbec34 9632 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 9633 }
0438d37f 9634 if (CONST_INT_P (operands[3])
9c08d1fa 9635 && !const_ok_for_arm (INTVAL (operands[3])))
e2348bcb 9636 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
9c08d1fa 9637 else
e2348bcb 9638 output_asm_insn (\"cmp\\t%2, %3\", operands);
40dbec34 9639 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
9c08d1fa 9640 if (which_alternative != 0)
129a2fe4 9641 return \"mov%D6\\t%0, %1\";
9c08d1fa 9642 return \"\";
215b30b3 9643 "
8fa3ba89 9644 [(set_attr "conds" "clob")
1b7da4ac 9645 (set_attr "length" "8,12")
9646 (set_attr "type" "multiple")]
8fa3ba89 9647)
9c08d1fa 9648
8a18b90c 9649(define_insn "*if_arith_move"
129a2fe4 9650 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9651 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8a18b90c 9652 [(match_operand 6 "cc_register" "") (const_int 0)])
9653 (match_operator:SI 5 "shiftable_operator"
129a2fe4 9654 [(match_operand:SI 2 "s_register_operand" "r,r")
9655 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
9656 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
cffb2a26 9657 "TARGET_ARM"
8a18b90c 9658 "@
9659 %I5%d4\\t%0, %2, %3
129a2fe4 9660 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8fa3ba89 9661 [(set_attr "conds" "use")
9662 (set_attr "length" "4,8")
282b4c75 9663 (set_attr_alternative "type"
9664 [(if_then_else (match_operand 3 "const_int_operand" "")
9665 (const_string "alu_shift_imm" )
9666 (const_string "alu_shift_reg"))
9667 (const_string "multiple")])]
8fa3ba89 9668)
8a18b90c 9669
f7fbdd4a 9670(define_insn "*ifcompare_move_arith"
9c08d1fa 9671 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9672 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 9673 [(match_operand:SI 4 "s_register_operand" "r,r")
5565501b 9674 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 9675 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9c08d1fa 9676 (match_operator:SI 7 "shiftable_operator"
9677 [(match_operand:SI 2 "s_register_operand" "r,r")
9678 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 9679 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9680 "TARGET_ARM"
9c08d1fa 9681 "*
9c08d1fa 9682 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 9683 the conditional operator is LT or GE and we are comparing against zero and
9c08d1fa 9684 everything is in registers then we can do this in two instructions */
9685 if (operands[5] == const0_rtx
9686 && GET_CODE (operands[7]) != AND
0438d37f 9687 && REG_P (operands[3])
9688 && REG_P (operands[1])
9c08d1fa 9689 && REGNO (operands[1]) == REGNO (operands[2])
9690 && REGNO (operands[2]) != REGNO (operands[0]))
9691 {
9692 if (GET_CODE (operands[6]) == GE)
40dbec34 9693 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 9694 else if (GET_CODE (operands[6]) == LT)
40dbec34 9695 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 9696 }
40dbec34 9697
0438d37f 9698 if (CONST_INT_P (operands[5])
9c08d1fa 9699 && !const_ok_for_arm (INTVAL (operands[5])))
e2348bcb 9700 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
9c08d1fa 9701 else
e2348bcb 9702 output_asm_insn (\"cmp\\t%4, %5\", operands);
40dbec34 9703
9c08d1fa 9704 if (which_alternative != 0)
129a2fe4 9705 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
40dbec34 9706 return \"%I7%D6\\t%0, %2, %3\";
215b30b3 9707 "
8fa3ba89 9708 [(set_attr "conds" "clob")
1b7da4ac 9709 (set_attr "length" "8,12")
9710 (set_attr "type" "multiple")]
8fa3ba89 9711)
9c08d1fa 9712
8a18b90c 9713(define_insn "*if_move_arith"
129a2fe4 9714 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9715 (if_then_else:SI
8fa3ba89 9716 (match_operator 4 "arm_comparison_operator"
8a18b90c 9717 [(match_operand 6 "cc_register" "") (const_int 0)])
129a2fe4 9718 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 9719 (match_operator:SI 5 "shiftable_operator"
129a2fe4 9720 [(match_operand:SI 2 "s_register_operand" "r,r")
9721 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
cffb2a26 9722 "TARGET_ARM"
8a18b90c 9723 "@
9724 %I5%D4\\t%0, %2, %3
129a2fe4 9725 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
8fa3ba89 9726 [(set_attr "conds" "use")
9727 (set_attr "length" "4,8")
282b4c75 9728 (set_attr_alternative "type"
9729 [(if_then_else (match_operand 3 "const_int_operand" "")
9730 (const_string "alu_shift_imm" )
9731 (const_string "alu_shift_reg"))
9732 (const_string "multiple")])]
8fa3ba89 9733)
8a18b90c 9734
9735(define_insn "*ifcompare_move_not"
9c08d1fa 9736 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9737 (if_then_else:SI
8fa3ba89 9738 (match_operator 5 "arm_comparison_operator"
8a18b90c 9739 [(match_operand:SI 3 "s_register_operand" "r,r")
9740 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9741 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9742 (not:SI
9743 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 9744 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9745 "TARGET_ARM"
8a18b90c 9746 "#"
8fa3ba89 9747 [(set_attr "conds" "clob")
1b7da4ac 9748 (set_attr "length" "8,12")
9749 (set_attr "type" "multiple")]
8fa3ba89 9750)
9c08d1fa 9751
8a18b90c 9752(define_insn "*if_move_not"
9753 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9754 (if_then_else:SI
8fa3ba89 9755 (match_operator 4 "arm_comparison_operator"
8a18b90c 9756 [(match_operand 3 "cc_register" "") (const_int 0)])
9757 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9758 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
cffb2a26 9759 "TARGET_ARM"
8a18b90c 9760 "@
9761 mvn%D4\\t%0, %2
9762 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
9763 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
8fa3ba89 9764 [(set_attr "conds" "use")
1aed5204 9765 (set_attr "type" "mvn_reg")
1b7da4ac 9766 (set_attr "length" "4,8,8")
9767 (set_attr "type" "mvn_reg,multiple,multiple")]
8fa3ba89 9768)
8a18b90c 9769
9770(define_insn "*ifcompare_not_move"
9c08d1fa 9771 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9772 (if_then_else:SI
8fa3ba89 9773 (match_operator 5 "arm_comparison_operator"
8a18b90c 9774 [(match_operand:SI 3 "s_register_operand" "r,r")
9775 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9776 (not:SI
9777 (match_operand:SI 2 "s_register_operand" "r,r"))
9778 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 9779 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9780 "TARGET_ARM"
8a18b90c 9781 "#"
8fa3ba89 9782 [(set_attr "conds" "clob")
1b7da4ac 9783 (set_attr "length" "8,12")
9784 (set_attr "type" "multiple")]
8fa3ba89 9785)
9c08d1fa 9786
8a18b90c 9787(define_insn "*if_not_move"
9788 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9789 (if_then_else:SI
8fa3ba89 9790 (match_operator 4 "arm_comparison_operator"
8a18b90c 9791 [(match_operand 3 "cc_register" "") (const_int 0)])
9792 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9793 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 9794 "TARGET_ARM"
8a18b90c 9795 "@
9796 mvn%d4\\t%0, %2
9797 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
9798 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
8fa3ba89 9799 [(set_attr "conds" "use")
1b7da4ac 9800 (set_attr "type" "mvn_reg,multiple,multiple")
8fa3ba89 9801 (set_attr "length" "4,8,8")]
9802)
8a18b90c 9803
9804(define_insn "*ifcompare_shift_move"
9c08d1fa 9805 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9806 (if_then_else:SI
8fa3ba89 9807 (match_operator 6 "arm_comparison_operator"
8a18b90c 9808 [(match_operand:SI 4 "s_register_operand" "r,r")
9809 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9810 (match_operator:SI 7 "shift_operator"
9811 [(match_operand:SI 2 "s_register_operand" "r,r")
9812 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
9813 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 9814 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9815 "TARGET_ARM"
9c08d1fa 9816 "#"
8fa3ba89 9817 [(set_attr "conds" "clob")
1b7da4ac 9818 (set_attr "length" "8,12")
9819 (set_attr "type" "multiple")]
8fa3ba89 9820)
9c08d1fa 9821
8a18b90c 9822(define_insn "*if_shift_move"
9823 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9824 (if_then_else:SI
8fa3ba89 9825 (match_operator 5 "arm_comparison_operator"
8a18b90c 9826 [(match_operand 6 "cc_register" "") (const_int 0)])
9827 (match_operator:SI 4 "shift_operator"
9828 [(match_operand:SI 2 "s_register_operand" "r,r,r")
9829 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
9830 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 9831 "TARGET_ARM"
5565501b 9832 "@
8a18b90c 9833 mov%d5\\t%0, %2%S4
9834 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
9835 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
8fa3ba89 9836 [(set_attr "conds" "use")
331beb1a 9837 (set_attr "shift" "2")
a2cd141b 9838 (set_attr "length" "4,8,8")
282b4c75 9839 (set_attr_alternative "type"
9840 [(if_then_else (match_operand 3 "const_int_operand" "")
9841 (const_string "mov_shift" )
9842 (const_string "mov_shift_reg"))
9843 (const_string "multiple")
9844 (const_string "multiple")])]
8fa3ba89 9845)
5565501b 9846
8a18b90c 9847(define_insn "*ifcompare_move_shift"
9848 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 9849 (if_then_else:SI
8fa3ba89 9850 (match_operator 6 "arm_comparison_operator"
8a18b90c 9851 [(match_operand:SI 4 "s_register_operand" "r,r")
9852 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9853 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
5565501b 9854 (match_operator:SI 7 "shift_operator"
8a18b90c 9855 [(match_operand:SI 2 "s_register_operand" "r,r")
9856 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
bd5b4116 9857 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9858 "TARGET_ARM"
8a18b90c 9859 "#"
8fa3ba89 9860 [(set_attr "conds" "clob")
1b7da4ac 9861 (set_attr "length" "8,12")
9862 (set_attr "type" "multiple")]
8fa3ba89 9863)
5565501b 9864
8a18b90c 9865(define_insn "*if_move_shift"
9866 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 9867 (if_then_else:SI
8fa3ba89 9868 (match_operator 5 "arm_comparison_operator"
8a18b90c 9869 [(match_operand 6 "cc_register" "") (const_int 0)])
9870 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9871 (match_operator:SI 4 "shift_operator"
9872 [(match_operand:SI 2 "s_register_operand" "r,r,r")
9873 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
cffb2a26 9874 "TARGET_ARM"
5565501b 9875 "@
8a18b90c 9876 mov%D5\\t%0, %2%S4
9877 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
9878 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
8fa3ba89 9879 [(set_attr "conds" "use")
331beb1a 9880 (set_attr "shift" "2")
a2cd141b 9881 (set_attr "length" "4,8,8")
282b4c75 9882 (set_attr_alternative "type"
9883 [(if_then_else (match_operand 3 "const_int_operand" "")
9884 (const_string "mov_shift" )
9885 (const_string "mov_shift_reg"))
9886 (const_string "multiple")
9887 (const_string "multiple")])]
8fa3ba89 9888)
9c08d1fa 9889
f7fbdd4a 9890(define_insn "*ifcompare_shift_shift"
8a18b90c 9891 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 9892 (if_then_else:SI
8fa3ba89 9893 (match_operator 7 "arm_comparison_operator"
8a18b90c 9894 [(match_operand:SI 5 "s_register_operand" "r")
9895 (match_operand:SI 6 "arm_add_operand" "rIL")])
5565501b 9896 (match_operator:SI 8 "shift_operator"
8a18b90c 9897 [(match_operand:SI 1 "s_register_operand" "r")
9898 (match_operand:SI 2 "arm_rhs_operand" "rM")])
5565501b 9899 (match_operator:SI 9 "shift_operator"
8a18b90c 9900 [(match_operand:SI 3 "s_register_operand" "r")
9901 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
bd5b4116 9902 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9903 "TARGET_ARM"
8a18b90c 9904 "#"
8fa3ba89 9905 [(set_attr "conds" "clob")
1b7da4ac 9906 (set_attr "length" "12")
9907 (set_attr "type" "multiple")]
8fa3ba89 9908)
9c08d1fa 9909
8a18b90c 9910(define_insn "*if_shift_shift"
9911 [(set (match_operand:SI 0 "s_register_operand" "=r")
9912 (if_then_else:SI
8fa3ba89 9913 (match_operator 5 "arm_comparison_operator"
8a18b90c 9914 [(match_operand 8 "cc_register" "") (const_int 0)])
9915 (match_operator:SI 6 "shift_operator"
9916 [(match_operand:SI 1 "s_register_operand" "r")
9917 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9918 (match_operator:SI 7 "shift_operator"
9919 [(match_operand:SI 3 "s_register_operand" "r")
9920 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
cffb2a26 9921 "TARGET_ARM"
8a18b90c 9922 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
8fa3ba89 9923 [(set_attr "conds" "use")
331beb1a 9924 (set_attr "shift" "1")
a2cd141b 9925 (set_attr "length" "8")
9926 (set (attr "type") (if_then_else
9927 (and (match_operand 2 "const_int_operand" "")
9928 (match_operand 4 "const_int_operand" ""))
1aed5204 9929 (const_string "mov_shift")
9930 (const_string "mov_shift_reg")))]
8fa3ba89 9931)
8a18b90c 9932
f7fbdd4a 9933(define_insn "*ifcompare_not_arith"
8a18b90c 9934 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 9935 (if_then_else:SI
8fa3ba89 9936 (match_operator 6 "arm_comparison_operator"
8a18b90c 9937 [(match_operand:SI 4 "s_register_operand" "r")
9938 (match_operand:SI 5 "arm_add_operand" "rIL")])
9939 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5565501b 9940 (match_operator:SI 7 "shiftable_operator"
8a18b90c 9941 [(match_operand:SI 2 "s_register_operand" "r")
9942 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
bd5b4116 9943 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9944 "TARGET_ARM"
8a18b90c 9945 "#"
8fa3ba89 9946 [(set_attr "conds" "clob")
1b7da4ac 9947 (set_attr "length" "12")
9948 (set_attr "type" "multiple")]
8fa3ba89 9949)
9c08d1fa 9950
8a18b90c 9951(define_insn "*if_not_arith"
9952 [(set (match_operand:SI 0 "s_register_operand" "=r")
9953 (if_then_else:SI
8fa3ba89 9954 (match_operator 5 "arm_comparison_operator"
8a18b90c 9955 [(match_operand 4 "cc_register" "") (const_int 0)])
9956 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9957 (match_operator:SI 6 "shiftable_operator"
9958 [(match_operand:SI 2 "s_register_operand" "r")
9959 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
cffb2a26 9960 "TARGET_ARM"
8a18b90c 9961 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
8fa3ba89 9962 [(set_attr "conds" "use")
1aed5204 9963 (set_attr "type" "mvn_reg")
8fa3ba89 9964 (set_attr "length" "8")]
9965)
8a18b90c 9966
9967(define_insn "*ifcompare_arith_not"
9968 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 9969 (if_then_else:SI
8fa3ba89 9970 (match_operator 6 "arm_comparison_operator"
8a18b90c 9971 [(match_operand:SI 4 "s_register_operand" "r")
9972 (match_operand:SI 5 "arm_add_operand" "rIL")])
5565501b 9973 (match_operator:SI 7 "shiftable_operator"
8a18b90c 9974 [(match_operand:SI 2 "s_register_operand" "r")
9975 (match_operand:SI 3 "arm_rhs_operand" "rI")])
9976 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
bd5b4116 9977 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9978 "TARGET_ARM"
8a18b90c 9979 "#"
8fa3ba89 9980 [(set_attr "conds" "clob")
1b7da4ac 9981 (set_attr "length" "12")
9982 (set_attr "type" "multiple")]
8fa3ba89 9983)
9c08d1fa 9984
8a18b90c 9985(define_insn "*if_arith_not"
9986 [(set (match_operand:SI 0 "s_register_operand" "=r")
9987 (if_then_else:SI
8fa3ba89 9988 (match_operator 5 "arm_comparison_operator"
8a18b90c 9989 [(match_operand 4 "cc_register" "") (const_int 0)])
9990 (match_operator:SI 6 "shiftable_operator"
9991 [(match_operand:SI 2 "s_register_operand" "r")
9992 (match_operand:SI 3 "arm_rhs_operand" "rI")])
9993 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
cffb2a26 9994 "TARGET_ARM"
8a18b90c 9995 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
8fa3ba89 9996 [(set_attr "conds" "use")
1b7da4ac 9997 (set_attr "type" "multiple")
8fa3ba89 9998 (set_attr "length" "8")]
9999)
8a18b90c 10000
f7fbdd4a 10001(define_insn "*ifcompare_neg_move"
8a18b90c 10002 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 10003 (if_then_else:SI
8fa3ba89 10004 (match_operator 5 "arm_comparison_operator"
8a18b90c 10005 [(match_operand:SI 3 "s_register_operand" "r,r")
10006 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10007 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
10008 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 10009 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10010 "TARGET_ARM"
8a18b90c 10011 "#"
8fa3ba89 10012 [(set_attr "conds" "clob")
1b7da4ac 10013 (set_attr "length" "8,12")
10014 (set_attr "type" "multiple")]
8fa3ba89 10015)
8a18b90c 10016
530bb693 10017(define_insn_and_split "*if_neg_move"
10018 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
8a18b90c 10019 (if_then_else:SI
8fa3ba89 10020 (match_operator 4 "arm_comparison_operator"
8a18b90c 10021 [(match_operand 3 "cc_register" "") (const_int 0)])
530bb693 10022 (neg:SI (match_operand:SI 2 "s_register_operand" "l,r"))
10023 (match_operand:SI 1 "s_register_operand" "0,0")))]
10024 "TARGET_32BIT"
10025 "#"
10026 "&& reload_completed"
10027 [(cond_exec (match_op_dup 4 [(match_dup 3) (const_int 0)])
10028 (set (match_dup 0) (neg:SI (match_dup 2))))]
10029 ""
8fa3ba89 10030 [(set_attr "conds" "use")
530bb693 10031 (set_attr "length" "4")
10032 (set_attr "arch" "t2,32")
10033 (set_attr "enabled_for_depr_it" "yes,no")
10034 (set_attr "type" "logic_shift_imm")]
8fa3ba89 10035)
9c08d1fa 10036
f7fbdd4a 10037(define_insn "*ifcompare_move_neg"
8a18b90c 10038 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 10039 (if_then_else:SI
8fa3ba89 10040 (match_operator 5 "arm_comparison_operator"
8a18b90c 10041 [(match_operand:SI 3 "s_register_operand" "r,r")
10042 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10043 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
10044 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 10045 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10046 "TARGET_ARM"
8a18b90c 10047 "#"
8fa3ba89 10048 [(set_attr "conds" "clob")
1b7da4ac 10049 (set_attr "length" "8,12")
10050 (set_attr "type" "multiple")]
8fa3ba89 10051)
8a18b90c 10052
530bb693 10053(define_insn_and_split "*if_move_neg"
10054 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
8a18b90c 10055 (if_then_else:SI
8fa3ba89 10056 (match_operator 4 "arm_comparison_operator"
8a18b90c 10057 [(match_operand 3 "cc_register" "") (const_int 0)])
530bb693 10058 (match_operand:SI 1 "s_register_operand" "0,0")
10059 (neg:SI (match_operand:SI 2 "s_register_operand" "l,r"))))]
10060 "TARGET_32BIT"
10061 "#"
10062 "&& reload_completed"
10063 [(cond_exec (match_dup 5)
10064 (set (match_dup 0) (neg:SI (match_dup 2))))]
10065 {
10066 machine_mode mode = GET_MODE (operands[3]);
10067 rtx_code rc = GET_CODE (operands[4]);
10068
10069 if (mode == CCFPmode || mode == CCFPEmode)
10070 rc = reverse_condition_maybe_unordered (rc);
10071 else
10072 rc = reverse_condition (rc);
10073
10074 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[3], const0_rtx);
10075 }
0d66636f 10076 [(set_attr "conds" "use")
530bb693 10077 (set_attr "length" "4")
10078 (set_attr "arch" "t2,32")
10079 (set_attr "enabled_for_depr_it" "yes,no")
10080 (set_attr "type" "logic_shift_imm")]
0d66636f 10081)
9c08d1fa 10082
f7fbdd4a 10083(define_insn "*arith_adjacentmem"
9c08d1fa 10084 [(set (match_operand:SI 0 "s_register_operand" "=r")
10085 (match_operator:SI 1 "shiftable_operator"
10086 [(match_operand:SI 2 "memory_operand" "m")
10087 (match_operand:SI 3 "memory_operand" "m")]))
10088 (clobber (match_scratch:SI 4 "=r"))]
cffb2a26 10089 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9c08d1fa 10090 "*
215b30b3 10091 {
10092 rtx ldm[3];
10093 rtx arith[4];
94dee231 10094 rtx base_reg;
10095 HOST_WIDE_INT val1 = 0, val2 = 0;
9c08d1fa 10096
215b30b3 10097 if (REGNO (operands[0]) > REGNO (operands[4]))
10098 {
10099 ldm[1] = operands[4];
10100 ldm[2] = operands[0];
10101 }
10102 else
10103 {
10104 ldm[1] = operands[0];
10105 ldm[2] = operands[4];
10106 }
94dee231 10107
10108 base_reg = XEXP (operands[2], 0);
10109
10110 if (!REG_P (base_reg))
10111 {
10112 val1 = INTVAL (XEXP (base_reg, 1));
10113 base_reg = XEXP (base_reg, 0);
10114 }
10115
10116 if (!REG_P (XEXP (operands[3], 0)))
215b30b3 10117 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
94dee231 10118
215b30b3 10119 arith[0] = operands[0];
10120 arith[3] = operands[1];
94dee231 10121
215b30b3 10122 if (val1 < val2)
10123 {
10124 arith[1] = ldm[1];
10125 arith[2] = ldm[2];
10126 }
10127 else
10128 {
10129 arith[1] = ldm[2];
10130 arith[2] = ldm[1];
10131 }
94dee231 10132
10133 ldm[0] = base_reg;
10134 if (val1 !=0 && val2 != 0)
215b30b3 10135 {
cdb1295a 10136 rtx ops[3];
10137
94dee231 10138 if (val1 == 4 || val2 == 4)
10139 /* Other val must be 8, since we know they are adjacent and neither
10140 is zero. */
3ef90e77 10141 output_asm_insn (\"ldmib%?\\t%0, {%1, %2}\", ldm);
cdb1295a 10142 else if (const_ok_for_arm (val1) || const_ok_for_arm (-val1))
94dee231 10143 {
94dee231 10144 ldm[0] = ops[0] = operands[4];
10145 ops[1] = base_reg;
10146 ops[2] = GEN_INT (val1);
10147 output_add_immediate (ops);
10148 if (val1 < val2)
3ef90e77 10149 output_asm_insn (\"ldmia%?\\t%0, {%1, %2}\", ldm);
94dee231 10150 else
3ef90e77 10151 output_asm_insn (\"ldmda%?\\t%0, {%1, %2}\", ldm);
94dee231 10152 }
cdb1295a 10153 else
10154 {
10155 /* Offset is out of range for a single add, so use two ldr. */
10156 ops[0] = ldm[1];
10157 ops[1] = base_reg;
10158 ops[2] = GEN_INT (val1);
10159 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10160 ops[0] = ldm[2];
10161 ops[2] = GEN_INT (val2);
10162 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10163 }
215b30b3 10164 }
94dee231 10165 else if (val1 != 0)
215b30b3 10166 {
215b30b3 10167 if (val1 < val2)
3ef90e77 10168 output_asm_insn (\"ldmda%?\\t%0, {%1, %2}\", ldm);
215b30b3 10169 else
3ef90e77 10170 output_asm_insn (\"ldmia%?\\t%0, {%1, %2}\", ldm);
215b30b3 10171 }
10172 else
10173 {
215b30b3 10174 if (val1 < val2)
3ef90e77 10175 output_asm_insn (\"ldmia%?\\t%0, {%1, %2}\", ldm);
215b30b3 10176 else
3ef90e77 10177 output_asm_insn (\"ldmda%?\\t%0, {%1, %2}\", ldm);
215b30b3 10178 }
10179 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
10180 return \"\";
10181 }"
10182 [(set_attr "length" "12")
10183 (set_attr "predicable" "yes")
a2cd141b 10184 (set_attr "type" "load1")]
215b30b3 10185)
9c08d1fa 10186
9c08d1fa 10187; This pattern is never tried by combine, so do it as a peephole
10188
a0f94409 10189(define_peephole2
372575c7 10190 [(set (match_operand:SI 0 "arm_general_register_operand" "")
10191 (match_operand:SI 1 "arm_general_register_operand" ""))
bd5b4116 10192 (set (reg:CC CC_REGNUM)
aea4c774 10193 (compare:CC (match_dup 1) (const_int 0)))]
372575c7 10194 "TARGET_ARM"
a0f94409 10195 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
10196 (set (match_dup 0) (match_dup 1))])]
10197 ""
0d66636f 10198)
9c08d1fa 10199
9c08d1fa 10200(define_split
10201 [(set (match_operand:SI 0 "s_register_operand" "")
10202 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
10203 (const_int 0))
8fa3ba89 10204 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9c08d1fa 10205 [(match_operand:SI 3 "s_register_operand" "")
10206 (match_operand:SI 4 "arm_rhs_operand" "")]))))
10207 (clobber (match_operand:SI 5 "s_register_operand" ""))]
cffb2a26 10208 "TARGET_ARM"
9c08d1fa 10209 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
10210 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
10211 (match_dup 5)))]
215b30b3 10212 ""
10213)
9c08d1fa 10214
aea4c774 10215;; This split can be used because CC_Z mode implies that the following
10216;; branch will be an equality, or an unsigned inequality, so the sign
10217;; extension is not needed.
9c08d1fa 10218
aea4c774 10219(define_split
bd5b4116 10220 [(set (reg:CC_Z CC_REGNUM)
aea4c774 10221 (compare:CC_Z
10222 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9c08d1fa 10223 (const_int 24))
aea4c774 10224 (match_operand 1 "const_int_operand" "")))
10225 (clobber (match_scratch:SI 2 ""))]
cffb2a26 10226 "TARGET_ARM
10227 && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
10228 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
aea4c774 10229 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
bd5b4116 10230 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
aea4c774 10231 "
9c08d1fa 10232 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
215b30b3 10233 "
10234)
25f905c2 10235;; ??? Check the patterns above for Thumb-2 usefulness
9c08d1fa 10236
87b22bf7 10237(define_expand "prologue"
10238 [(clobber (const_int 0))]
cffb2a26 10239 "TARGET_EITHER"
25f905c2 10240 "if (TARGET_32BIT)
cffb2a26 10241 arm_expand_prologue ();
10242 else
25f905c2 10243 thumb1_expand_prologue ();
87b22bf7 10244 DONE;
cffb2a26 10245 "
10246)
87b22bf7 10247
56d27660 10248(define_expand "epilogue"
4c44712e 10249 [(clobber (const_int 0))]
cffb2a26 10250 "TARGET_EITHER"
56d27660 10251 "
18d50ae6 10252 if (crtl->calls_eh_return)
fb94f18b 10253 emit_insn (gen_force_register_use (gen_rtx_REG (Pmode, 2)));
25f905c2 10254 if (TARGET_THUMB1)
c3635784 10255 {
10256 thumb1_expand_epilogue ();
10257 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
10258 gen_rtvec (1, ret_rtx), VUNSPEC_EPILOGUE));
10259 }
10260 else if (HAVE_return)
10261 {
10262 /* HAVE_return is testing for USE_RETURN_INSN (FALSE). Hence,
10263 no need for explicit testing again. */
10264 emit_jump_insn (gen_return ());
10265 }
10266 else if (TARGET_32BIT)
10267 {
10268 arm_expand_epilogue (true);
10269 }
cffb2a26 10270 DONE;
10271 "
10272)
56d27660 10273
ef5651d0 10274;; Note - although unspec_volatile's USE all hard registers,
10275;; USEs are ignored after relaod has completed. Thus we need
10276;; to add an unspec of the link register to ensure that flow
10277;; does not think that it is unused by the sibcall branch that
10278;; will replace the standard function epilogue.
c3635784 10279(define_expand "sibcall_epilogue"
fb94f18b 10280 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_REGISTER_USE)
c3635784 10281 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
10282 "TARGET_32BIT"
10283 "
10284 arm_expand_epilogue (false);
10285 DONE;
10286 "
1c494086 10287)
10288
cffb2a26 10289(define_expand "eh_epilogue"
7db9af5d 10290 [(use (match_operand:SI 0 "register_operand" ""))
10291 (use (match_operand:SI 1 "register_operand" ""))
10292 (use (match_operand:SI 2 "register_operand" ""))]
cffb2a26 10293 "TARGET_EITHER"
10294 "
215b30b3 10295 {
10296 cfun->machine->eh_epilogue_sp_ofs = operands[1];
0438d37f 10297 if (!REG_P (operands[2]) || REGNO (operands[2]) != 2)
215b30b3 10298 {
10299 rtx ra = gen_rtx_REG (Pmode, 2);
10300
10301 emit_move_insn (ra, operands[2]);
10302 operands[2] = ra;
10303 }
5cf3595a 10304 /* This is a hack -- we may have crystalized the function type too
10305 early. */
10306 cfun->machine->func_type = 0;
215b30b3 10307 }"
10308)
56d27660 10309
9c08d1fa 10310;; This split is only used during output to reduce the number of patterns
10311;; that need assembler instructions adding to them. We allowed the setting
10312;; of the conditions to be implicit during rtl generation so that
10313;; the conditional compare patterns would work. However this conflicts to
8a18b90c 10314;; some extent with the conditional data operations, so we have to split them
9c08d1fa 10315;; up again here.
10316
25f905c2 10317;; ??? Need to audit these splitters for Thumb-2. Why isn't normal
10318;; conditional execution sufficient?
10319
9c08d1fa 10320(define_split
10321 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 10322 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10323 [(match_operand 2 "" "") (match_operand 3 "" "")])
10324 (match_dup 0)
10325 (match_operand 4 "" "")))
bd5b4116 10326 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10327 "TARGET_ARM && reload_completed"
8fa3ba89 10328 [(set (match_dup 5) (match_dup 6))
10329 (cond_exec (match_dup 7)
10330 (set (match_dup 0) (match_dup 4)))]
10331 "
10332 {
3754d046 10333 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8fa3ba89 10334 operands[2], operands[3]);
10335 enum rtx_code rc = GET_CODE (operands[1]);
10336
bd5b4116 10337 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10338 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10339 if (mode == CCFPmode || mode == CCFPEmode)
10340 rc = reverse_condition_maybe_unordered (rc);
10341 else
10342 rc = reverse_condition (rc);
10343
10344 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
10345 }"
10346)
10347
10348(define_split
10349 [(set (match_operand:SI 0 "s_register_operand" "")
10350 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10351 [(match_operand 2 "" "") (match_operand 3 "" "")])
10352 (match_operand 4 "" "")
10353 (match_dup 0)))
bd5b4116 10354 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10355 "TARGET_ARM && reload_completed"
8fa3ba89 10356 [(set (match_dup 5) (match_dup 6))
10357 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
10358 (set (match_dup 0) (match_dup 4)))]
10359 "
10360 {
3754d046 10361 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8fa3ba89 10362 operands[2], operands[3]);
10363
bd5b4116 10364 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10365 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10366 }"
10367)
10368
10369(define_split
10370 [(set (match_operand:SI 0 "s_register_operand" "")
10371 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9c08d1fa 10372 [(match_operand 2 "" "") (match_operand 3 "" "")])
10373 (match_operand 4 "" "")
10374 (match_operand 5 "" "")))
bd5b4116 10375 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10376 "TARGET_ARM && reload_completed"
8fa3ba89 10377 [(set (match_dup 6) (match_dup 7))
10378 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10379 (set (match_dup 0) (match_dup 4)))
10380 (cond_exec (match_dup 8)
10381 (set (match_dup 0) (match_dup 5)))]
10382 "
10383 {
3754d046 10384 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8fa3ba89 10385 operands[2], operands[3]);
10386 enum rtx_code rc = GET_CODE (operands[1]);
10387
bd5b4116 10388 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10389 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10390 if (mode == CCFPmode || mode == CCFPEmode)
10391 rc = reverse_condition_maybe_unordered (rc);
10392 else
10393 rc = reverse_condition (rc);
10394
10395 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10396 }"
10397)
10398
cffb2a26 10399(define_split
10400 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 10401 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
cffb2a26 10402 [(match_operand:SI 2 "s_register_operand" "")
10403 (match_operand:SI 3 "arm_add_operand" "")])
10404 (match_operand:SI 4 "arm_rhs_operand" "")
10405 (not:SI
10406 (match_operand:SI 5 "s_register_operand" ""))))
bd5b4116 10407 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10408 "TARGET_ARM && reload_completed"
cffb2a26 10409 [(set (match_dup 6) (match_dup 7))
f6c53574 10410 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10411 (set (match_dup 0) (match_dup 4)))
10412 (cond_exec (match_dup 8)
10413 (set (match_dup 0) (not:SI (match_dup 5))))]
cffb2a26 10414 "
215b30b3 10415 {
3754d046 10416 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
215b30b3 10417 operands[2], operands[3]);
f6c53574 10418 enum rtx_code rc = GET_CODE (operands[1]);
cffb2a26 10419
bd5b4116 10420 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
1a83b3ff 10421 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
f6c53574 10422 if (mode == CCFPmode || mode == CCFPEmode)
10423 rc = reverse_condition_maybe_unordered (rc);
10424 else
10425 rc = reverse_condition (rc);
10426
10427 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
215b30b3 10428 }"
10429)
cffb2a26 10430
10431(define_insn "*cond_move_not"
10432 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10433 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
cffb2a26 10434 [(match_operand 3 "cc_register" "") (const_int 0)])
10435 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10436 (not:SI
10437 (match_operand:SI 2 "s_register_operand" "r,r"))))]
10438 "TARGET_ARM"
10439 "@
10440 mvn%D4\\t%0, %2
10441 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
0d66636f 10442 [(set_attr "conds" "use")
1b7da4ac 10443 (set_attr "type" "mvn_reg,multiple")
0d66636f 10444 (set_attr "length" "4,8")]
10445)
cffb2a26 10446
9c08d1fa 10447;; The next two patterns occur when an AND operation is followed by a
10448;; scc insn sequence
10449
f7fbdd4a 10450(define_insn "*sign_extract_onebit"
9c08d1fa 10451 [(set (match_operand:SI 0 "s_register_operand" "=r")
10452 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10453 (const_int 1)
ed750274 10454 (match_operand:SI 2 "const_int_operand" "n")))
10455 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10456 "TARGET_ARM"
9c08d1fa 10457 "*
0d66636f 10458 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10459 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
10460 return \"mvnne\\t%0, #0\";
10461 "
10462 [(set_attr "conds" "clob")
1b7da4ac 10463 (set_attr "length" "8")
10464 (set_attr "type" "multiple")]
0d66636f 10465)
9c08d1fa 10466
f7fbdd4a 10467(define_insn "*not_signextract_onebit"
9c08d1fa 10468 [(set (match_operand:SI 0 "s_register_operand" "=r")
10469 (not:SI
10470 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10471 (const_int 1)
ed750274 10472 (match_operand:SI 2 "const_int_operand" "n"))))
10473 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10474 "TARGET_ARM"
9c08d1fa 10475 "*
0d66636f 10476 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10477 output_asm_insn (\"tst\\t%1, %2\", operands);
10478 output_asm_insn (\"mvneq\\t%0, #0\", operands);
10479 return \"movne\\t%0, #0\";
10480 "
10481 [(set_attr "conds" "clob")
1b7da4ac 10482 (set_attr "length" "12")
10483 (set_attr "type" "multiple")]
0d66636f 10484)
25f905c2 10485;; ??? The above patterns need auditing for Thumb-2
87b22bf7 10486
0d66636f 10487;; Push multiple registers to the stack. Registers are in parallel (use ...)
10488;; expressions. For simplicity, the first register is also in the unspec
10489;; part.
08508cbf 10490;; To avoid the usage of GNU extension, the length attribute is computed
10491;; in a C function arm_attr_length_push_multi.
f7fbdd4a 10492(define_insn "*push_multi"
87b22bf7 10493 [(match_parallel 2 "multi_register_push"
7571d3f7 10494 [(set (match_operand:BLK 0 "push_mult_memory_operand" "")
3cc80a30 10495 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "")]
e1159bbe 10496 UNSPEC_PUSH_MULT))])]
7571d3f7 10497 ""
87b22bf7 10498 "*
215b30b3 10499 {
10500 int num_saves = XVECLEN (operands[2], 0);
ed593f11 10501
215b30b3 10502 /* For the StrongARM at least it is faster to
25f905c2 10503 use STR to store only a single register.
542d5028 10504 In Thumb mode always use push, and the assembler will pick
10505 something appropriate. */
25f905c2 10506 if (num_saves == 1 && TARGET_ARM)
61309563 10507 output_asm_insn (\"str%?\\t%1, [%m0, #-4]!\", operands);
215b30b3 10508 else
10509 {
10510 int i;
10511 char pattern[100];
ed593f11 10512
3ef90e77 10513 if (TARGET_32BIT)
61309563 10514 strcpy (pattern, \"push%?\\t{%1\");
25f905c2 10515 else
10516 strcpy (pattern, \"push\\t{%1\");
215b30b3 10517
6079f055 10518 for (i = 1; i < num_saves; i++)
215b30b3 10519 {
10520 strcat (pattern, \", %|\");
10521 strcat (pattern,
10522 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
10523 }
10524
10525 strcat (pattern, \"}\");
10526 output_asm_insn (pattern, operands);
10527 }
10528
10529 return \"\";
10530 }"
a6864a24 10531 [(set_attr "type" "store4")
10532 (set (attr "length")
08508cbf 10533 (symbol_ref "arm_attr_length_push_multi (operands[2], operands[1])"))]
215b30b3 10534)
f7fbdd4a 10535
4c58c898 10536(define_insn "stack_tie"
10537 [(set (mem:BLK (scratch))
aaa37ad6 10538 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "rk")
10539 (match_operand:SI 1 "s_register_operand" "rk")]
4c58c898 10540 UNSPEC_PRLG_STK))]
10541 ""
10542 ""
1b7da4ac 10543 [(set_attr "length" "0")
10544 (set_attr "type" "block")]
4c58c898 10545)
10546
426be8c5 10547;; Pop (as used in epilogue RTL)
10548;;
10549(define_insn "*load_multiple_with_writeback"
10550 [(match_parallel 0 "load_multiple_operation"
10551 [(set (match_operand:SI 1 "s_register_operand" "+rk")
10552 (plus:SI (match_dup 1)
809003b3 10553 (match_operand:SI 2 "const_int_I_operand" "I")))
426be8c5 10554 (set (match_operand:SI 3 "s_register_operand" "=rk")
10555 (mem:SI (match_dup 1)))
10556 ])]
10557 "TARGET_32BIT && (reload_in_progress || reload_completed)"
10558 "*
10559 {
10560 arm_output_multireg_pop (operands, /*return_pc=*/false,
10561 /*cond=*/const_true_rtx,
10562 /*reverse=*/false,
10563 /*update=*/true);
10564 return \"\";
10565 }
10566 "
10567 [(set_attr "type" "load4")
10568 (set_attr "predicable" "yes")]
10569)
10570
10571;; Pop with return (as used in epilogue RTL)
10572;;
10573;; This instruction is generated when the registers are popped at the end of
10574;; epilogue. Here, instead of popping the value into LR and then generating
10575;; jump to LR, value is popped into PC directly. Hence, the pattern is combined
10576;; with (return).
10577(define_insn "*pop_multiple_with_writeback_and_return"
10578 [(match_parallel 0 "pop_multiple_return"
10579 [(return)
10580 (set (match_operand:SI 1 "s_register_operand" "+rk")
10581 (plus:SI (match_dup 1)
809003b3 10582 (match_operand:SI 2 "const_int_I_operand" "I")))
426be8c5 10583 (set (match_operand:SI 3 "s_register_operand" "=rk")
10584 (mem:SI (match_dup 1)))
10585 ])]
10586 "TARGET_32BIT && (reload_in_progress || reload_completed)"
10587 "*
10588 {
10589 arm_output_multireg_pop (operands, /*return_pc=*/true,
10590 /*cond=*/const_true_rtx,
10591 /*reverse=*/false,
10592 /*update=*/true);
10593 return \"\";
10594 }
10595 "
10596 [(set_attr "type" "load4")
10597 (set_attr "predicable" "yes")]
10598)
10599
10600(define_insn "*pop_multiple_with_return"
10601 [(match_parallel 0 "pop_multiple_return"
10602 [(return)
10603 (set (match_operand:SI 2 "s_register_operand" "=rk")
10604 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
10605 ])]
10606 "TARGET_32BIT && (reload_in_progress || reload_completed)"
10607 "*
10608 {
10609 arm_output_multireg_pop (operands, /*return_pc=*/true,
10610 /*cond=*/const_true_rtx,
10611 /*reverse=*/false,
10612 /*update=*/false);
10613 return \"\";
10614 }
10615 "
10616 [(set_attr "type" "load4")
10617 (set_attr "predicable" "yes")]
10618)
10619
10620;; Load into PC and return
10621(define_insn "*ldr_with_return"
10622 [(return)
10623 (set (reg:SI PC_REGNUM)
10624 (mem:SI (post_inc:SI (match_operand:SI 0 "s_register_operand" "+rk"))))]
10625 "TARGET_32BIT && (reload_in_progress || reload_completed)"
10626 "ldr%?\t%|pc, [%0], #4"
10627 [(set_attr "type" "load1")
10628 (set_attr "predicable" "yes")]
10629)
1a0b0f12 10630;; Pop for floating point registers (as used in epilogue RTL)
10631(define_insn "*vfp_pop_multiple_with_writeback"
10632 [(match_parallel 0 "pop_multiple_fp"
10633 [(set (match_operand:SI 1 "s_register_operand" "+rk")
10634 (plus:SI (match_dup 1)
809003b3 10635 (match_operand:SI 2 "const_int_I_operand" "I")))
2f2163a4 10636 (set (match_operand:DF 3 "vfp_hard_register_operand" "")
1a0b0f12 10637 (mem:DF (match_dup 1)))])]
10638 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
10639 "*
10640 {
10641 int num_regs = XVECLEN (operands[0], 0);
10642 char pattern[100];
10643 rtx op_list[2];
b34d8dac 10644 strcpy (pattern, \"vldm\\t\");
1a0b0f12 10645 strcat (pattern, reg_names[REGNO (SET_DEST (XVECEXP (operands[0], 0, 0)))]);
10646 strcat (pattern, \"!, {\");
10647 op_list[0] = XEXP (XVECEXP (operands[0], 0, 1), 0);
10648 strcat (pattern, \"%P0\");
10649 if ((num_regs - 1) > 1)
10650 {
10651 strcat (pattern, \"-%P1\");
10652 op_list [1] = XEXP (XVECEXP (operands[0], 0, num_regs - 1), 0);
10653 }
10654
10655 strcat (pattern, \"}\");
10656 output_asm_insn (pattern, op_list);
10657 return \"\";
10658 }
10659 "
10660 [(set_attr "type" "load4")
10661 (set_attr "conds" "unconditional")
10662 (set_attr "predicable" "no")]
10663)
10664
f7fbdd4a 10665;; Special patterns for dealing with the constant pool
10666
cffb2a26 10667(define_insn "align_4"
e1159bbe 10668 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
cffb2a26 10669 "TARGET_EITHER"
f7fbdd4a 10670 "*
cffb2a26 10671 assemble_align (32);
f7fbdd4a 10672 return \"\";
cffb2a26 10673 "
1b7da4ac 10674 [(set_attr "type" "no_insn")]
cffb2a26 10675)
f7fbdd4a 10676
755eb2b4 10677(define_insn "align_8"
10678 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
f9273c43 10679 "TARGET_EITHER"
755eb2b4 10680 "*
10681 assemble_align (64);
10682 return \"\";
10683 "
1b7da4ac 10684 [(set_attr "type" "no_insn")]
755eb2b4 10685)
10686
cffb2a26 10687(define_insn "consttable_end"
e1159bbe 10688 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
cffb2a26 10689 "TARGET_EITHER"
f7fbdd4a 10690 "*
cffb2a26 10691 making_const_table = FALSE;
f7fbdd4a 10692 return \"\";
cffb2a26 10693 "
1b7da4ac 10694 [(set_attr "type" "no_insn")]
cffb2a26 10695)
f7fbdd4a 10696
0e207eb8 10697(define_insn "consttable_1"
10698 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
10699 "TARGET_EITHER"
10700 "*
10701 making_const_table = TRUE;
10702 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
10703 assemble_zeros (3);
10704 return \"\";
10705 "
10706 [(set_attr "length" "4")
10707 (set_attr "type" "no_insn")]
10708)
10709
10710(define_insn "consttable_2"
10711 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
10712 "TARGET_EITHER"
10713 "*
10714 {
10715 rtx x = operands[0];
10716 making_const_table = TRUE;
10717 switch (GET_MODE_CLASS (GET_MODE (x)))
10718 {
10719 case MODE_FLOAT:
10720 arm_emit_fp16_const (x);
10721 break;
10722 default:
10723 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
10724 assemble_zeros (2);
10725 break;
10726 }
10727 return \"\";
10728 }"
10729 [(set_attr "length" "4")
10730 (set_attr "type" "no_insn")]
10731)
10732
cffb2a26 10733(define_insn "consttable_4"
e1159bbe 10734 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
cffb2a26 10735 "TARGET_EITHER"
10736 "*
10737 {
9b8516be 10738 rtx x = operands[0];
cffb2a26 10739 making_const_table = TRUE;
9b8516be 10740 switch (GET_MODE_CLASS (GET_MODE (x)))
cffb2a26 10741 {
10742 case MODE_FLOAT:
945f7b03 10743 assemble_real (*CONST_DOUBLE_REAL_VALUE (x), GET_MODE (x),
10744 BITS_PER_WORD);
10745 break;
cffb2a26 10746 default:
7b04c5d5 10747 /* XXX: Sometimes gcc does something really dumb and ends up with
10748 a HIGH in a constant pool entry, usually because it's trying to
10749 load into a VFP register. We know this will always be used in
10750 combination with a LO_SUM which ignores the high bits, so just
10751 strip off the HIGH. */
10752 if (GET_CODE (x) == HIGH)
10753 x = XEXP (x, 0);
9b8516be 10754 assemble_integer (x, 4, BITS_PER_WORD, 1);
10755 mark_symbol_refs_as_used (x);
cffb2a26 10756 break;
10757 }
10758 return \"\";
10759 }"
1b7da4ac 10760 [(set_attr "length" "4")
10761 (set_attr "type" "no_insn")]
cffb2a26 10762)
10763
10764(define_insn "consttable_8"
e1159bbe 10765 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
cffb2a26 10766 "TARGET_EITHER"
10767 "*
10768 {
10769 making_const_table = TRUE;
10770 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10771 {
945f7b03 10772 case MODE_FLOAT:
10773 assemble_real (*CONST_DOUBLE_REAL_VALUE (operands[0]),
10774 GET_MODE (operands[0]), BITS_PER_WORD);
10775 break;
cffb2a26 10776 default:
09d688ff 10777 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
cffb2a26 10778 break;
10779 }
10780 return \"\";
10781 }"
1b7da4ac 10782 [(set_attr "length" "8")
10783 (set_attr "type" "no_insn")]
cffb2a26 10784)
10785
d98a3884 10786(define_insn "consttable_16"
10787 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_16)]
10788 "TARGET_EITHER"
10789 "*
10790 {
10791 making_const_table = TRUE;
10792 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10793 {
945f7b03 10794 case MODE_FLOAT:
10795 assemble_real (*CONST_DOUBLE_REAL_VALUE (operands[0]),
10796 GET_MODE (operands[0]), BITS_PER_WORD);
10797 break;
d98a3884 10798 default:
10799 assemble_integer (operands[0], 16, BITS_PER_WORD, 1);
10800 break;
10801 }
10802 return \"\";
10803 }"
1b7da4ac 10804 [(set_attr "length" "16")
10805 (set_attr "type" "no_insn")]
d98a3884 10806)
10807
331beb1a 10808;; V5 Instructions,
10809
8f4be2be 10810(define_insn "clzsi2"
10811 [(set (match_operand:SI 0 "s_register_operand" "=r")
10812 (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 10813 "TARGET_32BIT && arm_arch5"
ee7cbe0e 10814 "clz%?\\t%0, %1"
bcaec148 10815 [(set_attr "predicable" "yes")
4a510717 10816 (set_attr "predicable_short_it" "no")
bebe9bbb 10817 (set_attr "type" "clz")])
331beb1a 10818
099ad98b 10819(define_insn "rbitsi2"
10820 [(set (match_operand:SI 0 "s_register_operand" "=r")
10821 (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")] UNSPEC_RBIT))]
10822 "TARGET_32BIT && arm_arch_thumb2"
10823 "rbit%?\\t%0, %1"
10824 [(set_attr "predicable" "yes")
4a510717 10825 (set_attr "predicable_short_it" "no")
bebe9bbb 10826 (set_attr "type" "clz")])
099ad98b 10827
10828(define_expand "ctzsi2"
10829 [(set (match_operand:SI 0 "s_register_operand" "")
10830 (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
10831 "TARGET_32BIT && arm_arch_thumb2"
10832 "
30191172 10833 {
10834 rtx tmp = gen_reg_rtx (SImode);
10835 emit_insn (gen_rbitsi2 (tmp, operands[1]));
10836 emit_insn (gen_clzsi2 (operands[0], tmp));
10837 }
099ad98b 10838 DONE;
10839 "
10840)
10841
e1159bbe 10842;; V5E instructions.
331beb1a 10843
10844(define_insn "prefetch"
f4e79814 10845 [(prefetch (match_operand:SI 0 "address_operand" "p")
10846 (match_operand:SI 1 "" "")
10847 (match_operand:SI 2 "" ""))]
25f905c2 10848 "TARGET_32BIT && arm_arch5e"
1b7da4ac 10849 "pld\\t%a0"
10850 [(set_attr "type" "load1")]
10851)
331beb1a 10852
0d66636f 10853;; General predication pattern
10854
10855(define_cond_exec
10856 [(match_operator 0 "arm_comparison_operator"
10857 [(match_operand 1 "cc_register" "")
10858 (const_int 0)])]
580f4c48 10859 "TARGET_32BIT
10860 && (!TARGET_NO_VOLATILE_CE || !volatile_refs_p (PATTERN (insn)))"
0d66636f 10861 ""
c7a58118 10862[(set_attr "predicated" "yes")]
0d66636f 10863)
10864
fb94f18b 10865(define_insn "force_register_use"
10866 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_REGISTER_USE)]
063a05c7 10867 ""
fb94f18b 10868 "%@ %0 needed"
1b7da4ac 10869 [(set_attr "length" "0")
10870 (set_attr "type" "no_insn")]
063a05c7 10871)
7db9af5d 10872
4c44712e 10873
10874;; Patterns for exception handling
10875
10876(define_expand "eh_return"
10877 [(use (match_operand 0 "general_operand" ""))]
10878 "TARGET_EITHER"
10879 "
10880 {
25f905c2 10881 if (TARGET_32BIT)
4c44712e 10882 emit_insn (gen_arm_eh_return (operands[0]));
10883 else
10884 emit_insn (gen_thumb_eh_return (operands[0]));
10885 DONE;
10886 }"
10887)
10888
10889;; We can't expand this before we know where the link register is stored.
10890(define_insn_and_split "arm_eh_return"
10891 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
10892 VUNSPEC_EH_RETURN)
10893 (clobber (match_scratch:SI 1 "=&r"))]
10894 "TARGET_ARM"
10895 "#"
10896 "&& reload_completed"
10897 [(const_int 0)]
10898 "
10899 {
10900 arm_set_return_address (operands[0], operands[1]);
10901 DONE;
10902 }"
10903)
10904
f655717d 10905\f
10906;; TLS support
10907
10908(define_insn "load_tp_hard"
10909 [(set (match_operand:SI 0 "register_operand" "=r")
10910 (unspec:SI [(const_int 0)] UNSPEC_TLS))]
10911 "TARGET_HARD_TP"
10912 "mrc%?\\tp15, 0, %0, c13, c0, 3\\t@ load_tp_hard"
1b7da4ac 10913 [(set_attr "predicable" "yes")
4b5d7374 10914 (set_attr "type" "mrs")]
f655717d 10915)
10916
10917;; Doesn't clobber R1-R3. Must use r0 for the first operand.
10918(define_insn "load_tp_soft"
10919 [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
10920 (clobber (reg:SI LR_REGNUM))
10921 (clobber (reg:SI IP_REGNUM))
10922 (clobber (reg:CC CC_REGNUM))]
10923 "TARGET_SOFT_TP"
10924 "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
1b7da4ac 10925 [(set_attr "conds" "clob")
10926 (set_attr "type" "branch")]
f655717d 10927)
10928
f41e4452 10929;; tls descriptor call
10930(define_insn "tlscall"
10931 [(set (reg:SI R0_REGNUM)
10932 (unspec:SI [(reg:SI R0_REGNUM)
10933 (match_operand:SI 0 "" "X")
10934 (match_operand 1 "" "")] UNSPEC_TLS))
10935 (clobber (reg:SI R1_REGNUM))
10936 (clobber (reg:SI LR_REGNUM))
10937 (clobber (reg:SI CC_REGNUM))]
10938 "TARGET_GNU2_TLS"
10939 {
10940 targetm.asm_out.internal_label (asm_out_file, "LPIC",
10941 INTVAL (operands[1]));
10942 return "bl\\t%c0(tlscall)";
10943 }
10944 [(set_attr "conds" "clob")
1b7da4ac 10945 (set_attr "length" "4")
10946 (set_attr "type" "branch")]
f41e4452 10947)
10948
1fe0edab 10949;; For thread pointer builtin
10950(define_expand "get_thread_pointersi"
10951 [(match_operand:SI 0 "s_register_operand" "=r")]
10952 ""
10953 "
10954 {
10955 arm_load_tp (operands[0]);
10956 DONE;
10957 }")
10958
f41e4452 10959;;
10960
aabe09ac 10961;; We only care about the lower 16 bits of the constant
10962;; being inserted into the upper 16 bits of the register.
eca5c984 10963(define_insn "*arm_movtas_ze"
10964 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
10965 (const_int 16)
10966 (const_int 16))
10967 (match_operand:SI 1 "const_int_operand" ""))]
181ab277 10968 "arm_arch_thumb2"
aabe09ac 10969 "movt%?\t%0, %L1"
eca5c984 10970 [(set_attr "predicable" "yes")
7c36fe71 10971 (set_attr "predicable_short_it" "no")
1b7da4ac 10972 (set_attr "length" "4")
282b4c75 10973 (set_attr "type" "alu_sreg")]
eca5c984 10974)
10975
c0fc3696 10976(define_insn "*arm_rev"
a486b499 10977 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
10978 (bswap:SI (match_operand:SI 1 "s_register_operand" "l,l,r")))]
10979 "arm_arch6"
10980 "@
10981 rev\t%0, %1
10982 rev%?\t%0, %1
10983 rev%?\t%0, %1"
10984 [(set_attr "arch" "t1,t2,32")
1b7da4ac 10985 (set_attr "length" "2,2,4")
4a510717 10986 (set_attr "predicable" "no,yes,yes")
10987 (set_attr "predicable_short_it" "no")
1b7da4ac 10988 (set_attr "type" "rev")]
ff82f757 10989)
10990
10991(define_expand "arm_legacy_rev"
10992 [(set (match_operand:SI 2 "s_register_operand" "")
10993 (xor:SI (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
10994 (const_int 16))
10995 (match_dup 1)))
10996 (set (match_dup 2)
10997 (lshiftrt:SI (match_dup 2)
10998 (const_int 8)))
10999 (set (match_operand:SI 3 "s_register_operand" "")
11000 (rotatert:SI (match_dup 1)
11001 (const_int 8)))
11002 (set (match_dup 2)
11003 (and:SI (match_dup 2)
11004 (const_int -65281)))
11005 (set (match_operand:SI 0 "s_register_operand" "")
11006 (xor:SI (match_dup 3)
11007 (match_dup 2)))]
11008 "TARGET_32BIT"
11009 ""
11010)
11011
11012;; Reuse temporaries to keep register pressure down.
11013(define_expand "thumb_legacy_rev"
11014 [(set (match_operand:SI 2 "s_register_operand" "")
11015 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
11016 (const_int 24)))
11017 (set (match_operand:SI 3 "s_register_operand" "")
11018 (lshiftrt:SI (match_dup 1)
11019 (const_int 24)))
11020 (set (match_dup 3)
11021 (ior:SI (match_dup 3)
11022 (match_dup 2)))
11023 (set (match_operand:SI 4 "s_register_operand" "")
11024 (const_int 16))
11025 (set (match_operand:SI 5 "s_register_operand" "")
11026 (rotatert:SI (match_dup 1)
11027 (match_dup 4)))
11028 (set (match_dup 2)
11029 (ashift:SI (match_dup 5)
11030 (const_int 24)))
11031 (set (match_dup 5)
11032 (lshiftrt:SI (match_dup 5)
11033 (const_int 24)))
11034 (set (match_dup 5)
11035 (ior:SI (match_dup 5)
11036 (match_dup 2)))
11037 (set (match_dup 5)
11038 (rotatert:SI (match_dup 5)
11039 (match_dup 4)))
11040 (set (match_operand:SI 0 "s_register_operand" "")
11041 (ior:SI (match_dup 5)
11042 (match_dup 3)))]
11043 "TARGET_THUMB"
11044 ""
11045)
11046
62e39b06 11047;; ARM-specific expansion of signed mod by power of 2
11048;; using conditional negate.
11049;; For r0 % n where n is a power of 2 produce:
11050;; rsbs r1, r0, #0
11051;; and r0, r0, #(n - 1)
11052;; and r1, r1, #(n - 1)
11053;; rsbpl r0, r1, #0
11054
11055(define_expand "modsi3"
11056 [(match_operand:SI 0 "register_operand" "")
11057 (match_operand:SI 1 "register_operand" "")
11058 (match_operand:SI 2 "const_int_operand" "")]
11059 "TARGET_32BIT"
11060 {
11061 HOST_WIDE_INT val = INTVAL (operands[2]);
11062
11063 if (val <= 0
11064 || exact_log2 (val) <= 0)
11065 FAIL;
11066
11067 rtx mask = GEN_INT (val - 1);
11068
11069 /* In the special case of x0 % 2 we can do the even shorter:
11070 cmp r0, #0
11071 and r0, r0, #1
11072 rsblt r0, r0, #0. */
11073
11074 if (val == 2)
11075 {
11076 rtx cc_reg = arm_gen_compare_reg (LT,
11077 operands[1], const0_rtx, NULL_RTX);
11078 rtx cond = gen_rtx_LT (SImode, cc_reg, const0_rtx);
11079 rtx masked = gen_reg_rtx (SImode);
11080
11081 emit_insn (gen_andsi3 (masked, operands[1], mask));
11082 emit_move_insn (operands[0],
11083 gen_rtx_IF_THEN_ELSE (SImode, cond,
11084 gen_rtx_NEG (SImode,
11085 masked),
11086 masked));
11087 DONE;
11088 }
11089
11090 rtx neg_op = gen_reg_rtx (SImode);
11091 rtx_insn *insn = emit_insn (gen_subsi3_compare0 (neg_op, const0_rtx,
11092 operands[1]));
11093
11094 /* Extract the condition register and mode. */
11095 rtx cmp = XVECEXP (PATTERN (insn), 0, 0);
11096 rtx cc_reg = SET_DEST (cmp);
11097 rtx cond = gen_rtx_GE (SImode, cc_reg, const0_rtx);
11098
11099 emit_insn (gen_andsi3 (operands[0], operands[1], mask));
11100
11101 rtx masked_neg = gen_reg_rtx (SImode);
11102 emit_insn (gen_andsi3 (masked_neg, neg_op, mask));
11103
11104 /* We want a conditional negate here, but emitting COND_EXEC rtxes
11105 during expand does not always work. Do an IF_THEN_ELSE instead. */
11106 emit_move_insn (operands[0],
11107 gen_rtx_IF_THEN_ELSE (SImode, cond,
11108 gen_rtx_NEG (SImode, masked_neg),
11109 operands[0]));
11110
11111
11112 DONE;
11113 }
11114)
11115
ff82f757 11116(define_expand "bswapsi2"
11117 [(set (match_operand:SI 0 "s_register_operand" "=r")
11118 (bswap:SI (match_operand:SI 1 "s_register_operand" "r")))]
8d1af482 11119"TARGET_EITHER && (arm_arch6 || !optimize_size)"
ff82f757 11120"
8d1af482 11121 if (!arm_arch6)
11122 {
11123 rtx op2 = gen_reg_rtx (SImode);
11124 rtx op3 = gen_reg_rtx (SImode);
ff82f757 11125
8d1af482 11126 if (TARGET_THUMB)
11127 {
11128 rtx op4 = gen_reg_rtx (SImode);
11129 rtx op5 = gen_reg_rtx (SImode);
ff82f757 11130
8d1af482 11131 emit_insn (gen_thumb_legacy_rev (operands[0], operands[1],
11132 op2, op3, op4, op5));
11133 }
11134 else
11135 {
11136 emit_insn (gen_arm_legacy_rev (operands[0], operands[1],
11137 op2, op3));
11138 }
ff82f757 11139
8d1af482 11140 DONE;
11141 }
ff82f757 11142 "
11143)
11144
a486b499 11145;; bswap16 patterns: use revsh and rev16 instructions for the signed
11146;; and unsigned variants, respectively. For rev16, expose
11147;; byte-swapping in the lower 16 bits only.
11148(define_insn "*arm_revsh"
11149 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
11150 (sign_extend:SI (bswap:HI (match_operand:HI 1 "s_register_operand" "l,l,r"))))]
11151 "arm_arch6"
11152 "@
11153 revsh\t%0, %1
11154 revsh%?\t%0, %1
11155 revsh%?\t%0, %1"
11156 [(set_attr "arch" "t1,t2,32")
1b7da4ac 11157 (set_attr "length" "2,2,4")
11158 (set_attr "type" "rev")]
a486b499 11159)
11160
11161(define_insn "*arm_rev16"
11162 [(set (match_operand:HI 0 "s_register_operand" "=l,l,r")
11163 (bswap:HI (match_operand:HI 1 "s_register_operand" "l,l,r")))]
11164 "arm_arch6"
11165 "@
11166 rev16\t%0, %1
11167 rev16%?\t%0, %1
11168 rev16%?\t%0, %1"
11169 [(set_attr "arch" "t1,t2,32")
1b7da4ac 11170 (set_attr "length" "2,2,4")
11171 (set_attr "type" "rev")]
09f69e55 11172)
11173
11174;; There are no canonicalisation rules for the position of the lshiftrt, ashift
11175;; operations within an IOR/AND RTX, therefore we have two patterns matching
11176;; each valid permutation.
11177
11178(define_insn "arm_rev16si2"
11179 [(set (match_operand:SI 0 "register_operand" "=l,l,r")
11180 (ior:SI (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "l,l,r")
11181 (const_int 8))
11182 (match_operand:SI 3 "const_int_operand" "n,n,n"))
11183 (and:SI (lshiftrt:SI (match_dup 1)
11184 (const_int 8))
11185 (match_operand:SI 2 "const_int_operand" "n,n,n"))))]
11186 "arm_arch6
11187 && aarch_rev16_shleft_mask_imm_p (operands[3], SImode)
11188 && aarch_rev16_shright_mask_imm_p (operands[2], SImode)"
11189 "rev16\\t%0, %1"
11190 [(set_attr "arch" "t1,t2,32")
11191 (set_attr "length" "2,2,4")
11192 (set_attr "type" "rev")]
11193)
11194
11195(define_insn "arm_rev16si2_alt"
11196 [(set (match_operand:SI 0 "register_operand" "=l,l,r")
11197 (ior:SI (and:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,l,r")
11198 (const_int 8))
11199 (match_operand:SI 2 "const_int_operand" "n,n,n"))
11200 (and:SI (ashift:SI (match_dup 1)
11201 (const_int 8))
11202 (match_operand:SI 3 "const_int_operand" "n,n,n"))))]
11203 "arm_arch6
11204 && aarch_rev16_shleft_mask_imm_p (operands[3], SImode)
11205 && aarch_rev16_shright_mask_imm_p (operands[2], SImode)"
11206 "rev16\\t%0, %1"
11207 [(set_attr "arch" "t1,t2,32")
11208 (set_attr "length" "2,2,4")
11209 (set_attr "type" "rev")]
a486b499 11210)
11211
11212(define_expand "bswaphi2"
11213 [(set (match_operand:HI 0 "s_register_operand" "=r")
11214 (bswap:HI (match_operand:HI 1 "s_register_operand" "r")))]
11215"arm_arch6"
11216""
11217)
11218
1653cf17 11219;; Patterns for LDRD/STRD in Thumb2 mode
11220
11221(define_insn "*thumb2_ldrd"
11222 [(set (match_operand:SI 0 "s_register_operand" "=r")
11223 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
11224 (match_operand:SI 2 "ldrd_strd_offset_operand" "Do"))))
11225 (set (match_operand:SI 3 "s_register_operand" "=r")
11226 (mem:SI (plus:SI (match_dup 1)
11227 (match_operand:SI 4 "const_int_operand" ""))))]
11228 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11229 && current_tune->prefer_ldrd_strd
11230 && ((INTVAL (operands[2]) + 4) == INTVAL (operands[4]))
11231 && (operands_ok_ldrd_strd (operands[0], operands[3],
11232 operands[1], INTVAL (operands[2]),
11233 false, true))"
11234 "ldrd%?\t%0, %3, [%1, %2]"
11235 [(set_attr "type" "load2")
d952d547 11236 (set_attr "predicable" "yes")
11237 (set_attr "predicable_short_it" "no")])
1653cf17 11238
11239(define_insn "*thumb2_ldrd_base"
11240 [(set (match_operand:SI 0 "s_register_operand" "=r")
11241 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
11242 (set (match_operand:SI 2 "s_register_operand" "=r")
11243 (mem:SI (plus:SI (match_dup 1)
11244 (const_int 4))))]
11245 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11246 && current_tune->prefer_ldrd_strd
11247 && (operands_ok_ldrd_strd (operands[0], operands[2],
11248 operands[1], 0, false, true))"
11249 "ldrd%?\t%0, %2, [%1]"
11250 [(set_attr "type" "load2")
d952d547 11251 (set_attr "predicable" "yes")
11252 (set_attr "predicable_short_it" "no")])
1653cf17 11253
11254(define_insn "*thumb2_ldrd_base_neg"
11255 [(set (match_operand:SI 0 "s_register_operand" "=r")
11256 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
11257 (const_int -4))))
11258 (set (match_operand:SI 2 "s_register_operand" "=r")
11259 (mem:SI (match_dup 1)))]
11260 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11261 && current_tune->prefer_ldrd_strd
11262 && (operands_ok_ldrd_strd (operands[0], operands[2],
11263 operands[1], -4, false, true))"
11264 "ldrd%?\t%0, %2, [%1, #-4]"
11265 [(set_attr "type" "load2")
d952d547 11266 (set_attr "predicable" "yes")
11267 (set_attr "predicable_short_it" "no")])
1653cf17 11268
11269(define_insn "*thumb2_strd"
11270 [(set (mem:SI (plus:SI (match_operand:SI 0 "s_register_operand" "rk")
11271 (match_operand:SI 1 "ldrd_strd_offset_operand" "Do")))
11272 (match_operand:SI 2 "s_register_operand" "r"))
11273 (set (mem:SI (plus:SI (match_dup 0)
11274 (match_operand:SI 3 "const_int_operand" "")))
11275 (match_operand:SI 4 "s_register_operand" "r"))]
11276 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11277 && current_tune->prefer_ldrd_strd
11278 && ((INTVAL (operands[1]) + 4) == INTVAL (operands[3]))
11279 && (operands_ok_ldrd_strd (operands[2], operands[4],
11280 operands[0], INTVAL (operands[1]),
11281 false, false))"
11282 "strd%?\t%2, %4, [%0, %1]"
11283 [(set_attr "type" "store2")
d952d547 11284 (set_attr "predicable" "yes")
11285 (set_attr "predicable_short_it" "no")])
1653cf17 11286
11287(define_insn "*thumb2_strd_base"
11288 [(set (mem:SI (match_operand:SI 0 "s_register_operand" "rk"))
11289 (match_operand:SI 1 "s_register_operand" "r"))
11290 (set (mem:SI (plus:SI (match_dup 0)
11291 (const_int 4)))
11292 (match_operand:SI 2 "s_register_operand" "r"))]
11293 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11294 && current_tune->prefer_ldrd_strd
11295 && (operands_ok_ldrd_strd (operands[1], operands[2],
11296 operands[0], 0, false, false))"
11297 "strd%?\t%1, %2, [%0]"
11298 [(set_attr "type" "store2")
d952d547 11299 (set_attr "predicable" "yes")
11300 (set_attr "predicable_short_it" "no")])
1653cf17 11301
11302(define_insn "*thumb2_strd_base_neg"
11303 [(set (mem:SI (plus:SI (match_operand:SI 0 "s_register_operand" "rk")
11304 (const_int -4)))
11305 (match_operand:SI 1 "s_register_operand" "r"))
11306 (set (mem:SI (match_dup 0))
11307 (match_operand:SI 2 "s_register_operand" "r"))]
11308 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11309 && current_tune->prefer_ldrd_strd
11310 && (operands_ok_ldrd_strd (operands[1], operands[2],
11311 operands[0], -4, false, false))"
11312 "strd%?\t%1, %2, [%0, #-4]"
11313 [(set_attr "type" "store2")
d952d547 11314 (set_attr "predicable" "yes")
11315 (set_attr "predicable_short_it" "no")])
1653cf17 11316
2a0c73f2 11317;; ARMv8 CRC32 instructions.
11318(define_insn "<crc_variant>"
11319 [(set (match_operand:SI 0 "s_register_operand" "=r")
11320 (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")
11321 (match_operand:<crc_mode> 2 "s_register_operand" "r")]
11322 CRC))]
11323 "TARGET_CRC32"
11324 "<crc_variant>\\t%0, %1, %2"
11325 [(set_attr "type" "crc")
11326 (set_attr "conds" "unconditional")]
11327)
1653cf17 11328
353cf59a 11329;; Load the load/store double peephole optimizations.
11330(include "ldrdstrd.md")
11331
320ea44d 11332;; Load the load/store multiple patterns
11333(include "ldmstm.md")
426be8c5 11334
11335;; Patterns in ldmstm.md don't cover more than 4 registers. This pattern covers
11336;; large lists without explicit writeback generated for APCS_FRAME epilogue.
11337(define_insn "*load_multiple"
11338 [(match_parallel 0 "load_multiple_operation"
11339 [(set (match_operand:SI 2 "s_register_operand" "=rk")
11340 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
11341 ])]
11342 "TARGET_32BIT"
11343 "*
11344 {
11345 arm_output_multireg_pop (operands, /*return_pc=*/false,
11346 /*cond=*/const_true_rtx,
11347 /*reverse=*/false,
11348 /*update=*/false);
11349 return \"\";
11350 }
11351 "
11352 [(set_attr "predicable" "yes")]
11353)
11354
84450ddc 11355(define_expand "copysignsf3"
11356 [(match_operand:SF 0 "register_operand")
11357 (match_operand:SF 1 "register_operand")
11358 (match_operand:SF 2 "register_operand")]
11359 "TARGET_SOFT_FLOAT && arm_arch_thumb2"
11360 "{
11361 emit_move_insn (operands[0], operands[2]);
11362 emit_insn (gen_insv_t2 (simplify_gen_subreg (SImode, operands[0], SFmode, 0),
11363 GEN_INT (31), GEN_INT (0),
11364 simplify_gen_subreg (SImode, operands[1], SFmode, 0)));
11365 DONE;
11366 }"
11367)
11368
11369(define_expand "copysigndf3"
11370 [(match_operand:DF 0 "register_operand")
11371 (match_operand:DF 1 "register_operand")
11372 (match_operand:DF 2 "register_operand")]
11373 "TARGET_SOFT_FLOAT && arm_arch_thumb2"
11374 "{
11375 rtx op0_low = gen_lowpart (SImode, operands[0]);
11376 rtx op0_high = gen_highpart (SImode, operands[0]);
11377 rtx op1_low = gen_lowpart (SImode, operands[1]);
11378 rtx op1_high = gen_highpart (SImode, operands[1]);
11379 rtx op2_high = gen_highpart (SImode, operands[2]);
11380
11381 rtx scratch1 = gen_reg_rtx (SImode);
11382 rtx scratch2 = gen_reg_rtx (SImode);
11383 emit_move_insn (scratch1, op2_high);
11384 emit_move_insn (scratch2, op1_high);
11385
d1f9b275 11386 emit_insn(gen_rtx_SET(scratch1,
84450ddc 11387 gen_rtx_LSHIFTRT (SImode, op2_high, GEN_INT(31))));
11388 emit_insn(gen_insv_t2(scratch2, GEN_INT(1), GEN_INT(31), scratch1));
11389 emit_move_insn (op0_low, op1_low);
11390 emit_move_insn (op0_high, scratch2);
11391
11392 DONE;
11393 }"
11394)
11395
115857ef 11396;; movmisalign patterns for HImode and SImode.
11397(define_expand "movmisalign<mode>"
11398 [(match_operand:HSI 0 "general_operand")
11399 (match_operand:HSI 1 "general_operand")]
11400 "unaligned_access"
11401{
11402 /* This pattern is not permitted to fail during expansion: if both arguments
11403 are non-registers (e.g. memory := constant), force operand 1 into a
11404 register. */
11405 rtx (* gen_unaligned_load)(rtx, rtx);
11406 rtx tmp_dest = operands[0];
11407 if (!s_register_operand (operands[0], <MODE>mode)
11408 && !s_register_operand (operands[1], <MODE>mode))
11409 operands[1] = force_reg (<MODE>mode, operands[1]);
11410
11411 if (<MODE>mode == HImode)
11412 {
11413 gen_unaligned_load = gen_unaligned_loadhiu;
11414 tmp_dest = gen_reg_rtx (SImode);
11415 }
11416 else
11417 gen_unaligned_load = gen_unaligned_loadsi;
11418
11419 if (MEM_P (operands[1]))
11420 {
11421 emit_insn (gen_unaligned_load (tmp_dest, operands[1]));
11422 if (<MODE>mode == HImode)
11423 emit_move_insn (operands[0], gen_lowpart (HImode, tmp_dest));
11424 }
11425 else
11426 emit_insn (gen_unaligned_store<mode> (operands[0], operands[1]));
11427
11428 DONE;
11429})
11430
d98a3884 11431;; Vector bits common to IWMMXT and Neon
11432(include "vec-common.md")
755eb2b4 11433;; Load the Intel Wireless Multimedia Extension patterns
11434(include "iwmmxt.md")
a2cd141b 11435;; Load the VFP co-processor patterns
11436(include "vfp.md")
bc360af8 11437;; Thumb-1 patterns
11438(include "thumb1.md")
25f905c2 11439;; Thumb-2 patterns
11440(include "thumb2.md")
d98a3884 11441;; Neon patterns
11442(include "neon.md")
e84fdf6e 11443;; Crypto patterns
11444(include "crypto.md")
06df6b17 11445;; Synchronization Primitives
11446(include "sync.md")
bbbe4599 11447;; Fixed-point patterns
11448(include "arm-fixed.md")