]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/arm/arm.md
contrib/
[thirdparty/gcc.git] / gcc / config / arm / arm.md
CommitLineData
129a2fe4 1;;- Machine description for ARM for GNU compiler
3aea1f79 2;; Copyright (C) 1991-2014 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
cb860649 25;; Beware of splitting Thumb1 patterns that output multiple
26;; assembly instructions, in particular instruction such as SBC and
27;; ADC which consume flags. For example, in the pattern thumb_subdi3
28;; below, the output SUB implicitly sets the flags (assembled to SUBS)
29;; and then the Carry flag is used by SBC to compute the correct
30;; result. If we split thumb_subdi3 pattern into two separate RTL
31;; insns (using define_insn_and_split), the scheduler might place
32;; other RTL insns between SUB and SBC, possibly modifying the Carry
33;; flag used by SBC. This might happen because most Thumb1 patterns
34;; for flag-setting instructions do not have explicit RTL for setting
35;; or clobbering the flags. Instead, they have the attribute "conds"
36;; with value "set" or "clob". However, this attribute is not used to
37;; identify dependencies and therefore the scheduler might reorder
38;; these instruction. Currenly, this problem cannot happen because
39;; there are no separate Thumb1 patterns for individual instruction
40;; that consume flags (except conditional execution, which is treated
41;; differently). In particular there is no Thumb1 armv6-m pattern for
42;; sbc or adc.
43
9c08d1fa 44\f
e1159bbe 45;;---------------------------------------------------------------------------
46;; Constants
47
bffbb863 48;; Register numbers -- All machine registers should be defined here
e1159bbe 49(define_constants
bffbb863 50 [(R0_REGNUM 0) ; First CORE register
51 (R1_REGNUM 1) ; Second CORE register
52 (IP_REGNUM 12) ; Scratch register
53 (SP_REGNUM 13) ; Stack pointer
54 (LR_REGNUM 14) ; Return address register
55 (PC_REGNUM 15) ; Program counter
56 (LAST_ARM_REGNUM 15) ;
57 (CC_REGNUM 100) ; Condition code pseudo register
58 (VFPCC_REGNUM 101) ; VFP Condition code pseudo register
e1159bbe 59 ]
60)
3c5afce6 61;; 3rd operand to select_dominance_cc_mode
62(define_constants
63 [(DOM_CC_X_AND_Y 0)
64 (DOM_CC_NX_OR_Y 1)
65 (DOM_CC_X_OR_Y 2)
66 ]
67)
2ff91fec 68;; conditional compare combination
69(define_constants
70 [(CMP_CMP 0)
71 (CMN_CMP 1)
72 (CMP_CMN 2)
73 (CMN_CMN 3)
74 (NUM_OF_COND_CMP 4)
75 ]
76)
e1159bbe 77
b11cae9e 78\f
e1159bbe 79;;---------------------------------------------------------------------------
9c08d1fa 80;; Attributes
81
a651f34d 82;; Processor type. This is created automatically from arm-cores.def.
83(include "arm-tune.md")
84
861033d5 85;; Instruction classification types
86(include "types.md")
87
215b30b3 88; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
89; generating ARM code. This is used to control the length of some insn
90; patterns that share the same RTL in both ARM and Thumb code.
1c494086 91(define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
cffb2a26 92
ef51b8e1 93; IS_ARCH6 is set to 'yes' when we are generating code form ARMv6.
94(define_attr "is_arch6" "no,yes" (const (symbol_ref "arm_arch6")))
95
747b7458 96; IS_THUMB1 is set to 'yes' iff we are generating Thumb-1 code.
97(define_attr "is_thumb1" "no,yes" (const (symbol_ref "thumb1_code")))
98
c7a58118 99; We use this attribute to disable alternatives that can produce 32-bit
100; instructions inside an IT-block in Thumb2 state. ARMv8 deprecates IT blocks
101; that contain 32-bit instructions.
102(define_attr "enabled_for_depr_it" "no,yes" (const_string "yes"))
103
104; This attribute is used to disable a predicated alternative when we have
105; arm_restrict_it.
106(define_attr "predicable_short_it" "no,yes" (const_string "yes"))
107
331beb1a 108;; Operand number of an input operand that is shifted. Zero if the
109;; given instruction does not shift one of its input operands.
331beb1a 110(define_attr "shift" "" (const_int 0))
111
3d91c5d6 112; Floating Point Unit. If we only have floating point emulation, then there
113; is no point in scheduling the floating point insns. (Well, for best
114; performance we should try and group them together).
bffbb863 115(define_attr "fpu" "none,vfp"
c7f506fd 116 (const (symbol_ref "arm_fpu_attr")))
3d91c5d6 117
c7a58118 118(define_attr "predicated" "yes,no" (const_string "no"))
119
094e994f 120; LENGTH of an instruction (in bytes)
06df6b17 121(define_attr "length" ""
e1b93706 122 (const_int 4))
9c08d1fa 123
d5d4dc8d 124; The architecture which supports the instruction (or alternative).
125; This can be "a" for ARM, "t" for either of the Thumbs, "32" for
126; TARGET_32BIT, "t1" or "t2" to specify a specific Thumb mode. "v6"
127; for ARM or Thumb-2 with arm_arch6, and nov6 for ARM without
128; arm_arch6. This attribute is used to compute attribute "enabled",
129; use type "any" to enable an alternative in all cases.
b6779ddc 130(define_attr "arch" "any,a,t,32,t1,t2,v6,nov6,neon_for_64bits,avoid_neon_for_64bits,iwmmxt,iwmmxt2"
d5d4dc8d 131 (const_string "any"))
132
133(define_attr "arch_enabled" "no,yes"
134 (cond [(eq_attr "arch" "any")
135 (const_string "yes")
136
137 (and (eq_attr "arch" "a")
0bf497f5 138 (match_test "TARGET_ARM"))
d5d4dc8d 139 (const_string "yes")
140
141 (and (eq_attr "arch" "t")
0bf497f5 142 (match_test "TARGET_THUMB"))
d5d4dc8d 143 (const_string "yes")
144
145 (and (eq_attr "arch" "t1")
0bf497f5 146 (match_test "TARGET_THUMB1"))
d5d4dc8d 147 (const_string "yes")
148
149 (and (eq_attr "arch" "t2")
0bf497f5 150 (match_test "TARGET_THUMB2"))
d5d4dc8d 151 (const_string "yes")
152
153 (and (eq_attr "arch" "32")
0bf497f5 154 (match_test "TARGET_32BIT"))
d5d4dc8d 155 (const_string "yes")
156
157 (and (eq_attr "arch" "v6")
0bf497f5 158 (match_test "TARGET_32BIT && arm_arch6"))
d5d4dc8d 159 (const_string "yes")
160
161 (and (eq_attr "arch" "nov6")
0bf497f5 162 (match_test "TARGET_32BIT && !arm_arch6"))
a651f34d 163 (const_string "yes")
164
b6779ddc 165 (and (eq_attr "arch" "avoid_neon_for_64bits")
166 (match_test "TARGET_NEON")
167 (not (match_test "TARGET_PREFER_NEON_64BITS")))
a651f34d 168 (const_string "yes")
169
b6779ddc 170 (and (eq_attr "arch" "neon_for_64bits")
171 (match_test "TARGET_NEON")
172 (match_test "TARGET_PREFER_NEON_64BITS"))
6b8f7c28 173 (const_string "yes")
174
175 (and (eq_attr "arch" "iwmmxt2")
176 (match_test "TARGET_REALLY_IWMMXT2"))
d5d4dc8d 177 (const_string "yes")]
6b8f7c28 178
d5d4dc8d 179 (const_string "no")))
180
aa06c51c 181(define_attr "opt" "any,speed,size"
182 (const_string "any"))
183
184(define_attr "opt_enabled" "no,yes"
185 (cond [(eq_attr "opt" "any")
186 (const_string "yes")
187
188 (and (eq_attr "opt" "speed")
189 (match_test "optimize_function_for_speed_p (cfun)"))
190 (const_string "yes")
191
192 (and (eq_attr "opt" "size")
193 (match_test "optimize_function_for_size_p (cfun)"))
194 (const_string "yes")]
195 (const_string "no")))
196
861033d5 197(define_attr "use_literal_pool" "no,yes"
198 (cond [(and (eq_attr "type" "f_loads,f_loadd")
199 (match_test "CONSTANT_P (operands[1])"))
200 (const_string "yes")]
201 (const_string "no")))
202
d5d4dc8d 203; Allows an insn to disable certain alternatives for reasons other than
204; arch support.
205(define_attr "insn_enabled" "no,yes"
206 (const_string "yes"))
207
208; Enable all alternatives that are both arch_enabled and insn_enabled.
93b431d9 209 (define_attr "enabled" "no,yes"
aa06c51c 210 (cond [(eq_attr "insn_enabled" "no")
211 (const_string "no")
212
c7a58118 213 (and (eq_attr "predicable_short_it" "no")
214 (and (eq_attr "predicated" "yes")
215 (match_test "arm_restrict_it")))
216 (const_string "no")
217
218 (and (eq_attr "enabled_for_depr_it" "no")
219 (match_test "arm_restrict_it"))
220 (const_string "no")
221
861033d5 222 (and (eq_attr "use_literal_pool" "yes")
223 (match_test "arm_disable_literal_pool"))
224 (const_string "no")
225
aa06c51c 226 (eq_attr "arch_enabled" "no")
227 (const_string "no")
228
229 (eq_attr "opt_enabled" "no")
230 (const_string "no")]
231 (const_string "yes")))
d5d4dc8d 232
56d27660 233; POOL_RANGE is how far away from a constant pool entry that this insn
234; can be placed. If the distance is zero, then this insn will never
235; reference the pool.
42e1de19 236; Note that for Thumb constant pools the PC value is rounded down to the
237; nearest multiple of four. Therefore, THUMB2_POOL_RANGE (and POOL_RANGE for
238; Thumb insns) should be set to <max_range> - 2.
cffb2a26 239; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
8848d797 240; before its address. It is set to <max_range> - (8 + <data_size>).
cde1623a 241(define_attr "arm_pool_range" "" (const_int 0))
242(define_attr "thumb2_pool_range" "" (const_int 0))
243(define_attr "arm_neg_pool_range" "" (const_int 0))
244(define_attr "thumb2_neg_pool_range" "" (const_int 0))
245
246(define_attr "pool_range" ""
247 (cond [(eq_attr "is_thumb" "yes") (attr "thumb2_pool_range")]
248 (attr "arm_pool_range")))
249(define_attr "neg_pool_range" ""
250 (cond [(eq_attr "is_thumb" "yes") (attr "thumb2_neg_pool_range")]
251 (attr "arm_neg_pool_range")))
56d27660 252
215b30b3 253; An assembler sequence may clobber the condition codes without us knowing.
4d7a8451 254; If such an insn references the pool, then we have no way of knowing how,
255; so use the most conservative value for pool_range.
9c08d1fa 256(define_asm_attributes
4d7a8451 257 [(set_attr "conds" "clob")
258 (set_attr "length" "4")
259 (set_attr "pool_range" "250")])
9c08d1fa 260
9888ad6d 261; Load scheduling, set from the arm_ld_sched variable
4c834714 262; initialized by arm_option_override()
9888ad6d 263(define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
849170fd 264
f7fbdd4a 265; condition codes: this one is used by final_prescan_insn to speed up
266; conditionalizing instructions. It saves having to scan the rtl to see if
267; it uses or alters the condition codes.
215b30b3 268;
f7fbdd4a 269; USE means that the condition codes are used by the insn in the process of
215b30b3 270; outputting code, this means (at present) that we can't use the insn in
271; inlined branches
272;
f7fbdd4a 273; SET means that the purpose of the insn is to set the condition codes in a
215b30b3 274; well defined manner.
275;
f7fbdd4a 276; CLOB means that the condition codes are altered in an undefined manner, if
215b30b3 277; they are altered at all
278;
ad6d3e2a 279; UNCONDITIONAL means the instruction can not be conditionally executed and
280; that the instruction does not use or alter the condition codes.
c52acdd2 281;
ad6d3e2a 282; NOCOND means that the instruction does not use or alter the condition
283; codes but can be converted into a conditionally exectuted instruction.
f7fbdd4a 284
b0694be0 285(define_attr "conds" "use,set,clob,unconditional,nocond"
747b7458 286 (if_then_else
287 (ior (eq_attr "is_thumb1" "yes")
288 (eq_attr "type" "call"))
c1a66faf 289 (const_string "clob")
32093010 290 (if_then_else (eq_attr "is_neon_type" "no")
52432540 291 (const_string "nocond")
292 (const_string "unconditional"))))
f7fbdd4a 293
215b30b3 294; Predicable means that the insn can be conditionally executed based on
295; an automatically added predicate (additional patterns are generated by
296; gen...). We default to 'no' because no Thumb patterns match this rule
297; and not all ARM patterns do.
0d66636f 298(define_attr "predicable" "no,yes" (const_string "no"))
299
129a2fe4 300; Only model the write buffer for ARM6 and ARM7. Earlier processors don't
301; have one. Later ones, such as StrongARM, have write-back caches, so don't
8d232dc7 302; suffer blockages enough to warrant modelling this (and it can adversely
129a2fe4 303; affect the schedule).
74a71f7d 304(define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_tune_wbuf")))
129a2fe4 305
215b30b3 306; WRITE_CONFLICT implies that a read following an unrelated write is likely
307; to stall the processor. Used with model_wbuf above.
9c08d1fa 308(define_attr "write_conflict" "no,yes"
309 (if_then_else (eq_attr "type"
96854199 310 "block,call,load1")
9c08d1fa 311 (const_string "yes")
312 (const_string "no")))
313
215b30b3 314; Classify the insns into those that take one cycle and those that take more
315; than one on the main cpu execution unit.
f7fbdd4a 316(define_attr "core_cycles" "single,multi"
317 (if_then_else (eq_attr "type"
d82e788e 318 "adc_imm, adc_reg, adcs_imm, adcs_reg, adr, alu_ext, alu_imm, alu_reg,\
319 alu_shift_imm, alu_shift_reg, alus_ext, alus_imm, alus_reg,\
320 alus_shift_imm, alus_shift_reg, bfm, csel, rev, logic_imm, logic_reg,\
321 logic_shift_imm, logic_shift_reg, logics_imm, logics_reg,\
322 logics_shift_imm, logics_shift_reg, extend, shift_imm, float, fcsel,\
7cb6c048 323 wmmx_wor, wmmx_wxor, wmmx_wand, wmmx_wandn, wmmx_wmov, wmmx_tmcrr,\
324 wmmx_tmrrc, wmmx_wldr, wmmx_wstr, wmmx_tmcr, wmmx_tmrc, wmmx_wadd,\
325 wmmx_wsub, wmmx_wmul, wmmx_wmac, wmmx_wavg2, wmmx_tinsr, wmmx_textrm,\
326 wmmx_wshufh, wmmx_wcmpeq, wmmx_wcmpgt, wmmx_wmax, wmmx_wmin, wmmx_wpack,\
327 wmmx_wunpckih, wmmx_wunpckil, wmmx_wunpckeh, wmmx_wunpckel, wmmx_wror,\
328 wmmx_wsra, wmmx_wsrl, wmmx_wsll, wmmx_wmadd, wmmx_tmia, wmmx_tmiaph,\
329 wmmx_tmiaxy, wmmx_tbcst, wmmx_tmovmsk, wmmx_wacc, wmmx_waligni,\
330 wmmx_walignr, wmmx_tandc, wmmx_textrc, wmmx_torc, wmmx_torvsc, wmmx_wsad,\
331 wmmx_wabs, wmmx_wabsdiff, wmmx_waddsubhx, wmmx_wsubaddhx, wmmx_wavg4,\
332 wmmx_wmulw, wmmx_wqmulm, wmmx_wqmulwm, wmmx_waddbhus, wmmx_wqmiaxy,\
333 wmmx_wmiaxy, wmmx_wmiawxy, wmmx_wmerge")
f7fbdd4a 334 (const_string "single")
335 (const_string "multi")))
336
cffb2a26 337;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
215b30b3 338;; distant label. Only applicable to Thumb code.
cffb2a26 339(define_attr "far_jump" "yes,no" (const_string "no"))
340
d51f92df 341
25f905c2 342;; The number of machine instructions this pattern expands to.
343;; Used for Thumb-2 conditional execution.
344(define_attr "ce_count" "" (const_int 1))
345
4182b724 346;;---------------------------------------------------------------------------
347;; Unspecs
348
349(include "unspecs.md")
350
d51f92df 351;;---------------------------------------------------------------------------
fd781bb2 352;; Mode iterators
d51f92df 353
3de0dec6 354(include "iterators.md")
03770691 355
d51f92df 356;;---------------------------------------------------------------------------
357;; Predicates
358
9c9db025 359(include "predicates.md")
234f6557 360(include "constraints.md")
9c9db025 361
a2cd141b 362;;---------------------------------------------------------------------------
363;; Pipeline descriptions
215b30b3 364
e3879fd0 365(define_attr "tune_cortexr4" "yes,no"
366 (const (if_then_else
7d3cda8c 367 (eq_attr "tune" "cortexr4,cortexr4f,cortexr5")
e3879fd0 368 (const_string "yes")
369 (const_string "no"))))
370
a2cd141b 371;; True if the generic scheduling description should be used.
372
373(define_attr "generic_sched" "yes,no"
2546d93a 374 (const (if_then_else
25b10f06 375 (ior (eq_attr "tune" "fa526,fa626,fa606te,fa626te,fmp626,fa726te,arm926ejs,arm1020e,arm1026ejs,arm1136js,arm1136jfs,cortexa5,cortexa7,cortexa8,cortexa9,cortexa12,cortexa15,cortexa53,cortexm4,marvell_pj4")
2546d93a 376 (eq_attr "tune_cortexr4" "yes"))
4d5cb40d 377 (const_string "no")
378 (const_string "yes"))))
379
c0e1af52 380(define_attr "generic_vfp" "yes,no"
381 (const (if_then_else
382 (and (eq_attr "fpu" "vfp")
43e4f6e8 383 (eq_attr "tune" "!arm1020e,arm1022e,cortexa5,cortexa7,cortexa8,cortexa9,cortexa53,cortexm4,marvell_pj4")
e3879fd0 384 (eq_attr "tune_cortexr4" "no"))
c0e1af52 385 (const_string "yes")
386 (const_string "no"))))
387
6b8f7c28 388(include "marvell-f-iwmmxt.md")
a2cd141b 389(include "arm-generic.md")
390(include "arm926ejs.md")
c0e1af52 391(include "arm1020e.md")
a2cd141b 392(include "arm1026ejs.md")
393(include "arm1136jfs.md")
0e266d06 394(include "fa526.md")
395(include "fa606te.md")
396(include "fa626te.md")
397(include "fmp626.md")
398(include "fa726te.md")
3f1e069f 399(include "cortex-a5.md")
d6b7f019 400(include "cortex-a7.md")
bcaec148 401(include "cortex-a8.md")
036068af 402(include "cortex-a9.md")
65f2f758 403(include "cortex-a15.md")
da10bc87 404(include "cortex-a53.md")
934a1e72 405(include "cortex-r4.md")
e3879fd0 406(include "cortex-r4f.md")
2546d93a 407(include "cortex-m4.md")
408(include "cortex-m4-fpu.md")
55e3ada8 409(include "vfp11.md")
ea7d210b 410(include "marvell-pj4.md")
3586df96 411
9c08d1fa 412\f
215b30b3 413;;---------------------------------------------------------------------------
e1159bbe 414;; Insn patterns
415;;
a0f94409 416;; Addition insns.
215b30b3 417
9c08d1fa 418;; Note: For DImode insns, there is normally no reason why operands should
419;; not be in the same register, what we don't want is for something being
420;; written to partially overlap something that is an input.
421
cffb2a26 422(define_expand "adddi3"
423 [(parallel
215b30b3 424 [(set (match_operand:DI 0 "s_register_operand" "")
cffb2a26 425 (plus:DI (match_operand:DI 1 "s_register_operand" "")
10e5ccd5 426 (match_operand:DI 2 "arm_adddi_operand" "")))
bd5b4116 427 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 428 "TARGET_EITHER"
429 "
25f905c2 430 if (TARGET_THUMB1)
cffb2a26 431 {
0438d37f 432 if (!REG_P (operands[1]))
bc5a93af 433 operands[1] = force_reg (DImode, operands[1]);
0438d37f 434 if (!REG_P (operands[2]))
bc5a93af 435 operands[2] = force_reg (DImode, operands[2]);
cffb2a26 436 }
437 "
438)
439
25f905c2 440(define_insn "*thumb1_adddi3"
cffb2a26 441 [(set (match_operand:DI 0 "register_operand" "=l")
442 (plus:DI (match_operand:DI 1 "register_operand" "%0")
215b30b3 443 (match_operand:DI 2 "register_operand" "l")))
bd5b4116 444 (clobber (reg:CC CC_REGNUM))
cffb2a26 445 ]
25f905c2 446 "TARGET_THUMB1"
cffb2a26 447 "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
1b7da4ac 448 [(set_attr "length" "4")
449 (set_attr "type" "multiple")]
cffb2a26 450)
451
a0f94409 452(define_insn_and_split "*arm_adddi3"
10e5ccd5 453 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r,&r,&r")
454 (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0, r, 0, r")
455 (match_operand:DI 2 "arm_adddi_operand" "r, 0, r, Dd, Dd")))
bd5b4116 456 (clobber (reg:CC CC_REGNUM))]
b805622c 457 "TARGET_32BIT && !TARGET_NEON"
33782ec7 458 "#"
94829feb 459 "TARGET_32BIT && reload_completed
460 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))"
a0f94409 461 [(parallel [(set (reg:CC_C CC_REGNUM)
462 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
463 (match_dup 1)))
464 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 465 (set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (match_dup 5))
466 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
a0f94409 467 "
468 {
469 operands[3] = gen_highpart (SImode, operands[0]);
470 operands[0] = gen_lowpart (SImode, operands[0]);
471 operands[4] = gen_highpart (SImode, operands[1]);
472 operands[1] = gen_lowpart (SImode, operands[1]);
10e5ccd5 473 operands[5] = gen_highpart_mode (SImode, DImode, operands[2]);
a0f94409 474 operands[2] = gen_lowpart (SImode, operands[2]);
475 }"
cffb2a26 476 [(set_attr "conds" "clob")
1b7da4ac 477 (set_attr "length" "8")
478 (set_attr "type" "multiple")]
cffb2a26 479)
9c08d1fa 480
a0f94409 481(define_insn_and_split "*adddi_sesidi_di"
9c08d1fa 482 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
483 (plus:DI (sign_extend:DI
97499065 484 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 485 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 486 (clobber (reg:CC CC_REGNUM))]
b805622c 487 "TARGET_32BIT"
33782ec7 488 "#"
25f905c2 489 "TARGET_32BIT && reload_completed"
a0f94409 490 [(parallel [(set (reg:CC_C CC_REGNUM)
491 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
492 (match_dup 1)))
493 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 494 (set (match_dup 3) (plus:SI (plus:SI (ashiftrt:SI (match_dup 2)
a0f94409 495 (const_int 31))
080c0b9a 496 (match_dup 4))
497 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
a0f94409 498 "
499 {
500 operands[3] = gen_highpart (SImode, operands[0]);
501 operands[0] = gen_lowpart (SImode, operands[0]);
502 operands[4] = gen_highpart (SImode, operands[1]);
503 operands[1] = gen_lowpart (SImode, operands[1]);
504 operands[2] = gen_lowpart (SImode, operands[2]);
505 }"
215b30b3 506 [(set_attr "conds" "clob")
1b7da4ac 507 (set_attr "length" "8")
508 (set_attr "type" "multiple")]
215b30b3 509)
9c08d1fa 510
a0f94409 511(define_insn_and_split "*adddi_zesidi_di"
9c08d1fa 512 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
513 (plus:DI (zero_extend:DI
97499065 514 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 515 (match_operand:DI 1 "s_register_operand" "0,r")))
a0f94409 516 (clobber (reg:CC CC_REGNUM))]
b805622c 517 "TARGET_32BIT"
33782ec7 518 "#"
25f905c2 519 "TARGET_32BIT && reload_completed"
a0f94409 520 [(parallel [(set (reg:CC_C CC_REGNUM)
521 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
522 (match_dup 1)))
523 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 524 (set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (const_int 0))
525 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
a0f94409 526 "
527 {
528 operands[3] = gen_highpart (SImode, operands[0]);
529 operands[0] = gen_lowpart (SImode, operands[0]);
530 operands[4] = gen_highpart (SImode, operands[1]);
531 operands[1] = gen_lowpart (SImode, operands[1]);
532 operands[2] = gen_lowpart (SImode, operands[2]);
533 }"
cffb2a26 534 [(set_attr "conds" "clob")
1b7da4ac 535 (set_attr "length" "8")
536 (set_attr "type" "multiple")]
cffb2a26 537)
b11cae9e 538
87b22bf7 539(define_expand "addsi3"
cffb2a26 540 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 541 (plus:SI (match_operand:SI 1 "s_register_operand" "")
542 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 543 "TARGET_EITHER"
87b22bf7 544 "
0438d37f 545 if (TARGET_32BIT && CONST_INT_P (operands[2]))
87b22bf7 546 {
96f57e36 547 arm_split_constant (PLUS, SImode, NULL_RTX,
548 INTVAL (operands[2]), operands[0], operands[1],
e1ba4a27 549 optimize && can_create_pseudo_p ());
87b22bf7 550 DONE;
551 }
cffb2a26 552 "
553)
87b22bf7 554
5bd751ff 555; If there is a scratch available, this will be faster than synthesizing the
a0f94409 556; addition.
557(define_peephole2
558 [(match_scratch:SI 3 "r")
372575c7 559 (set (match_operand:SI 0 "arm_general_register_operand" "")
560 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
cffb2a26 561 (match_operand:SI 2 "const_int_operand" "")))]
25f905c2 562 "TARGET_32BIT &&
a0f94409 563 !(const_ok_for_arm (INTVAL (operands[2]))
564 || const_ok_for_arm (-INTVAL (operands[2])))
565 && const_ok_for_arm (~INTVAL (operands[2]))"
566 [(set (match_dup 3) (match_dup 2))
567 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
568 ""
569)
87b22bf7 570
2f02c19f 571;; The r/r/k alternative is required when reloading the address
572;; (plus (reg rN) (reg sp)) into (reg rN). In this case reload will
573;; put the duplicated register first, and not try the commutative version.
a0f94409 574(define_insn_and_split "*arm_addsi3"
7c36fe71 575 [(set (match_operand:SI 0 "s_register_operand" "=rk,l,l ,l ,r ,k ,r,r ,k ,r ,k,k,r ,k ,r")
576 (plus:SI (match_operand:SI 1 "s_register_operand" "%0 ,l,0 ,l ,rk,k ,r,rk,k ,rk,k,r,rk,k ,rk")
577 (match_operand:SI 2 "reg_or_int_operand" "rk ,l,Py,Pd,rI,rI,k,Pj,Pj,L ,L,L,PJ,PJ,?n")))]
25f905c2 578 "TARGET_32BIT"
5565501b 579 "@
c24d855d 580 add%?\\t%0, %0, %2
5565501b 581 add%?\\t%0, %1, %2
a0b3420a 582 add%?\\t%0, %1, %2
7c36fe71 583 add%?\\t%0, %1, %2
584 add%?\\t%0, %1, %2
aaa37ad6 585 add%?\\t%0, %1, %2
2f02c19f 586 add%?\\t%0, %2, %1
d5cbae34 587 addw%?\\t%0, %1, %2
588 addw%?\\t%0, %1, %2
aaa37ad6 589 sub%?\\t%0, %1, #%n2
87b22bf7 590 sub%?\\t%0, %1, #%n2
d7757711 591 sub%?\\t%0, %1, #%n2
d5cbae34 592 subw%?\\t%0, %1, #%n2
593 subw%?\\t%0, %1, #%n2
87b22bf7 594 #"
a3ffc315 595 "TARGET_32BIT
0438d37f 596 && CONST_INT_P (operands[2])
d5cbae34 597 && !const_ok_for_op (INTVAL (operands[2]), PLUS)
a3ffc315 598 && (reload_completed || !arm_eliminable_register (operands[1]))"
a0f94409 599 [(clobber (const_int 0))]
600 "
96f57e36 601 arm_split_constant (PLUS, SImode, curr_insn,
602 INTVAL (operands[2]), operands[0],
a0f94409 603 operands[1], 0);
604 DONE;
605 "
7c36fe71 606 [(set_attr "length" "2,4,4,4,4,4,4,4,4,4,4,4,4,4,16")
d5cbae34 607 (set_attr "predicable" "yes")
7c36fe71 608 (set_attr "predicable_short_it" "yes,yes,yes,yes,no,no,no,no,no,no,no,no,no,no,no")
609 (set_attr "arch" "t2,t2,t2,t2,*,*,*,t2,t2,*,*,a,t2,t2,*")
65f68e55 610 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
d82e788e 611 (const_string "alu_imm")
612 (const_string "alu_reg")))
65f68e55 613 ]
cffb2a26 614)
615
0bdb6455 616(define_insn_and_split "*thumb1_addsi3"
bf7bc2f6 617 [(set (match_operand:SI 0 "register_operand" "=l,l,l,*rk,*hk,l,k,l,l,l")
618 (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,k,k,0,l,k")
619 (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*hk,*rk,M,O,Pa,Pb,Pc")))]
25f905c2 620 "TARGET_THUMB1"
cffb2a26 621 "*
0d66636f 622 static const char * const asms[] =
cffb2a26 623 {
624 \"add\\t%0, %0, %2\",
625 \"sub\\t%0, %0, #%n2\",
626 \"add\\t%0, %1, %2\",
627 \"add\\t%0, %0, %2\",
628 \"add\\t%0, %0, %2\",
629 \"add\\t%0, %1, %2\",
0bdb6455 630 \"add\\t%0, %1, %2\",
631 \"#\",
bf7bc2f6 632 \"#\",
0bdb6455 633 \"#\"
cffb2a26 634 };
635 if ((which_alternative == 2 || which_alternative == 6)
0438d37f 636 && CONST_INT_P (operands[2])
cffb2a26 637 && INTVAL (operands[2]) < 0)
638 return \"sub\\t%0, %1, #%n2\";
639 return asms[which_alternative];
640 "
0bdb6455 641 "&& reload_completed && CONST_INT_P (operands[2])
bf7bc2f6 642 && ((operands[1] != stack_pointer_rtx
643 && (INTVAL (operands[2]) > 255 || INTVAL (operands[2]) < -255))
644 || (operands[1] == stack_pointer_rtx
645 && INTVAL (operands[2]) > 1020))"
0bdb6455 646 [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
647 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 3)))]
648 {
649 HOST_WIDE_INT offset = INTVAL (operands[2]);
bf7bc2f6 650 if (operands[1] == stack_pointer_rtx)
651 offset -= 1020;
652 else
653 {
654 if (offset > 255)
655 offset = 255;
656 else if (offset < -255)
657 offset = -255;
658 }
0bdb6455 659 operands[3] = GEN_INT (offset);
660 operands[2] = GEN_INT (INTVAL (operands[2]) - offset);
661 }
1b7da4ac 662 [(set_attr "length" "2,2,2,2,2,2,2,4,4,4")
663 (set_attr "type" "alus_imm,alus_imm,alus_reg,alus_reg,alus_reg,
664 alus_reg,alus_reg,multiple,multiple,multiple")]
cffb2a26 665)
666
667;; Reloading and elimination of the frame pointer can
668;; sometimes cause this optimization to be missed.
a0f94409 669(define_peephole2
372575c7 670 [(set (match_operand:SI 0 "arm_general_register_operand" "")
a058e94a 671 (match_operand:SI 1 "const_int_operand" ""))
cffb2a26 672 (set (match_dup 0)
372575c7 673 (plus:SI (match_dup 0) (reg:SI SP_REGNUM)))]
25f905c2 674 "TARGET_THUMB1
cffb2a26 675 && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
676 && (INTVAL (operands[1]) & 3) == 0"
372575c7 677 [(set (match_dup 0) (plus:SI (reg:SI SP_REGNUM) (match_dup 1)))]
a0f94409 678 ""
cffb2a26 679)
b11cae9e 680
90c2bcf0 681(define_insn "addsi3_compare0"
bd5b4116 682 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 683 (compare:CC_NOOV
65f68e55 684 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r,r")
685 (match_operand:SI 2 "arm_add_operand" "I,L,r"))
5565501b 686 (const_int 0)))
65f68e55 687 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9c08d1fa 688 (plus:SI (match_dup 1) (match_dup 2)))]
ec792a7b 689 "TARGET_ARM"
5565501b 690 "@
25f905c2 691 add%.\\t%0, %1, %2
65f68e55 692 sub%.\\t%0, %1, #%n2
693 add%.\\t%0, %1, %2"
694 [(set_attr "conds" "set")
1b7da4ac 695 (set_attr "type" "alus_imm,alus_imm,alus_reg")]
cffb2a26 696)
9c08d1fa 697
aea4c774 698(define_insn "*addsi3_compare0_scratch"
bd5b4116 699 [(set (reg:CC_NOOV CC_REGNUM)
aea4c774 700 (compare:CC_NOOV
65f68e55 701 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r, r")
702 (match_operand:SI 1 "arm_add_operand" "I,L, r"))
aea4c774 703 (const_int 0)))]
ec792a7b 704 "TARGET_ARM"
cffb2a26 705 "@
706 cmn%?\\t%0, %1
65f68e55 707 cmp%?\\t%0, #%n1
708 cmn%?\\t%0, %1"
596e5e8f 709 [(set_attr "conds" "set")
65f68e55 710 (set_attr "predicable" "yes")
1b7da4ac 711 (set_attr "type" "alus_imm,alus_imm,alus_reg")]
0d66636f 712)
cffb2a26 713
aed179ae 714(define_insn "*compare_negsi_si"
715 [(set (reg:CC_Z CC_REGNUM)
716 (compare:CC_Z
7c36fe71 717 (neg:SI (match_operand:SI 0 "s_register_operand" "l,r"))
718 (match_operand:SI 1 "s_register_operand" "l,r")))]
25f905c2 719 "TARGET_32BIT"
aed179ae 720 "cmn%?\\t%1, %0"
596e5e8f 721 [(set_attr "conds" "set")
7c36fe71 722 (set_attr "predicable" "yes")
723 (set_attr "arch" "t2,*")
724 (set_attr "length" "2,4")
1b7da4ac 725 (set_attr "predicable_short_it" "yes,no")
726 (set_attr "type" "alus_reg")]
0d66636f 727)
aea4c774 728
203c488f 729;; This is the canonicalization of addsi3_compare0_for_combiner when the
730;; addend is a constant.
190efb17 731(define_insn "cmpsi2_addneg"
203c488f 732 [(set (reg:CC CC_REGNUM)
733 (compare:CC
734 (match_operand:SI 1 "s_register_operand" "r,r")
2a977b78 735 (match_operand:SI 2 "arm_addimm_operand" "L,I")))
203c488f 736 (set (match_operand:SI 0 "s_register_operand" "=r,r")
737 (plus:SI (match_dup 1)
2a977b78 738 (match_operand:SI 3 "arm_addimm_operand" "I,L")))]
25f905c2 739 "TARGET_32BIT && INTVAL (operands[2]) == -INTVAL (operands[3])"
203c488f 740 "@
2a977b78 741 add%.\\t%0, %1, %3
742 sub%.\\t%0, %1, #%n3"
1b7da4ac 743 [(set_attr "conds" "set")
744 (set_attr "type" "alus_reg")]
203c488f 745)
746
747;; Convert the sequence
748;; sub rd, rn, #1
749;; cmn rd, #1 (equivalent to cmp rd, #-1)
750;; bne dest
751;; into
752;; subs rd, rn, #1
753;; bcs dest ((unsigned)rn >= 1)
754;; similarly for the beq variant using bcc.
755;; This is a common looping idiom (while (n--))
756(define_peephole2
372575c7 757 [(set (match_operand:SI 0 "arm_general_register_operand" "")
758 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
203c488f 759 (const_int -1)))
760 (set (match_operand 2 "cc_register" "")
761 (compare (match_dup 0) (const_int -1)))
762 (set (pc)
763 (if_then_else (match_operator 3 "equality_operator"
764 [(match_dup 2) (const_int 0)])
765 (match_operand 4 "" "")
766 (match_operand 5 "" "")))]
25f905c2 767 "TARGET_32BIT && peep2_reg_dead_p (3, operands[2])"
203c488f 768 [(parallel[
769 (set (match_dup 2)
770 (compare:CC
771 (match_dup 1) (const_int 1)))
772 (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
773 (set (pc)
774 (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
775 (match_dup 4)
776 (match_dup 5)))]
777 "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
778 operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
779 ? GEU : LTU),
780 VOIDmode,
781 operands[2], const0_rtx);"
782)
783
ebcc79bc 784;; The next four insns work because they compare the result with one of
785;; the operands, and we know that the use of the condition code is
786;; either GEU or LTU, so we can use the carry flag from the addition
787;; instead of doing the compare a second time.
788(define_insn "*addsi3_compare_op1"
bd5b4116 789 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 790 (compare:CC_C
65f68e55 791 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
792 (match_operand:SI 2 "arm_add_operand" "I,L,r"))
ebcc79bc 793 (match_dup 1)))
65f68e55 794 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
ebcc79bc 795 (plus:SI (match_dup 1) (match_dup 2)))]
25f905c2 796 "TARGET_32BIT"
ebcc79bc 797 "@
25f905c2 798 add%.\\t%0, %1, %2
65f68e55 799 sub%.\\t%0, %1, #%n2
800 add%.\\t%0, %1, %2"
801 [(set_attr "conds" "set")
d82e788e 802 (set_attr "type" "alus_imm,alus_imm,alus_reg")]
0d66636f 803)
ebcc79bc 804
805(define_insn "*addsi3_compare_op2"
bd5b4116 806 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 807 (compare:CC_C
65f68e55 808 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
809 (match_operand:SI 2 "arm_add_operand" "I,L,r"))
ebcc79bc 810 (match_dup 2)))
65f68e55 811 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9c08d1fa 812 (plus:SI (match_dup 1) (match_dup 2)))]
25f905c2 813 "TARGET_32BIT"
5565501b 814 "@
65f68e55 815 add%.\\t%0, %1, %2
25f905c2 816 add%.\\t%0, %1, %2
817 sub%.\\t%0, %1, #%n2"
65f68e55 818 [(set_attr "conds" "set")
d82e788e 819 (set_attr "type" "alus_imm,alus_imm,alus_reg")]
0d66636f 820)
9c08d1fa 821
ebcc79bc 822(define_insn "*compare_addsi2_op0"
bd5b4116 823 [(set (reg:CC_C CC_REGNUM)
7c36fe71 824 (compare:CC_C
825 (plus:SI (match_operand:SI 0 "s_register_operand" "l,l,r,r,r")
826 (match_operand:SI 1 "arm_add_operand" "Pv,l,I,L,r"))
827 (match_dup 0)))]
25f905c2 828 "TARGET_32BIT"
ebcc79bc 829 "@
7c36fe71 830 cmp%?\\t%0, #%n1
831 cmn%?\\t%0, %1
ebcc79bc 832 cmn%?\\t%0, %1
65f68e55 833 cmp%?\\t%0, #%n1
834 cmn%?\\t%0, %1"
596e5e8f 835 [(set_attr "conds" "set")
65f68e55 836 (set_attr "predicable" "yes")
7c36fe71 837 (set_attr "arch" "t2,t2,*,*,*")
838 (set_attr "predicable_short_it" "yes,yes,no,no,no")
839 (set_attr "length" "2,2,4,4,4")
d82e788e 840 (set_attr "type" "alus_imm,alus_reg,alus_imm,alus_imm,alus_reg")]
0d66636f 841)
ebcc79bc 842
843(define_insn "*compare_addsi2_op1"
bd5b4116 844 [(set (reg:CC_C CC_REGNUM)
7c36fe71 845 (compare:CC_C
846 (plus:SI (match_operand:SI 0 "s_register_operand" "l,l,r,r,r")
847 (match_operand:SI 1 "arm_add_operand" "Pv,l,I,L,r"))
848 (match_dup 1)))]
25f905c2 849 "TARGET_32BIT"
ebcc79bc 850 "@
7c36fe71 851 cmp%?\\t%0, #%n1
852 cmn%?\\t%0, %1
ebcc79bc 853 cmn%?\\t%0, %1
65f68e55 854 cmp%?\\t%0, #%n1
855 cmn%?\\t%0, %1"
596e5e8f 856 [(set_attr "conds" "set")
65f68e55 857 (set_attr "predicable" "yes")
7c36fe71 858 (set_attr "arch" "t2,t2,*,*,*")
859 (set_attr "predicable_short_it" "yes,yes,no,no,no")
860 (set_attr "length" "2,2,4,4,4")
d82e788e 861 (set_attr "type" "alus_imm,alus_reg,alus_imm,alus_imm,alus_reg")]
7c36fe71 862 )
ebcc79bc 863
080c0b9a 864(define_insn "*addsi3_carryin_<optab>"
7c36fe71 865 [(set (match_operand:SI 0 "s_register_operand" "=l,r,r")
866 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%l,r,r")
867 (match_operand:SI 2 "arm_not_operand" "0,rI,K"))
868 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))]
25f905c2 869 "TARGET_32BIT"
10e5ccd5 870 "@
a0b3420a 871 adc%?\\t%0, %1, %2
10e5ccd5 872 adc%?\\t%0, %1, %2
873 sbc%?\\t%0, %1, #%B2"
a7de272d 874 [(set_attr "conds" "use")
7c36fe71 875 (set_attr "predicable" "yes")
876 (set_attr "arch" "t2,*,*")
877 (set_attr "length" "4")
1b7da4ac 878 (set_attr "predicable_short_it" "yes,no,no")
879 (set_attr "type" "adc_reg,adc_reg,adc_imm")]
cffb2a26 880)
ebcc79bc 881
080c0b9a 882(define_insn "*addsi3_carryin_alt2_<optab>"
7c36fe71 883 [(set (match_operand:SI 0 "s_register_operand" "=l,r,r")
884 (plus:SI (plus:SI (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))
885 (match_operand:SI 1 "s_register_operand" "%l,r,r"))
886 (match_operand:SI 2 "arm_rhs_operand" "l,rI,K")))]
25f905c2 887 "TARGET_32BIT"
10e5ccd5 888 "@
a0b3420a 889 adc%?\\t%0, %1, %2
10e5ccd5 890 adc%?\\t%0, %1, %2
891 sbc%?\\t%0, %1, #%B2"
a7de272d 892 [(set_attr "conds" "use")
7c36fe71 893 (set_attr "predicable" "yes")
894 (set_attr "arch" "t2,*,*")
895 (set_attr "length" "4")
1b7da4ac 896 (set_attr "predicable_short_it" "yes,no,no")
897 (set_attr "type" "adc_reg,adc_reg,adc_imm")]
0d66636f 898)
ebcc79bc 899
080c0b9a 900(define_insn "*addsi3_carryin_shift_<optab>"
ebcc79bc 901 [(set (match_operand:SI 0 "s_register_operand" "=r")
080c0b9a 902 (plus:SI (plus:SI
903 (match_operator:SI 2 "shift_operator"
904 [(match_operand:SI 3 "s_register_operand" "r")
905 (match_operand:SI 4 "reg_or_int_operand" "rM")])
906 (match_operand:SI 1 "s_register_operand" "r"))
907 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))]
25f905c2 908 "TARGET_32BIT"
080c0b9a 909 "adc%?\\t%0, %1, %3%S2"
910 [(set_attr "conds" "use")
a7de272d 911 (set_attr "predicable" "yes")
7c36fe71 912 (set_attr "predicable_short_it" "no")
080c0b9a 913 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
d82e788e 914 (const_string "alu_shift_imm")
915 (const_string "alu_shift_reg")))]
cffb2a26 916)
ebcc79bc 917
922b6913 918(define_insn "*addsi3_carryin_clobercc_<optab>"
919 [(set (match_operand:SI 0 "s_register_operand" "=r")
920 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%r")
921 (match_operand:SI 2 "arm_rhs_operand" "rI"))
922 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))
923 (clobber (reg:CC CC_REGNUM))]
924 "TARGET_32BIT"
925 "adc%.\\t%0, %1, %2"
1b7da4ac 926 [(set_attr "conds" "set")
927 (set_attr "type" "adcs_reg")]
922b6913 928)
929
9154bd82 930(define_insn "*subsi3_carryin"
931 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
932 (minus:SI (minus:SI (match_operand:SI 1 "reg_or_int_operand" "r,I")
933 (match_operand:SI 2 "s_register_operand" "r,r"))
934 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
935 "TARGET_32BIT"
936 "@
937 sbc%?\\t%0, %1, %2
938 rsc%?\\t%0, %2, %1"
939 [(set_attr "conds" "use")
940 (set_attr "arch" "*,a")
7c36fe71 941 (set_attr "predicable" "yes")
1b7da4ac 942 (set_attr "predicable_short_it" "no")
943 (set_attr "type" "adc_reg,adc_imm")]
9154bd82 944)
945
946(define_insn "*subsi3_carryin_const"
947 [(set (match_operand:SI 0 "s_register_operand" "=r")
948 (minus:SI (plus:SI (match_operand:SI 1 "reg_or_int_operand" "r")
949 (match_operand:SI 2 "arm_not_operand" "K"))
950 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
951 "TARGET_32BIT"
952 "sbc\\t%0, %1, #%B2"
1b7da4ac 953 [(set_attr "conds" "use")
954 (set_attr "type" "adc_imm")]
9154bd82 955)
956
957(define_insn "*subsi3_carryin_compare"
958 [(set (reg:CC CC_REGNUM)
959 (compare:CC (match_operand:SI 1 "s_register_operand" "r")
960 (match_operand:SI 2 "s_register_operand" "r")))
961 (set (match_operand:SI 0 "s_register_operand" "=r")
962 (minus:SI (minus:SI (match_dup 1)
963 (match_dup 2))
964 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
965 "TARGET_32BIT"
966 "sbcs\\t%0, %1, %2"
1b7da4ac 967 [(set_attr "conds" "set")
968 (set_attr "type" "adcs_reg")]
9154bd82 969)
970
971(define_insn "*subsi3_carryin_compare_const"
972 [(set (reg:CC CC_REGNUM)
973 (compare:CC (match_operand:SI 1 "reg_or_int_operand" "r")
974 (match_operand:SI 2 "arm_not_operand" "K")))
975 (set (match_operand:SI 0 "s_register_operand" "=r")
976 (minus:SI (plus:SI (match_dup 1)
977 (match_dup 2))
978 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
979 "TARGET_32BIT"
980 "sbcs\\t%0, %1, #%B2"
1b7da4ac 981 [(set_attr "conds" "set")
982 (set_attr "type" "adcs_imm")]
9154bd82 983)
984
985(define_insn "*subsi3_carryin_shift"
986 [(set (match_operand:SI 0 "s_register_operand" "=r")
987 (minus:SI (minus:SI
988 (match_operand:SI 1 "s_register_operand" "r")
989 (match_operator:SI 2 "shift_operator"
990 [(match_operand:SI 3 "s_register_operand" "r")
991 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
992 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
993 "TARGET_32BIT"
994 "sbc%?\\t%0, %1, %3%S2"
995 [(set_attr "conds" "use")
996 (set_attr "predicable" "yes")
997 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
d82e788e 998 (const_string "alu_shift_imm")
999 (const_string "alu_shift_reg")))]
9154bd82 1000)
1001
1002(define_insn "*rsbsi3_carryin_shift"
1003 [(set (match_operand:SI 0 "s_register_operand" "=r")
1004 (minus:SI (minus:SI
1005 (match_operator:SI 2 "shift_operator"
1006 [(match_operand:SI 3 "s_register_operand" "r")
1007 (match_operand:SI 4 "reg_or_int_operand" "rM")])
1008 (match_operand:SI 1 "s_register_operand" "r"))
1009 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1010 "TARGET_ARM"
1011 "rsc%?\\t%0, %1, %3%S2"
1012 [(set_attr "conds" "use")
1013 (set_attr "predicable" "yes")
1014 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
d82e788e 1015 (const_string "alu_shift_imm")
1016 (const_string "alu_shift_reg")))]
9154bd82 1017)
1018
d795fb69 1019; transform ((x << y) - 1) to ~(~(x-1) << y) Where X is a constant.
1020(define_split
1021 [(set (match_operand:SI 0 "s_register_operand" "")
1022 (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
1023 (match_operand:SI 2 "s_register_operand" ""))
1024 (const_int -1)))
1025 (clobber (match_operand:SI 3 "s_register_operand" ""))]
25f905c2 1026 "TARGET_32BIT"
d795fb69 1027 [(set (match_dup 3) (match_dup 1))
1028 (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
1029 "
1030 operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
1031")
1032
604f3a0a 1033(define_expand "addsf3"
1034 [(set (match_operand:SF 0 "s_register_operand" "")
1035 (plus:SF (match_operand:SF 1 "s_register_operand" "")
d86c91f6 1036 (match_operand:SF 2 "s_register_operand" "")))]
25f905c2 1037 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1038 "
604f3a0a 1039")
1040
604f3a0a 1041(define_expand "adddf3"
1042 [(set (match_operand:DF 0 "s_register_operand" "")
1043 (plus:DF (match_operand:DF 1 "s_register_operand" "")
d86c91f6 1044 (match_operand:DF 2 "s_register_operand" "")))]
a50d7267 1045 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 1046 "
604f3a0a 1047")
1048
cffb2a26 1049(define_expand "subdi3"
1050 [(parallel
1051 [(set (match_operand:DI 0 "s_register_operand" "")
1052 (minus:DI (match_operand:DI 1 "s_register_operand" "")
1053 (match_operand:DI 2 "s_register_operand" "")))
bd5b4116 1054 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 1055 "TARGET_EITHER"
1056 "
25f905c2 1057 if (TARGET_THUMB1)
cffb2a26 1058 {
0438d37f 1059 if (!REG_P (operands[1]))
5aa8c5f0 1060 operands[1] = force_reg (DImode, operands[1]);
0438d37f 1061 if (!REG_P (operands[2]))
5aa8c5f0 1062 operands[2] = force_reg (DImode, operands[2]);
cffb2a26 1063 }
1064 "
1065)
1066
2f9b23e3 1067(define_insn_and_split "*arm_subdi3"
cffb2a26 1068 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
9c08d1fa 1069 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
1070 (match_operand:DI 2 "s_register_operand" "r,0,0")))
bd5b4116 1071 (clobber (reg:CC CC_REGNUM))]
94829feb 1072 "TARGET_32BIT && !TARGET_NEON"
2f9b23e3 1073 "#" ; "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
1074 "&& reload_completed"
1075 [(parallel [(set (reg:CC CC_REGNUM)
1076 (compare:CC (match_dup 1) (match_dup 2)))
1077 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1078 (set (match_dup 3) (minus:SI (minus:SI (match_dup 4) (match_dup 5))
1079 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1080 {
1081 operands[3] = gen_highpart (SImode, operands[0]);
1082 operands[0] = gen_lowpart (SImode, operands[0]);
1083 operands[4] = gen_highpart (SImode, operands[1]);
1084 operands[1] = gen_lowpart (SImode, operands[1]);
1085 operands[5] = gen_highpart (SImode, operands[2]);
1086 operands[2] = gen_lowpart (SImode, operands[2]);
1087 }
cffb2a26 1088 [(set_attr "conds" "clob")
1b7da4ac 1089 (set_attr "length" "8")
1090 (set_attr "type" "multiple")]
cffb2a26 1091)
1092
1093(define_insn "*thumb_subdi3"
1094 [(set (match_operand:DI 0 "register_operand" "=l")
1095 (minus:DI (match_operand:DI 1 "register_operand" "0")
1096 (match_operand:DI 2 "register_operand" "l")))
bd5b4116 1097 (clobber (reg:CC CC_REGNUM))]
25f905c2 1098 "TARGET_THUMB1"
cffb2a26 1099 "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
1b7da4ac 1100 [(set_attr "length" "4")
1101 (set_attr "type" "multiple")]
cffb2a26 1102)
9c08d1fa 1103
2f9b23e3 1104(define_insn_and_split "*subdi_di_zesidi"
cffb2a26 1105 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 1106 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r")
9c08d1fa 1107 (zero_extend:DI
cffb2a26 1108 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 1109 (clobber (reg:CC CC_REGNUM))]
25f905c2 1110 "TARGET_32BIT"
2f9b23e3 1111 "#" ; "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
1112 "&& reload_completed"
1113 [(parallel [(set (reg:CC CC_REGNUM)
1114 (compare:CC (match_dup 1) (match_dup 2)))
1115 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1116 (set (match_dup 3) (minus:SI (plus:SI (match_dup 4) (match_dup 5))
1117 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1118 {
1119 operands[3] = gen_highpart (SImode, operands[0]);
1120 operands[0] = gen_lowpart (SImode, operands[0]);
1121 operands[4] = gen_highpart (SImode, operands[1]);
1122 operands[1] = gen_lowpart (SImode, operands[1]);
1123 operands[5] = GEN_INT (~0);
1124 }
cffb2a26 1125 [(set_attr "conds" "clob")
1b7da4ac 1126 (set_attr "length" "8")
1127 (set_attr "type" "multiple")]
cffb2a26 1128)
9c08d1fa 1129
2f9b23e3 1130(define_insn_and_split "*subdi_di_sesidi"
cffb2a26 1131 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 1132 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r")
9c08d1fa 1133 (sign_extend:DI
cffb2a26 1134 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 1135 (clobber (reg:CC CC_REGNUM))]
25f905c2 1136 "TARGET_32BIT"
2f9b23e3 1137 "#" ; "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
1138 "&& reload_completed"
1139 [(parallel [(set (reg:CC CC_REGNUM)
1140 (compare:CC (match_dup 1) (match_dup 2)))
1141 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1142 (set (match_dup 3) (minus:SI (minus:SI (match_dup 4)
1143 (ashiftrt:SI (match_dup 2)
1144 (const_int 31)))
1145 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1146 {
1147 operands[3] = gen_highpart (SImode, operands[0]);
1148 operands[0] = gen_lowpart (SImode, operands[0]);
1149 operands[4] = gen_highpart (SImode, operands[1]);
1150 operands[1] = gen_lowpart (SImode, operands[1]);
1151 }
cffb2a26 1152 [(set_attr "conds" "clob")
1b7da4ac 1153 (set_attr "length" "8")
1154 (set_attr "type" "multiple")]
cffb2a26 1155)
9c08d1fa 1156
2f9b23e3 1157(define_insn_and_split "*subdi_zesidi_di"
cffb2a26 1158 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1159 (minus:DI (zero_extend:DI
cffb2a26 1160 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 1161 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 1162 (clobber (reg:CC CC_REGNUM))]
cffb2a26 1163 "TARGET_ARM"
2f9b23e3 1164 "#" ; "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
1165 ; is equivalent to:
1166 ; "subs\\t%Q0, %2, %Q1\;rsc\\t%R0, %R1, #0"
1167 "&& reload_completed"
1168 [(parallel [(set (reg:CC CC_REGNUM)
1169 (compare:CC (match_dup 2) (match_dup 1)))
1170 (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))])
1171 (set (match_dup 3) (minus:SI (minus:SI (const_int 0) (match_dup 4))
1172 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1173 {
1174 operands[3] = gen_highpart (SImode, operands[0]);
1175 operands[0] = gen_lowpart (SImode, operands[0]);
1176 operands[4] = gen_highpart (SImode, operands[1]);
1177 operands[1] = gen_lowpart (SImode, operands[1]);
1178 }
cffb2a26 1179 [(set_attr "conds" "clob")
1b7da4ac 1180 (set_attr "length" "8")
1181 (set_attr "type" "multiple")]
cffb2a26 1182)
9c08d1fa 1183
2f9b23e3 1184(define_insn_and_split "*subdi_sesidi_di"
cffb2a26 1185 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1186 (minus:DI (sign_extend:DI
cffb2a26 1187 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 1188 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 1189 (clobber (reg:CC CC_REGNUM))]
cffb2a26 1190 "TARGET_ARM"
2f9b23e3 1191 "#" ; "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
1192 ; is equivalent to:
1193 ; "subs\\t%Q0, %2, %Q1\;rsc\\t%R0, %R1, %2, asr #31"
1194 "&& reload_completed"
1195 [(parallel [(set (reg:CC CC_REGNUM)
1196 (compare:CC (match_dup 2) (match_dup 1)))
1197 (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))])
1198 (set (match_dup 3) (minus:SI (minus:SI
1199 (ashiftrt:SI (match_dup 2)
1200 (const_int 31))
1201 (match_dup 4))
1202 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1203 {
1204 operands[3] = gen_highpart (SImode, operands[0]);
1205 operands[0] = gen_lowpart (SImode, operands[0]);
1206 operands[4] = gen_highpart (SImode, operands[1]);
1207 operands[1] = gen_lowpart (SImode, operands[1]);
1208 }
cffb2a26 1209 [(set_attr "conds" "clob")
1b7da4ac 1210 (set_attr "length" "8")
1211 (set_attr "type" "multiple")]
cffb2a26 1212)
9c08d1fa 1213
2f9b23e3 1214(define_insn_and_split "*subdi_zesidi_zesidi"
cffb2a26 1215 [(set (match_operand:DI 0 "s_register_operand" "=r")
9c08d1fa 1216 (minus:DI (zero_extend:DI
cffb2a26 1217 (match_operand:SI 1 "s_register_operand" "r"))
9c08d1fa 1218 (zero_extend:DI
cffb2a26 1219 (match_operand:SI 2 "s_register_operand" "r"))))
bd5b4116 1220 (clobber (reg:CC CC_REGNUM))]
25f905c2 1221 "TARGET_32BIT"
2f9b23e3 1222 "#" ; "subs\\t%Q0, %1, %2\;sbc\\t%R0, %1, %1"
1223 "&& reload_completed"
1224 [(parallel [(set (reg:CC CC_REGNUM)
1225 (compare:CC (match_dup 1) (match_dup 2)))
1226 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1227 (set (match_dup 3) (minus:SI (minus:SI (match_dup 1) (match_dup 1))
1228 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1229 {
1230 operands[3] = gen_highpart (SImode, operands[0]);
1231 operands[0] = gen_lowpart (SImode, operands[0]);
1232 }
cffb2a26 1233 [(set_attr "conds" "clob")
1b7da4ac 1234 (set_attr "length" "8")
1235 (set_attr "type" "multiple")]
cffb2a26 1236)
b11cae9e 1237
87b22bf7 1238(define_expand "subsi3"
cffb2a26 1239 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 1240 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
1241 (match_operand:SI 2 "s_register_operand" "")))]
cffb2a26 1242 "TARGET_EITHER"
87b22bf7 1243 "
0438d37f 1244 if (CONST_INT_P (operands[1]))
87b22bf7 1245 {
25f905c2 1246 if (TARGET_32BIT)
cffb2a26 1247 {
96f57e36 1248 arm_split_constant (MINUS, SImode, NULL_RTX,
1249 INTVAL (operands[1]), operands[0],
e1ba4a27 1250 operands[2], optimize && can_create_pseudo_p ());
cffb2a26 1251 DONE;
1252 }
25f905c2 1253 else /* TARGET_THUMB1 */
cffb2a26 1254 operands[1] = force_reg (SImode, operands[1]);
87b22bf7 1255 }
cffb2a26 1256 "
1257)
87b22bf7 1258
747b7458 1259(define_insn "thumb1_subsi3_insn"
cffb2a26 1260 [(set (match_operand:SI 0 "register_operand" "=l")
1261 (minus:SI (match_operand:SI 1 "register_operand" "l")
747b7458 1262 (match_operand:SI 2 "reg_or_int_operand" "lPd")))]
25f905c2 1263 "TARGET_THUMB1"
cffb2a26 1264 "sub\\t%0, %1, %2"
747b7458 1265 [(set_attr "length" "2")
1b7da4ac 1266 (set_attr "conds" "set")
1267 (set_attr "type" "alus_reg")]
1268)
cffb2a26 1269
25f905c2 1270; ??? Check Thumb-2 split length
a0f94409 1271(define_insn_and_split "*arm_subsi3_insn"
7c36fe71 1272 [(set (match_operand:SI 0 "s_register_operand" "=l,l ,l ,l ,r ,r,r,rk,r")
1273 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "l ,0 ,l ,Pz,rI,r,r,k ,?n")
1274 (match_operand:SI 2 "reg_or_int_operand" "l ,Py,Pd,l ,r ,I,r,r ,r")))]
25f905c2 1275 "TARGET_32BIT"
e2348bcb 1276 "@
7c36fe71 1277 sub%?\\t%0, %1, %2
1278 sub%?\\t%0, %2
1279 sub%?\\t%0, %1, %2
1280 rsb%?\\t%0, %2, %1
87b22bf7 1281 rsb%?\\t%0, %2, %1
aaa37ad6 1282 sub%?\\t%0, %1, %2
080c0b9a 1283 sub%?\\t%0, %1, %2
65f68e55 1284 sub%?\\t%0, %1, %2
87b22bf7 1285 #"
0438d37f 1286 "&& (CONST_INT_P (operands[1])
91a5e339 1287 && !const_ok_for_arm (INTVAL (operands[1])))"
87b22bf7 1288 [(clobber (const_int 0))]
1289 "
96f57e36 1290 arm_split_constant (MINUS, SImode, curr_insn,
1291 INTVAL (operands[1]), operands[0], operands[2], 0);
87b22bf7 1292 DONE;
cffb2a26 1293 "
7c36fe71 1294 [(set_attr "length" "4,4,4,4,4,4,4,4,16")
1295 (set_attr "arch" "t2,t2,t2,t2,*,*,*,*,*")
65f68e55 1296 (set_attr "predicable" "yes")
7c36fe71 1297 (set_attr "predicable_short_it" "yes,yes,yes,yes,no,no,no,no,no")
1b7da4ac 1298 (set_attr "type" "alu_reg,alu_reg,alu_reg,alu_reg,alu_imm,alu_imm,alu_reg,alu_reg,multiple")]
a0f94409 1299)
1300
1301(define_peephole2
1302 [(match_scratch:SI 3 "r")
372575c7 1303 (set (match_operand:SI 0 "arm_general_register_operand" "")
a0f94409 1304 (minus:SI (match_operand:SI 1 "const_int_operand" "")
372575c7 1305 (match_operand:SI 2 "arm_general_register_operand" "")))]
25f905c2 1306 "TARGET_32BIT
a0f94409 1307 && !const_ok_for_arm (INTVAL (operands[1]))
1308 && const_ok_for_arm (~INTVAL (operands[1]))"
1309 [(set (match_dup 3) (match_dup 1))
1310 (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1311 ""
cffb2a26 1312)
b11cae9e 1313
f7fbdd4a 1314(define_insn "*subsi3_compare0"
bd5b4116 1315 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1316 (compare:CC_NOOV
65f68e55 1317 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,r,I")
1318 (match_operand:SI 2 "arm_rhs_operand" "I,r,r"))
215b30b3 1319 (const_int 0)))
65f68e55 1320 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9c08d1fa 1321 (minus:SI (match_dup 1) (match_dup 2)))]
25f905c2 1322 "TARGET_32BIT"
e2348bcb 1323 "@
65f68e55 1324 sub%.\\t%0, %1, %2
25f905c2 1325 sub%.\\t%0, %1, %2
1326 rsb%.\\t%0, %2, %1"
65f68e55 1327 [(set_attr "conds" "set")
d82e788e 1328 (set_attr "type" "alus_imm,alus_reg,alus_reg")]
cffb2a26 1329)
9c08d1fa 1330
190efb17 1331(define_insn "subsi3_compare"
080c0b9a 1332 [(set (reg:CC CC_REGNUM)
65f68e55 1333 (compare:CC (match_operand:SI 1 "arm_rhs_operand" "r,r,I")
1334 (match_operand:SI 2 "arm_rhs_operand" "I,r,r")))
1335 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2df9477b 1336 (minus:SI (match_dup 1) (match_dup 2)))]
1337 "TARGET_32BIT"
1338 "@
65f68e55 1339 sub%.\\t%0, %1, %2
2df9477b 1340 sub%.\\t%0, %1, %2
1341 rsb%.\\t%0, %2, %1"
65f68e55 1342 [(set_attr "conds" "set")
d82e788e 1343 (set_attr "type" "alus_imm,alus_reg,alus_reg")]
2df9477b 1344)
1345
604f3a0a 1346(define_expand "subsf3"
1347 [(set (match_operand:SF 0 "s_register_operand" "")
d86c91f6 1348 (minus:SF (match_operand:SF 1 "s_register_operand" "")
1349 (match_operand:SF 2 "s_register_operand" "")))]
25f905c2 1350 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1351 "
604f3a0a 1352")
1353
604f3a0a 1354(define_expand "subdf3"
1355 [(set (match_operand:DF 0 "s_register_operand" "")
d86c91f6 1356 (minus:DF (match_operand:DF 1 "s_register_operand" "")
1357 (match_operand:DF 2 "s_register_operand" "")))]
a50d7267 1358 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 1359 "
604f3a0a 1360")
1361
b11cae9e 1362\f
1363;; Multiplication insns
1364
4422d91f 1365(define_expand "mulhi3"
1366 [(set (match_operand:HI 0 "s_register_operand" "")
1367 (mult:HI (match_operand:HI 1 "s_register_operand" "")
1368 (match_operand:HI 2 "s_register_operand" "")))]
1369 "TARGET_DSP_MULTIPLY"
1370 "
1371 {
1372 rtx result = gen_reg_rtx (SImode);
1373 emit_insn (gen_mulhisi3 (result, operands[1], operands[2]));
1374 emit_move_insn (operands[0], gen_lowpart (HImode, result));
1375 DONE;
1376 }"
1377)
1378
cffb2a26 1379(define_expand "mulsi3"
1380 [(set (match_operand:SI 0 "s_register_operand" "")
1381 (mult:SI (match_operand:SI 2 "s_register_operand" "")
1382 (match_operand:SI 1 "s_register_operand" "")))]
1383 "TARGET_EITHER"
1384 ""
1385)
1386
9c08d1fa 1387;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
cffb2a26 1388(define_insn "*arm_mulsi3"
1389 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1390 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1391 (match_operand:SI 1 "s_register_operand" "%0,r")))]
58d7d654 1392 "TARGET_32BIT && !arm_arch6"
f7fbdd4a 1393 "mul%?\\t%0, %2, %1"
9da0ec36 1394 [(set_attr "type" "mul")
0d66636f 1395 (set_attr "predicable" "yes")]
cffb2a26 1396)
1397
58d7d654 1398(define_insn "*arm_mulsi3_v6"
d952d547 1399 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
1400 (mult:SI (match_operand:SI 1 "s_register_operand" "0,l,r")
1401 (match_operand:SI 2 "s_register_operand" "l,0,r")))]
58d7d654 1402 "TARGET_32BIT && arm_arch6"
1403 "mul%?\\t%0, %1, %2"
9da0ec36 1404 [(set_attr "type" "mul")
d952d547 1405 (set_attr "predicable" "yes")
1406 (set_attr "arch" "t2,t2,*")
1407 (set_attr "length" "4")
1408 (set_attr "predicable_short_it" "yes,yes,no")]
58d7d654 1409)
1410
215b30b3 1411; Unfortunately with the Thumb the '&'/'0' trick can fails when operands
1412; 1 and 2; are the same, because reload will make operand 0 match
1413; operand 1 without realizing that this conflicts with operand 2. We fix
1414; this by adding another alternative to match this case, and then `reload'
1415; it ourselves. This alternative must come first.
cffb2a26 1416(define_insn "*thumb_mulsi3"
1417 [(set (match_operand:SI 0 "register_operand" "=&l,&l,&l")
1418 (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1419 (match_operand:SI 2 "register_operand" "l,l,l")))]
58d7d654 1420 "TARGET_THUMB1 && !arm_arch6"
cffb2a26 1421 "*
1422 if (which_alternative < 2)
20c4e896 1423 return \"mov\\t%0, %1\;mul\\t%0, %2\";
cffb2a26 1424 else
20c4e896 1425 return \"mul\\t%0, %2\";
cffb2a26 1426 "
1427 [(set_attr "length" "4,4,2")
9da0ec36 1428 (set_attr "type" "muls")]
cffb2a26 1429)
b11cae9e 1430
58d7d654 1431(define_insn "*thumb_mulsi3_v6"
1432 [(set (match_operand:SI 0 "register_operand" "=l,l,l")
1433 (mult:SI (match_operand:SI 1 "register_operand" "0,l,0")
1434 (match_operand:SI 2 "register_operand" "l,0,0")))]
1435 "TARGET_THUMB1 && arm_arch6"
1436 "@
1490694c 1437 mul\\t%0, %2
1438 mul\\t%0, %1
58d7d654 1439 mul\\t%0, %1"
1440 [(set_attr "length" "2")
9da0ec36 1441 (set_attr "type" "muls")]
58d7d654 1442)
1443
f7fbdd4a 1444(define_insn "*mulsi3_compare0"
bd5b4116 1445 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1446 (compare:CC_NOOV (mult:SI
1447 (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1448 (match_operand:SI 1 "s_register_operand" "%0,r"))
9c08d1fa 1449 (const_int 0)))
1450 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1451 (mult:SI (match_dup 2) (match_dup 1)))]
58d7d654 1452 "TARGET_ARM && !arm_arch6"
1453 "mul%.\\t%0, %2, %1"
1454 [(set_attr "conds" "set")
9da0ec36 1455 (set_attr "type" "muls")]
58d7d654 1456)
1457
1458(define_insn "*mulsi3_compare0_v6"
1459 [(set (reg:CC_NOOV CC_REGNUM)
1460 (compare:CC_NOOV (mult:SI
1461 (match_operand:SI 2 "s_register_operand" "r")
1462 (match_operand:SI 1 "s_register_operand" "r"))
1463 (const_int 0)))
1464 (set (match_operand:SI 0 "s_register_operand" "=r")
1465 (mult:SI (match_dup 2) (match_dup 1)))]
1466 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1467 "mul%.\\t%0, %2, %1"
cffb2a26 1468 [(set_attr "conds" "set")
9da0ec36 1469 (set_attr "type" "muls")]
cffb2a26 1470)
9c08d1fa 1471
f7fbdd4a 1472(define_insn "*mulsi_compare0_scratch"
bd5b4116 1473 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1474 (compare:CC_NOOV (mult:SI
1475 (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1476 (match_operand:SI 1 "s_register_operand" "%0,r"))
9c08d1fa 1477 (const_int 0)))
1478 (clobber (match_scratch:SI 0 "=&r,&r"))]
58d7d654 1479 "TARGET_ARM && !arm_arch6"
1480 "mul%.\\t%0, %2, %1"
1481 [(set_attr "conds" "set")
9da0ec36 1482 (set_attr "type" "muls")]
58d7d654 1483)
1484
1485(define_insn "*mulsi_compare0_scratch_v6"
1486 [(set (reg:CC_NOOV CC_REGNUM)
1487 (compare:CC_NOOV (mult:SI
1488 (match_operand:SI 2 "s_register_operand" "r")
1489 (match_operand:SI 1 "s_register_operand" "r"))
1490 (const_int 0)))
1491 (clobber (match_scratch:SI 0 "=r"))]
1492 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1493 "mul%.\\t%0, %2, %1"
cffb2a26 1494 [(set_attr "conds" "set")
9da0ec36 1495 (set_attr "type" "muls")]
cffb2a26 1496)
9c08d1fa 1497
b11cae9e 1498;; Unnamed templates to match MLA instruction.
1499
f7fbdd4a 1500(define_insn "*mulsi3addsi"
9c08d1fa 1501 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
c8f69309 1502 (plus:SI
9c08d1fa 1503 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1504 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1505 (match_operand:SI 3 "s_register_operand" "r,r,0,0")))]
58d7d654 1506 "TARGET_32BIT && !arm_arch6"
1507 "mla%?\\t%0, %2, %1, %3"
9da0ec36 1508 [(set_attr "type" "mla")
58d7d654 1509 (set_attr "predicable" "yes")]
1510)
1511
1512(define_insn "*mulsi3addsi_v6"
1513 [(set (match_operand:SI 0 "s_register_operand" "=r")
1514 (plus:SI
1515 (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1516 (match_operand:SI 1 "s_register_operand" "r"))
1517 (match_operand:SI 3 "s_register_operand" "r")))]
1518 "TARGET_32BIT && arm_arch6"
f7fbdd4a 1519 "mla%?\\t%0, %2, %1, %3"
9da0ec36 1520 [(set_attr "type" "mla")
d952d547 1521 (set_attr "predicable" "yes")
1522 (set_attr "predicable_short_it" "no")]
0d66636f 1523)
b11cae9e 1524
f7fbdd4a 1525(define_insn "*mulsi3addsi_compare0"
bd5b4116 1526 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1527 (compare:CC_NOOV
1528 (plus:SI (mult:SI
1529 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1530 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1531 (match_operand:SI 3 "s_register_operand" "r,r,0,0"))
215b30b3 1532 (const_int 0)))
9c08d1fa 1533 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1534 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1535 (match_dup 3)))]
58d7d654 1536 "TARGET_ARM && arm_arch6"
1537 "mla%.\\t%0, %2, %1, %3"
1538 [(set_attr "conds" "set")
9da0ec36 1539 (set_attr "type" "mlas")]
58d7d654 1540)
1541
1542(define_insn "*mulsi3addsi_compare0_v6"
1543 [(set (reg:CC_NOOV CC_REGNUM)
1544 (compare:CC_NOOV
1545 (plus:SI (mult:SI
1546 (match_operand:SI 2 "s_register_operand" "r")
1547 (match_operand:SI 1 "s_register_operand" "r"))
1548 (match_operand:SI 3 "s_register_operand" "r"))
1549 (const_int 0)))
1550 (set (match_operand:SI 0 "s_register_operand" "=r")
1551 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1552 (match_dup 3)))]
1553 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1554 "mla%.\\t%0, %2, %1, %3"
0d66636f 1555 [(set_attr "conds" "set")
9da0ec36 1556 (set_attr "type" "mlas")]
0d66636f 1557)
9c08d1fa 1558
f7fbdd4a 1559(define_insn "*mulsi3addsi_compare0_scratch"
bd5b4116 1560 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1561 (compare:CC_NOOV
1562 (plus:SI (mult:SI
1563 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1564 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
215b30b3 1565 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1566 (const_int 0)))
9c08d1fa 1567 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
58d7d654 1568 "TARGET_ARM && !arm_arch6"
1569 "mla%.\\t%0, %2, %1, %3"
1570 [(set_attr "conds" "set")
9da0ec36 1571 (set_attr "type" "mlas")]
58d7d654 1572)
1573
1574(define_insn "*mulsi3addsi_compare0_scratch_v6"
1575 [(set (reg:CC_NOOV CC_REGNUM)
1576 (compare:CC_NOOV
1577 (plus:SI (mult:SI
1578 (match_operand:SI 2 "s_register_operand" "r")
1579 (match_operand:SI 1 "s_register_operand" "r"))
1580 (match_operand:SI 3 "s_register_operand" "r"))
1581 (const_int 0)))
1582 (clobber (match_scratch:SI 0 "=r"))]
1583 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1584 "mla%.\\t%0, %2, %1, %3"
cffb2a26 1585 [(set_attr "conds" "set")
9da0ec36 1586 (set_attr "type" "mlas")]
cffb2a26 1587)
f7fbdd4a 1588
89545238 1589(define_insn "*mulsi3subsi"
1590 [(set (match_operand:SI 0 "s_register_operand" "=r")
1591 (minus:SI
1592 (match_operand:SI 3 "s_register_operand" "r")
1593 (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1594 (match_operand:SI 1 "s_register_operand" "r"))))]
1595 "TARGET_32BIT && arm_arch_thumb2"
1596 "mls%?\\t%0, %2, %1, %3"
9da0ec36 1597 [(set_attr "type" "mla")
d952d547 1598 (set_attr "predicable" "yes")
1599 (set_attr "predicable_short_it" "no")]
89545238 1600)
1601
5cdca009 1602(define_expand "maddsidi4"
1603 [(set (match_operand:DI 0 "s_register_operand" "")
1604 (plus:DI
1605 (mult:DI
1606 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1607 (sign_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 "*mulsidi3adddi"
fe8dbf85 1613 [(set (match_operand:DI 0 "s_register_operand" "=&r")
82b85d08 1614 (plus:DI
215b30b3 1615 (mult:DI
fe8dbf85 1616 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1617 (sign_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 "smlal%?\\t%Q0, %R0, %3, %2"
9da0ec36 1621 [(set_attr "type" "smlal")
58d7d654 1622 (set_attr "predicable" "yes")]
1623)
1624
1625(define_insn "*mulsidi3adddi_v6"
1626 [(set (match_operand:DI 0 "s_register_operand" "=r")
1627 (plus:DI
1628 (mult:DI
1629 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1630 (sign_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 "smlal%?\\t%Q0, %R0, %3, %2"
9da0ec36 1634 [(set_attr "type" "smlal")
d952d547 1635 (set_attr "predicable" "yes")
1636 (set_attr "predicable_short_it" "no")]
0d66636f 1637)
82b85d08 1638
957788b0 1639;; 32x32->64 widening multiply.
1640;; As with mulsi3, the only difference between the v3-5 and v6+
1641;; versions of these patterns is the requirement that the output not
1642;; overlap the inputs, but that still means we have to have a named
1643;; expander and two different starred insns.
1644
1645(define_expand "mulsidi3"
1646 [(set (match_operand:DI 0 "s_register_operand" "")
1647 (mult:DI
1648 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1649 (sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1650 "TARGET_32BIT && arm_arch3m"
1651 ""
1652)
1653
1654(define_insn "*mulsidi3_nov6"
f7fbdd4a 1655 [(set (match_operand:DI 0 "s_register_operand" "=&r")
215b30b3 1656 (mult:DI
1657 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1658 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
58d7d654 1659 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1660 "smull%?\\t%Q0, %R0, %1, %2"
9da0ec36 1661 [(set_attr "type" "smull")
58d7d654 1662 (set_attr "predicable" "yes")]
1663)
1664
957788b0 1665(define_insn "*mulsidi3_v6"
58d7d654 1666 [(set (match_operand:DI 0 "s_register_operand" "=r")
1667 (mult:DI
1668 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1669 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1670 "TARGET_32BIT && arm_arch6"
97499065 1671 "smull%?\\t%Q0, %R0, %1, %2"
9da0ec36 1672 [(set_attr "type" "smull")
d952d547 1673 (set_attr "predicable" "yes")
1674 (set_attr "predicable_short_it" "no")]
0d66636f 1675)
f7fbdd4a 1676
957788b0 1677(define_expand "umulsidi3"
1678 [(set (match_operand:DI 0 "s_register_operand" "")
1679 (mult:DI
1680 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1681 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1682 "TARGET_32BIT && arm_arch3m"
1683 ""
1684)
1685
1686(define_insn "*umulsidi3_nov6"
f7fbdd4a 1687 [(set (match_operand:DI 0 "s_register_operand" "=&r")
215b30b3 1688 (mult:DI
1689 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1690 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
58d7d654 1691 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1692 "umull%?\\t%Q0, %R0, %1, %2"
9da0ec36 1693 [(set_attr "type" "umull")
58d7d654 1694 (set_attr "predicable" "yes")]
1695)
1696
957788b0 1697(define_insn "*umulsidi3_v6"
58d7d654 1698 [(set (match_operand:DI 0 "s_register_operand" "=r")
1699 (mult:DI
1700 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1701 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1702 "TARGET_32BIT && arm_arch6"
97499065 1703 "umull%?\\t%Q0, %R0, %1, %2"
9da0ec36 1704 [(set_attr "type" "umull")
d952d547 1705 (set_attr "predicable" "yes")
1706 (set_attr "predicable_short_it" "no")]
0d66636f 1707)
b11cae9e 1708
5cdca009 1709(define_expand "umaddsidi4"
1710 [(set (match_operand:DI 0 "s_register_operand" "")
1711 (plus:DI
1712 (mult:DI
1713 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1714 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1715 (match_operand:DI 3 "s_register_operand" "")))]
1716 "TARGET_32BIT && arm_arch3m"
1717 "")
82b85d08 1718
1719(define_insn "*umulsidi3adddi"
8ead09f9 1720 [(set (match_operand:DI 0 "s_register_operand" "=&r")
82b85d08 1721 (plus:DI
215b30b3 1722 (mult:DI
fe8dbf85 1723 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1724 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1725 (match_operand:DI 1 "s_register_operand" "0")))]
58d7d654 1726 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1727 "umlal%?\\t%Q0, %R0, %3, %2"
9da0ec36 1728 [(set_attr "type" "umlal")
58d7d654 1729 (set_attr "predicable" "yes")]
1730)
1731
1732(define_insn "*umulsidi3adddi_v6"
1733 [(set (match_operand:DI 0 "s_register_operand" "=r")
1734 (plus:DI
1735 (mult:DI
1736 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1737 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1738 (match_operand:DI 1 "s_register_operand" "0")))]
1739 "TARGET_32BIT && arm_arch6"
fe8dbf85 1740 "umlal%?\\t%Q0, %R0, %3, %2"
9da0ec36 1741 [(set_attr "type" "umlal")
d952d547 1742 (set_attr "predicable" "yes")
1743 (set_attr "predicable_short_it" "no")]
0d66636f 1744)
82b85d08 1745
957788b0 1746(define_expand "smulsi3_highpart"
1747 [(parallel
1748 [(set (match_operand:SI 0 "s_register_operand" "")
1749 (truncate:SI
1750 (lshiftrt:DI
1751 (mult:DI
1752 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1753 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1754 (const_int 32))))
1755 (clobber (match_scratch:SI 3 ""))])]
1756 "TARGET_32BIT && arm_arch3m"
1757 ""
1758)
1759
1760(define_insn "*smulsi3_highpart_nov6"
f082f1c4 1761 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1762 (truncate:SI
1763 (lshiftrt:DI
215b30b3 1764 (mult:DI
e5fea38e 1765 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
215b30b3 1766 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
f082f1c4 1767 (const_int 32))))
1768 (clobber (match_scratch:SI 3 "=&r,&r"))]
58d7d654 1769 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1770 "smull%?\\t%3, %0, %2, %1"
9da0ec36 1771 [(set_attr "type" "smull")
58d7d654 1772 (set_attr "predicable" "yes")]
1773)
1774
957788b0 1775(define_insn "*smulsi3_highpart_v6"
58d7d654 1776 [(set (match_operand:SI 0 "s_register_operand" "=r")
1777 (truncate:SI
1778 (lshiftrt:DI
1779 (mult:DI
1780 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1781 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1782 (const_int 32))))
1783 (clobber (match_scratch:SI 3 "=r"))]
1784 "TARGET_32BIT && arm_arch6"
f082f1c4 1785 "smull%?\\t%3, %0, %2, %1"
9da0ec36 1786 [(set_attr "type" "smull")
d952d547 1787 (set_attr "predicable" "yes")
1788 (set_attr "predicable_short_it" "no")]
cffb2a26 1789)
f082f1c4 1790
957788b0 1791(define_expand "umulsi3_highpart"
1792 [(parallel
1793 [(set (match_operand:SI 0 "s_register_operand" "")
1794 (truncate:SI
1795 (lshiftrt:DI
1796 (mult:DI
1797 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1798 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1799 (const_int 32))))
1800 (clobber (match_scratch:SI 3 ""))])]
1801 "TARGET_32BIT && arm_arch3m"
1802 ""
1803)
1804
1805(define_insn "*umulsi3_highpart_nov6"
f082f1c4 1806 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1807 (truncate:SI
1808 (lshiftrt:DI
215b30b3 1809 (mult:DI
e5fea38e 1810 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
215b30b3 1811 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
f082f1c4 1812 (const_int 32))))
1813 (clobber (match_scratch:SI 3 "=&r,&r"))]
58d7d654 1814 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1815 "umull%?\\t%3, %0, %2, %1"
9da0ec36 1816 [(set_attr "type" "umull")
58d7d654 1817 (set_attr "predicable" "yes")]
1818)
1819
957788b0 1820(define_insn "*umulsi3_highpart_v6"
58d7d654 1821 [(set (match_operand:SI 0 "s_register_operand" "=r")
1822 (truncate:SI
1823 (lshiftrt:DI
1824 (mult:DI
1825 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1826 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1827 (const_int 32))))
1828 (clobber (match_scratch:SI 3 "=r"))]
1829 "TARGET_32BIT && arm_arch6"
f082f1c4 1830 "umull%?\\t%3, %0, %2, %1"
9da0ec36 1831 [(set_attr "type" "umull")
d952d547 1832 (set_attr "predicable" "yes")
1833 (set_attr "predicable_short_it" "no")]
cffb2a26 1834)
f082f1c4 1835
331beb1a 1836(define_insn "mulhisi3"
1837 [(set (match_operand:SI 0 "s_register_operand" "=r")
1838 (mult:SI (sign_extend:SI
1839 (match_operand:HI 1 "s_register_operand" "%r"))
1840 (sign_extend:SI
1841 (match_operand:HI 2 "s_register_operand" "r"))))]
25f905c2 1842 "TARGET_DSP_MULTIPLY"
61a2d04c 1843 "smulbb%?\\t%0, %1, %2"
9da0ec36 1844 [(set_attr "type" "smulxy")
fec538d9 1845 (set_attr "predicable" "yes")]
1846)
1847
1848(define_insn "*mulhisi3tb"
1849 [(set (match_operand:SI 0 "s_register_operand" "=r")
1850 (mult:SI (ashiftrt:SI
1851 (match_operand:SI 1 "s_register_operand" "r")
1852 (const_int 16))
1853 (sign_extend:SI
1854 (match_operand:HI 2 "s_register_operand" "r"))))]
25f905c2 1855 "TARGET_DSP_MULTIPLY"
fec538d9 1856 "smultb%?\\t%0, %1, %2"
9da0ec36 1857 [(set_attr "type" "smulxy")
d952d547 1858 (set_attr "predicable" "yes")
1859 (set_attr "predicable_short_it" "no")]
fec538d9 1860)
1861
1862(define_insn "*mulhisi3bt"
1863 [(set (match_operand:SI 0 "s_register_operand" "=r")
1864 (mult:SI (sign_extend:SI
1865 (match_operand:HI 1 "s_register_operand" "r"))
1866 (ashiftrt:SI
1867 (match_operand:SI 2 "s_register_operand" "r")
1868 (const_int 16))))]
25f905c2 1869 "TARGET_DSP_MULTIPLY"
fec538d9 1870 "smulbt%?\\t%0, %1, %2"
9da0ec36 1871 [(set_attr "type" "smulxy")
d952d547 1872 (set_attr "predicable" "yes")
1873 (set_attr "predicable_short_it" "no")]
fec538d9 1874)
1875
1876(define_insn "*mulhisi3tt"
1877 [(set (match_operand:SI 0 "s_register_operand" "=r")
1878 (mult:SI (ashiftrt:SI
1879 (match_operand:SI 1 "s_register_operand" "r")
1880 (const_int 16))
1881 (ashiftrt:SI
1882 (match_operand:SI 2 "s_register_operand" "r")
1883 (const_int 16))))]
25f905c2 1884 "TARGET_DSP_MULTIPLY"
fec538d9 1885 "smultt%?\\t%0, %1, %2"
9da0ec36 1886 [(set_attr "type" "smulxy")
d952d547 1887 (set_attr "predicable" "yes")
1888 (set_attr "predicable_short_it" "no")]
331beb1a 1889)
1890
5cdca009 1891(define_insn "maddhisi4"
331beb1a 1892 [(set (match_operand:SI 0 "s_register_operand" "=r")
cfa6c608 1893 (plus:SI (mult:SI (sign_extend:SI
1894 (match_operand:HI 1 "s_register_operand" "r"))
331beb1a 1895 (sign_extend:SI
cfa6c608 1896 (match_operand:HI 2 "s_register_operand" "r")))
1897 (match_operand:SI 3 "s_register_operand" "r")))]
25f905c2 1898 "TARGET_DSP_MULTIPLY"
5cdca009 1899 "smlabb%?\\t%0, %1, %2, %3"
9da0ec36 1900 [(set_attr "type" "smlaxy")
d952d547 1901 (set_attr "predicable" "yes")
1902 (set_attr "predicable_short_it" "no")]
331beb1a 1903)
1904
9a92f368 1905;; Note: there is no maddhisi4ibt because this one is canonical form
1906(define_insn "*maddhisi4tb"
1907 [(set (match_operand:SI 0 "s_register_operand" "=r")
1908 (plus:SI (mult:SI (ashiftrt:SI
1909 (match_operand:SI 1 "s_register_operand" "r")
1910 (const_int 16))
1911 (sign_extend:SI
1912 (match_operand:HI 2 "s_register_operand" "r")))
1913 (match_operand:SI 3 "s_register_operand" "r")))]
1914 "TARGET_DSP_MULTIPLY"
1915 "smlatb%?\\t%0, %1, %2, %3"
9da0ec36 1916 [(set_attr "type" "smlaxy")
d952d547 1917 (set_attr "predicable" "yes")
1918 (set_attr "predicable_short_it" "no")]
9a92f368 1919)
1920
1921(define_insn "*maddhisi4tt"
1922 [(set (match_operand:SI 0 "s_register_operand" "=r")
1923 (plus:SI (mult:SI (ashiftrt:SI
1924 (match_operand:SI 1 "s_register_operand" "r")
1925 (const_int 16))
1926 (ashiftrt:SI
1927 (match_operand:SI 2 "s_register_operand" "r")
1928 (const_int 16)))
1929 (match_operand:SI 3 "s_register_operand" "r")))]
1930 "TARGET_DSP_MULTIPLY"
1931 "smlatt%?\\t%0, %1, %2, %3"
9da0ec36 1932 [(set_attr "type" "smlaxy")
d952d547 1933 (set_attr "predicable" "yes")
1934 (set_attr "predicable_short_it" "no")]
9a92f368 1935)
1936
aff5fb4d 1937(define_insn "maddhidi4"
331beb1a 1938 [(set (match_operand:DI 0 "s_register_operand" "=r")
1939 (plus:DI
331beb1a 1940 (mult:DI (sign_extend:DI
d952d547 1941 (match_operand:HI 1 "s_register_operand" "r"))
331beb1a 1942 (sign_extend:DI
cfa6c608 1943 (match_operand:HI 2 "s_register_operand" "r")))
1944 (match_operand:DI 3 "s_register_operand" "0")))]
25f905c2 1945 "TARGET_DSP_MULTIPLY"
5cdca009 1946 "smlalbb%?\\t%Q0, %R0, %1, %2"
9da0ec36 1947 [(set_attr "type" "smlalxy")
d952d547 1948 (set_attr "predicable" "yes")
1949 (set_attr "predicable_short_it" "no")])
331beb1a 1950
9a92f368 1951;; Note: there is no maddhidi4ibt because this one is canonical form
1952(define_insn "*maddhidi4tb"
1953 [(set (match_operand:DI 0 "s_register_operand" "=r")
1954 (plus:DI
1955 (mult:DI (sign_extend:DI
1956 (ashiftrt:SI
1957 (match_operand:SI 1 "s_register_operand" "r")
1958 (const_int 16)))
1959 (sign_extend:DI
1960 (match_operand:HI 2 "s_register_operand" "r")))
1961 (match_operand:DI 3 "s_register_operand" "0")))]
1962 "TARGET_DSP_MULTIPLY"
1963 "smlaltb%?\\t%Q0, %R0, %1, %2"
9da0ec36 1964 [(set_attr "type" "smlalxy")
d952d547 1965 (set_attr "predicable" "yes")
1966 (set_attr "predicable_short_it" "no")])
9a92f368 1967
1968(define_insn "*maddhidi4tt"
1969 [(set (match_operand:DI 0 "s_register_operand" "=r")
1970 (plus:DI
1971 (mult:DI (sign_extend:DI
1972 (ashiftrt:SI
1973 (match_operand:SI 1 "s_register_operand" "r")
1974 (const_int 16)))
1975 (sign_extend:DI
1976 (ashiftrt:SI
1977 (match_operand:SI 2 "s_register_operand" "r")
1978 (const_int 16))))
1979 (match_operand:DI 3 "s_register_operand" "0")))]
1980 "TARGET_DSP_MULTIPLY"
1981 "smlaltt%?\\t%Q0, %R0, %1, %2"
9da0ec36 1982 [(set_attr "type" "smlalxy")
d952d547 1983 (set_attr "predicable" "yes")
1984 (set_attr "predicable_short_it" "no")])
9a92f368 1985
604f3a0a 1986(define_expand "mulsf3"
1987 [(set (match_operand:SF 0 "s_register_operand" "")
1988 (mult:SF (match_operand:SF 1 "s_register_operand" "")
d86c91f6 1989 (match_operand:SF 2 "s_register_operand" "")))]
25f905c2 1990 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1991 "
604f3a0a 1992")
1993
604f3a0a 1994(define_expand "muldf3"
1995 [(set (match_operand:DF 0 "s_register_operand" "")
1996 (mult:DF (match_operand:DF 1 "s_register_operand" "")
d86c91f6 1997 (match_operand:DF 2 "s_register_operand" "")))]
a50d7267 1998 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 1999 "
604f3a0a 2000")
b11cae9e 2001\f
2002;; Division insns
2003
7db9af5d 2004(define_expand "divsf3"
2005 [(set (match_operand:SF 0 "s_register_operand" "")
d86c91f6 2006 (div:SF (match_operand:SF 1 "s_register_operand" "")
2007 (match_operand:SF 2 "s_register_operand" "")))]
994606f8 2008 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
7db9af5d 2009 "")
9c08d1fa 2010
7db9af5d 2011(define_expand "divdf3"
2012 [(set (match_operand:DF 0 "s_register_operand" "")
d86c91f6 2013 (div:DF (match_operand:DF 1 "s_register_operand" "")
2014 (match_operand:DF 2 "s_register_operand" "")))]
994606f8 2015 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
7db9af5d 2016 "")
b11cae9e 2017\f
2018;; Boolean and,ior,xor insns
2019
f6ebffac 2020;; Split up double word logical operations
2021
2022;; Split up simple DImode logical operations. Simply perform the logical
2023;; operation on the upper and lower halves of the registers.
2024(define_split
2025 [(set (match_operand:DI 0 "s_register_operand" "")
2026 (match_operator:DI 6 "logical_binary_operator"
2027 [(match_operand:DI 1 "s_register_operand" "")
2028 (match_operand:DI 2 "s_register_operand" "")]))]
25f905c2 2029 "TARGET_32BIT && reload_completed
e2669ea7 2030 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))
25f905c2 2031 && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
f6ebffac 2032 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
2033 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
2034 "
215b30b3 2035 {
2036 operands[3] = gen_highpart (SImode, operands[0]);
2037 operands[0] = gen_lowpart (SImode, operands[0]);
2038 operands[4] = gen_highpart (SImode, operands[1]);
2039 operands[1] = gen_lowpart (SImode, operands[1]);
2040 operands[5] = gen_highpart (SImode, operands[2]);
2041 operands[2] = gen_lowpart (SImode, operands[2]);
2042 }"
2043)
f6ebffac 2044
f6ebffac 2045(define_split
2046 [(set (match_operand:DI 0 "s_register_operand" "")
2047 (match_operator:DI 6 "logical_binary_operator"
2048 [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
2049 (match_operand:DI 1 "s_register_operand" "")]))]
25f905c2 2050 "TARGET_32BIT && reload_completed"
f6ebffac 2051 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
2052 (set (match_dup 3) (match_op_dup:SI 6
2053 [(ashiftrt:SI (match_dup 2) (const_int 31))
2054 (match_dup 4)]))]
2055 "
215b30b3 2056 {
2057 operands[3] = gen_highpart (SImode, operands[0]);
2058 operands[0] = gen_lowpart (SImode, operands[0]);
2059 operands[4] = gen_highpart (SImode, operands[1]);
2060 operands[1] = gen_lowpart (SImode, operands[1]);
2061 operands[5] = gen_highpart (SImode, operands[2]);
2062 operands[2] = gen_lowpart (SImode, operands[2]);
2063 }"
2064)
f6ebffac 2065
f6ebffac 2066;; The zero extend of operand 2 means we can just copy the high part of
2067;; operand1 into operand0.
2068(define_split
2069 [(set (match_operand:DI 0 "s_register_operand" "")
2070 (ior:DI
2071 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
2072 (match_operand:DI 1 "s_register_operand" "")))]
25f905c2 2073 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
f6ebffac 2074 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
2075 (set (match_dup 3) (match_dup 4))]
2076 "
215b30b3 2077 {
2078 operands[4] = gen_highpart (SImode, operands[1]);
2079 operands[3] = gen_highpart (SImode, operands[0]);
2080 operands[0] = gen_lowpart (SImode, operands[0]);
2081 operands[1] = gen_lowpart (SImode, operands[1]);
2082 }"
2083)
f6ebffac 2084
2085;; The zero extend of operand 2 means we can just copy the high part of
2086;; operand1 into operand0.
2087(define_split
2088 [(set (match_operand:DI 0 "s_register_operand" "")
2089 (xor:DI
2090 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
2091 (match_operand:DI 1 "s_register_operand" "")))]
25f905c2 2092 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
f6ebffac 2093 [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
2094 (set (match_dup 3) (match_dup 4))]
2095 "
215b30b3 2096 {
2097 operands[4] = gen_highpart (SImode, operands[1]);
2098 operands[3] = gen_highpart (SImode, operands[0]);
2099 operands[0] = gen_lowpart (SImode, operands[0]);
2100 operands[1] = gen_lowpart (SImode, operands[1]);
2101 }"
2102)
f6ebffac 2103
e2669ea7 2104(define_expand "anddi3"
2105 [(set (match_operand:DI 0 "s_register_operand" "")
2106 (and:DI (match_operand:DI 1 "s_register_operand" "")
2107 (match_operand:DI 2 "neon_inv_logic_op2" "")))]
2108 "TARGET_32BIT"
2109 ""
2110)
2111
f6bbdcf6 2112(define_insn_and_split "*anddi3_insn"
0a314dcd 2113 [(set (match_operand:DI 0 "s_register_operand" "=w,w ,&r,&r,&r,&r,?w,?w")
2114 (and:DI (match_operand:DI 1 "s_register_operand" "%w,0 ,0 ,r ,0 ,r ,w ,0")
2115 (match_operand:DI 2 "arm_anddi_operand_neon" "w ,DL,r ,r ,De,De,w ,DL")))]
f6bbdcf6 2116 "TARGET_32BIT && !TARGET_IWMMXT"
2117{
2118 switch (which_alternative)
2119 {
0a314dcd 2120 case 0: /* fall through */
2121 case 6: return "vand\t%P0, %P1, %P2";
2122 case 1: /* fall through */
2123 case 7: return neon_output_logic_immediate ("vand", &operands[2],
2124 DImode, 1, VALID_NEON_QREG_MODE (DImode));
f6bbdcf6 2125 case 2:
0a314dcd 2126 case 3:
2127 case 4:
f6bbdcf6 2128 case 5: /* fall through */
0a314dcd 2129 return "#";
f6bbdcf6 2130 default: gcc_unreachable ();
2131 }
2132}
0a314dcd 2133 "TARGET_32BIT && !TARGET_IWMMXT && reload_completed
2134 && !(IS_VFP_REGNUM (REGNO (operands[0])))"
f6bbdcf6 2135 [(set (match_dup 3) (match_dup 4))
2136 (set (match_dup 5) (match_dup 6))]
2137 "
2138 {
2139 operands[3] = gen_lowpart (SImode, operands[0]);
2140 operands[5] = gen_highpart (SImode, operands[0]);
2141
2142 operands[4] = simplify_gen_binary (AND, SImode,
2143 gen_lowpart (SImode, operands[1]),
2144 gen_lowpart (SImode, operands[2]));
2145 operands[6] = simplify_gen_binary (AND, SImode,
2146 gen_highpart (SImode, operands[1]),
2147 gen_highpart_mode (SImode, DImode, operands[2]));
2148
2149 }"
32093010 2150 [(set_attr "type" "neon_logic,neon_logic,multiple,multiple,\
2151 multiple,multiple,neon_logic,neon_logic")
0a314dcd 2152 (set_attr "arch" "neon_for_64bits,neon_for_64bits,*,*,*,*,
f6bbdcf6 2153 avoid_neon_for_64bits,avoid_neon_for_64bits")
0a314dcd 2154 (set_attr "length" "*,*,8,8,8,8,*,*")
2155 ]
215b30b3 2156)
b11cae9e 2157
a0f94409 2158(define_insn_and_split "*anddi_zesidi_di"
9c08d1fa 2159 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2160 (and:DI (zero_extend:DI
2161 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 2162 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2163 "TARGET_32BIT"
f6ebffac 2164 "#"
25f905c2 2165 "TARGET_32BIT && reload_completed"
a0f94409 2166 ; The zero extend of operand 2 clears the high word of the output
2167 ; operand.
2168 [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
2169 (set (match_dup 3) (const_int 0))]
2170 "
2171 {
2172 operands[3] = gen_highpart (SImode, operands[0]);
2173 operands[0] = gen_lowpart (SImode, operands[0]);
2174 operands[1] = gen_lowpart (SImode, operands[1]);
2175 }"
1b7da4ac 2176 [(set_attr "length" "8")
2177 (set_attr "type" "multiple")]
215b30b3 2178)
b11cae9e 2179
f7fbdd4a 2180(define_insn "*anddi_sesdi_di"
cffb2a26 2181 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 2182 (and:DI (sign_extend:DI
2183 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 2184 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2185 "TARGET_32BIT"
f6ebffac 2186 "#"
1b7da4ac 2187 [(set_attr "length" "8")
2188 (set_attr "type" "multiple")]
cffb2a26 2189)
b11cae9e 2190
87b22bf7 2191(define_expand "andsi3"
cffb2a26 2192 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2193 (and:SI (match_operand:SI 1 "s_register_operand" "")
2194 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 2195 "TARGET_EITHER"
87b22bf7 2196 "
25f905c2 2197 if (TARGET_32BIT)
87b22bf7 2198 {
0438d37f 2199 if (CONST_INT_P (operands[2]))
cffb2a26 2200 {
47b5b27b 2201 if (INTVAL (operands[2]) == 255 && arm_arch6)
2202 {
2203 operands[1] = convert_to_mode (QImode, operands[1], 1);
2204 emit_insn (gen_thumb2_zero_extendqisi2_v6 (operands[0],
2205 operands[1]));
2206 }
2207 else
2208 arm_split_constant (AND, SImode, NULL_RTX,
2209 INTVAL (operands[2]), operands[0],
2210 operands[1],
2211 optimize && can_create_pseudo_p ());
615caa51 2212
cffb2a26 2213 DONE;
2214 }
87b22bf7 2215 }
25f905c2 2216 else /* TARGET_THUMB1 */
cffb2a26 2217 {
0438d37f 2218 if (!CONST_INT_P (operands[2]))
923ffadb 2219 {
2220 rtx tmp = force_reg (SImode, operands[2]);
2221 if (rtx_equal_p (operands[0], operands[1]))
2222 operands[2] = tmp;
2223 else
2224 {
2225 operands[2] = operands[1];
2226 operands[1] = tmp;
2227 }
2228 }
cffb2a26 2229 else
2230 {
2231 int i;
2232
215b30b3 2233 if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
cffb2a26 2234 {
215b30b3 2235 operands[2] = force_reg (SImode,
2236 GEN_INT (~INTVAL (operands[2])));
cffb2a26 2237
747b7458 2238 emit_insn (gen_thumb1_bicsi3 (operands[0], operands[2], operands[1]));
cffb2a26 2239
2240 DONE;
2241 }
87b22bf7 2242
cffb2a26 2243 for (i = 9; i <= 31; i++)
2244 {
2245 if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
2246 {
2247 emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
2248 const0_rtx));
2249 DONE;
2250 }
215b30b3 2251 else if ((((HOST_WIDE_INT) 1) << i) - 1
2252 == ~INTVAL (operands[2]))
cffb2a26 2253 {
2254 rtx shift = GEN_INT (i);
2255 rtx reg = gen_reg_rtx (SImode);
2256
2257 emit_insn (gen_lshrsi3 (reg, operands[1], shift));
2258 emit_insn (gen_ashlsi3 (operands[0], reg, shift));
2259
2260 DONE;
2261 }
2262 }
2263
2264 operands[2] = force_reg (SImode, operands[2]);
2265 }
215b30b3 2266 }
2267 "
cffb2a26 2268)
2269
25f905c2 2270; ??? Check split length for Thumb-2
a0f94409 2271(define_insn_and_split "*arm_andsi3_insn"
29e234a3 2272 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r,r,r")
2273 (and:SI (match_operand:SI 1 "s_register_operand" "%r,0,r,r,r")
2274 (match_operand:SI 2 "reg_or_int_operand" "I,l,K,r,?n")))]
25f905c2 2275 "TARGET_32BIT"
5565501b 2276 "@
29e234a3 2277 and%?\\t%0, %1, %2
5565501b 2278 and%?\\t%0, %1, %2
87b22bf7 2279 bic%?\\t%0, %1, #%B2
65f68e55 2280 and%?\\t%0, %1, %2
87b22bf7 2281 #"
25f905c2 2282 "TARGET_32BIT
0438d37f 2283 && CONST_INT_P (operands[2])
a0f94409 2284 && !(const_ok_for_arm (INTVAL (operands[2]))
2285 || const_ok_for_arm (~INTVAL (operands[2])))"
2286 [(clobber (const_int 0))]
2287 "
96f57e36 2288 arm_split_constant (AND, SImode, curr_insn,
2289 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 2290 DONE;
2291 "
29e234a3 2292 [(set_attr "length" "4,4,4,4,16")
65f68e55 2293 (set_attr "predicable" "yes")
29e234a3 2294 (set_attr "predicable_short_it" "no,yes,no,no,no")
d82e788e 2295 (set_attr "type" "logic_imm,logic_imm,logic_reg,logic_reg,logic_imm")]
cffb2a26 2296)
2297
25f905c2 2298(define_insn "*thumb1_andsi3_insn"
cffb2a26 2299 [(set (match_operand:SI 0 "register_operand" "=l")
2300 (and:SI (match_operand:SI 1 "register_operand" "%0")
2301 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 2302 "TARGET_THUMB1"
747b7458 2303 "and\\t%0, %2"
2304 [(set_attr "length" "2")
d82e788e 2305 (set_attr "type" "logic_imm")
747b7458 2306 (set_attr "conds" "set")])
87b22bf7 2307
f7fbdd4a 2308(define_insn "*andsi3_compare0"
bd5b4116 2309 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 2310 (compare:CC_NOOV
65f68e55 2311 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
2312 (match_operand:SI 2 "arm_not_operand" "I,K,r"))
5565501b 2313 (const_int 0)))
65f68e55 2314 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9c08d1fa 2315 (and:SI (match_dup 1) (match_dup 2)))]
25f905c2 2316 "TARGET_32BIT"
5565501b 2317 "@
25f905c2 2318 and%.\\t%0, %1, %2
65f68e55 2319 bic%.\\t%0, %1, #%B2
2320 and%.\\t%0, %1, %2"
2321 [(set_attr "conds" "set")
d82e788e 2322 (set_attr "type" "logics_imm,logics_imm,logics_reg")]
cffb2a26 2323)
9c08d1fa 2324
f7fbdd4a 2325(define_insn "*andsi3_compare0_scratch"
bd5b4116 2326 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 2327 (compare:CC_NOOV
65f68e55 2328 (and:SI (match_operand:SI 0 "s_register_operand" "r,r,r")
2329 (match_operand:SI 1 "arm_not_operand" "I,K,r"))
5565501b 2330 (const_int 0)))
65f68e55 2331 (clobber (match_scratch:SI 2 "=X,r,X"))]
25f905c2 2332 "TARGET_32BIT"
5565501b 2333 "@
2334 tst%?\\t%0, %1
65f68e55 2335 bic%.\\t%2, %0, #%B1
2336 tst%?\\t%0, %1"
2337 [(set_attr "conds" "set")
d82e788e 2338 (set_attr "type" "logics_imm,logics_imm,logics_reg")]
0d66636f 2339)
9c08d1fa 2340
f7fbdd4a 2341(define_insn "*zeroextractsi_compare0_scratch"
bd5b4116 2342 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2343 (compare:CC_NOOV (zero_extract:SI
2344 (match_operand:SI 0 "s_register_operand" "r")
d952d547 2345 (match_operand 1 "const_int_operand" "n")
206ee9a2 2346 (match_operand 2 "const_int_operand" "n"))
9c08d1fa 2347 (const_int 0)))]
25f905c2 2348 "TARGET_32BIT
cffb2a26 2349 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
2350 && INTVAL (operands[1]) > 0
2351 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
2352 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
9c08d1fa 2353 "*
5c49a439 2354 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
2355 << INTVAL (operands[2]));
40dbec34 2356 output_asm_insn (\"tst%?\\t%0, %1\", operands);
e2348bcb 2357 return \"\";
0d66636f 2358 "
596e5e8f 2359 [(set_attr "conds" "set")
65f68e55 2360 (set_attr "predicable" "yes")
d952d547 2361 (set_attr "predicable_short_it" "no")
d82e788e 2362 (set_attr "type" "logics_imm")]
0d66636f 2363)
9c08d1fa 2364
f4462328 2365(define_insn_and_split "*ne_zeroextractsi"
c4034607 2366 [(set (match_operand:SI 0 "s_register_operand" "=r")
2367 (ne:SI (zero_extract:SI
2368 (match_operand:SI 1 "s_register_operand" "r")
2369 (match_operand:SI 2 "const_int_operand" "n")
2370 (match_operand:SI 3 "const_int_operand" "n"))
3b8c7f7a 2371 (const_int 0)))
2372 (clobber (reg:CC CC_REGNUM))]
25f905c2 2373 "TARGET_32BIT
cffb2a26 2374 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2375 && INTVAL (operands[2]) > 0
2376 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2377 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
f4462328 2378 "#"
25f905c2 2379 "TARGET_32BIT
f4462328 2380 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2381 && INTVAL (operands[2]) > 0
2382 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2383 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
2384 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2385 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2386 (const_int 0)))
2387 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2388 (set (match_dup 0)
2389 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2390 (match_dup 0) (const_int 1)))]
2391 "
2392 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
2393 << INTVAL (operands[3]));
2394 "
2395 [(set_attr "conds" "clob")
25f905c2 2396 (set (attr "length")
2397 (if_then_else (eq_attr "is_thumb" "yes")
2398 (const_int 12)
1b7da4ac 2399 (const_int 8)))
2400 (set_attr "type" "multiple")]
f4462328 2401)
2402
2403(define_insn_and_split "*ne_zeroextractsi_shifted"
2404 [(set (match_operand:SI 0 "s_register_operand" "=r")
2405 (ne:SI (zero_extract:SI
2406 (match_operand:SI 1 "s_register_operand" "r")
2407 (match_operand:SI 2 "const_int_operand" "n")
2408 (const_int 0))
2409 (const_int 0)))
2410 (clobber (reg:CC CC_REGNUM))]
2411 "TARGET_ARM"
2412 "#"
2413 "TARGET_ARM"
2414 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2415 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2416 (const_int 0)))
2417 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2418 (set (match_dup 0)
2419 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2420 (match_dup 0) (const_int 1)))]
2421 "
2422 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
2423 "
2424 [(set_attr "conds" "clob")
1b7da4ac 2425 (set_attr "length" "8")
2426 (set_attr "type" "multiple")]
f4462328 2427)
2428
2429(define_insn_and_split "*ite_ne_zeroextractsi"
2430 [(set (match_operand:SI 0 "s_register_operand" "=r")
2431 (if_then_else:SI (ne (zero_extract:SI
2432 (match_operand:SI 1 "s_register_operand" "r")
2433 (match_operand:SI 2 "const_int_operand" "n")
2434 (match_operand:SI 3 "const_int_operand" "n"))
2435 (const_int 0))
2436 (match_operand:SI 4 "arm_not_operand" "rIK")
2437 (const_int 0)))
2438 (clobber (reg:CC CC_REGNUM))]
2439 "TARGET_ARM
2440 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2441 && INTVAL (operands[2]) > 0
2442 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 2443 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2444 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 2445 "#"
2446 "TARGET_ARM
2447 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2448 && INTVAL (operands[2]) > 0
2449 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 2450 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2451 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 2452 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2453 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2454 (const_int 0)))
2455 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2456 (set (match_dup 0)
2457 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2458 (match_dup 0) (match_dup 4)))]
2459 "
c4034607 2460 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
f4462328 2461 << INTVAL (operands[3]));
2462 "
2463 [(set_attr "conds" "clob")
1b7da4ac 2464 (set_attr "length" "8")
2465 (set_attr "type" "multiple")]
f4462328 2466)
2467
2468(define_insn_and_split "*ite_ne_zeroextractsi_shifted"
2469 [(set (match_operand:SI 0 "s_register_operand" "=r")
2470 (if_then_else:SI (ne (zero_extract:SI
2471 (match_operand:SI 1 "s_register_operand" "r")
2472 (match_operand:SI 2 "const_int_operand" "n")
2473 (const_int 0))
2474 (const_int 0))
2475 (match_operand:SI 3 "arm_not_operand" "rIK")
2476 (const_int 0)))
2477 (clobber (reg:CC CC_REGNUM))]
f8d7bf2f 2478 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 2479 "#"
f8d7bf2f 2480 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 2481 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2482 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2483 (const_int 0)))
2484 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2485 (set (match_dup 0)
2486 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2487 (match_dup 0) (match_dup 3)))]
2488 "
2489 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
0d66636f 2490 "
2491 [(set_attr "conds" "clob")
1b7da4ac 2492 (set_attr "length" "8")
2493 (set_attr "type" "multiple")]
215b30b3 2494)
9c08d1fa 2495
58d6528b 2496(define_split
2497 [(set (match_operand:SI 0 "s_register_operand" "")
2498 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
2499 (match_operand:SI 2 "const_int_operand" "")
2500 (match_operand:SI 3 "const_int_operand" "")))
2501 (clobber (match_operand:SI 4 "s_register_operand" ""))]
25f905c2 2502 "TARGET_THUMB1"
58d6528b 2503 [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
2504 (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
2505 "{
2506 HOST_WIDE_INT temp = INTVAL (operands[2]);
2507
2508 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
2509 operands[3] = GEN_INT (32 - temp);
2510 }"
2511)
2512
25f905c2 2513;; ??? Use Thumb-2 has bitfield insert/extract instructions.
d7863cfe 2514(define_split
2515 [(set (match_operand:SI 0 "s_register_operand" "")
2516 (match_operator:SI 1 "shiftable_operator"
2517 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2518 (match_operand:SI 3 "const_int_operand" "")
2519 (match_operand:SI 4 "const_int_operand" ""))
2520 (match_operand:SI 5 "s_register_operand" "")]))
2521 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2522 "TARGET_ARM"
2523 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2524 (set (match_dup 0)
2525 (match_op_dup 1
2526 [(lshiftrt:SI (match_dup 6) (match_dup 4))
2527 (match_dup 5)]))]
2528 "{
2529 HOST_WIDE_INT temp = INTVAL (operands[3]);
2530
2531 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2532 operands[4] = GEN_INT (32 - temp);
2533 }"
2534)
2535
58d6528b 2536(define_split
2537 [(set (match_operand:SI 0 "s_register_operand" "")
2538 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
2539 (match_operand:SI 2 "const_int_operand" "")
2540 (match_operand:SI 3 "const_int_operand" "")))]
25f905c2 2541 "TARGET_THUMB1"
58d6528b 2542 [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
2543 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
2544 "{
2545 HOST_WIDE_INT temp = INTVAL (operands[2]);
2546
2547 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
2548 operands[3] = GEN_INT (32 - temp);
2549 }"
2550)
2551
d7863cfe 2552(define_split
2553 [(set (match_operand:SI 0 "s_register_operand" "")
2554 (match_operator:SI 1 "shiftable_operator"
2555 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2556 (match_operand:SI 3 "const_int_operand" "")
2557 (match_operand:SI 4 "const_int_operand" ""))
2558 (match_operand:SI 5 "s_register_operand" "")]))
2559 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2560 "TARGET_ARM"
2561 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2562 (set (match_dup 0)
2563 (match_op_dup 1
2564 [(ashiftrt:SI (match_dup 6) (match_dup 4))
2565 (match_dup 5)]))]
2566 "{
2567 HOST_WIDE_INT temp = INTVAL (operands[3]);
2568
2569 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2570 operands[4] = GEN_INT (32 - temp);
2571 }"
2572)
2573
a42059fd 2574;;; ??? This pattern is bogus. If operand3 has bits outside the range
2575;;; represented by the bitfield, then this will produce incorrect results.
2576;;; Somewhere, the value needs to be truncated. On targets like the m68k,
ceb2fe0f 2577;;; which have a real bit-field insert instruction, the truncation happens
2578;;; in the bit-field insert instruction itself. Since arm does not have a
2579;;; bit-field insert instruction, we would have to emit code here to truncate
a42059fd 2580;;; the value before we insert. This loses some of the advantage of having
2581;;; this insv pattern, so this pattern needs to be reevalutated.
2582
8a18b90c 2583(define_expand "insv"
eb04cafb 2584 [(set (zero_extract (match_operand 0 "nonimmediate_operand" "")
2585 (match_operand 1 "general_operand" "")
2586 (match_operand 2 "general_operand" ""))
2587 (match_operand 3 "reg_or_int_operand" ""))]
8b054d5a 2588 "TARGET_ARM || arm_arch_thumb2"
8a18b90c 2589 "
215b30b3 2590 {
2591 int start_bit = INTVAL (operands[2]);
2592 int width = INTVAL (operands[1]);
2593 HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
2594 rtx target, subtarget;
2595
8b054d5a 2596 if (arm_arch_thumb2)
2597 {
eb04cafb 2598 if (unaligned_access && MEM_P (operands[0])
2599 && s_register_operand (operands[3], GET_MODE (operands[3]))
2600 && (width == 16 || width == 32) && (start_bit % BITS_PER_UNIT) == 0)
8b054d5a 2601 {
eb04cafb 2602 rtx base_addr;
2603
2604 if (BYTES_BIG_ENDIAN)
2605 start_bit = GET_MODE_BITSIZE (GET_MODE (operands[3])) - width
2606 - start_bit;
8b054d5a 2607
eb04cafb 2608 if (width == 32)
8b054d5a 2609 {
eb04cafb 2610 base_addr = adjust_address (operands[0], SImode,
2611 start_bit / BITS_PER_UNIT);
2612 emit_insn (gen_unaligned_storesi (base_addr, operands[3]));
8b054d5a 2613 }
eb04cafb 2614 else
2615 {
2616 rtx tmp = gen_reg_rtx (HImode);
8b054d5a 2617
eb04cafb 2618 base_addr = adjust_address (operands[0], HImode,
2619 start_bit / BITS_PER_UNIT);
2620 emit_move_insn (tmp, gen_lowpart (HImode, operands[3]));
2621 emit_insn (gen_unaligned_storehi (base_addr, tmp));
2622 }
2623 DONE;
8b054d5a 2624 }
eb04cafb 2625 else if (s_register_operand (operands[0], GET_MODE (operands[0])))
8b054d5a 2626 {
eb04cafb 2627 bool use_bfi = TRUE;
8b054d5a 2628
0438d37f 2629 if (CONST_INT_P (operands[3]))
eb04cafb 2630 {
2631 HOST_WIDE_INT val = INTVAL (operands[3]) & mask;
2632
2633 if (val == 0)
2634 {
2635 emit_insn (gen_insv_zero (operands[0], operands[1],
2636 operands[2]));
2637 DONE;
2638 }
2639
2640 /* See if the set can be done with a single orr instruction. */
2641 if (val == mask && const_ok_for_arm (val << start_bit))
2642 use_bfi = FALSE;
2643 }
2644
2645 if (use_bfi)
2646 {
0438d37f 2647 if (!REG_P (operands[3]))
eb04cafb 2648 operands[3] = force_reg (SImode, operands[3]);
2649
2650 emit_insn (gen_insv_t2 (operands[0], operands[1], operands[2],
2651 operands[3]));
2652 DONE;
2653 }
8b054d5a 2654 }
eb04cafb 2655 else
2656 FAIL;
8b054d5a 2657 }
2658
eb04cafb 2659 if (!s_register_operand (operands[0], GET_MODE (operands[0])))
2660 FAIL;
2661
3f8fde42 2662 target = copy_rtx (operands[0]);
215b30b3 2663 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
2664 subreg as the final target. */
2665 if (GET_CODE (target) == SUBREG)
2666 {
2667 subtarget = gen_reg_rtx (SImode);
2668 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
2669 < GET_MODE_SIZE (SImode))
2670 target = SUBREG_REG (target);
2671 }
2672 else
2673 subtarget = target;
8a18b90c 2674
0438d37f 2675 if (CONST_INT_P (operands[3]))
215b30b3 2676 {
2677 /* Since we are inserting a known constant, we may be able to
2678 reduce the number of bits that we have to clear so that
2679 the mask becomes simple. */
2680 /* ??? This code does not check to see if the new mask is actually
2681 simpler. It may not be. */
2682 rtx op1 = gen_reg_rtx (SImode);
2683 /* ??? Truncate operand3 to fit in the bitfield. See comment before
2684 start of this pattern. */
2685 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
2686 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
2687
c5b3a71b 2688 emit_insn (gen_andsi3 (op1, operands[0],
2689 gen_int_mode (~mask2, SImode)));
215b30b3 2690 emit_insn (gen_iorsi3 (subtarget, op1,
4292ca6b 2691 gen_int_mode (op3_value << start_bit, SImode)));
215b30b3 2692 }
2693 else if (start_bit == 0
2694 && !(const_ok_for_arm (mask)
2695 || const_ok_for_arm (~mask)))
2696 {
2697 /* A Trick, since we are setting the bottom bits in the word,
2698 we can shift operand[3] up, operand[0] down, OR them together
2699 and rotate the result back again. This takes 3 insns, and
5910bb95 2700 the third might be mergeable into another op. */
215b30b3 2701 /* The shift up copes with the possibility that operand[3] is
2702 wider than the bitfield. */
2703 rtx op0 = gen_reg_rtx (SImode);
2704 rtx op1 = gen_reg_rtx (SImode);
2705
2706 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2707 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
2708 emit_insn (gen_iorsi3 (op1, op1, op0));
2709 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
2710 }
2711 else if ((width + start_bit == 32)
2712 && !(const_ok_for_arm (mask)
2713 || const_ok_for_arm (~mask)))
2714 {
2715 /* Similar trick, but slightly less efficient. */
8a18b90c 2716
215b30b3 2717 rtx op0 = gen_reg_rtx (SImode);
2718 rtx op1 = gen_reg_rtx (SImode);
8a18b90c 2719
215b30b3 2720 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2721 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
2722 emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
2723 emit_insn (gen_iorsi3 (subtarget, op1, op0));
2724 }
2725 else
2726 {
c5b3a71b 2727 rtx op0 = gen_int_mode (mask, SImode);
215b30b3 2728 rtx op1 = gen_reg_rtx (SImode);
2729 rtx op2 = gen_reg_rtx (SImode);
8a18b90c 2730
215b30b3 2731 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
2732 {
2733 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 2734
215b30b3 2735 emit_insn (gen_movsi (tmp, op0));
2736 op0 = tmp;
2737 }
8a18b90c 2738
215b30b3 2739 /* Mask out any bits in operand[3] that are not needed. */
2740 emit_insn (gen_andsi3 (op1, operands[3], op0));
8a18b90c 2741
0438d37f 2742 if (CONST_INT_P (op0)
215b30b3 2743 && (const_ok_for_arm (mask << start_bit)
2744 || const_ok_for_arm (~(mask << start_bit))))
2745 {
c5b3a71b 2746 op0 = gen_int_mode (~(mask << start_bit), SImode);
215b30b3 2747 emit_insn (gen_andsi3 (op2, operands[0], op0));
2748 }
2749 else
2750 {
0438d37f 2751 if (CONST_INT_P (op0))
215b30b3 2752 {
2753 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 2754
215b30b3 2755 emit_insn (gen_movsi (tmp, op0));
2756 op0 = tmp;
2757 }
2758
2759 if (start_bit != 0)
2760 emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
a42059fd 2761
215b30b3 2762 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
2763 }
8a18b90c 2764
215b30b3 2765 if (start_bit != 0)
2766 emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
8a18b90c 2767
215b30b3 2768 emit_insn (gen_iorsi3 (subtarget, op1, op2));
2769 }
f082f1c4 2770
215b30b3 2771 if (subtarget != target)
2772 {
2773 /* If TARGET is still a SUBREG, then it must be wider than a word,
2774 so we must be careful only to set the subword we were asked to. */
2775 if (GET_CODE (target) == SUBREG)
2776 emit_move_insn (target, subtarget);
2777 else
2778 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
2779 }
8a18b90c 2780
215b30b3 2781 DONE;
2782 }"
2783)
8a18b90c 2784
8b054d5a 2785(define_insn "insv_zero"
2786 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
809003b3 2787 (match_operand:SI 1 "const_int_M_operand" "M")
2788 (match_operand:SI 2 "const_int_M_operand" "M"))
8b054d5a 2789 (const_int 0))]
2790 "arm_arch_thumb2"
2791 "bfc%?\t%0, %2, %1"
2792 [(set_attr "length" "4")
d952d547 2793 (set_attr "predicable" "yes")
d82e788e 2794 (set_attr "predicable_short_it" "no")
2795 (set_attr "type" "bfm")]
8b054d5a 2796)
2797
2798(define_insn "insv_t2"
2799 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
809003b3 2800 (match_operand:SI 1 "const_int_M_operand" "M")
2801 (match_operand:SI 2 "const_int_M_operand" "M"))
8b054d5a 2802 (match_operand:SI 3 "s_register_operand" "r"))]
2803 "arm_arch_thumb2"
2804 "bfi%?\t%0, %3, %2, %1"
2805 [(set_attr "length" "4")
d952d547 2806 (set_attr "predicable" "yes")
d82e788e 2807 (set_attr "predicable_short_it" "no")
2808 (set_attr "type" "bfm")]
8b054d5a 2809)
2810
215b30b3 2811; constants for op 2 will never be given to these patterns.
a0f94409 2812(define_insn_and_split "*anddi_notdi_di"
9c08d1fa 2813 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 2814 (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "0,r"))
2815 (match_operand:DI 2 "s_register_operand" "r,0")))]
25f905c2 2816 "TARGET_32BIT"
f6ebffac 2817 "#"
e2669ea7 2818 "TARGET_32BIT && reload_completed
2819 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))
2820 && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
a0f94409 2821 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2822 (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2823 "
2824 {
2825 operands[3] = gen_highpart (SImode, operands[0]);
2826 operands[0] = gen_lowpart (SImode, operands[0]);
2827 operands[4] = gen_highpart (SImode, operands[1]);
2828 operands[1] = gen_lowpart (SImode, operands[1]);
2829 operands[5] = gen_highpart (SImode, operands[2]);
2830 operands[2] = gen_lowpart (SImode, operands[2]);
2831 }"
0d66636f 2832 [(set_attr "length" "8")
1b7da4ac 2833 (set_attr "predicable" "yes")
2834 (set_attr "type" "multiple")]
0d66636f 2835)
d952d547 2836
a0f94409 2837(define_insn_and_split "*anddi_notzesidi_di"
9c08d1fa 2838 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2839 (and:DI (not:DI (zero_extend:DI
2840 (match_operand:SI 2 "s_register_operand" "r,r")))
e2348bcb 2841 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 2842 "TARGET_32BIT"
e2348bcb 2843 "@
97499065 2844 bic%?\\t%Q0, %Q1, %2
f6ebffac 2845 #"
a0f94409 2846 ; (not (zero_extend ...)) allows us to just copy the high word from
2847 ; operand1 to operand0.
25f905c2 2848 "TARGET_32BIT
a0f94409 2849 && reload_completed
2850 && operands[0] != operands[1]"
5a097f7d 2851 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
a0f94409 2852 (set (match_dup 3) (match_dup 4))]
2853 "
2854 {
2855 operands[3] = gen_highpart (SImode, operands[0]);
2856 operands[0] = gen_lowpart (SImode, operands[0]);
2857 operands[4] = gen_highpart (SImode, operands[1]);
2858 operands[1] = gen_lowpart (SImode, operands[1]);
2859 }"
0d66636f 2860 [(set_attr "length" "4,8")
d952d547 2861 (set_attr "predicable" "yes")
1b7da4ac 2862 (set_attr "predicable_short_it" "no")
2863 (set_attr "type" "multiple")]
0d66636f 2864)
d952d547 2865
d8cd5fa0 2866(define_insn_and_split "*anddi_notdi_zesidi"
2867 [(set (match_operand:DI 0 "s_register_operand" "=r")
2868 (and:DI (not:DI (match_operand:DI 2 "s_register_operand" "r"))
2869 (zero_extend:DI
2870 (match_operand:SI 1 "s_register_operand" "r"))))]
2871 "TARGET_32BIT"
2872 "#"
2873 "TARGET_32BIT && reload_completed"
2874 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2875 (set (match_dup 3) (const_int 0))]
2876 "
2877 {
2878 operands[3] = gen_highpart (SImode, operands[0]);
2879 operands[0] = gen_lowpart (SImode, operands[0]);
2880 operands[2] = gen_lowpart (SImode, operands[2]);
2881 }"
2882 [(set_attr "length" "8")
2883 (set_attr "predicable" "yes")
2884 (set_attr "predicable_short_it" "no")
2885 (set_attr "type" "multiple")]
2886)
2887
a0f94409 2888(define_insn_and_split "*anddi_notsesidi_di"
9c08d1fa 2889 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2890 (and:DI (not:DI (sign_extend:DI
2891 (match_operand:SI 2 "s_register_operand" "r,r")))
5a097f7d 2892 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2893 "TARGET_32BIT"
f6ebffac 2894 "#"
25f905c2 2895 "TARGET_32BIT && reload_completed"
5a097f7d 2896 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
a0f94409 2897 (set (match_dup 3) (and:SI (not:SI
2898 (ashiftrt:SI (match_dup 2) (const_int 31)))
2899 (match_dup 4)))]
2900 "
2901 {
2902 operands[3] = gen_highpart (SImode, operands[0]);
2903 operands[0] = gen_lowpart (SImode, operands[0]);
2904 operands[4] = gen_highpart (SImode, operands[1]);
2905 operands[1] = gen_lowpart (SImode, operands[1]);
2906 }"
0d66636f 2907 [(set_attr "length" "8")
d952d547 2908 (set_attr "predicable" "yes")
1b7da4ac 2909 (set_attr "predicable_short_it" "no")
2910 (set_attr "type" "multiple")]
0d66636f 2911)
d952d547 2912
8a18b90c 2913(define_insn "andsi_notsi_si"
9c08d1fa 2914 [(set (match_operand:SI 0 "s_register_operand" "=r")
2915 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2916 (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 2917 "TARGET_32BIT"
0d66636f 2918 "bic%?\\t%0, %1, %2"
d952d547 2919 [(set_attr "predicable" "yes")
1b7da4ac 2920 (set_attr "predicable_short_it" "no")
2921 (set_attr "type" "logic_reg")]
0d66636f 2922)
b11cae9e 2923
747b7458 2924(define_insn "thumb1_bicsi3"
cffb2a26 2925 [(set (match_operand:SI 0 "register_operand" "=l")
2926 (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2927 (match_operand:SI 2 "register_operand" "0")))]
25f905c2 2928 "TARGET_THUMB1"
747b7458 2929 "bic\\t%0, %1"
2930 [(set_attr "length" "2")
1b7da4ac 2931 (set_attr "conds" "set")
2932 (set_attr "type" "logics_reg")]
2933)
cffb2a26 2934
8a18b90c 2935(define_insn "andsi_not_shiftsi_si"
a2cd141b 2936 [(set (match_operand:SI 0 "s_register_operand" "=r")
2937 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2938 [(match_operand:SI 2 "s_register_operand" "r")
2939 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2940 (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 2941 "TARGET_ARM"
6c4c2133 2942 "bic%?\\t%0, %1, %2%S4"
344495ea 2943 [(set_attr "predicable" "yes")
331beb1a 2944 (set_attr "shift" "2")
a2cd141b 2945 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
d82e788e 2946 (const_string "logic_shift_imm")
2947 (const_string "logic_shift_reg")))]
6c4c2133 2948)
8a18b90c 2949
f7fbdd4a 2950(define_insn "*andsi_notsi_si_compare0"
bd5b4116 2951 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 2952 (compare:CC_NOOV
2953 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2954 (match_operand:SI 1 "s_register_operand" "r"))
2955 (const_int 0)))
9c08d1fa 2956 (set (match_operand:SI 0 "s_register_operand" "=r")
2957 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
25f905c2 2958 "TARGET_32BIT"
2959 "bic%.\\t%0, %1, %2"
d82e788e 2960 [(set_attr "conds" "set")
2961 (set_attr "type" "logics_shift_reg")]
0d66636f 2962)
9c08d1fa 2963
f7fbdd4a 2964(define_insn "*andsi_notsi_si_compare0_scratch"
bd5b4116 2965 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 2966 (compare:CC_NOOV
2967 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2968 (match_operand:SI 1 "s_register_operand" "r"))
2969 (const_int 0)))
9c08d1fa 2970 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 2971 "TARGET_32BIT"
2972 "bic%.\\t%0, %1, %2"
d82e788e 2973 [(set_attr "conds" "set")
2974 (set_attr "type" "logics_shift_reg")]
0d66636f 2975)
9c08d1fa 2976
e2669ea7 2977(define_expand "iordi3"
2978 [(set (match_operand:DI 0 "s_register_operand" "")
2979 (ior:DI (match_operand:DI 1 "s_register_operand" "")
2980 (match_operand:DI 2 "neon_logic_op2" "")))]
2981 "TARGET_32BIT"
2982 ""
2983)
2984
74d6113f 2985(define_insn_and_split "*iordi3_insn"
2986 [(set (match_operand:DI 0 "s_register_operand" "=w,w ,&r,&r,&r,&r,?w,?w")
2987 (ior:DI (match_operand:DI 1 "s_register_operand" "%w,0 ,0 ,r ,0 ,r ,w ,0")
e0fe6977 2988 (match_operand:DI 2 "arm_iordi_operand_neon" "w ,Dl,r ,r ,Df,Df,w ,Dl")))]
74d6113f 2989 "TARGET_32BIT && !TARGET_IWMMXT"
2990 {
2991 switch (which_alternative)
2992 {
2993 case 0: /* fall through */
2994 case 6: return "vorr\t%P0, %P1, %P2";
2995 case 1: /* fall through */
2996 case 7: return neon_output_logic_immediate ("vorr", &operands[2],
2997 DImode, 0, VALID_NEON_QREG_MODE (DImode));
2998 case 2:
2999 case 3:
3000 case 4:
3001 case 5:
3002 return "#";
3003 default: gcc_unreachable ();
3004 }
3005 }
3006 "TARGET_32BIT && !TARGET_IWMMXT && reload_completed
3007 && !(IS_VFP_REGNUM (REGNO (operands[0])))"
3008 [(set (match_dup 3) (match_dup 4))
3009 (set (match_dup 5) (match_dup 6))]
3010 "
3011 {
3012 operands[3] = gen_lowpart (SImode, operands[0]);
3013 operands[5] = gen_highpart (SImode, operands[0]);
3014
3015 operands[4] = simplify_gen_binary (IOR, SImode,
3016 gen_lowpart (SImode, operands[1]),
3017 gen_lowpart (SImode, operands[2]));
3018 operands[6] = simplify_gen_binary (IOR, SImode,
3019 gen_highpart (SImode, operands[1]),
3020 gen_highpart_mode (SImode, DImode, operands[2]));
3021
3022 }"
32093010 3023 [(set_attr "type" "neon_logic,neon_logic,multiple,multiple,multiple,\
3024 multiple,neon_logic,neon_logic")
e0fe6977 3025 (set_attr "length" "*,*,8,8,8,8,*,*")
74d6113f 3026 (set_attr "arch" "neon_for_64bits,neon_for_64bits,*,*,*,*,avoid_neon_for_64bits,avoid_neon_for_64bits")]
cffb2a26 3027)
9c08d1fa 3028
f7fbdd4a 3029(define_insn "*iordi_zesidi_di"
9c08d1fa 3030 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3031 (ior:DI (zero_extend:DI
3032 (match_operand:SI 2 "s_register_operand" "r,r"))
e2348bcb 3033 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 3034 "TARGET_32BIT"
e2348bcb 3035 "@
97499065 3036 orr%?\\t%Q0, %Q1, %2
f6ebffac 3037 #"
0d66636f 3038 [(set_attr "length" "4,8")
d952d547 3039 (set_attr "predicable" "yes")
1b7da4ac 3040 (set_attr "predicable_short_it" "no")
3041 (set_attr "type" "logic_reg,multiple")]
cffb2a26 3042)
9c08d1fa 3043
f7fbdd4a 3044(define_insn "*iordi_sesidi_di"
9c08d1fa 3045 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3046 (ior:DI (sign_extend:DI
3047 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 3048 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 3049 "TARGET_32BIT"
f6ebffac 3050 "#"
0d66636f 3051 [(set_attr "length" "8")
1b7da4ac 3052 (set_attr "predicable" "yes")
3053 (set_attr "type" "multiple")]
cffb2a26 3054)
9c08d1fa 3055
87b22bf7 3056(define_expand "iorsi3"
cffb2a26 3057 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3058 (ior:SI (match_operand:SI 1 "s_register_operand" "")
3059 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 3060 "TARGET_EITHER"
87b22bf7 3061 "
0438d37f 3062 if (CONST_INT_P (operands[2]))
87b22bf7 3063 {
25f905c2 3064 if (TARGET_32BIT)
cffb2a26 3065 {
96f57e36 3066 arm_split_constant (IOR, SImode, NULL_RTX,
3067 INTVAL (operands[2]), operands[0], operands[1],
e1ba4a27 3068 optimize && can_create_pseudo_p ());
cffb2a26 3069 DONE;
3070 }
25f905c2 3071 else /* TARGET_THUMB1 */
923ffadb 3072 {
3073 rtx tmp = force_reg (SImode, operands[2]);
3074 if (rtx_equal_p (operands[0], operands[1]))
3075 operands[2] = tmp;
3076 else
3077 {
3078 operands[2] = operands[1];
3079 operands[1] = tmp;
3080 }
3081 }
87b22bf7 3082 }
cffb2a26 3083 "
3084)
87b22bf7 3085
d5d4dc8d 3086(define_insn_and_split "*iorsi3_insn"
29e234a3 3087 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r,r,r")
3088 (ior:SI (match_operand:SI 1 "s_register_operand" "%r,0,r,r,r")
3089 (match_operand:SI 2 "reg_or_int_operand" "I,l,K,r,?n")))]
d5d4dc8d 3090 "TARGET_32BIT"
87b22bf7 3091 "@
29e234a3 3092 orr%?\\t%0, %1, %2
87b22bf7 3093 orr%?\\t%0, %1, %2
d5d4dc8d 3094 orn%?\\t%0, %1, #%B2
65f68e55 3095 orr%?\\t%0, %1, %2
87b22bf7 3096 #"
d5d4dc8d 3097 "TARGET_32BIT
0438d37f 3098 && CONST_INT_P (operands[2])
d5d4dc8d 3099 && !(const_ok_for_arm (INTVAL (operands[2]))
3100 || (TARGET_THUMB2 && const_ok_for_arm (~INTVAL (operands[2]))))"
a0f94409 3101 [(clobber (const_int 0))]
d5d4dc8d 3102{
29e234a3 3103 arm_split_constant (IOR, SImode, curr_insn,
96f57e36 3104 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 3105 DONE;
d5d4dc8d 3106}
29e234a3 3107 [(set_attr "length" "4,4,4,4,16")
3108 (set_attr "arch" "32,t2,t2,32,32")
65f68e55 3109 (set_attr "predicable" "yes")
29e234a3 3110 (set_attr "predicable_short_it" "no,yes,no,no,no")
d82e788e 3111 (set_attr "type" "logic_imm,logic_reg,logic_imm,logic_reg,logic_reg")]
65f68e55 3112)
cffb2a26 3113
747b7458 3114(define_insn "*thumb1_iorsi3_insn"
cffb2a26 3115 [(set (match_operand:SI 0 "register_operand" "=l")
3116 (ior:SI (match_operand:SI 1 "register_operand" "%0")
3117 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 3118 "TARGET_THUMB1"
747b7458 3119 "orr\\t%0, %2"
3120 [(set_attr "length" "2")
1b7da4ac 3121 (set_attr "conds" "set")
3122 (set_attr "type" "logics_reg")])
9c08d1fa 3123
a0f94409 3124(define_peephole2
3125 [(match_scratch:SI 3 "r")
372575c7 3126 (set (match_operand:SI 0 "arm_general_register_operand" "")
3127 (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
87b22bf7 3128 (match_operand:SI 2 "const_int_operand" "")))]
90560cad 3129 "TARGET_ARM
a0f94409 3130 && !const_ok_for_arm (INTVAL (operands[2]))
3131 && const_ok_for_arm (~INTVAL (operands[2]))"
3132 [(set (match_dup 3) (match_dup 2))
3133 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
3134 ""
215b30b3 3135)
a0f94409 3136
f7fbdd4a 3137(define_insn "*iorsi3_compare0"
bd5b4116 3138 [(set (reg:CC_NOOV CC_REGNUM)
65f68e55 3139 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r,r")
3140 (match_operand:SI 2 "arm_rhs_operand" "I,r"))
9c08d1fa 3141 (const_int 0)))
65f68e55 3142 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 3143 (ior:SI (match_dup 1) (match_dup 2)))]
25f905c2 3144 "TARGET_32BIT"
3145 "orr%.\\t%0, %1, %2"
65f68e55 3146 [(set_attr "conds" "set")
d82e788e 3147 (set_attr "type" "logics_imm,logics_reg")]
cffb2a26 3148)
9c08d1fa 3149
f7fbdd4a 3150(define_insn "*iorsi3_compare0_scratch"
bd5b4116 3151 [(set (reg:CC_NOOV CC_REGNUM)
65f68e55 3152 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r,r")
3153 (match_operand:SI 2 "arm_rhs_operand" "I,r"))
9c08d1fa 3154 (const_int 0)))
65f68e55 3155 (clobber (match_scratch:SI 0 "=r,r"))]
25f905c2 3156 "TARGET_32BIT"
3157 "orr%.\\t%0, %1, %2"
65f68e55 3158 [(set_attr "conds" "set")
d82e788e 3159 (set_attr "type" "logics_imm,logics_reg")]
0d66636f 3160)
9c08d1fa 3161
e2669ea7 3162(define_expand "xordi3"
3163 [(set (match_operand:DI 0 "s_register_operand" "")
3164 (xor:DI (match_operand:DI 1 "s_register_operand" "")
8ee7dc6f 3165 (match_operand:DI 2 "arm_xordi_operand" "")))]
e2669ea7 3166 "TARGET_32BIT"
3167 ""
3168)
3169
8ee7dc6f 3170(define_insn_and_split "*xordi3_insn"
3171 [(set (match_operand:DI 0 "s_register_operand" "=w,&r,&r,&r,&r,?w")
3172 (xor:DI (match_operand:DI 1 "s_register_operand" "w ,%0,r ,0 ,r ,w")
3173 (match_operand:DI 2 "arm_xordi_operand" "w ,r ,r ,Dg,Dg,w")))]
3174 "TARGET_32BIT && !TARGET_IWMMXT"
3175{
3176 switch (which_alternative)
3177 {
3178 case 1:
3179 case 2:
3180 case 3:
3181 case 4: /* fall through */
3182 return "#";
3183 case 0: /* fall through */
3184 case 5: return "veor\t%P0, %P1, %P2";
3185 default: gcc_unreachable ();
3186 }
3187}
3188 "TARGET_32BIT && !TARGET_IWMMXT && reload_completed
3189 && !(IS_VFP_REGNUM (REGNO (operands[0])))"
3190 [(set (match_dup 3) (match_dup 4))
3191 (set (match_dup 5) (match_dup 6))]
3192 "
3193 {
3194 operands[3] = gen_lowpart (SImode, operands[0]);
3195 operands[5] = gen_highpart (SImode, operands[0]);
3196
3197 operands[4] = simplify_gen_binary (XOR, SImode,
3198 gen_lowpart (SImode, operands[1]),
3199 gen_lowpart (SImode, operands[2]));
3200 operands[6] = simplify_gen_binary (XOR, SImode,
3201 gen_highpart (SImode, operands[1]),
3202 gen_highpart_mode (SImode, DImode, operands[2]));
3203
3204 }"
3205 [(set_attr "length" "*,8,8,8,8,*")
32093010 3206 (set_attr "type" "neon_logic,multiple,multiple,multiple,multiple,neon_logic")
8ee7dc6f 3207 (set_attr "arch" "neon_for_64bits,*,*,*,*,avoid_neon_for_64bits")]
cffb2a26 3208)
9c08d1fa 3209
f7fbdd4a 3210(define_insn "*xordi_zesidi_di"
9c08d1fa 3211 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3212 (xor:DI (zero_extend:DI
3213 (match_operand:SI 2 "s_register_operand" "r,r"))
e2348bcb 3214 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 3215 "TARGET_32BIT"
e2348bcb 3216 "@
97499065 3217 eor%?\\t%Q0, %Q1, %2
f6ebffac 3218 #"
0d66636f 3219 [(set_attr "length" "4,8")
d952d547 3220 (set_attr "predicable" "yes")
1b7da4ac 3221 (set_attr "predicable_short_it" "no")
3222 (set_attr "type" "logic_reg")]
cffb2a26 3223)
9c08d1fa 3224
f7fbdd4a 3225(define_insn "*xordi_sesidi_di"
9c08d1fa 3226 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3227 (xor:DI (sign_extend:DI
3228 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 3229 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 3230 "TARGET_32BIT"
f6ebffac 3231 "#"
0d66636f 3232 [(set_attr "length" "8")
1b7da4ac 3233 (set_attr "predicable" "yes")
3234 (set_attr "type" "multiple")]
cffb2a26 3235)
9c08d1fa 3236
cffb2a26 3237(define_expand "xorsi3"
3238 [(set (match_operand:SI 0 "s_register_operand" "")
3239 (xor:SI (match_operand:SI 1 "s_register_operand" "")
923ffadb 3240 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 3241 "TARGET_EITHER"
0438d37f 3242 "if (CONST_INT_P (operands[2]))
923ffadb 3243 {
3244 if (TARGET_32BIT)
3245 {
3246 arm_split_constant (XOR, SImode, NULL_RTX,
3247 INTVAL (operands[2]), operands[0], operands[1],
3248 optimize && can_create_pseudo_p ());
3249 DONE;
3250 }
3251 else /* TARGET_THUMB1 */
3252 {
3253 rtx tmp = force_reg (SImode, operands[2]);
3254 if (rtx_equal_p (operands[0], operands[1]))
3255 operands[2] = tmp;
3256 else
3257 {
3258 operands[2] = operands[1];
3259 operands[1] = tmp;
3260 }
3261 }
3262 }"
cffb2a26 3263)
3264
5dcb35d9 3265(define_insn_and_split "*arm_xorsi3"
29e234a3 3266 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r,r")
3267 (xor:SI (match_operand:SI 1 "s_register_operand" "%r,0,r,r")
3268 (match_operand:SI 2 "reg_or_int_operand" "I,l,r,?n")))]
25f905c2 3269 "TARGET_32BIT"
5dcb35d9 3270 "@
29e234a3 3271 eor%?\\t%0, %1, %2
65f68e55 3272 eor%?\\t%0, %1, %2
5dcb35d9 3273 eor%?\\t%0, %1, %2
3274 #"
3275 "TARGET_32BIT
0438d37f 3276 && CONST_INT_P (operands[2])
5dcb35d9 3277 && !const_ok_for_arm (INTVAL (operands[2]))"
3278 [(clobber (const_int 0))]
3279{
3280 arm_split_constant (XOR, SImode, curr_insn,
3281 INTVAL (operands[2]), operands[0], operands[1], 0);
3282 DONE;
3283}
29e234a3 3284 [(set_attr "length" "4,4,4,16")
65f68e55 3285 (set_attr "predicable" "yes")
29e234a3 3286 (set_attr "predicable_short_it" "no,yes,no,no")
1b7da4ac 3287 (set_attr "type" "logic_imm,logic_reg,logic_reg,multiple")]
cffb2a26 3288)
3289
747b7458 3290(define_insn "*thumb1_xorsi3_insn"
cffb2a26 3291 [(set (match_operand:SI 0 "register_operand" "=l")
3292 (xor:SI (match_operand:SI 1 "register_operand" "%0")
3293 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 3294 "TARGET_THUMB1"
747b7458 3295 "eor\\t%0, %2"
3296 [(set_attr "length" "2")
65f68e55 3297 (set_attr "conds" "set")
d82e788e 3298 (set_attr "type" "logics_reg")]
65f68e55 3299)
9c08d1fa 3300
f7fbdd4a 3301(define_insn "*xorsi3_compare0"
bd5b4116 3302 [(set (reg:CC_NOOV CC_REGNUM)
65f68e55 3303 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r,r")
3304 (match_operand:SI 2 "arm_rhs_operand" "I,r"))
9c08d1fa 3305 (const_int 0)))
65f68e55 3306 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 3307 (xor:SI (match_dup 1) (match_dup 2)))]
25f905c2 3308 "TARGET_32BIT"
3309 "eor%.\\t%0, %1, %2"
65f68e55 3310 [(set_attr "conds" "set")
d82e788e 3311 (set_attr "type" "logics_imm,logics_reg")]
0d66636f 3312)
9c08d1fa 3313
f7fbdd4a 3314(define_insn "*xorsi3_compare0_scratch"
bd5b4116 3315 [(set (reg:CC_NOOV CC_REGNUM)
65f68e55 3316 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r,r")
3317 (match_operand:SI 1 "arm_rhs_operand" "I,r"))
9c08d1fa 3318 (const_int 0)))]
25f905c2 3319 "TARGET_32BIT"
40dbec34 3320 "teq%?\\t%0, %1"
65f68e55 3321 [(set_attr "conds" "set")
d82e788e 3322 (set_attr "type" "logics_imm,logics_reg")]
cffb2a26 3323)
9c08d1fa 3324
215b30b3 3325; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
3326; (NOT D) we can sometimes merge the final NOT into one of the following
3327; insns.
9c08d1fa 3328
3329(define_split
a058e94a 3330 [(set (match_operand:SI 0 "s_register_operand" "")
3331 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
3332 (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
3333 (match_operand:SI 3 "arm_rhs_operand" "")))
3334 (clobber (match_operand:SI 4 "s_register_operand" ""))]
25f905c2 3335 "TARGET_32BIT"
9c08d1fa 3336 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
3337 (not:SI (match_dup 3))))
3338 (set (match_dup 0) (not:SI (match_dup 4)))]
3339 ""
3340)
3341
ba6a3b2f 3342(define_insn_and_split "*andsi_iorsi3_notsi"
9c08d1fa 3343 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
e5fea38e 3344 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "%0,r,r")
9c08d1fa 3345 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
3346 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
25f905c2 3347 "TARGET_32BIT"
ba6a3b2f 3348 "#" ; "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
3349 "&& reload_completed"
3350 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
3351 (set (match_dup 0) (and:SI (not:SI (match_dup 3)) (match_dup 0)))]
3352 ""
0d66636f 3353 [(set_attr "length" "8")
25f905c2 3354 (set_attr "ce_count" "2")
d952d547 3355 (set_attr "predicable" "yes")
1b7da4ac 3356 (set_attr "predicable_short_it" "no")
3357 (set_attr "type" "multiple")]
cffb2a26 3358)
9c08d1fa 3359
25f905c2 3360; ??? Are these four splitters still beneficial when the Thumb-2 bitfield
3361; insns are available?
d7863cfe 3362(define_split
3363 [(set (match_operand:SI 0 "s_register_operand" "")
3364 (match_operator:SI 1 "logical_binary_operator"
3365 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
3366 (match_operand:SI 3 "const_int_operand" "")
3367 (match_operand:SI 4 "const_int_operand" ""))
3368 (match_operator:SI 9 "logical_binary_operator"
3369 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3370 (match_operand:SI 6 "const_int_operand" ""))
3371 (match_operand:SI 7 "s_register_operand" "")])]))
3372 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3373 "TARGET_32BIT
d7863cfe 3374 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3375 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3376 [(set (match_dup 8)
3377 (match_op_dup 1
3378 [(ashift:SI (match_dup 2) (match_dup 4))
3379 (match_dup 5)]))
3380 (set (match_dup 0)
3381 (match_op_dup 1
3382 [(lshiftrt:SI (match_dup 8) (match_dup 6))
3383 (match_dup 7)]))]
3384 "
3385 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3386")
3387
3388(define_split
3389 [(set (match_operand:SI 0 "s_register_operand" "")
3390 (match_operator:SI 1 "logical_binary_operator"
3391 [(match_operator:SI 9 "logical_binary_operator"
3392 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3393 (match_operand:SI 6 "const_int_operand" ""))
3394 (match_operand:SI 7 "s_register_operand" "")])
3395 (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
3396 (match_operand:SI 3 "const_int_operand" "")
3397 (match_operand:SI 4 "const_int_operand" ""))]))
3398 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3399 "TARGET_32BIT
d7863cfe 3400 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3401 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3402 [(set (match_dup 8)
3403 (match_op_dup 1
3404 [(ashift:SI (match_dup 2) (match_dup 4))
3405 (match_dup 5)]))
3406 (set (match_dup 0)
3407 (match_op_dup 1
3408 [(lshiftrt:SI (match_dup 8) (match_dup 6))
3409 (match_dup 7)]))]
3410 "
3411 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3412")
3413
3414(define_split
3415 [(set (match_operand:SI 0 "s_register_operand" "")
3416 (match_operator:SI 1 "logical_binary_operator"
3417 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
3418 (match_operand:SI 3 "const_int_operand" "")
3419 (match_operand:SI 4 "const_int_operand" ""))
3420 (match_operator:SI 9 "logical_binary_operator"
3421 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3422 (match_operand:SI 6 "const_int_operand" ""))
3423 (match_operand:SI 7 "s_register_operand" "")])]))
3424 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3425 "TARGET_32BIT
d7863cfe 3426 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3427 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3428 [(set (match_dup 8)
3429 (match_op_dup 1
3430 [(ashift:SI (match_dup 2) (match_dup 4))
3431 (match_dup 5)]))
3432 (set (match_dup 0)
3433 (match_op_dup 1
3434 [(ashiftrt:SI (match_dup 8) (match_dup 6))
3435 (match_dup 7)]))]
3436 "
3437 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3438")
3439
3440(define_split
3441 [(set (match_operand:SI 0 "s_register_operand" "")
3442 (match_operator:SI 1 "logical_binary_operator"
3443 [(match_operator:SI 9 "logical_binary_operator"
3444 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3445 (match_operand:SI 6 "const_int_operand" ""))
3446 (match_operand:SI 7 "s_register_operand" "")])
3447 (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
3448 (match_operand:SI 3 "const_int_operand" "")
3449 (match_operand:SI 4 "const_int_operand" ""))]))
3450 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3451 "TARGET_32BIT
d7863cfe 3452 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3453 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3454 [(set (match_dup 8)
3455 (match_op_dup 1
3456 [(ashift:SI (match_dup 2) (match_dup 4))
3457 (match_dup 5)]))
3458 (set (match_dup 0)
3459 (match_op_dup 1
3460 [(ashiftrt:SI (match_dup 8) (match_dup 6))
3461 (match_dup 7)]))]
3462 "
3463 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3464")
9c08d1fa 3465\f
3466
3467;; Minimum and maximum insns
3468
8b9dc177 3469(define_expand "smaxsi3"
3470 [(parallel [
3471 (set (match_operand:SI 0 "s_register_operand" "")
3472 (smax:SI (match_operand:SI 1 "s_register_operand" "")
3473 (match_operand:SI 2 "arm_rhs_operand" "")))
3474 (clobber (reg:CC CC_REGNUM))])]
25f905c2 3475 "TARGET_32BIT"
8b9dc177 3476 "
8774928b 3477 if (operands[2] == const0_rtx || operands[2] == constm1_rtx)
8b9dc177 3478 {
3479 /* No need for a clobber of the condition code register here. */
3480 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3481 gen_rtx_SMAX (SImode, operands[1],
3482 operands[2])));
3483 DONE;
3484 }
3485")
3486
3487(define_insn "*smax_0"
3488 [(set (match_operand:SI 0 "s_register_operand" "=r")
3489 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3490 (const_int 0)))]
25f905c2 3491 "TARGET_32BIT"
8b9dc177 3492 "bic%?\\t%0, %1, %1, asr #31"
d952d547 3493 [(set_attr "predicable" "yes")
1b7da4ac 3494 (set_attr "predicable_short_it" "no")
3495 (set_attr "type" "logic_shift_reg")]
8b9dc177 3496)
3497
8774928b 3498(define_insn "*smax_m1"
3499 [(set (match_operand:SI 0 "s_register_operand" "=r")
3500 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3501 (const_int -1)))]
25f905c2 3502 "TARGET_32BIT"
8774928b 3503 "orr%?\\t%0, %1, %1, asr #31"
d952d547 3504 [(set_attr "predicable" "yes")
1b7da4ac 3505 (set_attr "predicable_short_it" "no")
3506 (set_attr "type" "logic_shift_reg")]
8774928b 3507)
3508
3dc953f2 3509(define_insn_and_split "*arm_smax_insn"
8b9dc177 3510 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3511 (smax:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3512 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
bd5b4116 3513 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3514 "TARGET_ARM"
3dc953f2 3515 "#"
3516 ; cmp\\t%1, %2\;movlt\\t%0, %2
3517 ; cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
3518 "TARGET_ARM"
3519 [(set (reg:CC CC_REGNUM)
3520 (compare:CC (match_dup 1) (match_dup 2)))
3521 (set (match_dup 0)
3522 (if_then_else:SI (ge:SI (reg:CC CC_REGNUM) (const_int 0))
3523 (match_dup 1)
3524 (match_dup 2)))]
3525 ""
cffb2a26 3526 [(set_attr "conds" "clob")
1b7da4ac 3527 (set_attr "length" "8,12")
3528 (set_attr "type" "multiple")]
cffb2a26 3529)
9c08d1fa 3530
8b9dc177 3531(define_expand "sminsi3"
3532 [(parallel [
3533 (set (match_operand:SI 0 "s_register_operand" "")
3534 (smin:SI (match_operand:SI 1 "s_register_operand" "")
3535 (match_operand:SI 2 "arm_rhs_operand" "")))
3536 (clobber (reg:CC CC_REGNUM))])]
25f905c2 3537 "TARGET_32BIT"
8b9dc177 3538 "
3539 if (operands[2] == const0_rtx)
3540 {
3541 /* No need for a clobber of the condition code register here. */
3542 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3543 gen_rtx_SMIN (SImode, operands[1],
3544 operands[2])));
3545 DONE;
3546 }
3547")
3548
3549(define_insn "*smin_0"
3550 [(set (match_operand:SI 0 "s_register_operand" "=r")
3551 (smin:SI (match_operand:SI 1 "s_register_operand" "r")
3552 (const_int 0)))]
25f905c2 3553 "TARGET_32BIT"
8b9dc177 3554 "and%?\\t%0, %1, %1, asr #31"
d952d547 3555 [(set_attr "predicable" "yes")
1b7da4ac 3556 (set_attr "predicable_short_it" "no")
3557 (set_attr "type" "logic_shift_reg")]
8b9dc177 3558)
3559
3dc953f2 3560(define_insn_and_split "*arm_smin_insn"
8b9dc177 3561 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3562 (smin:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3563 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
bd5b4116 3564 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3565 "TARGET_ARM"
3dc953f2 3566 "#"
3567 ; cmp\\t%1, %2\;movge\\t%0, %2
3568 ; cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
3569 "TARGET_ARM"
3570 [(set (reg:CC CC_REGNUM)
3571 (compare:CC (match_dup 1) (match_dup 2)))
3572 (set (match_dup 0)
3573 (if_then_else:SI (lt:SI (reg:CC CC_REGNUM) (const_int 0))
3574 (match_dup 1)
3575 (match_dup 2)))]
3576 ""
0d66636f 3577 [(set_attr "conds" "clob")
1b7da4ac 3578 (set_attr "length" "8,12")
3579 (set_attr "type" "multiple,multiple")]
0d66636f 3580)
9c08d1fa 3581
25f905c2 3582(define_expand "umaxsi3"
3583 [(parallel [
3584 (set (match_operand:SI 0 "s_register_operand" "")
3585 (umax:SI (match_operand:SI 1 "s_register_operand" "")
3586 (match_operand:SI 2 "arm_rhs_operand" "")))
3587 (clobber (reg:CC CC_REGNUM))])]
3588 "TARGET_32BIT"
3589 ""
3590)
3591
3dc953f2 3592(define_insn_and_split "*arm_umaxsi3"
9c08d1fa 3593 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3594 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3595 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 3596 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3597 "TARGET_ARM"
3dc953f2 3598 "#"
3599 ; cmp\\t%1, %2\;movcc\\t%0, %2
3600 ; cmp\\t%1, %2\;movcs\\t%0, %1
3601 ; cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
3602 "TARGET_ARM"
3603 [(set (reg:CC CC_REGNUM)
3604 (compare:CC (match_dup 1) (match_dup 2)))
3605 (set (match_dup 0)
3606 (if_then_else:SI (geu:SI (reg:CC CC_REGNUM) (const_int 0))
3607 (match_dup 1)
3608 (match_dup 2)))]
3609 ""
0d66636f 3610 [(set_attr "conds" "clob")
1b7da4ac 3611 (set_attr "length" "8,8,12")
3612 (set_attr "type" "store1")]
0d66636f 3613)
9c08d1fa 3614
25f905c2 3615(define_expand "uminsi3"
3616 [(parallel [
3617 (set (match_operand:SI 0 "s_register_operand" "")
3618 (umin:SI (match_operand:SI 1 "s_register_operand" "")
3619 (match_operand:SI 2 "arm_rhs_operand" "")))
3620 (clobber (reg:CC CC_REGNUM))])]
3621 "TARGET_32BIT"
3622 ""
3623)
3624
3dc953f2 3625(define_insn_and_split "*arm_uminsi3"
9c08d1fa 3626 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3627 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3628 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 3629 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3630 "TARGET_ARM"
3dc953f2 3631 "#"
3632 ; cmp\\t%1, %2\;movcs\\t%0, %2
3633 ; cmp\\t%1, %2\;movcc\\t%0, %1
3634 ; cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
3635 "TARGET_ARM"
3636 [(set (reg:CC CC_REGNUM)
3637 (compare:CC (match_dup 1) (match_dup 2)))
3638 (set (match_dup 0)
3639 (if_then_else:SI (ltu:SI (reg:CC CC_REGNUM) (const_int 0))
3640 (match_dup 1)
3641 (match_dup 2)))]
3642 ""
0d66636f 3643 [(set_attr "conds" "clob")
1b7da4ac 3644 (set_attr "length" "8,8,12")
3645 (set_attr "type" "store1")]
0d66636f 3646)
9c08d1fa 3647
8a18b90c 3648(define_insn "*store_minmaxsi"
9c08d1fa 3649 [(set (match_operand:SI 0 "memory_operand" "=m")
3650 (match_operator:SI 3 "minmax_operator"
3651 [(match_operand:SI 1 "s_register_operand" "r")
3652 (match_operand:SI 2 "s_register_operand" "r")]))
bd5b4116 3653 (clobber (reg:CC CC_REGNUM))]
5ce0ce9b 3654 "TARGET_32BIT && optimize_function_for_size_p (cfun)"
9c08d1fa 3655 "*
dc55b8a9 3656 operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
3657 operands[1], operands[2]);
e2348bcb 3658 output_asm_insn (\"cmp\\t%1, %2\", operands);
25f905c2 3659 if (TARGET_THUMB2)
3660 output_asm_insn (\"ite\t%d3\", operands);
e2348bcb 3661 output_asm_insn (\"str%d3\\t%1, %0\", operands);
3662 output_asm_insn (\"str%D3\\t%2, %0\", operands);
3663 return \"\";
0d66636f 3664 "
3665 [(set_attr "conds" "clob")
25f905c2 3666 (set (attr "length")
3667 (if_then_else (eq_attr "is_thumb" "yes")
3668 (const_int 14)
3669 (const_int 12)))
0d66636f 3670 (set_attr "type" "store1")]
3671)
9c08d1fa 3672
8a18b90c 3673; Reject the frame pointer in operand[1], since reloading this after
3674; it has been eliminated can cause carnage.
f7fbdd4a 3675(define_insn "*minmax_arithsi"
9c08d1fa 3676 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3677 (match_operator:SI 4 "shiftable_operator"
3678 [(match_operator:SI 5 "minmax_operator"
3679 [(match_operand:SI 2 "s_register_operand" "r,r")
3680 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
3681 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 3682 (clobber (reg:CC CC_REGNUM))]
7c36fe71 3683 "TARGET_32BIT && !arm_eliminable_register (operands[1]) && !arm_restrict_it"
9c08d1fa 3684 "*
0d66636f 3685 {
3686 enum rtx_code code = GET_CODE (operands[4]);
25f905c2 3687 bool need_else;
3688
3689 if (which_alternative != 0 || operands[3] != const0_rtx
ca0fc5a2 3690 || (code != PLUS && code != IOR && code != XOR))
25f905c2 3691 need_else = true;
3692 else
3693 need_else = false;
0d66636f 3694
dc55b8a9 3695 operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
3696 operands[2], operands[3]);
0d66636f 3697 output_asm_insn (\"cmp\\t%2, %3\", operands);
25f905c2 3698 if (TARGET_THUMB2)
3699 {
3700 if (need_else)
3701 output_asm_insn (\"ite\\t%d5\", operands);
3702 else
3703 output_asm_insn (\"it\\t%d5\", operands);
3704 }
0d66636f 3705 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
25f905c2 3706 if (need_else)
0d66636f 3707 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
3708 return \"\";
215b30b3 3709 }"
0d66636f 3710 [(set_attr "conds" "clob")
25f905c2 3711 (set (attr "length")
3712 (if_then_else (eq_attr "is_thumb" "yes")
3713 (const_int 14)
1b7da4ac 3714 (const_int 12)))
3715 (set_attr "type" "multiple")]
0d66636f 3716)
9c08d1fa 3717
4164bca1 3718; Reject the frame pointer in operand[1], since reloading this after
3719; it has been eliminated can cause carnage.
3720(define_insn_and_split "*minmax_arithsi_non_canon"
7c36fe71 3721 [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts")
4164bca1 3722 (minus:SI
7c36fe71 3723 (match_operand:SI 1 "s_register_operand" "0,?Ts")
4164bca1 3724 (match_operator:SI 4 "minmax_operator"
7c36fe71 3725 [(match_operand:SI 2 "s_register_operand" "Ts,Ts")
3726 (match_operand:SI 3 "arm_rhs_operand" "TsI,TsI")])))
4164bca1 3727 (clobber (reg:CC CC_REGNUM))]
7c36fe71 3728 "TARGET_32BIT && !arm_eliminable_register (operands[1])
3729 && !(arm_restrict_it && CONST_INT_P (operands[3]))"
4164bca1 3730 "#"
3731 "TARGET_32BIT && !arm_eliminable_register (operands[1]) && reload_completed"
3732 [(set (reg:CC CC_REGNUM)
3733 (compare:CC (match_dup 2) (match_dup 3)))
3734
3735 (cond_exec (match_op_dup 4 [(reg:CC CC_REGNUM) (const_int 0)])
3736 (set (match_dup 0)
3737 (minus:SI (match_dup 1)
3738 (match_dup 2))))
3739 (cond_exec (match_op_dup 5 [(reg:CC CC_REGNUM) (const_int 0)])
3740 (set (match_dup 0)
36ee0cde 3741 (match_dup 6)))]
4164bca1 3742 {
3743 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
3744 operands[2], operands[3]);
3745 enum rtx_code rc = minmax_code (operands[4]);
3746 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode,
3747 operands[2], operands[3]);
3748
3749 if (mode == CCFPmode || mode == CCFPEmode)
3750 rc = reverse_condition_maybe_unordered (rc);
3751 else
3752 rc = reverse_condition (rc);
3753 operands[5] = gen_rtx_fmt_ee (rc, SImode, operands[2], operands[3]);
36ee0cde 3754 if (CONST_INT_P (operands[3]))
3755 operands[6] = plus_constant (SImode, operands[1], -INTVAL (operands[3]));
3756 else
3757 operands[6] = gen_rtx_MINUS (SImode, operands[1], operands[3]);
4164bca1 3758 }
3759 [(set_attr "conds" "clob")
3760 (set (attr "length")
3761 (if_then_else (eq_attr "is_thumb" "yes")
3762 (const_int 14)
1b7da4ac 3763 (const_int 12)))
3764 (set_attr "type" "multiple")]
4164bca1 3765)
3766
b49e3742 3767(define_code_iterator SAT [smin smax])
3768(define_code_iterator SATrev [smin smax])
3769(define_code_attr SATlo [(smin "1") (smax "2")])
3770(define_code_attr SAThi [(smin "2") (smax "1")])
3771
3772(define_insn "*satsi_<SAT:code>"
3773 [(set (match_operand:SI 0 "s_register_operand" "=r")
3774 (SAT:SI (SATrev:SI (match_operand:SI 3 "s_register_operand" "r")
3775 (match_operand:SI 1 "const_int_operand" "i"))
3776 (match_operand:SI 2 "const_int_operand" "i")))]
3777 "TARGET_32BIT && arm_arch6 && <SAT:CODE> != <SATrev:CODE>
3778 && arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>], NULL, NULL)"
3779{
3780 int mask;
3781 bool signed_sat;
3782 if (!arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>],
3783 &mask, &signed_sat))
3784 gcc_unreachable ();
3785
3786 operands[1] = GEN_INT (mask);
3787 if (signed_sat)
3788 return "ssat%?\t%0, %1, %3";
3789 else
3790 return "usat%?\t%0, %1, %3";
3791}
7c36fe71 3792 [(set_attr "predicable" "yes")
1b7da4ac 3793 (set_attr "predicable_short_it" "no")
3794 (set_attr "type" "alus_imm")]
bebe9bbb 3795)
b49e3742 3796
3797(define_insn "*satsi_<SAT:code>_shift"
3798 [(set (match_operand:SI 0 "s_register_operand" "=r")
3799 (SAT:SI (SATrev:SI (match_operator:SI 3 "sat_shift_operator"
3800 [(match_operand:SI 4 "s_register_operand" "r")
3801 (match_operand:SI 5 "const_int_operand" "i")])
3802 (match_operand:SI 1 "const_int_operand" "i"))
3803 (match_operand:SI 2 "const_int_operand" "i")))]
3804 "TARGET_32BIT && arm_arch6 && <SAT:CODE> != <SATrev:CODE>
3805 && arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>], NULL, NULL)"
3806{
3807 int mask;
3808 bool signed_sat;
3809 if (!arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>],
3810 &mask, &signed_sat))
3811 gcc_unreachable ();
3812
3813 operands[1] = GEN_INT (mask);
3814 if (signed_sat)
3815 return "ssat%?\t%0, %1, %4%S3";
3816 else
3817 return "usat%?\t%0, %1, %4%S3";
3818}
3819 [(set_attr "predicable" "yes")
7c36fe71 3820 (set_attr "predicable_short_it" "no")
b49e3742 3821 (set_attr "shift" "3")
d82e788e 3822 (set_attr "type" "logic_shift_reg")])
b11cae9e 3823\f
3824;; Shift and rotation insns
3825
a2cd141b 3826(define_expand "ashldi3"
3827 [(set (match_operand:DI 0 "s_register_operand" "")
3828 (ashift:DI (match_operand:DI 1 "s_register_operand" "")
aa06c51c 3829 (match_operand:SI 2 "general_operand" "")))]
25f905c2 3830 "TARGET_32BIT"
a2cd141b 3831 "
aa06c51c 3832 if (TARGET_NEON)
3833 {
3834 /* Delay the decision whether to use NEON or core-regs until
3835 register allocation. */
3836 emit_insn (gen_ashldi3_neon (operands[0], operands[1], operands[2]));
3837 DONE;
3838 }
3839 else
3840 {
3841 /* Only the NEON case can handle in-memory shift counts. */
3842 if (!reg_or_int_operand (operands[2], SImode))
3843 operands[2] = force_reg (SImode, operands[2]);
3844 }
3845
b805622c 3846 if (!CONST_INT_P (operands[2]) && TARGET_REALLY_IWMMXT)
ffcc986d 3847 ; /* No special preparation statements; expand pattern as above. */
3848 else
a2cd141b 3849 {
ffcc986d 3850 rtx scratch1, scratch2;
3851
3852 if (CONST_INT_P (operands[2])
3853 && (HOST_WIDE_INT) INTVAL (operands[2]) == 1)
a2cd141b 3854 {
3855 emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
3856 DONE;
3857 }
ffcc986d 3858
3859 /* Ideally we should use iwmmxt here if we could know that operands[1]
3860 ends up already living in an iwmmxt register. Otherwise it's
3861 cheaper to have the alternate code being generated than moving
3862 values to iwmmxt regs and back. */
3863
3864 /* If we're optimizing for size, we prefer the libgcc calls. */
3865 if (optimize_function_for_size_p (cfun))
3866 FAIL;
3867
3868 /* Expand operation using core-registers.
3869 'FAIL' would achieve the same thing, but this is a bit smarter. */
3870 scratch1 = gen_reg_rtx (SImode);
3871 scratch2 = gen_reg_rtx (SImode);
3872 arm_emit_coreregs_64bit_shift (ASHIFT, operands[0], operands[1],
3873 operands[2], scratch1, scratch2);
3874 DONE;
a2cd141b 3875 }
a2cd141b 3876 "
3877)
3878
2837e3fb 3879(define_insn "arm_ashldi3_1bit"
50ad1bf9 3880 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 3881 (ashift:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 3882 (const_int 1)))
3883 (clobber (reg:CC CC_REGNUM))]
25f905c2 3884 "TARGET_32BIT"
2837e3fb 3885 "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
a2cd141b 3886 [(set_attr "conds" "clob")
1b7da4ac 3887 (set_attr "length" "8")
3888 (set_attr "type" "multiple")]
a2cd141b 3889)
3890
87b22bf7 3891(define_expand "ashlsi3"
cffb2a26 3892 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3893 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
3894 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3895 "TARGET_EITHER"
87b22bf7 3896 "
0438d37f 3897 if (CONST_INT_P (operands[2])
87b22bf7 3898 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3899 {
3900 emit_insn (gen_movsi (operands[0], const0_rtx));
3901 DONE;
3902 }
cffb2a26 3903 "
3904)
3905
25f905c2 3906(define_insn "*thumb1_ashlsi3"
cffb2a26 3907 [(set (match_operand:SI 0 "register_operand" "=l,l")
3908 (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
3909 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
25f905c2 3910 "TARGET_THUMB1"
cffb2a26 3911 "lsl\\t%0, %1, %2"
747b7458 3912 [(set_attr "length" "2")
d82e788e 3913 (set_attr "type" "shift_imm,shift_reg")
747b7458 3914 (set_attr "conds" "set")])
b11cae9e 3915
a2cd141b 3916(define_expand "ashrdi3"
3917 [(set (match_operand:DI 0 "s_register_operand" "")
3918 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
3919 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3920 "TARGET_32BIT"
a2cd141b 3921 "
aa06c51c 3922 if (TARGET_NEON)
3923 {
3924 /* Delay the decision whether to use NEON or core-regs until
3925 register allocation. */
3926 emit_insn (gen_ashrdi3_neon (operands[0], operands[1], operands[2]));
3927 DONE;
3928 }
3929
b805622c 3930 if (!CONST_INT_P (operands[2]) && TARGET_REALLY_IWMMXT)
ffcc986d 3931 ; /* No special preparation statements; expand pattern as above. */
3932 else
a2cd141b 3933 {
ffcc986d 3934 rtx scratch1, scratch2;
3935
3936 if (CONST_INT_P (operands[2])
3937 && (HOST_WIDE_INT) INTVAL (operands[2]) == 1)
a2cd141b 3938 {
3939 emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
3940 DONE;
3941 }
ffcc986d 3942
3943 /* Ideally we should use iwmmxt here if we could know that operands[1]
3944 ends up already living in an iwmmxt register. Otherwise it's
3945 cheaper to have the alternate code being generated than moving
3946 values to iwmmxt regs and back. */
3947
3948 /* If we're optimizing for size, we prefer the libgcc calls. */
3949 if (optimize_function_for_size_p (cfun))
3950 FAIL;
3951
3952 /* Expand operation using core-registers.
3953 'FAIL' would achieve the same thing, but this is a bit smarter. */
3954 scratch1 = gen_reg_rtx (SImode);
3955 scratch2 = gen_reg_rtx (SImode);
3956 arm_emit_coreregs_64bit_shift (ASHIFTRT, operands[0], operands[1],
3957 operands[2], scratch1, scratch2);
3958 DONE;
a2cd141b 3959 }
a2cd141b 3960 "
3961)
3962
2837e3fb 3963(define_insn "arm_ashrdi3_1bit"
50ad1bf9 3964 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 3965 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 3966 (const_int 1)))
3967 (clobber (reg:CC CC_REGNUM))]
25f905c2 3968 "TARGET_32BIT"
2837e3fb 3969 "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
a2cd141b 3970 [(set_attr "conds" "clob")
1b7da4ac 3971 (set_attr "length" "8")
3972 (set_attr "type" "multiple")]
a2cd141b 3973)
3974
87b22bf7 3975(define_expand "ashrsi3"
cffb2a26 3976 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3977 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
3978 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3979 "TARGET_EITHER"
87b22bf7 3980 "
0438d37f 3981 if (CONST_INT_P (operands[2])
87b22bf7 3982 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3983 operands[2] = GEN_INT (31);
cffb2a26 3984 "
3985)
3986
25f905c2 3987(define_insn "*thumb1_ashrsi3"
cffb2a26 3988 [(set (match_operand:SI 0 "register_operand" "=l,l")
3989 (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
3990 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
25f905c2 3991 "TARGET_THUMB1"
cffb2a26 3992 "asr\\t%0, %1, %2"
747b7458 3993 [(set_attr "length" "2")
d82e788e 3994 (set_attr "type" "shift_imm,shift_reg")
747b7458 3995 (set_attr "conds" "set")])
b11cae9e 3996
a2cd141b 3997(define_expand "lshrdi3"
3998 [(set (match_operand:DI 0 "s_register_operand" "")
3999 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
4000 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 4001 "TARGET_32BIT"
a2cd141b 4002 "
aa06c51c 4003 if (TARGET_NEON)
4004 {
4005 /* Delay the decision whether to use NEON or core-regs until
4006 register allocation. */
4007 emit_insn (gen_lshrdi3_neon (operands[0], operands[1], operands[2]));
4008 DONE;
4009 }
4010
b805622c 4011 if (!CONST_INT_P (operands[2]) && TARGET_REALLY_IWMMXT)
ffcc986d 4012 ; /* No special preparation statements; expand pattern as above. */
4013 else
a2cd141b 4014 {
ffcc986d 4015 rtx scratch1, scratch2;
4016
4017 if (CONST_INT_P (operands[2])
4018 && (HOST_WIDE_INT) INTVAL (operands[2]) == 1)
a2cd141b 4019 {
4020 emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
4021 DONE;
4022 }
ffcc986d 4023
4024 /* Ideally we should use iwmmxt here if we could know that operands[1]
4025 ends up already living in an iwmmxt register. Otherwise it's
4026 cheaper to have the alternate code being generated than moving
4027 values to iwmmxt regs and back. */
4028
4029 /* If we're optimizing for size, we prefer the libgcc calls. */
4030 if (optimize_function_for_size_p (cfun))
4031 FAIL;
4032
4033 /* Expand operation using core-registers.
4034 'FAIL' would achieve the same thing, but this is a bit smarter. */
4035 scratch1 = gen_reg_rtx (SImode);
4036 scratch2 = gen_reg_rtx (SImode);
4037 arm_emit_coreregs_64bit_shift (LSHIFTRT, operands[0], operands[1],
4038 operands[2], scratch1, scratch2);
4039 DONE;
a2cd141b 4040 }
a2cd141b 4041 "
4042)
4043
2837e3fb 4044(define_insn "arm_lshrdi3_1bit"
50ad1bf9 4045 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 4046 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 4047 (const_int 1)))
4048 (clobber (reg:CC CC_REGNUM))]
25f905c2 4049 "TARGET_32BIT"
2837e3fb 4050 "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
a2cd141b 4051 [(set_attr "conds" "clob")
1b7da4ac 4052 (set_attr "length" "8")
4053 (set_attr "type" "multiple")]
a2cd141b 4054)
4055
87b22bf7 4056(define_expand "lshrsi3"
cffb2a26 4057 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 4058 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
4059 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 4060 "TARGET_EITHER"
87b22bf7 4061 "
0438d37f 4062 if (CONST_INT_P (operands[2])
87b22bf7 4063 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
4064 {
4065 emit_insn (gen_movsi (operands[0], const0_rtx));
4066 DONE;
4067 }
cffb2a26 4068 "
4069)
4070
25f905c2 4071(define_insn "*thumb1_lshrsi3"
cffb2a26 4072 [(set (match_operand:SI 0 "register_operand" "=l,l")
4073 (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
4074 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
25f905c2 4075 "TARGET_THUMB1"
cffb2a26 4076 "lsr\\t%0, %1, %2"
747b7458 4077 [(set_attr "length" "2")
d82e788e 4078 (set_attr "type" "shift_imm,shift_reg")
747b7458 4079 (set_attr "conds" "set")])
b11cae9e 4080
87b22bf7 4081(define_expand "rotlsi3"
cffb2a26 4082 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 4083 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
4084 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 4085 "TARGET_32BIT"
87b22bf7 4086 "
0438d37f 4087 if (CONST_INT_P (operands[2]))
87b22bf7 4088 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
4089 else
b11cae9e 4090 {
87b22bf7 4091 rtx reg = gen_reg_rtx (SImode);
4092 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
4093 operands[2] = reg;
b11cae9e 4094 }
cffb2a26 4095 "
4096)
9c08d1fa 4097
87b22bf7 4098(define_expand "rotrsi3"
cffb2a26 4099 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 4100 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
4101 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 4102 "TARGET_EITHER"
87b22bf7 4103 "
25f905c2 4104 if (TARGET_32BIT)
cffb2a26 4105 {
0438d37f 4106 if (CONST_INT_P (operands[2])
cffb2a26 4107 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
4108 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
4109 }
25f905c2 4110 else /* TARGET_THUMB1 */
cffb2a26 4111 {
0438d37f 4112 if (CONST_INT_P (operands [2]))
cffb2a26 4113 operands [2] = force_reg (SImode, operands[2]);
4114 }
4115 "
4116)
87b22bf7 4117
25f905c2 4118(define_insn "*thumb1_rotrsi3"
cffb2a26 4119 [(set (match_operand:SI 0 "register_operand" "=l")
4120 (rotatert:SI (match_operand:SI 1 "register_operand" "0")
4121 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 4122 "TARGET_THUMB1"
cffb2a26 4123 "ror\\t%0, %0, %2"
6b6abc9c 4124 [(set_attr "type" "shift_reg")
4125 (set_attr "length" "2")]
cffb2a26 4126)
4127
4128(define_insn "*arm_shiftsi3"
88c29385 4129 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r,r")
cffb2a26 4130 (match_operator:SI 3 "shift_operator"
88c29385 4131 [(match_operand:SI 1 "s_register_operand" "0,l,r,r")
4132 (match_operand:SI 2 "reg_or_int_operand" "l,M,M,r")]))]
25f905c2 4133 "TARGET_32BIT"
4134 "* return arm_output_shift(operands, 0);"
344495ea 4135 [(set_attr "predicable" "yes")
88c29385 4136 (set_attr "arch" "t2,t2,*,*")
4137 (set_attr "predicable_short_it" "yes,yes,no,no")
7c36fe71 4138 (set_attr "length" "4")
331beb1a 4139 (set_attr "shift" "1")
88c29385 4140 (set_attr "type" "alu_shift_reg,alu_shift_imm,alu_shift_imm,alu_shift_reg")]
6c4c2133 4141)
87b22bf7 4142
f7fbdd4a 4143(define_insn "*shiftsi3_compare0"
bd5b4116 4144 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 4145 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
6b6abc9c 4146 [(match_operand:SI 1 "s_register_operand" "r,r")
4147 (match_operand:SI 2 "arm_rhs_operand" "M,r")])
9c08d1fa 4148 (const_int 0)))
6b6abc9c 4149 (set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 4150 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
25f905c2 4151 "TARGET_32BIT"
4152 "* return arm_output_shift(operands, 1);"
344495ea 4153 [(set_attr "conds" "set")
331beb1a 4154 (set_attr "shift" "1")
d82e788e 4155 (set_attr "type" "alus_shift_imm,alus_shift_reg")]
0d66636f 4156)
9c08d1fa 4157
f7fbdd4a 4158(define_insn "*shiftsi3_compare0_scratch"
bd5b4116 4159 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 4160 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
6b6abc9c 4161 [(match_operand:SI 1 "s_register_operand" "r,r")
4162 (match_operand:SI 2 "arm_rhs_operand" "M,r")])
9c08d1fa 4163 (const_int 0)))
6b6abc9c 4164 (clobber (match_scratch:SI 0 "=r,r"))]
25f905c2 4165 "TARGET_32BIT"
4166 "* return arm_output_shift(operands, 1);"
344495ea 4167 [(set_attr "conds" "set")
6b6abc9c 4168 (set_attr "shift" "1")
d82e788e 4169 (set_attr "type" "shift_imm,shift_reg")]
0d66636f 4170)
9c08d1fa 4171
d5d4dc8d 4172(define_insn "*not_shiftsi"
4173 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 4174 (not:SI (match_operator:SI 3 "shift_operator"
d5d4dc8d 4175 [(match_operand:SI 1 "s_register_operand" "r,r")
4176 (match_operand:SI 2 "shift_amount_operand" "M,rM")])))]
4177 "TARGET_32BIT"
6c4c2133 4178 "mvn%?\\t%0, %1%S3"
344495ea 4179 [(set_attr "predicable" "yes")
d952d547 4180 (set_attr "predicable_short_it" "no")
331beb1a 4181 (set_attr "shift" "1")
d5d4dc8d 4182 (set_attr "arch" "32,a")
1aed5204 4183 (set_attr "type" "mvn_shift,mvn_shift_reg")])
9c08d1fa 4184
d5d4dc8d 4185(define_insn "*not_shiftsi_compare0"
bd5b4116 4186 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 4187 (compare:CC_NOOV
4188 (not:SI (match_operator:SI 3 "shift_operator"
4189 [(match_operand:SI 1 "s_register_operand" "r,r")
4190 (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
4191 (const_int 0)))
4192 (set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 4193 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
d5d4dc8d 4194 "TARGET_32BIT"
25f905c2 4195 "mvn%.\\t%0, %1%S3"
344495ea 4196 [(set_attr "conds" "set")
331beb1a 4197 (set_attr "shift" "1")
d5d4dc8d 4198 (set_attr "arch" "32,a")
1aed5204 4199 (set_attr "type" "mvn_shift,mvn_shift_reg")])
9c08d1fa 4200
d5d4dc8d 4201(define_insn "*not_shiftsi_compare0_scratch"
bd5b4116 4202 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 4203 (compare:CC_NOOV
4204 (not:SI (match_operator:SI 3 "shift_operator"
4205 [(match_operand:SI 1 "s_register_operand" "r,r")
4206 (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
4207 (const_int 0)))
4208 (clobber (match_scratch:SI 0 "=r,r"))]
4209 "TARGET_32BIT"
25f905c2 4210 "mvn%.\\t%0, %1%S3"
344495ea 4211 [(set_attr "conds" "set")
331beb1a 4212 (set_attr "shift" "1")
d5d4dc8d 4213 (set_attr "arch" "32,a")
1aed5204 4214 (set_attr "type" "mvn_shift,mvn_shift_reg")])
9c08d1fa 4215
cffb2a26 4216;; We don't really have extzv, but defining this using shifts helps
4217;; to reduce register pressure later on.
4218
4219(define_expand "extzv"
eb04cafb 4220 [(set (match_operand 0 "s_register_operand" "")
4221 (zero_extract (match_operand 1 "nonimmediate_operand" "")
4222 (match_operand 2 "const_int_operand" "")
4223 (match_operand 3 "const_int_operand" "")))]
8b054d5a 4224 "TARGET_THUMB1 || arm_arch_thumb2"
cffb2a26 4225 "
4226 {
4227 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
4228 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
4229
8b054d5a 4230 if (arm_arch_thumb2)
4231 {
eb04cafb 4232 HOST_WIDE_INT width = INTVAL (operands[2]);
4233 HOST_WIDE_INT bitpos = INTVAL (operands[3]);
4234
4235 if (unaligned_access && MEM_P (operands[1])
4236 && (width == 16 || width == 32) && (bitpos % BITS_PER_UNIT) == 0)
4237 {
4238 rtx base_addr;
4239
4240 if (BYTES_BIG_ENDIAN)
4241 bitpos = GET_MODE_BITSIZE (GET_MODE (operands[0])) - width
4242 - bitpos;
4243
4244 if (width == 32)
4245 {
4246 base_addr = adjust_address (operands[1], SImode,
4247 bitpos / BITS_PER_UNIT);
4248 emit_insn (gen_unaligned_loadsi (operands[0], base_addr));
4249 }
4250 else
4251 {
4252 rtx dest = operands[0];
4253 rtx tmp = gen_reg_rtx (SImode);
4254
4255 /* We may get a paradoxical subreg here. Strip it off. */
4256 if (GET_CODE (dest) == SUBREG
4257 && GET_MODE (dest) == SImode
4258 && GET_MODE (SUBREG_REG (dest)) == HImode)
4259 dest = SUBREG_REG (dest);
4260
4261 if (GET_MODE_BITSIZE (GET_MODE (dest)) != width)
4262 FAIL;
4263
4264 base_addr = adjust_address (operands[1], HImode,
4265 bitpos / BITS_PER_UNIT);
4266 emit_insn (gen_unaligned_loadhiu (tmp, base_addr));
4267 emit_move_insn (gen_lowpart (SImode, dest), tmp);
4268 }
4269 DONE;
4270 }
4271 else if (s_register_operand (operands[1], GET_MODE (operands[1])))
4272 {
4273 emit_insn (gen_extzv_t2 (operands[0], operands[1], operands[2],
4274 operands[3]));
4275 DONE;
4276 }
4277 else
4278 FAIL;
8b054d5a 4279 }
eb04cafb 4280
4281 if (!s_register_operand (operands[1], GET_MODE (operands[1])))
4282 FAIL;
8b054d5a 4283
cffb2a26 4284 operands[3] = GEN_INT (rshift);
4285
4286 if (lshift == 0)
4287 {
4288 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
4289 DONE;
4290 }
4291
eb04cafb 4292 emit_insn (gen_extzv_t1 (operands[0], operands[1], GEN_INT (lshift),
4293 operands[3], gen_reg_rtx (SImode)));
4294 DONE;
215b30b3 4295 }"
cffb2a26 4296)
4297
eb04cafb 4298;; Helper for extzv, for the Thumb-1 register-shifts case.
4299
4300(define_expand "extzv_t1"
4301 [(set (match_operand:SI 4 "s_register_operand" "")
4302 (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "")
4303 (match_operand:SI 2 "const_int_operand" "")))
4304 (set (match_operand:SI 0 "s_register_operand" "")
4305 (lshiftrt:SI (match_dup 4)
4306 (match_operand:SI 3 "const_int_operand" "")))]
4307 "TARGET_THUMB1"
4308 "")
4309
4310(define_expand "extv"
4311 [(set (match_operand 0 "s_register_operand" "")
4312 (sign_extract (match_operand 1 "nonimmediate_operand" "")
4313 (match_operand 2 "const_int_operand" "")
4314 (match_operand 3 "const_int_operand" "")))]
4315 "arm_arch_thumb2"
4316{
4317 HOST_WIDE_INT width = INTVAL (operands[2]);
4318 HOST_WIDE_INT bitpos = INTVAL (operands[3]);
4319
4320 if (unaligned_access && MEM_P (operands[1]) && (width == 16 || width == 32)
4321 && (bitpos % BITS_PER_UNIT) == 0)
4322 {
4323 rtx base_addr;
4324
4325 if (BYTES_BIG_ENDIAN)
4326 bitpos = GET_MODE_BITSIZE (GET_MODE (operands[0])) - width - bitpos;
4327
4328 if (width == 32)
4329 {
4330 base_addr = adjust_address (operands[1], SImode,
4331 bitpos / BITS_PER_UNIT);
4332 emit_insn (gen_unaligned_loadsi (operands[0], base_addr));
4333 }
4334 else
4335 {
4336 rtx dest = operands[0];
4337 rtx tmp = gen_reg_rtx (SImode);
4338
4339 /* We may get a paradoxical subreg here. Strip it off. */
4340 if (GET_CODE (dest) == SUBREG
4341 && GET_MODE (dest) == SImode
4342 && GET_MODE (SUBREG_REG (dest)) == HImode)
4343 dest = SUBREG_REG (dest);
4344
4345 if (GET_MODE_BITSIZE (GET_MODE (dest)) != width)
4346 FAIL;
4347
4348 base_addr = adjust_address (operands[1], HImode,
4349 bitpos / BITS_PER_UNIT);
4350 emit_insn (gen_unaligned_loadhis (tmp, base_addr));
4351 emit_move_insn (gen_lowpart (SImode, dest), tmp);
4352 }
4353
4354 DONE;
4355 }
4356 else if (!s_register_operand (operands[1], GET_MODE (operands[1])))
4357 FAIL;
4358 else if (GET_MODE (operands[0]) == SImode
4359 && GET_MODE (operands[1]) == SImode)
4360 {
4361 emit_insn (gen_extv_regsi (operands[0], operands[1], operands[2],
4362 operands[3]));
4363 DONE;
4364 }
4365
4366 FAIL;
4367})
4368
4369; Helper to expand register forms of extv with the proper modes.
4370
4371(define_expand "extv_regsi"
4372 [(set (match_operand:SI 0 "s_register_operand" "")
4373 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
4374 (match_operand 2 "const_int_operand" "")
4375 (match_operand 3 "const_int_operand" "")))]
4376 ""
4377{
4378})
4379
4380; ARMv6+ unaligned load/store instructions (used for packed structure accesses).
4381
4382(define_insn "unaligned_loadsi"
4383 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4384 (unspec:SI [(match_operand:SI 1 "memory_operand" "Uw,m")]
4385 UNSPEC_UNALIGNED_LOAD))]
4386 "unaligned_access && TARGET_32BIT"
4387 "ldr%?\t%0, %1\t@ unaligned"
4388 [(set_attr "arch" "t2,any")
4389 (set_attr "length" "2,4")
4390 (set_attr "predicable" "yes")
d952d547 4391 (set_attr "predicable_short_it" "yes,no")
eb04cafb 4392 (set_attr "type" "load1")])
4393
4394(define_insn "unaligned_loadhis"
4395 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4396 (sign_extend:SI
4397 (unspec:HI [(match_operand:HI 1 "memory_operand" "Uw,m")]
4398 UNSPEC_UNALIGNED_LOAD)))]
4399 "unaligned_access && TARGET_32BIT"
4400 "ldr%(sh%)\t%0, %1\t@ unaligned"
4401 [(set_attr "arch" "t2,any")
4402 (set_attr "length" "2,4")
4403 (set_attr "predicable" "yes")
d952d547 4404 (set_attr "predicable_short_it" "yes,no")
eb04cafb 4405 (set_attr "type" "load_byte")])
4406
4407(define_insn "unaligned_loadhiu"
4408 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4409 (zero_extend:SI
4410 (unspec:HI [(match_operand:HI 1 "memory_operand" "Uw,m")]
4411 UNSPEC_UNALIGNED_LOAD)))]
4412 "unaligned_access && TARGET_32BIT"
4413 "ldr%(h%)\t%0, %1\t@ unaligned"
4414 [(set_attr "arch" "t2,any")
4415 (set_attr "length" "2,4")
4416 (set_attr "predicable" "yes")
d952d547 4417 (set_attr "predicable_short_it" "yes,no")
eb04cafb 4418 (set_attr "type" "load_byte")])
4419
4420(define_insn "unaligned_storesi"
4421 [(set (match_operand:SI 0 "memory_operand" "=Uw,m")
4422 (unspec:SI [(match_operand:SI 1 "s_register_operand" "l,r")]
4423 UNSPEC_UNALIGNED_STORE))]
4424 "unaligned_access && TARGET_32BIT"
4425 "str%?\t%1, %0\t@ unaligned"
4426 [(set_attr "arch" "t2,any")
4427 (set_attr "length" "2,4")
4428 (set_attr "predicable" "yes")
d952d547 4429 (set_attr "predicable_short_it" "yes,no")
eb04cafb 4430 (set_attr "type" "store1")])
4431
4432(define_insn "unaligned_storehi"
4433 [(set (match_operand:HI 0 "memory_operand" "=Uw,m")
4434 (unspec:HI [(match_operand:HI 1 "s_register_operand" "l,r")]
4435 UNSPEC_UNALIGNED_STORE))]
4436 "unaligned_access && TARGET_32BIT"
4437 "str%(h%)\t%1, %0\t@ unaligned"
4438 [(set_attr "arch" "t2,any")
4439 (set_attr "length" "2,4")
4440 (set_attr "predicable" "yes")
d952d547 4441 (set_attr "predicable_short_it" "yes,no")
eb04cafb 4442 (set_attr "type" "store1")])
4443
ae51a965 4444;; Unaligned double-word load and store.
4445;; Split after reload into two unaligned single-word accesses.
4446;; It prevents lower_subreg from splitting some other aligned
4447;; double-word accesses too early. Used for internal memcpy.
4448
4449(define_insn_and_split "unaligned_loaddi"
4450 [(set (match_operand:DI 0 "s_register_operand" "=l,r")
4451 (unspec:DI [(match_operand:DI 1 "memory_operand" "o,o")]
4452 UNSPEC_UNALIGNED_LOAD))]
4453 "unaligned_access && TARGET_32BIT"
4454 "#"
4455 "&& reload_completed"
4456 [(set (match_dup 0) (unspec:SI [(match_dup 1)] UNSPEC_UNALIGNED_LOAD))
4457 (set (match_dup 2) (unspec:SI [(match_dup 3)] UNSPEC_UNALIGNED_LOAD))]
4458 {
4459 operands[2] = gen_highpart (SImode, operands[0]);
4460 operands[0] = gen_lowpart (SImode, operands[0]);
4461 operands[3] = gen_highpart (SImode, operands[1]);
4462 operands[1] = gen_lowpart (SImode, operands[1]);
4463
4464 /* If the first destination register overlaps with the base address,
4465 swap the order in which the loads are emitted. */
4466 if (reg_overlap_mentioned_p (operands[0], operands[1]))
4467 {
4468 rtx tmp = operands[1];
4469 operands[1] = operands[3];
4470 operands[3] = tmp;
4471 tmp = operands[0];
4472 operands[0] = operands[2];
4473 operands[2] = tmp;
4474 }
4475 }
4476 [(set_attr "arch" "t2,any")
4477 (set_attr "length" "4,8")
4478 (set_attr "predicable" "yes")
4479 (set_attr "type" "load2")])
4480
4481(define_insn_and_split "unaligned_storedi"
4482 [(set (match_operand:DI 0 "memory_operand" "=o,o")
4483 (unspec:DI [(match_operand:DI 1 "s_register_operand" "l,r")]
4484 UNSPEC_UNALIGNED_STORE))]
4485 "unaligned_access && TARGET_32BIT"
4486 "#"
4487 "&& reload_completed"
4488 [(set (match_dup 0) (unspec:SI [(match_dup 1)] UNSPEC_UNALIGNED_STORE))
4489 (set (match_dup 2) (unspec:SI [(match_dup 3)] UNSPEC_UNALIGNED_STORE))]
4490 {
4491 operands[2] = gen_highpart (SImode, operands[0]);
4492 operands[0] = gen_lowpart (SImode, operands[0]);
4493 operands[3] = gen_highpart (SImode, operands[1]);
4494 operands[1] = gen_lowpart (SImode, operands[1]);
4495 }
4496 [(set_attr "arch" "t2,any")
4497 (set_attr "length" "4,8")
4498 (set_attr "predicable" "yes")
4499 (set_attr "type" "store2")])
4500
4501
eb04cafb 4502(define_insn "*extv_reg"
8b054d5a 4503 [(set (match_operand:SI 0 "s_register_operand" "=r")
4504 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
809003b3 4505 (match_operand:SI 2 "const_int_M_operand" "M")
4506 (match_operand:SI 3 "const_int_M_operand" "M")))]
8b054d5a 4507 "arm_arch_thumb2"
4508 "sbfx%?\t%0, %1, %3, %2"
4509 [(set_attr "length" "4")
d952d547 4510 (set_attr "predicable" "yes")
d82e788e 4511 (set_attr "predicable_short_it" "no")
4512 (set_attr "type" "bfm")]
8b054d5a 4513)
4514
4515(define_insn "extzv_t2"
4516 [(set (match_operand:SI 0 "s_register_operand" "=r")
4517 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "r")
809003b3 4518 (match_operand:SI 2 "const_int_M_operand" "M")
4519 (match_operand:SI 3 "const_int_M_operand" "M")))]
8b054d5a 4520 "arm_arch_thumb2"
4521 "ubfx%?\t%0, %1, %3, %2"
4522 [(set_attr "length" "4")
d952d547 4523 (set_attr "predicable" "yes")
d82e788e 4524 (set_attr "predicable_short_it" "no")
4525 (set_attr "type" "bfm")]
8b054d5a 4526)
4527
7d3cda8c 4528
4529;; Division instructions
4530(define_insn "divsi3"
4531 [(set (match_operand:SI 0 "s_register_operand" "=r")
4532 (div:SI (match_operand:SI 1 "s_register_operand" "r")
4533 (match_operand:SI 2 "s_register_operand" "r")))]
4534 "TARGET_IDIV"
4535 "sdiv%?\t%0, %1, %2"
4536 [(set_attr "predicable" "yes")
d952d547 4537 (set_attr "predicable_short_it" "no")
9da0ec36 4538 (set_attr "type" "sdiv")]
7d3cda8c 4539)
4540
4541(define_insn "udivsi3"
4542 [(set (match_operand:SI 0 "s_register_operand" "=r")
4543 (udiv:SI (match_operand:SI 1 "s_register_operand" "r")
4544 (match_operand:SI 2 "s_register_operand" "r")))]
4545 "TARGET_IDIV"
4546 "udiv%?\t%0, %1, %2"
4547 [(set_attr "predicable" "yes")
d952d547 4548 (set_attr "predicable_short_it" "no")
9da0ec36 4549 (set_attr "type" "udiv")]
7d3cda8c 4550)
4551
b11cae9e 4552\f
4553;; Unary arithmetic insns
4554
cffb2a26 4555(define_expand "negdi2"
4556 [(parallel
8135a42b 4557 [(set (match_operand:DI 0 "s_register_operand" "")
4558 (neg:DI (match_operand:DI 1 "s_register_operand" "")))
bd5b4116 4559 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 4560 "TARGET_EITHER"
774d2fbb 4561 {
4562 if (TARGET_NEON)
4563 {
4564 emit_insn (gen_negdi2_neon (operands[0], operands[1]));
4565 DONE;
4566 }
4567 }
cffb2a26 4568)
4569
4570;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
e5fea38e 4571;; The first alternative allows the common case of a *full* overlap.
ba6a3b2f 4572(define_insn_and_split "*arm_negdi2"
458a8706 4573 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 4574 (neg:DI (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 4575 (clobber (reg:CC CC_REGNUM))]
cffb2a26 4576 "TARGET_ARM"
ba6a3b2f 4577 "#" ; "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
4578 "&& reload_completed"
4579 [(parallel [(set (reg:CC CC_REGNUM)
4580 (compare:CC (const_int 0) (match_dup 1)))
4581 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 1)))])
4582 (set (match_dup 2) (minus:SI (minus:SI (const_int 0) (match_dup 3))
4583 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
4584 {
4585 operands[2] = gen_highpart (SImode, operands[0]);
4586 operands[0] = gen_lowpart (SImode, operands[0]);
4587 operands[3] = gen_highpart (SImode, operands[1]);
4588 operands[1] = gen_lowpart (SImode, operands[1]);
4589 }
cffb2a26 4590 [(set_attr "conds" "clob")
1b7da4ac 4591 (set_attr "length" "8")
4592 (set_attr "type" "multiple")]
cffb2a26 4593)
b11cae9e 4594
25f905c2 4595(define_insn "*thumb1_negdi2"
8135a42b 4596 [(set (match_operand:DI 0 "register_operand" "=&l")
4597 (neg:DI (match_operand:DI 1 "register_operand" "l")))
bd5b4116 4598 (clobber (reg:CC CC_REGNUM))]
25f905c2 4599 "TARGET_THUMB1"
cffb2a26 4600 "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
1b7da4ac 4601 [(set_attr "length" "6")
4602 (set_attr "type" "multiple")]
cffb2a26 4603)
4604
4605(define_expand "negsi2"
4606 [(set (match_operand:SI 0 "s_register_operand" "")
4607 (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
4608 "TARGET_EITHER"
b11cae9e 4609 ""
cffb2a26 4610)
4611
4612(define_insn "*arm_negsi2"
d952d547 4613 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4614 (neg:SI (match_operand:SI 1 "s_register_operand" "l,r")))]
25f905c2 4615 "TARGET_32BIT"
cffb2a26 4616 "rsb%?\\t%0, %1, #0"
d952d547 4617 [(set_attr "predicable" "yes")
4618 (set_attr "predicable_short_it" "yes,no")
4619 (set_attr "arch" "t2,*")
1b7da4ac 4620 (set_attr "length" "4")
4621 (set_attr "type" "alu_reg")]
cffb2a26 4622)
4623
25f905c2 4624(define_insn "*thumb1_negsi2"
cffb2a26 4625 [(set (match_operand:SI 0 "register_operand" "=l")
4626 (neg:SI (match_operand:SI 1 "register_operand" "l")))]
25f905c2 4627 "TARGET_THUMB1"
cffb2a26 4628 "neg\\t%0, %1"
1b7da4ac 4629 [(set_attr "length" "2")
4630 (set_attr "type" "alu_imm")]
cffb2a26 4631)
b11cae9e 4632
604f3a0a 4633(define_expand "negsf2"
4634 [(set (match_operand:SF 0 "s_register_operand" "")
4635 (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
994606f8 4636 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
604f3a0a 4637 ""
4638)
4639
4640(define_expand "negdf2"
4641 [(set (match_operand:DF 0 "s_register_operand" "")
4642 (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
994606f8 4643 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
604f3a0a 4644 "")
4645
7eaf2be0 4646(define_insn_and_split "*zextendsidi_negsi"
4647 [(set (match_operand:DI 0 "s_register_operand" "=r")
4648 (zero_extend:DI (neg:SI (match_operand:SI 1 "s_register_operand" "r"))))]
4649 "TARGET_32BIT"
4650 "#"
4651 ""
4652 [(set (match_dup 2)
4653 (neg:SI (match_dup 1)))
4654 (set (match_dup 3)
4655 (const_int 0))]
4656 {
4657 operands[2] = gen_lowpart (SImode, operands[0]);
4658 operands[3] = gen_highpart (SImode, operands[0]);
4659 }
4660 [(set_attr "length" "8")
4661 (set_attr "type" "multiple")]
4662)
4663
83e2b922 4664;; Negate an extended 32-bit value.
4665(define_insn_and_split "*negdi_extendsidi"
61fa8ff2 4666 [(set (match_operand:DI 0 "s_register_operand" "=l,r")
4667 (neg:DI (sign_extend:DI
4668 (match_operand:SI 1 "s_register_operand" "l,r"))))
83e2b922 4669 (clobber (reg:CC CC_REGNUM))]
4670 "TARGET_32BIT"
61fa8ff2 4671 "#"
83e2b922 4672 "&& reload_completed"
4673 [(const_int 0)]
4674 {
61fa8ff2 4675 rtx low = gen_lowpart (SImode, operands[0]);
4676 rtx high = gen_highpart (SImode, operands[0]);
4677
4678 if (reg_overlap_mentioned_p (low, operands[1]))
4679 {
4680 /* Input overlaps the low word of the output. Use:
4681 asr Rhi, Rin, #31
4682 rsbs Rlo, Rin, #0
4683 rsc Rhi, Rhi, #0 (thumb2: sbc Rhi, Rhi, Rhi, lsl #1). */
4684 rtx cc_reg = gen_rtx_REG (CC_Cmode, CC_REGNUM);
4685
4686 emit_insn (gen_rtx_SET (VOIDmode, high,
4687 gen_rtx_ASHIFTRT (SImode, operands[1],
4688 GEN_INT (31))));
4689
4690 emit_insn (gen_subsi3_compare (low, const0_rtx, operands[1]));
4691 if (TARGET_ARM)
4692 emit_insn (gen_rtx_SET (VOIDmode, high,
4693 gen_rtx_MINUS (SImode,
4694 gen_rtx_MINUS (SImode,
4695 const0_rtx,
4696 high),
4697 gen_rtx_LTU (SImode,
4698 cc_reg,
4699 const0_rtx))));
4700 else
4701 {
4702 rtx two_x = gen_rtx_ASHIFT (SImode, high, GEN_INT (1));
4703 emit_insn (gen_rtx_SET (VOIDmode, high,
4704 gen_rtx_MINUS (SImode,
4705 gen_rtx_MINUS (SImode,
4706 high,
4707 two_x),
4708 gen_rtx_LTU (SImode,
4709 cc_reg,
4710 const0_rtx))));
4711 }
4712 }
4713 else
4714 {
4715 /* No overlap, or overlap on high word. Use:
4716 rsb Rlo, Rin, #0
4717 bic Rhi, Rlo, Rin
4718 asr Rhi, Rhi, #31
4719 Flags not needed for this sequence. */
4720 emit_insn (gen_rtx_SET (VOIDmode, low,
4721 gen_rtx_NEG (SImode, operands[1])));
4722 emit_insn (gen_rtx_SET (VOIDmode, high,
4723 gen_rtx_AND (SImode,
4724 gen_rtx_NOT (SImode, operands[1]),
4725 low)));
4726 emit_insn (gen_rtx_SET (VOIDmode, high,
4727 gen_rtx_ASHIFTRT (SImode, high,
4728 GEN_INT (31))));
4729 }
4730 DONE;
83e2b922 4731 }
61fa8ff2 4732 [(set_attr "length" "12")
4733 (set_attr "arch" "t2,*")
1b7da4ac 4734 (set_attr "type" "multiple")]
83e2b922 4735)
4736
4737(define_insn_and_split "*negdi_zero_extendsidi"
4738 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
4739 (neg:DI (zero_extend:DI (match_operand:SI 1 "s_register_operand" "0,r"))))
4740 (clobber (reg:CC CC_REGNUM))]
4741 "TARGET_32BIT"
4742 "#" ; "rsbs\\t%Q0, %1, #0\;sbc\\t%R0,%R0,%R0"
4743 ;; Don't care what register is input to sbc,
4744 ;; since we just just need to propagate the carry.
4745 "&& reload_completed"
4746 [(parallel [(set (reg:CC CC_REGNUM)
4747 (compare:CC (const_int 0) (match_dup 1)))
4748 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 1)))])
4749 (set (match_dup 2) (minus:SI (minus:SI (match_dup 2) (match_dup 2))
4750 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
4751 {
4752 operands[2] = gen_highpart (SImode, operands[0]);
4753 operands[0] = gen_lowpart (SImode, operands[0]);
4754 }
4755 [(set_attr "conds" "clob")
1b7da4ac 4756 (set_attr "length" "8")
4757 (set_attr "type" "multiple")] ;; length in thumb is 4
83e2b922 4758)
4759
9c08d1fa 4760;; abssi2 doesn't really clobber the condition codes if a different register
4761;; is being set. To keep things simple, assume during rtl manipulations that
4762;; it does, but tell the final scan operator the truth. Similarly for
4763;; (neg (abs...))
4764
604f3a0a 4765(define_expand "abssi2"
4766 [(parallel
4767 [(set (match_operand:SI 0 "s_register_operand" "")
4768 (abs:SI (match_operand:SI 1 "s_register_operand" "")))
ba156559 4769 (clobber (match_dup 2))])]
4770 "TARGET_EITHER"
4771 "
25f905c2 4772 if (TARGET_THUMB1)
ba156559 4773 operands[2] = gen_rtx_SCRATCH (SImode);
4774 else
4775 operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
4776")
604f3a0a 4777
ba6a3b2f 4778(define_insn_and_split "*arm_abssi2"
ba156559 4779 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
9c08d1fa 4780 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
bd5b4116 4781 (clobber (reg:CC CC_REGNUM))]
cffb2a26 4782 "TARGET_ARM"
ba6a3b2f 4783 "#"
4784 "&& reload_completed"
4785 [(const_int 0)]
4786 {
4787 /* if (which_alternative == 0) */
4788 if (REGNO(operands[0]) == REGNO(operands[1]))
4789 {
4790 /* Emit the pattern:
4791 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
4792 [(set (reg:CC CC_REGNUM)
4793 (compare:CC (match_dup 0) (const_int 0)))
4794 (cond_exec (lt:CC (reg:CC CC_REGNUM) (const_int 0))
4795 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 1))))]
4796 */
4797 emit_insn (gen_rtx_SET (VOIDmode,
4798 gen_rtx_REG (CCmode, CC_REGNUM),
4799 gen_rtx_COMPARE (CCmode, operands[0], const0_rtx)));
4800 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
4801 (gen_rtx_LT (SImode,
4802 gen_rtx_REG (CCmode, CC_REGNUM),
4803 const0_rtx)),
4804 (gen_rtx_SET (VOIDmode,
4805 operands[0],
4806 (gen_rtx_MINUS (SImode,
4807 const0_rtx,
4808 operands[1]))))));
4809 DONE;
4810 }
4811 else
4812 {
4813 /* Emit the pattern:
4814 alt1: eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31
4815 [(set (match_dup 0)
4816 (xor:SI (match_dup 1)
4817 (ashiftrt:SI (match_dup 1) (const_int 31))))
4818 (set (match_dup 0)
4819 (minus:SI (match_dup 0)
4820 (ashiftrt:SI (match_dup 1) (const_int 31))))]
4821 */
4822 emit_insn (gen_rtx_SET (VOIDmode,
4823 operands[0],
4824 gen_rtx_XOR (SImode,
4825 gen_rtx_ASHIFTRT (SImode,
4826 operands[1],
4827 GEN_INT (31)),
4828 operands[1])));
4829 emit_insn (gen_rtx_SET (VOIDmode,
4830 operands[0],
4831 gen_rtx_MINUS (SImode,
4832 operands[0],
4833 gen_rtx_ASHIFTRT (SImode,
4834 operands[1],
4835 GEN_INT (31)))));
4836 DONE;
4837 }
4838 }
cffb2a26 4839 [(set_attr "conds" "clob,*")
331beb1a 4840 (set_attr "shift" "1")
2ad08b65 4841 (set_attr "predicable" "no, yes")
1b7da4ac 4842 (set_attr "length" "8")
4843 (set_attr "type" "multiple")]
cffb2a26 4844)
9c08d1fa 4845
25f905c2 4846(define_insn_and_split "*thumb1_abssi2"
ba156559 4847 [(set (match_operand:SI 0 "s_register_operand" "=l")
4848 (abs:SI (match_operand:SI 1 "s_register_operand" "l")))
4849 (clobber (match_scratch:SI 2 "=&l"))]
25f905c2 4850 "TARGET_THUMB1"
ba156559 4851 "#"
25f905c2 4852 "TARGET_THUMB1 && reload_completed"
ba156559 4853 [(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31)))
4854 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
4855 (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 2)))]
4856 ""
1b7da4ac 4857 [(set_attr "length" "6")
4858 (set_attr "type" "multiple")]
ba156559 4859)
4860
ba6a3b2f 4861(define_insn_and_split "*arm_neg_abssi2"
9c08d1fa 4862 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
4863 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
bd5b4116 4864 (clobber (reg:CC CC_REGNUM))]
cffb2a26 4865 "TARGET_ARM"
ba6a3b2f 4866 "#"
4867 "&& reload_completed"
4868 [(const_int 0)]
4869 {
4870 /* if (which_alternative == 0) */
4871 if (REGNO (operands[0]) == REGNO (operands[1]))
4872 {
4873 /* Emit the pattern:
4874 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
4875 */
4876 emit_insn (gen_rtx_SET (VOIDmode,
4877 gen_rtx_REG (CCmode, CC_REGNUM),
4878 gen_rtx_COMPARE (CCmode, operands[0], const0_rtx)));
4879 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
4880 gen_rtx_GT (SImode,
4881 gen_rtx_REG (CCmode, CC_REGNUM),
4882 const0_rtx),
4883 gen_rtx_SET (VOIDmode,
4884 operands[0],
4885 (gen_rtx_MINUS (SImode,
4886 const0_rtx,
4887 operands[1])))));
4888 }
4889 else
4890 {
4891 /* Emit the pattern:
4892 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31
4893 */
4894 emit_insn (gen_rtx_SET (VOIDmode,
4895 operands[0],
4896 gen_rtx_XOR (SImode,
4897 gen_rtx_ASHIFTRT (SImode,
4898 operands[1],
4899 GEN_INT (31)),
4900 operands[1])));
4901 emit_insn (gen_rtx_SET (VOIDmode,
4902 operands[0],
4903 gen_rtx_MINUS (SImode,
4904 gen_rtx_ASHIFTRT (SImode,
4905 operands[1],
4906 GEN_INT (31)),
4907 operands[0])));
4908 }
4909 DONE;
4910 }
cffb2a26 4911 [(set_attr "conds" "clob,*")
331beb1a 4912 (set_attr "shift" "1")
2ad08b65 4913 (set_attr "predicable" "no, yes")
1b7da4ac 4914 (set_attr "length" "8")
4915 (set_attr "type" "multiple")]
cffb2a26 4916)
b11cae9e 4917
25f905c2 4918(define_insn_and_split "*thumb1_neg_abssi2"
ba156559 4919 [(set (match_operand:SI 0 "s_register_operand" "=l")
4920 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "l"))))
4921 (clobber (match_scratch:SI 2 "=&l"))]
25f905c2 4922 "TARGET_THUMB1"
ba156559 4923 "#"
25f905c2 4924 "TARGET_THUMB1 && reload_completed"
ba156559 4925 [(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31)))
4926 (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))
4927 (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 2)))]
4928 ""
1b7da4ac 4929 [(set_attr "length" "6")
4930 (set_attr "type" "multiple")]
ba156559 4931)
4932
604f3a0a 4933(define_expand "abssf2"
4934 [(set (match_operand:SF 0 "s_register_operand" "")
4935 (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
25f905c2 4936 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 4937 "")
4938
604f3a0a 4939(define_expand "absdf2"
4940 [(set (match_operand:DF 0 "s_register_operand" "")
4941 (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 4942 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 4943 "")
4944
7db9af5d 4945(define_expand "sqrtsf2"
4946 [(set (match_operand:SF 0 "s_register_operand" "")
4947 (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
994606f8 4948 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
7db9af5d 4949 "")
9c08d1fa 4950
7db9af5d 4951(define_expand "sqrtdf2"
4952 [(set (match_operand:DF 0 "s_register_operand" "")
4953 (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
994606f8 4954 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
7db9af5d 4955 "")
9c08d1fa 4956
a0f94409 4957(define_insn_and_split "one_cmpldi2"
10efb95f 4958 [(set (match_operand:DI 0 "s_register_operand" "=w,&r,&r,?w")
4959 (not:DI (match_operand:DI 1 "s_register_operand" " w, 0, r, w")))]
25f905c2 4960 "TARGET_32BIT"
10efb95f 4961 "@
4962 vmvn\t%P0, %P1
4963 #
4964 #
4965 vmvn\t%P0, %P1"
4966 "TARGET_32BIT && reload_completed
4967 && arm_general_register_operand (operands[0], DImode)"
a0f94409 4968 [(set (match_dup 0) (not:SI (match_dup 1)))
4969 (set (match_dup 2) (not:SI (match_dup 3)))]
4970 "
4971 {
4972 operands[2] = gen_highpart (SImode, operands[0]);
4973 operands[0] = gen_lowpart (SImode, operands[0]);
4974 operands[3] = gen_highpart (SImode, operands[1]);
4975 operands[1] = gen_lowpart (SImode, operands[1]);
4976 }"
10efb95f 4977 [(set_attr "length" "*,8,8,*")
4978 (set_attr "predicable" "no,yes,yes,no")
32093010 4979 (set_attr "type" "neon_move,multiple,multiple,neon_move")
b6779ddc 4980 (set_attr "arch" "neon_for_64bits,*,*,avoid_neon_for_64bits")]
cffb2a26 4981)
b11cae9e 4982
cffb2a26 4983(define_expand "one_cmplsi2"
4984 [(set (match_operand:SI 0 "s_register_operand" "")
4985 (not:SI (match_operand:SI 1 "s_register_operand" "")))]
4986 "TARGET_EITHER"
b11cae9e 4987 ""
cffb2a26 4988)
4989
4990(define_insn "*arm_one_cmplsi2"
d952d547 4991 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4992 (not:SI (match_operand:SI 1 "s_register_operand" "l,r")))]
25f905c2 4993 "TARGET_32BIT"
cffb2a26 4994 "mvn%?\\t%0, %1"
d2a518d1 4995 [(set_attr "predicable" "yes")
d952d547 4996 (set_attr "predicable_short_it" "yes,no")
4997 (set_attr "arch" "t2,*")
4998 (set_attr "length" "4")
1aed5204 4999 (set_attr "type" "mvn_reg")]
cffb2a26 5000)
5001
25f905c2 5002(define_insn "*thumb1_one_cmplsi2"
cffb2a26 5003 [(set (match_operand:SI 0 "register_operand" "=l")
5004 (not:SI (match_operand:SI 1 "register_operand" "l")))]
25f905c2 5005 "TARGET_THUMB1"
cffb2a26 5006 "mvn\\t%0, %1"
d2a518d1 5007 [(set_attr "length" "2")
1aed5204 5008 (set_attr "type" "mvn_reg")]
cffb2a26 5009)
9c08d1fa 5010
f7fbdd4a 5011(define_insn "*notsi_compare0"
bd5b4116 5012 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 5013 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5014 (const_int 0)))
5015 (set (match_operand:SI 0 "s_register_operand" "=r")
5016 (not:SI (match_dup 1)))]
25f905c2 5017 "TARGET_32BIT"
5018 "mvn%.\\t%0, %1"
d2a518d1 5019 [(set_attr "conds" "set")
1aed5204 5020 (set_attr "type" "mvn_reg")]
cffb2a26 5021)
9c08d1fa 5022
f7fbdd4a 5023(define_insn "*notsi_compare0_scratch"
bd5b4116 5024 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 5025 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5026 (const_int 0)))
5027 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 5028 "TARGET_32BIT"
5029 "mvn%.\\t%0, %1"
d2a518d1 5030 [(set_attr "conds" "set")
1aed5204 5031 (set_attr "type" "mvn_reg")]
cffb2a26 5032)
b11cae9e 5033\f
5034;; Fixed <--> Floating conversion insns
5035
9b8516be 5036(define_expand "floatsihf2"
5037 [(set (match_operand:HF 0 "general_operand" "")
5038 (float:HF (match_operand:SI 1 "general_operand" "")))]
5039 "TARGET_EITHER"
5040 "
5041 {
5042 rtx op1 = gen_reg_rtx (SFmode);
5043 expand_float (op1, operands[1], 0);
5044 op1 = convert_to_mode (HFmode, op1, 0);
5045 emit_move_insn (operands[0], op1);
5046 DONE;
5047 }"
5048)
5049
5050(define_expand "floatdihf2"
5051 [(set (match_operand:HF 0 "general_operand" "")
5052 (float:HF (match_operand:DI 1 "general_operand" "")))]
5053 "TARGET_EITHER"
5054 "
5055 {
5056 rtx op1 = gen_reg_rtx (SFmode);
5057 expand_float (op1, operands[1], 0);
5058 op1 = convert_to_mode (HFmode, op1, 0);
5059 emit_move_insn (operands[0], op1);
5060 DONE;
5061 }"
5062)
5063
604f3a0a 5064(define_expand "floatsisf2"
5065 [(set (match_operand:SF 0 "s_register_operand" "")
5066 (float:SF (match_operand:SI 1 "s_register_operand" "")))]
25f905c2 5067 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 5068 "
604f3a0a 5069")
5070
604f3a0a 5071(define_expand "floatsidf2"
5072 [(set (match_operand:DF 0 "s_register_operand" "")
5073 (float:DF (match_operand:SI 1 "s_register_operand" "")))]
a50d7267 5074 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 5075 "
604f3a0a 5076")
5077
9b8516be 5078(define_expand "fix_trunchfsi2"
5079 [(set (match_operand:SI 0 "general_operand" "")
5080 (fix:SI (fix:HF (match_operand:HF 1 "general_operand" ""))))]
5081 "TARGET_EITHER"
5082 "
5083 {
5084 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
5085 expand_fix (operands[0], op1, 0);
5086 DONE;
5087 }"
5088)
5089
5090(define_expand "fix_trunchfdi2"
5091 [(set (match_operand:DI 0 "general_operand" "")
5092 (fix:DI (fix:HF (match_operand:HF 1 "general_operand" ""))))]
5093 "TARGET_EITHER"
5094 "
5095 {
5096 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
5097 expand_fix (operands[0], op1, 0);
5098 DONE;
5099 }"
5100)
5101
604f3a0a 5102(define_expand "fix_truncsfsi2"
5103 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 5104 (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" ""))))]
25f905c2 5105 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 5106 "
604f3a0a 5107")
5108
604f3a0a 5109(define_expand "fix_truncdfsi2"
5110 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 5111 (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" ""))))]
a50d7267 5112 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 5113 "
604f3a0a 5114")
5115
f544c6d2 5116;; Truncation insns
b11cae9e 5117
604f3a0a 5118(define_expand "truncdfsf2"
5119 [(set (match_operand:SF 0 "s_register_operand" "")
5120 (float_truncate:SF
5121 (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 5122 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 5123 ""
5124)
9b8516be 5125
5126/* DFmode -> HFmode conversions have to go through SFmode. */
5127(define_expand "truncdfhf2"
5128 [(set (match_operand:HF 0 "general_operand" "")
5129 (float_truncate:HF
5130 (match_operand:DF 1 "general_operand" "")))]
5131 "TARGET_EITHER"
5132 "
5133 {
5134 rtx op1;
5135 op1 = convert_to_mode (SFmode, operands[1], 0);
5136 op1 = convert_to_mode (HFmode, op1, 0);
5137 emit_move_insn (operands[0], op1);
5138 DONE;
5139 }"
5140)
b11cae9e 5141\f
9c08d1fa 5142;; Zero and sign extension instructions.
b11cae9e 5143
848e66ac 5144(define_insn "zero_extend<mode>di2"
6aa689e8 5145 [(set (match_operand:DI 0 "s_register_operand" "=w,r,?r,w")
6d97728e 5146 (zero_extend:DI (match_operand:QHSI 1 "<qhs_zextenddi_op>"
5147 "<qhs_zextenddi_cstr>")))]
848e66ac 5148 "TARGET_32BIT <qhs_zextenddi_cond>"
5149 "#"
6aa689e8 5150 [(set_attr "length" "8,4,8,8")
b6779ddc 5151 (set_attr "arch" "neon_for_64bits,*,*,avoid_neon_for_64bits")
848e66ac 5152 (set_attr "ce_count" "2")
efbb5e19 5153 (set_attr "predicable" "yes")
5154 (set_attr "type" "multiple,mov_reg,multiple,multiple")]
25f905c2 5155)
5156
848e66ac 5157(define_insn "extend<mode>di2"
6aa689e8 5158 [(set (match_operand:DI 0 "s_register_operand" "=w,r,?r,?r,w")
63d204a8 5159 (sign_extend:DI (match_operand:QHSI 1 "<qhs_extenddi_op>"
5160 "<qhs_extenddi_cstr>")))]
848e66ac 5161 "TARGET_32BIT <qhs_sextenddi_cond>"
5162 "#"
6aa689e8 5163 [(set_attr "length" "8,4,8,8,8")
848e66ac 5164 (set_attr "ce_count" "2")
5165 (set_attr "shift" "1")
8012d2c2 5166 (set_attr "predicable" "yes")
1b7da4ac 5167 (set_attr "arch" "neon_for_64bits,*,a,t,avoid_neon_for_64bits")
5168 (set_attr "type" "multiple,mov_reg,multiple,multiple,multiple")]
0d66636f 5169)
9c08d1fa 5170
848e66ac 5171;; Splits for all extensions to DImode
5172(define_split
5173 [(set (match_operand:DI 0 "s_register_operand" "")
5174 (zero_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
6aa689e8 5175 "TARGET_32BIT && reload_completed && !IS_VFP_REGNUM (REGNO (operands[0]))"
848e66ac 5176 [(set (match_dup 0) (match_dup 1))]
5177{
848e66ac 5178 rtx lo_part = gen_lowpart (SImode, operands[0]);
5179 enum machine_mode src_mode = GET_MODE (operands[1]);
5180
5181 if (REG_P (operands[0])
5182 && !reg_overlap_mentioned_p (operands[0], operands[1]))
5183 emit_clobber (operands[0]);
5184 if (!REG_P (lo_part) || src_mode != SImode
5185 || !rtx_equal_p (lo_part, operands[1]))
5186 {
5187 if (src_mode == SImode)
5188 emit_move_insn (lo_part, operands[1]);
5189 else
5190 emit_insn (gen_rtx_SET (VOIDmode, lo_part,
5191 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
5192 operands[1] = lo_part;
5193 }
5194 operands[0] = gen_highpart (SImode, operands[0]);
5195 operands[1] = const0_rtx;
5196})
9c08d1fa 5197
848e66ac 5198(define_split
25f905c2 5199 [(set (match_operand:DI 0 "s_register_operand" "")
848e66ac 5200 (sign_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
6aa689e8 5201 "TARGET_32BIT && reload_completed && !IS_VFP_REGNUM (REGNO (operands[0]))"
848e66ac 5202 [(set (match_dup 0) (ashiftrt:SI (match_dup 1) (const_int 31)))]
5203{
5204 rtx lo_part = gen_lowpart (SImode, operands[0]);
5205 enum machine_mode src_mode = GET_MODE (operands[1]);
25f905c2 5206
848e66ac 5207 if (REG_P (operands[0])
5208 && !reg_overlap_mentioned_p (operands[0], operands[1]))
5209 emit_clobber (operands[0]);
5210
5211 if (!REG_P (lo_part) || src_mode != SImode
5212 || !rtx_equal_p (lo_part, operands[1]))
5213 {
5214 if (src_mode == SImode)
5215 emit_move_insn (lo_part, operands[1]);
5216 else
5217 emit_insn (gen_rtx_SET (VOIDmode, lo_part,
5218 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
5219 operands[1] = lo_part;
5220 }
5221 operands[0] = gen_highpart (SImode, operands[0]);
5222})
9c08d1fa 5223
5224(define_expand "zero_extendhisi2"
ef51b8e1 5225 [(set (match_operand:SI 0 "s_register_operand" "")
5226 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
cffb2a26 5227 "TARGET_EITHER"
ef51b8e1 5228{
5229 if (TARGET_ARM && !arm_arch4 && MEM_P (operands[1]))
f7fbdd4a 5230 {
ef51b8e1 5231 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
5232 DONE;
25f7a26e 5233 }
ef51b8e1 5234 if (!arm_arch6 && !MEM_P (operands[1]))
5235 {
5236 rtx t = gen_lowpart (SImode, operands[1]);
5237 rtx tmp = gen_reg_rtx (SImode);
5238 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
5239 emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (16)));
5240 DONE;
5241 }
5242})
9c08d1fa 5243
ef51b8e1 5244(define_split
b146458f 5245 [(set (match_operand:SI 0 "s_register_operand" "")
5246 (zero_extend:SI (match_operand:HI 1 "s_register_operand" "")))]
ef51b8e1 5247 "!TARGET_THUMB2 && !arm_arch6"
5248 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
5249 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 16)))]
5250{
5251 operands[2] = gen_lowpart (SImode, operands[1]);
5252})
5253
5254(define_insn "*thumb1_zero_extendhisi2"
a2cd141b 5255 [(set (match_operand:SI 0 "register_operand" "=l,l")
5256 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
ef51b8e1 5257 "TARGET_THUMB1"
848e66ac 5258{
a2cd141b 5259 rtx mem;
5260
ef51b8e1 5261 if (which_alternative == 0 && arm_arch6)
848e66ac 5262 return "uxth\t%0, %1";
ef51b8e1 5263 if (which_alternative == 0)
848e66ac 5264 return "#";
a2cd141b 5265
5266 mem = XEXP (operands[1], 0);
5267
5268 if (GET_CODE (mem) == CONST)
5269 mem = XEXP (mem, 0);
5270
a2cd141b 5271 if (GET_CODE (mem) == PLUS)
5272 {
5273 rtx a = XEXP (mem, 0);
a2cd141b 5274
5275 /* This can happen due to bugs in reload. */
0438d37f 5276 if (REG_P (a) && REGNO (a) == SP_REGNUM)
a2cd141b 5277 {
5278 rtx ops[2];
5279 ops[0] = operands[0];
5280 ops[1] = a;
5281
848e66ac 5282 output_asm_insn ("mov\t%0, %1", ops);
a2cd141b 5283
5284 XEXP (mem, 0) = operands[0];
5285 }
a2cd141b 5286 }
5287
848e66ac 5288 return "ldrh\t%0, %1";
5289}
ef51b8e1 5290 [(set_attr_alternative "length"
5291 [(if_then_else (eq_attr "is_arch6" "yes")
5292 (const_int 2) (const_int 4))
5293 (const_int 4)])
6b6abc9c 5294 (set_attr "type" "extend,load_byte")]
a2cd141b 5295)
5296
cffb2a26 5297(define_insn "*arm_zero_extendhisi2"
ef51b8e1 5298 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5299 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 5300 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 5301 "@
5302 #
5303 ldr%(h%)\\t%0, %1"
d82e788e 5304 [(set_attr "type" "alu_shift_reg,load_byte")
848e66ac 5305 (set_attr "predicable" "yes")]
cffb2a26 5306)
f7fbdd4a 5307
a2cd141b 5308(define_insn "*arm_zero_extendhisi2_v6"
5309 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5310 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
5311 "TARGET_ARM && arm_arch6"
5312 "@
5313 uxth%?\\t%0, %1
25f905c2 5314 ldr%(h%)\\t%0, %1"
65f68e55 5315 [(set_attr "predicable" "yes")
6b6abc9c 5316 (set_attr "type" "extend,load_byte")]
a2cd141b 5317)
5318
5319(define_insn "*arm_zero_extendhisi2addsi"
5320 [(set (match_operand:SI 0 "s_register_operand" "=r")
5321 (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
5322 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 5323 "TARGET_INT_SIMD"
a2cd141b 5324 "uxtah%?\\t%0, %2, %1"
d82e788e 5325 [(set_attr "type" "alu_shift_reg")
d952d547 5326 (set_attr "predicable" "yes")
5327 (set_attr "predicable_short_it" "no")]
a2cd141b 5328)
5329
87b22bf7 5330(define_expand "zero_extendqisi2"
cffb2a26 5331 [(set (match_operand:SI 0 "s_register_operand" "")
5332 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
5333 "TARGET_EITHER"
ef51b8e1 5334{
0438d37f 5335 if (TARGET_ARM && !arm_arch6 && !MEM_P (operands[1]))
87b22bf7 5336 {
ef51b8e1 5337 emit_insn (gen_andsi3 (operands[0],
5338 gen_lowpart (SImode, operands[1]),
5339 GEN_INT (255)));
5340 DONE;
5341 }
5342 if (!arm_arch6 && !MEM_P (operands[1]))
5343 {
5344 rtx t = gen_lowpart (SImode, operands[1]);
5345 rtx tmp = gen_reg_rtx (SImode);
5346 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
5347 emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (24)));
5348 DONE;
5349 }
5350})
cffb2a26 5351
ef51b8e1 5352(define_split
b146458f 5353 [(set (match_operand:SI 0 "s_register_operand" "")
5354 (zero_extend:SI (match_operand:QI 1 "s_register_operand" "")))]
ef51b8e1 5355 "!arm_arch6"
5356 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
5357 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 24)))]
5358{
5359 operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
5360 if (TARGET_ARM)
5361 {
5362 emit_insn (gen_andsi3 (operands[0], operands[2], GEN_INT (255)));
87b22bf7 5363 DONE;
5364 }
ef51b8e1 5365})
9c08d1fa 5366
25f905c2 5367(define_insn "*thumb1_zero_extendqisi2"
ef51b8e1 5368 [(set (match_operand:SI 0 "register_operand" "=l,l")
5369 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
25f905c2 5370 "TARGET_THUMB1 && !arm_arch6"
ef51b8e1 5371 "@
5372 #
5373 ldrb\\t%0, %1"
5374 [(set_attr "length" "4,2")
d82e788e 5375 (set_attr "type" "alu_shift_reg,load_byte")
ef51b8e1 5376 (set_attr "pool_range" "*,32")]
cffb2a26 5377)
5378
25f905c2 5379(define_insn "*thumb1_zero_extendqisi2_v6"
a2cd141b 5380 [(set (match_operand:SI 0 "register_operand" "=l,l")
5381 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
25f905c2 5382 "TARGET_THUMB1 && arm_arch6"
a2cd141b 5383 "@
5384 uxtb\\t%0, %1
5385 ldrb\\t%0, %1"
848e66ac 5386 [(set_attr "length" "2")
6b6abc9c 5387 (set_attr "type" "extend,load_byte")]
a2cd141b 5388)
5389
cffb2a26 5390(define_insn "*arm_zero_extendqisi2"
ef51b8e1 5391 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5392 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 5393 "TARGET_ARM && !arm_arch6"
ef51b8e1 5394 "@
5395 #
5396 ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
5397 [(set_attr "length" "8,4")
d82e788e 5398 (set_attr "type" "alu_shift_reg,load_byte")
848e66ac 5399 (set_attr "predicable" "yes")]
cffb2a26 5400)
87b22bf7 5401
a2cd141b 5402(define_insn "*arm_zero_extendqisi2_v6"
5403 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5404 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
5405 "TARGET_ARM && arm_arch6"
5406 "@
25f905c2 5407 uxtb%(%)\\t%0, %1
5408 ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
6b6abc9c 5409 [(set_attr "type" "extend,load_byte")
848e66ac 5410 (set_attr "predicable" "yes")]
a2cd141b 5411)
5412
5413(define_insn "*arm_zero_extendqisi2addsi"
5414 [(set (match_operand:SI 0 "s_register_operand" "=r")
5415 (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
5416 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 5417 "TARGET_INT_SIMD"
a2cd141b 5418 "uxtab%?\\t%0, %2, %1"
5419 [(set_attr "predicable" "yes")
d952d547 5420 (set_attr "predicable_short_it" "no")
d82e788e 5421 (set_attr "type" "alu_shift_reg")]
a2cd141b 5422)
5423
87b22bf7 5424(define_split
5425 [(set (match_operand:SI 0 "s_register_operand" "")
5426 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
5427 (clobber (match_operand:SI 2 "s_register_operand" ""))]
0438d37f 5428 "TARGET_32BIT && (!MEM_P (operands[1])) && ! BYTES_BIG_ENDIAN"
87b22bf7 5429 [(set (match_dup 2) (match_dup 1))
5430 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
cffb2a26 5431 ""
5432)
9c08d1fa 5433
8a4d25d6 5434(define_split
5435 [(set (match_operand:SI 0 "s_register_operand" "")
5436 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 3)))
5437 (clobber (match_operand:SI 2 "s_register_operand" ""))]
0438d37f 5438 "TARGET_32BIT && (!MEM_P (operands[1])) && BYTES_BIG_ENDIAN"
8a4d25d6 5439 [(set (match_dup 2) (match_dup 1))
5440 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
5441 ""
5442)
5443
1c274529 5444
5445(define_split
5446 [(set (match_operand:SI 0 "s_register_operand" "")
5447 (ior_xor:SI (and:SI (ashift:SI
5448 (match_operand:SI 1 "s_register_operand" "")
5449 (match_operand:SI 2 "const_int_operand" ""))
5450 (match_operand:SI 3 "const_int_operand" ""))
5451 (zero_extend:SI
5452 (match_operator 5 "subreg_lowpart_operator"
5453 [(match_operand:SI 4 "s_register_operand" "")]))))]
5454 "TARGET_32BIT
63787642 5455 && ((unsigned HOST_WIDE_INT) INTVAL (operands[3])
1c274529 5456 == (GET_MODE_MASK (GET_MODE (operands[5]))
5457 & (GET_MODE_MASK (GET_MODE (operands[5]))
5458 << (INTVAL (operands[2])))))"
5459 [(set (match_dup 0) (ior_xor:SI (ashift:SI (match_dup 1) (match_dup 2))
5460 (match_dup 4)))
5461 (set (match_dup 0) (zero_extend:SI (match_dup 5)))]
5462 "operands[5] = gen_lowpart (GET_MODE (operands[5]), operands[0]);"
5463)
5464
f7fbdd4a 5465(define_insn "*compareqi_eq0"
bd5b4116 5466 [(set (reg:CC_Z CC_REGNUM)
206ee9a2 5467 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
87b22bf7 5468 (const_int 0)))]
25f905c2 5469 "TARGET_32BIT"
596e5e8f 5470 "tst%?\\t%0, #255"
5471 [(set_attr "conds" "set")
d952d547 5472 (set_attr "predicable" "yes")
1b7da4ac 5473 (set_attr "predicable_short_it" "no")
5474 (set_attr "type" "logic_imm")]
cffb2a26 5475)
b11cae9e 5476
b11cae9e 5477(define_expand "extendhisi2"
ef51b8e1 5478 [(set (match_operand:SI 0 "s_register_operand" "")
5479 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
cffb2a26 5480 "TARGET_EITHER"
ef51b8e1 5481{
5482 if (TARGET_THUMB1)
5483 {
5484 emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1]));
5485 DONE;
5486 }
5487 if (MEM_P (operands[1]) && TARGET_ARM && !arm_arch4)
5488 {
5489 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
5490 DONE;
5491 }
ed29c566 5492
ef51b8e1 5493 if (!arm_arch6 && !MEM_P (operands[1]))
5494 {
5495 rtx t = gen_lowpart (SImode, operands[1]);
5496 rtx tmp = gen_reg_rtx (SImode);
5497 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
5498 emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (16)));
5499 DONE;
5500 }
5501})
cffb2a26 5502
ef51b8e1 5503(define_split
5504 [(parallel
5505 [(set (match_operand:SI 0 "register_operand" "")
5506 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))
5507 (clobber (match_scratch:SI 2 ""))])]
5508 "!arm_arch6"
5509 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
5510 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
5511{
5512 operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
5513})
25f7a26e 5514
a2cd141b 5515;; We used to have an early-clobber on the scratch register here.
5516;; However, there's a bug somewhere in reload which means that this
5517;; can be partially ignored during spill allocation if the memory
ed29c566 5518;; address also needs reloading; this causes us to die later on when
a2cd141b 5519;; we try to verify the operands. Fortunately, we don't really need
5520;; the early-clobber: we can always use operand 0 if operand 2
5521;; overlaps the address.
ef51b8e1 5522(define_insn "thumb1_extendhisi2"
a2cd141b 5523 [(set (match_operand:SI 0 "register_operand" "=l,l")
5524 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
5525 (clobber (match_scratch:SI 2 "=X,l"))]
ef51b8e1 5526 "TARGET_THUMB1"
a2cd141b 5527 "*
5528 {
5529 rtx ops[4];
5530 rtx mem;
5531
ef51b8e1 5532 if (which_alternative == 0 && !arm_arch6)
5533 return \"#\";
a2cd141b 5534 if (which_alternative == 0)
5535 return \"sxth\\t%0, %1\";
5536
5537 mem = XEXP (operands[1], 0);
5538
5539 /* This code used to try to use 'V', and fix the address only if it was
5540 offsettable, but this fails for e.g. REG+48 because 48 is outside the
5541 range of QImode offsets, and offsettable_address_p does a QImode
5542 address check. */
5543
5544 if (GET_CODE (mem) == CONST)
5545 mem = XEXP (mem, 0);
5546
5547 if (GET_CODE (mem) == LABEL_REF)
5548 return \"ldr\\t%0, %1\";
5549
5550 if (GET_CODE (mem) == PLUS)
5551 {
5552 rtx a = XEXP (mem, 0);
5553 rtx b = XEXP (mem, 1);
5554
5555 if (GET_CODE (a) == LABEL_REF
0438d37f 5556 && CONST_INT_P (b))
a2cd141b 5557 return \"ldr\\t%0, %1\";
5558
0438d37f 5559 if (REG_P (b))
a2cd141b 5560 return \"ldrsh\\t%0, %1\";
5561
5562 ops[1] = a;
5563 ops[2] = b;
5564 }
5565 else
5566 {
5567 ops[1] = mem;
5568 ops[2] = const0_rtx;
5569 }
5570
0438d37f 5571 gcc_assert (REG_P (ops[1]));
a2cd141b 5572
5573 ops[0] = operands[0];
5574 if (reg_mentioned_p (operands[2], ops[1]))
5575 ops[3] = ops[0];
5576 else
5577 ops[3] = operands[2];
5578 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
5579 return \"\";
5580 }"
ef51b8e1 5581 [(set_attr_alternative "length"
5582 [(if_then_else (eq_attr "is_arch6" "yes")
5583 (const_int 2) (const_int 4))
5584 (const_int 4)])
6b6abc9c 5585 (set_attr "type" "extend,load_byte")
42e1de19 5586 (set_attr "pool_range" "*,1018")]
a2cd141b 5587)
5588
25f905c2 5589;; This pattern will only be used when ldsh is not available
25f7a26e 5590(define_expand "extendhisi2_mem"
eab14235 5591 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 5592 (set (match_dup 3)
eab14235 5593 (zero_extend:SI (match_dup 7)))
25f7a26e 5594 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
5595 (set (match_operand:SI 0 "" "")
5596 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
cffb2a26 5597 "TARGET_ARM"
25f7a26e 5598 "
215b30b3 5599 {
5600 rtx mem1, mem2;
5601 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
5602
788fcce0 5603 mem1 = change_address (operands[1], QImode, addr);
29c05e22 5604 mem2 = change_address (operands[1], QImode,
5605 plus_constant (Pmode, addr, 1));
215b30b3 5606 operands[0] = gen_lowpart (SImode, operands[0]);
5607 operands[1] = mem1;
5608 operands[2] = gen_reg_rtx (SImode);
5609 operands[3] = gen_reg_rtx (SImode);
5610 operands[6] = gen_reg_rtx (SImode);
5611 operands[7] = mem2;
25f7a26e 5612
215b30b3 5613 if (BYTES_BIG_ENDIAN)
5614 {
5615 operands[4] = operands[2];
5616 operands[5] = operands[3];
5617 }
5618 else
5619 {
5620 operands[4] = operands[3];
5621 operands[5] = operands[2];
5622 }
5623 }"
5624)
b11cae9e 5625
ef51b8e1 5626(define_split
5627 [(set (match_operand:SI 0 "register_operand" "")
5628 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
5629 "!arm_arch6"
5630 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
5631 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
5632{
5633 operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
5634})
5635
a2cd141b 5636(define_insn "*arm_extendhisi2"
ef51b8e1 5637 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5638 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 5639 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 5640 "@
5641 #
5642 ldr%(sh%)\\t%0, %1"
5643 [(set_attr "length" "8,4")
d82e788e 5644 (set_attr "type" "alu_shift_reg,load_byte")
0d66636f 5645 (set_attr "predicable" "yes")
ef51b8e1 5646 (set_attr "pool_range" "*,256")
5647 (set_attr "neg_pool_range" "*,244")]
cffb2a26 5648)
f7fbdd4a 5649
25f905c2 5650;; ??? Check Thumb-2 pool range
a2cd141b 5651(define_insn "*arm_extendhisi2_v6"
5652 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5653 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
25f905c2 5654 "TARGET_32BIT && arm_arch6"
a2cd141b 5655 "@
5656 sxth%?\\t%0, %1
25f905c2 5657 ldr%(sh%)\\t%0, %1"
6b6abc9c 5658 [(set_attr "type" "extend,load_byte")
a2cd141b 5659 (set_attr "predicable" "yes")
d952d547 5660 (set_attr "predicable_short_it" "no")
a2cd141b 5661 (set_attr "pool_range" "*,256")
5662 (set_attr "neg_pool_range" "*,244")]
5663)
5664
5665(define_insn "*arm_extendhisi2addsi"
5666 [(set (match_operand:SI 0 "s_register_operand" "=r")
5667 (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
5668 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 5669 "TARGET_INT_SIMD"
a2cd141b 5670 "sxtah%?\\t%0, %2, %1"
1b7da4ac 5671 [(set_attr "type" "alu_shift_reg")]
a2cd141b 5672)
5673
c8f69309 5674(define_expand "extendqihi2"
5675 [(set (match_dup 2)
bed7d9a5 5676 (ashift:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")
c8f69309 5677 (const_int 24)))
9c08d1fa 5678 (set (match_operand:HI 0 "s_register_operand" "")
c8f69309 5679 (ashiftrt:SI (match_dup 2)
5680 (const_int 24)))]
cffb2a26 5681 "TARGET_ARM"
c8f69309 5682 "
215b30b3 5683 {
0438d37f 5684 if (arm_arch4 && MEM_P (operands[1]))
215b30b3 5685 {
5686 emit_insn (gen_rtx_SET (VOIDmode,
5687 operands[0],
5688 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
5689 DONE;
5690 }
5691 if (!s_register_operand (operands[1], QImode))
5692 operands[1] = copy_to_mode_reg (QImode, operands[1]);
5693 operands[0] = gen_lowpart (SImode, operands[0]);
5694 operands[1] = gen_lowpart (SImode, operands[1]);
5695 operands[2] = gen_reg_rtx (SImode);
5696 }"
5697)
f7fbdd4a 5698
25f905c2 5699(define_insn "*arm_extendqihi_insn"
b4e8a300 5700 [(set (match_operand:HI 0 "s_register_operand" "=r")
bed7d9a5 5701 (sign_extend:HI (match_operand:QI 1 "arm_extendqisi_mem_op" "Uq")))]
cffb2a26 5702 "TARGET_ARM && arm_arch4"
25f905c2 5703 "ldr%(sb%)\\t%0, %1"
a2cd141b 5704 [(set_attr "type" "load_byte")
0d66636f 5705 (set_attr "predicable" "yes")
cffb2a26 5706 (set_attr "pool_range" "256")
5707 (set_attr "neg_pool_range" "244")]
5708)
3fc2009e 5709
b11cae9e 5710(define_expand "extendqisi2"
ef51b8e1 5711 [(set (match_operand:SI 0 "s_register_operand" "")
5712 (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")))]
cffb2a26 5713 "TARGET_EITHER"
ef51b8e1 5714{
5715 if (!arm_arch4 && MEM_P (operands[1]))
5716 operands[1] = copy_to_mode_reg (QImode, operands[1]);
a2cd141b 5717
ef51b8e1 5718 if (!arm_arch6 && !MEM_P (operands[1]))
5719 {
5720 rtx t = gen_lowpart (SImode, operands[1]);
5721 rtx tmp = gen_reg_rtx (SImode);
5722 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
5723 emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (24)));
5724 DONE;
5725 }
5726})
a2cd141b 5727
ef51b8e1 5728(define_split
5729 [(set (match_operand:SI 0 "register_operand" "")
5730 (sign_extend:SI (match_operand:QI 1 "register_operand" "")))]
5731 "!arm_arch6"
5732 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
5733 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))]
5734{
5735 operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
5736})
f7fbdd4a 5737
a2cd141b 5738(define_insn "*arm_extendqisi"
ef51b8e1 5739 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5740 (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
a2cd141b 5741 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 5742 "@
5743 #
5744 ldr%(sb%)\\t%0, %1"
5745 [(set_attr "length" "8,4")
d82e788e 5746 (set_attr "type" "alu_shift_reg,load_byte")
0d66636f 5747 (set_attr "predicable" "yes")
ef51b8e1 5748 (set_attr "pool_range" "*,256")
5749 (set_attr "neg_pool_range" "*,244")]
cffb2a26 5750)
3fc2009e 5751
a2cd141b 5752(define_insn "*arm_extendqisi_v6"
5753 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
bed7d9a5 5754 (sign_extend:SI
5755 (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
a2cd141b 5756 "TARGET_ARM && arm_arch6"
b4e8a300 5757 "@
5758 sxtb%?\\t%0, %1
25f905c2 5759 ldr%(sb%)\\t%0, %1"
6b6abc9c 5760 [(set_attr "type" "extend,load_byte")
a2cd141b 5761 (set_attr "predicable" "yes")
a2cd141b 5762 (set_attr "pool_range" "*,256")
5763 (set_attr "neg_pool_range" "*,244")]
5764)
5765
5766(define_insn "*arm_extendqisi2addsi"
5767 [(set (match_operand:SI 0 "s_register_operand" "=r")
5768 (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
5769 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 5770 "TARGET_INT_SIMD"
a2cd141b 5771 "sxtab%?\\t%0, %2, %1"
d82e788e 5772 [(set_attr "type" "alu_shift_reg")
d952d547 5773 (set_attr "predicable" "yes")
5774 (set_attr "predicable_short_it" "no")]
a2cd141b 5775)
5776
ef51b8e1 5777(define_split
5778 [(set (match_operand:SI 0 "register_operand" "")
5779 (sign_extend:SI (match_operand:QI 1 "memory_operand" "")))]
5780 "TARGET_THUMB1 && reload_completed"
5781 [(set (match_dup 0) (match_dup 2))
5782 (set (match_dup 0) (sign_extend:SI (match_dup 3)))]
5783{
5784 rtx addr = XEXP (operands[1], 0);
cffb2a26 5785
ef51b8e1 5786 if (GET_CODE (addr) == CONST)
5787 addr = XEXP (addr, 0);
cffb2a26 5788
ef51b8e1 5789 if (GET_CODE (addr) == PLUS
5790 && REG_P (XEXP (addr, 0)) && REG_P (XEXP (addr, 1)))
5791 /* No split necessary. */
5792 FAIL;
5793
5794 if (GET_CODE (addr) == PLUS
5795 && !REG_P (XEXP (addr, 0)) && !REG_P (XEXP (addr, 1)))
5796 FAIL;
5797
5798 if (reg_overlap_mentioned_p (operands[0], addr))
5799 {
5800 rtx t = gen_lowpart (QImode, operands[0]);
5801 emit_move_insn (t, operands[1]);
5802 emit_insn (gen_thumb1_extendqisi2 (operands[0], t));
5803 DONE;
5804 }
5805
5806 if (REG_P (addr))
5807 {
5808 addr = gen_rtx_PLUS (Pmode, addr, operands[0]);
5809 operands[2] = const0_rtx;
5810 }
5811 else if (GET_CODE (addr) != PLUS)
5812 FAIL;
5813 else if (REG_P (XEXP (addr, 0)))
5814 {
5815 operands[2] = XEXP (addr, 1);
5816 addr = gen_rtx_PLUS (Pmode, XEXP (addr, 0), operands[0]);
5817 }
5818 else
5819 {
5820 operands[2] = XEXP (addr, 0);
5821 addr = gen_rtx_PLUS (Pmode, XEXP (addr, 1), operands[0]);
5822 }
cffb2a26 5823
ef51b8e1 5824 operands[3] = change_address (operands[1], QImode, addr);
5825})
5826
8a3b73a1 5827(define_peephole2
5828 [(set (match_operand:SI 0 "register_operand" "")
5829 (plus:SI (match_dup 0) (match_operand 1 "const_int_operand")))
5830 (set (match_operand:SI 2 "register_operand" "") (const_int 0))
5831 (set (match_operand:SI 3 "register_operand" "")
5832 (sign_extend:SI (match_operand:QI 4 "memory_operand" "")))]
5833 "TARGET_THUMB1
5834 && GET_CODE (XEXP (operands[4], 0)) == PLUS
5835 && rtx_equal_p (operands[0], XEXP (XEXP (operands[4], 0), 0))
5836 && rtx_equal_p (operands[2], XEXP (XEXP (operands[4], 0), 1))
5837 && (peep2_reg_dead_p (3, operands[0])
5838 || rtx_equal_p (operands[0], operands[3]))
5839 && (peep2_reg_dead_p (3, operands[2])
5840 || rtx_equal_p (operands[2], operands[3]))"
5841 [(set (match_dup 2) (match_dup 1))
5842 (set (match_dup 3) (sign_extend:SI (match_dup 4)))]
5843{
5844 rtx addr = gen_rtx_PLUS (Pmode, operands[0], operands[2]);
5845 operands[4] = change_address (operands[4], QImode, addr);
5846})
5847
ef51b8e1 5848(define_insn "thumb1_extendqisi2"
a2cd141b 5849 [(set (match_operand:SI 0 "register_operand" "=l,l,l")
5850 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
ef51b8e1 5851 "TARGET_THUMB1"
5852{
5853 rtx addr;
a2cd141b 5854
ef51b8e1 5855 if (which_alternative == 0 && arm_arch6)
5856 return "sxtb\\t%0, %1";
5857 if (which_alternative == 0)
5858 return "#";
a2cd141b 5859
ef51b8e1 5860 addr = XEXP (operands[1], 0);
5861 if (GET_CODE (addr) == PLUS
5862 && REG_P (XEXP (addr, 0)) && REG_P (XEXP (addr, 1)))
5863 return "ldrsb\\t%0, %1";
a2cd141b 5864
ef51b8e1 5865 return "#";
5866}
5867 [(set_attr_alternative "length"
5868 [(if_then_else (eq_attr "is_arch6" "yes")
5869 (const_int 2) (const_int 4))
5870 (const_int 2)
5871 (if_then_else (eq_attr "is_arch6" "yes")
5872 (const_int 4) (const_int 6))])
6b6abc9c 5873 (set_attr "type" "extend,load_byte,load_byte")]
a2cd141b 5874)
5875
caedf871 5876(define_expand "extendsfdf2"
5877 [(set (match_operand:DF 0 "s_register_operand" "")
5878 (float_extend:DF (match_operand:SF 1 "s_register_operand" "")))]
a50d7267 5879 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
caedf871 5880 ""
5881)
9b8516be 5882
5883/* HFmode -> DFmode conversions have to go through SFmode. */
5884(define_expand "extendhfdf2"
5885 [(set (match_operand:DF 0 "general_operand" "")
5886 (float_extend:DF (match_operand:HF 1 "general_operand" "")))]
5887 "TARGET_EITHER"
5888 "
5889 {
5890 rtx op1;
5891 op1 = convert_to_mode (SFmode, operands[1], 0);
5892 op1 = convert_to_mode (DFmode, op1, 0);
5893 emit_insn (gen_movdf (operands[0], op1));
5894 DONE;
5895 }"
5896)
b11cae9e 5897\f
5898;; Move insns (including loads and stores)
5899
5900;; XXX Just some ideas about movti.
9c08d1fa 5901;; I don't think these are a good idea on the arm, there just aren't enough
5902;; registers
b11cae9e 5903;;(define_expand "loadti"
9c08d1fa 5904;; [(set (match_operand:TI 0 "s_register_operand" "")
b11cae9e 5905;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
5906;; "" "")
5907
5908;;(define_expand "storeti"
5909;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
9c08d1fa 5910;; (match_operand:TI 1 "s_register_operand" ""))]
b11cae9e 5911;; "" "")
5912
5913;;(define_expand "movti"
5914;; [(set (match_operand:TI 0 "general_operand" "")
5915;; (match_operand:TI 1 "general_operand" ""))]
5916;; ""
5917;; "
5918;;{
5919;; rtx insn;
5920;;
0438d37f 5921;; if (MEM_P (operands[0]) && MEM_P (operands[1]))
b11cae9e 5922;; operands[1] = copy_to_reg (operands[1]);
0438d37f 5923;; if (MEM_P (operands[0]))
b11cae9e 5924;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
0438d37f 5925;; else if (MEM_P (operands[1]))
b11cae9e 5926;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
5927;; else
5928;; FAIL;
5929;;
5930;; emit_insn (insn);
5931;; DONE;
5932;;}")
5933
a2f10574 5934;; Recognize garbage generated above.
b11cae9e 5935
5936;;(define_insn ""
5937;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
5938;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
5939;; ""
5940;; "*
5941;; {
5942;; register mem = (which_alternative < 3);
0d66636f 5943;; register const char *template;
b11cae9e 5944;;
5945;; operands[mem] = XEXP (operands[mem], 0);
5946;; switch (which_alternative)
5947;; {
5948;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
5949;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
5950;; case 2: template = \"ldmia\\t%1, %M0\"; break;
5951;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
5952;; case 4: template = \"stmia\\t%0!, %M1\"; break;
5953;; case 5: template = \"stmia\\t%0, %M1\"; break;
5954;; }
e2348bcb 5955;; output_asm_insn (template, operands);
5956;; return \"\";
b11cae9e 5957;; }")
5958
cffb2a26 5959(define_expand "movdi"
5960 [(set (match_operand:DI 0 "general_operand" "")
5961 (match_operand:DI 1 "general_operand" ""))]
5962 "TARGET_EITHER"
5963 "
e1ba4a27 5964 if (can_create_pseudo_p ())
cffb2a26 5965 {
0438d37f 5966 if (!REG_P (operands[0]))
b2778788 5967 operands[1] = force_reg (DImode, operands[1]);
cffb2a26 5968 }
5969 "
5970)
b11cae9e 5971
cffb2a26 5972(define_insn "*arm_movdi"
353cf59a 5973 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, q, m")
5974 (match_operand:DI 1 "di_operand" "rDa,Db,Dc,mi,q"))]
cde1623a 5975 "TARGET_32BIT
b805622c 5976 && !(TARGET_HARD_FLOAT && TARGET_VFP)
b2778788 5977 && !TARGET_IWMMXT
5978 && ( register_operand (operands[0], DImode)
5979 || register_operand (operands[1], DImode))"
b11cae9e 5980 "*
d51f92df 5981 switch (which_alternative)
5982 {
5983 case 0:
5984 case 1:
5985 case 2:
5986 return \"#\";
5987 default:
26ff80c0 5988 return output_move_double (operands, true, NULL);
d51f92df 5989 }
cffb2a26 5990 "
359a6e9f 5991 [(set_attr "length" "8,12,16,8,8")
1b7da4ac 5992 (set_attr "type" "multiple,multiple,multiple,load2,store2")
cde1623a 5993 (set_attr "arm_pool_range" "*,*,*,1020,*")
8848d797 5994 (set_attr "arm_neg_pool_range" "*,*,*,1004,*")
42e1de19 5995 (set_attr "thumb2_pool_range" "*,*,*,4094,*")
cde1623a 5996 (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
cffb2a26 5997)
5998
d51f92df 5999(define_split
6000 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
6001 (match_operand:ANY64 1 "const_double_operand" ""))]
25f905c2 6002 "TARGET_32BIT
d51f92df 6003 && reload_completed
6004 && (arm_const_double_inline_cost (operands[1])
861033d5 6005 <= arm_max_const_double_inline_cost ())"
d51f92df 6006 [(const_int 0)]
6007 "
6008 arm_split_constant (SET, SImode, curr_insn,
6009 INTVAL (gen_lowpart (SImode, operands[1])),
6010 gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
6011 arm_split_constant (SET, SImode, curr_insn,
6012 INTVAL (gen_highpart_mode (SImode,
6013 GET_MODE (operands[0]),
6014 operands[1])),
6015 gen_highpart (SImode, operands[0]), NULL_RTX, 0);
6016 DONE;
6017 "
6018)
6019
e5ba9289 6020; If optimizing for size, or if we have load delay slots, then
6021; we want to split the constant into two separate operations.
6022; In both cases this may split a trivial part into a single data op
6023; leaving a single complex constant to load. We can also get longer
6024; offsets in a LDR which means we get better chances of sharing the pool
6025; entries. Finally, we can normally do a better job of scheduling
6026; LDR instructions than we can with LDM.
6027; This pattern will only match if the one above did not.
6028(define_split
6029 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
6030 (match_operand:ANY64 1 "const_double_operand" ""))]
6031 "TARGET_ARM && reload_completed
6032 && arm_const_double_by_parts (operands[1])"
6033 [(set (match_dup 0) (match_dup 1))
6034 (set (match_dup 2) (match_dup 3))]
6035 "
6036 operands[2] = gen_highpart (SImode, operands[0]);
6037 operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
6038 operands[1]);
6039 operands[0] = gen_lowpart (SImode, operands[0]);
6040 operands[1] = gen_lowpart (SImode, operands[1]);
6041 "
6042)
6043
d51f92df 6044(define_split
6045 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
6046 (match_operand:ANY64 1 "arm_general_register_operand" ""))]
6047 "TARGET_EITHER && reload_completed"
6048 [(set (match_dup 0) (match_dup 1))
6049 (set (match_dup 2) (match_dup 3))]
6050 "
6051 operands[2] = gen_highpart (SImode, operands[0]);
6052 operands[3] = gen_highpart (SImode, operands[1]);
6053 operands[0] = gen_lowpart (SImode, operands[0]);
6054 operands[1] = gen_lowpart (SImode, operands[1]);
6055
6056 /* Handle a partial overlap. */
6057 if (rtx_equal_p (operands[0], operands[3]))
6058 {
6059 rtx tmp0 = operands[0];
6060 rtx tmp1 = operands[1];
6061
6062 operands[0] = operands[2];
6063 operands[1] = operands[3];
6064 operands[2] = tmp0;
6065 operands[3] = tmp1;
6066 }
6067 "
6068)
6069
a8a3b539 6070;; We can't actually do base+index doubleword loads if the index and
6071;; destination overlap. Split here so that we at least have chance to
6072;; schedule.
6073(define_split
6074 [(set (match_operand:DI 0 "s_register_operand" "")
6075 (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
6076 (match_operand:SI 2 "s_register_operand" ""))))]
6077 "TARGET_LDRD
6078 && reg_overlap_mentioned_p (operands[0], operands[1])
6079 && reg_overlap_mentioned_p (operands[0], operands[2])"
6080 [(set (match_dup 4)
6081 (plus:SI (match_dup 1)
6082 (match_dup 2)))
6083 (set (match_dup 0)
6084 (mem:DI (match_dup 4)))]
6085 "
6086 operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
6087 "
6088)
6089
cffb2a26 6090;;; ??? This should have alternatives for constants.
6091;;; ??? This was originally identical to the movdf_insn pattern.
6092;;; ??? The 'i' constraint looks funny, but it should always be replaced by
6093;;; thumb_reorg with a memory reference.
25f905c2 6094(define_insn "*thumb1_movdi_insn"
215b30b3 6095 [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
6096 (match_operand:DI 1 "general_operand" "l, I,J,>,l,mi,l,*r"))]
25f905c2 6097 "TARGET_THUMB1
cffb2a26 6098 && ( register_operand (operands[0], DImode)
6099 || register_operand (operands[1], DImode))"
6100 "*
6101 {
6102 switch (which_alternative)
6103 {
6104 default:
6105 case 0:
6106 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
6107 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
6108 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
6109 case 1:
6110 return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
6111 case 2:
6112 operands[1] = GEN_INT (- INTVAL (operands[1]));
6113 return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
6114 case 3:
6115 return \"ldmia\\t%1, {%0, %H0}\";
6116 case 4:
6117 return \"stmia\\t%0, {%1, %H1}\";
6118 case 5:
6119 return thumb_load_double_from_address (operands);
6120 case 6:
1a83b3ff 6121 operands[2] = gen_rtx_MEM (SImode,
29c05e22 6122 plus_constant (Pmode, XEXP (operands[0], 0), 4));
cffb2a26 6123 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
6124 return \"\";
6125 case 7:
6126 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
6127 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
6128 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
6129 }
6130 }"
6131 [(set_attr "length" "4,4,6,2,2,6,4,4")
ad4fc3c0 6132 (set_attr "type" "multiple,multiple,multiple,load2,store2,load2,store2,multiple")
42e1de19 6133 (set_attr "pool_range" "*,*,*,*,*,1018,*,*")]
cffb2a26 6134)
b11cae9e 6135
9c08d1fa 6136(define_expand "movsi"
6137 [(set (match_operand:SI 0 "general_operand" "")
6138 (match_operand:SI 1 "general_operand" ""))]
cffb2a26 6139 "TARGET_EITHER"
9c08d1fa 6140 "
befb0bac 6141 {
e348ff3e 6142 rtx base, offset, tmp;
6143
25f905c2 6144 if (TARGET_32BIT)
9c08d1fa 6145 {
674a8f0b 6146 /* Everything except mem = const or mem = mem can be done easily. */
0438d37f 6147 if (MEM_P (operands[0]))
cffb2a26 6148 operands[1] = force_reg (SImode, operands[1]);
a2cd141b 6149 if (arm_general_register_operand (operands[0], SImode)
0438d37f 6150 && CONST_INT_P (operands[1])
cffb2a26 6151 && !(const_ok_for_arm (INTVAL (operands[1]))
6152 || const_ok_for_arm (~INTVAL (operands[1]))))
6153 {
96f57e36 6154 arm_split_constant (SET, SImode, NULL_RTX,
6155 INTVAL (operands[1]), operands[0], NULL_RTX,
e1ba4a27 6156 optimize && can_create_pseudo_p ());
cffb2a26 6157 DONE;
6158 }
6159 }
25f905c2 6160 else /* TARGET_THUMB1... */
cffb2a26 6161 {
e1ba4a27 6162 if (can_create_pseudo_p ())
cffb2a26 6163 {
0438d37f 6164 if (!REG_P (operands[0]))
cffb2a26 6165 operands[1] = force_reg (SImode, operands[1]);
6166 }
9c08d1fa 6167 }
f655717d 6168
e348ff3e 6169 if (ARM_OFFSETS_MUST_BE_WITHIN_SECTIONS_P)
6170 {
6171 split_const (operands[1], &base, &offset);
6172 if (GET_CODE (base) == SYMBOL_REF
6173 && !offset_within_block_p (base, INTVAL (offset)))
6174 {
b308ddcf 6175 tmp = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
e348ff3e 6176 emit_move_insn (tmp, base);
6177 emit_insn (gen_addsi3 (operands[0], tmp, offset));
6178 DONE;
6179 }
6180 }
6181
f655717d 6182 /* Recognize the case where operand[1] is a reference to thread-local
6183 data and load its address to a register. */
6184 if (arm_tls_referenced_p (operands[1]))
6185 {
6186 rtx tmp = operands[1];
6187 rtx addend = NULL;
6188
6189 if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
6190 {
6191 addend = XEXP (XEXP (tmp, 0), 1);
6192 tmp = XEXP (XEXP (tmp, 0), 0);
6193 }
6194
6195 gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
6196 gcc_assert (SYMBOL_REF_TLS_MODEL (tmp) != 0);
6197
e1ba4a27 6198 tmp = legitimize_tls_address (tmp,
6199 !can_create_pseudo_p () ? operands[0] : 0);
f655717d 6200 if (addend)
6201 {
6202 tmp = gen_rtx_PLUS (SImode, tmp, addend);
6203 tmp = force_operand (tmp, operands[0]);
6204 }
6205 operands[1] = tmp;
6206 }
6207 else if (flag_pic
6208 && (CONSTANT_P (operands[1])
6209 || symbol_mentioned_p (operands[1])
6210 || label_mentioned_p (operands[1])))
6211 operands[1] = legitimize_pic_address (operands[1], SImode,
e1ba4a27 6212 (!can_create_pseudo_p ()
6213 ? operands[0]
6214 : 0));
befb0bac 6215 }
215b30b3 6216 "
6217)
9c08d1fa 6218
d0e6a121 6219;; The ARM LO_SUM and HIGH are backwards - HIGH sets the low bits, and
6220;; LO_SUM adds in the high bits. Fortunately these are opaque operations
6221;; so this does not matter.
6222(define_insn "*arm_movt"
6223 [(set (match_operand:SI 0 "nonimmediate_operand" "=r")
6224 (lo_sum:SI (match_operand:SI 1 "nonimmediate_operand" "0")
6225 (match_operand:SI 2 "general_operand" "i")))]
c9b2ce40 6226 "arm_arch_thumb2"
d0e6a121 6227 "movt%?\t%0, #:upper16:%c2"
6228 [(set_attr "predicable" "yes")
d952d547 6229 (set_attr "predicable_short_it" "no")
1b7da4ac 6230 (set_attr "length" "4")
6231 (set_attr "type" "mov_imm")]
d0e6a121 6232)
6233
cffb2a26 6234(define_insn "*arm_movsi_insn"
aaa37ad6 6235 [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,rk,m")
110eae03 6236 (match_operand:SI 1 "general_operand" "rk, I,K,j,mi,rk"))]
755eb2b4 6237 "TARGET_ARM && ! TARGET_IWMMXT
a2cd141b 6238 && !(TARGET_HARD_FLOAT && TARGET_VFP)
cffb2a26 6239 && ( register_operand (operands[0], SImode)
6240 || register_operand (operands[1], SImode))"
f7fbdd4a 6241 "@
aaa37ad6 6242 mov%?\\t%0, %1
f7fbdd4a 6243 mov%?\\t%0, %1
6244 mvn%?\\t%0, #%B1
25f905c2 6245 movw%?\\t%0, %1
f7fbdd4a 6246 ldr%?\\t%0, %1
6247 str%?\\t%1, %0"
1aed5204 6248 [(set_attr "type" "mov_reg,mov_imm,mvn_imm,mov_imm,load1,store1")
0d66636f 6249 (set_attr "predicable" "yes")
aaa37ad6 6250 (set_attr "pool_range" "*,*,*,*,4096,*")
6251 (set_attr "neg_pool_range" "*,*,*,*,4084,*")]
cffb2a26 6252)
87b22bf7 6253
6254(define_split
a2cd141b 6255 [(set (match_operand:SI 0 "arm_general_register_operand" "")
87b22bf7 6256 (match_operand:SI 1 "const_int_operand" ""))]
25f905c2 6257 "TARGET_32BIT
215b30b3 6258 && (!(const_ok_for_arm (INTVAL (operands[1]))
6259 || const_ok_for_arm (~INTVAL (operands[1]))))"
87b22bf7 6260 [(clobber (const_int 0))]
6261 "
96f57e36 6262 arm_split_constant (SET, SImode, NULL_RTX,
6263 INTVAL (operands[1]), operands[0], NULL_RTX, 0);
87b22bf7 6264 DONE;
215b30b3 6265 "
6266)
9c08d1fa 6267
861033d5 6268;; A normal way to do (symbol + offset) requires three instructions at least
6269;; (depends on how big the offset is) as below:
6270;; movw r0, #:lower16:g
6271;; movw r0, #:upper16:g
6272;; adds r0, #4
6273;;
6274;; A better way would be:
6275;; movw r0, #:lower16:g+4
6276;; movw r0, #:upper16:g+4
6277;;
6278;; The limitation of this way is that the length of offset should be a 16-bit
6279;; signed value, because current assembler only supports REL type relocation for
6280;; such case. If the more powerful RELA type is supported in future, we should
6281;; update this pattern to go with better way.
6282(define_split
6283 [(set (match_operand:SI 0 "arm_general_register_operand" "")
6284 (const:SI (plus:SI (match_operand:SI 1 "general_operand" "")
6285 (match_operand:SI 2 "const_int_operand" ""))))]
6286 "TARGET_THUMB2
6287 && arm_disable_literal_pool
6288 && reload_completed
6289 && GET_CODE (operands[1]) == SYMBOL_REF"
6290 [(clobber (const_int 0))]
6291 "
6292 int offset = INTVAL (operands[2]);
6293
6294 if (offset < -0x8000 || offset > 0x7fff)
6295 {
6296 arm_emit_movpair (operands[0], operands[1]);
6297 emit_insn (gen_rtx_SET (SImode, operands[0],
6298 gen_rtx_PLUS (SImode, operands[0], operands[2])));
6299 }
6300 else
6301 {
6302 rtx op = gen_rtx_CONST (SImode,
6303 gen_rtx_PLUS (SImode, operands[1], operands[2]));
6304 arm_emit_movpair (operands[0], op);
6305 }
6306 "
6307)
6308
b8d5d078 6309;; Split symbol_refs at the later stage (after cprop), instead of generating
6310;; movt/movw pair directly at expand. Otherwise corresponding high_sum
6311;; and lo_sum would be merged back into memory load at cprop. However,
6312;; if the default is to prefer movt/movw rather than a load from the constant
6313;; pool, the performance is better.
6314(define_split
6315 [(set (match_operand:SI 0 "arm_general_register_operand" "")
6316 (match_operand:SI 1 "general_operand" ""))]
6317 "TARGET_32BIT
6318 && TARGET_USE_MOVT && GET_CODE (operands[1]) == SYMBOL_REF
6319 && !flag_pic && !target_word_relocations
6320 && !arm_tls_referenced_p (operands[1])"
6321 [(clobber (const_int 0))]
6322{
6323 arm_emit_movpair (operands[0], operands[1]);
6324 DONE;
6325})
6326
25f905c2 6327(define_insn "*thumb1_movsi_insn"
55a0d64c 6328 [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*l*h*k")
6329 (match_operand:SI 1 "general_operand" "l, I,J,K,>,l,mi,l,*l*h*k"))]
25f905c2 6330 "TARGET_THUMB1
cffb2a26 6331 && ( register_operand (operands[0], SImode)
6332 || register_operand (operands[1], SImode))"
6333 "@
6334 mov %0, %1
6335 mov %0, %1
6336 #
6337 #
6338 ldmia\\t%1, {%0}
6339 stmia\\t%0, {%1}
6340 ldr\\t%0, %1
6341 str\\t%1, %0
6342 mov\\t%0, %1"
6343 [(set_attr "length" "2,2,4,4,2,2,2,2,2")
1b7da4ac 6344 (set_attr "type" "mov_reg,mov_imm,multiple,multiple,load1,store1,load1,store1,mov_reg")
42e1de19 6345 (set_attr "pool_range" "*,*,*,*,*,*,1018,*,*")
747b7458 6346 (set_attr "conds" "set,clob,*,*,nocond,nocond,nocond,nocond,nocond")])
cffb2a26 6347
6348(define_split
6349 [(set (match_operand:SI 0 "register_operand" "")
6350 (match_operand:SI 1 "const_int_operand" ""))]
25f905c2 6351 "TARGET_THUMB1 && satisfies_constraint_J (operands[1])"
1276f1b8 6352 [(set (match_dup 2) (match_dup 1))
6353 (set (match_dup 0) (neg:SI (match_dup 2)))]
6354 "
6355 {
6356 operands[1] = GEN_INT (- INTVAL (operands[1]));
6357 operands[2] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
6358 }"
cffb2a26 6359)
6360
6361(define_split
6362 [(set (match_operand:SI 0 "register_operand" "")
6363 (match_operand:SI 1 "const_int_operand" ""))]
25f905c2 6364 "TARGET_THUMB1 && satisfies_constraint_K (operands[1])"
1276f1b8 6365 [(set (match_dup 2) (match_dup 1))
6366 (set (match_dup 0) (ashift:SI (match_dup 2) (match_dup 3)))]
cffb2a26 6367 "
6368 {
e4aeee53 6369 unsigned HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffffffffu;
cffb2a26 6370 unsigned HOST_WIDE_INT mask = 0xff;
6371 int i;
6372
6373 for (i = 0; i < 25; i++)
6374 if ((val & (mask << i)) == val)
6375 break;
6376
1276f1b8 6377 /* Don't split if the shift is zero. */
cffb2a26 6378 if (i == 0)
6379 FAIL;
6380
6381 operands[1] = GEN_INT (val >> i);
1276f1b8 6382 operands[2] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
6383 operands[3] = GEN_INT (i);
cffb2a26 6384 }"
6385)
6386
c5b75283 6387;; For thumb1 split imm move [256-510] into mov [1-255] and add #255
6388(define_split
6389 [(set (match_operand:SI 0 "register_operand" "")
6390 (match_operand:SI 1 "const_int_operand" ""))]
6391 "TARGET_THUMB1 && satisfies_constraint_Pe (operands[1])"
6392 [(set (match_dup 2) (match_dup 1))
6393 (set (match_dup 0) (plus:SI (match_dup 2) (match_dup 3)))]
6394 "
6395 {
6396 operands[1] = GEN_INT (INTVAL (operands[1]) - 255);
6397 operands[2] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
6398 operands[3] = GEN_INT (255);
6399 }"
6400)
6401
67336bcf 6402;; When generating pic, we need to load the symbol offset into a register.
6403;; So that the optimizer does not confuse this with a normal symbol load
6404;; we use an unspec. The offset will be loaded from a constant pool entry,
6405;; since that is the only type of relocation we can use.
6406
94f8caca 6407;; Wrap calculation of the whole PIC address in a single pattern for the
6408;; benefit of optimizers, particularly, PRE and HOIST. Calculation of
6409;; a PIC address involves two loads from memory, so we want to CSE it
6410;; as often as possible.
6411;; This pattern will be split into one of the pic_load_addr_* patterns
6412;; and a move after GCSE optimizations.
6413;;
6414;; Note: Update arm.c: legitimize_pic_address() when changing this pattern.
6415(define_expand "calculate_pic_address"
6416 [(set (match_operand:SI 0 "register_operand" "")
6417 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "")
6418 (unspec:SI [(match_operand:SI 2 "" "")]
6419 UNSPEC_PIC_SYM))))]
6420 "flag_pic"
6421)
6422
6423;; Split calculate_pic_address into pic_load_addr_* and a move.
6424(define_split
6425 [(set (match_operand:SI 0 "register_operand" "")
6426 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "")
6427 (unspec:SI [(match_operand:SI 2 "" "")]
6428 UNSPEC_PIC_SYM))))]
6429 "flag_pic"
6430 [(set (match_dup 3) (unspec:SI [(match_dup 2)] UNSPEC_PIC_SYM))
6431 (set (match_dup 0) (mem:SI (plus:SI (match_dup 1) (match_dup 3))))]
6432 "operands[3] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];"
6433)
6434
350ccca5 6435;; operand1 is the memory address to go into
6436;; pic_load_addr_32bit.
6437;; operand2 is the PIC label to be emitted
6438;; from pic_add_dot_plus_eight.
6439;; We do this to allow hoisting of the entire insn.
6440(define_insn_and_split "pic_load_addr_unified"
6441 [(set (match_operand:SI 0 "s_register_operand" "=r,r,l")
6442 (unspec:SI [(match_operand:SI 1 "" "mX,mX,mX")
6443 (match_operand:SI 2 "" "")]
6444 UNSPEC_PIC_UNIFIED))]
6445 "flag_pic"
6446 "#"
6447 "&& reload_completed"
6448 [(set (match_dup 0) (unspec:SI [(match_dup 1)] UNSPEC_PIC_SYM))
6449 (set (match_dup 0) (unspec:SI [(match_dup 0) (match_dup 3)
6450 (match_dup 2)] UNSPEC_PIC_BASE))]
6451 "operands[3] = TARGET_THUMB ? GEN_INT (4) : GEN_INT (8);"
6452 [(set_attr "type" "load1,load1,load1")
42e1de19 6453 (set_attr "pool_range" "4096,4094,1022")
350ccca5 6454 (set_attr "neg_pool_range" "4084,0,0")
6455 (set_attr "arch" "a,t2,t1")
6456 (set_attr "length" "8,6,4")]
6457)
6458
67336bcf 6459;; The rather odd constraints on the following are to force reload to leave
6460;; the insn alone, and to force the minipool generation pass to then move
6461;; the GOT symbol to memory.
849170fd 6462
b3cd5f55 6463(define_insn "pic_load_addr_32bit"
849170fd 6464 [(set (match_operand:SI 0 "s_register_operand" "=r")
e1159bbe 6465 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
b3cd5f55 6466 "TARGET_32BIT && flag_pic"
67336bcf 6467 "ldr%?\\t%0, %1"
a2cd141b 6468 [(set_attr "type" "load1")
42e1de19 6469 (set (attr "pool_range")
6470 (if_then_else (eq_attr "is_thumb" "no")
6471 (const_int 4096)
6472 (const_int 4094)))
b3cd5f55 6473 (set (attr "neg_pool_range")
6474 (if_then_else (eq_attr "is_thumb" "no")
6475 (const_int 4084)
6476 (const_int 0)))]
8c4d8060 6477)
6478
25f905c2 6479(define_insn "pic_load_addr_thumb1"
8c4d8060 6480 [(set (match_operand:SI 0 "s_register_operand" "=l")
e1159bbe 6481 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
25f905c2 6482 "TARGET_THUMB1 && flag_pic"
8c4d8060 6483 "ldr\\t%0, %1"
a2cd141b 6484 [(set_attr "type" "load1")
42e1de19 6485 (set (attr "pool_range") (const_int 1018))]
cffb2a26 6486)
849170fd 6487
cffb2a26 6488(define_insn "pic_add_dot_plus_four"
15d5d060 6489 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 6490 (unspec:SI [(match_operand:SI 1 "register_operand" "0")
6491 (const_int 4)
beef0fb5 6492 (match_operand 2 "" "")]
6493 UNSPEC_PIC_BASE))]
b3cd5f55 6494 "TARGET_THUMB"
cffb2a26 6495 "*
6cdcb15c 6496 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
6497 INTVAL (operands[2]));
cffb2a26 6498 return \"add\\t%0, %|pc\";
6499 "
1b7da4ac 6500 [(set_attr "length" "2")
6501 (set_attr "type" "alu_reg")]
cffb2a26 6502)
849170fd 6503
6504(define_insn "pic_add_dot_plus_eight"
15d5d060 6505 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 6506 (unspec:SI [(match_operand:SI 1 "register_operand" "r")
6507 (const_int 8)
beef0fb5 6508 (match_operand 2 "" "")]
6509 UNSPEC_PIC_BASE))]
f655717d 6510 "TARGET_ARM"
c4034607 6511 "*
6cdcb15c 6512 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
6513 INTVAL (operands[2]));
15d5d060 6514 return \"add%?\\t%0, %|pc, %1\";
cffb2a26 6515 "
1b7da4ac 6516 [(set_attr "predicable" "yes")
6517 (set_attr "type" "alu_reg")]
cffb2a26 6518)
849170fd 6519
f655717d 6520(define_insn "tls_load_dot_plus_eight"
cc071db6 6521 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 6522 (mem:SI (unspec:SI [(match_operand:SI 1 "register_operand" "r")
6523 (const_int 8)
beef0fb5 6524 (match_operand 2 "" "")]
6525 UNSPEC_PIC_BASE)))]
f655717d 6526 "TARGET_ARM"
6527 "*
6cdcb15c 6528 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
6529 INTVAL (operands[2]));
f655717d 6530 return \"ldr%?\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_eight\";
6531 "
1b7da4ac 6532 [(set_attr "predicable" "yes")
6533 (set_attr "type" "load1")]
f655717d 6534)
6535
6536;; PIC references to local variables can generate pic_add_dot_plus_eight
6537;; followed by a load. These sequences can be crunched down to
6538;; tls_load_dot_plus_eight by a peephole.
6539
6540(define_peephole2
c0c1fba5 6541 [(set (match_operand:SI 0 "register_operand" "")
6542 (unspec:SI [(match_operand:SI 3 "register_operand" "")
6543 (const_int 8)
6544 (match_operand 1 "" "")]
6545 UNSPEC_PIC_BASE))
2d05dfad 6546 (set (match_operand:SI 2 "arm_general_register_operand" "")
6547 (mem:SI (match_dup 0)))]
f655717d 6548 "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
c0c1fba5 6549 [(set (match_dup 2)
6550 (mem:SI (unspec:SI [(match_dup 3)
6551 (const_int 8)
6552 (match_dup 1)]
6553 UNSPEC_PIC_BASE)))]
f655717d 6554 ""
6555)
6556
bac7fc85 6557(define_insn "pic_offset_arm"
6558 [(set (match_operand:SI 0 "register_operand" "=r")
6559 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
6560 (unspec:SI [(match_operand:SI 2 "" "X")]
6561 UNSPEC_PIC_OFFSET))))]
6562 "TARGET_VXWORKS_RTP && TARGET_ARM && flag_pic"
6563 "ldr%?\\t%0, [%1,%2]"
6564 [(set_attr "type" "load1")]
6565)
6566
95373f08 6567(define_expand "builtin_setjmp_receiver"
6568 [(label_ref (match_operand 0 "" ""))]
6569 "flag_pic"
6570 "
6571{
b935b306 6572 /* r3 is clobbered by set/longjmp, so we can use it as a scratch
6573 register. */
2cb7d577 6574 if (arm_pic_register != INVALID_REGNUM)
6575 arm_load_pic_register (1UL << 3);
95373f08 6576 DONE;
6577}")
6578
9c08d1fa 6579;; If copying one reg to another we can set the condition codes according to
6580;; its value. Such a move is common after a return from subroutine and the
6581;; result is being tested against zero.
6582
f7fbdd4a 6583(define_insn "*movsi_compare0"
bd5b4116 6584 [(set (reg:CC CC_REGNUM)
cffb2a26 6585 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
6586 (const_int 0)))
6587 (set (match_operand:SI 0 "s_register_operand" "=r,r")
6588 (match_dup 1))]
25f905c2 6589 "TARGET_32BIT"
e2348bcb 6590 "@
40dbec34 6591 cmp%?\\t%0, #0
25f905c2 6592 sub%.\\t%0, %1, #0"
65f68e55 6593 [(set_attr "conds" "set")
d82e788e 6594 (set_attr "type" "alus_imm,alus_imm")]
cffb2a26 6595)
b11cae9e 6596
b11cae9e 6597;; Subroutine to store a half word from a register into memory.
6598;; Operand 0 is the source register (HImode)
c8f69309 6599;; Operand 1 is the destination address in a register (SImode)
b11cae9e 6600
9c08d1fa 6601;; In both this routine and the next, we must be careful not to spill
01cc3b75 6602;; a memory address of reg+large_const into a separate PLUS insn, since this
9c08d1fa 6603;; can generate unrecognizable rtl.
6604
b11cae9e 6605(define_expand "storehi"
c8f69309 6606 [;; store the low byte
f082f1c4 6607 (set (match_operand 1 "" "") (match_dup 3))
b11cae9e 6608 ;; extract the high byte
c8f69309 6609 (set (match_dup 2)
6610 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
b11cae9e 6611 ;; store the high byte
787f8210 6612 (set (match_dup 4) (match_dup 5))]
cffb2a26 6613 "TARGET_ARM"
b11cae9e 6614 "
215b30b3 6615 {
537ffcfc 6616 rtx op1 = operands[1];
6617 rtx addr = XEXP (op1, 0);
215b30b3 6618 enum rtx_code code = GET_CODE (addr);
6619
0438d37f 6620 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
215b30b3 6621 || code == MINUS)
537ffcfc 6622 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
215b30b3 6623
537ffcfc 6624 operands[4] = adjust_address (op1, QImode, 1);
e513d163 6625 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 6626 operands[3] = gen_lowpart (QImode, operands[0]);
6627 operands[0] = gen_lowpart (SImode, operands[0]);
787f8210 6628 operands[2] = gen_reg_rtx (SImode);
6629 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 6630 }"
6631)
b11cae9e 6632
c7597b5d 6633(define_expand "storehi_bigend"
f082f1c4 6634 [(set (match_dup 4) (match_dup 3))
c7597b5d 6635 (set (match_dup 2)
6636 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
787f8210 6637 (set (match_operand 1 "" "") (match_dup 5))]
cffb2a26 6638 "TARGET_ARM"
b11cae9e 6639 "
215b30b3 6640 {
537ffcfc 6641 rtx op1 = operands[1];
6642 rtx addr = XEXP (op1, 0);
215b30b3 6643 enum rtx_code code = GET_CODE (addr);
6644
0438d37f 6645 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
215b30b3 6646 || code == MINUS)
537ffcfc 6647 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
215b30b3 6648
537ffcfc 6649 operands[4] = adjust_address (op1, QImode, 1);
e513d163 6650 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 6651 operands[3] = gen_lowpart (QImode, operands[0]);
6652 operands[0] = gen_lowpart (SImode, operands[0]);
6653 operands[2] = gen_reg_rtx (SImode);
787f8210 6654 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 6655 }"
6656)
c7597b5d 6657
6658;; Subroutine to store a half word integer constant into memory.
6659(define_expand "storeinthi"
f082f1c4 6660 [(set (match_operand 0 "" "")
787f8210 6661 (match_operand 1 "" ""))
9e8503e6 6662 (set (match_dup 3) (match_dup 2))]
cffb2a26 6663 "TARGET_ARM"
c7597b5d 6664 "
215b30b3 6665 {
6666 HOST_WIDE_INT value = INTVAL (operands[1]);
6667 rtx addr = XEXP (operands[0], 0);
537ffcfc 6668 rtx op0 = operands[0];
215b30b3 6669 enum rtx_code code = GET_CODE (addr);
c7597b5d 6670
0438d37f 6671 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
215b30b3 6672 || code == MINUS)
537ffcfc 6673 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
c7597b5d 6674
215b30b3 6675 operands[1] = gen_reg_rtx (SImode);
6676 if (BYTES_BIG_ENDIAN)
6677 {
6678 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
6679 if ((value & 255) == ((value >> 8) & 255))
6680 operands[2] = operands[1];
6681 else
6682 {
6683 operands[2] = gen_reg_rtx (SImode);
6684 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
6685 }
6686 }
6687 else
6688 {
6689 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
6690 if ((value & 255) == ((value >> 8) & 255))
6691 operands[2] = operands[1];
6692 else
6693 {
6694 operands[2] = gen_reg_rtx (SImode);
6695 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
6696 }
6697 }
c7597b5d 6698
537ffcfc 6699 operands[3] = adjust_address (op0, QImode, 1);
e513d163 6700 operands[0] = adjust_address (operands[0], QImode, 0);
9e8503e6 6701 operands[2] = gen_lowpart (QImode, operands[2]);
787f8210 6702 operands[1] = gen_lowpart (QImode, operands[1]);
215b30b3 6703 }"
6704)
b11cae9e 6705
f7fbdd4a 6706(define_expand "storehi_single_op"
6707 [(set (match_operand:HI 0 "memory_operand" "")
6708 (match_operand:HI 1 "general_operand" ""))]
25f905c2 6709 "TARGET_32BIT && arm_arch4"
f7fbdd4a 6710 "
215b30b3 6711 if (!s_register_operand (operands[1], HImode))
f7fbdd4a 6712 operands[1] = copy_to_mode_reg (HImode, operands[1]);
215b30b3 6713 "
6714)
f7fbdd4a 6715
b11cae9e 6716(define_expand "movhi"
6717 [(set (match_operand:HI 0 "general_operand" "")
c8f69309 6718 (match_operand:HI 1 "general_operand" ""))]
cffb2a26 6719 "TARGET_EITHER"
b11cae9e 6720 "
cffb2a26 6721 if (TARGET_ARM)
b11cae9e 6722 {
e1ba4a27 6723 if (can_create_pseudo_p ())
cffb2a26 6724 {
0438d37f 6725 if (MEM_P (operands[0]))
b11cae9e 6726 {
cffb2a26 6727 if (arm_arch4)
6728 {
6729 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
6730 DONE;
6731 }
0438d37f 6732 if (CONST_INT_P (operands[1]))
cffb2a26 6733 emit_insn (gen_storeinthi (operands[0], operands[1]));
c7597b5d 6734 else
cffb2a26 6735 {
0438d37f 6736 if (MEM_P (operands[1]))
cffb2a26 6737 operands[1] = force_reg (HImode, operands[1]);
6738 if (BYTES_BIG_ENDIAN)
6739 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
6740 else
6741 emit_insn (gen_storehi (operands[1], operands[0]));
6742 }
6743 DONE;
b11cae9e 6744 }
cffb2a26 6745 /* Sign extend a constant, and keep it in an SImode reg. */
0438d37f 6746 else if (CONST_INT_P (operands[1]))
9c08d1fa 6747 {
cffb2a26 6748 rtx reg = gen_reg_rtx (SImode);
6749 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
6750
6751 /* If the constant is already valid, leave it alone. */
215b30b3 6752 if (!const_ok_for_arm (val))
cffb2a26 6753 {
6754 /* If setting all the top bits will make the constant
6755 loadable in a single instruction, then set them.
6756 Otherwise, sign extend the number. */
6757
215b30b3 6758 if (const_ok_for_arm (~(val | ~0xffff)))
cffb2a26 6759 val |= ~0xffff;
6760 else if (val & 0x8000)
6761 val |= ~0xffff;
6762 }
6763
6764 emit_insn (gen_movsi (reg, GEN_INT (val)));
9e8503e6 6765 operands[1] = gen_lowpart (HImode, reg);
9c08d1fa 6766 }
e1ba4a27 6767 else if (arm_arch4 && optimize && can_create_pseudo_p ()
0438d37f 6768 && MEM_P (operands[1]))
0045890a 6769 {
6770 rtx reg = gen_reg_rtx (SImode);
6771
6772 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
6773 operands[1] = gen_lowpart (HImode, reg);
6774 }
215b30b3 6775 else if (!arm_arch4)
f7fbdd4a 6776 {
0438d37f 6777 if (MEM_P (operands[1]))
cffb2a26 6778 {
c1a66faf 6779 rtx base;
6780 rtx offset = const0_rtx;
6781 rtx reg = gen_reg_rtx (SImode);
6782
0438d37f 6783 if ((REG_P (base = XEXP (operands[1], 0))
c1a66faf 6784 || (GET_CODE (base) == PLUS
0438d37f 6785 && (CONST_INT_P (offset = XEXP (base, 1)))
c1a66faf 6786 && ((INTVAL(offset) & 1) != 1)
0438d37f 6787 && REG_P (base = XEXP (base, 0))))
c1a66faf 6788 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
206ee9a2 6789 {
8deb3959 6790 rtx new_rtx;
c1a66faf 6791
8deb3959 6792 new_rtx = widen_memory_access (operands[1], SImode,
6793 ((INTVAL (offset) & ~3)
6794 - INTVAL (offset)));
6795 emit_insn (gen_movsi (reg, new_rtx));
c1a66faf 6796 if (((INTVAL (offset) & 2) != 0)
6797 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
6798 {
6799 rtx reg2 = gen_reg_rtx (SImode);
6800
6801 emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
6802 reg = reg2;
6803 }
206ee9a2 6804 }
c1a66faf 6805 else
6806 emit_insn (gen_movhi_bytes (reg, operands[1]));
6807
6808 operands[1] = gen_lowpart (HImode, reg);
cffb2a26 6809 }
6810 }
6811 }
674a8f0b 6812 /* Handle loading a large integer during reload. */
0438d37f 6813 else if (CONST_INT_P (operands[1])
215b30b3 6814 && !const_ok_for_arm (INTVAL (operands[1]))
6815 && !const_ok_for_arm (~INTVAL (operands[1])))
cffb2a26 6816 {
6817 /* Writing a constant to memory needs a scratch, which should
6818 be handled with SECONDARY_RELOADs. */
0438d37f 6819 gcc_assert (REG_P (operands[0]));
cffb2a26 6820
6821 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
6822 emit_insn (gen_movsi (operands[0], operands[1]));
6823 DONE;
6824 }
6825 }
25f905c2 6826 else if (TARGET_THUMB2)
6827 {
6828 /* Thumb-2 can do everything except mem=mem and mem=const easily. */
e1ba4a27 6829 if (can_create_pseudo_p ())
25f905c2 6830 {
0438d37f 6831 if (!REG_P (operands[0]))
25f905c2 6832 operands[1] = force_reg (HImode, operands[1]);
6833 /* Zero extend a constant, and keep it in an SImode reg. */
0438d37f 6834 else if (CONST_INT_P (operands[1]))
25f905c2 6835 {
6836 rtx reg = gen_reg_rtx (SImode);
6837 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
6838
6839 emit_insn (gen_movsi (reg, GEN_INT (val)));
6840 operands[1] = gen_lowpart (HImode, reg);
6841 }
6842 }
6843 }
6844 else /* TARGET_THUMB1 */
cffb2a26 6845 {
e1ba4a27 6846 if (can_create_pseudo_p ())
cffb2a26 6847 {
0438d37f 6848 if (CONST_INT_P (operands[1]))
6cffc037 6849 {
6850 rtx reg = gen_reg_rtx (SImode);
6851
6852 emit_insn (gen_movsi (reg, operands[1]));
6853 operands[1] = gen_lowpart (HImode, reg);
6854 }
cffb2a26 6855
6856 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 6857 happen if we are passed a SP (never OK for HImode/QImode) or
bc409cb4 6858 virtual register (also rejected as illegitimate for HImode/QImode)
6859 relative address. */
cffb2a26 6860 /* ??? This should perhaps be fixed elsewhere, for instance, in
6861 fixup_stack_1, by checking for other kinds of invalid addresses,
6862 e.g. a bare reference to a virtual register. This may confuse the
6863 alpha though, which must handle this case differently. */
0438d37f 6864 if (MEM_P (operands[0])
215b30b3 6865 && !memory_address_p (GET_MODE (operands[0]),
6866 XEXP (operands[0], 0)))
537ffcfc 6867 operands[0]
6868 = replace_equiv_address (operands[0],
6869 copy_to_reg (XEXP (operands[0], 0)));
cffb2a26 6870
0438d37f 6871 if (MEM_P (operands[1])
215b30b3 6872 && !memory_address_p (GET_MODE (operands[1]),
6873 XEXP (operands[1], 0)))
537ffcfc 6874 operands[1]
6875 = replace_equiv_address (operands[1],
6876 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 6877
0438d37f 6878 if (MEM_P (operands[1]) && optimize > 0)
6cffc037 6879 {
6880 rtx reg = gen_reg_rtx (SImode);
6881
6882 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
6883 operands[1] = gen_lowpart (HImode, reg);
6884 }
6885
0438d37f 6886 if (MEM_P (operands[0]))
6cffc037 6887 operands[1] = force_reg (HImode, operands[1]);
cffb2a26 6888 }
0438d37f 6889 else if (CONST_INT_P (operands[1])
234f6557 6890 && !satisfies_constraint_I (operands[1]))
cffb2a26 6891 {
6cffc037 6892 /* Handle loading a large integer during reload. */
6893
cffb2a26 6894 /* Writing a constant to memory needs a scratch, which should
6895 be handled with SECONDARY_RELOADs. */
0438d37f 6896 gcc_assert (REG_P (operands[0]));
cffb2a26 6897
1a83b3ff 6898 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
cffb2a26 6899 emit_insn (gen_movsi (operands[0], operands[1]));
6900 DONE;
6901 }
b11cae9e 6902 }
cffb2a26 6903 "
6904)
6905
25f905c2 6906(define_insn "*thumb1_movhi_insn"
a941568e 6907 [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
6908 (match_operand:HI 1 "general_operand" "l,m,l,*h,*r,I"))]
25f905c2 6909 "TARGET_THUMB1
cffb2a26 6910 && ( register_operand (operands[0], HImode)
6911 || register_operand (operands[1], HImode))"
6912 "*
6913 switch (which_alternative)
d79300ac 6914 {
cffb2a26 6915 case 0: return \"add %0, %1, #0\";
6916 case 2: return \"strh %1, %0\";
6917 case 3: return \"mov %0, %1\";
6918 case 4: return \"mov %0, %1\";
6919 case 5: return \"mov %0, %1\";
ed29c566 6920 default: gcc_unreachable ();
cffb2a26 6921 case 1:
6922 /* The stack pointer can end up being taken as an index register.
6923 Catch this case here and deal with it. */
6924 if (GET_CODE (XEXP (operands[1], 0)) == PLUS
0438d37f 6925 && REG_P (XEXP (XEXP (operands[1], 0), 0))
cffb2a26 6926 && REGNO (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
6927 {
6928 rtx ops[2];
6929 ops[0] = operands[0];
6930 ops[1] = XEXP (XEXP (operands[1], 0), 0);
6931
6932 output_asm_insn (\"mov %0, %1\", ops);
6933
6934 XEXP (XEXP (operands[1], 0), 0) = operands[0];
6935
6936 }
6937 return \"ldrh %0, %1\";
6938 }"
6939 [(set_attr "length" "2,4,2,2,2,2")
1b7da4ac 6940 (set_attr "type" "alus_imm,load1,store1,mov_reg,mov_reg,mov_imm")
747b7458 6941 (set_attr "conds" "clob,nocond,nocond,nocond,nocond,clob")])
d79300ac 6942
b11cae9e 6943
25f7a26e 6944(define_expand "movhi_bytes"
eab14235 6945 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 6946 (set (match_dup 3)
eab14235 6947 (zero_extend:SI (match_dup 6)))
25f7a26e 6948 (set (match_operand:SI 0 "" "")
6949 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
cffb2a26 6950 "TARGET_ARM"
25f7a26e 6951 "
215b30b3 6952 {
6953 rtx mem1, mem2;
6954 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
6955
788fcce0 6956 mem1 = change_address (operands[1], QImode, addr);
29c05e22 6957 mem2 = change_address (operands[1], QImode,
6958 plus_constant (Pmode, addr, 1));
215b30b3 6959 operands[0] = gen_lowpart (SImode, operands[0]);
6960 operands[1] = mem1;
6961 operands[2] = gen_reg_rtx (SImode);
6962 operands[3] = gen_reg_rtx (SImode);
6963 operands[6] = mem2;
25f7a26e 6964
215b30b3 6965 if (BYTES_BIG_ENDIAN)
6966 {
6967 operands[4] = operands[2];
6968 operands[5] = operands[3];
6969 }
6970 else
6971 {
6972 operands[4] = operands[3];
6973 operands[5] = operands[2];
6974 }
6975 }"
6976)
25f7a26e 6977
c7597b5d 6978(define_expand "movhi_bigend"
6979 [(set (match_dup 2)
6980 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
6981 (const_int 16)))
6982 (set (match_dup 3)
6983 (ashiftrt:SI (match_dup 2) (const_int 16)))
6984 (set (match_operand:HI 0 "s_register_operand" "")
787f8210 6985 (match_dup 4))]
cffb2a26 6986 "TARGET_ARM"
c7597b5d 6987 "
6988 operands[2] = gen_reg_rtx (SImode);
6989 operands[3] = gen_reg_rtx (SImode);
787f8210 6990 operands[4] = gen_lowpart (HImode, operands[3]);
215b30b3 6991 "
6992)
b11cae9e 6993
a2f10574 6994;; Pattern to recognize insn generated default case above
f7fbdd4a 6995(define_insn "*movhi_insn_arch4"
cde1623a 6996 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
85e02ccb 6997 (match_operand:HI 1 "general_operand" "rI,K,r,mi"))]
cffb2a26 6998 "TARGET_ARM
6999 && arm_arch4
85e02ccb 7000 && (register_operand (operands[0], HImode)
7001 || register_operand (operands[1], HImode))"
f7fbdd4a 7002 "@
7003 mov%?\\t%0, %1\\t%@ movhi
7004 mvn%?\\t%0, #%B1\\t%@ movhi
25f905c2 7005 str%(h%)\\t%1, %0\\t%@ movhi
7006 ldr%(h%)\\t%0, %1\\t%@ movhi"
65f68e55 7007 [(set_attr "predicable" "yes")
cffb2a26 7008 (set_attr "pool_range" "*,*,*,256")
65f68e55 7009 (set_attr "neg_pool_range" "*,*,*,244")
7010 (set_attr_alternative "type"
7011 [(if_then_else (match_operand 1 "const_int_operand" "")
1aed5204 7012 (const_string "mov_imm" )
7013 (const_string "mov_reg"))
7014 (const_string "mvn_imm")
65f68e55 7015 (const_string "store1")
7016 (const_string "load1")])]
cffb2a26 7017)
f7fbdd4a 7018
f7fbdd4a 7019(define_insn "*movhi_bytes"
65f68e55 7020 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
7021 (match_operand:HI 1 "arm_rhs_operand" "I,r,K"))]
c1a66faf 7022 "TARGET_ARM"
25f7a26e 7023 "@
65f68e55 7024 mov%?\\t%0, %1\\t%@ movhi
25f7a26e 7025 mov%?\\t%0, %1\\t%@ movhi
0d66636f 7026 mvn%?\\t%0, #%B1\\t%@ movhi"
d2a518d1 7027 [(set_attr "predicable" "yes")
1aed5204 7028 (set_attr "type" "mov_imm,mov_reg,mvn_imm")]
0d66636f 7029)
25f7a26e 7030
f90b51f1 7031(define_expand "thumb_movhi_clobber"
7032 [(set (match_operand:HI 0 "memory_operand" "")
7033 (match_operand:HI 1 "register_operand" ""))
7034 (clobber (match_operand:DI 2 "register_operand" ""))]
25f905c2 7035 "TARGET_THUMB1"
f90b51f1 7036 "
7037 if (strict_memory_address_p (HImode, XEXP (operands[0], 0))
7038 && REGNO (operands[1]) <= LAST_LO_REGNUM)
7039 {
7040 emit_insn (gen_movhi (operands[0], operands[1]));
7041 DONE;
7042 }
7043 /* XXX Fixme, need to handle other cases here as well. */
7044 gcc_unreachable ();
7045 "
cffb2a26 7046)
7047
bc5c7e08 7048;; We use a DImode scratch because we may occasionally need an additional
7049;; temporary if the address isn't offsettable -- push_reload doesn't seem
7050;; to take any notice of the "o" constraints on reload_memory_operand operand.
d3373b54 7051(define_expand "reload_outhi"
cffb2a26 7052 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
215b30b3 7053 (match_operand:HI 1 "s_register_operand" "r")
7054 (match_operand:DI 2 "s_register_operand" "=&l")])]
cffb2a26 7055 "TARGET_EITHER"
7056 "if (TARGET_ARM)
7057 arm_reload_out_hi (operands);
7058 else
7059 thumb_reload_out_hi (operands);
d3373b54 7060 DONE;
cffb2a26 7061 "
7062)
d3373b54 7063
25f7a26e 7064(define_expand "reload_inhi"
7065 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
cffb2a26 7066 (match_operand:HI 1 "arm_reload_memory_operand" "o")
bc5c7e08 7067 (match_operand:DI 2 "s_register_operand" "=&r")])]
c1a66faf 7068 "TARGET_EITHER"
25f7a26e 7069 "
cffb2a26 7070 if (TARGET_ARM)
7071 arm_reload_in_hi (operands);
7072 else
7073 thumb_reload_out_hi (operands);
25f7a26e 7074 DONE;
7075")
7076
9c08d1fa 7077(define_expand "movqi"
7078 [(set (match_operand:QI 0 "general_operand" "")
7079 (match_operand:QI 1 "general_operand" ""))]
cffb2a26 7080 "TARGET_EITHER"
9c08d1fa 7081 "
6cffc037 7082 /* Everything except mem = const or mem = mem can be done easily */
0045890a 7083
e1ba4a27 7084 if (can_create_pseudo_p ())
cffb2a26 7085 {
0438d37f 7086 if (CONST_INT_P (operands[1]))
6cffc037 7087 {
7088 rtx reg = gen_reg_rtx (SImode);
7089
03770691 7090 /* For thumb we want an unsigned immediate, then we are more likely
7091 to be able to use a movs insn. */
7092 if (TARGET_THUMB)
7093 operands[1] = GEN_INT (INTVAL (operands[1]) & 255);
7094
6cffc037 7095 emit_insn (gen_movsi (reg, operands[1]));
7096 operands[1] = gen_lowpart (QImode, reg);
7097 }
cffb2a26 7098
6cffc037 7099 if (TARGET_THUMB)
7100 {
cffb2a26 7101 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 7102 happen if we are passed a SP (never OK for HImode/QImode) or
bc409cb4 7103 virtual register (also rejected as illegitimate for HImode/QImode)
7104 relative address. */
cffb2a26 7105 /* ??? This should perhaps be fixed elsewhere, for instance, in
7106 fixup_stack_1, by checking for other kinds of invalid addresses,
7107 e.g. a bare reference to a virtual register. This may confuse the
7108 alpha though, which must handle this case differently. */
0438d37f 7109 if (MEM_P (operands[0])
215b30b3 7110 && !memory_address_p (GET_MODE (operands[0]),
cffb2a26 7111 XEXP (operands[0], 0)))
537ffcfc 7112 operands[0]
7113 = replace_equiv_address (operands[0],
7114 copy_to_reg (XEXP (operands[0], 0)));
0438d37f 7115 if (MEM_P (operands[1])
215b30b3 7116 && !memory_address_p (GET_MODE (operands[1]),
cffb2a26 7117 XEXP (operands[1], 0)))
537ffcfc 7118 operands[1]
7119 = replace_equiv_address (operands[1],
7120 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 7121 }
7122
0438d37f 7123 if (MEM_P (operands[1]) && optimize > 0)
6cffc037 7124 {
7125 rtx reg = gen_reg_rtx (SImode);
7126
7127 emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
7128 operands[1] = gen_lowpart (QImode, reg);
7129 }
7130
0438d37f 7131 if (MEM_P (operands[0]))
6cffc037 7132 operands[1] = force_reg (QImode, operands[1]);
7133 }
7134 else if (TARGET_THUMB
0438d37f 7135 && CONST_INT_P (operands[1])
234f6557 7136 && !satisfies_constraint_I (operands[1]))
6cffc037 7137 {
674a8f0b 7138 /* Handle loading a large integer during reload. */
cffb2a26 7139
6cffc037 7140 /* Writing a constant to memory needs a scratch, which should
7141 be handled with SECONDARY_RELOADs. */
0438d37f 7142 gcc_assert (REG_P (operands[0]));
6cffc037 7143
7144 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
7145 emit_insn (gen_movsi (operands[0], operands[1]));
7146 DONE;
cffb2a26 7147 }
7148 "
7149)
b11cae9e 7150
cffb2a26 7151(define_insn "*arm_movqi_insn"
fd711051 7152 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,l,r,l,Uu,r,m")
7153 (match_operand:QI 1 "general_operand" "r,r,I,Py,K,Uu,l,m,r"))]
25f905c2 7154 "TARGET_32BIT
cffb2a26 7155 && ( register_operand (operands[0], QImode)
7156 || register_operand (operands[1], QImode))"
5565501b 7157 "@
fd711051 7158 mov%?\\t%0, %1
7159 mov%?\\t%0, %1
65f68e55 7160 mov%?\\t%0, %1
5565501b 7161 mov%?\\t%0, %1
7162 mvn%?\\t%0, #%B1
25f905c2 7163 ldr%(b%)\\t%0, %1
a54e3e7b 7164 str%(b%)\\t%1, %0
7165 ldr%(b%)\\t%0, %1
25f905c2 7166 str%(b%)\\t%1, %0"
1aed5204 7167 [(set_attr "type" "mov_reg,mov_reg,mov_imm,mov_imm,mvn_imm,load1,store1,load1,store1")
a54e3e7b 7168 (set_attr "predicable" "yes")
fd711051 7169 (set_attr "predicable_short_it" "yes,yes,yes,no,no,no,no,no,no")
7170 (set_attr "arch" "t2,any,any,t2,any,t2,t2,any,any")
7171 (set_attr "length" "2,4,4,2,4,2,2,4,4")]
cffb2a26 7172)
7173
25f905c2 7174(define_insn "*thumb1_movqi_insn"
cffb2a26 7175 [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
215b30b3 7176 (match_operand:QI 1 "general_operand" "l, m,l,*h,*r,I"))]
25f905c2 7177 "TARGET_THUMB1
cffb2a26 7178 && ( register_operand (operands[0], QImode)
7179 || register_operand (operands[1], QImode))"
7180 "@
7181 add\\t%0, %1, #0
7182 ldrb\\t%0, %1
7183 strb\\t%1, %0
7184 mov\\t%0, %1
7185 mov\\t%0, %1
7186 mov\\t%0, %1"
7187 [(set_attr "length" "2")
d82e788e 7188 (set_attr "type" "alu_imm,load1,store1,mov_reg,mov_imm,mov_imm")
747b7458 7189 (set_attr "pool_range" "*,32,*,*,*,*")
7190 (set_attr "conds" "clob,nocond,nocond,nocond,nocond,clob")])
b11cae9e 7191
9b8516be 7192;; HFmode moves
7193(define_expand "movhf"
7194 [(set (match_operand:HF 0 "general_operand" "")
7195 (match_operand:HF 1 "general_operand" ""))]
7196 "TARGET_EITHER"
7197 "
7198 if (TARGET_32BIT)
7199 {
0438d37f 7200 if (MEM_P (operands[0]))
9b8516be 7201 operands[1] = force_reg (HFmode, operands[1]);
7202 }
7203 else /* TARGET_THUMB1 */
7204 {
7205 if (can_create_pseudo_p ())
7206 {
0438d37f 7207 if (!REG_P (operands[0]))
9b8516be 7208 operands[1] = force_reg (HFmode, operands[1]);
7209 }
7210 }
7211 "
7212)
7213
7214(define_insn "*arm32_movhf"
7215 [(set (match_operand:HF 0 "nonimmediate_operand" "=r,m,r,r")
7216 (match_operand:HF 1 "general_operand" " m,r,r,F"))]
7c36fe71 7217 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_FP16) && !arm_restrict_it
9b8516be 7218 && ( s_register_operand (operands[0], HFmode)
7219 || s_register_operand (operands[1], HFmode))"
7220 "*
7221 switch (which_alternative)
7222 {
7223 case 0: /* ARM register from memory */
7224 return \"ldr%(h%)\\t%0, %1\\t%@ __fp16\";
7225 case 1: /* memory from ARM register */
7226 return \"str%(h%)\\t%1, %0\\t%@ __fp16\";
7227 case 2: /* ARM register from ARM register */
7228 return \"mov%?\\t%0, %1\\t%@ __fp16\";
7229 case 3: /* ARM register from constant */
7230 {
7231 REAL_VALUE_TYPE r;
7232 long bits;
7233 rtx ops[4];
7234
7235 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
7236 bits = real_to_target (NULL, &r, HFmode);
7237 ops[0] = operands[0];
7238 ops[1] = GEN_INT (bits);
7239 ops[2] = GEN_INT (bits & 0xff00);
7240 ops[3] = GEN_INT (bits & 0x00ff);
7241
7242 if (arm_arch_thumb2)
7243 output_asm_insn (\"movw%?\\t%0, %1\", ops);
7244 else
7245 output_asm_insn (\"mov%?\\t%0, %2\;orr%?\\t%0, %0, %3\", ops);
7246 return \"\";
7247 }
7248 default:
7249 gcc_unreachable ();
7250 }
7251 "
7252 [(set_attr "conds" "unconditional")
ad4fc3c0 7253 (set_attr "type" "load1,store1,mov_reg,multiple")
9b8516be 7254 (set_attr "length" "4,4,4,8")
d2a518d1 7255 (set_attr "predicable" "yes")]
9b8516be 7256)
7257
7258(define_insn "*thumb1_movhf"
7259 [(set (match_operand:HF 0 "nonimmediate_operand" "=l,l,m,*r,*h")
7260 (match_operand:HF 1 "general_operand" "l,mF,l,*h,*r"))]
7261 "TARGET_THUMB1
7262 && ( s_register_operand (operands[0], HFmode)
7263 || s_register_operand (operands[1], HFmode))"
7264 "*
7265 switch (which_alternative)
7266 {
7267 case 1:
7268 {
7269 rtx addr;
0438d37f 7270 gcc_assert (MEM_P (operands[1]));
9b8516be 7271 addr = XEXP (operands[1], 0);
7272 if (GET_CODE (addr) == LABEL_REF
7273 || (GET_CODE (addr) == CONST
7274 && GET_CODE (XEXP (addr, 0)) == PLUS
7275 && GET_CODE (XEXP (XEXP (addr, 0), 0)) == LABEL_REF
0438d37f 7276 && CONST_INT_P (XEXP (XEXP (addr, 0), 1))))
9b8516be 7277 {
7278 /* Constant pool entry. */
7279 return \"ldr\\t%0, %1\";
7280 }
7281 return \"ldrh\\t%0, %1\";
7282 }
7283 case 2: return \"strh\\t%1, %0\";
7284 default: return \"mov\\t%0, %1\";
7285 }
7286 "
7287 [(set_attr "length" "2")
1aed5204 7288 (set_attr "type" "mov_reg,load1,store1,mov_reg,mov_reg")
42e1de19 7289 (set_attr "pool_range" "*,1018,*,*,*")
747b7458 7290 (set_attr "conds" "clob,nocond,nocond,nocond,nocond")])
9b8516be 7291
87b22bf7 7292(define_expand "movsf"
7293 [(set (match_operand:SF 0 "general_operand" "")
7294 (match_operand:SF 1 "general_operand" ""))]
cffb2a26 7295 "TARGET_EITHER"
87b22bf7 7296 "
25f905c2 7297 if (TARGET_32BIT)
cffb2a26 7298 {
0438d37f 7299 if (MEM_P (operands[0]))
cffb2a26 7300 operands[1] = force_reg (SFmode, operands[1]);
7301 }
25f905c2 7302 else /* TARGET_THUMB1 */
cffb2a26 7303 {
e1ba4a27 7304 if (can_create_pseudo_p ())
cffb2a26 7305 {
0438d37f 7306 if (!REG_P (operands[0]))
cffb2a26 7307 operands[1] = force_reg (SFmode, operands[1]);
7308 }
7309 }
7310 "
7311)
7312
03d440a6 7313;; Transform a floating-point move of a constant into a core register into
7314;; an SImode operation.
cffb2a26 7315(define_split
03d440a6 7316 [(set (match_operand:SF 0 "arm_general_register_operand" "")
cffb2a26 7317 (match_operand:SF 1 "immediate_operand" ""))]
339034d0 7318 "TARGET_EITHER
cffb2a26 7319 && reload_completed
0438d37f 7320 && CONST_DOUBLE_P (operands[1])"
cffb2a26 7321 [(set (match_dup 2) (match_dup 3))]
7322 "
7323 operands[2] = gen_lowpart (SImode, operands[0]);
7324 operands[3] = gen_lowpart (SImode, operands[1]);
7325 if (operands[2] == 0 || operands[3] == 0)
7326 FAIL;
215b30b3 7327 "
7328)
87b22bf7 7329
cffb2a26 7330(define_insn "*arm_movsf_soft_insn"
7331 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
7332 (match_operand:SF 1 "general_operand" "r,mE,r"))]
cde1623a 7333 "TARGET_32BIT
cffb2a26 7334 && TARGET_SOFT_FLOAT
0438d37f 7335 && (!MEM_P (operands[0])
215b30b3 7336 || register_operand (operands[1], SFmode))"
9a1112d7 7337 "@
7338 mov%?\\t%0, %1
7339 ldr%?\\t%0, %1\\t%@ float
7340 str%?\\t%1, %0\\t%@ float"
cde1623a 7341 [(set_attr "predicable" "yes")
7c36fe71 7342 (set_attr "predicable_short_it" "no")
1aed5204 7343 (set_attr "type" "mov_reg,load1,store1")
42e1de19 7344 (set_attr "arm_pool_range" "*,4096,*")
7345 (set_attr "thumb2_pool_range" "*,4094,*")
cde1623a 7346 (set_attr "arm_neg_pool_range" "*,4084,*")
7347 (set_attr "thumb2_neg_pool_range" "*,0,*")]
cffb2a26 7348)
7349
7350;;; ??? This should have alternatives for constants.
25f905c2 7351(define_insn "*thumb1_movsf_insn"
215b30b3 7352 [(set (match_operand:SF 0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
7353 (match_operand:SF 1 "general_operand" "l, >,l,mF,l,*h,*r"))]
25f905c2 7354 "TARGET_THUMB1
cffb2a26 7355 && ( register_operand (operands[0], SFmode)
7356 || register_operand (operands[1], SFmode))"
7357 "@
7358 add\\t%0, %1, #0
7359 ldmia\\t%1, {%0}
7360 stmia\\t%0, {%1}
7361 ldr\\t%0, %1
7362 str\\t%1, %0
7363 mov\\t%0, %1
7364 mov\\t%0, %1"
7365 [(set_attr "length" "2")
1b7da4ac 7366 (set_attr "type" "alus_imm,load1,store1,load1,store1,mov_reg,mov_reg")
42e1de19 7367 (set_attr "pool_range" "*,*,*,1018,*,*,*")
747b7458 7368 (set_attr "conds" "clob,nocond,nocond,nocond,nocond,nocond,nocond")]
cffb2a26 7369)
9a1112d7 7370
9c08d1fa 7371(define_expand "movdf"
87b22bf7 7372 [(set (match_operand:DF 0 "general_operand" "")
7373 (match_operand:DF 1 "general_operand" ""))]
cffb2a26 7374 "TARGET_EITHER"
9c08d1fa 7375 "
25f905c2 7376 if (TARGET_32BIT)
cffb2a26 7377 {
0438d37f 7378 if (MEM_P (operands[0]))
cffb2a26 7379 operands[1] = force_reg (DFmode, operands[1]);
7380 }
7381 else /* TARGET_THUMB */
7382 {
e1ba4a27 7383 if (can_create_pseudo_p ())
cffb2a26 7384 {
0438d37f 7385 if (!REG_P (operands[0]))
cffb2a26 7386 operands[1] = force_reg (DFmode, operands[1]);
7387 }
7388 }
7389 "
7390)
b11cae9e 7391
9c08d1fa 7392;; Reloading a df mode value stored in integer regs to memory can require a
7393;; scratch reg.
7394(define_expand "reload_outdf"
cffb2a26 7395 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
87b22bf7 7396 (match_operand:DF 1 "s_register_operand" "r")
7397 (match_operand:SI 2 "s_register_operand" "=&r")]
06adefdc 7398 "TARGET_THUMB2"
87b22bf7 7399 "
215b30b3 7400 {
7401 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
f7fbdd4a 7402
215b30b3 7403 if (code == REG)
7404 operands[2] = XEXP (operands[0], 0);
7405 else if (code == POST_INC || code == PRE_DEC)
7406 {
7407 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
7408 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
7409 emit_insn (gen_movdi (operands[0], operands[1]));
7410 DONE;
7411 }
7412 else if (code == PRE_INC)
7413 {
7414 rtx reg = XEXP (XEXP (operands[0], 0), 0);
f7fbdd4a 7415
215b30b3 7416 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
7417 operands[2] = reg;
7418 }
7419 else if (code == POST_DEC)
7420 operands[2] = XEXP (XEXP (operands[0], 0), 0);
7421 else
7422 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
7423 XEXP (XEXP (operands[0], 0), 1)));
f7fbdd4a 7424
788fcce0 7425 emit_insn (gen_rtx_SET (VOIDmode,
7426 replace_equiv_address (operands[0], operands[2]),
215b30b3 7427 operands[1]));
f7fbdd4a 7428
215b30b3 7429 if (code == POST_DEC)
7430 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
7431
7432 DONE;
7433 }"
7434)
9c08d1fa 7435
9a1112d7 7436(define_insn "*movdf_soft_insn"
353cf59a 7437 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,q,m")
7438 (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,q"))]
cde1623a 7439 "TARGET_32BIT && TARGET_SOFT_FLOAT
b2778788 7440 && ( register_operand (operands[0], DFmode)
7441 || register_operand (operands[1], DFmode))"
d51f92df 7442 "*
7443 switch (which_alternative)
7444 {
7445 case 0:
7446 case 1:
7447 case 2:
7448 return \"#\";
7449 default:
26ff80c0 7450 return output_move_double (operands, true, NULL);
d51f92df 7451 }
7452 "
359a6e9f 7453 [(set_attr "length" "8,12,16,8,8")
1b7da4ac 7454 (set_attr "type" "multiple,multiple,multiple,load2,store2")
42e1de19 7455 (set_attr "arm_pool_range" "*,*,*,1020,*")
7456 (set_attr "thumb2_pool_range" "*,*,*,1018,*")
8848d797 7457 (set_attr "arm_neg_pool_range" "*,*,*,1004,*")
cde1623a 7458 (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
cffb2a26 7459)
7460
7461;;; ??? This should have alternatives for constants.
7462;;; ??? This was originally identical to the movdi_insn pattern.
7463;;; ??? The 'F' constraint looks funny, but it should always be replaced by
7464;;; thumb_reorg with a memory reference.
7465(define_insn "*thumb_movdf_insn"
215b30b3 7466 [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
7467 (match_operand:DF 1 "general_operand" "l, >,l,mF,l,*r"))]
25f905c2 7468 "TARGET_THUMB1
cffb2a26 7469 && ( register_operand (operands[0], DFmode)
7470 || register_operand (operands[1], DFmode))"
7471 "*
7472 switch (which_alternative)
7473 {
7474 default:
7475 case 0:
7476 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
7477 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
7478 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
7479 case 1:
7480 return \"ldmia\\t%1, {%0, %H0}\";
7481 case 2:
7482 return \"stmia\\t%0, {%1, %H1}\";
7483 case 3:
7484 return thumb_load_double_from_address (operands);
7485 case 4:
1a83b3ff 7486 operands[2] = gen_rtx_MEM (SImode,
29c05e22 7487 plus_constant (Pmode,
7488 XEXP (operands[0], 0), 4));
cffb2a26 7489 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
7490 return \"\";
7491 case 5:
7492 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
7493 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
7494 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
7495 }
7496 "
7497 [(set_attr "length" "4,2,2,6,4,4")
ad4fc3c0 7498 (set_attr "type" "multiple,load2,store2,load2,store2,multiple")
42e1de19 7499 (set_attr "pool_range" "*,*,*,1018,*,*")]
cffb2a26 7500)
b11cae9e 7501\f
b11cae9e 7502
9c08d1fa 7503;; load- and store-multiple insns
7504;; The arm can load/store any set of registers, provided that they are in
320ea44d 7505;; ascending order, but these expanders assume a contiguous set.
b11cae9e 7506
9c08d1fa 7507(define_expand "load_multiple"
7508 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
7509 (match_operand:SI 1 "" ""))
7510 (use (match_operand:SI 2 "" ""))])]
25f905c2 7511 "TARGET_32BIT"
9580c25f 7512{
7513 HOST_WIDE_INT offset = 0;
7514
bd5b4116 7515 /* Support only fixed point registers. */
0438d37f 7516 if (!CONST_INT_P (operands[2])
9c08d1fa 7517 || INTVAL (operands[2]) > 14
7518 || INTVAL (operands[2]) < 2
0438d37f 7519 || !MEM_P (operands[1])
7520 || !REG_P (operands[0])
bd5b4116 7521 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
7522 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 7523 FAIL;
7524
7525 operands[3]
320ea44d 7526 = arm_gen_load_multiple (arm_regs_in_sequence + REGNO (operands[0]),
7527 INTVAL (operands[2]),
f082f1c4 7528 force_reg (SImode, XEXP (operands[1], 0)),
320ea44d 7529 FALSE, operands[1], &offset);
9580c25f 7530})
b11cae9e 7531
9c08d1fa 7532(define_expand "store_multiple"
7533 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
7534 (match_operand:SI 1 "" ""))
7535 (use (match_operand:SI 2 "" ""))])]
25f905c2 7536 "TARGET_32BIT"
9580c25f 7537{
7538 HOST_WIDE_INT offset = 0;
7539
674a8f0b 7540 /* Support only fixed point registers. */
0438d37f 7541 if (!CONST_INT_P (operands[2])
9c08d1fa 7542 || INTVAL (operands[2]) > 14
7543 || INTVAL (operands[2]) < 2
0438d37f 7544 || !REG_P (operands[1])
7545 || !MEM_P (operands[0])
bd5b4116 7546 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
7547 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 7548 FAIL;
7549
7550 operands[3]
320ea44d 7551 = arm_gen_store_multiple (arm_regs_in_sequence + REGNO (operands[1]),
7552 INTVAL (operands[2]),
f082f1c4 7553 force_reg (SImode, XEXP (operands[0], 0)),
320ea44d 7554 FALSE, operands[0], &offset);
9580c25f 7555})
b11cae9e 7556
9c08d1fa 7557
7558;; Move a block of memory if it is word aligned and MORE than 2 words long.
7559;; We could let this apply for blocks of less than this, but it clobbers so
7560;; many registers that there is then probably a better way.
7561
008c057d 7562(define_expand "movmemqi"
34191dd1 7563 [(match_operand:BLK 0 "general_operand" "")
7564 (match_operand:BLK 1 "general_operand" "")
7565 (match_operand:SI 2 "const_int_operand" "")
7566 (match_operand:SI 3 "const_int_operand" "")]
ae51a965 7567 ""
9c08d1fa 7568 "
25f905c2 7569 if (TARGET_32BIT)
cffb2a26 7570 {
ae51a965 7571 if (TARGET_LDRD && current_tune->prefer_ldrd_strd
7572 && !optimize_function_for_size_p (cfun))
7573 {
7574 if (gen_movmem_ldrd_strd (operands))
7575 DONE;
7576 FAIL;
7577 }
7578
008c057d 7579 if (arm_gen_movmemqi (operands))
cffb2a26 7580 DONE;
7581 FAIL;
7582 }
25f905c2 7583 else /* TARGET_THUMB1 */
cffb2a26 7584 {
7585 if ( INTVAL (operands[3]) != 4
7586 || INTVAL (operands[2]) > 48)
7587 FAIL;
7588
008c057d 7589 thumb_expand_movmemqi (operands);
cffb2a26 7590 DONE;
7591 }
7592 "
7593)
7594
2162064c 7595;; Thumb block-move insns
cffb2a26 7596
7597(define_insn "movmem12b"
960f3acf 7598 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
7599 (mem:SI (match_operand:SI 3 "register_operand" "1")))
7600 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
7601 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
7602 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
7603 (mem:SI (plus:SI (match_dup 3) (const_int 8))))
7604 (set (match_operand:SI 0 "register_operand" "=l")
7605 (plus:SI (match_dup 2) (const_int 12)))
7606 (set (match_operand:SI 1 "register_operand" "=l")
7607 (plus:SI (match_dup 3) (const_int 12)))
7608 (clobber (match_scratch:SI 4 "=&l"))
7609 (clobber (match_scratch:SI 5 "=&l"))
7610 (clobber (match_scratch:SI 6 "=&l"))]
25f905c2 7611 "TARGET_THUMB1"
cffb2a26 7612 "* return thumb_output_move_mem_multiple (3, operands);"
7613 [(set_attr "length" "4")
215b30b3 7614 ; This isn't entirely accurate... It loads as well, but in terms of
7615 ; scheduling the following insn it is better to consider it as a store
cffb2a26 7616 (set_attr "type" "store3")]
7617)
7618
7619(define_insn "movmem8b"
960f3acf 7620 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
7621 (mem:SI (match_operand:SI 3 "register_operand" "1")))
7622 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
7623 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
7624 (set (match_operand:SI 0 "register_operand" "=l")
7625 (plus:SI (match_dup 2) (const_int 8)))
7626 (set (match_operand:SI 1 "register_operand" "=l")
7627 (plus:SI (match_dup 3) (const_int 8)))
7628 (clobber (match_scratch:SI 4 "=&l"))
7629 (clobber (match_scratch:SI 5 "=&l"))]
25f905c2 7630 "TARGET_THUMB1"
cffb2a26 7631 "* return thumb_output_move_mem_multiple (2, operands);"
7632 [(set_attr "length" "4")
215b30b3 7633 ; This isn't entirely accurate... It loads as well, but in terms of
7634 ; scheduling the following insn it is better to consider it as a store
cffb2a26 7635 (set_attr "type" "store2")]
7636)
7637
9c08d1fa 7638\f
b11cae9e 7639
341940e8 7640;; Compare & branch insns
8d232dc7 7641;; The range calculations are based as follows:
341940e8 7642;; For forward branches, the address calculation returns the address of
7643;; the next instruction. This is 2 beyond the branch instruction.
7644;; For backward branches, the address calculation returns the address of
7645;; the first instruction in this pattern (cmp). This is 2 before the branch
7646;; instruction for the shortest sequence, and 4 before the branch instruction
7647;; if we have to jump around an unconditional branch.
7648;; To the basic branch range the PC offset must be added (this is +4).
7649;; So for forward branches we have
7650;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
7651;; And for backward branches we have
7652;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
7653;;
7654;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
7655;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
cffb2a26 7656
aeac46d4 7657(define_expand "cbranchsi4"
7658 [(set (pc) (if_then_else
aa06947a 7659 (match_operator 0 "expandable_comparison_operator"
aeac46d4 7660 [(match_operand:SI 1 "s_register_operand" "")
7661 (match_operand:SI 2 "nonmemory_operand" "")])
7662 (label_ref (match_operand 3 "" ""))
7663 (pc)))]
f9aa4160 7664 "TARGET_EITHER"
aeac46d4 7665 "
74f4459c 7666 if (!TARGET_THUMB1)
7667 {
f9aa4160 7668 if (!arm_validize_comparison (&operands[0], &operands[1], &operands[2]))
7669 FAIL;
74f4459c 7670 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
7671 operands[3]));
7672 DONE;
7673 }
25f905c2 7674 if (thumb1_cmpneg_operand (operands[2], SImode))
aeac46d4 7675 {
7676 emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
7677 operands[3], operands[0]));
7678 DONE;
7679 }
25f905c2 7680 if (!thumb1_cmp_operand (operands[2], SImode))
aeac46d4 7681 operands[2] = force_reg (SImode, operands[2]);
7682 ")
7683
a8e6c15d 7684;; A pattern to recognize a special situation and optimize for it.
7685;; On the thumb, zero-extension from memory is preferrable to sign-extension
7686;; due to the available addressing modes. Hence, convert a signed comparison
7687;; with zero into an unsigned comparison with 127 if possible.
7688(define_expand "cbranchqi4"
7689 [(set (pc) (if_then_else
7690 (match_operator 0 "lt_ge_comparison_operator"
7691 [(match_operand:QI 1 "memory_operand" "")
7692 (match_operand:QI 2 "const0_operand" "")])
7693 (label_ref (match_operand 3 "" ""))
7694 (pc)))]
7695 "TARGET_THUMB1"
7696{
d0f6c30d 7697 rtx xops[4];
a8e6c15d 7698 xops[1] = gen_reg_rtx (SImode);
7699 emit_insn (gen_zero_extendqisi2 (xops[1], operands[1]));
7700 xops[2] = GEN_INT (127);
7701 xops[0] = gen_rtx_fmt_ee (GET_CODE (operands[0]) == GE ? LEU : GTU,
7702 VOIDmode, xops[1], xops[2]);
7703 xops[3] = operands[3];
7704 emit_insn (gen_cbranchsi4 (xops[0], xops[1], xops[2], xops[3]));
7705 DONE;
7706})
7707
74f4459c 7708(define_expand "cbranchsf4"
7709 [(set (pc) (if_then_else
aa06947a 7710 (match_operator 0 "expandable_comparison_operator"
74f4459c 7711 [(match_operand:SF 1 "s_register_operand" "")
7712 (match_operand:SF 2 "arm_float_compare_operand" "")])
7713 (label_ref (match_operand 3 "" ""))
7714 (pc)))]
7715 "TARGET_32BIT && TARGET_HARD_FLOAT"
7716 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
7717 operands[3])); DONE;"
7718)
7719
7720(define_expand "cbranchdf4"
7721 [(set (pc) (if_then_else
aa06947a 7722 (match_operator 0 "expandable_comparison_operator"
74f4459c 7723 [(match_operand:DF 1 "s_register_operand" "")
7724 (match_operand:DF 2 "arm_float_compare_operand" "")])
7725 (label_ref (match_operand 3 "" ""))
7726 (pc)))]
a50d7267 7727 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
74f4459c 7728 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
7729 operands[3])); DONE;"
7730)
7731
74f4459c 7732(define_expand "cbranchdi4"
7733 [(set (pc) (if_then_else
aa06947a 7734 (match_operator 0 "expandable_comparison_operator"
b8eae306 7735 [(match_operand:DI 1 "s_register_operand" "")
a8045a4f 7736 (match_operand:DI 2 "cmpdi_operand" "")])
74f4459c 7737 (label_ref (match_operand 3 "" ""))
7738 (pc)))]
a8045a4f 7739 "TARGET_32BIT"
7740 "{
0438d37f 7741 if (!arm_validize_comparison (&operands[0], &operands[1], &operands[2]))
f9aa4160 7742 FAIL;
7743 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
a8045a4f 7744 operands[3]));
7745 DONE;
7746 }"
74f4459c 7747)
7748
d60047aa 7749(define_insn "cbranchsi4_insn"
aeac46d4 7750 [(set (pc) (if_then_else
7751 (match_operator 0 "arm_comparison_operator"
747b7458 7752 [(match_operand:SI 1 "s_register_operand" "l,l*h")
25f905c2 7753 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r")])
aeac46d4 7754 (label_ref (match_operand 3 "" ""))
7755 (pc)))]
25f905c2 7756 "TARGET_THUMB1"
747b7458 7757{
7758 rtx t = cfun->machine->thumb1_cc_insn;
7759 if (t != NULL_RTX)
d60047aa 7760 {
747b7458 7761 if (!rtx_equal_p (cfun->machine->thumb1_cc_op0, operands[1])
7762 || !rtx_equal_p (cfun->machine->thumb1_cc_op1, operands[2]))
7763 t = NULL_RTX;
7764 if (cfun->machine->thumb1_cc_mode == CC_NOOVmode)
7765 {
7766 if (!noov_comparison_operator (operands[0], VOIDmode))
7767 t = NULL_RTX;
7768 }
7769 else if (cfun->machine->thumb1_cc_mode != CCmode)
d60047aa 7770 t = NULL_RTX;
7771 }
d60047aa 7772 if (t == NULL_RTX)
747b7458 7773 {
7774 output_asm_insn ("cmp\t%1, %2", operands);
7775 cfun->machine->thumb1_cc_insn = insn;
7776 cfun->machine->thumb1_cc_op0 = operands[1];
7777 cfun->machine->thumb1_cc_op1 = operands[2];
7778 cfun->machine->thumb1_cc_mode = CCmode;
7779 }
7780 else
7781 /* Ensure we emit the right type of condition code on the jump. */
7782 XEXP (operands[0], 0) = gen_rtx_REG (cfun->machine->thumb1_cc_mode,
7783 CC_REGNUM);
aeac46d4 7784
cffb2a26 7785 switch (get_attr_length (insn))
7786 {
7787 case 4: return \"b%d0\\t%l3\";
7788 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7789 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7790 }
747b7458 7791}
cffb2a26 7792 [(set (attr "far_jump")
7793 (if_then_else
7794 (eq_attr "length" "8")
7795 (const_string "yes")
7796 (const_string "no")))
7797 (set (attr "length")
7798 (if_then_else
7799 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7800 (le (minus (match_dup 3) (pc)) (const_int 256)))
7801 (const_int 4)
7802 (if_then_else
7803 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
341940e8 7804 (le (minus (match_dup 3) (pc)) (const_int 2048)))
cffb2a26 7805 (const_int 6)
1b7da4ac 7806 (const_int 8))))
7807 (set_attr "type" "multiple")]
cffb2a26 7808)
7809
aeac46d4 7810(define_insn "cbranchsi4_scratch"
7811 [(set (pc) (if_then_else
7812 (match_operator 4 "arm_comparison_operator"
7813 [(match_operand:SI 1 "s_register_operand" "l,0")
25f905c2 7814 (match_operand:SI 2 "thumb1_cmpneg_operand" "L,J")])
aeac46d4 7815 (label_ref (match_operand 3 "" ""))
7816 (pc)))
7817 (clobber (match_scratch:SI 0 "=l,l"))]
25f905c2 7818 "TARGET_THUMB1"
aeac46d4 7819 "*
7820 output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
7821
7822 switch (get_attr_length (insn))
7823 {
7824 case 4: return \"b%d4\\t%l3\";
7825 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7826 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7827 }
7828 "
7829 [(set (attr "far_jump")
7830 (if_then_else
7831 (eq_attr "length" "8")
7832 (const_string "yes")
7833 (const_string "no")))
7834 (set (attr "length")
7835 (if_then_else
7836 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7837 (le (minus (match_dup 3) (pc)) (const_int 256)))
7838 (const_int 4)
7839 (if_then_else
7840 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7841 (le (minus (match_dup 3) (pc)) (const_int 2048)))
7842 (const_int 6)
1b7da4ac 7843 (const_int 8))))
7844 (set_attr "type" "multiple")]
aeac46d4 7845)
446a1e96 7846
cffb2a26 7847(define_insn "*negated_cbranchsi4"
7848 [(set (pc)
7849 (if_then_else
aed179ae 7850 (match_operator 0 "equality_operator"
aeac46d4 7851 [(match_operand:SI 1 "s_register_operand" "l")
7852 (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
7853 (label_ref (match_operand 3 "" ""))
215b30b3 7854 (pc)))]
25f905c2 7855 "TARGET_THUMB1"
cffb2a26 7856 "*
7857 output_asm_insn (\"cmn\\t%1, %2\", operands);
7858 switch (get_attr_length (insn))
7859 {
7860 case 4: return \"b%d0\\t%l3\";
7861 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7862 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7863 }
7864 "
7865 [(set (attr "far_jump")
7866 (if_then_else
7867 (eq_attr "length" "8")
7868 (const_string "yes")
7869 (const_string "no")))
7870 (set (attr "length")
7871 (if_then_else
7872 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
341940e8 7873 (le (minus (match_dup 3) (pc)) (const_int 256)))
cffb2a26 7874 (const_int 4)
7875 (if_then_else
341940e8 7876 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7877 (le (minus (match_dup 3) (pc)) (const_int 2048)))
cffb2a26 7878 (const_int 6)
1b7da4ac 7879 (const_int 8))))
7880 (set_attr "type" "multiple")]
cffb2a26 7881)
7882
58d6528b 7883(define_insn "*tbit_cbranch"
7884 [(set (pc)
7885 (if_then_else
7886 (match_operator 0 "equality_operator"
7887 [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
7888 (const_int 1)
7889 (match_operand:SI 2 "const_int_operand" "i"))
7890 (const_int 0)])
7891 (label_ref (match_operand 3 "" ""))
7892 (pc)))
7893 (clobber (match_scratch:SI 4 "=l"))]
25f905c2 7894 "TARGET_THUMB1"
58d6528b 7895 "*
7896 {
7897 rtx op[3];
7898 op[0] = operands[4];
7899 op[1] = operands[1];
7900 op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
7901
86efa74d 7902 output_asm_insn (\"lsl\\t%0, %1, %2\", op);
7903 switch (get_attr_length (insn))
7904 {
7905 case 4: return \"b%d0\\t%l3\";
7906 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7907 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7908 }
7909 }"
7910 [(set (attr "far_jump")
7911 (if_then_else
7912 (eq_attr "length" "8")
7913 (const_string "yes")
7914 (const_string "no")))
7915 (set (attr "length")
7916 (if_then_else
7917 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7918 (le (minus (match_dup 3) (pc)) (const_int 256)))
7919 (const_int 4)
7920 (if_then_else
7921 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7922 (le (minus (match_dup 3) (pc)) (const_int 2048)))
7923 (const_int 6)
1b7da4ac 7924 (const_int 8))))
7925 (set_attr "type" "multiple")]
86efa74d 7926)
7927
7928(define_insn "*tlobits_cbranch"
7929 [(set (pc)
7930 (if_then_else
7931 (match_operator 0 "equality_operator"
7932 [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
7933 (match_operand:SI 2 "const_int_operand" "i")
7934 (const_int 0))
7935 (const_int 0)])
7936 (label_ref (match_operand 3 "" ""))
7937 (pc)))
7938 (clobber (match_scratch:SI 4 "=l"))]
25f905c2 7939 "TARGET_THUMB1"
86efa74d 7940 "*
7941 {
7942 rtx op[3];
7943 op[0] = operands[4];
7944 op[1] = operands[1];
7945 op[2] = GEN_INT (32 - INTVAL (operands[2]));
7946
58d6528b 7947 output_asm_insn (\"lsl\\t%0, %1, %2\", op);
7948 switch (get_attr_length (insn))
7949 {
7950 case 4: return \"b%d0\\t%l3\";
7951 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7952 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7953 }
7954 }"
7955 [(set (attr "far_jump")
7956 (if_then_else
7957 (eq_attr "length" "8")
7958 (const_string "yes")
7959 (const_string "no")))
7960 (set (attr "length")
7961 (if_then_else
7962 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7963 (le (minus (match_dup 3) (pc)) (const_int 256)))
7964 (const_int 4)
7965 (if_then_else
7966 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7967 (le (minus (match_dup 3) (pc)) (const_int 2048)))
7968 (const_int 6)
1b7da4ac 7969 (const_int 8))))
7970 (set_attr "type" "multiple")]
58d6528b 7971)
747b7458 7972
aeac46d4 7973(define_insn "*tstsi3_cbranch"
58d6528b 7974 [(set (pc)
7975 (if_then_else
aeac46d4 7976 (match_operator 3 "equality_operator"
7977 [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
7978 (match_operand:SI 1 "s_register_operand" "l"))
58d6528b 7979 (const_int 0)])
aeac46d4 7980 (label_ref (match_operand 2 "" ""))
7981 (pc)))]
25f905c2 7982 "TARGET_THUMB1"
58d6528b 7983 "*
7984 {
aeac46d4 7985 output_asm_insn (\"tst\\t%0, %1\", operands);
58d6528b 7986 switch (get_attr_length (insn))
7987 {
aeac46d4 7988 case 4: return \"b%d3\\t%l2\";
7989 case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
7990 default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
58d6528b 7991 }
7992 }"
7993 [(set (attr "far_jump")
7994 (if_then_else
7995 (eq_attr "length" "8")
7996 (const_string "yes")
7997 (const_string "no")))
7998 (set (attr "length")
7999 (if_then_else
aeac46d4 8000 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
8001 (le (minus (match_dup 2) (pc)) (const_int 256)))
58d6528b 8002 (const_int 4)
8003 (if_then_else
aeac46d4 8004 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
8005 (le (minus (match_dup 2) (pc)) (const_int 2048)))
58d6528b 8006 (const_int 6)
1b7da4ac 8007 (const_int 8))))
8008 (set_attr "type" "multiple")]
58d6528b 8009)
8010
203c488f 8011(define_insn "*cbranchne_decr1"
8012 [(set (pc)
8013 (if_then_else (match_operator 3 "equality_operator"
8014 [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
8015 (const_int 0)])
8016 (label_ref (match_operand 4 "" ""))
8017 (pc)))
aeac46d4 8018 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
203c488f 8019 (plus:SI (match_dup 2) (const_int -1)))
8020 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
25f905c2 8021 "TARGET_THUMB1"
203c488f 8022 "*
8023 {
8024 rtx cond[2];
8025 cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
8026 ? GEU : LTU),
58d6528b 8027 VOIDmode, operands[2], const1_rtx);
203c488f 8028 cond[1] = operands[4];
8029
8030 if (which_alternative == 0)
8031 output_asm_insn (\"sub\\t%0, %2, #1\", operands);
8032 else if (which_alternative == 1)
8033 {
8034 /* We must provide an alternative for a hi reg because reload
8035 cannot handle output reloads on a jump instruction, but we
8036 can't subtract into that. Fortunately a mov from lo to hi
8037 does not clobber the condition codes. */
8038 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
8039 output_asm_insn (\"mov\\t%0, %1\", operands);
8040 }
8041 else
8042 {
8043 /* Similarly, but the target is memory. */
8044 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
8045 output_asm_insn (\"str\\t%1, %0\", operands);
8046 }
8047
8048 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
8049 {
8050 case 4:
8aea555f 8051 output_asm_insn (\"b%d0\\t%l1\", cond);
203c488f 8052 return \"\";
8053 case 6:
8aea555f 8054 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
203c488f 8055 return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
8056 default:
8aea555f 8057 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
203c488f 8058 return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
8059 }
8060 }
8061 "
8062 [(set (attr "far_jump")
8063 (if_then_else
8064 (ior (and (eq (symbol_ref ("which_alternative"))
8065 (const_int 0))
8066 (eq_attr "length" "8"))
8067 (eq_attr "length" "10"))
8068 (const_string "yes")
8069 (const_string "no")))
8070 (set_attr_alternative "length"
8071 [
8072 ;; Alternative 0
8073 (if_then_else
8074 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
8075 (le (minus (match_dup 4) (pc)) (const_int 256)))
8076 (const_int 4)
8077 (if_then_else
8078 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
8079 (le (minus (match_dup 4) (pc)) (const_int 2048)))
8080 (const_int 6)
8081 (const_int 8)))
8082 ;; Alternative 1
8083 (if_then_else
8084 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
8085 (le (minus (match_dup 4) (pc)) (const_int 256)))
8086 (const_int 6)
8087 (if_then_else
8088 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
8089 (le (minus (match_dup 4) (pc)) (const_int 2048)))
8090 (const_int 8)
8091 (const_int 10)))
8092 ;; Alternative 2
8093 (if_then_else
8094 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
8095 (le (minus (match_dup 4) (pc)) (const_int 256)))
8096 (const_int 6)
8097 (if_then_else
8098 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
8099 (le (minus (match_dup 4) (pc)) (const_int 2048)))
8100 (const_int 8)
8101 (const_int 10)))
8102 ;; Alternative 3
8103 (if_then_else
8104 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
8105 (le (minus (match_dup 4) (pc)) (const_int 256)))
8106 (const_int 6)
8107 (if_then_else
8108 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
8109 (le (minus (match_dup 4) (pc)) (const_int 2048)))
8110 (const_int 8)
1b7da4ac 8111 (const_int 10)))])
8112 (set_attr "type" "multiple")]
203c488f 8113)
cffb2a26 8114
58d6528b 8115(define_insn "*addsi3_cbranch"
8116 [(set (pc)
8117 (if_then_else
b0694be0 8118 (match_operator 4 "arm_comparison_operator"
58d6528b 8119 [(plus:SI
e54011cb 8120 (match_operand:SI 2 "s_register_operand" "%0,l,*l,1,1,1")
8121 (match_operand:SI 3 "reg_or_int_operand" "IJ,lL,*l,lIJ,lIJ,lIJ"))
58d6528b 8122 (const_int 0)])
8123 (label_ref (match_operand 5 "" ""))
8124 (pc)))
aeac46d4 8125 (set
8126 (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
8127 (plus:SI (match_dup 2) (match_dup 3)))
956a6170 8128 (clobber (match_scratch:SI 1 "=X,X,l,l,&l,&l"))]
25f905c2 8129 "TARGET_THUMB1
58d6528b 8130 && (GET_CODE (operands[4]) == EQ
8131 || GET_CODE (operands[4]) == NE
8132 || GET_CODE (operands[4]) == GE
8133 || GET_CODE (operands[4]) == LT)"
8134 "*
8135 {
8136 rtx cond[3];
8137
956a6170 8138 cond[0] = (which_alternative < 2) ? operands[0] : operands[1];
58d6528b 8139 cond[1] = operands[2];
8140 cond[2] = operands[3];
8141
0438d37f 8142 if (CONST_INT_P (cond[2]) && INTVAL (cond[2]) < 0)
58d6528b 8143 output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
8144 else
8145 output_asm_insn (\"add\\t%0, %1, %2\", cond);
8146
956a6170 8147 if (which_alternative >= 2
58d6528b 8148 && which_alternative < 4)
8149 output_asm_insn (\"mov\\t%0, %1\", operands);
8150 else if (which_alternative >= 4)
8151 output_asm_insn (\"str\\t%1, %0\", operands);
8152
d0f6c30d 8153 switch (get_attr_length (insn) - ((which_alternative >= 2) ? 2 : 0))
58d6528b 8154 {
8155 case 4:
8156 return \"b%d4\\t%l5\";
8157 case 6:
8158 return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
8159 default:
8160 return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
8161 }
8162 }
8163 "
8164 [(set (attr "far_jump")
8165 (if_then_else
8166 (ior (and (lt (symbol_ref ("which_alternative"))
d0f6c30d 8167 (const_int 2))
58d6528b 8168 (eq_attr "length" "8"))
8169 (eq_attr "length" "10"))
8170 (const_string "yes")
8171 (const_string "no")))
8172 (set (attr "length")
8173 (if_then_else
8174 (lt (symbol_ref ("which_alternative"))
d0f6c30d 8175 (const_int 2))
58d6528b 8176 (if_then_else
8177 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
8178 (le (minus (match_dup 5) (pc)) (const_int 256)))
8179 (const_int 4)
8180 (if_then_else
8181 (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
8182 (le (minus (match_dup 5) (pc)) (const_int 2048)))
8183 (const_int 6)
8184 (const_int 8)))
8185 (if_then_else
8186 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
8187 (le (minus (match_dup 5) (pc)) (const_int 256)))
8188 (const_int 6)
8189 (if_then_else
8190 (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
8191 (le (minus (match_dup 5) (pc)) (const_int 2048)))
8192 (const_int 8)
1b7da4ac 8193 (const_int 10)))))
8194 (set_attr "type" "multiple")]
58d6528b 8195)
8196
8197(define_insn "*addsi3_cbranch_scratch"
8198 [(set (pc)
8199 (if_then_else
b0694be0 8200 (match_operator 3 "arm_comparison_operator"
58d6528b 8201 [(plus:SI
8202 (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
3a445a04 8203 (match_operand:SI 2 "reg_or_int_operand" "J,l,L,IJ"))
58d6528b 8204 (const_int 0)])
8205 (label_ref (match_operand 4 "" ""))
8206 (pc)))
8207 (clobber (match_scratch:SI 0 "=X,X,l,l"))]
25f905c2 8208 "TARGET_THUMB1
58d6528b 8209 && (GET_CODE (operands[3]) == EQ
8210 || GET_CODE (operands[3]) == NE
8211 || GET_CODE (operands[3]) == GE
8212 || GET_CODE (operands[3]) == LT)"
8213 "*
8214 {
8215 switch (which_alternative)
8216 {
8217 case 0:
8218 output_asm_insn (\"cmp\t%1, #%n2\", operands);
8219 break;
8220 case 1:
8221 output_asm_insn (\"cmn\t%1, %2\", operands);
8222 break;
0f5e9701 8223 case 2:
3a445a04 8224 if (INTVAL (operands[2]) < 0)
8225 output_asm_insn (\"sub\t%0, %1, %2\", operands);
8226 else
8227 output_asm_insn (\"add\t%0, %1, %2\", operands);
58d6528b 8228 break;
0f5e9701 8229 case 3:
3a445a04 8230 if (INTVAL (operands[2]) < 0)
8231 output_asm_insn (\"sub\t%0, %0, %2\", operands);
8232 else
8233 output_asm_insn (\"add\t%0, %0, %2\", operands);
58d6528b 8234 break;
8235 }
8236
8237 switch (get_attr_length (insn))
8238 {
8239 case 4:
8240 return \"b%d3\\t%l4\";
8241 case 6:
8242 return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
8243 default:
8244 return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
8245 }
8246 }
8247 "
8248 [(set (attr "far_jump")
8249 (if_then_else
8250 (eq_attr "length" "8")
8251 (const_string "yes")
8252 (const_string "no")))
8253 (set (attr "length")
8254 (if_then_else
8255 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
8256 (le (minus (match_dup 4) (pc)) (const_int 256)))
8257 (const_int 4)
8258 (if_then_else
8259 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
8260 (le (minus (match_dup 4) (pc)) (const_int 2048)))
8261 (const_int 6)
1b7da4ac 8262 (const_int 8))))
8263 (set_attr "type" "multiple")]
58d6528b 8264)
8265
58d6528b 8266
9c08d1fa 8267;; Comparison and test insns
8268
cffb2a26 8269(define_insn "*arm_cmpsi_insn"
bd5b4116 8270 [(set (reg:CC CC_REGNUM)
f9f234ec 8271 (compare:CC (match_operand:SI 0 "s_register_operand" "l,r,r,r,r")
8272 (match_operand:SI 1 "arm_add_operand" "Py,r,r,I,L")))]
25f905c2 8273 "TARGET_32BIT"
5565501b 8274 "@
a6864a24 8275 cmp%?\\t%0, %1
8276 cmp%?\\t%0, %1
aea4c774 8277 cmp%?\\t%0, %1
f9f234ec 8278 cmp%?\\t%0, %1
aea4c774 8279 cmn%?\\t%0, #%n1"
a6864a24 8280 [(set_attr "conds" "set")
f9f234ec 8281 (set_attr "arch" "t2,t2,any,any,any")
8282 (set_attr "length" "2,2,4,4,4")
65f68e55 8283 (set_attr "predicable" "yes")
f9f234ec 8284 (set_attr "predicable_short_it" "yes,yes,yes,no,no")
8285 (set_attr "type" "alus_imm,alus_reg,alus_reg,alus_imm,alus_imm")]
cffb2a26 8286)
b11cae9e 8287
d5d4dc8d 8288(define_insn "*cmpsi_shiftsi"
bd5b4116 8289 [(set (reg:CC CC_REGNUM)
d82e788e 8290 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r,r")
cffb2a26 8291 (match_operator:SI 3 "shift_operator"
d82e788e 8292 [(match_operand:SI 1 "s_register_operand" "r,r,r")
8293 (match_operand:SI 2 "shift_amount_operand" "M,r,M")])))]
d5d4dc8d 8294 "TARGET_32BIT"
f9f234ec 8295 "cmp\\t%0, %1%S3"
344495ea 8296 [(set_attr "conds" "set")
331beb1a 8297 (set_attr "shift" "1")
d82e788e 8298 (set_attr "arch" "32,a,a")
8299 (set_attr "type" "alus_shift_imm,alu_shift_reg,alus_shift_imm")])
b11cae9e 8300
d5d4dc8d 8301(define_insn "*cmpsi_shiftsi_swp"
bd5b4116 8302 [(set (reg:CC_SWP CC_REGNUM)
aea4c774 8303 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
d82e788e 8304 [(match_operand:SI 1 "s_register_operand" "r,r,r")
8305 (match_operand:SI 2 "shift_amount_operand" "M,r,M")])
8306 (match_operand:SI 0 "s_register_operand" "r,r,r")))]
d5d4dc8d 8307 "TARGET_32BIT"
aea4c774 8308 "cmp%?\\t%0, %1%S3"
344495ea 8309 [(set_attr "conds" "set")
331beb1a 8310 (set_attr "shift" "1")
d82e788e 8311 (set_attr "arch" "32,a,a")
8312 (set_attr "type" "alus_shift_imm,alu_shift_reg,alus_shift_imm")])
b11cae9e 8313
25f905c2 8314(define_insn "*arm_cmpsi_negshiftsi_si"
aed179ae 8315 [(set (reg:CC_Z CC_REGNUM)
8316 (compare:CC_Z
8317 (neg:SI (match_operator:SI 1 "shift_operator"
8318 [(match_operand:SI 2 "s_register_operand" "r")
8319 (match_operand:SI 3 "reg_or_int_operand" "rM")]))
8320 (match_operand:SI 0 "s_register_operand" "r")))]
cffb2a26 8321 "TARGET_ARM"
aed179ae 8322 "cmn%?\\t%0, %2%S1"
344495ea 8323 [(set_attr "conds" "set")
aed179ae 8324 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
d82e788e 8325 (const_string "alus_shift_imm")
8326 (const_string "alus_shift_reg")))
596e5e8f 8327 (set_attr "predicable" "yes")]
0d66636f 8328)
b11cae9e 8329
a8045a4f 8330;; DImode comparisons. The generic code generates branches that
8331;; if-conversion can not reduce to a conditional compare, so we do
8332;; that directly.
8333
ba6a3b2f 8334(define_insn_and_split "*arm_cmpdi_insn"
a8045a4f 8335 [(set (reg:CC_NCV CC_REGNUM)
8336 (compare:CC_NCV (match_operand:DI 0 "s_register_operand" "r")
8337 (match_operand:DI 1 "arm_di_operand" "rDi")))
8338 (clobber (match_scratch:SI 2 "=r"))]
b805622c 8339 "TARGET_32BIT"
ba6a3b2f 8340 "#" ; "cmp\\t%Q0, %Q1\;sbcs\\t%2, %R0, %R1"
8341 "&& reload_completed"
8342 [(set (reg:CC CC_REGNUM)
8343 (compare:CC (match_dup 0) (match_dup 1)))
8344 (parallel [(set (reg:CC CC_REGNUM)
8345 (compare:CC (match_dup 3) (match_dup 4)))
8346 (set (match_dup 2)
8347 (minus:SI (match_dup 5)
8348 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))])]
8349 {
8350 operands[3] = gen_highpart (SImode, operands[0]);
8351 operands[0] = gen_lowpart (SImode, operands[0]);
8352 if (CONST_INT_P (operands[1]))
8353 {
8354 operands[4] = GEN_INT (~INTVAL (gen_highpart_mode (SImode,
8355 DImode,
8356 operands[1])));
8357 operands[5] = gen_rtx_PLUS (SImode, operands[3], operands[4]);
8358 }
8359 else
8360 {
8361 operands[4] = gen_highpart (SImode, operands[1]);
8362 operands[5] = gen_rtx_MINUS (SImode, operands[3], operands[4]);
8363 }
8364 operands[1] = gen_lowpart (SImode, operands[1]);
8365 operands[2] = gen_lowpart (SImode, operands[2]);
8366 }
a8045a4f 8367 [(set_attr "conds" "set")
1b7da4ac 8368 (set_attr "length" "8")
8369 (set_attr "type" "multiple")]
a8045a4f 8370)
8371
ba6a3b2f 8372(define_insn_and_split "*arm_cmpdi_unsigned"
a8045a4f 8373 [(set (reg:CC_CZ CC_REGNUM)
7c36fe71 8374 (compare:CC_CZ (match_operand:DI 0 "s_register_operand" "l,r,r")
8375 (match_operand:DI 1 "arm_di_operand" "Py,r,rDi")))]
8376
48a98053 8377 "TARGET_32BIT"
ba6a3b2f 8378 "#" ; "cmp\\t%R0, %R1\;it eq\;cmpeq\\t%Q0, %Q1"
8379 "&& reload_completed"
8380 [(set (reg:CC CC_REGNUM)
8381 (compare:CC (match_dup 2) (match_dup 3)))
8382 (cond_exec (eq:SI (reg:CC CC_REGNUM) (const_int 0))
8383 (set (reg:CC CC_REGNUM)
8384 (compare:CC (match_dup 0) (match_dup 1))))]
8385 {
8386 operands[2] = gen_highpart (SImode, operands[0]);
8387 operands[0] = gen_lowpart (SImode, operands[0]);
8388 if (CONST_INT_P (operands[1]))
8389 operands[3] = gen_highpart_mode (SImode, DImode, operands[1]);
8390 else
8391 operands[3] = gen_highpart (SImode, operands[1]);
8392 operands[1] = gen_lowpart (SImode, operands[1]);
8393 }
a8045a4f 8394 [(set_attr "conds" "set")
7c36fe71 8395 (set_attr "enabled_for_depr_it" "yes,yes,no")
8396 (set_attr "arch" "t2,t2,*")
1b7da4ac 8397 (set_attr "length" "6,6,8")
8398 (set_attr "type" "multiple")]
a8045a4f 8399)
8400
8401(define_insn "*arm_cmpdi_zero"
8402 [(set (reg:CC_Z CC_REGNUM)
8403 (compare:CC_Z (match_operand:DI 0 "s_register_operand" "r")
8404 (const_int 0)))
8405 (clobber (match_scratch:SI 1 "=r"))]
8406 "TARGET_32BIT"
8407 "orr%.\\t%1, %Q0, %R0"
1b7da4ac 8408 [(set_attr "conds" "set")
8409 (set_attr "type" "logics_reg")]
a8045a4f 8410)
8411
8412(define_insn "*thumb_cmpdi_zero"
8413 [(set (reg:CC_Z CC_REGNUM)
8414 (compare:CC_Z (match_operand:DI 0 "s_register_operand" "l")
8415 (const_int 0)))
8416 (clobber (match_scratch:SI 1 "=l"))]
8417 "TARGET_THUMB1"
8418 "orr\\t%1, %Q0, %R0"
8419 [(set_attr "conds" "set")
1b7da4ac 8420 (set_attr "length" "2")
8421 (set_attr "type" "logics_reg")]
a8045a4f 8422)
8423
9c08d1fa 8424; This insn allows redundant compares to be removed by cse, nothing should
8425; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
8426; is deleted later on. The match_dup will match the mode here, so that
8427; mode changes of the condition codes aren't lost by this even though we don't
8428; specify what they are.
8429
8a18b90c 8430(define_insn "*deleted_compare"
9c08d1fa 8431 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
25f905c2 8432 "TARGET_32BIT"
40dbec34 8433 "\\t%@ deleted compare"
cffb2a26 8434 [(set_attr "conds" "set")
1b7da4ac 8435 (set_attr "length" "0")
8436 (set_attr "type" "no_insn")]
cffb2a26 8437)
9c08d1fa 8438
8439\f
8440;; Conditional branch insns
8441
74f4459c 8442(define_expand "cbranch_cc"
9c08d1fa 8443 [(set (pc)
74f4459c 8444 (if_then_else (match_operator 0 "" [(match_operand 1 "" "")
8445 (match_operand 2 "" "")])
8446 (label_ref (match_operand 3 "" ""))
9c08d1fa 8447 (pc)))]
25f905c2 8448 "TARGET_32BIT"
74f4459c 8449 "operands[1] = arm_gen_compare_reg (GET_CODE (operands[0]),
e1b93706 8450 operands[1], operands[2], NULL_RTX);
74f4459c 8451 operands[2] = const0_rtx;"
8fa3ba89 8452)
8453
8454;;
8455;; Patterns to match conditional branch insns.
8456;;
8457
ffcc986d 8458(define_insn "arm_cond_branch"
9c08d1fa 8459 [(set (pc)
8fa3ba89 8460 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 8461 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 8462 (label_ref (match_operand 0 "" ""))
8463 (pc)))]
25f905c2 8464 "TARGET_32BIT"
d75350ce 8465 "*
9c08d1fa 8466 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 8467 {
8468 arm_ccfsm_state += 2;
8469 return \"\";
8470 }
e2348bcb 8471 return \"b%d1\\t%l0\";
cffb2a26 8472 "
a2cd141b 8473 [(set_attr "conds" "use")
a6864a24 8474 (set_attr "type" "branch")
8475 (set (attr "length")
8476 (if_then_else
0bf497f5 8477 (and (match_test "TARGET_THUMB2")
a6864a24 8478 (and (ge (minus (match_dup 0) (pc)) (const_int -250))
8479 (le (minus (match_dup 0) (pc)) (const_int 256))))
8480 (const_int 2)
8481 (const_int 4)))]
cffb2a26 8482)
d75350ce 8483
cffb2a26 8484(define_insn "*arm_cond_branch_reversed"
9c08d1fa 8485 [(set (pc)
8fa3ba89 8486 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 8487 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 8488 (pc)
8489 (label_ref (match_operand 0 "" ""))))]
25f905c2 8490 "TARGET_32BIT"
d75350ce 8491 "*
9c08d1fa 8492 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 8493 {
8494 arm_ccfsm_state += 2;
8495 return \"\";
8496 }
e2348bcb 8497 return \"b%D1\\t%l0\";
cffb2a26 8498 "
a2cd141b 8499 [(set_attr "conds" "use")
a6864a24 8500 (set_attr "type" "branch")
8501 (set (attr "length")
8502 (if_then_else
0bf497f5 8503 (and (match_test "TARGET_THUMB2")
a6864a24 8504 (and (ge (minus (match_dup 0) (pc)) (const_int -250))
8505 (le (minus (match_dup 0) (pc)) (const_int 256))))
8506 (const_int 2)
8507 (const_int 4)))]
cffb2a26 8508)
8509
b11cae9e 8510\f
9c08d1fa 8511
8512; scc insns
8513
74f4459c 8514(define_expand "cstore_cc"
7db9af5d 8515 [(set (match_operand:SI 0 "s_register_operand" "")
74f4459c 8516 (match_operator:SI 1 "" [(match_operand 2 "" "")
8517 (match_operand 3 "" "")]))]
25f905c2 8518 "TARGET_32BIT"
74f4459c 8519 "operands[2] = arm_gen_compare_reg (GET_CODE (operands[1]),
e1b93706 8520 operands[2], operands[3], NULL_RTX);
74f4459c 8521 operands[3] = const0_rtx;"
8fa3ba89 8522)
8523
a3b84066 8524(define_insn_and_split "*mov_scc"
9c08d1fa 8525 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 8526 (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 8527 [(match_operand 2 "cc_register" "") (const_int 0)]))]
cffb2a26 8528 "TARGET_ARM"
a3b84066 8529 "#" ; "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
8530 "TARGET_ARM"
8531 [(set (match_dup 0)
8532 (if_then_else:SI (match_dup 1)
8533 (const_int 1)
8534 (const_int 0)))]
8535 ""
cffb2a26 8536 [(set_attr "conds" "use")
1b7da4ac 8537 (set_attr "length" "8")
8538 (set_attr "type" "multiple")]
cffb2a26 8539)
9c08d1fa 8540
a3b84066 8541(define_insn_and_split "*mov_negscc"
9c08d1fa 8542 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 8543 (neg:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 8544 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 8545 "TARGET_ARM"
a3b84066 8546 "#" ; "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
8547 "TARGET_ARM"
8548 [(set (match_dup 0)
8549 (if_then_else:SI (match_dup 1)
8550 (match_dup 3)
8551 (const_int 0)))]
8552 {
8553 operands[3] = GEN_INT (~0);
8554 }
cffb2a26 8555 [(set_attr "conds" "use")
1b7da4ac 8556 (set_attr "length" "8")
8557 (set_attr "type" "multiple")]
cffb2a26 8558)
9c08d1fa 8559
a3b84066 8560(define_insn_and_split "*mov_notscc"
9c08d1fa 8561 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 8562 (not:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 8563 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 8564 "TARGET_ARM"
a3b84066 8565 "#" ; "mvn%D1\\t%0, #0\;mvn%d1\\t%0, #1"
8566 "TARGET_ARM"
8567 [(set (match_dup 0)
8568 (if_then_else:SI (match_dup 1)
8569 (match_dup 3)
8570 (match_dup 4)))]
8571 {
8572 operands[3] = GEN_INT (~1);
8573 operands[4] = GEN_INT (~0);
8574 }
cffb2a26 8575 [(set_attr "conds" "use")
1b7da4ac 8576 (set_attr "length" "8")
8577 (set_attr "type" "multiple")]
cffb2a26 8578)
9c08d1fa 8579
595d88b5 8580(define_expand "cstoresi4"
8581 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 8582 (match_operator:SI 1 "expandable_comparison_operator"
595d88b5 8583 [(match_operand:SI 2 "s_register_operand" "")
8584 (match_operand:SI 3 "reg_or_int_operand" "")]))]
74f4459c 8585 "TARGET_32BIT || TARGET_THUMB1"
595d88b5 8586 "{
8587 rtx op3, scratch, scratch2;
8588
74f4459c 8589 if (!TARGET_THUMB1)
8590 {
8591 if (!arm_add_operand (operands[3], SImode))
8592 operands[3] = force_reg (SImode, operands[3]);
8593 emit_insn (gen_cstore_cc (operands[0], operands[1],
8594 operands[2], operands[3]));
8595 DONE;
8596 }
8597
595d88b5 8598 if (operands[3] == const0_rtx)
8599 {
8600 switch (GET_CODE (operands[1]))
8601 {
8602 case EQ:
25f905c2 8603 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], operands[2]));
595d88b5 8604 break;
8605
8606 case NE:
25f905c2 8607 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], operands[2]));
595d88b5 8608 break;
8609
8610 case LE:
8611 scratch = expand_binop (SImode, add_optab, operands[2], constm1_rtx,
8612 NULL_RTX, 0, OPTAB_WIDEN);
8613 scratch = expand_binop (SImode, ior_optab, operands[2], scratch,
8614 NULL_RTX, 0, OPTAB_WIDEN);
8615 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
8616 operands[0], 1, OPTAB_WIDEN);
8617 break;
8618
8619 case GE:
8620 scratch = expand_unop (SImode, one_cmpl_optab, operands[2],
8621 NULL_RTX, 1);
8622 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
8623 NULL_RTX, 1, OPTAB_WIDEN);
8624 break;
8625
8626 case GT:
8627 scratch = expand_binop (SImode, ashr_optab, operands[2],
8628 GEN_INT (31), NULL_RTX, 0, OPTAB_WIDEN);
8629 scratch = expand_binop (SImode, sub_optab, scratch, operands[2],
8630 NULL_RTX, 0, OPTAB_WIDEN);
8631 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31), operands[0],
8632 0, OPTAB_WIDEN);
8633 break;
8634
8635 /* LT is handled by generic code. No need for unsigned with 0. */
8636 default:
8637 FAIL;
8638 }
8639 DONE;
8640 }
8641
8642 switch (GET_CODE (operands[1]))
8643 {
8644 case EQ:
8645 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
8646 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 8647 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], scratch));
595d88b5 8648 break;
8649
8650 case NE:
8651 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
8652 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 8653 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], scratch));
595d88b5 8654 break;
8655
8656 case LE:
8657 op3 = force_reg (SImode, operands[3]);
8658
8659 scratch = expand_binop (SImode, lshr_optab, operands[2], GEN_INT (31),
8660 NULL_RTX, 1, OPTAB_WIDEN);
8661 scratch2 = expand_binop (SImode, ashr_optab, op3, GEN_INT (31),
8662 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 8663 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
595d88b5 8664 op3, operands[2]));
8665 break;
8666
8667 case GE:
8668 op3 = operands[3];
25f905c2 8669 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 8670 op3 = force_reg (SImode, op3);
8671 scratch = expand_binop (SImode, ashr_optab, operands[2], GEN_INT (31),
8672 NULL_RTX, 0, OPTAB_WIDEN);
8673 scratch2 = expand_binop (SImode, lshr_optab, op3, GEN_INT (31),
8674 NULL_RTX, 1, OPTAB_WIDEN);
25f905c2 8675 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
595d88b5 8676 operands[2], op3));
8677 break;
8678
8679 case LEU:
8680 op3 = force_reg (SImode, operands[3]);
8681 scratch = force_reg (SImode, const0_rtx);
25f905c2 8682 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
595d88b5 8683 op3, operands[2]));
8684 break;
8685
8686 case GEU:
8687 op3 = operands[3];
25f905c2 8688 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 8689 op3 = force_reg (SImode, op3);
8690 scratch = force_reg (SImode, const0_rtx);
25f905c2 8691 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
595d88b5 8692 operands[2], op3));
8693 break;
8694
8695 case LTU:
8696 op3 = operands[3];
25f905c2 8697 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 8698 op3 = force_reg (SImode, op3);
8699 scratch = gen_reg_rtx (SImode);
408b7ae5 8700 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], operands[2], op3));
595d88b5 8701 break;
8702
8703 case GTU:
8704 op3 = force_reg (SImode, operands[3]);
8705 scratch = gen_reg_rtx (SImode);
408b7ae5 8706 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], op3, operands[2]));
595d88b5 8707 break;
8708
8709 /* No good sequences for GT, LT. */
8710 default:
8711 FAIL;
8712 }
8713 DONE;
8714}")
8715
74f4459c 8716(define_expand "cstoresf4"
8717 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 8718 (match_operator:SI 1 "expandable_comparison_operator"
74f4459c 8719 [(match_operand:SF 2 "s_register_operand" "")
8720 (match_operand:SF 3 "arm_float_compare_operand" "")]))]
8721 "TARGET_32BIT && TARGET_HARD_FLOAT"
8722 "emit_insn (gen_cstore_cc (operands[0], operands[1],
8723 operands[2], operands[3])); DONE;"
8724)
8725
8726(define_expand "cstoredf4"
8727 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 8728 (match_operator:SI 1 "expandable_comparison_operator"
74f4459c 8729 [(match_operand:DF 2 "s_register_operand" "")
8730 (match_operand:DF 3 "arm_float_compare_operand" "")]))]
d63ed457 8731 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
74f4459c 8732 "emit_insn (gen_cstore_cc (operands[0], operands[1],
8733 operands[2], operands[3])); DONE;"
8734)
8735
74f4459c 8736(define_expand "cstoredi4"
8737 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 8738 (match_operator:SI 1 "expandable_comparison_operator"
b8eae306 8739 [(match_operand:DI 2 "s_register_operand" "")
a8045a4f 8740 (match_operand:DI 3 "cmpdi_operand" "")]))]
8741 "TARGET_32BIT"
8742 "{
f9aa4160 8743 if (!arm_validize_comparison (&operands[1],
8744 &operands[2],
8745 &operands[3]))
8746 FAIL;
8747 emit_insn (gen_cstore_cc (operands[0], operands[1], operands[2],
a8045a4f 8748 operands[3]));
8749 DONE;
8750 }"
74f4459c 8751)
8752
25f905c2 8753(define_expand "cstoresi_eq0_thumb1"
595d88b5 8754 [(parallel
8755 [(set (match_operand:SI 0 "s_register_operand" "")
8756 (eq:SI (match_operand:SI 1 "s_register_operand" "")
8757 (const_int 0)))
8758 (clobber (match_dup:SI 2))])]
25f905c2 8759 "TARGET_THUMB1"
595d88b5 8760 "operands[2] = gen_reg_rtx (SImode);"
8761)
8762
25f905c2 8763(define_expand "cstoresi_ne0_thumb1"
595d88b5 8764 [(parallel
8765 [(set (match_operand:SI 0 "s_register_operand" "")
8766 (ne:SI (match_operand:SI 1 "s_register_operand" "")
8767 (const_int 0)))
8768 (clobber (match_dup:SI 2))])]
25f905c2 8769 "TARGET_THUMB1"
595d88b5 8770 "operands[2] = gen_reg_rtx (SImode);"
8771)
8772
25f905c2 8773(define_insn "*cstoresi_eq0_thumb1_insn"
595d88b5 8774 [(set (match_operand:SI 0 "s_register_operand" "=&l,l")
8775 (eq:SI (match_operand:SI 1 "s_register_operand" "l,0")
8776 (const_int 0)))
8777 (clobber (match_operand:SI 2 "s_register_operand" "=X,l"))]
25f905c2 8778 "TARGET_THUMB1"
595d88b5 8779 "@
8780 neg\\t%0, %1\;adc\\t%0, %0, %1
8781 neg\\t%2, %1\;adc\\t%0, %1, %2"
1b7da4ac 8782 [(set_attr "length" "4")
8783 (set_attr "type" "multiple")]
595d88b5 8784)
8785
25f905c2 8786(define_insn "*cstoresi_ne0_thumb1_insn"
595d88b5 8787 [(set (match_operand:SI 0 "s_register_operand" "=l")
8788 (ne:SI (match_operand:SI 1 "s_register_operand" "0")
8789 (const_int 0)))
8790 (clobber (match_operand:SI 2 "s_register_operand" "=l"))]
25f905c2 8791 "TARGET_THUMB1"
595d88b5 8792 "sub\\t%2, %1, #1\;sbc\\t%0, %1, %2"
8793 [(set_attr "length" "4")]
8794)
8795
408b7ae5 8796;; Used as part of the expansion of thumb ltu and gtu sequences
25f905c2 8797(define_insn "cstoresi_nltu_thumb1"
595d88b5 8798 [(set (match_operand:SI 0 "s_register_operand" "=l,l")
a277ddf3 8799 (neg:SI (ltu:SI (match_operand:SI 1 "s_register_operand" "l,*h")
25f905c2 8800 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r"))))]
8801 "TARGET_THUMB1"
595d88b5 8802 "cmp\\t%1, %2\;sbc\\t%0, %0, %0"
1b7da4ac 8803 [(set_attr "length" "4")
8804 (set_attr "type" "multiple")]
595d88b5 8805)
8806
408b7ae5 8807(define_insn_and_split "cstoresi_ltu_thumb1"
8808 [(set (match_operand:SI 0 "s_register_operand" "=l,l")
8809 (ltu:SI (match_operand:SI 1 "s_register_operand" "l,*h")
8810 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r")))]
8811 "TARGET_THUMB1"
8812 "#"
8813 "TARGET_THUMB1"
8814 [(set (match_dup 3)
8815 (neg:SI (ltu:SI (match_dup 1) (match_dup 2))))
8816 (set (match_dup 0) (neg:SI (match_dup 3)))]
8817 "operands[3] = gen_reg_rtx (SImode);"
1b7da4ac 8818 [(set_attr "length" "4")
8819 (set_attr "type" "multiple")]
408b7ae5 8820)
8821
595d88b5 8822;; Used as part of the expansion of thumb les sequence.
25f905c2 8823(define_insn "thumb1_addsi3_addgeu"
595d88b5 8824 [(set (match_operand:SI 0 "s_register_operand" "=l")
8825 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8826 (match_operand:SI 2 "s_register_operand" "l"))
8827 (geu:SI (match_operand:SI 3 "s_register_operand" "l")
25f905c2 8828 (match_operand:SI 4 "thumb1_cmp_operand" "lI"))))]
8829 "TARGET_THUMB1"
595d88b5 8830 "cmp\\t%3, %4\;adc\\t%0, %1, %2"
1b7da4ac 8831 [(set_attr "length" "4")
8832 (set_attr "type" "multiple")]
595d88b5 8833)
8834
9c08d1fa 8835\f
39b5e676 8836;; Conditional move insns
8837
8838(define_expand "movsicc"
8a18b90c 8839 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 8840 (if_then_else:SI (match_operand 1 "expandable_comparison_operator" "")
aea4c774 8841 (match_operand:SI 2 "arm_not_operand" "")
8a18b90c 8842 (match_operand:SI 3 "arm_not_operand" "")))]
25f905c2 8843 "TARGET_32BIT"
39b5e676 8844 "
215b30b3 8845 {
f9aa4160 8846 enum rtx_code code;
278b301d 8847 rtx ccreg;
8848
f9aa4160 8849 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
8850 &XEXP (operands[1], 1)))
278b301d 8851 FAIL;
f9aa4160 8852
8853 code = GET_CODE (operands[1]);
74f4459c 8854 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
e1b93706 8855 XEXP (operands[1], 1), NULL_RTX);
29bb088d 8856 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 8857 }"
8858)
39b5e676 8859
8860(define_expand "movsfcc"
8a18b90c 8861 [(set (match_operand:SF 0 "s_register_operand" "")
4df97ffc 8862 (if_then_else:SF (match_operand 1 "arm_cond_move_operator" "")
8a18b90c 8863 (match_operand:SF 2 "s_register_operand" "")
d86c91f6 8864 (match_operand:SF 3 "s_register_operand" "")))]
19f6bf8d 8865 "TARGET_32BIT && TARGET_HARD_FLOAT"
39b5e676 8866 "
215b30b3 8867 {
8868 enum rtx_code code = GET_CODE (operands[1]);
8869 rtx ccreg;
f082f1c4 8870
f9aa4160 8871 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
8872 &XEXP (operands[1], 1)))
8873 FAIL;
39b5e676 8874
f9aa4160 8875 code = GET_CODE (operands[1]);
74f4459c 8876 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
e1b93706 8877 XEXP (operands[1], 1), NULL_RTX);
29bb088d 8878 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 8879 }"
8880)
39b5e676 8881
8882(define_expand "movdfcc"
8a18b90c 8883 [(set (match_operand:DF 0 "s_register_operand" "")
4df97ffc 8884 (if_then_else:DF (match_operand 1 "arm_cond_move_operator" "")
8a18b90c 8885 (match_operand:DF 2 "s_register_operand" "")
d86c91f6 8886 (match_operand:DF 3 "s_register_operand" "")))]
994606f8 8887 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
39b5e676 8888 "
215b30b3 8889 {
8890 enum rtx_code code = GET_CODE (operands[1]);
278b301d 8891 rtx ccreg;
39b5e676 8892
f9aa4160 8893 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
8894 &XEXP (operands[1], 1)))
8895 FAIL;
8896 code = GET_CODE (operands[1]);
74f4459c 8897 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
e1b93706 8898 XEXP (operands[1], 1), NULL_RTX);
29bb088d 8899 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 8900 }"
8901)
39b5e676 8902
91cb50d2 8903(define_insn "*cmov<mode>"
8904 [(set (match_operand:SDF 0 "s_register_operand" "=<F_constraint>")
8905 (if_then_else:SDF (match_operator 1 "arm_vsel_comparison_operator"
8906 [(match_operand 2 "cc_register" "") (const_int 0)])
8907 (match_operand:SDF 3 "s_register_operand"
8908 "<F_constraint>")
8909 (match_operand:SDF 4 "s_register_operand"
8910 "<F_constraint>")))]
8911 "TARGET_HARD_FLOAT && TARGET_FPU_ARMV8 <vfp_double_cond>"
8912 "*
8913 {
8914 enum arm_cond_code code = maybe_get_arm_condition_code (operands[1]);
8915 switch (code)
8916 {
8917 case ARM_GE:
8918 case ARM_GT:
8919 case ARM_EQ:
8920 case ARM_VS:
8921 return \"vsel%d1.<V_if_elem>\\t%<V_reg>0, %<V_reg>3, %<V_reg>4\";
8922 case ARM_LT:
8923 case ARM_LE:
8924 case ARM_NE:
8925 case ARM_VC:
8926 return \"vsel%D1.<V_if_elem>\\t%<V_reg>0, %<V_reg>4, %<V_reg>3\";
8927 default:
8928 gcc_unreachable ();
8929 }
8930 return \"\";
8931 }"
8932 [(set_attr "conds" "use")
8933 (set_attr "type" "f_sel<vfp_type>")]
8934)
8935
190efb17 8936(define_insn_and_split "*movsicc_insn"
f082f1c4 8937 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
8a18b90c 8938 (if_then_else:SI
8fa3ba89 8939 (match_operator 3 "arm_comparison_operator"
8a18b90c 8940 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 8941 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
8942 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
cffb2a26 8943 "TARGET_ARM"
39b5e676 8944 "@
8a18b90c 8945 mov%D3\\t%0, %2
8946 mvn%D3\\t%0, #%B2
f082f1c4 8947 mov%d3\\t%0, %1
8948 mvn%d3\\t%0, #%B1
190efb17 8949 #
8950 #
8951 #
8952 #"
8953 ; alt4: mov%d3\\t%0, %1\;mov%D3\\t%0, %2
8954 ; alt5: mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
8955 ; alt6: mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
8956 ; alt7: mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
8957 "&& reload_completed"
8958 [(const_int 0)]
8959 {
8960 enum rtx_code rev_code;
8961 enum machine_mode mode;
8962 rtx rev_cond;
8963
8964 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
8965 operands[3],
8966 gen_rtx_SET (VOIDmode,
8967 operands[0],
8968 operands[1])));
8969
8970 rev_code = GET_CODE (operands[3]);
8971 mode = GET_MODE (operands[4]);
8972 if (mode == CCFPmode || mode == CCFPEmode)
8973 rev_code = reverse_condition_maybe_unordered (rev_code);
8974 else
8975 rev_code = reverse_condition (rev_code);
8976
8977 rev_cond = gen_rtx_fmt_ee (rev_code,
8978 VOIDmode,
8979 operands[4],
8980 const0_rtx);
8981 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
8982 rev_cond,
8983 gen_rtx_SET (VOIDmode,
8984 operands[0],
8985 operands[2])));
8986 DONE;
8987 }
f082f1c4 8988 [(set_attr "length" "4,4,4,4,8,8,8,8")
d2a518d1 8989 (set_attr "conds" "use")
65f68e55 8990 (set_attr_alternative "type"
8991 [(if_then_else (match_operand 2 "const_int_operand" "")
1aed5204 8992 (const_string "mov_imm")
8993 (const_string "mov_reg"))
8994 (const_string "mvn_imm")
65f68e55 8995 (if_then_else (match_operand 1 "const_int_operand" "")
1aed5204 8996 (const_string "mov_imm")
8997 (const_string "mov_reg"))
8998 (const_string "mvn_imm")
8999 (const_string "mov_reg")
9000 (const_string "mov_reg")
9001 (const_string "mov_reg")
9002 (const_string "mov_reg")])]
215b30b3 9003)
39b5e676 9004
39b5e676 9005(define_insn "*movsfcc_soft_insn"
f082f1c4 9006 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
8fa3ba89 9007 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
8a18b90c 9008 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 9009 (match_operand:SF 1 "s_register_operand" "0,r")
9010 (match_operand:SF 2 "s_register_operand" "r,0")))]
cffb2a26 9011 "TARGET_ARM && TARGET_SOFT_FLOAT"
f082f1c4 9012 "@
9013 mov%D3\\t%0, %2
9014 mov%d3\\t%0, %1"
d2a518d1 9015 [(set_attr "conds" "use")
1aed5204 9016 (set_attr "type" "mov_reg")]
8fa3ba89 9017)
39b5e676 9018
39b5e676 9019\f
9c08d1fa 9020;; Jump and linkage insns
9021
cffb2a26 9022(define_expand "jump"
9c08d1fa 9023 [(set (pc)
9024 (label_ref (match_operand 0 "" "")))]
cffb2a26 9025 "TARGET_EITHER"
9c08d1fa 9026 ""
cffb2a26 9027)
9028
9029(define_insn "*arm_jump"
9030 [(set (pc)
9031 (label_ref (match_operand 0 "" "")))]
25f905c2 9032 "TARGET_32BIT"
9c08d1fa 9033 "*
0d66636f 9034 {
9035 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
9036 {
9037 arm_ccfsm_state += 2;
9038 return \"\";
9039 }
9040 return \"b%?\\t%l0\";
9041 }
9042 "
a6864a24 9043 [(set_attr "predicable" "yes")
9044 (set (attr "length")
9045 (if_then_else
0bf497f5 9046 (and (match_test "TARGET_THUMB2")
a6864a24 9047 (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
9048 (le (minus (match_dup 0) (pc)) (const_int 2048))))
9049 (const_int 2)
1b7da4ac 9050 (const_int 4)))
9051 (set_attr "type" "branch")]
0d66636f 9052)
9c08d1fa 9053
cffb2a26 9054(define_insn "*thumb_jump"
9055 [(set (pc)
9056 (label_ref (match_operand 0 "" "")))]
25f905c2 9057 "TARGET_THUMB1"
cffb2a26 9058 "*
9059 if (get_attr_length (insn) == 2)
9060 return \"b\\t%l0\";
9061 return \"bl\\t%l0\\t%@ far jump\";
9062 "
9063 [(set (attr "far_jump")
9064 (if_then_else
9065 (eq_attr "length" "4")
9066 (const_string "yes")
9067 (const_string "no")))
9068 (set (attr "length")
9069 (if_then_else
911ed8af 9070 (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
9071 (le (minus (match_dup 0) (pc)) (const_int 2048)))
cffb2a26 9072 (const_int 2)
1b7da4ac 9073 (const_int 4)))
9074 (set_attr "type" "branch")]
cffb2a26 9075)
9076
d3373b54 9077(define_expand "call"
9078 [(parallel [(call (match_operand 0 "memory_operand" "")
9079 (match_operand 1 "general_operand" ""))
cffb2a26 9080 (use (match_operand 2 "" ""))
bd5b4116 9081 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 9082 "TARGET_EITHER"
6c4c2133 9083 "
9084 {
bac7fc85 9085 rtx callee, pat;
bbe777ea 9086
bbe777ea 9087 /* In an untyped call, we can get NULL for operand 2. */
9088 if (operands[2] == NULL_RTX)
9089 operands[2] = const0_rtx;
9090
de55252a 9091 /* Decide if we should generate indirect calls by loading the
85c36fd1 9092 32-bit address of the callee into a register before performing the
de55252a 9093 branch and link. */
9094 callee = XEXP (operands[0], 0);
9095 if (GET_CODE (callee) == SYMBOL_REF
9096 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
9097 : !REG_P (callee))
bbe777ea 9098 XEXP (operands[0], 0) = force_reg (Pmode, callee);
bac7fc85 9099
9100 pat = gen_call_internal (operands[0], operands[1], operands[2]);
9101 arm_emit_call_insn (pat, XEXP (operands[0], 0));
9102 DONE;
6c4c2133 9103 }"
9104)
d3373b54 9105
bac7fc85 9106(define_expand "call_internal"
9107 [(parallel [(call (match_operand 0 "memory_operand" "")
9108 (match_operand 1 "general_operand" ""))
9109 (use (match_operand 2 "" ""))
9110 (clobber (reg:SI LR_REGNUM))])])
9111
f1039640 9112(define_insn "*call_reg_armv5"
d3373b54 9113 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
cffb2a26 9114 (match_operand 1 "" ""))
9115 (use (match_operand 2 "" ""))
bd5b4116 9116 (clobber (reg:SI LR_REGNUM))]
33ae7c4b 9117 "TARGET_ARM && arm_arch5 && !SIBLING_CALL_P (insn)"
f1039640 9118 "blx%?\\t%0"
9119 [(set_attr "type" "call")]
9120)
9121
9122(define_insn "*call_reg_arm"
9123 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
9124 (match_operand 1 "" ""))
9125 (use (match_operand 2 "" ""))
9126 (clobber (reg:SI LR_REGNUM))]
33ae7c4b 9127 "TARGET_ARM && !arm_arch5 && !SIBLING_CALL_P (insn)"
9c08d1fa 9128 "*
5565501b 9129 return output_call (operands);
cffb2a26 9130 "
9131 ;; length is worst case, normally it is only two
9132 [(set_attr "length" "12")
9133 (set_attr "type" "call")]
9134)
9c08d1fa 9135
89504fc1 9136
9137;; Note: not used for armv5+ because the sequence used (ldr pc, ...) is not
9138;; considered a function call by the branch predictor of some cores (PR40887).
9139;; Falls back to blx rN (*call_reg_armv5).
9140
f7fbdd4a 9141(define_insn "*call_mem"
a3c63a9d 9142 [(call (mem:SI (match_operand:SI 0 "call_memory_operand" "m"))
cffb2a26 9143 (match_operand 1 "" ""))
9144 (use (match_operand 2 "" ""))
bd5b4116 9145 (clobber (reg:SI LR_REGNUM))]
33ae7c4b 9146 "TARGET_ARM && !arm_arch5 && !SIBLING_CALL_P (insn)"
9c08d1fa 9147 "*
5565501b 9148 return output_call_mem (operands);
cffb2a26 9149 "
9150 [(set_attr "length" "12")
9151 (set_attr "type" "call")]
9152)
9153
25f905c2 9154(define_insn "*call_reg_thumb1_v5"
cffb2a26 9155 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
9156 (match_operand 1 "" ""))
9157 (use (match_operand 2 "" ""))
bd5b4116 9158 (clobber (reg:SI LR_REGNUM))]
33ae7c4b 9159 "TARGET_THUMB1 && arm_arch5 && !SIBLING_CALL_P (insn)"
f1039640 9160 "blx\\t%0"
9161 [(set_attr "length" "2")
9162 (set_attr "type" "call")]
cffb2a26 9163)
9164
25f905c2 9165(define_insn "*call_reg_thumb1"
f1039640 9166 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
9167 (match_operand 1 "" ""))
9168 (use (match_operand 2 "" ""))
bd5b4116 9169 (clobber (reg:SI LR_REGNUM))]
33ae7c4b 9170 "TARGET_THUMB1 && !arm_arch5 && !SIBLING_CALL_P (insn)"
cffb2a26 9171 "*
9172 {
150502c9 9173 if (!TARGET_CALLER_INTERWORKING)
afe27f3b 9174 return thumb_call_via_reg (operands[0]);
150502c9 9175 else if (operands[1] == const0_rtx)
f1039640 9176 return \"bl\\t%__interwork_call_via_%0\";
150502c9 9177 else if (frame_pointer_needed)
9178 return \"bl\\t%__interwork_r7_call_via_%0\";
cffb2a26 9179 else
150502c9 9180 return \"bl\\t%__interwork_r11_call_via_%0\";
cffb2a26 9181 }"
9182 [(set_attr "type" "call")]
9183)
9c08d1fa 9184
d3373b54 9185(define_expand "call_value"
e0698af7 9186 [(parallel [(set (match_operand 0 "" "")
9187 (call (match_operand 1 "memory_operand" "")
9188 (match_operand 2 "general_operand" "")))
cffb2a26 9189 (use (match_operand 3 "" ""))
bd5b4116 9190 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 9191 "TARGET_EITHER"
6c4c2133 9192 "
9193 {
bac7fc85 9194 rtx pat, callee;
bbe777ea 9195
9196 /* In an untyped call, we can get NULL for operand 2. */
9197 if (operands[3] == 0)
9198 operands[3] = const0_rtx;
9199
de55252a 9200 /* Decide if we should generate indirect calls by loading the
9201 32-bit address of the callee into a register before performing the
9202 branch and link. */
9203 callee = XEXP (operands[1], 0);
9204 if (GET_CODE (callee) == SYMBOL_REF
9205 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
9206 : !REG_P (callee))
78fe751b 9207 XEXP (operands[1], 0) = force_reg (Pmode, callee);
bac7fc85 9208
9209 pat = gen_call_value_internal (operands[0], operands[1],
9210 operands[2], operands[3]);
9211 arm_emit_call_insn (pat, XEXP (operands[1], 0));
9212 DONE;
6c4c2133 9213 }"
9214)
d3373b54 9215
bac7fc85 9216(define_expand "call_value_internal"
9217 [(parallel [(set (match_operand 0 "" "")
9218 (call (match_operand 1 "memory_operand" "")
9219 (match_operand 2 "general_operand" "")))
9220 (use (match_operand 3 "" ""))
9221 (clobber (reg:SI LR_REGNUM))])])
9222
f1039640 9223(define_insn "*call_value_reg_armv5"
27ed6835 9224 [(set (match_operand 0 "" "")
755eb2b4 9225 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
cffb2a26 9226 (match_operand 2 "" "")))
bbe777ea 9227 (use (match_operand 3 "" ""))
bd5b4116 9228 (clobber (reg:SI LR_REGNUM))]
33ae7c4b 9229 "TARGET_ARM && arm_arch5 && !SIBLING_CALL_P (insn)"
f1039640 9230 "blx%?\\t%1"
9231 [(set_attr "type" "call")]
9232)
9233
9234(define_insn "*call_value_reg_arm"
9235 [(set (match_operand 0 "" "")
9236 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
9237 (match_operand 2 "" "")))
9238 (use (match_operand 3 "" ""))
9239 (clobber (reg:SI LR_REGNUM))]
33ae7c4b 9240 "TARGET_ARM && !arm_arch5 && !SIBLING_CALL_P (insn)"
9c08d1fa 9241 "*
215b30b3 9242 return output_call (&operands[1]);
cffb2a26 9243 "
9244 [(set_attr "length" "12")
9245 (set_attr "type" "call")]
9246)
9c08d1fa 9247
89504fc1 9248;; Note: see *call_mem
9249
f7fbdd4a 9250(define_insn "*call_value_mem"
27ed6835 9251 [(set (match_operand 0 "" "")
a3c63a9d 9252 (call (mem:SI (match_operand:SI 1 "call_memory_operand" "m"))
cffb2a26 9253 (match_operand 2 "" "")))
bbe777ea 9254 (use (match_operand 3 "" ""))
bd5b4116 9255 (clobber (reg:SI LR_REGNUM))]
33ae7c4b 9256 "TARGET_ARM && !arm_arch5 && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
9257 && !SIBLING_CALL_P (insn)"
9c08d1fa 9258 "*
215b30b3 9259 return output_call_mem (&operands[1]);
cffb2a26 9260 "
9261 [(set_attr "length" "12")
9262 (set_attr "type" "call")]
9263)
9c08d1fa 9264
25f905c2 9265(define_insn "*call_value_reg_thumb1_v5"
f1039640 9266 [(set (match_operand 0 "" "")
9267 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
9268 (match_operand 2 "" "")))
9269 (use (match_operand 3 "" ""))
9270 (clobber (reg:SI LR_REGNUM))]
25f905c2 9271 "TARGET_THUMB1 && arm_arch5"
f1039640 9272 "blx\\t%1"
9273 [(set_attr "length" "2")
9274 (set_attr "type" "call")]
9275)
9276
25f905c2 9277(define_insn "*call_value_reg_thumb1"
f1039640 9278 [(set (match_operand 0 "" "")
9279 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
9280 (match_operand 2 "" "")))
9281 (use (match_operand 3 "" ""))
9282 (clobber (reg:SI LR_REGNUM))]
25f905c2 9283 "TARGET_THUMB1 && !arm_arch5"
f1039640 9284 "*
9285 {
150502c9 9286 if (!TARGET_CALLER_INTERWORKING)
afe27f3b 9287 return thumb_call_via_reg (operands[1]);
150502c9 9288 else if (operands[2] == const0_rtx)
f1039640 9289 return \"bl\\t%__interwork_call_via_%1\";
150502c9 9290 else if (frame_pointer_needed)
9291 return \"bl\\t%__interwork_r7_call_via_%1\";
f1039640 9292 else
150502c9 9293 return \"bl\\t%__interwork_r11_call_via_%1\";
f1039640 9294 }"
9295 [(set_attr "type" "call")]
9296)
9297
9c08d1fa 9298;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
9299;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
9300
f7fbdd4a 9301(define_insn "*call_symbol"
27ed6835 9302 [(call (mem:SI (match_operand:SI 0 "" ""))
cffb2a26 9303 (match_operand 1 "" ""))
bbe777ea 9304 (use (match_operand 2 "" ""))
bd5b4116 9305 (clobber (reg:SI LR_REGNUM))]
d68c2c10 9306 "TARGET_32BIT
33ae7c4b 9307 && !SIBLING_CALL_P (insn)
cffb2a26 9308 && (GET_CODE (operands[0]) == SYMBOL_REF)
de55252a 9309 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
6ebaa29d 9310 "*
9311 {
55c1e470 9312 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
6ebaa29d 9313 }"
cffb2a26 9314 [(set_attr "type" "call")]
9315)
9c08d1fa 9316
f7fbdd4a 9317(define_insn "*call_value_symbol"
ccd90aaa 9318 [(set (match_operand 0 "" "")
27ed6835 9319 (call (mem:SI (match_operand:SI 1 "" ""))
dd6d7504 9320 (match_operand:SI 2 "" "")))
bbe777ea 9321 (use (match_operand 3 "" ""))
bd5b4116 9322 (clobber (reg:SI LR_REGNUM))]
d68c2c10 9323 "TARGET_32BIT
33ae7c4b 9324 && !SIBLING_CALL_P (insn)
cffb2a26 9325 && (GET_CODE (operands[1]) == SYMBOL_REF)
de55252a 9326 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
6ebaa29d 9327 "*
9328 {
55c1e470 9329 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
6ebaa29d 9330 }"
cffb2a26 9331 [(set_attr "type" "call")]
9332)
9333
9334(define_insn "*call_insn"
27ed6835 9335 [(call (mem:SI (match_operand:SI 0 "" ""))
cffb2a26 9336 (match_operand:SI 1 "" ""))
9337 (use (match_operand 2 "" ""))
bd5b4116 9338 (clobber (reg:SI LR_REGNUM))]
d68c2c10 9339 "TARGET_THUMB1
1675c6e9 9340 && GET_CODE (operands[0]) == SYMBOL_REF
de55252a 9341 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
cffb2a26 9342 "bl\\t%a0"
9343 [(set_attr "length" "4")
9344 (set_attr "type" "call")]
9345)
9346
9347(define_insn "*call_value_insn"
ccd90aaa 9348 [(set (match_operand 0 "" "")
27ed6835 9349 (call (mem:SI (match_operand 1 "" ""))
cffb2a26 9350 (match_operand 2 "" "")))
9351 (use (match_operand 3 "" ""))
bd5b4116 9352 (clobber (reg:SI LR_REGNUM))]
d68c2c10 9353 "TARGET_THUMB1
1675c6e9 9354 && GET_CODE (operands[1]) == SYMBOL_REF
de55252a 9355 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
cffb2a26 9356 "bl\\t%a1"
9357 [(set_attr "length" "4")
9358 (set_attr "type" "call")]
9359)
9c08d1fa 9360
1c494086 9361;; We may also be able to do sibcalls for Thumb, but it's much harder...
9362(define_expand "sibcall"
9363 [(parallel [(call (match_operand 0 "memory_operand" "")
9364 (match_operand 1 "general_operand" ""))
2ba80634 9365 (return)
9366 (use (match_operand 2 "" ""))])]
d68c2c10 9367 "TARGET_32BIT"
1c494086 9368 "
9369 {
3112c3f7 9370 if ((!REG_P (XEXP (operands[0], 0))
9371 && GET_CODE (XEXP (operands[0], 0)) != SYMBOL_REF)
9372 || (GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
9373 && arm_is_long_call_p (SYMBOL_REF_DECL (XEXP (operands[0], 0)))))
33ae7c4b 9374 XEXP (operands[0], 0) = force_reg (SImode, XEXP (operands[0], 0));
9375
1c494086 9376 if (operands[2] == NULL_RTX)
9377 operands[2] = const0_rtx;
1c494086 9378 }"
9379)
9380
9381(define_expand "sibcall_value"
ccd90aaa 9382 [(parallel [(set (match_operand 0 "" "")
1c494086 9383 (call (match_operand 1 "memory_operand" "")
9384 (match_operand 2 "general_operand" "")))
2ba80634 9385 (return)
9386 (use (match_operand 3 "" ""))])]
d68c2c10 9387 "TARGET_32BIT"
1c494086 9388 "
9389 {
3112c3f7 9390 if ((!REG_P (XEXP (operands[1], 0))
9391 && GET_CODE (XEXP (operands[1], 0)) != SYMBOL_REF)
9392 || (GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
9393 && arm_is_long_call_p (SYMBOL_REF_DECL (XEXP (operands[1], 0)))))
33ae7c4b 9394 XEXP (operands[1], 0) = force_reg (SImode, XEXP (operands[1], 0));
9395
1c494086 9396 if (operands[3] == NULL_RTX)
9397 operands[3] = const0_rtx;
1c494086 9398 }"
9399)
9400
9401(define_insn "*sibcall_insn"
84ce8e5c 9402 [(call (mem:SI (match_operand:SI 0 "call_insn_operand" "Cs, US"))
1c494086 9403 (match_operand 1 "" ""))
2ba80634 9404 (return)
9405 (use (match_operand 2 "" ""))]
33ae7c4b 9406 "TARGET_32BIT && SIBLING_CALL_P (insn)"
1c494086 9407 "*
33ae7c4b 9408 if (which_alternative == 1)
9409 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
9410 else
9411 {
9412 if (arm_arch5 || arm_arch4t)
947d113e 9413 return \"bx%?\\t%0\\t%@ indirect register sibling call\";
33ae7c4b 9414 else
9415 return \"mov%?\\t%|pc, %0\\t%@ indirect register sibling call\";
9416 }
1c494086 9417 "
9418 [(set_attr "type" "call")]
9419)
9420
9421(define_insn "*sibcall_value_insn"
84ce8e5c 9422 [(set (match_operand 0 "" "")
9423 (call (mem:SI (match_operand:SI 1 "call_insn_operand" "Cs,US"))
1c494086 9424 (match_operand 2 "" "")))
2ba80634 9425 (return)
9426 (use (match_operand 3 "" ""))]
33ae7c4b 9427 "TARGET_32BIT && SIBLING_CALL_P (insn)"
1c494086 9428 "*
33ae7c4b 9429 if (which_alternative == 1)
9430 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
9431 else
9432 {
9433 if (arm_arch5 || arm_arch4t)
84ce8e5c 9434 return \"bx%?\\t%1\";
33ae7c4b 9435 else
9436 return \"mov%?\\t%|pc, %1\\t@ indirect sibling call \";
9437 }
1c494086 9438 "
9439 [(set_attr "type" "call")]
9440)
9441
0686440e 9442(define_expand "<return_str>return"
9443 [(returns)]
8cba51a5 9444 "(TARGET_ARM || (TARGET_THUMB2
9445 && ARM_FUNC_TYPE (arm_current_func_type ()) == ARM_FT_NORMAL
9446 && !IS_STACKALIGN (arm_current_func_type ())))
0686440e 9447 <return_cond_false>"
8cba51a5 9448 "
9449 {
9450 if (TARGET_THUMB2)
9451 {
0686440e 9452 thumb2_expand_return (<return_simple_p>);
8cba51a5 9453 DONE;
9454 }
9455 }
9456 "
9457)
d68c2c10 9458
9c08d1fa 9459;; Often the return insn will be the same as loading from memory, so set attr
d68c2c10 9460(define_insn "*arm_return"
9c08d1fa 9461 [(return)]
cffb2a26 9462 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
9c08d1fa 9463 "*
9c08d1fa 9464 {
cffb2a26 9465 if (arm_ccfsm_state == 2)
9466 {
9467 arm_ccfsm_state += 2;
9468 return \"\";
9469 }
e2549f81 9470 return output_return_instruction (const_true_rtx, true, false, false);
cffb2a26 9471 }"
a2cd141b 9472 [(set_attr "type" "load1")
755eb2b4 9473 (set_attr "length" "12")
0d66636f 9474 (set_attr "predicable" "yes")]
cffb2a26 9475)
9c08d1fa 9476
0686440e 9477(define_insn "*cond_<return_str>return"
9c08d1fa 9478 [(set (pc)
8fa3ba89 9479 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 9480 [(match_operand 1 "cc_register" "") (const_int 0)])
0686440e 9481 (returns)
9c08d1fa 9482 (pc)))]
0686440e 9483 "TARGET_ARM <return_cond_true>"
9c08d1fa 9484 "*
8fa3ba89 9485 {
9486 if (arm_ccfsm_state == 2)
9487 {
9488 arm_ccfsm_state += 2;
9489 return \"\";
9490 }
0686440e 9491 return output_return_instruction (operands[0], true, false,
9492 <return_simple_p>);
8fa3ba89 9493 }"
9494 [(set_attr "conds" "use")
755eb2b4 9495 (set_attr "length" "12")
a2cd141b 9496 (set_attr "type" "load1")]
8fa3ba89 9497)
9c08d1fa 9498
0686440e 9499(define_insn "*cond_<return_str>return_inverted"
9c08d1fa 9500 [(set (pc)
8fa3ba89 9501 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 9502 [(match_operand 1 "cc_register" "") (const_int 0)])
9c08d1fa 9503 (pc)
0686440e 9504 (returns)))]
9505 "TARGET_ARM <return_cond_true>"
9c08d1fa 9506 "*
8fa3ba89 9507 {
9508 if (arm_ccfsm_state == 2)
9509 {
9510 arm_ccfsm_state += 2;
9511 return \"\";
9512 }
0686440e 9513 return output_return_instruction (operands[0], true, true,
9514 <return_simple_p>);
8fa3ba89 9515 }"
9516 [(set_attr "conds" "use")
37a1317b 9517 (set_attr "length" "12")
a2cd141b 9518 (set_attr "type" "load1")]
8fa3ba89 9519)
9c08d1fa 9520
e2549f81 9521(define_insn "*arm_simple_return"
9522 [(simple_return)]
9523 "TARGET_ARM"
9524 "*
9525 {
9526 if (arm_ccfsm_state == 2)
9527 {
9528 arm_ccfsm_state += 2;
9529 return \"\";
9530 }
9531 return output_return_instruction (const_true_rtx, true, false, true);
9532 }"
9533 [(set_attr "type" "branch")
9534 (set_attr "length" "4")
9535 (set_attr "predicable" "yes")]
9536)
9537
68121397 9538;; Generate a sequence of instructions to determine if the processor is
9539;; in 26-bit or 32-bit mode, and return the appropriate return address
9540;; mask.
9541
9542(define_expand "return_addr_mask"
9543 [(set (match_dup 1)
9544 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
9545 (const_int 0)))
9546 (set (match_operand:SI 0 "s_register_operand" "")
9547 (if_then_else:SI (eq (match_dup 1) (const_int 0))
9548 (const_int -1)
9549 (const_int 67108860)))] ; 0x03fffffc
9550 "TARGET_ARM"
9551 "
62eddbd4 9552 operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
68121397 9553 ")
9554
9555(define_insn "*check_arch2"
9556 [(set (match_operand:CC_NOOV 0 "cc_register" "")
9557 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
9558 (const_int 0)))]
9559 "TARGET_ARM"
9560 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
9561 [(set_attr "length" "8")
1b7da4ac 9562 (set_attr "conds" "set")
9563 (set_attr "type" "multiple")]
68121397 9564)
9565
9c08d1fa 9566;; Call subroutine returning any type.
9567
9568(define_expand "untyped_call"
9569 [(parallel [(call (match_operand 0 "" "")
9570 (const_int 0))
9571 (match_operand 1 "" "")
9572 (match_operand 2 "" "")])]
ccd90aaa 9573 "TARGET_EITHER"
9c08d1fa 9574 "
215b30b3 9575 {
9576 int i;
ccd90aaa 9577 rtx par = gen_rtx_PARALLEL (VOIDmode,
9578 rtvec_alloc (XVECLEN (operands[2], 0)));
9579 rtx addr = gen_reg_rtx (Pmode);
9580 rtx mem;
9581 int size = 0;
9c08d1fa 9582
ccd90aaa 9583 emit_move_insn (addr, XEXP (operands[1], 0));
9584 mem = change_address (operands[1], BLKmode, addr);
9c08d1fa 9585
215b30b3 9586 for (i = 0; i < XVECLEN (operands[2], 0); i++)
9587 {
ccd90aaa 9588 rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
9c08d1fa 9589
ccd90aaa 9590 /* Default code only uses r0 as a return value, but we could
9591 be using anything up to 4 registers. */
9592 if (REGNO (src) == R0_REGNUM)
9593 src = gen_rtx_REG (TImode, R0_REGNUM);
9594
9595 XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
9596 GEN_INT (size));
9597 size += GET_MODE_SIZE (GET_MODE (src));
9598 }
9599
9600 emit_call_insn (GEN_CALL_VALUE (par, operands[0], const0_rtx, NULL,
9601 const0_rtx));
9602
9603 size = 0;
9604
9605 for (i = 0; i < XVECLEN (par, 0); i++)
9606 {
9607 HOST_WIDE_INT offset = 0;
9608 rtx reg = XEXP (XVECEXP (par, 0, i), 0);
9609
9610 if (size != 0)
29c05e22 9611 emit_move_insn (addr, plus_constant (Pmode, addr, size));
ccd90aaa 9612
9613 mem = change_address (mem, GET_MODE (reg), NULL);
9614 if (REGNO (reg) == R0_REGNUM)
9615 {
9616 /* On thumb we have to use a write-back instruction. */
320ea44d 9617 emit_insn (arm_gen_store_multiple (arm_regs_in_sequence, 4, addr,
9618 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
ccd90aaa 9619 size = TARGET_ARM ? 16 : 0;
9620 }
9621 else
9622 {
9623 emit_move_insn (mem, reg);
9624 size = GET_MODE_SIZE (GET_MODE (reg));
9625 }
215b30b3 9626 }
9c08d1fa 9627
215b30b3 9628 /* The optimizer does not know that the call sets the function value
9629 registers we stored in the result block. We avoid problems by
9630 claiming that all hard registers are used and clobbered at this
9631 point. */
9632 emit_insn (gen_blockage ());
9633
9634 DONE;
9635 }"
9636)
9c08d1fa 9637
ccd90aaa 9638(define_expand "untyped_return"
9639 [(match_operand:BLK 0 "memory_operand" "")
9640 (match_operand 1 "" "")]
9641 "TARGET_EITHER"
9642 "
9643 {
9644 int i;
9645 rtx addr = gen_reg_rtx (Pmode);
9646 rtx mem;
9647 int size = 0;
9648
9649 emit_move_insn (addr, XEXP (operands[0], 0));
9650 mem = change_address (operands[0], BLKmode, addr);
9651
9652 for (i = 0; i < XVECLEN (operands[1], 0); i++)
9653 {
9654 HOST_WIDE_INT offset = 0;
9655 rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
9656
9657 if (size != 0)
29c05e22 9658 emit_move_insn (addr, plus_constant (Pmode, addr, size));
ccd90aaa 9659
9660 mem = change_address (mem, GET_MODE (reg), NULL);
9661 if (REGNO (reg) == R0_REGNUM)
9662 {
9663 /* On thumb we have to use a write-back instruction. */
320ea44d 9664 emit_insn (arm_gen_load_multiple (arm_regs_in_sequence, 4, addr,
9665 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
ccd90aaa 9666 size = TARGET_ARM ? 16 : 0;
9667 }
9668 else
9669 {
9670 emit_move_insn (reg, mem);
9671 size = GET_MODE_SIZE (GET_MODE (reg));
9672 }
9673 }
9674
9675 /* Emit USE insns before the return. */
9676 for (i = 0; i < XVECLEN (operands[1], 0); i++)
18b42941 9677 emit_use (SET_DEST (XVECEXP (operands[1], 0, i)));
ccd90aaa 9678
9679 /* Construct the return. */
9680 expand_naked_return ();
9681
9682 DONE;
9683 }"
9684)
9685
9c08d1fa 9686;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
9687;; all of memory. This blocks insns from being moved across this point.
9688
9689(define_insn "blockage"
e1159bbe 9690 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
cffb2a26 9691 "TARGET_EITHER"
9c08d1fa 9692 ""
cffb2a26 9693 [(set_attr "length" "0")
9694 (set_attr "type" "block")]
9695)
9c08d1fa 9696
f7fbdd4a 9697(define_expand "casesi"
9698 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
aea4c774 9699 (match_operand:SI 1 "const_int_operand" "") ; lower bound
9700 (match_operand:SI 2 "const_int_operand" "") ; total range
f7fbdd4a 9701 (match_operand:SI 3 "" "") ; table label
9702 (match_operand:SI 4 "" "")] ; Out of range label
e6ac8414 9703 "TARGET_32BIT || optimize_size || flag_pic"
f7fbdd4a 9704 "
215b30b3 9705 {
e6ac8414 9706 enum insn_code code;
215b30b3 9707 if (operands[1] != const0_rtx)
9708 {
e6ac8414 9709 rtx reg = gen_reg_rtx (SImode);
f7fbdd4a 9710
215b30b3 9711 emit_insn (gen_addsi3 (reg, operands[0],
d022fa24 9712 gen_int_mode (-INTVAL (operands[1]),
9713 SImode)));
215b30b3 9714 operands[0] = reg;
9715 }
9c08d1fa 9716
25f905c2 9717 if (TARGET_ARM)
e6ac8414 9718 code = CODE_FOR_arm_casesi_internal;
3db2019b 9719 else if (TARGET_THUMB1)
e6ac8414 9720 code = CODE_FOR_thumb1_casesi_internal_pic;
25f905c2 9721 else if (flag_pic)
e6ac8414 9722 code = CODE_FOR_thumb2_casesi_internal_pic;
25f905c2 9723 else
e6ac8414 9724 code = CODE_FOR_thumb2_casesi_internal;
9725
9726 if (!insn_data[(int) code].operand[1].predicate(operands[2], SImode))
9727 operands[2] = force_reg (SImode, operands[2]);
9728
9729 emit_jump_insn (GEN_FCN ((int) code) (operands[0], operands[2],
9730 operands[3], operands[4]));
215b30b3 9731 DONE;
9732 }"
9733)
f7fbdd4a 9734
f082f1c4 9735;; The USE in this pattern is needed to tell flow analysis that this is
9736;; a CASESI insn. It has no other purpose.
25f905c2 9737(define_insn "arm_casesi_internal"
f082f1c4 9738 [(parallel [(set (pc)
9739 (if_then_else
9740 (leu (match_operand:SI 0 "s_register_operand" "r")
9741 (match_operand:SI 1 "arm_rhs_operand" "rI"))
9742 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
9743 (label_ref (match_operand 2 "" ""))))
9744 (label_ref (match_operand 3 "" ""))))
bd5b4116 9745 (clobber (reg:CC CC_REGNUM))
f082f1c4 9746 (use (label_ref (match_dup 2)))])]
cffb2a26 9747 "TARGET_ARM"
f7fbdd4a 9748 "*
0d66636f 9749 if (flag_pic)
9750 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
9751 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
9752 "
9753 [(set_attr "conds" "clob")
1b7da4ac 9754 (set_attr "length" "12")
9755 (set_attr "type" "multiple")]
0d66636f 9756)
9c08d1fa 9757
e6ac8414 9758(define_expand "thumb1_casesi_internal_pic"
9759 [(match_operand:SI 0 "s_register_operand" "")
9760 (match_operand:SI 1 "thumb1_cmp_operand" "")
9761 (match_operand 2 "" "")
9762 (match_operand 3 "" "")]
3db2019b 9763 "TARGET_THUMB1"
e6ac8414 9764 {
9765 rtx reg0;
9766 rtx test = gen_rtx_GTU (VOIDmode, operands[0], operands[1]);
9767 emit_jump_insn (gen_cbranchsi4 (test, operands[0], operands[1],
9768 operands[3]));
9769 reg0 = gen_rtx_REG (SImode, 0);
9770 emit_move_insn (reg0, operands[0]);
9771 emit_jump_insn (gen_thumb1_casesi_dispatch (operands[2]/*, operands[3]*/));
9772 DONE;
9773 }
9774)
9775
9776(define_insn "thumb1_casesi_dispatch"
9777 [(parallel [(set (pc) (unspec [(reg:SI 0)
9778 (label_ref (match_operand 0 "" ""))
9779;; (label_ref (match_operand 1 "" ""))
9780]
9781 UNSPEC_THUMB1_CASESI))
9782 (clobber (reg:SI IP_REGNUM))
9783 (clobber (reg:SI LR_REGNUM))])]
3db2019b 9784 "TARGET_THUMB1"
e6ac8414 9785 "* return thumb1_output_casesi(operands);"
1b7da4ac 9786 [(set_attr "length" "4")
9787 (set_attr "type" "multiple")]
e6ac8414 9788)
9789
cffb2a26 9790(define_expand "indirect_jump"
9c08d1fa 9791 [(set (pc)
cffb2a26 9792 (match_operand:SI 0 "s_register_operand" ""))]
9793 "TARGET_EITHER"
25f905c2 9794 "
9795 /* Thumb-2 doesn't have mov pc, reg. Explicitly set the low bit of the
9796 address and use bx. */
9797 if (TARGET_THUMB2)
9798 {
9799 rtx tmp;
9800 tmp = gen_reg_rtx (SImode);
9801 emit_insn (gen_iorsi3 (tmp, operands[0], GEN_INT(1)));
9802 operands[0] = tmp;
9803 }
9804 "
cffb2a26 9805)
9806
f1039640 9807;; NB Never uses BX.
cffb2a26 9808(define_insn "*arm_indirect_jump"
9809 [(set (pc)
9810 (match_operand:SI 0 "s_register_operand" "r"))]
9811 "TARGET_ARM"
9812 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
1b7da4ac 9813 [(set_attr "predicable" "yes")
9814 (set_attr "type" "branch")]
cffb2a26 9815)
9c08d1fa 9816
f7fbdd4a 9817(define_insn "*load_indirect_jump"
9c08d1fa 9818 [(set (pc)
9819 (match_operand:SI 0 "memory_operand" "m"))]
cffb2a26 9820 "TARGET_ARM"
9821 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
a2cd141b 9822 [(set_attr "type" "load1")
61a2d04c 9823 (set_attr "pool_range" "4096")
9824 (set_attr "neg_pool_range" "4084")
0d66636f 9825 (set_attr "predicable" "yes")]
cffb2a26 9826)
9827
f1039640 9828;; NB Never uses BX.
25f905c2 9829(define_insn "*thumb1_indirect_jump"
cffb2a26 9830 [(set (pc)
9831 (match_operand:SI 0 "register_operand" "l*r"))]
25f905c2 9832 "TARGET_THUMB1"
cffb2a26 9833 "mov\\tpc, %0"
9834 [(set_attr "conds" "clob")
1b7da4ac 9835 (set_attr "length" "2")
9836 (set_attr "type" "branch")]
cffb2a26 9837)
9838
9c08d1fa 9839\f
9840;; Misc insns
9841
9842(define_insn "nop"
9843 [(const_int 0)]
cffb2a26 9844 "TARGET_EITHER"
9845 "*
25f905c2 9846 if (TARGET_UNIFIED_ASM)
9847 return \"nop\";
cffb2a26 9848 if (TARGET_ARM)
9849 return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
9850 return \"mov\\tr8, r8\";
9851 "
9852 [(set (attr "length")
9853 (if_then_else (eq_attr "is_thumb" "yes")
9854 (const_int 2)
1b7da4ac 9855 (const_int 4)))
9856 (set_attr "type" "mov_reg")]
cffb2a26 9857)
9858
ad9d4399 9859(define_insn "trap"
9860 [(trap_if (const_int 1) (const_int 0))]
9861 ""
9862 "*
9863 if (TARGET_ARM)
9864 return \".inst\\t0xe7f000f0\";
9865 else
9866 return \".inst\\t0xdeff\";
9867 "
9868 [(set (attr "length")
9869 (if_then_else (eq_attr "is_thumb" "yes")
9870 (const_int 2)
9871 (const_int 4)))
9872 (set_attr "type" "trap")
9873 (set_attr "conds" "unconditional")]
9874)
9875
9c08d1fa 9876\f
9877;; Patterns to allow combination of arithmetic, cond code and shifts
9878
f7fbdd4a 9879(define_insn "*arith_shiftsi"
7392680c 9880 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
9c08d1fa 9881 (match_operator:SI 1 "shiftable_operator"
9882 [(match_operator:SI 3 "shift_operator"
7392680c 9883 [(match_operand:SI 4 "s_register_operand" "r,r,r,r")
9884 (match_operand:SI 5 "shift_amount_operand" "M,M,M,r")])
9885 (match_operand:SI 2 "s_register_operand" "rk,rk,r,rk")]))]
d5d4dc8d 9886 "TARGET_32BIT"
6c4c2133 9887 "%i1%?\\t%0, %2, %4%S3"
344495ea 9888 [(set_attr "predicable" "yes")
331beb1a 9889 (set_attr "shift" "4")
7392680c 9890 (set_attr "arch" "a,t2,t2,a")
9891 ;; Thumb2 doesn't allow the stack pointer to be used for
9892 ;; operand1 for all operations other than add and sub. In this case
9893 ;; the minus operation is a candidate for an rsub and hence needs
9894 ;; to be disabled.
9895 ;; We have to make sure to disable the fourth alternative if
d5d4dc8d 9896 ;; the shift_operator is MULT, since otherwise the insn will
9897 ;; also match a multiply_accumulate pattern and validate_change
9898 ;; will allow a replacement of the constant with a register
9899 ;; despite the checks done in shift_operator.
9900 (set_attr_alternative "insn_enabled"
9901 [(const_string "yes")
7392680c 9902 (if_then_else
9903 (match_operand:SI 1 "add_operator" "")
9904 (const_string "yes") (const_string "no"))
9905 (const_string "yes")
d5d4dc8d 9906 (if_then_else
9907 (match_operand:SI 3 "mult_operator" "")
9908 (const_string "no") (const_string "yes"))])
d82e788e 9909 (set_attr "type" "alu_shift_imm,alu_shift_imm,alu_shift_imm,alu_shift_reg")])
9c08d1fa 9910
d7863cfe 9911(define_split
9912 [(set (match_operand:SI 0 "s_register_operand" "")
9913 (match_operator:SI 1 "shiftable_operator"
9914 [(match_operator:SI 2 "shiftable_operator"
9915 [(match_operator:SI 3 "shift_operator"
9916 [(match_operand:SI 4 "s_register_operand" "")
9917 (match_operand:SI 5 "reg_or_int_operand" "")])
9918 (match_operand:SI 6 "s_register_operand" "")])
9919 (match_operand:SI 7 "arm_rhs_operand" "")]))
9920 (clobber (match_operand:SI 8 "s_register_operand" ""))]
d5d4dc8d 9921 "TARGET_32BIT"
d7863cfe 9922 [(set (match_dup 8)
9923 (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
9924 (match_dup 6)]))
9925 (set (match_dup 0)
9926 (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
9927 "")
9928
f7fbdd4a 9929(define_insn "*arith_shiftsi_compare0"
bd5b4116 9930 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 9931 (compare:CC_NOOV
9932 (match_operator:SI 1 "shiftable_operator"
9933 [(match_operator:SI 3 "shift_operator"
9934 [(match_operand:SI 4 "s_register_operand" "r,r")
9935 (match_operand:SI 5 "shift_amount_operand" "M,r")])
9936 (match_operand:SI 2 "s_register_operand" "r,r")])
9937 (const_int 0)))
9938 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 9939 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
9940 (match_dup 2)]))]
d5d4dc8d 9941 "TARGET_32BIT"
25f905c2 9942 "%i1%.\\t%0, %2, %4%S3"
344495ea 9943 [(set_attr "conds" "set")
331beb1a 9944 (set_attr "shift" "4")
d5d4dc8d 9945 (set_attr "arch" "32,a")
d82e788e 9946 (set_attr "type" "alus_shift_imm,alus_shift_reg")])
9c08d1fa 9947
f7fbdd4a 9948(define_insn "*arith_shiftsi_compare0_scratch"
bd5b4116 9949 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 9950 (compare:CC_NOOV
9951 (match_operator:SI 1 "shiftable_operator"
9952 [(match_operator:SI 3 "shift_operator"
9953 [(match_operand:SI 4 "s_register_operand" "r,r")
9954 (match_operand:SI 5 "shift_amount_operand" "M,r")])
9955 (match_operand:SI 2 "s_register_operand" "r,r")])
9956 (const_int 0)))
9957 (clobber (match_scratch:SI 0 "=r,r"))]
9958 "TARGET_32BIT"
25f905c2 9959 "%i1%.\\t%0, %2, %4%S3"
344495ea 9960 [(set_attr "conds" "set")
331beb1a 9961 (set_attr "shift" "4")
d5d4dc8d 9962 (set_attr "arch" "32,a")
d82e788e 9963 (set_attr "type" "alus_shift_imm,alus_shift_reg")])
9c08d1fa 9964
f7fbdd4a 9965(define_insn "*sub_shiftsi"
d5d4dc8d 9966 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9967 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
9c08d1fa 9968 (match_operator:SI 2 "shift_operator"
d5d4dc8d 9969 [(match_operand:SI 3 "s_register_operand" "r,r")
9970 (match_operand:SI 4 "shift_amount_operand" "M,r")])))]
9971 "TARGET_32BIT"
6c4c2133 9972 "sub%?\\t%0, %1, %3%S2"
344495ea 9973 [(set_attr "predicable" "yes")
331beb1a 9974 (set_attr "shift" "3")
d5d4dc8d 9975 (set_attr "arch" "32,a")
d82e788e 9976 (set_attr "type" "alus_shift_imm,alus_shift_reg")])
9c08d1fa 9977
f7fbdd4a 9978(define_insn "*sub_shiftsi_compare0"
bd5b4116 9979 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 9980 (compare:CC_NOOV
d82e788e 9981 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
40dbec34 9982 (match_operator:SI 2 "shift_operator"
d82e788e 9983 [(match_operand:SI 3 "s_register_operand" "r,r,r")
9984 (match_operand:SI 4 "shift_amount_operand" "M,r,M")]))
40dbec34 9985 (const_int 0)))
d82e788e 9986 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
d5d4dc8d 9987 (minus:SI (match_dup 1)
9988 (match_op_dup 2 [(match_dup 3) (match_dup 4)])))]
9989 "TARGET_32BIT"
25f905c2 9990 "sub%.\\t%0, %1, %3%S2"
344495ea 9991 [(set_attr "conds" "set")
a2cd141b 9992 (set_attr "shift" "3")
d82e788e 9993 (set_attr "arch" "32,a,a")
9994 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
9c08d1fa 9995
f7fbdd4a 9996(define_insn "*sub_shiftsi_compare0_scratch"
bd5b4116 9997 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 9998 (compare:CC_NOOV
d82e788e 9999 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
40dbec34 10000 (match_operator:SI 2 "shift_operator"
d82e788e 10001 [(match_operand:SI 3 "s_register_operand" "r,r,r")
10002 (match_operand:SI 4 "shift_amount_operand" "M,r,M")]))
40dbec34 10003 (const_int 0)))
d82e788e 10004 (clobber (match_scratch:SI 0 "=r,r,r"))]
d5d4dc8d 10005 "TARGET_32BIT"
25f905c2 10006 "sub%.\\t%0, %1, %3%S2"
344495ea 10007 [(set_attr "conds" "set")
a2cd141b 10008 (set_attr "shift" "3")
d82e788e 10009 (set_attr "arch" "32,a,a")
10010 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
9c08d1fa 10011\f
10012
190efb17 10013(define_insn_and_split "*and_scc"
9c08d1fa 10014 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 10015 (and:SI (match_operator:SI 1 "arm_comparison_operator"
190efb17 10016 [(match_operand 2 "cc_register" "") (const_int 0)])
10017 (match_operand:SI 3 "s_register_operand" "r")))]
cffb2a26 10018 "TARGET_ARM"
190efb17 10019 "#" ; "mov%D1\\t%0, #0\;and%d1\\t%0, %3, #1"
10020 "&& reload_completed"
10021 [(cond_exec (match_dup 5) (set (match_dup 0) (const_int 0)))
10022 (cond_exec (match_dup 4) (set (match_dup 0)
10023 (and:SI (match_dup 3) (const_int 1))))]
10024 {
10025 enum machine_mode mode = GET_MODE (operands[2]);
10026 enum rtx_code rc = GET_CODE (operands[1]);
10027
10028 /* Note that operands[4] is the same as operands[1],
10029 but with VOIDmode as the result. */
10030 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
10031 if (mode == CCFPmode || mode == CCFPEmode)
10032 rc = reverse_condition_maybe_unordered (rc);
10033 else
10034 rc = reverse_condition (rc);
10035 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
10036 }
8fa3ba89 10037 [(set_attr "conds" "use")
1b7da4ac 10038 (set_attr "type" "multiple")
8fa3ba89 10039 (set_attr "length" "8")]
10040)
9c08d1fa 10041
190efb17 10042(define_insn_and_split "*ior_scc"
9c08d1fa 10043 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
190efb17 10044 (ior:SI (match_operator:SI 1 "arm_comparison_operator"
10045 [(match_operand 2 "cc_register" "") (const_int 0)])
10046 (match_operand:SI 3 "s_register_operand" "0,?r")))]
cffb2a26 10047 "TARGET_ARM"
e2348bcb 10048 "@
190efb17 10049 orr%d1\\t%0, %3, #1
10050 #"
10051 "&& reload_completed
10052 && REGNO (operands [0]) != REGNO (operands[3])"
10053 ;; && which_alternative == 1
10054 ; mov%D1\\t%0, %3\;orr%d1\\t%0, %3, #1
10055 [(cond_exec (match_dup 5) (set (match_dup 0) (match_dup 3)))
10056 (cond_exec (match_dup 4) (set (match_dup 0)
10057 (ior:SI (match_dup 3) (const_int 1))))]
10058 {
10059 enum machine_mode mode = GET_MODE (operands[2]);
10060 enum rtx_code rc = GET_CODE (operands[1]);
10061
10062 /* Note that operands[4] is the same as operands[1],
10063 but with VOIDmode as the result. */
10064 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
10065 if (mode == CCFPmode || mode == CCFPEmode)
10066 rc = reverse_condition_maybe_unordered (rc);
10067 else
10068 rc = reverse_condition (rc);
10069 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
10070 }
8fa3ba89 10071 [(set_attr "conds" "use")
1b7da4ac 10072 (set_attr "length" "4,8")
10073 (set_attr "type" "logic_imm,multiple")]
8fa3ba89 10074)
9c08d1fa 10075
2df9477b 10076; A series of splitters for the compare_scc pattern below. Note that
10077; order is important.
10078(define_split
10079 [(set (match_operand:SI 0 "s_register_operand" "")
10080 (lt:SI (match_operand:SI 1 "s_register_operand" "")
10081 (const_int 0)))
10082 (clobber (reg:CC CC_REGNUM))]
10083 "TARGET_32BIT && reload_completed"
10084 [(set (match_dup 0) (lshiftrt:SI (match_dup 1) (const_int 31)))])
10085
10086(define_split
10087 [(set (match_operand:SI 0 "s_register_operand" "")
10088 (ge:SI (match_operand:SI 1 "s_register_operand" "")
10089 (const_int 0)))
10090 (clobber (reg:CC CC_REGNUM))]
10091 "TARGET_32BIT && reload_completed"
10092 [(set (match_dup 0) (not:SI (match_dup 1)))
10093 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 31)))])
10094
98562479 10095(define_split
10096 [(set (match_operand:SI 0 "s_register_operand" "")
10097 (eq:SI (match_operand:SI 1 "s_register_operand" "")
10098 (const_int 0)))
10099 (clobber (reg:CC CC_REGNUM))]
10100 "arm_arch5 && TARGET_32BIT"
10101 [(set (match_dup 0) (clz:SI (match_dup 1)))
10102 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 5)))]
10103)
10104
2df9477b 10105(define_split
10106 [(set (match_operand:SI 0 "s_register_operand" "")
10107 (eq:SI (match_operand:SI 1 "s_register_operand" "")
10108 (const_int 0)))
10109 (clobber (reg:CC CC_REGNUM))]
10110 "TARGET_32BIT && reload_completed"
10111 [(parallel
080c0b9a 10112 [(set (reg:CC CC_REGNUM)
10113 (compare:CC (const_int 1) (match_dup 1)))
2df9477b 10114 (set (match_dup 0)
10115 (minus:SI (const_int 1) (match_dup 1)))])
080c0b9a 10116 (cond_exec (ltu:CC (reg:CC CC_REGNUM) (const_int 0))
2df9477b 10117 (set (match_dup 0) (const_int 0)))])
10118
10119(define_split
10120 [(set (match_operand:SI 0 "s_register_operand" "")
10121 (ne:SI (match_operand:SI 1 "s_register_operand" "")
10122 (match_operand:SI 2 "const_int_operand" "")))
10123 (clobber (reg:CC CC_REGNUM))]
10124 "TARGET_32BIT && reload_completed"
10125 [(parallel
10126 [(set (reg:CC CC_REGNUM)
10127 (compare:CC (match_dup 1) (match_dup 2)))
10128 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))])
10129 (cond_exec (ne:CC (reg:CC CC_REGNUM) (const_int 0))
10130 (set (match_dup 0) (const_int 1)))]
10131{
10132 operands[3] = GEN_INT (-INTVAL (operands[2]));
10133})
10134
10135(define_split
10136 [(set (match_operand:SI 0 "s_register_operand" "")
10137 (ne:SI (match_operand:SI 1 "s_register_operand" "")
10138 (match_operand:SI 2 "arm_add_operand" "")))
10139 (clobber (reg:CC CC_REGNUM))]
10140 "TARGET_32BIT && reload_completed"
10141 [(parallel
10142 [(set (reg:CC_NOOV CC_REGNUM)
10143 (compare:CC_NOOV (minus:SI (match_dup 1) (match_dup 2))
10144 (const_int 0)))
10145 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
10146 (cond_exec (ne:CC_NOOV (reg:CC_NOOV CC_REGNUM) (const_int 0))
10147 (set (match_dup 0) (const_int 1)))])
10148
10149(define_insn_and_split "*compare_scc"
fd711051 10150 [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts")
8fa3ba89 10151 (match_operator:SI 1 "arm_comparison_operator"
5565501b 10152 [(match_operand:SI 2 "s_register_operand" "r,r")
10153 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
bd5b4116 10154 (clobber (reg:CC CC_REGNUM))]
2df9477b 10155 "TARGET_32BIT"
10156 "#"
10157 "&& reload_completed"
10158 [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 3)))
10159 (cond_exec (match_dup 4) (set (match_dup 0) (const_int 0)))
10160 (cond_exec (match_dup 5) (set (match_dup 0) (const_int 1)))]
10161{
10162 rtx tmp1;
10163 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10164 operands[2], operands[3]);
10165 enum rtx_code rc = GET_CODE (operands[1]);
e2348bcb 10166
2df9477b 10167 tmp1 = gen_rtx_REG (mode, CC_REGNUM);
080c0b9a 10168
2df9477b 10169 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
10170 if (mode == CCFPmode || mode == CCFPEmode)
10171 rc = reverse_condition_maybe_unordered (rc);
10172 else
10173 rc = reverse_condition (rc);
10174 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
1b7da4ac 10175}
10176 [(set_attr "type" "multiple")]
10177)
9c08d1fa 10178
080c0b9a 10179;; Attempt to improve the sequence generated by the compare_scc splitters
10180;; not to use conditional execution.
98562479 10181
10182;; Rd = (eq (reg1) (const_int0)) // ARMv5
10183;; clz Rd, reg1
10184;; lsr Rd, Rd, #5
080c0b9a 10185(define_peephole2
10186 [(set (reg:CC CC_REGNUM)
10187 (compare:CC (match_operand:SI 1 "register_operand" "")
98562479 10188 (const_int 0)))
10189 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
10190 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
10191 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
10192 (set (match_dup 0) (const_int 1)))]
10193 "arm_arch5 && TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)"
10194 [(set (match_dup 0) (clz:SI (match_dup 1)))
10195 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 5)))]
10196)
10197
10198;; Rd = (eq (reg1) (const_int0)) // !ARMv5
10199;; negs Rd, reg1
10200;; adc Rd, Rd, reg1
10201(define_peephole2
10202 [(set (reg:CC CC_REGNUM)
10203 (compare:CC (match_operand:SI 1 "register_operand" "")
10204 (const_int 0)))
080c0b9a 10205 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
10206 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
10207 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
10208 (set (match_dup 0) (const_int 1)))
98562479 10209 (match_scratch:SI 2 "r")]
10210 "TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)"
922b6913 10211 [(parallel
10212 [(set (reg:CC CC_REGNUM)
98562479 10213 (compare:CC (const_int 0) (match_dup 1)))
10214 (set (match_dup 2) (minus:SI (const_int 0) (match_dup 1)))])
10215 (set (match_dup 0)
10216 (plus:SI (plus:SI (match_dup 1) (match_dup 2))
10217 (geu:SI (reg:CC CC_REGNUM) (const_int 0))))]
10218)
10219
31991287 10220;; Rd = (eq (reg1) (reg2/imm)) // ARMv5 and optimising for speed.
98562479 10221;; sub Rd, Reg1, reg2
10222;; clz Rd, Rd
10223;; lsr Rd, Rd, #5
10224(define_peephole2
10225 [(set (reg:CC CC_REGNUM)
10226 (compare:CC (match_operand:SI 1 "register_operand" "")
10227 (match_operand:SI 2 "arm_rhs_operand" "")))
10228 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
10229 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
10230 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
10231 (set (match_dup 0) (const_int 1)))]
31991287 10232 "arm_arch5 && TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)
10233 && !(TARGET_THUMB2 && optimize_insn_for_size_p ())"
98562479 10234 [(set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))
10235 (set (match_dup 0) (clz:SI (match_dup 0)))
10236 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 5)))]
10237)
10238
10239
31991287 10240;; Rd = (eq (reg1) (reg2)) // ! ARMv5 or optimising for size.
98562479 10241;; sub T1, Reg1, reg2
10242;; negs Rd, T1
10243;; adc Rd, Rd, T1
10244(define_peephole2
10245 [(set (reg:CC CC_REGNUM)
10246 (compare:CC (match_operand:SI 1 "register_operand" "")
10247 (match_operand:SI 2 "arm_rhs_operand" "")))
10248 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
10249 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
10250 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
10251 (set (match_dup 0) (const_int 1)))
10252 (match_scratch:SI 3 "r")]
10253 "TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)"
31991287 10254 [(set (match_dup 3) (match_dup 4))
080c0b9a 10255 (parallel
10256 [(set (reg:CC CC_REGNUM)
10257 (compare:CC (const_int 0) (match_dup 3)))
10258 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 3)))])
98562479 10259 (set (match_dup 0)
10260 (plus:SI (plus:SI (match_dup 0) (match_dup 3))
10261 (geu:SI (reg:CC CC_REGNUM) (const_int 0))))]
31991287 10262 "
10263 if (CONST_INT_P (operands[2]))
10264 operands[4] = plus_constant (SImode, operands[1], -INTVAL (operands[2]));
10265 else
10266 operands[4] = gen_rtx_MINUS (SImode, operands[1], operands[2]);
10267 ")
080c0b9a 10268
f7fbdd4a 10269(define_insn "*cond_move"
9c08d1fa 10270 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
aea4c774 10271 (if_then_else:SI (match_operator 3 "equality_operator"
8fa3ba89 10272 [(match_operator 4 "arm_comparison_operator"
8a18b90c 10273 [(match_operand 5 "cc_register" "") (const_int 0)])
aea4c774 10274 (const_int 0)])
10275 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
10276 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
cffb2a26 10277 "TARGET_ARM"
9c08d1fa 10278 "*
8fa3ba89 10279 if (GET_CODE (operands[3]) == NE)
10280 {
10281 if (which_alternative != 1)
10282 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
10283 if (which_alternative != 0)
10284 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
10285 return \"\";
10286 }
10287 if (which_alternative != 0)
10288 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
10289 if (which_alternative != 1)
10290 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
10291 return \"\";
10292 "
10293 [(set_attr "conds" "use")
1b7da4ac 10294 (set_attr "type" "mov_reg,mov_reg,multiple")
8fa3ba89 10295 (set_attr "length" "4,4,8")]
10296)
9c08d1fa 10297
f7fbdd4a 10298(define_insn "*cond_arith"
9c08d1fa 10299 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10300 (match_operator:SI 5 "shiftable_operator"
8fa3ba89 10301 [(match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 10302 [(match_operand:SI 2 "s_register_operand" "r,r")
10303 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
10304 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 10305 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10306 "TARGET_ARM"
9c08d1fa 10307 "*
8fa3ba89 10308 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
10309 return \"%i5\\t%0, %1, %2, lsr #31\";
40dbec34 10310
8fa3ba89 10311 output_asm_insn (\"cmp\\t%2, %3\", operands);
10312 if (GET_CODE (operands[5]) == AND)
10313 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
10314 else if (GET_CODE (operands[5]) == MINUS)
10315 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
10316 else if (which_alternative != 0)
10317 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
10318 return \"%i5%d4\\t%0, %1, #1\";
10319 "
10320 [(set_attr "conds" "clob")
1b7da4ac 10321 (set_attr "length" "12")
10322 (set_attr "type" "multiple")]
8fa3ba89 10323)
9c08d1fa 10324
f7fbdd4a 10325(define_insn "*cond_sub"
9c08d1fa 10326 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10327 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8fa3ba89 10328 (match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 10329 [(match_operand:SI 2 "s_register_operand" "r,r")
10330 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 10331 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10332 "TARGET_ARM"
9c08d1fa 10333 "*
8fa3ba89 10334 output_asm_insn (\"cmp\\t%2, %3\", operands);
10335 if (which_alternative != 0)
10336 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
10337 return \"sub%d4\\t%0, %1, #1\";
10338 "
10339 [(set_attr "conds" "clob")
1b7da4ac 10340 (set_attr "length" "8,12")
10341 (set_attr "type" "multiple")]
8fa3ba89 10342)
9c08d1fa 10343
aea4c774 10344(define_insn "*cmp_ite0"
cffb2a26 10345 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 10346 (compare
10347 (if_then_else:SI
8fa3ba89 10348 (match_operator 4 "arm_comparison_operator"
2ff91fec 10349 [(match_operand:SI 0 "s_register_operand"
10350 "l,l,l,r,r,r,r,r,r")
10351 (match_operand:SI 1 "arm_add_operand"
10352 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
8fa3ba89 10353 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 10354 [(match_operand:SI 2 "s_register_operand"
10355 "l,r,r,l,l,r,r,r,r")
10356 (match_operand:SI 3 "arm_add_operand"
10357 "lPy,rI,L,lPy,lPy,rI,rI,L,L")])
aea4c774 10358 (const_int 0))
10359 (const_int 0)))]
2ff91fec 10360 "TARGET_32BIT"
9c08d1fa 10361 "*
aea4c774 10362 {
2ff91fec 10363 static const char * const cmp1[NUM_OF_COND_CMP][2] =
10364 {
10365 {\"cmp%d5\\t%0, %1\",
10366 \"cmp%d4\\t%2, %3\"},
10367 {\"cmn%d5\\t%0, #%n1\",
10368 \"cmp%d4\\t%2, %3\"},
10369 {\"cmp%d5\\t%0, %1\",
10370 \"cmn%d4\\t%2, #%n3\"},
10371 {\"cmn%d5\\t%0, #%n1\",
10372 \"cmn%d4\\t%2, #%n3\"}
10373 };
10374 static const char * const cmp2[NUM_OF_COND_CMP][2] =
10375 {
10376 {\"cmp\\t%2, %3\",
10377 \"cmp\\t%0, %1\"},
10378 {\"cmp\\t%2, %3\",
10379 \"cmn\\t%0, #%n1\"},
10380 {\"cmn\\t%2, #%n3\",
10381 \"cmp\\t%0, %1\"},
10382 {\"cmn\\t%2, #%n3\",
10383 \"cmn\\t%0, #%n1\"}
10384 };
10385 static const char * const ite[2] =
8fa3ba89 10386 {
2ff91fec 10387 \"it\\t%d5\",
10388 \"it\\t%d4\"
8fa3ba89 10389 };
2ff91fec 10390 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
10391 CMP_CMP, CMN_CMP, CMP_CMP,
10392 CMN_CMP, CMP_CMN, CMN_CMN};
8fa3ba89 10393 int swap =
10394 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
10395
2ff91fec 10396 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
10397 if (TARGET_THUMB2) {
10398 output_asm_insn (ite[swap], operands);
10399 }
10400 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
10401 return \"\";
8fa3ba89 10402 }"
10403 [(set_attr "conds" "set")
2ff91fec 10404 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
1b7da4ac 10405 (set_attr "type" "multiple")
2ff91fec 10406 (set_attr_alternative "length"
10407 [(const_int 6)
10408 (const_int 8)
10409 (const_int 8)
10410 (const_int 8)
10411 (const_int 8)
10412 (if_then_else (eq_attr "is_thumb" "no")
10413 (const_int 8)
10414 (const_int 10))
10415 (if_then_else (eq_attr "is_thumb" "no")
10416 (const_int 8)
10417 (const_int 10))
10418 (if_then_else (eq_attr "is_thumb" "no")
10419 (const_int 8)
10420 (const_int 10))
10421 (if_then_else (eq_attr "is_thumb" "no")
10422 (const_int 8)
10423 (const_int 10))])]
8fa3ba89 10424)
9c08d1fa 10425
aea4c774 10426(define_insn "*cmp_ite1"
cffb2a26 10427 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 10428 (compare
10429 (if_then_else:SI
8fa3ba89 10430 (match_operator 4 "arm_comparison_operator"
2ff91fec 10431 [(match_operand:SI 0 "s_register_operand"
10432 "l,l,l,r,r,r,r,r,r")
10433 (match_operand:SI 1 "arm_add_operand"
10434 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
8fa3ba89 10435 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 10436 [(match_operand:SI 2 "s_register_operand"
10437 "l,r,r,l,l,r,r,r,r")
10438 (match_operand:SI 3 "arm_add_operand"
10439 "lPy,rI,L,lPy,lPy,rI,rI,L,L")])
aea4c774 10440 (const_int 1))
10441 (const_int 0)))]
2ff91fec 10442 "TARGET_32BIT"
9c08d1fa 10443 "*
9c08d1fa 10444 {
2ff91fec 10445 static const char * const cmp1[NUM_OF_COND_CMP][2] =
10446 {
10447 {\"cmp\\t%0, %1\",
10448 \"cmp\\t%2, %3\"},
10449 {\"cmn\\t%0, #%n1\",
10450 \"cmp\\t%2, %3\"},
10451 {\"cmp\\t%0, %1\",
10452 \"cmn\\t%2, #%n3\"},
10453 {\"cmn\\t%0, #%n1\",
10454 \"cmn\\t%2, #%n3\"}
10455 };
10456 static const char * const cmp2[NUM_OF_COND_CMP][2] =
215b30b3 10457 {
2ff91fec 10458 {\"cmp%d4\\t%2, %3\",
10459 \"cmp%D5\\t%0, %1\"},
10460 {\"cmp%d4\\t%2, %3\",
10461 \"cmn%D5\\t%0, #%n1\"},
10462 {\"cmn%d4\\t%2, #%n3\",
10463 \"cmp%D5\\t%0, %1\"},
10464 {\"cmn%d4\\t%2, #%n3\",
10465 \"cmn%D5\\t%0, #%n1\"}
215b30b3 10466 };
2ff91fec 10467 static const char * const ite[2] =
10468 {
10469 \"it\\t%d4\",
10470 \"it\\t%D5\"
10471 };
10472 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
10473 CMP_CMP, CMN_CMP, CMP_CMP,
10474 CMN_CMP, CMP_CMN, CMN_CMN};
215b30b3 10475 int swap =
10476 comparison_dominates_p (GET_CODE (operands[5]),
10477 reverse_condition (GET_CODE (operands[4])));
10478
2ff91fec 10479 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
10480 if (TARGET_THUMB2) {
10481 output_asm_insn (ite[swap], operands);
10482 }
10483 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
10484 return \"\";
215b30b3 10485 }"
8fa3ba89 10486 [(set_attr "conds" "set")
2ff91fec 10487 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
10488 (set_attr_alternative "length"
10489 [(const_int 6)
10490 (const_int 8)
10491 (const_int 8)
10492 (const_int 8)
10493 (const_int 8)
10494 (if_then_else (eq_attr "is_thumb" "no")
10495 (const_int 8)
10496 (const_int 10))
10497 (if_then_else (eq_attr "is_thumb" "no")
10498 (const_int 8)
10499 (const_int 10))
10500 (if_then_else (eq_attr "is_thumb" "no")
10501 (const_int 8)
10502 (const_int 10))
10503 (if_then_else (eq_attr "is_thumb" "no")
10504 (const_int 8)
1b7da4ac 10505 (const_int 10))])
10506 (set_attr "type" "multiple")]
8fa3ba89 10507)
9c08d1fa 10508
f6c53574 10509(define_insn "*cmp_and"
10510 [(set (match_operand 6 "dominant_cc_register" "")
10511 (compare
10512 (and:SI
10513 (match_operator 4 "arm_comparison_operator"
2ff91fec 10514 [(match_operand:SI 0 "s_register_operand"
10515 "l,l,l,r,r,r,r,r,r")
10516 (match_operand:SI 1 "arm_add_operand"
10517 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
f6c53574 10518 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 10519 [(match_operand:SI 2 "s_register_operand"
10520 "l,r,r,l,l,r,r,r,r")
10521 (match_operand:SI 3 "arm_add_operand"
10522 "lPy,rI,L,lPy,lPy,rI,rI,L,L")]))
f6c53574 10523 (const_int 0)))]
2ff91fec 10524 "TARGET_32BIT"
f6c53574 10525 "*
10526 {
2ff91fec 10527 static const char *const cmp1[NUM_OF_COND_CMP][2] =
f6c53574 10528 {
2ff91fec 10529 {\"cmp%d5\\t%0, %1\",
10530 \"cmp%d4\\t%2, %3\"},
10531 {\"cmn%d5\\t%0, #%n1\",
10532 \"cmp%d4\\t%2, %3\"},
10533 {\"cmp%d5\\t%0, %1\",
10534 \"cmn%d4\\t%2, #%n3\"},
10535 {\"cmn%d5\\t%0, #%n1\",
10536 \"cmn%d4\\t%2, #%n3\"}
f6c53574 10537 };
2ff91fec 10538 static const char *const cmp2[NUM_OF_COND_CMP][2] =
10539 {
10540 {\"cmp\\t%2, %3\",
10541 \"cmp\\t%0, %1\"},
10542 {\"cmp\\t%2, %3\",
10543 \"cmn\\t%0, #%n1\"},
10544 {\"cmn\\t%2, #%n3\",
10545 \"cmp\\t%0, %1\"},
10546 {\"cmn\\t%2, #%n3\",
10547 \"cmn\\t%0, #%n1\"}
10548 };
10549 static const char *const ite[2] =
10550 {
10551 \"it\\t%d5\",
10552 \"it\\t%d4\"
10553 };
10554 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
10555 CMP_CMP, CMN_CMP, CMP_CMP,
10556 CMN_CMP, CMP_CMN, CMN_CMN};
f6c53574 10557 int swap =
10558 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
10559
2ff91fec 10560 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
10561 if (TARGET_THUMB2) {
10562 output_asm_insn (ite[swap], operands);
10563 }
10564 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
10565 return \"\";
f6c53574 10566 }"
10567 [(set_attr "conds" "set")
10568 (set_attr "predicable" "no")
2ff91fec 10569 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
10570 (set_attr_alternative "length"
10571 [(const_int 6)
10572 (const_int 8)
10573 (const_int 8)
10574 (const_int 8)
10575 (const_int 8)
10576 (if_then_else (eq_attr "is_thumb" "no")
10577 (const_int 8)
10578 (const_int 10))
10579 (if_then_else (eq_attr "is_thumb" "no")
10580 (const_int 8)
10581 (const_int 10))
10582 (if_then_else (eq_attr "is_thumb" "no")
10583 (const_int 8)
10584 (const_int 10))
10585 (if_then_else (eq_attr "is_thumb" "no")
10586 (const_int 8)
1b7da4ac 10587 (const_int 10))])
10588 (set_attr "type" "multiple")]
f6c53574 10589)
10590
10591(define_insn "*cmp_ior"
10592 [(set (match_operand 6 "dominant_cc_register" "")
10593 (compare
10594 (ior:SI
10595 (match_operator 4 "arm_comparison_operator"
2ff91fec 10596 [(match_operand:SI 0 "s_register_operand"
10597 "l,l,l,r,r,r,r,r,r")
10598 (match_operand:SI 1 "arm_add_operand"
10599 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
f6c53574 10600 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 10601 [(match_operand:SI 2 "s_register_operand"
10602 "l,r,r,l,l,r,r,r,r")
10603 (match_operand:SI 3 "arm_add_operand"
10604 "lPy,rI,L,lPy,lPy,rI,rI,L,L")]))
f6c53574 10605 (const_int 0)))]
2ff91fec 10606 "TARGET_32BIT"
f6c53574 10607 "*
f6c53574 10608 {
2ff91fec 10609 static const char *const cmp1[NUM_OF_COND_CMP][2] =
10610 {
10611 {\"cmp\\t%0, %1\",
10612 \"cmp\\t%2, %3\"},
10613 {\"cmn\\t%0, #%n1\",
10614 \"cmp\\t%2, %3\"},
10615 {\"cmp\\t%0, %1\",
10616 \"cmn\\t%2, #%n3\"},
10617 {\"cmn\\t%0, #%n1\",
10618 \"cmn\\t%2, #%n3\"}
10619 };
10620 static const char *const cmp2[NUM_OF_COND_CMP][2] =
10621 {
10622 {\"cmp%D4\\t%2, %3\",
10623 \"cmp%D5\\t%0, %1\"},
10624 {\"cmp%D4\\t%2, %3\",
10625 \"cmn%D5\\t%0, #%n1\"},
10626 {\"cmn%D4\\t%2, #%n3\",
10627 \"cmp%D5\\t%0, %1\"},
10628 {\"cmn%D4\\t%2, #%n3\",
10629 \"cmn%D5\\t%0, #%n1\"}
10630 };
10631 static const char *const ite[2] =
10632 {
10633 \"it\\t%D4\",
10634 \"it\\t%D5\"
10635 };
10636 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
10637 CMP_CMP, CMN_CMP, CMP_CMP,
10638 CMN_CMP, CMP_CMN, CMN_CMN};
10639 int swap =
10640 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
10641
10642 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
10643 if (TARGET_THUMB2) {
10644 output_asm_insn (ite[swap], operands);
10645 }
10646 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
10647 return \"\";
10648 }
10649 "
f6c53574 10650 [(set_attr "conds" "set")
2ff91fec 10651 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
10652 (set_attr_alternative "length"
10653 [(const_int 6)
10654 (const_int 8)
10655 (const_int 8)
10656 (const_int 8)
10657 (const_int 8)
10658 (if_then_else (eq_attr "is_thumb" "no")
10659 (const_int 8)
10660 (const_int 10))
10661 (if_then_else (eq_attr "is_thumb" "no")
10662 (const_int 8)
10663 (const_int 10))
10664 (if_then_else (eq_attr "is_thumb" "no")
10665 (const_int 8)
10666 (const_int 10))
10667 (if_then_else (eq_attr "is_thumb" "no")
10668 (const_int 8)
1b7da4ac 10669 (const_int 10))])
10670 (set_attr "type" "multiple")]
f6c53574 10671)
10672
3c5afce6 10673(define_insn_and_split "*ior_scc_scc"
fd711051 10674 [(set (match_operand:SI 0 "s_register_operand" "=Ts")
3c5afce6 10675 (ior:SI (match_operator:SI 3 "arm_comparison_operator"
10676 [(match_operand:SI 1 "s_register_operand" "r")
10677 (match_operand:SI 2 "arm_add_operand" "rIL")])
10678 (match_operator:SI 6 "arm_comparison_operator"
10679 [(match_operand:SI 4 "s_register_operand" "r")
10680 (match_operand:SI 5 "arm_add_operand" "rIL")])))
10681 (clobber (reg:CC CC_REGNUM))]
2ff91fec 10682 "TARGET_32BIT
3c5afce6 10683 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
10684 != CCmode)"
10685 "#"
2ff91fec 10686 "TARGET_32BIT && reload_completed"
3c5afce6 10687 [(set (match_dup 7)
10688 (compare
10689 (ior:SI
10690 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
10691 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
10692 (const_int 0)))
10693 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
10694 "operands[7]
10695 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
10696 DOM_CC_X_OR_Y),
601f584c 10697 CC_REGNUM);"
10698 [(set_attr "conds" "clob")
1b7da4ac 10699 (set_attr "length" "16")
10700 (set_attr "type" "multiple")]
10701)
601f584c 10702
10703; If the above pattern is followed by a CMP insn, then the compare is
10704; redundant, since we can rework the conditional instruction that follows.
10705(define_insn_and_split "*ior_scc_scc_cmp"
10706 [(set (match_operand 0 "dominant_cc_register" "")
10707 (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
10708 [(match_operand:SI 1 "s_register_operand" "r")
10709 (match_operand:SI 2 "arm_add_operand" "rIL")])
10710 (match_operator:SI 6 "arm_comparison_operator"
10711 [(match_operand:SI 4 "s_register_operand" "r")
10712 (match_operand:SI 5 "arm_add_operand" "rIL")]))
10713 (const_int 0)))
fd711051 10714 (set (match_operand:SI 7 "s_register_operand" "=Ts")
601f584c 10715 (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
10716 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
2ff91fec 10717 "TARGET_32BIT"
601f584c 10718 "#"
2ff91fec 10719 "TARGET_32BIT && reload_completed"
601f584c 10720 [(set (match_dup 0)
10721 (compare
10722 (ior:SI
10723 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
10724 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
10725 (const_int 0)))
10726 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
10727 ""
10728 [(set_attr "conds" "set")
1b7da4ac 10729 (set_attr "length" "16")
10730 (set_attr "type" "multiple")]
10731)
3c5afce6 10732
10733(define_insn_and_split "*and_scc_scc"
fd711051 10734 [(set (match_operand:SI 0 "s_register_operand" "=Ts")
3c5afce6 10735 (and:SI (match_operator:SI 3 "arm_comparison_operator"
10736 [(match_operand:SI 1 "s_register_operand" "r")
10737 (match_operand:SI 2 "arm_add_operand" "rIL")])
10738 (match_operator:SI 6 "arm_comparison_operator"
10739 [(match_operand:SI 4 "s_register_operand" "r")
10740 (match_operand:SI 5 "arm_add_operand" "rIL")])))
10741 (clobber (reg:CC CC_REGNUM))]
2ff91fec 10742 "TARGET_32BIT
3c5afce6 10743 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
10744 != CCmode)"
10745 "#"
2ff91fec 10746 "TARGET_32BIT && reload_completed
601f584c 10747 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
10748 != CCmode)"
3c5afce6 10749 [(set (match_dup 7)
10750 (compare
10751 (and:SI
10752 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
10753 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
10754 (const_int 0)))
10755 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
10756 "operands[7]
10757 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
10758 DOM_CC_X_AND_Y),
601f584c 10759 CC_REGNUM);"
10760 [(set_attr "conds" "clob")
1b7da4ac 10761 (set_attr "length" "16")
10762 (set_attr "type" "multiple")]
10763)
601f584c 10764
10765; If the above pattern is followed by a CMP insn, then the compare is
10766; redundant, since we can rework the conditional instruction that follows.
10767(define_insn_and_split "*and_scc_scc_cmp"
10768 [(set (match_operand 0 "dominant_cc_register" "")
10769 (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
10770 [(match_operand:SI 1 "s_register_operand" "r")
10771 (match_operand:SI 2 "arm_add_operand" "rIL")])
10772 (match_operator:SI 6 "arm_comparison_operator"
10773 [(match_operand:SI 4 "s_register_operand" "r")
10774 (match_operand:SI 5 "arm_add_operand" "rIL")]))
10775 (const_int 0)))
fd711051 10776 (set (match_operand:SI 7 "s_register_operand" "=Ts")
601f584c 10777 (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
10778 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
2ff91fec 10779 "TARGET_32BIT"
601f584c 10780 "#"
2ff91fec 10781 "TARGET_32BIT && reload_completed"
601f584c 10782 [(set (match_dup 0)
10783 (compare
10784 (and:SI
10785 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
10786 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
10787 (const_int 0)))
10788 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
10789 ""
10790 [(set_attr "conds" "set")
1b7da4ac 10791 (set_attr "length" "16")
10792 (set_attr "type" "multiple")]
10793)
601f584c 10794
10795;; If there is no dominance in the comparison, then we can still save an
10796;; instruction in the AND case, since we can know that the second compare
10797;; need only zero the value if false (if true, then the value is already
10798;; correct).
10799(define_insn_and_split "*and_scc_scc_nodom"
fd711051 10800 [(set (match_operand:SI 0 "s_register_operand" "=&Ts,&Ts,&Ts")
601f584c 10801 (and:SI (match_operator:SI 3 "arm_comparison_operator"
10802 [(match_operand:SI 1 "s_register_operand" "r,r,0")
10803 (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
10804 (match_operator:SI 6 "arm_comparison_operator"
10805 [(match_operand:SI 4 "s_register_operand" "r,r,r")
10806 (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
10807 (clobber (reg:CC CC_REGNUM))]
2ff91fec 10808 "TARGET_32BIT
601f584c 10809 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
10810 == CCmode)"
10811 "#"
2ff91fec 10812 "TARGET_32BIT && reload_completed"
601f584c 10813 [(parallel [(set (match_dup 0)
10814 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
10815 (clobber (reg:CC CC_REGNUM))])
10816 (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
10817 (set (match_dup 0)
10818 (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
10819 (match_dup 0)
10820 (const_int 0)))]
10821 "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
10822 operands[4], operands[5]),
10823 CC_REGNUM);
10824 operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
10825 operands[5]);"
10826 [(set_attr "conds" "clob")
1b7da4ac 10827 (set_attr "length" "20")
10828 (set_attr "type" "multiple")]
10829)
3c5afce6 10830
3a0bdee0 10831(define_split
10832 [(set (reg:CC_NOOV CC_REGNUM)
10833 (compare:CC_NOOV (ior:SI
10834 (and:SI (match_operand:SI 0 "s_register_operand" "")
10835 (const_int 1))
b0694be0 10836 (match_operator:SI 1 "arm_comparison_operator"
3a0bdee0 10837 [(match_operand:SI 2 "s_register_operand" "")
10838 (match_operand:SI 3 "arm_add_operand" "")]))
10839 (const_int 0)))
10840 (clobber (match_operand:SI 4 "s_register_operand" ""))]
10841 "TARGET_ARM"
10842 [(set (match_dup 4)
10843 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
10844 (match_dup 0)))
10845 (set (reg:CC_NOOV CC_REGNUM)
10846 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
10847 (const_int 0)))]
10848 "")
10849
10850(define_split
10851 [(set (reg:CC_NOOV CC_REGNUM)
10852 (compare:CC_NOOV (ior:SI
b0694be0 10853 (match_operator:SI 1 "arm_comparison_operator"
3a0bdee0 10854 [(match_operand:SI 2 "s_register_operand" "")
10855 (match_operand:SI 3 "arm_add_operand" "")])
10856 (and:SI (match_operand:SI 0 "s_register_operand" "")
10857 (const_int 1)))
10858 (const_int 0)))
10859 (clobber (match_operand:SI 4 "s_register_operand" ""))]
10860 "TARGET_ARM"
10861 [(set (match_dup 4)
10862 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
10863 (match_dup 0)))
10864 (set (reg:CC_NOOV CC_REGNUM)
10865 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
10866 (const_int 0)))]
10867 "")
25f905c2 10868;; ??? The conditional patterns above need checking for Thumb-2 usefulness
3a0bdee0 10869
190efb17 10870(define_insn_and_split "*negscc"
9c08d1fa 10871 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 10872 (neg:SI (match_operator 3 "arm_comparison_operator"
9c08d1fa 10873 [(match_operand:SI 1 "s_register_operand" "r")
10874 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
bd5b4116 10875 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10876 "TARGET_ARM"
190efb17 10877 "#"
10878 "&& reload_completed"
10879 [(const_int 0)]
10880 {
10881 rtx cc_reg = gen_rtx_REG (CCmode, CC_REGNUM);
e2348bcb 10882
190efb17 10883 if (GET_CODE (operands[3]) == LT && operands[2] == const0_rtx)
10884 {
10885 /* Emit mov\\t%0, %1, asr #31 */
10886 emit_insn (gen_rtx_SET (VOIDmode,
10887 operands[0],
10888 gen_rtx_ASHIFTRT (SImode,
10889 operands[1],
10890 GEN_INT (31))));
10891 DONE;
10892 }
10893 else if (GET_CODE (operands[3]) == NE)
10894 {
10895 /* Emit subs\\t%0, %1, %2\;mvnne\\t%0, #0 */
10896 if (CONST_INT_P (operands[2]))
10897 emit_insn (gen_cmpsi2_addneg (operands[0], operands[1], operands[2],
10898 GEN_INT (- INTVAL (operands[2]))));
10899 else
10900 emit_insn (gen_subsi3_compare (operands[0], operands[1], operands[2]));
10901
10902 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
10903 gen_rtx_NE (SImode,
10904 cc_reg,
10905 const0_rtx),
10906 gen_rtx_SET (SImode,
10907 operands[0],
10908 GEN_INT (~0))));
10909 DONE;
10910 }
10911 else
10912 {
10913 /* Emit: cmp\\t%1, %2\;mov%D3\\t%0, #0\;mvn%d3\\t%0, #0 */
10914 emit_insn (gen_rtx_SET (VOIDmode,
10915 cc_reg,
10916 gen_rtx_COMPARE (CCmode, operands[1], operands[2])));
10917 enum rtx_code rc = GET_CODE (operands[3]);
10918
10919 rc = reverse_condition (rc);
10920 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
10921 gen_rtx_fmt_ee (rc,
10922 VOIDmode,
10923 cc_reg,
10924 const0_rtx),
10925 gen_rtx_SET (VOIDmode, operands[0], const0_rtx)));
10926 rc = GET_CODE (operands[3]);
10927 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
10928 gen_rtx_fmt_ee (rc,
10929 VOIDmode,
10930 cc_reg,
10931 const0_rtx),
10932 gen_rtx_SET (VOIDmode,
10933 operands[0],
10934 GEN_INT (~0))));
10935 DONE;
10936 }
10937 FAIL;
10938 }
8fa3ba89 10939 [(set_attr "conds" "clob")
1b7da4ac 10940 (set_attr "length" "12")
10941 (set_attr "type" "multiple")]
8fa3ba89 10942)
9c08d1fa 10943
90404b57 10944(define_insn_and_split "movcond_addsi"
10945 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r")
10946 (if_then_else:SI
10947 (match_operator 5 "comparison_operator"
10948 [(plus:SI (match_operand:SI 3 "s_register_operand" "r,r,r")
10949 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL"))
10950 (const_int 0)])
10951 (match_operand:SI 1 "arm_rhs_operand" "rI,rPy,r")
10952 (match_operand:SI 2 "arm_rhs_operand" "rI,rPy,r")))
10953 (clobber (reg:CC CC_REGNUM))]
10954 "TARGET_32BIT"
10955 "#"
10956 "&& reload_completed"
10957 [(set (reg:CC_NOOV CC_REGNUM)
10958 (compare:CC_NOOV
10959 (plus:SI (match_dup 3)
10960 (match_dup 4))
10961 (const_int 0)))
10962 (set (match_dup 0) (match_dup 1))
10963 (cond_exec (match_dup 6)
10964 (set (match_dup 0) (match_dup 2)))]
10965 "
10966 {
10967 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[5]),
10968 operands[3], operands[4]);
10969 enum rtx_code rc = GET_CODE (operands[5]);
10970
10971 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
10972 gcc_assert (!(mode == CCFPmode || mode == CCFPEmode));
10973 rc = reverse_condition (rc);
10974
10975 operands[6] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10976 }
10977 "
10978 [(set_attr "conds" "clob")
1b7da4ac 10979 (set_attr "enabled_for_depr_it" "no,yes,yes")
10980 (set_attr "type" "multiple")]
90404b57 10981)
10982
9c08d1fa 10983(define_insn "movcond"
10984 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 10985 (if_then_else:SI
8fa3ba89 10986 (match_operator 5 "arm_comparison_operator"
5565501b 10987 [(match_operand:SI 3 "s_register_operand" "r,r,r")
10988 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
10989 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
10990 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 10991 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10992 "TARGET_ARM"
9c08d1fa 10993 "*
10994 if (GET_CODE (operands[5]) == LT
10995 && (operands[4] == const0_rtx))
10996 {
0438d37f 10997 if (which_alternative != 1 && REG_P (operands[1]))
9c08d1fa 10998 {
9c08d1fa 10999 if (operands[2] == const0_rtx)
e2348bcb 11000 return \"and\\t%0, %1, %3, asr #31\";
11001 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
9c08d1fa 11002 }
0438d37f 11003 else if (which_alternative != 0 && REG_P (operands[2]))
9c08d1fa 11004 {
9c08d1fa 11005 if (operands[1] == const0_rtx)
e2348bcb 11006 return \"bic\\t%0, %2, %3, asr #31\";
11007 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
9c08d1fa 11008 }
11009 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 11010 are constants. */
9c08d1fa 11011 }
e2348bcb 11012
9c08d1fa 11013 if (GET_CODE (operands[5]) == GE
11014 && (operands[4] == const0_rtx))
11015 {
0438d37f 11016 if (which_alternative != 1 && REG_P (operands[1]))
9c08d1fa 11017 {
9c08d1fa 11018 if (operands[2] == const0_rtx)
e2348bcb 11019 return \"bic\\t%0, %1, %3, asr #31\";
11020 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
9c08d1fa 11021 }
0438d37f 11022 else if (which_alternative != 0 && REG_P (operands[2]))
9c08d1fa 11023 {
9c08d1fa 11024 if (operands[1] == const0_rtx)
e2348bcb 11025 return \"and\\t%0, %2, %3, asr #31\";
11026 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
9c08d1fa 11027 }
11028 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 11029 are constants. */
9c08d1fa 11030 }
0438d37f 11031 if (CONST_INT_P (operands[4])
9c08d1fa 11032 && !const_ok_for_arm (INTVAL (operands[4])))
e2348bcb 11033 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
9c08d1fa 11034 else
e2348bcb 11035 output_asm_insn (\"cmp\\t%3, %4\", operands);
9c08d1fa 11036 if (which_alternative != 0)
e2348bcb 11037 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
9c08d1fa 11038 if (which_alternative != 1)
e2348bcb 11039 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
9c08d1fa 11040 return \"\";
215b30b3 11041 "
8fa3ba89 11042 [(set_attr "conds" "clob")
1b7da4ac 11043 (set_attr "length" "8,8,12")
11044 (set_attr "type" "multiple")]
8fa3ba89 11045)
9c08d1fa 11046
25f905c2 11047;; ??? The patterns below need checking for Thumb-2 usefulness.
11048
8a18b90c 11049(define_insn "*ifcompare_plus_move"
11050 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 11051 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 11052 [(match_operand:SI 4 "s_register_operand" "r,r")
11053 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
11054 (plus:SI
11055 (match_operand:SI 2 "s_register_operand" "r,r")
11056 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
129a2fe4 11057 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 11058 (clobber (reg:CC CC_REGNUM))]
cffb2a26 11059 "TARGET_ARM"
8a18b90c 11060 "#"
8fa3ba89 11061 [(set_attr "conds" "clob")
1b7da4ac 11062 (set_attr "length" "8,12")
11063 (set_attr "type" "multiple")]
8fa3ba89 11064)
8a18b90c 11065
11066(define_insn "*if_plus_move"
129a2fe4 11067 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 11068 (if_then_else:SI
8fa3ba89 11069 (match_operator 4 "arm_comparison_operator"
8a18b90c 11070 [(match_operand 5 "cc_register" "") (const_int 0)])
11071 (plus:SI
129a2fe4 11072 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
11073 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
11074 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
cffb2a26 11075 "TARGET_ARM"
8a18b90c 11076 "@
11077 add%d4\\t%0, %2, %3
11078 sub%d4\\t%0, %2, #%n3
11079 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
129a2fe4 11080 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8fa3ba89 11081 [(set_attr "conds" "use")
11082 (set_attr "length" "4,4,8,8")
65f68e55 11083 (set_attr_alternative "type"
11084 [(if_then_else (match_operand 3 "const_int_operand" "")
d82e788e 11085 (const_string "alu_imm" )
1b7da4ac 11086 (const_string "alu_reg"))
d82e788e 11087 (const_string "alu_imm")
1b7da4ac 11088 (const_string "alu_reg")
11089 (const_string "alu_reg")])]
8fa3ba89 11090)
8a18b90c 11091
11092(define_insn "*ifcompare_move_plus"
5565501b 11093 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 11094 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 11095 [(match_operand:SI 4 "s_register_operand" "r,r")
11096 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 11097 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 11098 (plus:SI
11099 (match_operand:SI 2 "s_register_operand" "r,r")
11100 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
bd5b4116 11101 (clobber (reg:CC CC_REGNUM))]
cffb2a26 11102 "TARGET_ARM"
8a18b90c 11103 "#"
8fa3ba89 11104 [(set_attr "conds" "clob")
1b7da4ac 11105 (set_attr "length" "8,12")
11106 (set_attr "type" "multiple")]
8fa3ba89 11107)
8a18b90c 11108
11109(define_insn "*if_move_plus"
129a2fe4 11110 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 11111 (if_then_else:SI
8fa3ba89 11112 (match_operator 4 "arm_comparison_operator"
8a18b90c 11113 [(match_operand 5 "cc_register" "") (const_int 0)])
129a2fe4 11114 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8a18b90c 11115 (plus:SI
129a2fe4 11116 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
11117 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
cffb2a26 11118 "TARGET_ARM"
8a18b90c 11119 "@
11120 add%D4\\t%0, %2, %3
11121 sub%D4\\t%0, %2, #%n3
11122 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
129a2fe4 11123 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8fa3ba89 11124 [(set_attr "conds" "use")
11125 (set_attr "length" "4,4,8,8")
1b7da4ac 11126 (set_attr "type" "alu_reg,alu_imm,multiple,multiple")]
8fa3ba89 11127)
8a18b90c 11128
11129(define_insn "*ifcompare_arith_arith"
11130 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 11131 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8a18b90c 11132 [(match_operand:SI 5 "s_register_operand" "r")
11133 (match_operand:SI 6 "arm_add_operand" "rIL")])
9c08d1fa 11134 (match_operator:SI 8 "shiftable_operator"
8a18b90c 11135 [(match_operand:SI 1 "s_register_operand" "r")
11136 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9c08d1fa 11137 (match_operator:SI 7 "shiftable_operator"
8a18b90c 11138 [(match_operand:SI 3 "s_register_operand" "r")
11139 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
bd5b4116 11140 (clobber (reg:CC CC_REGNUM))]
cffb2a26 11141 "TARGET_ARM"
8a18b90c 11142 "#"
8fa3ba89 11143 [(set_attr "conds" "clob")
1b7da4ac 11144 (set_attr "length" "12")
11145 (set_attr "type" "multiple")]
8fa3ba89 11146)
9c08d1fa 11147
8a18b90c 11148(define_insn "*if_arith_arith"
11149 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 11150 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8a18b90c 11151 [(match_operand 8 "cc_register" "") (const_int 0)])
11152 (match_operator:SI 6 "shiftable_operator"
11153 [(match_operand:SI 1 "s_register_operand" "r")
11154 (match_operand:SI 2 "arm_rhs_operand" "rI")])
11155 (match_operator:SI 7 "shiftable_operator"
11156 [(match_operand:SI 3 "s_register_operand" "r")
11157 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
cffb2a26 11158 "TARGET_ARM"
8a18b90c 11159 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8fa3ba89 11160 [(set_attr "conds" "use")
1b7da4ac 11161 (set_attr "length" "8")
11162 (set_attr "type" "multiple")]
8fa3ba89 11163)
8a18b90c 11164
f7fbdd4a 11165(define_insn "*ifcompare_arith_move"
9c08d1fa 11166 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 11167 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 11168 [(match_operand:SI 2 "s_register_operand" "r,r")
5565501b 11169 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
9c08d1fa 11170 (match_operator:SI 7 "shiftable_operator"
11171 [(match_operand:SI 4 "s_register_operand" "r,r")
11172 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
129a2fe4 11173 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 11174 (clobber (reg:CC CC_REGNUM))]
cffb2a26 11175 "TARGET_ARM"
9c08d1fa 11176 "*
9c08d1fa 11177 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 11178 the conditional operator is LT or GE and we are comparing against zero and
674a8f0b 11179 everything is in registers then we can do this in two instructions. */
9c08d1fa 11180 if (operands[3] == const0_rtx
11181 && GET_CODE (operands[7]) != AND
0438d37f 11182 && REG_P (operands[5])
11183 && REG_P (operands[1])
9c08d1fa 11184 && REGNO (operands[1]) == REGNO (operands[4])
11185 && REGNO (operands[4]) != REGNO (operands[0]))
11186 {
11187 if (GET_CODE (operands[6]) == LT)
40dbec34 11188 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 11189 else if (GET_CODE (operands[6]) == GE)
40dbec34 11190 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 11191 }
0438d37f 11192 if (CONST_INT_P (operands[3])
9c08d1fa 11193 && !const_ok_for_arm (INTVAL (operands[3])))
e2348bcb 11194 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
9c08d1fa 11195 else
e2348bcb 11196 output_asm_insn (\"cmp\\t%2, %3\", operands);
40dbec34 11197 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
9c08d1fa 11198 if (which_alternative != 0)
129a2fe4 11199 return \"mov%D6\\t%0, %1\";
9c08d1fa 11200 return \"\";
215b30b3 11201 "
8fa3ba89 11202 [(set_attr "conds" "clob")
1b7da4ac 11203 (set_attr "length" "8,12")
11204 (set_attr "type" "multiple")]
8fa3ba89 11205)
9c08d1fa 11206
8a18b90c 11207(define_insn "*if_arith_move"
129a2fe4 11208 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 11209 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8a18b90c 11210 [(match_operand 6 "cc_register" "") (const_int 0)])
11211 (match_operator:SI 5 "shiftable_operator"
129a2fe4 11212 [(match_operand:SI 2 "s_register_operand" "r,r")
11213 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
11214 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
cffb2a26 11215 "TARGET_ARM"
8a18b90c 11216 "@
11217 %I5%d4\\t%0, %2, %3
129a2fe4 11218 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8fa3ba89 11219 [(set_attr "conds" "use")
11220 (set_attr "length" "4,8")
1b7da4ac 11221 (set_attr "type" "alu_shift_reg,multiple")]
8fa3ba89 11222)
8a18b90c 11223
f7fbdd4a 11224(define_insn "*ifcompare_move_arith"
9c08d1fa 11225 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 11226 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 11227 [(match_operand:SI 4 "s_register_operand" "r,r")
5565501b 11228 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 11229 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9c08d1fa 11230 (match_operator:SI 7 "shiftable_operator"
11231 [(match_operand:SI 2 "s_register_operand" "r,r")
11232 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 11233 (clobber (reg:CC CC_REGNUM))]
cffb2a26 11234 "TARGET_ARM"
9c08d1fa 11235 "*
9c08d1fa 11236 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 11237 the conditional operator is LT or GE and we are comparing against zero and
9c08d1fa 11238 everything is in registers then we can do this in two instructions */
11239 if (operands[5] == const0_rtx
11240 && GET_CODE (operands[7]) != AND
0438d37f 11241 && REG_P (operands[3])
11242 && REG_P (operands[1])
9c08d1fa 11243 && REGNO (operands[1]) == REGNO (operands[2])
11244 && REGNO (operands[2]) != REGNO (operands[0]))
11245 {
11246 if (GET_CODE (operands[6]) == GE)
40dbec34 11247 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 11248 else if (GET_CODE (operands[6]) == LT)
40dbec34 11249 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 11250 }
40dbec34 11251
0438d37f 11252 if (CONST_INT_P (operands[5])
9c08d1fa 11253 && !const_ok_for_arm (INTVAL (operands[5])))
e2348bcb 11254 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
9c08d1fa 11255 else
e2348bcb 11256 output_asm_insn (\"cmp\\t%4, %5\", operands);
40dbec34 11257
9c08d1fa 11258 if (which_alternative != 0)
129a2fe4 11259 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
40dbec34 11260 return \"%I7%D6\\t%0, %2, %3\";
215b30b3 11261 "
8fa3ba89 11262 [(set_attr "conds" "clob")
1b7da4ac 11263 (set_attr "length" "8,12")
11264 (set_attr "type" "multiple")]
8fa3ba89 11265)
9c08d1fa 11266
8a18b90c 11267(define_insn "*if_move_arith"
129a2fe4 11268 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 11269 (if_then_else:SI
8fa3ba89 11270 (match_operator 4 "arm_comparison_operator"
8a18b90c 11271 [(match_operand 6 "cc_register" "") (const_int 0)])
129a2fe4 11272 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 11273 (match_operator:SI 5 "shiftable_operator"
129a2fe4 11274 [(match_operand:SI 2 "s_register_operand" "r,r")
11275 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
cffb2a26 11276 "TARGET_ARM"
8a18b90c 11277 "@
11278 %I5%D4\\t%0, %2, %3
129a2fe4 11279 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
8fa3ba89 11280 [(set_attr "conds" "use")
11281 (set_attr "length" "4,8")
1b7da4ac 11282 (set_attr "type" "alu_shift_reg,multiple")]
8fa3ba89 11283)
8a18b90c 11284
11285(define_insn "*ifcompare_move_not"
9c08d1fa 11286 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 11287 (if_then_else:SI
8fa3ba89 11288 (match_operator 5 "arm_comparison_operator"
8a18b90c 11289 [(match_operand:SI 3 "s_register_operand" "r,r")
11290 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
11291 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
11292 (not:SI
11293 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 11294 (clobber (reg:CC CC_REGNUM))]
cffb2a26 11295 "TARGET_ARM"
8a18b90c 11296 "#"
8fa3ba89 11297 [(set_attr "conds" "clob")
1b7da4ac 11298 (set_attr "length" "8,12")
11299 (set_attr "type" "multiple")]
8fa3ba89 11300)
9c08d1fa 11301
8a18b90c 11302(define_insn "*if_move_not"
11303 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
11304 (if_then_else:SI
8fa3ba89 11305 (match_operator 4 "arm_comparison_operator"
8a18b90c 11306 [(match_operand 3 "cc_register" "") (const_int 0)])
11307 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
11308 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
cffb2a26 11309 "TARGET_ARM"
8a18b90c 11310 "@
11311 mvn%D4\\t%0, %2
11312 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
11313 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
8fa3ba89 11314 [(set_attr "conds" "use")
1aed5204 11315 (set_attr "type" "mvn_reg")
1b7da4ac 11316 (set_attr "length" "4,8,8")
11317 (set_attr "type" "mvn_reg,multiple,multiple")]
8fa3ba89 11318)
8a18b90c 11319
11320(define_insn "*ifcompare_not_move"
9c08d1fa 11321 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 11322 (if_then_else:SI
8fa3ba89 11323 (match_operator 5 "arm_comparison_operator"
8a18b90c 11324 [(match_operand:SI 3 "s_register_operand" "r,r")
11325 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
11326 (not:SI
11327 (match_operand:SI 2 "s_register_operand" "r,r"))
11328 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 11329 (clobber (reg:CC CC_REGNUM))]
cffb2a26 11330 "TARGET_ARM"
8a18b90c 11331 "#"
8fa3ba89 11332 [(set_attr "conds" "clob")
1b7da4ac 11333 (set_attr "length" "8,12")
11334 (set_attr "type" "multiple")]
8fa3ba89 11335)
9c08d1fa 11336
8a18b90c 11337(define_insn "*if_not_move"
11338 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
11339 (if_then_else:SI
8fa3ba89 11340 (match_operator 4 "arm_comparison_operator"
8a18b90c 11341 [(match_operand 3 "cc_register" "") (const_int 0)])
11342 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
11343 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 11344 "TARGET_ARM"
8a18b90c 11345 "@
11346 mvn%d4\\t%0, %2
11347 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
11348 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
8fa3ba89 11349 [(set_attr "conds" "use")
1b7da4ac 11350 (set_attr "type" "mvn_reg,multiple,multiple")
8fa3ba89 11351 (set_attr "length" "4,8,8")]
11352)
8a18b90c 11353
11354(define_insn "*ifcompare_shift_move"
9c08d1fa 11355 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 11356 (if_then_else:SI
8fa3ba89 11357 (match_operator 6 "arm_comparison_operator"
8a18b90c 11358 [(match_operand:SI 4 "s_register_operand" "r,r")
11359 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
11360 (match_operator:SI 7 "shift_operator"
11361 [(match_operand:SI 2 "s_register_operand" "r,r")
11362 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
11363 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 11364 (clobber (reg:CC CC_REGNUM))]
cffb2a26 11365 "TARGET_ARM"
9c08d1fa 11366 "#"
8fa3ba89 11367 [(set_attr "conds" "clob")
1b7da4ac 11368 (set_attr "length" "8,12")
11369 (set_attr "type" "multiple")]
8fa3ba89 11370)
9c08d1fa 11371
8a18b90c 11372(define_insn "*if_shift_move"
11373 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
11374 (if_then_else:SI
8fa3ba89 11375 (match_operator 5 "arm_comparison_operator"
8a18b90c 11376 [(match_operand 6 "cc_register" "") (const_int 0)])
11377 (match_operator:SI 4 "shift_operator"
11378 [(match_operand:SI 2 "s_register_operand" "r,r,r")
11379 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
11380 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 11381 "TARGET_ARM"
5565501b 11382 "@
8a18b90c 11383 mov%d5\\t%0, %2%S4
11384 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
11385 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
8fa3ba89 11386 [(set_attr "conds" "use")
331beb1a 11387 (set_attr "shift" "2")
a2cd141b 11388 (set_attr "length" "4,8,8")
1b7da4ac 11389 (set_attr "type" "mov_shift_reg,multiple,multiple")]
8fa3ba89 11390)
5565501b 11391
8a18b90c 11392(define_insn "*ifcompare_move_shift"
11393 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 11394 (if_then_else:SI
8fa3ba89 11395 (match_operator 6 "arm_comparison_operator"
8a18b90c 11396 [(match_operand:SI 4 "s_register_operand" "r,r")
11397 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
11398 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
5565501b 11399 (match_operator:SI 7 "shift_operator"
8a18b90c 11400 [(match_operand:SI 2 "s_register_operand" "r,r")
11401 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
bd5b4116 11402 (clobber (reg:CC CC_REGNUM))]
cffb2a26 11403 "TARGET_ARM"
8a18b90c 11404 "#"
8fa3ba89 11405 [(set_attr "conds" "clob")
1b7da4ac 11406 (set_attr "length" "8,12")
11407 (set_attr "type" "multiple")]
8fa3ba89 11408)
5565501b 11409
8a18b90c 11410(define_insn "*if_move_shift"
11411 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 11412 (if_then_else:SI
8fa3ba89 11413 (match_operator 5 "arm_comparison_operator"
8a18b90c 11414 [(match_operand 6 "cc_register" "") (const_int 0)])
11415 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
11416 (match_operator:SI 4 "shift_operator"
11417 [(match_operand:SI 2 "s_register_operand" "r,r,r")
11418 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
cffb2a26 11419 "TARGET_ARM"
5565501b 11420 "@
8a18b90c 11421 mov%D5\\t%0, %2%S4
11422 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
11423 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
8fa3ba89 11424 [(set_attr "conds" "use")
331beb1a 11425 (set_attr "shift" "2")
a2cd141b 11426 (set_attr "length" "4,8,8")
1b7da4ac 11427 (set_attr "type" "mov_shift_reg,multiple,multiple")]
8fa3ba89 11428)
9c08d1fa 11429
f7fbdd4a 11430(define_insn "*ifcompare_shift_shift"
8a18b90c 11431 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 11432 (if_then_else:SI
8fa3ba89 11433 (match_operator 7 "arm_comparison_operator"
8a18b90c 11434 [(match_operand:SI 5 "s_register_operand" "r")
11435 (match_operand:SI 6 "arm_add_operand" "rIL")])
5565501b 11436 (match_operator:SI 8 "shift_operator"
8a18b90c 11437 [(match_operand:SI 1 "s_register_operand" "r")
11438 (match_operand:SI 2 "arm_rhs_operand" "rM")])
5565501b 11439 (match_operator:SI 9 "shift_operator"
8a18b90c 11440 [(match_operand:SI 3 "s_register_operand" "r")
11441 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
bd5b4116 11442 (clobber (reg:CC CC_REGNUM))]
cffb2a26 11443 "TARGET_ARM"
8a18b90c 11444 "#"
8fa3ba89 11445 [(set_attr "conds" "clob")
1b7da4ac 11446 (set_attr "length" "12")
11447 (set_attr "type" "multiple")]
8fa3ba89 11448)
9c08d1fa 11449
8a18b90c 11450(define_insn "*if_shift_shift"
11451 [(set (match_operand:SI 0 "s_register_operand" "=r")
11452 (if_then_else:SI
8fa3ba89 11453 (match_operator 5 "arm_comparison_operator"
8a18b90c 11454 [(match_operand 8 "cc_register" "") (const_int 0)])
11455 (match_operator:SI 6 "shift_operator"
11456 [(match_operand:SI 1 "s_register_operand" "r")
11457 (match_operand:SI 2 "arm_rhs_operand" "rM")])
11458 (match_operator:SI 7 "shift_operator"
11459 [(match_operand:SI 3 "s_register_operand" "r")
11460 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
cffb2a26 11461 "TARGET_ARM"
8a18b90c 11462 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
8fa3ba89 11463 [(set_attr "conds" "use")
331beb1a 11464 (set_attr "shift" "1")
a2cd141b 11465 (set_attr "length" "8")
11466 (set (attr "type") (if_then_else
11467 (and (match_operand 2 "const_int_operand" "")
11468 (match_operand 4 "const_int_operand" ""))
1aed5204 11469 (const_string "mov_shift")
11470 (const_string "mov_shift_reg")))]
8fa3ba89 11471)
8a18b90c 11472
f7fbdd4a 11473(define_insn "*ifcompare_not_arith"
8a18b90c 11474 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 11475 (if_then_else:SI
8fa3ba89 11476 (match_operator 6 "arm_comparison_operator"
8a18b90c 11477 [(match_operand:SI 4 "s_register_operand" "r")
11478 (match_operand:SI 5 "arm_add_operand" "rIL")])
11479 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5565501b 11480 (match_operator:SI 7 "shiftable_operator"
8a18b90c 11481 [(match_operand:SI 2 "s_register_operand" "r")
11482 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
bd5b4116 11483 (clobber (reg:CC CC_REGNUM))]
cffb2a26 11484 "TARGET_ARM"
8a18b90c 11485 "#"
8fa3ba89 11486 [(set_attr "conds" "clob")
1b7da4ac 11487 (set_attr "length" "12")
11488 (set_attr "type" "multiple")]
8fa3ba89 11489)
9c08d1fa 11490
8a18b90c 11491(define_insn "*if_not_arith"
11492 [(set (match_operand:SI 0 "s_register_operand" "=r")
11493 (if_then_else:SI
8fa3ba89 11494 (match_operator 5 "arm_comparison_operator"
8a18b90c 11495 [(match_operand 4 "cc_register" "") (const_int 0)])
11496 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
11497 (match_operator:SI 6 "shiftable_operator"
11498 [(match_operand:SI 2 "s_register_operand" "r")
11499 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
cffb2a26 11500 "TARGET_ARM"
8a18b90c 11501 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
8fa3ba89 11502 [(set_attr "conds" "use")
1aed5204 11503 (set_attr "type" "mvn_reg")
8fa3ba89 11504 (set_attr "length" "8")]
11505)
8a18b90c 11506
11507(define_insn "*ifcompare_arith_not"
11508 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 11509 (if_then_else:SI
8fa3ba89 11510 (match_operator 6 "arm_comparison_operator"
8a18b90c 11511 [(match_operand:SI 4 "s_register_operand" "r")
11512 (match_operand:SI 5 "arm_add_operand" "rIL")])
5565501b 11513 (match_operator:SI 7 "shiftable_operator"
8a18b90c 11514 [(match_operand:SI 2 "s_register_operand" "r")
11515 (match_operand:SI 3 "arm_rhs_operand" "rI")])
11516 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
bd5b4116 11517 (clobber (reg:CC CC_REGNUM))]
cffb2a26 11518 "TARGET_ARM"
8a18b90c 11519 "#"
8fa3ba89 11520 [(set_attr "conds" "clob")
1b7da4ac 11521 (set_attr "length" "12")
11522 (set_attr "type" "multiple")]
8fa3ba89 11523)
9c08d1fa 11524
8a18b90c 11525(define_insn "*if_arith_not"
11526 [(set (match_operand:SI 0 "s_register_operand" "=r")
11527 (if_then_else:SI
8fa3ba89 11528 (match_operator 5 "arm_comparison_operator"
8a18b90c 11529 [(match_operand 4 "cc_register" "") (const_int 0)])
11530 (match_operator:SI 6 "shiftable_operator"
11531 [(match_operand:SI 2 "s_register_operand" "r")
11532 (match_operand:SI 3 "arm_rhs_operand" "rI")])
11533 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
cffb2a26 11534 "TARGET_ARM"
8a18b90c 11535 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
8fa3ba89 11536 [(set_attr "conds" "use")
1b7da4ac 11537 (set_attr "type" "multiple")
8fa3ba89 11538 (set_attr "length" "8")]
11539)
8a18b90c 11540
f7fbdd4a 11541(define_insn "*ifcompare_neg_move"
8a18b90c 11542 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 11543 (if_then_else:SI
8fa3ba89 11544 (match_operator 5 "arm_comparison_operator"
8a18b90c 11545 [(match_operand:SI 3 "s_register_operand" "r,r")
11546 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
11547 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
11548 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 11549 (clobber (reg:CC CC_REGNUM))]
cffb2a26 11550 "TARGET_ARM"
8a18b90c 11551 "#"
8fa3ba89 11552 [(set_attr "conds" "clob")
1b7da4ac 11553 (set_attr "length" "8,12")
11554 (set_attr "type" "multiple")]
8fa3ba89 11555)
8a18b90c 11556
11557(define_insn "*if_neg_move"
11558 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
11559 (if_then_else:SI
8fa3ba89 11560 (match_operator 4 "arm_comparison_operator"
8a18b90c 11561 [(match_operand 3 "cc_register" "") (const_int 0)])
11562 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
11563 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 11564 "TARGET_ARM"
8a18b90c 11565 "@
11566 rsb%d4\\t%0, %2, #0
11567 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
11568 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
8fa3ba89 11569 [(set_attr "conds" "use")
1b7da4ac 11570 (set_attr "length" "4,8,8")
11571 (set_attr "type" "logic_shift_imm,multiple,multiple")]
8fa3ba89 11572)
9c08d1fa 11573
f7fbdd4a 11574(define_insn "*ifcompare_move_neg"
8a18b90c 11575 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 11576 (if_then_else:SI
8fa3ba89 11577 (match_operator 5 "arm_comparison_operator"
8a18b90c 11578 [(match_operand:SI 3 "s_register_operand" "r,r")
11579 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
11580 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
11581 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 11582 (clobber (reg:CC CC_REGNUM))]
cffb2a26 11583 "TARGET_ARM"
8a18b90c 11584 "#"
8fa3ba89 11585 [(set_attr "conds" "clob")
1b7da4ac 11586 (set_attr "length" "8,12")
11587 (set_attr "type" "multiple")]
8fa3ba89 11588)
8a18b90c 11589
11590(define_insn "*if_move_neg"
11591 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
11592 (if_then_else:SI
8fa3ba89 11593 (match_operator 4 "arm_comparison_operator"
8a18b90c 11594 [(match_operand 3 "cc_register" "") (const_int 0)])
11595 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
11596 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
cffb2a26 11597 "TARGET_ARM"
8a18b90c 11598 "@
11599 rsb%D4\\t%0, %2, #0
11600 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
11601 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
0d66636f 11602 [(set_attr "conds" "use")
1b7da4ac 11603 (set_attr "length" "4,8,8")
11604 (set_attr "type" "logic_shift_imm,multiple,multiple")]
0d66636f 11605)
9c08d1fa 11606
f7fbdd4a 11607(define_insn "*arith_adjacentmem"
9c08d1fa 11608 [(set (match_operand:SI 0 "s_register_operand" "=r")
11609 (match_operator:SI 1 "shiftable_operator"
11610 [(match_operand:SI 2 "memory_operand" "m")
11611 (match_operand:SI 3 "memory_operand" "m")]))
11612 (clobber (match_scratch:SI 4 "=r"))]
cffb2a26 11613 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9c08d1fa 11614 "*
215b30b3 11615 {
11616 rtx ldm[3];
11617 rtx arith[4];
94dee231 11618 rtx base_reg;
11619 HOST_WIDE_INT val1 = 0, val2 = 0;
9c08d1fa 11620
215b30b3 11621 if (REGNO (operands[0]) > REGNO (operands[4]))
11622 {
11623 ldm[1] = operands[4];
11624 ldm[2] = operands[0];
11625 }
11626 else
11627 {
11628 ldm[1] = operands[0];
11629 ldm[2] = operands[4];
11630 }
94dee231 11631
11632 base_reg = XEXP (operands[2], 0);
11633
11634 if (!REG_P (base_reg))
11635 {
11636 val1 = INTVAL (XEXP (base_reg, 1));
11637 base_reg = XEXP (base_reg, 0);
11638 }
11639
11640 if (!REG_P (XEXP (operands[3], 0)))
215b30b3 11641 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
94dee231 11642
215b30b3 11643 arith[0] = operands[0];
11644 arith[3] = operands[1];
94dee231 11645
215b30b3 11646 if (val1 < val2)
11647 {
11648 arith[1] = ldm[1];
11649 arith[2] = ldm[2];
11650 }
11651 else
11652 {
11653 arith[1] = ldm[2];
11654 arith[2] = ldm[1];
11655 }
94dee231 11656
11657 ldm[0] = base_reg;
11658 if (val1 !=0 && val2 != 0)
215b30b3 11659 {
cdb1295a 11660 rtx ops[3];
11661
94dee231 11662 if (val1 == 4 || val2 == 4)
11663 /* Other val must be 8, since we know they are adjacent and neither
11664 is zero. */
25f905c2 11665 output_asm_insn (\"ldm%(ib%)\\t%0, {%1, %2}\", ldm);
cdb1295a 11666 else if (const_ok_for_arm (val1) || const_ok_for_arm (-val1))
94dee231 11667 {
94dee231 11668 ldm[0] = ops[0] = operands[4];
11669 ops[1] = base_reg;
11670 ops[2] = GEN_INT (val1);
11671 output_add_immediate (ops);
11672 if (val1 < val2)
25f905c2 11673 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
94dee231 11674 else
25f905c2 11675 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
94dee231 11676 }
cdb1295a 11677 else
11678 {
11679 /* Offset is out of range for a single add, so use two ldr. */
11680 ops[0] = ldm[1];
11681 ops[1] = base_reg;
11682 ops[2] = GEN_INT (val1);
11683 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
11684 ops[0] = ldm[2];
11685 ops[2] = GEN_INT (val2);
11686 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
11687 }
215b30b3 11688 }
94dee231 11689 else if (val1 != 0)
215b30b3 11690 {
215b30b3 11691 if (val1 < val2)
25f905c2 11692 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
215b30b3 11693 else
25f905c2 11694 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
215b30b3 11695 }
11696 else
11697 {
215b30b3 11698 if (val1 < val2)
25f905c2 11699 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
215b30b3 11700 else
25f905c2 11701 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
215b30b3 11702 }
11703 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
11704 return \"\";
11705 }"
11706 [(set_attr "length" "12")
11707 (set_attr "predicable" "yes")
a2cd141b 11708 (set_attr "type" "load1")]
215b30b3 11709)
9c08d1fa 11710
9c08d1fa 11711; This pattern is never tried by combine, so do it as a peephole
11712
a0f94409 11713(define_peephole2
372575c7 11714 [(set (match_operand:SI 0 "arm_general_register_operand" "")
11715 (match_operand:SI 1 "arm_general_register_operand" ""))
bd5b4116 11716 (set (reg:CC CC_REGNUM)
aea4c774 11717 (compare:CC (match_dup 1) (const_int 0)))]
372575c7 11718 "TARGET_ARM"
a0f94409 11719 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
11720 (set (match_dup 0) (match_dup 1))])]
11721 ""
0d66636f 11722)
9c08d1fa 11723
9c08d1fa 11724(define_split
11725 [(set (match_operand:SI 0 "s_register_operand" "")
11726 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
11727 (const_int 0))
8fa3ba89 11728 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9c08d1fa 11729 [(match_operand:SI 3 "s_register_operand" "")
11730 (match_operand:SI 4 "arm_rhs_operand" "")]))))
11731 (clobber (match_operand:SI 5 "s_register_operand" ""))]
cffb2a26 11732 "TARGET_ARM"
9c08d1fa 11733 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
11734 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
11735 (match_dup 5)))]
215b30b3 11736 ""
11737)
9c08d1fa 11738
aea4c774 11739;; This split can be used because CC_Z mode implies that the following
11740;; branch will be an equality, or an unsigned inequality, so the sign
11741;; extension is not needed.
9c08d1fa 11742
aea4c774 11743(define_split
bd5b4116 11744 [(set (reg:CC_Z CC_REGNUM)
aea4c774 11745 (compare:CC_Z
11746 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9c08d1fa 11747 (const_int 24))
aea4c774 11748 (match_operand 1 "const_int_operand" "")))
11749 (clobber (match_scratch:SI 2 ""))]
cffb2a26 11750 "TARGET_ARM
11751 && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
11752 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
aea4c774 11753 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
bd5b4116 11754 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
aea4c774 11755 "
9c08d1fa 11756 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
215b30b3 11757 "
11758)
25f905c2 11759;; ??? Check the patterns above for Thumb-2 usefulness
9c08d1fa 11760
87b22bf7 11761(define_expand "prologue"
11762 [(clobber (const_int 0))]
cffb2a26 11763 "TARGET_EITHER"
25f905c2 11764 "if (TARGET_32BIT)
cffb2a26 11765 arm_expand_prologue ();
11766 else
25f905c2 11767 thumb1_expand_prologue ();
87b22bf7 11768 DONE;
cffb2a26 11769 "
11770)
87b22bf7 11771
56d27660 11772(define_expand "epilogue"
4c44712e 11773 [(clobber (const_int 0))]
cffb2a26 11774 "TARGET_EITHER"
56d27660 11775 "
18d50ae6 11776 if (crtl->calls_eh_return)
fb94f18b 11777 emit_insn (gen_force_register_use (gen_rtx_REG (Pmode, 2)));
25f905c2 11778 if (TARGET_THUMB1)
c3635784 11779 {
11780 thumb1_expand_epilogue ();
11781 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
11782 gen_rtvec (1, ret_rtx), VUNSPEC_EPILOGUE));
11783 }
11784 else if (HAVE_return)
11785 {
11786 /* HAVE_return is testing for USE_RETURN_INSN (FALSE). Hence,
11787 no need for explicit testing again. */
11788 emit_jump_insn (gen_return ());
11789 }
11790 else if (TARGET_32BIT)
11791 {
11792 arm_expand_epilogue (true);
11793 }
cffb2a26 11794 DONE;
11795 "
11796)
56d27660 11797
7571d3f7 11798(define_insn "prologue_thumb1_interwork"
11799 [(unspec_volatile [(const_int 0)] VUNSPEC_THUMB1_INTERWORK)]
11800 "TARGET_THUMB1"
11801 "* return thumb1_output_interwork ();"
1b7da4ac 11802 [(set_attr "length" "8")
11803 (set_attr "type" "multiple")]
7571d3f7 11804)
11805
ef5651d0 11806;; Note - although unspec_volatile's USE all hard registers,
11807;; USEs are ignored after relaod has completed. Thus we need
11808;; to add an unspec of the link register to ensure that flow
11809;; does not think that it is unused by the sibcall branch that
11810;; will replace the standard function epilogue.
c3635784 11811(define_expand "sibcall_epilogue"
fb94f18b 11812 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_REGISTER_USE)
c3635784 11813 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
11814 "TARGET_32BIT"
11815 "
11816 arm_expand_epilogue (false);
11817 DONE;
11818 "
1c494086 11819)
11820
cffb2a26 11821(define_insn "*epilogue_insns"
e1159bbe 11822 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
b1324f4f 11823 "TARGET_THUMB1"
56d27660 11824 "*
e7fd8dfa 11825 return thumb1_unexpanded_epilogue ();
cffb2a26 11826 "
215b30b3 11827 ; Length is absolute worst case
cffb2a26 11828 [(set_attr "length" "44")
defc47cf 11829 (set_attr "type" "block")
11830 ;; We don't clobber the conditions, but the potential length of this
11831 ;; operation is sufficient to make conditionalizing the sequence
11832 ;; unlikely to be profitable.
11833 (set_attr "conds" "clob")]
cffb2a26 11834)
11835
11836(define_expand "eh_epilogue"
7db9af5d 11837 [(use (match_operand:SI 0 "register_operand" ""))
11838 (use (match_operand:SI 1 "register_operand" ""))
11839 (use (match_operand:SI 2 "register_operand" ""))]
cffb2a26 11840 "TARGET_EITHER"
11841 "
215b30b3 11842 {
11843 cfun->machine->eh_epilogue_sp_ofs = operands[1];
0438d37f 11844 if (!REG_P (operands[2]) || REGNO (operands[2]) != 2)
215b30b3 11845 {
11846 rtx ra = gen_rtx_REG (Pmode, 2);
11847
11848 emit_move_insn (ra, operands[2]);
11849 operands[2] = ra;
11850 }
5cf3595a 11851 /* This is a hack -- we may have crystalized the function type too
11852 early. */
11853 cfun->machine->func_type = 0;
215b30b3 11854 }"
11855)
56d27660 11856
9c08d1fa 11857;; This split is only used during output to reduce the number of patterns
11858;; that need assembler instructions adding to them. We allowed the setting
11859;; of the conditions to be implicit during rtl generation so that
11860;; the conditional compare patterns would work. However this conflicts to
8a18b90c 11861;; some extent with the conditional data operations, so we have to split them
9c08d1fa 11862;; up again here.
11863
25f905c2 11864;; ??? Need to audit these splitters for Thumb-2. Why isn't normal
11865;; conditional execution sufficient?
11866
9c08d1fa 11867(define_split
11868 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 11869 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
11870 [(match_operand 2 "" "") (match_operand 3 "" "")])
11871 (match_dup 0)
11872 (match_operand 4 "" "")))
bd5b4116 11873 (clobber (reg:CC CC_REGNUM))]
ac8b093b 11874 "TARGET_ARM && reload_completed"
8fa3ba89 11875 [(set (match_dup 5) (match_dup 6))
11876 (cond_exec (match_dup 7)
11877 (set (match_dup 0) (match_dup 4)))]
11878 "
11879 {
11880 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
11881 operands[2], operands[3]);
11882 enum rtx_code rc = GET_CODE (operands[1]);
11883
bd5b4116 11884 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 11885 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
11886 if (mode == CCFPmode || mode == CCFPEmode)
11887 rc = reverse_condition_maybe_unordered (rc);
11888 else
11889 rc = reverse_condition (rc);
11890
11891 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
11892 }"
11893)
11894
11895(define_split
11896 [(set (match_operand:SI 0 "s_register_operand" "")
11897 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
11898 [(match_operand 2 "" "") (match_operand 3 "" "")])
11899 (match_operand 4 "" "")
11900 (match_dup 0)))
bd5b4116 11901 (clobber (reg:CC CC_REGNUM))]
ac8b093b 11902 "TARGET_ARM && reload_completed"
8fa3ba89 11903 [(set (match_dup 5) (match_dup 6))
11904 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
11905 (set (match_dup 0) (match_dup 4)))]
11906 "
11907 {
11908 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
11909 operands[2], operands[3]);
11910
bd5b4116 11911 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 11912 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
11913 }"
11914)
11915
11916(define_split
11917 [(set (match_operand:SI 0 "s_register_operand" "")
11918 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9c08d1fa 11919 [(match_operand 2 "" "") (match_operand 3 "" "")])
11920 (match_operand 4 "" "")
11921 (match_operand 5 "" "")))
bd5b4116 11922 (clobber (reg:CC CC_REGNUM))]
ac8b093b 11923 "TARGET_ARM && reload_completed"
8fa3ba89 11924 [(set (match_dup 6) (match_dup 7))
11925 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
11926 (set (match_dup 0) (match_dup 4)))
11927 (cond_exec (match_dup 8)
11928 (set (match_dup 0) (match_dup 5)))]
11929 "
11930 {
11931 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
11932 operands[2], operands[3]);
11933 enum rtx_code rc = GET_CODE (operands[1]);
11934
bd5b4116 11935 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 11936 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
11937 if (mode == CCFPmode || mode == CCFPEmode)
11938 rc = reverse_condition_maybe_unordered (rc);
11939 else
11940 rc = reverse_condition (rc);
11941
11942 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
11943 }"
11944)
11945
cffb2a26 11946(define_split
11947 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 11948 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
cffb2a26 11949 [(match_operand:SI 2 "s_register_operand" "")
11950 (match_operand:SI 3 "arm_add_operand" "")])
11951 (match_operand:SI 4 "arm_rhs_operand" "")
11952 (not:SI
11953 (match_operand:SI 5 "s_register_operand" ""))))
bd5b4116 11954 (clobber (reg:CC CC_REGNUM))]
ac8b093b 11955 "TARGET_ARM && reload_completed"
cffb2a26 11956 [(set (match_dup 6) (match_dup 7))
f6c53574 11957 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
11958 (set (match_dup 0) (match_dup 4)))
11959 (cond_exec (match_dup 8)
11960 (set (match_dup 0) (not:SI (match_dup 5))))]
cffb2a26 11961 "
215b30b3 11962 {
11963 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
11964 operands[2], operands[3]);
f6c53574 11965 enum rtx_code rc = GET_CODE (operands[1]);
cffb2a26 11966
bd5b4116 11967 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
1a83b3ff 11968 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
f6c53574 11969 if (mode == CCFPmode || mode == CCFPEmode)
11970 rc = reverse_condition_maybe_unordered (rc);
11971 else
11972 rc = reverse_condition (rc);
11973
11974 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
215b30b3 11975 }"
11976)
cffb2a26 11977
11978(define_insn "*cond_move_not"
11979 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 11980 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
cffb2a26 11981 [(match_operand 3 "cc_register" "") (const_int 0)])
11982 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
11983 (not:SI
11984 (match_operand:SI 2 "s_register_operand" "r,r"))))]
11985 "TARGET_ARM"
11986 "@
11987 mvn%D4\\t%0, %2
11988 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
0d66636f 11989 [(set_attr "conds" "use")
1b7da4ac 11990 (set_attr "type" "mvn_reg,multiple")
0d66636f 11991 (set_attr "length" "4,8")]
11992)
cffb2a26 11993
9c08d1fa 11994;; The next two patterns occur when an AND operation is followed by a
11995;; scc insn sequence
11996
f7fbdd4a 11997(define_insn "*sign_extract_onebit"
9c08d1fa 11998 [(set (match_operand:SI 0 "s_register_operand" "=r")
11999 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
12000 (const_int 1)
ed750274 12001 (match_operand:SI 2 "const_int_operand" "n")))
12002 (clobber (reg:CC CC_REGNUM))]
cffb2a26 12003 "TARGET_ARM"
9c08d1fa 12004 "*
0d66636f 12005 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
12006 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
12007 return \"mvnne\\t%0, #0\";
12008 "
12009 [(set_attr "conds" "clob")
1b7da4ac 12010 (set_attr "length" "8")
12011 (set_attr "type" "multiple")]
0d66636f 12012)
9c08d1fa 12013
f7fbdd4a 12014(define_insn "*not_signextract_onebit"
9c08d1fa 12015 [(set (match_operand:SI 0 "s_register_operand" "=r")
12016 (not:SI
12017 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
12018 (const_int 1)
ed750274 12019 (match_operand:SI 2 "const_int_operand" "n"))))
12020 (clobber (reg:CC CC_REGNUM))]
cffb2a26 12021 "TARGET_ARM"
9c08d1fa 12022 "*
0d66636f 12023 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
12024 output_asm_insn (\"tst\\t%1, %2\", operands);
12025 output_asm_insn (\"mvneq\\t%0, #0\", operands);
12026 return \"movne\\t%0, #0\";
12027 "
12028 [(set_attr "conds" "clob")
1b7da4ac 12029 (set_attr "length" "12")
12030 (set_attr "type" "multiple")]
0d66636f 12031)
25f905c2 12032;; ??? The above patterns need auditing for Thumb-2
87b22bf7 12033
0d66636f 12034;; Push multiple registers to the stack. Registers are in parallel (use ...)
12035;; expressions. For simplicity, the first register is also in the unspec
12036;; part.
08508cbf 12037;; To avoid the usage of GNU extension, the length attribute is computed
12038;; in a C function arm_attr_length_push_multi.
f7fbdd4a 12039(define_insn "*push_multi"
87b22bf7 12040 [(match_parallel 2 "multi_register_push"
7571d3f7 12041 [(set (match_operand:BLK 0 "push_mult_memory_operand" "")
3cc80a30 12042 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "")]
e1159bbe 12043 UNSPEC_PUSH_MULT))])]
7571d3f7 12044 ""
87b22bf7 12045 "*
215b30b3 12046 {
12047 int num_saves = XVECLEN (operands[2], 0);
ed593f11 12048
215b30b3 12049 /* For the StrongARM at least it is faster to
25f905c2 12050 use STR to store only a single register.
542d5028 12051 In Thumb mode always use push, and the assembler will pick
12052 something appropriate. */
25f905c2 12053 if (num_saves == 1 && TARGET_ARM)
61309563 12054 output_asm_insn (\"str%?\\t%1, [%m0, #-4]!\", operands);
215b30b3 12055 else
12056 {
12057 int i;
12058 char pattern[100];
ed593f11 12059
25f905c2 12060 if (TARGET_ARM)
61309563 12061 strcpy (pattern, \"stm%(fd%)\\t%m0!, {%1\");
12062 else if (TARGET_THUMB2)
12063 strcpy (pattern, \"push%?\\t{%1\");
25f905c2 12064 else
12065 strcpy (pattern, \"push\\t{%1\");
215b30b3 12066
6079f055 12067 for (i = 1; i < num_saves; i++)
215b30b3 12068 {
12069 strcat (pattern, \", %|\");
12070 strcat (pattern,
12071 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
12072 }
12073
12074 strcat (pattern, \"}\");
12075 output_asm_insn (pattern, operands);
12076 }
12077
12078 return \"\";
12079 }"
a6864a24 12080 [(set_attr "type" "store4")
12081 (set (attr "length")
08508cbf 12082 (symbol_ref "arm_attr_length_push_multi (operands[2], operands[1])"))]
215b30b3 12083)
f7fbdd4a 12084
4c58c898 12085(define_insn "stack_tie"
12086 [(set (mem:BLK (scratch))
aaa37ad6 12087 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "rk")
12088 (match_operand:SI 1 "s_register_operand" "rk")]
4c58c898 12089 UNSPEC_PRLG_STK))]
12090 ""
12091 ""
1b7da4ac 12092 [(set_attr "length" "0")
12093 (set_attr "type" "block")]
4c58c898 12094)
12095
426be8c5 12096;; Pop (as used in epilogue RTL)
12097;;
12098(define_insn "*load_multiple_with_writeback"
12099 [(match_parallel 0 "load_multiple_operation"
12100 [(set (match_operand:SI 1 "s_register_operand" "+rk")
12101 (plus:SI (match_dup 1)
809003b3 12102 (match_operand:SI 2 "const_int_I_operand" "I")))
426be8c5 12103 (set (match_operand:SI 3 "s_register_operand" "=rk")
12104 (mem:SI (match_dup 1)))
12105 ])]
12106 "TARGET_32BIT && (reload_in_progress || reload_completed)"
12107 "*
12108 {
12109 arm_output_multireg_pop (operands, /*return_pc=*/false,
12110 /*cond=*/const_true_rtx,
12111 /*reverse=*/false,
12112 /*update=*/true);
12113 return \"\";
12114 }
12115 "
12116 [(set_attr "type" "load4")
12117 (set_attr "predicable" "yes")]
12118)
12119
12120;; Pop with return (as used in epilogue RTL)
12121;;
12122;; This instruction is generated when the registers are popped at the end of
12123;; epilogue. Here, instead of popping the value into LR and then generating
12124;; jump to LR, value is popped into PC directly. Hence, the pattern is combined
12125;; with (return).
12126(define_insn "*pop_multiple_with_writeback_and_return"
12127 [(match_parallel 0 "pop_multiple_return"
12128 [(return)
12129 (set (match_operand:SI 1 "s_register_operand" "+rk")
12130 (plus:SI (match_dup 1)
809003b3 12131 (match_operand:SI 2 "const_int_I_operand" "I")))
426be8c5 12132 (set (match_operand:SI 3 "s_register_operand" "=rk")
12133 (mem:SI (match_dup 1)))
12134 ])]
12135 "TARGET_32BIT && (reload_in_progress || reload_completed)"
12136 "*
12137 {
12138 arm_output_multireg_pop (operands, /*return_pc=*/true,
12139 /*cond=*/const_true_rtx,
12140 /*reverse=*/false,
12141 /*update=*/true);
12142 return \"\";
12143 }
12144 "
12145 [(set_attr "type" "load4")
12146 (set_attr "predicable" "yes")]
12147)
12148
12149(define_insn "*pop_multiple_with_return"
12150 [(match_parallel 0 "pop_multiple_return"
12151 [(return)
12152 (set (match_operand:SI 2 "s_register_operand" "=rk")
12153 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
12154 ])]
12155 "TARGET_32BIT && (reload_in_progress || reload_completed)"
12156 "*
12157 {
12158 arm_output_multireg_pop (operands, /*return_pc=*/true,
12159 /*cond=*/const_true_rtx,
12160 /*reverse=*/false,
12161 /*update=*/false);
12162 return \"\";
12163 }
12164 "
12165 [(set_attr "type" "load4")
12166 (set_attr "predicable" "yes")]
12167)
12168
12169;; Load into PC and return
12170(define_insn "*ldr_with_return"
12171 [(return)
12172 (set (reg:SI PC_REGNUM)
12173 (mem:SI (post_inc:SI (match_operand:SI 0 "s_register_operand" "+rk"))))]
12174 "TARGET_32BIT && (reload_in_progress || reload_completed)"
12175 "ldr%?\t%|pc, [%0], #4"
12176 [(set_attr "type" "load1")
12177 (set_attr "predicable" "yes")]
12178)
1a0b0f12 12179;; Pop for floating point registers (as used in epilogue RTL)
12180(define_insn "*vfp_pop_multiple_with_writeback"
12181 [(match_parallel 0 "pop_multiple_fp"
12182 [(set (match_operand:SI 1 "s_register_operand" "+rk")
12183 (plus:SI (match_dup 1)
809003b3 12184 (match_operand:SI 2 "const_int_I_operand" "I")))
2f2163a4 12185 (set (match_operand:DF 3 "vfp_hard_register_operand" "")
1a0b0f12 12186 (mem:DF (match_dup 1)))])]
12187 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
12188 "*
12189 {
12190 int num_regs = XVECLEN (operands[0], 0);
12191 char pattern[100];
12192 rtx op_list[2];
12193 strcpy (pattern, \"fldmfdd\\t\");
12194 strcat (pattern, reg_names[REGNO (SET_DEST (XVECEXP (operands[0], 0, 0)))]);
12195 strcat (pattern, \"!, {\");
12196 op_list[0] = XEXP (XVECEXP (operands[0], 0, 1), 0);
12197 strcat (pattern, \"%P0\");
12198 if ((num_regs - 1) > 1)
12199 {
12200 strcat (pattern, \"-%P1\");
12201 op_list [1] = XEXP (XVECEXP (operands[0], 0, num_regs - 1), 0);
12202 }
12203
12204 strcat (pattern, \"}\");
12205 output_asm_insn (pattern, op_list);
12206 return \"\";
12207 }
12208 "
12209 [(set_attr "type" "load4")
12210 (set_attr "conds" "unconditional")
12211 (set_attr "predicable" "no")]
12212)
12213
f7fbdd4a 12214;; Special patterns for dealing with the constant pool
12215
cffb2a26 12216(define_insn "align_4"
e1159bbe 12217 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
cffb2a26 12218 "TARGET_EITHER"
f7fbdd4a 12219 "*
cffb2a26 12220 assemble_align (32);
f7fbdd4a 12221 return \"\";
cffb2a26 12222 "
1b7da4ac 12223 [(set_attr "type" "no_insn")]
cffb2a26 12224)
f7fbdd4a 12225
755eb2b4 12226(define_insn "align_8"
12227 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
f9273c43 12228 "TARGET_EITHER"
755eb2b4 12229 "*
12230 assemble_align (64);
12231 return \"\";
12232 "
1b7da4ac 12233 [(set_attr "type" "no_insn")]
755eb2b4 12234)
12235
cffb2a26 12236(define_insn "consttable_end"
e1159bbe 12237 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
cffb2a26 12238 "TARGET_EITHER"
f7fbdd4a 12239 "*
cffb2a26 12240 making_const_table = FALSE;
f7fbdd4a 12241 return \"\";
cffb2a26 12242 "
1b7da4ac 12243 [(set_attr "type" "no_insn")]
cffb2a26 12244)
f7fbdd4a 12245
cffb2a26 12246(define_insn "consttable_1"
e1159bbe 12247 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
25f905c2 12248 "TARGET_THUMB1"
f7fbdd4a 12249 "*
cffb2a26 12250 making_const_table = TRUE;
09d688ff 12251 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
cffb2a26 12252 assemble_zeros (3);
f7fbdd4a 12253 return \"\";
cffb2a26 12254 "
1b7da4ac 12255 [(set_attr "length" "4")
12256 (set_attr "type" "no_insn")]
cffb2a26 12257)
f7fbdd4a 12258
cffb2a26 12259(define_insn "consttable_2"
e1159bbe 12260 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
25f905c2 12261 "TARGET_THUMB1"
f7fbdd4a 12262 "*
cffb2a26 12263 making_const_table = TRUE;
9b8516be 12264 gcc_assert (GET_MODE_CLASS (GET_MODE (operands[0])) != MODE_FLOAT);
09d688ff 12265 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
cffb2a26 12266 assemble_zeros (2);
f7fbdd4a 12267 return \"\";
cffb2a26 12268 "
1b7da4ac 12269 [(set_attr "length" "4")
12270 (set_attr "type" "no_insn")]
cffb2a26 12271)
12272
12273(define_insn "consttable_4"
e1159bbe 12274 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
cffb2a26 12275 "TARGET_EITHER"
12276 "*
12277 {
9b8516be 12278 rtx x = operands[0];
cffb2a26 12279 making_const_table = TRUE;
9b8516be 12280 switch (GET_MODE_CLASS (GET_MODE (x)))
cffb2a26 12281 {
12282 case MODE_FLOAT:
9b8516be 12283 if (GET_MODE (x) == HFmode)
12284 arm_emit_fp16_const (x);
12285 else
12286 {
12287 REAL_VALUE_TYPE r;
12288 REAL_VALUE_FROM_CONST_DOUBLE (r, x);
12289 assemble_real (r, GET_MODE (x), BITS_PER_WORD);
12290 }
12291 break;
cffb2a26 12292 default:
7b04c5d5 12293 /* XXX: Sometimes gcc does something really dumb and ends up with
12294 a HIGH in a constant pool entry, usually because it's trying to
12295 load into a VFP register. We know this will always be used in
12296 combination with a LO_SUM which ignores the high bits, so just
12297 strip off the HIGH. */
12298 if (GET_CODE (x) == HIGH)
12299 x = XEXP (x, 0);
9b8516be 12300 assemble_integer (x, 4, BITS_PER_WORD, 1);
12301 mark_symbol_refs_as_used (x);
cffb2a26 12302 break;
12303 }
12304 return \"\";
12305 }"
1b7da4ac 12306 [(set_attr "length" "4")
12307 (set_attr "type" "no_insn")]
cffb2a26 12308)
12309
12310(define_insn "consttable_8"
e1159bbe 12311 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
cffb2a26 12312 "TARGET_EITHER"
12313 "*
12314 {
12315 making_const_table = TRUE;
12316 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
12317 {
12318 case MODE_FLOAT:
12319 {
badfe841 12320 REAL_VALUE_TYPE r;
12321 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
12322 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
cffb2a26 12323 break;
12324 }
12325 default:
09d688ff 12326 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
cffb2a26 12327 break;
12328 }
12329 return \"\";
12330 }"
1b7da4ac 12331 [(set_attr "length" "8")
12332 (set_attr "type" "no_insn")]
cffb2a26 12333)
12334
d98a3884 12335(define_insn "consttable_16"
12336 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_16)]
12337 "TARGET_EITHER"
12338 "*
12339 {
12340 making_const_table = TRUE;
12341 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
12342 {
12343 case MODE_FLOAT:
12344 {
12345 REAL_VALUE_TYPE r;
12346 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
12347 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
12348 break;
12349 }
12350 default:
12351 assemble_integer (operands[0], 16, BITS_PER_WORD, 1);
12352 break;
12353 }
12354 return \"\";
12355 }"
1b7da4ac 12356 [(set_attr "length" "16")
12357 (set_attr "type" "no_insn")]
d98a3884 12358)
12359
cffb2a26 12360;; Miscellaneous Thumb patterns
12361
fd957ef3 12362(define_expand "tablejump"
7db9af5d 12363 [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
fd957ef3 12364 (use (label_ref (match_operand 1 "" "")))])]
25f905c2 12365 "TARGET_THUMB1"
fd957ef3 12366 "
12367 if (flag_pic)
12368 {
12369 /* Hopefully, CSE will eliminate this copy. */
12370 rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
12371 rtx reg2 = gen_reg_rtx (SImode);
12372
12373 emit_insn (gen_addsi3 (reg2, operands[0], reg1));
12374 operands[0] = reg2;
12375 }
12376 "
12377)
12378
f1039640 12379;; NB never uses BX.
25f905c2 12380(define_insn "*thumb1_tablejump"
cffb2a26 12381 [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
12382 (use (label_ref (match_operand 1 "" "")))]
25f905c2 12383 "TARGET_THUMB1"
fd957ef3 12384 "mov\\t%|pc, %0"
1b7da4ac 12385 [(set_attr "length" "2")
12386 (set_attr "type" "no_insn")]
cffb2a26 12387)
0d66636f 12388
331beb1a 12389;; V5 Instructions,
12390
8f4be2be 12391(define_insn "clzsi2"
12392 [(set (match_operand:SI 0 "s_register_operand" "=r")
12393 (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 12394 "TARGET_32BIT && arm_arch5"
ee7cbe0e 12395 "clz%?\\t%0, %1"
bcaec148 12396 [(set_attr "predicable" "yes")
bebe9bbb 12397 (set_attr "type" "clz")])
331beb1a 12398
099ad98b 12399(define_insn "rbitsi2"
12400 [(set (match_operand:SI 0 "s_register_operand" "=r")
12401 (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")] UNSPEC_RBIT))]
12402 "TARGET_32BIT && arm_arch_thumb2"
12403 "rbit%?\\t%0, %1"
12404 [(set_attr "predicable" "yes")
bebe9bbb 12405 (set_attr "type" "clz")])
099ad98b 12406
12407(define_expand "ctzsi2"
12408 [(set (match_operand:SI 0 "s_register_operand" "")
12409 (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
12410 "TARGET_32BIT && arm_arch_thumb2"
12411 "
30191172 12412 {
12413 rtx tmp = gen_reg_rtx (SImode);
12414 emit_insn (gen_rbitsi2 (tmp, operands[1]));
12415 emit_insn (gen_clzsi2 (operands[0], tmp));
12416 }
099ad98b 12417 DONE;
12418 "
12419)
12420
e1159bbe 12421;; V5E instructions.
331beb1a 12422
12423(define_insn "prefetch"
f4e79814 12424 [(prefetch (match_operand:SI 0 "address_operand" "p")
12425 (match_operand:SI 1 "" "")
12426 (match_operand:SI 2 "" ""))]
25f905c2 12427 "TARGET_32BIT && arm_arch5e"
1b7da4ac 12428 "pld\\t%a0"
12429 [(set_attr "type" "load1")]
12430)
331beb1a 12431
0d66636f 12432;; General predication pattern
12433
12434(define_cond_exec
12435 [(match_operator 0 "arm_comparison_operator"
12436 [(match_operand 1 "cc_register" "")
12437 (const_int 0)])]
25f905c2 12438 "TARGET_32BIT"
0d66636f 12439 ""
c7a58118 12440[(set_attr "predicated" "yes")]
0d66636f 12441)
12442
fb94f18b 12443(define_insn "force_register_use"
12444 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_REGISTER_USE)]
063a05c7 12445 ""
fb94f18b 12446 "%@ %0 needed"
1b7da4ac 12447 [(set_attr "length" "0")
12448 (set_attr "type" "no_insn")]
063a05c7 12449)
7db9af5d 12450
4c44712e 12451
12452;; Patterns for exception handling
12453
12454(define_expand "eh_return"
12455 [(use (match_operand 0 "general_operand" ""))]
12456 "TARGET_EITHER"
12457 "
12458 {
25f905c2 12459 if (TARGET_32BIT)
4c44712e 12460 emit_insn (gen_arm_eh_return (operands[0]));
12461 else
12462 emit_insn (gen_thumb_eh_return (operands[0]));
12463 DONE;
12464 }"
12465)
12466
12467;; We can't expand this before we know where the link register is stored.
12468(define_insn_and_split "arm_eh_return"
12469 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
12470 VUNSPEC_EH_RETURN)
12471 (clobber (match_scratch:SI 1 "=&r"))]
12472 "TARGET_ARM"
12473 "#"
12474 "&& reload_completed"
12475 [(const_int 0)]
12476 "
12477 {
12478 arm_set_return_address (operands[0], operands[1]);
12479 DONE;
12480 }"
12481)
12482
12483(define_insn_and_split "thumb_eh_return"
12484 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "l")]
12485 VUNSPEC_EH_RETURN)
12486 (clobber (match_scratch:SI 1 "=&l"))]
25f905c2 12487 "TARGET_THUMB1"
4c44712e 12488 "#"
12489 "&& reload_completed"
12490 [(const_int 0)]
12491 "
12492 {
12493 thumb_set_return_address (operands[0], operands[1]);
12494 DONE;
12495 }"
1b7da4ac 12496 [(set_attr "type" "mov_reg")]
4c44712e 12497)
12498
f655717d 12499\f
12500;; TLS support
12501
12502(define_insn "load_tp_hard"
12503 [(set (match_operand:SI 0 "register_operand" "=r")
12504 (unspec:SI [(const_int 0)] UNSPEC_TLS))]
12505 "TARGET_HARD_TP"
12506 "mrc%?\\tp15, 0, %0, c13, c0, 3\\t@ load_tp_hard"
1b7da4ac 12507 [(set_attr "predicable" "yes")
4b5d7374 12508 (set_attr "type" "mrs")]
f655717d 12509)
12510
12511;; Doesn't clobber R1-R3. Must use r0 for the first operand.
12512(define_insn "load_tp_soft"
12513 [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
12514 (clobber (reg:SI LR_REGNUM))
12515 (clobber (reg:SI IP_REGNUM))
12516 (clobber (reg:CC CC_REGNUM))]
12517 "TARGET_SOFT_TP"
12518 "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
1b7da4ac 12519 [(set_attr "conds" "clob")
12520 (set_attr "type" "branch")]
f655717d 12521)
12522
f41e4452 12523;; tls descriptor call
12524(define_insn "tlscall"
12525 [(set (reg:SI R0_REGNUM)
12526 (unspec:SI [(reg:SI R0_REGNUM)
12527 (match_operand:SI 0 "" "X")
12528 (match_operand 1 "" "")] UNSPEC_TLS))
12529 (clobber (reg:SI R1_REGNUM))
12530 (clobber (reg:SI LR_REGNUM))
12531 (clobber (reg:SI CC_REGNUM))]
12532 "TARGET_GNU2_TLS"
12533 {
12534 targetm.asm_out.internal_label (asm_out_file, "LPIC",
12535 INTVAL (operands[1]));
12536 return "bl\\t%c0(tlscall)";
12537 }
12538 [(set_attr "conds" "clob")
1b7da4ac 12539 (set_attr "length" "4")
12540 (set_attr "type" "branch")]
f41e4452 12541)
12542
1fe0edab 12543;; For thread pointer builtin
12544(define_expand "get_thread_pointersi"
12545 [(match_operand:SI 0 "s_register_operand" "=r")]
12546 ""
12547 "
12548 {
12549 arm_load_tp (operands[0]);
12550 DONE;
12551 }")
12552
f41e4452 12553;;
12554
aabe09ac 12555;; We only care about the lower 16 bits of the constant
12556;; being inserted into the upper 16 bits of the register.
eca5c984 12557(define_insn "*arm_movtas_ze"
12558 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
12559 (const_int 16)
12560 (const_int 16))
12561 (match_operand:SI 1 "const_int_operand" ""))]
181ab277 12562 "arm_arch_thumb2"
aabe09ac 12563 "movt%?\t%0, %L1"
eca5c984 12564 [(set_attr "predicable" "yes")
7c36fe71 12565 (set_attr "predicable_short_it" "no")
1b7da4ac 12566 (set_attr "length" "4")
12567 (set_attr "type" "mov_imm")]
eca5c984 12568)
12569
c0fc3696 12570(define_insn "*arm_rev"
a486b499 12571 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
12572 (bswap:SI (match_operand:SI 1 "s_register_operand" "l,l,r")))]
12573 "arm_arch6"
12574 "@
12575 rev\t%0, %1
12576 rev%?\t%0, %1
12577 rev%?\t%0, %1"
12578 [(set_attr "arch" "t1,t2,32")
1b7da4ac 12579 (set_attr "length" "2,2,4")
12580 (set_attr "type" "rev")]
ff82f757 12581)
12582
12583(define_expand "arm_legacy_rev"
12584 [(set (match_operand:SI 2 "s_register_operand" "")
12585 (xor:SI (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
12586 (const_int 16))
12587 (match_dup 1)))
12588 (set (match_dup 2)
12589 (lshiftrt:SI (match_dup 2)
12590 (const_int 8)))
12591 (set (match_operand:SI 3 "s_register_operand" "")
12592 (rotatert:SI (match_dup 1)
12593 (const_int 8)))
12594 (set (match_dup 2)
12595 (and:SI (match_dup 2)
12596 (const_int -65281)))
12597 (set (match_operand:SI 0 "s_register_operand" "")
12598 (xor:SI (match_dup 3)
12599 (match_dup 2)))]
12600 "TARGET_32BIT"
12601 ""
12602)
12603
12604;; Reuse temporaries to keep register pressure down.
12605(define_expand "thumb_legacy_rev"
12606 [(set (match_operand:SI 2 "s_register_operand" "")
12607 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
12608 (const_int 24)))
12609 (set (match_operand:SI 3 "s_register_operand" "")
12610 (lshiftrt:SI (match_dup 1)
12611 (const_int 24)))
12612 (set (match_dup 3)
12613 (ior:SI (match_dup 3)
12614 (match_dup 2)))
12615 (set (match_operand:SI 4 "s_register_operand" "")
12616 (const_int 16))
12617 (set (match_operand:SI 5 "s_register_operand" "")
12618 (rotatert:SI (match_dup 1)
12619 (match_dup 4)))
12620 (set (match_dup 2)
12621 (ashift:SI (match_dup 5)
12622 (const_int 24)))
12623 (set (match_dup 5)
12624 (lshiftrt:SI (match_dup 5)
12625 (const_int 24)))
12626 (set (match_dup 5)
12627 (ior:SI (match_dup 5)
12628 (match_dup 2)))
12629 (set (match_dup 5)
12630 (rotatert:SI (match_dup 5)
12631 (match_dup 4)))
12632 (set (match_operand:SI 0 "s_register_operand" "")
12633 (ior:SI (match_dup 5)
12634 (match_dup 3)))]
12635 "TARGET_THUMB"
12636 ""
12637)
12638
12639(define_expand "bswapsi2"
12640 [(set (match_operand:SI 0 "s_register_operand" "=r")
12641 (bswap:SI (match_operand:SI 1 "s_register_operand" "r")))]
8d1af482 12642"TARGET_EITHER && (arm_arch6 || !optimize_size)"
ff82f757 12643"
8d1af482 12644 if (!arm_arch6)
12645 {
12646 rtx op2 = gen_reg_rtx (SImode);
12647 rtx op3 = gen_reg_rtx (SImode);
ff82f757 12648
8d1af482 12649 if (TARGET_THUMB)
12650 {
12651 rtx op4 = gen_reg_rtx (SImode);
12652 rtx op5 = gen_reg_rtx (SImode);
ff82f757 12653
8d1af482 12654 emit_insn (gen_thumb_legacy_rev (operands[0], operands[1],
12655 op2, op3, op4, op5));
12656 }
12657 else
12658 {
12659 emit_insn (gen_arm_legacy_rev (operands[0], operands[1],
12660 op2, op3));
12661 }
ff82f757 12662
8d1af482 12663 DONE;
12664 }
ff82f757 12665 "
12666)
12667
a486b499 12668;; bswap16 patterns: use revsh and rev16 instructions for the signed
12669;; and unsigned variants, respectively. For rev16, expose
12670;; byte-swapping in the lower 16 bits only.
12671(define_insn "*arm_revsh"
12672 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
12673 (sign_extend:SI (bswap:HI (match_operand:HI 1 "s_register_operand" "l,l,r"))))]
12674 "arm_arch6"
12675 "@
12676 revsh\t%0, %1
12677 revsh%?\t%0, %1
12678 revsh%?\t%0, %1"
12679 [(set_attr "arch" "t1,t2,32")
1b7da4ac 12680 (set_attr "length" "2,2,4")
12681 (set_attr "type" "rev")]
a486b499 12682)
12683
12684(define_insn "*arm_rev16"
12685 [(set (match_operand:HI 0 "s_register_operand" "=l,l,r")
12686 (bswap:HI (match_operand:HI 1 "s_register_operand" "l,l,r")))]
12687 "arm_arch6"
12688 "@
12689 rev16\t%0, %1
12690 rev16%?\t%0, %1
12691 rev16%?\t%0, %1"
12692 [(set_attr "arch" "t1,t2,32")
1b7da4ac 12693 (set_attr "length" "2,2,4")
12694 (set_attr "type" "rev")]
09f69e55 12695)
12696
12697;; There are no canonicalisation rules for the position of the lshiftrt, ashift
12698;; operations within an IOR/AND RTX, therefore we have two patterns matching
12699;; each valid permutation.
12700
12701(define_insn "arm_rev16si2"
12702 [(set (match_operand:SI 0 "register_operand" "=l,l,r")
12703 (ior:SI (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "l,l,r")
12704 (const_int 8))
12705 (match_operand:SI 3 "const_int_operand" "n,n,n"))
12706 (and:SI (lshiftrt:SI (match_dup 1)
12707 (const_int 8))
12708 (match_operand:SI 2 "const_int_operand" "n,n,n"))))]
12709 "arm_arch6
12710 && aarch_rev16_shleft_mask_imm_p (operands[3], SImode)
12711 && aarch_rev16_shright_mask_imm_p (operands[2], SImode)"
12712 "rev16\\t%0, %1"
12713 [(set_attr "arch" "t1,t2,32")
12714 (set_attr "length" "2,2,4")
12715 (set_attr "type" "rev")]
12716)
12717
12718(define_insn "arm_rev16si2_alt"
12719 [(set (match_operand:SI 0 "register_operand" "=l,l,r")
12720 (ior:SI (and:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,l,r")
12721 (const_int 8))
12722 (match_operand:SI 2 "const_int_operand" "n,n,n"))
12723 (and:SI (ashift:SI (match_dup 1)
12724 (const_int 8))
12725 (match_operand:SI 3 "const_int_operand" "n,n,n"))))]
12726 "arm_arch6
12727 && aarch_rev16_shleft_mask_imm_p (operands[3], SImode)
12728 && aarch_rev16_shright_mask_imm_p (operands[2], SImode)"
12729 "rev16\\t%0, %1"
12730 [(set_attr "arch" "t1,t2,32")
12731 (set_attr "length" "2,2,4")
12732 (set_attr "type" "rev")]
a486b499 12733)
12734
12735(define_expand "bswaphi2"
12736 [(set (match_operand:HI 0 "s_register_operand" "=r")
12737 (bswap:HI (match_operand:HI 1 "s_register_operand" "r")))]
12738"arm_arch6"
12739""
12740)
12741
1653cf17 12742;; Patterns for LDRD/STRD in Thumb2 mode
12743
12744(define_insn "*thumb2_ldrd"
12745 [(set (match_operand:SI 0 "s_register_operand" "=r")
12746 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
12747 (match_operand:SI 2 "ldrd_strd_offset_operand" "Do"))))
12748 (set (match_operand:SI 3 "s_register_operand" "=r")
12749 (mem:SI (plus:SI (match_dup 1)
12750 (match_operand:SI 4 "const_int_operand" ""))))]
12751 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
12752 && current_tune->prefer_ldrd_strd
12753 && ((INTVAL (operands[2]) + 4) == INTVAL (operands[4]))
12754 && (operands_ok_ldrd_strd (operands[0], operands[3],
12755 operands[1], INTVAL (operands[2]),
12756 false, true))"
12757 "ldrd%?\t%0, %3, [%1, %2]"
12758 [(set_attr "type" "load2")
d952d547 12759 (set_attr "predicable" "yes")
12760 (set_attr "predicable_short_it" "no")])
1653cf17 12761
12762(define_insn "*thumb2_ldrd_base"
12763 [(set (match_operand:SI 0 "s_register_operand" "=r")
12764 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
12765 (set (match_operand:SI 2 "s_register_operand" "=r")
12766 (mem:SI (plus:SI (match_dup 1)
12767 (const_int 4))))]
12768 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
12769 && current_tune->prefer_ldrd_strd
12770 && (operands_ok_ldrd_strd (operands[0], operands[2],
12771 operands[1], 0, false, true))"
12772 "ldrd%?\t%0, %2, [%1]"
12773 [(set_attr "type" "load2")
d952d547 12774 (set_attr "predicable" "yes")
12775 (set_attr "predicable_short_it" "no")])
1653cf17 12776
12777(define_insn "*thumb2_ldrd_base_neg"
12778 [(set (match_operand:SI 0 "s_register_operand" "=r")
12779 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
12780 (const_int -4))))
12781 (set (match_operand:SI 2 "s_register_operand" "=r")
12782 (mem:SI (match_dup 1)))]
12783 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
12784 && current_tune->prefer_ldrd_strd
12785 && (operands_ok_ldrd_strd (operands[0], operands[2],
12786 operands[1], -4, false, true))"
12787 "ldrd%?\t%0, %2, [%1, #-4]"
12788 [(set_attr "type" "load2")
d952d547 12789 (set_attr "predicable" "yes")
12790 (set_attr "predicable_short_it" "no")])
1653cf17 12791
12792(define_insn "*thumb2_strd"
12793 [(set (mem:SI (plus:SI (match_operand:SI 0 "s_register_operand" "rk")
12794 (match_operand:SI 1 "ldrd_strd_offset_operand" "Do")))
12795 (match_operand:SI 2 "s_register_operand" "r"))
12796 (set (mem:SI (plus:SI (match_dup 0)
12797 (match_operand:SI 3 "const_int_operand" "")))
12798 (match_operand:SI 4 "s_register_operand" "r"))]
12799 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
12800 && current_tune->prefer_ldrd_strd
12801 && ((INTVAL (operands[1]) + 4) == INTVAL (operands[3]))
12802 && (operands_ok_ldrd_strd (operands[2], operands[4],
12803 operands[0], INTVAL (operands[1]),
12804 false, false))"
12805 "strd%?\t%2, %4, [%0, %1]"
12806 [(set_attr "type" "store2")
d952d547 12807 (set_attr "predicable" "yes")
12808 (set_attr "predicable_short_it" "no")])
1653cf17 12809
12810(define_insn "*thumb2_strd_base"
12811 [(set (mem:SI (match_operand:SI 0 "s_register_operand" "rk"))
12812 (match_operand:SI 1 "s_register_operand" "r"))
12813 (set (mem:SI (plus:SI (match_dup 0)
12814 (const_int 4)))
12815 (match_operand:SI 2 "s_register_operand" "r"))]
12816 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
12817 && current_tune->prefer_ldrd_strd
12818 && (operands_ok_ldrd_strd (operands[1], operands[2],
12819 operands[0], 0, false, false))"
12820 "strd%?\t%1, %2, [%0]"
12821 [(set_attr "type" "store2")
d952d547 12822 (set_attr "predicable" "yes")
12823 (set_attr "predicable_short_it" "no")])
1653cf17 12824
12825(define_insn "*thumb2_strd_base_neg"
12826 [(set (mem:SI (plus:SI (match_operand:SI 0 "s_register_operand" "rk")
12827 (const_int -4)))
12828 (match_operand:SI 1 "s_register_operand" "r"))
12829 (set (mem:SI (match_dup 0))
12830 (match_operand:SI 2 "s_register_operand" "r"))]
12831 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
12832 && current_tune->prefer_ldrd_strd
12833 && (operands_ok_ldrd_strd (operands[1], operands[2],
12834 operands[0], -4, false, false))"
12835 "strd%?\t%1, %2, [%0, #-4]"
12836 [(set_attr "type" "store2")
d952d547 12837 (set_attr "predicable" "yes")
12838 (set_attr "predicable_short_it" "no")])
1653cf17 12839
2a0c73f2 12840;; ARMv8 CRC32 instructions.
12841(define_insn "<crc_variant>"
12842 [(set (match_operand:SI 0 "s_register_operand" "=r")
12843 (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")
12844 (match_operand:<crc_mode> 2 "s_register_operand" "r")]
12845 CRC))]
12846 "TARGET_CRC32"
12847 "<crc_variant>\\t%0, %1, %2"
12848 [(set_attr "type" "crc")
12849 (set_attr "conds" "unconditional")]
12850)
1653cf17 12851
353cf59a 12852;; Load the load/store double peephole optimizations.
12853(include "ldrdstrd.md")
12854
320ea44d 12855;; Load the load/store multiple patterns
12856(include "ldmstm.md")
426be8c5 12857
12858;; Patterns in ldmstm.md don't cover more than 4 registers. This pattern covers
12859;; large lists without explicit writeback generated for APCS_FRAME epilogue.
12860(define_insn "*load_multiple"
12861 [(match_parallel 0 "load_multiple_operation"
12862 [(set (match_operand:SI 2 "s_register_operand" "=rk")
12863 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
12864 ])]
12865 "TARGET_32BIT"
12866 "*
12867 {
12868 arm_output_multireg_pop (operands, /*return_pc=*/false,
12869 /*cond=*/const_true_rtx,
12870 /*reverse=*/false,
12871 /*update=*/false);
12872 return \"\";
12873 }
12874 "
12875 [(set_attr "predicable" "yes")]
12876)
12877
d98a3884 12878;; Vector bits common to IWMMXT and Neon
12879(include "vec-common.md")
755eb2b4 12880;; Load the Intel Wireless Multimedia Extension patterns
12881(include "iwmmxt.md")
a2cd141b 12882;; Load the VFP co-processor patterns
12883(include "vfp.md")
25f905c2 12884;; Thumb-2 patterns
12885(include "thumb2.md")
d98a3884 12886;; Neon patterns
12887(include "neon.md")
e84fdf6e 12888;; Crypto patterns
12889(include "crypto.md")
06df6b17 12890;; Synchronization Primitives
12891(include "sync.md")
bbbe4599 12892;; Fixed-point patterns
12893(include "arm-fixed.md")